From 114c68ff0bbb685720d9ac20a0156ce492b6e576 Mon Sep 17 00:00:00 2001 From: Ben Burwood Date: Thu, 14 Mar 2024 19:53:29 +0000 Subject: [PATCH] Add IpRange Model and Form with Validation --- NetworkMapper/ip/forms.py | 6 +++++ NetworkMapper/ip/models/ip.py | 47 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 NetworkMapper/ip/models/ip.py diff --git a/NetworkMapper/ip/forms.py b/NetworkMapper/ip/forms.py index 707b114..ed82da1 100644 --- a/NetworkMapper/ip/forms.py +++ b/NetworkMapper/ip/forms.py @@ -1,6 +1,12 @@ from django import forms from .models import ClientDevice, VLAN, WifiNetwork +from .models.ip import IpRange + +class IpRangeForm(forms.Form): + class Meta: + model = IpRange + fields = ["start_address", "end_address", "num_addresses", "description"] class VLANForm(forms.ModelForm): diff --git a/NetworkMapper/ip/models/ip.py b/NetworkMapper/ip/models/ip.py new file mode 100644 index 0000000..4da1a71 --- /dev/null +++ b/NetworkMapper/ip/models/ip.py @@ -0,0 +1,47 @@ +from django.core.exceptions import ValidationError +from django.db import models + + +class IpRange(models.Model): + start_address = models.GenericIPAddressField() + end_address = models.GenericIPAddressField() + num_addresses = models.PositiveIntegerField() + description = models.TextField(blank=True, null=True) + + def clean(self): + super().clean() + + if self.start_address > self.end_address: + raise ValidationError("Start Address must be Lower than End Address") + + if self.start_address.protocol != self.end_address.protocol: + raise ValidationError("Start Address and End Address must be of the same IP Version") + + for other_ip_range in IpRange.objects.exclude(pk=self.pk): + if self.check_overlap(other_ip_range): + raise ValidationError("IP Range overlaps with another IP Range : " + other_ip_range) + + def check_overlap(self, other: "IpRange") -> bool: + """Check if the given IP Range overlaps with the current IP Range""" + if self.start_address <= other.start_address <= self.end_address: + return True + if self.start_address <= other.end_address <= self.end_address: + return True + if other.start_address <= self.start_address <= other.end_address: + return True + if other.start_address <= self.end_address <= other.end_address: + return True + return False + + @staticmethod + def ipv4_to_numeric(ip): + octets = ip.split(".") + + for octet in octets: + if not octet.isdigit() or not 0 <= int(octet) <= 255: + raise ValueError("Invalid IPv4 address format") + + numeric_ip = 0 + for i in range(4): + numeric_ip += int(octets[i]) * (256 ** (3 - i)) + return numeric_ip