4

I am trying to write a script which breaks down subnets larger(not greater than /16) than /24 to a /24 subnet. Eg : 10.10.10.0/23 should give me 10.10.10.0/24 and 10.10.11.0/24

My logic is to first scan for the CIDR mask. if smaller than 24, then subtract that from 24 and that number(lets say x) gives the total number of /24s and then 1 to third octet of the IP x times and /24.

eg: 10.10.8.0/22

if 22 < 24 
x = 24-22 = 2
total # of /24s = 2^x = 4
So output :
10.10.8.0/24
10.10.9.0/24 
10.10.10.0/24
10.10.11.0/24

I am not sure how to code/modify the string for the third octet only and add 1 to the third octet only.

I am thinking of creating a list of all the third octet values and re constructing the IPs. But if there is a simpler way out there, that would help me a lot !!

Thanks !

poke
  • 369,085
  • 72
  • 557
  • 602
skd
  • 45
  • 1
  • 5
  • I am not asking for the code here, just a direction / few links on how to approach should be good to go. thanks ! – skd Mar 07 '15 at 21:34
  • Maybe try not to work with the decimal-dot notation, but the binary (or decimal, if you like) one. If you have a `IP/N` subnet, you want to generate all 24-bit numbers from 0 to `2^(24 - N) - 1`, add them to your base IP address, and you got yourself all prefixes for your `/24` subnets. Then you can convert them back to the decimal-dot notation if you like. – Carsten Mar 07 '15 at 21:41
  • @Carsten But I will still have the "dots" The dots dont go away if i convert to binary eg : 192.168.1.1 == 11000000.10101000.00000001.00000001 – skd Mar 07 '15 at 21:49
  • 1
    The dots are just there as a delimiter for you and fellow humans who have to enter these addresses. The string representation "192.168.1.1" is the same as the binary representation "11000000101010000000000100000001" and the same as the decimal representation "3232235777". – Carsten Mar 07 '15 at 21:54
  • @Carsten .. duh,, my bad.. human error(layer 8 issue) thanks for your ideas. i see its definitely possible that way – skd Mar 08 '15 at 15:32

2 Answers2

6

If you're using Python 3.3 or newer, you can use the ipaddress module. Using the subnets method, you can do it in one line:

>>> list(ipaddress.ip_network('10.10.8.0/22').subnets(new_prefix=24))
[IPv4Network('10.10.8.0/24'), IPv4Network('10.10.9.0/24'), IPv4Network('10.10.10.0/24'), IPv4Network('10.10.11.0/24')]

Converting to strings is trivial. Just cast to str.

Carsten
  • 17,991
  • 4
  • 48
  • 53
  • I am still using py 2.7. But I will up-vote this since the output shows what I need ! thanks ! – skd Mar 08 '15 at 15:33
4

Take a look at the netaddr package. It already comes with built-in support for understanding net masks and is able to generate a list of subnets for any desired length:

>>> n = netaddr.IPNetwork('10.10.8.0/22')
>>> list(n.subnet(24))
[IPNetwork('10.10.8.0/24'), IPNetwork('10.10.9.0/24'), IPNetwork('10.10.10.0/24'), IPNetwork('10.10.11.0/24')]
>>> [str(sn) for sn in n.subnet(24)]
['10.10.8.0/24', '10.10.9.0/24', '10.10.10.0/24', '10.10.11.0/24']

Since Python 3.3, this functionality is also available in the new built-in ipaddress module.

poke
  • 369,085
  • 72
  • 557
  • 602