use NetAddr::IP;
use FS::addr_block;
use FS::router;
+use FS::addr_range;
use FS::Record qw(qsearch);
use FS::Conf;
# careful about importing anything here--it will end up in a LOT of
$self->ip_addr('');
}
+ # Will strip extraneous leading zeros from ip adddresses
+ # e.g. 10.0.022.220 corrected to 10.0.22.220
+ $self->ut_ip46n('ip_addr');
+
if ( $self->ip_addr
and !$self->router
and $self->conf->exists('auto_router') ) {
my $self = shift;
my %opt = @_;
+ #otherwise we'll get the same assignment for concurrent identical calls
+ # this will serialize them
+ $_->lock_table foreach @subclasses;
+
my @blocks;
my $na = $self->NetAddr;
# don't exit early on assigning a free address--check the rest of
# the blocks to see if the current address is in one of them.
if (!$new_addr) {
- $new_addr = $block->next_free_addr->addr;
+ $new_addr = $block->next_free_addr;
$new_block = $block;
}
}
return 'No IP address available on this router' unless $new_addr;
- $self->ip_addr($new_addr);
+ $self->ip_addr($new_addr->addr);
$self->addr_block($new_block);
'';
}
return '' if $addr eq '';
my $na = $self->NetAddr
or return "Can't parse address '$addr'";
+ # if there's a chosen address block, check that the address is in it
if ( my $block = $self->addr_block ) {
if ( !$block->NetAddr->contains($na) ) {
return "Address $addr not in block ".$block->cidr;
}
}
- # this returns '' if the address is in use by $self.
+ # if the address is in any designated ranges, check that they don't
+ # disallow use
+ foreach my $range (FS::addr_range->any_contains($addr)) {
+ if ( !$range->allow_use ) {
+ return "Address $addr is in ".$range->desc." range ".$range->as_string;
+ }
+ }
+ # check that nobody else is sitting on the address
+ # (this returns '' if the address is in use by $self)
if ( my $dup = $self->is_used($self->ip_addr) ) {
return "Address $addr in use by $dup";
}
FS::router->by_key($self->routernum);
}
-=item used_addresses [ BLOCK ]
+=item used_addresses [ FS::addr_block ]
-Returns a list of all addresses (in BLOCK, or in all blocks)
-that are in use. If called as an instance method, excludes
-that instance from the search.
+Returns a list of all addresses in use within the given L<FS::addr_block>.
+
+If called as an instance method, excludes that instance from the search.
=cut
sub used_addresses {
- my $self = shift;
- my $block = shift;
- return ( map { $_->_used_addresses($block, $self) } @subclasses );
+ my ($self, $block) = @_;
+
+ (
+ $block->ip_gateway ? $block->ip_gateway : (),
+ $block->NetAddr->broadcast->addr,
+ map { $_->_used_addresses($block, $self ) } @subclasses
+ );
}
sub _used_addresses {