【问题标题】:All IP's in a subnet (C)子网中的所有 IP (C)
【发布时间】:2016-11-23 21:00:00
【问题描述】:

有人有一个很好的例子来说明我可以使用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++; 
}

只要我能理解就可以了。

如果您认为对我有帮助,请随时评论帖子的链接。

编辑:可能值得一提的是我发现了很多计算广播地址等的东西我只是不确定如何将所有这些函数链接在一起。

【问题讨论】:

  • 目前只有两个 IP:IPv4 和 IPv6。我认为您的意思是 IP 地址,而不是 IP(互联网协议)。
  • @Ron Maupin 是的,这就是我的意思。为清晰起见进行了编辑

标签: c networking cidr netmask


【解决方案1】:

首先,将您的 IPv4 地址打包成一个 uint32_t(在 &lt;stdint.h&gt; 中定义),将最左边的八位字节以点分十进制表示法放入最高有效位。例如,

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 == 8016, 64 == 4016, 32 == 2016 和 16 == 1016)。


您还需要将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 &lt;= last 并从 first 迭代到 last(含)并调用 ipv4_unpack() 将值解压缩为点分十进制表示法),生成范围内的所有 IPv4 地址。


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

【讨论】:

    猜你喜欢
    • 2012-08-26
    • 2011-03-14
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 2013-06-09
    • 2012-12-02
    • 2014-02-09
    • 1970-01-01
    相关资源
    最近更新 更多