Commit 49359a9d authored by Nick Morrott's avatar Nick Morrott

Import Upstream version 0.14

parent 38e03228
# Net::CIDR
#
# Copyright 2001-2009 Sam Varshavchik.
# Copyright 2001-2010 Sam Varshavchik.
#
# with contributions from David Cantrell.
#
# This program is free software; you can redistribute it
# and/or modify it under the same terms as Perl itself.
#
# $Revision: 1.19 $
package Net::CIDR;
......@@ -19,8 +17,6 @@ require Exporter;
# use AutoLoader qw(AUTOLOAD);
use Carp;
use Math::BigInt;
@ISA = qw(Exporter);
# Items to export into callers namespace by default. Note: do not export
......@@ -54,7 +50,7 @@ use Math::BigInt;
);
$VERSION = "0.13";
$VERSION = "0.14";
1;
......@@ -285,13 +281,10 @@ sub cidr2range {
my ($ip, $pfix)=($1, $2);
my $isipv6;
($isipv6, $ip)=_ipv6to4($ip);
my @ips= split (/\.+/, $ip);
my @ips=_iptoipa($ip);
grep {
croak "$_, as in '$cidr', is not a byte" unless $_ >= 0 && $_ <= 255 && $_ =~ /^[0-9]+$/;
} @ips;
$isipv6=shift @ips;
croak "$pfix, as in '$cidr', does not make sense"
unless $pfix >= 0 && $pfix <= ($#ips+1) * 8 && $pfix =~ /^[0-9]+$/;
......@@ -419,6 +412,28 @@ sub _ipv4to6 {
return join(":", splice (@words, 0, $ind)) . "::"
. join(":", @s);
}
# An IP address to an octet list.
# Returns a list. First element, flag: true if it was an IPv6 flag. Remaining
# values are octets.
sub _iptoipa {
my $iparg=shift;
my $isipv6;
my $ip;
($isipv6, $ip)=_ipv6to4($iparg);
my @ips= split (/\.+/, $ip);
grep {
croak "$_, in $iparg, is not a byte" unless $_ >= 0 && $_ <= 255 && $_ =~ /^[0-9]+$/;
} @ips;
return ($isipv6, @ips);
}
sub _h62d {
my $h=shift;
......@@ -474,39 +489,45 @@ sub _cidr2iprange {
#
sub addr2cidr {
my(@blocks, $address, $bitmask, $net, $octetstash) = ();
my($isIPv6, $addr) = _ipv6to4(shift);
my $bitsInAddress = ($isIPv6)?128:32;
# create BigInts if necessary. Straight assignment of ints to
# BigInts breaks BigInt-ness hence the bizarre subtractions later.
if($isIPv6) {
$address = new Math::BigInt 0;
$bitmask = new Math::BigInt 0;
$net = new Math::BigInt 0;
$octetstash = new Math::BigInt 0;
} else { ($address, $bitmask, $net, $octetstash) = (0, 0, 0, 0); }
# convert dotted-octets into an int (or BigInt)
do { $address = $address << 8; $address = $address + $_ }
for split(/\./, $addr);
foreach my $bits (reverse 0..$bitsInAddress) {
$octetstash = $octetstash - $octetstash + 255;
$bitmask = $bitmask - $bitmask;
for(1 .. $bits) { $bitmask = ($bitmask << 1) + 1; }
$bitmask = $bitmask << ($bitsInAddress - $bits);
$net = $address & $bitmask;
push @blocks, (map { $_ =~ s/\+//; (($isIPv6)?_ipv4to6($_):$_) }
join('.', reverse map {
my $temp = ($octetstash & $net) >> ($_ * 8);
$octetstash = $octetstash << 8;
$temp;
} (0 .. $bitsInAddress / 8 - 1)
))[0]."/$bits";
my @ips=_iptoipa(shift);
my $isipv6=shift @ips;
my $nbits;
if ($isipv6)
{
croak "An IPv6 address is 16 bytes long" unless $#ips == 15;
$nbits=128;
}
else
{
croak "An IPv4 address is 4 bytes long" unless $#ips == 3;
$nbits=32;
}
my @blocks;
foreach my $bits (reverse 0..$nbits)
{
my @ipcpy=@ips;
my $n=$bits;
while ($n < $nbits)
{
@ipcpy[$n / 8] &= (0xFF00 >> ($n % 8));
$n += 8;
$n &= 0xF8;
}
return @blocks;
my $s=join(".", @ipcpy);
push @blocks, ($isipv6 ? _ipv4to6($s):$s) . "/$bits";
}
return @blocks;
}
# Address and netmask to CIDR
......@@ -844,13 +865,9 @@ sub cidr2octets {
my $isipv6;
($isipv6, $ip)=_ipv6to4($ip);
my @ips= split (/\.+/, $ip);
my @ips=_iptoipa($ip);
grep {
croak "$_, as in '$cidr', is not a byte" unless $_ >= 0 && $_ <= 255 && $_ =~ /^[0-9]+$/;
} @ips;
$isipv6=shift @ips;
croak "$pfix, as in '$cidr', does not make sense"
unless $pfix >= 0 && $pfix <= ($#ips+1) * 8 && $pfix =~ /^[0-9]+$/;
......@@ -1172,10 +1189,16 @@ sub cidrlookup {
=head2 $ip=Net::CIDR::cidrvalidate($ip);
Validate whether $ip is a valid IPv4 or IPv6 address.
Validate whether $ip is a valid IPv4 or IPv6 address, or a CIDR.
Returns its argument or undef.
Spaces are removed, and IPv6 hexadecimal address are converted to lowercase.
If $ip contains a "/", it must be a valid CIDR, otherwise it must be a valid
IPv4 or an IPv6 address.
A technically invalid CIDR, such as "192.168.0.1/24" fails validation, returning
undef.
=cut
sub cidrvalidate {
......@@ -1185,6 +1208,16 @@ sub cidrvalidate {
$v=lc($v);
my $suffix;
($v, $suffix)=($1, $2) if $v =~ m@(.*)/(.*)@;
if (defined $suffix)
{
return undef unless $suffix =~ /^\d+$/ &&
($suffix eq "0" || $suffix =~ /^[123456789]/);
}
if ($v =~ /^([0-9\.]+)$/ || $v =~ /^::ffff:([0-9\.]+)$/ ||
$v =~ /^:([0-9\.]+)$/)
{
......@@ -1201,7 +1234,25 @@ sub cidrvalidate {
return if /^0./;
return if $_ < 0 || $_ > 255;
}
return $v;
if ($v =~ /^::ffff/)
{
$suffix=128 unless defined $suffix;
return undef if $suffix < 128-32;
$suffix -= 128-32;
}
else
{
$suffix=32 unless defined $suffix;
}
foreach (addr2cidr($n))
{
return $v if $_ eq "$n/$suffix";
}
return undef;
}
return undef unless $v =~ /^[0-9a-f:]+$/;
......@@ -1218,7 +1269,13 @@ sub cidrvalidate {
return undef if length ($_) > 4;
}
return $v;
$suffix=128 unless defined $suffix;
foreach (addr2cidr($v))
{
return $v if $_ eq "$v/$suffix";
}
return undef;
}
=pod
......@@ -1226,7 +1283,7 @@ sub cidrvalidate {
=head1 BUGS
Garbage in, garbage out.
Always use validate() before doing anything with untrusted input.
Always use cidrvalidate() before doing anything with untrusted input.
Otherwise,
"slightly" invalid input will work (extraneous whitespace
is generally OK),
......
......@@ -26,3 +26,9 @@ Revision history for Perl extension Net::CIDR.
0.13 Sun Jan 18 19:51:43 EST 2009
- Fix some documentation typos.
0.14 Sun Jun 27 09:34:22 EDT 2010
- corrected some documentation errors. cidrvalidate() will validate
either an IP address or a CIDR, either one. Reimplemented addr2cidr.
New implementation does not use Math::BigInt, much faster with ipv6
addresses.
\ No newline at end of file
......@@ -7,3 +7,4 @@ COPYING
README
Net-CIDR.spec
Net-CIDR.spec.PL
META.yml Module meta-data (added by MakeMaker)
--- #YAML:1.0
name: Net-CIDR
version: 0.13
abstract: Manipulate IPv4/IPv6 netblocks in CIDR notation
license: ~
author:
name: Net-CIDR
version: 0.14
abstract: Manipulate IPv4/IPv6 netblocks in CIDR notation
author:
- Sam Varshavchik <sam@email-scan.com>
generated_by: ExtUtils::MakeMaker version 6.42
distribution_type: module
requires:
Carp: 0
license: unknown
distribution_type: module
configure_requires:
ExtUtils::MakeMaker: 0
build_requires:
ExtUtils::MakeMaker: 0
requires:
Carp: 0
no_index:
directory:
- t
- inc
generated_by: ExtUtils::MakeMaker version 6.55_02
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.3.html
version: 1.3
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: 1.4
Summary: Net::CIDR Perl module
Name: perl-Net-CIDR
Version: 0.13
Version: 0.14
Release: 1%(%{__perl} -e 'my $v=$^V; $v =~ s/(.)/".".ord($1)/ge;print "$v\n";')
Source0: Net-CIDR-%{version}.tar.gz
License: Perl
......
......@@ -6,7 +6,7 @@
# Change 1..1 below to 1..last_test_to_print .
# (It may become useful if the test is moved to ./t subdirectory.)
BEGIN { $| = 1; print "1..1\n"; }
BEGIN { $| = 1; print "1..9\n"; }
END {print "not ok 1\n" unless $loaded;}
use Net::CIDR;
$loaded = 1;
......@@ -18,3 +18,98 @@ print "ok 1\n";
# (correspondingly "not ok 13") depending on the success of chunk 13
# of the test code):
{
my @octet_list=Net::CIDR::cidr2octets("10.0.0.0/14", "192.68.0.0/24");
push @octet_list, Net::CIDR::cidr2octets("::dead:beef:0:0/110");
my @res=("10.0", "10.1", "10.2", "10.3", "192.68.0",
"0000:0000:0000:0000:dead:beef:0000",
"0000:0000:0000:0000:dead:beef:0001",
"0000:0000:0000:0000:dead:beef:0002",
"0000:0000:0000:0000:dead:beef:0003");
if (join(" ", @octet_list) eq join(" ", @res))
{
print "ok 2\n";
}
else
{
print "not ok 2\n";
}
}
if (join(" ", Net::CIDR::addr2cidr('192.68.0.31'))
eq "192.68.0.31/32 192.68.0.30/31 192.68.0.28/30 192.68.0.24/29 192.68.0.16/28 192.68.0.0/27 192.68.0.0/26 192.68.0.0/25 192.68.0.0/24 192.68.0.0/23 192.68.0.0/22 192.68.0.0/21 192.68.0.0/20 192.68.0.0/19 192.68.0.0/18 192.68.0.0/17 192.68.0.0/16 192.68.0.0/15 192.68.0.0/14 192.64.0.0/13 192.64.0.0/12 192.64.0.0/11 192.64.0.0/10 192.0.0.0/9 192.0.0.0/8 192.0.0.0/7 192.0.0.0/6 192.0.0.0/5 192.0.0.0/4 192.0.0.0/3 192.0.0.0/2 128.0.0.0/1 0.0.0.0/0")
{
print "ok 3\n";
}
else
{
print "not ok 3\n";
}
if (join("",
Net::CIDR::cidr2range("192.68.0.0/16")) eq "192.68.0.0-192.68.255.255"
&& join("", Net::CIDR::cidr2range("dead::beef::/46"))
eq "dead:beef::-dead:beef:3:ffff:ffff:ffff:ffff:ffff")
{
print "ok 4\n";
}
else
{
print "not ok 4\n";
}
if (Net::CIDR::cidrvalidate("192.168.0.1") &&
Net::CIDR::cidrvalidate("::ffff:192.168.0.1") &&
Net::CIDR::cidrvalidate("192.168.0.0/24") &&
Net::CIDR::cidrvalidate("::ffff:192.168.0.0/120"))
{
print "ok 5\n";
}
else
{
print "not ok 5\n";
}
if (Net::CIDR::cidrvalidate("192.168.0.1/24") ||
Net::CIDR::cidrvalidate("::ffff:192.168.0.1/120"))
{
print "not ok 6\n";
}
else
{
print "ok 6\n";
}
if (Net::CIDR::cidrvalidate("dead:beef::") &&
Net::CIDR::cidrvalidate("dead:beef::/32") &&
Net::CIDR::cidrvalidate("dead:beef::/120"))
{
print "ok 7\n";
}
else
{
print "not ok 7\n";
}
if (Net::CIDR::cidrvalidate("dead:beef::/31"))
{
print "not ok 8\n";
}
else
{
print "ok 8\n";
}
if (join(" ", Net::CIDR::addr2cidr("192.168.0.31"))
eq "192.168.0.31/32 192.168.0.30/31 192.168.0.28/30 192.168.0.24/29 192.168.0.16/28 192.168.0.0/27 192.168.0.0/26 192.168.0.0/25 192.168.0.0/24 192.168.0.0/23 192.168.0.0/22 192.168.0.0/21 192.168.0.0/20 192.168.0.0/19 192.168.0.0/18 192.168.0.0/17 192.168.0.0/16 192.168.0.0/15 192.168.0.0/14 192.168.0.0/13 192.160.0.0/12 192.160.0.0/11 192.128.0.0/10 192.128.0.0/9 192.0.0.0/8 192.0.0.0/7 192.0.0.0/6 192.0.0.0/5 192.0.0.0/4 192.0.0.0/3 192.0.0.0/2 128.0.0.0/1 0.0.0.0/0")
{
print "ok 9\n";
}
else
{
print "not ok 9\n";
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment