]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/socket-util.c
treewide: auto-convert the simple cases to log_*_errno()
[thirdparty/systemd.git] / src / shared / socket-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <assert.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <arpa/inet.h>
28 #include <stdio.h>
29 #include <net/if.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <stddef.h>
33 #include <sys/ioctl.h>
34 #include <netdb.h>
35
36 #include "macro.h"
37 #include "util.h"
38 #include "mkdir.h"
39 #include "path-util.h"
40 #include "socket-util.h"
41 #include "missing.h"
42 #include "fileio.h"
43
44 int socket_address_parse(SocketAddress *a, const char *s) {
45 char *e, *n;
46 unsigned u;
47 int r;
48
49 assert(a);
50 assert(s);
51
52 zero(*a);
53 a->type = SOCK_STREAM;
54
55 if (*s == '[') {
56 /* IPv6 in [x:.....:z]:p notation */
57
58 if (!socket_ipv6_is_supported()) {
59 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
60 return -EAFNOSUPPORT;
61 }
62
63 e = strchr(s+1, ']');
64 if (!e)
65 return -EINVAL;
66
67 n = strndupa(s+1, e-s-1);
68
69 errno = 0;
70 if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0)
71 return errno > 0 ? -errno : -EINVAL;
72
73 e++;
74 if (*e != ':')
75 return -EINVAL;
76
77 e++;
78 r = safe_atou(e, &u);
79 if (r < 0)
80 return r;
81
82 if (u <= 0 || u > 0xFFFF)
83 return -EINVAL;
84
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);
88
89 } else if (*s == '/') {
90 /* AF_UNIX socket */
91
92 size_t l;
93
94 l = strlen(s);
95 if (l >= sizeof(a->sockaddr.un.sun_path))
96 return -EINVAL;
97
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;
101
102 } else if (*s == '@') {
103 /* Abstract AF_UNIX socket */
104 size_t l;
105
106 l = strlen(s+1);
107 if (l >= sizeof(a->sockaddr.un.sun_path) - 1)
108 return -EINVAL;
109
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;
113
114 } else {
115 e = strchr(s, ':');
116 if (e) {
117 r = safe_atou(e+1, &u);
118 if (r < 0)
119 return r;
120
121 if (u <= 0 || u > 0xFFFF)
122 return -EINVAL;
123
124 n = strndupa(s, e-s);
125
126 /* IPv4 in w.x.y.z:p notation? */
127 r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr);
128 if (r < 0)
129 return -errno;
130
131 if (r > 0) {
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);
136 } else {
137 unsigned idx;
138
139 if (strlen(n) > IF_NAMESIZE-1)
140 return -EINVAL;
141
142 /* Uh, our last resort, an interface name */
143 idx = if_nametoindex(n);
144 if (idx == 0)
145 return -EINVAL;
146
147 if (!socket_ipv6_is_supported()) {
148 log_warning("Binding to interface is not available since kernel does not support IPv6.");
149 return -EAFNOSUPPORT;
150 }
151
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);
157 }
158 } else {
159
160 /* Just a port */
161 r = safe_atou(s, &u);
162 if (r < 0)
163 return r;
164
165 if (u <= 0 || u > 0xFFFF)
166 return -EINVAL;
167
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);
173 } else {
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);
178 }
179 }
180 }
181
182 return 0;
183 }
184
185 int socket_address_parse_netlink(SocketAddress *a, const char *s) {
186 int family;
187 unsigned group = 0;
188 _cleanup_free_ char *sfamily = NULL;
189 assert(a);
190 assert(s);
191
192 zero(*a);
193 a->type = SOCK_RAW;
194
195 errno = 0;
196 if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
197 return errno > 0 ? -errno : -EINVAL;
198
199 family = netlink_family_from_string(sfamily);
200 if (family < 0)
201 return -EINVAL;
202
203 a->sockaddr.nl.nl_family = AF_NETLINK;
204 a->sockaddr.nl.nl_groups = group;
205
206 a->type = SOCK_RAW;
207 a->size = sizeof(struct sockaddr_nl);
208 a->protocol = family;
209
210 return 0;
211 }
212
213 int socket_address_verify(const SocketAddress *a) {
214 assert(a);
215
216 switch (socket_address_family(a)) {
217
218 case AF_INET:
219 if (a->size != sizeof(struct sockaddr_in))
220 return -EINVAL;
221
222 if (a->sockaddr.in.sin_port == 0)
223 return -EINVAL;
224
225 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
226 return -EINVAL;
227
228 return 0;
229
230 case AF_INET6:
231 if (a->size != sizeof(struct sockaddr_in6))
232 return -EINVAL;
233
234 if (a->sockaddr.in6.sin6_port == 0)
235 return -EINVAL;
236
237 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
238 return -EINVAL;
239
240 return 0;
241
242 case AF_UNIX:
243 if (a->size < offsetof(struct sockaddr_un, sun_path))
244 return -EINVAL;
245
246 if (a->size > offsetof(struct sockaddr_un, sun_path)) {
247
248 if (a->sockaddr.un.sun_path[0] != 0) {
249 char *e;
250
251 /* path */
252 e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
253 if (!e)
254 return -EINVAL;
255
256 if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
257 return -EINVAL;
258 }
259 }
260
261 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET)
262 return -EINVAL;
263
264 return 0;
265
266 case AF_NETLINK:
267
268 if (a->size != sizeof(struct sockaddr_nl))
269 return -EINVAL;
270
271 if (a->type != SOCK_RAW && a->type != SOCK_DGRAM)
272 return -EINVAL;
273
274 return 0;
275
276 default:
277 return -EAFNOSUPPORT;
278 }
279 }
280
281 int socket_address_print(const SocketAddress *a, char **ret) {
282 int r;
283
284 assert(a);
285 assert(ret);
286
287 r = socket_address_verify(a);
288 if (r < 0)
289 return r;
290
291 if (socket_address_family(a) == AF_NETLINK) {
292 _cleanup_free_ char *sfamily = NULL;
293
294 r = netlink_family_to_string_alloc(a->protocol, &sfamily);
295 if (r < 0)
296 return r;
297
298 r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
299 if (r < 0)
300 return -ENOMEM;
301
302 return 0;
303 }
304
305 return sockaddr_pretty(&a->sockaddr.sa, a->size, false, ret);
306 }
307
308 bool socket_address_can_accept(const SocketAddress *a) {
309 assert(a);
310
311 return
312 a->type == SOCK_STREAM ||
313 a->type == SOCK_SEQPACKET;
314 }
315
316 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
317 assert(a);
318 assert(b);
319
320 /* Invalid addresses are unequal to all */
321 if (socket_address_verify(a) < 0 ||
322 socket_address_verify(b) < 0)
323 return false;
324
325 if (a->type != b->type)
326 return false;
327
328 if (a->size != b->size)
329 return false;
330
331 if (socket_address_family(a) != socket_address_family(b))
332 return false;
333
334 switch (socket_address_family(a)) {
335
336 case AF_INET:
337 if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr)
338 return false;
339
340 if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port)
341 return false;
342
343 break;
344
345 case AF_INET6:
346 if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0)
347 return false;
348
349 if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
350 return false;
351
352 break;
353
354 case AF_UNIX:
355
356 if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
357 return false;
358
359 if (a->sockaddr.un.sun_path[0]) {
360 if (!strneq(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, sizeof(a->sockaddr.un.sun_path)))
361 return false;
362 } else {
363 if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
364 return false;
365 }
366
367 break;
368
369 case AF_NETLINK:
370
371 if (a->protocol != b->protocol)
372 return false;
373
374 if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
375 return false;
376
377 break;
378
379 default:
380 /* Cannot compare, so we assume the addresses are different */
381 return false;
382 }
383
384 return true;
385 }
386
387 bool socket_address_is(const SocketAddress *a, const char *s, int type) {
388 struct SocketAddress b;
389
390 assert(a);
391 assert(s);
392
393 if (socket_address_parse(&b, s) < 0)
394 return false;
395
396 b.type = type;
397
398 return socket_address_equal(a, &b);
399 }
400
401 bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
402 struct SocketAddress b;
403
404 assert(a);
405 assert(s);
406
407 if (socket_address_parse_netlink(&b, s) < 0)
408 return false;
409
410 return socket_address_equal(a, &b);
411 }
412
413 const char* socket_address_get_path(const SocketAddress *a) {
414 assert(a);
415
416 if (socket_address_family(a) != AF_UNIX)
417 return NULL;
418
419 if (a->sockaddr.un.sun_path[0] == 0)
420 return NULL;
421
422 return a->sockaddr.un.sun_path;
423 }
424
425 bool socket_ipv6_is_supported(void) {
426 _cleanup_free_ char *l = NULL;
427
428 if (access("/sys/module/ipv6", F_OK) != 0)
429 return false;
430
431 /* If we can't check "disable" parameter, assume enabled */
432 if (read_one_line_file("/sys/module/ipv6/parameters/disable", &l) < 0)
433 return true;
434
435 /* If module was loaded with disable=1 no IPv6 available */
436 return l[0] == '0';
437 }
438
439 bool socket_address_matches_fd(const SocketAddress *a, int fd) {
440 union sockaddr_union sa;
441 socklen_t salen = sizeof(sa), solen;
442 int protocol, type;
443
444 assert(a);
445 assert(fd >= 0);
446
447 if (getsockname(fd, &sa.sa, &salen) < 0)
448 return false;
449
450 if (sa.sa.sa_family != a->sockaddr.sa.sa_family)
451 return false;
452
453 solen = sizeof(type);
454 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &solen) < 0)
455 return false;
456
457 if (type != a->type)
458 return false;
459
460 if (a->protocol != 0) {
461 solen = sizeof(protocol);
462 if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &solen) < 0)
463 return false;
464
465 if (protocol != a->protocol)
466 return false;
467 }
468
469 switch (sa.sa.sa_family) {
470
471 case AF_INET:
472 return sa.in.sin_port == a->sockaddr.in.sin_port &&
473 sa.in.sin_addr.s_addr == a->sockaddr.in.sin_addr.s_addr;
474
475 case AF_INET6:
476 return sa.in6.sin6_port == a->sockaddr.in6.sin6_port &&
477 memcmp(&sa.in6.sin6_addr, &a->sockaddr.in6.sin6_addr, sizeof(struct in6_addr)) == 0;
478
479 case AF_UNIX:
480 return salen == a->size &&
481 memcmp(sa.un.sun_path, a->sockaddr.un.sun_path, salen - offsetof(struct sockaddr_un, sun_path)) == 0;
482
483 }
484
485 return false;
486 }
487
488 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, char **ret) {
489 union sockaddr_union *sa = (union sockaddr_union*) _sa;
490 char *p;
491
492 assert(sa);
493 assert(salen >= sizeof(sa->sa.sa_family));
494
495 switch (sa->sa.sa_family) {
496
497 case AF_INET: {
498 uint32_t a;
499
500 a = ntohl(sa->in.sin_addr.s_addr);
501
502 if (asprintf(&p,
503 "%u.%u.%u.%u:%u",
504 a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
505 ntohs(sa->in.sin_port)) < 0)
506 return -ENOMEM;
507
508 break;
509 }
510
511 case AF_INET6: {
512 static const unsigned char ipv4_prefix[] = {
513 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
514 };
515
516 if (translate_ipv6 && memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
517 const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;
518
519 if (asprintf(&p,
520 "%u.%u.%u.%u:%u",
521 a[0], a[1], a[2], a[3],
522 ntohs(sa->in6.sin6_port)) < 0)
523 return -ENOMEM;
524 } else {
525 char a[INET6_ADDRSTRLEN];
526
527 if (asprintf(&p,
528 "[%s]:%u",
529 inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a)),
530 ntohs(sa->in6.sin6_port)) < 0)
531 return -ENOMEM;
532 }
533
534 break;
535 }
536
537 case AF_UNIX:
538 if (salen <= offsetof(struct sockaddr_un, sun_path)) {
539 p = strdup("<unnamed>");
540 if (!p)
541 return -ENOMEM;
542
543 } else if (sa->un.sun_path[0] == 0) {
544 /* abstract */
545
546 /* FIXME: We assume we can print the
547 * socket path here and that it hasn't
548 * more than one NUL byte. That is
549 * actually an invalid assumption */
550
551 p = new(char, sizeof(sa->un.sun_path)+1);
552 if (!p)
553 return -ENOMEM;
554
555 p[0] = '@';
556 memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1);
557 p[sizeof(sa->un.sun_path)] = 0;
558
559 } else {
560 p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path));
561 if (!ret)
562 return -ENOMEM;
563 }
564
565 break;
566
567 default:
568 return -ENOTSUP;
569 }
570
571
572 *ret = p;
573 return 0;
574 }
575
576 int getpeername_pretty(int fd, char **ret) {
577 union sockaddr_union sa;
578 socklen_t salen = sizeof(sa);
579 int r;
580
581 assert(fd >= 0);
582 assert(ret);
583
584 if (getpeername(fd, &sa.sa, &salen) < 0)
585 return -errno;
586
587 if (sa.sa.sa_family == AF_UNIX) {
588 struct ucred ucred = {};
589
590 /* UNIX connection sockets are anonymous, so let's use
591 * PID/UID as pretty credentials instead */
592
593 r = getpeercred(fd, &ucred);
594 if (r < 0)
595 return r;
596
597 if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0)
598 return -ENOMEM;
599
600 return 0;
601 }
602
603 /* For remote sockets we translate IPv6 addresses back to IPv4
604 * if applicable, since that's nicer. */
605
606 return sockaddr_pretty(&sa.sa, salen, true, ret);
607 }
608
609 int getsockname_pretty(int fd, char **ret) {
610 union sockaddr_union sa;
611 socklen_t salen = sizeof(sa);
612
613 assert(fd >= 0);
614 assert(ret);
615
616 if (getsockname(fd, &sa.sa, &salen) < 0)
617 return -errno;
618
619 /* For local sockets we do not translate IPv6 addresses back
620 * to IPv6 if applicable, since this is usually used for
621 * listening sockets where the difference between IPv4 and
622 * IPv6 matters. */
623
624 return sockaddr_pretty(&sa.sa, salen, false, ret);
625 }
626
627 int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) {
628 int r;
629 char host[NI_MAXHOST], *ret;
630
631 assert(_ret);
632
633 r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0,
634 NI_IDN|NI_IDN_USE_STD3_ASCII_RULES);
635 if (r != 0) {
636 int saved_errno = errno;
637
638 r = sockaddr_pretty(&sa->sa, salen, true, &ret);
639 if (r < 0) {
640 log_error_errno(-r, "sockadd_pretty() failed: %m");
641 return r;
642 }
643
644 log_debug("getnameinfo(%s) failed: %s", ret, strerror(saved_errno));
645 } else {
646 ret = strdup(host);
647 if (!ret)
648 return log_oom();
649 }
650
651 *_ret = ret;
652 return 0;
653 }
654
655 int getnameinfo_pretty(int fd, char **ret) {
656 union sockaddr_union sa;
657 socklen_t salen = sizeof(sa);
658
659 assert(fd >= 0);
660 assert(ret);
661
662 if (getsockname(fd, &sa.sa, &salen) < 0) {
663 log_error("getsockname(%d) failed: %m", fd);
664 return -errno;
665 }
666
667 return socknameinfo_pretty(&sa, salen, ret);
668 }
669
670 int socket_address_unlink(SocketAddress *a) {
671 assert(a);
672
673 if (socket_address_family(a) != AF_UNIX)
674 return 0;
675
676 if (a->sockaddr.un.sun_path[0] == 0)
677 return 0;
678
679 if (unlink(a->sockaddr.un.sun_path) < 0)
680 return -errno;
681
682 return 1;
683 }
684
685 static const char* const netlink_family_table[] = {
686 [NETLINK_ROUTE] = "route",
687 [NETLINK_FIREWALL] = "firewall",
688 [NETLINK_INET_DIAG] = "inet-diag",
689 [NETLINK_NFLOG] = "nflog",
690 [NETLINK_XFRM] = "xfrm",
691 [NETLINK_SELINUX] = "selinux",
692 [NETLINK_ISCSI] = "iscsi",
693 [NETLINK_AUDIT] = "audit",
694 [NETLINK_FIB_LOOKUP] = "fib-lookup",
695 [NETLINK_CONNECTOR] = "connector",
696 [NETLINK_NETFILTER] = "netfilter",
697 [NETLINK_IP6_FW] = "ip6-fw",
698 [NETLINK_DNRTMSG] = "dnrtmsg",
699 [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
700 [NETLINK_GENERIC] = "generic",
701 [NETLINK_SCSITRANSPORT] = "scsitransport",
702 [NETLINK_ECRYPTFS] = "ecryptfs"
703 };
704
705 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
706
707 static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
708 [SOCKET_ADDRESS_DEFAULT] = "default",
709 [SOCKET_ADDRESS_BOTH] = "both",
710 [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
711 };
712
713 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
714
715 bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
716 assert(a);
717 assert(b);
718
719 if (a->sa.sa_family != b->sa.sa_family)
720 return false;
721
722 if (a->sa.sa_family == AF_INET)
723 return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
724
725 if (a->sa.sa_family == AF_INET6)
726 return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
727
728 return false;
729 }
730
731 char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
732 assert(addr);
733 assert(buffer);
734
735 /* Like ether_ntoa() but uses %02x instead of %x to print
736 * ethernet addresses, which makes them look less funny. Also,
737 * doesn't use a static buffer. */
738
739 sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
740 addr->ether_addr_octet[0],
741 addr->ether_addr_octet[1],
742 addr->ether_addr_octet[2],
743 addr->ether_addr_octet[3],
744 addr->ether_addr_octet[4],
745 addr->ether_addr_octet[5]);
746
747 return buffer;
748 }