【问题标题】:C Programming: Check if the IP address is added on any given NICC 编程:检查是否在任何给定的 NIC 上添加了 IP 地址
【发布时间】:2015-10-08 22:21:59
【问题描述】:

问题描述: 我有一个 IP 地址(可以是 IPv4/IPv6)和 NIC 地址,我如何检查是否使用 C 将 IP 地址添加到给定的 NIC(或任何 NIC)。

我知道在命令行/使用脚本上做同样的事情很简单,但是我需要在 C 程序中进行检查。

示例:
IP - 192.168.0.1
网卡-eth0

使用命令行(linux平台),下面的命令会告诉我是否添加了IP:

ip addr show | grep "192.168.0.1"

p.s.:是否有任何库函数可以用来获得类似的输出?

【问题讨论】:

    标签: c linux ip


    【解决方案1】:

    您想使用getifaddrs,它会返回一个网络接口列表以及与它们关联的地址。

    来自手册页:

    int getifaddrs(struct ifaddrs **ifap);
    

    getifaddrs() 函数创建结构的链表 描述本地系统的网络接口,并存储 *ifap 中列表第一项的地址。名单 由ifaddrs 结构组成,定义如下:

           struct ifaddrs {
               struct ifaddrs  *ifa_next;    /* Next item in list */
               char            *ifa_name;    /* Name of interface */
               unsigned int     ifa_flags;   /* Flags from SIOCGIFFLAGS */
               struct sockaddr *ifa_addr;    /* Address of interface */
               struct sockaddr *ifa_netmask; /* Netmask of interface */
               union {
                   struct sockaddr *ifu_broadaddr;
                                    /* Broadcast address of interface */
                   struct sockaddr *ifu_dstaddr;
                                    /* Point-to-point destination address */
               } ifa_ifu;
           #define              ifa_broadaddr ifa_ifu.ifu_broadaddr
           #define              ifa_dstaddr   ifa_ifu.ifu_dstaddr
               void            *ifa_data;    /* Address-specific data */
           };
    

    这是我如何在我的一个程序中使用它的示例:

    union sockaddr_u {
        struct sockaddr_storage ss;
        struct sockaddr_in sin;
        struct sockaddr_in6 sin6;
    };
    
    struct iflist {
        char name[IFNAME_LEN];
        union sockaddr_u su;
        int isloopback;
        int ismulti;
        int ifidx;
    };
    
    void getiflist(struct iflist *list, int *len)
    {
        struct ifaddrs *ifa, *ifa_tmp;
        int count;
        unsigned ifidx;
    
        if (getifaddrs(&ifa) == -1) {
            perror("getifaddrs failed");
            *len = 0;
            return;
        }
        ifa_tmp = ifa;
        count = *len;
        *len = 0;
        while (ifa_tmp && (*len < count)) {
            if ((ifidx = if_nametoindex(ifa_tmp->ifa_name)) == 0) {
                perror("Error getting interface index for interface %s",
                                  ifa_tmp->ifa_name);
                continue;
            }
            if (ifa_tmp->ifa_addr && ((ifa_tmp->ifa_addr->sa_family == AF_INET) ||
                                      (ifa_tmp->ifa_addr->sa_family == AF_INET6)) &&
                        ((ifa_tmp->ifa_flags & IFF_UP) != 0)) {
                memset(&list[*len], 0, sizeof(struct iflist));
                strncpy(list[*len].name, ifa_tmp->ifa_name,
                        sizeof(list[*len].name) - 1);
                memcpy(&list[*len].su, ifa_tmp->ifa_addr,
                        sizeof(struct sockaddr_storage));
                list[*len].isloopback = (ifa_tmp->ifa_flags & IFF_LOOPBACK) != 0;
                list[*len].ismulti = (ifa_tmp->ifa_flags & IFF_MULTICAST) != 0;
                list[*len].ifidx = ifidx;
                (*len)++;
            }
            ifa_tmp = ifa_tmp->ifa_next;
        }
        freeifaddrs(ifa);
    }
    

    【讨论】:

    • 非常感谢,这样就可以了
    【解决方案2】:

    【讨论】:

    • 非常感谢,这样就可以了
    【解决方案3】:

    这应该工作:

    #define _BSD_SOURCE
    #include <ifaddrs.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<netdb.h>
    
    
    int main(void){
        struct ifaddrs *ip, *hosst;
        int s;
        char host[NI_MAXHOST];
    
        if (getifaddrs(&ip) == -1){
            perror("getifaddrs");
            return 1;
        }
    
        for (hosst = ip; hosst != NULL; hosst = hosst->ifa_next){
            if (hosst->ifa_addr == NULL){
                continue;
            }
    
            s=getnameinfo(hosst->ifa_addr,sizeof(struct sockaddr_in),host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
    
            if((strcmp(hosst->ifa_name,"wlan0")==0)&&(hosst->ifa_addr->sa_family==AF_INET)){
                if (s != 0){
                    printf("getnameinfo() failed: %s\n", gai_strerror(s));
                    return 1;
                }
                printf("IP  - %s\n", host);
                printf("NIC - %s\n",hosst->ifa_name );
            }
        }
    
        free(ip);
        return 0;
    }
    

    输出:

    IP  - 192.168.0.110
    NIC - wlan0
    

    【讨论】:

    • 感谢您的回答,但我正在寻找与 NIC 关联的 IP
    • 我意识到,现在我在工作,我明天会更新我的帖子。
    【解决方案4】:

    上面建议的方法(GETIFADDRS)是所述问题描述的正确解决方案。 getifaddrs 浏览 NIC 上的所有 IP。

    但是,在我的情况下,NIC/系统上添加了许多 IP 地址,我可以知道 IP 是否存在于任何 NIC 中。我找到了一个更简单/更快的解决方案。

    要检查 IP 是否添加到机器的任何 NIC 卡上,只需打开一个 TCP 套接字并绑定 port=zero(0) 和要检查的 IP 地址。成功的绑定将表明 IP 可用/存在。

    注意:如果在系统中的任何 NIC 卡上添加了 IP,则此方法有效。应该使用端口 0 而不是硬编码,因为它会选择系统中的任何可用端口 (参考http://compnetworking.about.com/od/tcpip/p/port-numbers-0.htm

    此方法在 UNIX 环境(rhel)中针对 IPv4/IPv6 进行了测试

    PS:验证IP存在后不要忘记关闭socket

    【讨论】:

    • 很遗憾,bind()方法不起作用,如果/proc/sys/net/ipv4/ip_nonlocal_binnd=1,即sysctl net.ipv4.ip_nonlocal_bind为1
    猜你喜欢
    • 2011-11-30
    • 2017-05-28
    • 2021-06-20
    • 2012-11-14
    • 2013-08-22
    • 2022-01-14
    • 2017-10-30
    • 2022-03-03
    • 1970-01-01
    相关资源
    最近更新 更多