2016-11-23 60 views
0

是否有人有一种方法,我可以采取以CIDR一个IP地址,如192.168.1.1/24并返回范围如192.168.1.1, 192.168.1.2, 192.168.1.3 ...全部IP子网中(C)

我里面所有的IP地址一个很好的例子没事用它的unsigned long一个数组中返回,一个char或者只是像

/* Pseudocode */ 
while(currnetip <= finalip) { 
    print(currnetip); 
    currnetip++; 
} 

只要我能理解它的罚款。

如果您认为它可以帮助我,请随时评论一篇文章的链接。

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

+0

只有两个当前IP:IPv4和IPv6。我认为你的意思是IP地址,而不是IP(互联网协议)。 –

+0

@Ron Maupin是的,这就是我的意思。为清晰起见进行编辑 –

回答

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 ,64 == 40 ,32 == 20 和16 == 10 )。


您需要的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以及从firstlast(包括端点)的迭代,并且调用ipv4_unpack()将该值解包为点分十进制表示法),将所有IPv4地址 范围。


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