У меня есть список IPaddress / маска, которая должна быть преобразована в нотацию CIDR.
например, 12.174.36.240/24 необходимо преобразовать в 12.174.36.0/24
или что-то вроде того http://www.subnet-calculator.com/cidr.php делает
Как это может быть достигнуто?
PS: значение маски не всегда 24.
Просто чтобы привести вас в правильном направлении, подумайте, что такое адрес IPv4 (32-разрядное целое число). Теперь рассмотрим, что такое маска (битовое поле, используемое в побитовых операциях).
Возьмите адрес 127.0.0.1 в системе с прямым порядком байтов. В гексе это 0x7f000001
, 24-битная маска 0xffffff00
(24 бита по 1, 8 бит по 0, всего 32 бита). Побитовый и адрес и маска 0x7f000001 & 0xffffff00 = 0x7f000000
это формат CIDR
Я оставляю вам решать, как лучше всего проанализировать адрес, преобразовать адрес IPv4 в его целочисленную форму (и обратно) и создать битовую маску из маски префикса маршрутизации, хотя я скажу вам, что существуют стандартные функции для меньше всего манипулирование адресом.
Таким образом, в основном IPV4-адрес и маска сети представляют собой 32-битное целое число без знака, отображаемое в парах по 8 бит с точкой между ними.
Так что если у вас есть «a.b.c.d», вы можете получить целочисленное значение, выполнив
(a<<24) + (b<<16) + (c<<8) + d
Если вы не привыкли к << он сдвигает биты числа влево на количество раз в качестве правого аргумента. Таким образом a<<b
такой же как a*2^b
Теперь в CIDR число после косой черты говорит вам, сколько битов (из 32) являются частью числа перед косой чертой. например. 10.10.10.1/28 имеет 28 битную сеть и 32-28 = 4 битную хостовую часть. Это означает, что если вы берете ip и переводите его в число (= 0x0A0A0A01) и делаете логический &
с 0xFFFFFFFF<<4 (= 0xFFFFFFF0) вы получите 0x0A0A0A00. Если вы переведете это обратно в IP со следующим:
sprintf("%d.%d.%d.%d", (n>>24)&0xff, (n>>16)&0xff, (n>>8)&0xff, n&0xff)
Вы получаете 10.10.10.0. Также, если вы переведете 0xFFFFFFF0 в ip с тем же алгоритмом, вы получите 255.255.255.248, то есть маску сети, которая соответствует длине маски 28.
IPv6 точно такой же, за исключением того, что 128 битов разделены на 8 16-битных кластеров, отображаемых в шестнадцатеричном виде с запятыми между ними с некоторыми причудливыми ярлыками для нескольких прогонов 0 (: 🙂 ..
например.
fe80::52e5:49ff:ffc9:1889/64 ==
;;convert the mask
0xffffffffffffffffffffffffffffffff << (128-64) =
0xffffffffffffffff0000000000000000
;;convert the ip:
fe80::52e5:49ff:ffc9:1889 ==
fe80:0000:0000:0000:52e5:49ff:ffc9:1889 ==
0xfe8000000000000052e549ffffc91889
0xfe8000000000000052e549ffffc91889
& 0xffffffffffffffff0000000000000000
= 0xfe800000000000000000000000000000
;;convert first address in range back to string:
fe80:0000:0000:0000:0000:0000:0000:0000 =
fe80::
Я думаю, что на основе этого вы можете сделать функцию, которая делает то, что вы хотите.