Во-первых, упакуйте свой 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 соответствует маске 1111111111111111111111100000000 в двоичном формате и 0xFFFFFF00 в шестнадцатеричном.
Префикс 28 соответствует маске 1111111111111111111111111110000 в двоичном формате и 0xFFFFFFFF0 в шестнадцатеричном.
Для адреса 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
. (Конечно, его можно эмулировать с меньшими целочисленными типами без знака, выполнив несколько дополнительных инструкций, но логика останется прежней.)
person
Nominal Animal
schedule
23.11.2016