# NOTE: Derived from blib/lib/NetAddr/IP.pm.
# Changes made here will be lost when autosplit is run again.
# See AutoSplit.pm.
package NetAddr::IP;
#line 1015 "blib/lib/NetAddr/IP.pm (autosplit into blib/lib/auto/NetAddr/IP/_splitplan.al)"
# input: $naip,
# @bits, list of masks for splits
#
# returns: empty array request will not fit in submitted net
# (\@bits,undef) if there is just one plan item i.e. return original net
# (\@bits,\%masks) for a real plan
#
sub _splitplan {
my($ip,@bits) = @_;
my $addr = $ip->addr();
my $isV6 = $ip->{isv6};
unless (@bits) {
$bits[0] = $isV6 ? 128 : 32;
}
my $basem = $ip->masklen();
my(%nets,$dif);
my $denom = 0;
my($x,$maddr);
foreach(@bits) {
if (ref $_) { # is a NetAddr::IP
$x = $_->{isv6} ? $_->{addr} : $_->{addr} | V4mask;
($x,$maddr) = notcontiguous($x);
return () if $x; # spurious bits
$_ = $isV6 ? $maddr : $maddr - 96;
}
elsif ( $_ =~ /^d+$/ ) { # is a negative number of the form -nnnn
;
}
elsif ($_ = NetAddr::IP->new($addr,$_,$isV6)) { # will be undefined if bad mask and will fall into oops!
$_ = $_->masklen();
}
else {
return (); # oops!
}
$dif = $_ - $basem; # for normalization
return () if $dif < 0; # overange nets not allowed
return (\@bits,undef) unless ($dif || $#bits); # return if original net = mask alone
$denom = $dif if $dif > $denom;
next if exists $nets{$_};
$nets{$_} = $_ - $basem; # for normalization
}
# $denom is the normalization denominator, since these are all exponents
# normalization can use add/subtract to accomplish normalization
#
# keys of %nets are the masks used by this split
# values of %nets are the normalized weighting for
# calculating when the split is "full" or complete
# %masks values contain the actual masks for each split subnet
# @bits contains the masks in the order the user actually wants them
#
my %masks; # calculate masks
my $maskbase = $isV6 ? 128 : 32;
foreach( keys %nets ) {
$nets{$_} = 2 ** ($denom - $nets{$_});
$masks{$_} = shiftleft(Ones, $maskbase - $_);
}
my @plan;
my $idx = 0;
$denom = 2 ** $denom;
PLAN:
while ($denom > 0) { # make a net plan
my $nexmask = ($idx < $#bits) ? $bits[$idx] : $bits[$#bits];
++$idx;
unless (($denom -= $nets{$nexmask}) < 0) {
return () if (push @plan, $nexmask) > $_netlimit;
next;
}
# a fractional net is needed that is not in the mask list or the replicant
$denom += $nets{$nexmask}; # restore mistake
TRY:
foreach (sort { $a <=> $b } keys %nets) {
next TRY if $nexmask > $_;
do {
next TRY if $denom - $nets{$_} < 0;
return () if (push @plan, $_) > $_netlimit;
$denom -= $nets{$_};
} while $denom;
}
die 'ERROR: miscalculated weights' if $denom;
}
return () if $idx < @bits; # overrange original subnet request
return (\@plan,\%masks);
}
# end of NetAddr::IP::_splitplan
1;
Copyright 2K16 - 2K18 Indonesian Hacker Rulez