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>
29 #include <sys/types.h>
33 #include "formats-util.h"
36 #include "path-util.h"
37 #include "string-util.h"
39 #include "socket-util.h"
41 int socket_address_parse(SocketAddress
*a
, const char *s
) {
50 a
->type
= SOCK_STREAM
;
53 /* IPv6 in [x:.....:z]:p notation */
59 n
= strndupa(s
+1, e
-s
-1);
62 if (inet_pton(AF_INET6
, n
, &a
->sockaddr
.in6
.sin6_addr
) <= 0)
63 return errno
> 0 ? -errno
: -EINVAL
;
74 if (u
<= 0 || u
> 0xFFFF)
77 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
78 a
->sockaddr
.in6
.sin6_port
= htons((uint16_t) u
);
79 a
->size
= sizeof(struct sockaddr_in6
);
81 } else if (*s
== '/') {
87 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
))
90 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
91 memcpy(a
->sockaddr
.un
.sun_path
, s
, l
);
92 a
->size
= offsetof(struct sockaddr_un
, sun_path
) + l
+ 1;
94 } else if (*s
== '@') {
95 /* Abstract AF_UNIX socket */
99 if (l
>= sizeof(a
->sockaddr
.un
.sun_path
) - 1)
102 a
->sockaddr
.un
.sun_family
= AF_UNIX
;
103 memcpy(a
->sockaddr
.un
.sun_path
+1, s
+1, l
);
104 a
->size
= offsetof(struct sockaddr_un
, sun_path
) + 1 + l
;
109 r
= safe_atou(e
+1, &u
);
113 if (u
<= 0 || u
> 0xFFFF)
116 n
= strndupa(s
, e
-s
);
118 /* IPv4 in w.x.y.z:p notation? */
119 r
= inet_pton(AF_INET
, n
, &a
->sockaddr
.in
.sin_addr
);
124 /* Gotcha, it's a traditional IPv4 address */
125 a
->sockaddr
.in
.sin_family
= AF_INET
;
126 a
->sockaddr
.in
.sin_port
= htons((uint16_t) u
);
127 a
->size
= sizeof(struct sockaddr_in
);
131 if (strlen(n
) > IF_NAMESIZE
-1)
134 /* Uh, our last resort, an interface name */
135 idx
= if_nametoindex(n
);
139 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
140 a
->sockaddr
.in6
.sin6_port
= htons((uint16_t) u
);
141 a
->sockaddr
.in6
.sin6_scope_id
= idx
;
142 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
143 a
->size
= sizeof(struct sockaddr_in6
);
148 r
= safe_atou(s
, &u
);
152 if (u
<= 0 || u
> 0xFFFF)
155 if (socket_ipv6_is_supported()) {
156 a
->sockaddr
.in6
.sin6_family
= AF_INET6
;
157 a
->sockaddr
.in6
.sin6_port
= htons((uint16_t) u
);
158 a
->sockaddr
.in6
.sin6_addr
= in6addr_any
;
159 a
->size
= sizeof(struct sockaddr_in6
);
161 a
->sockaddr
.in
.sin_family
= AF_INET
;
162 a
->sockaddr
.in
.sin_port
= htons((uint16_t) u
);
163 a
->sockaddr
.in
.sin_addr
.s_addr
= INADDR_ANY
;
164 a
->size
= sizeof(struct sockaddr_in
);
172 int socket_address_parse_and_warn(SocketAddress
*a
, const char *s
) {
176 /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */
178 r
= socket_address_parse(&b
, s
);
182 if (!socket_ipv6_is_supported() && b
.sockaddr
.sa
.sa_family
== AF_INET6
) {
183 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
184 return -EAFNOSUPPORT
;
191 int socket_address_parse_netlink(SocketAddress
*a
, const char *s
) {
194 _cleanup_free_
char *sfamily
= NULL
;
202 if (sscanf(s
, "%ms %u", &sfamily
, &group
) < 1)
203 return errno
> 0 ? -errno
: -EINVAL
;
205 family
= netlink_family_from_string(sfamily
);
209 a
->sockaddr
.nl
.nl_family
= AF_NETLINK
;
210 a
->sockaddr
.nl
.nl_groups
= group
;
213 a
->size
= sizeof(struct sockaddr_nl
);
214 a
->protocol
= family
;
219 int socket_address_verify(const SocketAddress
*a
) {
222 switch (socket_address_family(a
)) {
225 if (a
->size
!= sizeof(struct sockaddr_in
))
228 if (a
->sockaddr
.in
.sin_port
== 0)
231 if (a
->type
!= SOCK_STREAM
&& a
->type
!= SOCK_DGRAM
)
237 if (a
->size
!= sizeof(struct sockaddr_in6
))
240 if (a
->sockaddr
.in6
.sin6_port
== 0)
243 if (a
->type
!= SOCK_STREAM
&& a
->type
!= SOCK_DGRAM
)
249 if (a
->size
< offsetof(struct sockaddr_un
, sun_path
))
252 if (a
->size
> offsetof(struct sockaddr_un
, sun_path
)) {
254 if (a
->sockaddr
.un
.sun_path
[0] != 0) {
258 e
= memchr(a
->sockaddr
.un
.sun_path
, 0, sizeof(a
->sockaddr
.un
.sun_path
));
262 if (a
->size
!= offsetof(struct sockaddr_un
, sun_path
) + (e
- a
->sockaddr
.un
.sun_path
) + 1)
267 if (a
->type
!= SOCK_STREAM
&& a
->type
!= SOCK_DGRAM
&& a
->type
!= SOCK_SEQPACKET
)
274 if (a
->size
!= sizeof(struct sockaddr_nl
))
277 if (a
->type
!= SOCK_RAW
&& a
->type
!= SOCK_DGRAM
)
283 return -EAFNOSUPPORT
;
287 int socket_address_print(const SocketAddress
*a
, char **ret
) {
293 r
= socket_address_verify(a
);
297 if (socket_address_family(a
) == AF_NETLINK
) {
298 _cleanup_free_
char *sfamily
= NULL
;
300 r
= netlink_family_to_string_alloc(a
->protocol
, &sfamily
);
304 r
= asprintf(ret
, "%s %u", sfamily
, a
->sockaddr
.nl
.nl_groups
);
311 return sockaddr_pretty(&a
->sockaddr
.sa
, a
->size
, false, true, ret
);
314 bool socket_address_can_accept(const SocketAddress
*a
) {
318 a
->type
== SOCK_STREAM
||
319 a
->type
== SOCK_SEQPACKET
;
322 bool socket_address_equal(const SocketAddress
*a
, const SocketAddress
*b
) {
326 /* Invalid addresses are unequal to all */
327 if (socket_address_verify(a
) < 0 ||
328 socket_address_verify(b
) < 0)
331 if (a
->type
!= b
->type
)
334 if (socket_address_family(a
) != socket_address_family(b
))
337 switch (socket_address_family(a
)) {
340 if (a
->sockaddr
.in
.sin_addr
.s_addr
!= b
->sockaddr
.in
.sin_addr
.s_addr
)
343 if (a
->sockaddr
.in
.sin_port
!= b
->sockaddr
.in
.sin_port
)
349 if (memcmp(&a
->sockaddr
.in6
.sin6_addr
, &b
->sockaddr
.in6
.sin6_addr
, sizeof(a
->sockaddr
.in6
.sin6_addr
)) != 0)
352 if (a
->sockaddr
.in6
.sin6_port
!= b
->sockaddr
.in6
.sin6_port
)
358 if (a
->size
<= offsetof(struct sockaddr_un
, sun_path
) ||
359 b
->size
<= offsetof(struct sockaddr_un
, sun_path
))
362 if ((a
->sockaddr
.un
.sun_path
[0] == 0) != (b
->sockaddr
.un
.sun_path
[0] == 0))
365 if (a
->sockaddr
.un
.sun_path
[0]) {
366 if (!path_equal_or_files_same(a
->sockaddr
.un
.sun_path
, b
->sockaddr
.un
.sun_path
))
369 if (a
->size
!= b
->size
)
372 if (memcmp(a
->sockaddr
.un
.sun_path
, b
->sockaddr
.un
.sun_path
, a
->size
) != 0)
379 if (a
->protocol
!= b
->protocol
)
382 if (a
->sockaddr
.nl
.nl_groups
!= b
->sockaddr
.nl
.nl_groups
)
388 /* Cannot compare, so we assume the addresses are different */
395 bool socket_address_is(const SocketAddress
*a
, const char *s
, int type
) {
396 struct SocketAddress b
;
401 if (socket_address_parse(&b
, s
) < 0)
406 return socket_address_equal(a
, &b
);
409 bool socket_address_is_netlink(const SocketAddress
*a
, const char *s
) {
410 struct SocketAddress b
;
415 if (socket_address_parse_netlink(&b
, s
) < 0)
418 return socket_address_equal(a
, &b
);
421 const char* socket_address_get_path(const SocketAddress
*a
) {
424 if (socket_address_family(a
) != AF_UNIX
)
427 if (a
->sockaddr
.un
.sun_path
[0] == 0)
430 return a
->sockaddr
.un
.sun_path
;
433 bool socket_ipv6_is_supported(void) {
434 _cleanup_free_
char *l
= NULL
;
436 if (access("/sys/module/ipv6", F_OK
) != 0)
439 /* If we can't check "disable" parameter, assume enabled */
440 if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l
) < 0)
443 /* If module was loaded with disable=1 no IPv6 available */
447 bool socket_address_matches_fd(const SocketAddress
*a
, int fd
) {
454 b
.size
= sizeof(b
.sockaddr
);
455 if (getsockname(fd
, &b
.sockaddr
.sa
, &b
.size
) < 0)
458 if (b
.sockaddr
.sa
.sa_family
!= a
->sockaddr
.sa
.sa_family
)
461 solen
= sizeof(b
.type
);
462 if (getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &b
.type
, &solen
) < 0)
465 if (b
.type
!= a
->type
)
468 if (a
->protocol
!= 0) {
469 solen
= sizeof(b
.protocol
);
470 if (getsockopt(fd
, SOL_SOCKET
, SO_PROTOCOL
, &b
.protocol
, &solen
) < 0)
473 if (b
.protocol
!= a
->protocol
)
477 return socket_address_equal(a
, &b
);
480 int sockaddr_port(const struct sockaddr
*_sa
) {
481 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
485 if (!IN_SET(sa
->sa
.sa_family
, AF_INET
, AF_INET6
))
486 return -EAFNOSUPPORT
;
488 return ntohs(sa
->sa
.sa_family
== AF_INET6
?
493 int sockaddr_pretty(const struct sockaddr
*_sa
, socklen_t salen
, bool translate_ipv6
, bool include_port
, char **ret
) {
494 union sockaddr_union
*sa
= (union sockaddr_union
*) _sa
;
499 assert(salen
>= sizeof(sa
->sa
.sa_family
));
501 switch (sa
->sa
.sa_family
) {
506 a
= ntohl(sa
->in
.sin_addr
.s_addr
);
511 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF,
512 ntohs(sa
->in
.sin_port
));
516 a
>> 24, (a
>> 16) & 0xFF, (a
>> 8) & 0xFF, a
& 0xFF);
523 static const unsigned char ipv4_prefix
[] = {
524 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
527 if (translate_ipv6
&&
528 memcmp(&sa
->in6
.sin6_addr
, ipv4_prefix
, sizeof(ipv4_prefix
)) == 0) {
529 const uint8_t *a
= sa
->in6
.sin6_addr
.s6_addr
+12;
533 a
[0], a
[1], a
[2], a
[3],
534 ntohs(sa
->in6
.sin6_port
));
538 a
[0], a
[1], a
[2], a
[3]);
542 char a
[INET6_ADDRSTRLEN
];
544 inet_ntop(AF_INET6
, &sa
->in6
.sin6_addr
, a
, sizeof(a
));
550 ntohs(sa
->in6
.sin6_port
));
564 if (salen
<= offsetof(struct sockaddr_un
, sun_path
)) {
565 p
= strdup("<unnamed>");
569 } else if (sa
->un
.sun_path
[0] == 0) {
572 /* FIXME: We assume we can print the
573 * socket path here and that it hasn't
574 * more than one NUL byte. That is
575 * actually an invalid assumption */
577 p
= new(char, sizeof(sa
->un
.sun_path
)+1);
582 memcpy(p
+1, sa
->un
.sun_path
+1, sizeof(sa
->un
.sun_path
)-1);
583 p
[sizeof(sa
->un
.sun_path
)] = 0;
586 p
= strndup(sa
->un
.sun_path
, sizeof(sa
->un
.sun_path
));
602 int getpeername_pretty(int fd
, char **ret
) {
603 union sockaddr_union sa
;
604 socklen_t salen
= sizeof(sa
);
610 if (getpeername(fd
, &sa
.sa
, &salen
) < 0)
613 if (sa
.sa
.sa_family
== AF_UNIX
) {
614 struct ucred ucred
= {};
616 /* UNIX connection sockets are anonymous, so let's use
617 * PID/UID as pretty credentials instead */
619 r
= getpeercred(fd
, &ucred
);
623 if (asprintf(ret
, "PID "PID_FMT
"/UID "UID_FMT
, ucred
.pid
, ucred
.uid
) < 0)
629 /* For remote sockets we translate IPv6 addresses back to IPv4
630 * if applicable, since that's nicer. */
632 return sockaddr_pretty(&sa
.sa
, salen
, true, true, ret
);
635 int getsockname_pretty(int fd
, char **ret
) {
636 union sockaddr_union sa
;
637 socklen_t salen
= sizeof(sa
);
642 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
645 /* For local sockets we do not translate IPv6 addresses back
646 * to IPv6 if applicable, since this is usually used for
647 * listening sockets where the difference between IPv4 and
650 return sockaddr_pretty(&sa
.sa
, salen
, false, true, ret
);
653 int socknameinfo_pretty(union sockaddr_union
*sa
, socklen_t salen
, char **_ret
) {
655 char host
[NI_MAXHOST
], *ret
;
659 r
= getnameinfo(&sa
->sa
, salen
, host
, sizeof(host
), NULL
, 0,
660 NI_IDN
|NI_IDN_USE_STD3_ASCII_RULES
);
662 int saved_errno
= errno
;
664 r
= sockaddr_pretty(&sa
->sa
, salen
, true, true, &ret
);
668 log_debug_errno(saved_errno
, "getnameinfo(%s) failed: %m", ret
);
679 int getnameinfo_pretty(int fd
, char **ret
) {
680 union sockaddr_union sa
;
681 socklen_t salen
= sizeof(sa
);
686 if (getsockname(fd
, &sa
.sa
, &salen
) < 0)
689 return socknameinfo_pretty(&sa
, salen
, ret
);
692 int socket_address_unlink(SocketAddress
*a
) {
695 if (socket_address_family(a
) != AF_UNIX
)
698 if (a
->sockaddr
.un
.sun_path
[0] == 0)
701 if (unlink(a
->sockaddr
.un
.sun_path
) < 0)
707 static const char* const netlink_family_table
[] = {
708 [NETLINK_ROUTE
] = "route",
709 [NETLINK_FIREWALL
] = "firewall",
710 [NETLINK_INET_DIAG
] = "inet-diag",
711 [NETLINK_NFLOG
] = "nflog",
712 [NETLINK_XFRM
] = "xfrm",
713 [NETLINK_SELINUX
] = "selinux",
714 [NETLINK_ISCSI
] = "iscsi",
715 [NETLINK_AUDIT
] = "audit",
716 [NETLINK_FIB_LOOKUP
] = "fib-lookup",
717 [NETLINK_CONNECTOR
] = "connector",
718 [NETLINK_NETFILTER
] = "netfilter",
719 [NETLINK_IP6_FW
] = "ip6-fw",
720 [NETLINK_DNRTMSG
] = "dnrtmsg",
721 [NETLINK_KOBJECT_UEVENT
] = "kobject-uevent",
722 [NETLINK_GENERIC
] = "generic",
723 [NETLINK_SCSITRANSPORT
] = "scsitransport",
724 [NETLINK_ECRYPTFS
] = "ecryptfs"
727 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family
, int, INT_MAX
);
729 static const char* const socket_address_bind_ipv6_only_table
[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX
] = {
730 [SOCKET_ADDRESS_DEFAULT
] = "default",
731 [SOCKET_ADDRESS_BOTH
] = "both",
732 [SOCKET_ADDRESS_IPV6_ONLY
] = "ipv6-only"
735 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only
, SocketAddressBindIPv6Only
);
737 bool sockaddr_equal(const union sockaddr_union
*a
, const union sockaddr_union
*b
) {
741 if (a
->sa
.sa_family
!= b
->sa
.sa_family
)
744 if (a
->sa
.sa_family
== AF_INET
)
745 return a
->in
.sin_addr
.s_addr
== b
->in
.sin_addr
.s_addr
;
747 if (a
->sa
.sa_family
== AF_INET6
)
748 return memcmp(&a
->in6
.sin6_addr
, &b
->in6
.sin6_addr
, sizeof(a
->in6
.sin6_addr
)) == 0;
753 char* ether_addr_to_string(const struct ether_addr
*addr
, char buffer
[ETHER_ADDR_TO_STRING_MAX
]) {
757 /* Like ether_ntoa() but uses %02x instead of %x to print
758 * ethernet addresses, which makes them look less funny. Also,
759 * doesn't use a static buffer. */
761 sprintf(buffer
, "%02x:%02x:%02x:%02x:%02x:%02x",
762 addr
->ether_addr_octet
[0],
763 addr
->ether_addr_octet
[1],
764 addr
->ether_addr_octet
[2],
765 addr
->ether_addr_octet
[3],
766 addr
->ether_addr_octet
[4],
767 addr
->ether_addr_octet
[5]);