2010-01-21 17 views
7

मैंने राउटर पते को इस तरह लाने की कोशिश की।उद्देश्य-सी: राउटर पता कैसे प्राप्त करें?

- (NSString *) routerIp { 

    NSString *address = @"error"; 
    struct ifaddrs *interfaces = NULL; 
    struct ifaddrs *temp_addr = NULL; 
    int success = 0; 

    // retrieve the current interfaces - returns 0 on success 
    success = getifaddrs(&interfaces); 
    if (success == 0) 
    { 
    // Loop through linked list of interfaces 
    temp_addr = interfaces; 
    while(temp_addr != NULL) 
    { 
     if(temp_addr->ifa_addr->sa_family == AF_INET) 
     { 
     // Check if interface is en0 which is the wifi connection on the iPhone 
     if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) 
     { 
      // Get NSString from C String //ifa_addr 
      address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_dstaddr)->sin_addr)]; 
     } 
     } 

     temp_addr = temp_addr->ifa_next; 
    } 
    } 

    // Free memory 
    freeifaddrs(interfaces); 

    return address; 
} 

रूटर पता हमेशा xxx.xxx.255.255 की तरह दिखता है, लेकिन यह xxx.xxx.0.1 या कुछ इस तरह से की तरह लग रहे करने के लिए माना जाता है ...

वहाँ वैध प्राप्त करने के लिए कुछ भी है पता?

आपकी मदद के लिए धन्यवाद!

+0

ifa-> ifa_dstaddr प्रसारण पता है, जो "255 के" बताते है: मैं क्या जब मैं 'scutil' के उत्पादन, जो सिस्टम विन्यास फ्रेमवर्क खुद का उपयोग करता है की जाँच की खोज करने के लिए की एक विचार मिल गया। – Bill

+0

यह लिंक देखें http://stackoverflow.com/questions/6530322/fetching-ip-address-of-router-to-which-iphone-is-connected –

उत्तर

1

xxx.xxx.255.255 सबनेट मास्क है। आपको गेटवे पता चाहिए। http://developer.apple.com/Mac/library/documentation/Networking/Conceptual/SystemConfigFrameworks/SystemConfigFrameworks.pdf

HTML संस्करण यहाँ है: http://developer.apple.com/Mac/library/documentation/Networking/Conceptual/SystemConfigFrameworks/SC_Overview/SC_Overview.html

+0

यह वास्तव में प्रसारण पता है, नहीं सबनेट मास्क। –

+0

यदि ऐसा है तो यह एक विशाल प्रसारण डोमेन है। 255 के दो ऑक्टेट्स 2^16 = 65536 होस्ट के तहत प्रसारित करने के लिए काफी बड़े होंगे। – pokstad

4

यहाँ है कुछ कोड मैं मशीन के लिए मार्गों को खोजने के लिए लिखा था

देखें तालिका 3-10, वहाँ thsi पीडीएफ में रूटर के लिए एक प्रवेश है । मैंने netstat के लिए कोड से सिस्टम कॉल की प्रतिलिपि बनाई। ध्यान दें कि मुझे ऐसा करने के खिलाफ दृढ़ता से अनुशंसा की गई थी, क्योंकि ये सिस्टम कॉल समर्थित API नहीं हैं और किसी भी समय बदल सकते हैं। उन्होंने अनुशंसा की कि मैं सिर्फ netstat के आउटपुट को पार्स करें।

CustomRoute.c:

#import "CustomRoute.h" 
@implementation CustomRoute 

+ (NSMutableArray*) getRoutes 
{ 
    NSMutableArray* routeArray = [NSMutableArray array]; 
    CustomRoute* route = nil; 

    size_t needed; 
    int mib[6]; 
    char *buf, *next, *lim; 
    register struct rt_msghdr2 *rtm; 

    mib[0] = CTL_NET; 
    mib[1] = PF_ROUTE; 
    mib[2] = 0; 
    mib[3] = 0; 
    mib[4] = NET_RT_DUMP2; 
    mib[5] = 0; 

    if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { 
     err(1, "sysctl: net.route.0.0.dump estimate"); 
    } 

    if ((buf = malloc(needed)) == 0) { 
     err(2, "malloc(%lu)", (unsigned long)needed); 
    } 
    if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 
     err(1, "sysctl: net.route.0.0.dump"); 
    } 

    lim = buf + needed; 

    for (next = buf; next < lim; next += rtm->rtm_msglen) { 
     rtm = (struct rt_msghdr2 *)next; 
     route = [self getRoute:rtm]; 
     if(route != nil) 
     { 
      [routeArray addObject:route]; 
     } 
    } 
    free(buf); 
    printf("Total routes: %u\n", [routeArray count]); 
    return routeArray; 
} 


+ (CustomRoute*) getRoute:(struct rt_msghdr2 *)rtm 
{ 
    //sockaddrs are after the message header 
    struct sockaddr* dst_sa = (struct sockaddr *)(rtm + 1); 

    CustomRoute* route = nil; 

    if(rtm->rtm_addrs & RTA_DST) 
    { 
     switch(dst_sa->sa_family) 
     { 
      case AF_INET: 
       if(dst_sa->sa_family == AF_INET && !((rtm->rtm_flags & RTF_WASCLONED) && (rtm->rtm_parentflags & RTF_PRCLONING))) 
       { 
        route = [[CustomRoute alloc] initWithRtm:rtm]; 
       } 
      break; 

     } 
    } 

    return route; 
} 

-(void) setAddr:(struct sockaddr*)sa index:(int)rtax_index 
{ 
    if(rtax_index >= 0 && rtax_index < RTAX_MAX) 
    { 
     memcpy(&(m_addrs[rtax_index]), sa, sizeof(struct sockaddr)); 
    } 

} 

-(NSString*) getDestination 
{ 
    return [self getAddrStringByIndex:RTAX_DST]; 
} 

-(NSString*) getNetmask 
{ 
    return [self getAddrStringByIndex:RTAX_NETMASK]; 
} 

-(NSString*) getGateway 
{ 
    return [self getAddrStringByIndex:RTAX_GATEWAY]; 
} 

-(NSString*) getDetails 
{ 
    NSMutableString* result = [[NSMutableString alloc] init]; 
    [result appendFormat: [NSString stringWithFormat: @"message type: 0x%06x\n", m_rtm.rtm_type]]; 
    [result appendFormat: [NSString stringWithFormat: @"flags: 0x%06x\n", m_rtm.rtm_flags]]; 
    [result appendFormat: [NSString stringWithFormat: @"addrs: 0x%06x\n", m_rtm.rtm_addrs]]; 


    return result; 
} 


-initWithRtm: (struct rt_msghdr2*) rtm 
{ 
    int i; 
    struct sockaddr* sa = (struct sockaddr*)(rtm + 1); 


    //copy over the route message 
    memcpy(&(m_rtm), rtm, sizeof(struct rt_msghdr2)); 
    for(i = 0; i < RTAX_MAX; i++) 
    { 
     [self setAddr:&(sa[i]) index:i]; 
    } 
    return self; 
} 

- init 
{ 
    memset(m_addrs, 0, sizeof(m_addrs)); 
    return self; 
} 

@end 


@implementation CustomRoute (Private) 

-(NSString*) getAddrStringByIndex: (int)rtax_index 
{ 
    NSString * routeString = nil; 
    struct sockaddr* sa = &(m_addrs[rtax_index]); 
    int flagVal = 1 << rtax_index; 

    if(!(m_rtm.rtm_addrs & flagVal)) 
    { 
     return @"none"; 
    } 


    if(rtax_index >= 0 && rtax_index < RTAX_MAX) 
    { 
     switch(sa->sa_family) 
     { 
      case AF_INET: 
      { 
       struct sockaddr_in* si = (struct sockaddr_in *)sa; 
       if(si->sin_addr.s_addr == INADDR_ANY) 
        routeString = @"default"; 
       else 
        routeString = [NSString stringWithCString:(char *)inet_ntoa(si->sin_addr) encoding:NSASCIIStringEncoding]; 
      } 
      break; 

      case AF_LINK: 
       { 
        struct sockaddr_dl* sdl = (struct sockaddr_dl*)sa; 
        if(sdl->sdl_nlen + sdl->sdl_alen + sdl->sdl_slen == 0) 
        { 
         routeString = [NSString stringWithFormat: @"link #%d", sdl->sdl_index]; 
        } 
        else 
         routeString = [NSString stringWithCString:link_ntoa(sdl) encoding:NSASCIIStringEncoding]; 
       } 
      break; 

      default: 
       { 
        char a[3 * sa->sa_len]; 
        char *cp; 
        char *sep = ""; 
        int i; 

        if(sa->sa_len == 0) 
        { 
         routeString = @"empty"; 
        } 
        else 
        { 
         a[0] = (char)NULL; 
         for(i = 0, cp = a; i < sa->sa_len; i++) 
         { 
          cp += sprintf(cp, "%s%02x", sep, (unsigned char)sa->sa_data[i]); 
          sep = ":"; 
         } 
         routeString = [NSString stringWithCString:a encoding:NSASCIIStringEncoding]; 
        } 
       } 
     } 
    } 
    return routeString; 
} 

@end 

CustomRoute.h:

#import <Cocoa/Cocoa.h> 
#import <net/route.h> 
#import <sys/socket.h> 
#import <netinet/in.h> 
#import <net/if_dl.h> 
#import <sys/sysctl.h> 

@interface CustomRoute : NSObject { 
    struct sockaddr  m_addrs[RTAX_MAX]; 
    struct rt_msghdr2 m_rtm; 
    int     m_len;  /* length of the sockaddr array */ 
} 

+ (NSMutableArray*) getRoutes; 
+ (CustomRoute*) getRoute:(struct rt_msghdr2 *)rtm; 

- (void) setAddr:(struct sockaddr*)sa index:(int)rtax_index; 

- (NSString*) getDestination; 
- (NSString*) getNetmask; 
- (NSString*) getGateway; 
- initWithRtm: (struct rt_msghdr2*) rtm; 


@end 
+0

आईओएस पर मैक ओएस पुस्तकालयों और ढांचे का उपयोग करना सामान्य नहीं है। – Alena

10

मैं एक तरह से चूक के आईपी पते पाने के लिए तलाश रहे हैं अपने आप को गेटवे। मैं इस पर ध्यान केंद्रित करने जा रहा हूं - मुझे डिफ़ॉल्ट राउटर का मैक पता प्राप्त करने की आवश्यकता नहीं थी, इसलिए यह केवल आंशिक रूप से ओपी के प्रश्न का उत्तर देता है।

मुझे नेटस्टैट आउटपुट को पार्स करने का विचार पसंद नहीं आया। साथ ही, आपको आईपी पते के आधार पर एक डिफ़ॉल्ट मार्ग नहीं मिल सकता है जो आपके मशीन पर एक इंटरफ़ेस है। आपके जैसे ही सीमा के भीतर कोई भी आईपी पता डिफ़ॉल्ट गेटवे हो सकता है - एकमात्र नियम यह है कि आपके आईपी और डिफ़ॉल्ट गेटवे दोनों को एक ही सबनेट का हिस्सा होना चाहिए।

एक और चीज जिसे मैं सुनिश्चित करना चाहता था, डिफ़ॉल्ट गेटवे का आईपी पता प्राप्त करना है, भले ही मेरे स्थानीय इंटरफेस में से एक से अधिक आईपी एड्रेस सौंपा गया हो (उदाहरण के लिए मैं वाईफ़ाई और वायर्ड से जुड़ा हूं एक ही समय में ईथरनेट, और दोनों इंटरफ़ेस ऊपर आईपी पते के साथ हैं)। मेरे आवेदन के लिए, इससे कोई फ़र्क नहीं पड़ता कि डिफ़ॉल्ट मार्ग किस इंटरफ़ेस के माध्यम से सेट किया गया है (यह en0, en1, ppp0 या कुछ भी हो सकता है)।

मुझे लगता है कि यह जानकारी प्राप्त करने के लिए सबसे अच्छा (और सबसे ऐप्पल-जैसे) तरीका सिस्टम कॉन्फ़िगरेशन फ्रेमवर्क का उपयोग करना है - इस धागे में उपरोक्त पोस्ट में दिए गए लिंक ने मुझे उस दिशा में इंगित किया है, लेकिन वास्तव में बहुत अधिक विवरण नहीं दिया इसका उपयोग कैसे करें, और मुझे एप्पल दस्तावेज बहुत उपयोगी नहीं मिला (कम से कम मेरे कौशल स्तर को ध्यान में रखते हुए)।

कृपया ध्यान दें कि मैं उद्देश्य-सी में बहुत अनुभवी नहीं हूं - मैं एक ऐप लिखने के बीच में हूं जिसे मुझे खुद की जरूरत है (और जो मुझे नहीं मिला), और उस ऐप के लिए मुझे बस आईपी की आवश्यकता है डिफ़ॉल्ट गेटवे का पता।

तो - यहाँ मैं अपने अनुप्रयोग में क्या कर रहा है, और यह काम करने ठीक लग रहा है (प्लस बहुत कम और अधिकांश अन्य समाधान मैं अब तक पाया की तुलना में सरल है:

- (NSString *)defaultRouter { 

    SCDynamicStoreRef ds = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("myapp"), NULL, NULL); 
    CFDictionaryRef dr = SCDynamicStoreCopyValue(ds, CFSTR("State:/Network/Global/IPv4")); 
    CFStringRef router = CFDictionaryGetValue(dr, CFSTR("Router")); 
    NSString *routerString = [NSString stringWithString:(__bridge NSString *)router]; 
    CFRelease(dr); 
    CFRelease(ds); 

    return routerString; 
} 

कृपया ध्यान दें कि में मेरा ऐप, उपर्युक्त एक बड़ी विधि का हिस्सा है (मेरे पास वास्तव में एक डिफ़ॉल्ट राउटर नहीं है: वहां विधि)। इसके अलावा, मैंने ब्रेवटी के लिए कुछ चेक (जैसे [राउटरस्ट्रिंग लम्बाई] और इतने पर) छोड़ा है।

उम्मीद है कि किसी को यह उपयोगी लगेगा। कृपया उपरोक्त कोड में होने वाली किसी भी त्रुटि को ठीक करने के लिए भी स्वतंत्र महसूस करें - मैं अभी भी एक नौसिखिया हूं!

पीएस।

MacBook:~$ scutil 
> show State:/Network/Global/IPv4 
<dictionary> { 
    PrimaryInterface : en1 
    PrimaryService : <service_id> 
    Router : <ipv4_address> 
} 
> show State:/Network/Global/IPv6 
<dictionary> { 
    PrimaryInterface : en1 
    PrimaryService : <service_id> 
    Router : <ipv6_address> 
} 
+10

'SCDynamicStoreCreate' और' SCDynamicStoreCopyValue' आईओएस पर उपलब्ध नहीं हैं। यह केवल मैक के लिए काम करेगा। – thegrinner

+0

@thegrinner मैंने इन funcs को आजमाया नहीं है, लेकिन ये फ़ंक्शन आईओएस के तहत उपलब्ध हैं। आप इसे अगले कमांड के साथ सुनिश्चित कर सकते हैं: 'nm -m/अनुप्रयोग /Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.1.sdk/System/Library/Frameworks/SystemConfiguration.framework/System कॉन्फ़िगरेशन | grep SCDynamicStoreCreate' – Speakus

+0

नहीं, ये आईओएस 8.1 पर सार्वजनिक रूप से उपलब्ध नहीं हैं। SCDynamicStore.h में: SCDynamicStoreCreate \t \t \t ... \t \t \t \t __OSX_AVAILABLE_STARTING (__ MAC_10_1, __ IPHONE_NA); इन्हें संदर्भित करने का प्रयास एक कंपाइलर त्रुटि उत्पन्न करता है। –

संबंधित मुद्दे