LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Networking (http://www.linuxquestions.org/questions/linux-networking-3/)
-   -   bind() fails with EADDRNOTAVAIL after calling an SIOCSIFADDR ioctl for IPV6 address (http://www.linuxquestions.org/questions/linux-networking-3/bind-fails-with-eaddrnotavail-after-calling-an-siocsifaddr-ioctl-for-ipv6-address-836723/)

lprasanna 10-07-2010 06:14 AM

bind() fails with EADDRNOTAVAIL after calling an SIOCSIFADDR ioctl for IPV6 address
 
Hi,

I am trying to assign an IPV6 address to the interface using SIOCSIFADDR ioctl call. After that trying to bind to that particular IPV6 address added. Bind fails with errno 99 (EADDRNOTAVAIL).
Tried introducing some sleep after ioctl and before bind() call, the same error is returned.

Linux kernel version is 2.6.28.9.

Does anyone know how to fix this??

The program is below:
OUTPUT:

fed1::81
Error: 0
Return of Bind: -1, errno: 99


struct sockaddr_in6 in_addr;
void setIP()
{
struct ifreq ifr;
struct in6_ifreq ifr6;
int socv6;
char ip[50]={0};

memset(&in_addr, 0, sizeof(in_addr));

socv6=socket(AF_INET6, SOCK_DGRAM, 0);
strcpy(ifr.ifr_name,"eth0");
ioctl(socv6, SIOGIFINDEX, &ifr);

ifr6.ifr6_ifindex = ifr.ifr_ifindex;
ifr6.ifr6_prefixlen = 64;

inet_pton(AF_INET6, "fed1::81", &in_addr);
inet_pton(AF_INET6, "fed1::81", &ifr6.ifr6_addr);
inet_ntop(AF_INET6, &in_addr, &ip, sizeof(ip) );

inet_ntop(AF_INET6, &ifr6.ifr6_addr, &ip, sizeof(ip) );
printf("%s:\n", ip);

ioctl(socv6,SIOCSIFADDR,&ifr6);
printf("Error: %d\n",errno);
}
int main()
{
int sockFd=0, ret =0;

setIP();

sockFd = socket(AF_INET6, SOCK_STREAM, 0);
inet_pton(AF_INET6, "fed1::81", &(in_addr.sin6_addr));

int one = 1;

if (setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &one,
sizeof(one)) < 0)
{
printf("ERROR in set_sockopt(): %d\n", errno);
return 0;
}

in_addr.sin6_port = htons(8888);
in_addr.sin6_family = AF_INET6;

ret = bind(sockFd, (struct sockaddr *)&in_addr, sizeof(in_addr));
printf("Return of Bind: %d, errno: %d\n", ret, errno);

getchar();
return 0;
}

thanks in advance,
Lakshmi

lprasanna 10-12-2010 11:48 PM

Hi,

Found a workaround at this blog http://mwnnlin.blogspot.com/2010/05/...nd-issues.html.

If anyone knows of another solution other than modifying the Kernel source and disabling DAD requests, please reply..

thanks
Lakshmi


Quote:

Originally Posted by lprasanna (Post 4120390)
Hi,

I am trying to assign an IPV6 address to the interface using SIOCSIFADDR ioctl call. After that trying to bind to that particular IPV6 address added. Bind fails with errno 99 (EADDRNOTAVAIL).
Tried introducing some sleep after ioctl and before bind() call, the same error is returned.

Linux kernel version is 2.6.28.9.

Does anyone know how to fix this??

The program is below:
OUTPUT:

fed1::81
Error: 0
Return of Bind: -1, errno: 99


struct sockaddr_in6 in_addr;
void setIP()
{
struct ifreq ifr;
struct in6_ifreq ifr6;
int socv6;
char ip[50]={0};

memset(&in_addr, 0, sizeof(in_addr));

socv6=socket(AF_INET6, SOCK_DGRAM, 0);
strcpy(ifr.ifr_name,"eth0");
ioctl(socv6, SIOGIFINDEX, &ifr);

ifr6.ifr6_ifindex = ifr.ifr_ifindex;
ifr6.ifr6_prefixlen = 64;

inet_pton(AF_INET6, "fed1::81", &in_addr);
inet_pton(AF_INET6, "fed1::81", &ifr6.ifr6_addr);
inet_ntop(AF_INET6, &in_addr, &ip, sizeof(ip) );

inet_ntop(AF_INET6, &ifr6.ifr6_addr, &ip, sizeof(ip) );
printf("%s:\n", ip);

ioctl(socv6,SIOCSIFADDR,&ifr6);
printf("Error: %d\n",errno);
}
int main()
{
int sockFd=0, ret =0;

setIP();

sockFd = socket(AF_INET6, SOCK_STREAM, 0);
inet_pton(AF_INET6, "fed1::81", &(in_addr.sin6_addr));

int one = 1;

if (setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &one,
sizeof(one)) < 0)
{
printf("ERROR in set_sockopt(): %d\n", errno);
return 0;
}

in_addr.sin6_port = htons(8888);
in_addr.sin6_family = AF_INET6;

ret = bind(sockFd, (struct sockaddr *)&in_addr, sizeof(in_addr));
printf("Return of Bind: %d, errno: %d\n", ret, errno);

getchar();
return 0;
}

thanks in advance,
Lakshmi


AGWA 08-15-2011 02:29 PM

It's possible to disable DAD (and thus fix this problem) without patching the kernel. You just need to set net.ipv6.conf.INTERFACE.accept_dad to 0 in sysctl.

For example, before bringing up eth0, run:

Code:

echo 0 > /proc/sys/net/ipv6/conf/eth0/accept_dad
If you're using Debian, you can put this in your interfaces file as a "pre-up" command.


All times are GMT -5. The time now is 06:56 PM.