Име на домейн към IPv6 адрес в Perl

Имам следния код на Perl за превод на име на домейн в IP адрес. Работи добре в IPv4.

$host = "example.com";
$ip_address = join('.', unpack('C4',(gethostbyname($host))[4]));

Това обаче не работи, ако е име на домейн само за IPv6, като например „ipv6.google.com“.

Как мога да получа един ред код (предпочитам CORE библиотека), за да получа IPv6 IP адрес?

$host = "ipv6.google.com";
$ip_address = ???

person Michael C.    schedule 04.07.2014    source източник
comment
коя версия на perl?   -  person ysth    schedule 04.07.2014
comment
Гледам Perl 5.10 и по-нова версия   -  person Michael C.    schedule 04.07.2014


Отговори (2)


В 5.14 и по-нови можете да използвате ядрото Socket:

use 5.014;
use warnings;
use Socket ();

# protocol and family are optional and restrict the addresses returned
my ( $err, @addrs ) = Socket::getaddrinfo( $ARGV[0], 0, { 'protocol' => Socket::IPPROTO_TCP, 'family' => Socket::AF_INET6 } );
die $err if $err;

for my $addr (@addrs) {
    my ( $err, $host ) = Socket::getnameinfo( $addr->{addr}, Socket::NI_NUMERICHOST );
    if ($err) { warn $err; next }
    say $host;
}

За по-стари perl същите функции са налични от Socket::GetAddrInfo на CPAN.

person ysth    schedule 04.07.2014
comment
Гнездото е с двоен живот. Има ли някаква причина да инсталирате Socket::GetAddrInfo вместо да надграждате Socket? - person ikegami; 04.07.2014
comment
Получавам следната грешка при използване на Perl 5.16 Windows. ai_family не се поддържа в a.pl ред 7. - person Michael C.; 04.07.2014
comment
@Micheal C., Репликирано и решено чрез надграждане на Socket (cpan Socket) - person ikegami; 04.07.2014
comment
@ikegami Имам най-новия Socket 2.014, но същата грешка. - person Michael C.; 04.07.2014
comment
@MichaelC. Може просто да използвате компилация на Windows или Perl, която не поддържа директно IPv6. Това е правилният метод за изпълнение на 'v6 резолюции, така че ако не работи, значи нещо някъде във веригата липсва. - person LeoNerd; 05.07.2014
comment
@ysth: Някаква причина да извършите празен импорт от Socket, след което да наречете всички функции и константи напълно квалифицирани? Обикновено би било по-спретнато да импортирате необходимите символи. - person LeoNerd; 05.07.2014
comment
Намирам за по-прилично при всяко обаждане да посочвам в кой пакет е нещо, особено константите. - person ysth; 06.07.2014

Net::DNS също може да ви помогне:

#!/usr/bin/perl -w                                                                                                  
use strict;
use warnings;

use Net::DNS;

my $res   = Net::DNS::Resolver->new;
my $query = $res->query("ipv6.google.com", "AAAA")
    or die "query failed: ", $res->errorstring;

foreach my $rr (grep { $_->type eq 'AAAA' } $query->answer) {
    print $rr->address, "\n";
}

Изходи:

2607:f8b0:4010:801:0:0:0:1005
person Hamster    schedule 04.07.2014
comment
Обърнете внимание, че директният достъп до DNS вместо използването на интерфейса за търсене на име на системата (getaddrinfo) ще скрие записите в хост файла. - person ikegami; 04.07.2014
comment
Така или иначе, за да избегнете използването на Net::DNS? - person Michael C.; 05.07.2014
comment
Гласуване против, защото: Никога не трябва да се занимавате директно с DNS, освен ако това не е цялата ви функция - да извършвате някакво търсене, специфично за DNS. В 99,9% от случаите програмите не са. Вместо това те просто искат да използват системния резолвер, getaddrinfo. Вижте друг отговор. - person LeoNerd; 05.07.2014