MoarVM / MoarVM

A VM with adaptive optimization and JIT compilation, built for Rakudo
https://moarvm.org/
Other
697 stars 172 forks source link

MVM_io_resolve_host_name should accept an optional sa_family argument #683

Closed book closed 6 years ago

book commented 7 years ago

In MVM_io_resolve_host_name, the result struct in the call to getaddrinfo is an addrinfo, which is in fact a linked list, with the next item in the list is in ai_next.

Right now, MVM_io_resolve_host_name returns the first socket in the list. The comment above the definition claims it's not an issue, however in Perl 6 IO::Socket::INET accepts a :$family argument which defaults to 2 (i.e. IPv4).

This behaviour means that on a machine where localhost can be resolved in both IPv4 and IPv6,

$ getent ahosts localhost
::1             STREAM localhost
::1             DGRAM  
::1             RAW    
127.0.0.1       STREAM 
127.0.0.1       DGRAM  
127.0.0.1       RAW    

this code:

my $server = IO::Socket::INET.new(:localhost<localhost>, :localport(4444), :listen);

will return an IPv6 socket (listening), even though, according to the documentation and the code, it should be IPv4.

I don't think it's actually necessary to iterate over the list, because getaddrinfo's third argument is a hints structure which can be either NULL (like it is at the moment in MVM_io_resolve_host_name) or an addrinfo structure with the type of service requested.

So, MVM_io_resolve_host_name should accept an additional (optional?) arguments, which could be the hints structure to be passed to getaddrinfo, or at least a ai_family value that could be used to create the hints to be passed.

This way, the first item in the linked list would be an IPv4 or IPv6 socket depending on what was required on the Perl 6 side.

duke-m commented 7 years ago

with

::1               localhost
127.0.0.1         localhost

the family used/returned with your code above is 2 (IPv4), FreeBSD 11.1-RELEASE-p1, Rakudo version 2017.07 built on MoarVM version 2017.07.

duke-m commented 7 years ago

@samcv since you've just did some builds on FreeBSD, too, can you also check, if you please? thanks

samcv commented 7 years ago

I get family => 2 on FreeBSD 1.1. Localhost is pingable with ::1 or 127.0.0.1

duke-m commented 7 years ago

@book can you re-check and tell us what versions you are using? I always get family => 2 on all tested environments.

the-eater commented 6 years ago

I don't really get what @duke-m and @samcv are testing, if you look at the MVM_io_resolve_host_name you see we only do address resolving via getaddrinfo, and IO::Socket::INET only uses $family for host and port splitting and never passes it to bind_sock to the point that if you don't specify an localhost but specify family => 3 it still listens to IPv4.

e.g.:

my $server = IO::Socket::INET.new(:localport(4444), :listen, :family(3));
say shell('lsof -nPi | grep 4444');

Since this is in the same definition space (sa_family_t) as AF_UNIX which also had to be passed we can just $family << 16 and add it to the port number :)