我正在使用以下代码:
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, 克里斯
答案 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
#define
为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
中的任何有效地址并使其有效。
答案 1 :(得分:0)
在struct sockaddr
内使用struct ifreq
的平台也有一个IPv6友好版本struct lifreq
,使用struct sockaddr_storage
代替Solaris,其他平台如Linux和AIX已经使用结构越久。