From 6356a7168ec51ce98145b77b095a7bc8dffb3880 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Mon, 13 Jan 2014 18:55:37 -0800 Subject: [PATCH] fix auto-assignment when forbidden range is very far from selected block, #26868, from #25530 --- FS/FS/addr_block.pm | 2 +- FS/FS/addr_range.pm | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/FS/FS/addr_block.pm b/FS/FS/addr_block.pm index 8dd09ab96..3e62a688b 100755 --- a/FS/FS/addr_block.pm +++ b/FS/FS/addr_block.pm @@ -242,7 +242,7 @@ sub next_free_addr { # also make sure it's not blocked from assignment by an address range if ( !$used{$freeaddr->addr } ) { my ($range) = grep { !$_->allow_use } - FS::addr_range->any_contains($freeaddr); + FS::addr_range->any_contains($freeaddr->addr); if ( !$range ) { # then we've found a free address return $freeaddr; diff --git a/FS/FS/addr_range.pm b/FS/FS/addr_range.pm index 18ae1e2ea..3cf746f7d 100644 --- a/FS/FS/addr_range.pm +++ b/FS/FS/addr_range.pm @@ -149,7 +149,10 @@ sub end { $self->set('start', $end); ($end, $start) = ($start, $end); } - $self->set('length', $end - $start + 1); + # bigints are PROBABLY not needed here...but if someone wants to exclude + # all the address space not assigned to them, for example, that could be + # a pretty large part of IPv4. + $self->set('length', $end->bigint - $start->bigint + 1); return $end->addr; } my $end = $start + $self->get('length') - 1; @@ -165,13 +168,13 @@ Checks whether IPADDR (a dotted-quad IPv4 address) is within the range. sub contains { my $self = shift; my $addr = shift; - $addr = NetAddr::IP->new($addr, 0) - unless ref($addr) and UNIVERSAL::isa($addr, 'NetAddr::IP'); + $addr = NetAddr::IP->new($addr, 0); return 0 unless $addr; my $start = NetAddr::IP->new($self->start, 0); - return ($addr >= $start and $addr - $start < $self->length) ? 1 : 0; + return ($addr >= $start and $addr->bigint - $start->bigint < $self->length) + ? 1 : 0; } =item as_string @@ -242,10 +245,14 @@ sub any_contains { =head1 DEVELOPER NOTE -L objects have netmasks. When using them to represent -range endpoints, be sure to set the netmask to I so that math on -the address doesn't stop at the subnet boundary. (The default is /32, -which doesn't work very well. Address ranges ignore subnet boundaries.) +L objects have netmasks. They also have overloaded operators +for addition and subtraction, but those have range limitations when comparing +addresses. (An IPv4 address is effectively a uint32; the difference +between two IPv4 addresses is the same range, but signed.) Therefore, +the distance between two addresses should be calculated using the +C method ($addr2->bigint - $addr1->bigint), which returns the +address as a L object, and also conveniently discards the +netmask. =head1 BUGS -- 2.11.0