
from __future__ import print_function

"""
RCSid:
	$Id: iputils.py,v 1.3 2015/05/30 03:01:01 sjg Exp $

	@(#) Copyright (c) 2012 Simon J. Gerraty

	This file is provided in the hope that it will
	be of use.  There is absolutely NO WARRANTY.
	Permission to copy, redistribute or otherwise
	use this file is hereby granted provided that 
	the above copyright notice and this notice are
	left intact. 
      
	Please send copies of changes and bug-fixes to:
	sjg@crufty.net

"""

def int2octets(n):
    o = []
    for i in range(4):
        o.append(n & 0xff)
        n >>= 8
    o.reverse()
    return o

def ip2octets(ip):
    return list(map(int, ip.split('.')))

def int2ip(n):
    """convert a number to dotted quad"""
    octets = int2octets(n)
    return '.'.join(map(str, octets))

def ip2int(ip):
    """convert IP address to an number"""
    octets = ip2octets(ip)
    n = 0
    for i in octets:
        n <<= 8
        n |= i
    return n

def mask2int(mask):
    """convert mask to a number
    mask can be /bits or a dotted quad"""
    if mask.find('.') > 0:
        return ip2int(mask)
    if mask.startswith('0x'):
        return int(mask, base=16)
    # assume it is /bits or just bits
    bits = int(mask.lstrip('/'))
    if bits == 32:
        return 0xffffffff
    elif bits == 0:
        return 0
    n = ~((1<<(32 - bits)) - 1) & 0xffffffff
    return n

def netmask(ip, mask=None):
    if not mask:
        octets = ip2octets(ip)
        if octets[0] < 128:
            return 0xff000000
        if octets[0] < 192:
            return 0xffff0000
        return 0xffffff00
    return mask2int(mask)

def mask2bits(m):
    hm = ~m & 0xffffffff
    n = 0
    if hm == 0:
        return 0
    for b in range(32):
        n |= (1<<b)
        if n == hm:
            return b
    
def ip2cidr(ip, mask=None):
    m = netmask(ip, mask)
    i = ip2int(ip)
    b = mask2bits(m)
    n = i & m
    return '{}/{}'.format(int2ip(n),b)

def cidr_range_int(ip, mask=None):
    m = netmask(ip, mask)
    i = ip2int(ip)
    n = i & m;
    x = 0
    bits = mask2bits(m)
    for j in range(bits):
        x |= (1<<j)
    return n,n+x

def cidr_range_ip(ip, mask=None):
    s,e = cidr_range_int(ip, mask)
    return int2ip(s),int2ip(e)

if __name__ == '__main__':
    import sys
    import getopt

    masks= []
    
    opts,args = getopt.getopt(sys.argv[1:], 'm:')
    for o,a in opts:
        if o == '-m':
            masks.append(a)

    if len(masks) != 0:

        for msk in masks:
            m = mask2int(msk)
            dm = int2ip(m)
            hm = hex(m)
            print('mask:',msk,hm,dm)

            for ip in args:
                print(ip,dm)
                print(ip2cidr(ip,msk))
                s,e = cidr_range_ip(ip,msk)
                print(s,e)
        sys.exit(0)
        
    for ip in args:
        print(ip)
        i = ip2int(ip)
        print(hex(i))
        o = ip2octets(ip)
        print(o)
        m = netmask(ip)
        print(hex(m))
        n = i & m
        print(hex(n))
        print(int2ip(n))

        for msk in ['/16', '255.254.0.0']:
            m = mask2int(msk)
            print('mask:',msk,hex(m))

            n = i & m
            print(hex(n))
            print(int2ip(n))
    
