1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <arpa/inet.h>
26 #include <netinet/ip.h>
35 #include "alloc-util.h"
38 #include "format-util.h"
42 #include "parse-util.h"
43 #include "path-util.h"
44 //#include "process-util.h"
45 #include "socket-util.h"
46 #include "string-table.h"
47 #include "string-util.h"
49 #include "user-util.h"
53 #if 0 /// UNNEEDED by elogind
55 # define IDN_FLAGS NI_IDN
60 static const char* const socket_address_type_table[] = {
61 [SOCK_STREAM] = "Stream",
62 [SOCK_DGRAM] = "Datagram",
64 [SOCK_RDM] = "ReliableDatagram",
65 [SOCK_SEQPACKET] = "SequentialPacket",
66 [SOCK_DCCP] = "DatagramCongestionControl",
69 DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
71 int socket_address_parse(SocketAddress *a, const char *s) {
80 a->type = SOCK_STREAM;
85 /* IPv6 in [x:.....:z]:p notation */
91 n = strndupa(s+1, e-s-1);
94 if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0)
95 return errno > 0 ? -errno : -EINVAL;
102 r = safe_atou(e, &u);
103 r = parse_ip_port(e, &port);
107 if (u <= 0 || u > 0xFFFF)
110 a->sockaddr.in6.sin6_family = AF_INET6;
111 a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
112 a->sockaddr.in6.sin6_port = htobe16(port);
113 a->size = sizeof(struct sockaddr_in6);
115 } else if (*s == '/') {
121 if (l >= sizeof(a->sockaddr.un.sun_path))
124 a->sockaddr.un.sun_family = AF_UNIX;
125 memcpy(a->sockaddr.un.sun_path, s, l);
126 a->size = offsetof(struct sockaddr_un, sun_path) + l + 1;
128 } else if (*s == '@') {
129 /* Abstract AF_UNIX socket */
133 if (l >= sizeof(a->sockaddr.un.sun_path) - 1)
136 a->sockaddr.un.sun_family = AF_UNIX;
137 memcpy(a->sockaddr.un.sun_path+1, s+1, l);
138 a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
140 } else if (startswith(s, "vsock:")) {
141 /* AF_VSOCK socket in vsock:cid:port notation */
142 const char *cid_start = s + STRLEN("vsock:");
145 e = strchr(cid_start, ':');
149 r = safe_atou(e+1, &u);
150 r = safe_atou(e+1, &port);
154 n = strndupa(cid_start, e - cid_start);
156 r = safe_atou(n, &a->sockaddr.vm.svm_cid);
160 a->sockaddr.vm.svm_cid = VMADDR_CID_ANY;
162 a->sockaddr.vm.svm_family = AF_VSOCK;
163 a->sockaddr.vm.svm_port = u;
164 a->sockaddr.vm.svm_port = port;
165 a->size = sizeof(struct sockaddr_vm);
172 r = safe_atou(e+1, &u);
173 r = parse_ip_port(e + 1, &port);
177 if (u <= 0 || u > 0xFFFF)
180 n = strndupa(s, e-s);
182 /* IPv4 in w.x.y.z:p notation? */
183 r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr);
188 /* Gotcha, it's a traditional IPv4 address */
189 a->sockaddr.in.sin_family = AF_INET;
190 a->sockaddr.in.sin_port = htobe16((uint16_t)u);
191 a->sockaddr.in.sin_port = htobe16(port);
192 a->size = sizeof(struct sockaddr_in);
196 if (strlen(n) > IF_NAMESIZE-1)
199 /* Uh, our last resort, an interface name */
200 idx = if_nametoindex(n);
204 a->sockaddr.in6.sin6_family = AF_INET6;
205 a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
206 a->sockaddr.in6.sin6_port = htobe16(port);
207 a->sockaddr.in6.sin6_scope_id = idx;
208 a->sockaddr.in6.sin6_addr = in6addr_any;
209 a->size = sizeof(struct sockaddr_in6);
214 r = safe_atou(s, &u);
215 r = parse_ip_port(s, &port);
219 if (u <= 0 || u > 0xFFFF)
222 if (socket_ipv6_is_supported()) {
223 a->sockaddr.in6.sin6_family = AF_INET6;
224 a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
225 a->sockaddr.in6.sin6_port = htobe16(port);
226 a->sockaddr.in6.sin6_addr = in6addr_any;
227 a->size = sizeof(struct sockaddr_in6);
229 a->sockaddr.in.sin_family = AF_INET;
230 a->sockaddr.in.sin_port = htobe16((uint16_t)u);
231 a->sockaddr.in.sin_port = htobe16(port);
232 a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
233 a->size = sizeof(struct sockaddr_in);
241 int socket_address_parse_and_warn(SocketAddress *a, const char *s) {
245 /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */
247 r = socket_address_parse(&b, s);
251 if (!socket_ipv6_is_supported() && b.sockaddr.sa.sa_family == AF_INET6) {
252 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
253 return -EAFNOSUPPORT;
260 int socket_address_parse_netlink(SocketAddress *a, const char *s) {
263 _cleanup_free_ char *sfamily = NULL;
271 if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
272 return errno > 0 ? -errno : -EINVAL;
274 family = netlink_family_from_string(sfamily);
278 a->sockaddr.nl.nl_family = AF_NETLINK;
279 a->sockaddr.nl.nl_groups = group;
282 a->size = sizeof(struct sockaddr_nl);
283 a->protocol = family;
288 int socket_address_verify(const SocketAddress *a) {
291 switch (socket_address_family(a)) {
294 if (a->size != sizeof(struct sockaddr_in))
297 if (a->sockaddr.in.sin_port == 0)
300 if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM))
306 if (a->size != sizeof(struct sockaddr_in6))
309 if (a->sockaddr.in6.sin6_port == 0)
312 if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM))
318 if (a->size < offsetof(struct sockaddr_un, sun_path))
321 if (a->size > offsetof(struct sockaddr_un, sun_path)) {
323 if (a->sockaddr.un.sun_path[0] != 0) {
327 e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
331 if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
336 if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET))
343 if (a->size != sizeof(struct sockaddr_nl))
346 if (!IN_SET(a->type, SOCK_RAW, SOCK_DGRAM))
352 if (a->size != sizeof(struct sockaddr_vm))
355 if (!IN_SET(a->type, SOCK_STREAM, SOCK_DGRAM))
361 return -EAFNOSUPPORT;
365 int socket_address_print(const SocketAddress *a, char **ret) {
371 r = socket_address_verify(a);
375 if (socket_address_family(a) == AF_NETLINK) {
376 _cleanup_free_ char *sfamily = NULL;
378 r = netlink_family_to_string_alloc(a->protocol, &sfamily);
382 r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
389 return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret);
392 bool socket_address_can_accept(const SocketAddress *a) {
396 IN_SET(a->type, SOCK_STREAM, SOCK_SEQPACKET);
399 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
403 /* Invalid addresses are unequal to all */
404 if (socket_address_verify(a) < 0 ||
405 socket_address_verify(b) < 0)
408 if (a->type != b->type)
411 if (socket_address_family(a) != socket_address_family(b))
414 switch (socket_address_family(a)) {
417 if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr)
420 if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port)
426 if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0)
429 if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
435 if (a->size <= offsetof(struct sockaddr_un, sun_path) ||
436 b->size <= offsetof(struct sockaddr_un, sun_path))
439 if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
442 if (a->sockaddr.un.sun_path[0]) {
443 if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, 0))
446 if (a->size != b->size)
449 if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
456 if (a->protocol != b->protocol)
459 if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
465 if (a->sockaddr.vm.svm_cid != b->sockaddr.vm.svm_cid)
468 if (a->sockaddr.vm.svm_port != b->sockaddr.vm.svm_port)
474 /* Cannot compare, so we assume the addresses are different */
481 bool socket_address_is(const SocketAddress *a, const char *s, int type) {
482 struct SocketAddress b;
487 if (socket_address_parse(&b, s) < 0)
492 return socket_address_equal(a, &b);
495 bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
496 struct SocketAddress b;
501 if (socket_address_parse_netlink(&b, s) < 0)
504 return socket_address_equal(a, &b);
507 const char* socket_address_get_path(const SocketAddress *a) {
510 if (socket_address_family(a) != AF_UNIX)
513 if (a->sockaddr.un.sun_path[0] == 0)
516 return a->sockaddr.un.sun_path;
519 bool socket_ipv6_is_supported(void) {
520 if (access("/proc/net/if_inet6", F_OK) != 0)
526 bool socket_address_matches_fd(const SocketAddress *a, int fd) {
533 b.size = sizeof(b.sockaddr);
534 if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0)
537 if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family)
540 solen = sizeof(b.type);
541 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0)
544 if (b.type != a->type)
547 if (a->protocol != 0) {
548 solen = sizeof(b.protocol);
549 if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0)
552 if (b.protocol != a->protocol)
556 return socket_address_equal(a, &b);
559 int sockaddr_port(const struct sockaddr *_sa, unsigned *port) {
560 int sockaddr_port(const struct sockaddr *_sa, unsigned *ret_port) {
561 union sockaddr_union *sa = (union sockaddr_union*) _sa;
563 /* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */
567 switch (sa->sa.sa_family) {
570 *port = be16toh(sa->in.sin_port);
571 *ret_port = be16toh(sa->in.sin_port);
575 *port = be16toh(sa->in6.sin6_port);
576 *ret_port = be16toh(sa->in6.sin6_port);
580 *port = sa->vm.svm_port;
581 *ret_port = sa->vm.svm_port;
585 return -EAFNOSUPPORT;
589 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
590 union sockaddr_union *sa = (union sockaddr_union*) _sa;
595 assert(salen >= sizeof(sa->sa.sa_family));
597 switch (sa->sa.sa_family) {
602 a = be32toh(sa->in.sin_addr.s_addr);
607 a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
608 be16toh(sa->in.sin_port));
612 a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF);
619 static const unsigned char ipv4_prefix[] = {
620 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
623 if (translate_ipv6 &&
624 memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
625 const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;
629 a[0], a[1], a[2], a[3],
630 be16toh(sa->in6.sin6_port));
634 a[0], a[1], a[2], a[3]);
638 char a[INET6_ADDRSTRLEN];
640 inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a));
646 be16toh(sa->in6.sin6_port));
660 if (salen <= offsetof(struct sockaddr_un, sun_path)) {
661 p = strdup("<unnamed>");
665 } else if (sa->un.sun_path[0] == 0) {
668 /* FIXME: We assume we can print the
669 * socket path here and that it hasn't
670 * more than one NUL byte. That is
671 * actually an invalid assumption */
673 p = new(char, sizeof(sa->un.sun_path)+1);
678 memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1);
679 p[sizeof(sa->un.sun_path)] = 0;
682 p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path));
696 r = asprintf(&p, "vsock:%u", sa->vm.svm_cid);
710 int getpeername_pretty(int fd, bool include_port, char **ret) {
711 union sockaddr_union sa;
712 socklen_t salen = sizeof(sa);
718 if (getpeername(fd, &sa.sa, &salen) < 0)
721 if (sa.sa.sa_family == AF_UNIX) {
722 struct ucred ucred = {};
724 /* UNIX connection sockets are anonymous, so let's use
725 * PID/UID as pretty credentials instead */
727 r = getpeercred(fd, &ucred);
731 if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0)
737 /* For remote sockets we translate IPv6 addresses back to IPv4
738 * if applicable, since that's nicer. */
740 return sockaddr_pretty(&sa.sa, salen, true, include_port, ret);
743 int getsockname_pretty(int fd, char **ret) {
744 union sockaddr_union sa;
745 socklen_t salen = sizeof(sa);
750 if (getsockname(fd, &sa.sa, &salen) < 0)
753 /* For local sockets we do not translate IPv6 addresses back
754 * to IPv6 if applicable, since this is usually used for
755 * listening sockets where the difference between IPv4 and
758 return sockaddr_pretty(&sa.sa, salen, false, true, ret);
761 int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) {
763 char host[NI_MAXHOST], *ret;
767 r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0, IDN_FLAGS);
769 int saved_errno = errno;
771 r = sockaddr_pretty(&sa->sa, salen, true, true, &ret);
775 log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret);
786 int getnameinfo_pretty(int fd, char **ret) {
787 union sockaddr_union sa;
788 socklen_t salen = sizeof(sa);
793 if (getsockname(fd, &sa.sa, &salen) < 0)
796 return socknameinfo_pretty(&sa, salen, ret);
799 int socket_address_unlink(SocketAddress *a) {
802 if (socket_address_family(a) != AF_UNIX)
805 if (a->sockaddr.un.sun_path[0] == 0)
808 if (unlink(a->sockaddr.un.sun_path) < 0)
814 static const char* const netlink_family_table[] = {
815 [NETLINK_ROUTE] = "route",
816 [NETLINK_FIREWALL] = "firewall",
817 [NETLINK_INET_DIAG] = "inet-diag",
818 [NETLINK_NFLOG] = "nflog",
819 [NETLINK_XFRM] = "xfrm",
820 [NETLINK_SELINUX] = "selinux",
821 [NETLINK_ISCSI] = "iscsi",
822 [NETLINK_AUDIT] = "audit",
823 [NETLINK_FIB_LOOKUP] = "fib-lookup",
824 [NETLINK_CONNECTOR] = "connector",
825 [NETLINK_NETFILTER] = "netfilter",
826 [NETLINK_IP6_FW] = "ip6-fw",
827 [NETLINK_DNRTMSG] = "dnrtmsg",
828 [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
829 [NETLINK_GENERIC] = "generic",
830 [NETLINK_SCSITRANSPORT] = "scsitransport",
831 [NETLINK_ECRYPTFS] = "ecryptfs",
832 [NETLINK_RDMA] = "rdma",
835 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
837 static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
838 [SOCKET_ADDRESS_DEFAULT] = "default",
839 [SOCKET_ADDRESS_BOTH] = "both",
840 [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
843 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
845 SocketAddressBindIPv6Only parse_socket_address_bind_ipv6_only_or_bool(const char *n) {
848 r = parse_boolean(n);
850 return SOCKET_ADDRESS_IPV6_ONLY;
852 return SOCKET_ADDRESS_BOTH;
854 return socket_address_bind_ipv6_only_from_string(n);
857 bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
861 if (a->sa.sa_family != b->sa.sa_family)
864 if (a->sa.sa_family == AF_INET)
865 return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
867 if (a->sa.sa_family == AF_INET6)
868 return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
870 if (a->sa.sa_family == AF_VSOCK)
871 return a->vm.svm_cid == b->vm.svm_cid;
877 int fd_inc_sndbuf(int fd, size_t n) {
879 socklen_t l = sizeof(value);
881 r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
882 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
885 /* If we have the privileges we will ignore the kernel limit. */
888 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
889 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
895 int fd_inc_rcvbuf(int fd, size_t n) {
897 socklen_t l = sizeof(value);
899 r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
900 if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
903 /* If we have the privileges we will ignore the kernel limit. */
906 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
907 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
912 #if 0 /// UNNEEDED by elogind
913 static const char* const ip_tos_table[] = {
914 [IPTOS_LOWDELAY] = "low-delay",
915 [IPTOS_THROUGHPUT] = "throughput",
916 [IPTOS_RELIABILITY] = "reliability",
917 [IPTOS_LOWCOST] = "low-cost",
920 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
922 bool ifname_valid(const char *p) {
925 /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
926 * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
927 * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
932 if (strlen(p) >= IFNAMSIZ)
935 if (dot_or_dot_dot(p))
939 if ((unsigned char) *p >= 127U)
942 if ((unsigned char) *p <= 32U)
945 if (IN_SET(*p, ':', '/'))
948 numeric = numeric && (*p >= '0' && *p <= '9');
958 bool address_label_valid(const char *p) {
963 if (strlen(p) >= IFNAMSIZ)
967 if ((uint8_t) *p >= 127U)
970 if ((uint8_t) *p <= 31U)
979 int getpeercred(int fd, struct ucred *ucred) {
980 socklen_t n = sizeof(struct ucred);
987 r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
991 if (n != sizeof(struct ucred))
994 /* Check if the data is actually useful and not suppressed due to namespacing issues */
995 if (!pid_is_valid(u.pid))
998 /* Note that we don't check UID/GID here, as namespace translation works differently there: instead of
999 * receiving in "invalid" user/group we get the overflow UID/GID. */
1005 int getpeersec(int fd, char **ret) {
1006 _cleanup_free_ char *s = NULL;
1013 s = new0(char, n+1);
1017 if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n) >= 0)
1020 if (errno != ERANGE)
1035 int getpeergroups(int fd, gid_t **ret) {
1036 socklen_t n = sizeof(gid_t) * 64;
1037 _cleanup_free_ gid_t *d = NULL;
1047 if (getsockopt(fd, SOL_SOCKET, SO_PEERGROUPS, d, &n) >= 0)
1050 if (errno != ERANGE)
1056 assert_se(n % sizeof(gid_t) == 0);
1059 if ((socklen_t) (int) n != n)
1071 const struct sockaddr *sa, socklen_t len,
1075 struct cmsghdr cmsghdr;
1076 uint8_t buf[CMSG_SPACE(sizeof(int))];
1078 struct msghdr mh = {
1079 .msg_name = (struct sockaddr*) sa,
1081 .msg_control = &control,
1082 .msg_controllen = sizeof(control),
1084 struct cmsghdr *cmsg;
1086 assert(transport_fd >= 0);
1089 cmsg = CMSG_FIRSTHDR(&mh);
1090 cmsg->cmsg_level = SOL_SOCKET;
1091 cmsg->cmsg_type = SCM_RIGHTS;
1092 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1093 memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
1095 mh.msg_controllen = CMSG_SPACE(sizeof(int));
1096 if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0)
1102 #if 0 /// UNNEEDED by elogind
1103 int receive_one_fd(int transport_fd, int flags) {
1105 struct cmsghdr cmsghdr;
1106 uint8_t buf[CMSG_SPACE(sizeof(int))];
1108 struct msghdr mh = {
1109 .msg_control = &control,
1110 .msg_controllen = sizeof(control),
1112 struct cmsghdr *cmsg, *found = NULL;
1114 assert(transport_fd >= 0);
1117 * Receive a single FD via @transport_fd. We don't care for
1118 * the transport-type. We retrieve a single FD at most, so for
1119 * packet-based transports, the caller must ensure to send
1120 * only a single FD per packet. This is best used in
1121 * combination with send_one_fd().
1124 if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0)
1127 CMSG_FOREACH(cmsg, &mh) {
1128 if (cmsg->cmsg_level == SOL_SOCKET &&
1129 cmsg->cmsg_type == SCM_RIGHTS &&
1130 cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
1138 cmsg_close_all(&mh);
1142 return *(int*) CMSG_DATA(found);
1145 ssize_t next_datagram_size_fd(int fd) {
1149 /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
1150 * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
1151 * do. This difference is actually of major importance as we need to be sure that the size returned here
1152 * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
1153 * the wrong size. */
1155 l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
1157 if (IN_SET(errno, EOPNOTSUPP, EFAULT))
1170 /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
1171 * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
1173 if (ioctl(fd, FIONREAD, &k) < 0)
1179 int flush_accept(int fd) {
1181 struct pollfd pollfd = {
1188 /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
1193 r = poll(&pollfd, 1, 0);
1203 cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
1208 if (errno == EAGAIN)
1218 struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) {
1219 struct cmsghdr *cmsg;
1223 CMSG_FOREACH(cmsg, mh)
1224 if (cmsg->cmsg_level == level &&
1225 cmsg->cmsg_type == type &&
1226 (length == (socklen_t) -1 || length == cmsg->cmsg_len))
1232 int socket_ioctl_fd(void) {
1235 /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for
1236 * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not
1237 * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more
1238 * generic AF_NETLINK. */
1240 fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
1242 fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_GENERIC);