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
) {
77 a
->type
= SOCK_STREAM
;
82 /* IPv6 in [x:.....:z]:p notation */
88 n
= strndupa(s
+1, e
-s
-1);
91 if (inet_pton(AF_INET6
, n
, &a
->sockaddr
.in6
.sin6_addr
) <= 0)
92 return errno
> 0 ? -errno
: -EINVAL
;
99 r
= parse_ip_port(e
, &port
);
103 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
104 a
->sockaddr
.in6
.sin6_port
= htobe16(port
);
105 a
->size
= sizeof(struct sockaddr_in6
);
107 } else if (*s
== '/') {
113 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
))
116 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
117 memcpy(a
->sockaddr
.un
.sun_path
, s
, l
);
118 a
->size
= offsetof(struct sockaddr_un
, sun_path
) + l
+ 1;
120 } else if (*s
== '@') {
121 /* Abstract AF_UNIX socket */
125 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
) - 1)
128 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
129 memcpy(a
->sockaddr
.un
.sun_path
+1, s
+1, l
);
130 a
->size
= offsetof(struct sockaddr_un
, sun_path
) + 1 + l
;
132 } else if (startswith(s
, "vsock:")) {
133 /* AF_VSOCK socket in vsock:cid:port notation */
134 const char *cid_start
= s
+ STRLEN("vsock:");
137 e
= strchr(cid_start
, ':');
141 r
= safe_atou(e
+1, &port
);
145 n
= strndupa(cid_start
, e
- cid_start
);
147 r
= safe_atou(n
, &a
->sockaddr
.vm
.svm_cid
);
151 a
->sockaddr
.vm
.svm_cid
= VMADDR_CID_ANY
;
153 a
->sockaddr
.vm
.svm_family
= AF_VSOCK
;
154 a
->sockaddr
.vm
.svm_port
= port
;
155 a
->size
= sizeof(struct sockaddr_vm
);
162 r
= parse_ip_port(e
+ 1, &port
);
166 n
= strndupa(s
, e
-s
);
168 /* IPv4 in w.x.y.z:p notation? */
169 r
= inet_pton(AF_INET
, n
, &a
->sockaddr
.in
.sin_addr
);
174 /* Gotcha, it's a traditional IPv4 address */
175 a
->sockaddr
.in
.sin_family
= AF_INET
;
176 a
->sockaddr
.in
.sin_port
= htobe16(port
);
177 a
->size
= sizeof(struct sockaddr_in
);
181 if (strlen(n
) > IF_NAMESIZE
-1)
184 /* Uh, our last resort, an interface name */
185 idx
= if_nametoindex(n
);
189 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
190 a
->sockaddr
.in6
.sin6_port
= htobe16(port
);
191 a
->sockaddr
.in6
.sin6_scope_id
= idx
;
192 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
193 a
->size
= sizeof(struct sockaddr_in6
);
198 r
= parse_ip_port(s
, &port
);
202 if (socket_ipv6_is_supported()) {
203 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
204 a
->sockaddr
.in6
.sin6_port
= htobe16(port
);
205 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
206 a
->size
= sizeof(struct sockaddr_in6
);
208 a
->sockaddr
.in
.sin_family
= AF_INET
;
209 a
->sockaddr
.in
.sin_port
= htobe16(port
);
210 a
->sockaddr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
211 a
->size
= sizeof(struct sockaddr_in
);
219 int socket_address_parse_and_warn(SocketAddress
*a
, const char *s
) {
223 /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */
225 r
= socket_address_parse(&b
, s
);
229 if (!socket_ipv6_is_supported() && b
.sockaddr
.sa
.sa_family
== AF_INET6
) {
230 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
231 return -EAFNOSUPPORT
;
238 int socket_address_parse_netlink(SocketAddress
*a
, const char *s
) {
241 _cleanup_free_
char *sfamily
= NULL
;
249 if (sscanf(s
, "%ms %u", &sfamily
, &group
) < 1)
250 return errno
> 0 ? -errno
: -EINVAL
;
252 family
= netlink_family_from_string(sfamily
);
256 a
->sockaddr
.nl
.nl_family
= AF_NETLINK
;
257 a
->sockaddr
.nl
.nl_groups
= group
;
260 a
->size
= sizeof(struct sockaddr_nl
);
261 a
->protocol
= family
;
266 int socket_address_verify(const SocketAddress
*a
) {
269 switch (socket_address_family(a
)) {
272 if (a
->size
!= sizeof(struct sockaddr_in
))
275 if (a
->sockaddr
.in
.sin_port
== 0)
278 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
))
284 if (a
->size
!= sizeof(struct sockaddr_in6
))
287 if (a
->sockaddr
.in6
.sin6_port
== 0)
290 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
))
296 if (a
->size
< offsetof(struct sockaddr_un
, sun_path
))
299 if (a
->size
> offsetof(struct sockaddr_un
, sun_path
)) {
301 if (a
->sockaddr
.un
.sun_path
[0] != 0) {
305 e
= memchr(a
->sockaddr
.un
.sun_path
, 0, sizeof(a
->sockaddr
.un
.sun_path
));
309 if (a
->size
!= offsetof(struct sockaddr_un
, sun_path
) + (e
- a
->sockaddr
.un
.sun_path
) + 1)
314 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
, SOCK_SEQPACKET
))
321 if (a
->size
!= sizeof(struct sockaddr_nl
))
324 if (!IN_SET(a
->type
, SOCK_RAW
, SOCK_DGRAM
))
330 if (a
->size
!= sizeof(struct sockaddr_vm
))
333 if (!IN_SET(a
->type
, SOCK_STREAM
, SOCK_DGRAM
))
339 return -EAFNOSUPPORT
;
343 int socket_address_print(const SocketAddress
*a
, char **ret
) {
349 r
= socket_address_verify(a
);
353 if (socket_address_family(a
) == AF_NETLINK
) {
354 _cleanup_free_
char *sfamily
= NULL
;
356 r
= netlink_family_to_string_alloc(a
->protocol
, &sfamily
);
360 r
= asprintf(ret
, "%s %u", sfamily
, a
->sockaddr
.nl
.nl_groups
);
367 return sockaddr_pretty(&a
->sockaddr
.sa
, a
->size
, false, true, ret
);
370 bool socket_address_can_accept(const SocketAddress
*a
) {
374 IN_SET(a
->type
, SOCK_STREAM
, SOCK_SEQPACKET
);
377 bool socket_address_equal(const SocketAddress
*a
, const SocketAddress
*b
) {
381 /* Invalid addresses are unequal to all */
382 if (socket_address_verify(a
) < 0 ||
383 socket_address_verify(b
) < 0)
386 if (a
->type
!= b
->type
)
389 if (socket_address_family(a
) != socket_address_family(b
))
392 switch (socket_address_family(a
)) {
395 if (a
->sockaddr
.in
.sin_addr
.s_addr
!= b
->sockaddr
.in
.sin_addr
.s_addr
)
398 if (a
->sockaddr
.in
.sin_port
!= b
->sockaddr
.in
.sin_port
)
404 if (memcmp(&a
->sockaddr
.in6
.sin6_addr
, &b
->sockaddr
.in6
.sin6_addr
, sizeof(a
->sockaddr
.in6
.sin6_addr
)) != 0)
407 if (a
->sockaddr
.in6
.sin6_port
!= b
->sockaddr
.in6
.sin6_port
)
413 if (a
->size
<= offsetof(struct sockaddr_un
, sun_path
) ||
414 b
->size
<= offsetof(struct sockaddr_un
, sun_path
))
417 if ((a
->sockaddr
.un
.sun_path
[0] == 0) != (b
->sockaddr
.un
.sun_path
[0] == 0))
420 if (a
->sockaddr
.un
.sun_path
[0]) {
421 if (!path_equal_or_files_same(a
->sockaddr
.un
.sun_path
, b
->sockaddr
.un
.sun_path
, 0))
424 if (a
->size
!= b
->size
)
427 if (memcmp(a
->sockaddr
.un
.sun_path
, b
->sockaddr
.un
.sun_path
, a
->size
) != 0)
434 if (a
->protocol
!= b
->protocol
)
437 if (a
->sockaddr
.nl
.nl_groups
!= b
->sockaddr
.nl
.nl_groups
)
443 if (a
->sockaddr
.vm
.svm_cid
!= b
->sockaddr
.vm
.svm_cid
)
446 if (a
->sockaddr
.vm
.svm_port
!= b
->sockaddr
.vm
.svm_port
)
452 /* Cannot compare, so we assume the addresses are different */
459 bool socket_address_is(const SocketAddress
*a
, const char *s
, int type
) {
460 struct SocketAddress b
;
465 if (socket_address_parse(&b
, s
) < 0)
470 return socket_address_equal(a
, &b
);
473 bool socket_address_is_netlink(const SocketAddress
*a
, const char *s
) {
474 struct SocketAddress b
;
479 if (socket_address_parse_netlink(&b
, s
) < 0)
482 return socket_address_equal(a
, &b
);
485 const char* socket_address_get_path(const SocketAddress
*a
) {
488 if (socket_address_family(a
) != AF_UNIX
)
491 if (a
->sockaddr
.un
.sun_path
[0] == 0)
494 return a
->sockaddr
.un
.sun_path
;
497 bool socket_ipv6_is_supported(void) {
498 if (access("/proc/net/if_inet6", F_OK
) != 0)
504 bool socket_address_matches_fd(const SocketAddress
*a
, int fd
) {
511 b
.size
= sizeof(b
.sockaddr
);
512 if (getsockname(fd
, &b
.sockaddr
.sa
, &b
.size
) < 0)
515 if (b
.sockaddr
.sa
.sa_family
!= a
->sockaddr
.sa
.sa_family
)
518 solen
= sizeof(b
.type
);
519 if (getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &b
.type
, &solen
) < 0)
522 if (b
.type
!= a
->type
)
525 if (a
->protocol
!= 0) {
526 solen
= sizeof(b
.protocol
);
527 if (getsockopt(fd
, SOL_SOCKET
, SO_PROTOCOL
, &b
.protocol
, &solen
) < 0)
530 if (b
.protocol
!= a
->protocol
)
534 return socket_address_equal(a
, &b
);
537 int sockaddr_port(const struct sockaddr
*_sa
, unsigned *ret_port
) {
538 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
540 /* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */
544 switch (sa
->sa
.sa_family
) {
547 *ret_port
= be16toh(sa
->in
.sin_port
);
551 *ret_port
= be16toh(sa
->in6
.sin6_port
);
555 *ret_port
= sa
->vm
.svm_port
;
559 return -EAFNOSUPPORT
;
563 int sockaddr_pretty(const struct sockaddr
*_sa
, socklen_t salen
, bool translate_ipv6
, bool include_port
, char **ret
) {
564 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
569 assert(salen
>= sizeof(sa
->sa
.sa_family
));
571 switch (sa
->sa
.sa_family
) {
576 a
= be32toh(sa
->in
.sin_addr
.s_addr
);
581 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF,
582 be16toh(sa
->in
.sin_port
));
586 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF);
593 static const unsigned char ipv4_prefix
[] = {
594 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
597 if (translate_ipv6
&&
598 memcmp(&sa
->in6
.sin6_addr
, ipv4_prefix
, sizeof(ipv4_prefix
)) == 0) {
599 const uint8_t *a
= sa
->in6
.sin6_addr
.s6_addr
+12;
603 a
[0], a
[1], a
[2], a
[3],
604 be16toh(sa
->in6
.sin6_port
));
608 a
[0], a
[1], a
[2], a
[3]);
612 char a
[INET6_ADDRSTRLEN
];
614 inet_ntop(AF_INET6
, &sa
->in6
.sin6_addr
, a
, sizeof(a
));
620 be16toh(sa
->in6
.sin6_port
));
634 if (salen
<= offsetof(struct sockaddr_un
, sun_path
)) {
635 p
= strdup("<unnamed>");
639 } else if (sa
->un
.sun_path
[0] == 0) {
642 /* FIXME: We assume we can print the
643 * socket path here and that it hasn't
644 * more than one NUL byte. That is
645 * actually an invalid assumption */
647 p
= new(char, sizeof(sa
->un
.sun_path
)+1);
652 memcpy(p
+1, sa
->un
.sun_path
+1, sizeof(sa
->un
.sun_path
)-1);
653 p
[sizeof(sa
->un
.sun_path
)] = 0;
656 p
= strndup(sa
->un
.sun_path
, sizeof(sa
->un
.sun_path
));
670 r
= asprintf(&p
, "vsock:%u", sa
->vm
.svm_cid
);
684 int getpeername_pretty(int fd
, bool include_port
, char **ret
) {
685 union sockaddr_union sa
;
686 socklen_t salen
= sizeof(sa
);
692 if (getpeername(fd
, &sa
.sa
, &salen
) < 0)
695 if (sa
.sa
.sa_family
== AF_UNIX
) {
696 struct ucred ucred
= {};
698 /* UNIX connection sockets are anonymous, so let's use
699 * PID/UID as pretty credentials instead */
701 r
= getpeercred(fd
, &ucred
);
705 if (asprintf(ret
, "PID "PID_FMT
"/UID "UID_FMT
, ucred
.pid
, ucred
.uid
) < 0)
711 /* For remote sockets we translate IPv6 addresses back to IPv4
712 * if applicable, since that's nicer. */
714 return sockaddr_pretty(&sa
.sa
, salen
, true, include_port
, ret
);
717 int getsockname_pretty(int fd
, char **ret
) {
718 union sockaddr_union sa
;
719 socklen_t salen
= sizeof(sa
);
724 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
727 /* For local sockets we do not translate IPv6 addresses back
728 * to IPv6 if applicable, since this is usually used for
729 * listening sockets where the difference between IPv4 and
732 return sockaddr_pretty(&sa
.sa
, salen
, false, true, ret
);
735 int socknameinfo_pretty(union sockaddr_union
*sa
, socklen_t salen
, char **_ret
) {
737 char host
[NI_MAXHOST
], *ret
;
741 r
= getnameinfo(&sa
->sa
, salen
, host
, sizeof(host
), NULL
, 0, IDN_FLAGS
);
743 int saved_errno
= errno
;
745 r
= sockaddr_pretty(&sa
->sa
, salen
, true, true, &ret
);
749 log_debug_errno(saved_errno
, "getnameinfo(%s) failed: %m", ret
);
760 int getnameinfo_pretty(int fd
, char **ret
) {
761 union sockaddr_union sa
;
762 socklen_t salen
= sizeof(sa
);
767 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
770 return socknameinfo_pretty(&sa
, salen
, ret
);
773 int socket_address_unlink(SocketAddress
*a
) {
776 if (socket_address_family(a
) != AF_UNIX
)
779 if (a
->sockaddr
.un
.sun_path
[0] == 0)
782 if (unlink(a
->sockaddr
.un
.sun_path
) < 0)
788 static const char* const netlink_family_table
[] = {
789 [NETLINK_ROUTE
] = "route",
790 [NETLINK_FIREWALL
] = "firewall",
791 [NETLINK_INET_DIAG
] = "inet-diag",
792 [NETLINK_NFLOG
] = "nflog",
793 [NETLINK_XFRM
] = "xfrm",
794 [NETLINK_SELINUX
] = "selinux",
795 [NETLINK_ISCSI
] = "iscsi",
796 [NETLINK_AUDIT
] = "audit",
797 [NETLINK_FIB_LOOKUP
] = "fib-lookup",
798 [NETLINK_CONNECTOR
] = "connector",
799 [NETLINK_NETFILTER
] = "netfilter",
800 [NETLINK_IP6_FW
] = "ip6-fw",
801 [NETLINK_DNRTMSG
] = "dnrtmsg",
802 [NETLINK_KOBJECT_UEVENT
] = "kobject-uevent",
803 [NETLINK_GENERIC
] = "generic",
804 [NETLINK_SCSITRANSPORT
] = "scsitransport",
805 [NETLINK_ECRYPTFS
] = "ecryptfs",
806 [NETLINK_RDMA
] = "rdma",
809 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family
, int, INT_MAX
);
811 static const char* const socket_address_bind_ipv6_only_table
[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX
] = {
812 [SOCKET_ADDRESS_DEFAULT
] = "default",
813 [SOCKET_ADDRESS_BOTH
] = "both",
814 [SOCKET_ADDRESS_IPV6_ONLY
] = "ipv6-only"
817 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only
, SocketAddressBindIPv6Only
);
819 SocketAddressBindIPv6Only
parse_socket_address_bind_ipv6_only_or_bool(const char *n
) {
822 r
= parse_boolean(n
);
824 return SOCKET_ADDRESS_IPV6_ONLY
;
826 return SOCKET_ADDRESS_BOTH
;
828 return socket_address_bind_ipv6_only_from_string(n
);
831 bool sockaddr_equal(const union sockaddr_union
*a
, const union sockaddr_union
*b
) {
835 if (a
->sa
.sa_family
!= b
->sa
.sa_family
)
838 if (a
->sa
.sa_family
== AF_INET
)
839 return a
->in
.sin_addr
.s_addr
== b
->in
.sin_addr
.s_addr
;
841 if (a
->sa
.sa_family
== AF_INET6
)
842 return memcmp(&a
->in6
.sin6_addr
, &b
->in6
.sin6_addr
, sizeof(a
->in6
.sin6_addr
)) == 0;
844 if (a
->sa
.sa_family
== AF_VSOCK
)
845 return a
->vm
.svm_cid
== b
->vm
.svm_cid
;
850 int fd_inc_sndbuf(int fd
, size_t n
) {
852 socklen_t l
= sizeof(value
);
854 r
= getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, &l
);
855 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
858 /* If we have the privileges we will ignore the kernel limit. */
861 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUFFORCE
, &value
, sizeof(value
)) < 0)
862 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, sizeof(value
)) < 0)
868 int fd_inc_rcvbuf(int fd
, size_t n
) {
870 socklen_t l
= sizeof(value
);
872 r
= getsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, &l
);
873 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
876 /* If we have the privileges we will ignore the kernel limit. */
879 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUFFORCE
, &value
, sizeof(value
)) < 0)
880 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, sizeof(value
)) < 0)
885 static const char* const ip_tos_table
[] = {
886 [IPTOS_LOWDELAY
] = "low-delay",
887 [IPTOS_THROUGHPUT
] = "throughput",
888 [IPTOS_RELIABILITY
] = "reliability",
889 [IPTOS_LOWCOST
] = "low-cost",
892 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos
, int, 0xff);
894 bool ifname_valid(const char *p
) {
897 /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
898 * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
899 * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
904 if (strlen(p
) >= IFNAMSIZ
)
907 if (dot_or_dot_dot(p
))
911 if ((unsigned char) *p
>= 127U)
914 if ((unsigned char) *p
<= 32U)
917 if (IN_SET(*p
, ':', '/'))
920 numeric
= numeric
&& (*p
>= '0' && *p
<= '9');
930 bool address_label_valid(const char *p
) {
935 if (strlen(p
) >= IFNAMSIZ
)
939 if ((uint8_t) *p
>= 127U)
942 if ((uint8_t) *p
<= 31U)
950 int getpeercred(int fd
, struct ucred
*ucred
) {
951 socklen_t n
= sizeof(struct ucred
);
958 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &u
, &n
);
962 if (n
!= sizeof(struct ucred
))
965 /* Check if the data is actually useful and not suppressed due to namespacing issues */
966 if (!pid_is_valid(u
.pid
))
969 /* Note that we don't check UID/GID here, as namespace translation works differently there: instead of
970 * receiving in "invalid" user/group we get the overflow UID/GID. */
976 int getpeersec(int fd
, char **ret
) {
977 _cleanup_free_
char *s
= NULL
;
988 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERSEC
, s
, &n
) >= 0)
1006 int getpeergroups(int fd
, gid_t
**ret
) {
1007 socklen_t n
= sizeof(gid_t
) * 64;
1008 _cleanup_free_ gid_t
*d
= NULL
;
1018 if (getsockopt(fd
, SOL_SOCKET
, SO_PEERGROUPS
, d
, &n
) >= 0)
1021 if (errno
!= ERANGE
)
1027 assert_se(n
% sizeof(gid_t
) == 0);
1030 if ((socklen_t
) (int) n
!= n
)
1042 const struct sockaddr
*sa
, socklen_t len
,
1046 struct cmsghdr cmsghdr
;
1047 uint8_t buf
[CMSG_SPACE(sizeof(int))];
1049 struct msghdr mh
= {
1050 .msg_name
= (struct sockaddr
*) sa
,
1052 .msg_control
= &control
,
1053 .msg_controllen
= sizeof(control
),
1055 struct cmsghdr
*cmsg
;
1057 assert(transport_fd
>= 0);
1060 cmsg
= CMSG_FIRSTHDR(&mh
);
1061 cmsg
->cmsg_level
= SOL_SOCKET
;
1062 cmsg
->cmsg_type
= SCM_RIGHTS
;
1063 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
1064 memcpy(CMSG_DATA(cmsg
), &fd
, sizeof(int));
1066 mh
.msg_controllen
= CMSG_SPACE(sizeof(int));
1067 if (sendmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| flags
) < 0)
1073 int receive_one_fd(int transport_fd
, int flags
) {
1075 struct cmsghdr cmsghdr
;
1076 uint8_t buf
[CMSG_SPACE(sizeof(int))];
1078 struct msghdr mh
= {
1079 .msg_control
= &control
,
1080 .msg_controllen
= sizeof(control
),
1082 struct cmsghdr
*cmsg
, *found
= NULL
;
1084 assert(transport_fd
>= 0);
1087 * Receive a single FD via @transport_fd. We don't care for
1088 * the transport-type. We retrieve a single FD at most, so for
1089 * packet-based transports, the caller must ensure to send
1090 * only a single FD per packet. This is best used in
1091 * combination with send_one_fd().
1094 if (recvmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| MSG_CMSG_CLOEXEC
| flags
) < 0)
1097 CMSG_FOREACH(cmsg
, &mh
) {
1098 if (cmsg
->cmsg_level
== SOL_SOCKET
&&
1099 cmsg
->cmsg_type
== SCM_RIGHTS
&&
1100 cmsg
->cmsg_len
== CMSG_LEN(sizeof(int))) {
1108 cmsg_close_all(&mh
);
1112 return *(int*) CMSG_DATA(found
);
1115 ssize_t
next_datagram_size_fd(int fd
) {
1119 /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
1120 * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
1121 * do. This difference is actually of major importance as we need to be sure that the size returned here
1122 * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
1123 * the wrong size. */
1125 l
= recv(fd
, NULL
, 0, MSG_PEEK
|MSG_TRUNC
);
1127 if (IN_SET(errno
, EOPNOTSUPP
, EFAULT
))
1140 /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
1141 * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
1143 if (ioctl(fd
, FIONREAD
, &k
) < 0)
1149 int flush_accept(int fd
) {
1151 struct pollfd pollfd
= {
1158 /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
1163 r
= poll(&pollfd
, 1, 0);
1173 cfd
= accept4(fd
, NULL
, NULL
, SOCK_NONBLOCK
|SOCK_CLOEXEC
);
1178 if (errno
== EAGAIN
)
1188 struct cmsghdr
* cmsg_find(struct msghdr
*mh
, int level
, int type
, socklen_t length
) {
1189 struct cmsghdr
*cmsg
;
1193 CMSG_FOREACH(cmsg
, mh
)
1194 if (cmsg
->cmsg_level
== level
&&
1195 cmsg
->cmsg_type
== type
&&
1196 (length
== (socklen_t
) -1 || length
== cmsg
->cmsg_len
))
1202 int socket_ioctl_fd(void) {
1205 /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for
1206 * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not
1207 * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more
1208 * generic AF_NETLINK. */
1210 fd
= socket(AF_INET
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
1212 fd
= socket(AF_NETLINK
, SOCK_RAW
|SOCK_CLOEXEC
, NETLINK_GENERIC
);