Skip to content

Instantly share code, notes, and snippets.

@abersheeran
Created February 29, 2024 08:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abersheeran/9ba21fcec08146b9948ea34746a190bd to your computer and use it in GitHub Desktop.
Save abersheeran/9ba21fcec08146b9948ea34746a190bd to your computer and use it in GitHub Desktop.
Merge ip range to ip network list
import ipaddress
def ip_range(
start_ip: ipaddress.IPv4Address, end_ip: ipaddress.IPv4Address
) -> list[ipaddress.IPv4Network]:
if start_ip > end_ip:
raise ValueError("Start IP must be less than end IP")
res = []
s = int(start_ip)
stop = False
while not stop:
start_ip_bin = "{:0>32}".format(bin(s)[2:])
for i, letter in enumerate(reversed(start_ip_bin)):
if letter == "1":
network = ipaddress.ip_network(
"{}/{}".format(
ipaddress.ip_address(
int("{:0<32}".format(start_ip_bin[: 32 - i]), 2)
),
32 - i,
)
)
res.append(network)
if end_ip in network:
stop = True
break
s = s + 2**i
break
end_ip_bin = "{:0>32}".format(bin(int(end_ip) + 1)[2:])
j = end_ip_bin.rfind("1") + 1
end_network = ipaddress.ip_network(
"{}/{}".format(
ipaddress.ip_address(int("{:0<32}".format(end_ip_bin[:j]), 2)), j
)
)
latest_network = res.pop()
if latest_network.overlaps(end_network):
res.extend(
filter(
lambda n: end_ip > next(iter(n)),
latest_network.address_exclude(end_network),
)
)
else:
res.append(latest_network)
return res
if __name__ == "__main__":
networks = ip_range(
ipaddress.ip_address("10.254.16.0"), ipaddress.ip_address("10.254.18.21")
)
print(networks)
for network in networks:
print(network)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment