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 "socket-util.h"
45 #include "string-table.h"
46 #include "string-util.h"
48 #include "user-util.h"
53 # define IDN_FLAGS (NI_IDN|NI_IDN_USE_STD3_ASCII_RULES)
58 static const char* const socket_address_type_table
[] = {
59 [SOCK_STREAM
] = "Stream",
60 [SOCK_DGRAM
] = "Datagram",
62 [SOCK_RDM
] = "ReliableDatagram",
63 [SOCK_SEQPACKET
] = "SequentialPacket",
64 [SOCK_DCCP
] = "DatagramCongestionControl",
67 DEFINE_STRING_TABLE_LOOKUP(socket_address_type
, int);
69 int socket_address_parse(SocketAddress
*a
, const char *s
) {
78 a
->type
= SOCK_STREAM
;
81 /* IPv6 in [x:.....:z]:p notation */
87 n
= strndupa(s
+1, e
-s
-1);
90 if (inet_pton(AF_INET6
, n
, &a
->sockaddr
.in6
.sin6_addr
) <= 0)
91 return errno
> 0 ? -errno
: -EINVAL
;
102 if (u
<= 0 || u
> 0xFFFF)
105 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
106 a
->sockaddr
.in6
.sin6_port
= htobe16((uint16_t)u
);
107 a
->size
= sizeof(struct sockaddr_in6
);
109 } else if (*s
== '/') {
115 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
))
118 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
119 memcpy(a
->sockaddr
.un
.sun_path
, s
, l
);
120 a
->size
= offsetof(struct sockaddr_un
, sun_path
) + l
+ 1;
122 } else if (*s
== '@') {
123 /* Abstract AF_UNIX socket */
127 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
) - 1)
130 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
131 memcpy(a
->sockaddr
.un
.sun_path
+1, s
+1, l
);
132 a
->size
= offsetof(struct sockaddr_un
, sun_path
) + 1 + l
;
134 } else if (startswith(s
, "vsock:")) {
135 /* AF_VSOCK socket in vsock:cid:port notation */
136 const char *cid_start
= s
+ STRLEN("vsock:");
138 e
= strchr(cid_start
, ':');
142 r
= safe_atou(e
+1, &u
);
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
= u
;
156 a
->size
= sizeof(struct sockaddr_vm
);
161 r
= safe_atou(e
+1, &u
);
165 if (u
<= 0 || u
> 0xFFFF)
168 n
= strndupa(s
, e
-s
);
170 /* IPv4 in w.x.y.z:p notation? */
171 r
= inet_pton(AF_INET
, n
, &a
->sockaddr
.in
.sin_addr
);
176 /* Gotcha, it's a traditional IPv4 address */
177 a
->sockaddr
.in
.sin_family
= AF_INET
;
178 a
->sockaddr
.in
.sin_port
= htobe16((uint16_t)u
);
179 a
->size
= sizeof(struct sockaddr_in
);
183 if (strlen(n
) > IF_NAMESIZE
-1)
186 /* Uh, our last resort, an interface name */
187 idx
= if_nametoindex(n
);
191 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
192 a
->sockaddr
.in6
.sin6_port
= htobe16((uint16_t)u
);
193 a
->sockaddr
.in6
.sin6_scope_id
= idx
;
194 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
195 a
->size
= sizeof(struct sockaddr_in6
);
200 r
= safe_atou(s
, &u
);
204 if (u
<= 0 || u
> 0xFFFF)
207 if (socket_ipv6_is_supported()) {
208 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
209 a
->sockaddr
.in6
.sin6_port
= htobe16((uint16_t)u
);
210 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
211 a
->size
= sizeof(struct sockaddr_in6
);
213 a
->sockaddr
.in
.sin_family
= AF_INET
;
214 a
->sockaddr
.in
.sin_port
= htobe16((uint16_t)u
);
215 a
->sockaddr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
216 a
->size
= sizeof(struct sockaddr_in
);
224 int socket_address_parse_and_warn(SocketAddress
*a
, const char *s
) {
228 /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */
230 r
= socket_address_parse(&b
, s
);
234 if (!socket_ipv6_is_supported() && b
.sockaddr
.sa
.sa_family
== AF_INET6
) {
235 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
236 return -EAFNOSUPPORT
;
243 int socket_address_parse_netlink(SocketAddress
*a
, const char *s
) {
246 _cleanup_free_
char *sfamily
= NULL
;
254 if (sscanf(s
, "%ms %u", &sfamily
, &group
) < 1)
255 return errno
> 0 ? -errno
: -EINVAL
;
257 family
= netlink_family_from_string(sfamily
);
261 a
->sockaddr
.nl
.nl_family
= AF_NETLINK
;
262 a
->sockaddr
.nl
.nl_groups
= group
;
265 a
->size
= sizeof(struct sockaddr_nl
);
266 a
->protocol
= family
;
271 int socket_address_verify(const SocketAddress
*a
) {
274 switch (socket_address_family(a
)) {
277 if (a
->size
!= sizeof(struct sockaddr_in
))
280 if (a
->sockaddr
.in
.sin_port
== 0)
283 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
))
289 if (a
->size
!= sizeof(struct sockaddr_in6
))
292 if (a
->sockaddr
.in6
.sin6_port
== 0)
295 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
))
301 if (a
->size
< offsetof(struct sockaddr_un
, sun_path
))
304 if (a
->size
> offsetof(struct sockaddr_un
, sun_path
)) {
306 if (a
->sockaddr
.un
.sun_path
[0] != 0) {
310 e
= memchr(a
->sockaddr
.un
.sun_path
, 0, sizeof(a
->sockaddr
.un
.sun_path
));
314 if (a
->size
!= offsetof(struct sockaddr_un
, sun_path
) + (e
- a
->sockaddr
.un
.sun_path
) + 1)
319 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
, SOCK_SEQPACKET
))
326 if (a
->size
!= sizeof(struct sockaddr_nl
))
329 if (!IN_SET(a
->type
, SOCK_RAW
, SOCK_DGRAM
))
335 if (a
->size
!= sizeof(struct sockaddr_vm
))
338 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
))
344 return -EAFNOSUPPORT
;
348 int socket_address_print(const SocketAddress
*a
, char **ret
) {
354 r
= socket_address_verify(a
);
358 if (socket_address_family(a
) == AF_NETLINK
) {
359 _cleanup_free_
char *sfamily
= NULL
;
361 r
= netlink_family_to_string_alloc(a
->protocol
, &sfamily
);
365 r
= asprintf(ret
, "%s %u", sfamily
, a
->sockaddr
.nl
.nl_groups
);
372 return sockaddr_pretty(&a
->sockaddr
.sa
, a
->size
, false, true, ret
);
375 bool socket_address_can_accept(const SocketAddress
*a
) {
379 IN_SET(a
->type
, SOCK_STREAM
, SOCK_SEQPACKET
);
382 bool socket_address_equal(const SocketAddress
*a
, const SocketAddress
*b
) {
386 /* Invalid addresses are unequal to all */
387 if (socket_address_verify(a
) < 0 ||
388 socket_address_verify(b
) < 0)
391 if (a
->type
!= b
->type
)
394 if (socket_address_family(a
) != socket_address_family(b
))
397 switch (socket_address_family(a
)) {
400 if (a
->sockaddr
.in
.sin_addr
.s_addr
!= b
->sockaddr
.in
.sin_addr
.s_addr
)
403 if (a
->sockaddr
.in
.sin_port
!= b
->sockaddr
.in
.sin_port
)
409 if (memcmp(&a
->sockaddr
.in6
.sin6_addr
, &b
->sockaddr
.in6
.sin6_addr
, sizeof(a
->sockaddr
.in6
.sin6_addr
)) != 0)
412 if (a
->sockaddr
.in6
.sin6_port
!= b
->sockaddr
.in6
.sin6_port
)
418 if (a
->size
<= offsetof(struct sockaddr_un
, sun_path
) ||
419 b
->size
<= offsetof(struct sockaddr_un
, sun_path
))
422 if ((a
->sockaddr
.un
.sun_path
[0] == 0) != (b
->sockaddr
.un
.sun_path
[0] == 0))
425 if (a
->sockaddr
.un
.sun_path
[0]) {
426 if (!path_equal_or_files_same(a
->sockaddr
.un
.sun_path
, b
->sockaddr
.un
.sun_path
, 0))
429 if (a
->size
!= b
->size
)
432 if (memcmp(a
->sockaddr
.un
.sun_path
, b
->sockaddr
.un
.sun_path
, a
->size
) != 0)
439 if (a
->protocol
!= b
->protocol
)
442 if (a
->sockaddr
.nl
.nl_groups
!= b
->sockaddr
.nl
.nl_groups
)
448 if (a
->sockaddr
.vm
.svm_cid
!= b
->sockaddr
.vm
.svm_cid
)
451 if (a
->sockaddr
.vm
.svm_port
!= b
->sockaddr
.vm
.svm_port
)
457 /* Cannot compare, so we assume the addresses are different */
464 bool socket_address_is(const SocketAddress
*a
, const char *s
, int type
) {
465 struct SocketAddress b
;
470 if (socket_address_parse(&b
, s
) < 0)
475 return socket_address_equal(a
, &b
);
478 bool socket_address_is_netlink(const SocketAddress
*a
, const char *s
) {
479 struct SocketAddress b
;
484 if (socket_address_parse_netlink(&b
, s
) < 0)
487 return socket_address_equal(a
, &b
);
490 const char* socket_address_get_path(const SocketAddress
*a
) {
493 if (socket_address_family(a
) != AF_UNIX
)
496 if (a
->sockaddr
.un
.sun_path
[0] == 0)
499 return a
->sockaddr
.un
.sun_path
;
502 bool socket_ipv6_is_supported(void) {
503 if (access("/proc/net/if_inet6", F_OK
) != 0)
509 bool socket_address_matches_fd(const SocketAddress
*a
, int fd
) {
516 b
.size
= sizeof(b
.sockaddr
);
517 if (getsockname(fd
, &b
.sockaddr
.sa
, &b
.size
) < 0)
520 if (b
.sockaddr
.sa
.sa_family
!= a
->sockaddr
.sa
.sa_family
)
523 solen
= sizeof(b
.type
);
524 if (getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &b
.type
, &solen
) < 0)
527 if (b
.type
!= a
->type
)
530 if (a
->protocol
!= 0) {
531 solen
= sizeof(b
.protocol
);
532 if (getsockopt(fd
, SOL_SOCKET
, SO_PROTOCOL
, &b
.protocol
, &solen
) < 0)
535 if (b
.protocol
!= a
->protocol
)
539 return socket_address_equal(a
, &b
);
542 int sockaddr_port(const struct sockaddr
*_sa
, unsigned *port
) {
543 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
547 switch (sa
->sa
.sa_family
) {
549 *port
= be16toh(sa
->in
.sin_port
);
553 *port
= be16toh(sa
->in6
.sin6_port
);
557 *port
= sa
->vm
.svm_port
;
561 return -EAFNOSUPPORT
;
565 int sockaddr_pretty(const struct sockaddr
*_sa
, socklen_t salen
, bool translate_ipv6
, bool include_port
, char **ret
) {
566 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
571 assert(salen
>= sizeof(sa
->sa
.sa_family
));
573 switch (sa
->sa
.sa_family
) {
578 a
= be32toh(sa
->in
.sin_addr
.s_addr
);
583 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF,
584 be16toh(sa
->in
.sin_port
));
588 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF);
595 static const unsigned char ipv4_prefix
[] = {
596 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
599 if (translate_ipv6
&&
600 memcmp(&sa
->in6
.sin6_addr
, ipv4_prefix
, sizeof(ipv4_prefix
)) == 0) {
601 const uint8_t *a
= sa
->in6
.sin6_addr
.s6_addr
+12;
605 a
[0], a
[1], a
[2], a
[3],
606 be16toh(sa
->in6
.sin6_port
));
610 a
[0], a
[1], a
[2], a
[3]);
614 char a
[INET6_ADDRSTRLEN
];
616 inet_ntop(AF_INET6
, &sa
->in6
.sin6_addr
, a
, sizeof(a
));
622 be16toh(sa
->in6
.sin6_port
));
636 if (salen
<= offsetof(struct sockaddr_un
, sun_path
)) {
637 p
= strdup("<unnamed>");
641 } else if (sa
->un
.sun_path
[0] == 0) {
644 /* FIXME: We assume we can print the
645 * socket path here and that it hasn't
646 * more than one NUL byte. That is
647 * actually an invalid assumption */
649 p
= new(char, sizeof(sa
->un
.sun_path
)+1);
654 memcpy(p
+1, sa
->un
.sun_path
+1, sizeof(sa
->un
.sun_path
)-1);
655 p
[sizeof(sa
->un
.sun_path
)] = 0;
658 p
= strndup(sa
->un
.sun_path
, sizeof(sa
->un
.sun_path
));
672 r
= asprintf(&p
, "vsock:%u", sa
->vm
.svm_cid
);
686 int getpeername_pretty(int fd
, bool include_port
, char **ret
) {
687 union sockaddr_union sa
;
688 socklen_t salen
= sizeof(sa
);
694 if (getpeername(fd
, &sa
.sa
, &salen
) < 0)
697 if (sa
.sa
.sa_family
== AF_UNIX
) {
698 struct ucred ucred
= {};
700 /* UNIX connection sockets are anonymous, so let's use
701 * PID/UID as pretty credentials instead */
703 r
= getpeercred(fd
, &ucred
);
707 if (asprintf(ret
, "PID "PID_FMT
"/UID "UID_FMT
, ucred
.pid
, ucred
.uid
) < 0)
713 /* For remote sockets we translate IPv6 addresses back to IPv4
714 * if applicable, since that's nicer. */
716 return sockaddr_pretty(&sa
.sa
, salen
, true, include_port
, ret
);
719 int getsockname_pretty(int fd
, char **ret
) {
720 union sockaddr_union sa
;
721 socklen_t salen
= sizeof(sa
);
726 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
729 /* For local sockets we do not translate IPv6 addresses back
730 * to IPv6 if applicable, since this is usually used for
731 * listening sockets where the difference between IPv4 and
734 return sockaddr_pretty(&sa
.sa
, salen
, false, true, ret
);
737 int socknameinfo_pretty(union sockaddr_union
*sa
, socklen_t salen
, char **_ret
) {
739 char host
[NI_MAXHOST
], *ret
;
743 r
= getnameinfo(&sa
->sa
, salen
, host
, sizeof(host
), NULL
, 0, IDN_FLAGS
);
745 int saved_errno
= errno
;
747 r
= sockaddr_pretty(&sa
->sa
, salen
, true, true, &ret
);
751 log_debug_errno(saved_errno
, "getnameinfo(%s) failed: %m", ret
);
762 int getnameinfo_pretty(int fd
, char **ret
) {
763 union sockaddr_union sa
;
764 socklen_t salen
= sizeof(sa
);
769 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
772 return socknameinfo_pretty(&sa
, salen
, ret
);
775 int socket_address_unlink(SocketAddress
*a
) {
778 if (socket_address_family(a
) != AF_UNIX
)
781 if (a
->sockaddr
.un
.sun_path
[0] == 0)
784 if (unlink(a
->sockaddr
.un
.sun_path
) < 0)
790 static const char* const netlink_family_table
[] = {
791 [NETLINK_ROUTE
] = "route",
792 [NETLINK_FIREWALL
] = "firewall",
793 [NETLINK_INET_DIAG
] = "inet-diag",
794 [NETLINK_NFLOG
] = "nflog",
795 [NETLINK_XFRM
] = "xfrm",
796 [NETLINK_SELINUX
] = "selinux",
797 [NETLINK_ISCSI
] = "iscsi",
798 [NETLINK_AUDIT
] = "audit",
799 [NETLINK_FIB_LOOKUP
] = "fib-lookup",
800 [NETLINK_CONNECTOR
] = "connector",
801 [NETLINK_NETFILTER
] = "netfilter",
802 [NETLINK_IP6_FW
] = "ip6-fw",
803 [NETLINK_DNRTMSG
] = "dnrtmsg",
804 [NETLINK_KOBJECT_UEVENT
] = "kobject-uevent",
805 [NETLINK_GENERIC
] = "generic",
806 [NETLINK_SCSITRANSPORT
] = "scsitransport",
807 [NETLINK_ECRYPTFS
] = "ecryptfs",
808 [NETLINK_RDMA
] = "rdma",
811 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family
, int, INT_MAX
);
813 static const char* const socket_address_bind_ipv6_only_table
[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX
] = {
814 [SOCKET_ADDRESS_DEFAULT
] = "default",
815 [SOCKET_ADDRESS_BOTH
] = "both",
816 [SOCKET_ADDRESS_IPV6_ONLY
] = "ipv6-only"
819 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only
, SocketAddressBindIPv6Only
);
821 SocketAddressBindIPv6Only
parse_socket_address_bind_ipv6_only_or_bool(const char *n
) {
824 r
= parse_boolean(n
);
826 return SOCKET_ADDRESS_IPV6_ONLY
;
828 return SOCKET_ADDRESS_BOTH
;
830 return socket_address_bind_ipv6_only_from_string(n
);
833 bool sockaddr_equal(const union sockaddr_union
*a
, const union sockaddr_union
*b
) {
837 if (a
->sa
.sa_family
!= b
->sa
.sa_family
)
840 if (a
->sa
.sa_family
== AF_INET
)
841 return a
->in
.sin_addr
.s_addr
== b
->in
.sin_addr
.s_addr
;
843 if (a
->sa
.sa_family
== AF_INET6
)
844 return memcmp(&a
->in6
.sin6_addr
, &b
->in6
.sin6_addr
, sizeof(a
->in6
.sin6_addr
)) == 0;
846 if (a
->sa
.sa_family
== AF_VSOCK
)
847 return a
->vm
.svm_cid
== b
->vm
.svm_cid
;
852 int fd_inc_sndbuf(int fd
, size_t n
) {
854 socklen_t l
= sizeof(value
);
856 r
= getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, &l
);
857 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
860 /* If we have the privileges we will ignore the kernel limit. */
863 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUFFORCE
, &value
, sizeof(value
)) < 0)
864 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, sizeof(value
)) < 0)
870 int fd_inc_rcvbuf(int fd
, size_t n
) {
872 socklen_t l
= sizeof(value
);
874 r
= getsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, &l
);
875 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
878 /* If we have the privileges we will ignore the kernel limit. */
881 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUFFORCE
, &value
, sizeof(value
)) < 0)
882 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, sizeof(value
)) < 0)
887 static const char* const ip_tos_table
[] = {
888 [IPTOS_LOWDELAY
] = "low-delay",
889 [IPTOS_THROUGHPUT
] = "throughput",
890 [IPTOS_RELIABILITY
] = "reliability",
891 [IPTOS_LOWCOST
] = "low-cost",
894 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos
, int, 0xff);
896 bool ifname_valid(const char *p
) {
899 /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
900 * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
901 * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
906 if (strlen(p
) >= IFNAMSIZ
)
909 if (dot_or_dot_dot(p
))
913 if ((unsigned char) *p
>= 127U)
916 if ((unsigned char) *p
<= 32U)
919 if (IN_SET(*p
, ':', '/'))
922 numeric
= numeric
&& (*p
>= '0' && *p
<= '9');
932 bool address_label_valid(const char *p
) {
937 if (strlen(p
) >= IFNAMSIZ
)
941 if ((uint8_t) *p
>= 127U)
944 if ((uint8_t) *p
<= 31U)
952 int getpeercred(int fd
, struct ucred
*ucred
) {
953 socklen_t n
= sizeof(struct ucred
);
960 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &u
, &n
);
964 if (n
!= sizeof(struct ucred
))
967 /* Check if the data is actually useful and not suppressed due
968 * to namespacing issues */
971 if (u
.uid
== UID_INVALID
)
973 if (u
.gid
== GID_INVALID
)
980 int getpeersec(int fd
, char **ret
) {
992 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERSEC
, s
, &n
);
1003 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERSEC
, s
, &n
);
1022 const struct sockaddr
*sa
, socklen_t len
,
1026 struct cmsghdr cmsghdr
;
1027 uint8_t buf
[CMSG_SPACE(sizeof(int))];
1029 struct msghdr mh
= {
1030 .msg_name
= (struct sockaddr
*) sa
,
1032 .msg_control
= &control
,
1033 .msg_controllen
= sizeof(control
),
1035 struct cmsghdr
*cmsg
;
1037 assert(transport_fd
>= 0);
1040 cmsg
= CMSG_FIRSTHDR(&mh
);
1041 cmsg
->cmsg_level
= SOL_SOCKET
;
1042 cmsg
->cmsg_type
= SCM_RIGHTS
;
1043 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
1044 memcpy(CMSG_DATA(cmsg
), &fd
, sizeof(int));
1046 mh
.msg_controllen
= CMSG_SPACE(sizeof(int));
1047 if (sendmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| flags
) < 0)
1053 int receive_one_fd(int transport_fd
, int flags
) {
1055 struct cmsghdr cmsghdr
;
1056 uint8_t buf
[CMSG_SPACE(sizeof(int))];
1058 struct msghdr mh
= {
1059 .msg_control
= &control
,
1060 .msg_controllen
= sizeof(control
),
1062 struct cmsghdr
*cmsg
, *found
= NULL
;
1064 assert(transport_fd
>= 0);
1067 * Receive a single FD via @transport_fd. We don't care for
1068 * the transport-type. We retrieve a single FD at most, so for
1069 * packet-based transports, the caller must ensure to send
1070 * only a single FD per packet. This is best used in
1071 * combination with send_one_fd().
1074 if (recvmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| MSG_CMSG_CLOEXEC
| flags
) < 0)
1077 CMSG_FOREACH(cmsg
, &mh
) {
1078 if (cmsg
->cmsg_level
== SOL_SOCKET
&&
1079 cmsg
->cmsg_type
== SCM_RIGHTS
&&
1080 cmsg
->cmsg_len
== CMSG_LEN(sizeof(int))) {
1088 cmsg_close_all(&mh
);
1092 return *(int*) CMSG_DATA(found
);
1095 ssize_t
next_datagram_size_fd(int fd
) {
1099 /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
1100 * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
1101 * do. This difference is actually of major importance as we need to be sure that the size returned here
1102 * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
1103 * the wrong size. */
1105 l
= recv(fd
, NULL
, 0, MSG_PEEK
|MSG_TRUNC
);
1107 if (IN_SET(errno
, EOPNOTSUPP
, EFAULT
))
1120 /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
1121 * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
1123 if (ioctl(fd
, FIONREAD
, &k
) < 0)
1129 int flush_accept(int fd
) {
1131 struct pollfd pollfd
= {
1138 /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
1143 r
= poll(&pollfd
, 1, 0);
1153 cfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
1158 if (errno
== EAGAIN
)
1168 struct cmsghdr
* cmsg_find(struct msghdr
*mh
, int level
, int type
, socklen_t length
) {
1169 struct cmsghdr
*cmsg
;
1173 CMSG_FOREACH(cmsg
, mh
)
1174 if (cmsg
->cmsg_level
== level
&&
1175 cmsg
->cmsg_type
== type
&&
1176 (length
== (socklen_t
) -1 || length
== cmsg
->cmsg_len
))
1182 int socket_ioctl_fd(void) {
1185 /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for
1186 * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not
1187 * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more
1188 * generic AF_NETLINK. */
1190 fd
= socket(AF_INET
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
1192 fd
= socket(AF_NETLINK
, SOCK_RAW
|SOCK_CLOEXEC
, NETLINK_GENERIC
);