• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 14815796853

02 May 2025 11:41AM UTC coverage: 72.24% (-0.003%) from 72.243%
14815796853

push

github

web-flow
Various changes to prepare for running IWYU on the repository (#37319)

These are various commits that were required to get things compiling
after running IWYU. I think all of them make sense on their own, hence
this split PR to merge them ahead of time.

81 of 96 new or added lines in 48 files covered. (84.38%)

209 existing lines in 39 files now uncovered.

297219 of 411432 relevant lines covered (72.24%)

693693.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.72
/src/basic/socket-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <arpa/inet.h>
4
#include <errno.h>
5
#include <limits.h>
6
#include <linux/if.h>
7
#include <linux/if_arp.h>
8
#include <net/if.h>
9
#include <netdb.h>
10
#include <netinet/ip.h>
11
#include <poll.h>
12
#include <stddef.h>
13
#include <stdint.h>
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <sys/ioctl.h>
17
#include <unistd.h>
18

19
#include "alloc-util.h"
20
#include "errno-util.h"
21
#include "escape.h"
22
#include "fd-util.h"
23
#include "fileio.h"
24
#include "format-ifname.h"
25
#include "io-util.h"
26
#include "log.h"
27
#include "memory-util.h"
28
#include "parse-util.h"
29
#include "path-util.h"
30
#include "process-util.h"
31
#include "random-util.h"
32
#include "socket-util.h"
33
#include "string-table.h"
34
#include "string-util.h"
35
#include "strv.h"
36
#include "sysctl-util.h"
37
#include "user-util.h"
38
#include "utf8.h"
39

40
#if ENABLE_IDN
41
#  define IDN_FLAGS NI_IDN
42
#else
43
#  define IDN_FLAGS 0
44
#endif
45

46
/* From the kernel's include/net/scm.h */
47
#ifndef SCM_MAX_FD
48
#  define SCM_MAX_FD 253
49
#endif
50

51
static const char* const socket_address_type_table[] = {
52
        [SOCK_STREAM] =    "Stream",
53
        [SOCK_DGRAM] =     "Datagram",
54
        [SOCK_RAW] =       "Raw",
55
        [SOCK_RDM] =       "ReliableDatagram",
56
        [SOCK_SEQPACKET] = "SequentialPacket",
57
        [SOCK_DCCP] =      "DatagramCongestionControl",
58
};
59

60
DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
×
61

62
int socket_address_verify(const SocketAddress *a, bool strict) {
8,043✔
63
        assert(a);
8,043✔
64

65
        /* With 'strict' we enforce additional sanity constraints which are not set by the standard,
66
         * but should only apply to sockets we create ourselves. */
67

68
        switch (socket_address_family(a)) {
8,043✔
69

70
        case AF_INET:
25✔
71
                if (a->size != sizeof(struct sockaddr_in))
25✔
72
                        return -EINVAL;
73

74
                if (a->sockaddr.in.sin_port == 0)
25✔
75
                        return -EINVAL;
76

77
                if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
25✔
78
                        return -EINVAL;
1✔
79

80
                return 0;
81

82
        case AF_INET6:
16✔
83
                if (a->size != sizeof(struct sockaddr_in6))
16✔
84
                        return -EINVAL;
85

86
                if (a->sockaddr.in6.sin6_port == 0)
16✔
87
                        return -EINVAL;
88

89
                if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
16✔
90
                        return -EINVAL;
×
91

92
                return 0;
93

94
        case AF_UNIX:
7,568✔
95
                if (a->size < offsetof(struct sockaddr_un, sun_path))
7,568✔
96
                        return -EINVAL;
97
                if (a->size > sizeof(struct sockaddr_un) + !strict)
7,568✔
98
                        /* If !strict, allow one extra byte, since getsockname() on Linux will append
99
                         * a NUL byte if we have path sockets that are above sun_path's full size. */
100
                        return -EINVAL;
101

102
                if (a->size > offsetof(struct sockaddr_un, sun_path) &&
7,568✔
103
                    a->sockaddr.un.sun_path[0] != 0 &&
7,568✔
104
                    strict) {
105
                        /* Only validate file system sockets here, and only in strict mode */
106
                        const char *e;
2,282✔
107

108
                        e = memchr(a->sockaddr.un.sun_path, 0, sizeof(a->sockaddr.un.sun_path));
2,282✔
109
                        if (e) {
2,282✔
110
                                /* If there's an embedded NUL byte, make sure the size of the socket address matches it */
111
                                if (a->size != offsetof(struct sockaddr_un, sun_path) + (e - a->sockaddr.un.sun_path) + 1)
2,282✔
112
                                        return -EINVAL;
113
                        } else {
114
                                /* If there's no embedded NUL byte, then the size needs to match the whole
115
                                 * structure or the structure with one extra NUL byte suffixed. (Yeah, Linux is awful,
116
                                 * and considers both equivalent: getsockname() even extends sockaddr_un beyond its
117
                                 * size if the path is non NUL terminated.) */
118
                                if (!IN_SET(a->size, sizeof(a->sockaddr.un.sun_path), sizeof(a->sockaddr.un.sun_path)+1))
×
119
                                        return -EINVAL;
120
                        }
121
                }
122

123
                if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET))
7,568✔
124
                        return -EINVAL;
×
125

126
                return 0;
127

128
        case AF_NETLINK:
349✔
129

130
                if (a->size != sizeof(struct sockaddr_nl))
349✔
131
                        return -EINVAL;
132

133
                if (!IN_SET(a->type, 0, SOCK_RAW, SOCK_DGRAM))
349✔
134
                        return -EINVAL;
×
135

136
                return 0;
137

138
        case AF_VSOCK:
68✔
139
                if (a->size != sizeof(struct sockaddr_vm))
68✔
140
                        return -EINVAL;
141

142
                if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
68✔
143
                        return -EINVAL;
×
144

145
                return 0;
146

147
        default:
148
                return -EAFNOSUPPORT;
149
        }
150
}
151

152
int socket_address_print(const SocketAddress *a, char **ret) {
1,679✔
153
        int r;
1,679✔
154

155
        assert(a);
1,679✔
156
        assert(ret);
1,679✔
157

158
        r = socket_address_verify(a, false); /* We do non-strict validation, because we want to be
1,679✔
159
                                              * able to pretty-print any socket the kernel considers
160
                                              * valid. We still need to do validation to know if we
161
                                              * can meaningfully print the address. */
162
        if (r < 0)
1,679✔
163
                return r;
164

165
        if (socket_address_family(a) == AF_NETLINK) {
1,679✔
166
                _cleanup_free_ char *sfamily = NULL;
115✔
167

168
                r = netlink_family_to_string_alloc(a->protocol, &sfamily);
115✔
169
                if (r < 0)
115✔
170
                        return r;
171

172
                r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
115✔
173
                if (r < 0)
115✔
174
                        return -ENOMEM;
175

176
                return 0;
115✔
177
        }
178

179
        return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret);
1,564✔
180
}
181

182
bool socket_address_can_accept(const SocketAddress *a) {
4,749✔
183
        assert(a);
4,749✔
184

185
        return
4,749✔
186
                IN_SET(a->type, SOCK_STREAM, SOCK_SEQPACKET);
4,749✔
187
}
188

189
bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
1,993✔
190
        assert(a);
1,993✔
191
        assert(b);
1,993✔
192

193
        /* Invalid addresses are unequal to all */
194
        if (socket_address_verify(a, false) < 0 ||
3,986✔
195
            socket_address_verify(b, false) < 0)
1,993✔
196
                return false;
197

198
        if (a->type != b->type)
1,992✔
199
                return false;
200

201
        if (socket_address_family(a) != socket_address_family(b))
1,991✔
202
                return false;
203

204
        switch (socket_address_family(a)) {
1,989✔
205

206
        case AF_INET:
6✔
207
                if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr)
6✔
208
                        return false;
209

210
                if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port)
5✔
211
                        return false;
1✔
212

213
                break;
214

215
        case AF_INET6:
2✔
216
                if (memcmp(&a->sockaddr.in6.sin6_addr, &b->sockaddr.in6.sin6_addr, sizeof(a->sockaddr.in6.sin6_addr)) != 0)
2✔
217
                        return false;
218

219
                if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
2✔
220
                        return false;
×
221

222
                break;
223

224
        case AF_UNIX:
1,875✔
225
                if (a->size <= offsetof(struct sockaddr_un, sun_path) ||
1,875✔
226
                    b->size <= offsetof(struct sockaddr_un, sun_path))
1,875✔
227
                        return false;
228

229
                if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
1,875✔
230
                        return false;
231

232
                if (a->sockaddr.un.sun_path[0]) {
1,610✔
233
                        if (!path_equal_or_inode_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, 0))
1,608✔
234
                                return false;
433✔
235
                } else {
236
                        if (a->size != b->size)
2✔
237
                                return false;
238

239
                        if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
2✔
240
                                return false;
×
241
                }
242

243
                break;
244

245
        case AF_NETLINK:
87✔
246
                if (a->protocol != b->protocol)
87✔
247
                        return false;
248

249
                if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
87✔
250
                        return false;
1✔
251

252
                break;
253

254
        case AF_VSOCK:
19✔
255
                if (a->sockaddr.vm.svm_cid != b->sockaddr.vm.svm_cid)
19✔
256
                        return false;
257

258
                if (a->sockaddr.vm.svm_port != b->sockaddr.vm.svm_port)
18✔
259
                        return false;
1✔
260

261
                break;
262

263
        default:
264
                /* Cannot compare, so we assume the addresses are different */
265
                return false;
266
        }
267

268
        return true;
269
}
270

271
const char* socket_address_get_path(const SocketAddress *a) {
10,583✔
272
        assert(a);
10,583✔
273

274
        if (socket_address_family(a) != AF_UNIX)
10,583✔
275
                return NULL;
276

277
        if (a->sockaddr.un.sun_path[0] == 0)
10,097✔
278
                return NULL;
279

280
        /* Note that this is only safe because we know that there's an extra NUL byte after the sockaddr_un
281
         * structure. On Linux AF_UNIX file system socket addresses don't have to be NUL terminated if they take up the
282
         * full sun_path space. */
283
        assert_cc(sizeof(union sockaddr_union) >= sizeof(struct sockaddr_un)+1);
10,096✔
284
        return a->sockaddr.un.sun_path;
10,096✔
285
}
286

287
bool socket_ipv6_is_supported(void) {
140,586✔
288
        static int cached = -1;
140,586✔
289

290
        if (cached < 0) {
140,586✔
291

292
                if (access("/proc/net/if_inet6", F_OK) < 0) {
1,130✔
293

294
                        if (errno != ENOENT) {
×
295
                                log_debug_errno(errno, "Unexpected error when checking whether /proc/net/if_inet6 exists: %m");
×
296
                                return false;
×
297
                        }
298

299
                        cached = false;
×
300
                } else
301
                        cached = true;
1,130✔
302
        }
303

304
        return cached;
140,586✔
305
}
306

307
bool socket_ipv6_is_enabled(void) {
101,584✔
308
        _cleanup_free_ char *v = NULL;
101,584✔
309
        int r;
101,584✔
310

311
        /* Much like socket_ipv6_is_supported(), but also checks that the sysctl that disables IPv6 on all
312
         * interfaces isn't turned on */
313

314
        if (!socket_ipv6_is_supported())
101,584✔
315
                return false;
316

317
        r = sysctl_read_ip_property(AF_INET6, "all", "disable_ipv6", &v);
101,584✔
318
        if (r < 0) {
101,584✔
319
                log_debug_errno(r, "Unexpected error reading 'net.ipv6.conf.all.disable_ipv6' sysctl: %m");
×
320
                return true;
×
321
        }
322

323
        r = parse_boolean(v);
101,584✔
324
        if (r < 0) {
101,584✔
325
                log_debug_errno(r, "Failed to pare 'net.ipv6.conf.all.disable_ipv6' sysctl: %m");
×
326
                return true;
×
327
        }
328

329
        return !r;
101,584✔
330
}
331

332
bool socket_address_matches_fd(const SocketAddress *a, int fd) {
938✔
333
        SocketAddress b;
938✔
334
        socklen_t solen;
938✔
335

336
        assert(a);
938✔
337
        assert(fd >= 0);
938✔
338

339
        b.size = sizeof(b.sockaddr);
938✔
340
        if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0)
938✔
341
                return false;
938✔
342

343
        if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family)
938✔
344
                return false;
345

346
        solen = sizeof(b.type);
823✔
347
        if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0)
823✔
348
                return false;
349

350
        if (b.type != a->type)
823✔
351
                return false;
352

353
        if (a->protocol != 0)  {
698✔
354
                solen = sizeof(b.protocol);
×
355
                if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &b.protocol, &solen) < 0)
×
356
                        return false;
357

358
                if (b.protocol != a->protocol)
×
359
                        return false;
360
        }
361

362
        return socket_address_equal(a, &b);
698✔
363
}
364

365
int sockaddr_port(const struct sockaddr *_sa, unsigned *ret_port) {
×
366
        const union sockaddr_union *sa = (const union sockaddr_union*) _sa;
×
367

368
        /* Note, this returns the port as 'unsigned' rather than 'uint16_t', as AF_VSOCK knows larger ports */
369

370
        assert(sa);
×
371

372
        switch (sa->sa.sa_family) {
×
373

374
        case AF_INET:
×
375
                *ret_port = be16toh(sa->in.sin_port);
×
376
                return 0;
×
377

378
        case AF_INET6:
×
379
                *ret_port = be16toh(sa->in6.sin6_port);
×
380
                return 0;
×
381

382
        case AF_VSOCK:
×
383
                *ret_port = sa->vm.svm_port;
×
384
                return 0;
×
385

386
        default:
387
                return -EAFNOSUPPORT;
388
        }
389
}
390

391
const union in_addr_union *sockaddr_in_addr(const struct sockaddr *_sa) {
401✔
392
        const union sockaddr_union *sa = (const union sockaddr_union*) _sa;
401✔
393

394
        if (!sa)
401✔
395
                return NULL;
396

397
        switch (sa->sa.sa_family) {
401✔
398

399
        case AF_INET:
300✔
400
                return (const union in_addr_union*) &sa->in.sin_addr;
300✔
401

402
        case AF_INET6:
101✔
403
                return (const union in_addr_union*) &sa->in6.sin6_addr;
101✔
404

405
        default:
406
                return NULL;
407
        }
408
}
409

410
int sockaddr_set_in_addr(
698✔
411
                union sockaddr_union *u,
412
                int family,
413
                const union in_addr_union *a,
414
                uint16_t port) {
415

416
        assert(u);
698✔
417
        assert(a);
698✔
418

419
        switch (family) {
698✔
420

421
        case AF_INET:
695✔
422
                u->in = (struct sockaddr_in) {
695✔
423
                        .sin_family = AF_INET,
424
                        .sin_addr = a->in,
695✔
425
                        .sin_port = htobe16(port),
695✔
426
                };
427

428
                return 0;
695✔
429

430
        case AF_INET6:
3✔
431
                u->in6 = (struct sockaddr_in6) {
3✔
432
                        .sin6_family = AF_INET6,
433
                        .sin6_addr = a->in6,
3✔
434
                        .sin6_port = htobe16(port),
3✔
435
                };
436

437
                return 0;
3✔
438

439
        default:
440
                return -EAFNOSUPPORT;
441

442
        }
443
}
444

445
int sockaddr_pretty(
9,450✔
446
                const struct sockaddr *_sa,
447
                socklen_t salen,
448
                bool translate_ipv6,
449
                bool include_port,
450
                char **ret) {
451

452
        union sockaddr_union *sa = (union sockaddr_union*) _sa;
9,450✔
453
        char *p;
9,450✔
454
        int r;
9,450✔
455

456
        assert(sa);
9,450✔
457
        assert(salen >= sizeof(sa->sa.sa_family));
9,450✔
458
        assert(ret);
9,450✔
459

460
        switch (sa->sa.sa_family) {
9,450✔
461

462
        case AF_INET: {
108✔
463
                uint32_t a;
108✔
464

465
                a = be32toh(sa->in.sin_addr.s_addr);
108✔
466

467
                if (include_port)
108✔
468
                        r = asprintf(&p,
108✔
469
                                     "%u.%u.%u.%u:%u",
470
                                     a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
471
                                     be16toh(sa->in.sin_port));
108✔
472
                else
473
                        r = asprintf(&p,
×
474
                                     "%u.%u.%u.%u",
475
                                     a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF);
476
                if (r < 0)
108✔
477
                        return -ENOMEM;
9,450✔
478
                break;
479
        }
480

481
        case AF_INET6: {
18✔
482
                static const unsigned char ipv4_prefix[] = {
18✔
483
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
484
                };
485

486
                if (translate_ipv6 &&
18✔
487
                    memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {
10✔
488
                        const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;
×
489
                        if (include_port)
×
490
                                r = asprintf(&p,
×
491
                                             "%u.%u.%u.%u:%u",
492
                                             a[0], a[1], a[2], a[3],
×
493
                                             be16toh(sa->in6.sin6_port));
×
494
                        else
495
                                r = asprintf(&p,
×
496
                                             "%u.%u.%u.%u",
497
                                             a[0], a[1], a[2], a[3]);
×
498
                        if (r < 0)
×
499
                                return -ENOMEM;
500
                } else {
501
                        const char *a = IN6_ADDR_TO_STRING(&sa->in6.sin6_addr);
18✔
502

503
                        if (include_port) {
18✔
504
                                if (asprintf(&p,
16✔
505
                                             "[%s]:%u%s%s",
506
                                             a,
507
                                             be16toh(sa->in6.sin6_port),
16✔
508
                                             sa->in6.sin6_scope_id != 0 ? "%" : "",
16✔
509
                                             FORMAT_IFNAME_FULL(sa->in6.sin6_scope_id, FORMAT_IFNAME_IFINDEX)) < 0)
16✔
510
                                        return -ENOMEM;
×
511
                        } else {
512
                                if (sa->in6.sin6_scope_id != 0)
2✔
513
                                        p = strjoin(a, "%", FORMAT_IFNAME_FULL(sa->in6.sin6_scope_id, FORMAT_IFNAME_IFINDEX));
×
514
                                else
515
                                        p = strdup(a);
2✔
516
                                if (!p)
2✔
517
                                        return -ENOMEM;
518
                        }
519
                }
520

521
                break;
522
        }
523

524
        case AF_UNIX:
9,302✔
525
                if (salen <= offsetof(struct sockaddr_un, sun_path) ||
9,302✔
526
                    (sa->un.sun_path[0] == 0 && salen == offsetof(struct sockaddr_un, sun_path) + 1))
9,300✔
527
                        /* The name must have at least one character (and the leading NUL does not count) */
528
                        p = strdup("<unnamed>");
4✔
529
                else {
530
                        /* Note that we calculate the path pointer here through the .un_buffer[] field, in order to
531
                         * outtrick bounds checking tools such as ubsan, which are too smart for their own good: on
532
                         * Linux the kernel may return sun_path[] data one byte longer than the declared size of the
533
                         * field. */
534
                        char *path = (char*) sa->un_buffer + offsetof(struct sockaddr_un, sun_path);
9,298✔
535
                        size_t path_len = salen - offsetof(struct sockaddr_un, sun_path);
9,298✔
536

537
                        if (path[0] == 0) {
9,298✔
538
                                /* Abstract socket. When parsing address information from, we
539
                                 * explicitly reject overly long paths and paths with embedded NULs.
540
                                 * But we might get such a socket from the outside. Let's return
541
                                 * something meaningful and printable in this case. */
542

543
                                _cleanup_free_ char *e = NULL;
8✔
544

545
                                e = cescape_length(path + 1, path_len - 1);
8✔
546
                                if (!e)
8✔
547
                                        return -ENOMEM;
×
548

549
                                p = strjoin("@", e);
8✔
550
                        } else {
551
                                if (path[path_len - 1] == '\0')
9,290✔
552
                                        /* We expect a terminating NUL and don't print it */
553
                                        path_len--;
9,289✔
554

555
                                p = cescape_length(path, path_len);
9,290✔
556
                        }
557
                }
558
                if (!p)
9,302✔
559
                        return -ENOMEM;
560

561
                break;
562

563
        case AF_VSOCK:
22✔
564
                if (include_port) {
22✔
565
                        if (sa->vm.svm_cid == VMADDR_CID_ANY)
22✔
566
                                r = asprintf(&p, "vsock::%u", sa->vm.svm_port);
19✔
567
                        else
568
                                r = asprintf(&p, "vsock:%u:%u", sa->vm.svm_cid, sa->vm.svm_port);
3✔
569
                } else
570
                        r = asprintf(&p, "vsock:%u", sa->vm.svm_cid);
×
571
                if (r < 0)
22✔
572
                        return -ENOMEM;
573
                break;
574

575
        default:
576
                return -EOPNOTSUPP;
577
        }
578

579
        *ret = p;
9,450✔
580
        return 0;
9,450✔
581
}
582

583
int getpeername_pretty(int fd, bool include_port, char **ret) {
4✔
584
        union sockaddr_union sa;
4✔
585
        socklen_t salen = sizeof(sa);
4✔
586
        int r;
4✔
587

588
        assert(fd >= 0);
4✔
589
        assert(ret);
4✔
590

591
        if (getpeername(fd, &sa.sa, &salen) < 0)
4✔
592
                return -errno;
×
593

594
        if (sa.sa.sa_family == AF_UNIX) {
4✔
595
                struct ucred ucred = UCRED_INVALID;
2✔
596

597
                /* UNIX connection sockets are anonymous, so let's use
598
                 * PID/UID as pretty credentials instead */
599

600
                r = getpeercred(fd, &ucred);
2✔
601
                if (r < 0)
2✔
602
                        return r;
2✔
603

604
                if (asprintf(ret, "PID "PID_FMT"/UID "UID_FMT, ucred.pid, ucred.uid) < 0)
2✔
605
                        return -ENOMEM;
606

607
                return 0;
2✔
608
        }
609

610
        /* For remote sockets we translate IPv6 addresses back to IPv4
611
         * if applicable, since that's nicer. */
612

613
        return sockaddr_pretty(&sa.sa, salen, true, include_port, ret);
2✔
614
}
615

616
int getsockname_pretty(int fd, char **ret) {
1✔
617
        union sockaddr_union sa;
1✔
618
        socklen_t salen = sizeof(sa);
1✔
619

620
        assert(fd >= 0);
1✔
621
        assert(ret);
1✔
622

623
        if (getsockname(fd, &sa.sa, &salen) < 0)
1✔
624
                return -errno;
×
625

626
        /* For local sockets we do not translate IPv6 addresses back
627
         * to IPv6 if applicable, since this is usually used for
628
         * listening sockets where the difference between IPv4 and
629
         * IPv6 matters. */
630

631
        return sockaddr_pretty(&sa.sa, salen, false, true, ret);
1✔
632
}
633

634
int socknameinfo_pretty(const struct sockaddr *sa, socklen_t salen, char **ret) {
×
635
        char host[NI_MAXHOST];
×
636
        int r;
×
637

638
        assert(sa);
×
639
        assert(salen >= sizeof(sa_family_t));
×
640
        assert(ret);
×
641

642
        r = getnameinfo(sa, salen, host, sizeof(host), /* service= */ NULL, /* service_len= */ 0, IDN_FLAGS);
×
643
        if (r != 0) {
×
644
                if (r == EAI_MEMORY)
×
645
                        return log_oom_debug();
×
646
                if (r == EAI_SYSTEM)
×
647
                        log_debug_errno(errno, "getnameinfo() failed, ignoring: %m");
×
648
                else
649
                        log_debug("getnameinfo() failed, ignoring: %s", gai_strerror(r));
×
650

651
                return sockaddr_pretty(sa, salen, /* translate_ipv6= */ true, /* include_port= */ true, ret);
×
652
        }
653

654
        return strdup_to(ret, host);
×
655
}
656

657
static const char* const netlink_family_table[] = {
658
        [NETLINK_ROUTE]          = "route",
659
        [NETLINK_FIREWALL]       = "firewall",
660
        [NETLINK_INET_DIAG]      = "inet-diag",
661
        [NETLINK_NFLOG]          = "nflog",
662
        [NETLINK_XFRM]           = "xfrm",
663
        [NETLINK_SELINUX]        = "selinux",
664
        [NETLINK_ISCSI]          = "iscsi",
665
        [NETLINK_AUDIT]          = "audit",
666
        [NETLINK_FIB_LOOKUP]     = "fib-lookup",
667
        [NETLINK_CONNECTOR]      = "connector",
668
        [NETLINK_NETFILTER]      = "netfilter",
669
        [NETLINK_IP6_FW]         = "ip6-fw",
670
        [NETLINK_DNRTMSG]        = "dnrtmsg",
671
        [NETLINK_KOBJECT_UEVENT] = "kobject-uevent",
672
        [NETLINK_GENERIC]        = "generic",
673
        [NETLINK_SCSITRANSPORT]  = "scsitransport",
674
        [NETLINK_ECRYPTFS]       = "ecryptfs",
675
        [NETLINK_RDMA]           = "rdma",
676
};
677

678
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
540✔
679

680
static const char* const socket_address_bind_ipv6_only_table[_SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX] = {
681
        [SOCKET_ADDRESS_DEFAULT] = "default",
682
        [SOCKET_ADDRESS_BOTH] = "both",
683
        [SOCKET_ADDRESS_IPV6_ONLY] = "ipv6-only"
684
};
685

686
DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
160✔
687

688
SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *n) {
×
689
        int r;
×
690

691
        r = parse_boolean(n);
×
692
        if (r > 0)
×
693
                return SOCKET_ADDRESS_IPV6_ONLY;
694
        if (r == 0)
×
695
                return SOCKET_ADDRESS_BOTH;
696

697
        return socket_address_bind_ipv6_only_from_string(n);
×
698
}
699

700
bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
7✔
701
        assert(a);
7✔
702
        assert(b);
7✔
703

704
        if (a->sa.sa_family != b->sa.sa_family)
7✔
705
                return false;
706

707
        if (a->sa.sa_family == AF_INET)
6✔
708
                return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
4✔
709

710
        if (a->sa.sa_family == AF_INET6)
2✔
711
                return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
1✔
712

713
        if (a->sa.sa_family == AF_VSOCK)
1✔
714
                return a->vm.svm_cid == b->vm.svm_cid;
1✔
715

716
        return false;
717
}
718

719
int fd_set_sndbuf(int fd, size_t n, bool increase) {
400,808✔
720
        int r, value;
400,808✔
721
        socklen_t l = sizeof(value);
400,808✔
722

723
        if (n > INT_MAX)
400,808✔
724
                return -ERANGE;
400,808✔
725

726
        r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
400,808✔
727
        if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
400,808✔
728
                return 0;
729

730
        /* First, try to set the buffer size with SO_SNDBUF. */
731
        r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n);
400,808✔
732
        if (r < 0)
400,808✔
733
                return r;
734

735
        /* SO_SNDBUF above may set to the kernel limit, instead of the requested size.
736
         * So, we need to check the actual buffer size here. */
737
        l = sizeof(value);
400,808✔
738
        r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
400,808✔
739
        if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
400,808✔
740
                return 1;
741

742
        /* If we have the privileges we will ignore the kernel limit. */
743
        r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
400,808✔
744
        if (r < 0)
400,808✔
745
                return r;
33,409✔
746

747
        return 1;
748
}
749

750
int fd_set_rcvbuf(int fd, size_t n, bool increase) {
32,772✔
751
        int r, value;
32,772✔
752
        socklen_t l = sizeof(value);
32,772✔
753

754
        if (n > INT_MAX)
32,772✔
755
                return -ERANGE;
32,772✔
756

757
        r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
32,772✔
758
        if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
32,772✔
759
                return 0;
760

761
        /* First, try to set the buffer size with SO_RCVBUF. */
762
        r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n);
32,771✔
763
        if (r < 0)
32,771✔
764
                return r;
765

766
        /* SO_RCVBUF above may set to the kernel limit, instead of the requested size.
767
         * So, we need to check the actual buffer size here. */
768
        l = sizeof(value);
32,771✔
769
        r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
32,771✔
770
        if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
32,771✔
771
                return 1;
772

773
        /* If we have the privileges we will ignore the kernel limit. */
774
        r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
32,771✔
775
        if (r < 0)
32,771✔
776
                return r;
7,067✔
777

778
        return 1;
779
}
780

781
static const char* const ip_tos_table[] = {
782
        [IPTOS_LOWDELAY]    = "low-delay",
783
        [IPTOS_THROUGHPUT]  = "throughput",
784
        [IPTOS_RELIABILITY] = "reliability",
785
        [IPTOS_LOWCOST]     = "low-cost",
786
};
787

788
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
×
789

790
bool ifname_valid_char(char a) {
444,012✔
791
        if ((unsigned char) a >= 127U)
444,012✔
792
                return false;
793

794
        if ((unsigned char) a <= 32U)
444,012✔
795
                return false;
796

797
        if (IN_SET(a,
444,008✔
798
                   ':',  /* colons are used by the legacy "alias" interface logic */
799
                   '/',  /* slashes cannot work, since we need to use network interfaces in sysfs paths, and in paths slashes are separators */
800
                   '%')) /* %d is used in the kernel's weird foo%d format string naming feature which we really really don't want to ever run into by accident */
801
                return false;
10✔
802

803
        return true;
804
}
805

806
bool ifname_valid_full(const char *p, IfnameValidFlags flags) {
127,661✔
807
        bool numeric = true;
127,661✔
808

809
        /* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
810
         * but slightly stricter, as we only allow non-control, non-space ASCII characters in the interface name. We
811
         * also don't permit names that only container numbers, to avoid confusion with numeric interface indexes. */
812

813
        assert(!(flags & ~_IFNAME_VALID_ALL));
127,661✔
814

815
        if (isempty(p))
127,661✔
816
                return false;
817

818
        /* A valid ifindex? If so, it's valid iff IFNAME_VALID_NUMERIC is set */
819
        if (parse_ifindex(p) >= 0)
123,215✔
820
                return flags & IFNAME_VALID_NUMERIC;
57✔
821

822
        if (flags & IFNAME_VALID_ALTERNATIVE) {
123,158✔
823
                if (strlen(p) >= ALTIFNAMSIZ)
11,700✔
824
                        return false;
825
        } else {
826
                if (strlen(p) >= IFNAMSIZ)
111,458✔
827
                        return false;
828
        }
829

830
        if (dot_or_dot_dot(p))
123,151✔
831
                return false;
832

833
        /* Let's refuse "all" and "default" as interface name, to avoid collisions with the special sysctl
834
         * directories /proc/sys/net/{ipv4,ipv6}/conf/{all,default} */
835
        if (!FLAGS_SET(flags, IFNAME_VALID_SPECIAL) && STR_IN_SET(p, "all", "default"))
123,149✔
836
                return false;
×
837

838
        for (const char *t = p; *t; t++) {
560,222✔
839
                if (!ifname_valid_char(*t))
437,087✔
840
                        return false;
841

842
                numeric = numeric && ascii_isdigit(*t);
560,212✔
843
        }
844

845
        /* It's fully numeric but didn't parse as valid ifindex above? if so, it must be too large or zero or
846
         * so, let's refuse that. */
847
        if (numeric)
123,135✔
848
                return false;
2✔
849

850
        return true;
851
}
852

853
bool address_label_valid(const char *p) {
44✔
854

855
        if (isempty(p))
44✔
856
                return false;
857

858
        if (strlen(p) >= IFNAMSIZ)
44✔
859
                return false;
860

861
        while (*p) {
376✔
862
                if ((uint8_t) *p >= 127U)
332✔
863
                        return false;
864

865
                if ((uint8_t) *p <= 31U)
332✔
866
                        return false;
867
                p++;
332✔
868
        }
869

870
        return true;
871
}
872

873
int getpeercred(int fd, struct ucred *ucred) {
66,410✔
874
        socklen_t n = sizeof(struct ucred);
66,410✔
875
        struct ucred u;
66,410✔
876

877
        assert(fd >= 0);
66,410✔
878
        assert(ucred);
66,410✔
879

880
        if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n) < 0)
66,410✔
881
                return -errno;
×
882

883
        if (n != sizeof(struct ucred))
66,410✔
884
                return -EIO;
885

886
        /* Check if the data is actually useful and not suppressed due to namespacing issues */
887
        if (!pid_is_valid(u.pid))
66,410✔
888
                return -ENODATA;
889

890
        /* Note that we don't check UID/GID here, as namespace translation works differently there: instead of
891
         * receiving in "invalid" user/group we get the overflow UID/GID. */
892

893
        *ucred = u;
66,410✔
894
        return 0;
66,410✔
895
}
896

897
int getpeersec(int fd, char **ret) {
19,986✔
898
        _cleanup_free_ char *s = NULL;
39,972✔
899
        socklen_t n = 64;
19,986✔
900

901
        assert(fd >= 0);
19,986✔
902
        assert(ret);
19,986✔
903

904
        for (;;) {
19,986✔
905
                s = new0(char, n+1);
19,986✔
906
                if (!s)
19,986✔
907
                        return -ENOMEM;
908

909
                if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n) >= 0) {
19,986✔
910
                        s[n] = 0;
7,089✔
911
                        break;
7,089✔
912
                }
913

914
                if (errno != ERANGE)
12,897✔
915
                        return -errno;
12,897✔
916

917
                s = mfree(s);
×
918
        }
919

920
        if (isempty(s))
7,089✔
921
                return -EOPNOTSUPP;
922

923
        *ret = TAKE_PTR(s);
7,089✔
924

925
        return 0;
7,089✔
926
}
927

928
int getpeergroups(int fd, gid_t **ret) {
19,987✔
929
        socklen_t n = sizeof(gid_t) * 64U;
19,987✔
930
        _cleanup_free_ gid_t *d = NULL;
19,987✔
931

932
        assert(fd >= 0);
19,987✔
933
        assert(ret);
19,987✔
934

935
        long ngroups_max = sysconf(_SC_NGROUPS_MAX);
19,987✔
936
        if (ngroups_max > 0)
19,987✔
937
                n = MAX(n, sizeof(gid_t) * (socklen_t) ngroups_max);
19,987✔
938

939
        for (;;) {
19,987✔
940
                d = malloc(n);
19,987✔
941
                if (!d)
19,987✔
942
                        return -ENOMEM;
943

944
                if (getsockopt(fd, SOL_SOCKET, SO_PEERGROUPS, d, &n) >= 0)
19,987✔
945
                        break;
946

947
                if (errno != ERANGE)
×
948
                        return -errno;
×
949

950
                d = mfree(d);
×
951
        }
952

953
        assert_se(n % sizeof(gid_t) == 0);
19,987✔
954
        n /= sizeof(gid_t);
19,987✔
955

956
        if (n > INT_MAX)
19,987✔
957
                return -E2BIG;
958

959
        *ret = TAKE_PTR(d);
19,987✔
960

961
        return (int) n;
19,987✔
962
}
963

964
int getpeerpidfd(int fd) {
20,275✔
965
        socklen_t n = sizeof(int);
20,275✔
966
        int pidfd = -EBADF;
20,275✔
967

968
        assert(fd >= 0);
20,275✔
969

970
        if (getsockopt(fd, SOL_SOCKET, SO_PEERPIDFD, &pidfd, &n) < 0)
20,275✔
971
                return -errno;
2✔
972

973
        if (n != sizeof(int))
20,273✔
974
                return -EIO;
975

976
        return pidfd;
20,273✔
977
}
978

979
int getpeerpidref(int fd, PidRef *ret) {
4✔
980
        int r;
4✔
981

982
        assert(fd >= 0);
4✔
983
        assert(ret);
4✔
984

985
        int pidfd = getpeerpidfd(fd);
4✔
986
        if (pidfd < 0) {
4✔
987
                if (!ERRNO_IS_NEG_NOT_SUPPORTED(pidfd))
×
988
                        return pidfd;
×
989

990
                struct ucred ucred;
×
991
                r = getpeercred(fd, &ucred);
×
992
                if (r < 0)
×
993
                        return r;
994

995
                return pidref_set_pid(ret, ucred.pid);
×
996
        }
997

998
        return pidref_set_pidfd_consume(ret, pidfd);
4✔
999
}
1000

1001
ssize_t send_many_fds_iov_sa(
1✔
1002
                int transport_fd,
1003
                int *fds_array, size_t n_fds_array,
1004
                const struct iovec *iov, size_t iovlen,
1005
                const struct sockaddr *sa, socklen_t len,
1006
                int flags) {
1007

1008
        _cleanup_free_ struct cmsghdr *cmsg = NULL;
1✔
1009
        struct msghdr mh = {
1✔
1010
                .msg_name = (struct sockaddr*) sa,
1011
                .msg_namelen = len,
1012
                .msg_iov = (struct iovec *)iov,
1013
                .msg_iovlen = iovlen,
1014
        };
1015
        ssize_t k;
1✔
1016

1017
        assert(transport_fd >= 0);
1✔
1018
        assert(fds_array || n_fds_array == 0);
1✔
1019

1020
        /* The kernel will reject sending more than SCM_MAX_FD FDs at once */
1021
        if (n_fds_array > SCM_MAX_FD)
1✔
1022
                return -E2BIG;
1023

1024
        /* We need either an FD array or data to send. If there's nothing, return an error. */
1025
        if (n_fds_array == 0 && !iov)
1✔
1026
                return -EINVAL;
1027

1028
        if (n_fds_array > 0) {
1✔
1029
                mh.msg_controllen = CMSG_SPACE(sizeof(int) * n_fds_array);
1✔
1030
                mh.msg_control = cmsg = malloc(mh.msg_controllen);
1✔
1031
                if (!cmsg)
1✔
1032
                        return -ENOMEM;
1033

1034
                *cmsg = (struct cmsghdr) {
1✔
1035
                        .cmsg_len = CMSG_LEN(sizeof(int) * n_fds_array),
1✔
1036
                        .cmsg_level = SOL_SOCKET,
1037
                        .cmsg_type = SCM_RIGHTS,
1038
                };
1039
                memcpy(CMSG_DATA(cmsg), fds_array, sizeof(int) * n_fds_array);
1✔
1040
        }
1041
        k = sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags);
1✔
1042
        if (k < 0)
1✔
1043
                return (ssize_t) -errno;
×
1044

1045
        return k;
1046
}
1047

1048
ssize_t send_one_fd_iov_sa(
741✔
1049
                int transport_fd,
1050
                int fd,
1051
                const struct iovec *iov, size_t iovlen,
1052
                const struct sockaddr *sa, socklen_t len,
1053
                int flags) {
1054

1055
        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control = {};
741✔
1056
        struct msghdr mh = {
741✔
1057
                .msg_name = (struct sockaddr*) sa,
1058
                .msg_namelen = len,
1059
                .msg_iov = (struct iovec *)iov,
1060
                .msg_iovlen = iovlen,
1061
        };
1062
        ssize_t k;
741✔
1063

1064
        assert(transport_fd >= 0);
741✔
1065

1066
        /*
1067
         * We need either an FD or data to send.
1068
         * If there's nothing, return an error.
1069
         */
1070
        if (fd < 0 && !iov)
741✔
1071
                return -EINVAL;
741✔
1072

1073
        if (fd >= 0) {
740✔
1074
                struct cmsghdr *cmsg;
738✔
1075

1076
                mh.msg_control = &control;
738✔
1077
                mh.msg_controllen = sizeof(control);
738✔
1078

1079
                cmsg = CMSG_FIRSTHDR(&mh);
738✔
1080
                cmsg->cmsg_level = SOL_SOCKET;
738✔
1081
                cmsg->cmsg_type = SCM_RIGHTS;
738✔
1082
                cmsg->cmsg_len = CMSG_LEN(sizeof(int));
738✔
1083
                memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
738✔
1084
        }
1085
        k = sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags);
740✔
1086
        if (k < 0)
740✔
1087
                return (ssize_t) -errno;
×
1088

1089
        return k;
1090
}
1091

1092
int send_one_fd_sa(
6✔
1093
                int transport_fd,
1094
                int fd,
1095
                const struct sockaddr *sa, socklen_t len,
1096
                int flags) {
1097

1098
        assert(fd >= 0);
6✔
1099

1100
        return (int) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, sa, len, flags);
6✔
1101
}
1102

1103
ssize_t receive_many_fds_iov(
1✔
1104
                int transport_fd,
1105
                struct iovec *iov, size_t iovlen,
1106
                int **ret_fds_array, size_t *ret_n_fds_array,
1107
                int flags) {
1108

1109
        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int) * SCM_MAX_FD)) control;
1✔
1110
        struct msghdr mh = {
1✔
1111
                .msg_control = &control,
1112
                .msg_controllen = sizeof(control),
1113
                .msg_iov = iov,
1114
                .msg_iovlen = iovlen,
1115
        };
1116
        _cleanup_free_ int *fds_array = NULL;
1✔
1117
        size_t n_fds_array = 0;
1✔
1118
        struct cmsghdr *cmsg;
1✔
1119
        ssize_t k;
1✔
1120

1121
        assert(transport_fd >= 0);
1✔
1122
        assert(ret_fds_array);
1✔
1123
        assert(ret_n_fds_array);
1✔
1124

1125
        /*
1126
         * Receive many FDs via @transport_fd. We don't care for the transport-type. We retrieve all the FDs
1127
         * at once. This is best used in combination with send_many_fds().
1128
         */
1129

1130
        k = recvmsg_safe(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags);
1✔
1131
        if (k < 0)
1✔
1132
                return k;
1133

1134
        CMSG_FOREACH(cmsg, &mh)
4✔
1135
                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
1✔
1136
                        size_t n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
1✔
1137

1138
                        if (!GREEDY_REALLOC_APPEND(fds_array, n_fds_array, CMSG_TYPED_DATA(cmsg, int), n)) {
1✔
1139
                                cmsg_close_all(&mh);
×
1140
                                return -ENOMEM;
1141
                        }
1142
                }
1143

1144
        if (n_fds_array == 0) {
1✔
1145
                cmsg_close_all(&mh);
×
1146

1147
                /* If didn't receive an FD or any data, return an error. */
1148
                if (k == 0)
×
1149
                        return -EIO;
1150
        }
1151

1152
        *ret_fds_array = TAKE_PTR(fds_array);
1✔
1153
        *ret_n_fds_array = n_fds_array;
1✔
1154

1155
        return k;
1✔
1156
}
1157

1158
int receive_many_fds(int transport_fd, int **ret_fds_array, size_t *ret_n_fds_array, int flags) {
×
1159
        ssize_t k;
×
1160

1161
        k = receive_many_fds_iov(transport_fd, NULL, 0, ret_fds_array, ret_n_fds_array, flags);
×
1162
        if (k == 0)
×
1163
                return 0;
1164

1165
        /* k must be negative, since receive_many_fds_iov() only returns a positive value if data was received
1166
         * through the iov. */
1167
        assert(k < 0);
×
1168
        return (int) k;
×
1169
}
1170

1171
ssize_t receive_one_fd_iov(
5,101✔
1172
                int transport_fd,
1173
                struct iovec *iov, size_t iovlen,
1174
                int flags,
1175
                int *ret_fd) {
1176

1177
        CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int))) control;
5,101✔
1178
        struct msghdr mh = {
5,101✔
1179
                .msg_control = &control,
1180
                .msg_controllen = sizeof(control),
1181
                .msg_iov = iov,
1182
                .msg_iovlen = iovlen,
1183
        };
1184
        struct cmsghdr *found;
5,101✔
1185
        ssize_t k;
5,101✔
1186

1187
        assert(transport_fd >= 0);
5,101✔
1188
        assert(ret_fd);
5,101✔
1189

1190
        /*
1191
         * Receive a single FD via @transport_fd. We don't care for
1192
         * the transport-type. We retrieve a single FD at most, so for
1193
         * packet-based transports, the caller must ensure to send
1194
         * only a single FD per packet.  This is best used in
1195
         * combination with send_one_fd().
1196
         */
1197

1198
        k = recvmsg_safe(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags);
5,101✔
1199
        if (k < 0)
5,101✔
1200
                return k;
5,101✔
1201

1202
        found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int)));
4,920✔
1203
        if (!found) {
4,920✔
1204
                cmsg_close_all(&mh);
1,542✔
1205

1206
                /* If didn't receive an FD or any data, return an error. */
1207
                if (k == 0)
1,542✔
1208
                        return -EIO;
1209
        }
1210

1211
        if (found)
3,379✔
1212
                *ret_fd = *CMSG_TYPED_DATA(found, int);
3,378✔
1213
        else
1214
                *ret_fd = -EBADF;
1✔
1215

1216
        return k;
1217
}
1218

1219
int receive_one_fd(int transport_fd, int flags) {
587✔
1220
        int fd;
587✔
1221
        ssize_t k;
587✔
1222

1223
        k = receive_one_fd_iov(transport_fd, NULL, 0, flags, &fd);
587✔
1224
        if (k == 0)
587✔
1225
                return fd;
519✔
1226

1227
        /* k must be negative, since receive_one_fd_iov() only returns
1228
         * a positive value if data was received through the iov. */
1229
        assert(k < 0);
68✔
1230
        return (int) k;
68✔
1231
}
1232

1233
ssize_t next_datagram_size_fd(int fd) {
203,834✔
1234
        ssize_t l;
203,834✔
1235
        int k;
203,834✔
1236

1237
        /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
1238
         * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD doesn't
1239
         * do. This difference is actually of major importance as we need to be sure that the size returned here
1240
         * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
1241
         * the wrong size. */
1242

1243
        l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
203,834✔
1244
        if (l < 0) {
203,834✔
1245
                if (IN_SET(errno, EOPNOTSUPP, EFAULT))
606✔
1246
                        goto fallback;
×
1247

1248
                return -errno;
606✔
1249
        }
1250
        if (l == 0)
203,228✔
1251
                goto fallback;
65✔
1252

1253
        return l;
1254

1255
fallback:
65✔
1256
        k = 0;
65✔
1257

1258
        /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
1259
         * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
1260

1261
        if (ioctl(fd, FIONREAD, &k) < 0)
65✔
1262
                return -errno;
×
1263

1264
        return (ssize_t) k;
65✔
1265
}
1266

1267
/* Put a limit on how many times will attempt to call accept4(). We loop
1268
 * only on "transient" errors, but let's make sure we don't loop forever. */
1269
#define MAX_FLUSH_ITERATIONS 1024
1270

1271
int flush_accept(int fd) {
12✔
1272

1273
        int r, b;
12✔
1274
        socklen_t l = sizeof(b);
12✔
1275

1276
        /* Similar to flush_fd() but flushes all incoming connections by accepting and immediately closing
1277
         * them. */
1278

1279
        if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0)
12✔
1280
                return -errno;
×
1281

1282
        assert(l == sizeof(b));
12✔
1283
        if (!b) /* Let's check if this socket accepts connections before calling accept(). accept4() can
12✔
1284
                 * return EOPNOTSUPP if the fd is not a listening socket, which we should treat as a fatal
1285
                 * error, or in case the incoming TCP connection triggered a network issue, which we want to
1286
                 * treat as a transient error. Thus, let's rule out the first reason for EOPNOTSUPP early, so
1287
                 * we can loop safely on transient errors below. */
1288
                return -ENOTTY;
1289

1290
        for (unsigned iteration = 0;; iteration++) {
2✔
1291
                int cfd;
6✔
1292

1293
                r = fd_wait_for_event(fd, POLLIN, 0);
6✔
1294
                if (r < 0) {
6✔
1295
                        if (r == -EINTR)
×
1296
                                continue;
×
1297

1298
                        return r;
1299
                }
1300
                if (r == 0)
6✔
1301
                        return 0;
1302

1303
                if (iteration >= MAX_FLUSH_ITERATIONS)
2✔
1304
                        return log_debug_errno(SYNTHETIC_ERRNO(EBUSY),
×
1305
                                               "Failed to flush connections within " STRINGIFY(MAX_FLUSH_ITERATIONS) " iterations.");
1306

1307
                cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
2✔
1308
                if (cfd < 0) {
2✔
1309
                        if (errno == EAGAIN)
×
1310
                                return 0;
1311

1312
                        if (ERRNO_IS_ACCEPT_AGAIN(errno))
×
1313
                                continue;
×
1314

1315
                        return -errno;
×
1316
                }
1317

1318
                safe_close(cfd);
2✔
1319
        }
1320
}
1321

1322
struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) {
370,472✔
1323
        struct cmsghdr *cmsg;
370,472✔
1324

1325
        assert(mh);
370,472✔
1326

1327
        CMSG_FOREACH(cmsg, mh)
741,476✔
1328
                if (cmsg->cmsg_level == level &&
348,391✔
1329
                    cmsg->cmsg_type == type &&
348,125✔
1330
                    (length == (socklen_t) -1 || length == cmsg->cmsg_len))
347,668✔
1331
                        return cmsg;
1332

1333
        return NULL;
1334
}
1335

1336
void* cmsg_find_and_copy_data(struct msghdr *mh, int level, int type, void *buf, size_t buf_len) {
299✔
1337
        struct cmsghdr *cmsg;
299✔
1338

1339
        assert(mh);
299✔
1340
        assert(buf);
299✔
1341
        assert(buf_len > 0);
299✔
1342

1343
        /* This is similar to cmsg_find_data(), but copy the found data to buf. This should be typically used
1344
         * when reading possibly unaligned data such as timestamp, as time_t is 64-bit and size_t is 32-bit on
1345
         * RISCV32. See issue #27241. */
1346

1347
        cmsg = cmsg_find(mh, level, type, CMSG_LEN(buf_len));
299✔
1348
        if (!cmsg)
299✔
1349
                return NULL;
1350

1351
        return memcpy_safe(buf, CMSG_DATA(cmsg), buf_len);
294✔
1352
}
1353

1354
size_t sockaddr_ll_len(const struct sockaddr_ll *sa) {
306✔
1355
        /* Certain hardware address types (e.g Infiniband) do not fit into sll_addr
1356
         * (8 bytes) and run over the structure. This function returns the correct size that
1357
         * must be passed to kernel. */
1358

1359
        assert(sa->sll_family == AF_PACKET);
306✔
1360

1361
        size_t mac_len = sizeof(sa->sll_addr);
306✔
1362

1363
        if (be16toh(sa->sll_hatype) == ARPHRD_ETHER)
306✔
1364
                mac_len = MAX(mac_len, (size_t) ETH_ALEN);
306✔
1365
        if (be16toh(sa->sll_hatype) == ARPHRD_INFINIBAND)
306✔
NEW
1366
                mac_len = MAX(mac_len, (size_t) INFINIBAND_ALEN);
×
1367

1368
        return offsetof(struct sockaddr_ll, sll_addr) + mac_len;
306✔
1369
}
1370

1371
size_t sockaddr_un_len(const struct sockaddr_un *sa) {
2,471✔
1372
        /* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
1373

1374
        assert(sa->sun_family == AF_UNIX);
2,471✔
1375

1376
        return offsetof(struct sockaddr_un, sun_path) +
7,413✔
1377
                (sa->sun_path[0] == 0 ?
2,471✔
1378
                        1 + strnlen(sa->sun_path+1, sizeof(sa->sun_path)-1) :
587✔
1379
                        strnlen(sa->sun_path, sizeof(sa->sun_path))+1);
1,884✔
1380
}
1381

1382
size_t sockaddr_len(const union sockaddr_union *sa) {
207✔
1383
        switch (sa->sa.sa_family) {
207✔
1384
        case AF_INET:
1385
                return sizeof(struct sockaddr_in);
1386
        case AF_INET6:
64✔
1387
                return sizeof(struct sockaddr_in6);
64✔
1388
        case AF_UNIX:
3✔
1389
                return sockaddr_un_len(&sa->un);
3✔
NEW
1390
        case AF_PACKET:
×
NEW
1391
                return sockaddr_ll_len(&sa->ll);
×
NEW
1392
        case AF_NETLINK:
×
NEW
1393
                return sizeof(struct sockaddr_nl);
×
1394
        case AF_VSOCK:
1395
                return sizeof(struct sockaddr_vm);
NEW
1396
        default:
×
NEW
1397
                assert_not_reached();
×
1398
        }
1399
}
1400

1401
int socket_ioctl_fd(void) {
4,273✔
1402
        int fd;
4,273✔
1403

1404
        /* Create a socket to invoke the various network interface ioctl()s on. Traditionally only AF_INET was good for
1405
         * that. Since kernel 4.6 AF_NETLINK works for this too. We first try to use AF_INET hence, but if that's not
1406
         * available (for example, because it is made unavailable via SECCOMP or such), we'll fall back to the more
1407
         * generic AF_NETLINK. */
1408

1409
        fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
4,273✔
1410
        if (fd < 0)
4,273✔
1411
                fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_GENERIC);
×
1412
        if (fd < 0)
×
1413
                return -errno;
×
1414

1415
        return fd;
1416
}
1417

1418
int sockaddr_un_unlink(const struct sockaddr_un *sa) {
1,458✔
1419
        const char *p, * nul;
1,458✔
1420

1421
        assert(sa);
1,458✔
1422

1423
        if (sa->sun_family != AF_UNIX)
1,458✔
1424
                return -EPROTOTYPE;
1425

1426
        if (sa->sun_path[0] == 0) /* Nothing to do for abstract sockets */
1,458✔
1427
                return 0;
1428

1429
        /* The path in .sun_path is not necessarily NUL terminated. Let's fix that. */
1430
        nul = memchr(sa->sun_path, 0, sizeof(sa->sun_path));
1,458✔
1431
        if (nul)
1,458✔
1432
                p = sa->sun_path;
1433
        else
1434
                p = memdupa_suffix0(sa->sun_path, sizeof(sa->sun_path));
×
1435

1436
        if (unlink(p) < 0)
1,458✔
1437
                return -errno;
1,319✔
1438

1439
        return 1;
1440
}
1441

1442
int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
367,351✔
1443
        size_t l;
367,351✔
1444

1445
        assert(ret);
367,351✔
1446
        assert(path);
367,351✔
1447

1448
        /* Initialize ret->sun_path from the specified argument. This will interpret paths starting with '@' as
1449
         * abstract namespace sockets, and those starting with '/' as regular filesystem sockets. It won't accept
1450
         * anything else (i.e. no relative paths), to avoid ambiguities. Note that this function cannot be used to
1451
         * reference paths in the abstract namespace that include NUL bytes in the name. */
1452

1453
        l = strlen(path);
367,351✔
1454
        if (l < 2)
367,351✔
1455
                return -EINVAL;
1456
        if (!IN_SET(path[0], '/', '@'))
367,350✔
1457
                return -EINVAL;
1458

1459
        /* Don't allow paths larger than the space in sockaddr_un. Note that we are a tiny bit more restrictive than
1460
         * the kernel is: we insist on NUL termination (both for abstract namespace and regular file system socket
1461
         * addresses!), which the kernel doesn't. We do this to reduce chance of incompatibility with other apps that
1462
         * do not expect non-NUL terminated file system path. */
1463
        if (l+1 > sizeof(ret->sun_path))
367,350✔
1464
                return path[0] == '@' ? -EINVAL : -ENAMETOOLONG; /* return a recognizable error if this is
2✔
1465
                                                                  * too long to fit into a sockaddr_un, but
1466
                                                                  * is a file system path, and thus might be
1467
                                                                  * connectible via O_PATH indirection. */
1468

1469
        *ret = (struct sockaddr_un) {
367,348✔
1470
                .sun_family = AF_UNIX,
1471
        };
1472

1473
        if (path[0] == '@') {
367,348✔
1474
                /* Abstract namespace socket */
1475
                memcpy(ret->sun_path + 1, path + 1, l); /* copy *with* trailing NUL byte */
211,901✔
1476
                return (int) (offsetof(struct sockaddr_un, sun_path) + l); /* 🔥 *don't* 🔥 include trailing NUL in size */
211,901✔
1477

1478
        } else {
1479
                assert(path[0] == '/');
155,447✔
1480

1481
                /* File system socket */
1482
                memcpy(ret->sun_path, path, l + 1); /* copy *with* trailing NUL byte */
155,447✔
1483
                return (int) (offsetof(struct sockaddr_un, sun_path) + l + 1); /* include trailing NUL in size */
155,447✔
1484
        }
1485
}
1486

1487
int socket_bind_to_ifname(int fd, const char *ifname) {
1✔
1488
        assert(fd >= 0);
1✔
1489

1490
        /* Call with NULL to drop binding */
1491

1492
        return RET_NERRNO(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen_ptr(ifname)));
2✔
1493
}
1494

1495
int socket_bind_to_ifindex(int fd, int ifindex) {
704✔
1496
        assert(fd >= 0);
704✔
1497

1498
        if (ifindex <= 0)
704✔
1499
                /* Drop binding */
1500
                return RET_NERRNO(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, NULL, 0));
52✔
1501

1502
        return setsockopt_int(fd, SOL_SOCKET, SO_BINDTOIFINDEX, ifindex);
652✔
1503
}
1504

1505
int socket_autobind(int fd, char **ret_name) {
239✔
1506
        _cleanup_free_ char *name = NULL;
239✔
1507
        uint64_t random;
239✔
1508
        int r;
239✔
1509

1510
        /* Generate a random abstract socket name and bind fd to it. This is modeled after the kernel
1511
         * "autobind" feature, but uses 64-bit random number internally. */
1512

1513
        assert(fd >= 0);
239✔
1514
        assert(ret_name);
239✔
1515

1516
        random = random_u64();
239✔
1517

1518
        if (asprintf(&name, "@%" PRIu64, random) < 0)
239✔
1519
                return -ENOMEM;
1520

1521
        union sockaddr_union sa;
239✔
1522
        assert_cc(DECIMAL_STR_MAX(uint64_t) < sizeof(sa.un.sun_path));
239✔
1523

1524
        r = sockaddr_un_set_path(&sa.un, name);
239✔
1525
        if (r < 0)
239✔
1526
                return r;
1527

1528
        if (bind(fd, &sa.sa, r) < 0)
239✔
1529
                return -errno;
×
1530

1531
        *ret_name = TAKE_PTR(name);
239✔
1532
        return 0;
239✔
1533
}
1534

1535
ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
2,875,925✔
1536
        ssize_t n;
2,875,925✔
1537

1538
        /* A wrapper around recvmsg() that checks for MSG_CTRUNC and MSG_TRUNC, and turns them into an error,
1539
         * in a reasonably safe way, closing any received fds in the error path.
1540
         *
1541
         * Note that unlike our usual coding style this might modify *msg on failure. */
1542

1543
        assert(sockfd >= 0);
2,875,925✔
1544
        assert(msg);
2,875,925✔
1545

1546
        n = recvmsg(sockfd, msg, flags);
2,875,925✔
1547
        if (n < 0)
2,875,925✔
1548
                return -errno;
269,596✔
1549

1550
        if (FLAGS_SET(msg->msg_flags, MSG_CTRUNC) ||
2,606,329✔
1551
            (!FLAGS_SET(flags, MSG_PEEK) && FLAGS_SET(msg->msg_flags, MSG_TRUNC))) {
2,606,329✔
1552
                cmsg_close_all(msg);
×
1553
                return FLAGS_SET(msg->msg_flags, MSG_CTRUNC) ? -ECHRNG : -EXFULL;
×
1554
        }
1555

1556
        return n;
1557
}
1558

1559
int socket_get_family(int fd) {
19,608✔
1560
        int af;
19,608✔
1561
        socklen_t sl = sizeof(af);
19,608✔
1562

1563
        if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0)
19,608✔
1564
                return -errno;
×
1565

1566
        if (sl != sizeof(af))
19,608✔
1567
                return -EINVAL;
1568

1569
        return af;
19,608✔
1570
}
1571

1572
int socket_set_recvpktinfo(int fd, int af, bool b) {
13,831✔
1573

1574
        if (af == AF_UNSPEC) {
13,831✔
1575
                af = socket_get_family(fd);
×
1576
                if (af < 0)
×
1577
                        return af;
1578
        }
1579

1580
        switch (af) {
13,831✔
1581

1582
        case AF_INET:
7,250✔
1583
                return setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, b);
7,250✔
1584

1585
        case AF_INET6:
6,548✔
1586
                return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, b);
6,548✔
1587

1588
        case AF_NETLINK:
33✔
1589
                return setsockopt_int(fd, SOL_NETLINK, NETLINK_PKTINFO, b);
33✔
1590

1591
        case AF_PACKET:
×
1592
                return setsockopt_int(fd, SOL_PACKET, PACKET_AUXDATA, b);
×
1593

1594
        default:
1595
                return -EAFNOSUPPORT;
1596
        }
1597
}
1598

1599
int socket_set_unicast_if(int fd, int af, int ifi) {
123✔
1600
        be32_t ifindex_be = htobe32(ifi);
123✔
1601

1602
        if (af == AF_UNSPEC) {
123✔
1603
                af = socket_get_family(fd);
×
1604
                if (af < 0)
×
1605
                        return af;
123✔
1606
        }
1607

1608
        switch (af) {
123✔
1609

1610
        case AF_INET:
89✔
1611
                return RET_NERRNO(setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)));
89✔
1612

1613
        case AF_INET6:
34✔
1614
                return RET_NERRNO(setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)));
34✔
1615

1616
        default:
1617
                return -EAFNOSUPPORT;
1618
        }
1619
}
1620

1621
int socket_set_option(int fd, int af, int opt_ipv4, int opt_ipv6, int val) {
27,473✔
1622
        if (af == AF_UNSPEC) {
27,473✔
1623
                af = socket_get_family(fd);
×
1624
                if (af < 0)
×
1625
                        return af;
1626
        }
1627

1628
        switch (af) {
27,473✔
1629

1630
        case AF_INET:
14,367✔
1631
                return setsockopt_int(fd, IPPROTO_IP, opt_ipv4, val);
14,367✔
1632

1633
        case AF_INET6:
13,106✔
1634
                return setsockopt_int(fd, IPPROTO_IPV6, opt_ipv6, val);
13,106✔
1635

1636
        default:
1637
                return -EAFNOSUPPORT;
1638
        }
1639
}
1640

1641
int socket_get_mtu(int fd, int af, size_t *ret) {
734✔
1642
        int mtu, r;
734✔
1643

1644
        if (af == AF_UNSPEC) {
734✔
1645
                af = socket_get_family(fd);
×
1646
                if (af < 0)
×
1647
                        return af;
734✔
1648
        }
1649

1650
        switch (af) {
734✔
1651

1652
        case AF_INET:
342✔
1653
                r = getsockopt_int(fd, IPPROTO_IP, IP_MTU, &mtu);
342✔
1654
                break;
1655

1656
        case AF_INET6:
392✔
1657
                r = getsockopt_int(fd, IPPROTO_IPV6, IPV6_MTU, &mtu);
392✔
1658
                break;
1659

1660
        default:
1661
                return -EAFNOSUPPORT;
1662
        }
1663

1664
        if (r < 0)
734✔
1665
                return r;
1666
        if (mtu <= 0)
682✔
1667
                return -EINVAL;
1668

1669
        *ret = (size_t) mtu;
682✔
1670
        return 0;
682✔
1671
}
1672

1673
static int connect_unix_path_simple(int fd, const char *path) {
162,532✔
1674
        union sockaddr_union sa = {
162,532✔
1675
                .un.sun_family = AF_UNIX,
1676
        };
1677
        size_t l;
162,532✔
1678

1679
        assert(fd >= 0);
162,532✔
1680
        assert(path);
162,532✔
1681

1682
        l = strlen(path);
162,532✔
1683
        assert(l > 0);
162,532✔
1684
        assert(l < sizeof(sa.un.sun_path));
162,532✔
1685

1686
        memcpy(sa.un.sun_path, path, l + 1);
162,532✔
1687
        return RET_NERRNO(connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + l + 1));
162,532✔
1688
}
1689

1690
static int connect_unix_inode(int fd, int inode_fd) {
14✔
1691
        assert(fd >= 0);
14✔
1692
        assert(inode_fd >= 0);
14✔
1693

1694
        return connect_unix_path_simple(fd, FORMAT_PROC_FD_PATH(inode_fd));
14✔
1695
}
1696

1697
int connect_unix_path(int fd, int dir_fd, const char *path) {
162,532✔
1698
        _cleanup_close_ int inode_fd = -EBADF;
162,532✔
1699

1700
        assert(fd >= 0);
162,532✔
1701
        assert(dir_fd == AT_FDCWD || dir_fd >= 0);
162,532✔
1702

1703
        /* Connects to the specified AF_UNIX socket in the file system. Works around the 108 byte size limit
1704
         * in sockaddr_un, by going via O_PATH if needed. This hence works for any kind of path. */
1705

1706
        if (!path)
162,532✔
1707
                return connect_unix_inode(fd, dir_fd); /* If no path is specified, then dir_fd refers to the socket inode to connect to. */
1✔
1708

1709
        /* Refuse zero length path early, to make sure AF_UNIX stack won't mistake this for an abstract
1710
         * namespace path, since first char is NUL */
1711
        if (isempty(path))
325,063✔
1712
                return -EINVAL;
1713

1714
        /* Shortcut for the simple case */
1715
        if (dir_fd == AT_FDCWD && strlen(path) < sizeof_field(struct sockaddr_un, sun_path))
162,531✔
1716
                return connect_unix_path_simple(fd, path);
162,518✔
1717

1718
        /* If dir_fd is specified, then we need to go the indirect O_PATH route, because connectat() does not
1719
         * exist. If the path is too long, we also need to take the indirect route, since we can't fit this
1720
         * into a sockaddr_un directly. */
1721

1722
        inode_fd = openat(dir_fd, path, O_PATH|O_CLOEXEC);
13✔
1723
        if (inode_fd < 0)
13✔
1724
                return -errno;
×
1725

1726
        return connect_unix_inode(fd, inode_fd);
13✔
1727
}
1728

1729
int socket_address_parse_unix(SocketAddress *ret_address, const char *s) {
217,151✔
1730
        struct sockaddr_un un;
217,151✔
1731
        int r;
217,151✔
1732

1733
        assert(ret_address);
217,151✔
1734
        assert(s);
217,151✔
1735

1736
        if (!IN_SET(*s, '/', '@'))
217,151✔
1737
                return -EPROTO;
217,151✔
1738

1739
        r = sockaddr_un_set_path(&un, s);
216,712✔
1740
        if (r < 0)
216,712✔
1741
                return r;
1742

1743
        *ret_address = (SocketAddress) {
216,710✔
1744
                .sockaddr.un = un,
1745
                .size = r,
1746
        };
1747

1748
        return 0;
216,710✔
1749
}
1750

1751
int vsock_parse_port(const char *s, unsigned *ret) {
371✔
1752
        int r;
371✔
1753

1754
        assert(ret);
371✔
1755

1756
        if (!s)
371✔
1757
                return -EINVAL;
371✔
1758

1759
        unsigned u;
371✔
1760
        r = safe_atou(s, &u);
371✔
1761
        if (r < 0)
371✔
1762
                return r;
1763

1764
        /* Port 0 is apparently valid and not special in AF_VSOCK (unlike on IP). But VMADDR_PORT_ANY
1765
         * (UINT32_MAX) is. Hence refuse that. */
1766

1767
        if (u == VMADDR_PORT_ANY)
368✔
1768
                return -EINVAL;
1769

1770
        *ret = u;
368✔
1771
        return 0;
368✔
1772
}
1773

1774
int vsock_parse_cid(const char *s, unsigned *ret) {
331✔
1775
        assert(ret);
331✔
1776

1777
        if (!s)
331✔
1778
                return -EINVAL;
1779

1780
        /* Parsed an AF_VSOCK "CID". This is a 32bit entity, and the usual type is "unsigned". We recognize
1781
         * the three special CIDs as strings, and otherwise parse the numeric CIDs. */
1782

1783
        if (streq(s, "hypervisor"))
331✔
1784
                *ret = VMADDR_CID_HYPERVISOR;
×
1785
        else if (streq(s, "local"))
331✔
1786
                *ret = VMADDR_CID_LOCAL;
×
1787
        else if (streq(s, "host"))
331✔
1788
                *ret = VMADDR_CID_HOST;
×
1789
        else
1790
                return safe_atou(s, ret);
331✔
1791

1792
        return 0;
1793
}
1794

1795
int socket_address_parse_vsock(SocketAddress *ret_address, const char *s) {
439✔
1796
        /* AF_VSOCK socket in vsock:cid:port notation */
1797
        _cleanup_free_ char *n = NULL;
439✔
1798
        char *e, *cid_start;
439✔
1799
        unsigned port, cid;
439✔
1800
        int type, r;
439✔
1801

1802
        assert(ret_address);
439✔
1803
        assert(s);
439✔
1804

1805
        if ((cid_start = startswith(s, "vsock:")))
439✔
1806
                type = 0;
1807
        else if ((cid_start = startswith(s, "vsock-dgram:")))
387✔
1808
                type = SOCK_DGRAM;
1809
        else if ((cid_start = startswith(s, "vsock-seqpacket:")))
387✔
1810
                type = SOCK_SEQPACKET;
1811
        else if ((cid_start = startswith(s, "vsock-stream:")))
387✔
1812
                type = SOCK_STREAM;
1813
        else
1814
                return -EPROTO;
1815

1816
        e = strchr(cid_start, ':');
373✔
1817
        if (!e)
373✔
1818
                return -EINVAL;
1819

1820
        r = vsock_parse_port(e+1, &port);
371✔
1821
        if (r < 0)
371✔
1822
                return r;
1823

1824
        n = strndup(cid_start, e - cid_start);
368✔
1825
        if (!n)
368✔
1826
                return -ENOMEM;
1827

1828
        if (isempty(n))
368✔
1829
                cid = VMADDR_CID_ANY;
37✔
1830
        else {
1831
                r = vsock_parse_cid(n, &cid);
331✔
1832
                if (r < 0)
331✔
1833
                        return r;
1834
        }
1835

1836
        *ret_address = (SocketAddress) {
365✔
1837
                .sockaddr.vm = {
1838
                        .svm_family = AF_VSOCK,
1839
                        .svm_cid = cid,
1840
                        .svm_port = port,
1841
                },
1842
                .type = type,
1843
                .size = sizeof(struct sockaddr_vm),
1844
        };
1845

1846
        return 0;
365✔
1847
}
1848

1849
int vsock_get_local_cid(unsigned *ret) {
16✔
1850
        _cleanup_close_ int vsock_fd = -EBADF;
16✔
1851

1852
        vsock_fd = open("/dev/vsock", O_RDONLY|O_CLOEXEC);
16✔
1853
        if (vsock_fd < 0)
16✔
1854
                return log_debug_errno(errno, "Failed to open /dev/vsock: %m");
13✔
1855

1856
        unsigned tmp;
3✔
1857
        if (ioctl(vsock_fd, IOCTL_VM_SOCKETS_GET_LOCAL_CID, ret ?: &tmp) < 0)
6✔
1858
                return log_debug_errno(errno, "Failed to query local AF_VSOCK CID: %m");
×
1859

1860
        return 0;
1861
}
1862

1863
int netlink_socket_get_multicast_groups(int fd, size_t *ret_len, uint32_t **ret_groups) {
11,999✔
1864
        _cleanup_free_ uint32_t *groups = NULL;
23,998✔
1865
        socklen_t len = 0, old_len;
11,999✔
1866

1867
        assert(fd >= 0);
11,999✔
1868

1869
        if (getsockopt(fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len) < 0)
11,999✔
1870
                return -errno;
×
1871

1872
        if (len == 0)
11,999✔
1873
                goto finalize;
11,582✔
1874

1875
        groups = new0(uint32_t, len);
417✔
1876
        if (!groups)
417✔
1877
                return -ENOMEM;
1878

1879
        old_len = len;
417✔
1880

1881
        if (getsockopt(fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len) < 0)
417✔
1882
                return -errno;
×
1883

1884
        if (old_len != len)
417✔
1885
                return -EIO;
1886

1887
finalize:
417✔
1888
        if (ret_len)
11,999✔
1889
                *ret_len = len;
11,999✔
1890
        if (ret_groups)
11,999✔
1891
                *ret_groups = TAKE_PTR(groups);
11,999✔
1892

1893
        return 0;
1894
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc