connect() returns "invalid argument" with ipv6 address

14,960

Solution 1

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?

Solution 2

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..

Share:
14,960

Related videos on Youtube

flyjohny
Author by

flyjohny

Junior software developer

Updated on July 11, 2022

Comments

  • flyjohny
    flyjohny almost 2 years

    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;
    }
    
    • Ariel
      Ariel over 11 years
      What is this problematic address that ping rejects?
  • flyjohny
    flyjohny over 11 years
    I know that I am lazy ass but could you tell me how to turn on the ip6 protocol in the interface? I am using a Linux box.
  • Oliver
    Oliver over 11 years
    First check this Guide tldp.org/HOWTO/Linux+IPv6-HOWTO/x790.html after that try this on your specific interface : ping6 -I eth0 "fill the ip6addr here" it could be that your loopback interface has ip6 support activated and therefore the local ping works with no issues, Can you maybe tell us your Linux distro and the kernel version?
  • Simon Richter
    Simon Richter over 11 years
    This field should contain the interface number. Have you specified the scope with the %eth0 or %1 (1 being the interface number, which you can look up with the ip tool) notation?\
  • flyjohny
    flyjohny over 11 years
    Nope. When I do that, this scope field is filled with some value and it seems to work (although I need to configure my specific FW, but I get no invalid argument anymore). But I seem to miss something and in all the materials connected with ipv6 I was reading I didn't come across this - do I need to specify the interface whenever I use link-local address?
  • Simon Richter
    Simon Richter over 11 years
    Yes, you do. Link-local address means precisely that uniqueness of the address is only guaranteed on this particular link, so the system has no way of finding out which interface to send the data to unless you tell it. The alternative is to assign addresses with global scope and use a routing table.
  • kaps
    kaps over 5 years
    @SimonRichter - If I am using the local link address, does it mean that the scope_id field will be always 0 and we need to explicitly specify it ? Can system pick this automatically with any config in /etc/hosts ot any other config ? (Note : I have no DNS in place in my network)
  • Simon Richter
    Simon Richter over 5 years
    @kaps, no, there is no way to have the system auto-select the interface. It is perfectly legal to have ppp0, ppp1 and ppp2 all configured to use a local address of fe80::1 and a peer address of fe80::2, so the OS could not decide which interface to use for a destination address of fe80::2. So the program needs to fill in the scope_id. When the addresses are configured by the user, getaddrinfo will fill it out when the user uses the % notation, when you use multicast for discovery, you can use the scope ID from the discovery packet's origin.