`ifreq`结构中的IPv6地址问题

时间:2011-04-01 17:01:39

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

我正在使用以下代码:

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

ifr_addr的类型为struct sockaddr,为方便起见,请在此处报告:

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

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

我哪里错了?

TIA, 克里斯

2 个答案:

答案 0 :(得分:3)

幸运的是,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 #defineifr_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中的任何有效地址并使其有效。

答案 1 :(得分:0)

struct sockaddr内使用struct ifreq的平台也有一个IPv6友好版本struct lifreq,使用struct sockaddr_storage代替Solaris,其他平台如Linux和AIX已经使用结构越久。