如何从C程序为接口设置ipv6地址
我正在编写一个程序,需要设置接口的ip地址,并将其设置为如何从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
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