问题是如何在MACOSX上获取路由表?
我的意思不是 netstat -nr 。我的意思是如何使用 C 以编程方式执行此操作。
首先,我从opensource.apple.com下载了netstat源代码。
我在 mroute.c 中找到了 void mroutepr(void)功能。
这个函数看起来像获取路由表的函数,但我不确定。
有一个数组声明: struct vif viftable [CONFIG_MAXVIFS];
但是当我尝试编译mroutepr时,我发现struct vif没有在 /usr/include/netinet/ip_mroute.h中声明 我添加了所有必要的包含。我已经检查了七次:))
然后我检查xnu内核源代码。 我在xnu内核中找到了这个结构,在这个文件中: xnu / bsd / netinet / ip_mroute.h。 struct vif有完整的定义。
似乎这种结构仅在内核模式下可用。
我很困惑。
如何只为内核代码声明struct vif? netstat 工具如何运作?
上面的Everythig不正确:))) 解决方案在route.c文件中 ntreestuff(void)函数是获取路由表的入口点。 然后在 np_rtentry(rtm)函数中,我们将表打印到控制台。
static void ntreestuff(void)
{
size_t needed;
int mib[6];
char *buf, *next, *lim;
struct rt_msghdr2 *rtm;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = 0;
mib[4] = NET_RT_DUMP2;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
{
err(1, "sysctl: net.route.0.0.dump estimate");
}
if ((buf = malloc(needed)) == 0)
{
err(2, "malloc(%lu)", (unsigned long)needed);
}
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
{
err(1, "sysctl: net.route.0.0.dump");
}
lim = buf + needed;
for (next = buf; next < lim; next += rtm->rtm_msglen)
{
rtm = (struct rt_msghdr2 *)next;
np_rtentry(rtm);
}
}
答案 0 :(得分:1)
这基本上可以满足您的需求。还有另一种机制(我个人比sysctl更喜欢 - 但我认为它们都需要root访问权限,所以它是一个清洗......但是,通过向路由套接字发出RTM_GET请求,你可以获得相同的信息。一半,一半十几个等等。
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/route.h>
/* Darwin doesn't define this for some very odd reason */
#ifndef SA_SIZE
# define SA_SIZE(sa) \
( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \
sizeof(long) : \
1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
#endif
static void
ntreestuff(void)
{
size_t needed;
int mib[6];
char *buf, *next, *lim;
struct rt_msghdr *rtm;
struct sockaddr *sa;
struct sockaddr_in *sockin;
char line[MAXHOSTNAMELEN];
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = 0;
mib[4] = NET_RT_DUMP;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
err(1, "sysctl: net.route.0.0.dump estimate");
}
if ((buf = (char *)malloc(needed)) == NULL) {
errx(2, "malloc(%lu)", (unsigned long)needed);
}
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
err(1, "sysctl: net.route.0.0.dump");
}
lim = buf + needed;
for (next = buf; next < lim; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)next;
sa = (struct sockaddr *)(rtm + 1);
sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);
sockin = (struct sockaddr_in *)sa;
inet_ntop(AF_INET, &sockin->sin_addr.s_addr, line, sizeof(line) - 1);
printf("defaultrouter=%s\n", line);
break;
}
free(buf);
}
int
main(int argc __unused, char *argv[] __unused)
{
ntreestuff();
return (0);
}