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

systemd / systemd / 14766779411

30 Apr 2025 04:55PM UTC coverage: 72.225% (-0.06%) from 72.282%
14766779411

push

github

web-flow
wait-online: handle varlink connection errors while waiting for DNS (#37283)

Currently, if systemd-networkd-wait-online is started with --dns, and
systemd-resolved is not running, it will exit with an error right away.
Similarly, if systemd-resolved is restarted while waiting for DNS
configuration, systemd-networkd-wait-online will not attempt to
re-connect, and will potentially never see subsequent DNS
configurations.

Improve this by adding socket units for the systemd-resolved varlink
servers, and re-establish the connection in systemd-networkd-wait-online
when we receive `SD_VARLINK_ERROR_DISCONNECTED`.

8 of 16 new or added lines in 2 files covered. (50.0%)

5825 existing lines in 217 files now uncovered.

297168 of 411450 relevant lines covered (72.22%)

695892.62 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 <linux/netdevice.h>
4
#include <net/if.h>
5
#include <netinet/in.h>
6
#include <unistd.h>
7

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

46
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
5,377✔
47
                network_hash_ops,
48
                char, string_hash_func, string_compare_func,
49
                Network, network_unref);
50

51
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
132✔
52
                stacked_netdevs_hash_ops,
53
                char, string_hash_func, string_compare_func,
54
                NetDev, netdev_unref);
55

56
static int network_resolve_netdev_one(Network *network, const char *name, NetDevKind kind, NetDev **ret) {
21,733✔
57
        const char *kind_string;
21,733✔
58
        NetDev *netdev;
21,733✔
59
        int r;
21,733✔
60

61
        /* For test-networkd-conf, the check must be earlier than the assertions. */
62
        if (!name)
21,733✔
63
                return 0;
21,733✔
64

65
        assert(network);
174✔
66
        assert(network->manager);
174✔
67
        assert(network->filename);
174✔
68
        assert(ret);
174✔
69

70
        if (kind == _NETDEV_KIND_TUNNEL)
174✔
71
                kind_string = "tunnel";
72
        else {
73
                kind_string = netdev_kind_to_string(kind);
88✔
74
                if (!kind_string)
88✔
UNCOV
75
                        return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
×
76
                                                 "%s: Invalid NetDev kind of %s, ignoring assignment.",
77
                                                 network->filename, name);
78
        }
79

80
        r = netdev_get(network->manager, name, &netdev);
174✔
81
        if (r < 0)
174✔
82
                return log_warning_errno(r, "%s: %s NetDev could not be found, ignoring assignment.",
1✔
83
                                         network->filename, name);
84

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

101
        *ret = netdev_ref(netdev);
173✔
102
        return 1;
173✔
103
}
104

105
static int network_resolve_stacked_netdevs(Network *network) {
5,400✔
106
        void *name, *kind;
5,400✔
107
        int r;
5,400✔
108

109
        assert(network);
5,400✔
110

111
        HASHMAP_FOREACH_KEY(kind, name, network->stacked_netdev_names) {
5,533✔
UNCOV
112
                _cleanup_(netdev_unrefp) NetDev *netdev = NULL;
×
113

114
                if (network_resolve_netdev_one(network, name, PTR_TO_INT(kind), &netdev) <= 0)
133✔
115
                        continue;
1✔
116

117
                r = hashmap_ensure_put(&network->stacked_netdevs, &stacked_netdevs_hash_ops, netdev->ifname, netdev);
132✔
118
                if (r == -ENOMEM)
132✔
UNCOV
119
                        return log_oom();
×
120
                if (r < 0)
132✔
UNCOV
121
                        log_warning_errno(r, "%s: Failed to add NetDev '%s' to network, ignoring: %m",
×
122
                                          network->filename, (const char *) name);
123

124
                TAKE_PTR(netdev);
132✔
125
        }
126

127
        return 0;
5,400✔
128
}
129

130
int network_verify(Network *network) {
6,376✔
131
        int r;
6,376✔
132

133
        assert(network);
6,376✔
134
        assert(network->manager);
6,376✔
135
        assert(network->filename);
6,376✔
136

137
        if (net_match_is_empty(&network->match) && !network->conditions)
6,376✔
UNCOV
138
                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
×
139
                                         "%s: No valid settings found in the [Match] section, ignoring file. "
140
                                         "To match all interfaces, add Name=* in the [Match] section.",
141
                                         network->filename);
142

143
        /* skip out early if configuration does not match the environment */
144
        if (!condition_test_list(network->conditions, environ, NULL, NULL, NULL))
6,376✔
145
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
976✔
146
                                       "%s: Conditions in the file do not match the system environment, skipping.",
147
                                       network->filename);
148

149
        if (network->keep_master) {
5,400✔
150
                if (network->batadv_name)
556✔
UNCOV
151
                        log_warning("%s: BatmanAdvanced= set with KeepMaster= enabled, ignoring BatmanAdvanced=.",
×
152
                                    network->filename);
153
                if (network->bond_name)
556✔
UNCOV
154
                        log_warning("%s: Bond= set with KeepMaster= enabled, ignoring Bond=.",
×
155
                                    network->filename);
156
                if (network->bridge_name)
556✔
UNCOV
157
                        log_warning("%s: Bridge= set with KeepMaster= enabled, ignoring Bridge=.",
×
158
                                    network->filename);
159
                if (network->vrf_name)
556✔
UNCOV
160
                        log_warning("%s: VRF= set with KeepMaster= enabled, ignoring VRF=.",
×
161
                                    network->filename);
162

163
                network->batadv_name = mfree(network->batadv_name);
556✔
164
                network->bond_name = mfree(network->bond_name);
556✔
165
                network->bridge_name = mfree(network->bridge_name);
556✔
166
                network->vrf_name = mfree(network->vrf_name);
556✔
167
        }
168

169
        (void) network_resolve_netdev_one(network, network->batadv_name, NETDEV_KIND_BATADV, &network->batadv);
5,400✔
170
        (void) network_resolve_netdev_one(network, network->bond_name, NETDEV_KIND_BOND, &network->bond);
5,400✔
171
        (void) network_resolve_netdev_one(network, network->bridge_name, NETDEV_KIND_BRIDGE, &network->bridge);
5,400✔
172
        (void) network_resolve_netdev_one(network, network->vrf_name, NETDEV_KIND_VRF, &network->vrf);
5,400✔
173
        r = network_resolve_stacked_netdevs(network);
5,400✔
174
        if (r < 0)
5,400✔
175
                return r;
176

177
        /* Free unnecessary entries. */
178
        network->batadv_name = mfree(network->batadv_name);
5,400✔
179
        network->bond_name = mfree(network->bond_name);
5,400✔
180
        network->bridge_name = mfree(network->bridge_name);
5,400✔
181
        network->vrf_name = mfree(network->vrf_name);
5,400✔
182
        network->stacked_netdev_names = hashmap_free(network->stacked_netdev_names);
5,400✔
183

184
        if (network->bond) {
5,400✔
185
                /* Bonding slave does not support addressing. */
186
                if (network->link_local >= 0 && network->link_local != ADDRESS_FAMILY_NO) {
8✔
187
                        log_warning("%s: Cannot enable LinkLocalAddressing= when Bond= is specified, disabling LinkLocalAddressing=.",
1✔
188
                                    network->filename);
189
                        network->link_local = ADDRESS_FAMILY_NO;
1✔
190
                }
191
                if (!ordered_hashmap_isempty(network->addresses_by_section))
8✔
192
                        log_warning("%s: Cannot set addresses when Bond= is specified, ignoring addresses.",
1✔
193
                                    network->filename);
194
                if (!hashmap_isempty(network->routes_by_section))
8✔
195
                        log_warning("%s: Cannot set routes when Bond= is specified, ignoring routes.",
1✔
196
                                    network->filename);
197

198
                network->addresses_by_section = ordered_hashmap_free(network->addresses_by_section);
8✔
199
                network->routes_by_section = hashmap_free(network->routes_by_section);
8✔
200
        }
201

202
        if (network->link_local < 0) {
5,400✔
203
                network->link_local = ADDRESS_FAMILY_IPV6;
1,750✔
204

205
                if (network->keep_master || network->bridge)
1,750✔
206
                        network->link_local = ADDRESS_FAMILY_NO;
28✔
207
                else {
208
                        NetDev *netdev;
1,722✔
209

210
                        HASHMAP_FOREACH(netdev, network->stacked_netdevs) {
1,832✔
211
                                MacVlan *m;
126✔
212

213
                                if (netdev->kind == NETDEV_KIND_MACVLAN)
126✔
214
                                        m = MACVLAN(netdev);
8✔
215
                                else if (netdev->kind == NETDEV_KIND_MACVTAP)
118✔
216
                                        m = MACVTAP(netdev);
8✔
217
                                else
218
                                        continue;
110✔
219

220
                                if (m->mode == NETDEV_MACVLAN_MODE_PASSTHRU)
16✔
221
                                        network->link_local = ADDRESS_FAMILY_NO;
4✔
222

223
                                /* There won't be a passthru MACVLAN/MACVTAP if there's already one in another mode */
224
                                break;
225
                        }
226
                }
227
        }
228

229
        if (network->ipv6ll_address_gen_mode == IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE)
5,400✔
UNCOV
230
                SET_FLAG(network->link_local, ADDRESS_FAMILY_IPV6, false);
×
231

232
        if (in6_addr_is_set(&network->ipv6ll_stable_secret) &&
5,400✔
233
            network->ipv6ll_address_gen_mode < 0)
1✔
234
                network->ipv6ll_address_gen_mode = IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_STABLE_PRIVACY;
1✔
235

236
        network_adjust_ipv6_proxy_ndp(network);
5,400✔
237
        network_adjust_ndisc(network);
5,400✔
238
        network_adjust_dhcp(network);
5,400✔
239
        network_adjust_radv(network);
5,400✔
240
        network_adjust_bridge_vlan(network);
5,400✔
241

242
        if (network->mtu > 0 && network->dhcp_use_mtu) {
5,400✔
UNCOV
243
                log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
×
244
                            "Disabling UseMTU=.", network->filename);
UNCOV
245
                network->dhcp_use_mtu = false;
×
246
        }
247

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

260
        if (!strv_isempty(network->bind_carrier)) {
5,400✔
261
                if (!IN_SET(network->activation_policy, _ACTIVATION_POLICY_INVALID, ACTIVATION_POLICY_BOUND))
6✔
UNCOV
262
                        log_warning("%s: ActivationPolicy=bound is required with BindCarrier=. "
×
263
                                    "Setting ActivationPolicy=bound.", network->filename);
264
                network->activation_policy = ACTIVATION_POLICY_BOUND;
6✔
265
        } else if (network->activation_policy == ACTIVATION_POLICY_BOUND) {
5,394✔
UNCOV
266
                log_warning("%s: ActivationPolicy=bound requires BindCarrier=. "
×
267
                            "Ignoring ActivationPolicy=bound.", network->filename);
UNCOV
268
                network->activation_policy = ACTIVATION_POLICY_UP;
×
269
        }
270

271
        if (network->activation_policy == _ACTIVATION_POLICY_INVALID)
5,400✔
272
                network->activation_policy = ACTIVATION_POLICY_UP;
5,345✔
273

274
        if (network->activation_policy == ACTIVATION_POLICY_ALWAYS_UP) {
5,400✔
275
                if (network->ignore_carrier_loss_set && network->ignore_carrier_loss_usec < USEC_INFINITY)
5✔
UNCOV
276
                        log_warning("%s: IgnoreCarrierLoss=no or finite timespan conflicts with ActivationPolicy=always-up. "
×
277
                                    "Setting IgnoreCarrierLoss=yes.", network->filename);
278
                network->ignore_carrier_loss_set = true;
5✔
279
                network->ignore_carrier_loss_usec = USEC_INFINITY;
5✔
280
        }
281

282
        if (!network->ignore_carrier_loss_set) /* Set implied default. */
5,400✔
283
                network->ignore_carrier_loss_usec = network->configure_without_carrier ? USEC_INFINITY : 0;
10,780✔
284

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

297
        if (network->required_for_online < 0)
5,400✔
298
                network->required_for_online = true;
2,581✔
299

300
        if (network->keep_configuration < 0)
5,400✔
301
                network->keep_configuration = KEEP_CONFIGURATION_NO;
5,369✔
302

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

324
        return 0;
5,400✔
325
}
326

327
int network_load_one(Manager *manager, OrderedHashmap **networks, const char *filename) {
6,355✔
328
        _cleanup_free_ char *fname = NULL, *name = NULL;
6,355✔
329
        _cleanup_(network_unrefp) Network *network = NULL;
6,355✔
330
        const char *dropin_dirname;
6,355✔
331
        char *d;
6,355✔
332
        int r;
6,355✔
333

334
        assert(manager);
6,355✔
335
        assert(filename);
6,355✔
336

337
        r = null_or_empty_path(filename);
6,355✔
338
        if (r < 0)
6,355✔
UNCOV
339
                return log_warning_errno(r, "Failed to check if \"%s\" is empty: %m", filename);
×
340
        if (r > 0) {
6,355✔
341
                log_debug("Skipping empty file: %s", filename);
2✔
342
                return 0;
2✔
343
        }
344

345
        fname = strdup(filename);
6,353✔
346
        if (!fname)
6,353✔
UNCOV
347
                return log_oom();
×
348

349
        name = strdup(basename(filename));
6,353✔
350
        if (!name)
6,353✔
UNCOV
351
                return log_oom();
×
352

353
        d = strrchr(name, '.');
6,353✔
354
        if (!d)
6,353✔
UNCOV
355
                return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid file name: %s", filename);
×
356

357
        *d = '\0';
6,353✔
358

359
        dropin_dirname = strjoina(name, ".network.d");
31,765✔
360

361
        network = new(Network, 1);
6,353✔
362
        if (!network)
6,353✔
UNCOV
363
                return log_oom();
×
364

365
        *network = (Network) {
6,353✔
366
                .filename = TAKE_PTR(fname),
6,353✔
367
                .name = TAKE_PTR(name),
6,353✔
368

369
                .manager = manager,
370
                .n_ref = 1,
371

372
                .required_for_online = -1,
373
                .required_operstate_for_online = LINK_OPERSTATE_RANGE_INVALID,
374
                .activation_policy = _ACTIVATION_POLICY_INVALID,
375
                .group = -1,
376
                .arp = -1,
377
                .multicast = -1,
378
                .allmulticast = -1,
379
                .promiscuous = -1,
380

381
                .keep_configuration = manager->keep_configuration,
6,353✔
382

383
                .use_domains = _USE_DOMAINS_INVALID,
384

385
                .compat_dhcp_use_domains = _USE_DOMAINS_INVALID,
386
                .compat_dhcp_use_dns = -1,
387
                .compat_dhcp_use_ntp = -1,
388

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

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

428
                .dhcp_pd = -1,
429
                .dhcp_pd_announce = true,
430
                .dhcp_pd_assign = true,
431
                .dhcp_pd_manage_temporary_address = true,
432
                .dhcp_pd_subnet_id = -1,
433
                .dhcp_pd_route_metric = DHCP6PD_ROUTE_METRIC,
434

435
                .dhcp_server_bind_to_interface = true,
436
                .dhcp_server_emit[SD_DHCP_LEASE_DNS].emit = true,
437
                .dhcp_server_emit[SD_DHCP_LEASE_NTP].emit = true,
438
                .dhcp_server_emit[SD_DHCP_LEASE_SIP].emit = true,
439
                .dhcp_server_emit_router = true,
440
                .dhcp_server_emit_timezone = true,
441
                .dhcp_server_rapid_commit = true,
442
                .dhcp_server_persist_leases = -1,
443

444
                .router_lifetime_usec = RADV_DEFAULT_ROUTER_LIFETIME_USEC,
445
                .router_dns_lifetime_usec = RADV_DEFAULT_VALID_LIFETIME_USEC,
446
                .router_emit_dns = true,
447
                .router_emit_domains = true,
448

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

467
                .bridge_vlan_pvid = BRIDGE_VLAN_KEEP_PVID,
468

469
                .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
470
                .lldp_multicast_mode = _SD_LLDP_MULTICAST_MODE_INVALID,
471

472
                .dns_default_route = -1,
473
                .llmnr = RESOLVE_SUPPORT_YES,
474
                .mdns = RESOLVE_SUPPORT_NO,
475
                .dnssec_mode = _DNSSEC_MODE_INVALID,
476
                .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
477

478
                /* If LinkLocalAddressing= is not set, then set to ADDRESS_FAMILY_IPV6 later. */
479
                .link_local = _ADDRESS_FAMILY_INVALID,
480
                .ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
481

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

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

514
                .can_termination = -1,
515

516
                .ipoib_mode = _IP_OVER_INFINIBAND_MODE_INVALID,
517
                .ipoib_umcast = -1,
518
        };
519

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

588
        r = network_add_ipv4ll_route(network);
6,353✔
589
        if (r < 0)
6,353✔
UNCOV
590
                return log_warning_errno(r, "%s: Failed to add IPv4LL route: %m", network->filename);
×
591

592
        r = network_add_default_route_on_device(network);
6,353✔
593
        if (r < 0)
6,353✔
UNCOV
594
                return log_warning_errno(r, "%s: Failed to add default route on device: %m",
×
595
                                         network->filename);
596

597
        r = network_verify(network);
6,353✔
598
        if (r < 0)
6,353✔
599
                return r; /* network_verify() logs internally. */
600

601
        r = ordered_hashmap_ensure_put(networks, &network_hash_ops, network->name, network);
5,377✔
602
        if (r < 0)
5,377✔
UNCOV
603
                return log_warning_errno(r, "%s: Failed to store configuration into hashmap: %m", filename);
×
604

605
        TAKE_PTR(network);
5,377✔
606
        log_syntax(/* unit = */ NULL, LOG_DEBUG, filename, /* config_line = */ 0, /* error = */ 0, "Successfully loaded.");
5,377✔
607
        return 0;
608
}
609

610
int network_load(Manager *manager, OrderedHashmap **ret) {
554✔
611
        _cleanup_strv_free_ char **files = NULL;
554✔
612
        OrderedHashmap *networks = NULL;
554✔
613
        int r;
554✔
614

615
        assert(manager);
554✔
616
        assert(ret);
554✔
617

618
        r = conf_files_list_strv(&files, ".network", NULL, 0, NETWORK_DIRS);
554✔
619
        if (r < 0)
554✔
UNCOV
620
                return log_error_errno(r, "Failed to enumerate network files: %m");
×
621

622
        STRV_FOREACH(f, files)
6,909✔
623
                (void) network_load_one(manager, &networks, *f);
6,355✔
624

625
        *ret = TAKE_PTR(networks);
554✔
626
        return 0;
554✔
627
}
628

629
static bool network_netdev_equal(Network *a, Network *b) {
1,262✔
630
        assert(a);
1,262✔
631
        assert(b);
1,262✔
632

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

640
        if (hashmap_size(a->stacked_netdevs) != hashmap_size(b->stacked_netdevs))
1,262✔
641
                return false;
642

643
        NetDev *n;
1,262✔
644
        HASHMAP_FOREACH(n, a->stacked_netdevs)
1,263✔
645
                if (hashmap_get(b->stacked_netdevs, n->ifname) != n)
34✔
646
                        return false;
33✔
647

648
        return true;
1,229✔
649
}
650

651
int network_reload(Manager *manager) {
136✔
652
        _cleanup_ordered_hashmap_free_ OrderedHashmap *new_networks = NULL;
136✔
653
        Network *n, *old;
136✔
654
        int r;
136✔
655

656
        assert(manager);
136✔
657

658
        r = network_load(manager, &new_networks);
136✔
659
        if (r < 0)
136✔
660
                return r;
661

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

669
                if (!stats_by_path_equal(n->stats_by_path, old->stats_by_path)) {
1,342✔
670
                        log_debug("%s: Found updated .network file.", n->filename);
80✔
671
                        continue;
80✔
672
                }
673

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

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

684
                network_ref(old);
1,229✔
685
                network_unref(n);
1,229✔
686
        }
687

688
        ordered_hashmap_free_and_replace(manager->networks, new_networks);
136✔
689

690
        r = manager_build_dhcp_pd_subnet_ids(manager);
136✔
691
        if (r < 0)
136✔
692
                return r;
693

694
        r = manager_build_nexthop_ids(manager);
136✔
695
        if (r < 0)
136✔
UNCOV
696
                return r;
×
697

698
        return 0;
699
}
700

701
int manager_build_dhcp_pd_subnet_ids(Manager *manager) {
554✔
702
        Network *n;
554✔
703
        int r;
554✔
704

705
        assert(manager);
554✔
706

707
        set_clear(manager->dhcp_pd_subnet_ids);
554✔
708

709
        ORDERED_HASHMAP_FOREACH(n, manager->networks) {
5,931✔
710
                if (n->unmanaged)
5,377✔
711
                        continue;
341✔
712

713
                if (!n->dhcp_pd)
5,036✔
714
                        continue;
4,466✔
715

716
                if (n->dhcp_pd_subnet_id < 0)
570✔
717
                        continue;
556✔
718

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

724
        return 0;
554✔
725
}
726

727
static Network *network_free(Network *network) {
6,376✔
728
        if (!network)
6,376✔
729
                return NULL;
730

731
        free(network->name);
6,376✔
732
        free(network->filename);
6,376✔
733
        free(network->description);
6,376✔
734
        strv_free(network->dropins);
6,376✔
735
        hashmap_free(network->stats_by_path);
6,376✔
736

737
        /* conditions */
738
        net_match_clear(&network->match);
6,376✔
739
        condition_free_list(network->conditions);
6,376✔
740

741
        /* link settings */
742
        strv_free(network->bind_carrier);
6,376✔
743

744
        /* NTP */
745
        strv_free(network->ntp);
6,376✔
746

747
        /* DNS */
748
        for (unsigned i = 0; i < network->n_dns; i++)
6,385✔
749
                in_addr_full_free(network->dns[i]);
9✔
750
        free(network->dns);
6,376✔
751
        ordered_set_free(network->search_domains);
6,376✔
752
        ordered_set_free(network->route_domains);
6,376✔
753
        set_free(network->dnssec_negative_trust_anchors);
6,376✔
754

755
        /* DHCP server */
756
        free(network->dhcp_server_relay_agent_circuit_id);
6,376✔
757
        free(network->dhcp_server_relay_agent_remote_id);
6,376✔
758
        free(network->dhcp_server_boot_server_name);
6,376✔
759
        free(network->dhcp_server_boot_filename);
6,376✔
760
        free(network->dhcp_server_timezone);
6,376✔
761
        free(network->dhcp_server_uplink_name);
6,376✔
762
        for (sd_dhcp_lease_server_type_t t = 0; t < _SD_DHCP_LEASE_SERVER_TYPE_MAX; t++)
44,632✔
763
                free(network->dhcp_server_emit[t].addresses);
38,256✔
764
        ordered_hashmap_free(network->dhcp_server_send_options);
6,376✔
765
        ordered_hashmap_free(network->dhcp_server_send_vendor_options);
6,376✔
766

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

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

792
        /* DHCP PD */
793
        free(network->dhcp_pd_uplink_name);
6,376✔
794
        set_free(network->dhcp_pd_tokens);
6,376✔
795
        free(network->dhcp_pd_netlabel);
6,376✔
796
        nft_set_context_clear(&network->dhcp_pd_nft_set_context);
6,376✔
797

798
        /* Router advertisement */
799
        ordered_set_free(network->router_search_domains);
6,376✔
800
        free(network->router_dns);
6,376✔
801
        free(network->router_uplink_name);
6,376✔
802

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

814
        /* LLDP */
815
        free(network->lldp_mudurl);
6,376✔
816

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

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

846
        return mfree(network);
6,376✔
847
}
848

849
DEFINE_TRIVIAL_REF_UNREF_FUNC(Network, network, network_free);
14,228✔
850

851
int network_get_by_name(Manager *manager, const char *name, Network **ret) {
1,383✔
852
        Network *network;
1,383✔
853

854
        assert(manager);
1,383✔
855
        assert(name);
1,383✔
856
        assert(ret);
1,383✔
857

858
        network = ordered_hashmap_get(manager->networks, name);
1,383✔
859
        if (!network)
1,383✔
860
                return -ENOENT;
861

862
        *ret = network;
1,351✔
863

864
        return 0;
1,351✔
865
}
866

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

874
        assert(network);
94✔
875

876
        ORDERED_HASHMAP_FOREACH(address, network->addresses_by_section)
97✔
877
                if (address->family == AF_INET6)
24✔
878
                        return true;
21✔
879

880
        HASHMAP_FOREACH(route, network->routes_by_section)
73✔
UNCOV
881
                if (route->family == AF_INET6)
×
882
                        return true;
×
883

884
        HASHMAP_FOREACH(fdb, network->bridge_fdb_entries_by_section)
73✔
UNCOV
885
                if (fdb->family == AF_INET6)
×
886
                        return true;
×
887

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

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

896
        if (!hashmap_isempty(network->address_labels_by_section))
71✔
897
                return true;
898

899
        if (!hashmap_isempty(network->prefixes_by_section))
71✔
900
                return true;
901

902
        if (!hashmap_isempty(network->route_prefixes_by_section))
71✔
903
                return true;
904

905
        if (!hashmap_isempty(network->pref64_prefixes_by_section))
71✔
UNCOV
906
                return true;
×
907

908
        return false;
909
}
910

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

923
        _cleanup_free_ char *name = NULL;
133✔
924
        NetDevKind kind = ltype;
133✔
925
        Hashmap **h = ASSERT_PTR(data);
133✔
926
        int r;
133✔
927

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

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

949
        name = strdup(rvalue);
133✔
950
        if (!name)
133✔
UNCOV
951
                return log_oom();
×
952

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

965
        return 0;
966
}
967

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

980
        Network *network = ASSERT_PTR(userdata);
2,786✔
981
        int r;
2,786✔
982

983
        assert(filename);
2,786✔
984
        assert(lvalue);
2,786✔
985
        assert(rvalue);
2,786✔
986

987
        if (isempty(rvalue)) {
2,786✔
UNCOV
988
                network->required_for_online = -1;
×
989
                network->required_operstate_for_online = LINK_OPERSTATE_RANGE_INVALID;
×
990
                return 0;
×
991
        }
992

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

1003
                network->required_for_online = r;
2,785✔
1004
                network->required_operstate_for_online = LINK_OPERSTATE_RANGE_DEFAULT;
2,785✔
1005
                return 0;
2,785✔
1006
        }
1007

1008
        network->required_for_online = true;
1✔
1009
        return 0;
1✔
1010
}
1011

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

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

UNCOV
1028
        assert(filename);
×
1029
        assert(lvalue);
×
1030
        assert(rvalue);
×
1031

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

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

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

UNCOV
1050
        network->group = group;
×
1051
        return 0;
×
1052
}
1053

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

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

1070
        assert(filename);
3✔
1071
        assert(lvalue);
3✔
1072
        assert(rvalue);
3✔
1073

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

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

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

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

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

1110
        KeepConfiguration t, *k = ASSERT_PTR(data);
8✔
1111
        Network *network = ASSERT_PTR(userdata);
8✔
1112

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

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

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

1129
        t = keep_configuration_from_string(rvalue);
8✔
1130
        if (t < 0)
8✔
UNCOV
1131
                return log_syntax_parse_error(unit, filename, line, t, lvalue, rvalue);
×
1132

1133
        *k = t;
8✔
1134
        return 0;
8✔
1135
}
1136

1137
DEFINE_CONFIG_PARSE_ENUM(config_parse_required_family_for_online, link_required_address_family, AddressFamily);
1✔
1138

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

1147
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(keep_configuration, KeepConfiguration, KEEP_CONFIGURATION_YES);
8✔
1148

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

1158
DEFINE_STRING_TABLE_LOOKUP(activation_policy, ActivationPolicy);
4,891✔
1159
DEFINE_CONFIG_PARSE_ENUM(config_parse_activation_policy, activation_policy, ActivationPolicy);
29✔
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