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