ActiveState Code

Recipe 576483: Convert Subnetmask from CIDR notation to dot.decimal form


How to convert the CIDR notation (192.168.0.0/24) of a subnetmask to the dotted decimal form (255.255.255.0).

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python

import sys

def usage():
    print "Call : %s <BitCount>" % sys.argv[0]
    print " shows the dotted netmask (i.e %s 24  => 255.255.255.0)"  % sys.argv[0]


def calcDottedNetmask(mask):
    bits = 0
    for i in xrange(32-mask,32):
        bits |= (1 << i)
    return "%d.%d.%d.%d" % ((bits & 0xff000000) >> 24, (bits & 0xff0000) >> 16, (bits & 0xff00) >> 8 , (bits & 0xff))

if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1].isdigit():
        print calcDottedNetmask(int(sys.argv[1]))
    else:
        usage()

Comments

  1. 1. At 1:12 p.m. on 3 sep 2008, David Moss said:

    Actually, the following drops the looping construct and is over 4x faster!

    from socket import inet_ntoa
    from struct import pack
    
    ...
    
    def calcDottedNetmask(mask):
        bits = 0xffffffff ^ (1 << 32 - mask) - 1
        return inet_ntoa(pack('>I', bits))
    
  2. 2. At 3:06 p.m. on 3 sep 2008, David Moss said:

    Nice bit of logic which I'll likely add to the netaddr project in due course ;-)

    I would change the return statement slightly to improve readability (and save some typing).

    from socket import inet_ntoa
    from struct import pack
    
    ...
    
    def calcDottedNetmask(mask):
        bits = 0
        for i in xrange(32-mask,32):
            bits |= (1 << i)
        return inet_ntoa(pack('>I', bits))
    
    ...
    

    Also, a range check for the mask argument might be a good idea as the calcDottedNetmask() function currently accepts negative values such as -1, albeit returning a 'safe' 0.0.0.0, which should probably more correctly raise an error.

    Dave M.

Sign in to comment