1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <arpa/inet.h>
26 #include <netinet/ip.h>
30 #include <sys/types.h>
35 #include "formats-util.h"
38 #include "parse-util.h"
39 #include "path-util.h"
40 #include "socket-util.h"
41 #include "string-table.h"
42 #include "string-util.h"
45 int socket_address_parse(SocketAddress
*a
, const char *s
) {
54 a
->type
= SOCK_STREAM
;
57 /* IPv6 in [x:.....:z]:p notation */
63 n
= strndupa(s
+1, e
-s
-1);
66 if (inet_pton(AF_INET6
, n
, &a
->sockaddr
.in6
.sin6_addr
) <= 0)
67 return errno
> 0 ? -errno
: -EINVAL
;
78 if (u
<= 0 || u
> 0xFFFF)
81 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
82 a
->sockaddr
.in6
.sin6_port
= htons((uint16_t) u
);
83 a
->size
= sizeof(struct sockaddr_in6
);
85 } else if (*s
== '/') {
91 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
))
94 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
95 memcpy(a
->sockaddr
.un
.sun_path
, s
, l
);
96 a
->size
= offsetof(struct sockaddr_un
, sun_path
) + l
+ 1;
98 } else if (*s
== '@') {
99 /* Abstract AF_UNIX socket */
103 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
) - 1)
106 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
107 memcpy(a
->sockaddr
.un
.sun_path
+1, s
+1, l
);
108 a
->size
= offsetof(struct sockaddr_un
, sun_path
) + 1 + l
;
113 r
= safe_atou(e
+1, &u
);
117 if (u
<= 0 || u
> 0xFFFF)
120 n
= strndupa(s
, e
-s
);
122 /* IPv4 in w.x.y.z:p notation? */
123 r
= inet_pton(AF_INET
, n
, &a
->sockaddr
.in
.sin_addr
);
128 /* Gotcha, it's a traditional IPv4 address */
129 a
->sockaddr
.in
.sin_family
= AF_INET
;
130 a
->sockaddr
.in
.sin_port
= htons((uint16_t) u
);
131 a
->size
= sizeof(struct sockaddr_in
);
135 if (strlen(n
) > IF_NAMESIZE
-1)
138 /* Uh, our last resort, an interface name */
139 idx
= if_nametoindex(n
);
143 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
144 a
->sockaddr
.in6
.sin6_port
= htons((uint16_t) u
);
145 a
->sockaddr
.in6
.sin6_scope_id
= idx
;
146 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
147 a
->size
= sizeof(struct sockaddr_in6
);
152 r
= safe_atou(s
, &u
);
156 if (u
<= 0 || u
> 0xFFFF)
159 if (socket_ipv6_is_supported()) {
160 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
161 a
->sockaddr
.in6
.sin6_port
= htons((uint16_t) u
);
162 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
163 a
->size
= sizeof(struct sockaddr_in6
);
165 a
->sockaddr
.in
.sin_family
= AF_INET
;
166 a
->sockaddr
.in
.sin_port
= htons((uint16_t) u
);
167 a
->sockaddr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
168 a
->size
= sizeof(struct sockaddr_in
);
176 int socket_address_parse_and_warn(SocketAddress
*a
, const char *s
) {
180 /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */
182 r
= socket_address_parse(&b
, s
);
186 if (!socket_ipv6_is_supported() && b
.sockaddr
.sa
.sa_family
== AF_INET6
) {
187 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
188 return -EAFNOSUPPORT
;
195 int socket_address_parse_netlink(SocketAddress
*a
, const char *s
) {
198 _cleanup_free_
char *sfamily
= NULL
;
206 if (sscanf(s
, "%ms %u", &sfamily
, &group
) < 1)
207 return errno
> 0 ? -errno
: -EINVAL
;
209 family
= netlink_family_from_string(sfamily
);
213 a
->sockaddr
.nl
.nl_family
= AF_NETLINK
;
214 a
->sockaddr
.nl
.nl_groups
= group
;
217 a
->size
= sizeof(struct sockaddr_nl
);
218 a
->protocol
= family
;
223 int socket_address_verify(const SocketAddress
*a
) {
226 switch (socket_address_family(a
)) {
229 if (a
->size
!= sizeof(struct sockaddr_in
))
232 if (a
->sockaddr
.in
.sin_port
== 0)
235 if (a
->type
!= SOCK_STREAM
&& a
->type
!= SOCK_DGRAM
)
241 if (a
->size
!= sizeof(struct sockaddr_in6
))
244 if (a
->sockaddr
.in6
.sin6_port
== 0)
247 if (a
->type
!= SOCK_STREAM
&& a
->type
!= SOCK_DGRAM
)
253 if (a
->size
< offsetof(struct sockaddr_un
, sun_path
))
256 if (a
->size
> offsetof(struct sockaddr_un
, sun_path
)) {
258 if (a
->sockaddr
.un
.sun_path
[0] != 0) {
262 e
= memchr(a
->sockaddr
.un
.sun_path
, 0, sizeof(a
->sockaddr
.un
.sun_path
));
266 if (a
->size
!= offsetof(struct sockaddr_un
, sun_path
) + (e
- a
->sockaddr
.un
.sun_path
) + 1)
271 if (a
->type
!= SOCK_STREAM
&& a
->type
!= SOCK_DGRAM
&& a
->type
!= SOCK_SEQPACKET
)
278 if (a
->size
!= sizeof(struct sockaddr_nl
))
281 if (a
->type
!= SOCK_RAW
&& a
->type
!= SOCK_DGRAM
)
287 return -EAFNOSUPPORT
;
291 int socket_address_print(const SocketAddress
*a
, char **ret
) {
297 r
= socket_address_verify(a
);
301 if (socket_address_family(a
) == AF_NETLINK
) {
302 _cleanup_free_
char *sfamily
= NULL
;
304 r
= netlink_family_to_string_alloc(a
->protocol
, &sfamily
);
308 r
= asprintf(ret
, "%s %u", sfamily
, a
->sockaddr
.nl
.nl_groups
);
315 return sockaddr_pretty(&a
->sockaddr
.sa
, a
->size
, false, true, ret
);
318 bool socket_address_can_accept(const SocketAddress
*a
) {
322 a
->type
== SOCK_STREAM
||
323 a
->type
== SOCK_SEQPACKET
;
326 bool socket_address_equal(const SocketAddress
*a
, const SocketAddress
*b
) {
330 /* Invalid addresses are unequal to all */
331 if (socket_address_verify(a
) < 0 ||
332 socket_address_verify(b
) < 0)
335 if (a
->type
!= b
->type
)
338 if (socket_address_family(a
) != socket_address_family(b
))
341 switch (socket_address_family(a
)) {
344 if (a
->sockaddr
.in
.sin_addr
.s_addr
!= b
->sockaddr
.in
.sin_addr
.s_addr
)
347 if (a
->sockaddr
.in
.sin_port
!= b
->sockaddr
.in
.sin_port
)
353 if (memcmp(&a
->sockaddr
.in6
.sin6_addr
, &b
->sockaddr
.in6
.sin6_addr
, sizeof(a
->sockaddr
.in6
.sin6_addr
)) != 0)
356 if (a
->sockaddr
.in6
.sin6_port
!= b
->sockaddr
.in6
.sin6_port
)
362 if (a
->size
<= offsetof(struct sockaddr_un
, sun_path
) ||
363 b
->size
<= offsetof(struct sockaddr_un
, sun_path
))
366 if ((a
->sockaddr
.un
.sun_path
[0] == 0) != (b
->sockaddr
.un
.sun_path
[0] == 0))
369 if (a
->sockaddr
.un
.sun_path
[0]) {
370 if (!path_equal_or_files_same(a
->sockaddr
.un
.sun_path
, b
->sockaddr
.un
.sun_path
))
373 if (a
->size
!= b
->size
)
376 if (memcmp(a
->sockaddr
.un
.sun_path
, b
->sockaddr
.un
.sun_path
, a
->size
) != 0)
383 if (a
->protocol
!= b
->protocol
)
386 if (a
->sockaddr
.nl
.nl_groups
!= b
->sockaddr
.nl
.nl_groups
)
392 /* Cannot compare, so we assume the addresses are different */
399 bool socket_address_is(const SocketAddress
*a
, const char *s
, int type
) {
400 struct SocketAddress b
;
405 if (socket_address_parse(&b
, s
) < 0)
410 return socket_address_equal(a
, &b
);
413 bool socket_address_is_netlink(const SocketAddress
*a
, const char *s
) {
414 struct SocketAddress b
;
419 if (socket_address_parse_netlink(&b
, s
) < 0)
422 return socket_address_equal(a
, &b
);
425 const char* socket_address_get_path(const SocketAddress
*a
) {
428 if (socket_address_family(a
) != AF_UNIX
)
431 if (a
->sockaddr
.un
.sun_path
[0] == 0)
434 return a
->sockaddr
.un
.sun_path
;
437 bool socket_ipv6_is_supported(void) {
438 _cleanup_free_
char *l
= NULL
;
440 if (access("/sys/module/ipv6", F_OK
) != 0)
443 /* If we can't check "disable" parameter, assume enabled */
444 if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l
) < 0)
447 /* If module was loaded with disable=1 no IPv6 available */
451 bool socket_address_matches_fd(const SocketAddress
*a
, int fd
) {
458 b
.size
= sizeof(b
.sockaddr
);
459 if (getsockname(fd
, &b
.sockaddr
.sa
, &b
.size
) < 0)
462 if (b
.sockaddr
.sa
.sa_family
!= a
->sockaddr
.sa
.sa_family
)
465 solen
= sizeof(b
.type
);
466 if (getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &b
.type
, &solen
) < 0)
469 if (b
.type
!= a
->type
)
472 if (a
->protocol
!= 0) {
473 solen
= sizeof(b
.protocol
);
474 if (getsockopt(fd
, SOL_SOCKET
, SO_PROTOCOL
, &b
.protocol
, &solen
) < 0)
477 if (b
.protocol
!= a
->protocol
)
481 return socket_address_equal(a
, &b
);
484 int sockaddr_port(const struct sockaddr
*_sa
) {
485 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
489 if (!IN_SET(sa
->sa
.sa_family
, AF_INET
, AF_INET6
))
490 return -EAFNOSUPPORT
;
492 return ntohs(sa
->sa
.sa_family
== AF_INET6
?
497 int sockaddr_pretty(const struct sockaddr
*_sa
, socklen_t salen
, bool translate_ipv6
, bool include_port
, char **ret
) {
498 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
503 assert(salen
>= sizeof(sa
->sa
.sa_family
));
505 switch (sa
->sa
.sa_family
) {
510 a
= ntohl(sa
->in
.sin_addr
.s_addr
);
515 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF,
516 ntohs(sa
->in
.sin_port
));
520 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF);
527 static const unsigned char ipv4_prefix
[] = {
528 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
531 if (translate_ipv6
&&
532 memcmp(&sa
->in6
.sin6_addr
, ipv4_prefix
, sizeof(ipv4_prefix
)) == 0) {
533 const uint8_t *a
= sa
->in6
.sin6_addr
.s6_addr
+12;
537 a
[0], a
[1], a
[2], a
[3],
538 ntohs(sa
->in6
.sin6_port
));
542 a
[0], a
[1], a
[2], a
[3]);
546 char a
[INET6_ADDRSTRLEN
];
548 inet_ntop(AF_INET6
, &sa
->in6
.sin6_addr
, a
, sizeof(a
));
554 ntohs(sa
->in6
.sin6_port
));
568 if (salen
<= offsetof(struct sockaddr_un
, sun_path
)) {
569 p
= strdup("<unnamed>");
573 } else if (sa
->un
.sun_path
[0] == 0) {
576 /* FIXME: We assume we can print the
577 * socket path here and that it hasn't
578 * more than one NUL byte. That is
579 * actually an invalid assumption */
581 p
= new(char, sizeof(sa
->un
.sun_path
)+1);
586 memcpy(p
+1, sa
->un
.sun_path
+1, sizeof(sa
->un
.sun_path
)-1);
587 p
[sizeof(sa
->un
.sun_path
)] = 0;
590 p
= strndup(sa
->un
.sun_path
, sizeof(sa
->un
.sun_path
));
606 int getpeername_pretty(int fd
, char **ret
) {
607 union sockaddr_union sa
;
608 socklen_t salen
= sizeof(sa
);
614 if (getpeername(fd
, &sa
.sa
, &salen
) < 0)
617 if (sa
.sa
.sa_family
== AF_UNIX
) {
618 struct ucred ucred
= {};
620 /* UNIX connection sockets are anonymous, so let's use
621 * PID/UID as pretty credentials instead */
623 r
= getpeercred(fd
, &ucred
);
627 if (asprintf(ret
, "PID "PID_FMT
"/UID "UID_FMT
, ucred
.pid
, ucred
.uid
) < 0)
633 /* For remote sockets we translate IPv6 addresses back to IPv4
634 * if applicable, since that's nicer. */
636 return sockaddr_pretty(&sa
.sa
, salen
, true, true, ret
);
639 int getsockname_pretty(int fd
, char **ret
) {
640 union sockaddr_union sa
;
641 socklen_t salen
= sizeof(sa
);
646 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
649 /* For local sockets we do not translate IPv6 addresses back
650 * to IPv6 if applicable, since this is usually used for
651 * listening sockets where the difference between IPv4 and
654 return sockaddr_pretty(&sa
.sa
, salen
, false, true, ret
);
657 int socknameinfo_pretty(union sockaddr_union
*sa
, socklen_t salen
, char **_ret
) {
659 char host
[NI_MAXHOST
], *ret
;
663 r
= getnameinfo(&sa
->sa
, salen
, host
, sizeof(host
), NULL
, 0,
664 NI_IDN
|NI_IDN_USE_STD3_ASCII_RULES
);
666 int saved_errno
= errno
;
668 r
= sockaddr_pretty(&sa
->sa
, salen
, true, true, &ret
);
672 log_debug_errno(saved_errno
, "getnameinfo(%s) failed: %m", ret
);
683 int getnameinfo_pretty(int fd
, char **ret
) {
684 union sockaddr_union sa
;
685 socklen_t salen
= sizeof(sa
);
690 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
693 return socknameinfo_pretty(&sa
, salen
, ret
);
696 int socket_address_unlink(SocketAddress
*a
) {
699 if (socket_address_family(a
) != AF_UNIX
)
702 if (a
->sockaddr
.un
.sun_path
[0] == 0)
705 if (unlink(a
->sockaddr
.un
.sun_path
) < 0)
711 static const char* const netlink_family_table
[] = {
712 [NETLINK_ROUTE
] = "route",
713 [NETLINK_FIREWALL
] = "firewall",
714 [NETLINK_INET_DIAG
] = "inet-diag",
715 [NETLINK_NFLOG
] = "nflog",
716 [NETLINK_XFRM
] = "xfrm",
717 [NETLINK_SELINUX
] = "selinux",
718 [NETLINK_ISCSI
] = "iscsi",
719 [NETLINK_AUDIT
] = "audit",
720 [NETLINK_FIB_LOOKUP
] = "fib-lookup",
721 [NETLINK_CONNECTOR
] = "connector",
722 [NETLINK_NETFILTER
] = "netfilter",
723 [NETLINK_IP6_FW
] = "ip6-fw",
724 [NETLINK_DNRTMSG
] = "dnrtmsg",
725 [NETLINK_KOBJECT_UEVENT
] = "kobject-uevent",
726 [NETLINK_GENERIC
] = "generic",
727 [NETLINK_SCSITRANSPORT
] = "scsitransport",
728 [NETLINK_ECRYPTFS
] = "ecryptfs"
731 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family
, int, INT_MAX
);
733 static const char* const socket_address_bind_ipv6_only_table
[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX
] = {
734 [SOCKET_ADDRESS_DEFAULT
] = "default",
735 [SOCKET_ADDRESS_BOTH
] = "both",
736 [SOCKET_ADDRESS_IPV6_ONLY
] = "ipv6-only"
739 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only
, SocketAddressBindIPv6Only
);
741 bool sockaddr_equal(const union sockaddr_union
*a
, const union sockaddr_union
*b
) {
745 if (a
->sa
.sa_family
!= b
->sa
.sa_family
)
748 if (a
->sa
.sa_family
== AF_INET
)
749 return a
->in
.sin_addr
.s_addr
== b
->in
.sin_addr
.s_addr
;
751 if (a
->sa
.sa_family
== AF_INET6
)
752 return memcmp(&a
->in6
.sin6_addr
, &b
->in6
.sin6_addr
, sizeof(a
->in6
.sin6_addr
)) == 0;
757 int fd_inc_sndbuf(int fd
, size_t n
) {
759 socklen_t l
= sizeof(value
);
761 r
= getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, &l
);
762 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
765 /* If we have the privileges we will ignore the kernel limit. */
768 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUFFORCE
, &value
, sizeof(value
)) < 0)
769 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &value
, sizeof(value
)) < 0)
775 int fd_inc_rcvbuf(int fd
, size_t n
) {
777 socklen_t l
= sizeof(value
);
779 r
= getsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, &l
);
780 if (r
>= 0 && l
== sizeof(value
) && (size_t) value
>= n
*2)
783 /* If we have the privileges we will ignore the kernel limit. */
786 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUFFORCE
, &value
, sizeof(value
)) < 0)
787 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, &value
, sizeof(value
)) < 0)
792 static const char* const ip_tos_table
[] = {
793 [IPTOS_LOWDELAY
] = "low-delay",
794 [IPTOS_THROUGHPUT
] = "throughput",
795 [IPTOS_RELIABILITY
] = "reliability",
796 [IPTOS_LOWCOST
] = "low-cost",
799 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos
, int, 0xff);
801 int getpeercred(int fd
, struct ucred
*ucred
) {
802 socklen_t n
= sizeof(struct ucred
);
809 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERCRED
, &u
, &n
);
813 if (n
!= sizeof(struct ucred
))
816 /* Check if the data is actually useful and not suppressed due
817 * to namespacing issues */
820 if (u
.uid
== UID_INVALID
)
822 if (u
.gid
== GID_INVALID
)
829 int getpeersec(int fd
, char **ret
) {
841 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERSEC
, s
, &n
);
852 r
= getsockopt(fd
, SOL_SOCKET
, SO_PEERSEC
, s
, &n
);
868 int send_one_fd(int transport_fd
, int fd
, int flags
) {
870 struct cmsghdr cmsghdr
;
871 uint8_t buf
[CMSG_SPACE(sizeof(int))];
874 .msg_control
= &control
,
875 .msg_controllen
= sizeof(control
),
877 struct cmsghdr
*cmsg
;
879 assert(transport_fd
>= 0);
882 cmsg
= CMSG_FIRSTHDR(&mh
);
883 cmsg
->cmsg_level
= SOL_SOCKET
;
884 cmsg
->cmsg_type
= SCM_RIGHTS
;
885 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
886 memcpy(CMSG_DATA(cmsg
), &fd
, sizeof(int));
888 mh
.msg_controllen
= CMSG_SPACE(sizeof(int));
889 if (sendmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| flags
) < 0)
895 int receive_one_fd(int transport_fd
, int flags
) {
897 struct cmsghdr cmsghdr
;
898 uint8_t buf
[CMSG_SPACE(sizeof(int))];
901 .msg_control
= &control
,
902 .msg_controllen
= sizeof(control
),
904 struct cmsghdr
*cmsg
, *found
= NULL
;
906 assert(transport_fd
>= 0);
909 * Receive a single FD via @transport_fd. We don't care for
910 * the transport-type. We retrieve a single FD at most, so for
911 * packet-based transports, the caller must ensure to send
912 * only a single FD per packet. This is best used in
913 * combination with send_one_fd().
916 if (recvmsg(transport_fd
, &mh
, MSG_NOSIGNAL
| MSG_CMSG_CLOEXEC
| flags
) < 0)
919 CMSG_FOREACH(cmsg
, &mh
) {
920 if (cmsg
->cmsg_level
== SOL_SOCKET
&&
921 cmsg
->cmsg_type
== SCM_RIGHTS
&&
922 cmsg
->cmsg_len
== CMSG_LEN(sizeof(int))) {
934 return *(int*) CMSG_DATA(found
);