From: Daan De Meyer Date: Wed, 30 Apr 2025 20:09:37 +0000 (+0200) Subject: socket-util: Replace sockaddr length macros with functions X-Git-Tag: v258-rc1~701^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a0233fcd86b8ccdb5104cd4a37b0ee2cc9947654;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index b86b67e783f..61a77370eb4 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index d0aedb524e8..a69277c6396 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -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); diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c index e9e500623d3..207f68a5e6e 100644 --- a/src/libsystemd-network/dhcp-network.c +++ b/src/libsystemd-network/dhcp-network.c @@ -136,7 +136,7 @@ static int _bind_raw_socket( /* We may overflow link->ll. link->ll_buffer ensures we have enough space. */ memcpy(link->ll.sll_addr, bcast_addr->bytes, bcast_addr->length); - r = bind(s, &link->sa, SOCKADDR_LL_LEN(link->ll)); + r = bind(s, &link->sa, sockaddr_ll_len(&link->ll)); if (r < 0) return -errno; @@ -258,7 +258,7 @@ int dhcp_network_send_raw_socket( assert(packet); assert(len > 0); - if (sendto(s, packet, len, 0, &link->sa, SOCKADDR_LL_LEN(link->ll)) < 0) + if (sendto(s, packet, len, 0, &link->sa, sockaddr_ll_len(&link->ll)) < 0) return -errno; return 0; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index db8c19e4516..bbde421ebca 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -1030,7 +1030,7 @@ static int parse_container_unix_address(sd_bus *b, const char **p, char **guid) /* Note that we use the old /var/run prefix here, to increase compatibility with really old containers */ .sun_path = "/var/run/dbus/system_bus_socket", }; - b->sockaddr_size = SOCKADDR_UN_LEN(b->sockaddr.un); + b->sockaddr_size = sockaddr_un_len(&b->sockaddr.un); b->is_local = false; return 0; diff --git a/src/libsystemd/sd-journal/journal-send.c b/src/libsystemd/sd-journal/journal-send.c index 012592b4cd2..d043e1882d0 100644 --- a/src/libsystemd/sd-journal/journal-send.c +++ b/src/libsystemd/sd-journal/journal-send.c @@ -230,7 +230,7 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) { }; struct msghdr mh = { .msg_name = (struct sockaddr*) &sa.sa, - .msg_namelen = SOCKADDR_UN_LEN(sa.un), + .msg_namelen = sockaddr_un_len(&sa.un), }; ssize_t k; bool have_syslog_identifier = false; diff --git a/src/libsystemd/sd-resolve/test-resolve.c b/src/libsystemd/sd-resolve/test-resolve.c index 829e13ea69d..7a599925f4c 100644 --- a/src/libsystemd/sd-resolve/test-resolve.c +++ b/src/libsystemd/sd-resolve/test-resolve.c @@ -84,7 +84,7 @@ int main(int argc, char *argv[]) { /* Make an address -> name query */ sa.in.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71"); - r = sd_resolve_getnameinfo(resolve, &q2, &sa.sa, SOCKADDR_LEN(sa), 0, SD_RESOLVE_GET_BOTH, getnameinfo_handler, NULL); + r = sd_resolve_getnameinfo(resolve, &q2, &sa.sa, sockaddr_len(&sa), 0, SD_RESOLVE_GET_BOTH, getnameinfo_handler, NULL); if (r < 0) log_error_errno(r, "sd_resolve_getnameinfo(): %m"); diff --git a/src/mountfsd/mountfsd-manager.c b/src/mountfsd/mountfsd-manager.c index 9b10f15937f..0d24e2d696a 100644 --- a/src/mountfsd/mountfsd-manager.c +++ b/src/mountfsd/mountfsd-manager.c @@ -256,7 +256,7 @@ int manager_startup(Manager *m) { (void) sockaddr_un_unlink(&sockaddr.un); WITH_UMASK(0000) - if (bind(m->listen_fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0) + if (bind(m->listen_fd, &sockaddr.sa, sockaddr_un_len(&sockaddr.un)) < 0) return log_error_errno(errno, "Failed to bind socket: %m"); if (listen(m->listen_fd, SOMAXCONN) < 0) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index b1eeef335df..dd9649d71e0 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -3660,7 +3660,7 @@ static int setup_notify_child(const void *directory) { (void) sockaddr_un_unlink(&sa.un); WITH_UMASK(0577) { /* only set "w" bit, which is all that's necessary for connecting from the container */ - r = bind(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); + r = bind(fd, &sa.sa, sockaddr_un_len(&sa.un)); if (r < 0) return log_error_errno(errno, "bind(" NSPAWN_NOTIFY_SOCKET_PATH ") failed: %m"); } diff --git a/src/nsresourced/nsresourced-manager.c b/src/nsresourced/nsresourced-manager.c index 9849d63b0a0..ee52f09f84f 100644 --- a/src/nsresourced/nsresourced-manager.c +++ b/src/nsresourced/nsresourced-manager.c @@ -445,7 +445,7 @@ static int manager_make_listen_socket(Manager *m) { (void) sockaddr_un_unlink(&sockaddr.un); WITH_UMASK(0000) - if (bind(m->listen_fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0) + if (bind(m->listen_fd, &sockaddr.sa, sockaddr_un_len(&sockaddr.un)) < 0) return log_error_errno(errno, "Failed to bind socket: %m"); r = mkdir_p("/run/systemd/userdb", 0755); diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 36b7f74813a..5996d9bcc6a 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -1274,7 +1274,7 @@ int dns_server_is_accessible(DnsServer *s) { return r; } - r = RET_NERRNO(connect(fd, &sa.sa, SOCKADDR_LEN(sa))); + r = RET_NERRNO(connect(fd, &sa.sa, sockaddr_len(&sa))); if (!IN_SET(r, 0, -ENETUNREACH, diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c index 41c31c5a415..03c6cd7cf4d 100644 --- a/src/resolve/resolved-dns-stream.c +++ b/src/resolve/resolved-dns-stream.c @@ -572,7 +572,7 @@ int dns_stream_new( if (tfo_address) { s->tfo_address = *tfo_address; - s->tfo_salen = SOCKADDR_LEN(*tfo_address); + s->tfo_salen = sockaddr_len(tfo_address); } *ret = TAKE_PTR(s); diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 08b35690ba8..053365f7fa6 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -1322,7 +1322,7 @@ static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int ty log_debug_errno(r, "Failed to enable fragment size reception, ignoring: %m"); } - r = RET_NERRNO(bind(fd, &sa.sa, SOCKADDR_LEN(sa))); + r = RET_NERRNO(bind(fd, &sa.sa, sockaddr_len(&sa))); if (r < 0) goto fail; diff --git a/src/resolve/test-resolved-stream.c b/src/resolve/test-resolved-stream.c index ef5c2763ec1..b5e8ce9f955 100644 --- a/src/resolve/test-resolved-stream.c +++ b/src/resolve/test-resolved-stream.c @@ -111,7 +111,7 @@ static void *tcp_dns_server(void *p) { assert_se((bindfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)) >= 0); assert_se(setsockopt(bindfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) >= 0); - assert_se(bind(bindfd, &server_address.sa, SOCKADDR_LEN(server_address)) >= 0); + assert_se(bind(bindfd, &server_address.sa, sockaddr_len(&server_address)) >= 0); assert_se(listen(bindfd, 1) >= 0); assert_se((acceptfd = accept(bindfd, NULL, NULL)) >= 0); server_handle(acceptfd); @@ -246,7 +246,7 @@ static void test_dns_stream(bool tls) { assert_se((clientfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)) >= 0); for (int i = 0; i < 100; i++) { - r = connect(clientfd, &server_address.sa, SOCKADDR_LEN(server_address)); + r = connect(clientfd, &server_address.sa, sockaddr_len(&server_address)); if (r >= 0) break; usleep_safe(EVENT_TIMEOUT_USEC / 100); diff --git a/src/shared/local-addresses.c b/src/shared/local-addresses.c index 1874bcbcee1..85269d4d709 100644 --- a/src/shared/local-addresses.c +++ b/src/shared/local-addresses.c @@ -680,16 +680,16 @@ int local_outbounds( * make use of the binding and return it. Hence, let's not unnecessarily fail early here: we * can still easily detect if the auto-binding worked or not, by comparing the bound IP * address with zero — which we do below. */ - if (connect(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) + if (connect(fd, &sa.sa, sockaddr_len(&sa)) < 0) log_debug_errno(errno, "Failed to connect SOCK_DGRAM socket to gateway, ignoring: %m"); /* Let's now read the socket address of the socket. A routing decision should have been * made. Let's verify that and use the data. */ - salen = SOCKADDR_LEN(sa); + salen = sockaddr_len(&sa); if (getsockname(fd, &sa.sa, &salen) < 0) return -errno; assert(sa.sa.sa_family == i->family); - assert(salen == SOCKADDR_LEN(sa)); + assert(salen == sockaddr_len(&sa)); switch (i->family) { diff --git a/src/shared/plymouth-util.c b/src/shared/plymouth-util.c index 8ef52d90c88..72f282f9bd7 100644 --- a/src/shared/plymouth-util.c +++ b/src/shared/plymouth-util.c @@ -17,7 +17,7 @@ int plymouth_connect(int flags) { if (fd < 0) return -errno; - if (connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) + if (connect(fd, &sa.sa, sockaddr_un_len(&sa.un)) < 0) return -errno; return TAKE_FD(fd); diff --git a/src/ssh-generator/ssh-proxy.c b/src/ssh-generator/ssh-proxy.c index 3c21f8d8981..86db2e1cde8 100644 --- a/src/ssh-generator/ssh-proxy.c +++ b/src/ssh-generator/ssh-proxy.c @@ -37,7 +37,7 @@ static int process_vsock_cid(unsigned cid, const char *port) { if (fd < 0) return log_error_errno(errno, "Failed to allocate AF_VSOCK socket: %m"); - if (connect(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) + if (connect(fd, &sa.sa, sockaddr_len(&sa)) < 0) return log_error_errno(errno, "Failed to connect to vsock:%u:%u: %m", sa.vm.svm_cid, sa.vm.svm_port); /* OpenSSH wants us to send a single byte along with the file descriptor, hence do so */ diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index 97eeb59afbb..731a37caf1d 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -928,7 +928,7 @@ TEST(read_full_file_socket) { assert_se(sockaddr_un_set_path(&sa.un, j) >= 0); - assert_se(bind(listener, &sa.sa, SOCKADDR_UN_LEN(sa.un)) >= 0); + assert_se(bind(listener, &sa.sa, sockaddr_un_len(&sa.un)) >= 0); assert_se(listen(listener, 1) >= 0); /* Make sure the socket doesn't fit into a struct sockaddr_un, but we can still access it */ diff --git a/src/test/test-mempress.c b/src/test/test-mempress.c index 6bbc485de6d..6f4e6586161 100644 --- a/src/test/test-mempress.c +++ b/src/test/test-mempress.c @@ -86,7 +86,7 @@ TEST(fake_pressure) { socket_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); assert_se(socket_fd >= 0); assert_se(sockaddr_un_set_path(&sa.un, k) >= 0); - assert_se(bind(socket_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) >= 0); + assert_se(bind(socket_fd, &sa.sa, sockaddr_un_len(&sa.un)) >= 0); assert_se(listen(socket_fd, 1) >= 0); /* Ideally we'd just allocate this on the stack, but AddressSanitizer doesn't like it if threads diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c index 63bbb1d1d27..acf11f3639d 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -134,8 +134,8 @@ TEST(sockaddr_un_len) { .sun_path = "\0foobar", }; - assert_se(SOCKADDR_UN_LEN(fs) == offsetof(struct sockaddr_un, sun_path) + strlen(fs.sun_path) + 1); - assert_se(SOCKADDR_UN_LEN(abstract) == offsetof(struct sockaddr_un, sun_path) + 1 + strlen(abstract.sun_path + 1)); + assert_se(sockaddr_un_len(&fs) == offsetof(struct sockaddr_un, sun_path) + strlen(fs.sun_path) + 1); + assert_se(sockaddr_un_len(&abstract) == offsetof(struct sockaddr_un, sun_path) + 1 + strlen(abstract.sun_path + 1)); } TEST(in_addr_is_multicast) { @@ -564,14 +564,14 @@ TEST(sockaddr_un_set_path) { fd1 = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); assert_se(fd1 >= 0); - assert_se(bind(fd1, &sa.sa, SOCKADDR_LEN(sa)) >= 0); + assert_se(bind(fd1, &sa.sa, sockaddr_len(&sa)) >= 0); assert_se(listen(fd1, 1) >= 0); sh = unlink_and_free(sh); /* remove temporary symlink */ fd2 = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); assert_se(fd2 >= 0); - assert_se(connect(fd2, &sa.sa, SOCKADDR_LEN(sa)) < 0); + assert_se(connect(fd2, &sa.sa, sockaddr_len(&sa)) < 0); assert_se(errno == ENOENT); /* we removed the symlink, must fail */ free(j); @@ -581,7 +581,7 @@ TEST(sockaddr_un_set_path) { assert_se(fd3 > 0); assert_se(sockaddr_un_set_path(&sa.un, FORMAT_PROC_FD_PATH(fd3)) >= 0); /* connect via O_PATH instead, circumventing 108ch limit */ - assert_se(connect(fd2, &sa.sa, SOCKADDR_LEN(sa)) >= 0); + assert_se(connect(fd2, &sa.sa, sockaddr_len(&sa)) >= 0); } TEST(getpeerpidref) { diff --git a/src/udev/udev-ctrl.c b/src/udev/udev-ctrl.c index 42e42ee3362..1914bf7929f 100644 --- a/src/udev/udev-ctrl.c +++ b/src/udev/udev-ctrl.c @@ -73,7 +73,7 @@ int udev_ctrl_new_from_fd(UdevCtrl **ret, int fd) { .sun_path = "/run/udev/control", }; - uctrl->addrlen = SOCKADDR_UN_LEN(uctrl->saddr.un); + uctrl->addrlen = sockaddr_un_len(&uctrl->saddr.un); *ret = TAKE_PTR(uctrl); return 0; diff --git a/src/userdb/userdbd-manager.c b/src/userdb/userdbd-manager.c index 63a53f0e00e..e30ec8ed757 100644 --- a/src/userdb/userdbd-manager.c +++ b/src/userdb/userdbd-manager.c @@ -287,7 +287,7 @@ static int manager_make_listen_socket(Manager *m) { (void) sockaddr_un_unlink(&sockaddr.un); WITH_UMASK(0000) - if (bind(m->listen_fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0) + if (bind(m->listen_fd, &sockaddr.sa, sockaddr_un_len(&sockaddr.un)) < 0) return log_error_errno(errno, "Failed to bind socket: %m"); FOREACH_STRING(alias,