在MACOSX上获取路由表(以编程方式) [英] Getting routing table on MACOSX (programmatically)

查看:310
本文介绍了在MACOSX上获取路由表(以编程方式)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题是如何在MACOSX上获取路由表?
我不是说 netstat -nr 。我的意思是如何使用 C 以编程方式进行操作。
首先,我从opensource.apple.com下载了netstat源代码。
我在 mroute.c 中发现了 void mroutepr(void)函数。

这个函数看起来像获取路由表的函数,但是我不确定。

The question is how can I get routing table on MACOSX? I don’t mean netstat -nr. I mean how to do it programmatically using C. The first of all I have downloaded netstat source codes from opensource.apple.com. I have found void mroutepr(void) function in mroute.c.
This function looks like function which get routing table but I am not sure.

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

但是当我尝试编译mroutepr时,我发现在 /usr/include/netinet/ip_mroute.h 中未声明struct vif。我已经添加了所有必需的包含。我已经检查了七次:))

But when I tried to compile mroutepr I revealed that struct vif is not declared in /usr/include/netinet/ip_mroute.h I have added all necessary includes. I have checked it seven times :))

然后我检查了xnu内核源代码。
我在xnu内核的这个文件中找到了这个结构体: xnu / bsd / netinet / ip_mroute.h。
完整的struct vif定义。

Then I check xnu kernel source code. I have found this structute in xnu kernel, in this file: xnu/bsd/netinet/ip_mroute.h. There was complete definition of struct vif.

此结构似乎仅在内核模式下可用。

It seems that this structure available only in kernel mode.

我很困惑。

如何只能在内核代码中声明struct vif? netstat 实用程序如何工作?

I am puzzled.
How can struct vif be declared only for kernel code? How netstat utility works?

上面的内容都不正确:))))
解决方案在route.c文件中。

ntreestuff(void)函数是获取路由表的入口点。
然后在 np_rtentry(rtm)函数中,将表打印到控制台。

Everythig above is incorrect :))) The solution is in route.c file.
ntreestuff(void) function is entry point for getting routing table. Then in np_rtentry(rtm) function we print table to the console.

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


推荐答案

此基本上可以满足您的需求。还有另一种机制(我个人比sysctl更喜欢-但我认为两者都需要root访问权,所以这是一种洗手。.但是,通过向路由套接字发出RTM_GET请求,您可以获得相同的信息。六分之一,一半一打,等等。

This basically does what you want. There's another mechanism that (personally I like a little more than sysctl - but I think both require root access so it's a wash.. But, by making an RTM_GET request to a routing socket you can get the same info. 6 of one, half a dozen, etc.

#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);
}

这篇关于在MACOSX上获取路由表(以编程方式)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆