为什么glibc2.23更改struct sockaddr_storage?

时间:2017-08-28 07:10:00

标签: c sockets ipv6 glibc

我将git日志检查为https://patchwork.sourceware.org/patch/12453/。此修改似乎解决了特定平台上的问题。 但我不明白为什么要在struct sockaddr_storage中交换__ss_align和__ss_padding。 我正在开发的Qualcomm平台有如下大量的类型。

struct sockaddr_storage prefix_addr

(struct sockaddr_in6 *)&(prefix_addr)->sin6_addr.s6_addr 

在我们的Cortex A7平台上,struct alignment如下:

在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地址错误。

2 个答案:

答案 0 :(得分:1)

请参阅Florian的回复:

  

在09/01/2017 12:07 PM,honan li写道:

     
    

定义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));       ...     }

  
     

目前可在此公开:

     

https://github.com/Bigcountry907/HTC_a13_vzw_Kernel/blob/master/vendor/qcom/proprietary/data/mobileap_v2/server/src/QCMAP_ConnectionManager.cpp#L3658

     

我希望应用程序可以这样做:

     

struct sockaddr_in6 sin6; memset(& sin6,0,sizeof(sin6));
  sin6.sin6_family = AF_INET6; memcpy(& sin6.sin6_addr,RTA_DATA   (rta),sizeof(sin6.sin6_addr));的memcpy   (& ipv6_prefix_info-> prefix_addr,& sin6,sizeof(sin6));

     

这可以避免任何别名问题和对内部的依赖   struct sockaddr_storage(仅用于分配a的方式)   通用结构sockaddr足够大小和对齐)。它也是   初始化套接字地址的其他组件(例如   端口号和流标签)。

     

谢谢,Florian

另请参阅: https://books.google.com.hk/books?id=ptSC4LpwGA0C&pg=PA72&lpg=PA72&dq=alignment+sufficient&source=bl&ots=Kt0BQhjiMt&sig=HTUbm2bzVNSoMxNX98EMzORFc30&hl=zh-CN&sa=X&ved=0ahUKEwiP78iMoovWAhVLipQKHYFdCxcQ6AEIQzAF#v=onepage&q=alignment%20sufficient&f=false

结论是高通公司对sockaddr_storage的使用是不正确的。

答案 1 :(得分:0)

我不确定这是glibc中产生对齐警告的变化:此更改对您显示的源代码没有影响。

相反,我认为高通正在使用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);

这可能会避免对齐警告。