如何从getifaddr读取子网掩码?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (200)

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

例如:

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

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

提问于
用户回答回答于

你的赋值tmpMask是错误的,因为你输入的类型ifa_netmask错误,因此sin_addr通过无效指针访问其成员。

你正在服用的地址ifa_netmask和类型转换,要sockaddr_in*,但你需要输入它的,而不是就像你做的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_netmask,你正在输出其原始指针值(使用%u,这是指针的未定义行为)。你应该像格式化一样格式化ifa_netmask为可读的字符串ifa_addr,因为它们都是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);

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励