简体   繁体   English

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

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

I need to obtain the IP address of the default gateway in an iPhone application.我需要在 iPhone 应用程序中获取默认网关的 IP 地址。 I cannot find the proper API.我找不到合适的 API。 Anyone know if iPhone exposes this information?有谁知道 iPhone 是否会公开这些信息?

I have solved this, though i dunno if this solution is valid (wont be rejected by apple)我已经解决了这个问题,虽然我不知道这个解决方案是否有效(不会被苹果拒绝)

first i'll give you the sources i used to build my solution upon:首先,我会给你我用来构建我的解决方案的来源:

http://code.google.com/p/doubango/source/browse/trunk/thirdparties/iphone/include/net/route.h?r=348 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 http://code.google.com/p/touchcode/source/browse/Experimental/TouchHTTPD/Externals/libnatpmp-20071213/getgateway.c?r=bc90b03205cbebb0633a7b5b203c2c6d5cb860dc

It would be great to get some feedback if you think apple will allow this kind of code.如果你认为苹果会允许这种代码,那么得到一些反馈会很棒。

getgateway.h获取网关.h

#ifndef __GETGATEWAY_H__
#define __GETGATEWAY_H__

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

#endif

getgateway.c获取网关

#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

I was successful obtaining the address from SSDP protocol by sending a UDP packet out looking for service type "urn:schemas-upnp-org:device:InternetGatewayDevice:1" and noting the first device (if any) that replies (ignoring the payload, since I only want the IP address of the gateway).通过发送 UDP 数据包寻找服务类型“urn:schemas-upnp-org:device:InternetGatewayDevice:1”并注意响应的第一个设备(如果有)(忽略有效负载,因为我只想要网关的 IP 地址)。

This works for my application, but requires that the router implement SSDP, which is not perfect, although works in my case.这适用于我的应用程序,但需要路由器实现 SSDP,这并不完美,尽管在我的情况下有效。

Since this is a special-purpose iPhone App (in-house, only), I am going to go with this.由于这是一个特殊用途的 iPhone 应用程序(仅限内部使用),我将采用它。 I won't mark this as "the answer" because it is not a general purpose solution.我不会将此标记为“答案”,因为它不是通用解决方案。 If I come back to this and look for a general purpose solution (such as using ICMP), or figuring out how to use the iPhone SDK configuration APIs to query for this information, I will post here.如果我回到这里并寻找通用解决方案(例如使用 ICMP),或者弄清楚如何使用 iPhone SDK 配置 API 来查询此信息,我将在此处发布。

for those who need human readable IP, i modified my getgateway.c as follow:对于那些需要人类可读 IP 的人,我修改了我的 getgateway.c 如下:

add to includes:添加到包括:

#include <arpa/inet.h>

inside the last if statement, between *addr and r=0;在最后一个 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;
}

On iOS ≥ 12, you can use the Network framework.在 iOS ≥ 12 上,您可以使用Network框架。

The NWPath you get from the NWPathMonitor.pathUpdateHandler will have the NWPath.gateways variable set to the gateways IPs.您从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"))

If I'm not mistaken, the gateway IP is always whatever your device IP address is, with the last octet set to "1", isn't it?如果我没记错的话,网关 IP 始终是您的设备 IP 地址,最后一个八位字节设置为“1”,不是吗? If that's what you're looking for, you should be able to find the hints you need from the localhostAddresses.m file which is part of the samples in CocoaHTTPServer sources.如果这就是您要查找的内容,您应该能够从 localhostAddresses.m 文件中找到您需要的提示,该文件是 CocoaHTTPServer 源中示例的一部分。 I use the project to add an internal webserver within my app and I get the devices IP from that source file's methods.我使用该项目在我的应用程序中添加一个内部网络服务器,并从该源文件的方法中获取设备 IP。

Dr. Touch talks about it at this link . Touch 博士在此链接中对此进行了讨论。

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

相关问题 如何以编程方式确定iPhone上的默认铃声? - How can I programmatically determine the default ringtone on an iPhone? iPhone:如何确定主机是否可访问? - iPhone: How can I determine a host is reachable or not? iPhone SDK:如何确定TabBarController中的最后一个活动标签? - iPhone SDK: How can I determine the last active tab in a TabBarController? 如何以编程方式确定我的应用程序是iPad还是iPhone - How can I programmatically determine if my app iPad or iPhone 如何以编程方式确定我的应用程序正在iPhone,iPad或iPhone 4上运行? - How can I determine programmatically that my app is running on an iPhone, iPad or iPhone 4? 如何修改iPhone上默认“后退”按钮的目标? - How can I modify the target of the default Back button on iphone? 如何在 iPhone 上默认显示数字键盘? - How can I show the numeric keyboard by default on iPhone? 如何在iPhone应用程序中拥有2个leftBarButtonItems,并且1是默认的后退按钮? - How can I have 2 leftBarButtonItems in iPhone app, and 1 be the default back button? 按下时如何更改iPhone上按钮的默认颜色? - How can I change the default color of the button on iPhone when pressed? iOS模拟器-如何将默认模拟器设为iPhone - iOS simulator - How can I make default simulator as iPhone
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM