chiark / gitweb /
6a8ca1d7e375168fce35c6eb1d9a29e28c84907f
[elogind.git] / src / basic / socket-util.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2010 Lennart Poettering
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <arpa/inet.h>
21 #include <errno.h>
22 #include <limits.h>
23 #include <net/if.h>
24 #include <netdb.h>
25 #include <netinet/ip.h>
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 #include "alloc-util.h"
34 #include "fd-util.h"
35 #include "fileio.h"
36 #include "format-util.h"
37 #include "log.h"
38 #include "macro.h"
39 #include "missing.h"
40 #include "parse-util.h"
41 #include "path-util.h"
42 #include "socket-util.h"
43 #include "string-table.h"
44 #include "string-util.h"
45 #include "strv.h"
46 #include "user-util.h"
47 #include "util.h"
48
49 #if 0 /// UNNEEDED by elogind
50 int socket_address_parse(SocketAddress *a, const char *s) {
51         char *e, *n;
52         unsigned u;
53         int r;
54
55         assert(a);
56         assert(s);
57
58         zero(*a);
59         a->type = SOCK_STREAM;
60
61         if (*s == '[') {
62                 /* IPv6 in [x:.....:z]:p notation */
63
64                 e = strchr(s+1, ']');
65                 if (!e)
66                         return -EINVAL;
67
68                 n = strndupa(s+1, e-s-1);
69
70                 errno = 0;
71                 if (inet_pton(AF_INET6, n, &a->sockaddr.in6.sin6_addr) <= 0)
72                         return errno > 0 ? -errno : -EINVAL;
73
74                 e++;
75                 if (*e != ':')
76                         return -EINVAL;
77
78                 e++;
79                 r = safe_atou(e, &u);
80                 if (r < 0)
81                         return r;
82
83                 if (u <= 0 || u > 0xFFFF)
84                         return -EINVAL;
85
86                 a->sockaddr.in6.sin6_family = AF_INET6;
87                 a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
88                 a->size = sizeof(struct sockaddr_in6);
89
90         } else if (*s == '/') {
91                 /* AF_UNIX socket */
92
93                 size_t l;
94
95                 l = strlen(s);
96                 if (l >= sizeof(a->sockaddr.un.sun_path))
97                         return -EINVAL;
98
99                 a->sockaddr.un.sun_family = AF_UNIX;
100                 memcpy(a->sockaddr.un.sun_path, s, l);
101                 a->size = offsetof(struct sockaddr_un, sun_path) + l + 1;
102
103         } else if (*s == '@') {
104                 /* Abstract AF_UNIX socket */
105                 size_t l;
106
107                 l = strlen(s+1);
108                 if (l >= sizeof(a->sockaddr.un.sun_path) - 1)
109                         return -EINVAL;
110
111                 a->sockaddr.un.sun_family = AF_UNIX;
112                 memcpy(a->sockaddr.un.sun_path+1, s+1, l);
113                 a->size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
114
115         } else if (startswith(s, "vsock:")) {
116                 /* AF_VSOCK socket in vsock:cid:port notation */
117                 const char *cid_start = s + strlen("vsock:");
118
119                 e = strchr(cid_start, ':');
120                 if (!e)
121                         return -EINVAL;
122
123                 r = safe_atou(e+1, &u);
124                 if (r < 0)
125                         return r;
126
127                 n = strndupa(cid_start, e - cid_start);
128                 if (!isempty(n)) {
129                         r = safe_atou(n, &a->sockaddr.vm.svm_cid);
130                         if (r < 0)
131                                 return r;
132                 } else
133                         a->sockaddr.vm.svm_cid = VMADDR_CID_ANY;
134
135                 a->sockaddr.vm.svm_family = AF_VSOCK;
136                 a->sockaddr.vm.svm_port = u;
137                 a->size = sizeof(struct sockaddr_vm);
138
139         } else {
140                 e = strchr(s, ':');
141                 if (e) {
142                         r = safe_atou(e+1, &u);
143                         if (r < 0)
144                                 return r;
145
146                         if (u <= 0 || u > 0xFFFF)
147                                 return -EINVAL;
148
149                         n = strndupa(s, e-s);
150
151                         /* IPv4 in w.x.y.z:p notation? */
152                         r = inet_pton(AF_INET, n, &a->sockaddr.in.sin_addr);
153                         if (r < 0)
154                                 return -errno;
155
156                         if (r > 0) {
157                                 /* Gotcha, it's a traditional IPv4 address */
158                                 a->sockaddr.in.sin_family = AF_INET;
159                                 a->sockaddr.in.sin_port = htobe16((uint16_t)u);
160                                 a->size = sizeof(struct sockaddr_in);
161                         } else {
162                                 unsigned idx;
163
164                                 if (strlen(n) > IF_NAMESIZE-1)
165                                         return -EINVAL;
166
167                                 /* Uh, our last resort, an interface name */
168                                 idx = if_nametoindex(n);
169                                 if (idx == 0)
170                                         return -EINVAL;
171
172                                 a->sockaddr.in6.sin6_family = AF_INET6;
173                                 a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
174                                 a->sockaddr.in6.sin6_scope_id = idx;
175                                 a->sockaddr.in6.sin6_addr = in6addr_any;
176                                 a->size = sizeof(struct sockaddr_in6);
177                         }
178                 } else {
179
180                         /* Just a port */
181                         r = safe_atou(s, &u);
182                         if (r < 0)
183                                 return r;
184
185                         if (u <= 0 || u > 0xFFFF)
186                                 return -EINVAL;
187
188                         if (socket_ipv6_is_supported()) {
189                                 a->sockaddr.in6.sin6_family = AF_INET6;
190                                 a->sockaddr.in6.sin6_port = htobe16((uint16_t)u);
191                                 a->sockaddr.in6.sin6_addr = in6addr_any;
192                                 a->size = sizeof(struct sockaddr_in6);
193                         } else {
194                                 a->sockaddr.in.sin_family = AF_INET;
195                                 a->sockaddr.in.sin_port = htobe16((uint16_t)u);
196                                 a->sockaddr.in.sin_addr.s_addr = INADDR_ANY;
197                                 a->size = sizeof(struct sockaddr_in);
198                         }
199                 }
200         }
201
202         return 0;
203 }
204
205 int socket_address_parse_and_warn(SocketAddress *a, const char *s) {
206         SocketAddress b;
207         int r;
208
209         /* Similar to socket_address_parse() but warns for IPv6 sockets when we don't support them. */
210
211         r = socket_address_parse(&b, s);
212         if (r < 0)
213                 return r;
214
215         if (!socket_ipv6_is_supported() && b.sockaddr.sa.sa_family == AF_INET6) {
216                 log_warning("Binding to IPv6 address not available since kernel does not support IPv6.");
217                 return -EAFNOSUPPORT;
218         }
219
220         *a = b;
221         return 0;
222 }
223
224 int socket_address_parse_netlink(SocketAddress *a, const char *s) {
225         int family;
226         unsigned group = 0;
227         _cleanup_free_ char *sfamily = NULL;
228         assert(a);
229         assert(s);
230
231         zero(*a);
232         a->type = SOCK_RAW;
233
234         errno = 0;
235         if (sscanf(s, "%ms %u", &sfamily, &group) < 1)
236                 return errno > 0 ? -errno : -EINVAL;
237
238         family = netlink_family_from_string(sfamily);
239         if (family < 0)
240                 return -EINVAL;
241
242         a->sockaddr.nl.nl_family = AF_NETLINK;
243         a->sockaddr.nl.nl_groups = group;
244
245         a->type = SOCK_RAW;
246         a->size = sizeof(struct sockaddr_nl);
247         a->protocol = family;
248
249         return 0;
250 }
251
252 int socket_address_verify(const SocketAddress *a) {
253         assert(a);
254
255         switch (socket_address_family(a)) {
256
257         case AF_INET:
258                 if (a->size != sizeof(struct sockaddr_in))
259                         return -EINVAL;
260
261                 if (a->sockaddr.in.sin_port == 0)
262                         return -EINVAL;
263
264                 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
265                         return -EINVAL;
266
267                 return 0;
268
269         case AF_INET6:
270                 if (a->size != sizeof(struct sockaddr_in6))
271                         return -EINVAL;
272
273                 if (a->sockaddr.in6.sin6_port == 0)
274                         return -EINVAL;
275
276                 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
277                         return -EINVAL;
278
279                 return 0;
280
281         case AF_UNIX:
282                 if (a->size < offsetof(struct sockaddr_un, sun_path))
283                         return -EINVAL;
284
285                 if (a->size > offsetof(struct sockaddr_un, sun_path)) {
286
287                         if (a->sockaddr.un.sun_path[0] != 0) {
288                                 char *e;
289
290                                 /* path */
291                                 e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
292                                 if (!e)
293                                         return -EINVAL;
294
295                                 if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
296                                         return -EINVAL;
297                         }
298                 }
299
300                 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM && a->type != SOCK_SEQPACKET)
301                         return -EINVAL;
302
303                 return 0;
304
305         case AF_NETLINK:
306
307                 if (a->size != sizeof(struct sockaddr_nl))
308                         return -EINVAL;
309
310                 if (a->type != SOCK_RAW && a->type != SOCK_DGRAM)
311                         return -EINVAL;
312
313                 return 0;
314
315         case AF_VSOCK:
316                 if (a->size != sizeof(struct sockaddr_vm))
317                         return -EINVAL;
318
319                 if (a->type != SOCK_STREAM && a->type != SOCK_DGRAM)
320                         return -EINVAL;
321
322                 return 0;
323
324         default:
325                 return -EAFNOSUPPORT;
326         }
327 }
328
329 int socket_address_print(const SocketAddress *a, char **ret) {
330         int r;
331
332         assert(a);
333         assert(ret);
334
335         r = socket_address_verify(a);
336         if (r < 0)
337                 return r;
338
339         if (socket_address_family(a) == AF_NETLINK) {
340                 _cleanup_free_ char *sfamily = NULL;
341
342                 r = netlink_family_to_string_alloc(a->protocol, &sfamily);
343                 if (r < 0)
344                         return r;
345
346                 r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
347                 if (r < 0)
348                         return -ENOMEM;
349
350                 return 0;
351         }
352
353         return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret);
354 }
355
356 bool socket_address_can_accept(const SocketAddress *a) {
357         assert(a);
358
359         return
360                 a->type == SOCK_STREAM ||
361                 a->type == SOCK_SEQPACKET;
362 }
363
364 bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
365         assert(a);
366         assert(b);
367
368         /* Invalid addresses are unequal to all */
369         if (socket_address_verify(a) < 0 ||
370             socket_address_verify(b) < 0)
371                 return false;
372
373         if (a->type != b->type)
374                 return false;
375
376         if (socket_address_family(a) != socket_address_family(b))
377                 return false;
378
379         switch (socket_address_family(a)) {
380
381         case AF_INET:
382                 if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr)
383                         return false;
384
385                 if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port)
386                         return false;
387
388                 break;
389
390         case AF_INET6:
391                 if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0)
392                         return false;
393
394                 if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
395                         return false;
396
397                 break;
398
399         case AF_UNIX:
400                 if (a->size <= offsetof(struct sockaddr_un, sun_path) ||
401                     b->size <= offsetof(struct sockaddr_un, sun_path))
402                         return false;
403
404                 if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
405                         return false;
406
407                 if (a->sockaddr.un.sun_path[0]) {
408                         if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path))
409                                 return false;
410                 } else {
411                         if (a->size != b->size)
412                                 return false;
413
414                         if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
415                                 return false;
416                 }
417
418                 break;
419
420         case AF_NETLINK:
421                 if (a->protocol != b->protocol)
422                         return false;
423
424                 if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
425                         return false;
426
427                 break;
428
429         case AF_VSOCK:
430                 if (a->sockaddr.vm.svm_cid != b->sockaddr.vm.svm_cid)
431                         return false;
432
433                 if (a->sockaddr.vm.svm_port != b->sockaddr.vm.svm_port)
434                         return false;
435
436                 break;
437
438         default:
439                 /* Cannot compare, so we assume the addresses are different */
440                 return false;
441         }
442
443         return true;
444 }
445
446 bool socket_address_is(const SocketAddress *a, const char *s, int type) {
447         struct SocketAddress b;
448
449         assert(a);
450         assert(s);
451
452         if (socket_address_parse(&b, s) < 0)
453                 return false;
454
455         b.type = type;
456
457         return socket_address_equal(a, &b);
458 }
459
460 bool socket_address_is_netlink(const SocketAddress *a, const char *s) {
461         struct SocketAddress b;
462
463         assert(a);
464         assert(s);
465
466         if (socket_address_parse_netlink(&b, s) < 0)
467                 return false;
468
469         return socket_address_equal(a, &b);
470 }
471
472 const char* socket_address_get_path(const SocketAddress *a) {
473         assert(a);
474
475         if (socket_address_family(a) != AF_UNIX)
476                 return NULL;
477
478         if (a->sockaddr.un.sun_path[0] == 0)
479                 return NULL;
480
481         return a->sockaddr.un.sun_path;
482 }
483 #endif // 0
484
485 bool socket_ipv6_is_supported(void) {
486         if (access("/proc/net/if_inet6", F_OK) != 0)
487                 return false;
488
489         return true;
490 }
491
492 #if 0 /// UNNEEDED by elogind
493 bool socket_address_matches_fd(const SocketAddress *a, int fd) {
494         SocketAddress b;
495         socklen_t solen;
496
497         assert(a);
498         assert(fd >= 0);
499
500         b.size = sizeof(b.sockaddr);
501         if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0)
502                 return false;
503
504         if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family)
505                 return false;
506
507         solen = sizeof(b.type);
508         if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0)
509                 return false;
510
511         if (b.type != a->type)
512                 return false;
513
514         if (a->protocol != 0)  {
515                 solen = sizeof(b.protocol);
516                 if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0)
517                         return false;
518
519                 if (b.protocol != a->protocol)
520                         return false;
521         }
522
523         return socket_address_equal(a, &b);
524 }
525
526 int sockaddr_port(const struct sockaddr *_sa, unsigned *port) {
527         union sockaddr_union *sa = (union sockaddr_union*) _sa;
528
529         assert(sa);
530
531         switch (sa->sa.sa_family) {
532         case AF_INET:
533                 *port = be16toh(sa->in.sin_port);
534                 return 0;
535
536         case AF_INET6:
537                 *port = be16toh(sa->in6.sin6_port);
538                 return 0;
539
540         case AF_VSOCK:
541                 *port = sa->vm.svm_port;
542                 return 0;
543
544         default:
545                 return -EAFNOSUPPORT;
546         }
547 }
548
549 int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, bool include_port, char **ret) {
550         union sockaddr_union *sa = (union sockaddr_union*) _sa;
551         char *p;
552         int r;
553
554         assert(sa);
555         assert(salen >= sizeof(sa->sa.sa_family));
556
557         switch (sa->sa.sa_family) {
558
559         case AF_INET: {
560                 uint32_t a;
561
562                 a = be32toh(sa->in.sin_addr.s_addr);
563
564                 if (include_port)
565                         r = asprintf(&p,
566                                      "%u.%u.%u.%u:%u",
567                                      a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
568                                      be16toh(sa->in.sin_port));
569                 else
570                         r = asprintf(&p,
571                                      "%u.%u.%u.%u",
572                                      a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF);
573                 if (r < 0)
574                         return -ENOMEM;
575                 break;
576         }
577
578         case AF_INET6: {
579                 static const unsigned char ipv4_prefix[] = {
580                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
581                 };
582
583                 if (translate_ipv6 &&
584                     memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
585                         const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;
586                         if (include_port)
587                                 r = asprintf(&p,
588                                              "%u.%u.%u.%u:%u",
589                                              a[0], a[1], a[2], a[3],
590                                              be16toh(sa->in6.sin6_port));
591                         else
592                                 r = asprintf(&p,
593                                              "%u.%u.%u.%u",
594                                              a[0], a[1], a[2], a[3]);
595                         if (r < 0)
596                                 return -ENOMEM;
597                 } else {
598                         char a[INET6_ADDRSTRLEN];
599
600                         inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a));
601
602                         if (include_port) {
603                                 r = asprintf(&p,
604                                              "[%s]:%u",
605                                              a,
606                                              be16toh(sa->in6.sin6_port));
607                                 if (r < 0)
608                                         return -ENOMEM;
609                         } else {
610                                 p = strdup(a);
611                                 if (!p)
612                                         return -ENOMEM;
613                         }
614                 }
615
616                 break;
617         }
618
619         case AF_UNIX:
620                 if (salen <= offsetof(struct sockaddr_un, sun_path)) {
621                         p = strdup("<unnamed>");
622                         if (!p)
623                                 return -ENOMEM;
624
625                 } else if (sa->un.sun_path[0] == 0) {
626                         /* abstract */
627
628                         /* FIXME: We assume we can print the
629                          * socket path here and that it hasn't
630                          * more than one NUL byte. That is
631                          * actually an invalid assumption */
632
633                         p = new(char, sizeof(sa->un.sun_path)+1);
634                         if (!p)
635                                 return -ENOMEM;
636
637                         p[0] = '@';
638                         memcpy(p+1, sa->un.sun_path+1, sizeof(sa->un.sun_path)-1);
639                         p[sizeof(sa->un.sun_path)] = 0;
640
641                 } else {
642                         p = strndup(sa->un.sun_path, sizeof(sa->un.sun_path));
643                         if (!p)
644                                 return -ENOMEM;
645                 }
646
647                 break;
648
649         case AF_VSOCK:
650                 if (include_port)
651                         r = asprintf(&p,
652                                      "vsock:%u:%u",
653                                      sa->vm.svm_cid,
654                                      sa->vm.svm_port);
655                 else
656                         r = asprintf(&p, "vsock:%u", sa->vm.svm_cid);
657                 if (r < 0)
658                         return -ENOMEM;
659                 break;
660
661         default:
662                 return -EOPNOTSUPP;
663         }
664
665
666         *ret = p;
667         return 0;
668 }
669
670 int getpeername_pretty(int fd, bool include_port, char **ret) {
671         union sockaddr_union sa;
672         socklen_t salen = sizeof(sa);
673         int r;
674
675         assert(fd >= 0);
676         assert(ret);
677
678         if (getpeername(fd, &sa.sa, &salen) < 0)
679                 return -errno;
680
681         if (sa.sa.sa_family == AF_UNIX) {
682                 struct ucred ucred = {};
683
684                 /* UNIX connection sockets are anonymous, so let's use
685                  * PID/UID as pretty credentials instead */
686
687                 r = getpeercred(fd, &ucred);
688                 if (r < 0)
689                         return r;
690
691                 if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0)
692                         return -ENOMEM;
693
694                 return 0;
695         }
696
697         /* For remote sockets we translate IPv6 addresses back to IPv4
698          * if applicable, since that's nicer. */
699
700         return sockaddr_pretty(&sa.sa, salen, true, include_port, ret);
701 }
702
703 int getsockname_pretty(int fd, char **ret) {
704         union sockaddr_union sa;
705         socklen_t salen = sizeof(sa);
706
707         assert(fd >= 0);
708         assert(ret);
709
710         if (getsockname(fd, &sa.sa, &salen) < 0)
711                 return -errno;
712
713         /* For local sockets we do not translate IPv6 addresses back
714          * to IPv6 if applicable, since this is usually used for
715          * listening sockets where the difference between IPv4 and
716          * IPv6 matters. */
717
718         return sockaddr_pretty(&sa.sa, salen, false, true, ret);
719 }
720
721 int socknameinfo_pretty(union sockaddr_union *sa, socklen_t salen, char **_ret) {
722         int r;
723         char host[NI_MAXHOST], *ret;
724
725         assert(_ret);
726
727         r = getnameinfo(&sa->sa, salen, host, sizeof(host), NULL, 0,
728                         NI_IDN|NI_IDN_USE_STD3_ASCII_RULES);
729         if (r != 0) {
730                 int saved_errno = errno;
731
732                 r = sockaddr_pretty(&sa->sa, salen, true, true, &ret);
733                 if (r < 0)
734                         return r;
735
736                 log_debug_errno(saved_errno, "getnameinfo(%s) failed: %m", ret);
737         } else {
738                 ret = strdup(host);
739                 if (!ret)
740                         return -ENOMEM;
741         }
742
743         *_ret = ret;
744         return 0;
745 }
746
747 int getnameinfo_pretty(int fd, char **ret) {
748         union sockaddr_union sa;
749         socklen_t salen = sizeof(sa);
750
751         assert(fd >= 0);
752         assert(ret);
753
754         if (getsockname(fd, &sa.sa, &salen) < 0)
755                 return -errno;
756
757         return socknameinfo_pretty(&sa, salen, ret);
758 }
759
760 int socket_address_unlink(SocketAddress *a) {
761         assert(a);
762
763         if (socket_address_family(a) != AF_UNIX)
764                 return 0;
765
766         if (a->sockaddr.un.sun_path[0] == 0)
767                 return 0;
768
769         if (unlink(a->sockaddr.un.sun_path) < 0)
770                 return -errno;
771
772         return 1;
773 }
774
775 static const char* const netlink_family_table[] = {
776         [NETLINK_ROUTE] = "route",
777         [NETLINK_FIREWALL] = "firewall",
778         [NETLINK_INET_DIAG] = "inet-diag",
779         [NETLINK_NFLOG] = "nflog",
780         [NETLINK_XFRM] = "xfrm",
781         [NETLINK_SELINUX] = "selinux",
782         [NETLINK_ISCSI] = "iscsi",
783         [NETLINK_AUDIT] = "audit",
784         [NETLINK_FIB_LOOKUP] = "fib-lookup",
785         [NETLINK_CONNECTOR] = "connector",
786         [NETLINK_NETFILTER] = "netfilter",
787         [NETLINK_IP6_FW] = "ip6-fw",
788         [NETLINK_DNRTMSG] = "dnrtmsg",
789         [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
790         [NETLINK_GENERIC] = "generic",
791         [NETLINK_SCSITRANSPORT] = "scsitransport",
792         [NETLINK_ECRYPTFS] = "ecryptfs"
793 };
794
795 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
796
797 static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
798         [SOCKET_ADDRESS_DEFAULT] = "default",
799         [SOCKET_ADDRESS_BOTH] = "both",
800         [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
801 };
802
803 DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
804
805 bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
806         assert(a);
807         assert(b);
808
809         if (a->sa.sa_family != b->sa.sa_family)
810                 return false;
811
812         if (a->sa.sa_family == AF_INET)
813                 return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
814
815         if (a->sa.sa_family == AF_INET6)
816                 return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
817
818         if (a->sa.sa_family == AF_VSOCK)
819                 return a->vm.svm_cid == b->vm.svm_cid;
820
821         return false;
822 }
823 #endif // 0
824
825 int fd_inc_sndbuf(int fd, size_t n) {
826         int r, value;
827         socklen_t l = sizeof(value);
828
829         r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
830         if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
831                 return 0;
832
833         /* If we have the privileges we will ignore the kernel limit. */
834
835         value = (int) n;
836         if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
837                 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
838                         return -errno;
839
840         return 1;
841 }
842
843 int fd_inc_rcvbuf(int fd, size_t n) {
844         int r, value;
845         socklen_t l = sizeof(value);
846
847         r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
848         if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
849                 return 0;
850
851         /* If we have the privileges we will ignore the kernel limit. */
852
853         value = (int) n;
854         if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
855                 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
856                         return -errno;
857         return 1;
858 }
859
860 #if 0 /// UNNEEDED by elogind
861 static const char* const ip_tos_table[] = {
862         [IPTOS_LOWDELAY] = "low-delay",
863         [IPTOS_THROUGHPUT] = "throughput",
864         [IPTOS_RELIABILITY] = "reliability",
865         [IPTOS_LOWCOST] = "low-cost",
866 };
867
868 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
869 #endif // 0
870
871 bool ifname_valid(const char *p) {
872         bool numeric = true;
873
874         /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
875          * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
876          * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
877
878         if (isempty(p))
879                 return false;
880
881         if (strlen(p) >= IFNAMSIZ)
882                 return false;
883
884         if (STR_IN_SET(p, ".", ".."))
885                 return false;
886
887         while (*p) {
888                 if ((unsigned char) *p >= 127U)
889                         return false;
890
891                 if ((unsigned char) *p <= 32U)
892                         return false;
893
894                 if (*p == ':' || *p == '/')
895                         return false;
896
897                 numeric = numeric && (*p >= '0' && *p <= '9');
898                 p++;
899         }
900
901         if (numeric)
902                 return false;
903
904         return true;
905 }
906
907 int getpeercred(int fd, struct ucred *ucred) {
908         socklen_t n = sizeof(struct ucred);
909         struct ucred u;
910         int r;
911
912         assert(fd >= 0);
913         assert(ucred);
914
915         r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
916         if (r < 0)
917                 return -errno;
918
919         if (n != sizeof(struct ucred))
920                 return -EIO;
921
922         /* Check if the data is actually useful and not suppressed due
923          * to namespacing issues */
924         if (u.pid <= 0)
925                 return -ENODATA;
926         if (u.uid == UID_INVALID)
927                 return -ENODATA;
928         if (u.gid == GID_INVALID)
929                 return -ENODATA;
930
931         *ucred = u;
932         return 0;
933 }
934
935 int getpeersec(int fd, char **ret) {
936         socklen_t n = 64;
937         char *s;
938         int r;
939
940         assert(fd >= 0);
941         assert(ret);
942
943         s = new0(char, n);
944         if (!s)
945                 return -ENOMEM;
946
947         r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
948         if (r < 0) {
949                 free(s);
950
951                 if (errno != ERANGE)
952                         return -errno;
953
954                 s = new0(char, n);
955                 if (!s)
956                         return -ENOMEM;
957
958                 r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
959                 if (r < 0) {
960                         free(s);
961                         return -errno;
962                 }
963         }
964
965         if (isempty(s)) {
966                 free(s);
967                 return -EOPNOTSUPP;
968         }
969
970         *ret = s;
971         return 0;
972 }
973
974 int send_one_fd_sa(
975                 int transport_fd,
976                 int fd,
977                 const struct sockaddr *sa, socklen_t len,
978                 int flags) {
979
980         union {
981                 struct cmsghdr cmsghdr;
982                 uint8_t buf[CMSG_SPACE(sizeof(int))];
983         } control = {};
984         struct msghdr mh = {
985                 .msg_name = (struct sockaddr*) sa,
986                 .msg_namelen = len,
987                 .msg_control = &control,
988                 .msg_controllen = sizeof(control),
989         };
990         struct cmsghdr *cmsg;
991
992         assert(transport_fd >= 0);
993         assert(fd >= 0);
994
995         cmsg = CMSG_FIRSTHDR(&mh);
996         cmsg->cmsg_level = SOL_SOCKET;
997         cmsg->cmsg_type = SCM_RIGHTS;
998         cmsg->cmsg_len = CMSG_LEN(sizeof(int));
999         memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
1000
1001         mh.msg_controllen = CMSG_SPACE(sizeof(int));
1002         if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0)
1003                 return -errno;
1004
1005         return 0;
1006 }
1007
1008 #if 0 /// UNNEEDED by elogind
1009 int receive_one_fd(int transport_fd, int flags) {
1010         union {
1011                 struct cmsghdr cmsghdr;
1012                 uint8_t buf[CMSG_SPACE(sizeof(int))];
1013         } control = {};
1014         struct msghdr mh = {
1015                 .msg_control = &control,
1016                 .msg_controllen = sizeof(control),
1017         };
1018         struct cmsghdr *cmsg, *found = NULL;
1019
1020         assert(transport_fd >= 0);
1021
1022         /*
1023          * Receive a single FD via @transport_fd. We don't care for
1024          * the transport-type. We retrieve a single FD at most, so for
1025          * packet-based transports, the caller must ensure to send
1026          * only a single FD per packet.  This is best used in
1027          * combination with send_one_fd().
1028          */
1029
1030         if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0)
1031                 return -errno;
1032
1033         CMSG_FOREACH(cmsg, &mh) {
1034                 if (cmsg->cmsg_level == SOL_SOCKET &&
1035                     cmsg->cmsg_type == SCM_RIGHTS &&
1036                     cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
1037                         assert(!found);
1038                         found = cmsg;
1039                         break;
1040                 }
1041         }
1042
1043         if (!found) {
1044                 cmsg_close_all(&mh);
1045                 return -EIO;
1046         }
1047
1048         return *(int*) CMSG_DATA(found);
1049 }
1050
1051 ssize_t next_datagram_size_fd(int fd) {
1052         ssize_t l;
1053         int k;
1054
1055         /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
1056          * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
1057          * do. This difference is actually of major importance as we need to be sure that the size returned here
1058          * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
1059          * the wrong size. */
1060
1061         l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
1062         if (l < 0) {
1063                 if (errno == EOPNOTSUPP || errno == EFAULT)
1064                         goto fallback;
1065
1066                 return -errno;
1067         }
1068         if (l == 0)
1069                 goto fallback;
1070
1071         return l;
1072
1073 fallback:
1074         k = 0;
1075
1076         /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
1077          * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
1078
1079         if (ioctl(fd, FIONREAD, &k) < 0)
1080                 return -errno;
1081
1082         return (ssize_t) k;
1083 }
1084
1085 int flush_accept(int fd) {
1086
1087         struct pollfd pollfd = {
1088                 .fd = fd,
1089                 .events = POLLIN,
1090         };
1091         int r;
1092
1093
1094         /* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
1095
1096         for (;;) {
1097                 int cfd;
1098
1099                 r = poll(&pollfd, 1, 0);
1100                 if (r < 0) {
1101                         if (errno == EINTR)
1102                                 continue;
1103
1104                         return -errno;
1105
1106                 } else if (r == 0)
1107                         return 0;
1108
1109                 cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
1110                 if (cfd < 0) {
1111                         if (errno == EINTR)
1112                                 continue;
1113
1114                         if (errno == EAGAIN)
1115                                 return 0;
1116
1117                         return -errno;
1118                 }
1119
1120                 close(cfd);
1121         }
1122 }
1123 #endif // 0
1124
1125 struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) {
1126         struct cmsghdr *cmsg;
1127
1128         assert(mh);
1129
1130         CMSG_FOREACH(cmsg, mh)
1131                 if (cmsg->cmsg_level == level &&
1132                     cmsg->cmsg_type == type &&
1133                     (length == (socklen_t) -1 || length == cmsg->cmsg_len))
1134                         return cmsg;
1135
1136         return NULL;
1137 }
1138
1139 #if 0 /// UNNEEDED by elogind
1140 int socket_ioctl_fd(void) {
1141         int fd;
1142
1143         /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for
1144          * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not
1145          * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more
1146          * generic AF_NETLINK. */
1147
1148         fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
1149         if (fd < 0)
1150                 fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_GENERIC);
1151         if (fd < 0)
1152                 return -errno;
1153
1154         return fd;
1155 }
1156 #endif // 0