1 # Written by John Hoffman
2 # see LICENSE.txt for license information
4 from bisect import bisect, insort
11 bool = lambda x: not not x
43 chrbinmap[n] = ''.join(b)
46 def to_bitfield_ipv4(ip):
49 raise ValueError, "bad address"
52 b.append(chrbinmap[int(i)])
55 def to_bitfield_ipv6(ip):
60 raise ValueError, "bad address"
61 if ip == '::': # boundary handling
66 raise ValueError, "bad address"
70 raise ValueError, "bad address"
71 for n in ip.split(':'):
72 if n == '': # double-colon
74 raise ValueError, "bad address"
78 if n.find('.') >= 0: # IPv4
79 n = to_bitfield_ipv4(n)
80 b += n + '0'*(32-len(n))
82 n = ('x'*(4-len(n))) + n
87 b = b[:pos]+('0'*(129-len(b)))+b[pos+1:]
88 if len(b) != 128: # always check size
89 raise ValueError, "bad address"
92 ipv4addrmask = to_bitfield_ipv6('::ffff:0:0')[:96]
99 def __nonzero__(self):
100 return bool(self.ipv4list or self.ipv6list)
103 def append(self, ip, depth = 256):
104 if ip.find(':') < 0: # IPv4
105 insort(self.ipv4list, to_bitfield_ipv4(ip)[:depth])
107 b = to_bitfield_ipv6(ip)
108 if b.startswith(ipv4addrmask):
109 insort(self.ipv4list, b[96:][:depth-96])
111 insort(self.ipv6list, b[:depth])
114 def includes(self, ip):
115 if not (self.ipv4list or self.ipv6list):
117 if ip.find(':') < 0: # IPv4
118 b = to_bitfield_ipv4(ip)
120 b = to_bitfield_ipv6(ip)
121 if b.startswith(ipv4addrmask):
127 for map in l[bisect(l, b)-1:]:
128 if b.startswith(map):
135 def read_fieldlist(self, file): # reads a list from a file in the format 'ip/len <whatever>'
141 line = line.strip().expandtabs()
142 if not line or line[0] == '#':
145 line, garbage = line.split(' ', 1)
149 line, garbage = line.split('#', 1)
153 ip, depth = line.split('/')
158 if depth is not None:
160 self.append(ip, depth)
162 print '*** WARNING *** could not parse IP range: '+line
166 def set_intranet_addresses(self):
167 self.append('127.0.0.1', 8)
168 self.append('10.0.0.0', 8)
169 self.append('172.16.0.0', 12)
170 self.append('192.168.0.0', 16)
171 self.append('169.254.0.0', 16)
173 self.append('fe80::', 16)
174 self.append('fec0::', 16)
176 def set_ipv4_addresses(self):
177 self.append('::ffff:0:0', 96)
179 def ipv6_to_ipv4(ip):
180 ip = to_bitfield_ipv6(ip)
181 if not ip.startswith(ipv4addrmask):
182 raise ValueError, "not convertible to IPv4"
186 x += str(int(ip[:8], 2))
196 return ipv6_to_ipv4(ip)
199 return ip.find(':') < 0