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