CC: | Rob Riepel <riepel [...] networking.Stanford.EDU> |
Subject: | short() does not follow rfc5952 for ipv6 addresses starting with 0: |
Date: | Thu, 26 Jan 2017 11:26:13 -0500 |
To: | bug-NetAddr-IP [...] rt.cpan.org, bug-Net-IP [...] rt.cpan.org |
From: | Duane Bronson <nerdmachine [...] gmail.com> |
Beloved Authors/Maintainers of Net::IP and NetAddr::IP,
Here are some commands run on a linux machine:
$ perl -wE 'use NetAddr::IP; my $ip = new NetAddr::IP(qq(::1:0:0:0:1));say $ip->short()'
0:0:0:1::1
$ perl -wE 'use Net::IP; my $ip = new Net::IP(qq(::1:0:0:0:1));say $ip->short()'
0:0:0:1::1
$ ip route get to ::1:0:0:0:1
::1:0:0:0:1 via fe80::214:1bff:1:1 dev br0 proto kernel src 2600:1:1:1:20e:b6ff:fe9a:d031 metric 1024 expires 1776sec mtu 1500 advmss 1440 hoplimit 64
$ ip route get to 0:0:0:1::1
::1:0:0:0:1 via fe80::214:1bff:1:1 dev br0 proto kernel src 2600:1:1:1:20e:b6ff:fe9a:d031 metric 1024 expires 1776sec mtu 1500 advmss 1440 hoplimit 64
(note: some ip addresses changed)
Notice that linux's ip command normalizes this ip address differently than Net::IP::short and NetAddr::IP::short, so they can't be reliably used as a hash key interchangeably. It turns out there is a standard that they should be following - rfc5952.
From https://www.rfc-editor.org/rfc/rfc5952.txt <https://www.rfc-editor.org/rfc/rfc5952.txt> :
4.2. "::" Usage
4.2.1. Shorten as Much as Possible
The use of the symbol "::" MUST be used to its maximum capability.
For example, 2001:db8:0:0:0:0:2:1 must be shortened to 2001:db8::2:1.
Likewise, 2001:db8::0:1 is not acceptable, because the symbol "::"
could have been used to produce a shorter representation 2001:db8::1.
4.2.2. Handling One 16-Bit 0 Field
The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field.
For example, the representation 2001:db8:0:1:1:1:1:1 is correct, but
2001:db8::1:1:1:1:1 is not correct.
4.2.3. Choice in Placement of "::"
When there is an alternative choice in the placement of a "::", the
longest run of consecutive 16-bit 0 fields MUST be shortened (i.e.,
the sequence with three consecutive zero fields is shortened in 2001:
0:0:1:0:0:0:1). When the length of the consecutive 16-bit 0 fields
are equal (i.e., 2001:db8:0:0:1:0:0:1), the first sequence of zero
bits MUST be shortened. For example, 2001:db8::1:0:0:1 is correct
representation.
TIMTOWTDI, but a simple fix for both Net::IP and NetAddr::IP are simply to add 2 to the length calculation to prioritize the initial 0: over the embedded :0:
*** ./.cpan/build/NetAddr-IP-4.079-3G2VcG/blib/lib/NetAddr/IP.pm 2016-03-25 20:55:36.000000000 -0400
--- /tmp/NetAddr/IP.pm 2017-01-26 11:08:24.000000000 -0500
***************
*** 852,858 ****
sub _compV6 ($) {
my $ip = shift;
return $ip unless my @candidates = $ip =~ /((?:^|:)0(?::0)+(?::|$))/g;
! my $longest = (sort { length($b) <=> length($a) } @candidates)[0];
$ip =~ s/$longest/::/;
return $ip;
}
--- 852,858 ----
sub _compV6 ($) {
my $ip = shift;
return $ip unless my @candidates = $ip =~ /((?:^|:)0(?::0)+(?::|$))/g;
! my $longest = (sort { (substr($b,0,1) eq ":"?0:2) + length($b) <=> (substr($a,0,1) eq ":"?0:2) + length($a) } @candidates)[0];
$ip =~ s/$longest/::/;
return $ip;
}
and
*** /System/Library/Perl/Extras/5.18/Net/IP.pm 2012-11-28 10:23:38.000000000 -0500
--- /tmp/Net/IP.pm 2017-01-26 11:06:36.000000000 -0500
***************
*** 1561,1567 ****
/gx
)
{
! $reg = $1 if (length($reg) < length($1));
}
# Replace sequence by '::'
--- 1561,1567 ----
/gx
)
{
! $reg = $1 if ((substr($reg,0,1) eq ":"?0:2) + length($reg) < (substr($1,0,1) eq ":"?0:2) + length($1));
}
# Replace sequence by '::'
I did some simple testing and here are my results:
$ perl foo.pl 0:0:0:1:0:0:1:1
NetAddr::IP old: ::1:0:0:1:1
NetAddr::IP new ::1:0:0:1:1
Net::IP old ::1:0:0:1:1
Net::IP new ::1:0:0:1:1
$ perl foo.pl 0:0:0:1:0:0:0:1
NetAddr::IP old: 0:0:0:1::1
NetAddr::IP new ::1:0:0:0:1
Net::IP old 0:0:0:1::1
Net::IP new ::1:0:0:0:1
$ perl foo.pl 0:0:1:1:0:0:0:1
NetAddr::IP old: 0:0:1:1::1
NetAddr::IP new 0:0:1:1::1
Net::IP old 0:0:1:1::1
Net::IP new 0:0:1:1::1
$ perl foo.pl 1:0:0:1:1:0:0:1
NetAddr::IP old: 1::1:1:0:0:1
NetAddr::IP new 1::1:1:0:0:1
Net::IP old 1::1:1:0:0:1
Net::IP new 1::1:1:0:0:1
$ perl foo.pl 0:0:1:0:0:1:0:0
NetAddr::IP old: 0:0:1::1:0:0
NetAddr::IP new ::1:0:0:1:0:0
Net::IP old 0:0:1::1:0:0
Net::IP new ::1:0:0:1:0:0
Other trivial details:
perl 5.18.2 and 5.10.1 on OS X and Scientific Linux 6.2
NetAddr-IP-4.079
Net::IP-1.26
Thanks,
Duane
Duane Bronson
NerdMachine@gmail.com <mailto:NerdMachine@gmail.com>
http://www.nerdlogic.com/ <http://www.nerdlogic.com/>
5 Goden St.
Belmont, MA 02478
Message body is not shown because it is too large.