LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices

Reply
 
Search this Thread
Old 04-24-2010, 01:53 AM   #1
mwnn
LQ Newbie
 
Registered: Apr 2010
Posts: 2

Rep: Reputation: 0
Program to assign globa lIPv6 address and bind() to the previously assigned address.


Consider the following program:
Code:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>

#define IPV6_BINARY_LEN 128

int32_t set_ip_addr(const char *dev, const char *ip, int32_t prefix_len);

int main(int argc, char *argv[])
{
	struct sockaddr_in6 sa;
	int32_t sd;
	int32_t local_errno;
	int32_t one = 1;
	int32_t ret;

	if (argc != 4) {
		fprintf(stderr, "Usage: %s <dev> <ip address> <prefix Length>.\n",
			argv[0]);
		goto out1;
	}

	ret = set_ip_addr(argv[1], argv[2], atoi(argv[3]));
	if (ret == -1) {
		fprintf(stderr, "Unable to set IP address.\n");
		goto out1;
	}

	sd = socket(AF_INET6, SOCK_DGRAM, 0);
	if (sd == -1) {
		perror("socket");
		goto out1;
	}

	ret = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (void *)&one,
			 sizeof(one));
	if (ret == -1) {
		perror("setsockopt");
		goto out1;
	}

	ret = setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&one,
			 sizeof(one));
	if (ret == -1) {
		perror("setsockopt");
		goto out1;
	}

	memset(&sa, 0, sizeof(sa));
	sa.sin6_family = AF_INET6;
	sa.sin6_port = htons(4915);
	sa.sin6_scope_id = 0;
	ret = inet_pton(AF_INET6, argv[2], sa.sin6_addr.s6_addr);
	if (ret != 1) {
		perror("inet_pton");
		goto out2;
	}
#if 0
	printf("Sleeping before bind ...\n");
	sleep(30);
#endif
	ret = bind(sd, (struct sockaddr *)&sa, sizeof(sa));
	if (ret == -1) {
		local_errno = errno;
		printf("errno = %d.\n", errno);
		perror("bind");
		goto out2;
	}

	printf("Bind success!\n");

	close(sd);

	exit(0);
out2:
	close(sd);
out1:
	exit(1);
}

struct in6_ifreq {
	struct in6_addr	ifr6_addr;
	uint32_t	ifr6_prefixlen;
	int		ifr6_ifindex;
};

int32_t set_ip_addr(const char *dev, const char *ip, int32_t prefix_len)
{
	struct in6_ifreq in6_ifreq;
	struct ifreq ifreq;
	uint8_t ip_bin[IPV6_BINARY_LEN];
	int32_t sd;
	int32_t one = 1;
	int32_t ret;

	if ((dev == NULL) || (ip == NULL) || (prefix_len < 0)) {
		fprintf(stderr, "%s: Invalid arguments.\n", __func__);
		goto out1;
	}

	ret = inet_pton(AF_INET6, ip, ip_bin);
	if (ret != 1) {
		perror("inet_pton");
		goto out1;
	}

	sd = socket(AF_INET6, SOCK_DGRAM, 0);
	if (sd == -1) {
		perror("socket");
		goto out1;
	}

	ret = setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&one,
			 sizeof(one));
	if (ret == -1) {
		perror("setsockopt");
		goto out1;
	}

	memset(&ifreq, 0, sizeof(ifreq));
	strncpy(ifreq.ifr_name, dev, IFNAMSIZ - 1);
	ret = ioctl(sd, SIOCGIFINDEX, &ifreq);
	if (ret == -1) {
		perror("ioctl");
		goto out2;
	}

	memset(&in6_ifreq, 0, sizeof(in6_ifreq));
	ret = inet_pton(AF_INET6, ip, &in6_ifreq.ifr6_addr.s6_addr);
	if (ret != 1) {
		perror("inet_pton");
		goto out2;
	}

	in6_ifreq.ifr6_ifindex = ifreq.ifr_ifindex;
	in6_ifreq.ifr6_prefixlen = prefix_len;

	ret = ioctl(sd, SIOCSIFADDR, &in6_ifreq);
	if (ret == -1) {
		perror("ioctl");
		goto out2;
	}

	return 0;

out2:
	close(sd);
out1:
	return -1;
}
The program can be executed as shown below:
Code:
# ./set_ip_and_bind eth0 2001:0db8:0:f101::1 64
The bind() call fails with errno 99 (Cannot assign requested address).
If the sleep(30) is enabled the bind() call executes successfully.
 
Old 04-24-2010, 11:11 PM   #2
mwnn
LQ Newbie
 
Registered: Apr 2010
Posts: 2

Original Poster
Rep: Reputation: 0
In Linux-2.6.33, the function ipv6_add_addr() in addrconf.c sets ifa->flags to IFA_F_TENTATIVE. This is set to IFA_F_PERMANENT only after "Duplicate Address Detection" procedure is completed successfully. In the above listed program, bind() is being called immediately after assigning the IP address. Hence the inet6_bind() in af_inet6.c fails since ifa->flags is still set to IFA_F_TENTATIVE. This issue can probably be resolved by using the IFA_F_NODAD flag (which disables "Duplicate address detection" procedure). So the question is, how do I pass this flag from userspace to the kernel?
 
Old 10-07-2010, 02:29 AM   #3
lprasanna
LQ Newbie
 
Registered: Oct 2010
Posts: 3

Rep: Reputation: 0
bind fails with 99 after SIOCSIFADDR ioctl

Hi all,

Did u find any solution for the problem??

I am also seeing the same issue...
Even if i keep a sleep also, i am unable to bind with 99 error.

I am using Fedora 2.6.28.9-x86_64 kernel.

Any help will be appreciated...

thanks,
Lakshmi
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] dhcp-client get assigned a network address instead of a regular IP address kenneho Linux - Networking 3 11-27-2009 03:43 AM
Set IP address to static from DHCP assigned address jborn Linux - Networking 4 02-02-2007 08:38 PM
DHCP Server MAC Address found, IP address not assigned wmburke Linux - Wireless Networking 17 11-17-2004 10:33 AM
Help me with this socket address bind program. rnice Linux - Networking 0 09-17-2004 07:33 PM
sendmail quits - cannot bind: Cannot assign requested address scott_r_wagner Linux - Software 5 09-14-2003 05:40 PM


All times are GMT -5. The time now is 06:20 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration