Skip to content

Instantly share code, notes, and snippets.

@Gowee
Last active Jan 14, 2019
Embed
What would you like to do?
#!/usr/bin/env python3
import urllib.request
import re
from collections import namedtuple
from math import log
def ip2num(ip_address: str) -> int:
a, b, c, d = map(int, ip_address.split("."))
return (a << 24) + (b << 16) + (c << 8) + d
def num2ip(num: int) -> str:
ip = [0 for _ in range(4)]
for i in range(3, -1, -1):
num, r = divmod(num, 256)
ip[i] = str(r)
return ".".join(ip)
lg = lambda x: log(x, 2)
# Returns the position of the rightest 1 of a num as binary.
def rightest_one(num: int) -> int:
r = 0
i = 0
while num > 0:
num, r = divmod(num, 2)
if r == 1:
return i
i += 1
return i
print("Download data from APNIC...")
with urllib.request.urlopen("https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-latest") as c:
rir_data = c.read().decode("ASCII")
rir_stats = ((ip2num(e.group(1)), int(e.group(3))) for e in re.finditer(r"apnic\|CN\|ipv4\|((\d{0,3}\.){3}\d{0,3})\|(\d+)\|\d{8}\|[assigned|allocated]", rir_data, re.A))
print("Data downloaded.")
rir_stats = sorted(rir_stats, key=lambda e: e[0])
# Assume: the above data is sorted and has no overlap.
# shrink
shrinked_entries = []
last_entry = rir_stats[0]
for entry in rir_stats[1:]:
#print(entry)
if entry[0] - last_entry[0] == last_entry[1]: # consecutive ip range pair
#print("merge {} with {}".format(last_entry, entry))
last_entry = last_entry[0], last_entry[1] + entry[1] # merge
else:
shrinked_entries.append(last_entry)
#print(last_entry)
#__import__("time").sleep(2)
last_entry = entry
# blow up
entries = []
for (addr, c) in shrinked_entries:
while c != 0:
# Assume: all CIDR are well-formed (couterexample: 1.0.1.0/16).
b = min(c, 2 ** int(lg(c)), 2 ** rightest_one(addr))
entries.append("{0}/{1}".format(num2ip(addr), 32 - int(lg(b))))
c -= b
addr += b
#assert b == 2 ** (32 - entries[-1][1])
with open("./test.txt", "w", encoding="ASCII") as f:
f.write("\n".join(entries))
print("Generated successfully with {} routes.".format(len(entries)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment