Commit 059593b1 by Őry Máté

firewall: fix _magic_ipv6_template()

parent 6299201d
......@@ -375,8 +375,7 @@ class Vlan(AclBase, models.Model):
'specification like %(a)02x to get the first byte as two '
'hexadecimal digits. Usual choices for mapping '
'198.51.100.0/24 to 2001:0DB8:1:1::/64 would be '
'"2001:0DB8:51:1:1:%(d)d::" and '
'"2001:0DB8:51:1:1:%(d)x00::".'),
'"2001:db8:1:1:%(d)d::" and "2001:db8:1:1:%(d)02x00::".'),
validators=[val_ipv6_template], verbose_name=_('ipv6 template'))
dhcp_pool = models.TextField(blank=True, verbose_name=_('DHCP pool'),
help_text=_(
......@@ -406,37 +405,46 @@ class Vlan(AclBase, models.Model):
_("%(ip6)s (translated from %(ip4)s) is outside of "
"the IPv6 network.") % {"ip4": i, "ip6": i6})
if not self.ipv6_template and self.network6:
# come up with some sensible default
self.ipv6_template = self._magic_ipv6_template()
host4_bytes = int(ceil((32 - self.network4.prefixlen) / 8))
host6_bytes = int(ceil((128 - self.network6.prefixlen) / 8))
host4_bytes = self._host_bytes(self.network4.prefixlen, 4)
host6_bytes = self._host_bytes(self.network6.prefixlen, 16)
if host4_bytes > host6_bytes:
raise ValidationError(
_("IPv6 network is too small to map IPv4 addresses to it."))
def _magic_ipv6_template(self):
host4_bytes = int(ceil((32 - self.network4.prefixlen) / 8))
host6_bytes = int(ceil((128 - self.network6.prefixlen) / 8))
letters = ascii_letters[4-host4_bytes:4]
remove = host6_bytes // 2
ipstr = self.network6.network.format(ipv6_full)
s = ipstr.split(":")[0:-remove]
if 2 * (host4_bytes + 1) < host6_bytes: # use verbose format
for i in letters:
s.append("%({})d".format(i))
else: # use short format
remain = host6_bytes
for i in letters:
if remain % 2 == 1: # can use last half word
if s[-1].endswith("00"):
s[-1] = s[-1][:-2]
s[-1] += "%({})02x".format(i)
else:
s.append("%({})02x00".format(i))
remain -= 1
if host6_bytes > host4_bytes:
s.append(":")
return ":".join(s)
@staticmethod
def _host_bytes(prefixlen, maxbytes):
return int(ceil((maxbytes - prefixlen / 8.0)))
@classmethod
def _magic_ipv6_template(cls, network4, network6, verbose=None):
"""Offer a sensible ipv6_template value."""
host4_bytes = cls._host_bytes(network4.prefixlen, 4)
host6_bytes = cls._host_bytes(network6.prefixlen, 16)
letters = ascii_letters[4-host4_bytes:4]
remove = host6_bytes // 2
ipstr = network6.network.format(ipv6_full)
s = ipstr.split(":")[0:-remove]
if verbose is None: # use verbose format if net6 much wider
verbose = 2 * (host4_bytes + 1) < host6_bytes
if verbose:
for i in letters:
s.append("%({})d".format(i))
else:
remain = host6_bytes
for i in letters:
if remain % 2 == 1: # can use last half word
assert s[-1] == "0" or s[-1].endswith("00")
if s[-1].endswith("00"):
s[-1] = s[-1][:-2]
s[-1] += "%({})02x".format(i)
s[-1].lstrip("0")
else:
s.append("%({})02x00".format(i))
remain -= 1
if host6_bytes > host4_bytes:
s.append(":")
return ":".join(s)
def __unicode__(self):
return "%s - %s" % ("managed" if self.managed else "unmanaged",
......
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 sign in to comment