4

I have a list of ipaddress/mask which needs to be converted to CIDR notation.

for e.g. 12.174.36.240/24 needs to be converted to 12.174.36.0/24 or something like what http://www.subnet-calculator.com/cidr.php does

How can this be acheived?

PS: the mask value is not always 24.

chingupt
  • 403
  • 2
  • 7
  • 19

2 Answers2

4

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.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
Sylwester
  • 47,942
  • 4
  • 47
  • 79
  • 1
    Thanks. I found a similiar approach on the net also. However i was looking for some standard c++ libraries which perform a similiar task? I guess there are not hence will have to device my own function for this. Will post the code once done. – chingupt Dec 14 '13 at 04:11
2

Just to lead you in the right direction, consider what an IPv4 address is (a 32-bit integer). Now, consider what a mask is (a bit field used in bitwise operations).

Take the address 127.0.0.1 on a big-endian system. In hex, that's 0x7f000001. A 24-bit mask is 0xffffff00 (24 bits of 1, 8 bits of 0, 32 bits total). The bitwise and of the address and the mask 0x7f000001 & 0xffffff00 = 0x7f000000 is the CIDR format.

I leave it to you to determine how best to parse the address, convert the IPv4 address to its integer form (and back), and create a bit mask from a routing prefix mask, though I will tell you that there are standard functions for at least the address manipulation.

Elliot Robinson
  • 1,384
  • 7
  • 16