So basically an IPV4-address and netmask are 32 bit unsigned integer displayed in pairs of 8 bit with a dot between them.
So if you have "a.b.c.d" you could get the integer value by doing
(a<<24) + (b<<16) + (c<<8) + d
If you're not used to the << it's shifts the bits in the number to the left the number of times as the right argument.. Thus a<<b
is the same as a*2^b
Now in a CIDR the number after the slash tells you how many bits (of 32) that are the network part of the number before the slash. eg. 10.10.10.1/28 has 28 bits network and 32-28=4 bits host part. That means that if you take the ip and translate it to a number (=0x0A0A0A01) and do a logical &
with 0xFFFFFFFF<<4 (= 0xFFFFFFF0) you get 0x0A0A0A00. If you translate that back to a ip with the following:
sprintf("%d.%d.%d.%d", (n>>24)&0xff, (n>>16)&0xff, (n>>8)&0xff, n&0xff)
You get 10.10.10.0. Also if you translate 0xFFFFFFF0 to a ip with the same algorithm you get 255.255.255.248 which is the netmask that corresponds to mask length 28.
IPv6 is exactly the same, except it's 128 bits divided in 8 16 bit clusters displayed in hex with commas between them with some fancy shortcut for multiple runs of 0 (::)..
eg.
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::
I guess that on the basis of this you can make a function that does what you want.