Доменное имя на адрес IPv6 в Perl

У меня есть следующий код Perl для перевода доменного имени в IP-адрес. Он отлично работает в IPv4.

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

Однако это не работает, если это доменное имя только для IPv6, например «ipv6.google.com».

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

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

person Michael C.    schedule 04.07.2014    source источник
comment
какая версия перла?   -  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;
}

Для более ранних версий perls те же функции доступны по ссылке 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 не поддерживается в строке 7 a.pl. - 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
@МайклС. Возможно, вы просто используете сборку 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