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/>.
25 #include <arpa/inet.h>
28 #include <sys/types.h>
33 #include "path-util.h"
35 #include "socket-util.h"
38 #include "formats-util.h"
40 int socket_address_parse(SocketAddress *a, const char *s) {
49 a->type = SOCK_STREAM;
52 /* IPv6 in [x:.....:z]:p notation */
58 n = strndupa(s+1, e-s-1);
61 if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0)
62 return errno > 0 ? -errno : -EINVAL;
73 if (u <= 0 || u > 0xFFFF)
76 a->sockaddr.in6.sin6_family = AF_INET6;
77 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
78 a->size = sizeof(struct sockaddr_in6);
80 } else if (*s == '/') {
86 if (l >= sizeof(a->sockaddr.un.sun_path))
89 a->sockaddr.un.sun_family = AF_UNIX;
90 memcpy(a->sockaddr.un.sun_path, s, l);
91 a->size = offsetof(struct sockaddr_un, sun_path) + l + 1;
93 } else if (*s == '@') {
94 /* Abstract AF_UNIX socket */
98 if (l >= sizeof(a->sockaddr.un.sun_path) - 1)
101 a->sockaddr.un.sun_family = AF_UNIX;
102 memcpy(a->sockaddr.un.sun_path+1, s+1, l);
103 a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
108 r = safe_atou(e+1, &u);
112 if (u <= 0 || u > 0xFFFF)
115 n = strndupa(s, e-s);
117 /* IPv4 in w.x.y.z:p notation? */
118 r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr);
123 /* Gotcha, it's a traditional IPv4 address */
124 a->sockaddr.in.sin_family = AF_INET;
125 a->sockaddr.in.sin_port = htons((uint16_t) u);
126 a->size = sizeof(struct sockaddr_in);
130 if (strlen(n) > IF_NAMESIZE-1)
133 /* Uh, our last resort, an interface name */
134 idx = if_nametoindex(n);
138 a->sockaddr.in6.sin6_family = AF_INET6;
139 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
140 a->sockaddr.in6.sin6_scope_id = idx;
141 a->sockaddr.in6.sin6_addr = in6addr_any;
142 a->size = sizeof(struct sockaddr_in6);
147 r = safe_atou(s, &u);
151 if (u <= 0 || u > 0xFFFF)
154 if (socket_ipv6_is_supported()) {
155 a->sockaddr.in6.sin6_family = AF_INET6;
156 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
157 a->sockaddr.in6.sin6_addr = in6addr_any;
158 a->size = sizeof(struct sockaddr_in6);
160 a->sockaddr.in.sin_family = AF_INET;
161 a->sockaddr.in.sin_port = htons((uint16_t) u);
162 a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
163 a->size = sizeof(struct sockaddr_in);
171 int socket_address_parse_and_warn(SocketAddress *a, const char *s) {
175 /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */
177 r = socket_address_parse(&b, s);
181 if (!socket_ipv6_is_supported() && b.sockaddr.sa.sa_family == AF_INET6) {
182 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
183 return -EAFNOSUPPORT;
190 int socket_address_parse_netlink(SocketAddress *a, const char *s) {
193 _cleanup_free_ char *sfamily = NULL;
201 if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
202 return errno > 0 ? -errno : -EINVAL;
204 family = netlink_family_from_string(sfamily);
208 a->sockaddr.nl.nl_family = AF_NETLINK;
209 a->sockaddr.nl.nl_groups = group;
212 a->size = sizeof(struct sockaddr_nl);
213 a->protocol = family;
218 int socket_address_verify(const SocketAddress *a) {
221 switch (socket_address_family(a)) {
224 if (a->size != sizeof(struct sockaddr_in))
227 if (a->sockaddr.in.sin_port == 0)
230 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
236 if (a->size != sizeof(struct sockaddr_in6))
239 if (a->sockaddr.in6.sin6_port == 0)
242 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
248 if (a->size < offsetof(struct sockaddr_un, sun_path))
251 if (a->size > offsetof(struct sockaddr_un, sun_path)) {
253 if (a->sockaddr.un.sun_path[0] != 0) {
257 e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
261 if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
266 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET)
273 if (a->size != sizeof(struct sockaddr_nl))
276 if (a->type != SOCK_RAW && a->type != SOCK_DGRAM)
282 return -EAFNOSUPPORT;
286 int socket_address_print(const SocketAddress *a, char **ret) {
292 r = socket_address_verify(a);
296 if (socket_address_family(a) == AF_NETLINK) {
297 _cleanup_free_ char *sfamily = NULL;
299 r = netlink_family_to_string_alloc(a->protocol, &sfamily);
303 r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
310 return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret);
313 bool socket_address_can_accept(const SocketAddress *a) {
317 a->type == SOCK_STREAM ||
318 a->type == SOCK_SEQPACKET;
321 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
325 /* Invalid addresses are unequal to all */
326 if (socket_address_verify(a) < 0 ||
327 socket_address_verify(b) < 0)
330 if (a->type != b->type)
333 if (socket_address_family(a) != socket_address_family(b))
336 switch (socket_address_family(a)) {
339 if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr)
342 if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port)
348 if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0)
351 if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
357 if (a->size <= offsetof(struct sockaddr_un, sun_path) ||
358 b->size <= offsetof(struct sockaddr_un, sun_path))
361 if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
364 if (a->sockaddr.un.sun_path[0]) {
365 if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path))
368 if (a->size != b->size)
371 if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
378 if (a->protocol != b->protocol)
381 if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
387 /* Cannot compare, so we assume the addresses are different */
394 bool socket_address_is(const SocketAddress *a, const char *s, int type) {
395 struct SocketAddress b;
400 if (socket_address_parse(&b, s) < 0)
405 return socket_address_equal(a, &b);
408 bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
409 struct SocketAddress b;
414 if (socket_address_parse_netlink(&b, s) < 0)
417 return socket_address_equal(a, &b);
420 const char* socket_address_get_path(const SocketAddress *a) {
423 if (socket_address_family(a) != AF_UNIX)
426 if (a->sockaddr.un.sun_path[0] == 0)
429 return a->sockaddr.un.sun_path;
432 bool socket_ipv6_is_supported(void) {
433 _cleanup_free_ char *l = NULL;
435 if (access("/sys/module/ipv6", F_OK) != 0)
438 /* If we can't check "disable" parameter, assume enabled */
439 if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l) < 0)
442 /* If module was loaded with disable=1 no IPv6 available */
446 bool socket_address_matches_fd(const SocketAddress *a, int fd) {
453 b.size = sizeof(b.sockaddr);
454 if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0)
457 if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family)
460 solen = sizeof(b.type);
461 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0)
464 if (b.type != a->type)
467 if (a->protocol != 0) {
468 solen = sizeof(b.protocol);
469 if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0)
472 if (b.protocol != a->protocol)
476 return socket_address_equal(a, &b);
479 int sockaddr_port(const struct sockaddr *_sa) {
480 union sockaddr_union *sa = (union sockaddr_union*) _sa;
484 if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6))
485 return -EAFNOSUPPORT;
487 return ntohs(sa->sa.sa_family == AF_INET6 ?
492 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
493 union sockaddr_union *sa = (union sockaddr_union*) _sa;
498 assert(salen >= sizeof(sa->sa.sa_family));
500 switch (sa->sa.sa_family) {
505 a = ntohl(sa->in.sin_addr.s_addr);
510 a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
511 ntohs(sa->in.sin_port));
515 a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF);
522 static const unsigned char ipv4_prefix[] = {
523 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
526 if (translate_ipv6 &&
527 memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
528 const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;
532 a[0], a[1], a[2], a[3],
533 ntohs(sa->in6.sin6_port));
537 a[0], a[1], a[2], a[3]);
541 char a[INET6_ADDRSTRLEN];
543 inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a));
549 ntohs(sa->in6.sin6_port));
563 if (salen <= offsetof(struct sockaddr_un, sun_path)) {
564 p = strdup("<unnamed>");
568 } else if (sa->un.sun_path[0] == 0) {
571 /* FIXME: We assume we can print the
572 * socket path here and that it hasn't
573 * more than one NUL byte. That is
574 * actually an invalid assumption */
576 p = new(char, sizeof(sa->un.sun_path)+1);
581 memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1);
582 p[sizeof(sa->un.sun_path)] = 0;
585 p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path));
601 int getpeername_pretty(int fd, char **ret) {
602 union sockaddr_union sa;
603 socklen_t salen = sizeof(sa);
609 if (getpeername(fd, &sa.sa, &salen) < 0)
612 if (sa.sa.sa_family == AF_UNIX) {
613 struct ucred ucred = {};
615 /* UNIX connection sockets are anonymous, so let's use
616 * PID/UID as pretty credentials instead */
618 r = getpeercred(fd, &ucred);
622 if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0)
628 /* For remote sockets we translate IPv6 addresses back to IPv4
629 * if applicable, since that's nicer. */
631 return sockaddr_pretty(&sa.sa, salen, true, true, ret);
634 int getsockname_pretty(int fd, char **ret) {
635 union sockaddr_union sa;
636 socklen_t salen = sizeof(sa);
641 if (getsockname(fd, &sa.sa, &salen) < 0)
644 /* For local sockets we do not translate IPv6 addresses back
645 * to IPv6 if applicable, since this is usually used for
646 * listening sockets where the difference between IPv4 and
649 return sockaddr_pretty(&sa.sa, salen, false, true, ret);
652 int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) {
654 char host[NI_MAXHOST], *ret;
658 r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0,
659 NI_IDN|NI_IDN_USE_STD3_ASCII_RULES);
661 int saved_errno = errno;
663 r = sockaddr_pretty(&sa->sa, salen, true, true, &ret);
665 return log_error_errno(r, "sockadd_pretty() failed: %m");
667 log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret);
678 int getnameinfo_pretty(int fd, char **ret) {
679 union sockaddr_union sa;
680 socklen_t salen = sizeof(sa);
685 if (getsockname(fd, &sa.sa, &salen) < 0)
686 return log_error_errno(errno, "getsockname(%d) failed: %m", fd);
688 return socknameinfo_pretty(&sa, salen, ret);
691 int socket_address_unlink(SocketAddress *a) {
694 if (socket_address_family(a) != AF_UNIX)
697 if (a->sockaddr.un.sun_path[0] == 0)
700 if (unlink(a->sockaddr.un.sun_path) < 0)
706 static const char* const netlink_family_table[] = {
707 [NETLINK_ROUTE] = "route",
708 [NETLINK_FIREWALL] = "firewall",
709 [NETLINK_INET_DIAG] = "inet-diag",
710 [NETLINK_NFLOG] = "nflog",
711 [NETLINK_XFRM] = "xfrm",
712 [NETLINK_SELINUX] = "selinux",
713 [NETLINK_ISCSI] = "iscsi",
714 [NETLINK_AUDIT] = "audit",
715 [NETLINK_FIB_LOOKUP] = "fib-lookup",
716 [NETLINK_CONNECTOR] = "connector",
717 [NETLINK_NETFILTER] = "netfilter",
718 [NETLINK_IP6_FW] = "ip6-fw",
719 [NETLINK_DNRTMSG] = "dnrtmsg",
720 [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
721 [NETLINK_GENERIC] = "generic",
722 [NETLINK_SCSITRANSPORT] = "scsitransport",
723 [NETLINK_ECRYPTFS] = "ecryptfs"
726 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
728 static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
729 [SOCKET_ADDRESS_DEFAULT] = "default",
730 [SOCKET_ADDRESS_BOTH] = "both",
731 [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
734 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
736 bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
740 if (a->sa.sa_family != b->sa.sa_family)
743 if (a->sa.sa_family == AF_INET)
744 return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
746 if (a->sa.sa_family == AF_INET6)
747 return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
752 char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
756 /* Like ether_ntoa() but uses %02x instead of %x to print
757 * ethernet addresses, which makes them look less funny. Also,
758 * doesn't use a static buffer. */
760 sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
761 addr->ether_addr_octet[0],
762 addr->ether_addr_octet[1],
763 addr->ether_addr_octet[2],
764 addr->ether_addr_octet[3],
765 addr->ether_addr_octet[4],
766 addr->ether_addr_octet[5]);