我需要找出来,是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 < 0 || 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范围?
答案 0 :(得分:8)
所以把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);
答案 1 :(得分:2)
此函数计算网络掩码(例如255.255.255.128形式的东西)。因此,要检查指定的IP地址是否属于指定的子网,只需将掩码应用于CIDR地址和IP地址(使用bitwise AND执行此操作)。如果结果相同,则IP地址有效。
答案 2 :(得分:2)
如果你有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;
}
答案 3 :(得分:0)
尝试一下:
const std::uint32_t CIDR_PREFIXES[33] = {
[0] = htonl(0),
[1] = htonl(0x80000000),
[2] = htonl(0xC0000000),
[3] = htonl(0xE0000000),
[4] = htonl(0xF0000000),
[5] = htonl(0xF8000000),
[6] = htonl(0xFC000000),
[7] = htonl(0xFE000000),
[8] = htonl(0xFF000000),
[9] = htonl(0xFF800000),
[10] = htonl(0xFFC00000),
[11] = htonl(0xFFE00000),
[12] = htonl(0xFFF00000),
[13] = htonl(0xFFF80000),
[14] = htonl(0xFFFC0000),
[15] = htonl(0xFFFE0000),
[16] = htonl(0xFFFF0000),
[17] = htonl(0xFFFF8000),
[18] = htonl(0xFFFFC000),
[19] = htonl(0xFFFFE000),
[20] = htonl(0xFFFFF000),
[21] = htonl(0xFFFFF800),
[22] = htonl(0xFFFFFC00),
[23] = htonl(0xFFFFFE00),
[24] = htonl(0xFFFFFF00),
[25] = htonl(0xFFFFFF80),
[26] = htonl(0xFFFFFFC0),
[27] = htonl(0xFFFFFFE0),
[28] = htonl(0xFFFFFFF0),
[29] = htonl(0xFFFFFFF8),
[30] = htonl(0xFFFFFFFC),
[31] = htonl(0xFFFFFFFE),
[32] = htonl(0xFFFFFFFF),
};
bool matchCIDR(const in_addr &network, const in_addr &addr, unsigned prefix)
{
if (prefix > 32)
return false;
std::uint32_t cidr = CIDR_PREFIXES[prefix];
std::uint32_t hNetwork = network.s_addr;
std::uint32_t hAddr = addr.s_addr;
return hNetwork == (hAddr & cidr);
}
但是在C ++中,使其变得很容易C