一尘不染

如何以编程方式找到在Linux中为特定网络设备配置的IP地址/网络掩码/网关?

linux

我想编写一段代码,为每个网络设备(例如eth0,lo,主设备)检查有关该设备的一些统计信息和配置数据。
我可以在/ sys / class / net / …中找到统计数据(以及大多数配置数据),但是,在列出inet addr的procfs /
sysfs中找不到任何C / C ++ API或任何条目,网络掩码和网关。

我检查了一些替代方法:

  • 解析ifconfig / route /其他实用程序的输出:我不想每次需要进行检查时都启动一个子进程。
  • 解析/ etc / sysconfig / network-scripts /:只会给我启动配置,而不是当前状态。

另外,由于此代码是针对我的工作场所中的产品而设计的,因此这里的每个外部库都经过全面检查(这意味着我将永远需要添加任何外部库),因此我更喜欢依赖Linux本机API而非外部库的解决方案。

谢谢!


阅读 272

收藏
2020-06-07

共1个答案

一尘不染

确保使用了ifreq和ioctl()调用的结构,您可以获取所有接口信息:

手册页在这里Ifreq手册页

/* local interface info */
    typedef struct{
        char *iface;
        struct ether_addr hwa;
        struct in_addr ipa;
        struct in_addr bcast;
        struct in_addr nmask;
        u_short mtu;
    } ifcfg_t; 
    /*
     * Grabs local network interface information and stores in a ifcfg_t 
     * defined in network.h, returns 0 on success -1 on failure
    */
    int get_local_info(int rsock, ifcfg_t *ifcfg)
    {
        struct ifreq ifr;

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, ifcfg->iface, IF_NAMESIZE);
        if((ioctl(rsock, SIOCGIFHWADDR, &ifr)) == -1){
            perror("ioctl():");
            return -1;
        }
        memcpy(&(ifcfg->hwa), &ifr.ifr_hwaddr.sa_data, 6);

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, ifcfg->iface, IF_NAMESIZE);
        if((ioctl(rsock, SIOCGIFADDR, &ifr)) == -1){
            perror("ioctl():");
            return -1;
        }
        memcpy(&ifcfg->ipa, &(*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr, 4);

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, ifcfg->iface, IF_NAMESIZE);
        if((ioctl(rsock, SIOCGIFBRDADDR, &ifr)) == -1){
            perror("ioctl():");
            return -1;
        }
        memcpy(&ifcfg->bcast, &(*(struct sockaddr_in *)&ifr.ifr_broadaddr).sin_addr, 4);

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, ifcfg->iface, IF_NAMESIZE);
        if((ioctl(rsock, SIOCGIFNETMASK, &ifr)) == -1){
            perror("ioctl():");
            return -1;
        }
        memcpy(&ifcfg->nmask.s_addr, &(*(struct sockaddr_in *)&ifr.ifr_netmask).sin_addr, 4);

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, ifcfg->iface, IF_NAMESIZE);
        if((ioctl(rsock, SIOCGIFMTU, &ifr)) == -1){
            perror("ioctl():");
            return -1;
        }
        ifcfg->mtu = ifr.ifr_mtu;

        return 0;
    }

快速编辑,此功能要求在调用接口之前已经分配了接口,如下所示:

strcpy(if_cfg->iface, iface)

确保先分配了内存,然后像这样调用

if((get_local_info(sock, if_cfg)) != 0){
    printf("Unable to get network device info\n");
    return -1;
}
2020-06-07