diff --git a/IP.pm b/IP.pm index 6b291ab..19a3e7e 100644 --- a/IP.pm +++ b/IP.pm @@ -1,6 +1,6 @@ #!/usr/bin/perl -w -# $Id: IP.pm,v 1.6 2002/12/10 17:14:02 lem Exp $ +# $Id: IP.pm,v 1.11 2003/02/12 00:09:57 lem Exp $ package NetAddr::IP; @@ -44,8 +44,13 @@ use Socket; use strict; use warnings; +require Exporter; -our $VERSION = '3.14_1'; +our @EXPORT_OK = qw(Compact); + +our @ISA = qw(Exporter); + +our $VERSION = '3.14_3'; ############################################# # These are the overload methods, placed here @@ -82,20 +87,18 @@ return 0 unless ref $_[1] eq 'NetAddr::IP'; $_[0]->cidr eq $_[1]->cidr; }, - # The comparisons below are not portable - # when attempted with the full bit vector. - # This is why we break them down and do it - # one octet at a time. String comparison - - # is not portable because of endianness. '>' => sub { return undef unless $_[0]->{bits} == $_[1]->{bits}; + return ($_[0]->numeric)[1] > ($_[1]->numeric)[1] + if scalar($_[0]->numeric()) == scalar($_[1]->numeric()); return scalar($_[0]->numeric()) > scalar($_[1]->numeric()); }, '<' => sub { return undef unless $_[0]->{bits} == $_[1]->{bits}; + return ($_[0]->numeric)[1] < ($_[1]->numeric)[1] + if scalar($_[0]->numeric()) == scalar($_[1]->numeric()); return scalar($_[0]->numeric()) < scalar($_[1]->numeric()); }, @@ -112,12 +115,16 @@ '<=>' => sub { return undef unless $_[0]->{bits} == $_[1]->{bits}; + return ($_[0]->numeric)[1] <=> ($_[1]->numeric)[1] + if scalar($_[0]->numeric()) == scalar($_[1]->numeric()); return scalar($_[0]->numeric()) <=> scalar($_[1]->numeric()); }, 'cmp' => sub { return undef unless $_[0]->{bits} == $_[1]->{bits}; + return ($_[0]->numeric)[1] <=> ($_[1]->numeric)[1] + if scalar($_[0]->numeric()) == scalar($_[1]->numeric()); return scalar($_[0]->numeric()) <=> scalar($_[1]->numeric()); }, @@ -461,19 +468,31 @@ vec($addr, 0, 8) = 127; vec($addr, 3, 8) = 1; } - elsif ($ip =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { + elsif ($ip =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ + and $1 >= 0 and $1 <= 255 + and $2 >= 0 and $2 <= 255 + and $3 >= 0 and $3 <= 255 + and $4 >= 0 and $4 <= 255) + { vec($addr, 0, 8) = $1; vec($addr, 1, 8) = $2; vec($addr, 2, 8) = $3; vec($addr, 3, 8) = $4; } - elsif ($ip =~ m/^(\d+)\.(\d+)$/) { + elsif ($ip =~ m/^(\d+)\.(\d+)$/ + and $1 >= 0 and $1 <= 255 + and $2 >= 0 and $2 <= 255) + { vec($addr, 0, 8) = $1; vec($addr, 1, 8) = ($present ? $2 : 0); vec($addr, 2, 8) = 0; vec($addr, 3, 8) = ($present ? 0 : $2); } - elsif ($ip =~ m/^(\d+)\.(\d+)\.(\d+)$/) { + elsif ($ip =~ m/^(\d+)\.(\d+)\.(\d+)$/ + and $1 >= 0 and $1 <= 255 + and $2 >= 0 and $2 <= 255 + and $3 >= 0 and $3 <= 255) + { vec($addr, 0, 8) = $1; vec($addr, 1, 8) = $2; vec($addr, 2, 8) = ($present ? $3 : 0); @@ -907,6 +926,27 @@ =pod +=item C<-Ebits()> + +Returns the wide of the address in bits. Normally 32 for v4 and 128 for v6. + +=cut + +sub bits { return $_[0]->{bits}; } + +=pod + +=item C<-Eversion()> + +Returns the version of the address or subnet. Currently this can be +either 4 or 6. + +=cut + +sub version { return $_[0]->{bits} == 32 ? 4 : 6; } + +=pod + =item C<-Ecidr()> Returns a scalar with the address and mask in CIDR notation. A @@ -1211,6 +1251,8 @@ return @{compactref(\@_)}; } +*Compact = \&compact; + =pod =item C<$me-Ecompactref(\@list)> @@ -1222,10 +1264,8 @@ =cut sub compactref ($) { - my @addr = sort - - @{$_[0]} or - return []; + my @addr = sort @{$_[0]} + or return []; my $bits = $addr[0]->{bits}; my $changed; @@ -1245,7 +1285,7 @@ -- $i; } elsif (vec($lip->{mask}, 0, $bits) - == vec($hip->{mask}, 0, $bits)) + == vec($hip->{mask}, 0, $bits)) { my $la = $lip->{addr}; my $ha = $hip->{addr}; @@ -1362,7 +1402,7 @@ =head1 HISTORY -$Id: IP.pm,v 1.6 2002/12/10 17:14:02 lem Exp $ +$Id: IP.pm,v 1.11 2003/02/12 00:09:57 lem Exp $ =over @@ -1852,6 +1892,42 @@ =back +=item 3.14_2 + +Minor development release. + +=over + +=item * + +Added C<-Eversion> and C<-Ebits>, including testing. + +=item * + +C can now be exported if the user so requests. + +=item * + +Fixed a bug when octets in a dotted quad were > 256 (ie, were not +octets). Thanks to Anton Berezin for pointing this out. + +=back + +=item 3.14_3 + +Fixed a bug pointed out by Brent Imhoff related to the implicit +comparison that happens within C. The netmask was being +ignored in the comparison (ie, 10/8 was considered the same as +10.0/16). Since some people have requested that 10.0/16 was considered +larger than 10/8, I added this change, which makes the bug go +away. This will be the last '_' release, pending new bugs. + +Regarding the comparison of subnets, I'm still open to debate so as to +wether 10.0/16 > 10/8. Certainly 255.255.0.0 > 255.0.0.0, but 2 ** 24 +are more hosts than 2 ** 16. I think we might use gt & friends for +this semantic and make everyone happy, but I won't do anything else +here without (significant) feedback. + =back =head1 AUTHOR diff --git a/MANIFEST b/MANIFEST index efdefbe..4956ca7 100644 --- a/MANIFEST +++ b/MANIFEST @@ -9,6 +9,7 @@ t/v4-new.t t/v4-num.t t/relops.t +t/imhoff.t t/v4-aton.t t/v4-snew.t t/v4-cnew.t diff --git a/t/imhoff.t b/t/imhoff.t new file mode 100755 index 0000000..b750eaf --- /dev/null +++ b/t/imhoff.t @@ -0,0 +1,35 @@ +#!/usr/bin/perl + +# This code was provided by Brent Imhoff and adapted to become a real test. +# What this excercises, is that ::compact() should provide the same result +# without caring about the order of its arguments. -lem + +use strict; +use warnings; +use Test::More tests => 3; +use NetAddr::IP qw(Compact); + +my @temp = ; + +my @sortreg = sort @temp; +my @sortdec = sort { $b cmp $a} @temp; +my @sortnum = sort { $a cmp $b} @temp; + +my $sortnum = Compact(map { NetAddr::IP->new($_) } @sortnum); +my $sorttag = Compact(map { NetAddr::IP->new($_) } @sortreg); +my $sortdec = Compact(map { NetAddr::IP->new($_) } @sortdec); + +is($sortnum, $sorttag); +is($sortnum, $sortdec); +is($sortdec, $sorttag); # I know this one is redundant + +__END__ +205.170.190.0/24 +216.175.9.0/24 +205.170.188.0/24 +206.175.9.0/24 +205.170.0.0/20 +205.170.0.0/19 +205.170.0.0/18 +205.170.0.0/17 +205.170.0.0/16 diff --git a/t/relops.t b/t/relops.t index ed7a2a8..69037b9 100644 --- a/t/relops.t +++ b/t/relops.t @@ -1,22 +1,23 @@ use NetAddr::IP; -# $Id: relops.t,v 1.2 2002/10/31 04:30:35 lem Exp $ +# $Id: relops.t,v 1.3 2003/02/12 00:09:58 lem Exp $ -my @gt = ( +BEGIN { +@gt = ( [ '255.255.255.255/32', '0.0.0.0/0' ], [ '10.0.1.0/16', '10.0.0.1/24' ], [ '10.0.0.1/24', '10.0.0.0/24' ], ); -my @ngt = ( +@ngt = ( [ '0.0.0.0/0', '255.255.255.255/32' ], [ '10.0.0.0/24', '10.0.0.0/24' ], ); -my @cmp = ( +@cmp = ( [ '0.0.0.0/0', '255.255.255.255/32', -1 ], - [ '10.0.0.0/16', '10.0.0.0/8', 0 ], - [ '10.0.0.0/24', '10.0.0.0/8', 0 ], + [ '10.0.0.0/16', '10.0.0.0/8', 1 ], + [ '10.0.0.0/24', '10.0.0.0/8', 1 ], [ '255.255.255.255/32', '0.0.0.0/0', 1 ], [ '142.52.5.87', '142.52.2.88', 1 ], [ '10.0.0.0/24', '10.0.0.0/24', 0 ], @@ -25,60 +26,29 @@ [ 'loopback', 'loopback', 0], ); -$| = 1; +}; -print "1..", @gt + @ngt + (2 * @cmp), "\n"; - -my $count = 1; +use Test::More tests => @gt + @ngt + (2 * @cmp); for my $a (@gt) { my $a_ip = new NetAddr::IP $a->[0]; my $b_ip = new NetAddr::IP $a->[1]; - if ($a_ip > $b_ip) { - print "ok $count # $a_ip > $b_ip\n"; - } - else { - print "not ok $count # $a_ip > $b_ip\n"; - } - ++$count; + ok($a_ip > $b_ip, "$a_ip > $b_ip"); } for my $a (@ngt) { my $a_ip = new NetAddr::IP $a->[0]; my $b_ip = new NetAddr::IP $a->[1]; - if (not ($a_ip > $b_ip)) { - print "ok $count # $a_ip !> $b_ip\n"; - } - else { - print "not ok $count # $a_ip !> $b_ip\n"; - } - ++$count; + ok(!($a_ip > $b_ip), "$a_ip !> $b_ip"); } for my $a (@cmp) { my $a_ip = new NetAddr::IP $a->[0]; my $b_ip = new NetAddr::IP $a->[1]; - if (($a_ip <=> $b_ip) == $a->[2]) { - print "ok $count # $a_ip <=> $b_ip\n"; - } - else { - print "not ok $count # $a_ip <=> $b_ip\n"; - } - ++$count; + is($a_ip <=> $b_ip, $a->[2], "$a_ip <=> $b_ip is $a->[2]"); + is($a_ip cmp $b_ip, $a->[2], "$a_ip cmp $b_ip is $a->[2]"); } -for my $a (@cmp) { - my $a_ip = new NetAddr::IP $a->[0]; - my $b_ip = new NetAddr::IP $a->[1]; - - if (($a_ip cmp $b_ip) == $a->[2]) { - print "ok $count # $a_ip cmp $b_ip\n"; - } - else { - print "not ok $count # $a_ip cmp $b_ip\n"; - } - ++$count; -} diff --git a/t/v4-compact.t b/t/v4-compact.t index 207db76..991331b 100644 --- a/t/v4-compact.t +++ b/t/v4-compact.t @@ -1,6 +1,6 @@ -use NetAddr::IP; +use NetAddr::IP qw(Compact); -# $Id: v4-compact.t,v 1.2 2002/10/31 04:30:36 lem Exp $ +# $Id: v4-compact.t,v 1.3 2002/12/27 20:37:55 lem Exp $ my @r = ( [ '10.0.0.0', '255.255.255.0'], @@ -30,7 +30,7 @@ push @ips, NetAddr::IP->new($ip, 16)->split(28); } -my @c = NetAddr::IP::compact(@ips); +my @c = Compact(@ips); my @m; for my $c (@c) { diff --git a/t/v4-new.t b/t/v4-new.t index d802523..e392c31 100644 --- a/t/v4-new.t +++ b/t/v4-new.t @@ -1,9 +1,9 @@ use NetAddr::IP; -#require "IP.pm"; -# $Id: v4-new.t,v 1.2 2002/10/31 04:30:36 lem Exp $ +# $Id: v4-new.t,v 1.5 2002/12/27 20:37:55 lem Exp $ -my @a = ( +BEGIN { +our @a = ( [ 'localhost', '127.0.0.1' ], [ 0x01010101, '1.1.1.1' ], [ 1, '0.0.0.1' ], @@ -11,7 +11,7 @@ [ 'any', '0.0.0.0' ], ); -my @m = ( +our @m = ( [ 0, '0.0.0.0' ], [ 1, '128.0.0.0' ], [ 2, '192.0.0.0' ], @@ -28,33 +28,22 @@ [ '255.255.128.0', '255.255.128.0' ], [ 0b11111111111111110000000000000000, '255.255.0.0' ], ); +}; -$| = 1; +use Test::More tests => (4 * scalar @a * scalar @m) + 4; -print '1..', (2 * scalar @a * scalar @m), "\n"; - -my $count = 1; +ok(! defined NetAddr::IP->new('256.1.1.1'), "Invalid IP returns undef"); +ok(! defined NetAddr::IP->new('256.256.1.1'), "Invalid IP returns undef"); +ok(! defined NetAddr::IP->new('256.256.256.1'), "Invalid IP returns undef"); +ok(! defined NetAddr::IP->new('256.256.256.256'), "Invalid IP returns undef"); for my $a (@a) { for my $m (@m) { my $ip = new NetAddr::IP $a->[0], $m->[0]; - if ($ip->addr eq $a->[1]) { - print "ok ", $count++, "\n"; - } - else { - print "not ok ", $count++, "\n"; - } - - if ($ip->mask eq $m->[1]) { - print "ok ", $count++, "\n"; - } - else { - print "not ok ", $count++, "\n"; - } - -# print "mask=", $ip->mask, "\n"; - + is($ip->addr, $a->[1]); + is($ip->mask, $m->[1]); + is($ip->bits, 32); + is($ip->version, 4); } } - diff --git a/t/v6-base.t b/t/v6-base.t index 2a95bfe..e1ce883 100644 --- a/t/v6-base.t +++ b/t/v6-base.t @@ -1,11 +1,11 @@ # This -*- perl -*- code excercises the basic v6 functionality -# $Id: v6-base.t,v 1.2 2002/12/10 16:55:52 lem Exp $ +# $Id: v6-base.t,v 1.4 2002/12/17 05:09:50 lem Exp $ BEGIN { our @addr = qw(:: ::1 f34::123/40 ); }; use NetAddr::IP; -use Test::More tests => 2 * @addr + 4; +use Test::More tests => 4 * @addr + 4; my($a, $ip, $test); @@ -14,6 +14,8 @@ $a =~ s,/\d+,,; isa_ok($ip, 'NetAddr::IP'); is($ip->compact_addr, $a); + is($ip->bits, 128); + is($ip->version, 6); } $test = new NetAddr::IP f34::1;