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 *ret_port
) {
543 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
545 /* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */
549 switch (sa
->sa
.sa_family
) {
552 *ret_port
= be16toh(sa
->in
.sin_port
);
556 *ret_port
= be16toh(sa
->in6
.sin6_port
);
560 *ret_port
= sa
->vm
.svm_port
;
564 return -EAFNOSUPPORT
;
568 int sockaddr_pretty(const struct sockaddr
*_sa
, socklen_t salen
, bool translate_ipv6
, bool include_port
, char **ret
) {
569 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
574 assert(salen
>= sizeof(sa
->sa
.sa_family
));
576 switch (sa
->sa
.sa_family
) {
581 a
= be32toh(sa
->in
.sin_addr
.s_addr
);
586 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF,
587 be16toh(sa
->in
.sin_port
));
591 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF);
598 static const unsigned char ipv4_prefix
[] = {
599 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
602 if (translate_ipv6
&&
603 memcmp(&sa
->in6
.sin6_addr
, ipv4_prefix
, sizeof(ipv4_prefix
)) == 0) {
604 const uint8_t *a
= sa
->in6
.sin6_addr
.s6_addr
+12;
608 a
[0], a
[1], a
[2], a
[3],
609 be16toh(sa
->in6
.sin6_port
));
613 a
[0], a
[1], a
[2], a
[3]);
617 char a
[INET6_ADDRSTRLEN
];
619 inet_ntop(AF_INET6
, &sa
->in6
.sin6_addr
, a
, sizeof(a
));
625 be16toh(sa
->in6
.sin6_port
));
639 if (salen
<= offsetof(struct sockaddr_un
, sun_path
)) {
640 p
= strdup("<unnamed>");
644 } else if (sa
->un
.sun_path
[0] == 0) {
647 /* FIXME: We assume we can print the
648 * socket path here and that it hasn't
649 * more than one NUL byte. That is
650 * actually an invalid assumption */
652 p
= new(char, sizeof(sa
->un
.sun_path
)+1);
657 memcpy(p
+1, sa
->un
.sun_path
+1, sizeof(sa
->un
.sun_path
)-1);
658 p
[sizeof(sa
->un
.sun_path
)] = 0;
661 p
= strndup(sa
->un
.sun_path
, sizeof(sa
->un
.sun_path
));
675 r
= asprintf(&p
, "vsock:%u", sa
->vm
.svm_cid
);
689 int getpeername_pretty(int fd
, bool include_port
, char **ret
) {
690 union sockaddr_union sa
;
691 socklen_t salen
= sizeof(sa
);
697 if (getpeername(fd
, &sa
.sa
, &salen
) < 0)
700 if (sa
.sa
.sa_family
== AF_UNIX
) {
701 struct ucred ucred
= {};
703 /* UNIX connection sockets are anonymous, so let's use
704 * PID/UID as pretty credentials instead */
706 r
= getpeercred(fd
, &ucred
);
710 if (asprintf(ret
, "PID "PID_FMT
"/UID "UID_FMT
, ucred
.pid
, ucred
.uid
) < 0)
716 /* For remote sockets we translate IPv6 addresses back to IPv4
717 * if applicable, since that's nicer. */
719 return sockaddr_pretty(&sa
.sa
, salen
, true, include_port
, ret
);
722 int getsockname_pretty(int fd
, char **ret
) {
723 union sockaddr_union sa
;
724 socklen_t salen
= sizeof(sa
);
729 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
732 /* For local sockets we do not translate IPv6 addresses back
733 * to IPv6 if applicable, since this is usually used for
734 * listening sockets where the difference between IPv4 and
737 return sockaddr_pretty(&sa
.sa
, salen
, false, true, ret
);
740 int socknameinfo_pretty(union sockaddr_union
*sa
, socklen_t salen
, char **_ret
) {
742 char host
[NI_MAXHOST
], *ret
;
746 r
= getnameinfo(&sa
->sa
, salen
, host
, sizeof(host
), NULL
, 0, IDN_FLAGS
);
748 int saved_errno
= errno
;
750 r
= sockaddr_pretty(&sa
->sa
, salen
, true, true, &ret
);
754 log_debug_errno(saved_errno
, "getnameinfo(%s) failed: %m", ret
);
765 int getnameinfo_pretty(int fd
, char **ret
) {
766 union sockaddr_union sa
;
767 socklen_t salen
= sizeof(sa
);
772 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
775 return socknameinfo_pretty(&sa
, salen
, ret
);
778 int socket_address_unlink(SocketAddress
*a
) {
781 if (socket_address_family(a
) != AF_UNIX
)
784 if (a
->sockaddr
.un
.sun_path
[0] == 0)
787 if (unlink(a
->sockaddr
.un
.sun_path
) < 0)
793 static const char* const netlink_family_table
[] = {
794 [NETLINK_ROUTE
] = "route",
795 [NETLINK_FIREWALL
] = "firewall",
796 [NETLINK_INET_DIAG
] = "inet-diag",
797 [NETLINK_NFLOG
] = "nflog",
798 [NETLINK_XFRM
] = "xfrm",
799 [NETLINK_SELINUX
] = "selinux",
800 [NETLINK_ISCSI
] = "iscsi",
801 [NETLINK_AUDIT
] = "audit",
802 [NETLINK_FIB_LOOKUP
] = "fib-lookup",
803 [NETLINK_CONNECTOR
] = "connector",
804 [NETLINK_NETFILTER
] = "netfilter",
805 [NETLINK_IP6_FW
] = "ip6-fw",
806 [NETLINK_DNRTMSG
] = "dnrtmsg",
807 [NETLINK_KOBJECT_UEVENT
] = "kobject-uevent",
808 [NETLINK_GENERIC
] = "generic",
809 [NETLINK_SCSITRANSPORT
] = "scsitransport",
810 [NETLINK_ECRYPTFS
] = "ecryptfs",
811 [NETLINK_RDMA
] = "rdma",
814 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family
, int, INT_MAX
);
816 static const char* const socket_address_bind_ipv6_only_table
[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX
] = {
817 [SOCKET_ADDRESS_DEFAULT
] = "default",
818 [SOCKET_ADDRESS_BOTH
] = "both",
819 [SOCKET_ADDRESS_IPV6_ONLY
] = "ipv6-only"
822 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only
, SocketAddressBindIPv6Only
);
824 SocketAddressBindIPv6Only
parse_socket_address_bind_ipv6_only_or_bool(const char *n
) {
827 r
= parse_boolean(n
);
829 return SOCKET_ADDRESS_IPV6_ONLY
;
831 return SOCKET_ADDRESS_BOTH
;
833 return socket_address_bind_ipv6_only_from_string(n
);
836 bool sockaddr_equal(const union sockaddr_union
*a
, const union sockaddr_union
*b
) {
840 if (a
->sa
.sa_family
!= b
->sa
.sa_family
)
843 if (a
->sa
.sa_family
== AF_INET
)
844 return a
->in
.sin_addr
.s_addr
== b
->in
.sin_addr
.s_addr
;
846 if (a
->sa
.sa_family
== AF_INET6
)
847 return memcmp(&a
->in6
.sin6_addr
, &b
->in6
.sin6_addr
, sizeof(a
->in6
.sin6_addr
)) == 0;
849 if (a
->sa
.sa_family
== AF_VSOCK
)
850 return a
->vm
.svm_cid
== b
->vm
.svm_cid
;
855 int fd_inc_sndbuf(int fd
, size_t n
) {
857 socklen_t l
= sizeof(value
);
859 r
= getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, &l
);
860 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
863 /* If we have the privileges we will ignore the kernel limit. */
866 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUFFORCE
, &value
, sizeof(value
)) < 0)
867 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, sizeof(value
)) < 0)
873 int fd_inc_rcvbuf(int fd
, size_t n
) {
875 socklen_t l
= sizeof(value
);
877 r
= getsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, &l
);
878 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
881 /* If we have the privileges we will ignore the kernel limit. */
884 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUFFORCE
, &value
, sizeof(value
)) < 0)
885 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, sizeof(value
)) < 0)
890 static const char* const ip_tos_table
[] = {
891 [IPTOS_LOWDELAY
] = "low-delay",
892 [IPTOS_THROUGHPUT
] = "throughput",
893 [IPTOS_RELIABILITY
] = "reliability",
894 [IPTOS_LOWCOST
] = "low-cost",
897 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos
, int, 0xff);
899 bool ifname_valid(const char *p
) {
902 /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
903 * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
904 * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
909 if (strlen(p
) >= IFNAMSIZ
)
912 if (dot_or_dot_dot(p
))
916 if ((unsigned char) *p
>= 127U)
919 if ((unsigned char) *p
<= 32U)
922 if (IN_SET(*p
, ':', '/'))
925 numeric
= numeric
&& (*p
>= '0' && *p
<= '9');
935 bool address_label_valid(const char *p
) {
940 if (strlen(p
) >= IFNAMSIZ
)
944 if ((uint8_t) *p
>= 127U)
947 if ((uint8_t) *p
<= 31U)
955 int getpeercred(int fd
, struct ucred
*ucred
) {
956 socklen_t n
= sizeof(struct ucred
);
963 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &u
, &n
);
967 if (n
!= sizeof(struct ucred
))
970 /* Check if the data is actually useful and not suppressed due to namespacing issues */
971 if (!pid_is_valid(u
.pid
))
974 /* Note that we don't check UID/GID here, as namespace translation works differently there: instead of
975 * receiving in "invalid" user/group we get the overflow UID/GID. */
981 int getpeersec(int fd
, char **ret
) {
993 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERSEC
, s
, &n
);
1004 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERSEC
, s
, &n
);
1020 int getpeergroups(int fd
, gid_t
**ret
) {
1021 socklen_t n
= sizeof(gid_t
) * 64;
1022 _cleanup_free_ gid_t
*d
= NULL
;
1032 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERGROUPS
, d
, &n
) >= 0)
1035 if (errno
!= ERANGE
)
1041 assert_se(n
% sizeof(gid_t
) == 0);
1044 if ((socklen_t
) (int) n
!= n
)
1056 const struct sockaddr
*sa
, socklen_t len
,
1060 struct cmsghdr cmsghdr
;
1061 uint8_t buf
[CMSG_SPACE(sizeof(int))];
1063 struct msghdr mh
= {
1064 .msg_name
= (struct sockaddr
*) sa
,
1066 .msg_control
= &control
,
1067 .msg_controllen
= sizeof(control
),
1069 struct cmsghdr
*cmsg
;
1071 assert(transport_fd
>= 0);
1074 cmsg
= CMSG_FIRSTHDR(&mh
);
1075 cmsg
->cmsg_level
= SOL_SOCKET
;
1076 cmsg
->cmsg_type
= SCM_RIGHTS
;
1077 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
1078 memcpy(CMSG_DATA(cmsg
), &fd
, sizeof(int));
1080 mh
.msg_controllen
= CMSG_SPACE(sizeof(int));
1081 if (sendmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| flags
) < 0)
1087 int receive_one_fd(int transport_fd
, int flags
) {
1089 struct cmsghdr cmsghdr
;
1090 uint8_t buf
[CMSG_SPACE(sizeof(int))];
1092 struct msghdr mh
= {
1093 .msg_control
= &control
,
1094 .msg_controllen
= sizeof(control
),
1096 struct cmsghdr
*cmsg
, *found
= NULL
;
1098 assert(transport_fd
>= 0);
1101 * Receive a single FD via @transport_fd. We don't care for
1102 * the transport-type. We retrieve a single FD at most, so for
1103 * packet-based transports, the caller must ensure to send
1104 * only a single FD per packet. This is best used in
1105 * combination with send_one_fd().
1108 if (recvmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| MSG_CMSG_CLOEXEC
| flags
) < 0)
1111 CMSG_FOREACH(cmsg
, &mh
) {
1112 if (cmsg
->cmsg_level
== SOL_SOCKET
&&
1113 cmsg
->cmsg_type
== SCM_RIGHTS
&&
1114 cmsg
->cmsg_len
== CMSG_LEN(sizeof(int))) {
1122 cmsg_close_all(&mh
);
1126 return *(int*) CMSG_DATA(found
);
1129 ssize_t
next_datagram_size_fd(int fd
) {
1133 /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
1134 * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
1135 * do. This difference is actually of major importance as we need to be sure that the size returned here
1136 * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
1137 * the wrong size. */
1139 l
= recv(fd
, NULL
, 0, MSG_PEEK
|MSG_TRUNC
);
1141 if (IN_SET(errno
, EOPNOTSUPP
, EFAULT
))
1154 /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
1155 * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
1157 if (ioctl(fd
, FIONREAD
, &k
) < 0)
1163 int flush_accept(int fd
) {
1165 struct pollfd pollfd
= {
1172 /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
1177 r
= poll(&pollfd
, 1, 0);
1187 cfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
1192 if (errno
== EAGAIN
)
1202 struct cmsghdr
* cmsg_find(struct msghdr
*mh
, int level
, int type
, socklen_t length
) {
1203 struct cmsghdr
*cmsg
;
1207 CMSG_FOREACH(cmsg
, mh
)
1208 if (cmsg
->cmsg_level
== level
&&
1209 cmsg
->cmsg_type
== type
&&
1210 (length
== (socklen_t
) -1 || length
== cmsg
->cmsg_len
))
1216 int socket_ioctl_fd(void) {
1219 /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for
1220 * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not
1221 * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more
1222 * generic AF_NETLINK. */
1224 fd
= socket(AF_INET
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
1226 fd
= socket(AF_NETLINK
, SOCK_RAW
|SOCK_CLOEXEC
, NETLINK_GENERIC
);