Closed
Description
Deployment Type
Self-hosted
NetBox Version
v4.0.11
Python Version
3.12
Steps to Reproduce
- Create an IPRange with start 1.2.3.100/24 and end 1.2.3.200/24
- Create an IPRange with start 1.2.3.123/26 and end 1.2.3.124/26
Expected Behavior
The second IPRange should be rejected, as it overlaps with the first. (There is code in IPRange.clean()
which is clearly intended to do this)
Observed Behavior
The overlapping range is accepted.
The problem occurs because the Django ORM lte/gte filter for overlapping ranges only works if the prefix lengths match:
>>> ip = "1.2.3.101/24"
>>> IPRange.objects.filter(start_address__lte=ip, end_address__gte=ip, vrf=None)
<RestrictedQuerySet [<IPRange: 1.2.3.100-200/24>]>
>>> ip = "1.2.3.101/26"
>>> IPRange.objects.filter(start_address__lte=ip, end_address__gte=ip, vrf=None)
<RestrictedQuerySet []>
I cannot see an obvious solution here, apart from brute force iterating over all possible prefix lengths:
>>> [IPRange.objects.filter(start_address__lte=f"1.2.3.101/{pl}", end_address__gte=f"1.2.3.101/{pl}", vrf=None).count() for pl in range(33)]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
Alternatively, changing the data model so that a range uses IPAddress instead of IPNetwork for the start/end addresses would eliminate this problem.