子网中的所有IP(C)

时间:2016-11-23 21:00:00

标签: c networking cidr netmask

有人有一个很好的例子,说明我可以使用192.168.1.1/24等CIDR获取IP地址并返回该范围内的所有IP地址,例如192.168.1.1, 192.168.1.2, 192.168.1.3 ...

我很好,它以unsigned longchar或类似

的数组返回
/* Pseudocode */
while(currnetip <= finalip) { 
    print(currnetip); 
    currnetip++; 
}

只要我能理解它就好了。

如果您认为可以帮助我,请随意评论某个帖子的链接。

编辑:可能值得一提的是我发现了许多计算广播地址的东西,我不知道如何将所有这些功能连接在一起。

1 个答案:

答案 0 :(得分:2)

首先,将您的IPv4地址打包成uint32_t(在<stdint.h>中定义),将最左边的八位字节用点分十进制表示法放入最重要的位。例如,

uint32_t ipv4_pack(const uint8_t octet1,
                   const uint8_t octet2,
                   const uint8_t octet3,
                   const uint8_t octet4)
{
    return (((uint32_t)octet1) << 24)
         | (((uint32_t)octet2) << 16)
         | (((uint32_t)octet3) <<  8)
         |  ((uint32_t)octet4);
}

及其逆,

unsigned char *ipv4_unpack(unsigned char *addr, const uint32_t packed)
{
    addr[3] = (uint8_t)(packed);
    addr[2] = (uint8_t)(packed >> 8);
    addr[1] = (uint8_t)(packed >> 16);
    addr[0] = (uint8_t)(packed >> 24);
    return addr;
}

128.64.32.16这样的地址被打包到0x80402010(128 == 80 16 ,64 == 40 16 ,32 == 20 16 ,16 = = 10 16 )。

您还需要将CIDR前缀大小(1到32)转换为设置了多个最高位的二进制掩码:

uint32_t ipv4_mask(const int prefix_size)
{
    if (prefix_size > 31)
        return (uint32_t)0xFFFFFFFFU;
    else
    if (prefix_size > 0)
        return ((uint32_t)0xFFFFFFFFU) << (32 - prefix_size);
    else
        return (uint32_t)0U;
}

前缀24对应于二进制的掩码11111111111111111111111100000000和十六进制的0xFFFFFF00。

前缀28对应于二进制的掩码11111111111111111111111111110000和十六进制的0xFFFFFFF0。

对于地址addr1.addr2.addr3.addr4/prefix,范围中的第一个地址(通常是所述范围的网关地址)是

uint32_t first = ipv4_pack(addr1, addr2, addr3, addr4) & ipv4_mask(prefix);

和最后一个地址(通常是所述范围的广播地址)是

uint32_t last = ipv4_pack(addr1, addr2, addr3, addr4) | (~ipv4_mask(prefix));

在所有情况下,first <= last,并从first迭代到last,包括在内,并调用ipv4_unpack()将值解压缩为点分十进制表示法),产生所有范围内的IPv4地址。

同样适用于IPv6,但需要类似uint128_t类型的内容。 (它可以使用较小的无符号整数类型进行模拟,当然,需要更多指令,但逻辑保持不变。)