Commit 9f89cf66 authored by Xavier Thompson's avatar Xavier Thompson

slapformat: Ensure IPv6 ranges are not used twice

parent 57118615
This commit is part of merge request !455. Comments created here will be created in the context of that merge request.
......@@ -1003,6 +1003,7 @@ class Interface(object):
self.name = str(name)
self.ipv4_local_network = ipv4_local_network
self.ipv6_interface = ipv6_interface or name
self._ipv6_ranges = set()
# XXX no __getinitargs__, as instances of this class are never deserialized.
......@@ -1077,7 +1078,6 @@ class Interface(object):
address_string = '%s/%s' % (address, netmaskToPrefixIPv4(netmask))
interface_name = self.name
if tap:
interface_name = tap.name
# check if address is already took by any other interface
......@@ -1152,6 +1152,25 @@ class Interface(object):
# confirmed to be configured
return dict(addr=addr, netmask=netmask)
def _checkIpv6Range(self, address, prefixlen):
network = str(netaddr.IPNetwork("%s/%d" % (address, prefixlen)).cidr)
if network in self._ipv6_ranges:
self._logger.warning(
"Address range %s/%d is already attributed", address, prefixlen)
return False
return True
def _reserveIpv6Range(self, address, prefixlen):
network = str(netaddr.IPNetwork("%s/%d" % (address, prefixlen)).cidr)
assert(network not in self._ipv6_ranges)
self._ipv6_ranges.add(network)
def _tryReserveIpv6Range(self, address, prefixlen):
if self._checkIpv6Range(address, prefixlen):
self._reserveIpv6Range(address, prefixlen)
return True
return False
def _generateRandomIPv6Addr(self, address_dict):
netmask = address_dict['netmask']
netmask_len = lenNetmaskIpv6(netmask)
......@@ -1247,8 +1266,11 @@ class Interface(object):
result_addr['netmask'] = netmaskFromLenIPv6(128)
else:
result_addr = getPartitionIpv6Addr(address_dict, partition_index)
result_addr['netmask'] = netmaskFromLenIPv6(result_addr.pop('prefixlen'))
result_addr['netmask'] = netmaskFromLenIPv6(result_addr['prefixlen'])
if not tap or self._checkIpv6Range(result_addr['addr'], result_addr['prefixlen']):
if self._addSystemAddress(result_addr['addr'], result_addr['netmask'], tap=tap):
if tap:
self._reserveIpv6Range(result_addr['addr'], result_addr['prefixlen'])
return result_addr
# Try 10 times to add address, raise in case if not possible
......@@ -1260,10 +1282,14 @@ class Interface(object):
else:
result_addr = self._generateRandomIPv6Addr(address_dict)
# Checking the validity of the IPv6 address
if self._addSystemAddress(result_addr['addr'], result_addr['netmask'], tap=tap):
addr = result_addr['addr']
if not tap or self._checkIpv6Range(addr, result_addr['prefixlen']):
if self._addSystemAddress(addr, result_addr['netmask'], tap=tap):
if tap:
self._reserveIpv6Range(addr, result_addr['prefixlen'])
return result_addr
raise AddressGenerationError(result_addr['addr'])
raise AddressGenerationError(addr)
def generateIPv6Range(self, i):
"""
......@@ -1289,7 +1315,14 @@ class Interface(object):
ipv6_range = getPartitionIpv6Range(address_dict, i)
ipv6_range['netmask'] = netmaskFromLenIPv6(ipv6_range['prefixlen'])
ipv6_range['network'] = '%(addr)s/%(prefixlen)d' % ipv6_range
if self._tryReserveIpv6Range(ipv6_range['addr'], ipv6_range['prefixlen']):
return ipv6_range
# Try 10 times to add address, raise in case if not possible
for _ in range(10):
ipv6_range = self._generateRandomIPv6Range(address_dict, suffix='0')
if self._tryReserveIpv6Range(ipv6_range['addr'], ipv6_range['prefixlen']):
return ipv6_range
raise AddressGenerationError(ipv6_range['addr'])
def allowUseInexistingIpv6Address(self):
# This will allow the usage of unexisting IPv6 adrdresses.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment