diff --git a/Changes b/Changes index 6a71437..b17c964 100644 --- a/Changes +++ b/Changes @@ -1,10 +1,26 @@ Revision history for Perl extension NetAddr::IP +4.042 Tue Mar 22 15:26:02 PDT 2011 + Update Lite.pm v1.27 to encompass treatment of /31 and /127 + point-to-point networks as described in RFC 3021 + + NOTE: for /31's and /127's + this changes the behavior of the following methods: + first returns the "network" address + last returns the "broadcast" address + nth index 0 returns "network" addr instead of undef + nth index 1 returns "broadcast" addr instead of undef + num returns 2 instead of 0 (zero) + + "old_nth" behavior is unchanged + + Thanks to Todd Caine todd.caine@gmail.com for pointing this out. + 4.041 Tue Mar 8 15:18:16 PST 2011 - Updated Lite.pm v1.26, "sub num" to support usable IP ranges + Updated Lite.pm v1.26, "sub num" to support usable IP ranges greater than 2**32 - Thanks to Jan Ploski jan@plosquare.com for finding this bug + Thanks to Jan Ploski jan@plosquare.com for finding this bug 4.040 Sat Feb 19 10:04:00 PST 2011 correction to use of Util.pm package lexicals diff --git a/IP.pm b/IP.pm index faa955b..fe4443c 100644 --- a/IP.pm +++ b/IP.pm @@ -4,7 +4,7 @@ use strict; #use diagnostics; -use NetAddr::IP::Lite 1.26 qw(Zero Zeros Ones V4mask V4net); +use NetAddr::IP::Lite 1.27 qw(Zero Zeros Ones V4mask V4net); use NetAddr::IP::Util 1.36 qw( sub128 inet_aton @@ -34,7 +34,7 @@ @ISA = qw(Exporter NetAddr::IP::Lite); -$VERSION = do { sprintf " %d.%03d", (q$Revision: 4.41 $ =~ /\d+/g) }; +$VERSION = do { sprintf " %d.%03d", (q$Revision: 4.42 $ =~ /\d+/g) }; =pod @@ -1234,16 +1234,49 @@ use NetAddr::IP::Lite qw(:old_nth); + old behavior: + NetAddr::IP->new('10/32')->nth(0) == undef + NetAddr::IP->new('10/32')->nth(1) == undef + NetAddr::IP->new('10/31')->nth(0) == undef + NetAddr::IP->new('10/31')->nth(1) == 10.0.0.1/31 + NetAddr::IP->new('10/30')->nth(0) == undef + NetAddr::IP->new('10/30')->nth(1) == 10.0.0.1/30 + NetAddr::IP->new('10/30')->nth(2) == 10.0.0.2/30 + NetAddr::IP->new('10/30')->nth(3) == 10.0.0.3/30 + +Note that in each case, the broadcast address is represented in the +output set and that the 'zero'th index is alway undef except for +a point-to-point /31 or /127 network where there are exactly two +addresses in the network. + + new behavior: + NetAddr::IP->new('10/32')->nth(0) == 10.0.0.0/32 + NetAddr::IP->new('10.1/32'->nth(0) == 10.0.0.1/32 + NetAddr::IP->new('10/31')->nth(0) == 10.0.0.0/32 + NetAddr::IP->new('10/31')->nth(1) == 10.0.0.1/32 + NetAddr::IP->new('10/30')->nth(0) == 10.0.0.1/30 + NetAddr::IP->new('10/30')->nth(1) == 10.0.0.2/30 + NetAddr::IP->new('10/30')->nth(2) == undef + +Note that a /32 net always has 1 usable address while a /31 has exactly +two usable addresses for point-to-point addressing. The first +index (0) returns the address immediately following the network address +except for a /31 or /127 when it return the network address. + =item C<-Enum()> +As of version 4.42 of NetAddr::IP and version 1.27 of NetAddr::IP::Lite +a /31 and /127 with return a net B value of 2 instead of 0 (zero) +for point-to-point networks. + Version 4.00 of NetAddr::IP and version 1.00 of NetAddr::IP::Lite return the number of usable IP addresses within the subnet, not counting the broadcast or network address. -Previous versions worked only for ipV4 addresses, returned a +Previous versions worked only for ipV4 addresses, returned a maximum span of 2**32 and returned the number of IP addresses not counting the broadcast address. - (one greater than the new behavior) + (one greater than the new behavior) To use the old behavior for C<-Enth($index)> and C<-Enum()>: @@ -1252,7 +1285,7 @@ WARNING: NetAddr::IP will calculate and return a numeric string for network -ranges as large as 2**128. These values are TEXT strings and perl +ranges as large as 2**128. These values are TEXT strings and perl can treat them as integers for numeric calculations. Perl on 32 bit platforms only handles integer numbers up to 2**32 @@ -1260,7 +1293,7 @@ If you wish to manipulate numeric strings returned by NetAddr::IP that are larger than 2**32 or 2**64, respectively, you must load -additional modules such as Math::BigInt, bignum or some similar +additional modules such as Math::BigInt, bignum or some similar package to do the integer math. =item C<-Ere()> diff --git a/Lite/Changes b/Lite/Changes index 3273878..e77bf05 100644 --- a/Lite/Changes +++ b/Lite/Changes @@ -1,5 +1,21 @@ Revision history for Perl extension NetAddr::IP::Lite +1.27 Tue Mar 22 15:26:02 PDT 2011 + Update Lite.pm to encompass treatment of /31 and /127 + point-to-point networks as described in RFC 3021 + + NOTE: for /31's and /127's + this changes the behavior of the following methods: + first returns the "network" address + last returns the "broadcast" address + nth index 0 returns "network" addr instead of undef + nth index 1 returns "broadcast" addr instead of undef + num returns 2 instead of 0 (zero) + + "old_nth" behavior is unchanged + + Thanks to Todd Caine todd.caine@gmail.com for pointing this out. + 1.26 Tue Mar 8 15:18:16 PST 2011 Updated "sub num" to support usable IP ranges greater than 2**32 diff --git a/Lite/Lite.pm b/Lite/Lite.pm index a0ae628..8b57be0 100644 --- a/Lite/Lite.pm +++ b/Lite/Lite.pm @@ -29,7 +29,7 @@ use vars qw(@ISA @EXPORT_OK $VERSION $Accept_Binary_IP $Old_nth $AUTOLOAD *Zero); -$VERSION = do { my @r = (q$Revision: 1.26 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; +$VERSION = do { my @r = (q$Revision: 1.27 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; require Exporter; @@ -1139,8 +1139,15 @@ =cut +my $_cidr127 = pack('N4',0xffffffff,0xffffffff,0xffffffff,0xfffffffe); + sub first ($) { - return $_[0]->network + 1; + if (hasbits($_[0]->{mask} ^ $_cidr127)) { + return $_[0]->network + 1; + } else { + return $_[0]->network; + } +# return $_[0]->network + 1; } =item C<-Elast()> @@ -1151,7 +1158,12 @@ =cut sub last ($) { - return $_[0]->broadcast - 1; + if (hasbits($_[0]->{mask} ^ $_cidr127)) { + return $_[0]->broadcast - 1; + } else { + return $_[0]->broadcast; + } +# return $_[0]->broadcast - 1; } =item C<-Enth($index)> @@ -1181,20 +1193,23 @@ NetAddr::IP->new('10/30')->nth(3) == 10.0.0.3/30 Note that in each case, the broadcast address is represented in the -output set and that the 'zero'th index is alway undef. +output set and that the 'zero'th index is alway undef except for +a point-to-point /31 or /127 network where there are exactly two +addresses in the network. new behavior: NetAddr::IP->new('10/32')->nth(0) == 10.0.0.0/32 NetAddr::IP->new('10.1/32'->nth(0) == 10.0.0.1/32 - NetAddr::IP->new('10/31')->nth(0) == undef - NetAddr::IP->new('10/31')->nth(1) == undef + NetAddr::IP->new('10/31')->nth(0) == 10.0.0.0/32 + NetAddr::IP->new('10/31')->nth(1) == 10.0.0.1/32 NetAddr::IP->new('10/30')->nth(0) == 10.0.0.1/30 NetAddr::IP->new('10/30')->nth(1) == 10.0.0.2/30 NetAddr::IP->new('10/30')->nth(2) == undef -Note that a /32 net always has 1 usable address while a /31 has none since -it has a network and broadcast address, but no host addresses. The first -index (0) returns the address immediately following the network address. +Note that a /32 net always has 1 usable address while a /31 has exactly +two usable addresses for point-to-point addressing. The first +index (0) returns the address immediately following the network address +except for a /31 or /127 when it return the network address. =cut @@ -1202,13 +1217,26 @@ my $self = shift; my $count = shift; - ++$count unless ($Old_nth); - return undef if ($count < 1 or $count > $self->num ()); + my $slash31 = ! hasbits($self->{mask} ^ $_cidr127); + if ($Old_nth) { + return undef if $slash31 && $count != 1; + return undef if ($count < 1 or $count > $self->num ()); + } + elsif ($slash31) { + return undef if ($count && $count != 1); # only index 0, 1 allowed for /31 + } else { + ++$count; + return undef if ($count < 1 or $count > $self->num ()); + } return $self->network + $count; } =item C<-Enum()> +As of version 4.42 of NetAddr::IP and version 1.27 of NetAddr::IP::Lite +a /31 and /127 with return a net B value of 2 instead of 0 (zero) +for point-to-point networks. + Version 4.00 of NetAddr::IP and version 1.00 of NetAddr::IP::Lite return the number of usable IP addresses within the subnet, not counting the broadcast or network address. @@ -1244,11 +1272,11 @@ # number of ip's less broadcast return 0xfffffffe if $net[0] || $net[1] || $net[2]; # 2**32 -1 return $net[3] if $net[3]; - } else { # returns 1 for /32 /128, 0 for /31 /127 else n-2 up to 2**32 + } else { # returns 1 for /32 /128, 2 for /31 /127 else n-2 up to 2**32 (undef, my $net) = addconst($_[0]->{mask},1); return 1 unless hasbits($net); # ipV4/32 or ipV6/128 $net = $net ^ Ones; - return 0 unless hasbits($net); # ipV4/31 or ipV6/127 + return 2 unless hasbits($net); # ipV4/31 or ipV6/127 return bin2bcd($net); } } diff --git a/Lite/README b/Lite/README index 4abc560..2b7df59 100644 --- a/Lite/README +++ b/Lite/README @@ -391,23 +391,30 @@ NetAddr::IP->new('10/30')->nth(3) == 10.0.0.3/30 Note that in each case, the broadcast address is represented in the - output set and that the 'zero'th index is alway undef. + output set and that the 'zero'th index is alway undef except for a + point-to-point /31 or /127 network where there are exactly two + addresses in the network. new behavior: NetAddr::IP->new('10/32')->nth(0) == 10.0.0.0/32 NetAddr::IP->new('10.1/32'->nth(0) == 10.0.0.1/32 - NetAddr::IP->new('10/31')->nth(0) == undef - NetAddr::IP->new('10/31')->nth(1) == undef + NetAddr::IP->new('10/31')->nth(0) == 10.0.0.0/32 + NetAddr::IP->new('10/31')->nth(1) == 10.0.0.1/32 NetAddr::IP->new('10/30')->nth(0) == 10.0.0.1/30 NetAddr::IP->new('10/30')->nth(1) == 10.0.0.2/30 NetAddr::IP->new('10/30')->nth(2) == undef - Note that a /32 net always has 1 usable address while a /31 has none - since it has a network and broadcast address, but no host addresses. - The first index (0) returns the address immediately following the - network address. + Note that a /32 net always has 1 usable address while a /31 has + exactly two usable addresses for point-to-point addressing. The + first index (0) returns the address immediately following the + network address except for a /31 or /127 when it return the network + address. "->num()" + As of version 4.42 of NetAddr::IP and version 1.27 of + NetAddr::IP::Lite a /31 and /127 with return a net num value of 2 + instead of 0 (zero) for point-to-point networks. + Version 4.00 of NetAddr::IP and version 1.00 of NetAddr::IP::Lite return the number of usable IP addresses within the subnet, not counting the broadcast or network address. diff --git a/Lite/t/firstlast.t b/Lite/t/firstlast.t index 5c4418a..edb9f3c 100644 --- a/Lite/t/firstlast.t +++ b/Lite/t/firstlast.t @@ -4,7 +4,7 @@ $| = 1; -print "1..4\n"; +print "1..8\n"; my $test = 1; sub ok() { @@ -37,3 +37,30 @@ print "got: $rv, exp: $exp\nnot " unless $rv eq $exp; &ok; + +$ip4 = NetAddr::IP::Lite->new('1.2.3.11/31'); +$ip6 = NetAddr::IP::Lite->new('FF::8B/127'); + +$exp = '1.2.3.10'; +$rv = $ip4->first->addr; +print "got: $rv, exp: $exp\nnot " + unless $rv eq $exp; +&ok; + +$exp = '1.2.3.11'; +$rv = $ip4->last->addr; +print "got: $rv, exp: $exp\nnot " + unless $rv eq $exp; +&ok; + +$exp = 'FF:0:0:0:0:0:0:8A'; +$rv = $ip6->first->addr; +print "got: $rv, exp: $exp\nnot " + unless $rv eq $exp; +&ok; + +$exp = 'FF:0:0:0:0:0:0:8B'; +$rv = $ip6->last->addr; +print "got: $rv, exp: $exp\nnot " + unless $rv eq $exp; +&ok; diff --git a/Lite/t/new-nth.t b/Lite/t/new-nth.t index 1595dca..adcd77a 100644 --- a/Lite/t/new-nth.t +++ b/Lite/t/new-nth.t @@ -39,6 +39,6 @@ &ok; print "got: $_, exp: 0\nnot " - unless defined ($_ = NetAddr::IP::Lite->new('1.2.3.4/31')->num()) && $_ == 0; + unless defined ($_ = NetAddr::IP::Lite->new('1.2.3.4/31')->num()) && $_ == 2; &ok; diff --git a/Lite/t/new-num.t b/Lite/t/new-num.t index b8563f6..76b6510 100644 --- a/Lite/t/new-num.t +++ b/Lite/t/new-num.t @@ -10,10 +10,10 @@ my @try = qw( 10/32 1 - 10/31 0 + 10/31 2 10/30 2 ::1/128 1 - ::1/127 0 + ::1/127 2 ::1/126 2 1.2.3.11/29 6 FF::8B/125 6 diff --git a/Lite/t/v4-num.t b/Lite/t/v4-num.t index 667e3c1..8d74bb6 100644 --- a/Lite/t/v4-num.t +++ b/Lite/t/v4-num.t @@ -21,9 +21,10 @@ for my $a (keys %$nets) { my $nc = $nets->{$a}->[1] - $new; # net count $nc = 1 if $nc < 0; + $nc = 2 if $new && $nets->{$a}->[0] == 31; # special case for /31, /127 my $ip = new NetAddr::IP::Lite $a, $nets->{$a}->[0]; print "got: $_, exp: $nc\nnot " - unless $ip->num == $nc; + unless ($_ = $ip->num) == $nc; print "ok ", $test++, "\n"; } } diff --git a/Lite/t/v6-num.t b/Lite/t/v6-num.t index 93148aa..66297eb 100644 --- a/Lite/t/v6-num.t +++ b/Lite/t/v6-num.t @@ -2,7 +2,7 @@ my $nets = { 'F0::' => [ 128, '1' ], - 'F1::' => [ 127, '0' ], + 'F1::' => [ 127, '2' ], 'F2::' => [ 126, '2' ], 'F3::' => [ 125, '6' ], 'F4::' => [ 124, '14' ], @@ -25,7 +25,7 @@ 'F60::' => [ 2, '85070591730234615865843651857942052862' ], 'F70::' => [ 1, '170141183460469231731687303715884105726' ], 'F80::' => [ 0, '340282366920938463463374607431768211454' ], - '0.0.0.1' => [ 31, '0' ], + '0.0.0.1' => [ 31, '2' ], '0.0.0.2' => [ 30, '2' ], '0.0.0.3' => [ 2, '1073741822' ], '0.0.0.4' => [ 1, '2147483646' ], @@ -33,8 +33,6 @@ '0.0.0.6' => [ 32, '1' ], }; -my $new = 1; # flag for old vs new numeric returns - $| = 1; $test = keys %$nets; diff --git a/META.yml b/META.yml index aa75795..095cca9 100644 --- a/META.yml +++ b/META.yml @@ -1,6 +1,6 @@ --- #YAML:1.0 name: NetAddr-IP -version: 4.041 +version: 4.042 abstract: Manages IPv4 and IPv6 addresses and subnets license: ~ author: