Commit 059593b1 by Őry Máté

firewall: fix _magic_ipv6_template()

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