繁体   English   中英

如何确定 iPhone 上的默认网关?

[英]How can I determine the default gateway on iPhone?

我需要在 iPhone 应用程序中获取默认网关的 IP 地址。 我找不到合适的 API。 有谁知道 iPhone 是否会公开这些信息?

我已经解决了这个问题,虽然我不知道这个解决方案是否有效(不会被苹果拒绝)

首先,我会给你我用来构建我的解决方案的来源:

http://code.google.com/p/doubango/source/browse/trunk/thirdparties/iphone/include/net/route.h?r=348

http://code.google.com/p/touchcode/source/browse/Experimental/TouchHTTPD/Externals/libnatpmp-20071213/getgateway.c?r=bc90b03205cbebb0633a7b5b203c2c6d5cb860dc

如果你认为苹果会允许这种代码,那么得到一些反馈会很棒。

获取网关.h

#ifndef __GETGATEWAY_H__
#define __GETGATEWAY_H__

/* getdefaultgateway() :
 * return value :
 *    0 : success
 *   -1 : failure    */
int getdefaultgateway(in_addr_t * addr);

#endif

获取网关

#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

通过发送 UDP 数据包寻找服务类型“urn:schemas-upnp-org:device:InternetGatewayDevice:1”并注意响应的第一个设备(如果有)(忽略有效负载,因为我只想要网关的 IP 地址)。

这适用于我的应用程序,但需要路由器实现 SSDP,这并不完美,尽管在我的情况下有效。

由于这是一个特殊用途的 iPhone 应用程序(仅限内部使用),我将采用它。 我不会将此标记为“答案”,因为它不是通用解决方案。 如果我回到这里并寻找通用解决方案(例如使用 ICMP),或者弄清楚如何使用 iPhone SDK 配置 API 来查询此信息,我将在此处发布。

对于那些需要人类可读 IP 的人,我修改了我的 getgateway.c 如下:

添加到包括:

#include <arpa/inet.h>

在最后一个 if 语句中,在 *addr 和 r=0 之间;

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

*addr = ((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr;

char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(((struct sockaddr_in *)(sa_tab[RTAX_GATEWAY]))->sin_addr.s_addr), str, INET_ADDRSTRLEN); // supports IPv6
printf("IP: %s\n", str); // prints "192.0.2.33"

r = 0;
}

在 iOS ≥ 12 上,您可以使用Network框架。

您从NWPath获得的NWPathMonitor.pathUpdateHandler会将NWPath.gateways变量设置为网关 IP。

let monitor = NWPathMonitor(requiredInterfaceType: .wifi)
monitor.pathUpdateHandler = { path in
    print(path.gateways)
}
monitor.start(queue: DispatchQueue(label: "nwpathmonitor.queue"))

如果我没记错的话,网关 IP 始终是您的设备 IP 地址,最后一个八位字节设置为“1”,不是吗? 如果这就是您要查找的内容,您应该能够从 localhostAddresses.m 文件中找到您需要的提示,该文件是 CocoaHTTPServer 源中示例的一部分。 我使用该项目在我的应用程序中添加一个内部网络服务器,并从该源文件的方法中获取设备 IP。

Touch 博士在此链接中对此进行了讨论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM