代码之家  ›  专栏  ›  技术社区  ›  hookenz

如何从getifaddr[duplicate]读取子网掩码

  •  0
  • hookenz  · 技术社区  · 6 年前

    这个问题已经有了答案:

    使用 getifaddrs() 函数我要提取网络IP和掩码 采用CIDR格式(即24而不是255.255.255.0),这与其他问题不同。但我在面具部分有困难。

    例如:

    192.168.0.114/24号

    这就是我到目前为止一直在搞的。但我一定是看错了网络掩码。完全错了。

    #include <stdio.h>
    #include <sys/types.h>
    #include <ifaddrs.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <arpa/inet.h>
    
    unsigned int cidrMask(unsigned int n) {
        unsigned int count = 0;
        while (n) {
            count += n & 1;
            n >>= 1;
        }
        return 32-count;
    }
    
    
    int main (int argc, const char * argv[]) {
        struct ifaddrs * ifAddrStruct=NULL;
        struct ifaddrs * ifa=NULL;
        void * tmpAddrPtr=NULL;
        unsigned int tmpMask;
    
        getifaddrs(&ifAddrStruct);
    
        for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
            if (!ifa->ifa_addr) {
                continue;
            }
    
            if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
                // is a valid IP4 Address
                tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
                memcpy(&tmpMask, &(*(struct sockaddr_in *)&ifa->ifa_netmask).sin_addr, 4);
    
                char addressBuffer[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
                printf("%s IP Address %s, mask=%u, %u\n", ifa->ifa_name, addressBuffer, ifa->ifa_netmask, cidrMask(tmpMask));
                    printf("tmpmask=%d\n", tmpMask);
            }
        }
        if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
        return 0;
    }
    

    所以网络掩码的输出是完全错误的。

    lo IP Address 127.0.0.1, mask=3106544572, 22
    tmpmask=21982
    enp0s25 IP Address 192.168.0.114, mask=3106544756, 22
    tmpmask=21982
    docker0 IP Address 172.17.0.1, mask=3106544940, 22
    tmpmask=21982
    

    如何读取网络掩码并生成正确的输出?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Remy Lebeau    6 年前

    你的任务 tmpMask 是错误的,因为你是类型铸造 ifa_netmask 错了,所以你正在访问它 sin_addr 通过无效指针的成员。

    你拿的是 地址 属于 ifa_网络掩码 并将其键入 sockaddr_in* ,但您需要键入cast 价值 相反,就像你 ifa_addr 以下内容:

    memcpy(&tmpMask, &(((struct sockaddr_in *)(ifa->ifa_netmask))->sin_addr.s_addr), 4); 
    

    可以通过删除 memcpy() 以下内容:

    tmpMask = ((struct sockaddr_in *)(ifa->ifa_netmask))->sin_addr.s_addr;
    

    当你打印出来时 ifa_网络掩码 ,您正在打印 原始指针值 (使用 %u ,这是指针的未定义行为)。你应该格式化 ifa_网络掩码 以与设置格式相同的方式设置为可读字符串 IFA_地址 ,因为它们都是指向 sockaddr_in 结构:

    char addressBuffer[INET_ADDRSTRLEN];
    char maskBuffer[INET_ADDRSTRLEN];
    
    tmpAddrPtr = &((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr;
    inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
    
    tmpAddrPtr = &((struct sockaddr_in *)(ifa->ifa_netmask))->sin_addr;
    inet_ntop(AF_INET, tmpAddrPtr, maskBuffer, INET_ADDRSTRLEN);
    
    tmpMask = ((struct sockaddr_in *)(ifa->ifa_netmask))->sin_addr.s_addr;
    
    printf("%s IP Address %s, Mask %s, %u\n", ifa->ifa_name, addressBuffer, maskBuffer, cidrMask(tmpMask));
    printf("tmpmask=%u\n", tmpMask);