11

I have a python dictionary that I've created, this dictionary contains a list of subnets in the following format:

x.x.x.x/24
y.y.y,y/25
z.z.z.z/26
a.a.a.a/27 

etc...

I would like to take the items in this dictionary, parse it, then spit out the results in the following format:

x.x.x.x 255.255.255.0
y.y.y.y 255.255.255.128
x.x.x.x 255.255.255.192
a.a.a.a 255.255.255.224 

I don't have much on this as of right now because I can't find a lot on this topic on the web, not anything that can be in a quick and concise way that is. Thoughts?

falsetru
  • 357,413
  • 63
  • 732
  • 636
just1han85
  • 313
  • 1
  • 4
  • 14

4 Answers4

15

Code:

import socket
import struct

def cidr_to_netmask(cidr):
    network, net_bits = cidr.split('/')
    host_bits = 32 - int(net_bits)
    netmask = socket.inet_ntoa(struct.pack('!I', (1 << 32) - (1 << host_bits)))
    return network, netmask

Usage:

>>> cidr_to_netmask('10.10.1.32/27')
('10.10.1.32', '255.255.255.224')
>>> cidr_to_netmask('208.128.0.0/11')
('208.128.0.0', '255.224.0.0')
>>> cidr_to_netmask('208.130.28.0/22')
('208.130.28.0', '255.255.252.0')
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • Goes without saying, but for the IPv6 initiated. CIDR is the official notation for IPv6, there for netmask is not a thing anymore. But if you still wanted to, you could do it: https://gist.github.com/Torxed/148303f1677e56dcca794386e90299fc – Torxed Jan 07 '22 at 15:40
11

I thought I'd throw in my own solution, since I was going for a little bit more readability in it than the other answers shown.

def cidr_to_netmask(cidr):
  cidr = int(cidr)
  mask = (0xffffffff >> (32 - cidr)) << (32 - cidr)
  return (str( (0xff000000 & mask) >> 24)   + '.' +
          str( (0x00ff0000 & mask) >> 16)   + '.' +
          str( (0x0000ff00 & mask) >> 8)    + '.' +
          str( (0x000000ff & mask)))

It's now easier to see what's going on, and that is:

  1. Get the numeric mask by padding the front with 1s and having the cidr make up the rest
  2. For each bit, apply the mask
  3. Concatenate all the bits together, separated by periods

This is very procedural and does not use any libraries.

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Dave
  • 3,428
  • 30
  • 28
10

Try this solution:

Python3

from ipaddress import IPv4Network

networks = {'n1':'10.1.0.0/21','n2':'10.2.0.0/22','n3':'10.3.0.0/23','n4':'10.4.0.0/24'}

for x,y in enumerate(networks):
    print(IPv4Network(networks[y]).network_address, IPv4Network(networks[y]).netmask)

Result:

10.1.0.0 255.255.248.0
10.2.0.0 255.255.252.0
10.3.0.0 255.255.254.0
10.4.0.0 255.255.255.0

Python2

from netaddr import IPNetwork

networks = {'n1':'10.1.0.0/21','n2':'10.2.0.0/22','n3':'10.3.0.0/23','n4':'10.4.0.0/24'}

for x,y in enumerate(networks):
    print(str(IPNetwork(networks[y]).network), str(IPNetwork(networks[y]).netmask))

Result:

('10.1.0.0', '255.255.248.0')
('10.2.0.0', '255.255.252.0')
('10.3.0.0', '255.255.254.0')
('10.4.0.0', '255.255.255.0')
  • `apt install python-netaddr` – xinthose Dec 06 '18 at 22:54
  • https://pypi.org/project/ipaddress/ is a "Port of the 3.3+ ipaddress module to 2.6, 2.7, 3.2" in case you still need to maintain Python2 code and want to use `ipaddress`. – yaobin Jan 06 '22 at 21:51
0

Try this

lsIP = []
ans = 0
CIDR = 32
IP = [1] * CIDR
for i in range(len(IP)):
    iIdx = i % 8
    if iIdx == 0:
        if i >= 8:
            lsIP.append(ans)
            ans = 0
    ans += pow(2, 7 - iIdx)
lsIP.append(ans)

[lsIP.append(0) for i in range(4 - len(lsIP))]
print lsIP
Mangu Singh Rajpurohit
  • 10,806
  • 4
  • 68
  • 97