Skip Menu |

This queue is for tickets about the Socket CPAN distribution.

Report information
The Basics
Id: 78890
Status: resolved
Priority: 0/
Queue: Socket

People
Owner: Nobody in particular
Requestors: VINSWORLD [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 2.002
Fixed in: 2.005



Subject: Windows support for IPv6 - there, but broken in this release
Windows 7 x64 / Strawberry Perl 5.14.2, 5.16.1 both using latest Socket 2.002 from CPAN: Socket::inet_ntop not implemented on this architecture at C:\Users\ ... inet_ntop is certainly available on Windows 7. Seems the gcc include files and lib files may be lacking? Using the following process, I can write a C program using get*info calls and inet_ntop / pton and they work correctly. Quick fix for Perl Socket module, but doesn't resolve completely: add to ws2tcpip.h line 304: #include <ws2tcpip-win.h> -- Attached file is the ws2tcpip-win.h file. Additionally, create new libws2-32.a library: Show quoted text
> pexports \Windows\system32\ws2_32.dll > WS2_32.def > dlltool --as-flags=--64 -m i386:x86-64 -k --output-lib libws2_32-new.a
--input-def WS2_32.def Put both files in locations: \strawberry\c\x86_64-w64-mingw32\include\ws2tcpip-win.h \strawberry\c\x86_64-w64-mingw32\lib\libws2_32-new.a Edit generated Makefile: DEFINE = -DHAS_IP_MREQ -DHAS_GETADDRINFO -DHAS_GETNAMEINFO - DHAS_INETNTOP -DHAS_INETPTON -DAF_INET6 -DHAS_SOCKADDR_IN6 LDLOADLIBS = -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool - lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid - lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32 -lws2_32- new dmake test But ... still errors: Socket-2.002> perl -Mblib ..\..\tmp\v4v6Lookup.pl OLD: gethostbyname()/inet_ntoa() Address = 10.200.200.254 OLD: gethostbyname()/inet_ntoa() Address = 10.100.100.254 OLD: gethostbyname()/inet_ntoa() Address = 192.168.100.254 OLD: gethostbyname()/inet_ntoa() Address = 192.168.10.101 OLD: gethostbyname()/inet_ntoa() Address = 192.168.12.1 OLD: gethostbyname()/inet_ntoa() Address = 192.168.58.1 NEW: getaddrinfo()/inet_ntop() Address = 3000:6e00:7273:6500:: NEW: getaddrinfo()/inet_ntop() Address = 3000:6e00:7273:6500:: NEW: getaddrinfo()/inet_ntop() Address = 3000:6e00:7273:6500:: NEW: getaddrinfo()/inet_ntop() Address = 3000:6e00:7273:6500:: NEW: getaddrinfo()/inet_ntop() Address = 3000:6e00:7273:6500:: NEW: getaddrinfo()/inet_ntop() Address = 3000:6e00:7273:6500:: NEW: getaddrinfo()/inet_ntop() Address = 192.168.12.1 NEW: getaddrinfo()/inet_ntop() Address = 192.168.58.1 NEW: getaddrinfo()/inet_ntop() Address = 192.168.10.101 NEW: getaddrinfo()/inet_ntop() Address = 10.200.200.254 NEW: getaddrinfo()/inet_ntop() Address = 10.100.100.254 NEW: getaddrinfo()/inet_ntop() Address = 192.168.100.254 Notice the IPv6 addresses are wrong. They correctly resolve with Perl 5.12.3 using Socket::GetAddrInfo and the above process: Show quoted text
> perl v4v6Lookup.pl
OLD: gethostbyname()/inet_ntoa() Address = 10.200.200.254 OLD: gethostbyname()/inet_ntoa() Address = 10.100.100.254 OLD: gethostbyname()/inet_ntoa() Address = 192.168.100.254 OLD: gethostbyname()/inet_ntoa() Address = 192.168.10.101 OLD: gethostbyname()/inet_ntoa() Address = 192.168.12.1 OLD: gethostbyname()/inet_ntoa() Address = 192.168.58.1 NEW: getaddrinfo()/inet_ntop() Address = fe80::eda4:ae73:XXXX:YYYY NEW: getaddrinfo()/inet_ntop() Address = fe80::8923:a275:XXXX:YYYY NEW: getaddrinfo()/inet_ntop() Address = fe80::3db7:ac68:XXXX:YYYY NEW: getaddrinfo()/inet_ntop() Address = 2001:470:1f07:157c:3db7:ac68:XXXX:YYYY NEW: getaddrinfo()/inet_ntop() Address = fe80::c4d5:7cb1:XXXX:YYYY NEW: getaddrinfo()/inet_ntop() Address = fe80::f800:da27:XXXX:YYYY NEW: getaddrinfo()/inet_ntop() Address = 192.168.12.1 NEW: getaddrinfo()/inet_ntop() Address = 192.168.58.1 NEW: getaddrinfo()/inet_ntop() Address = 192.168.10.101 NEW: getaddrinfo()/inet_ntop() Address = 10.200.200.254 NEW: getaddrinfo()/inet_ntop() Address = 10.100.100.254 NEW: getaddrinfo()/inet_ntop() Address = 192.168.100.254 NOTE: XXXX:YYYY added to obscure addresses.
Subject: v4v6Lookup.pl
#!/usr/bin/perl use strict; use warnings; use Getopt::Long qw(:config no_ignore_case); use Pod::Usage; use if $] < 5.014, "Socket" => qw(inet_ntoa unpack_sockaddr_in IPPROTO_TCP AF_INET AF_UNSPEC); use if $] < 5.014, "Socket6"; use if $] < 5.014, "Socket::GetAddrInfo" => qw(getaddrinfo getnameinfo); use if $] >= 5.014, "Socket" => qw(:addrinfo inet_ntoa inet_ntop unpack_sockaddr_in unpack_sockaddr_in6 IPPROTO_TCP AF_INET AF_UNSPEC); use Sys::Hostname; my %opt; my ($opt_help, $opt_man); GetOptions( 'new!' => \$opt{new}, 'old!' => \$opt{old}, 'reverse!' => \$opt{rev}, 'help!' => \$opt_help, 'man!' => \$opt_man ) or pod2usage(-verbose => 0); pod2usage(-verbose => 1) if defined $opt_help; pod2usage(-verbose => 2) if defined $opt_man; if (!@ARGV) { $ARGV[0] = hostname; } if ((!defined($opt{new})) && (!defined($opt{old}))) { $opt{new} = $opt{old} = 1 } if ($opt{old}) { if (my @gethost = gethostbyname($ARGV[0])) { for (4..$#gethost) { my $addr = inet_ntoa($gethost[$_]); print "OLD: gethostbyname()/inet_ntoa() Address = $addr\n"; if ($opt{rev}) { my $host = gethostbyaddr($gethost[$_], AF_INET); printf " |_> gethostbyaddr() Name = %s\n", (defined($host)) ? $host : '' } } } else { print "$0: gethostbyname() failed\n" } } if ($opt{new}) { my %hints = ( family => AF_UNSPEC, protocol => IPPROTO_TCP ); my ($err, @getaddr) = getaddrinfo($ARGV[0], undef, \%hints); if (defined($getaddr[0])) { for my $addr (@getaddr) { my $address; if ($addr->{family} == AF_INET) { $address = unpack_sockaddr_in($addr->{addr}) } else { $address = unpack_sockaddr_in6($addr->{addr}) } my $host = inet_ntop($addr->{family}, $address); print "NEW: getaddrinfo()/inet_ntop() Address = $host\n"; if ($opt{rev}) { my ($err, $host, $service) = getnameinfo($addr->{addr}, NI_NAMEREQD); printf " |_> getnameinfo() Name = %s\n", (defined($host)) ? $host : $err } } } else { print "$0: getaddrinfo() failed - error = $err\n" } } __END__ =head1 SYNOPSIS v4v6Lookup [options] [IP[v6]_address | hostname] =head1 OPTIONS hostname Name or IP[v6] to lookup. -n, --new Use the new getaddrinfo()/inet_ntop() functions. DEFAULT: (or not specified) Both. -o, --old Use the old gethostbyname()/inet_ntoa() functions. DEFAULT: (or not specified) Both. -r, --reverse Do number to name lookup on resolved output. DEFAULT: (or not specified) no reverse. --help Print Options and Arguments. --man Print complete man page.
Subject: ws2tcpip-win.h
#ifndef WS2TCPIP_WIN_H #define WS2TCPIP_WIN_H typedef USHORT ADDRESS_FAMILY; #if (NTDDI_VERSION >= NTDDI_VISTA) WINSOCK_API_LINKAGE INT WSAAPI inet_pton(INT, PCSTR, PVOID); WINSOCK_API_LINKAGE INT WSAAPI InetPtonW(INT, PCWSTR, PVOID); WINSOCK_API_LINKAGE PCSTR WSAAPI inet_ntop(INT, PVOID, PSTR, size_t); WINSOCK_API_LINKAGE PCWSTR WSAAPI InetNtopW(INT, PVOID, PWSTR, size_t); #define InetPtonA inet_pton #define InetNtopA inet_ntop #ifdef UNICODE #define InetPton InetPtonW #define InetNtop InetNtopW #else #define InetPton InetPtonA #define InetNtop InetNtopA #endif #if INCL_WINSOCK_API_TYPEDEFS typedef INT (WSAAPI * LPFN_INET_PTONA)(INT Family, PCSTR pszAddrString, PVOID pAddrBuf); typedef INT (WSAAPI * LPFN_INET_PTONW)(INT Family, PCWSTR pszAddrString, PVOID pAddrBuf); typedef PCSTR (WSAAPI * LPFN_INET_NTOPA)(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize); typedef PCWSTR (WSAAPI * LPFN_INET_NTOPW)(INT Family, PVOID pAddr, PWSTR pStringBuf, size_t StringBufSize); #ifdef UNICODE #define LPFN_INET_PTON LPFN_INET_PTONW #define LPFN_INET_NTOP LPFN_INET_NTOPW #else #define LPFN_INET_PTON LPFN_INET_PTONA #define LPFN_INET_NTOP LPFN_INET_NTOPA #endif #endif // TYPEDEFS #endif // (NTDDI_VERSION >= NTDDI_VISTA) #endif
On Fri Aug 10 11:32:28 2012, VINSWORLD wrote: Show quoted text
> Windows 7 x64 / Strawberry Perl 5.14.2, 5.16.1 both using latest Socket > 2.002 from CPAN: > > Socket::inet_ntop not implemented on this architecture at C:\Users\ ... > > inet_ntop is certainly available on Windows 7. Seems the gcc include > files and lib files may be lacking? Using the following process, I can > write a C program using get*info calls and inet_ntop / pton and they > work correctly. > > Quick fix for Perl Socket module, but doesn't resolve completely: > > add to ws2tcpip.h line 304: > > #include <ws2tcpip-win.h> > > -- > Attached file is the ws2tcpip-win.h file. Additionally, create new > libws2-32.a library: >
> > pexports \Windows\system32\ws2_32.dll > WS2_32.def > > dlltool --as-flags=--64 -m i386:x86-64 -k --output-lib libws2_32-new.a
> --input-def WS2_32.def > > Put both files in locations: > > \strawberry\c\x86_64-w64-mingw32\include\ws2tcpip-win.h > \strawberry\c\x86_64-w64-mingw32\lib\libws2_32-new.a > > Edit generated Makefile: > > DEFINE = -DHAS_IP_MREQ -DHAS_GETADDRINFO -DHAS_GETNAMEINFO - > DHAS_INETNTOP -DHAS_INETPTON -DAF_INET6 -DHAS_SOCKADDR_IN6 > > LDLOADLIBS = -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool - > lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid - > lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32 -lws2_32- > new > > dmake test
This sounds like quite a long complex workaround here. Hopefully we can find a neater solution; this level of hackery ought not be necessary. Show quoted text
> But ... still errors:
Yes, that's due to a bug in your v4v6Lookup.pl. It failed the same way for me on Linux: $ perl -Mblib v4v6Lookup.pl cel.leonerd.org.uk OLD: gethostbyname()/inet_ntoa() Address = 81.187.167.226 NEW: getaddrinfo()/inet_ntop() Address = 81.187.167.226 NEW: getaddrinfo()/inet_ntop() Address = 3000:a7e2:7f:0:e8e0:4a91 $ perl -Mblib v4v6Lookup.pl cel.leonerd.org.uk OLD: gethostbyname()/inet_ntoa() Address = 81.187.167.226 NEW: getaddrinfo()/inet_ntop() Address = 48.0.110.1 NEW: getaddrinfo()/inet_ntop() Address = 3000:6e01::b80e:c84d:ee7 That itself looks like a bug in Socket, perhaps using some uninitialised memory. I'll hunt it down later. unpack_sockaddr_in and _in6 return a list, whose first element is the port number and the second is the raw IPv4 or v6 address. Lines 61-65 ought to read: 61 if ($addr->{family} == AF_INET) { 62 (undef, $address) = unpack_sockaddr_in($addr->{addr}) 63 } else { 64 (undef, $address) = unpack_sockaddr_in6($addr->{addr}) 65 } With this change in place, it now behaves as expected: $ perl -Mblib v4v6Lookup.pl cel.leonerd.org.uk OLD: gethostbyname()/inet_ntoa() Address = 81.187.167.226 NEW: getaddrinfo()/inet_ntop() Address = 81.187.167.226 NEW: getaddrinfo()/inet_ntop() Address = 2001:8b0:3f7::2 Try that change, and see if yours now works. -- Paul Evans
Subject: Re: [rt.cpan.org #78890] Windows support for IPv6 - there, but broken in this release
Date: Thu, 16 Aug 2012 15:47:41 -0400
To: bug-Socket [...] rt.cpan.org
From: Vince <vin [...] vinsworld.com>
Wow. I *hate* it when I'm the culprit of a fix easily obtained with a RTFM solution. My apologies for the mistake in my script that incorrectly attributed an error to Socket.pm. Thanks for taking the time to respond and set me straight and not just let this fade away. Very much appreciate the work you're doing to get IPv6 working in Perl. When I *correctly* implemented the unpack_sockaddr_in(6) routines as per your recommendation, the script using Socket 2.004 indeed worked. Weird that the mistakes in my code did produce the correct results on Perl 5.12.3 using the Socket6 module. Anyway, not for further concern on this topic / forum. HOWEVER: A simple: perl Makefile.PL dmake dmake test perl -Mblib v4v6lookup.pl still failed with the Socket::inet_ntop error. My elaborate jiggery-pokery GCC messing about was needed for Socket to compile and then produce the correct result (after fixing my script) on Windows. I've included the build process below, although like I said, this ultimately seems to be a GCC library / include file issue not related to the Socket module. Go ahead and close this ticket. ----<Socket 2.004 build process output>---- VinsWorldcom@C:\Users\VinsWorldcom\Downloads\Socket-2.004> perl Makefile.PL Checking HAS_SOCKADDR_SA_LEN... test-0.c: In function 'main': test-0.c:15: error: 'struct sockaddr' has no member named 'sa_len' Checking HAS_SOCKADDR_IN6... Checking HAS_SIN6_SCOPE_ID... Checking HAS_IP_MREQ... Checking HAS_IPV6_MREQ... Checking if your kit is complete... Looks good Writing Makefile for Socket VinsWorldcom@C:\Users\VinsWorldcom\Downloads\Socket-2.004> dmake cp Socket.pm blib\lib\Socket.pm C:\strawberry\perl\bin\perl.exe C:\strawberry\perl\lib\ExtUtils\xsubpp -noprototypes -typemap C:\strawberry\perl\lib\ExtUtils\typemap -typemap typemap Socket.xs > Socket.xsc && C:\strawberry\perl\bin\perl.exe -MExtUtils::Command -e "mv" -- Socket.xsc Socket.c gcc -c -s -O2 -DWIN32 -DHAVE_DES_FCRYPT -DWIN64 -DCONSERVATIVE -DUSE_SITECUSTOMIZE -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -fno-strict-aliasing -mms-bitfields -DPERL_MSVCRT_READFIX -s -O2 -DVERSION=\"2.004\" -DXS_VER SION=\"2.004\" "-IC:\strawberry\perl\lib\CORE" -DHAS_SOCKADDR_IN6 -DHAS_SIN6_SCOPE_ID -DHAS_IP_MREQ -DHAS_IPV6_MREQ Socket.c Socket.xs: In function 'XS_Socket_pack_sockaddr_un': Socket.xs:699: warning: cast to pointer from integer of different size Socket.xs: In function 'XS_Socket_unpack_sockaddr_un': Socket.xs:745: warning: cast to pointer from integer of different size Socket.xs: In function 'XS_Socket_inet_ntop': Socket.xs:920: warning: cast to pointer from integer of different size Socket.xs: In function 'XS_Socket_inet_pton': Socket.xs:962: warning: cast to pointer from integer of different size Running Mkbootstrap for Socket () C:\strawberry\perl\bin\perl.exe -MExtUtils::Command -e "chmod" -- 644 Socket.bs C:\strawberry\perl\bin\perl.exe -MExtUtils::Mksymlists \ -e "Mksymlists('NAME'=>\"Socket\", 'DLBASE' => 'Socket', 'DL_FUNCS' => { }, 'FUNCLIST' => [], 'IMPORTS' => { }, 'DL_VARS' => []);" dlltool --def Socket.def --output-exp dll.exp g++ -o blib\arch\auto\Socket\Socket.dll -Wl,--base-file -Wl,dll.base -mdll -s -L"C:\strawberry\perl\lib\CORE" -L"C:\strawberry\c\lib" Socket.o -Wl,--image-base,0x361b0000 C:\strawberry\perl\lib\CORE\libperl512.a -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32 dll.exp dlltool --def Socket.def --base-file dll.base --output-exp dll.exp g++ -o blib\arch\auto\Socket\Socket.dll -mdll -s -L"C:\strawberry\perl\lib\CORE" -L"C:\strawberry\c\lib" Socket.o -Wl,--image-base,0x361b0000 C:\strawberry\perl\lib\CORE\libperl512.a -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32 dll.exp C:\strawberry\perl\bin\perl.exe -MExtUtils::Command -e "chmod" -- 755 blib\arch\auto\Socket\Socket.dll C:\strawberry\perl\bin\perl.exe -MExtUtils::Command -e "cp" -- Socket.bs blib\arch\auto\Socket\Socket.bs C:\strawberry\perl\bin\perl.exe -MExtUtils::Command -e "chmod" -- 644 blib\arch\auto\Socket\Socket.bs VinsWorldcom@C:\Users\vincen_m\Downloads\Socket-2.004> perl -Mblib ..\..\tmp\v4v6Lookup.pl www.google.com OLD: gethostbyname()/inet_ntoa() Address = 173.194.73.106 OLD: gethostbyname()/inet_ntoa() Address = 173.194.73.104 OLD: gethostbyname()/inet_ntoa() Address = 173.194.73.99 OLD: gethostbyname()/inet_ntoa() Address = 173.194.73.147 OLD: gethostbyname()/inet_ntoa() Address = 173.194.73.103 OLD: gethostbyname()/inet_ntoa() Address = 173.194.73.105 Socket::inet_ntop not implemented on this architecture at ..\..\tmp\v4v6Lookup.pl line 68. On Thu, Aug 16, 2012 at 3:03 PM, Paul Evans via RT <bug-Socket@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=78890 > > > On Fri Aug 10 11:32:28 2012, VINSWORLD wrote:
>> Windows 7 x64 / Strawberry Perl 5.14.2, 5.16.1 both using latest Socket >> 2.002 from CPAN: >> >> Socket::inet_ntop not implemented on this architecture at C:\Users\ ... >> >> inet_ntop is certainly available on Windows 7. Seems the gcc include >> files and lib files may be lacking? Using the following process, I can >> write a C program using get*info calls and inet_ntop / pton and they >> work correctly. >> >> Quick fix for Perl Socket module, but doesn't resolve completely: >> >> add to ws2tcpip.h line 304: >> >> #include <ws2tcpip-win.h> >> >> -- >> Attached file is the ws2tcpip-win.h file. Additionally, create new >> libws2-32.a library: >>
>> > pexports \Windows\system32\ws2_32.dll > WS2_32.def >> > dlltool --as-flags=--64 -m i386:x86-64 -k --output-lib libws2_32-new.a
>> --input-def WS2_32.def >> >> Put both files in locations: >> >> \strawberry\c\x86_64-w64-mingw32\include\ws2tcpip-win.h >> \strawberry\c\x86_64-w64-mingw32\lib\libws2_32-new.a >> >> Edit generated Makefile: >> >> DEFINE = -DHAS_IP_MREQ -DHAS_GETADDRINFO -DHAS_GETNAMEINFO - >> DHAS_INETNTOP -DHAS_INETPTON -DAF_INET6 -DHAS_SOCKADDR_IN6 >> >> LDLOADLIBS = -lmoldname -lkernel32 -luser32 -lgdi32 -lwinspool - >> lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -lnetapi32 -luuid - >> lws2_32 -lmpr -lwinmm -lversion -lodbc32 -lodbccp32 -lcomctl32 -lws2_32- >> new >> >> dmake test
> > This sounds like quite a long complex workaround here. Hopefully we can > find a neater solution; this level of hackery ought not be necessary. >
>> But ... still errors:
> > Yes, that's due to a bug in your v4v6Lookup.pl. It failed the same way > for me on Linux: > > $ perl -Mblib v4v6Lookup.pl cel.leonerd.org.uk > OLD: gethostbyname()/inet_ntoa() Address = 81.187.167.226 > NEW: getaddrinfo()/inet_ntop() Address = 81.187.167.226 > NEW: getaddrinfo()/inet_ntop() Address = 3000:a7e2:7f:0:e8e0:4a91 > > $ perl -Mblib v4v6Lookup.pl cel.leonerd.org.uk > OLD: gethostbyname()/inet_ntoa() Address = 81.187.167.226 > NEW: getaddrinfo()/inet_ntop() Address = 48.0.110.1 > NEW: getaddrinfo()/inet_ntop() Address = 3000:6e01::b80e:c84d:ee7 > > That itself looks like a bug in Socket, perhaps using some uninitialised > memory. I'll hunt it down later. > > > unpack_sockaddr_in and _in6 return a list, whose first element is the > port number and the second is the raw IPv4 or v6 address. Lines 61-65 > ought to read: > > 61 if ($addr->{family} == AF_INET) { > 62 (undef, $address) = unpack_sockaddr_in($addr->{addr}) > 63 } else { > 64 (undef, $address) = unpack_sockaddr_in6($addr->{addr}) > 65 } > > With this change in place, it now behaves as expected: > > $ perl -Mblib v4v6Lookup.pl cel.leonerd.org.uk > OLD: gethostbyname()/inet_ntoa() Address = 81.187.167.226 > NEW: getaddrinfo()/inet_ntop() Address = 81.187.167.226 > NEW: getaddrinfo()/inet_ntop() Address = 2001:8b0:3f7::2 > > Try that change, and see if yours now works. > > -- > > Paul Evans
On Thu Aug 16 15:47:57 2012, vinsworldcom@gmail.com wrote: Show quoted text
> Wow. I *hate* it when I'm the culprit of a fix easily obtained with a > RTFM solution. My apologies for the mistake in my script that > incorrectly attributed an error to Socket.pm. Thanks for taking the > time to respond and set me straight and not just let this fade away. > Very much appreciate the work you're doing to get IPv6 working in > Perl. > > When I *correctly* implemented the unpack_sockaddr_in(6) routines as > per your recommendation, the script using Socket 2.004 indeed worked. > > Weird that the mistakes in my code did produce the correct results on > Perl 5.12.3 using the Socket6 module. Anyway, not for further concern > on this topic / forum.
I was looking into that, and I think it's a side-effect of calling an XS function in scalar context that's expecting to be called in list context; it has the effect of yielding the last value in the list. Socket6's unpack_sockaddr_in6 only returned ($port, $address), so in scalar context it still returned the address. Socket's additionally returns the flow info and scope ID fields, so I suspect what happened was that your $address actually had the scope ID, which was a plain 0. When inet_ntop() wanted to get the raw PV bytes out of that, it converted the 0 into the string "0", whose first two bytes are 0x30, 0x00. Hence all your results starting with 3000:... I suspect what I'll actually do, to avoid this breakage in future, is to have unpack_sockaddr_in6() yield just the address when called in scalar context, to match Socket6, and the IPv4 unpack_sockaddr_in(). This feels the most useful behaviour anyway, as if you wanted just one value that's the most likely one. -- Paul Evans
Subject: Re: [rt.cpan.org #78890] Windows support for IPv6 - there, but broken in this release
Date: Thu, 16 Aug 2012 16:33:13 -0400
To: bug-Socket [...] rt.cpan.org
From: Vince <vin [...] vinsworld.com>
Show quoted text
> On Thu Aug 16 15:47:57 2012, vinsworldcom@gmail.com wrote:
>> Wow. I *hate* it when I'm the culprit of a fix easily obtained with a >> RTFM solution. My apologies for the mistake in my script that >> incorrectly attributed an error to Socket.pm. Thanks for taking the >> time to respond and set me straight and not just let this fade away. >> Very much appreciate the work you're doing to get IPv6 working in >> Perl. >> >> When I *correctly* implemented the unpack_sockaddr_in(6) routines as >> per your recommendation, the script using Socket 2.004 indeed worked. >> >> Weird that the mistakes in my code did produce the correct results on >> Perl 5.12.3 using the Socket6 module. Anyway, not for further concern >> on this topic / forum.
> > I was looking into that, and I think it's a side-effect of calling an XS > function in scalar context that's expecting to be called in list > context; it has the effect of yielding the last value in the list. > > Socket6's unpack_sockaddr_in6 only returned ($port, $address), so in > scalar context it still returned the address. Socket's additionally > returns the flow info and scope ID fields, so I suspect what happened > was that your $address actually had the scope ID, which was a plain 0. > When inet_ntop() wanted to get the raw PV bytes out of that, it > converted the 0 into the string "0", whose first two bytes are 0x30, > 0x00. Hence all your results starting with 3000:...
Yes, because when I printed $address before sending to inet_ntop(), I got 0, which lead me to believe there was an error not so much in inet_ntop(), but again, I was wrong anyway, but this does explain all the identical 3000: ... results. Show quoted text
> I suspect what I'll actually do, to avoid this breakage in future, is to > have unpack_sockaddr_in6() yield just the address when called in scalar > context, to match Socket6, and the IPv4 unpack_sockaddr_in(). This feels > the most useful behaviour anyway, as if you wanted just one value that's > the most likely one. > > -- > > Paul Evans
Brilliant - thanks again Paul.
On Thu Aug 16 16:33:23 2012, vinsworldcom@gmail.com wrote: Show quoted text
> > I suspect what I'll actually do, to avoid this breakage in future, is to > > have unpack_sockaddr_in6() yield just the address when called in scalar > > context, to match Socket6, and the IPv4 unpack_sockaddr_in(). This feels > > the most useful behaviour anyway, as if you wanted just one value that's > > the most likely one.
Done. Also added a check to inet_ntop to ensure it was passed the right length scalars: $ perl -Mblib -MSocket=inet_ntop,AF_INET6 -E 'say inet_ntop AF_INET6, 0' Bad address length for Socket::inet_ntop on AF_INET6; got -954301850, should be 16 at -e l ine 1. as compared to: $ perl -MSocket=inet_ntop,AF_INET6 -E 'say inet_ntop AF_INET6, 0' 3000:2602:0:0:6c00:: Released as 2.005. -- Paul Evans