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