Commit 85539a1f by Őry Máté

firewall: magically compute host_ipv6_prefixlen too

parent 4a7515c4
...@@ -404,9 +404,13 @@ class Vlan(AclBase, models.Model): ...@@ -404,9 +404,13 @@ class Vlan(AclBase, models.Model):
raise ValidationError( raise ValidationError(
_("%(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 self.network6:
self.ipv6_template = self._magic_ipv6_template(self.network4, tpl, prefixlen = self._magic_ipv6_template(self.network4,
self.network6) self.network6)
if not self.ipv6_template:
self.ipv6_template = tpl
if not self.host_ipv6_prefixlen:
self.host_ipv6_prefixlen = prefixlen
host4_bytes = self._host_bytes(self.network4.prefixlen, 4) host4_bytes = self._host_bytes(self.network4.prefixlen, 4)
host6_bytes = self._host_bytes(self.network6.prefixlen, 16) host6_bytes = self._host_bytes(self.network6.prefixlen, 16)
if host4_bytes > host6_bytes: if host4_bytes > host6_bytes:
...@@ -419,7 +423,19 @@ class Vlan(AclBase, models.Model): ...@@ -419,7 +423,19 @@ class Vlan(AclBase, models.Model):
@classmethod @classmethod
def _magic_ipv6_template(cls, network4, network6, verbose=None): def _magic_ipv6_template(cls, network4, network6, verbose=None):
"""Offer a sensible ipv6_template value.""" """Offer a sensible ipv6_template value.
Based on prefix lengths the method magically selects verbose (decimal)
format:
>>> Vlan._magic_ipv6_template(IPNetwork("198.51.100.0/24"),
... IPNetwork("2001:0DB8:1:1::/64"))
('2001:db8:1:1:%(d)d::', 80)
However you can explicitly select non-verbose, i.e. hexa format:
>>> Vlan._magic_ipv6_template(IPNetwork("198.51.100.0/24"),
... IPNetwork("2001:0DB8:1:1::/64"), False)
('2001:db8:1:1:%(d)02x00::', 72)
"""
host4_bytes = cls._host_bytes(network4.prefixlen, 4) host4_bytes = cls._host_bytes(network4.prefixlen, 4)
host6_bytes = cls._host_bytes(network6.prefixlen, 16) host6_bytes = cls._host_bytes(network6.prefixlen, 16)
letters = ascii_letters[4-host4_bytes:4] letters = ascii_letters[4-host4_bytes:4]
...@@ -434,18 +450,18 @@ class Vlan(AclBase, models.Model): ...@@ -434,18 +450,18 @@ class Vlan(AclBase, models.Model):
else: else:
remain = host6_bytes remain = host6_bytes
for i in letters: for i in letters:
if remain % 2 == 1: # can use last half word cls._append_hexa(s, i, remain % 2 == 1)
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 remain -= 1
if host6_bytes > host4_bytes: if host6_bytes > host4_bytes:
s.append(":") s.append(":")
return ":".join(s) tpl = ":".join(s)
# compute prefix length
mask = int(IPAddress(tpl % {"a": 1, "b": 1, "c": 1, "d": 1}))
prefixlen = 128
while mask % 2 == 0:
mask /= 2
prefixlen -= 1
return (tpl, prefixlen)
def __unicode__(self): def __unicode__(self):
return "%s - %s" % ("managed" if self.managed else "unmanaged", return "%s - %s" % ("managed" if self.managed else "unmanaged",
......
...@@ -708,11 +708,11 @@ class VlanMagicMixin(object): ...@@ -708,11 +708,11 @@ class VlanMagicMixin(object):
result = {} result = {}
if "network4" in GET and "network6" in GET: if "network4" in GET and "network6" in GET:
try: try:
result["ipv6_template"] = Vlan._magic_ipv6_template( result["ipv6_template"], result["host_ipv6_prefixlen"] = (
IPNetwork(GET['network4']), Vlan._magic_ipv6_template(IPNetwork(GET['network4']),
IPNetwork(GET['network6'])) IPNetwork(GET['network6'])))
except: except:
result["ipv6_template"] = "" result["ipv6_template"] = result["host_ipv6_prefixlen"] = ""
return JsonResponse({k: unicode(result[k] or "") for k in result}) return JsonResponse({k: unicode(result[k] or "") for k in result})
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
......
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