-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.py
134 lines (97 loc) · 2.38 KB
/
util.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import socket
import struct
def ip2long(ip):
packedIP = socket.inet_aton(ip)
return struct.unpack("!L", packedIP)[0]
def long2ip(l):
return socket.inet_ntoa(struct.pack('!L', l))
def ip_range(s):
if '-' in s:
a1, a2 = s.split('-')
try:
ret = (ip2long(a1), ip2long(a2))
except:
print(a1.encode('iso-8859-1'))
print('w', a2.encode('iso-8859-1'))
exit()
return ret
else:
if '/' in s:
addr, pl = s.split('/')
else:
addr, pl = s, 32
addr = ip2long(addr)
nbits = 32-int(pl)
mask = (1 << nbits) -1
addr |= mask
return (addr ^ mask, addr)
def range_to_cidrs(start, end):
last_addr = caddr = start
ret = []
while True:
cplen = 32
while True:
cplen -= 1
test_bit = 1<<(31-cplen)
if caddr & test_bit:
break
new_last = caddr | ((test_bit<<1)-1)
if cplen == -1 or new_last > end:
break
else:
last_addr = new_last
cplen += 1
ret.append((caddr, cplen))
last_addr = caddr = last_addr+1
if caddr > end:
break
return ret
def cidr_to_str(cidr):
return long2ip(cidr[0])+'/'+str(cidr[1])
def ranges_from_file(f):
ranges = []
for line in f:
line = line.strip()
if not line or line[0] == '#':
continue
r = ip_range(line)
ranges.append(r)
return ranges
def merge_ranges(ranges):
if not ranges:
return []
ranges.sort(key=lambda x: x[0])
new_ranges = [list(ranges[0])]
for r in ranges:
if r[0] <= new_ranges[-1][1]+1:
if r[1] > new_ranges[-1][1]:
new_ranges[-1][1] = r[1]
else:
new_ranges.append(list(r))
return new_ranges
def invert_ranges(ranges):
ranges = merge_ranges(ranges)
new_ranges = [[0, 2**32-1]]
for s, e in ranges:
if s == new_ranges[-1][0]:
new_ranges[-1][0] = e+1
else:
new_ranges[-1][1] = s-1
if e < 2**32-1:
new_ranges.append([e+1, 2**32-1])
# for continuation that ends on 2**32-1
if new_ranges[-1][0] == new_ranges[-1][1]+1:
new_ranges = new_ranges[:-1]
return new_ranges
def ranges_total(ranges):
total = 0
for start, end in ranges:
total += end - start + 1
return total
def output_ranges(ranges, no_cidr=False):
for start, end in ranges:
if no_cidr:
yield long2ip(start)+'-'+long2ip(end)
else:
for cidr in range_to_cidrs(start, end):
yield cidr_to_str(cidr)