How does a Perl socket resolve hostnames under Linux?

I have (from which I can tell) a perfectly working Linux installation (Ubuntu 8.04), where all the tools (nslookup, curl, wget, firefox, etc.) can resolve addresses. However, the following code does not work:

$s = new IO::Socket::INET(
    PeerAddr => 'stackoverflow.com',
    PeerPort => 80,
    Proto => 'tcp',
);

die "Error: $!\n" unless $s;

I checked the following things:

  • Perl can resolve addresses using gethostbyname (i.e. the code below):

    my $ret = gethostbyname('stackoverflow.com'); print inet_ntoa($ret);

  • The source code runs on Windows

  • This is how it should work (i.e. it must resolve hostnames) as LWP is trying to use this behavior (I actually came across a problem trying to debug why LWP didn’t work for me)
  • Running the script does not generate DNS queries (therefore, it does not even try to resolve the name). Tested with Wireshark
+3
source share
3

IO:: Socket:: INET

sub _get_addr {
    my($sock,$addr_str, $multi) = @_;
    my @addr;
    if ($multi && $addr_str !~ /^\d+(?:\.\d+){3}$/) {
        (undef, undef, undef, undef, @addr) = gethostbyname($addr_str);
    } else {
        my $h = inet_aton($addr_str);
        push(@addr, $h) if defined $h;
    }
    @addr;
}

( ) MultiHomed => 1, .

inet_aton("hostname.com") inet_aton() Socket.pm. Win32, Unix, , .

Socket.xs inet_aton:

void
inet_aton(host)
    char *  host
    CODE:
    {
        struct in_addr ip_address;
        struct hostent * phe;

        if (phe = gethostbyname(host)) {
            Copy( phe->h_addr, &ip_address, phe->h_length, char );
        } else {
            ip_address.s_addr = inet_addr(host);
        }

        ST(0) = sv_newmortal();
        if(ip_address.s_addr != INADDR_NONE) {
            sv_setpvn( ST(0), (char *)&ip_address, sizeof ip_address );
        }
    }

, Perl gethostbyname() , C gethostbyname() .

+7

, ? , , !

( " IO:: Socket:: INET" Mac OS X, .

, Multihomed , .

0

Make sure you have an operator

use IO::Socket::INET;

At the beginning of the source code. If you leave this, you will probably get an error message:

Unable to find object method "new" through package "IO :: Socket :: INET"

In addition, you can check the operation of DNS using Net :: DNS :: Resoler, see more information here .

use Net::DNS;

my $res = Net::DNS::Resolver->new;

# Perform a lookup, using the searchlist if appropriate.
my $answer = $res->search('example.com');
-1
source

Source: https://habr.com/ru/post/1697796/


All Articles