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"
54 # define IDN_FLAGS NI_IDN
59 static const char* const socket_address_type_table
[] = {
60 [SOCK_STREAM
] = "Stream",
61 [SOCK_DGRAM
] = "Datagram",
63 [SOCK_RDM
] = "ReliableDatagram",
64 [SOCK_SEQPACKET
] = "SequentialPacket",
65 [SOCK_DCCP
] = "DatagramCongestionControl",
68 DEFINE_STRING_TABLE_LOOKUP(socket_address_type
, int);
70 int socket_address_parse(SocketAddress
*a
, const char *s
) {
78 a
->type
= SOCK_STREAM
;
83 /* IPv6 in [x:.....:z]:p notation */
89 n
= strndupa(s
+1, e
-s
-1);
92 if (inet_pton(AF_INET6
, n
, &a
->sockaddr
.in6
.sin6_addr
) <= 0)
93 return errno
> 0 ? -errno
: -EINVAL
;
100 r
= parse_ip_port(e
, &port
);
104 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
105 a
->sockaddr
.in6
.sin6_port
= htobe16(port
);
106 a
->size
= sizeof(struct sockaddr_in6
);
108 } else if (*s
== '/') {
114 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
))
117 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
118 memcpy(a
->sockaddr
.un
.sun_path
, s
, l
);
119 a
->size
= offsetof(struct sockaddr_un
, sun_path
) + l
+ 1;
121 } else if (*s
== '@') {
122 /* Abstract AF_UNIX socket */
126 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
) - 1)
129 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
130 memcpy(a
->sockaddr
.un
.sun_path
+1, s
+1, l
);
131 a
->size
= offsetof(struct sockaddr_un
, sun_path
) + 1 + l
;
133 } else if (startswith(s
, "vsock:")) {
134 /* AF_VSOCK socket in vsock:cid:port notation */
135 const char *cid_start
= s
+ STRLEN("vsock:");
138 e
= strchr(cid_start
, ':');
142 r
= safe_atou(e
+1, &port
);
146 n
= strndupa(cid_start
, e
- cid_start
);
148 r
= safe_atou(n
, &a
->sockaddr
.vm
.svm_cid
);
152 a
->sockaddr
.vm
.svm_cid
= VMADDR_CID_ANY
;
154 a
->sockaddr
.vm
.svm_family
= AF_VSOCK
;
155 a
->sockaddr
.vm
.svm_port
= port
;
156 a
->size
= sizeof(struct sockaddr_vm
);
163 r
= parse_ip_port(e
+ 1, &port
);
167 n
= strndupa(s
, e
-s
);
169 /* IPv4 in w.x.y.z:p notation? */
170 r
= inet_pton(AF_INET
, n
, &a
->sockaddr
.in
.sin_addr
);
175 /* Gotcha, it's a traditional IPv4 address */
176 a
->sockaddr
.in
.sin_family
= AF_INET
;
177 a
->sockaddr
.in
.sin_port
= htobe16(port
);
178 a
->size
= sizeof(struct sockaddr_in
);
182 if (strlen(n
) > IF_NAMESIZE
-1)
185 /* Uh, our last resort, an interface name */
186 idx
= if_nametoindex(n
);
190 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
191 a
->sockaddr
.in6
.sin6_port
= htobe16(port
);
192 a
->sockaddr
.in6
.sin6_scope_id
= idx
;
193 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
194 a
->size
= sizeof(struct sockaddr_in6
);
199 r
= parse_ip_port(s
, &port
);
203 if (socket_ipv6_is_supported()) {
204 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
205 a
->sockaddr
.in6
.sin6_port
= htobe16(port
);
206 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
207 a
->size
= sizeof(struct sockaddr_in6
);
209 a
->sockaddr
.in
.sin_family
= AF_INET
;
210 a
->sockaddr
.in
.sin_port
= htobe16(port
);
211 a
->sockaddr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
212 a
->size
= sizeof(struct sockaddr_in
);
220 int socket_address_parse_and_warn(SocketAddress
*a
, const char *s
) {
224 /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */
226 r
= socket_address_parse(&b
, s
);
230 if (!socket_ipv6_is_supported() && b
.sockaddr
.sa
.sa_family
== AF_INET6
) {
231 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
232 return -EAFNOSUPPORT
;
239 int socket_address_parse_netlink(SocketAddress
*a
, const char *s
) {
242 _cleanup_free_
char *sfamily
= NULL
;
250 if (sscanf(s
, "%ms %u", &sfamily
, &group
) < 1)
251 return errno
> 0 ? -errno
: -EINVAL
;
253 family
= netlink_family_from_string(sfamily
);
257 a
->sockaddr
.nl
.nl_family
= AF_NETLINK
;
258 a
->sockaddr
.nl
.nl_groups
= group
;
261 a
->size
= sizeof(struct sockaddr_nl
);
262 a
->protocol
= family
;
267 int socket_address_verify(const SocketAddress
*a
) {
270 switch (socket_address_family(a
)) {
273 if (a
->size
!= sizeof(struct sockaddr_in
))
276 if (a
->sockaddr
.in
.sin_port
== 0)
279 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
))
285 if (a
->size
!= sizeof(struct sockaddr_in6
))
288 if (a
->sockaddr
.in6
.sin6_port
== 0)
291 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
))
297 if (a
->size
< offsetof(struct sockaddr_un
, sun_path
))
300 if (a
->size
> offsetof(struct sockaddr_un
, sun_path
)) {
302 if (a
->sockaddr
.un
.sun_path
[0] != 0) {
306 e
= memchr(a
->sockaddr
.un
.sun_path
, 0, sizeof(a
->sockaddr
.un
.sun_path
));
310 if (a
->size
!= offsetof(struct sockaddr_un
, sun_path
) + (e
- a
->sockaddr
.un
.sun_path
) + 1)
315 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
, SOCK_SEQPACKET
))
322 if (a
->size
!= sizeof(struct sockaddr_nl
))
325 if (!IN_SET(a
->type
, SOCK_RAW
, SOCK_DGRAM
))
331 if (a
->size
!= sizeof(struct sockaddr_vm
))
334 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
))
340 return -EAFNOSUPPORT
;
344 int socket_address_print(const SocketAddress
*a
, char **ret
) {
350 r
= socket_address_verify(a
);
354 if (socket_address_family(a
) == AF_NETLINK
) {
355 _cleanup_free_
char *sfamily
= NULL
;
357 r
= netlink_family_to_string_alloc(a
->protocol
, &sfamily
);
361 r
= asprintf(ret
, "%s %u", sfamily
, a
->sockaddr
.nl
.nl_groups
);
368 return sockaddr_pretty(&a
->sockaddr
.sa
, a
->size
, false, true, ret
);
371 bool socket_address_can_accept(const SocketAddress
*a
) {
375 IN_SET(a
->type
, SOCK_STREAM
, SOCK_SEQPACKET
);
378 bool socket_address_equal(const SocketAddress
*a
, const SocketAddress
*b
) {
382 /* Invalid addresses are unequal to all */
383 if (socket_address_verify(a
) < 0 ||
384 socket_address_verify(b
) < 0)
387 if (a
->type
!= b
->type
)
390 if (socket_address_family(a
) != socket_address_family(b
))
393 switch (socket_address_family(a
)) {
396 if (a
->sockaddr
.in
.sin_addr
.s_addr
!= b
->sockaddr
.in
.sin_addr
.s_addr
)
399 if (a
->sockaddr
.in
.sin_port
!= b
->sockaddr
.in
.sin_port
)
405 if (memcmp(&a
->sockaddr
.in6
.sin6_addr
, &b
->sockaddr
.in6
.sin6_addr
, sizeof(a
->sockaddr
.in6
.sin6_addr
)) != 0)
408 if (a
->sockaddr
.in6
.sin6_port
!= b
->sockaddr
.in6
.sin6_port
)
414 if (a
->size
<= offsetof(struct sockaddr_un
, sun_path
) ||
415 b
->size
<= offsetof(struct sockaddr_un
, sun_path
))
418 if ((a
->sockaddr
.un
.sun_path
[0] == 0) != (b
->sockaddr
.un
.sun_path
[0] == 0))
421 if (a
->sockaddr
.un
.sun_path
[0]) {
422 if (!path_equal_or_files_same(a
->sockaddr
.un
.sun_path
, b
->sockaddr
.un
.sun_path
, 0))
425 if (a
->size
!= b
->size
)
428 if (memcmp(a
->sockaddr
.un
.sun_path
, b
->sockaddr
.un
.sun_path
, a
->size
) != 0)
435 if (a
->protocol
!= b
->protocol
)
438 if (a
->sockaddr
.nl
.nl_groups
!= b
->sockaddr
.nl
.nl_groups
)
444 if (a
->sockaddr
.vm
.svm_cid
!= b
->sockaddr
.vm
.svm_cid
)
447 if (a
->sockaddr
.vm
.svm_port
!= b
->sockaddr
.vm
.svm_port
)
453 /* Cannot compare, so we assume the addresses are different */
460 bool socket_address_is(const SocketAddress
*a
, const char *s
, int type
) {
461 struct SocketAddress b
;
466 if (socket_address_parse(&b
, s
) < 0)
471 return socket_address_equal(a
, &b
);
474 bool socket_address_is_netlink(const SocketAddress
*a
, const char *s
) {
475 struct SocketAddress b
;
480 if (socket_address_parse_netlink(&b
, s
) < 0)
483 return socket_address_equal(a
, &b
);
486 const char* socket_address_get_path(const SocketAddress
*a
) {
489 if (socket_address_family(a
) != AF_UNIX
)
492 if (a
->sockaddr
.un
.sun_path
[0] == 0)
495 return a
->sockaddr
.un
.sun_path
;
498 bool socket_ipv6_is_supported(void) {
499 if (access("/proc/net/if_inet6", F_OK
) != 0)
505 bool socket_address_matches_fd(const SocketAddress
*a
, int fd
) {
512 b
.size
= sizeof(b
.sockaddr
);
513 if (getsockname(fd
, &b
.sockaddr
.sa
, &b
.size
) < 0)
516 if (b
.sockaddr
.sa
.sa_family
!= a
->sockaddr
.sa
.sa_family
)
519 solen
= sizeof(b
.type
);
520 if (getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &b
.type
, &solen
) < 0)
523 if (b
.type
!= a
->type
)
526 if (a
->protocol
!= 0) {
527 solen
= sizeof(b
.protocol
);
528 if (getsockopt(fd
, SOL_SOCKET
, SO_PROTOCOL
, &b
.protocol
, &solen
) < 0)
531 if (b
.protocol
!= a
->protocol
)
535 return socket_address_equal(a
, &b
);
538 int sockaddr_port(const struct sockaddr
*_sa
, unsigned *ret_port
) {
539 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
541 /* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */
545 switch (sa
->sa
.sa_family
) {
548 *ret_port
= be16toh(sa
->in
.sin_port
);
552 *ret_port
= be16toh(sa
->in6
.sin6_port
);
556 *ret_port
= sa
->vm
.svm_port
;
560 return -EAFNOSUPPORT
;
564 int sockaddr_pretty(const struct sockaddr
*_sa
, socklen_t salen
, bool translate_ipv6
, bool include_port
, char **ret
) {
565 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
570 assert(salen
>= sizeof(sa
->sa
.sa_family
));
572 switch (sa
->sa
.sa_family
) {
577 a
= be32toh(sa
->in
.sin_addr
.s_addr
);
582 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF,
583 be16toh(sa
->in
.sin_port
));
587 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF);
594 static const unsigned char ipv4_prefix
[] = {
595 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
598 if (translate_ipv6
&&
599 memcmp(&sa
->in6
.sin6_addr
, ipv4_prefix
, sizeof(ipv4_prefix
)) == 0) {
600 const uint8_t *a
= sa
->in6
.sin6_addr
.s6_addr
+12;
604 a
[0], a
[1], a
[2], a
[3],
605 be16toh(sa
->in6
.sin6_port
));
609 a
[0], a
[1], a
[2], a
[3]);
613 char a
[INET6_ADDRSTRLEN
];
615 inet_ntop(AF_INET6
, &sa
->in6
.sin6_addr
, a
, sizeof(a
));
621 be16toh(sa
->in6
.sin6_port
));
635 if (salen
<= offsetof(struct sockaddr_un
, sun_path
)) {
636 p
= strdup("<unnamed>");
640 } else if (sa
->un
.sun_path
[0] == 0) {
643 /* FIXME: We assume we can print the
644 * socket path here and that it hasn't
645 * more than one NUL byte. That is
646 * actually an invalid assumption */
648 p
= new(char, sizeof(sa
->un
.sun_path
)+1);
653 memcpy(p
+1, sa
->un
.sun_path
+1, sizeof(sa
->un
.sun_path
)-1);
654 p
[sizeof(sa
->un
.sun_path
)] = 0;
657 p
= strndup(sa
->un
.sun_path
, sizeof(sa
->un
.sun_path
));
671 r
= asprintf(&p
, "vsock:%u", sa
->vm
.svm_cid
);
685 int getpeername_pretty(int fd
, bool include_port
, char **ret
) {
686 union sockaddr_union sa
;
687 socklen_t salen
= sizeof(sa
);
693 if (getpeername(fd
, &sa
.sa
, &salen
) < 0)
696 if (sa
.sa
.sa_family
== AF_UNIX
) {
697 struct ucred ucred
= {};
699 /* UNIX connection sockets are anonymous, so let's use
700 * PID/UID as pretty credentials instead */
702 r
= getpeercred(fd
, &ucred
);
706 if (asprintf(ret
, "PID "PID_FMT
"/UID "UID_FMT
, ucred
.pid
, ucred
.uid
) < 0)
712 /* For remote sockets we translate IPv6 addresses back to IPv4
713 * if applicable, since that's nicer. */
715 return sockaddr_pretty(&sa
.sa
, salen
, true, include_port
, ret
);
718 int getsockname_pretty(int fd
, char **ret
) {
719 union sockaddr_union sa
;
720 socklen_t salen
= sizeof(sa
);
725 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
728 /* For local sockets we do not translate IPv6 addresses back
729 * to IPv6 if applicable, since this is usually used for
730 * listening sockets where the difference between IPv4 and
733 return sockaddr_pretty(&sa
.sa
, salen
, false, true, ret
);
736 int socknameinfo_pretty(union sockaddr_union
*sa
, socklen_t salen
, char **_ret
) {
738 char host
[NI_MAXHOST
], *ret
;
742 r
= getnameinfo(&sa
->sa
, salen
, host
, sizeof(host
), NULL
, 0, IDN_FLAGS
);
744 int saved_errno
= errno
;
746 r
= sockaddr_pretty(&sa
->sa
, salen
, true, true, &ret
);
750 log_debug_errno(saved_errno
, "getnameinfo(%s) failed: %m", ret
);
761 int socket_address_unlink(SocketAddress
*a
) {
764 if (socket_address_family(a
) != AF_UNIX
)
767 if (a
->sockaddr
.un
.sun_path
[0] == 0)
770 if (unlink(a
->sockaddr
.un
.sun_path
) < 0)
776 static const char* const netlink_family_table
[] = {
777 [NETLINK_ROUTE
] = "route",
778 [NETLINK_FIREWALL
] = "firewall",
779 [NETLINK_INET_DIAG
] = "inet-diag",
780 [NETLINK_NFLOG
] = "nflog",
781 [NETLINK_XFRM
] = "xfrm",
782 [NETLINK_SELINUX
] = "selinux",
783 [NETLINK_ISCSI
] = "iscsi",
784 [NETLINK_AUDIT
] = "audit",
785 [NETLINK_FIB_LOOKUP
] = "fib-lookup",
786 [NETLINK_CONNECTOR
] = "connector",
787 [NETLINK_NETFILTER
] = "netfilter",
788 [NETLINK_IP6_FW
] = "ip6-fw",
789 [NETLINK_DNRTMSG
] = "dnrtmsg",
790 [NETLINK_KOBJECT_UEVENT
] = "kobject-uevent",
791 [NETLINK_GENERIC
] = "generic",
792 [NETLINK_SCSITRANSPORT
] = "scsitransport",
793 [NETLINK_ECRYPTFS
] = "ecryptfs",
794 [NETLINK_RDMA
] = "rdma",
797 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family
, int, INT_MAX
);
799 static const char* const socket_address_bind_ipv6_only_table
[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX
] = {
800 [SOCKET_ADDRESS_DEFAULT
] = "default",
801 [SOCKET_ADDRESS_BOTH
] = "both",
802 [SOCKET_ADDRESS_IPV6_ONLY
] = "ipv6-only"
805 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only
, SocketAddressBindIPv6Only
);
807 SocketAddressBindIPv6Only
parse_socket_address_bind_ipv6_only_or_bool(const char *n
) {
810 r
= parse_boolean(n
);
812 return SOCKET_ADDRESS_IPV6_ONLY
;
814 return SOCKET_ADDRESS_BOTH
;
816 return socket_address_bind_ipv6_only_from_string(n
);
819 bool sockaddr_equal(const union sockaddr_union
*a
, const union sockaddr_union
*b
) {
823 if (a
->sa
.sa_family
!= b
->sa
.sa_family
)
826 if (a
->sa
.sa_family
== AF_INET
)
827 return a
->in
.sin_addr
.s_addr
== b
->in
.sin_addr
.s_addr
;
829 if (a
->sa
.sa_family
== AF_INET6
)
830 return memcmp(&a
->in6
.sin6_addr
, &b
->in6
.sin6_addr
, sizeof(a
->in6
.sin6_addr
)) == 0;
832 if (a
->sa
.sa_family
== AF_VSOCK
)
833 return a
->vm
.svm_cid
== b
->vm
.svm_cid
;
838 int fd_inc_sndbuf(int fd
, size_t n
) {
840 socklen_t l
= sizeof(value
);
842 r
= getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, &l
);
843 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
846 /* If we have the privileges we will ignore the kernel limit. */
849 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUFFORCE
, &value
, sizeof(value
)) < 0)
850 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, sizeof(value
)) < 0)
856 int fd_inc_rcvbuf(int fd
, size_t n
) {
858 socklen_t l
= sizeof(value
);
860 r
= getsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, &l
);
861 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
864 /* If we have the privileges we will ignore the kernel limit. */
867 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUFFORCE
, &value
, sizeof(value
)) < 0)
868 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, sizeof(value
)) < 0)
873 static const char* const ip_tos_table
[] = {
874 [IPTOS_LOWDELAY
] = "low-delay",
875 [IPTOS_THROUGHPUT
] = "throughput",
876 [IPTOS_RELIABILITY
] = "reliability",
877 [IPTOS_LOWCOST
] = "low-cost",
880 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos
, int, 0xff);
882 bool ifname_valid(const char *p
) {
885 /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
886 * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
887 * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
892 if (strlen(p
) >= IFNAMSIZ
)
895 if (dot_or_dot_dot(p
))
899 if ((unsigned char) *p
>= 127U)
902 if ((unsigned char) *p
<= 32U)
905 if (IN_SET(*p
, ':', '/'))
908 numeric
= numeric
&& (*p
>= '0' && *p
<= '9');
918 bool address_label_valid(const char *p
) {
923 if (strlen(p
) >= IFNAMSIZ
)
927 if ((uint8_t) *p
>= 127U)
930 if ((uint8_t) *p
<= 31U)
938 int getpeercred(int fd
, struct ucred
*ucred
) {
939 socklen_t n
= sizeof(struct ucred
);
946 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &u
, &n
);
950 if (n
!= sizeof(struct ucred
))
953 /* Check if the data is actually useful and not suppressed due to namespacing issues */
954 if (!pid_is_valid(u
.pid
))
957 /* Note that we don't check UID/GID here, as namespace translation works differently there: instead of
958 * receiving in "invalid" user/group we get the overflow UID/GID. */
964 int getpeersec(int fd
, char **ret
) {
965 _cleanup_free_
char *s
= NULL
;
976 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERSEC
, s
, &n
) >= 0)
994 int getpeergroups(int fd
, gid_t
**ret
) {
995 socklen_t n
= sizeof(gid_t
) * 64;
996 _cleanup_free_ gid_t
*d
= NULL
;
1006 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERGROUPS
, d
, &n
) >= 0)
1009 if (errno
!= ERANGE
)
1015 assert_se(n
% sizeof(gid_t
) == 0);
1018 if ((socklen_t
) (int) n
!= n
)
1030 const struct sockaddr
*sa
, socklen_t len
,
1034 struct cmsghdr cmsghdr
;
1035 uint8_t buf
[CMSG_SPACE(sizeof(int))];
1037 struct msghdr mh
= {
1038 .msg_name
= (struct sockaddr
*) sa
,
1040 .msg_control
= &control
,
1041 .msg_controllen
= sizeof(control
),
1043 struct cmsghdr
*cmsg
;
1045 assert(transport_fd
>= 0);
1048 cmsg
= CMSG_FIRSTHDR(&mh
);
1049 cmsg
->cmsg_level
= SOL_SOCKET
;
1050 cmsg
->cmsg_type
= SCM_RIGHTS
;
1051 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
1052 memcpy(CMSG_DATA(cmsg
), &fd
, sizeof(int));
1054 mh
.msg_controllen
= CMSG_SPACE(sizeof(int));
1055 if (sendmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| flags
) < 0)
1061 int receive_one_fd(int transport_fd
, int flags
) {
1063 struct cmsghdr cmsghdr
;
1064 uint8_t buf
[CMSG_SPACE(sizeof(int))];
1066 struct msghdr mh
= {
1067 .msg_control
= &control
,
1068 .msg_controllen
= sizeof(control
),
1070 struct cmsghdr
*cmsg
, *found
= NULL
;
1072 assert(transport_fd
>= 0);
1075 * Receive a single FD via @transport_fd. We don't care for
1076 * the transport-type. We retrieve a single FD at most, so for
1077 * packet-based transports, the caller must ensure to send
1078 * only a single FD per packet. This is best used in
1079 * combination with send_one_fd().
1082 if (recvmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| MSG_CMSG_CLOEXEC
| flags
) < 0)
1085 CMSG_FOREACH(cmsg
, &mh
) {
1086 if (cmsg
->cmsg_level
== SOL_SOCKET
&&
1087 cmsg
->cmsg_type
== SCM_RIGHTS
&&
1088 cmsg
->cmsg_len
== CMSG_LEN(sizeof(int))) {
1096 cmsg_close_all(&mh
);
1100 return *(int*) CMSG_DATA(found
);
1103 ssize_t
next_datagram_size_fd(int fd
) {
1107 /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
1108 * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
1109 * do. This difference is actually of major importance as we need to be sure that the size returned here
1110 * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
1111 * the wrong size. */
1113 l
= recv(fd
, NULL
, 0, MSG_PEEK
|MSG_TRUNC
);
1115 if (IN_SET(errno
, EOPNOTSUPP
, EFAULT
))
1128 /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
1129 * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
1131 if (ioctl(fd
, FIONREAD
, &k
) < 0)
1137 int flush_accept(int fd
) {
1139 struct pollfd pollfd
= {
1146 /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
1151 r
= poll(&pollfd
, 1, 0);
1161 cfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
1166 if (errno
== EAGAIN
)
1176 struct cmsghdr
* cmsg_find(struct msghdr
*mh
, int level
, int type
, socklen_t length
) {
1177 struct cmsghdr
*cmsg
;
1181 CMSG_FOREACH(cmsg
, mh
)
1182 if (cmsg
->cmsg_level
== level
&&
1183 cmsg
->cmsg_type
== type
&&
1184 (length
== (socklen_t
) -1 || length
== cmsg
->cmsg_len
))
1190 int socket_ioctl_fd(void) {
1193 /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for
1194 * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not
1195 * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more
1196 * generic AF_NETLINK. */
1198 fd
= socket(AF_INET
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
1200 fd
= socket(AF_NETLINK
, SOCK_RAW
|SOCK_CLOEXEC
, NETLINK_GENERIC
);