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

systemd / systemd / 18578253386

16 Oct 2025 06:50PM UTC coverage: 72.363% (+0.3%) from 72.072%
18578253386

push

github

web-flow
core/mount: properly handle REMOUNTING_* states in mount_stop() (#39269)

5 of 9 new or added lines in 1 file covered. (55.56%)

3694 existing lines in 74 files now uncovered.

304611 of 420946 relevant lines covered (72.36%)

1092905.84 hits per line

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

83.69
/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,408✔
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) {
25,921✔
53
        const char *kind_string;
25,921✔
54
        NetDev *netdev;
25,921✔
55
        int r;
25,921✔
56

57
        /* For test-networkd-conf, the check must be earlier than the assertions. */
58
        if (!name)
25,921✔
59
                return 0;
25,921✔
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,431✔
102
        void *name, *kind;
6,431✔
103
        int r;
6,431✔
104

105
        assert(network);
6,431✔
106

107
        HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names) {
6,628✔
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,431✔
124
}
125

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

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

133
        if (net_match_is_empty(&network->match) && !network->conditions)
7,475✔
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,475✔
141
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
1,044✔
142
                                       "%s: Conditions in the file do not match the system environment, skipping.",
143
                                       network->filename);
144

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

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

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

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

180
        if (network->bond) {
6,431✔
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,431✔
199
                network->link_local = ADDRESS_FAMILY_IPV6;
1,873✔
200

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

206
                        HASHMAP_FOREACH(netdev, network->stacked_netdevs) {
2,019✔
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,431✔
226
                SET_FLAG(network->link_local, ADDRESS_FAMILY_IPV6, false);
×
227

228
        if (in6_addr_is_set(&network->ipv6ll_stable_secret) &&
6,431✔
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,431✔
233
        network_adjust_ndisc(network);
6,431✔
234
        network_adjust_dhcp(network);
6,431✔
235
        network_adjust_radv(network);
6,431✔
236
        network_adjust_bridge_vlan(network);
6,431✔
237

238
        if (network->mtu > 0 && network->dhcp_use_mtu) {
6,431✔
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,431✔
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,431✔
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,423✔
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,431✔
268
                network->activation_policy = ACTIVATION_POLICY_UP;
6,373✔
269

270
        if (network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
6,431✔
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,431✔
279
                network->ignore_carrier_loss_usec = network->configure_without_carrier ? USEC_INFINITY : 0;
12,842✔
280

281
        if (IN_SET(network->activation_policy, ACTIVATION_POLICY_DOWN, ACTIVATION_POLICY_ALWAYS_DOWN, ACTIVATION_POLICY_MANUAL)) {
6,431✔
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,431✔
294
                network->required_for_online = true;
2,823✔
295

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

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

320
        return 0;
6,431✔
321
}
322

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

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

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

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

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

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

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

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

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

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

585
        r = network_add_ipv4ll_route(network);
7,452✔
586
        if (r < 0)
7,452✔
587
                return log_warning_errno(r, "%s: Failed to add IPv4LL route: %m", network->filename);
×
588

589
        r = network_add_default_route_on_device(network);
7,452✔
590
        if (r < 0)
7,452✔
591
                return log_warning_errno(r, "%s: Failed to add default route on device: %m",
×
592
                                         network->filename);
593

594
        r = network_verify(network);
7,452✔
595
        if (r < 0)
7,452✔
596
                return r; /* network_verify() logs internally. */
597

598
        r = ordered_hashmap_ensure_put(networks, &network_hash_ops, network->name, network);
6,408✔
599
        if (r < 0)
6,408✔
600
                return log_warning_errno(r, "%s: Failed to store configuration into hashmap: %m", filename);
×
601

602
        TAKE_PTR(network);
6,408✔
603
        log_syntax(/* unit = */ NULL, LOG_DEBUG, filename, /* config_line = */ 0, /* error = */ 0, "Successfully loaded.");
6,408✔
604
        return 0;
605
}
606

607
int network_load(Manager *manager, OrderedHashmap **ret) {
593✔
608
        _cleanup_strv_free_ char **files = NULL;
593✔
609
        OrderedHashmap *networks = NULL;
593✔
610
        int r;
593✔
611

612
        assert(manager);
593✔
613
        assert(ret);
593✔
614

615
        r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
593✔
616
        if (r < 0)
593✔
617
                return log_error_errno(r, "Failed to enumerate network files: %m");
×
618

619
        STRV_FOREACH(f, files)
8,047✔
620
                (void) network_load_one(manager, &networks, *f);
7,454✔
621

622
        *ret = TAKE_PTR(networks);
593✔
623
        return 0;
593✔
624
}
625

626
static bool network_netdev_equal(Network *a, Network *b) {
1,615✔
627
        assert(a);
1,615✔
628
        assert(b);
1,615✔
629

630
        if (a->batadv != b->batadv ||
1,615✔
631
            a->bridge != b->bridge ||
1,615✔
632
            a->bond != b->bond ||
1,615✔
633
            a->vrf != b->vrf ||
1,615✔
634
            a->xfrm != b->xfrm)
1,615✔
635
                return false;
1,615✔
636

637
        if (hashmap_size(a->stacked_netdevs) != hashmap_size(b->stacked_netdevs))
1,615✔
638
                return false;
639

640
        NetDev *n;
1,615✔
641
        HASHMAP_FOREACH(n, a->stacked_netdevs)
1,616✔
642
                if (hashmap_get(b->stacked_netdevs, n->ifname) != n)
45✔
643
                        return false;
44✔
644

645
        return true;
1,571✔
646
}
647

648
int network_reload(Manager *manager) {
154✔
649
        _cleanup_ordered_hashmap_free_ OrderedHashmap *new_networks = NULL;
154✔
650
        Network *n, *old;
154✔
651
        int r;
154✔
652

653
        assert(manager);
154✔
654

655
        r = network_load(manager, &new_networks);
154✔
656
        if (r < 0)
154✔
657
                return r;
658

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

666
                if (!stats_by_path_equal(n->stats_by_path, old->stats_by_path)) {
1,702✔
667
                        log_debug("%s: Found updated .network file.", n->filename);
87✔
668
                        continue;
87✔
669
                }
670

671
                if (!network_netdev_equal(n, old)) {
1,615✔
672
                        log_debug("%s: Detected update of referenced .netdev file(s).", n->filename);
44✔
673
                        continue;
44✔
674
                }
675

676
                /* Nothing updated, use the existing Network object, and drop the new one. */
677
                r = ordered_hashmap_replace(new_networks, old->name, old);
1,571✔
678
                if (r < 0)
1,571✔
679
                        return r;
×
680

681
                network_ref(old);
1,571✔
682
                network_unref(n);
1,571✔
683
        }
684

685
        ordered_hashmap_free_and_replace(manager->networks, new_networks);
154✔
686

687
        r = manager_build_dhcp_pd_subnet_ids(manager);
154✔
688
        if (r < 0)
154✔
689
                return r;
690

691
        r = manager_build_nexthop_ids(manager);
154✔
692
        if (r < 0)
154✔
693
                return r;
×
694

695
        return 0;
696
}
697

698
int manager_build_dhcp_pd_subnet_ids(Manager *manager) {
593✔
699
        Network *n;
593✔
700
        int r;
593✔
701

702
        assert(manager);
593✔
703

704
        set_clear(manager->dhcp_pd_subnet_ids);
593✔
705

706
        ORDERED_HASHMAP_FOREACH(n, manager->networks) {
7,001✔
707
                if (n->unmanaged)
6,408✔
708
                        continue;
357✔
709

710
                if (!n->dhcp_pd)
6,051✔
711
                        continue;
5,442✔
712

713
                if (n->dhcp_pd_subnet_id < 0)
609✔
714
                        continue;
595✔
715

716
                r = set_ensure_put(&manager->dhcp_pd_subnet_ids, &uint64_hash_ops, &n->dhcp_pd_subnet_id);
14✔
717
                if (r < 0)
14✔
718
                        return r;
×
719
        }
720

721
        return 0;
593✔
722
}
723

724
static Network *network_free(Network *network) {
7,475✔
725
        if (!network)
7,475✔
726
                return NULL;
727

728
        free(network->name);
7,475✔
729
        free(network->filename);
7,475✔
730
        free(network->description);
7,475✔
731
        strv_free(network->dropins);
7,475✔
732
        hashmap_free(network->stats_by_path);
7,475✔
733

734
        /* conditions */
735
        net_match_clear(&network->match);
7,475✔
736
        condition_free_list(network->conditions);
7,475✔
737

738
        /* link settings */
739
        strv_free(network->bind_carrier);
7,475✔
740

741
        /* NTP */
742
        strv_free(network->ntp);
7,475✔
743

744
        /* DNS */
745
        for (unsigned i = 0; i < network->n_dns; i++)
7,489✔
746
                in_addr_full_free(network->dns[i]);
14✔
747
        free(network->dns);
7,475✔
748
        ordered_set_free(network->search_domains);
7,475✔
749
        ordered_set_free(network->route_domains);
7,475✔
750
        set_free(network->dnssec_negative_trust_anchors);
7,475✔
751

752
        /* DHCP server */
753
        free(network->dhcp_server_relay_agent_circuit_id);
7,475✔
754
        free(network->dhcp_server_relay_agent_remote_id);
7,475✔
755
        free(network->dhcp_server_boot_server_name);
7,475✔
756
        free(network->dhcp_server_boot_filename);
7,475✔
757
        free(network->dhcp_server_timezone);
7,475✔
758
        free(network->dhcp_server_domain);
7,475✔
759
        free(network->dhcp_server_uplink_name);
7,475✔
760
        for (sd_dhcp_lease_server_type_t t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
52,325✔
761
                free(network->dhcp_server_emit[t].addresses);
44,850✔
762
        ordered_hashmap_free(network->dhcp_server_send_options);
7,475✔
763
        ordered_hashmap_free(network->dhcp_server_send_vendor_options);
7,475✔
764

765
        /* DHCP client */
766
        free(network->dhcp_vendor_class_identifier);
7,475✔
767
        free(network->dhcp_mudurl);
7,475✔
768
        free(network->dhcp_hostname);
7,475✔
769
        free(network->dhcp_label);
7,475✔
770
        set_free(network->dhcp_deny_listed_ip);
7,475✔
771
        set_free(network->dhcp_allow_listed_ip);
7,475✔
772
        strv_free(network->dhcp_user_class);
7,475✔
773
        set_free(network->dhcp_request_options);
7,475✔
774
        ordered_hashmap_free(network->dhcp_client_send_options);
7,475✔
775
        ordered_hashmap_free(network->dhcp_client_send_vendor_options);
7,475✔
776
        free(network->dhcp_netlabel);
7,475✔
777
        nft_set_context_clear(&network->dhcp_nft_set_context);
7,475✔
778

779
        /* DHCPv6 client */
780
        free(network->dhcp6_mudurl);
7,475✔
781
        free(network->dhcp6_hostname);
7,475✔
782
        strv_free(network->dhcp6_user_class);
7,475✔
783
        strv_free(network->dhcp6_vendor_class);
7,475✔
784
        set_free(network->dhcp6_request_options);
7,475✔
785
        ordered_hashmap_free(network->dhcp6_client_send_options);
7,475✔
786
        ordered_hashmap_free(network->dhcp6_client_send_vendor_options);
7,475✔
787
        free(network->dhcp6_netlabel);
7,475✔
788
        nft_set_context_clear(&network->dhcp6_nft_set_context);
7,475✔
789

790
        /* DHCP PD */
791
        free(network->dhcp_pd_uplink_name);
7,475✔
792
        set_free(network->dhcp_pd_tokens);
7,475✔
793
        free(network->dhcp_pd_netlabel);
7,475✔
794
        nft_set_context_clear(&network->dhcp_pd_nft_set_context);
7,475✔
795

796
        /* Router advertisement */
797
        ordered_set_free(network->router_search_domains);
7,475✔
798
        free(network->router_dns);
7,475✔
799
        free(network->router_uplink_name);
7,475✔
800

801
        /* NDisc */
802
        set_free(network->ndisc_deny_listed_router);
7,475✔
803
        set_free(network->ndisc_allow_listed_router);
7,475✔
804
        set_free(network->ndisc_deny_listed_prefix);
7,475✔
805
        set_free(network->ndisc_allow_listed_prefix);
7,475✔
806
        set_free(network->ndisc_deny_listed_route_prefix);
7,475✔
807
        set_free(network->ndisc_allow_listed_route_prefix);
7,475✔
808
        set_free(network->ndisc_tokens);
7,475✔
809
        free(network->ndisc_netlabel);
7,475✔
810
        nft_set_context_clear(&network->ndisc_nft_set_context);
7,475✔
811

812
        /* LLDP */
813
        free(network->lldp_mudurl);
7,475✔
814

815
        /* netdev */
816
        free(network->batadv_name);
7,475✔
817
        free(network->bridge_name);
7,475✔
818
        free(network->bond_name);
7,475✔
819
        free(network->vrf_name);
7,475✔
820
        hashmap_free(network->stacked_netdev_names);
7,475✔
821
        netdev_unref(network->bridge);
7,475✔
822
        netdev_unref(network->bond);
7,475✔
823
        netdev_unref(network->vrf);
7,475✔
824
        hashmap_free(network->stacked_netdevs);
7,475✔
825

826
        /* static configs */
827
        set_free(network->ipv6_proxy_ndp_addresses);
7,475✔
828
        ordered_hashmap_free(network->addresses_by_section);
7,475✔
829
        hashmap_free(network->routes_by_section);
7,475✔
830
        ordered_hashmap_free(network->nexthops_by_section);
7,475✔
831
        hashmap_free(network->bridge_fdb_entries_by_section);
7,475✔
832
        hashmap_free(network->bridge_mdb_entries_by_section);
7,475✔
833
        ordered_hashmap_free(network->neighbors_by_section);
7,475✔
834
        hashmap_free(network->address_labels_by_section);
7,475✔
835
        hashmap_free(network->prefixes_by_section);
7,475✔
836
        hashmap_free(network->route_prefixes_by_section);
7,475✔
837
        hashmap_free(network->pref64_prefixes_by_section);
7,475✔
838
        hashmap_free(network->rules_by_section);
7,475✔
839
        hashmap_free(network->dhcp_static_leases_by_section);
7,475✔
840
        ordered_hashmap_free(network->sr_iov_by_section);
7,475✔
841
        hashmap_free(network->qdiscs_by_section);
7,475✔
842
        hashmap_free(network->tclasses_by_section);
7,475✔
843

844
        return mfree(network);
7,475✔
845
}
846

847
DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
16,385✔
848

849
int network_get_by_name(Manager *manager, const char *name, Network **ret) {
1,745✔
850
        Network *network;
1,745✔
851

852
        assert(manager);
1,745✔
853
        assert(name);
1,745✔
854
        assert(ret);
1,745✔
855

856
        network = ordered_hashmap_get(manager->networks, name);
1,745✔
857
        if (!network)
1,745✔
858
                return -ENOENT;
859

860
        *ret = network;
1,712✔
861

862
        return 0;
1,712✔
863
}
864

865
bool network_has_static_ipv6_configurations(Network *network) {
114✔
866
        Address *address;
114✔
867
        Route *route;
114✔
868
        BridgeFDB *fdb;
114✔
869
        BridgeMDB *mdb;
114✔
870
        Neighbor *neighbor;
114✔
871

872
        assert(network);
114✔
873

874
        ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)
119✔
875
                if (address->family == AF_INET6)
48✔
876
                        return true;
43✔
877

878
        HASHMAP_FOREACH(route, network->routes_by_section)
71✔
879
                if (route->family == AF_INET6)
×
UNCOV
880
                        return true;
×
881

882
        HASHMAP_FOREACH(fdb, network->bridge_fdb_entries_by_section)
71✔
883
                if (fdb->family == AF_INET6)
×
UNCOV
884
                        return true;
×
885

886
        HASHMAP_FOREACH(mdb, network->bridge_mdb_entries_by_section)
73✔
887
                if (mdb->family == AF_INET6)
4✔
888
                        return true;
2✔
889

890
        ORDERED_HASHMAP_FOREACH(neighbor, network->neighbors_by_section)
71✔
891
                if (neighbor->dst_addr.family == AF_INET6)
2✔
UNCOV
892
                        return true;
×
893

894
        if (!hashmap_isempty(network->address_labels_by_section))
69✔
895
                return true;
896

897
        if (!hashmap_isempty(network->prefixes_by_section))
69✔
898
                return true;
899

900
        if (!hashmap_isempty(network->route_prefixes_by_section))
69✔
901
                return true;
902

903
        if (!hashmap_isempty(network->pref64_prefixes_by_section))
69✔
UNCOV
904
                return true;
×
905

906
        return false;
907
}
908

909
int config_parse_stacked_netdev(
197✔
910
                const char *unit,
911
                const char *filename,
912
                unsigned line,
913
                const char *section,
914
                unsigned section_line,
915
                const char *lvalue,
916
                int ltype,
917
                const char *rvalue,
918
                void *data,
919
                void *userdata) {
920

921
        _cleanup_free_ char *name = NULL;
197✔
922
        NetDevKind kind = ltype;
197✔
923
        Hashmap **h = ASSERT_PTR(data);
197✔
924
        int r;
197✔
925

926
        assert(filename);
197✔
927
        assert(lvalue);
197✔
928
        assert(rvalue);
197✔
929
        assert(IN_SET(kind,
197✔
930
                      NETDEV_KIND_IPOIB,
931
                      NETDEV_KIND_IPVLAN,
932
                      NETDEV_KIND_IPVTAP,
933
                      NETDEV_KIND_MACSEC,
934
                      NETDEV_KIND_MACVLAN,
935
                      NETDEV_KIND_MACVTAP,
936
                      NETDEV_KIND_VLAN,
937
                      NETDEV_KIND_VXLAN,
938
                      NETDEV_KIND_XFRM,
939
                      _NETDEV_KIND_TUNNEL));
940

941
        if (!ifname_valid(rvalue)) {
197✔
UNCOV
942
                log_syntax(unit, LOG_WARNING, filename, line, 0,
×
943
                           "Invalid netdev name in %s=, ignoring assignment: %s", lvalue, rvalue);
UNCOV
944
                return 0;
×
945
        }
946

947
        name = strdup(rvalue);
197✔
948
        if (!name)
197✔
UNCOV
949
                return log_oom();
×
950

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

963
        return 0;
964
}
965

966
int config_parse_required_for_online(
3,575✔
967
                const char *unit,
968
                const char *filename,
969
                unsigned line,
970
                const char *section,
971
                unsigned section_line,
972
                const char *lvalue,
973
                int ltype,
974
                const char *rvalue,
975
                void *data,
976
                void *userdata) {
977

978
        Network *network = ASSERT_PTR(userdata);
3,575✔
979
        int r;
3,575✔
980

981
        assert(filename);
3,575✔
982
        assert(lvalue);
3,575✔
983
        assert(rvalue);
3,575✔
984

985
        if (isempty(rvalue)) {
3,575✔
986
                network->required_for_online = -1;
×
987
                network->required_operstate_for_online = LINK_OPERSTATE_RANGE_INVALID;
×
UNCOV
988
                return 0;
×
989
        }
990

991
        r = parse_operational_state_range(rvalue, &network->required_operstate_for_online);
3,575✔
992
        if (r < 0) {
3,575✔
993
                r = parse_boolean(rvalue);
3,574✔
994
                if (r < 0) {
3,574✔
UNCOV
995
                        log_syntax(unit, LOG_WARNING, filename, line, r,
×
996
                                   "Failed to parse %s= setting, ignoring assignment: %s",
997
                                   lvalue, rvalue);
UNCOV
998
                        return 0;
×
999
                }
1000

1001
                network->required_for_online = r;
3,574✔
1002
                network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
3,574✔
1003
                return 0;
3,574✔
1004
        }
1005

1006
        network->required_for_online = true;
1✔
1007
        return 0;
1✔
1008
}
1009

UNCOV
1010
int config_parse_link_group(
×
1011
                const char *unit,
1012
                const char *filename,
1013
                unsigned line,
1014
                const char *section,
1015
                unsigned section_line,
1016
                const char *lvalue,
1017
                int ltype,
1018
                const char *rvalue,
1019
                void *data,
1020
                void *userdata) {
1021

1022
        Network *network = ASSERT_PTR(userdata);
×
1023
        int r;
×
UNCOV
1024
        int32_t group;
×
1025

1026
        assert(filename);
×
1027
        assert(lvalue);
×
UNCOV
1028
        assert(rvalue);
×
1029

1030
        if (isempty(rvalue)) {
×
1031
                network->group = -1;
×
UNCOV
1032
                return 0;
×
1033
        }
1034

1035
        r = safe_atoi32(rvalue, &group);
×
1036
        if (r < 0) {
×
UNCOV
1037
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
1038
                           "Failed to parse Group=, ignoring assignment: %s", rvalue);
UNCOV
1039
                return 0;
×
1040
        }
1041

1042
        if (group < 0) {
×
UNCOV
1043
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
1044
                           "Value of Group= must be in the range 0…2147483647, ignoring assignment: %s", rvalue);
UNCOV
1045
                return 0;
×
1046
        }
1047

1048
        network->group = group;
×
UNCOV
1049
        return 0;
×
1050
}
1051

1052
int config_parse_ignore_carrier_loss(
3✔
1053
                const char *unit,
1054
                const char *filename,
1055
                unsigned line,
1056
                const char *section,
1057
                unsigned section_line,
1058
                const char *lvalue,
1059
                int ltype,
1060
                const char *rvalue,
1061
                void *data,
1062
                void *userdata) {
1063

1064
        Network *network = ASSERT_PTR(userdata);
3✔
1065
        usec_t usec;
3✔
1066
        int r;
3✔
1067

1068
        assert(filename);
3✔
1069
        assert(lvalue);
3✔
1070
        assert(rvalue);
3✔
1071

1072
        if (isempty(rvalue)) {
3✔
1073
                network->ignore_carrier_loss_set = false;
×
UNCOV
1074
                return 0;
×
1075
        }
1076

1077
        r = parse_boolean(rvalue);
3✔
1078
        if (r >= 0) {
3✔
1079
                network->ignore_carrier_loss_set = true;
3✔
1080
                network->ignore_carrier_loss_usec = r > 0 ? USEC_INFINITY : 0;
3✔
1081
                return 0;
3✔
1082
        }
1083

1084
        r = parse_sec(rvalue, &usec);
×
1085
        if (r < 0) {
×
UNCOV
1086
                log_syntax(unit, LOG_WARNING, filename, line, r,
×
1087
                           "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
UNCOV
1088
                return 0;
×
1089
        }
1090

1091
        network->ignore_carrier_loss_set = true;
×
1092
        network->ignore_carrier_loss_usec = usec;
×
UNCOV
1093
        return 0;
×
1094
}
1095

1096
int config_parse_keep_configuration(
10✔
1097
                const char *unit,
1098
                const char *filename,
1099
                unsigned line,
1100
                const char *section,
1101
                unsigned section_line,
1102
                const char *lvalue,
1103
                int ltype,
1104
                const char *rvalue,
1105
                void *data,
1106
                void *userdata) {
1107

1108
        KeepConfiguration t, *k = ASSERT_PTR(data);
10✔
1109
        Network *network = ASSERT_PTR(userdata);
10✔
1110

1111
        if (isempty(rvalue)) {
10✔
1112
                *k = ASSERT_PTR(network->manager)->keep_configuration;
×
UNCOV
1113
                return 0;
×
1114
        }
1115

1116
        /* backward compatibility */
1117
        if (streq(rvalue, "dhcp")) {
10✔
1118
                *k = KEEP_CONFIGURATION_DYNAMIC;
×
UNCOV
1119
                return 0;
×
1120
        }
1121

1122
        if (streq(rvalue, "dhcp-on-stop")) {
10✔
1123
                *k = KEEP_CONFIGURATION_DYNAMIC_ON_STOP;
×
UNCOV
1124
                return 0;
×
1125
        }
1126

1127
        t = keep_configuration_from_string(rvalue);
10✔
1128
        if (t < 0)
10✔
UNCOV
1129
                return log_syntax_parse_error(unit, filename, line, t, lvalue, rvalue);
×
1130

1131
        *k = t;
10✔
1132
        return 0;
10✔
1133
}
1134

1135
DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online, link_required_address_family, AddressFamily);
1✔
1136

1137
static const char* const keep_configuration_table[_KEEP_CONFIGURATION_MAX] = {
1138
        [KEEP_CONFIGURATION_NO]              = "no",
1139
        [KEEP_CONFIGURATION_DYNAMIC_ON_STOP] = "dynamic-on-stop",
1140
        [KEEP_CONFIGURATION_DYNAMIC]         = "dynamic",
1141
        [KEEP_CONFIGURATION_STATIC]          = "static",
1142
        [KEEP_CONFIGURATION_YES]             = "yes",
1143
};
1144

1145
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
10✔
1146

1147
static const char* const activation_policy_table[_ACTIVATION_POLICY_MAX] = {
1148
        [ACTIVATION_POLICY_UP]          = "up",
1149
        [ACTIVATION_POLICY_ALWAYS_UP]   = "always-up",
1150
        [ACTIVATION_POLICY_MANUAL]      = "manual",
1151
        [ACTIVATION_POLICY_ALWAYS_DOWN] = "always-down",
1152
        [ACTIVATION_POLICY_DOWN]        = "down",
1153
        [ACTIVATION_POLICY_BOUND]       = "bound",
1154
};
1155

1156
DEFINE_STRING_TABLE_LOOKUP(activation_policy, ActivationPolicy);
5,482✔
1157
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