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