-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathrex2cidr.py
executable file
·81 lines (69 loc) · 2.39 KB
/
rex2cidr.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
#!/usr/local/bin/python
import sys
import struct
import socket
import re
import operator
import netaddr
import itertools
import ipaddress
import exrex
import argparse
from re import sre_parse
parser = argparse.ArgumentParser("Convert a regular expression matching IP addressses to a list of CIDR blocks")
parser.add_argument('-l', '--list', action="store_true", dest="list_only", help="output list of IP addresses rather than a list of CIDR blocks")
args = parser.parse_args()
unichr = chr
# Change alpabeth used by exrex. We only need characters used in IPv4 and IPv6 addresses
exrex.CATEGORIES = {
sre_parse.CATEGORY_SPACE: sorted(frozenset({})),
sre_parse.CATEGORY_DIGIT: sorted(frozenset({'1', '6', '4', '5', '9', '2', '7', '0', '8', '3'})),
'category_any': sorted(frozenset({'a','b','c','d','e','f', ':', '.', '1', '6', '4', '5', '9', '2', '7', '0', '8', '3'})),
}
def gen_cidr(ip_start, ip_end):
return netaddr.iprange_to_cidrs(ip_start, ip_end)
def create_range(ip_addresses):
groups = []
for _, g in itertools.groupby(enumerate(sorted(ip_addresses)), lambda ix:ix[0]-int(ix[1])):
group = list(map(operator.itemgetter(1), g))
if len(list(group)) > 1:
groups.append("{}-{}".format(group[0], group[-1]))
else:
groups.append(str(group[0]))
return groups
def is_valid(addr):
try:
ipaddress.ip_address(addr)
return True
except ValueError:
return False
def sort_ip_list(ip_list):
from IPy import IP
ipl = [(IP(str(ip)).int(), ip) for ip in ip_list]
ipl.sort()
return [ip[1] for ip in ipl]
pattern = ''
for line in sys.stdin:
if re.search(r"[*+]", line):
print("Ignoring line '{}' because it contains unsupported quantifiers like + or *".format(line.rstrip()))
continue
pattern += line.strip(' \t\n') + "|"
pattern = str(pattern).rstrip('|')
a = set([])
try:
#for i in list(exrex.generate(pattern, limit=sys.maxsize)):
for i in list(exrex.generate(pattern, limit=(1<<32))):
if not is_valid(i): continue
a.add(ipaddress.ip_address(i))
except re.error:
print("\nPattern error\n")
exit(1)
if args.list_only:
for i in sort_ip_list(list(a)):
print(i)
else:
for i in create_range(a):
start = i.split('-')[0]
end = i.split('-')[-1]
for x in gen_cidr(start, end):
print(str(x).replace('/32',''))