IP cidr匹配函数

IP cidr匹配函数,c,cidr,C,Cidr,我需要找出,ip是否属于ip掩码。 例如: ip=192.168.0.1 掩码=192.168.0.1/24 我找到了将ip转换为掩码的函数: inet_cidrtoaddr(int cidr, struct in_addr *addr) { int ocets; if (cidr < 0 || cidr > 32) { errno = EINVAL; return -1;

我需要找出,ip是否属于ip掩码。 例如:

ip=192.168.0.1 掩码=192.168.0.1/24

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

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;
}
inet\u-cidroaddr(int-cidr,struct-in\u-addr*addr)
{
内部流程;
如果(cidr<0 | | cidr>32){
errno=EINVAL;
返回-1;
}
ocets=(cidr+7)/8;
地址->s_地址=0;
如果(ocets>0){
memset(&addr->s_addr,255,(大小)ocets-1);
memset((无符号字符*)&addr->s_addr+(ocets-1),

(256-(1此函数计算网络掩码(例如,255.255.255.128的形式)。因此,要检查指定的IP地址是否在指定的子网内,只需将掩码应用于CIDR地址和IP地址(您可以使用)。如果结果相同,则IP地址有效。

如果您有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;
}

所以,要把答案写成代码:

// 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));
不过,我更喜欢这种方法:

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);
试试这个:

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</P>函数的更容易的形式:<代码> ADDR > SyAdDr= 0xFFFFFFFUU> Stest-O:如果代码> PrimeLime< /Cube >为0,则会导致未定义的结果。注意:对于IPv6,请参见
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);
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);
}