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|NI_IDN_USE_STD3_ASCII_RULES)
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 getnameinfo_pretty(int fd
, char **ret
) {
762 union sockaddr_union sa
;
763 socklen_t salen
= sizeof(sa
);
768 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
771 return socknameinfo_pretty(&sa
, salen
, ret
);
774 int socket_address_unlink(SocketAddress
*a
) {
777 if (socket_address_family(a
) != AF_UNIX
)
780 if (a
->sockaddr
.un
.sun_path
[0] == 0)
783 if (unlink(a
->sockaddr
.un
.sun_path
) < 0)
789 static const char* const netlink_family_table
[] = {
790 [NETLINK_ROUTE
] = "route",
791 [NETLINK_FIREWALL
] = "firewall",
792 [NETLINK_INET_DIAG
] = "inet-diag",
793 [NETLINK_NFLOG
] = "nflog",
794 [NETLINK_XFRM
] = "xfrm",
795 [NETLINK_SELINUX
] = "selinux",
796 [NETLINK_ISCSI
] = "iscsi",
797 [NETLINK_AUDIT
] = "audit",
798 [NETLINK_FIB_LOOKUP
] = "fib-lookup",
799 [NETLINK_CONNECTOR
] = "connector",
800 [NETLINK_NETFILTER
] = "netfilter",
801 [NETLINK_IP6_FW
] = "ip6-fw",
802 [NETLINK_DNRTMSG
] = "dnrtmsg",
803 [NETLINK_KOBJECT_UEVENT
] = "kobject-uevent",
804 [NETLINK_GENERIC
] = "generic",
805 [NETLINK_SCSITRANSPORT
] = "scsitransport",
806 [NETLINK_ECRYPTFS
] = "ecryptfs",
807 [NETLINK_RDMA
] = "rdma",
810 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family
, int, INT_MAX
);
812 static const char* const socket_address_bind_ipv6_only_table
[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX
] = {
813 [SOCKET_ADDRESS_DEFAULT
] = "default",
814 [SOCKET_ADDRESS_BOTH
] = "both",
815 [SOCKET_ADDRESS_IPV6_ONLY
] = "ipv6-only"
818 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only
, SocketAddressBindIPv6Only
);
820 SocketAddressBindIPv6Only
parse_socket_address_bind_ipv6_only_or_bool(const char *n
) {
823 r
= parse_boolean(n
);
825 return SOCKET_ADDRESS_IPV6_ONLY
;
827 return SOCKET_ADDRESS_BOTH
;
829 return socket_address_bind_ipv6_only_from_string(n
);
832 bool sockaddr_equal(const union sockaddr_union
*a
, const union sockaddr_union
*b
) {
836 if (a
->sa
.sa_family
!= b
->sa
.sa_family
)
839 if (a
->sa
.sa_family
== AF_INET
)
840 return a
->in
.sin_addr
.s_addr
== b
->in
.sin_addr
.s_addr
;
842 if (a
->sa
.sa_family
== AF_INET6
)
843 return memcmp(&a
->in6
.sin6_addr
, &b
->in6
.sin6_addr
, sizeof(a
->in6
.sin6_addr
)) == 0;
845 if (a
->sa
.sa_family
== AF_VSOCK
)
846 return a
->vm
.svm_cid
== b
->vm
.svm_cid
;
851 int fd_inc_sndbuf(int fd
, size_t n
) {
853 socklen_t l
= sizeof(value
);
855 r
= getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, &l
);
856 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
859 /* If we have the privileges we will ignore the kernel limit. */
862 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUFFORCE
, &value
, sizeof(value
)) < 0)
863 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, sizeof(value
)) < 0)
869 int fd_inc_rcvbuf(int fd
, size_t n
) {
871 socklen_t l
= sizeof(value
);
873 r
= getsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, &l
);
874 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
877 /* If we have the privileges we will ignore the kernel limit. */
880 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUFFORCE
, &value
, sizeof(value
)) < 0)
881 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, sizeof(value
)) < 0)
886 static const char* const ip_tos_table
[] = {
887 [IPTOS_LOWDELAY
] = "low-delay",
888 [IPTOS_THROUGHPUT
] = "throughput",
889 [IPTOS_RELIABILITY
] = "reliability",
890 [IPTOS_LOWCOST
] = "low-cost",
893 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos
, int, 0xff);
895 bool ifname_valid(const char *p
) {
898 /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
899 * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
900 * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
905 if (strlen(p
) >= IFNAMSIZ
)
908 if (dot_or_dot_dot(p
))
912 if ((unsigned char) *p
>= 127U)
915 if ((unsigned char) *p
<= 32U)
918 if (IN_SET(*p
, ':', '/'))
921 numeric
= numeric
&& (*p
>= '0' && *p
<= '9');
931 bool address_label_valid(const char *p
) {
936 if (strlen(p
) >= IFNAMSIZ
)
940 if ((uint8_t) *p
>= 127U)
943 if ((uint8_t) *p
<= 31U)
951 int getpeercred(int fd
, struct ucred
*ucred
) {
952 socklen_t n
= sizeof(struct ucred
);
959 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &u
, &n
);
963 if (n
!= sizeof(struct ucred
))
966 /* Check if the data is actually useful and not suppressed due to namespacing issues */
967 if (!pid_is_valid(u
.pid
))
970 /* Note that we don't check UID/GID here, as namespace translation works differently there: instead of
971 * receiving in "invalid" user/group we get the overflow UID/GID. */
977 int getpeersec(int fd
, char **ret
) {
978 _cleanup_free_
char *s
= NULL
;
989 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERSEC
, s
, &n
) >= 0)
1007 int getpeergroups(int fd
, gid_t
**ret
) {
1008 socklen_t n
= sizeof(gid_t
) * 64;
1009 _cleanup_free_ gid_t
*d
= NULL
;
1019 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERGROUPS
, d
, &n
) >= 0)
1022 if (errno
!= ERANGE
)
1028 assert_se(n
% sizeof(gid_t
) == 0);
1031 if ((socklen_t
) (int) n
!= n
)
1043 const struct sockaddr
*sa
, socklen_t len
,
1047 struct cmsghdr cmsghdr
;
1048 uint8_t buf
[CMSG_SPACE(sizeof(int))];
1050 struct msghdr mh
= {
1051 .msg_name
= (struct sockaddr
*) sa
,
1053 .msg_control
= &control
,
1054 .msg_controllen
= sizeof(control
),
1056 struct cmsghdr
*cmsg
;
1058 assert(transport_fd
>= 0);
1061 cmsg
= CMSG_FIRSTHDR(&mh
);
1062 cmsg
->cmsg_level
= SOL_SOCKET
;
1063 cmsg
->cmsg_type
= SCM_RIGHTS
;
1064 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
1065 memcpy(CMSG_DATA(cmsg
), &fd
, sizeof(int));
1067 mh
.msg_controllen
= CMSG_SPACE(sizeof(int));
1068 if (sendmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| flags
) < 0)
1074 int receive_one_fd(int transport_fd
, int flags
) {
1076 struct cmsghdr cmsghdr
;
1077 uint8_t buf
[CMSG_SPACE(sizeof(int))];
1079 struct msghdr mh
= {
1080 .msg_control
= &control
,
1081 .msg_controllen
= sizeof(control
),
1083 struct cmsghdr
*cmsg
, *found
= NULL
;
1085 assert(transport_fd
>= 0);
1088 * Receive a single FD via @transport_fd. We don't care for
1089 * the transport-type. We retrieve a single FD at most, so for
1090 * packet-based transports, the caller must ensure to send
1091 * only a single FD per packet. This is best used in
1092 * combination with send_one_fd().
1095 if (recvmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| MSG_CMSG_CLOEXEC
| flags
) < 0)
1098 CMSG_FOREACH(cmsg
, &mh
) {
1099 if (cmsg
->cmsg_level
== SOL_SOCKET
&&
1100 cmsg
->cmsg_type
== SCM_RIGHTS
&&
1101 cmsg
->cmsg_len
== CMSG_LEN(sizeof(int))) {
1109 cmsg_close_all(&mh
);
1113 return *(int*) CMSG_DATA(found
);
1116 ssize_t
next_datagram_size_fd(int fd
) {
1120 /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
1121 * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
1122 * do. This difference is actually of major importance as we need to be sure that the size returned here
1123 * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
1124 * the wrong size. */
1126 l
= recv(fd
, NULL
, 0, MSG_PEEK
|MSG_TRUNC
);
1128 if (IN_SET(errno
, EOPNOTSUPP
, EFAULT
))
1141 /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
1142 * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
1144 if (ioctl(fd
, FIONREAD
, &k
) < 0)
1150 int flush_accept(int fd
) {
1152 struct pollfd pollfd
= {
1159 /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
1164 r
= poll(&pollfd
, 1, 0);
1174 cfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
1179 if (errno
== EAGAIN
)
1189 struct cmsghdr
* cmsg_find(struct msghdr
*mh
, int level
, int type
, socklen_t length
) {
1190 struct cmsghdr
*cmsg
;
1194 CMSG_FOREACH(cmsg
, mh
)
1195 if (cmsg
->cmsg_level
== level
&&
1196 cmsg
->cmsg_type
== type
&&
1197 (length
== (socklen_t
) -1 || length
== cmsg
->cmsg_len
))
1203 int socket_ioctl_fd(void) {
1206 /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for
1207 * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not
1208 * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more
1209 * generic AF_NETLINK. */
1211 fd
= socket(AF_INET
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
1213 fd
= socket(AF_NETLINK
, SOCK_RAW
|SOCK_CLOEXEC
, NETLINK_GENERIC
);