Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从C程序为接口设置ipv6地址_C_Linux_Network Programming_Ioctl - Fatal编程技术网

如何从C程序为接口设置ipv6地址

如何从C程序为接口设置ipv6地址,c,linux,network-programming,ioctl,C,Linux,Network Programming,Ioctl,我正在编写一个程序,需要设置接口的ip地址,并将其设置为UP和RUNNING。我可以使用ioctl(SIOCSIFADDR)对ipv4地址执行此操作,但对ipv6地址执行同样的操作会产生错误 以下是代码片段: 329 memset(&ifr, 0, sizeof(ifr)); 330 strncpy(ifr.ifr_name, in.dev.device, IFNAMSIZ); 331 332 /* we need a socket descriptor

我正在编写一个程序,需要设置接口的ip地址,并将其设置为
UP
RUNNING
。我可以使用
ioctl(SIOCSIFADDR)
对ipv4地址执行此操作,但对ipv6地址执行同样的操作会产生错误

以下是代码片段:

 329     memset(&ifr, 0, sizeof(ifr));
 330     strncpy(ifr.ifr_name, in.dev.device, IFNAMSIZ);
 331 
 332     /* we need a socket descriptor for ioctl(). Cant use tun descriptor */
 333     s = socket(in.over_n, SOCK_DGRAM, 0);
 334     /* Now check if socket we got is ok */
 335     if (s < 0)
 336         raise_error("socket()");
 337         
 338 
 339 
 340     switch (in.over_n) {
 341     
 342     case AF_INET:   memset(&addr4, 0, sizeof(addr4));
 343                     addr4.sin_family = AF_INET;
 344                     /* Convert ip to network binary */
 345                     stat = inet_pton(addr4.sin_family, in.dev.ip_addr, &addr4.sin_addr);
 346                     ifr.ifr_addr = *(struct sockaddr *) &addr4;
 347                     break;
 348                     
 349     case AF_INET6:  memset(&addr6, 0, sizeof(addr6));
 350                     addr6.sin6_family = AF_INET6;
 351                     /* Convert ip to network binary */
 352                     stat = inet_pton(addr6.sin6_family, in.dev.ip_addr, &addr6.sin6_addr);
 353                     ifr.ifr_addr = *(struct sockaddr *) &addr6.sin6_addr;
 354                     break; 
 355     default:        raise_error("invalid network prot");
 356     }               
 357                     
 358     /* Check if conversion happened properly */
 359     if (stat == 0)
 360         raise_error("inet_pton() - invalid ip");
 361     if (stat == -1)
 362         raise_error("inet_pton() - invalid family");
 363         
 364     if (stat != 1)
 365         raise_error("inet_pton()");
 366         
 367     char dum[BUFF_SIZE];
 368     if (inet_ntop(in.over_n, &ifr.ifr_addr, dum, BUFF_SIZE) != NULL)
 369         printf("name = %s, ip = %s\n",ifr.ifr_name,dum);
 370     
 371     /* Set ip */
 372     if (ioctl(s, SIOCSIFADDR, (caddr_t) &ifr) == -1) 
 373         raise_error("ioctl() - SIOCSIFADDR");
如果我把第353行改成

 353                     ifr.ifr_addr = *(struct sockaddr *) &addr6;
然后错误变为

name = tun9, ip = a00::aaaa:0:0:0
ioctl() - SIOCSIFADDR: No such device
我注意到
struct ifreq
有一个成员
struct sockaddr
,我认为它比
struct sockaddr\u在6
中小,但与
中的
sockaddr\u一样大。我想知道这是否是问题所在,
struct ifreq
无法保存ipv6地址。如果这是真的,那么对于涉及ipv6地址的
ioctl()

我试图设置的输入ip地址是
aaaa::bbbbbb
in.over\u n
AF\u INET
AF\u INET6

任何帮助都将不胜感激。请让我知道,如果我需要张贴更多的代码,输出等


非常感谢。

对于IPv6,您应该使用rtnetlink API。这是像ip这样的工具所使用的API,在现代版本中,ifconfig可能也使用它

rtnetlink的优势在于,它支持每个设备的多个地址,并且可以提供更多的信息,因为它更具动态性,并且可以做许多新奇的事情


但rtnetlink API在开始工作时也可能很棘手,因为它需要选择一些结构来正确填充和解析,包括一些奇怪的成员组合,需要填写正确的sizeof()。

可能要感谢@ScottyBauer,它对ip地址有效,但对掩码无效。我需要调试更多的代码,但我无法理解代码到底在做什么。对此答案没有任何解释。你能告诉我那里到底在做什么吗?谢谢你,当我有时间的时候,我会添加评论。非常感谢。如果你能给我指一下关于
ioctl()
ifreq
和相关内容的任何指南或文档,那就太好了。我试图在网上搜索,但找不到确切的来源。
name = tun9, ip = a00::aaaa:0:0:0
ioctl() - SIOCSIFADDR: No such device