]> git.ipfire.org Git - people/shoehn/ipfire.org.git/blame - www/pages/torrent/client/subnetparse.py
Change Color of Menuitem CeBIT.
[people/shoehn/ipfire.org.git] / www / pages / torrent / client / subnetparse.py
CommitLineData
879aa787
MT
1# Written by John Hoffman
2# see LICENSE.txt for license information
3
4from bisect import bisect, insort
5
6try:
7 True
8except:
9 True = 1
10 False = 0
11 bool = lambda x: not not x
12
13hexbinmap = {
14 '0': '0000',
15 '1': '0001',
16 '2': '0010',
17 '3': '0011',
18 '4': '0100',
19 '5': '0101',
20 '6': '0110',
21 '7': '0111',
22 '8': '1000',
23 '9': '1001',
24 'a': '1010',
25 'b': '1011',
26 'c': '1100',
27 'd': '1101',
28 'e': '1110',
29 'f': '1111',
30 'x': '0000',
31}
32
33chrbinmap = {}
34for n in xrange(256):
35 b = []
36 nn = n
37 for i in xrange(8):
38 if nn & 0x80:
39 b.append('1')
40 else:
41 b.append('0')
42 nn <<= 1
43 chrbinmap[n] = ''.join(b)
44
45
46def to_bitfield_ipv4(ip):
47 ip = ip.split('.')
48 if len(ip) != 4:
49 raise ValueError, "bad address"
50 b = []
51 for i in ip:
52 b.append(chrbinmap[int(i)])
53 return ''.join(b)
54
55def to_bitfield_ipv6(ip):
56 b = ''
57 doublecolon = False
58
59 if ip == '':
60 raise ValueError, "bad address"
61 if ip == '::': # boundary handling
62 ip = ''
63 elif ip[:2] == '::':
64 ip = ip[1:]
65 elif ip[0] == ':':
66 raise ValueError, "bad address"
67 elif ip[-2:] == '::':
68 ip = ip[:-1]
69 elif ip[-1] == ':':
70 raise ValueError, "bad address"
71 for n in ip.split(':'):
72 if n == '': # double-colon
73 if doublecolon:
74 raise ValueError, "bad address"
75 doublecolon = True
76 b += ':'
77 continue
78 if n.find('.') >= 0: # IPv4
79 n = to_bitfield_ipv4(n)
80 b += n + '0'*(32-len(n))
81 continue
82 n = ('x'*(4-len(n))) + n
83 for i in n:
84 b += hexbinmap[i]
85 if doublecolon:
86 pos = b.find(':')
87 b = b[:pos]+('0'*(129-len(b)))+b[pos+1:]
88 if len(b) != 128: # always check size
89 raise ValueError, "bad address"
90 return b
91
92ipv4addrmask = to_bitfield_ipv6('::ffff:0:0')[:96]
93
94class IP_List:
95 def __init__(self):
96 self.ipv4list = []
97 self.ipv6list = []
98
99 def __nonzero__(self):
100 return bool(self.ipv4list or self.ipv6list)
101
102
103 def append(self, ip, depth = 256):
104 if ip.find(':') < 0: # IPv4
105 insort(self.ipv4list,to_bitfield_ipv4(ip)[:depth])
106 else:
107 b = to_bitfield_ipv6(ip)
108 if b.startswith(ipv4addrmask):
109 insort(self.ipv4list,b[96:][:depth-96])
110 else:
111 insort(self.ipv6list,b[:depth])
112
113
114 def includes(self, ip):
115 if not (self.ipv4list or self.ipv6list):
116 return False
117 if ip.find(':') < 0: # IPv4
118 b = to_bitfield_ipv4(ip)
119 else:
120 b = to_bitfield_ipv6(ip)
121 if b.startswith(ipv4addrmask):
122 b = b[96:]
123 if len(b) > 32:
124 l = self.ipv6list
125 else:
126 l = self.ipv4list
127 for map in l[bisect(l,b)-1:]:
128 if b.startswith(map):
129 return True
130 if map > b:
131 return False
132 return False
133
134
135 def read_fieldlist(self, file): # reads a list from a file in the format 'ip/len <whatever>'
136 f = open(file, 'r')
137 while True:
138 line = f.readline()
139 if not line:
140 break
141 line = line.strip().expandtabs()
142 if not line or line[0] == '#':
143 continue
144 try:
145 line, garbage = line.split(' ',1)
146 except:
147 pass
148 try:
149 line, garbage = line.split('#',1)
150 except:
151 pass
152 try:
153 ip, depth = line.split('/')
154 except:
155 ip = line
156 depth = None
157 try:
158 if depth is not None:
159 depth = int(depth)
160 self.append(ip,depth)
161 except:
162 print '*** WARNING *** could not parse IP range: '+line
163 f.close()
164
165
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)
172 self.append('::1')
173 self.append('fe80::',16)
174 self.append('fec0::',16)
175
176 def set_ipv4_addresses(self):
177 self.append('::ffff:0:0',96)
178
179def ipv6_to_ipv4(ip):
180 ip = to_bitfield_ipv6(ip)
181 if not ip.startswith(ipv4addrmask):
182 raise ValueError, "not convertible to IPv4"
183 ip = ip[-32:]
184 x = ''
185 for i in range(4):
186 x += str(int(ip[:8],2))
187 if i < 3:
188 x += '.'
189 ip = ip[8:]
190 return x
191
192def to_ipv4(ip):
193 if is_ipv4(ip):
194 _valid_ipv4(ip)
195 return ip
196 return ipv6_to_ipv4(ip)
197
198def is_ipv4(ip):
199 return ip.find(':') < 0
200
201def _valid_ipv4(ip):
202 ip = ip.split('.')
203 if len(ip) != 4:
204 raise ValueError
205 for i in ip:
206 chr(int(i))
207
208def is_valid_ip(ip):
209 try:
210 if not ip:
211 return False
212 if is_ipv4(ip):
213 _valid_ipv4(ip)
214 return True
215 to_bitfield_ipv6(ip)
216 return True
217 except:
218 return False