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

systemd / systemd / 15263807472

26 May 2025 08:53PM UTC coverage: 72.046% (-0.002%) from 72.048%
15263807472

push

github

yuwata
src/core/manager.c: log preset activity on first boot

This gives us a little more information about what units were enabled
or disabled on that first boot and will be useful for OS developers
tracking down the source of unit state.

An example with this enabled looks like:

```
NET: Registered PF_VSOCK protocol family
systemd[1]: Applying preset policy.
systemd[1]: Unit /etc/systemd/system/dnsmasq.service is masked, ignoring.
systemd[1]: Unit /etc/systemd/system/systemd-repart.service is masked, ignoring.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket'.
systemd[1]: Removed '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir.mount' → '/etc/systemd/system/var-mnt-workdir.mount'.
systemd[1]: Created symlink '/etc/systemd/system/multi-user.target.wants/var-mnt-workdir\x2dtmp.mount' → '/etc/systemd/system/var-mnt-workdir\x2dtmp.mount'.
systemd[1]: Created symlink '/etc/systemd/system/afterburn-sshkeys.target.requires/afterburn-sshkeys@core.service' → '/usr/lib/systemd/system/afterburn-sshkeys@.service'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-varlink.socket' → '/usr/lib/systemd/system/systemd-resolved-varlink.socket'.
systemd[1]: Created symlink '/etc/systemd/system/sockets.target.wants/systemd-resolved-monitor.socket' → '/usr/lib/systemd/system/systemd-resolved-monitor.socket'.
systemd[1]: Populated /etc with preset unit settings.
```

Considering it only happens on first boot and not on every boot I think
the extra information is worth the extra verbosity in the logs just for
that boot.

5 of 6 new or added lines in 1 file covered. (83.33%)

5463 existing lines in 165 files now uncovered.

299151 of 415222 relevant lines covered (72.05%)

702386.45 hits per line

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

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

3
#include <fcntl.h>
4
#include <linux/if.h>
5
#include <linux/if_arp.h>
6
#include <mqueue.h>
7
#include <net/if.h>
8
#include <netdb.h>
9
#include <netinet/ip.h>
10
#include <poll.h>
11
#include <stdio.h>
12
#include <sys/ioctl.h>
13
#include <unistd.h>
14

15
#include "alloc-util.h"
16
#include "errno-util.h"
17
#include "escape.h"
18
#include "fd-util.h"
19
#include "format-ifname.h"
20
#include "format-util.h"
21
#include "in-addr-util.h"
22
#include "io-util.h"
23
#include "log.h"
24
#include "memory-util.h"
25
#include "parse-util.h"
26
#include "path-util.h"
27
#include "pidref.h"
28
#include "process-util.h"
29
#include "random-util.h"
30
#include "socket-util.h"
31
#include "sparse-endian.h"
32
#include "string-table.h"
33
#include "string-util.h"
34
#include "strv.h"
35
#include "sysctl-util.h"
36

37
#if ENABLE_IDN
38
#  define IDN_FLAGS NI_IDN
39
#else
40
#  define IDN_FLAGS 0
41
#endif
42

43
/* From the kernel's include/net/scm.h */
44
#ifndef SCM_MAX_FD
45
#  define SCM_MAX_FD 253
46
#endif
47

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

UNCOV
57
DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
×
58

59
int socket_address_verify(const SocketAddress *a, bool strict) {
8,064✔
60
        assert(a);
8,064✔
61

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

65
        switch (socket_address_family(a)) {
8,064✔
66

67
        case AF_INET:
25✔
68
                if (a->size != sizeof(struct sockaddr_in))
25✔
69
                        return -EINVAL;
70

71
                if (a->sockaddr.in.sin_port == 0)
25✔
72
                        return -EINVAL;
73

74
                if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
25✔
75
                        return -EINVAL;
1✔
76

77
                return 0;
78

79
        case AF_INET6:
16✔
80
                if (a->size != sizeof(struct sockaddr_in6))
16✔
81
                        return -EINVAL;
82

83
                if (a->sockaddr.in6.sin6_port == 0)
16✔
84
                        return -EINVAL;
85

86
                if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
16✔
UNCOV
87
                        return -EINVAL;
×
88

89
                return 0;
90

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

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

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

120
                if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET))
7,577✔
UNCOV
121
                        return -EINVAL;
×
122

123
                return 0;
124

125
        case AF_NETLINK:
361✔
126

127
                if (a->size != sizeof(struct sockaddr_nl))
361✔
128
                        return -EINVAL;
129

130
                if (!IN_SET(a->type, 0, SOCK_RAW, SOCK_DGRAM))
361✔
UNCOV
131
                        return -EINVAL;
×
132

133
                return 0;
134

135
        case AF_VSOCK:
68✔
136
                if (a->size != sizeof(struct sockaddr_vm))
68✔
137
                        return -EINVAL;
138

139
                if (!IN_SET(a->type, 0, SOCK_STREAM, SOCK_DGRAM))
68✔
UNCOV
140
                        return -EINVAL;
×
141

142
                return 0;
143

144
        default:
145
                return -EAFNOSUPPORT;
146
        }
147
}
148

149
int socket_address_print(const SocketAddress *a, char **ret) {
1,688✔
150
        int r;
1,688✔
151

152
        assert(a);
1,688✔
153
        assert(ret);
1,688✔
154

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

162
        if (socket_address_family(a) == AF_NETLINK) {
1,688✔
163
                _cleanup_free_ char *sfamily = NULL;
124✔
164

165
                r = netlink_family_to_string_alloc(a->protocol, &sfamily);
124✔
166
                if (r < 0)
124✔
167
                        return r;
168

169
                r = asprintf(ret, "%s %u", sfamily, a->sockaddr.nl.nl_groups);
124✔
170
                if (r < 0)
124✔
171
                        return -ENOMEM;
172

173
                return 0;
124✔
174
        }
175

176
        return sockaddr_pretty(&a->sockaddr.sa, a->size, false, true, ret);
1,564✔
177
}
178

179
bool socket_address_can_accept(const SocketAddress *a) {
4,757✔
180
        assert(a);
4,757✔
181

182
        return
4,757✔
183
                IN_SET(a->type, SOCK_STREAM, SOCK_SEQPACKET);
4,757✔
184
}
185

186
bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
1,996✔
187
        assert(a);
1,996✔
188
        assert(b);
1,996✔
189

190
        /* Invalid addresses are unequal to all */
191
        if (socket_address_verify(a, false) < 0 ||
3,992✔
192
            socket_address_verify(b, false) < 0)
1,996✔
193
                return false;
194

195
        if (a->type != b->type)
1,995✔
196
                return false;
197

198
        if (socket_address_family(a) != socket_address_family(b))
1,994✔
199
                return false;
200

201
        switch (socket_address_family(a)) {
1,992✔
202

203
        case AF_INET:
6✔
204
                if (a->sockaddr.in.sin_addr.s_addr != b->sockaddr.in.sin_addr.s_addr)
6✔
205
                        return false;
206

207
                if (a->sockaddr.in.sin_port != b->sockaddr.in.sin_port)
5✔
208
                        return false;
1✔
209

210
                break;
211

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

216
                if (a->sockaddr.in6.sin6_port != b->sockaddr.in6.sin6_port)
2✔
UNCOV
217
                        return false;
×
218

219
                break;
220

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

226
                if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
1,875✔
227
                        return false;
228

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

236
                        if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
2✔
UNCOV
237
                                return false;
×
238
                }
239

240
                break;
241

242
        case AF_NETLINK:
90✔
243
                if (a->protocol != b->protocol)
90✔
244
                        return false;
245

246
                if (a->sockaddr.nl.nl_groups != b->sockaddr.nl.nl_groups)
90✔
247
                        return false;
1✔
248

249
                break;
250

251
        case AF_VSOCK:
19✔
252
                if (a->sockaddr.vm.svm_cid != b->sockaddr.vm.svm_cid)
19✔
253
                        return false;
254

255
                if (a->sockaddr.vm.svm_port != b->sockaddr.vm.svm_port)
18✔
256
                        return false;
1✔
257

258
                break;
259

260
        default:
261
                /* Cannot compare, so we assume the addresses are different */
262
                return false;
263
        }
264

265
        return true;
266
}
267

268
const char* socket_address_get_path(const SocketAddress *a) {
10,604✔
269
        assert(a);
10,604✔
270

271
        if (socket_address_family(a) != AF_UNIX)
10,604✔
272
                return NULL;
273

274
        if (a->sockaddr.un.sun_path[0] == 0)
10,124✔
275
                return NULL;
276

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

284
bool socket_ipv6_is_supported(void) {
142,036✔
285
        static int cached = -1;
142,036✔
286

287
        if (cached < 0) {
142,036✔
288

289
                if (access("/proc/net/if_inet6", F_OK) < 0) {
1,135✔
290

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

296
                        cached = false;
×
297
                } else
298
                        cached = true;
1,135✔
299
        }
300

301
        return cached;
142,036✔
302
}
303

304
bool socket_ipv6_is_enabled(void) {
102,766✔
305
        _cleanup_free_ char *v = NULL;
102,766✔
306
        int r;
102,766✔
307

308
        /* Much like socket_ipv6_is_supported(), but also checks that the sysctl that disables IPv6 on all
309
         * interfaces isn't turned on */
310

311
        if (!socket_ipv6_is_supported())
102,766✔
312
                return false;
313

314
        r = sysctl_read_ip_property(AF_INET6, "all", "disable_ipv6", &v);
102,766✔
315
        if (r < 0) {
102,766✔
UNCOV
316
                log_debug_errno(r, "Unexpected error reading 'net.ipv6.conf.all.disable_ipv6' sysctl: %m");
×
UNCOV
317
                return true;
×
318
        }
319

320
        r = parse_boolean(v);
102,766✔
321
        if (r < 0) {
102,766✔
UNCOV
322
                log_debug_errno(r, "Failed to pare 'net.ipv6.conf.all.disable_ipv6' sysctl: %m");
×
UNCOV
323
                return true;
×
324
        }
325

326
        return !r;
102,766✔
327
}
328

329
bool socket_address_matches_fd(const SocketAddress *a, int fd) {
935✔
330
        SocketAddress b;
935✔
331
        socklen_t solen;
935✔
332

333
        assert(a);
935✔
334
        assert(fd >= 0);
935✔
335

336
        b.size = sizeof(b.sockaddr);
935✔
337
        if (getsockname(fd, &b.sockaddr.sa, &b.size) < 0)
935✔
338
                return false;
935✔
339

340
        if (b.sockaddr.sa.sa_family != a->sockaddr.sa.sa_family)
935✔
341
                return false;
342

343
        solen = sizeof(b.type);
823✔
344
        if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &b.type, &solen) < 0)
823✔
345
                return false;
346

347
        if (b.type != a->type)
823✔
348
                return false;
349

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

355
                if (b.protocol != a->protocol)
×
356
                        return false;
357
        }
358

359
        return socket_address_equal(a, &b);
698✔
360
}
361

UNCOV
362
int sockaddr_port(const struct sockaddr *_sa, unsigned *ret_port) {
×
UNCOV
363
        const union sockaddr_union *sa = (const union sockaddr_union*) _sa;
×
364

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

367
        assert(sa);
×
368

UNCOV
369
        switch (sa->sa.sa_family) {
×
370

371
        case AF_INET:
×
UNCOV
372
                *ret_port = be16toh(sa->in.sin_port);
×
373
                return 0;
×
374

375
        case AF_INET6:
×
376
                *ret_port = be16toh(sa->in6.sin6_port);
×
377
                return 0;
×
378

379
        case AF_VSOCK:
×
380
                *ret_port = sa->vm.svm_port;
×
381
                return 0;
×
382

383
        default:
384
                return -EAFNOSUPPORT;
385
        }
386
}
387

388
const union in_addr_union *sockaddr_in_addr(const struct sockaddr *_sa) {
297✔
389
        const union sockaddr_union *sa = (const union sockaddr_union*) _sa;
297✔
390

391
        if (!sa)
297✔
392
                return NULL;
393

394
        switch (sa->sa.sa_family) {
297✔
395

396
        case AF_INET:
248✔
397
                return (const union in_addr_union*) &sa->in.sin_addr;
248✔
398

399
        case AF_INET6:
49✔
400
                return (const union in_addr_union*) &sa->in6.sin6_addr;
49✔
401

402
        default:
403
                return NULL;
404
        }
405
}
406

407
int sockaddr_set_in_addr(
708✔
408
                union sockaddr_union *u,
409
                int family,
410
                const union in_addr_union *a,
411
                uint16_t port) {
412

413
        assert(u);
708✔
414
        assert(a);
708✔
415

416
        switch (family) {
708✔
417

418
        case AF_INET:
705✔
419
                u->in = (struct sockaddr_in) {
705✔
420
                        .sin_family = AF_INET,
421
                        .sin_addr = a->in,
705✔
422
                        .sin_port = htobe16(port),
705✔
423
                };
424

425
                return 0;
705✔
426

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

434
                return 0;
3✔
435

436
        default:
437
                return -EAFNOSUPPORT;
438

439
        }
440
}
441

442
int sockaddr_pretty(
9,121✔
443
                const struct sockaddr *_sa,
444
                socklen_t salen,
445
                bool translate_ipv6,
446
                bool include_port,
447
                char **ret) {
448

449
        union sockaddr_union *sa = (union sockaddr_union*) _sa;
9,121✔
450
        char *p;
9,121✔
451
        int r;
9,121✔
452

453
        assert(sa);
9,121✔
454
        assert(salen >= sizeof(sa->sa.sa_family));
9,121✔
455
        assert(ret);
9,121✔
456

457
        switch (sa->sa.sa_family) {
9,121✔
458

459
        case AF_INET: {
92✔
460
                uint32_t a;
92✔
461

462
                a = be32toh(sa->in.sin_addr.s_addr);
92✔
463

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

478
        case AF_INET6: {
17✔
479
                static const unsigned char ipv4_prefix[] = {
17✔
480
                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF
481
                };
482

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

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

518
                break;
519
        }
520

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

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

540
                                _cleanup_free_ char *e = NULL;
8✔
541

542
                                e = cescape_length(path + 1, path_len - 1);
8✔
543
                                if (!e)
8✔
UNCOV
544
                                        return -ENOMEM;
×
545

546
                                p = strjoin("@", e);
8✔
547
                        } else {
548
                                if (path[path_len - 1] == '\0')
8,978✔
549
                                        /* We expect a terminating NUL and don't print it */
550
                                        path_len--;
8,977✔
551

552
                                p = cescape_length(path, path_len);
8,978✔
553
                        }
554
                }
555
                if (!p)
8,990✔
556
                        return -ENOMEM;
557

558
                break;
559

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

572
        default:
573
                return -EOPNOTSUPP;
574
        }
575

576
        *ret = p;
9,121✔
577
        return 0;
9,121✔
578
}
579

580
int getpeername_pretty(int fd, bool include_port, char **ret) {
3✔
581
        union sockaddr_union sa;
3✔
582
        socklen_t salen = sizeof(sa);
3✔
583
        int r;
3✔
584

585
        assert(fd >= 0);
3✔
586
        assert(ret);
3✔
587

588
        if (getpeername(fd, &sa.sa, &salen) < 0)
3✔
UNCOV
589
                return -errno;
×
590

591
        if (sa.sa.sa_family == AF_UNIX) {
3✔
592
                struct ucred ucred = UCRED_INVALID;
2✔
593

594
                /* UNIX connection sockets are anonymous, so let's use
595
                 * PID/UID as pretty credentials instead */
596

597
                r = getpeercred(fd, &ucred);
2✔
598
                if (r < 0)
2✔
599
                        return r;
2✔
600

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

604
                return 0;
2✔
605
        }
606

607
        /* For remote sockets we translate IPv6 addresses back to IPv4
608
         * if applicable, since that's nicer. */
609

610
        return sockaddr_pretty(&sa.sa, salen, true, include_port, ret);
1✔
611
}
612

613
int getsockname_pretty(int fd, char **ret) {
1✔
614
        union sockaddr_union sa;
1✔
615
        socklen_t salen = sizeof(sa);
1✔
616

617
        assert(fd >= 0);
1✔
618
        assert(ret);
1✔
619

620
        if (getsockname(fd, &sa.sa, &salen) < 0)
1✔
UNCOV
621
                return -errno;
×
622

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

628
        return sockaddr_pretty(&sa.sa, salen, false, true, ret);
1✔
629
}
630

UNCOV
631
int socknameinfo_pretty(const struct sockaddr *sa, socklen_t salen, char **ret) {
×
UNCOV
632
        char host[NI_MAXHOST];
×
UNCOV
633
        int r;
×
634

635
        assert(sa);
×
636
        assert(salen >= sizeof(sa_family_t));
×
637
        assert(ret);
×
638

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

648
                return sockaddr_pretty(sa, salen, /* translate_ipv6= */ true, /* include_port= */ true, ret);
×
649
        }
650

UNCOV
651
        return strdup_to(ret, host);
×
652
}
653

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

675
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(netlink_family, int, INT_MAX);
552✔
676

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

683
DEFINE_STRING_TABLE_LOOKUP(socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
160✔
684

UNCOV
685
SocketAddressBindIPv6Only socket_address_bind_ipv6_only_or_bool_from_string(const char *n) {
×
UNCOV
686
        int r;
×
687

UNCOV
688
        r = parse_boolean(n);
×
689
        if (r > 0)
×
690
                return SOCKET_ADDRESS_IPV6_ONLY;
UNCOV
691
        if (r == 0)
×
692
                return SOCKET_ADDRESS_BOTH;
693

UNCOV
694
        return socket_address_bind_ipv6_only_from_string(n);
×
695
}
696

697
bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b) {
1,286✔
698
        assert(a);
1,286✔
699
        assert(b);
1,286✔
700

701
        if (a->sa.sa_family != b->sa.sa_family)
1,286✔
702
                return false;
703

704
        if (a->sa.sa_family == AF_INET)
1,285✔
705
                return a->in.sin_addr.s_addr == b->in.sin_addr.s_addr;
4✔
706

707
        if (a->sa.sa_family == AF_INET6)
1,281✔
708
                return memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)) == 0;
1✔
709

710
        if (a->sa.sa_family == AF_VSOCK)
1,280✔
711
                return a->vm.svm_cid == b->vm.svm_cid;
1✔
712

713
        return false;
714
}
715

716
int fd_set_sndbuf(int fd, size_t n, bool increase) {
406,339✔
717
        int r, value;
406,339✔
718
        socklen_t l = sizeof(value);
406,339✔
719

720
        if (n > INT_MAX)
406,339✔
721
                return -ERANGE;
406,339✔
722

723
        r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
406,339✔
724
        if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
406,339✔
725
                return 0;
726

727
        /* First, try to set the buffer size with SO_SNDBUF. */
728
        r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, n);
406,339✔
729
        if (r < 0)
406,339✔
730
                return r;
731

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

739
        /* If we have the privileges we will ignore the kernel limit. */
740
        r = setsockopt_int(fd, SOL_SOCKET, SO_SNDBUFFORCE, n);
406,339✔
741
        if (r < 0)
406,339✔
742
                return r;
33,838✔
743

744
        return 1;
745
}
746

747
int fd_set_rcvbuf(int fd, size_t n, bool increase) {
32,284✔
748
        int r, value;
32,284✔
749
        socklen_t l = sizeof(value);
32,284✔
750

751
        if (n > INT_MAX)
32,284✔
752
                return -ERANGE;
32,284✔
753

754
        r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
32,284✔
755
        if (r >= 0 && l == sizeof(value) && increase ? (size_t) value >= n*2 : (size_t) value == n*2)
32,284✔
756
                return 0;
757

758
        /* First, try to set the buffer size with SO_RCVBUF. */
759
        r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, n);
32,283✔
760
        if (r < 0)
32,283✔
761
                return r;
762

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

770
        /* If we have the privileges we will ignore the kernel limit. */
771
        r = setsockopt_int(fd, SOL_SOCKET, SO_RCVBUFFORCE, n);
32,283✔
772
        if (r < 0)
32,283✔
773
                return r;
6,856✔
774

775
        return 1;
776
}
777

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

UNCOV
785
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
×
786

787
bool ifname_valid_char(char a) {
448,231✔
788
        if ((unsigned char) a >= 127U)
448,231✔
789
                return false;
790

791
        if ((unsigned char) a <= 32U)
448,231✔
792
                return false;
793

794
        if (IN_SET(a,
448,227✔
795
                   ':',  /* colons are used by the legacy "alias" interface logic */
796
                   '/',  /* slashes cannot work, since we need to use network interfaces in sysfs paths, and in paths slashes are separators */
797
                   '%')) /* %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 */
798
                return false;
10✔
799

800
        return true;
801
}
802

803
bool ifname_valid_full(const char *p, IfnameValidFlags flags) {
129,055✔
804
        bool numeric = true;
129,055✔
805

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

810
        assert(!(flags & ~_IFNAME_VALID_ALL));
129,055✔
811

812
        if (isempty(p))
129,055✔
813
                return false;
814

815
        /* A valid ifindex? If so, it's valid iff IFNAME_VALID_NUMERIC is set */
816
        if (parse_ifindex(p) >= 0)
124,529✔
817
                return flags & IFNAME_VALID_NUMERIC;
57✔
818

819
        if (flags & IFNAME_VALID_ALTERNATIVE) {
124,472✔
820
                if (strlen(p) >= ALTIFNAMSIZ)
11,754✔
821
                        return false;
822
        } else {
823
                if (strlen(p) >= IFNAMSIZ)
112,718✔
824
                        return false;
825
        }
826

827
        if (dot_or_dot_dot(p))
124,465✔
828
                return false;
829

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

835
        for (const char *t = p; *t; t++) {
565,974✔
836
                if (!ifname_valid_char(*t))
441,525✔
837
                        return false;
838

839
                numeric = numeric && ascii_isdigit(*t);
565,964✔
840
        }
841

842
        /* It's fully numeric but didn't parse as valid ifindex above? if so, it must be too large or zero or
843
         * so, let's refuse that. */
844
        if (numeric)
124,449✔
845
                return false;
2✔
846

847
        return true;
848
}
849

850
bool address_label_valid(const char *p) {
44✔
851

852
        if (isempty(p))
44✔
853
                return false;
854

855
        if (strlen(p) >= IFNAMSIZ)
44✔
856
                return false;
857

858
        while (*p) {
376✔
859
                if ((uint8_t) *p >= 127U)
332✔
860
                        return false;
861

862
                if ((uint8_t) *p <= 31U)
332✔
863
                        return false;
864
                p++;
332✔
865
        }
866

867
        return true;
868
}
869

870
int getpeercred(int fd, struct ucred *ucred) {
81,678✔
871
        socklen_t n = sizeof(struct ucred);
81,678✔
872
        struct ucred u;
81,678✔
873

874
        assert(fd >= 0);
81,678✔
875
        assert(ucred);
81,678✔
876

877
        if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n) < 0)
81,678✔
UNCOV
878
                return -errno;
×
879

880
        if (n != sizeof(struct ucred))
81,678✔
881
                return -EIO;
882

883
        /* Check if the data is actually useful and not suppressed due to namespacing issues */
884
        if (!pid_is_valid(u.pid))
81,678✔
885
                return -ENODATA;
886

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

890
        *ucred = u;
81,678✔
891
        return 0;
81,678✔
892
}
893

894
int getpeersec(int fd, char **ret) {
20,119✔
895
        _cleanup_free_ char *s = NULL;
40,238✔
896
        socklen_t n = 64;
20,119✔
897

898
        assert(fd >= 0);
20,119✔
899
        assert(ret);
20,119✔
900

901
        for (;;) {
20,119✔
902
                s = new0(char, n+1);
20,119✔
903
                if (!s)
20,119✔
904
                        return -ENOMEM;
905

906
                if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n) >= 0) {
20,119✔
907
                        s[n] = 0;
7,148✔
908
                        break;
7,148✔
909
                }
910

911
                if (errno != ERANGE)
12,971✔
912
                        return -errno;
12,971✔
913

UNCOV
914
                s = mfree(s);
×
915
        }
916

917
        if (isempty(s))
7,148✔
918
                return -EOPNOTSUPP;
919

920
        *ret = TAKE_PTR(s);
7,148✔
921

922
        return 0;
7,148✔
923
}
924

925
int getpeergroups(int fd, gid_t **ret) {
20,120✔
926
        socklen_t n = sizeof(gid_t) * 64U;
20,120✔
927
        _cleanup_free_ gid_t *d = NULL;
20,120✔
928

929
        assert(fd >= 0);
20,120✔
930
        assert(ret);
20,120✔
931

932
        long ngroups_max = sysconf(_SC_NGROUPS_MAX);
20,120✔
933
        if (ngroups_max > 0)
20,120✔
934
                n = MAX(n, sizeof(gid_t) * (socklen_t) ngroups_max);
20,120✔
935

936
        for (;;) {
20,120✔
937
                d = malloc(n);
20,120✔
938
                if (!d)
20,120✔
939
                        return -ENOMEM;
940

941
                if (getsockopt(fd, SOL_SOCKET, SO_PEERGROUPS, d, &n) >= 0)
20,120✔
942
                        break;
943

UNCOV
944
                if (errno != ERANGE)
×
UNCOV
945
                        return -errno;
×
946

UNCOV
947
                d = mfree(d);
×
948
        }
949

950
        assert_se(n % sizeof(gid_t) == 0);
20,120✔
951
        n /= sizeof(gid_t);
20,120✔
952

953
        if (n > INT_MAX)
20,120✔
954
                return -E2BIG;
955

956
        *ret = TAKE_PTR(d);
20,120✔
957

958
        return (int) n;
20,120✔
959
}
960

961
int getpeerpidfd(int fd) {
20,417✔
962
        socklen_t n = sizeof(int);
20,417✔
963
        int pidfd = -EBADF;
20,417✔
964

965
        assert(fd >= 0);
20,417✔
966

967
        if (getsockopt(fd, SOL_SOCKET, SO_PEERPIDFD, &pidfd, &n) < 0)
20,417✔
968
                return -errno;
2✔
969

970
        if (n != sizeof(int))
20,415✔
971
                return -EIO;
972

973
        return pidfd;
20,415✔
974
}
975

976
int getpeerpidref(int fd, PidRef *ret) {
4✔
977
        int r;
4✔
978

979
        assert(fd >= 0);
4✔
980
        assert(ret);
4✔
981

982
        int pidfd = getpeerpidfd(fd);
4✔
983
        if (pidfd < 0) {
4✔
UNCOV
984
                if (!ERRNO_IS_NEG_NOT_SUPPORTED(pidfd))
×
UNCOV
985
                        return pidfd;
×
986

UNCOV
987
                struct ucred ucred;
×
988
                r = getpeercred(fd, &ucred);
×
989
                if (r < 0)
×
990
                        return r;
991

992
                return pidref_set_pid(ret, ucred.pid);
×
993
        }
994

995
        return pidref_set_pidfd_consume(ret, pidfd);
4✔
996
}
997

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

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

1014
        assert(transport_fd >= 0);
1✔
1015
        assert(fds_array || n_fds_array == 0);
1✔
1016

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

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

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

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

1042
        return k;
1043
}
1044

1045
ssize_t send_one_fd_iov_sa(
801✔
1046
                int transport_fd,
1047
                int fd,
1048
                const struct iovec *iov, size_t iovlen,
1049
                const struct sockaddr *sa, socklen_t len,
1050
                int flags) {
1051

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

1061
        assert(transport_fd >= 0);
801✔
1062

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

1070
        if (fd >= 0) {
800✔
1071
                struct cmsghdr *cmsg;
798✔
1072

1073
                mh.msg_control = &control;
798✔
1074
                mh.msg_controllen = sizeof(control);
798✔
1075

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

1086
        return k;
1087
}
1088

1089
int send_one_fd_sa(
8✔
1090
                int transport_fd,
1091
                int fd,
1092
                const struct sockaddr *sa, socklen_t len,
1093
                int flags) {
1094

1095
        assert(fd >= 0);
8✔
1096

1097
        return (int) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, sa, len, flags);
8✔
1098
}
1099

1100
ssize_t receive_many_fds_iov(
1✔
1101
                int transport_fd,
1102
                struct iovec *iov, size_t iovlen,
1103
                int **ret_fds_array, size_t *ret_n_fds_array,
1104
                int flags) {
1105

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

1118
        assert(transport_fd >= 0);
1✔
1119
        assert(ret_fds_array);
1✔
1120
        assert(ret_n_fds_array);
1✔
1121

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

1127
        k = recvmsg_safe(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags);
1✔
1128
        if (k < 0)
1✔
1129
                return k;
1130

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

1135
                        if (!GREEDY_REALLOC_APPEND(fds_array, n_fds_array, CMSG_TYPED_DATA(cmsg, int), n)) {
1✔
UNCOV
1136
                                cmsg_close_all(&mh);
×
1137
                                return -ENOMEM;
1138
                        }
1139
                }
1140

1141
        if (n_fds_array == 0) {
1✔
UNCOV
1142
                cmsg_close_all(&mh);
×
1143

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

1149
        *ret_fds_array = TAKE_PTR(fds_array);
1✔
1150
        *ret_n_fds_array = n_fds_array;
1✔
1151

1152
        return k;
1✔
1153
}
1154

UNCOV
1155
int receive_many_fds(int transport_fd, int **ret_fds_array, size_t *ret_n_fds_array, int flags) {
×
UNCOV
1156
        ssize_t k;
×
1157

UNCOV
1158
        k = receive_many_fds_iov(transport_fd, NULL, 0, ret_fds_array, ret_n_fds_array, flags);
×
1159
        if (k == 0)
×
1160
                return 0;
1161

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

1168
ssize_t receive_one_fd_iov(
5,153✔
1169
                int transport_fd,
1170
                struct iovec *iov, size_t iovlen,
1171
                int flags,
1172
                int *ret_fd) {
1173

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

1184
        assert(transport_fd >= 0);
5,153✔
1185
        assert(ret_fd);
5,153✔
1186

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

1195
        k = recvmsg_safe(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags);
5,153✔
1196
        if (k < 0)
5,153✔
1197
                return k;
5,153✔
1198

1199
        found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int)));
4,968✔
1200
        if (!found) {
4,968✔
1201
                cmsg_close_all(&mh);
1,542✔
1202

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

1208
        if (found)
3,427✔
1209
                *ret_fd = *CMSG_TYPED_DATA(found, int);
3,426✔
1210
        else
1211
                *ret_fd = -EBADF;
1✔
1212

1213
        return k;
1214
}
1215

1216
int receive_one_fd(int transport_fd, int flags) {
638✔
1217
        int fd;
638✔
1218
        ssize_t k;
638✔
1219

1220
        k = receive_one_fd_iov(transport_fd, NULL, 0, flags, &fd);
638✔
1221
        if (k == 0)
638✔
1222
                return fd;
566✔
1223

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

1230
ssize_t next_datagram_size_fd(int fd) {
208,503✔
1231
        ssize_t l;
208,503✔
1232
        int k;
208,503✔
1233

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

1240
        l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
208,503✔
1241
        if (l < 0) {
208,503✔
1242
                if (IN_SET(errno, EOPNOTSUPP, EFAULT))
570✔
UNCOV
1243
                        goto fallback;
×
1244

1245
                return -errno;
570✔
1246
        }
1247
        if (l == 0)
207,933✔
1248
                goto fallback;
73✔
1249

1250
        return l;
1251

1252
fallback:
73✔
1253
        k = 0;
73✔
1254

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

1258
        if (ioctl(fd, FIONREAD, &k) < 0)
73✔
UNCOV
1259
                return -errno;
×
1260

1261
        return (ssize_t) k;
73✔
1262
}
1263

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

1268
int flush_accept(int fd) {
12✔
1269

1270
        int r, b;
12✔
1271
        socklen_t l = sizeof(b);
12✔
1272

1273
        /* Similar to flush_fd() but flushes all incoming connections by accepting and immediately closing
1274
         * them. */
1275

1276
        if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0)
12✔
UNCOV
1277
                return -errno;
×
1278

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

1287
        for (unsigned iteration = 0;; iteration++) {
2✔
1288
                int cfd;
6✔
1289

1290
                r = fd_wait_for_event(fd, POLLIN, 0);
6✔
1291
                if (r < 0) {
6✔
UNCOV
1292
                        if (r == -EINTR)
×
UNCOV
1293
                                continue;
×
1294

1295
                        return r;
1296
                }
1297
                if (r == 0)
6✔
1298
                        return 0;
1299

1300
                if (iteration >= MAX_FLUSH_ITERATIONS)
2✔
UNCOV
1301
                        return log_debug_errno(SYNTHETIC_ERRNO(EBUSY),
×
1302
                                               "Failed to flush connections within " STRINGIFY(MAX_FLUSH_ITERATIONS) " iterations.");
1303

1304
                cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
2✔
1305
                if (cfd < 0) {
2✔
UNCOV
1306
                        if (errno == EAGAIN)
×
1307
                                return 0;
1308

UNCOV
1309
                        if (ERRNO_IS_ACCEPT_AGAIN(errno))
×
1310
                                continue;
×
1311

UNCOV
1312
                        return -errno;
×
1313
                }
1314

1315
                safe_close(cfd);
2✔
1316
        }
1317
}
1318

UNCOV
1319
ssize_t flush_mqueue(int fd) {
×
UNCOV
1320
        _cleanup_free_ char *buf = NULL;
×
UNCOV
1321
        struct mq_attr attr;
×
UNCOV
1322
        ssize_t count = 0;
×
1323
        int r;
×
1324

1325
        assert(fd >= 0);
×
1326

1327
        /* Similar to flush_fd() but flushes all messages from a POSIX message queue. */
1328

1329
        for (;;) {
×
UNCOV
1330
                ssize_t l;
×
1331

UNCOV
1332
                r = fd_wait_for_event(fd, POLLIN, /* timeout= */ 0);
×
1333
                if (r < 0) {
×
1334
                        if (r == -EINTR)
×
UNCOV
1335
                                continue;
×
1336

1337
                        return r;
×
1338
                }
1339
                if (r == 0)
×
1340
                        return count;
1341

UNCOV
1342
                if (!buf) {
×
1343
                        /* Buffer must be at least as large as mq_msgsize. */
UNCOV
1344
                        if (mq_getattr(fd, &attr) < 0)
×
UNCOV
1345
                                return -errno;
×
1346

UNCOV
1347
                        buf = malloc(attr.mq_msgsize);
×
1348
                        if (!buf)
×
1349
                                return -ENOMEM;
1350
                }
1351

1352
                l = mq_receive(fd, buf, attr.mq_msgsize, /* msg_prio = */ NULL);
×
UNCOV
1353
                if (l < 0) {
×
UNCOV
1354
                        if (errno == EINTR)
×
UNCOV
1355
                                continue;
×
1356

1357
                        if (errno == EAGAIN)
×
1358
                                return count;
1359

UNCOV
1360
                        return -errno;
×
1361
                }
1362

UNCOV
1363
                count += l;
×
1364
        }
1365
}
1366

1367
struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) {
385,872✔
1368
        struct cmsghdr *cmsg;
385,872✔
1369

1370
        assert(mh);
385,872✔
1371

1372
        CMSG_FOREACH(cmsg, mh)
772,290✔
1373
                if (cmsg->cmsg_level == level &&
352,704✔
1374
                    cmsg->cmsg_type == type &&
352,431✔
1375
                    (length == (socklen_t) -1 || length == cmsg->cmsg_len))
351,979✔
1376
                        return cmsg;
1377

1378
        return NULL;
1379
}
1380

1381
void* cmsg_find_and_copy_data(struct msghdr *mh, int level, int type, void *buf, size_t buf_len) {
305✔
1382
        struct cmsghdr *cmsg;
305✔
1383

1384
        assert(mh);
305✔
1385
        assert(buf);
305✔
1386
        assert(buf_len > 0);
305✔
1387

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

1392
        cmsg = cmsg_find(mh, level, type, CMSG_LEN(buf_len));
305✔
1393
        if (!cmsg)
305✔
1394
                return NULL;
1395

1396
        return memcpy_safe(buf, CMSG_DATA(cmsg), buf_len);
300✔
1397
}
1398

1399
size_t sockaddr_ll_len(const struct sockaddr_ll *sa) {
308✔
1400
        /* Certain hardware address types (e.g Infiniband) do not fit into sll_addr
1401
         * (8 bytes) and run over the structure. This function returns the correct size that
1402
         * must be passed to kernel. */
1403

1404
        assert(sa->sll_family == AF_PACKET);
308✔
1405

1406
        size_t mac_len = sizeof(sa->sll_addr);
308✔
1407

1408
        if (be16toh(sa->sll_hatype) == ARPHRD_ETHER)
308✔
1409
                mac_len = MAX(mac_len, (size_t) ETH_ALEN);
308✔
1410
        if (be16toh(sa->sll_hatype) == ARPHRD_INFINIBAND)
308✔
UNCOV
1411
                mac_len = MAX(mac_len, (size_t) INFINIBAND_ALEN);
×
1412

1413
        return offsetof(struct sockaddr_ll, sll_addr) + mac_len;
308✔
1414
}
1415

1416
size_t sockaddr_un_len(const struct sockaddr_un *sa) {
2,480✔
1417
        /* Covers only file system and abstract AF_UNIX socket addresses, but not unnamed socket addresses. */
1418

1419
        assert(sa->sun_family == AF_UNIX);
2,480✔
1420

1421
        return offsetof(struct sockaddr_un, sun_path) +
7,440✔
1422
                (sa->sun_path[0] == 0 ?
2,480✔
1423
                        1 + strnlen(sa->sun_path+1, sizeof(sa->sun_path)-1) :
587✔
1424
                        strnlen(sa->sun_path, sizeof(sa->sun_path))+1);
1,893✔
1425
}
1426

1427
size_t sockaddr_len(const union sockaddr_union *sa) {
175✔
1428
        switch (sa->sa.sa_family) {
175✔
1429
        case AF_INET:
1430
                return sizeof(struct sockaddr_in);
1431
        case AF_INET6:
42✔
1432
                return sizeof(struct sockaddr_in6);
42✔
1433
        case AF_UNIX:
3✔
1434
                return sockaddr_un_len(&sa->un);
3✔
UNCOV
1435
        case AF_PACKET:
×
UNCOV
1436
                return sockaddr_ll_len(&sa->ll);
×
UNCOV
1437
        case AF_NETLINK:
×
UNCOV
1438
                return sizeof(struct sockaddr_nl);
×
1439
        case AF_VSOCK:
1440
                return sizeof(struct sockaddr_vm);
1441
        default:
×
1442
                assert_not_reached();
×
1443
        }
1444
}
1445

1446
int socket_ioctl_fd(void) {
4,320✔
1447
        int fd;
4,320✔
1448

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

1454
        fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
4,320✔
1455
        if (fd < 0)
4,320✔
UNCOV
1456
                fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_GENERIC);
×
UNCOV
1457
        if (fd < 0)
×
UNCOV
1458
                return -errno;
×
1459

1460
        return fd;
1461
}
1462

1463
int sockaddr_un_unlink(const struct sockaddr_un *sa) {
1,767✔
1464
        const char *p, * nul;
1,767✔
1465

1466
        assert(sa);
1,767✔
1467

1468
        if (sa->sun_family != AF_UNIX)
1,767✔
1469
                return -EPROTOTYPE;
1470

1471
        if (sa->sun_path[0] == 0) /* Nothing to do for abstract sockets */
1,767✔
1472
                return 0;
1473

1474
        /* The path in .sun_path is not necessarily NUL terminated. Let's fix that. */
1475
        nul = memchr(sa->sun_path, 0, sizeof(sa->sun_path));
1,767✔
1476
        if (nul)
1,767✔
1477
                p = sa->sun_path;
1478
        else
UNCOV
1479
                p = memdupa_suffix0(sa->sun_path, sizeof(sa->sun_path));
×
1480

1481
        if (unlink(p) < 0)
1,767✔
1482
                return -errno;
1,526✔
1483

1484
        return 1;
1485
}
1486

1487
int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path) {
411,722✔
1488
        size_t l;
411,722✔
1489

1490
        assert(ret);
411,722✔
1491
        assert(path);
411,722✔
1492

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

1498
        l = strlen(path);
411,722✔
1499
        if (l < 2)
411,722✔
1500
                return -EINVAL;
1501
        if (!IN_SET(path[0], '/', '@'))
411,721✔
1502
                return -EINVAL;
1503

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

1514
        *ret = (struct sockaddr_un) {
411,719✔
1515
                .sun_family = AF_UNIX,
1516
        };
1517

1518
        if (path[0] == '@') {
411,719✔
1519
                /* Abstract namespace socket */
1520
                memcpy(ret->sun_path + 1, path + 1, l); /* copy *with* trailing NUL byte */
212,721✔
1521
                return (int) (offsetof(struct sockaddr_un, sun_path) + l); /* 🔥 *don't* 🔥 include trailing NUL in size */
212,721✔
1522

1523
        } else {
1524
                assert(path[0] == '/');
198,998✔
1525

1526
                /* File system socket */
1527
                memcpy(ret->sun_path, path, l + 1); /* copy *with* trailing NUL byte */
198,998✔
1528
                return (int) (offsetof(struct sockaddr_un, sun_path) + l + 1); /* include trailing NUL in size */
198,998✔
1529
        }
1530
}
1531

1532
int getsockopt_int(int fd, int level, int optname, int *ret) {
12,888✔
1533
        int v;
12,888✔
1534
        socklen_t sl = sizeof(v);
12,888✔
1535

1536
        assert(fd >= 0);
12,888✔
1537
        assert(ret);
12,888✔
1538

1539
        if (getsockopt(fd, level, optname, &v, &sl) < 0)
12,888✔
1540
                return negative_errno();
52✔
1541
        if (sl != sizeof(v))
12,836✔
1542
                return -EIO;
1543

1544
        *ret = v;
12,836✔
1545
        return 0;
12,836✔
1546
}
1547

1548
int socket_bind_to_ifname(int fd, const char *ifname) {
1✔
1549
        assert(fd >= 0);
1✔
1550

1551
        /* Call with NULL to drop binding */
1552

1553
        return RET_NERRNO(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen_ptr(ifname)));
2✔
1554
}
1555

1556
int socket_bind_to_ifindex(int fd, int ifindex) {
706✔
1557
        assert(fd >= 0);
706✔
1558

1559
        if (ifindex <= 0)
706✔
1560
                /* Drop binding */
1561
                return RET_NERRNO(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, NULL, 0));
52✔
1562

1563
        return setsockopt_int(fd, SOL_SOCKET, SO_BINDTOIFINDEX, ifindex);
654✔
1564
}
1565

1566
int socket_autobind(int fd, char **ret_name) {
243✔
1567
        _cleanup_free_ char *name = NULL;
243✔
1568
        uint64_t random;
243✔
1569
        int r;
243✔
1570

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

1574
        assert(fd >= 0);
243✔
1575

1576
        random = random_u64();
243✔
1577

1578
        if (asprintf(&name, "@%" PRIu64, random) < 0)
243✔
1579
                return -ENOMEM;
1580

1581
        union sockaddr_union sa;
243✔
1582
        assert_cc(DECIMAL_STR_MAX(uint64_t) < sizeof(sa.un.sun_path));
243✔
1583

1584
        r = sockaddr_un_set_path(&sa.un, name);
243✔
1585
        if (r < 0)
243✔
1586
                return r;
1587

1588
        if (bind(fd, &sa.sa, r) < 0)
243✔
UNCOV
1589
                return -errno;
×
1590

1591
        if (ret_name)
243✔
1592
                *ret_name = TAKE_PTR(name);
241✔
1593
        return 0;
1594
}
1595

1596
ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
2,957,874✔
1597
        ssize_t n;
2,957,874✔
1598

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

1604
        assert(sockfd >= 0);
2,957,874✔
1605
        assert(msg);
2,957,874✔
1606

1607
        n = recvmsg(sockfd, msg, flags);
2,957,874✔
1608
        if (n < 0)
2,957,874✔
1609
                return -errno;
290,988✔
1610

1611
        if (FLAGS_SET(msg->msg_flags, MSG_CTRUNC) ||
2,666,886✔
1612
            (!FLAGS_SET(flags, MSG_PEEK) && FLAGS_SET(msg->msg_flags, MSG_TRUNC))) {
2,666,886✔
1613
                cmsg_close_all(msg);
×
UNCOV
1614
                return FLAGS_SET(msg->msg_flags, MSG_CTRUNC) ? -ECHRNG : -EXFULL;
×
1615
        }
1616

1617
        return n;
1618
}
1619

1620
int socket_get_family(int fd) {
30,737✔
1621
        int af;
30,737✔
1622
        socklen_t sl = sizeof(af);
30,737✔
1623

1624
        if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0)
30,737✔
1625
                return -errno;
×
1626

1627
        if (sl != sizeof(af))
30,737✔
1628
                return -EINVAL;
1629

1630
        return af;
30,737✔
1631
}
1632

1633
int socket_set_recvpktinfo(int fd, int af, bool b) {
13,607✔
1634

1635
        if (af == AF_UNSPEC) {
13,607✔
UNCOV
1636
                af = socket_get_family(fd);
×
UNCOV
1637
                if (af < 0)
×
1638
                        return af;
1639
        }
1640

1641
        switch (af) {
13,607✔
1642

1643
        case AF_INET:
7,152✔
1644
                return setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, b);
7,152✔
1645

1646
        case AF_INET6:
6,422✔
1647
                return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, b);
6,422✔
1648

1649
        case AF_NETLINK:
33✔
1650
                return setsockopt_int(fd, SOL_NETLINK, NETLINK_PKTINFO, b);
33✔
1651

1652
        case AF_PACKET:
×
1653
                return setsockopt_int(fd, SOL_PACKET, PACKET_AUXDATA, b);
×
1654

1655
        default:
1656
                return -EAFNOSUPPORT;
1657
        }
1658
}
1659

1660
int socket_set_unicast_if(int fd, int af, int ifi) {
118✔
1661
        be32_t ifindex_be = htobe32(ifi);
118✔
1662

1663
        if (af == AF_UNSPEC) {
118✔
UNCOV
1664
                af = socket_get_family(fd);
×
UNCOV
1665
                if (af < 0)
×
1666
                        return af;
118✔
1667
        }
1668

1669
        switch (af) {
118✔
1670

1671
        case AF_INET:
82✔
1672
                return RET_NERRNO(setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)));
82✔
1673

1674
        case AF_INET6:
36✔
1675
                return RET_NERRNO(setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)));
36✔
1676

1677
        default:
1678
                return -EAFNOSUPPORT;
1679
        }
1680
}
1681

1682
int socket_set_option(int fd, int af, int opt_ipv4, int opt_ipv6, int val) {
27,017✔
1683
        if (af == AF_UNSPEC) {
27,017✔
UNCOV
1684
                af = socket_get_family(fd);
×
UNCOV
1685
                if (af < 0)
×
1686
                        return af;
1687
        }
1688

1689
        switch (af) {
27,017✔
1690

1691
        case AF_INET:
14,164✔
1692
                return setsockopt_int(fd, IPPROTO_IP, opt_ipv4, val);
14,164✔
1693

1694
        case AF_INET6:
12,853✔
1695
                return setsockopt_int(fd, IPPROTO_IPV6, opt_ipv6, val);
12,853✔
1696

1697
        default:
1698
                return -EAFNOSUPPORT;
1699
        }
1700
}
1701

1702
int socket_get_mtu(int fd, int af, size_t *ret) {
715✔
1703
        int mtu, r;
715✔
1704

1705
        if (af == AF_UNSPEC) {
715✔
UNCOV
1706
                af = socket_get_family(fd);
×
UNCOV
1707
                if (af < 0)
×
1708
                        return af;
715✔
1709
        }
1710

1711
        switch (af) {
715✔
1712

1713
        case AF_INET:
302✔
1714
                r = getsockopt_int(fd, IPPROTO_IP, IP_MTU, &mtu);
302✔
1715
                break;
1716

1717
        case AF_INET6:
413✔
1718
                r = getsockopt_int(fd, IPPROTO_IPV6, IPV6_MTU, &mtu);
413✔
1719
                break;
1720

1721
        default:
1722
                return -EAFNOSUPPORT;
1723
        }
1724

1725
        if (r < 0)
715✔
1726
                return r;
1727
        if (mtu <= 0)
663✔
1728
                return -EINVAL;
1729

1730
        *ret = (size_t) mtu;
663✔
1731
        return 0;
663✔
1732
}
1733

1734
static int connect_unix_path_simple(int fd, const char *path) {
167,477✔
1735
        union sockaddr_union sa = {
167,477✔
1736
                .un.sun_family = AF_UNIX,
1737
        };
1738
        size_t l;
167,477✔
1739

1740
        assert(fd >= 0);
167,477✔
1741
        assert(path);
167,477✔
1742

1743
        l = strlen(path);
167,477✔
1744
        assert(l > 0);
167,477✔
1745
        assert(l < sizeof(sa.un.sun_path));
167,477✔
1746

1747
        memcpy(sa.un.sun_path, path, l + 1);
167,477✔
1748
        return RET_NERRNO(connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + l + 1));
167,477✔
1749
}
1750

1751
static int connect_unix_inode(int fd, int inode_fd) {
14✔
1752
        assert(fd >= 0);
14✔
1753
        assert(inode_fd >= 0);
14✔
1754

1755
        return connect_unix_path_simple(fd, FORMAT_PROC_FD_PATH(inode_fd));
14✔
1756
}
1757

1758
int connect_unix_path(int fd, int dir_fd, const char *path) {
167,477✔
1759
        _cleanup_close_ int inode_fd = -EBADF;
167,477✔
1760

1761
        assert(fd >= 0);
167,477✔
1762
        assert(dir_fd == AT_FDCWD || dir_fd >= 0);
167,477✔
1763

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

1767
        if (!path)
167,477✔
1768
                return connect_unix_inode(fd, dir_fd); /* If no path is specified, then dir_fd refers to the socket inode to connect to. */
1✔
1769

1770
        /* Refuse zero length path early, to make sure AF_UNIX stack won't mistake this for an abstract
1771
         * namespace path, since first char is NUL */
1772
        if (isempty(path))
334,953✔
1773
                return -EINVAL;
1774

1775
        /* Shortcut for the simple case */
1776
        if (dir_fd == AT_FDCWD && strlen(path) < sizeof_field(struct sockaddr_un, sun_path))
167,476✔
1777
                return connect_unix_path_simple(fd, path);
167,463✔
1778

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

1783
        inode_fd = openat(dir_fd, path, O_PATH|O_CLOEXEC);
13✔
1784
        if (inode_fd < 0)
13✔
UNCOV
1785
                return -errno;
×
1786

1787
        return connect_unix_inode(fd, inode_fd);
13✔
1788
}
1789

1790
int socket_address_parse_unix(SocketAddress *ret_address, const char *s) {
220,837✔
1791
        struct sockaddr_un un;
220,837✔
1792
        int r;
220,837✔
1793

1794
        assert(ret_address);
220,837✔
1795
        assert(s);
220,837✔
1796

1797
        if (!IN_SET(*s, '/', '@'))
220,837✔
1798
                return -EPROTO;
220,837✔
1799

1800
        r = sockaddr_un_set_path(&un, s);
220,398✔
1801
        if (r < 0)
220,398✔
1802
                return r;
1803

1804
        *ret_address = (SocketAddress) {
220,396✔
1805
                .sockaddr.un = un,
1806
                .size = r,
1807
        };
1808

1809
        return 0;
220,396✔
1810
}
1811

1812
int socket_address_equal_unix(const char *a, const char *b) {
1,279✔
1813
        SocketAddress socket_a, socket_b;
1,279✔
1814
        int r;
1,279✔
1815

1816
        assert(a);
1,279✔
1817
        assert(b);
1,279✔
1818

1819
        r = socket_address_parse_unix(&socket_a, a);
1,279✔
1820
        if (r < 0)
1,279✔
1821
                return r;
1,279✔
1822

1823
        r = socket_address_parse_unix(&socket_b, b);
1,279✔
1824
        if (r < 0)
1,279✔
1825
                return r;
1826

1827
        return sockaddr_equal(&socket_a.sockaddr, &socket_b.sockaddr);
1,279✔
1828
}
1829

1830
int vsock_parse_port(const char *s, unsigned *ret) {
371✔
1831
        int r;
371✔
1832

1833
        assert(ret);
371✔
1834

1835
        if (!s)
371✔
1836
                return -EINVAL;
371✔
1837

1838
        unsigned u;
371✔
1839
        r = safe_atou(s, &u);
371✔
1840
        if (r < 0)
371✔
1841
                return r;
1842

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

1846
        if (u == VMADDR_PORT_ANY)
368✔
1847
                return -EINVAL;
1848

1849
        *ret = u;
368✔
1850
        return 0;
368✔
1851
}
1852

1853
int vsock_parse_cid(const char *s, unsigned *ret) {
331✔
1854
        assert(ret);
331✔
1855

1856
        if (!s)
331✔
1857
                return -EINVAL;
1858

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

1862
        if (streq(s, "hypervisor"))
331✔
UNCOV
1863
                *ret = VMADDR_CID_HYPERVISOR;
×
1864
        else if (streq(s, "local"))
331✔
UNCOV
1865
                *ret = VMADDR_CID_LOCAL;
×
1866
        else if (streq(s, "host"))
331✔
UNCOV
1867
                *ret = VMADDR_CID_HOST;
×
1868
        else
1869
                return safe_atou(s, ret);
331✔
1870

1871
        return 0;
1872
}
1873

1874
int socket_address_parse_vsock(SocketAddress *ret_address, const char *s) {
439✔
1875
        /* AF_VSOCK socket in vsock:cid:port notation */
1876
        _cleanup_free_ char *n = NULL;
439✔
1877
        char *e, *cid_start;
439✔
1878
        unsigned port, cid;
439✔
1879
        int type, r;
439✔
1880

1881
        assert(ret_address);
439✔
1882
        assert(s);
439✔
1883

1884
        if ((cid_start = startswith(s, "vsock:")))
439✔
1885
                type = 0;
1886
        else if ((cid_start = startswith(s, "vsock-dgram:")))
387✔
1887
                type = SOCK_DGRAM;
1888
        else if ((cid_start = startswith(s, "vsock-seqpacket:")))
387✔
1889
                type = SOCK_SEQPACKET;
1890
        else if ((cid_start = startswith(s, "vsock-stream:")))
387✔
1891
                type = SOCK_STREAM;
1892
        else
1893
                return -EPROTO;
1894

1895
        e = strchr(cid_start, ':');
373✔
1896
        if (!e)
373✔
1897
                return -EINVAL;
1898

1899
        r = vsock_parse_port(e+1, &port);
371✔
1900
        if (r < 0)
371✔
1901
                return r;
1902

1903
        n = strndup(cid_start, e - cid_start);
368✔
1904
        if (!n)
368✔
1905
                return -ENOMEM;
1906

1907
        if (isempty(n))
368✔
1908
                cid = VMADDR_CID_ANY;
37✔
1909
        else {
1910
                r = vsock_parse_cid(n, &cid);
331✔
1911
                if (r < 0)
331✔
1912
                        return r;
1913
        }
1914

1915
        *ret_address = (SocketAddress) {
365✔
1916
                .sockaddr.vm = {
1917
                        .svm_family = AF_VSOCK,
1918
                        .svm_cid = cid,
1919
                        .svm_port = port,
1920
                },
1921
                .type = type,
1922
                .size = sizeof(struct sockaddr_vm),
1923
        };
1924

1925
        return 0;
365✔
1926
}
1927

1928
int vsock_get_local_cid(unsigned *ret) {
16✔
1929
        _cleanup_close_ int vsock_fd = -EBADF;
16✔
1930

1931
        vsock_fd = open("/dev/vsock", O_RDONLY|O_CLOEXEC);
16✔
1932
        if (vsock_fd < 0)
16✔
1933
                return log_debug_errno(errno, "Failed to open /dev/vsock: %m");
13✔
1934

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

1939
        return 0;
1940
}
1941

1942
int netlink_socket_get_multicast_groups(int fd, size_t *ret_len, uint32_t **ret_groups) {
12,173✔
1943
        _cleanup_free_ uint32_t *groups = NULL;
24,346✔
1944
        socklen_t len = 0, old_len;
12,173✔
1945

1946
        assert(fd >= 0);
12,173✔
1947

1948
        if (getsockopt(fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len) < 0)
12,173✔
1949
                return -errno;
×
1950

1951
        if (len == 0)
12,173✔
1952
                goto finalize;
11,754✔
1953

1954
        groups = new0(uint32_t, len);
419✔
1955
        if (!groups)
419✔
1956
                return -ENOMEM;
1957

1958
        old_len = len;
419✔
1959

1960
        if (getsockopt(fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len) < 0)
419✔
UNCOV
1961
                return -errno;
×
1962

1963
        if (old_len != len)
419✔
1964
                return -EIO;
1965

1966
finalize:
419✔
1967
        if (ret_len)
12,173✔
1968
                *ret_len = len;
12,173✔
1969
        if (ret_groups)
12,173✔
1970
                *ret_groups = TAKE_PTR(groups);
12,173✔
1971

1972
        return 0;
1973
}
1974

1975
int socket_get_cookie(int fd, uint64_t *ret) {
126✔
1976
        assert(fd >= 0);
126✔
1977

1978
        uint64_t cookie = 0;
126✔
1979
        socklen_t cookie_len = sizeof(cookie);
126✔
1980
        if (getsockopt(fd, SOL_SOCKET, SO_COOKIE, &cookie, &cookie_len) < 0)
126✔
UNCOV
1981
                return -errno;
×
1982

1983
        assert(cookie_len == sizeof(cookie));
126✔
1984
        if (ret)
126✔
1985
                *ret = cookie;
126✔
1986

1987
        return 0;
1988
}
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