socket-util: Replace sockaddr length macros with functions

There's no need for these to be macros, let's just make them regular
functions instead.
This commit is contained in:
Daan De Meyer
2025-05-02 09:41:41 +02:00
parent 256c4203f9
commit a0233fcd86
21 changed files with 78 additions and 81 deletions
+48
View File
@@ -4,6 +4,7 @@
#include <errno.h>
#include <limits.h>
#include <linux/if.h>
#include <linux/if_arp.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/ip.h>
@@ -1350,6 +1351,53 @@ void* cmsg_find_and_copy_data(struct msghdr *mh, int level, int type, void *buf,
return memcpy_safe(buf, CMSG_DATA(cmsg), buf_len);
}
size_t sockaddr_ll_len(const struct sockaddr_ll *sa) {
/* Certain hardware address types (e.g Infiniband) do not fit into sll_addr
* (8 bytes) and run over the structure. This function returns the correct size that
* must be passed to kernel. */
assert(sa->sll_family == AF_PACKET);
size_t mac_len = sizeof(sa->sll_addr);
if (be16toh(sa->sll_hatype) == ARPHRD_ETHER)
mac_len = MAX(mac_len, (size_t) ETH_ALEN);
if (be16toh(sa->sll_hatype) == ARPHRD_INFINIBAND)
mac_len = MAX(mac_len, (size_t) INFINIBAND_ALEN);
return offsetof(struct sockaddr_ll, sll_addr) + mac_len;
}
size_t sockaddr_un_len(const struct sockaddr_un *sa) {
/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
assert(sa->sun_family == AF_UNIX);
return offsetof(struct sockaddr_un, sun_path) +
(sa->sun_path[0] == 0 ?
1 + strnlen(sa->sun_path+1, sizeof(sa->sun_path)-1) :
strnlen(sa->sun_path, sizeof(sa->sun_path))+1);
}
size_t sockaddr_len(const union sockaddr_union *sa) {
switch (sa->sa.sa_family) {
case AF_INET:
return sizeof(struct sockaddr_in);
case AF_INET6:
return sizeof(struct sockaddr_in6);
case AF_UNIX:
return sockaddr_un_len(&sa->un);
case AF_PACKET:
return sockaddr_ll_len(&sa->ll);
case AF_NETLINK:
return sizeof(struct sockaddr_nl);
case AF_VSOCK:
return sizeof(struct sockaddr_vm);
default:
assert_not_reached();
}
}
int socket_ioctl_fd(void) {
int fd;
+3 -54
View File
@@ -238,62 +238,11 @@ void* cmsg_find_and_copy_data(struct msghdr *mh, int level, int type, void *buf,
(size) == CMSG_ALIGN(size) ? 1 : -1]; \
}
/*
* Certain hardware address types (e.g Infiniband) do not fit into sll_addr
* (8 bytes) and run over the structure. This macro returns the correct size that
* must be passed to kernel.
*/
#define SOCKADDR_LL_LEN(sa) \
({ \
const struct sockaddr_ll *_sa = &(sa); \
size_t _mac_len = sizeof(_sa->sll_addr); \
assert(_sa->sll_family == AF_PACKET); \
if (be16toh(_sa->sll_hatype) == ARPHRD_ETHER) \
_mac_len = MAX(_mac_len, (size_t) ETH_ALEN); \
if (be16toh(_sa->sll_hatype) == ARPHRD_INFINIBAND) \
_mac_len = MAX(_mac_len, (size_t) INFINIBAND_ALEN); \
offsetof(struct sockaddr_ll, sll_addr) + _mac_len; \
})
size_t sockaddr_ll_len(const struct sockaddr_ll *sa);
/* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
#define SOCKADDR_UN_LEN(sa) \
({ \
const struct sockaddr_un *_sa = &(sa); \
assert(_sa->sun_family == AF_UNIX); \
offsetof(struct sockaddr_un, sun_path) + \
(_sa->sun_path[0] == 0 ? \
1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : \
strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \
})
size_t sockaddr_un_len(const struct sockaddr_un *sa);
#define SOCKADDR_LEN(saddr) \
({ \
const union sockaddr_union *__sa = &(saddr); \
size_t _len; \
switch (__sa->sa.sa_family) { \
case AF_INET: \
_len = sizeof(struct sockaddr_in); \
break; \
case AF_INET6: \
_len = sizeof(struct sockaddr_in6); \
break; \
case AF_UNIX: \
_len = SOCKADDR_UN_LEN(__sa->un); \
break; \
case AF_PACKET: \
_len = SOCKADDR_LL_LEN(__sa->ll); \
break; \
case AF_NETLINK: \
_len = sizeof(struct sockaddr_nl); \
break; \
case AF_VSOCK: \
_len = sizeof(struct sockaddr_vm); \
break; \
default: \
assert_not_reached(); \
} \
_len; \
})
size_t sockaddr_len(const union sockaddr_union *sa);
int socket_ioctl_fd(void);