子网中的所有 IP (C)
All IP's in a subnet (C)
有没有人有一个很好的例子,我可以用一个 CIDR 的 IP 地址,例如 192.168.1.1/24
和 return 该范围内的所有 IP 地址,例如 192.168.1.1, 192.168.1.2, 192.168.1.3 ...
我可以将其 return 编入 unsigned long
、char
或类似
的数组中
/* Pseudocode */
while(currnetip <= finalip) {
print(currnetip);
currnetip++;
}
只要我能看懂就可以了
如果您认为对我有帮助,请随时评论 link 到 post。
编辑:可能值得一提我发现了很多计算广播地址的东西我只是不确定如何link所有这些函数在一起。
首先,将您的 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 == 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 <= last
,并从 first
迭代到 last
,包括在内,并调用 ipv4_unpack()
将值解压缩为点分十进制表示法),产生范围内的所有 IPv4 地址。
同样适用于 IPv6,但需要类似 uint128_t
的类型。 (它可以用更小的无符号整数类型来模拟,当然,多走几条指令,但逻辑保持不变。)
有没有人有一个很好的例子,我可以用一个 CIDR 的 IP 地址,例如 192.168.1.1/24
和 return 该范围内的所有 IP 地址,例如 192.168.1.1, 192.168.1.2, 192.168.1.3 ...
我可以将其 return 编入 unsigned long
、char
或类似
/* Pseudocode */
while(currnetip <= finalip) {
print(currnetip);
currnetip++;
}
只要我能看懂就可以了
如果您认为对我有帮助,请随时评论 link 到 post。
编辑:可能值得一提我发现了很多计算广播地址的东西我只是不确定如何link所有这些函数在一起。
首先,将您的 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 == 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 <= last
,并从 first
迭代到 last
,包括在内,并调用 ipv4_unpack()
将值解压缩为点分十进制表示法),产生范围内的所有 IPv4 地址。
同样适用于 IPv6,但需要类似 uint128_t
的类型。 (它可以用更小的无符号整数类型来模拟,当然,多走几条指令,但逻辑保持不变。)