mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 08:56:15 +09:00
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:
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user