import string class IPv4: """ Simple class for IPv4 parsing, used as quick conversion if its really sure we get valid and complete 4-tuples. (in our case from REMOTE_ADDR and friends) It has much lesser overhead then the IPv4CIDR class below """ def __init__(self,ipstr): # ipstr in the form 'a.b.c.d' self.maskbits=32L self.mask=4294967295L # constants since this is a host address ipl=map(long,ipstr.split('.',3)) # sum them up self.ip=min(reduce(lambda x,y:(x<<8L)+y,ipl),4294967294L) def __str__(self): ip=self.ip s=[] while ip: ip,r=divmod(ip,256) s.insert(0,str(r)) s=(['0','0','0','0']+s)[-4:] if self.maskbits<32: return(string.join(s,'.')+'/'+str(self.maskbits)) return(string.join(s,'.')) def __repr__(self): return("IPv4('%s')" % self) def __getitem__(self,key): if key: raise IndexError('list index out of range') else: return self def __eq__(self,other): return((other.ip & other.mask) == (self.ip & other.mask)) class IPv4CIDR(IPv4): """ Helper class for IPv4 handling. Uses CIDR (classless interdomain routing) notation for subnets (or supernets, respectively) It should only trow exceptions during instantiation and only if something is completely wrong. Use: a=IPv4CIDR('192.168.15.5') n1=IPv4CIDR('192.168.15.0/24') n2=IPv4CIDR('172.16.0.0/18') a == n1 -> returns true (1) a == n2 -> returns false (0) a in [n1,n2] -> returns true (1) because a is in subnet n1 """ def __init__(self,ipstr): # ipstr in CIDR notation: ip/hostbits # if /hostbits are ommited, /32 is assumed # we have to check for the magic star first if ipstr: if ipstr[-1]=='*': ipstr=(ipstr[:-1]+'0.'*(4-ipstr.count('.')))[:-1]+'/'+str(ipstr.count('.')*8) ips,masks=(ipstr.split('/')+['32',])[:2] self.maskbits=min(long(masks),32L) self.mask=min(4294967296L-(1L<<(32-self.maskbits)),4294967295L) ipl=map(long,ips.split('.',3)) # now a bit magic... self.ip=min(reduce(lambda x,y:(x<<8L)+y,ipl[:-1]+[0L,]*(4-len(ipl))+ipl[-1:]),4294967294L) # and voilá - we have ip and mask with simple bound-checking else: self.mask=0 self.maskbits=0 self.ip=0 def __repr__(self): return("IPv4CIDR('%s')" % self) def __eq__(self,other): # we check which might be the host (or smaller subnet) if self.maskbits>other.maskbits: return((other.ip & other.mask) == ((self.ip & self.mask) & other.mask)) else: return((self.ip & self.mask) == ((other.ip & other.mask) & self.mask))