'''
version 1.00
IP address object class
October 2014
author: Guillermo Gomez (a.k.a Momo)
'''
import socket
import struct
class IP_addr(object):
'''
Defines an object containing an IP address, mask, prefix length, network
and a description of problems found in object manipulation.
address 'x.x.x.x'
prefix prefix length (integer from 0 to 32)
In case, prefix info is preferred to mask info
mask 'm.m.m.m'
network 'n.n.n.n'
error_description error description string
'''
def __init__(self, proposal=''):
'''
Tries to fill the object from an string in usual dot notation
'x.x.x.x/nn' or 'x.x.x.x/m.m.m.m'
Prefix or mask is optional
'''
if proposal <> '': # if there is one proposal analyze it
(self.address, morp, self.mask) = proposal.partition('/')
self.error_description = ''
if self.mask == '': # no mask means it's a host
self.prefix = 32
self.mask = '255.255.255.255'
if self.validate_address(): # IP must be valid
if self.validate_mask():
self.calculate_prefix()
else:
self.error_description = ''
try: # take care, prefix lenght is an integer
self.prefix = int (self.mask)
if self.validate_prefix():
self.calculate_mask()
else:
self.mask = '255.255.255.255'
self.error_description = 'Invalid Prefix Length'
except:
self.prefix = 32
self.mask = '255.255.255.255'
self.error_description = 'Invalid Mask/Prefix'
self.calculate_network()
else:
self.set_default()
self.error_description = 'Invalid Address'
else:
self.set_default()
def set_default(self):
'''
Set object to default values:
address = '127.0.0.1'
prefix = 32
mask = '255.255.255.255'
network = ''
error_descrition = ''
'''
self.address = '127.0.0.1'
self.prefix = 32
self.mask = '255.255.255.255'
self.network = ''
self.error_description = ''
def validate_address(self):
'''
Checks if the objects contains a valid IP Address
returns a bool
possible error 'Invalid Address'
'''
add_list = self.address.split ('.',3)
if len (add_list) == 4:
for i in range (0,4):
if add_list[i].isdigit():
if int(add_list[i]) < 0 or int(add_list[i]) > 255:
self.error_description = 'Invalid Address'
return False
else:
self.error_description = 'Invalid Address'
return False
else:
self.error_description = 'Invalid Address'
return False
self.error = ''
return True
def validate_mask(self):
'''
Checks if the objects contains a valid IP Mask
returns bool
possible error 'Invalid Mask'
'''
msk_list = self.mask.split ('.',3)
valid = ('255', '254', '252', '248', '240', '224', '192', '128', '0')
if len (msk_list) == 4:
for i in range (0,4):
if msk_list[i].isdigit():
if msk_list[i] not in valid:
self.error_description = 'Invalid Mask'
return False
elif msk_list[i] <> '255':
valid = ('0')
else:
self.error_description = 'Invalid Mask'
return False
else:
self.error_description = 'Invalid Mask'
return False
self.error = ''
return True
def validate_prefix(self):
'''
Checks if the objects contains a valid IP Prefix
returns bool
possible error 'Invalid Prefix Length'
'''
if self.prefix >= 0 and self.prefix <=32:
self.error = ''
return True
else:
self.prefix = 32
self.error_description = 'Invalid Prefix Length'
return False
def calculate_prefix(self):
'''
Calculates Prefix Length from Mask information
On error resets mask and prefix
'''
if self.validate_mask():
prfx_dict = {255:8, 254:7, 252:6, 248:5, 240:4, 224:3, 192:2, 128:1, 0:0}
self.prefix = 0
msk_list = self.mask.split ('.',3)
for i in range (0,4):
self.prefix += prfx_dict[int(msk_list[i])]
else:
self.prefix = 32
self.mask = '255.255.255.255'
def calculate_mask(self):
'''
Calculates Mask from Prefix Length information
On error resets mask and prefix
'''
valid_dict = {8:'255', 7:'254', 6:'252', 5:'248', 4:'240', 3:'224', 2:'192', 1:'128', 0:'0'}
if self.validate_prefix():
index = self.prefix
if self.prefix < 9:
index = self.prefix
self.mask = '{}.0.0.0'.format(valid_dict[index])
elif self.prefix < 17:
index = self.prefix - 8
self.mask = '255.{}.0.0'.format(valid_dict[index])
elif self.prefix < 25:
index = self.prefix - 16
self.mask = '255.255.{}.0'.format(valid_dict[index])
else:
index = self.prefix - 24
self.mask = '255.255.255.{}'.format(valid_dict[index])
else:
self.mask = '255.255.255.255'
self.prefix = 32
def calculate_network(self):
'''
Calculates Network address from IP Address and Prefix information
If there is no prefix info it tries from Mask info.
On error resets mask and prefix or even the whole object
'''
if self.validate_address(): # need a valid address
if not self.validate_prefix(): # there is no prefix info
self.calculate_prefix()
address = socket.inet_aton(self.address)
network = struct.unpack ('BBBB', address)
net0, net1, net2, net3 = network
if self.prefix < 9:
net0 = net0 >> (8 - self.prefix) << (8 - self.prefix)
net1 = net2 = net3 = 0
elif self.prefix < 17:
net1 = net1 >> (16 - self.prefix) << (16 - self.prefix)
net2 = net3 = 0
elif self.prefix < 25:
net2 = net2 >> (24 - self.prefix) << (24 - self.prefix)
net3 = 0
else: # there is a valid prefix
net3 = net3 >> (32 - self.prefix) << (32 - self.prefix)
address = struct.pack ('BBBB', net0, net1, net2, net3)
self.network = socket.inet_ntoa(address)
else:
self.set_default()
self.error_description = 'Invalid Address'
No comments:
Post a Comment