Browse Source

Validate CIDR values to be proper subnets, to avoid database errors

Baptiste Jonglez 11 years ago
parent
commit
0ba1772e9b
1 changed files with 13 additions and 2 deletions
  1. 13 2
      coin/resources/models.py

+ 13 - 2
coin/resources/models.py

@@ -5,6 +5,16 @@ from django.core.validators import MaxValueValidator
 from netfields import CidrAddressField, NetManager
 from netaddr import IPNetwork, IPSet
 
+
+def validate_subnet(cidr):
+    """Checks that a CIDR object is indeed a subnet, i.e. the host bits are
+    all set to zero."""
+    if not isinstance(cidr, IPNetwork):
+        raise ValidationError("Internal error, expected IPNetwork object")
+    if cidr.ip != cidr.network:
+        raise ValidationError("{} is not a proper subnet, you probably mean {}".format(cidr, cidr.cidr))
+
+
 class IPPool(models.Model):
     """Pool of IP addresses (either v4 or v6)."""
     name = models.CharField(max_length=255, blank=False, null=False,
@@ -12,7 +22,7 @@ class IPPool(models.Model):
     default_subnetsize = models.PositiveSmallIntegerField(blank=False,
                                                           verbose_name='Default subnet size to allocate to subscribers in this pool',
                                                           validators=[MaxValueValidator(64)])
-    inet = CidrAddressField()
+    inet = CidrAddressField(validators=[validate_subnet])
     objects = NetManager()
 
     def clean(self):
@@ -26,7 +36,8 @@ class IPPool(models.Model):
 
 
 class IPSubnet(models.Model):
-    inet = CidrAddressField(blank=True, verbose_name="Leave empty for automatic allocation")
+    inet = CidrAddressField(blank=True, validators=[validate_subnet],
+                            verbose_name="Leave empty for automatic allocation")
     objects = NetManager()
     ip_pool = models.ForeignKey(IPPool)
     offer_subscription = models.ForeignKey('offers.OfferSubscription',