Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

I've done some research and come to the conclusion that I can't do name lookup for IPv4 *and* IPv6 addresses (address family independent) with the current version of Perl on my platform. This question is basically to confirm or set me straight.

Windows 7 x64, Strawberry Perl 5.12.3

VinsWorldcom@C:\Users\VinsWorldcom> ver Microsoft Windows [Version 6.1.7601] VinsWorldcom@C:\Users\VinsWorldcom> perl -v This is perl 5, version 12, subversion 3 (v5.12.3) built for MSWin32-x +64-multi-thread [...]

Looking at http://www.perl.org/about/whitepapers/perl-ipv6.html, I successfully built a simple Perl web-server that listens on v4 *OR* v6 (not both at the same time) using IO::Socket::INET and IO::Socket::INET6 (also with IO::Socket::IP and some additional logic). All that worked fine using just IPv4/v6 addresses. I want to use names.

I have IPv6 enabled with a Hurricane Electric tunnel and can successfully ping ipv6.google.com (an IPv6 only site). In this case, I'm just looking to do name resolution.

With dig.exe on Windows:

VinsWorldcom@C:\Users\VinsWorldcom> dig -v DiG 9.8.1 VinsWorldcom@C:\Users\VinsWorldcom> dig ipv6.google.com aaaa @8.8.8.8 ; <<>> DiG 9.8.1 <<>> ipv6.google.com aaaa @8.8.8.8 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7089 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;ipv6.google.com. IN AAAA ;; ANSWER SECTION: ipv6.google.com. 86399 IN CNAME ipv6.l.google.com. ipv6.l.google.com. 299 IN AAAA 2001:4860:800f::63 ;; Query time: 69 msec ;; SERVER: 8.8.8.8#53(8.8.8.8) ;; WHEN: Tue Nov 15 10:05:14 2011 ;; MSG SIZE rcvd: 82

I put together a simple script to test name lookup the 'old' way (gethostbyname() and inet_ntoa()) and the 'new' way (getaddrinfo() and inet_ntop()). I also successfully installed the Socket6 and Socket::GetAddrInfo modules with Strawberry.

#!/usr/bin/perl use strict; use warnings; use Getopt::Long qw(:config no_ignore_case); use Pod::Usage; use Socket; use Socket6; use Socket::GetAddrInfo qw(getaddrinfo); my %opt; GetOptions( 'new!' => \$opt{new}, 'old!' => \$opt{old} ) or pod2usage(-verbose => 0); if (!@ARGV) { pod2usage(-verbose => 0, -message => "$0: host required\n") } if ((!defined($opt{new})) && (!defined($opt{old}))) { $opt{new} = $opt{old} = 1 } if ($opt{old}) { my $gethost = gethostbyname($ARGV[0]); my $host = inet_ntoa((gethostbyname($ARGV[0]))[4]); # print "OLD: gethostbyname() = $gethost\n"; print "OLD: inet_ntoa() Address = $host\n"; } if ($opt{new}) { my ($err, @getaddr) = getaddrinfo($ARGV[0], 0); if (!@getaddr) { print "$0: $err\n"; exit } my $host = inet_ntop(AF_INET6, (getaddrinfo($ARGV[0], 0))[1]->{add +r}); # printf "NEW: getaddrinfo() = %s\n", $getaddr[1]->{addr}; print "NEW: inet_ntop() Address = $host\n"; } __END__ =head1 SYNOPSIS program [--old|--new] IP[v6]_address | hostname

I believe the coding is correct (albeit not elegent). It just errors on the IPv6 host look ups and incorrectly does the IPv4 lookups the 'new' way.

VinsWorldcom@C:\Users\VinsWorldcom\tmp> v4v6Lookup.pl www.google.com OLD: inet_ntoa() Address = 72.14.204.105 NEW: inet_ntop() Address = 200:0:480e:cc69:: VinsWorldcom@C:\Users\VinsWorldcom\tmp> v4v6Lookup.pl 72.14.204.105 OLD: inet_ntoa() Address = 72.14.204.105 NEW: inet_ntop() Address = 200:0:480e:cc69::

Both addresses should be the v4 address. The inet_ntop function is converting to IPv6 even though it shouldn't - 72 = 48, 14 = 0e, 204 = cc, 105 = 69

With IPv6 name lookups, it doesn't work at all. I expect the runs without the '--new' switch to fail as gethostbyname() and inet_ntoa() don't support IPv6, but the runs with the '--new' switch also fail.

VinsWorldcom@C:\Users\VinsWorldcom\tmp> v4v6Lookup.pl ipv6.google.com Usage: Socket::inet_ntoa(ip_address_sv) at C:\Users\VinsWorldcom\tmp\v +4v6Lookup.pl line 29. VinsWorldcom@C:\Users\VinsWorldcom\tmp> v4v6Lookup.pl --new ipv6.googl +e.com C:\Users\VinsWorldcom\tmp\v4v6Lookup.pl: The requested name is valid, +but no data of the requested type was found. VinsWorldcom@C:\Users\VinsWorldcom\tmp> v4v6Lookup.pl 2001:4860:800f:: +63 Usage: Socket::inet_ntoa(ip_address_sv) at C:\Users\VinsWorldcom\tmp\v +4v6Lookup.pl line 29. VinsWorldcom@C:\Users\VinsWorldcom\tmp> v4v6Lookup.pl --new 2001:4860: +800f::63 Bad arg length for Socket6::inet_ntop, length is 28, should be 16 at C +:\Users\VinsWorldcom\tmp\v4v6Lookup.pl line 40.

As you can see, the gethostbyname() and inet_ntoa() worked well for host or IP resolution to an IP address in the IPv4 address family - and that's how I've always done it. Trying to extend that to let my scripts accommodate IPv4 and IPv6 is proving problematic. According to the above web link, Perl 5.14 will fix this and Strawberry just released 5.14 - I haven't tried that yet.

UPDATE:

Found a way to get it to work - less than ideal though:

#!/usr/bin/perl use strict; use warnings; use Getopt::Long qw(:config no_ignore_case); use Pod::Usage; use Socket; use Socket6; # Windows DOES support getaddrinfo and inet_ntop/pton functions # although it may *seem* like it doesn't from Strawberry's GCC # Don't need Socket6::GetAddrInfo my %opt; GetOptions( 'new!' => \$opt{new}, 'old!' => \$opt{old} ) or pod2usage(-verbose => 0); if (!@ARGV) { pod2usage(-verbose => 0, -message => "$0: host required\n") } if ((!defined($opt{new})) && (!defined($opt{old}))) { $opt{new} = $opt{old} = 1 } if ($opt{old}) { my $gethost = gethostbyname($ARGV[0]); my $host = inet_ntoa((gethostbyname($ARGV[0]))[4]); # print "OLD: gethostbyname() = $gethost\n"; print "OLD: inet_ntoa() Address = $host\n"; } if ($opt{new}) { my @getaddr = getaddrinfo($ARGV[0], 0); # IP[v6] address shows up at different locations in the [3] elemen +t # use substr to 'find' it - awful! my $host = inet_ntop($getaddr[0], substr($getaddr[3], (($getaddr[0 +] == AF_INET) ? 4 : 8), (($getaddr[0] == AF_INET) ? 4 : 16))); # printf "NEW: getaddrinfo() = %s\n", $getaddr[3]; print "NEW: inet_ntop() Address = $host\n"; } __END__ =head1 SYNOPSIS program [--old|--new] IP[v6]_address | hostname

And the output:

VinsWorldcom@C:\Users\VinsWorldcom\tmp> v4v6Lookup.pl --new www.google +.com NEW: inet_ntop() Address = 72.14.204.147 VinsWorldcom@C:\Users\VinsWorldcom\tmp> v4v6Lookup.pl --new ipv6.googl +e.com NEW: inet_ntop() Address = 2001:4860:800f::93

UPDATE

Realized getaddrinfo returns 5 element array, number 3 is the address *STRUCTURE* - not the address itself. Need the following code to massage out the IPv4/v6 address:

if ($opt{new}) { my @getaddr = getaddrinfo($ARGV[0], 0); my $address; # Get the pointer to the address itself, different fields in IPv4 +and IPv6 if ($getaddr[0] == AF_INET) { $address = (unpack_sockaddr_in($getaddr[3]))[1] } else { $address = (unpack_sockaddr_in6($getaddr[3]))[1] } my $host = inet_ntop($getaddr[0], $address); # printf "NEW: getaddrinfo() = %s\n", $getaddr[3]; print "NEW: inet_ntop() Address = $host\n"; }

In reply to IPv6 Name Resolution by VinsWorldcom

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (5)
As of 2024-04-24 07:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found