ButterLover
ButterLover

Reputation: 137

Socket programming: bind()-invalid argument

I am trying to bind my local IPv6 address to a socket. But always get "invalid argument". The reason I want to bind the specific IP address to socket is that if I don't bind the error "No route to host" came up. When I tried to ping an IPv6 address with command below it does not work.

ping6 fe80::7ed1:c3ff:fe86

I have to point out from which interface I want to send the packet.

ping6 -I en1 fe80::7ed1:c3ff:fe86

And this works fine. So I think if I bind the socket to the interface then I can send the packet successfully. Anyone can tell me how to send an IPv6 address without specify the interface or how to solve this problem of binding?

Here are the codes.

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>

#define LOCALADDR "fe80::7ed1:c3ff:fe86:ddae"

int main(void)
{
int sock,status;
struct addrinfo local_addr;
struct addrinfo *servinfo;
char buffer[1024];

/* create a DGRAM (UDP) socket in the INET6 (IPv6) protocol */
sock = socket(PF_INET6, SOCK_DGRAM, 0);

if (sock < 0) {
    perror("creating socket");
    exit(1);
}

/*Binding specific interface to socket*/
memset(&local_addr, 0, sizeof(local_addr));
local_addr.ai_family = AF_INET6;
local_addr.ai_socktype = SOCK_DGRAM;
local_addr.ai_flags = AI_PASSIVE;

if ((status = getaddrinfo(NULL, "3535", &local_addr, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    exit(1);
}

if (bind(sock, (struct sockaddr *) &local_addr, sizeof(local_addr)) < 0)
    error("ERROR on binding");

I have also tried to replace "NULL" in the "getaddrinfo" to be "LOCALADDR".

if ((status = getaddrinfo(LOCALADDR, "3535", &local_addr, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
    exit(1);
}

And I still get the same problem.

I can successfully binding the socket with "in6addr_any",but then I get the error "No route to host".

Upvotes: 2

Views: 5235

Answers (2)

Ron Maupin
Ron Maupin

Reputation: 6452

That is a link-local IPv6 address, not a routable IPv6 address. The link-local addresses are specific to a link, and each link can have the same addresses as the other links. For instance if you have three different interfaces, you can assign the same link-local address to each of the interfaces. To use a link-local address, you need to specify the interface so that the OS knows which link to use. All the interfaces will have a link-local address in the same network: fe80::/10.

If you use a routable IPv6 address, you will not need to specify an interface.

Upvotes: 4

John Bollinger
John Bollinger

Reputation: 180058

You are creating the socket incorrectly. The 'domain' (first argument) should be AF_INET6, not PF_INET6. I am uncertain whether these in fact expand to different values in your environment, but the AF_* macros are the ones designated for this purpose.

Otherwise, for a socket that accepts connections, you should get an address much the way you first present. In particular, the docs for getaddrinfo() say

If the AI_PASSIVE flag is specified in hints.ai_flags, and node is NULL, then the returned socket addresses will be suitable for bind(2)ing a socket that will accept(2) connections. The returned socket address will contain the "wildcard address" (INADDR_ANY for IPv4 addresses, IN6ADDR_ANY_INIT for IPv6 address). The wildcard address is used by applications (typically servers) that intend to accept connections on any of the hosts’s network addresses. If node is not NULL, then the AI_PASSIVE flag is ignored.

Thus, you certainly could and probably should specify a NULL first argument.

Note, however, that getaddrinfo() returns a linked list of addresses, and under some circumstances it is necessary to choose a different one than the first. I think the first ought to be fine in this particular case, though.

Do also be aware that a "no route to host" message from a client trying to connect does not necessarily indicate that the server is not listening. It could well be that the client is using the wrong address (c.f. @RonMaupin's answer) or, just as it says, that there is no (known) route through the network from the client to the server. That could arise because of router or firewall configuration, for example.

Upvotes: 0

Related Questions