23

How can I convert a ipv4 subnet mask to cidr notation using netaddr library?
Example: 255.255.255.0 to /24

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
Mik
  • 349
  • 1
  • 2
  • 4

5 Answers5

48

Using netaddr:

>>> from netaddr import IPAddress
>>> IPAddress('255.255.255.0').netmask_bits()
24

Using ipaddress from stdlib:

>>> from ipaddress import IPv4Network
>>> IPv4Network('0.0.0.0/255.255.255.0').prefixlen
24

You can also do it without using any libraries: just count 1-bits in the binary representation of the netmask:

>>> netmask = '255.255.255.0'
>>> sum(bin(int(x)).count('1') for x in netmask.split('.'))
24
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • Could the reverse i.e. cidr to netmask be done in a one liner? – Bilal Baqar May 26 '17 at 15:48
  • 1
    @Bilal check this [post](https://stackoverflow.com/q/23352028/244297). TLDR: `netmask = '.'.join([str((0xffffffff << (32 - prefix) >> i) & 0xff) for i in [24, 16, 8, 0]])` – Eugene Yarmash May 26 '17 at 15:54
7

Use the following function. it is fast, reliable, and don't use any library.

# code to convert netmask ip to cidr number
def netmask_to_cidr(netmask):
    '''
    :param netmask: netmask ip addr (eg: 255.255.255.0)
    :return: equivalent cidr number to given netmask ip (eg: 24)
    '''
    return sum([bin(int(x)).count('1') for x in netmask.split('.')])
Markus
  • 101
  • 6
IAmSurajBobade
  • 353
  • 6
  • 15
6
>>> IPNetwork('0.0.0.0/255.255.255.0').prefixlen
24
Derek Chadwell
  • 696
  • 1
  • 8
  • 22
3

As of Python 3.5:

import ipaddress
ip4 = ipaddress.IPv4Network((0,'255.255.255.0'))
print(ip4.prefixlen)
print(ip4.with_prefixlen)

will print:

24
0.0.0.0/24

gerardw
  • 5,822
  • 46
  • 39
1

How about this one? It does not need any additional library as well.

def translate_netmask_cidr(netmask):
    """
    Translate IP netmask to CIDR notation.
    :param netmask:
    :return: CIDR netmask as string
    """
    netmask_octets = netmask.split('.')
    negative_offset = 0

    for octet in reversed(netmask_octets):
        binary = format(int(octet), '08b')
        for char in reversed(binary):
            if char == '1':
                break
            negative_offset += 1

    return '/{0}'.format(32-negative_offset)

It is in some ways similar to IAmSurajBobade's approach but instead does the lookup reversed. It represents the way I would do the conversion manually by pen and paper.

kb-0
  • 98
  • 5