convert cidr to subnet mask in python
Asked Answered
A

5

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?

Angulo answered 17/11, 2015 at 6:8 Comment(2)
Your data is not dictionary as you mentioned!Anglice
If it helps to see an example, I made a class that does this here.Nodababus
P
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')
Paphos answered 17/11, 2015 at 6:39 Comment(1)
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: gist.github.com/Torxed/148303f1677e56dcca794386e90299fcPostcard
E
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.

Elvaelvah answered 11/5, 2017 at 0:24 Comment(0)
P
11

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')
Purnell answered 9/11, 2018 at 19:28 Comment(2)
apt install python-netaddrGustafson
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.Triptych
C
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
Cantor answered 17/11, 2015 at 6:28 Comment(0)
M
0

Here is one I made:

def cidr_to_netmask(cidr) -> str:
    cidr = int(cidr)
    mask_bin = f"{'1'*cidr}{'0'*(32-cidr)}"
    out = f"{int(mask_bin[0:8], 2)}.{int(mask_bin[8:16], 2)}.{int(mask_bin[16:24], 2)}.{int(mask_bin[24:32], 2)}"
    return out
Masera answered 21/2, 2024 at 22:21 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.