Sample usage:
use Net::CIDR::Lite;
my $cidr = Net::CIDR::Lite->new;
$cidr->add("209.152.214.112/30");
$cidr->add("209.152.214.116/31");
$cidr->add("209.152.214.118/31");
print "$_\n" for $cidr->list;
And the module:
##################################
package Net::CIDR::Lite;
use strict;
use Socket qw(inet_aton inet_ntoa);
use vars qw($VERSION);
$VERSION = '0.01';
my @masks = (0,0,map { pack("B*", substr("1" x $_ . "0" x 32, 0, 32))
+} 2..32);
my @bits2rng = (0,0,map { 2**(32 - $_) } 2..32);
my %rng2bits = map { $bits2rng[$_] => $_ } 0..32;
sub new {
my $proto = shift;
my $class = ref($proto) || $proto;
bless {}, $class;
}
sub add {
my $self = shift;
local $_ = shift;
my ($ip, $mask) = split "/";
my $start = inet_aton($ip) & $masks[$mask];
my $end = pack("N", unpack("N", $start) + $bits2rng[$mask]);
$$self{$start}++;
$$self{$end}--;
}
sub clean {
my $self = shift;
%$self = map { $$self{$_} ? ($_ => $$self{$_}) : () } keys %$self;
}
sub list {
my $self = shift;
my ($start, $total);
my @results;
for my $ip (sort keys %$self) {
$start = $ip unless $total;
$total += $$self{$ip};
unless ($total) {
my $diff = unpack("N", $ip) - unpack("N", $start);
while ($diff) {
(my $zeros = unpack("B*", $start)) =~ s/^.*1//;
my $range;
for my $i (32-length($zeros)..32) {
$range = $bits2rng[$i], last if $bits2rng[$i] <= $
+diff;
}
push @results, inet_ntoa($start)."/".$rng2bits{$range}
+;
$diff -= $range;
$start = pack("N", unpack("N", $start)+$range);
}
}
}
wantarray ? @results : \@results;
}
1;
__END__
=head1 NAME
Net::CIDR::Lite - Perl extension for merging CIDR addresses
=head1 SYNOPSIS
use Net::CIDR::Lite;
my $cidr = Net::CIDR::Lite->new;
$cidr->add($cidr_address);
@cidr_list = $cidr->list;
=head1 DESCRIPTION
Faster alternative to Net::CIDR::cidradd. Limited
for the time being to IPv4 addresses.
=head1 METHODS
=item new()
$cidr = Net::CIDR::Lite->new
Creates an object to represent a list of CIDR address ranges.
=item add()
$cidr->add($cidr_address)
Adds a CIDR address range to the list.
=item $cidr->clean()
$cidr->clean;
If you are going to call the list method more than once on the
same data, then for optimal performance, you can call this to
purge null nodes from the list.
=item $cidr->list()
@cidr_list = $cidr->list;
Returns a list of the merged CIDR addresses.
=head1 CAVEATS
Garbage in/garbage out. This module makes no attempt to validate
the format of your data.
=head1 AUTHOR
runrig=head1 COPYRIGHT
This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=head1 SEE ALSO
L<Net::CIDR>.
=cut
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.