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のように見えるはずです...

有効なアドレスを取得するために何かすることはありますか?

ご協力いただきありがとうございます!

4

3 に答える 3

10

デフォルト ゲートウェイの IP アドレスを自分で取得する方法を探していました。これだけに焦点を当てます-デフォルトルーターのMACアドレスを取得する必要はなかったので、これはOPの質問に部分的にしか答えません.

私は、netstat の出力を解析するという考えが好きではありませんでした。また、マシンのインターフェイスの IP アドレスに基づいてデフォルト ルートを取得することはできません。あなたの IP アドレスと同じ範囲内の任意の IP アドレスをデフォルト ゲートウェイにすることができます。唯一のルールは、IP とデフォルト ゲートウェイの両方が同じサブネットの一部である必要があるということです。

もう 1 つ確認したかったのは、複数のローカル インターフェイスに IP アドレスが割り当てられている場合でも、デフォルト ゲートウェイの IP アドレスを取得することです (たとえば、Wifi と有線イーサネットに同時に接続している場合)。両方のインターフェースが稼働しており、IP アドレスが設定されています)。私のアプリケーションでは、デフォルト ルートがどのインターフェイスを介して設定されているかは問題ではありません (en0、en1、ppp0、またはその他すべての可能性があります)。

その情報を取得するための最良の (そして最も Apple らしい) 方法は、System Configuration Framework を使用することだと思います。それを使用しますが、Apple のドキュメントはあまり役に立ちませんでした (少なくとも私のスキルレベルを考慮すると)。

私はObjective-Cの経験があまりないことに注意してください-私は自分で必要な(そして見つけることができなかった)アプリを書いている最中であり、そのアプリにはデフォルトのIPアドレスが必要ですゲートウェイ。

だから-これが私のアプリでやっていることで、うまく機能しているようです(さらに、これまでに見つけた他のほとんどのソリューションよりもはるかに短くてシンプルです:

- (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;
}

私のアプリでは、上記はより大きなメソッドの一部であることに注意してください (実際には defaultRouter: メソッドはありません)。また、簡潔にするために一部のチェック ([routerString length] など) を省略しました。

うまくいけば、誰かがこれが役に立つと思います。また、上記のコードにある可能性のあるエラーを自由に修正してください - 私はまだ初心者です!

PS。システム構成フレームワーク自体を使用する「scutil」の出力を確認したときに、何を探すべきかがわかりました。

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>
}
于 2012-12-03T21:14:37.677 に答える
4

これは、マシンのルートを見つけるために私が書いたコードです。のコードからシステム コールをコピーしました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
于 2010-01-23T21:45:31.400 に答える
1

xxx.xxx.255.255 はサブネット マスクです。ゲートウェイアドレスが必要です。

表 3-10 を参照してください。この PDF にルーターのエントリがあります: 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

于 2010-01-21T23:00:47.030 に答える