Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

connect() returns "invalid argument" with ipv6 address

I have this simple client-server application pair. The code is pretty simple, I'm using only new, advised methods like getaddinfo etc and everything works just fine for ipv4. Even for ipv6 loopback (::1) it works. Problems start when it comes to some other ipv6 addresses... I have two machines in a network, everything works fine when I pass their ipv4 addresses, but when I give my client ipv6 address, I get an error on connect function: invalid argument. Hey, don't I already know this? I do! When I try to ping6 this ipv6 address, I get the same error:

connect: Invalid argument

But there is a way to overcome this block - one should choose an interface with a -I switch and it all runs smoothly since then. But how can I achieve the same in my client app? What should I do? My client code looks like this:

struct addrinfo hints;
struct addrinfo *server;

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;

int status;
if((status = getaddrinfo(argv[1], argv[2], &hints, &server) != 0))
{
    perror("getaddrinfo error");
    return 1;
}

int sock_fd;
struct addrinfo *ptr;
for(ptr=server;ptr!=NULL;ptr=ptr->ai_next)
{
    if( (sock_fd = socket(ptr->ai_family,ptr->ai_socktype,ptr->ai_protocol)) == -1)
    {
        perror("socket error");
        continue;
    }
    if( connect(sock_fd, ptr->ai_addr,ptr->ai_addrlen) == -1 )
    {
        perror("connect error");
        continue;       
    }
    break;
}
like image 740
flyjohny Avatar asked Sep 04 '12 08:09

flyjohny


2 Answers

Addresses starting with ff... are multicast addresses. Connecting a stream to a multicast address does not work.

Addresses starting with fe80... are link-local addresses, which have an interface identifier associated with them. Try looking at the sockaddr returned from getaddrinfo, is the scope field filled out?

like image 158
Simon Richter Avatar answered Nov 09 '22 18:11

Simon Richter


You need to specify the interface for IPv6 ping (i.e. -I eth0):

ping6 -I eth0 fe80::208:54ff:fe34:22ae

Using link-local addresses for an IPv6 ping, requires to define what device it must send/receive the packet - each device has a link-local address.

Trying without this, will result in error message like:

--> # ping6 fe80::208:54ff:fe34:22ae 
connect: Invalid argument

In this case you have to specify the interface additionally like shown here:

--> # ping6 -I eth0 fe80::208:54ff:fe34:22ae
PING fe80::208:54ff:fe34:22ae(fe80::208:54ff:fe34:22ae) from fe80::208:54ff:fe34:22ae eth0: 56 data bytes
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=0 ttl=64 time=0.027 ms
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=1 ttl=64 time=0.030 ms
64 bytes from fe80::208:54ff:fe34:22ae: icmp_seq=2 ttl=64 time=0.036 ms

One similar approach you must to follow in your client APP..

like image 41
Marco Ladino Avatar answered Nov 09 '22 20:11

Marco Ladino