在Linux上使用C语言中的默认网关

13

如何在Linux上使用C语言查找路由表的默认网关?

我不想调用shell或读取文件。有添加和删除路由的ioctl(SIOCADDRT,SIOCDELRT)以及我找到了一个获取路由的参考(SIOCGRTCONF),但似乎我正在使用的内核版本不支持SIOCGRTCONF。


网卡没有默认网关,路由表有默认网关。 - womble
3个回答

12

我认为阅读/proc/net/route将是最好的选择。你会认为这是一个“文件”吗?

/proc/net/route的格式是众所周知的,并且是内存中的,因此没有I/O惩罚或担心它的更改(即相对于从/etc/network/*读取某些内容)。


8
您可能需要使用NETLINK_ROUTE套接字,这是PF_NETLINK套接字系列的一部分。请查看'iproute'程序的源代码,特别是它的'路由'子命令。

1
这里是一个示例代码的链接。 http://www.linuxquestions.org/questions/linux-networking-3/howto-find-gateway-address-through-code-397078/我进行了一些修改并实现了它,效果很好。 - Matt

8
您可以像这样使用/proc/net/route:
int GetDefaultGw ( std::string & gw )
{
    FILE *f;
    char line[100] , *p , *c, *g, *saveptr;
    int nRet=1;

    f = fopen("/proc/net/route" , "r");

    while(fgets(line , 100 , f))
    {
        p = strtok_r(line , " \t", &saveptr);
        c = strtok_r(NULL , " \t", &saveptr);
        g = strtok_r(NULL , " \t", &saveptr);

        if(p!=NULL && c!=NULL)
        {
            if(strcmp(c , "00000000") == 0)
            {
                //printf("Default interface is : %s \n" , p);
                if (g)
                {
                    char *pEnd;
                    int ng=strtol(g,&pEnd,16);
                    //ng=ntohl(ng);
                    struct in_addr addr;
                    addr.s_addr=ng;
                    gw=std::string( inet_ntoa(addr) );
                    nRet=0;
                }
                break;
            }
        }
    }

    fclose(f);
    return nRet;
}

2
如果您有多个接口,检查第二个if语句中的接口名称会更有意义。 - 3bdalla
2
必须使用'strtoul',否则某些情况会溢出。例如,默认网关是FEFEFEA9('169.254.254.254')。应该是'unsigned long int ng = strtoul(g, &pEnd, 16);' - Mystic Lin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接