Script actually aggregate list of network address to subnet, and some classes/bicycle under it :)
#!/usr/bin/env python
import socket
import struct
import sys
class Address():
""" Class for basic network address representation"""
def __init__(self, value):
if type(value) == type("str"):
if value.find(".") != -1: # symbol dot notation
self.data = self._fromDot(value)
elif value.isdigit():
# most probably integer notation
self.data = self._fromInt(value)
else:
raise ValueError, 'unknown data format'
else:
print "unreachable point reached!\n"
def toInt(self):
return struct.unpack(">I", self.data)[0]
def toString(self):
arr = struct.unpack("BBBB", self.data)
result = str(arr[0])
for i in xrange(1,4):
result += "." + str(arr[i])
return result
def toHex(self):
arr = struct.unpack("BBBB", self.data)
result = ""
for i in xrange(0,4):
result += "%02X" % arr[i]
return result
def __str__(self):
return self.toString()
def _fromInt(self, value):
return struct.pack("I", int(value))
def _fromDot(self, value):
return socket.inet_aton(value)
EMPTY_MASK = 0
FULL_MASK = 2**32
class NetMask(Address):
""" Class for network mask representation
and some net address netmask operations"""
def __init__(self, value):
if value is None:
self.data = self._fromInt(EMPTY_MASK)
if type(value) == type("str"):
if value.find(".") != -1: # symbol dot notation
self.data = self._fromDot(value)
elif value.find("/") != -1: # netmask notation
self.data = self._fromMask(value)
elif value.isdigit():
# most probably integer notation
self.data = self._fromInt(value)
else:
raise ValueError, 'unknown data format'
else:
print "unreachable point reached!\n"
def _fromMask(self, mask):
m = int(mask[mask.find("/")+1:])
result = 2 ** 32 - (2 ** (32 - m))
return struct.pack(">I", result)
def apply(self, ip):
mask = self.toInt()
net = ip & mask
host = ip ^ net
return net, host
def toMask(self):
mask = self.toInt()
xmask = 2**32 - 2**31
if mask == FULL_MASK:
return "/32"
for i in xrange(31, 0, -1):
tmask = xmask >> (32 - i)
if (mask & tmask) == 0:
return "/%s" % (32-i)
return "/0"
def aggregate(address_list):
for i in xrange(32, 0, -1):
complete = True
net = None
mask = NetMask("/%s" % i)
for ip in address_list:
a = Address(ip)
(curnet, curhost) = mask.apply(a.toInt())
if net is None:
net = curnet
continue
if net != curnet:
# go to check next mask
complete = False
break
if complete:
# mask is ok for all hosts
break
return "Result mask: %s (%s)" % (mask.toString(), mask.toMask())
usage = """
usage:
./ipcalc.py aggregate < address list >
"""
# test input
# sys.argv = ["scriptname", "aggregate", "10.0.0.21", "10.0.10.7", "10.0.14.1", "10.15.0.1"]
if len(sys.argv) > 1:
command = sys.argv[1]
addresses = sys.argv[2:]
if "aggregate" == command:
print aggregate(addresses)
else:
print usage
sys.exit(1)
else:
print usage
sys.exit(1)