It's blog about IT, software development, self improvement and so on...

Показаны сообщения с ярлыком scripting. Показать все сообщения
Показаны сообщения с ярлыком scripting. Показать все сообщения

четверг, 14 августа 2008 г.

network address aggregation script

It's personally for gescheit :)

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)