Net-IPAddress-Util
view release on metacpan or search on metacpan
lib/Net/IPAddress/Util/Range.pm view on Meta::CPAN
package Net::IPAddress::Util::Range;
use strict;
use warnings;
use 5.012;
use overload (
'""' => 'as_string',
'<=>' => '_spaceship',
'cmp' => '_spaceship',
);
use Net::IPAddress::Util qw( :constr :manip );
require Net::IPAddress::Util::Collection;
our $VERSION = '5.001';
sub new {
my $class = shift;
$class = ref($class) || $class;
my ($arg_ref) = @_;
my ($l, $u);
if ($arg_ref->{ lower } && $arg_ref->{ upper }) {
$arg_ref->{ lower } = IP($arg_ref->{ lower });
$arg_ref->{ upper } = IP($arg_ref->{ upper });
if ($arg_ref->{ lower } > $arg_ref->{ upper }) {
($arg_ref->{ lower }, $arg_ref->{ upper }) = ($arg_ref->{ upper }, $arg_ref->{ lower });
}
return bless $arg_ref => $class;
}
elsif ($arg_ref->{ ip }) {
my $ip;
my $nm = 2;
if ($arg_ref->{ netmask }) {
$ip = IP($arg_ref->{ ip });
my $was_ipv4 = $ip->is_ipv4;
$nm = IP($arg_ref->{ netmask });
$ip &= $nm;
$nm = ~$nm;
if ($was_ipv4) {
$nm &= ipv4_mask();
}
$l = $ip;
$u = $ip | $nm;
}
elsif ($arg_ref->{ ip } =~ m{(.*?)/(\d+)}) {
my ($t, $cidr) = ($1, $2);
$ip = IP($t);
my $was_ipv4 = $ip->is_ipv4;
my $span
= ($was_ipv4
? 32
: 128) - $cidr
;
$nm = implode_ip(substr(('1' x 128) . ('0' x $span), -128));
$ip &= $nm;
$l = $ip;
$u = $ip | ~$nm;
}
elsif ($arg_ref->{ cidr }) {
$ip = IP($arg_ref->{ ip });
my $was_ipv4 = $ip->is_ipv4;
my $cidr = $arg_ref->{ cidr };
my $span
= ($was_ipv4
? 32
: 128) - $cidr
;
$nm = implode_ip(substr(('1' x 128) . ('0' x $span), -128));
$ip &= $nm;
$l = $ip;
$u = $ip | ~$nm;
}
else {
$l = IP($arg_ref->{ ip });
$u = IP($arg_ref->{ ip });
}
}
return bless { lower => $l, upper => $u } => $class;
}
sub as_string {
my $self = shift;
return "($self->{ lower } .. $self->{ upper })";
}
sub outer_bounds {
my $self = shift;
my @l = explode_ip($self->{ lower });
my @u = explode_ip($self->{ upper });
my @cidr = common_prefix(@l, @u);
my $cidr = scalar @cidr;
my $base = implode_ip(ip_pad_prefix(@cidr));
if ($base->is_ipv4()) {
$cidr -= 96;
}
my @mask = prefix_mask(@l, @u);
my $nm = implode_ip(ip_pad_prefix(@mask));
my $x = ~$nm;
if ($base->is_ipv4()) {
$nm &= ipv4_mask();
}
my $hi = IP($base);
$hi |= $x;
return bless {
lower => $base,
cidr => $cidr,
netmask => $nm,
upper => $hi,
} => ref($self);
}
sub inner_bounds {
my $self = shift;
return $self if $self->{ upper } == $self->{ lower };
my $bounds = $self->outer_bounds();
my $new = ref($self)->new($self);
while ($bounds->{ upper } > $self->{ upper } or $bounds->{ lower } < $self->{ lower }) {
$new = ref($self)->new({ ip => $self->{ lower }, cidr => $bounds->{ cidr } + 1 });
$bounds = $new->outer_bounds();
}
return $new;
}
sub as_cidr {
my $self = shift;
my $hr = $self->outer_bounds();
return "$hr->{ lower }" . '/' . "$hr->{ cidr }";
}
sub as_netmask {
my $self = shift;
my $hr = $self->outer_bounds();
return "$hr->{ lower }" . ' (' . "$hr->{ netmask }" . ')';
}
sub loose {
my $self = shift;
my $hr = $self->outer_bounds();
( run in 0.414 second using v1.01-cache-2.11-cpan-13bb782fe5a )