Commit baacc263 by Bach Dániel

firewall: make ipv6 addresses configurable and optional #37

parent 44d036dd
...@@ -12,8 +12,9 @@ import re ...@@ -12,8 +12,9 @@ import re
mac_re = re.compile(r'^([0-9a-fA-F]{2}(:|$)){6}$') mac_re = re.compile(r'^([0-9a-fA-F]{2}(:|$)){6}$')
alfanum_re = re.compile(r'^[A-Za-z0-9_-]+$') alfanum_re = re.compile(r'^[A-Za-z0-9_-]+$')
domain_re = re.compile(r'^([A-Za-z0-9_-]\.?)+$') domain_re = re.compile(r'^([A-Za-z0-9_-]\.?)+$')
ipv4_re = re.compile('^[0-9]+\.([0-9]+)\.([0-9]+)\.([0-9]+)$') ipv4_re = re.compile('^([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)$')
reverse_domain_re = re.compile(r'^(%\([abcd]\)d|[a-z0-9.-])+$') reverse_domain_re = re.compile(r'^(%\([abcd]\)d|[a-z0-9.-])+$')
ipv6_template_re = re.compile(r'^(%\([abcd]\)[dxX]|[A-Za-z0-9:-])+$')
class MACAddressFormField(fields.RegexField): class MACAddressFormField(fields.RegexField):
...@@ -220,6 +221,17 @@ def val_reverse_domain(value): ...@@ -220,6 +221,17 @@ def val_reverse_domain(value):
raise ValidationError(u'%s - invalid reverse domain name' % value) raise ValidationError(u'%s - invalid reverse domain name' % value)
def is_valid_ipv6_template(value):
"""Check whether the parameter is a valid ipv6 template."""
return ipv6_template_re.match(value) is not None
def val_ipv6_template(value):
"""Validate whether the parameter is a valid ipv6 template."""
if not is_valid_ipv6_template(value):
raise ValidationError(u'%s - invalid reverse ipv6 template' % value)
def is_valid_ipv4_address(value): def is_valid_ipv4_address(value):
"""Check whether the parameter is a valid IPv4 address.""" """Check whether the parameter is a valid IPv4 address."""
return ipv4_re.match(value) is not None return ipv4_re.match(value) is not None
...@@ -249,9 +261,11 @@ def val_mx(value): ...@@ -249,9 +261,11 @@ def val_mx(value):
"Should be: <priority>:<hostname>")) "Should be: <priority>:<hostname>"))
def ipv4_2_ipv6(ipv4): def ipv4_2_ipv6(ipv6_template, ipv4):
"""Convert IPv4 address string to IPv6 address string.""" """Convert IPv4 address string to IPv6 address string."""
val_ipv4(ipv4) val_ipv4(ipv4)
m = ipv4_re.match(ipv4) m = ipv4_re.match(ipv4)
return ("2001:738:2001:4031:%s:%s:%s:0" % return (ipv6_template % {'a': int(m.group(1)),
(m.group(1), m.group(2), m.group(3))) 'b': int(m.group(2)),
'c': int(m.group(3)),
'd': int(m.group(4))})
...@@ -9,6 +9,7 @@ from django.db import models ...@@ -9,6 +9,7 @@ from django.db import models
from django.forms import ValidationError from django.forms import ValidationError
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from firewall.fields import (MACAddressField, val_alfanum, val_reverse_domain, from firewall.fields import (MACAddressField, val_alfanum, val_reverse_domain,
val_ipv6_template,
val_domain, val_ipv4, val_ipv6, val_mx, val_domain, val_ipv4, val_ipv6, val_mx,
ipv4_2_ipv6, IPNetworkField, IPAddressField) ipv4_2_ipv6, IPNetworkField, IPAddressField)
from django.core.validators import MinValueValidator, MaxValueValidator from django.core.validators import MinValueValidator, MaxValueValidator
...@@ -247,6 +248,10 @@ class Vlan(AclBase, models.Model): ...@@ -247,6 +248,10 @@ class Vlan(AclBase, models.Model):
'For example, the template for the standard reverse ' 'For example, the template for the standard reverse '
'address is: "%(d)d.%(c)d.%(b)d.%(a)d.in-addr.arpa".'), 'address is: "%(d)d.%(c)d.%(b)d.%(a)d.in-addr.arpa".'),
default="%(d)d.%(c)d.%(b)d.%(a)d.in-addr.arpa") default="%(d)d.%(c)d.%(b)d.%(a)d.in-addr.arpa")
ipv6_template = models.TextField(
validators=[val_ipv6_template],
verbose_name=_('ipv6 template'),
default="2001:738:2001:4031:%(b)d:%(c)d:%(d)d:0")
dhcp_pool = models.TextField(blank=True, verbose_name=_('DHCP pool'), dhcp_pool = models.TextField(blank=True, verbose_name=_('DHCP pool'),
help_text=_( help_text=_(
'The address range of the DHCP pool: ' 'The address range of the DHCP pool: '
...@@ -303,10 +308,13 @@ class Vlan(AclBase, models.Model): ...@@ -303,10 +308,13 @@ class Vlan(AclBase, models.Model):
ipv4 = str(ipv4) ipv4 = str(ipv4)
if ipv4 not in used_v4: if ipv4 not in used_v4:
logger.debug("Found unused IPv4 address %s.", ipv4) logger.debug("Found unused IPv4 address %s.", ipv4)
ipv6 = ipv4_2_ipv6(ipv4) if self.network6 is None:
if ipv6 not in used_v6: return {'ipv4': ipv4, 'ipv6': None}
logger.debug("Found unused IPv6 address %s.", ipv6) else:
return {'ipv4': ipv4, 'ipv6': ipv6} ipv6 = ipv4_2_ipv6(self.ipv6_template, ipv4)
if ipv6 not in used_v6:
logger.debug("Found unused IPv6 address %s.", ipv6)
return {'ipv4': ipv4, 'ipv6': ipv6}
raise ValidationError(_("All IP addresses are already in use.")) raise ValidationError(_("All IP addresses are already in use."))
...@@ -448,7 +456,7 @@ class Host(models.Model): ...@@ -448,7 +456,7 @@ class Host(models.Model):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.id and self.ipv6 == "auto": if not self.id and self.ipv6 == "auto":
self.ipv6 = ipv4_2_ipv6(self.ipv4) self.ipv6 = ipv4_2_ipv6(self.vlan.ipv6_template, self.ipv4)
self.full_clean() self.full_clean()
super(Host, self).save(*args, **kwargs) super(Host, self).save(*args, **kwargs)
......
...@@ -231,6 +231,7 @@ class VlanForm(ModelForm): ...@@ -231,6 +231,7 @@ class VlanForm(ModelForm):
Fieldset( Fieldset(
'IPv6', 'IPv6',
'network6', 'network6',
'ipv6_template',
), ),
Fieldset( Fieldset(
'Domain name service', 'Domain name service',
......
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