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->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) {
438 union sockaddr_union sa;
439 socklen_t salen = sizeof(sa), solen;
445 if (getsockname(fd, &sa.sa, &salen) < 0)
448 if (sa.sa.sa_family != a->sockaddr.sa.sa_family)
451 solen = sizeof(type);
452 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &solen) < 0)
458 if (a->protocol != 0) {
459 solen = sizeof(protocol);
460 if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &solen) < 0)
463 if (protocol != a->protocol)
467 switch (sa.sa.sa_family) {
470 return sa.in.sin_port == a->sockaddr.in.sin_port &&
471 sa.in.sin_addr.s_addr == a->sockaddr.in.sin_addr.s_addr;
474 return sa.in6.sin6_port == a->sockaddr.in6.sin6_port &&
475 memcmp(&sa.in6.sin6_addr, &a->sockaddr.in6.sin6_addr, sizeof(struct in6_addr)) == 0;
478 return salen == a->size &&
479 memcmp(sa.un.sun_path, a->sockaddr.un.sun_path, salen - offsetof(struct sockaddr_un, sun_path)) == 0;
486 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, char **ret) {
487 union sockaddr_union *sa = (union sockaddr_union*) _sa;
491 assert(salen >= sizeof(sa->sa.sa_family));
493 switch (sa->sa.sa_family) {
498 a = ntohl(sa->in.sin_addr.s_addr);
502 a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
503 ntohs(sa->in.sin_port)) < 0)
510 static const unsigned char ipv4_prefix[] = {
511 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
514 if (translate_ipv6 && memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
515 const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;
519 a[0], a[1], a[2], a[3],
520 ntohs(sa->in6.sin6_port)) < 0)
523 char a[INET6_ADDRSTRLEN];
527 inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)),
528 ntohs(sa->in6.sin6_port)) < 0)
536 if (salen <= offsetof(struct sockaddr_un, sun_path)) {
537 p = strdup("<unnamed>");
541 } else if (sa->un.sun_path[0] == 0) {
544 /* FIXME: We assume we can print the
545 * socket path here and that it hasn't
546 * more than one NUL byte. That is
547 * actually an invalid assumption */
549 p = new(char, sizeof(sa->un.sun_path)+1);
554 memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1);
555 p[sizeof(sa->un.sun_path)] = 0;
558 p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path));
574 int getpeername_pretty(int fd, char **ret) {
575 union sockaddr_union sa;
576 socklen_t salen = sizeof(sa);
582 if (getpeername(fd, &sa.sa, &salen) < 0)
585 if (sa.sa.sa_family == AF_UNIX) {
586 struct ucred ucred = {};
588 /* UNIX connection sockets are anonymous, so let's use
589 * PID/UID as pretty credentials instead */
591 r = getpeercred(fd, &ucred);
595 if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0)
601 /* For remote sockets we translate IPv6 addresses back to IPv4
602 * if applicable, since that's nicer. */
604 return sockaddr_pretty(&sa.sa, salen, true, ret);
607 int getsockname_pretty(int fd, char **ret) {
608 union sockaddr_union sa;
609 socklen_t salen = sizeof(sa);
614 if (getsockname(fd, &sa.sa, &salen) < 0)
617 /* For local sockets we do not translate IPv6 addresses back
618 * to IPv6 if applicable, since this is usually used for
619 * listening sockets where the difference between IPv4 and
622 return sockaddr_pretty(&sa.sa, salen, false, ret);
625 int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) {
627 char host[NI_MAXHOST], *ret;
631 r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0,
632 NI_IDN|NI_IDN_USE_STD3_ASCII_RULES);
634 int saved_errno = errno;
636 r = sockaddr_pretty(&sa->sa, salen, true, &ret);
638 return log_error_errno(r, "sockadd_pretty() failed: %m");
640 log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret);
651 int getnameinfo_pretty(int fd, char **ret) {
652 union sockaddr_union sa;
653 socklen_t salen = sizeof(sa);
658 if (getsockname(fd, &sa.sa, &salen) < 0)
659 return log_error_errno(errno, "getsockname(%d) failed: %m", fd);
661 return socknameinfo_pretty(&sa, salen, ret);
664 int socket_address_unlink(SocketAddress *a) {
667 if (socket_address_family(a) != AF_UNIX)
670 if (a->sockaddr.un.sun_path[0] == 0)
673 if (unlink(a->sockaddr.un.sun_path) < 0)
679 static const char* const netlink_family_table[] = {
680 [NETLINK_ROUTE] = "route",
681 [NETLINK_FIREWALL] = "firewall",
682 [NETLINK_INET_DIAG] = "inet-diag",
683 [NETLINK_NFLOG] = "nflog",
684 [NETLINK_XFRM] = "xfrm",
685 [NETLINK_SELINUX] = "selinux",
686 [NETLINK_ISCSI] = "iscsi",
687 [NETLINK_AUDIT] = "audit",
688 [NETLINK_FIB_LOOKUP] = "fib-lookup",
689 [NETLINK_CONNECTOR] = "connector",
690 [NETLINK_NETFILTER] = "netfilter",
691 [NETLINK_IP6_FW] = "ip6-fw",
692 [NETLINK_DNRTMSG] = "dnrtmsg",
693 [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
694 [NETLINK_GENERIC] = "generic",
695 [NETLINK_SCSITRANSPORT] = "scsitransport",
696 [NETLINK_ECRYPTFS] = "ecryptfs"
699 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
701 static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
702 [SOCKET_ADDRESS_DEFAULT] = "default",
703 [SOCKET_ADDRESS_BOTH] = "both",
704 [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
707 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
709 bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
713 if (a->sa.sa_family != b->sa.sa_family)
716 if (a->sa.sa_family == AF_INET)
717 return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
719 if (a->sa.sa_family == AF_INET6)
720 return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
725 char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
729 /* Like ether_ntoa() but uses %02x instead of %x to print
730 * ethernet addresses, which makes them look less funny. Also,
731 * doesn't use a static buffer. */
733 sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
734 addr->ether_addr_octet[0],
735 addr->ether_addr_octet[1],
736 addr->ether_addr_octet[2],
737 addr->ether_addr_octet[3],
738 addr->ether_addr_octet[4],
739 addr->ether_addr_octet[5]);