Why is the sockaddr_storage structure defined as a way to define it?

The following is a definition of the sockaddr_storage structure ( rfc2553 ). According to rfc2553, sockaddr_storage should be aligned with a 64-bit border, and it should be able to hold both sockaddr_in and sockaddr_in6. In addition, it must have the __ss_family attribute. The remaining fields are determined by the implementation.

#define _SS_MAXSIZE 128 /* Implementation specific max size */ #define _SS_ALIGNSIZE (sizeof (int64_t)) /* Implementation specific desired alignment */ /* * Definitions used for sockaddr_storage structure paddings design. */ #define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (sa_family_t)) #define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t)+ _SS_PAD1SIZE + _SS_ALIGNSIZE)) struct sockaddr_storage { sa_family_t __ss_family; /* address family */ /* Following fields are implementation specific */ char __ss_pad1[_SS_PAD1SIZE]; /* 6 byte pad, this is to make implementation /* specific pad up to alignment field that */ /* follows explicit in the data structure */ int64_t __ss_align; /* field to force desired structure */ /* storage alignment */ char __ss_pad2[_SS_PAD2SIZE]; /* 112 byte pad to achieve desired size, */ /* _SS_MAXSIZE value minus size of ss_family */ /* __ss_pad1, __ss_align fields is 112 */ }; 

My question is why sockaddr_storage is defined as the method above? Why can't it be listed below?

 struct sockaddr_storage { sa_family_t __ss_family; /* address family */ char __ss_pad[_SS_MAXSIZE - sizeof(sa_family_t) ]; //will there be any alignment issue here? }; 
+7
c unix sockets
source share
2 answers

Your suggested alternative will not align the entire structure to the 8-byte (64-bit) border that you mentioned as RFC2553 requirement.

In general, the structure takes on the strictest alignment required by any of its members. Since sa_family_t is probably u16_t , which requires only 2-byte alignment and char array requires no more than 1-byte alignment, the alternative you suggest requires only 2-byte alignment. (The compiler would probably give at least 4- and possibly 8-byte alignment anyway, but you cannot be sure.)

The actual definition style is an attempt to make sure that each byte in the structure is part of some named field, i.e. that the compiler does not insert any fields between fields. This is necessary (sort of), so _SS_PAD2SIZE has a value that can be calculated in terms of the sizes of all the other members.

However, I find this definition rather complicated. I'm sure the following works just as well, and it is a little easier to understand:

 struct sockaddr_storage { union { sa_family_t u_family; uint64_t u_pad[_SS_MAXSIZE / sizeof(uint64_t)]; } __ss_u; # define __ss_family __ss_u.u_family }; 

Here, the union receives the requirements for alignment of its strictly strictly aligned element, which then extends to the covering structure. Please note that in this version I have only one required field (although it is buried in the union) and one filling array, which is the exact size, I want the whole structure to be. The only slightly difficult part is defining the __ss_family macro. It is possible that the macro trick does not strictly comply with the RFC requirements, but there will be few (if any) ways to notice the difference.

+5
source share

So, from what you guys say, it seems that

but.

 int64_t __ss_align; 

causes alignment of the structure with a 64-bit border.

b. __ss_pad1 ensures that ss_family is on the 64-bit border immediately before __ss_align

from. __ss_pad2 provides the required overall size.

I read the code above at http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/socket.h.html#tag_13_61 . From what is written there, it seems that the value of _SS_MAXSIZE should be determined by the developer.

In the code mentioned by Dale, division by

uint64_t u_pad[_SS_MAXSIZE / sizeof(uint64_t)]

will cause a float which will then be truncated, which will cause the structure to be smaller than the required size (_SS_MAXSIZE).

:)

0
source share

All Articles