Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
any duplicates.
:param ip_addrs: an iterable sequence of IP addresses and subnets.
:return: a summarized list of `IPNetwork` objects.
"""
# The algorithm is quite simple: For each CIDR we create an IP range.
# Sort them and merge when possible. Afterwars split them again
# optimally.
if not hasattr(ip_addrs, '__iter__'):
raise ValueError('A sequence or iterator is expected!')
ranges = []
for ip in ip_addrs:
cidr = IPNetwork(ip)
# Since non-overlapping ranges are the common case, remember the original
ranges.append( (cidr.version, cidr.last, cidr.first, cidr) )
ranges.sort()
i = len(ranges) - 1
while i > 0:
if ranges[i][0] == ranges[i - 1][0] and ranges[i][2] - 1 <= ranges[i - 1][1]:
ranges[i - 1] = (ranges[i][0], ranges[i][1], min(ranges[i - 1][2], ranges[i][2]))
del ranges[i]
i -= 1
merged = []
for range_tuple in ranges:
# If this range wasn't merged we can simply use the old cidr.
if len(range_tuple) == 4:
merged.append(range_tuple[3])
else:
def cidr_partition(target, exclude):
"""
Partitions a target IP subnet on an exclude IP address.
:param target: the target IP address or subnet to be divided up.
:param exclude: the IP address or subnet to partition on
:return: list of `IPNetwork` objects before, the partition and after, sorted.
Adding the three lists returns the equivalent of the original subnet.
"""
target = IPNetwork(target)
exclude = IPNetwork(exclude)
if exclude.last < target.first:
# Exclude subnet's upper bound address less than target
# subnet's lower bound.
return [], [], [target.cidr]
elif target.last < exclude.first:
# Exclude subnet's lower bound address greater than target
# subnet's upper bound.
return [target.cidr], [], []
if target.prefixlen >= exclude.prefixlen:
# Exclude contains the target
return [], [target], []
left = []
right = []
left = []
right = []
new_prefixlen = target.prefixlen + 1
# Some @properties that are expensive to get and don't change below.
target_module_width = target._module.width
target_first = target.first
version = exclude.version
i_lower = target_first
i_upper = target_first + (2 ** (target_module_width - new_prefixlen))
while exclude.prefixlen >= new_prefixlen:
if exclude.first >= i_upper:
left.append(IPNetwork((i_lower, new_prefixlen), version=version))
matched = i_upper
else:
right.append(IPNetwork((i_upper, new_prefixlen), version=version))
matched = i_lower
new_prefixlen += 1
if new_prefixlen > target_module_width:
break
i_lower = matched
i_upper = matched + (2 ** (target_module_width - new_prefixlen))
return left, [exclude], right[::-1]
lowest_ip = sorted_ips[0]
highest_ip = sorted_ips[-1]
if lowest_ip.version != highest_ip.version:
raise TypeError('IP sequence cannot contain both IPv4 and IPv6!')
ipnum = highest_ip.last
prefixlen = highest_ip.prefixlen
lowest_ipnum = lowest_ip.first
width = highest_ip._module.width
while prefixlen > 0 and ipnum > lowest_ipnum:
prefixlen -= 1
ipnum &= -(1<<(width-prefixlen))
return IPNetwork( (ipnum, prefixlen), version=lowest_ip.version )
IPRange('225.0.0.0', '231.255.255.255'),
) + (IPV4_LOOPBACK, IPV4_6TO4)
#-----------------------------------------------------------------------------
# Cached IPv6 address range lookups.
#-----------------------------------------------------------------------------
IPV6_LOOPBACK = IPAddress('::1')
IPV6_PRIVATE = (
IPNetwork('fc00::/7'), # Unique Local Addresses (ULA)
IPNetwork('fec0::/10'), # Site Local Addresses (deprecated - RFC 3879)
)
IPV6_LINK_LOCAL = IPNetwork('fe80::/10')
IPV6_MULTICAST = IPNetwork('ff00::/8')
IPV6_RESERVED = (
IPNetwork('ff00::/12'), IPNetwork('::/8'),
IPNetwork('0100::/8'), IPNetwork('0200::/7'),
IPNetwork('0400::/6'), IPNetwork('0800::/5'),
IPNetwork('1000::/4'), IPNetwork('4000::/3'),
IPNetwork('6000::/3'), IPNetwork('8000::/3'),
IPNetwork('A000::/3'), IPNetwork('C000::/3'),
IPNetwork('E000::/4'), IPNetwork('F000::/5'),
IPNetwork('F800::/6'), IPNetwork('FE00::/9'),
)
IPNetwork('233.252.0.0/24'), # Multicast test network
IPRange('234.0.0.0', '238.255.255.255'),
IPRange('225.0.0.0', '231.255.255.255'),
) + (IPV4_LOOPBACK, IPV4_6TO4)
#-----------------------------------------------------------------------------
# Cached IPv6 address range lookups.
#-----------------------------------------------------------------------------
IPV6_LOOPBACK = IPAddress('::1')
IPV6_PRIVATE = (
IPNetwork('fc00::/7'), # Unique Local Addresses (ULA)
IPNetwork('fec0::/10'), # Site Local Addresses (deprecated - RFC 3879)
)
IPV6_LINK_LOCAL = IPNetwork('fe80::/10')
IPV6_MULTICAST = IPNetwork('ff00::/8')
IPV6_RESERVED = (
IPNetwork('ff00::/12'), IPNetwork('::/8'),
IPNetwork('0100::/8'), IPNetwork('0200::/7'),
IPNetwork('0400::/6'), IPNetwork('0800::/5'),
IPNetwork('1000::/4'), IPNetwork('4000::/3'),
IPNetwork('6000::/3'), IPNetwork('8000::/3'),
IPNetwork('A000::/3'), IPNetwork('C000::/3'),
IPNetwork('E000::/4'), IPNetwork('F000::/5'),
IPNetwork('F800::/6'), IPNetwork('FE00::/9'),
)
# Cached IPv6 address range lookups.
#-----------------------------------------------------------------------------
IPV6_LOOPBACK = IPAddress('::1')
IPV6_PRIVATE = (
IPNetwork('fc00::/7'), # Unique Local Addresses (ULA)
IPNetwork('fec0::/10'), # Site Local Addresses (deprecated - RFC 3879)
)
IPV6_LINK_LOCAL = IPNetwork('fe80::/10')
IPV6_MULTICAST = IPNetwork('ff00::/8')
IPV6_RESERVED = (
IPNetwork('ff00::/12'), IPNetwork('::/8'),
IPNetwork('0100::/8'), IPNetwork('0200::/7'),
IPNetwork('0400::/6'), IPNetwork('0800::/5'),
IPNetwork('1000::/4'), IPNetwork('4000::/3'),
IPNetwork('6000::/3'), IPNetwork('8000::/3'),
IPNetwork('A000::/3'), IPNetwork('C000::/3'),
IPNetwork('E000::/4'), IPNetwork('F000::/5'),
IPNetwork('F800::/6'), IPNetwork('FE00::/9'),
)
start = IPNetwork(start)
end = IPNetwork(end)
iprange = [start.first, end.last]
# Get spanning CIDR covering both addresses.
cidr_span = spanning_cidr([start, end])
width = start._module.width
if cidr_span.first < iprange[0]:
exclude = IPNetwork((iprange[0]-1, width), version=start.version)
cidr_list = cidr_partition(cidr_span, exclude)[2]
cidr_span = cidr_list.pop()
if cidr_span.last > iprange[1]:
exclude = IPNetwork((iprange[1]+1, width), version=start.version)
cidr_list += cidr_partition(cidr_span, exclude)[0]
else:
cidr_list.append(cidr_span)
return cidr_list
IPV6_LOOPBACK = IPAddress('::1')
IPV6_PRIVATE = (
IPNetwork('fc00::/7'), # Unique Local Addresses (ULA)
IPNetwork('fec0::/10'), # Site Local Addresses (deprecated - RFC 3879)
)
IPV6_LINK_LOCAL = IPNetwork('fe80::/10')
IPV6_MULTICAST = IPNetwork('ff00::/8')
IPV6_RESERVED = (
IPNetwork('ff00::/12'), IPNetwork('::/8'),
IPNetwork('0100::/8'), IPNetwork('0200::/7'),
IPNetwork('0400::/6'), IPNetwork('0800::/5'),
IPNetwork('1000::/4'), IPNetwork('4000::/3'),
IPNetwork('6000::/3'), IPNetwork('8000::/3'),
IPNetwork('A000::/3'), IPNetwork('C000::/3'),
IPNetwork('E000::/4'), IPNetwork('F000::/5'),
IPNetwork('F800::/6'), IPNetwork('FE00::/9'),
)