【问题标题】:IPv6 address problem in `ifreq` struct`ifreq` 结构中的 IPv6 地址问题
【发布时间】:2011-07-27 20:29:18
【问题描述】:

我正在使用以下代码:

struct sockaddr_in6 *sin;
struct ifreq ifr;
sin = (struct sockaddr_in6 *)&ifr.ifr_addr;

ifr_addrstruct sockaddr 类型,为方便起见,在下面报告:

struct sockaddr {
        sa_family_t     sa_family;      /* address family, AF_xxx       */
        char            sa_data[14];    /* 14 bytes of protocol address */
};

鉴于只有 14 个字节可用,我应该如何在 ifr_addr 字段中输入 IPv6 地址(通过 sin->sin6_addr.s6_addr)?

我哪里错了?

TIA, 克里斯

【问题讨论】:

    标签: c++ c sockets network-programming ipv6


    【解决方案1】:

    幸运的是,struct ifreq 被声明为在结构末尾的联合中包含地址:

    struct ifreq
      {
    
    
        union
          {
     char ifrn_name[16];
          } ifr_ifrn;
    
        union
          {
     struct sockaddr ifru_addr;
     struct sockaddr ifru_dstaddr;
     struct sockaddr ifru_broadaddr;
     struct sockaddr ifru_netmask;
     struct sockaddr ifru_hwaddr;
     short int ifru_flags;
     int ifru_ivalue;
     int ifru_mtu;
     struct ifmap ifru_map;
     char ifru_slave[16];
     char ifru_newname[16];
     __caddr_t ifru_data;
          } ifr_ifru;
      };
    

    请注意,以上是gcc -E 的结果,因此所有预处理器的内容都已扩展。还要注意ifr_addr#defined 是ifr_ifru.ifru_addr

    这意味着从技术上讲,您可以在结构末尾分配字节来保存地址。

    在我看来,这是非常草率的。应该声明联合以保存类型为sockaddr_storage 的值以及其他所有值。然后结构大小将足以容纳任何地址。

    如果你想声明你自己的大小合适的结构,你可以很容易地使用,只需这样做:

    union my_ifreq {
        struct ifreq sys_ifreq;
        struct {
            char name_pad[IFNAMSIZ];
            struct sockaddr_storage addr;
        } padding;
    };
    

    然后您将拥有一个始终具有足够存储空间的结构,您可以将任何有效地址填充到 sys_ifreq.ifr_addr 中并让它工作。

    【讨论】:

    • 很好的解释。非常感谢!我什至没有发现ifru_data 字段。但是,我仍然对如何使用它感到困惑。我的意思是,我能做的是sin = (struct sockaddr_in6 *)&ifr.padding.addr;。但是,当我绕过结构时,代码如何知道那个位置有一个地址?
    • @Jir:就这样做吧:sin = (struct sockaddr_in6 *)(&ifr.sys_ifreq.ifr_addr)padding 部分只是为了确保联合占用足够的空间并且不应该实际使用。大概您会将sin->sin6_family 字段设置为AF_INET6,这足以让系统知道那里有一个完整的IPv6 地址。如果您注意到,在所有不同 sockaddr 类型的开头,family 字段都是相同的。
    • 现在我明白了!这就是为什么您将my_ifreq 定义为一个联合,而不仅仅是一个结构!感谢您再次彻底解释细节!
    【解决方案2】:

    struct ifreq 中使用struct sockaddr 的平台也有一个使用struct sockaddr_storage 的IPv6 友好版本struct lifreq,例如Solaris,其他平台如Linux 和AIX 已经使用更长的结构。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    • 2021-09-01
    • 2012-07-12
    • 2018-09-23
    • 1970-01-01
    相关资源
    最近更新 更多