IP cidr匹配function

我需要找出来,是ip属于ip mask。 例如:

ip = 192.168.0.1 mask = 192.168.0.1/24。

我找到了将ip转换为mask的函数:

inet_cidrtoaddr(int cidr, struct in_addr *addr) { int ocets; if (cidr  32) { errno = EINVAL; return -1; } ocets = (cidr + 7) / 8; addr->s_addr = 0; if (ocets > 0) { memset(&addr->s_addr, 255, (size_t)ocets - 1); memset((unsigned char *)&addr->s_addr + (ocets - 1), (256 - (1 << (32 - cidr) % 8)), 1); } return 0; } 

我如何比较ip和cidr范围?

如果您有IP地址,网络地址和网络掩码,那么您可以使用如下函数:

 bool is_in_net ( const struct in_addr* addr, /* host byte order */ const struct in_addr* netaddr, const struct in_addr* netmask ) { if ((addr->s_addr & netmask->s_addr) == (netaddr->s_addr & netmask->s_addr)) return true; return false; } 

所以把Olis的答案放在代码中:

 // Check if 192.168.0.1 is inside 192.168.0.0/24 in_addr ip, net, netmask; inet_aton("192.168.0.1", &ip); inet_aton("192.168.0.0", &net); 

他说:

 inet_cidrtoaddr(24, &netmask); bool is_inside = ((ip.s_addr & netmask.s_addr) == (net.s_addr & netmask.s_addr)); 

我更喜欢addr4_match方法:

 bool cidr_match(const in_addr &addr, const in_addr &net, uint8_t bits) { if (bits == 0) { // C99 6.5.7 (3): u32 << 32 is undefined behaviour return true; } return !((addr.s_addr ^ net.s_addr) & htonl(0xFFFFFFFFu << (32 - bits))); } bool is_inside = cidr_match(ip, net, 24); 

我尝试了一堆不同的输入: https : //gist.github.com/duedal/b83303b4988a4afb2a75

如果发现这一点的人也想要一个IPv6解决方案:

 bool cidr6_match(const in6_addr &address, const in6_addr &network, uint8_t bits) { #ifdef LINUX const uint32_t *a = address.s6_addr32; const uint32_t *n = network.s6_addr32; #else const uint32_t *a = address.__u6_addr.__u6_addr32; const uint32_t *n = network.__u6_addr.__u6_addr32; #endif int bits_whole, bits_incomplete; bits_whole = bits >> 5; // number of whole u32 bits_incomplete = bits & 0x1F; // number of bits in incomplete u32 if (bits_whole) { if (memcmp(a, n, bits_whole << 2)) { return false; } } if (bits_incomplete) { uint32_t mask = htonl((0xFFFFFFFFu) << (32 - bits_incomplete)); if ((a[bits_whole] ^ n[bits_whole]) & mask) { return false; } } return true; } 

检查2001:db8 :: ff00:42:8329是否存在于2001:db8 / 32。 当心inet_net_pton非常挑剔,它是2001:db8 / 32而不是2001:db8 :: / 32。 但是2001:db8 :: / 48完全有效(也称为2001:db8:0/48)。

 in6_addr ip6, net6, net6_48; memset(&net6, 0, sizeof(net6)); memset(&net6_48, 0, sizeof(net6_48)); assert(inet_pton(AF_INET6, "2001:db8::ff00:42:8329", &ip6)); int bits = inet_net_pton(AF_INET6, "2001:db8/32", &net6, sizeof(net6)); assert((bits != -1)); // assert that inet_net_pton understood us bool is_inside6 = cidr6_match(ip6, net6, bits); int bits_48 = inet_net_pton(AF_INET6, "2001:db8::/48", &net6_48, sizeof(net6_48)); assert((bits_48 == 48)); bool is_inside6_48 = cidr6_match(ip6, net6_48, bits_48); 

此函数计算网络掩码(例如,forms为255.255.255.128)。 因此,要检查指定的IP地址是否属于指定的子网,只需将掩码应用于CIDR地址和IP地址(使用按位AND执行此操作)。 如果结果相同,则IP地址有效。