Tuesday, May 7, 2013

Python CIDR Subnet Calculator, 'IP to long', and IP range to CIDR

This collection of scripts is useful for converting and working with IP address data in an application. They were scattered around before now. I did not write these and I don't remember where I found them. Enjoy.

Source code at the bottom of the post.

Python CIDR Subnet Calculator


$ ./subnet.py 74.125.226.201/26
Address:  74.125.226.201
Netmask:  255.255.255.192
Network:  74.125.226.192
Broadcast:  74.125.226.255

Input an IP address in CIDR notation and the script will calculate the subnet mask, the network address and the broadcast address. 


IP address to long integer


When working with IP addresses in (MySQL) databases, it is best to store each IPv4 address as its 'long integer' value. For example:

$ ./ip2long.sh 192.168.1.100
3232235876


$ ./ip2long.sh 192.168.1.101
3232235877


Note how the integer and IP address incremented by one. All IP addresses have an integer equivalent. 

Long integer to IP address


This converts the input of a long integer into the IPv4 address.
$ ./long2ip.sh 3232235877
192.168.1.101

IP Range to CIDR notation


This little gem (perl?) is good when you need the CIDR notation from a range of IP addresses. For example:
$ ./range2cidr.pl 10.25.0.0-10.28.255.255
10.25.0.0/16
10.26.0.0/15
10.28.0.0/16
And for those who will be using this to configure routers, Cisco gear, etc. Take the output of the range2cidr script and use the subnet.py script:

$ ./subnet.py 10.25.0.0/16
Address:  10.25.0.0
Netmask:  255.255.0.0
Network:  10.25.0.0
Broadcast:  10.25.255.255
$ ./subnet.py 10.26.0.0/15
Address:  10.26.0.0
Netmask:  255.254.0.0
Network:  10.26.0.0
Broadcast:  10.27.255.255

Wunderbar! Ok, source code:




Python CIDR Subnet Calculator 


#!/usr/bin/env python
# python subnet.py 200.100.33.65/26

import sys

# Get address string and CIDR string from command line
(addrString, cidrString) = sys.argv[1].split('/')

# Split address into octets and turn CIDR into int
addr = addrString.split('.')
cidr = int(cidrString)

# Initialize the netmask and calculate based on CIDR mask
mask = [0, 0, 0, 0]
for i in range(cidr):
    mask[i/8] = mask[i/8] + (1 << (7 - i % 8))

# Initialize net and binary and netmask with addr to get network
net = []
for i in range(4):
    net.append(int(addr[i]) & mask[i])

# Duplicate net into broad array, gather host bits, and generate broadcast
broad = list(net)
brange = 32 - cidr
for i in range(brange):
    broad[3 - i/8] = broad[3 - i/8] + (1 << (i % 8))

# Print information, mapping integer lists to strings for easy printing
print "Address: " , addrString
print "Netmask: " , ".".join(map(str, mask))
print "Network: " , ".".join(map(str, net))
print "Broadcast: " , ".".join(map(str, broad))





IP address to long integer 


#!/bin/bash

INET_ATON() { #{{{
    local IFS=. ip num e
    ip=($1)
    for e in 3 2 1
    do
        (( num += ip[3-e] * 256 ** e ))
    done
    (( num += ip[3] ))
    echo $num
} #}}}

echo `INET_ATON $1`






Long integer to IP address


#!/bin/bash

INET_NTOA() { #{{{
    local IFS=. num quad ip e
    num=$1
    for e in 3 2 1
    do
        (( quad = 256 ** e))
        (( ip[3-e] = num / quad ))
        (( num = num % quad ))
    done
    ip[3]=$num
    echo "${ip[*]}"
} #}}}

echo `INET_NTOA $1`





IP range to CIDR notation routes

Note the dependency on Perl CPAN module Net::CIDR 
To install on Ubuntu: sudo cpan to open CPAN, followed by install Net::CIDR

#!/usr/bin/perl -w
# range2cidr.pl
# sudo cpan > install Net::CIDR


use Net::CIDR;
use Net::CIDR ':all';

if (@ARGV == 0) {
  die "Usage Example: $0 192.168.0.0-192.168.255.255 \n";
}

print join("\n", Net::CIDR::range2cidr("$ARGV[0]")) . "\n";




No comments:

Post a Comment