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.

eemceebee
  • 2,656
  • 9
  • 39
  • 49
  • One technique, though perhaps a little specialised, is outlined here http://stackoverflow.com/questions/2300149/how-can-i-determine-the-default-gateway-on-iphone – Paul Dixon Feb 02 '11 at 08:31

4 Answers4

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;

}
Alex0072005
  • 151
  • 1
  • 2
  • How can I update the code to ipv6 network only? – Jongers Aug 24 '16 at 08:17
  • is this possible to get all the wifi gateways addresses within the network – Boosa Ramesh Mar 01 '17 at 09:18
  • You make my day Man...its working like a charm :D... – Kalpesh Panchasara Jun 27 '17 at 14:36
  • TypeEN definitions are not good when phone is connected to 3G network or LTE. In that case removing that string comparison helps. – Juraj Antas Jan 17 '18 at 13:37
  • 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... – HormCodes Mar 17 '18 at 20:44
  • 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 project – hemelamed Sep 04 '22 at 13:31
  • 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. – hemelamed Sep 04 '22 at 13:42
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 <miniupnp@free.fr>
 *
 * 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
Jakob
  • 1,126
  • 3
  • 16
  • 38
  • 2
    Just a note to anyone trying this out on the simulator: "en1" might be the active network connection rather than "en0". – newenglander Oct 08 '13 at 11:45
  • 2
    You can get route.h from here: http://www.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"); }` – ddiego Aug 14 '14 at 21:23
  • Jakob, what argument do you pass into this method? It asks for in_addr_t but where does this come from? Thanks – Darren Nov 07 '14 at 10:47
  • Got it working with ddiego's comment. Thanks guys :) – Darren Nov 08 '14 at 11:30
  • Hi it is not working with 3g can you help? – souvickcse May 25 '15 at 11:21
  • I'm getting this error: Undefined symbols for archutecture arm64 "getdefaultgateway(unsigned int*)" can you help me please? – Jongers Jul 27 '16 at 07:18
  • How can I update it to support ipv6 network only? – Jongers Aug 24 '16 at 08:16
  • why not: a break when the address is fetched? – Karsten Apr 10 '18 at 15:48
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.

eemceebee
  • 2,656
  • 9
  • 39
  • 49
-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;
}
Community
  • 1
  • 1
Paul Dixon
  • 295,876
  • 54
  • 310
  • 348