Merge pull request #14736 from opensourcerouting/transparent-sockunion

lib: create a transparent union `sockunion`
This commit is contained in:
Donald Sharp 2023-11-06 08:09:48 -05:00 committed by GitHub
commit b66dc0909e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 22 deletions

View File

@ -424,10 +424,10 @@ _Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8,
* type.) * type.)
*/ */
#ifndef __cplusplus #ifndef __cplusplus
#define prefixtype(uname, typename, fieldname) typename *fieldname; #define uniontype(uname, typename, fieldname) typename *fieldname;
#define TRANSPARENT_UNION __attribute__((transparent_union)) #define TRANSPARENT_UNION __attribute__((transparent_union))
#else #else
#define prefixtype(uname, typename, fieldname) \ #define uniontype(uname, typename, fieldname) \
typename *fieldname; \ typename *fieldname; \
uname(typename *x) \ uname(typename *x) \
{ \ { \

View File

@ -286,23 +286,25 @@ struct prefix_sg {
struct in_addr grp; struct in_addr grp;
}; };
/* clang-format off */
union prefixptr { union prefixptr {
prefixtype(prefixptr, struct prefix, p) uniontype(prefixptr, struct prefix, p)
prefixtype(prefixptr, struct prefix_ipv4, p4) uniontype(prefixptr, struct prefix_ipv4, p4)
prefixtype(prefixptr, struct prefix_ipv6, p6) uniontype(prefixptr, struct prefix_ipv6, p6)
prefixtype(prefixptr, struct prefix_evpn, evp) uniontype(prefixptr, struct prefix_evpn, evp)
prefixtype(prefixptr, struct prefix_fs, fs) uniontype(prefixptr, struct prefix_fs, fs)
prefixtype(prefixptr, struct prefix_rd, rd) uniontype(prefixptr, struct prefix_rd, rd)
} TRANSPARENT_UNION; } TRANSPARENT_UNION;
union prefixconstptr { union prefixconstptr {
prefixtype(prefixconstptr, const struct prefix, p) uniontype(prefixconstptr, const struct prefix, p)
prefixtype(prefixconstptr, const struct prefix_ipv4, p4) uniontype(prefixconstptr, const struct prefix_ipv4, p4)
prefixtype(prefixconstptr, const struct prefix_ipv6, p6) uniontype(prefixconstptr, const struct prefix_ipv6, p6)
prefixtype(prefixconstptr, const struct prefix_evpn, evp) uniontype(prefixconstptr, const struct prefix_evpn, evp)
prefixtype(prefixconstptr, const struct prefix_fs, fs) uniontype(prefixconstptr, const struct prefix_fs, fs)
prefixtype(prefixconstptr, const struct prefix_rd, rd) uniontype(prefixconstptr, const struct prefix_rd, rd)
} TRANSPARENT_UNION; } TRANSPARENT_UNION;
/* clang-format on */
#ifndef INET_ADDRSTRLEN #ifndef INET_ADDRSTRLEN
#define INET_ADDRSTRLEN 16 #define INET_ADDRSTRLEN 16

View File

@ -7,6 +7,8 @@
#ifndef _ZEBRA_SOCKUNION_H #ifndef _ZEBRA_SOCKUNION_H
#define _ZEBRA_SOCKUNION_H #define _ZEBRA_SOCKUNION_H
#include "compiler.h"
#include "privs.h" #include "privs.h"
#include "if.h" #include "if.h"
#include <sys/un.h> #include <sys/un.h>
@ -27,8 +29,40 @@ union sockunion {
struct sockaddr_mpls smpls; struct sockaddr_mpls smpls;
struct sockaddr_rtlabel rtlabel; struct sockaddr_rtlabel rtlabel;
#endif #endif
/* sockaddr_storage is guaranteed to be larger than the others */
struct sockaddr_storage sa_storage;
}; };
/* clang-format off */
/* for functions that want to accept any sockaddr pointer without casts */
union sockaddrptr {
uniontype(sockaddrptr, union sockunion, su)
uniontype(sockaddrptr, struct sockaddr, sa)
uniontype(sockaddrptr, struct sockaddr_in, sin)
uniontype(sockaddrptr, struct sockaddr_in6, sin6)
uniontype(sockaddrptr, struct sockaddr_un, sun)
#ifdef __OpenBSD__
uniontype(sockaddrptr, struct sockaddr_mpls, smpls)
uniontype(sockaddrptr, struct sockaddr_rtlabel, rtlabel)
#endif
uniontype(sockaddrptr, struct sockaddr_storage, sa_storage)
} TRANSPARENT_UNION;
union sockaddrconstptr {
uniontype(sockaddrconstptr, const union sockunion, su)
uniontype(sockaddrconstptr, const struct sockaddr, sa)
uniontype(sockaddrconstptr, const struct sockaddr_in, sin)
uniontype(sockaddrconstptr, const struct sockaddr_in6, sin6)
uniontype(sockaddrconstptr, const struct sockaddr_un, sun)
#ifdef __OpenBSD__
uniontype(sockaddrconstptr, const struct sockaddr_mpls, smpls)
uniontype(sockaddrconstptr, const struct sockaddr_rtlabel, rtlabel)
#endif
uniontype(sockaddrconstptr, const struct sockaddr_storage, sa_storage)
} TRANSPARENT_UNION;
/* clang-format on */
enum connect_result { connect_error, connect_success, connect_in_progress }; enum connect_result { connect_error, connect_success, connect_in_progress };
/* Default address family. */ /* Default address family. */

View File

@ -33,13 +33,13 @@ typedef struct in_addr pim_addr;
#define PIM_ADDR_FUNCNAME(name) ipv4_##name #define PIM_ADDR_FUNCNAME(name) ipv4_##name
union pimprefixptr { union pimprefixptr {
prefixtype(pimprefixptr, struct prefix, p) uniontype(pimprefixptr, struct prefix, p)
prefixtype(pimprefixptr, struct prefix_ipv4, p4) uniontype(pimprefixptr, struct prefix_ipv4, p4)
} TRANSPARENT_UNION; } TRANSPARENT_UNION;
union pimprefixconstptr { union pimprefixconstptr {
prefixtype(pimprefixconstptr, const struct prefix, p) uniontype(pimprefixconstptr, const struct prefix, p)
prefixtype(pimprefixconstptr, const struct prefix_ipv4, p4) uniontype(pimprefixconstptr, const struct prefix_ipv4, p4)
} TRANSPARENT_UNION; } TRANSPARENT_UNION;
#else #else
@ -63,13 +63,13 @@ typedef struct in6_addr pim_addr;
#define PIM_ADDR_FUNCNAME(name) ipv6_##name #define PIM_ADDR_FUNCNAME(name) ipv6_##name
union pimprefixptr { union pimprefixptr {
prefixtype(pimprefixptr, struct prefix, p) uniontype(pimprefixptr, struct prefix, p)
prefixtype(pimprefixptr, struct prefix_ipv6, p6) uniontype(pimprefixptr, struct prefix_ipv6, p6)
} TRANSPARENT_UNION; } TRANSPARENT_UNION;
union pimprefixconstptr { union pimprefixconstptr {
prefixtype(pimprefixconstptr, const struct prefix, p) uniontype(pimprefixconstptr, const struct prefix, p)
prefixtype(pimprefixconstptr, const struct prefix_ipv6, p6) uniontype(pimprefixconstptr, const struct prefix_ipv6, p6)
} TRANSPARENT_UNION; } TRANSPARENT_UNION;
#endif #endif