Search code examples
c++carguments

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.

The 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;
}

Solution

  • 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?