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

systemd / systemd / 18066640619

27 Sep 2025 03:25PM UTC coverage: 72.087% (-0.1%) from 72.224%
18066640619

push

github

yuwata
vmspawn: try to set up swtpm state for 4K RSA keys support

The next version of swtpm will support RSA4096, but it needs to be called
with a new parameter in order to do so. Try with it first, and if
execution fails, fallback to running without it.

This is especially needed for OBS builds, as the signing key is RSA4096
and cannot be changed by users, so the generated UKIs have RSA4096 signatures
for the pcrsig sections, and swtpm refuses them without the new support.

0 of 11 new or added lines in 1 file covered. (0.0%)

1438 existing lines in 37 files now uncovered.

302728 of 419948 relevant lines covered (72.09%)

1152870.99 hits per line

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

81.73
/src/network/networkd-sysctl.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <linux/if_arp.h>
4

5
#include "sd-messages.h"
6

7
#include "af-list.h"
8
#include "conf-parser.h"
9
#include "alloc-util.h"
10
#include "cgroup-util.h"
11
#include "errno-util.h"
12
#include "event-util.h"
13
#include "fd-util.h"
14
#include "format-util.h"
15
#include "hashmap.h"
16
#include "networkd-link.h"
17
#include "networkd-lldp-tx.h"
18
#include "networkd-manager.h"
19
#include "networkd-ndisc.h"
20
#include "networkd-network.h"
21
#include "networkd-sysctl.h"
22
#include "path-util.h"
23
#include "set.h"
24
#include "socket-util.h"
25
#include "string-table.h"
26
#include "string-util.h"
27
#include "sysctl-util.h"
28

29
#if ENABLE_SYSCTL_BPF
30

31
#include "bpf-link.h"
32
#include "bpf/sysctl-monitor/sysctl-monitor-skel.h"
33
#include "bpf/sysctl-monitor/sysctl-write-event.h"
34

35
static struct sysctl_monitor_bpf* sysctl_monitor_bpf_free(struct sysctl_monitor_bpf *obj) {
463✔
36
        sysctl_monitor_bpf__destroy(obj);
463✔
37
        return NULL;
463✔
38
}
39

40
DEFINE_TRIVIAL_CLEANUP_FUNC(struct sysctl_monitor_bpf *, sysctl_monitor_bpf_free);
439✔
41

42
static int sysctl_event_handler(void *ctx, void *data, size_t data_sz) {
1✔
43
        struct sysctl_write_event *we = ASSERT_PTR(data);
1✔
44
        Hashmap **sysctl_shadow = ASSERT_PTR(ctx);
1✔
45
        _cleanup_free_ char *path = NULL;
1✔
46
        char *value;
1✔
47

48
        /* Returning a negative value interrupts the ring buffer polling,
49
         * so do it only in case of a fatal error like a version mismatch. */
50
        if (we->version != 1)
1✔
51
                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
×
52
                                         "Unexpected sysctl event, disabling sysctl monitoring: %d", we->version);
53

54
        if (we->errorcode != 0) {
1✔
55
                log_warning_errno(we->errorcode, "Sysctl monitor BPF returned error: %m");
×
56
                return 0;
×
57
        }
58

59
        path = path_join("/proc/sys", we->path);
1✔
60
        if (!path) {
1✔
61
                log_oom_warning();
×
62
                return 0;
63
        }
64

65
        /* If we never managed this handle, ignore it. */
66
        value = hashmap_get(*sysctl_shadow, path);
1✔
67
        if (!value)
1✔
68
                return 0;
69

70
        if (!strneq(value, we->newvalue, sizeof(we->newvalue)))
×
71
                log_struct(LOG_WARNING,
×
72
                           LOG_MESSAGE_ID(SD_MESSAGE_SYSCTL_CHANGED_STR),
73
                           LOG_ITEM("OBJECT_PID=" PID_FMT, we->pid),
74
                           LOG_ITEM("OBJECT_COMM=%s", we->comm),
75
                           LOG_ITEM("SYSCTL=%s", path),
76
                           LOG_ITEM("OLDVALUE=%s", we->current),
77
                           LOG_ITEM("NEWVALUE=%s", we->newvalue),
78
                           LOG_ITEM("OURVALUE=%s", value),
79
                           LOG_MESSAGE("Foreign process '%s[" PID_FMT "]' changed sysctl '%s' from '%s' to '%s', conflicting with our setting to '%s'.",
80
                                       we->comm, we->pid, path, we->current, we->newvalue, value));
81

82
        return 0;
83
}
84

85
static int on_ringbuf_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
1✔
86
        struct ring_buffer *rb = ASSERT_PTR(userdata);
1✔
87
        int r;
1✔
88

89
        r = sym_ring_buffer__poll(rb, /* timeout_msec= */ 0);
1✔
90
        if (r < 0 && errno != EINTR)
1✔
91
                log_error_errno(errno, "Error polling ring buffer: %m");
×
92

93
        return 0;
1✔
94
}
95

96
int manager_install_sysctl_monitor(Manager *manager) {
439✔
97
        _cleanup_(sysctl_monitor_bpf_freep) struct sysctl_monitor_bpf *obj = NULL;
439✔
98
        _cleanup_(bpf_link_freep) struct bpf_link *sysctl_link = NULL;
439✔
99
        _cleanup_(bpf_ring_buffer_freep) struct ring_buffer *sysctl_buffer = NULL;
×
100
        _cleanup_close_ int cgroup_fd = -EBADF, root_cgroup_fd = -EBADF;
878✔
101
        _cleanup_free_ char *cgroup = NULL;
439✔
102
        int idx = 0, r, fd;
439✔
103

104
        assert(manager);
439✔
105

106
        r = dlopen_bpf();
439✔
107
        if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
439✔
108
                return log_debug_errno(r, "sysctl monitor disabled, as BPF support is not available.");
×
109
        if (r < 0)
439✔
110
                return log_warning_errno(r, "Failed to load libbpf, not installing sysctl monitor: %m");
×
111

112
        r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
439✔
113
        if (r < 0)
439✔
114
                return log_warning_errno(r, "Failed to get cgroup path, ignoring: %m.");
×
115

116
        root_cgroup_fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, "/");
439✔
117
        if (root_cgroup_fd < 0)
439✔
118
                return log_warning_errno(root_cgroup_fd, "Failed to open cgroup, ignoring: %m");
×
119

120
        obj = sysctl_monitor_bpf__open_and_load();
439✔
121
        if (!obj)
439✔
122
                return log_full_errno(errno == EINVAL ? LOG_DEBUG : LOG_INFO, errno,
59✔
123
                                      "Unable to load sysctl monitor BPF program, ignoring: %m");
124

125
        cgroup_fd = cg_path_open(SYSTEMD_CGROUP_CONTROLLER, cgroup);
380✔
126
        if (cgroup_fd < 0)
380✔
127
                return log_warning_errno(cgroup_fd, "Failed to open cgroup: %m");
×
128

129
        if (sym_bpf_map_update_elem(sym_bpf_map__fd(obj->maps.cgroup_map), &idx, &cgroup_fd, BPF_ANY))
380✔
130
                return log_warning_errno(errno, "Failed to update cgroup map: %m");
×
131

132
        sysctl_link = sym_bpf_program__attach_cgroup(obj->progs.sysctl_monitor, root_cgroup_fd);
380✔
133
        r = bpf_get_error_translated(sysctl_link);
380✔
134
        if (r < 0)
380✔
135
                return log_warning_errno(r, "Unable to attach sysctl monitor BPF program to cgroup, ignoring: %m");
×
136

137
        fd = sym_bpf_map__fd(obj->maps.written_sysctls);
380✔
138
        if (fd < 0)
380✔
139
                return log_warning_errno(fd, "Failed to get fd of sysctl maps: %m");
×
140

141
        sysctl_buffer = sym_ring_buffer__new(fd, sysctl_event_handler, &manager->sysctl_shadow, NULL);
380✔
142
        if (!sysctl_buffer)
380✔
143
                return log_warning_errno(errno, "Failed to create ring buffer: %m");
×
144

145
        fd = sym_ring_buffer__epoll_fd(sysctl_buffer);
380✔
146
        if (fd < 0)
380✔
147
                return log_warning_errno(fd, "Failed to get poll fd of ring buffer: %m");
×
148

149
        r = sd_event_add_io(manager->event, &manager->sysctl_event_source,
380✔
150
                            fd, EPOLLIN, on_ringbuf_io, sysctl_buffer);
151
        if (r < 0)
380✔
152
                return log_warning_errno(r, "Failed to watch sysctl event ringbuffer: %m");
×
153

154
        manager->sysctl_link = TAKE_PTR(sysctl_link);
380✔
155
        manager->sysctl_skel = TAKE_PTR(obj);
380✔
156
        manager->sysctl_buffer = TAKE_PTR(sysctl_buffer);
380✔
157
        manager->cgroup_fd = TAKE_FD(cgroup_fd);
380✔
158

159
        return 0;
380✔
160
}
161

162
void manager_remove_sysctl_monitor(Manager *manager) {
463✔
163
        assert(manager);
463✔
164

165
        manager->sysctl_event_source = sd_event_source_disable_unref(manager->sysctl_event_source);
463✔
166
        manager->sysctl_buffer = bpf_ring_buffer_free(manager->sysctl_buffer);
463✔
167
        manager->sysctl_link = bpf_link_free(manager->sysctl_link);
463✔
168
        manager->sysctl_skel = sysctl_monitor_bpf_free(manager->sysctl_skel);
463✔
169
        manager->cgroup_fd = safe_close(manager->cgroup_fd);
463✔
170
        manager->sysctl_shadow = hashmap_free(manager->sysctl_shadow);
463✔
171
}
463✔
172

173
int link_clear_sysctl_shadows(Link *link) {
2,762✔
174
        _cleanup_free_ char *ipv4 = NULL, *ipv6 = NULL;
2,762✔
175
        char *key = NULL, *value = NULL;
2,762✔
176

177
        assert(link);
2,762✔
178
        assert(link->manager);
2,762✔
179

180
        ipv4 = path_join("/proc/sys/net/ipv4/conf", link->ifname);
2,762✔
181
        if (!ipv4)
2,762✔
182
                return log_oom();
×
183

184
        ipv6 = path_join("/proc/sys/net/ipv6/conf", link->ifname);
2,762✔
185
        if (!ipv6)
2,762✔
186
                return log_oom();
×
187

188
        HASHMAP_FOREACH_KEY(value, key, link->manager->sysctl_shadow)
9,587✔
189
                if (path_startswith(key, ipv4) || path_startswith(key, ipv6)) {
6,825✔
190
                        assert_se(hashmap_remove_value(link->manager->sysctl_shadow, key, value));
3,054✔
191
                        free(key);
3,054✔
192
                        free(value);
3,054✔
193
                }
194

195
        return 0;
2,762✔
196
}
197
#endif
198

199
static void manager_set_ip_forwarding(Manager *manager, int family) {
882✔
200
        int r, t;
882✔
201

202
        assert(manager);
882✔
203
        assert(IN_SET(family, AF_INET, AF_INET6));
882✔
204

205
        if (family == AF_INET6 && !socket_ipv6_is_supported())
882✔
206
                return;
207

208
        t = manager->ip_forwarding[family == AF_INET6];
882✔
209
        if (t < 0)
882✔
210
                return; /* keep */
211

212
        /* First, set the default value. */
213
        r = sysctl_write_ip_property_boolean(family, "default", "forwarding", t, manager_get_sysctl_shadow(manager));
4✔
214
        if (r < 0)
4✔
215
                log_warning_errno(r, "Failed to %s the default %s forwarding: %m",
×
216
                                  enable_disable(t), af_to_ipv4_ipv6(family));
217

218
        /* Then, set the value to all interfaces. */
219
        r = sysctl_write_ip_property_boolean(family, "all", "forwarding", t, manager_get_sysctl_shadow(manager));
4✔
220
        if (r < 0)
4✔
221
                log_warning_errno(r, "Failed to %s %s forwarding for all interfaces: %m",
×
222
                                  enable_disable(t), af_to_ipv4_ipv6(family));
223
}
224

225
void manager_set_sysctl(Manager *manager) {
439✔
226
        assert(manager);
439✔
227
        assert(!manager->test_mode);
439✔
228

229
        manager_set_ip_forwarding(manager, AF_INET);
439✔
230
        manager_set_ip_forwarding(manager, AF_INET6);
439✔
231
}
439✔
232

233
static bool link_is_configured_for_family(Link *link, int family) {
17,758✔
234
        assert(link);
17,758✔
235

236
        if (!link->network)
17,758✔
237
                return false;
238

239
        if (link->flags & IFF_LOOPBACK)
17,758✔
240
                return false;
241

242
        /* CAN devices do not support IP layer. Most of the functions below are never called for CAN devices,
243
         * but link_set_ipv6_mtu() may be called after setting interface MTU, and warn about the failure. For
244
         * safety, let's unconditionally check if the interface is not a CAN device. */
245
        if (IN_SET(family, AF_INET, AF_INET6, AF_MPLS) && link->iftype == ARPHRD_CAN)
17,758✔
246
                return false;
247

248
        if (family == AF_INET6 && !socket_ipv6_is_supported())
17,754✔
249
                return false;
×
250

251
        return true;
252
}
253

254
static int link_update_ipv6_sysctl(Link *link) {
851✔
255
        assert(link);
851✔
256
        assert(link->manager);
851✔
257

258
        if (!link_is_configured_for_family(link, AF_INET6))
851✔
259
                return 0;
260

261
        if (!link_ipv6_enabled(link))
851✔
262
                return 0;
263

264
        return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "disable_ipv6", false, manager_get_sysctl_shadow(link->manager));
784✔
265
}
266

267
static int link_set_proxy_arp(Link *link) {
851✔
268
        assert(link);
851✔
269
        assert(link->manager);
851✔
270

271
        if (!link_is_configured_for_family(link, AF_INET))
851✔
272
                return 0;
273

274
        if (link->network->proxy_arp < 0)
851✔
275
                return 0;
276

277
        return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp", link->network->proxy_arp > 0, manager_get_sysctl_shadow(link->manager));
2✔
278
}
279

280
static int link_set_proxy_arp_pvlan(Link *link) {
851✔
281
        assert(link);
851✔
282
        assert(link->manager);
851✔
283

284
        if (!link_is_configured_for_family(link, AF_INET))
851✔
285
                return 0;
286

287
        if (link->network->proxy_arp_pvlan < 0)
851✔
288
                return 0;
289

290
        return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "proxy_arp_pvlan", link->network->proxy_arp_pvlan > 0, manager_get_sysctl_shadow(link->manager));
2✔
291
}
292

293
int link_get_ip_forwarding(Link *link, int family) {
2,261✔
294
        assert(link);
2,261✔
295
        assert(link->manager);
2,261✔
296
        assert(link->network);
2,261✔
297
        assert(IN_SET(family, AF_INET, AF_INET6));
2,261✔
298

299
        /* If it is explicitly specified, then honor the setting. */
300
        int t = link->network->ip_forwarding[family == AF_INET6];
2,261✔
301
        if (t >= 0)
2,261✔
302
                return t;
303

304
        /* If IPMasquerade= is enabled, also enable IP forwarding. */
305
        if (FLAGS_SET(link->network->ip_masquerade, AF_TO_ADDRESS_FAMILY(family)))
3,543✔
306
                return true;
307

308
        /* If IPv6SendRA= is enabled, also enable IPv6 forwarding. */
309
        if (family == AF_INET6 && link_radv_enabled(link))
2,160✔
310
                return true;
311

312
        /* Otherwise, use the global setting. */
313
        return link->manager->ip_forwarding[family == AF_INET6];
2,127✔
314
}
315

316
static int link_set_ip_forwarding_impl(Link *link, int family) {
1,704✔
317
        int r, t;
1,704✔
318

319
        assert(link);
1,704✔
320
        assert(link->manager);
1,704✔
321
        assert(IN_SET(family, AF_INET, AF_INET6));
1,704✔
322

323
        if (!link_is_configured_for_family(link, family))
1,704✔
324
                return 0;
325

326
        t = link_get_ip_forwarding(link, family);
1,704✔
327
        if (t < 0)
1,704✔
328
                return 0; /* keep */
329

330
        r = sysctl_write_ip_property_boolean(family, link->ifname, "forwarding", t, manager_get_sysctl_shadow(link->manager));
123✔
331
        if (r < 0)
123✔
332
                return log_link_warning_errno(link, r, "Failed to %s %s forwarding, ignoring: %m",
×
333
                                              enable_disable(t), af_to_ipv4_ipv6(family));
334

335
        return 0;
336
}
337

338
static int link_reapply_ip_forwarding(Link *link, int family) {
10✔
339
        int r, ret = 0;
10✔
340

341
        assert(link);
10✔
342
        assert(IN_SET(family, AF_INET, AF_INET6));
10✔
343

344
        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
10✔
345
                return 0;
10✔
346

347
        (void) link_set_ip_forwarding_impl(link, family);
6✔
348

349
        r = link_lldp_tx_update_capabilities(link);
6✔
350
        if (r < 0)
6✔
351
                RET_GATHER(ret, log_link_warning_errno(link, r, "Could not update LLDP capabilities, ignoring: %m"));
×
352

353
        if (family == AF_INET6 && !link_ndisc_enabled(link)) {
6✔
354
                r = ndisc_stop(link);
3✔
355
                if (r < 0)
3✔
356
                        RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery, ignoring: %m"));
×
357

358
                ndisc_flush(link);
3✔
359
        }
360

361
        return ret;
362
}
363

364
static int link_set_ip_forwarding(Link *link, int family) {
1,702✔
365
        int r;
1,702✔
366

367
        assert(link);
1,702✔
368
        assert(link->manager);
1,702✔
369
        assert(link->network);
1,702✔
370
        assert(IN_SET(family, AF_INET, AF_INET6));
1,702✔
371

372
        if (!link_is_configured_for_family(link, family))
1,702✔
373
                return 0;
374

375
        /* When IPMasquerade= is enabled and the global setting is unset, enable _global_ IP forwarding, and
376
         * re-apply per-link setting for all links. */
377
        if (FLAGS_SET(link->network->ip_masquerade, AF_TO_ADDRESS_FAMILY(family)) &&
2,553✔
378
            link->manager->ip_forwarding[family == AF_INET6] < 0) {
30✔
379

380
                link->manager->ip_forwarding[family == AF_INET6] = true;
4✔
381
                manager_set_ip_forwarding(link->manager, family);
4✔
382

383
                Link *other;
4✔
384
                HASHMAP_FOREACH(other, link->manager->links_by_index) {
18✔
385
                        r = link_reapply_ip_forwarding(other, family);
10✔
386
                        if (r < 0)
10✔
387
                                link_enter_failed(other);
×
388
                }
389

390
                return 0;
4✔
391
        }
392

393
        /* Otherwise, apply per-link setting for _this_ link. */
394
        return link_set_ip_forwarding_impl(link, family);
1,698✔
395
}
396

397
static int link_set_ipv4_rp_filter(Link *link) {
851✔
398
        assert(link);
851✔
399
        assert(link->manager);
851✔
400

401
        if (!link_is_configured_for_family(link, AF_INET))
851✔
402
                return 0;
403

404
        if (link->network->ipv4_rp_filter < 0)
851✔
405
                return 0;
406

407
        return sysctl_write_ip_property_int(AF_INET, link->ifname, "rp_filter", link->network->ipv4_rp_filter, manager_get_sysctl_shadow(link->manager));
2✔
408
}
409

410
static int link_set_ipv4_force_igmp_version(Link *link) {
851✔
411
        assert(link);
851✔
412

413
        if (!link_is_configured_for_family(link, AF_INET))
851✔
414
                return 0;
415

416
        if (link->network->ipv4_force_igmp_version < 0)
851✔
417
                return 0;
418

419
        return sysctl_write_ip_property_int(AF_INET, link->ifname, "force_igmp_version", link->network->ipv4_force_igmp_version, manager_get_sysctl_shadow(link->manager));
2✔
420
}
421

422
static int link_set_ipv6_privacy_extensions(Link *link) {
851✔
423
        IPv6PrivacyExtensions val;
851✔
424

425
        assert(link);
851✔
426
        assert(link->manager);
851✔
427

428
        if (!link_is_configured_for_family(link, AF_INET6))
851✔
429
                return 0;
430

431
        val = link->network->ipv6_privacy_extensions;
851✔
432
        if (val < 0) /* If not specified, then use the global setting. */
851✔
433
                val = link->manager->ipv6_privacy_extensions;
826✔
434

435
        /* When "kernel", do not update the setting. */
436
        if (val == IPV6_PRIVACY_EXTENSIONS_KERNEL)
851✔
437
                return 0;
438

439
        return sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) val, manager_get_sysctl_shadow(link->manager));
851✔
440
}
441

442
static int link_set_ipv6_accept_ra(Link *link) {
851✔
443
        assert(link);
851✔
444
        assert(link->manager);
851✔
445

446
        if (!link_is_configured_for_family(link, AF_INET6))
851✔
447
                return 0;
448

449
        return sysctl_write_ip_property(AF_INET6, link->ifname, "accept_ra", "0", manager_get_sysctl_shadow(link->manager));
851✔
450
}
451

452
static int link_set_ipv6_dad_transmits(Link *link) {
851✔
453
        assert(link);
851✔
454
        assert(link->manager);
851✔
455

456
        if (!link_is_configured_for_family(link, AF_INET6))
851✔
457
                return 0;
458

459
        if (link->network->ipv6_dad_transmits < 0)
851✔
460
                return 0;
461

462
        return sysctl_write_ip_property_int(AF_INET6, link->ifname, "dad_transmits", link->network->ipv6_dad_transmits, manager_get_sysctl_shadow(link->manager));
2✔
463
}
464

465
static int link_set_ipv6_hop_limit(Link *link) {
851✔
466
        assert(link);
851✔
467
        assert(link->manager);
851✔
468

469
        if (!link_is_configured_for_family(link, AF_INET6))
851✔
470
                return 0;
471

472
        if (link->network->ipv6_hop_limit <= 0)
851✔
473
                return 0;
474

475
        return sysctl_write_ip_property_int(AF_INET6, link->ifname, "hop_limit", link->network->ipv6_hop_limit, manager_get_sysctl_shadow(link->manager));
2✔
476
}
477

478
static int link_set_ipv6_retransmission_time(Link *link) {
851✔
479
        usec_t retrans_time_ms;
851✔
480

481
        assert(link);
851✔
482
        assert(link->manager);
851✔
483

484
        if (!link_is_configured_for_family(link, AF_INET6))
851✔
485
                return 0;
486

487
        if (!timestamp_is_set(link->network->ipv6_retransmission_time))
851✔
488
                return 0;
489

490
        retrans_time_ms = DIV_ROUND_UP(link->network->ipv6_retransmission_time, USEC_PER_MSEC);
2✔
491
         if (retrans_time_ms <= 0 || retrans_time_ms > UINT32_MAX)
2✔
492
                return 0;
493

494
        return sysctl_write_ip_neighbor_property_uint32(AF_INET6, link->ifname, "retrans_time_ms", retrans_time_ms, manager_get_sysctl_shadow(link->manager));
2✔
495
}
496

497
static int link_set_ipv6_proxy_ndp(Link *link) {
851✔
498
        bool v;
851✔
499

500
        assert(link);
851✔
501
        assert(link->manager);
851✔
502

503
        if (!link_is_configured_for_family(link, AF_INET6))
851✔
504
                return 0;
505

506
        if (link->network->ipv6_proxy_ndp >= 0)
851✔
507
                v = link->network->ipv6_proxy_ndp;
2✔
508
        else
509
                v = !set_isempty(link->network->ipv6_proxy_ndp_addresses);
849✔
510

511
        return sysctl_write_ip_property_boolean(AF_INET6, link->ifname, "proxy_ndp", v, manager_get_sysctl_shadow(link->manager));
851✔
512
}
513

514
int link_set_ipv6_mtu(Link *link, int log_level) {
1,587✔
515
        uint32_t mtu = 0;
1,587✔
516
        int r;
1,587✔
517

518
        assert(link);
1,587✔
519
        assert(link->manager);
1,587✔
520

521
        if (!link_is_configured_for_family(link, AF_INET6))
1,587✔
522
                return 0;
523

524
        if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
1,583✔
525
                return 0;
526

527
        if (sd_event_source_get_enabled(link->ipv6_mtu_wait_synced_event_source, /* ret = */ NULL) > 0) {
1,583✔
UNCOV
528
                log_link_debug(link, "Waiting for IPv6 MTU is synced to link MTU, delaying to set IPv6 MTU.");
×
UNCOV
529
                return 0;
×
530
        }
531

532
        assert(link->network);
1,583✔
533

534
        if (link->network->ndisc_use_mtu)
1,583✔
535
                mtu = link->ndisc_mtu;
1,583✔
536
        if (mtu == 0)
1,583✔
537
                mtu = link->network->ipv6_mtu;
1,529✔
538
        if (mtu == 0)
1,529✔
539
                return 0;
540

541
        if (mtu > link->mtu) {
89✔
542
                log_link_full(link, log_level,
11✔
543
                              "Reducing requested IPv6 MTU %"PRIu32" to the interface's maximum MTU %"PRIu32".",
544
                              mtu, link->mtu);
545
                mtu = link->mtu;
11✔
546
        }
547

548
        r = sysctl_write_ip_property_uint32(AF_INET6, link->ifname, "mtu", mtu, manager_get_sysctl_shadow(link->manager));
89✔
549
        if (r < 0)
89✔
550
                return log_link_warning_errno(link, r, "Failed to set IPv6 MTU to %"PRIu32": %m", mtu);
×
551

552
        return 0;
553
}
554

555
static int ipv6_mtu_wait_synced_handler(sd_event_source *s, uint64_t usec, void *userdata);
556

557
static int link_set_ipv6_mtu_async_impl(Link *link) {
46✔
558
        uint32_t current_mtu;
46✔
559
        int r;
46✔
560

561
        assert(link);
46✔
562

563
        /* When the link MTU is updated, it seems that the kernel IPv6 MTU of the interface is asynchronously
564
         * reset to the link MTU. Hence, we need to check if it is already reset, and wait for a while if not. */
565

566
        if (++link->ipv6_mtu_wait_trial_count >= 10) {
46✔
567
                log_link_debug(link, "Timed out waiting for IPv6 MTU being synced to link MTU, proceeding anyway.");
×
568
                r = link_set_ipv6_mtu(link, LOG_INFO);
×
569
                if (r < 0)
×
570
                        return r;
46✔
571

572
                return 1; /* done */
×
573
        }
574

575
        /* Check if IPv6 MTU is synced. */
576
        r = sysctl_read_ip_property_uint32(AF_INET6, link->ifname, "mtu", &current_mtu);
46✔
577
        if (r < 0)
46✔
578
                return log_link_warning_errno(link, r, "Failed to read IPv6 MTU: %m");
1✔
579

580
        if (current_mtu == link->mtu) {
45✔
581
                /* Already synced. Update IPv6 MTU now. */
582
                r = link_set_ipv6_mtu(link, LOG_INFO);
45✔
583
                if (r < 0)
45✔
584
                        return r;
585

586
                return 1; /* done */
45✔
587
        }
588

589
        /* If not, set up a timer event source. */
UNCOV
590
        r = event_reset_time_relative(
×
UNCOV
591
                        link->manager->event, &link->ipv6_mtu_wait_synced_event_source,
×
592
                        CLOCK_BOOTTIME, 100 * USEC_PER_MSEC, 0,
593
                        ipv6_mtu_wait_synced_handler, link,
594
                        /* priority = */ 0, "ipv6-mtu-wait-synced", /* force_reset = */ true);
UNCOV
595
        if (r < 0)
×
596
                return log_link_warning_errno(link, r, "Failed to configure timer event source for waiting for IPv6 MTU being synced: %m");
×
597

598
        /* Check again. */
UNCOV
599
        r = sysctl_read_ip_property_uint32(AF_INET6, link->ifname, "mtu", &current_mtu);
×
UNCOV
600
        if (r < 0)
×
601
                return log_link_warning_errno(link, r, "Failed to read IPv6 MTU: %m");
×
602

UNCOV
603
        if (current_mtu == link->mtu) {
×
604
                /* Synced while setting up the timer event source. Disable it and update IPv6 MTU now. */
605
                r = sd_event_source_set_enabled(link->ipv6_mtu_wait_synced_event_source, SD_EVENT_OFF);
×
606
                if (r < 0)
×
607
                        log_link_debug_errno(link, r, "Failed to disable timer event source for IPv6 MTU, ignoring: %m");
×
608

609
                r = link_set_ipv6_mtu(link, LOG_INFO);
×
610
                if (r < 0)
×
611
                        return r;
612

613
                return 1; /* done */
×
614
        }
615

UNCOV
616
        log_link_debug(link, "IPv6 MTU is not synced to the link MTU after it is changed. Waiting for a while.");
×
617
        return 0; /* waiting */
618
}
619

UNCOV
620
static int ipv6_mtu_wait_synced_handler(sd_event_source *s, uint64_t usec, void *userdata) {
×
UNCOV
621
        (void) link_set_ipv6_mtu_async_impl(ASSERT_PTR(userdata));
×
UNCOV
622
        return 0;
×
623
}
624

625
int link_set_ipv6_mtu_async(Link *link) {
46✔
626
        assert(link);
46✔
627

628
        link->ipv6_mtu_wait_trial_count = 0;
46✔
629
        return link_set_ipv6_mtu_async_impl(link);
46✔
630
}
631

632
static int link_set_ipv4_accept_local(Link *link) {
851✔
633
        assert(link);
851✔
634
        assert(link->manager);
851✔
635

636
        if (!link_is_configured_for_family(link, AF_INET))
851✔
637
                return 0;
638

639
        if (link->network->ipv4_accept_local < 0)
851✔
640
                return 0;
641

642
        return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "accept_local", link->network->ipv4_accept_local > 0, manager_get_sysctl_shadow(link->manager));
2✔
643
}
644

645
static int link_set_ipv4_route_localnet(Link *link) {
851✔
646
        assert(link);
851✔
647
        assert(link->manager);
851✔
648

649
        if (!link_is_configured_for_family(link, AF_INET))
851✔
650
                return 0;
651

652
        if (link->network->ipv4_route_localnet < 0)
851✔
653
                return 0;
654

655
        return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "route_localnet", link->network->ipv4_route_localnet > 0, manager_get_sysctl_shadow(link->manager));
×
656
}
657

658
static int link_set_ipv4_promote_secondaries(Link *link) {
851✔
659
        assert(link);
851✔
660
        assert(link->manager);
851✔
661

662
        if (!link_is_configured_for_family(link, AF_INET))
851✔
663
                return 0;
664

665
        /* If promote_secondaries is not set, DHCP will work only as long as the IP address does not
666
         * changes between leases. The kernel will remove all secondary IP addresses of an interface
667
         * otherwise. The way systemd-networkd works is that the new IP of a lease is added as a
668
         * secondary IP and when the primary one expires it relies on the kernel to promote the
669
         * secondary IP. See also https://github.com/systemd/systemd/issues/7163 */
670
        return sysctl_write_ip_property_boolean(AF_INET, link->ifname, "promote_secondaries", true, manager_get_sysctl_shadow(link->manager));
851✔
671
}
672

673
static int link_set_mpls_input(Link *link) {
851✔
674
        assert(link);
851✔
675
        assert(link->manager);
851✔
676

677
        if (!link_is_configured_for_family(link, AF_MPLS))
851✔
678
                return 0;
679

680
        if (link->network->mpls_input < 0)
851✔
681
                return 0;
682

683
        return sysctl_write_ip_property_boolean(AF_MPLS, link->ifname, "input", link->network->mpls_input > 0, manager_get_sysctl_shadow(link->manager));
1✔
684
}
685

686
int link_set_sysctl(Link *link) {
851✔
687
        int r;
851✔
688

689
        assert(link);
851✔
690

691
        /* If IPv6 configured that is static IPv6 address and IPv6LL autoconfiguration is enabled
692
         * for this interface, then enable IPv6 */
693
        r = link_update_ipv6_sysctl(link);
851✔
694
        if (r < 0)
851✔
695
                log_link_warning_errno(link, r, "Cannot enable IPv6, ignoring: %m");
×
696

697
        r = link_set_proxy_arp(link);
851✔
698
        if (r < 0)
851✔
699
               log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface, ignoring: %m");
×
700

701
        r = link_set_proxy_arp_pvlan(link);
851✔
702
        if (r < 0)
851✔
703
                log_link_warning_errno(link, r, "Cannot configure proxy ARP private VLAN for interface, ignoring: %m");
×
704

705
        (void) link_set_ip_forwarding(link, AF_INET);
851✔
706
        (void) link_set_ip_forwarding(link, AF_INET6);
851✔
707

708
        r = link_set_ipv6_privacy_extensions(link);
851✔
709
        if (r < 0)
851✔
UNCOV
710
                log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extensions for interface, ignoring: %m");
×
711

712
        r = link_set_ipv6_accept_ra(link);
851✔
713
        if (r < 0)
851✔
UNCOV
714
                log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface, ignoring: %m");
×
715

716
        r = link_set_ipv6_dad_transmits(link);
851✔
717
        if (r < 0)
851✔
718
                log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface, ignoring: %m");
×
719

720
        r = link_set_ipv6_hop_limit(link);
851✔
721
        if (r < 0)
851✔
722
                log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface, ignoring: %m");
×
723

724
        r = link_set_ipv6_retransmission_time(link);
851✔
725
        if (r < 0)
851✔
726
                log_link_warning_errno(link, r, "Cannot set IPv6 retransmission time for interface, ignoring: %m");
×
727

728
        r = link_set_ipv6_proxy_ndp(link);
851✔
729
        if (r < 0)
851✔
UNCOV
730
                log_link_warning_errno(link, r, "Cannot set IPv6 proxy NDP, ignoring: %m");
×
731

732
        (void) link_set_ipv6_mtu(link, LOG_INFO);
851✔
733

734
        r = link_set_ipv6ll_stable_secret(link);
851✔
735
        if (r < 0)
851✔
736
                log_link_warning_errno(link, r, "Cannot set stable secret address for IPv6 link-local address: %m");
×
737

738
        r = link_set_ipv4_accept_local(link);
851✔
739
        if (r < 0)
851✔
740
                log_link_warning_errno(link, r, "Cannot set IPv4 accept_local flag for interface, ignoring: %m");
×
741

742
        r = link_set_ipv4_route_localnet(link);
851✔
743
        if (r < 0)
851✔
744
                log_link_warning_errno(link, r, "Cannot set IPv4 route_localnet flag for interface, ignoring: %m");
×
745

746
        r = link_set_ipv4_rp_filter(link);
851✔
747
        if (r < 0)
851✔
748
                log_link_warning_errno(link, r, "Cannot set IPv4 reverse path filtering for interface, ignoring: %m");
×
749

750
        r = link_set_ipv4_force_igmp_version(link);
851✔
751
        if (r < 0)
851✔
752
                log_link_warning_errno(link, r, "Cannot set IPv4 force igmp version, ignoring: %m");
×
753

754
        r = link_set_ipv4_promote_secondaries(link);
851✔
755
        if (r < 0)
851✔
UNCOV
756
                log_link_warning_errno(link, r, "Cannot enable promote_secondaries for interface, ignoring: %m");
×
757

758
        r = link_set_mpls_input(link);
851✔
759
        if (r < 0)
851✔
760
                log_link_warning_errno(link, r, "Cannot set MPLS input, ignoring: %m");
×
761

762
        return 0;
851✔
763
}
764

765
static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
766
        [IPV6_PRIVACY_EXTENSIONS_NO]            = "no",
767
        [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
768
        [IPV6_PRIVACY_EXTENSIONS_YES]           = "yes",
769
        [IPV6_PRIVACY_EXTENSIONS_KERNEL]        = "kernel",
770
};
771

772
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(ipv6_privacy_extensions, IPv6PrivacyExtensions,
76✔
773
                                        IPV6_PRIVACY_EXTENSIONS_YES);
774
DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv6_privacy_extensions, ipv6_privacy_extensions, IPv6PrivacyExtensions);
22✔
775

776
static const char* const ip_reverse_path_filter_table[_IP_REVERSE_PATH_FILTER_MAX] = {
777
        [IP_REVERSE_PATH_FILTER_NO]     = "no",
778
        [IP_REVERSE_PATH_FILTER_STRICT] = "strict",
779
        [IP_REVERSE_PATH_FILTER_LOOSE]  = "loose",
780
};
781

782
DEFINE_STRING_TABLE_LOOKUP(ip_reverse_path_filter, IPReversePathFilter);
2✔
783
DEFINE_CONFIG_PARSE_ENUM(config_parse_ip_reverse_path_filter, ip_reverse_path_filter, IPReversePathFilter);
2✔
784

785
int config_parse_ip_forward_deprecated(
×
786
                const char *unit,
787
                const char *filename,
788
                unsigned line,
789
                const char *section,
790
                unsigned section_line,
791
                const char *lvalue,
792
                int ltype,
793
                const char *rvalue,
794
                void *data,
795
                void *userdata) {
796

797
        assert(filename);
×
798

799
        log_syntax(unit, LOG_WARNING, filename, line, 0,
×
800
                   "IPForward= setting is deprecated. "
801
                   "Please use IPv4Forwarding= and/or IPv6Forwarding= in networkd.conf for global setting, "
802
                   "and the same settings in .network files for per-interface setting.");
803
        return 0;
×
804
}
805

806
static const char* const ipv4_force_igmp_version_table[_IPV4_FORCE_IGMP_VERSION_MAX] = {
807
        [IPV4_FORCE_IGMP_VERSION_NO] = "no",
808
        [IPV4_FORCE_IGMP_VERSION_1]  = "v1",
809
        [IPV4_FORCE_IGMP_VERSION_2]  = "v2",
810
        [IPV4_FORCE_IGMP_VERSION_3]  = "v3",
811
};
812

813
DEFINE_STRING_TABLE_LOOKUP(ipv4_force_igmp_version, IPv4ForceIgmpVersion);
2✔
814
DEFINE_CONFIG_PARSE_ENUM(config_parse_ipv4_force_igmp_version, ipv4_force_igmp_version, IPv4ForceIgmpVersion);
2✔
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