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

slapformat: Ensure IPv6 ranges are not used twice

parent 57118615
...@@ -1003,6 +1003,7 @@ class Interface(object): ...@@ -1003,6 +1003,7 @@ class Interface(object):
self.name = str(name) self.name = str(name)
self.ipv4_local_network = ipv4_local_network self.ipv4_local_network = ipv4_local_network
self.ipv6_interface = ipv6_interface or name self.ipv6_interface = ipv6_interface or name
self._ipv6_ranges = set()
# XXX no __getinitargs__, as instances of this class are never deserialized. # XXX no __getinitargs__, as instances of this class are never deserialized.
...@@ -1077,7 +1078,6 @@ class Interface(object): ...@@ -1077,7 +1078,6 @@ class Interface(object):
address_string = '%s/%s' % (address, netmaskToPrefixIPv4(netmask)) address_string = '%s/%s' % (address, netmaskToPrefixIPv4(netmask))
interface_name = self.name interface_name = self.name
if tap: if tap:
interface_name = tap.name interface_name = tap.name
# check if address is already took by any other interface # check if address is already took by any other interface
...@@ -1152,6 +1152,25 @@ class Interface(object): ...@@ -1152,6 +1152,25 @@ class Interface(object):
# confirmed to be configured # confirmed to be configured
return dict(addr=addr, netmask=netmask) 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): def _generateRandomIPv6Addr(self, address_dict):
netmask = address_dict['netmask'] netmask = address_dict['netmask']
netmask_len = lenNetmaskIpv6(netmask) netmask_len = lenNetmaskIpv6(netmask)
...@@ -1247,9 +1266,12 @@ class Interface(object): ...@@ -1247,9 +1266,12 @@ class Interface(object):
result_addr['netmask'] = netmaskFromLenIPv6(128) result_addr['netmask'] = netmaskFromLenIPv6(128)
else: else:
result_addr = getPartitionIpv6Addr(address_dict, partition_index) result_addr = getPartitionIpv6Addr(address_dict, partition_index)
result_addr['netmask'] = netmaskFromLenIPv6(result_addr.pop('prefixlen')) result_addr['netmask'] = netmaskFromLenIPv6(result_addr['prefixlen'])
if self._addSystemAddress(result_addr['addr'], result_addr['netmask'], tap=tap): if not tap or self._checkIpv6Range(result_addr['addr'], result_addr['prefixlen']):
return result_addr 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 # Try 10 times to add address, raise in case if not possible
for _ in range(10): for _ in range(10):
...@@ -1260,10 +1282,14 @@ class Interface(object): ...@@ -1260,10 +1282,14 @@ class Interface(object):
else: else:
result_addr = self._generateRandomIPv6Addr(address_dict) result_addr = self._generateRandomIPv6Addr(address_dict)
# Checking the validity of the IPv6 address # Checking the validity of the IPv6 address
if self._addSystemAddress(result_addr['addr'], result_addr['netmask'], tap=tap): addr = result_addr['addr']
return result_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): def generateIPv6Range(self, i):
""" """
...@@ -1289,7 +1315,14 @@ class Interface(object): ...@@ -1289,7 +1315,14 @@ class Interface(object):
ipv6_range = getPartitionIpv6Range(address_dict, i) ipv6_range = getPartitionIpv6Range(address_dict, i)
ipv6_range['netmask'] = netmaskFromLenIPv6(ipv6_range['prefixlen']) ipv6_range['netmask'] = netmaskFromLenIPv6(ipv6_range['prefixlen'])
ipv6_range['network'] = '%(addr)s/%(prefixlen)d' % ipv6_range ipv6_range['network'] = '%(addr)s/%(prefixlen)d' % ipv6_range
return 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): def allowUseInexistingIpv6Address(self):
# This will allow the usage of unexisting IPv6 adrdresses. # 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