【问题标题】:How to set ipv6 address for an interface from a C program如何从 C 程序中为接口设置 ipv6 地址
【发布时间】:2013-08-09 15:06:55
【问题描述】:

我正在写一个程序,需要设置一个接口的ip地址,设置UPRUNNING。我可以使用ioctl(SIOCSIFADDR) 对 ipv4 地址执行此操作,但对 ipv6 地址执行相同操作会出错。

下面是sn-p的代码:

 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");

这适用于 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::bbbbin.over_nAF_INETAF_INET6

任何帮助将不胜感激。如果我需要发布更多代码、输出等,请告诉我。

非常感谢。

【问题讨论】:

  • 可能duplicate
  • 感谢@ScottyBauer,它适用于 IP 地址,但不适用于掩码。我需要再调试一些,但我不明白代码到底在做什么。该答案没有任何解释。你能告诉我那里到底在做什么吗?谢谢
  • 是的,当我生病时添加 cmets。
  • 非常感谢。如果您可以向我指出有关ioctl()ifreq 和相关内容的任何指南或文档,那就太好了。我尝试在网上搜索,但找不到确切的来源。

标签: c linux network-programming ioctl


【解决方案1】:

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

rtnetlink 的优点是它支持每个设备多个地址,并且可以提供更多信息,因为它更具动态性,并且可以做很多花哨的事情。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-09
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多