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