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