How to get the WIFI gateway address on the iPhone? [duplicate]
Asked Answered
C

4

16

I need to get the gateway address of the wifi network I connect with the iPhone. Anyone knows how to get that ?

Just to clarify, I am looking for the information of this screen :

enter image description here

Thanks.

Conditioner answered 2/2, 2011 at 8:27 Comment(1)
One technique, though perhaps a little specialised, is outlined here #2300649Jp
C
2

After checking back with Apple, the SDK does not offer an easy way to do that. The hard way, if any, is to dig deep into the system or use a traceroute.

I filed a bug report, maybe they will add it in the future.

Conditioner answered 11/2, 2011 at 13:43 Comment(0)
S
14

Add to your project route.h file from http://opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/net/route.h

Create getgateway.h

int getdefaultgateway(in_addr_t * addr);

Create getgateway.c

#include <stdio.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#include "getgateway.h"

#include "TargetConditionals.h"
#if TARGET_IPHONE_SIMULATOR
    #include <net/route.h>
    #define TypeEN    "en1"
#else
    #include "route.h"
    #define TypeEN    "en0"
#endif

#include <net/if.h>
#include <string.h>

#define CTL_NET         4               /* network, see socket.h */


#if defined(BSD) || defined(__APPLE__)

#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))

int getdefaultgateway(in_addr_t * addr)
{
    int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
        NET_RT_FLAGS, RTF_GATEWAY};
    size_t l;
    char * buf, * p;
    struct rt_msghdr * rt;
    struct sockaddr * sa;
    struct sockaddr * sa_tab[RTAX_MAX];
    int i;
    int r = -1;
    if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
        return -1;
    }
    if(l>0) {
        buf = malloc(l);
        if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
            return -1;
        }
        for(p=buf; p<buf+l; p+=rt->rtm_msglen) {
            rt = (struct rt_msghdr *)p;
            sa = (struct sockaddr *)(rt + 1);
            for(i=0; i<RTAX_MAX; i++) {
                if(rt->rtm_addrs & (1 << i)) {
                    sa_tab[i] = sa;
                    sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
                } else {
                    sa_tab[i] = NULL;
                }
            }

            if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
               && sa_tab[RTAX_DST]->sa_family == AF_INET
               && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {


                if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
                        char ifName[128];
                        if_indextoname(rt->rtm_index,ifName);
                        if(strcmp(TypeEN,ifName)==0){
                            *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
                                r = 0;                        
                        }
                }
            }
        }
        free(buf);
    }
    return r;
}
#endif

Through the following snippet, this example will be good work on the simulator and the devise.

#include "TargetConditionals.h"
#if TARGET_IPHONE_SIMULATOR
    #include <net/route.h>
    #define TypeEN    "en1"
#else
    #include "route.h"
    #define TypeEN    "en0"
#endif

Use this code in your Objective C project

#import "getgateway.h"
#import <arpa/inet.h>

- (NSString *)getGatewayIP {
    NSString *ipString = nil;
    struct in_addr gatewayaddr;
    int r = getdefaultgateway(&(gatewayaddr.s_addr));
    if(r >= 0) {
        ipString = [NSString stringWithFormat: @"%s",inet_ntoa(gatewayaddr)];
        NSLog(@"default gateway : %@", ipString );
    } else {
        NSLog(@"getdefaultgateway() failed");
    }

    return ipString;

}
Scrag answered 3/4, 2015 at 21:53 Comment(7)
How can I update the code to ipv6 network only?Nedrud
is this possible to get all the wifi gateways addresses within the networkAugsburg
You make my day Man...its working like a charm :D...Nomanomad
TypeEN definitions are not good when phone is connected to 3G network or LTE. In that case removing that string comparison helps.Frown
Code works well. However don't you have problem with App Store Review? They send me crashlogs where problem was EXC_BREAKPOINT (SIGTRAP) from Swift method which is getting default gateway by way above...Single
Alex0072005, would you be willing to upload this code as a github gist and specify an MIT license? Stack overflow code from 2015 is released as CC BY-SA 3.0, which cannot easily be used in an MIT licensed projectGoerke
To clarify, MIT is not required, just something more permissive. Stack overflow code from 2015 is released as CC BY-SA 3.0, which cannot be modified without re-distribution under the same license. That makes it a bit tricky to include in open source software that has different licensing.Goerke
L
12

The following works for me, but a copy of route.h is required.

My general understanding is that this code queries and retrieves the systems routing table. It uses its entries to determine the default route aka gateway ip

/* $Id: getgateway.c,v 1.6 2007/12/13 14:46:06 nanard Exp $ */
/* libnatpmp
 * Copyright (c) 2007, Thomas BERNARD <[email protected]>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include <stdio.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#include "getgateway.h"
#include "route.h"
#include <net/if.h>
#include <string.h>

#define CTL_NET         4               /* network, see socket.h */


#if defined(BSD) || defined(__APPLE__)

#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))

int getdefaultgateway(in_addr_t * addr)
{
    int mib[] = {CTL_NET, PF_ROUTE, 0, AF_INET,
        NET_RT_FLAGS, RTF_GATEWAY};
    size_t l;
    char * buf, * p;
    struct rt_msghdr * rt;
    struct sockaddr * sa;
    struct sockaddr * sa_tab[RTAX_MAX];
    int i;
    int r = -1;
    if(sysctl(mib, sizeof(mib)/sizeof(int), 0, &l, 0, 0) < 0) {
        return -1;
    }
    if(l>0) {
        buf = malloc(l);
        if(sysctl(mib, sizeof(mib)/sizeof(int), buf, &l, 0, 0) < 0) {
            return -1;
        }
        for(p=buf; p<buf+l; p+=rt->rtm_msglen) {
            rt = (struct rt_msghdr *)p;
            sa = (struct sockaddr *)(rt + 1);
            for(i=0; i<RTAX_MAX; i++) {
                if(rt->rtm_addrs & (1 << i)) {
                    sa_tab[i] = sa;
                    sa = (struct sockaddr *)((char *)sa + ROUNDUP(sa->sa_len));
                } else {
                    sa_tab[i] = NULL;
                }
            }

            if( ((rt->rtm_addrs & (RTA_DST|RTA_GATEWAY)) == (RTA_DST|RTA_GATEWAY))
               && sa_tab[RTAX_DST]->sa_family == AF_INET
               && sa_tab[RTAX_GATEWAY]->sa_family == AF_INET) {


                if(((struct sockaddr_in *)sa_tab[RTAX_DST])->sin_addr.s_addr == 0) {
                        char ifName[128];
                        if_indextoname(rt->rtm_index,ifName);

                        if(strcmp("en0",ifName)==0){

                                *addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;
                                r = 0;                        
                        }
                }
            }
        }
        free(buf);
    }
    return r;
}
#endif
Larimore answered 7/2, 2012 at 9:32 Comment(8)
Just a note to anyone trying this out on the simulator: "en1" might be the active network connection rather than "en0".Invalidism
You can get route.h from here: opensource.apple.com/source/xnu/xnu-1456.1.26/bsd/net/route.h And then get the gate way like: struct in_addr gatewayaddr; int r = getdefaultgateway(&(gatewayaddr.s_addr)); if(r>=0){ NSString * ipString = [NSString stringWithFormat: @"%s",inet_ntoa(gatewayaddr)]; NSLog(@"default gateway : %@", ipString ); } else { NSLog(@"getdefaultgateway() failed"); }Complete
Jakob, what argument do you pass into this method? It asks for in_addr_t but where does this come from? ThanksFaroff
Got it working with ddiego's comment. Thanks guys :)Faroff
Hi it is not working with 3g can you help?Subdiaconate
I'm getting this error: Undefined symbols for archutecture arm64 "getdefaultgateway(unsigned int*)" can you help me please?Nedrud
How can I update it to support ipv6 network only?Nedrud
why not: a break when the address is fetched?Cocteau
C
2

After checking back with Apple, the SDK does not offer an easy way to do that. The hard way, if any, is to dig deep into the system or use a traceroute.

I filed a bug report, maybe they will add it in the future.

Conditioner answered 11/2, 2011 at 13:43 Comment(0)
J
-2

Take a look at the answers to Objective-C : How to fetch the router address?

Perhaps only tangentially related, but see the technique outlined in this blog post: http://blog.zachwaugh.com/post/309927273/programmatically-retrieving-ip-address-of-iphone

It obtains the IP address of the Wi-Fi interface, and might be a another jumping off point to finding another solution....

- (NSString *)getIPAddress
{
  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
          address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
        }
      }

      temp_addr = temp_addr->ifa_next;
    }
  }

  // Free memory
  freeifaddrs(interfaces);

  return address;
}
Jp answered 2/2, 2011 at 8:39 Comment(4)
good point, one should check that the gateway returned is the gateway on the wifi interfaceLarimore
The code above returns an IP address of the device not a gateway.Polynices
...which I did say in the last paragraphJp
it does return the device ip ...Jannjanna

© 2022 - 2024 — McMap. All rights reserved.