[英]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.