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/>.
27 #include <arpa/inet.h>
30 #include <sys/types.h>
33 #include <sys/ioctl.h>
39 #include "path-util.h"
40 #include "socket-util.h"
44 int socket_address_parse(SocketAddress *a, const char *s) {
53 a->type = SOCK_STREAM;
56 /* IPv6 in [x:.....:z]:p notation */
58 if (!socket_ipv6_is_supported()) {
59 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
67 n = strndupa(s+1, e-s-1);
70 if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0)
71 return errno > 0 ? -errno : -EINVAL;
82 if (u <= 0 || u > 0xFFFF)
85 a->sockaddr.in6.sin6_family = AF_INET6;
86 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
87 a->size = sizeof(struct sockaddr_in6);
89 } else if (*s == '/') {
95 if (l >= sizeof(a->sockaddr.un.sun_path))
98 a->sockaddr.un.sun_family = AF_UNIX;
99 memcpy(a->sockaddr.un.sun_path, s, l);
100 a->size = offsetof(struct sockaddr_un, sun_path) + l + 1;
102 } else if (*s == '@') {
103 /* Abstract AF_UNIX socket */
107 if (l >= sizeof(a->sockaddr.un.sun_path) - 1)
110 a->sockaddr.un.sun_family = AF_UNIX;
111 memcpy(a->sockaddr.un.sun_path+1, s+1, l);
112 a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
117 r = safe_atou(e+1, &u);
121 if (u <= 0 || u > 0xFFFF)
124 n = strndupa(s, e-s);
126 /* IPv4 in w.x.y.z:p notation? */
127 r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr);
132 /* Gotcha, it's a traditional IPv4 address */
133 a->sockaddr.in.sin_family = AF_INET;
134 a->sockaddr.in.sin_port = htons((uint16_t) u);
135 a->size = sizeof(struct sockaddr_in);
139 if (strlen(n) > IF_NAMESIZE-1)
142 /* Uh, our last resort, an interface name */
143 idx = if_nametoindex(n);
147 if (!socket_ipv6_is_supported()) {
148 log_warning("Binding to interface is not available since kernel does not support IPv6.");
149 return -EAFNOSUPPORT;
152 a->sockaddr.in6.sin6_family = AF_INET6;
153 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
154 a->sockaddr.in6.sin6_scope_id = idx;
155 a->sockaddr.in6.sin6_addr = in6addr_any;
156 a->size = sizeof(struct sockaddr_in6);
161 r = safe_atou(s, &u);
165 if (u <= 0 || u > 0xFFFF)
168 if (socket_ipv6_is_supported()) {
169 a->sockaddr.in6.sin6_family = AF_INET6;
170 a->sockaddr.in6.sin6_port = htons((uint16_t) u);
171 a->sockaddr.in6.sin6_addr = in6addr_any;
172 a->size = sizeof(struct sockaddr_in6);
174 a->sockaddr.in.sin_family = AF_INET;
175 a->sockaddr.in.sin_port = htons((uint16_t) u);
176 a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
177 a->size = sizeof(struct sockaddr_in);
185 int socket_address_parse_netlink(SocketAddress *a, const char *s) {
188 _cleanup_free_ char *sfamily = NULL;
196 if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
197 return errno > 0 ? -errno : -EINVAL;
199 family = netlink_family_from_string(sfamily);
203 a->sockaddr.nl.nl_family = AF_NETLINK;
204 a->sockaddr.nl.nl_groups = group;
207 a->size = sizeof(struct sockaddr_nl);
208 a->protocol = family;
213 int socket_address_verify(const SocketAddress *a) {
216 switch (socket_address_family(a)) {
219 if (a->size != sizeof(struct sockaddr_in))
222 if (a->sockaddr.in.sin_port == 0)
225 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
231 if (a->size != sizeof(struct sockaddr_in6))
234 if (a->sockaddr.in6.sin6_port == 0)
237 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
243 if (a->size < offsetof(struct sockaddr_un, sun_path))
246 if (a->size > offsetof(struct sockaddr_un, sun_path)) {
248 if (a->sockaddr.un.sun_path[0] != 0) {
252 e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
256 if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
261 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET)
268 if (a->size != sizeof(struct sockaddr_nl))
271 if (a->type != SOCK_RAW && a->type != SOCK_DGRAM)
277 return -EAFNOSUPPORT;
281 int socket_address_print(const SocketAddress *a, char **ret) {
287 r = socket_address_verify(a);
291 if (socket_address_family(a) == AF_NETLINK) {
292 _cleanup_free_ char *sfamily = NULL;
294 r = netlink_family_to_string_alloc(a->protocol, &sfamily);
298 r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
305 return sockaddr_pretty(&a->sockaddr.sa, a->size, false, ret);
308 bool socket_address_can_accept(const SocketAddress *a) {
312 a->type == SOCK_STREAM ||
313 a->type == SOCK_SEQPACKET;
316 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
320 /* Invalid addresses are unequal to all */
321 if (socket_address_verify(a) < 0 ||
322 socket_address_verify(b) < 0)
325 if (a->type != b->type)
328 if (socket_address_family(a) != socket_address_family(b))
331 switch (socket_address_family(a)) {
334 if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr)
337 if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port)
343 if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0)
346 if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
352 if (a->size <= offsetof(struct sockaddr_un, sun_path) ||
353 b->size <= offsetof(struct sockaddr_un, sun_path))
356 if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
359 if (a->sockaddr.un.sun_path[0]) {
360 if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path))
363 if (a->size != b->size)
366 if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
373 if (a->protocol != b->protocol)
376 if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
382 /* Cannot compare, so we assume the addresses are different */
389 bool socket_address_is(const SocketAddress *a, const char *s, int type) {
390 struct SocketAddress b;
395 if (socket_address_parse(&b, s) < 0)
400 return socket_address_equal(a, &b);
403 bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
404 struct SocketAddress b;
409 if (socket_address_parse_netlink(&b, s) < 0)
412 return socket_address_equal(a, &b);
415 const char* socket_address_get_path(const SocketAddress *a) {
418 if (socket_address_family(a) != AF_UNIX)
421 if (a->sockaddr.un.sun_path[0] == 0)
424 return a->sockaddr.un.sun_path;
427 bool socket_ipv6_is_supported(void) {
428 _cleanup_free_ char *l = NULL;
430 if (access("/sys/module/ipv6", F_OK) != 0)
433 /* If we can't check "disable" parameter, assume enabled */
434 if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l) < 0)
437 /* If module was loaded with disable=1 no IPv6 available */
441 bool socket_address_matches_fd(const SocketAddress *a, int fd) {
448 b.size = sizeof(b.sockaddr);
449 if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0)
452 if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family)
455 solen = sizeof(b.type);
456 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0)
459 if (b.type != a->type)
462 if (a->protocol != 0) {
463 solen = sizeof(b.protocol);
464 if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0)
467 if (b.protocol != a->protocol)
471 return socket_address_equal(a, &b);
474 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, char **ret) {
475 union sockaddr_union *sa = (union sockaddr_union*) _sa;
479 assert(salen >= sizeof(sa->sa.sa_family));
481 switch (sa->sa.sa_family) {
486 a = ntohl(sa->in.sin_addr.s_addr);
490 a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
491 ntohs(sa->in.sin_port)) < 0)
498 static const unsigned char ipv4_prefix[] = {
499 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
502 if (translate_ipv6 && memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
503 const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;
507 a[0], a[1], a[2], a[3],
508 ntohs(sa->in6.sin6_port)) < 0)
511 char a[INET6_ADDRSTRLEN];
515 inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)),
516 ntohs(sa->in6.sin6_port)) < 0)
524 if (salen <= offsetof(struct sockaddr_un, sun_path)) {
525 p = strdup("<unnamed>");
529 } else if (sa->un.sun_path[0] == 0) {
532 /* FIXME: We assume we can print the
533 * socket path here and that it hasn't
534 * more than one NUL byte. That is
535 * actually an invalid assumption */
537 p = new(char, sizeof(sa->un.sun_path)+1);
542 memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1);
543 p[sizeof(sa->un.sun_path)] = 0;
546 p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path));
562 int getpeername_pretty(int fd, char **ret) {
563 union sockaddr_union sa;
564 socklen_t salen = sizeof(sa);
570 if (getpeername(fd, &sa.sa, &salen) < 0)
573 if (sa.sa.sa_family == AF_UNIX) {
574 struct ucred ucred = {};
576 /* UNIX connection sockets are anonymous, so let's use
577 * PID/UID as pretty credentials instead */
579 r = getpeercred(fd, &ucred);
583 if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0)
589 /* For remote sockets we translate IPv6 addresses back to IPv4
590 * if applicable, since that's nicer. */
592 return sockaddr_pretty(&sa.sa, salen, true, ret);
595 int getsockname_pretty(int fd, char **ret) {
596 union sockaddr_union sa;
597 socklen_t salen = sizeof(sa);
602 if (getsockname(fd, &sa.sa, &salen) < 0)
605 /* For local sockets we do not translate IPv6 addresses back
606 * to IPv6 if applicable, since this is usually used for
607 * listening sockets where the difference between IPv4 and
610 return sockaddr_pretty(&sa.sa, salen, false, ret);
613 int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) {
615 char host[NI_MAXHOST], *ret;
619 r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0,
620 NI_IDN|NI_IDN_USE_STD3_ASCII_RULES);
622 int saved_errno = errno;
624 r = sockaddr_pretty(&sa->sa, salen, true, &ret);
626 return log_error_errno(r, "sockadd_pretty() failed: %m");
628 log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret);
639 int getnameinfo_pretty(int fd, char **ret) {
640 union sockaddr_union sa;
641 socklen_t salen = sizeof(sa);
646 if (getsockname(fd, &sa.sa, &salen) < 0)
647 return log_error_errno(errno, "getsockname(%d) failed: %m", fd);
649 return socknameinfo_pretty(&sa, salen, ret);
652 int socket_address_unlink(SocketAddress *a) {
655 if (socket_address_family(a) != AF_UNIX)
658 if (a->sockaddr.un.sun_path[0] == 0)
661 if (unlink(a->sockaddr.un.sun_path) < 0)
667 static const char* const netlink_family_table[] = {
668 [NETLINK_ROUTE] = "route",
669 [NETLINK_FIREWALL] = "firewall",
670 [NETLINK_INET_DIAG] = "inet-diag",
671 [NETLINK_NFLOG] = "nflog",
672 [NETLINK_XFRM] = "xfrm",
673 [NETLINK_SELINUX] = "selinux",
674 [NETLINK_ISCSI] = "iscsi",
675 [NETLINK_AUDIT] = "audit",
676 [NETLINK_FIB_LOOKUP] = "fib-lookup",
677 [NETLINK_CONNECTOR] = "connector",
678 [NETLINK_NETFILTER] = "netfilter",
679 [NETLINK_IP6_FW] = "ip6-fw",
680 [NETLINK_DNRTMSG] = "dnrtmsg",
681 [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
682 [NETLINK_GENERIC] = "generic",
683 [NETLINK_SCSITRANSPORT] = "scsitransport",
684 [NETLINK_ECRYPTFS] = "ecryptfs"
687 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
689 static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
690 [SOCKET_ADDRESS_DEFAULT] = "default",
691 [SOCKET_ADDRESS_BOTH] = "both",
692 [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
695 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
697 bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
701 if (a->sa.sa_family != b->sa.sa_family)
704 if (a->sa.sa_family == AF_INET)
705 return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
707 if (a->sa.sa_family == AF_INET6)
708 return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
713 char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
717 /* Like ether_ntoa() but uses %02x instead of %x to print
718 * ethernet addresses, which makes them look less funny. Also,
719 * doesn't use a static buffer. */
721 sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
722 addr->ether_addr_octet[0],
723 addr->ether_addr_octet[1],
724 addr->ether_addr_octet[2],
725 addr->ether_addr_octet[3],
726 addr->ether_addr_octet[4],
727 addr->ether_addr_octet[5]);