Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
04-24-2010, 02:53 AM
|
#1
|
LQ Newbie
Registered: Apr 2010
Posts: 2
Rep:
|
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.
|
|
|
04-25-2010, 12:11 AM
|
#2
|
LQ Newbie
Registered: Apr 2010
Posts: 2
Original Poster
Rep:
|
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?
|
|
|
10-07-2010, 03:29 AM
|
#3
|
LQ Newbie
Registered: Oct 2010
Posts: 3
Rep:
|
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
|
|
|
All times are GMT -5. The time now is 06:04 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|