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 */
54 if (!socket_ipv6_is_supported()) {
55 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
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 if (!socket_ipv6_is_supported()) {
144 log_warning("Binding to interface is not available since kernel does not support IPv6.");
145 return -EAFNOSUPPORT;
148 a->sockaddr.in6.sin6_family = AF_INET6;
149 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
150 a->sockaddr.in6.sin6_scope_id = idx;
151 a->sockaddr.in6.sin6_addr = in6addr_any;
152 a->size = sizeof(struct sockaddr_in6);
157 r = safe_atou(s, &u);
161 if (u <= 0 || u > 0xFFFF)
164 if (socket_ipv6_is_supported()) {
165 a->sockaddr.in6.sin6_family = AF_INET6;
166 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
167 a->sockaddr.in6.sin6_addr = in6addr_any;
168 a->size = sizeof(struct sockaddr_in6);
170 a->sockaddr.in.sin_family = AF_INET;
171 a->sockaddr.in.sin_port = htons((uint16_t) u);
172 a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
173 a->size = sizeof(struct sockaddr_in);
181 int socket_address_parse_netlink(SocketAddress *a, const char *s) {
184 _cleanup_free_ char *sfamily = NULL;
192 if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
193 return errno > 0 ? -errno : -EINVAL;
195 family = netlink_family_from_string(sfamily);
199 a->sockaddr.nl.nl_family = AF_NETLINK;
200 a->sockaddr.nl.nl_groups = group;
203 a->size = sizeof(struct sockaddr_nl);
204 a->protocol = family;
209 int socket_address_verify(const SocketAddress *a) {
212 switch (socket_address_family(a)) {
215 if (a->size != sizeof(struct sockaddr_in))
218 if (a->sockaddr.in.sin_port == 0)
221 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
227 if (a->size != sizeof(struct sockaddr_in6))
230 if (a->sockaddr.in6.sin6_port == 0)
233 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
239 if (a->size < offsetof(struct sockaddr_un, sun_path))
242 if (a->size > offsetof(struct sockaddr_un, sun_path)) {
244 if (a->sockaddr.un.sun_path[0] != 0) {
248 e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
252 if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
257 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET)
264 if (a->size != sizeof(struct sockaddr_nl))
267 if (a->type != SOCK_RAW && a->type != SOCK_DGRAM)
273 return -EAFNOSUPPORT;
277 int socket_address_print(const SocketAddress *a, char **ret) {
283 r = socket_address_verify(a);
287 if (socket_address_family(a) == AF_NETLINK) {
288 _cleanup_free_ char *sfamily = NULL;
290 r = netlink_family_to_string_alloc(a->protocol, &sfamily);
294 r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
301 return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret);
304 bool socket_address_can_accept(const SocketAddress *a) {
308 a->type == SOCK_STREAM ||
309 a->type == SOCK_SEQPACKET;
312 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
316 /* Invalid addresses are unequal to all */
317 if (socket_address_verify(a) < 0 ||
318 socket_address_verify(b) < 0)
321 if (a->type != b->type)
324 if (socket_address_family(a) != socket_address_family(b))
327 switch (socket_address_family(a)) {
330 if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr)
333 if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port)
339 if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0)
342 if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
348 if (a->size <= offsetof(struct sockaddr_un, sun_path) ||
349 b->size <= offsetof(struct sockaddr_un, sun_path))
352 if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
355 if (a->sockaddr.un.sun_path[0]) {
356 if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path))
359 if (a->size != b->size)
362 if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
369 if (a->protocol != b->protocol)
372 if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
378 /* Cannot compare, so we assume the addresses are different */
385 bool socket_address_is(const SocketAddress *a, const char *s, int type) {
386 struct SocketAddress b;
391 if (socket_address_parse(&b, s) < 0)
396 return socket_address_equal(a, &b);
399 bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
400 struct SocketAddress b;
405 if (socket_address_parse_netlink(&b, s) < 0)
408 return socket_address_equal(a, &b);
411 const char* socket_address_get_path(const SocketAddress *a) {
414 if (socket_address_family(a) != AF_UNIX)
417 if (a->sockaddr.un.sun_path[0] == 0)
420 return a->sockaddr.un.sun_path;
423 bool socket_ipv6_is_supported(void) {
424 _cleanup_free_ char *l = NULL;
426 if (access("/sys/module/ipv6", F_OK) != 0)
429 /* If we can't check "disable" parameter, assume enabled */
430 if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l) < 0)
433 /* If module was loaded with disable=1 no IPv6 available */
437 bool socket_address_matches_fd(const SocketAddress *a, int fd) {
444 b.size = sizeof(b.sockaddr);
445 if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0)
448 if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family)
451 solen = sizeof(b.type);
452 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0)
455 if (b.type != a->type)
458 if (a->protocol != 0) {
459 solen = sizeof(b.protocol);
460 if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0)
463 if (b.protocol != a->protocol)
467 return socket_address_equal(a, &b);
470 int sockaddr_port(const struct sockaddr *_sa) {
471 union sockaddr_union *sa = (union sockaddr_union*) _sa;
475 if (!IN_SET(sa->sa.sa_family, AF_INET, AF_INET6))
476 return -EAFNOSUPPORT;
478 return ntohs(sa->sa.sa_family == AF_INET6 ?
483 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
484 union sockaddr_union *sa = (union sockaddr_union*) _sa;
489 assert(salen >= sizeof(sa->sa.sa_family));
491 switch (sa->sa.sa_family) {
496 a = ntohl(sa->in.sin_addr.s_addr);
501 a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
502 ntohs(sa->in.sin_port));
506 a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF);
513 static const unsigned char ipv4_prefix[] = {
514 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
517 if (translate_ipv6 &&
518 memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
519 const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;
523 a[0], a[1], a[2], a[3],
524 ntohs(sa->in6.sin6_port));
528 a[0], a[1], a[2], a[3]);
532 char a[INET6_ADDRSTRLEN];
534 inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a));
540 ntohs(sa->in6.sin6_port));
554 if (salen <= offsetof(struct sockaddr_un, sun_path)) {
555 p = strdup("<unnamed>");
559 } else if (sa->un.sun_path[0] == 0) {
562 /* FIXME: We assume we can print the
563 * socket path here and that it hasn't
564 * more than one NUL byte. That is
565 * actually an invalid assumption */
567 p = new(char, sizeof(sa->un.sun_path)+1);
572 memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1);
573 p[sizeof(sa->un.sun_path)] = 0;
576 p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path));
592 int getpeername_pretty(int fd, char **ret) {
593 union sockaddr_union sa;
594 socklen_t salen = sizeof(sa);
600 if (getpeername(fd, &sa.sa, &salen) < 0)
603 if (sa.sa.sa_family == AF_UNIX) {
604 struct ucred ucred = {};
606 /* UNIX connection sockets are anonymous, so let's use
607 * PID/UID as pretty credentials instead */
609 r = getpeercred(fd, &ucred);
613 if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0)
619 /* For remote sockets we translate IPv6 addresses back to IPv4
620 * if applicable, since that's nicer. */
622 return sockaddr_pretty(&sa.sa, salen, true, true, ret);
625 int getsockname_pretty(int fd, char **ret) {
626 union sockaddr_union sa;
627 socklen_t salen = sizeof(sa);
632 if (getsockname(fd, &sa.sa, &salen) < 0)
635 /* For local sockets we do not translate IPv6 addresses back
636 * to IPv6 if applicable, since this is usually used for
637 * listening sockets where the difference between IPv4 and
640 return sockaddr_pretty(&sa.sa, salen, false, true, ret);
643 int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) {
645 char host[NI_MAXHOST], *ret;
649 r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0,
650 NI_IDN|NI_IDN_USE_STD3_ASCII_RULES);
652 int saved_errno = errno;
654 r = sockaddr_pretty(&sa->sa, salen, true, true, &ret);
656 return log_error_errno(r, "sockadd_pretty() failed: %m");
658 log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret);
669 int getnameinfo_pretty(int fd, char **ret) {
670 union sockaddr_union sa;
671 socklen_t salen = sizeof(sa);
676 if (getsockname(fd, &sa.sa, &salen) < 0)
677 return log_error_errno(errno, "getsockname(%d) failed: %m", fd);
679 return socknameinfo_pretty(&sa, salen, ret);
682 int socket_address_unlink(SocketAddress *a) {
685 if (socket_address_family(a) != AF_UNIX)
688 if (a->sockaddr.un.sun_path[0] == 0)
691 if (unlink(a->sockaddr.un.sun_path) < 0)
697 static const char* const netlink_family_table[] = {
698 [NETLINK_ROUTE] = "route",
699 [NETLINK_FIREWALL] = "firewall",
700 [NETLINK_INET_DIAG] = "inet-diag",
701 [NETLINK_NFLOG] = "nflog",
702 [NETLINK_XFRM] = "xfrm",
703 [NETLINK_SELINUX] = "selinux",
704 [NETLINK_ISCSI] = "iscsi",
705 [NETLINK_AUDIT] = "audit",
706 [NETLINK_FIB_LOOKUP] = "fib-lookup",
707 [NETLINK_CONNECTOR] = "connector",
708 [NETLINK_NETFILTER] = "netfilter",
709 [NETLINK_IP6_FW] = "ip6-fw",
710 [NETLINK_DNRTMSG] = "dnrtmsg",
711 [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
712 [NETLINK_GENERIC] = "generic",
713 [NETLINK_SCSITRANSPORT] = "scsitransport",
714 [NETLINK_ECRYPTFS] = "ecryptfs"
717 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
719 static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
720 [SOCKET_ADDRESS_DEFAULT] = "default",
721 [SOCKET_ADDRESS_BOTH] = "both",
722 [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
725 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
727 bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
731 if (a->sa.sa_family != b->sa.sa_family)
734 if (a->sa.sa_family == AF_INET)
735 return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
737 if (a->sa.sa_family == AF_INET6)
738 return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
743 char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
747 /* Like ether_ntoa() but uses %02x instead of %x to print
748 * ethernet addresses, which makes them look less funny. Also,
749 * doesn't use a static buffer. */
751 sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
752 addr->ether_addr_octet[0],
753 addr->ether_addr_octet[1],
754 addr->ether_addr_octet[2],
755 addr->ether_addr_octet[3],
756 addr->ether_addr_octet[4],
757 addr->ether_addr_octet[5]);