为什么 glibc2.23 改变 struct sockaddr_storage?
Why glibc2.23 change struct sockaddr_storage?
我检查 git 日志为 https://patchwork.sourceware.org/patch/12453/。此修改似乎解决了特定平台上的问题。
但是我不明白为什么要在 struct sockaddr_storage 中交换 __ss_align 和 __ss_padding。
我现在正在开发的高通平台有很多类型转换如下。
struct sockaddr_storage prefix_addr
(struct sockaddr_in6 *)&(prefix_addr)->sin6_addr.s6_addr
在我们的Cortex A7平台上,结构对齐方式如下:
glibc2.23 之前:
struct sockaddr_in6
{
sin6_family; //0th byte
sin6_port; //2nd byte
sin6_flowinfo; //4th byte
sin6_addr; //8th byte
};
struct sockaddr_storage
{
ss_family; //0th byte
__ss_align; //4th byte
__ss_padding; //8th byte
};
glibc2.23之后:
struct sockaddr_storage
{
ss_family; //0th byte
__ss_padding; //2nd byte
__ss_align; //124th byte
};
glibc 更改了 struct sockaddr_storage,但 struct sockaddr_in6 未更改,因此此修改会在我们的平台上导致许多对齐问题,从而导致获取 IPV6 地址错误。
我不确定这是 glibc 中生成对齐警告的更改:此更改对您显示的源代码没有影响。
相反,我认为 Qualcomm 正在使用 clang,并且以 clang 4.x 开头,我看到了一个新的对齐警告生成 误报关于对齐的警告,具体取决于您编写代码的方式:-Waddress-of-packed-member
.
您应该检查您使用的 clang 版本是否已更改,因为 glibc 已更改。如果是这种情况,这肯定可以解释你的问题。
使用临时变量使这些警告消失。
而不是像这样打电话:
my_function(((struct sockaddr_in6 *)&prefix_addr)->sin6_addr.s6_addr)
随便写:
struct sockaddr_in6 p = *(struct sockaddr_in6 *) &prefix_addr;
my_function(p.sin6_addr.s6_addr);
这可以避免对齐警告。
请参考Florian的回复:
On 09/01/2017 12:07 PM, honan li wrote:
define SASTORAGE_DATA(addr) (addr).__ss_padding
typedef struct qcmap_cm_nl_prefix_info_s {
boolean prefix_info_valid;
unsigned char prefix_len;
unsigned int mtu;
struct sockaddr_storage prefix_addr;
struct ifa_cacheinfo cache_info;
} qcmap_cm_nl_prefix_info_t;
void QCMAP_Backhaul::GetIPV6PrefixInfo(char *devname,
qcmap_cm_nl_prefix_info_t
*ipv6_prefix_info)
{
struct sockaddr_in6 *sin6 = NULL;
...
sin6 = (struct sockaddr_in6 *)&ipv6_prefix_info->prefix_addr;
memcpy(SASTORAGE_DATA(ipv6_prefix_info->prefix_addr),
RTA_DATA(rta),
sizeof(sin6->sin6_addr));
...
}
目前在此处公开可用:
我希望应用程序做这样的事情:
结构sockaddr_in6sin6; memset (&sin6, 0, sizeof (sin6));
sin6.sin6_family = AF_INET6; memcpy (&sin6.sin6_addr, RTA_DATA
(rta), sizeof (sin6.sin6_addr));内存文件
(&ipv6_prefix_info->prefix_addr, &sin6, sizeof (sin6));
这避免了任何别名问题和对内部结构的依赖
struct sockaddr_storage (这只是作为一种分配一个
具有足够大小和对齐方式的通用结构 sockaddr)。它也是
初始化套接字地址的其他组件(例如
端口号和流标签)。
谢谢,弗洛里安
结论是高通对sockaddr_storage的使用是不正确的。
我检查 git 日志为 https://patchwork.sourceware.org/patch/12453/。此修改似乎解决了特定平台上的问题。 但是我不明白为什么要在 struct sockaddr_storage 中交换 __ss_align 和 __ss_padding。 我现在正在开发的高通平台有很多类型转换如下。
struct sockaddr_storage prefix_addr
(struct sockaddr_in6 *)&(prefix_addr)->sin6_addr.s6_addr
在我们的Cortex A7平台上,结构对齐方式如下:
glibc2.23 之前:
struct sockaddr_in6
{
sin6_family; //0th byte
sin6_port; //2nd byte
sin6_flowinfo; //4th byte
sin6_addr; //8th byte
};
struct sockaddr_storage
{
ss_family; //0th byte
__ss_align; //4th byte
__ss_padding; //8th byte
};
glibc2.23之后:
struct sockaddr_storage
{
ss_family; //0th byte
__ss_padding; //2nd byte
__ss_align; //124th byte
};
glibc 更改了 struct sockaddr_storage,但 struct sockaddr_in6 未更改,因此此修改会在我们的平台上导致许多对齐问题,从而导致获取 IPV6 地址错误。
我不确定这是 glibc 中生成对齐警告的更改:此更改对您显示的源代码没有影响。
相反,我认为 Qualcomm 正在使用 clang,并且以 clang 4.x 开头,我看到了一个新的对齐警告生成 误报关于对齐的警告,具体取决于您编写代码的方式:-Waddress-of-packed-member
.
您应该检查您使用的 clang 版本是否已更改,因为 glibc 已更改。如果是这种情况,这肯定可以解释你的问题。
使用临时变量使这些警告消失。
而不是像这样打电话:
my_function(((struct sockaddr_in6 *)&prefix_addr)->sin6_addr.s6_addr)
随便写:
struct sockaddr_in6 p = *(struct sockaddr_in6 *) &prefix_addr;
my_function(p.sin6_addr.s6_addr);
这可以避免对齐警告。
请参考Florian的回复:
On 09/01/2017 12:07 PM, honan li wrote:
define SASTORAGE_DATA(addr) (addr).__ss_padding
typedef struct qcmap_cm_nl_prefix_info_s { boolean prefix_info_valid; unsigned char prefix_len; unsigned int mtu; struct sockaddr_storage prefix_addr; struct ifa_cacheinfo cache_info; } qcmap_cm_nl_prefix_info_t;
void QCMAP_Backhaul::GetIPV6PrefixInfo(char *devname, qcmap_cm_nl_prefix_info_t *ipv6_prefix_info) { struct sockaddr_in6 *sin6 = NULL;
...
sin6 = (struct sockaddr_in6 *)&ipv6_prefix_info->prefix_addr; memcpy(SASTORAGE_DATA(ipv6_prefix_info->prefix_addr), RTA_DATA(rta), sizeof(sin6->sin6_addr)); ... }
目前在此处公开可用:
我希望应用程序做这样的事情:
结构sockaddr_in6sin6; memset (&sin6, 0, sizeof (sin6));
sin6.sin6_family = AF_INET6; memcpy (&sin6.sin6_addr, RTA_DATA (rta), sizeof (sin6.sin6_addr));内存文件 (&ipv6_prefix_info->prefix_addr, &sin6, sizeof (sin6));这避免了任何别名问题和对内部结构的依赖 struct sockaddr_storage (这只是作为一种分配一个 具有足够大小和对齐方式的通用结构 sockaddr)。它也是 初始化套接字地址的其他组件(例如 端口号和流标签)。
谢谢,弗洛里安
结论是高通对sockaddr_storage的使用是不正确的。