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

systemd / systemd / 21419361949

27 Jan 2026 02:53PM UTC coverage: 72.793% (-0.03%) from 72.821%
21419361949

push

github

keszybz
kernel-install: handle removal unsuccessful UKIs and loader entries separately

When a tries file exists, 90-uki-copy.install removes a previous UKI of the
same kernel version and all it's unbooted variants. This removal is guarded
behind a check for the existence of the already booted UKI, i.e. if uki.efi
already exists, uki.efi and uki+*.efi will be removed.

This leaves the edge case that if uki.efi does not exist, but only an unbooted,
e.g. uki+3.efi, it will not be removed. This is not a problem, if the number of
tries is constant between both builds, since a new uki+3.efi would overwrite
the existing one, but if the number of tries is changed to, e.g. uki+5.efi, we
are left with both uki+3.efi and uki+5.efi.

The same is done for loader entries.

311334 of 427698 relevant lines covered (72.79%)

1157141.18 hits per line

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

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

3
#include <unistd.h>
4

5
#include "alloc-util.h"
6
#include "condition.h"
7
#include "conf-files.h"
8
#include "conf-parser.h"
9
#include "in-addr-util.h"
10
#include "net-condition.h"
11
#include "netdev/macvlan.h"
12
#include "netif-sriov.h"
13
#include "network-util.h"
14
#include "networkd-address.h"
15
#include "networkd-address-label.h"
16
#include "networkd-bridge-fdb.h"
17
#include "networkd-bridge-mdb.h"
18
#include "networkd-dhcp-common.h"
19
#include "networkd-dhcp-server-static-lease.h"
20
#include "networkd-ipv6-proxy-ndp.h"
21
#include "networkd-manager.h"
22
#include "networkd-ndisc.h"
23
#include "networkd-neighbor.h"
24
#include "networkd-network.h"
25
#include "networkd-nexthop.h"
26
#include "networkd-radv.h"
27
#include "networkd-route.h"
28
#include "networkd-routing-policy-rule.h"
29
#include "ordered-set.h"
30
#include "parse-util.h"
31
#include "path-util.h"
32
#include "qdisc.h"
33
#include "radv-internal.h"
34
#include "set.h"
35
#include "socket-util.h"
36
#include "stat-util.h"
37
#include "string-table.h"
38
#include "string-util.h"
39
#include "strv.h"
40
#include "tclass.h"
41

42
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
6,491✔
43
                network_hash_ops,
44
                char, string_hash_func, string_compare_func,
45
                Network, network_unref);
46

47
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
196✔
48
                stacked_netdevs_hash_ops,
49
                char, string_hash_func, string_compare_func,
50
                NetDev, netdev_unref);
51

52
static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret) {
26,253✔
53
        const char *kind_string;
26,253✔
54
        NetDev *netdev;
26,253✔
55
        int r;
26,253✔
56

57
        /* For test-networkd-conf, the check must be earlier than the assertions. */
58
        if (!name)
26,253✔
59
                return 0;
26,253✔
60

61
        assert(network);
239✔
62
        assert(network->manager);
239✔
63
        assert(network->filename);
239✔
64
        assert(ret);
239✔
65

66
        if (kind == _NETDEV_KIND_TUNNEL)
239✔
67
                kind_string = "tunnel";
68
        else {
69
                kind_string = netdev_kind_to_string(kind);
89✔
70
                if (!kind_string)
89✔
71
                        return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
×
72
                                                 "%s: Invalid NetDev kind of %s, ignoring assignment.",
73
                                                 network->filename, name);
74
        }
75

76
        r = netdev_get(network->manager, name, &netdev);
239✔
77
        if (r < 0)
239✔
78
                return log_warning_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
1✔
79
                                         network->filename, name);
80

81
        if (netdev->kind != kind && !(kind == _NETDEV_KIND_TUNNEL &&
238✔
82
                                      IN_SET(netdev->kind,
149✔
83
                                             NETDEV_KIND_ERSPAN,
84
                                             NETDEV_KIND_GRE,
85
                                             NETDEV_KIND_GRETAP,
86
                                             NETDEV_KIND_IP6GRE,
87
                                             NETDEV_KIND_IP6GRETAP,
88
                                             NETDEV_KIND_IP6TNL,
89
                                             NETDEV_KIND_IPIP,
90
                                             NETDEV_KIND_SIT,
91
                                             NETDEV_KIND_VTI,
92
                                             NETDEV_KIND_VTI6)))
93
                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
×
94
                                         "%s: NetDev %s is not a %s, ignoring assignment",
95
                                         network->filename, name, kind_string);
96

97
        *ret = netdev_ref(netdev);
238✔
98
        return 1;
238✔
99
}
100

101
static int network_resolve_stacked_netdevs(Network *network) {
6,514✔
102
        void *name, *kind;
6,514✔
103
        int r;
6,514✔
104

105
        assert(network);
6,514✔
106

107
        HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names) {
6,711✔
108
                _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
×
109

110
                if (network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev) <= 0)
197✔
111
                        continue;
1✔
112

113
                r = hashmap_ensure_put(&network->stacked_netdevs, &stacked_netdevs_hash_ops, netdev->ifname, netdev);
196✔
114
                if (r == -ENOMEM)
196✔
115
                        return log_oom();
×
116
                if (r < 0)
196✔
117
                        log_warning_errno(r, "%s: Failed to add NetDev '%s' to network, ignoring: %m",
×
118
                                          network->filename, (const char *) name);
119

120
                TAKE_PTR(netdev);
196✔
121
        }
122

123
        return 0;
6,514✔
124
}
125

126
int network_verify(Network *network) {
7,572✔
127
        int r;
7,572✔
128

129
        assert(network);
7,572✔
130
        assert(network->manager);
7,572✔
131
        assert(network->filename);
7,572✔
132

133
        if (net_match_is_empty(&network->match) && !network->conditions)
7,572✔
134
                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
×
135
                                         "%s: No valid settings found in the [Match] section, ignoring file. "
136
                                         "To match all interfaces, add Name=* in the [Match] section.",
137
                                         network->filename);
138

139
        /* skip out early if configuration does not match the environment */
140
        if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
7,572✔
141
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
1,058✔
142
                                       "%s: Conditions in the file do not match the system environment, skipping.",
143
                                       network->filename);
144

145
        if (network->keep_master) {
6,514✔
146
                if (network->batadv_name)
603✔
147
                        log_warning("%s: BatmanAdvanced= set with KeepMaster= enabled, ignoring BatmanAdvanced=.",
×
148
                                    network->filename);
149
                if (network->bond_name)
603✔
150
                        log_warning("%s: Bond= set with KeepMaster= enabled, ignoring Bond=.",
×
151
                                    network->filename);
152
                if (network->bridge_name)
603✔
153
                        log_warning("%s: Bridge= set with KeepMaster= enabled, ignoring Bridge=.",
×
154
                                    network->filename);
155
                if (network->vrf_name)
603✔
156
                        log_warning("%s: VRF= set with KeepMaster= enabled, ignoring VRF=.",
×
157
                                    network->filename);
158

159
                network->batadv_name = mfree(network->batadv_name);
603✔
160
                network->bond_name = mfree(network->bond_name);
603✔
161
                network->bridge_name = mfree(network->bridge_name);
603✔
162
                network->vrf_name = mfree(network->vrf_name);
603✔
163
        }
164

165
        (void) network_resolve_netdev_one(network, network->batadv_name, NETDEV_KIND_BATADV, &network->batadv);
6,514✔
166
        (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
6,514✔
167
        (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
6,514✔
168
        (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
6,514✔
169
        r = network_resolve_stacked_netdevs(network);
6,514✔
170
        if (r < 0)
6,514✔
171
                return r;
172

173
        /* Free unnecessary entries. */
174
        network->batadv_name = mfree(network->batadv_name);
6,514✔
175
        network->bond_name = mfree(network->bond_name);
6,514✔
176
        network->bridge_name = mfree(network->bridge_name);
6,514✔
177
        network->vrf_name = mfree(network->vrf_name);
6,514✔
178
        network->stacked_netdev_names = hashmap_free(network->stacked_netdev_names);
6,514✔
179

180
        if (network->bond) {
6,514✔
181
                /* Bonding slave does not support addressing. */
182
                if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
9✔
183
                        log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
2✔
184
                                    network->filename);
185
                        network->link_local = ADDRESS_FAMILY_NO;
2✔
186
                }
187
                if (!ordered_hashmap_isempty(network->addresses_by_section))
9✔
188
                        log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
2✔
189
                                    network->filename);
190
                if (!hashmap_isempty(network->routes_by_section))
9✔
191
                        log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
2✔
192
                                    network->filename);
193

194
                network->addresses_by_section = ordered_hashmap_free(network->addresses_by_section);
9✔
195
                network->routes_by_section = hashmap_free(network->routes_by_section);
9✔
196
        }
197

198
        if (network->link_local < 0) {
6,514✔
199
                network->link_local = ADDRESS_FAMILY_IPV6;
1,898✔
200

201
                if (network->keep_master || network->bridge)
1,898✔
202
                        network->link_local = ADDRESS_FAMILY_NO;
28✔
203
                else {
204
                        NetDev *netdev;
1,870✔
205

206
                        HASHMAP_FOREACH(netdev, network->stacked_netdevs) {
2,044✔
207
                                MacVlan *m;
190✔
208

209
                                if (netdev->kind == NETDEV_KIND_MACVLAN)
190✔
210
                                        m = MACVLAN(netdev);
8✔
211
                                else if (netdev->kind == NETDEV_KIND_MACVTAP)
182✔
212
                                        m = MACVTAP(netdev);
8✔
213
                                else
214
                                        continue;
174✔
215

216
                                if (m->mode == NETDEV_MACVLAN_MODE_PASSTHRU)
16✔
217
                                        network->link_local = ADDRESS_FAMILY_NO;
4✔
218

219
                                /* There won't be a passthru MACVLAN/MACVTAP if there's already one in another mode */
220
                                break;
221
                        }
222
                }
223
        }
224

225
        if (network->ipv6ll_address_gen_mode == IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE)
6,514✔
226
                SET_FLAG(network->link_local, ADDRESS_FAMILY_IPV6, false);
×
227

228
        if (in6_addr_is_set(&network->ipv6ll_stable_secret) &&
6,514✔
229
            network->ipv6ll_address_gen_mode < 0)
230
                network->ipv6ll_address_gen_mode = IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY;
1✔
231

232
        network_adjust_ipv6_proxy_ndp(network);
6,514✔
233
        network_adjust_ndisc(network);
6,514✔
234
        network_adjust_dhcp(network);
6,514✔
235
        network_adjust_radv(network);
6,514✔
236
        network_adjust_bridge_vlan(network);
6,514✔
237

238
        if (network->mtu > 0 && network->dhcp_use_mtu) {
6,514✔
239
                log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
×
240
                            "Disabling UseMTU=.", network->filename);
241
                network->dhcp_use_mtu = false;
×
242
        }
243

244
        if (network->dhcp_critical >= 0) {
6,514✔
245
                if (network->keep_configuration >= 0) {
23✔
246
                        if (network->manager->keep_configuration < 0)
23✔
247
                                log_warning("%s: Both KeepConfiguration= and deprecated CriticalConnection= are set. "
23✔
248
                                            "Ignoring CriticalConnection=.", network->filename);
249
                } else if (network->dhcp_critical)
×
250
                        /* CriticalConnection=yes also preserve foreign static configurations. */
251
                        network->keep_configuration = KEEP_CONFIGURATION_YES;
×
252
                else
253
                        network->keep_configuration = KEEP_CONFIGURATION_NO;
×
254
        }
255

256
        if (!strv_isempty(network->bind_carrier)) {
6,514✔
257
                if (!IN_SET(network->activation_policy, _ACTIVATION_POLICY_INVALID, ACTIVATION_POLICY_BOUND))
8✔
258
                        log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
×
259
                                    "Setting ActivationPolicy=bound.", network->filename);
260
                network->activation_policy = ACTIVATION_POLICY_BOUND;
8✔
261
        } else if (network->activation_policy == ACTIVATION_POLICY_BOUND) {
6,506✔
262
                log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
×
263
                            "Ignoring ActivationPolicy=bound.", network->filename);
264
                network->activation_policy = ACTIVATION_POLICY_UP;
×
265
        }
266

267
        if (network->activation_policy == _ACTIVATION_POLICY_INVALID)
6,514✔
268
                network->activation_policy = ACTIVATION_POLICY_UP;
6,456✔
269

270
        if (network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
6,514✔
271
                if (network->ignore_carrier_loss_set && network->ignore_carrier_loss_usec < USEC_INFINITY)
5✔
272
                        log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
×
273
                                    "Setting IgnoreCarrierLoss=yes.", network->filename);
274
                network->ignore_carrier_loss_set = true;
5✔
275
                network->ignore_carrier_loss_usec = USEC_INFINITY;
5✔
276
        }
277

278
        if (!network->ignore_carrier_loss_set) /* Set implied default. */
6,514✔
279
                network->ignore_carrier_loss_usec = network->configure_without_carrier ? USEC_INFINITY : 0;
13,008✔
280

281
        if (IN_SET(network->activation_policy, ACTIVATION_POLICY_DOWN, ACTIVATION_POLICY_ALWAYS_DOWN, ACTIVATION_POLICY_MANUAL)) {
6,514✔
282
                if (network->required_for_online < 0 ||
16✔
283
                    (network->required_for_online == true && network->activation_policy == ACTIVATION_POLICY_ALWAYS_DOWN)) {
3✔
284
                        log_debug("%s: Setting RequiredForOnline=no because ActivationPolicy=%s.", network->filename,
11✔
285
                                  activation_policy_to_string(network->activation_policy));
286
                        network->required_for_online = false;
11✔
287
                } else if (network->required_for_online == true)
5✔
288
                        log_warning("%s: RequiredForOnline=yes and ActivationPolicy=%s, "
2✔
289
                                    "this may cause a delay at boot.", network->filename,
290
                                    activation_policy_to_string(network->activation_policy));
291
        }
292

293
        if (network->required_for_online < 0)
6,514✔
294
                network->required_for_online = true;
2,858✔
295

296
        if (network->keep_configuration < 0)
6,514✔
297
                network->keep_configuration = KEEP_CONFIGURATION_NO;
6,481✔
298

299
        r = network_drop_invalid_addresses(network);
6,514✔
300
        if (r < 0)
6,514✔
301
                return r; /* network_drop_invalid_addresses() logs internally. */
302
        network_drop_invalid_routes(network);
6,514✔
303
        r = network_drop_invalid_nexthops(network);
6,514✔
304
        if (r < 0)
6,514✔
305
                return r;
306
        network_drop_invalid_bridge_fdb_entries(network);
6,514✔
307
        network_drop_invalid_bridge_mdb_entries(network);
6,514✔
308
        r = network_drop_invalid_neighbors(network);
6,514✔
309
        if (r < 0)
6,514✔
310
                return r;
311
        network_drop_invalid_address_labels(network);
6,514✔
312
        network_drop_invalid_routing_policy_rules(network);
6,514✔
313
        network_drop_invalid_qdisc(network);
6,514✔
314
        network_drop_invalid_tclass(network);
6,514✔
315
        r = sr_iov_drop_invalid_sections(UINT32_MAX, network->sr_iov_by_section);
6,514✔
316
        if (r < 0)
6,514✔
317
                return r; /* sr_iov_drop_invalid_sections() logs internally. */
318
        network_drop_invalid_static_leases(network);
6,514✔
319

320
        return 0;
6,514✔
321
}
322

323
int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
7,551✔
324
        _cleanup_free_ char *fname = NULL, *name = NULL;
7,551✔
325
        _cleanup_(network_unrefp) Network *network = NULL;
7,551✔
326
        const char *dropin_dirname;
7,551✔
327
        char *d;
7,551✔
328
        int r;
7,551✔
329

330
        assert(manager);
7,551✔
331
        assert(filename);
7,551✔
332

333
        r = null_or_empty_path(filename);
7,551✔
334
        if (r < 0)
7,551✔
335
                return log_warning_errno(r, "Failed to check if \"%s\" is empty: %m", filename);
×
336
        if (r > 0) {
7,551✔
337
                log_debug("Skipping empty file: %s", filename);
2✔
338
                return 0;
2✔
339
        }
340

341
        fname = strdup(filename);
7,549✔
342
        if (!fname)
7,549✔
343
                return log_oom();
×
344

345
        r = path_extract_filename(filename, &name);
7,549✔
346
        if (r < 0)
7,549✔
347
                return log_warning_errno(r, "Failed to extract file name of \"%s\": %m", filename);
×
348

349
        d = strrchr(name, '.');
7,549✔
350
        if (!d)
7,549✔
351
                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid file name: %s", filename);
×
352

353
        *d = '\0';
7,549✔
354

355
        dropin_dirname = strjoina(name, ".network.d");
37,745✔
356

357
        network = new(Network, 1);
7,549✔
358
        if (!network)
7,549✔
359
                return log_oom();
×
360

361
        *network = (Network) {
7,549✔
362
                .filename = TAKE_PTR(fname),
7,549✔
363
                .name = TAKE_PTR(name),
7,549✔
364

365
                .manager = manager,
366
                .n_ref = 1,
367

368
                .required_for_online = -1,
369
                .required_operstate_for_online = LINK_OPERSTATE_RANGE_INVALID,
370
                .activation_policy = _ACTIVATION_POLICY_INVALID,
371
                .group = -1,
372
                .arp = -1,
373
                .multicast = -1,
374
                .allmulticast = -1,
375
                .promiscuous = -1,
376

377
                .keep_configuration = manager->keep_configuration,
7,549✔
378

379
                .use_domains = _USE_DOMAINS_INVALID,
380

381
                .compat_dhcp_use_domains = _USE_DOMAINS_INVALID,
382
                .compat_dhcp_use_dns = -1,
383
                .compat_dhcp_use_ntp = -1,
384

385
                .dhcp_duid.type = _DUID_TYPE_INVALID,
386
                .dhcp_critical = -1,
387
                .dhcp_use_ntp = -1,
388
                .dhcp_routes_to_ntp = true,
389
                .dhcp_use_sip = true,
390
                .dhcp_use_captive_portal = true,
391
                .dhcp_use_dns = -1,
392
                .dhcp_use_dnr = -1,
393
                .dhcp_routes_to_dns = true,
394
                .dhcp_use_domains = _USE_DOMAINS_INVALID,
395
                .dhcp_use_hostname = true,
396
                .dhcp_use_routes = true,
397
                .dhcp_use_gateway = -1,
398
                .dhcp_send_hostname = true,
399
                .dhcp_send_release = true,
400
                .dhcp_route_metric = DHCP_ROUTE_METRIC,
401
                .dhcp_use_rapid_commit = -1,
402
                .dhcp_client_identifier = _DHCP_CLIENT_ID_INVALID,
403
                .dhcp_route_table = RT_TABLE_MAIN,
404
                .dhcp_ip_service_type = -1,
405
                .dhcp_broadcast = -1,
406
                .dhcp_ipv6_only_mode = -1,
407
                .dhcp_6rd_prefix_route_type = RTN_UNREACHABLE,
408

409
                .dhcp6_use_address = true,
410
                .dhcp6_use_pd_prefix = true,
411
                .dhcp6_use_dns = -1,
412
                .dhcp6_use_dnr = -1,
413
                .dhcp6_use_domains = _USE_DOMAINS_INVALID,
414
                .dhcp6_use_hostname = true,
415
                .dhcp6_use_ntp = -1,
416
                .dhcp6_use_sip = true,
417
                .dhcp6_use_captive_portal = true,
418
                .dhcp6_use_rapid_commit = true,
419
                .dhcp6_send_hostname = true,
420
                .dhcp6_duid.type = _DUID_TYPE_INVALID,
421
                .dhcp6_client_start_mode = _DHCP6_CLIENT_START_MODE_INVALID,
422
                .dhcp6_send_release = true,
423
                .dhcp6_pd_prefix_route_type = RTN_UNREACHABLE,
424

425
                .dhcp_pd = -1,
426
                .dhcp_pd_announce = true,
427
                .dhcp_pd_assign = true,
428
                .dhcp_pd_manage_temporary_address = true,
429
                .dhcp_pd_subnet_id = -1,
430
                .dhcp_pd_route_metric = DHCP6PD_ROUTE_METRIC,
431

432
                .dhcp_server_bind_to_interface = true,
433
                .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
434
                .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
435
                .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
436
                .dhcp_server_emit_router = true,
437
                .dhcp_server_emit_timezone = true,
438
                .dhcp_server_rapid_commit = true,
439
                .dhcp_server_persist_leases = _DHCP_SERVER_PERSIST_LEASES_INVALID,
440

441
                .router_lifetime_usec = RADV_DEFAULT_ROUTER_LIFETIME_USEC,
442
                .router_dns_lifetime_usec = RADV_DEFAULT_VALID_LIFETIME_USEC,
443
                .router_emit_dns = true,
444
                .router_emit_domains = true,
445

446
                .use_bpdu = -1,
447
                .hairpin = -1,
448
                .isolated = -1,
449
                .fast_leave = -1,
450
                .allow_port_to_be_root = -1,
451
                .unicast_flood = -1,
452
                .multicast_flood = -1,
453
                .multicast_to_unicast = -1,
454
                .neighbor_suppression = -1,
455
                .learning = -1,
456
                .bridge_proxy_arp = -1,
457
                .bridge_proxy_arp_wifi = -1,
458
                .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
459
                .multicast_router = _MULTICAST_ROUTER_INVALID,
460
                .bridge_locked = -1,
461
                .bridge_mac_authentication_bypass = -1,
462
                .bridge_vlan_tunnel = -1,
463

464
                .bridge_vlan_pvid = BRIDGE_VLAN_KEEP_PVID,
465

466
                .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
467
                .lldp_multicast_mode = _SD_LLDP_MULTICAST_MODE_INVALID,
468

469
                .dns_default_route = -1,
470
                .llmnr = RESOLVE_SUPPORT_YES,
471
                .mdns = RESOLVE_SUPPORT_NO,
472
                .dnssec_mode = _DNSSEC_MODE_INVALID,
473
                .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
474

475
                /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
476
                .link_local = _ADDRESS_FAMILY_INVALID,
477
                .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
478

479
                .ip_forwarding = { -1, -1, },
480
                .ipv4_accept_local = -1,
481
                .ipv4_route_localnet = -1,
482
                .ipv6_privacy_extensions = _IPV6_PRIVACY_EXTENSIONS_INVALID,
483
                .ipv6_dad_transmits = -1,
484
                .ipv6_proxy_ndp = -1,
485
                .proxy_arp = -1,
486
                .proxy_arp_pvlan = -1,
487
                .ipv4_rp_filter = _IP_REVERSE_PATH_FILTER_INVALID,
488
                .ipv4_force_igmp_version = _IPV4_FORCE_IGMP_VERSION_INVALID,
489
                .mpls_input = -1,
490

491
                .ndisc = -1,
492
                .ndisc_use_redirect = true,
493
                .ndisc_use_dns = -1,
494
                .ndisc_use_dnr = -1,
495
                .ndisc_use_gateway = true,
496
                .ndisc_use_captive_portal = true,
497
                .ndisc_use_route_prefix = true,
498
                .ndisc_use_autonomous_prefix = true,
499
                .ndisc_use_onlink_prefix = true,
500
                .ndisc_use_mtu = true,
501
                .ndisc_use_hop_limit = true,
502
                .ndisc_use_reachable_time = true,
503
                .ndisc_use_retransmission_time = true,
504
                .ndisc_use_domains = _USE_DOMAINS_INVALID,
505
                .ndisc_route_table = RT_TABLE_MAIN,
506
                .ndisc_route_metric_high = IPV6RA_ROUTE_METRIC_HIGH,
507
                .ndisc_route_metric_medium = IPV6RA_ROUTE_METRIC_MEDIUM,
508
                .ndisc_route_metric_low = IPV6RA_ROUTE_METRIC_LOW,
509
                .ndisc_start_dhcp6_client = IPV6_ACCEPT_RA_START_DHCP6_CLIENT_YES,
510

511
                .can_termination = -1,
512

513
                .ipoib_mode = _IP_OVER_INFINIBAND_MODE_INVALID,
514
                .ipoib_umcast = -1,
515
        };
516

517
        r = config_parse_many_full(
15,098✔
518
                        STRV_MAKE_CONST(filename),
7,549✔
519
                        NETWORK_DIRS,
7,549✔
520
                        dropin_dirname,
521
                        /* root= */ NULL,
522
                        /* root_fd= */ -EBADF,
523
                        "Match\0"
524
                        "Link\0"
525
                        "SR-IOV\0"
526
                        "Network\0"
527
                        "Address\0"
528
                        "Neighbor\0"
529
                        "IPv6AddressLabel\0"
530
                        "RoutingPolicyRule\0"
531
                        "Route\0"
532
                        "NextHop\0"
533
                        "DHCP\0" /* compat */
534
                        "DHCPv4\0"
535
                        "DHCPv6\0"
536
                        "DHCPv6PrefixDelegation\0" /* compat */
537
                        "DHCPPrefixDelegation\0"
538
                        "DHCPServer\0"
539
                        "DHCPServerStaticLease\0"
540
                        "IPv6AcceptRA\0"
541
                        "IPv6NDPProxyAddress\0"
542
                        "Bridge\0"
543
                        "BridgeFDB\0"
544
                        "BridgeMDB\0"
545
                        "BridgeVLAN\0"
546
                        "IPv6SendRA\0"
547
                        "IPv6PrefixDelegation\0"
548
                        "IPv6Prefix\0"
549
                        "IPv6RoutePrefix\0"
550
                        "IPv6PREF64Prefix\0"
551
                        "LLDP\0"
552
                        "TrafficControlQueueingDiscipline\0"
553
                        "CAN\0"
554
                        "QDisc\0"
555
                        "BFIFO\0"
556
                        "CAKE\0"
557
                        "ControlledDelay\0"
558
                        "DeficitRoundRobinScheduler\0"
559
                        "DeficitRoundRobinSchedulerClass\0"
560
                        "EnhancedTransmissionSelection\0"
561
                        "FairQueueing\0"
562
                        "FairQueueingControlledDelay\0"
563
                        "FlowQueuePIE\0"
564
                        "GenericRandomEarlyDetection\0"
565
                        "HeavyHitterFilter\0"
566
                        "HierarchyTokenBucket\0"
567
                        "HierarchyTokenBucketClass\0"
568
                        "ClassfulMultiQueueing\0"
569
                        "BandMultiQueueing\0"
570
                        "NetworkEmulator\0"
571
                        "PFIFO\0"
572
                        "PFIFOFast\0"
573
                        "PFIFOHeadDrop\0"
574
                        "PIE\0"
575
                        "QuickFairQueueing\0"
576
                        "QuickFairQueueingClass\0"
577
                        "StochasticFairBlue\0"
578
                        "StochasticFairnessQueueing\0"
579
                        "TokenBucketFilter\0"
580
                        "TrivialLinkEqualizer\0",
581
                        config_item_perf_lookup,
582
                        network_network_gperf_lookup,
583
                        CONFIG_PARSE_WARN,
584
                        network,
585
                        &network->stats_by_path,
586
                        &network->dropins);
7,549✔
587
        if (r < 0)
7,549✔
588
                return r; /* config_parse_many() logs internally. */
589

590
        r = network_add_ipv4ll_route(network);
7,549✔
591
        if (r < 0)
7,549✔
592
                return log_warning_errno(r, "%s: Failed to add IPv4LL route: %m", network->filename);
×
593

594
        r = network_add_default_route_on_device(network);
7,549✔
595
        if (r < 0)
7,549✔
596
                return log_warning_errno(r, "%s: Failed to add default route on device: %m",
×
597
                                         network->filename);
598

599
        r = network_verify(network);
7,549✔
600
        if (r < 0)
7,549✔
601
                return r; /* network_verify() logs internally. */
602

603
        r = ordered_hashmap_ensure_put(networks, &network_hash_ops, network->name, network);
6,491✔
604
        if (r < 0)
6,491✔
605
                return log_warning_errno(r, "%s: Failed to store configuration into hashmap: %m", filename);
×
606

607
        TAKE_PTR(network);
6,491✔
608
        log_syntax(/* unit= */ NULL, LOG_DEBUG, filename, /* config_line= */ 0, /* error= */ 0, "Successfully loaded.");
6,491✔
609
        return 0;
610
}
611

612
int network_load(Manager *manager, OrderedHashmap **ret) {
601✔
613
        _cleanup_strv_free_ char **files = NULL;
601✔
614
        OrderedHashmap *networks = NULL;
601✔
615
        int r;
601✔
616

617
        assert(manager);
601✔
618
        assert(ret);
601✔
619

620
        r = conf_files_list_strv(&files, ".network", /* root= */ NULL, CONF_FILES_WARN, NETWORK_DIRS);
601✔
621
        if (r < 0)
601✔
622
                return log_error_errno(r, "Failed to enumerate network files: %m");
×
623

624
        STRV_FOREACH(f, files)
8,152✔
625
                (void) network_load_one(manager, &networks, *f);
7,551✔
626

627
        *ret = TAKE_PTR(networks);
601✔
628
        return 0;
601✔
629
}
630

631
static bool network_netdev_equal(Network *a, Network *b) {
1,615✔
632
        assert(a);
1,615✔
633
        assert(b);
1,615✔
634

635
        if (a->batadv != b->batadv ||
1,615✔
636
            a->bridge != b->bridge ||
1,615✔
637
            a->bond != b->bond ||
1,615✔
638
            a->vrf != b->vrf ||
1,615✔
639
            a->xfrm != b->xfrm)
1,615✔
640
                return false;
1,615✔
641

642
        if (hashmap_size(a->stacked_netdevs) != hashmap_size(b->stacked_netdevs))
1,615✔
643
                return false;
644

645
        NetDev *n;
1,615✔
646
        HASHMAP_FOREACH(n, a->stacked_netdevs)
1,616✔
647
                if (hashmap_get(b->stacked_netdevs, n->ifname) != n)
45✔
648
                        return false;
44✔
649

650
        return true;
1,571✔
651
}
652

653
int network_reload(Manager *manager) {
154✔
654
        _cleanup_ordered_hashmap_free_ OrderedHashmap *new_networks = NULL;
154✔
655
        Network *n, *old;
154✔
656
        int r;
154✔
657

658
        assert(manager);
154✔
659

660
        r = network_load(manager, &new_networks);
154✔
661
        if (r < 0)
154✔
662
                return r;
663

664
        ORDERED_HASHMAP_FOREACH(n, new_networks) {
1,888✔
665
                r = network_get_by_name(manager, n->name, &old);
1,734✔
666
                if (r < 0) {
1,734✔
667
                        log_debug("%s: Found new .network file.", n->filename);
32✔
668
                        continue;
32✔
669
                }
670

671
                if (!stats_by_path_equal(n->stats_by_path, old->stats_by_path)) {
1,702✔
672
                        log_debug("%s: Found updated .network file.", n->filename);
87✔
673
                        continue;
87✔
674
                }
675

676
                if (!network_netdev_equal(n, old)) {
1,615✔
677
                        log_debug("%s: Detected update of referenced .netdev file(s).", n->filename);
44✔
678
                        continue;
44✔
679
                }
680

681
                /* Nothing updated, use the existing Network object, and drop the new one. */
682
                r = ordered_hashmap_replace(new_networks, old->name, old);
1,571✔
683
                if (r < 0)
1,571✔
684
                        return r;
×
685

686
                network_ref(old);
1,571✔
687
                network_unref(n);
1,571✔
688
        }
689

690
        ordered_hashmap_free_and_replace(manager->networks, new_networks);
154✔
691

692
        r = manager_build_dhcp_pd_subnet_ids(manager);
154✔
693
        if (r < 0)
154✔
694
                return r;
695

696
        r = manager_build_nexthop_ids(manager);
154✔
697
        if (r < 0)
154✔
698
                return r;
×
699

700
        return 0;
701
}
702

703
int manager_build_dhcp_pd_subnet_ids(Manager *manager) {
601✔
704
        Network *n;
601✔
705
        int r;
601✔
706

707
        assert(manager);
601✔
708

709
        set_clear(manager->dhcp_pd_subnet_ids);
601✔
710

711
        ORDERED_HASHMAP_FOREACH(n, manager->networks) {
7,092✔
712
                if (n->unmanaged)
6,491✔
713
                        continue;
362✔
714

715
                if (!n->dhcp_pd)
6,129✔
716
                        continue;
5,512✔
717

718
                if (n->dhcp_pd_subnet_id < 0)
617✔
719
                        continue;
603✔
720

721
                r = set_ensure_put(&manager->dhcp_pd_subnet_ids, &uint64_hash_ops, &n->dhcp_pd_subnet_id);
14✔
722
                if (r < 0)
14✔
723
                        return r;
×
724
        }
725

726
        return 0;
601✔
727
}
728

729
static Network *network_free(Network *network) {
7,572✔
730
        if (!network)
7,572✔
731
                return NULL;
732

733
        free(network->name);
7,572✔
734
        free(network->filename);
7,572✔
735
        free(network->description);
7,572✔
736
        strv_free(network->dropins);
7,572✔
737
        hashmap_free(network->stats_by_path);
7,572✔
738

739
        /* conditions */
740
        net_match_clear(&network->match);
7,572✔
741
        condition_free_list(network->conditions);
7,572✔
742

743
        /* link settings */
744
        strv_free(network->bind_carrier);
7,572✔
745

746
        /* NTP */
747
        strv_free(network->ntp);
7,572✔
748

749
        /* DNS */
750
        for (unsigned i = 0; i < network->n_dns; i++)
7,586✔
751
                in_addr_full_free(network->dns[i]);
14✔
752
        free(network->dns);
7,572✔
753
        ordered_set_free(network->search_domains);
7,572✔
754
        ordered_set_free(network->route_domains);
7,572✔
755
        set_free(network->dnssec_negative_trust_anchors);
7,572✔
756

757
        /* DHCP server */
758
        free(network->dhcp_server_relay_agent_circuit_id);
7,572✔
759
        free(network->dhcp_server_relay_agent_remote_id);
7,572✔
760
        free(network->dhcp_server_boot_server_name);
7,572✔
761
        free(network->dhcp_server_boot_filename);
7,572✔
762
        free(network->dhcp_server_timezone);
7,572✔
763
        free(network->dhcp_server_domain);
7,572✔
764
        free(network->dhcp_server_uplink_name);
7,572✔
765
        for (sd_dhcp_lease_server_type_t t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
53,004✔
766
                free(network->dhcp_server_emit[t].addresses);
45,432✔
767
        ordered_hashmap_free(network->dhcp_server_send_options);
7,572✔
768
        ordered_hashmap_free(network->dhcp_server_send_vendor_options);
7,572✔
769
        free(network->dhcp_server_local_lease_domain);
7,572✔
770

771
        /* DHCP client */
772
        free(network->dhcp_vendor_class_identifier);
7,572✔
773
        free(network->dhcp_mudurl);
7,572✔
774
        free(network->dhcp_hostname);
7,572✔
775
        free(network->dhcp_label);
7,572✔
776
        set_free(network->dhcp_deny_listed_ip);
7,572✔
777
        set_free(network->dhcp_allow_listed_ip);
7,572✔
778
        strv_free(network->dhcp_user_class);
7,572✔
779
        set_free(network->dhcp_request_options);
7,572✔
780
        ordered_hashmap_free(network->dhcp_client_send_options);
7,572✔
781
        ordered_hashmap_free(network->dhcp_client_send_vendor_options);
7,572✔
782
        free(network->dhcp_netlabel);
7,572✔
783
        nft_set_context_clear(&network->dhcp_nft_set_context);
7,572✔
784

785
        /* DHCPv6 client */
786
        free(network->dhcp6_mudurl);
7,572✔
787
        free(network->dhcp6_hostname);
7,572✔
788
        strv_free(network->dhcp6_user_class);
7,572✔
789
        strv_free(network->dhcp6_vendor_class);
7,572✔
790
        set_free(network->dhcp6_request_options);
7,572✔
791
        ordered_hashmap_free(network->dhcp6_client_send_options);
7,572✔
792
        ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
7,572✔
793
        free(network->dhcp6_netlabel);
7,572✔
794
        nft_set_context_clear(&network->dhcp6_nft_set_context);
7,572✔
795

796
        /* DHCP PD */
797
        free(network->dhcp_pd_uplink_name);
7,572✔
798
        set_free(network->dhcp_pd_tokens);
7,572✔
799
        free(network->dhcp_pd_netlabel);
7,572✔
800
        nft_set_context_clear(&network->dhcp_pd_nft_set_context);
7,572✔
801

802
        /* Router advertisement */
803
        ordered_set_free(network->router_search_domains);
7,572✔
804
        free(network->router_dns);
7,572✔
805
        free(network->router_uplink_name);
7,572✔
806

807
        /* NDisc */
808
        set_free(network->ndisc_deny_listed_router);
7,572✔
809
        set_free(network->ndisc_allow_listed_router);
7,572✔
810
        set_free(network->ndisc_deny_listed_prefix);
7,572✔
811
        set_free(network->ndisc_allow_listed_prefix);
7,572✔
812
        set_free(network->ndisc_deny_listed_route_prefix);
7,572✔
813
        set_free(network->ndisc_allow_listed_route_prefix);
7,572✔
814
        set_free(network->ndisc_tokens);
7,572✔
815
        free(network->ndisc_netlabel);
7,572✔
816
        nft_set_context_clear(&network->ndisc_nft_set_context);
7,572✔
817

818
        /* LLDP */
819
        free(network->lldp_mudurl);
7,572✔
820

821
        /* netdev */
822
        free(network->batadv_name);
7,572✔
823
        free(network->bridge_name);
7,572✔
824
        free(network->bond_name);
7,572✔
825
        free(network->vrf_name);
7,572✔
826
        hashmap_free(network->stacked_netdev_names);
7,572✔
827
        netdev_unref(network->bridge);
7,572✔
828
        netdev_unref(network->bond);
7,572✔
829
        netdev_unref(network->vrf);
7,572✔
830
        hashmap_free(network->stacked_netdevs);
7,572✔
831

832
        /* static configs */
833
        set_free(network->ipv6_proxy_ndp_addresses);
7,572✔
834
        ordered_hashmap_free(network->addresses_by_section);
7,572✔
835
        hashmap_free(network->routes_by_section);
7,572✔
836
        ordered_hashmap_free(network->nexthops_by_section);
7,572✔
837
        hashmap_free(network->bridge_fdb_entries_by_section);
7,572✔
838
        hashmap_free(network->bridge_mdb_entries_by_section);
7,572✔
839
        ordered_hashmap_free(network->neighbors_by_section);
7,572✔
840
        hashmap_free(network->address_labels_by_section);
7,572✔
841
        hashmap_free(network->prefixes_by_section);
7,572✔
842
        hashmap_free(network->route_prefixes_by_section);
7,572✔
843
        hashmap_free(network->pref64_prefixes_by_section);
7,572✔
844
        hashmap_free(network->rules_by_section);
7,572✔
845
        hashmap_free(network->dhcp_static_leases_by_section);
7,572✔
846
        ordered_hashmap_free(network->sr_iov_by_section);
7,572✔
847
        hashmap_free(network->qdiscs_by_section);
7,572✔
848
        hashmap_free(network->tclasses_by_section);
7,572✔
849

850
        return mfree(network);
7,572✔
851
}
852

853
DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
16,584✔
854

855
int network_get_by_name(Manager *manager, const char *name, Network **ret) {
1,745✔
856
        Network *network;
1,745✔
857

858
        assert(manager);
1,745✔
859
        assert(name);
1,745✔
860
        assert(ret);
1,745✔
861

862
        network = ordered_hashmap_get(manager->networks, name);
1,745✔
863
        if (!network)
1,745✔
864
                return -ENOENT;
865

866
        *ret = network;
1,712✔
867

868
        return 0;
1,712✔
869
}
870

871
bool network_has_static_ipv6_configurations(Network *network) {
125✔
872
        Address *address;
125✔
873
        Route *route;
125✔
874
        BridgeFDB *fdb;
125✔
875
        BridgeMDB *mdb;
125✔
876
        Neighbor *neighbor;
125✔
877

878
        assert(network);
125✔
879

880
        ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)
130✔
881
                if (address->family == AF_INET6)
48✔
882
                        return true;
43✔
883

884
        HASHMAP_FOREACH(route, network->routes_by_section)
82✔
885
                if (route->family == AF_INET6)
×
886
                        return true;
×
887

888
        HASHMAP_FOREACH(fdb, network->bridge_fdb_entries_by_section)
82✔
889
                if (fdb->family == AF_INET6)
×
890
                        return true;
×
891

892
        HASHMAP_FOREACH(mdb, network->bridge_mdb_entries_by_section)
84✔
893
                if (mdb->family == AF_INET6)
4✔
894
                        return true;
2✔
895

896
        ORDERED_HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
82✔
897
                if (neighbor->dst_addr.family == AF_INET6)
2✔
898
                        return true;
×
899

900
        if (!hashmap_isempty(network->address_labels_by_section))
80✔
901
                return true;
902

903
        if (!hashmap_isempty(network->prefixes_by_section))
80✔
904
                return true;
905

906
        if (!hashmap_isempty(network->route_prefixes_by_section))
80✔
907
                return true;
908

909
        if (!hashmap_isempty(network->pref64_prefixes_by_section))
80✔
910
                return true;
×
911

912
        return false;
913
}
914

915
int config_parse_stacked_netdev(
197✔
916
                const char *unit,
917
                const char *filename,
918
                unsigned line,
919
                const char *section,
920
                unsigned section_line,
921
                const char *lvalue,
922
                int ltype,
923
                const char *rvalue,
924
                void *data,
925
                void *userdata) {
926

927
        _cleanup_free_ char *name = NULL;
197✔
928
        NetDevKind kind = ltype;
197✔
929
        Hashmap **h = ASSERT_PTR(data);
197✔
930
        int r;
197✔
931

932
        assert(filename);
197✔
933
        assert(lvalue);
197✔
934
        assert(rvalue);
197✔
935
        assert(IN_SET(kind,
197✔
936
                      NETDEV_KIND_IPOIB,
937
                      NETDEV_KIND_IPVLAN,
938
                      NETDEV_KIND_IPVTAP,
939
                      NETDEV_KIND_MACSEC,
940
                      NETDEV_KIND_MACVLAN,
941
                      NETDEV_KIND_MACVTAP,
942
                      NETDEV_KIND_VLAN,
943
                      NETDEV_KIND_VXLAN,
944
                      NETDEV_KIND_XFRM,
945
                      _NETDEV_KIND_TUNNEL));
946

947
        if (!ifname_valid(rvalue)) {
197✔
948
                log_syntax(unit, LOG_WARNING, filename, line, 0,
×
949
                           "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
950
                return 0;
×
951
        }
952

953
        name = strdup(rvalue);
197✔
954
        if (!name)
197✔
955
                return log_oom();
×
956

957
        r = hashmap_ensure_put(h, &string_hash_ops_free, name, INT_TO_PTR(kind));
197✔
958
        if (r == -ENOMEM)
197✔
959
                return log_oom();
×
960
        if (r < 0)
197✔
961
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
962
                           "Cannot add NetDev '%s' to network, ignoring assignment: %m", name);
963
        else if (r == 0)
197✔
964
                log_syntax(unit, LOG_DEBUG, filename, line, r,
×
965
                           "NetDev '%s' specified twice, ignoring.", name);
966
        else
967
                TAKE_PTR(name);
968

969
        return 0;
970
}
971

972
int config_parse_required_for_online(
3,623✔
973
                const char *unit,
974
                const char *filename,
975
                unsigned line,
976
                const char *section,
977
                unsigned section_line,
978
                const char *lvalue,
979
                int ltype,
980
                const char *rvalue,
981
                void *data,
982
                void *userdata) {
983

984
        Network *network = ASSERT_PTR(userdata);
3,623✔
985
        int r;
3,623✔
986

987
        assert(filename);
3,623✔
988
        assert(lvalue);
3,623✔
989
        assert(rvalue);
3,623✔
990

991
        if (isempty(rvalue)) {
3,623✔
992
                network->required_for_online = -1;
×
993
                network->required_operstate_for_online = LINK_OPERSTATE_RANGE_INVALID;
×
994
                return 0;
×
995
        }
996

997
        r = parse_operational_state_range(rvalue, &network->required_operstate_for_online);
3,623✔
998
        if (r < 0) {
3,623✔
999
                r = parse_boolean(rvalue);
3,622✔
1000
                if (r < 0) {
3,622✔
1001
                        log_syntax(unit, LOG_WARNING, filename, line, r,
×
1002
                                   "Failed to parse %s= setting, ignoring assignment: %s",
1003
                                   lvalue, rvalue);
1004
                        return 0;
×
1005
                }
1006

1007
                network->required_for_online = r;
3,622✔
1008
                network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
3,622✔
1009
                return 0;
3,622✔
1010
        }
1011

1012
        network->required_for_online = true;
1✔
1013
        return 0;
1✔
1014
}
1015

1016
int config_parse_link_group(
×
1017
                const char *unit,
1018
                const char *filename,
1019
                unsigned line,
1020
                const char *section,
1021
                unsigned section_line,
1022
                const char *lvalue,
1023
                int ltype,
1024
                const char *rvalue,
1025
                void *data,
1026
                void *userdata) {
1027

1028
        Network *network = ASSERT_PTR(userdata);
×
1029
        int r;
×
1030
        int32_t group;
×
1031

1032
        assert(filename);
×
1033
        assert(lvalue);
×
1034
        assert(rvalue);
×
1035

1036
        if (isempty(rvalue)) {
×
1037
                network->group = -1;
×
1038
                return 0;
×
1039
        }
1040

1041
        r = safe_atoi32(rvalue, &group);
×
1042
        if (r < 0) {
×
1043
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
1044
                           "Failed to parse Group=, ignoring assignment: %s", rvalue);
1045
                return 0;
×
1046
        }
1047

1048
        if (group < 0) {
×
1049
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
1050
                           "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue);
1051
                return 0;
×
1052
        }
1053

1054
        network->group = group;
×
1055
        return 0;
×
1056
}
1057

1058
int config_parse_ignore_carrier_loss(
3✔
1059
                const char *unit,
1060
                const char *filename,
1061
                unsigned line,
1062
                const char *section,
1063
                unsigned section_line,
1064
                const char *lvalue,
1065
                int ltype,
1066
                const char *rvalue,
1067
                void *data,
1068
                void *userdata) {
1069

1070
        Network *network = ASSERT_PTR(userdata);
3✔
1071
        usec_t usec;
3✔
1072
        int r;
3✔
1073

1074
        assert(filename);
3✔
1075
        assert(lvalue);
3✔
1076
        assert(rvalue);
3✔
1077

1078
        if (isempty(rvalue)) {
3✔
1079
                network->ignore_carrier_loss_set = false;
×
1080
                return 0;
×
1081
        }
1082

1083
        r = parse_boolean(rvalue);
3✔
1084
        if (r >= 0) {
3✔
1085
                network->ignore_carrier_loss_set = true;
3✔
1086
                network->ignore_carrier_loss_usec = r > 0 ? USEC_INFINITY : 0;
3✔
1087
                return 0;
3✔
1088
        }
1089

1090
        r = parse_sec(rvalue, &usec);
×
1091
        if (r < 0) {
×
1092
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
1093
                           "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
1094
                return 0;
×
1095
        }
1096

1097
        network->ignore_carrier_loss_set = true;
×
1098
        network->ignore_carrier_loss_usec = usec;
×
1099
        return 0;
×
1100
}
1101

1102
int config_parse_keep_configuration(
10✔
1103
                const char *unit,
1104
                const char *filename,
1105
                unsigned line,
1106
                const char *section,
1107
                unsigned section_line,
1108
                const char *lvalue,
1109
                int ltype,
1110
                const char *rvalue,
1111
                void *data,
1112
                void *userdata) {
1113

1114
        KeepConfiguration t, *k = ASSERT_PTR(data);
10✔
1115
        Network *network = ASSERT_PTR(userdata);
10✔
1116

1117
        if (isempty(rvalue)) {
10✔
1118
                *k = ASSERT_PTR(network->manager)->keep_configuration;
×
1119
                return 0;
×
1120
        }
1121

1122
        /* backward compatibility */
1123
        if (streq(rvalue, "dhcp")) {
10✔
1124
                *k = KEEP_CONFIGURATION_DYNAMIC;
×
1125
                return 0;
×
1126
        }
1127

1128
        if (streq(rvalue, "dhcp-on-stop")) {
10✔
1129
                *k = KEEP_CONFIGURATION_DYNAMIC_ON_STOP;
×
1130
                return 0;
×
1131
        }
1132

1133
        t = keep_configuration_from_string(rvalue);
10✔
1134
        if (t < 0)
10✔
1135
                return log_syntax_parse_error(unit, filename, line, t, lvalue, rvalue);
×
1136

1137
        *k = t;
10✔
1138
        return 0;
10✔
1139
}
1140

1141
DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online, link_required_address_family, AddressFamily);
1✔
1142

1143
static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
1144
        [KEEP_CONFIGURATION_NO]              = "no",
1145
        [KEEP_CONFIGURATION_DYNAMIC_ON_STOP] = "dynamic-on-stop",
1146
        [KEEP_CONFIGURATION_DYNAMIC]         = "dynamic",
1147
        [KEEP_CONFIGURATION_STATIC]          = "static",
1148
        [KEEP_CONFIGURATION_YES]             = "yes",
1149
};
1150

1151
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
10✔
1152

1153
static const char* const activation_policy_table[_ACTIVATION_POLICY_MAX] = {
1154
        [ACTIVATION_POLICY_UP]          = "up",
1155
        [ACTIVATION_POLICY_ALWAYS_UP]   = "always-up",
1156
        [ACTIVATION_POLICY_MANUAL]      = "manual",
1157
        [ACTIVATION_POLICY_ALWAYS_DOWN] = "always-down",
1158
        [ACTIVATION_POLICY_DOWN]        = "down",
1159
        [ACTIVATION_POLICY_BOUND]       = "bound",
1160
};
1161

1162
DEFINE_STRING_TABLE_LOOKUP(activation_policy, ActivationPolicy);
5,570✔
1163
DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy, activation_policy, ActivationPolicy);
30✔
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