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