On Sun, Feb 05, 2023 at 04:28:36PM +0100, Alejandro Colomar wrote:
> As discussed before, and Bastien and I seem to agree, ideally we should
> define the following types:
>
> struct sockaddr_storage {
> union {
> struct {
> sa_family_t ss_family;
> };
> struct sockaddr_in sin;
> struct sockaddr_in6 sin6;
> struct sockaddr_un sun;
> // ...
> };
> };
AFAIK this is not permitted because of namespace. sys/socket.h is not
permitted to expose sockaddr_{in,in6,un}. And if you defined
differently-tagged structures with the same contents, it would not do
any good; accessing the members with the wrong-tagged struct type
would still be UB.
Really, there is no action needed here. Nothing is wrong on libc's
side. The problem is just that the type is *not useful for anything*
and should not be used except in the context of sizeof, which is
purely a documentation issue.
> struct [[deprecated]] sockaddr {
> sa_family_t sa_family;
> };
>
> union [[gnu::transparent_union]] sockaddr_ptr {
> struct sockaddr_storage *ss;
> struct sockaddr *sa;
> };
>
> And then we could define APIs like:
>
> int bind(int sockfd, const union sockaddr_ptr *addr, socklen_t len);
You cannot just change APIs because you wish they were different.
Ideally bind, etc. would just take void *, which is what the struct
sockaddr * is being used as. But they don't, so callers have to cast.
It's ugly but it's really not a big deal. Much less of a big deal than
breaking the interface because you think it would look prettier if it
had been done differently.
Rich