package FS::addr_block;
+use base qw(FS::Record);
use strict;
-use vars qw( @ISA );
-use FS::Record qw( qsearchs qsearch dbh );
-use FS::router;
-use FS::svc_broadband;
-use FS::Conf;
-use NetAddr::IP;
use Carp qw( carp );
-
-@ISA = qw( FS::Record );
+use List::Util qw( first );
+use NetAddr::IP;
+use FS::Conf;
+use FS::Record qw( qsearch dbh ); #qsearchs
+use FS::IP_Mixin;
+use FS::addr_range;
=head1 NAME
Returns the FS::router object corresponding to this object. If the
block is unassigned, returns undef.
-=cut
-
-sub router {
- my $self = shift;
- return qsearchs('router', { routernum => $self->routernum });
-}
-
=item svc_broadband
Returns a list of FS::svc_broadband objects associated
with this object.
-=cut
-
-sub svc_broadband {
- my $self = shift;
- return qsearch('svc_broadband', { blocknum => $self->blocknum });
-}
-
=item NetAddr
Returns a NetAddr::IP object for this block's address and netmask.
Returns a NetAddr::IP object corresponding to the first unassigned address
in the block (other than the network, broadcast, or gateway address). If
-there are no free addresses, returns false. There are never free addresses
+there are no free addresses, returns nothing. There are never free addresses
when manual_flag is true.
+There is no longer a method to return all free addresses in a block.
+
=cut
sub next_free_addr {
my $self = shift;
+ my $selfaddr = $self->NetAddr;
- return '' if $self->manual_flag;
+ return () if $self->manual_flag;
my $conf = new FS::Conf;
my @excludeaddr = $conf->config('exclude_ip_addr');
-
-my @used =
-( (map { $_->NetAddr->addr }
- ($self,
- qsearch('svc_broadband', { blocknum => $self->blocknum }))
- ), @excludeaddr
-);
-
- my @free = $self->NetAddr->hostenum;
- while (my $ip = shift @free) {
- if (not grep {$_ eq $ip->addr;} @used) { return $ip; };
- }
- '';
+ my %used = map { $_ => 1 }
+ (
+ @excludeaddr,
+ $selfaddr->addr,
+ $selfaddr->network->addr,
+ $selfaddr->broadcast->addr,
+ FS::IP_Mixin->used_addresses($self)
+ );
+
+ # just do a linear search of the block
+ my $freeaddr = $selfaddr->network + 1;
+ while ( $freeaddr < $selfaddr->broadcast ) {
+ # 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->addr);
+ if ( !$range ) {
+ # then we've found a free address
+ return $freeaddr;
+ }
+ # otherwise, skip to the end of the range
+ $freeaddr = NetAddr::IP->new($range->end, $self->ip_netmask);
+ }
+ $freeaddr++;
+ }
+ return;
}
Returns the agent (see L<FS::agent>) for this address block, if one exists.
-=cut
-
-sub agent {
- qsearchs('agent', { 'agentnum' => shift->agentnum } );
-}
-
=item label
Returns text including the router name, gateway ip, and netmask for this
($router ? $router->routername : '(unallocated)'). ':'. $self->NetAddr;
}
+=item router
+
+Returns the router assigned to this block.
+
+=cut
+
+# necessary, because this can't be foreign keyed
+
+sub router {
+ my $self = shift;
+ my $routernum = $self->routernum;
+ if ( $routernum ) {
+ return FS::router->by_key($routernum);
+ } else {
+ return;
+ }
+}
+
=back
=head1 BUGS