如何从C程序为接口设置ipv6地址
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从C程序为接口设置ipv6地址相关的知识,希望对你有一定的参考价值。
我正在编写一个程序,需要设置一个接口的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
",ifr.ifr_name,dum);
370
371 /* Set ip */
372 if (ioctl(s, SIOCSIFADDR, (caddr_t) &ifr) == -1)
373 raise_error("ioctl() - SIOCSIFADDR");
这适用于ipv4地址,但ipv6地址给我错误:
name = tun9, ip = aaaa::bbbb
ioctl() - SIOCSIFADDR: Invalid argument
如果我将第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_in6
小但是和sockaddr_in
一样大。我想知道这是否是问题,struct ifreq
无法保存ipv6地址。如果这是真的,那么我们对涉及ipv6地址的ioctl()
使用了什么?
我试图设置的输入IP地址是aaaa::bbbb
,in.over_n
是AF_INET
或AF_INET6
。
任何帮助都感激不尽。如果我需要发布更多代码,输出等,请告诉我。
非常感谢。
答案
对于IPv6,您应该使用rtnetlink API。这是ip等工具使用的API,ifconfig也可能在现代版本中使用它。
rtnetlink的优势在于它支持每个设备多个地址,并且可以提供更多信息,因为它更具动态性,可以做许多奇特的事情。
但是rtnetlink API最初工作也很棘手,因为它需要一些结构来正确填充和解析,包括需要填充正确sizeof()的一些奇怪的成员组合。
以上是关于如何从C程序为接口设置ipv6地址的主要内容,如果未能解决你的问题,请参考以下文章