2011-03-22 39 views
1

问题是如何在MACOSX上获取路由表? 我不是指netstat -nr。我的意思是如何以编程方式使用C。 首先,我从opensource.apple.com下载了netstat源代码。 我找到了void mroutepr(void) function in mroute.c
这个函数看起来像获取路由表的函数,但我不确定。在MACOSX上获取路由表(以编程方式)

有一个数组声明: struct vif viftable [CONFIG_MAXVIFS];

但是,当我试图编译mroutepr我发现,结构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); 
    } 
} 

回答

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); 
} 
+0

有一点要注意 - 你需要root权限才能做到系统调用或通过路由套接字倾销路由表。如果你没有,它不会做太多你。 – synthesizerpatel 2012-06-29 16:51:40

+0

谢谢你的例子。有没有办法转储IPv6路由表? – Bionix1441 2017-12-04 08:13:52

相关问题