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

systemd / systemd / 20684862027

03 Jan 2026 10:26PM UTC coverage: 72.702% (+0.03%) from 72.677%
20684862027

push

github

web-flow
core/dynamic-user: two trivial modernizations (#40264)

2 of 4 new or added lines in 1 file covered. (50.0%)

215 existing lines in 37 files now uncovered.

310139 of 426587 relevant lines covered (72.7%)

1143601.25 hits per line

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

83.45
/src/resolve/resolved-link.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <linux/if.h>
4
#include <unistd.h>
5

6
#include "sd-netlink.h"
7
#include "sd-network.h"
8

9
#include "alloc-util.h"
10
#include "dns-domain.h"
11
#include "dns-packet.h"
12
#include "dns-rr.h"
13
#include "env-file.h"
14
#include "extract-word.h"
15
#include "fd-util.h"
16
#include "fileio.h"
17
#include "fs-util.h"
18
#include "log-link.h"
19
#include "mkdir.h"
20
#include "netif-util.h"
21
#include "parse-util.h"
22
#include "resolved-dns-browse-services.h"
23
#include "resolved-dns-scope.h"
24
#include "resolved-dns-search-domain.h"
25
#include "resolved-dns-server.h"
26
#include "resolved-link.h"
27
#include "resolved-llmnr.h"
28
#include "resolved-manager.h"
29
#include "resolved-mdns.h"
30
#include "set.h"
31
#include "socket-netlink.h"
32
#include "stat-util.h"
33
#include "string-util.h"
34
#include "strv.h"
35
#include "tmpfile-util.h"
36

37
int link_new(Manager *m, Link **ret, int ifindex) {
1,342✔
38
        _cleanup_(link_freep) Link *l = NULL;
1,342✔
39
        int r;
1,342✔
40

41
        assert(m);
1,342✔
42
        assert(ifindex > 0);
1,342✔
43

44
        l = new(Link, 1);
1,342✔
45
        if (!l)
1,342✔
46
                return -ENOMEM;
47

48
        *l = (Link) {
1,342✔
49
                .ifindex = ifindex,
50
                .default_route = -1,
51
                .llmnr_support = RESOLVE_SUPPORT_YES,
52
                .mdns_support = RESOLVE_SUPPORT_YES,
53
                .dnssec_mode = _DNSSEC_MODE_INVALID,
54
                .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
55
                .operstate = IF_OPER_UNKNOWN,
56
        };
57

58
        if (asprintf(&l->state_file, "/run/systemd/resolve/netif/%i", ifindex) < 0)
1,342✔
59
                return -ENOMEM;
60

61
        r = hashmap_ensure_put(&m->links, NULL, INT_TO_PTR(ifindex), l);
1,342✔
62
        if (r < 0)
1,342✔
63
                return r;
64

65
        l->manager = m;
1,342✔
66

67
        if (ret)
1,342✔
68
                *ret = l;
1,342✔
69
        TAKE_PTR(l);
1,342✔
70

71
        return 0;
1,342✔
72
}
73

74
void link_flush_settings(Link *l) {
1,416✔
75
        assert(l);
1,416✔
76

77
        l->default_route = -1;
1,416✔
78
        l->llmnr_support = RESOLVE_SUPPORT_YES;
1,416✔
79
        l->mdns_support = RESOLVE_SUPPORT_YES;
1,416✔
80
        l->dnssec_mode = _DNSSEC_MODE_INVALID;
1,416✔
81
        l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
1,416✔
82

83
        dns_server_unlink_all(l->dns_servers);
1,416✔
84
        dns_search_domain_unlink_all(l->search_domains);
1,416✔
85

86
        l->dnssec_negative_trust_anchors = set_free(l->dnssec_negative_trust_anchors);
1,416✔
87
}
1,416✔
88

89
Link *link_free(Link *l) {
1,334✔
90
        if (!l)
1,334✔
91
                return NULL;
92

93
        /* Send goodbye messages. */
94
        dns_scope_announce(l->mdns_ipv4_scope, true);
1,334✔
95
        dns_scope_announce(l->mdns_ipv6_scope, true);
1,334✔
96

97
        link_flush_settings(l);
1,334✔
98

99
        while (l->addresses)
1,759✔
100
                (void) link_address_free(l->addresses);
425✔
101

102
        if (l->manager)
1,334✔
103
                hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
1,334✔
104

105
        dns_scope_free(l->unicast_scope);
1,334✔
106
        dns_scope_free(l->llmnr_ipv4_scope);
1,334✔
107
        dns_scope_free(l->llmnr_ipv6_scope);
1,334✔
108
        dns_scope_free(l->mdns_ipv4_scope);
1,334✔
109
        dns_scope_free(l->mdns_ipv6_scope);
1,334✔
110

111
        free(l->state_file);
1,334✔
112
        free(l->ifname);
1,334✔
113

114
        return mfree(l);
1,334✔
115
}
116

117
void link_allocate_scopes(Link *l) {
63,511✔
118
        bool unicast_relevant;
63,511✔
119
        int r;
63,511✔
120

121
        assert(l);
63,511✔
122

123
        /* If a link that used to be relevant is no longer, or a link that did not use to be relevant now becomes
124
         * relevant, let's reinit the learnt global DNS server information, since we might talk to different servers
125
         * now, even if they have the same addresses as before. */
126

127
        unicast_relevant = link_relevant(l, AF_UNSPEC, false);
63,511✔
128
        if (unicast_relevant != l->unicast_relevant) {
63,511✔
129
                l->unicast_relevant = unicast_relevant;
994✔
130

131
                dns_server_reset_features_all(l->manager->fallback_dns_servers);
994✔
132
                dns_server_reset_features_all(l->manager->dns_servers);
994✔
133

134
                /* Also, flush the global unicast scope, to deal with split horizon setups, where talking through one
135
                 * interface reveals different DNS zones than through others. */
136
                if (l->manager->unicast_scope)
994✔
137
                        dns_cache_flush(&l->manager->unicast_scope->cache);
989✔
138
        }
139

140
        /* And now, allocate all scopes that makes sense now if we didn't have them yet, and drop those which we don't
141
         * need anymore */
142

143
        if (unicast_relevant && l->dns_servers) {
63,511✔
144
                if (!l->unicast_scope) {
493✔
145
                        dns_server_reset_features_all(l->dns_servers);
138✔
146

147
                        r = dns_scope_new(l->manager, &l->unicast_scope, DNS_SCOPE_LINK, l, /* delegate= */ NULL, DNS_PROTOCOL_DNS, AF_UNSPEC);
138✔
148
                        if (r < 0)
138✔
149
                                log_link_warning_errno(l, r, "Failed to allocate DNS scope, ignoring: %m");
×
150
                }
151
        } else
152
                l->unicast_scope = dns_scope_free(l->unicast_scope);
63,018✔
153

154
        if (link_relevant(l, AF_INET, true) &&
65,646✔
155
            link_get_llmnr_support(l) != RESOLVE_SUPPORT_NO) {
2,135✔
156
                if (!l->llmnr_ipv4_scope) {
2,134✔
157
                        r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, DNS_SCOPE_LINK, l, /* delegate= */ NULL, DNS_PROTOCOL_LLMNR, AF_INET);
189✔
158
                        if (r < 0)
189✔
159
                                log_link_warning_errno(l, r, "Failed to allocate LLMNR IPv4 scope, ignoring: %m");
×
160
                }
161
        } else
162
                l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
61,377✔
163

164
        if (link_relevant(l, AF_INET6, true) &&
66,832✔
165
            link_get_llmnr_support(l) != RESOLVE_SUPPORT_NO) {
3,321✔
166
                if (!l->llmnr_ipv6_scope) {
3,320✔
167
                        r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, DNS_SCOPE_LINK, l, /* delegate= */ NULL, DNS_PROTOCOL_LLMNR, AF_INET6);
303✔
168
                        if (r < 0)
303✔
169
                                log_link_warning_errno(l, r, "Failed to allocate LLMNR IPv6 scope, ignoring: %m");
×
170
                }
171
        } else
172
                l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
60,191✔
173

174
        if (link_relevant(l, AF_INET, true) &&
65,646✔
175
            link_get_mdns_support(l) != RESOLVE_SUPPORT_NO) {
2,135✔
176
                if (!l->mdns_ipv4_scope) {
197✔
177
                        r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, DNS_SCOPE_LINK, l, /* delegate= */ NULL, DNS_PROTOCOL_MDNS, AF_INET);
30✔
178
                        if (r < 0)
30✔
179
                                log_link_warning_errno(l, r, "Failed to allocate mDNS IPv4 scope, ignoring: %m");
×
180
                        dns_browse_services_restart(l->manager);
30✔
181
                }
182
        } else
183
                l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
63,314✔
184

185
        if (link_relevant(l, AF_INET6, true) &&
66,832✔
186
            link_get_mdns_support(l) != RESOLVE_SUPPORT_NO) {
3,321✔
187
                if (!l->mdns_ipv6_scope) {
167✔
188
                        r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, DNS_SCOPE_LINK, l, /* delegate= */ NULL, DNS_PROTOCOL_MDNS, AF_INET6);
34✔
189
                        if (r < 0)
34✔
190
                                log_link_warning_errno(l, r, "Failed to allocate mDNS IPv6 scope, ignoring: %m");
×
191
                        dns_browse_services_restart(l->manager);
34✔
192
                }
193
        } else
194
                l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
63,344✔
195
}
63,511✔
196

197
void link_add_rrs(Link *l, bool force_remove) {
63,739✔
198
        int r;
63,739✔
199

200
        LIST_FOREACH(addresses, a, l->addresses)
252,721✔
201
                link_address_add_rrs(a, force_remove);
188,982✔
202

203
        if (!force_remove &&
127,355✔
204
            link_get_mdns_support(l) == RESOLVE_SUPPORT_YES) {
63,616✔
205

206
                if (l->mdns_ipv4_scope) {
48,694✔
207
                        r = dns_scope_add_dnssd_registered_services(l->mdns_ipv4_scope);
198✔
208
                        if (r < 0)
198✔
209
                                log_link_warning_errno(l, r, "Failed to add IPv4 DNS-SD services, ignoring: %m");
×
210
                }
211

212
                if (l->mdns_ipv6_scope) {
48,694✔
213
                        r = dns_scope_add_dnssd_registered_services(l->mdns_ipv6_scope);
168✔
214
                        if (r < 0)
168✔
215
                                log_link_warning_errno(l, r, "Failed to add IPv6 DNS-SD services, ignoring: %m");
×
216
                }
217

218
        } else {
219

220
                if (l->mdns_ipv4_scope) {
15,045✔
221
                        r = dns_scope_remove_dnssd_registered_services(l->mdns_ipv4_scope);
2✔
222
                        if (r < 0)
2✔
223
                                log_link_warning_errno(l, r, "Failed to remove IPv4 DNS-SD services, ignoring: %m");
×
224
                }
225

226
                if (l->mdns_ipv6_scope) {
15,045✔
227
                        r = dns_scope_remove_dnssd_registered_services(l->mdns_ipv6_scope);
2✔
228
                        if (r < 0)
2✔
229
                                log_link_warning_errno(l, r, "Failed to remove IPv6 DNS-SD services, ignoring: %m");
×
230
                }
231
        }
232
}
63,739✔
233

234
int link_process_rtnl(Link *l, sd_netlink_message *m) {
4,301✔
235
        const char *n = NULL;
4,301✔
236
        int r;
4,301✔
237

238
        assert(l);
4,301✔
239
        assert(m);
4,301✔
240

241
        r = sd_rtnl_message_link_get_flags(m, &l->flags);
4,301✔
242
        if (r < 0)
4,301✔
243
                return r;
4,301✔
244

245
        (void) sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
4,301✔
246
        (void) sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &l->operstate);
4,301✔
247

248
        if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0 &&
4,301✔
249
            !streq_ptr(l->ifname, n)) {
4,300✔
250
                if (l->ifname)
1,375✔
251
                        log_link_debug(l, "Interface name change detected: %s -> %s", l->ifname, n);
47✔
252

253
                r = free_and_strdup(&l->ifname, n);
1,375✔
254
                if (r < 0)
1,375✔
255
                        return r;
×
256
        }
257

258
        return 0;
259
}
260

261
static int link_update_dns_server_one(Link *l, const char *str) {
432✔
262
        _cleanup_free_ char *name = NULL;
432✔
263
        int family, ifindex, r;
432✔
264
        union in_addr_union a;
432✔
265
        DnsServer *s;
432✔
266
        uint16_t port;
432✔
267

268
        assert(l);
432✔
269
        assert(str);
432✔
270

271
        r = in_addr_port_ifindex_name_from_string_auto(str, &family, &a, &port, &ifindex, &name);
432✔
272
        if (r < 0)
432✔
273
                return r;
274

275
        if (ifindex != 0 && ifindex != l->ifindex)
432✔
276
                return -EINVAL;
277

278
        /* By default, the port number is determined with the transaction feature level.
279
         * See dns_transaction_port() and dns_server_port(). */
280
        if (IN_SET(port, 53, 853))
432✔
281
                port = 0;
×
282

283
        s = dns_server_find(l->dns_servers, family, &a, port, 0, name);
432✔
284
        if (s) {
432✔
285
                dns_server_move_back_and_unmark(s);
268✔
286
                return 0;
287
        }
288

289
        return dns_server_new(l->manager, /* ret= */ NULL, DNS_SERVER_LINK, l, /* delegate= */ NULL, family, &a, port, 0, name, RESOLVE_CONFIG_SOURCE_NETWORKD);
164✔
290
}
291

292
static int link_update_dns_servers(Link *l) {
3,518✔
293
        _cleanup_strv_free_ char **nameservers = NULL;
3,518✔
294
        int r;
3,518✔
295

296
        assert(l);
3,518✔
297

298
        r = sd_network_link_get_dns(l->ifindex, &nameservers);
3,518✔
299
        if (r == -ENODATA) {
3,518✔
300
                r = 0;
3,282✔
301
                goto clear;
3,282✔
302
        }
303
        if (r < 0)
236✔
UNCOV
304
                goto clear;
×
305

306
        dns_server_mark_all(l->dns_servers);
236✔
307

308
        STRV_FOREACH(nameserver, nameservers) {
668✔
309
                r = link_update_dns_server_one(l, *nameserver);
432✔
310
                if (r < 0)
432✔
311
                        goto clear;
×
312
        }
313

314
        dns_server_unlink_marked(l->dns_servers);
236✔
315

316
        dns_server_reset_accessible_all(l->dns_servers);
236✔
317

318
        return 0;
319

320
clear:
3,282✔
321
        dns_server_unlink_all(l->dns_servers);
3,282✔
322
        return r;
323
}
324

325
static int link_update_default_route(Link *l) {
3,518✔
326
        int r;
3,518✔
327

328
        assert(l);
3,518✔
329

330
        r = sd_network_link_get_dns_default_route(l->ifindex);
3,518✔
331
        if (r == -ENODATA) {
3,518✔
332
                r = 0;
3,506✔
333
                goto clear;
3,506✔
334
        }
335
        if (r < 0)
12✔
336
                goto clear;
2✔
337

338
        link_set_default_route(l, r > 0);
10✔
339
        return 0;
10✔
340

341
clear:
3,508✔
342
        l->default_route = -1;
3,508✔
343
        return r;
3,508✔
344
}
345

346
static int link_update_llmnr_support(Link *l) {
3,518✔
347
        _cleanup_free_ char *b = NULL;
3,518✔
348
        int r;
3,518✔
349

350
        assert(l);
3,518✔
351

352
        l->llmnr_support = RESOLVE_SUPPORT_YES; /* yes, yes, we set it twice which is ugly */
3,518✔
353

354
        r = sd_network_link_get_llmnr(l->ifindex, &b);
3,518✔
355
        if (r == -ENODATA)
3,518✔
356
                return 0;
357
        if (r < 0)
3,518✔
358
                return r;
359

360
        r = resolve_support_from_string(b);
3,518✔
361
        if (r < 0)
3,518✔
362
                return r;
363

364
        l->llmnr_support = r;
3,518✔
365
        return 0;
3,518✔
366
}
367

368
static int link_update_mdns_support(Link *l) {
3,518✔
369
        _cleanup_free_ char *b = NULL;
3,518✔
370
        int r;
3,518✔
371

372
        assert(l);
3,518✔
373

374
        l->mdns_support = RESOLVE_SUPPORT_YES;
3,518✔
375

376
        r = sd_network_link_get_mdns(l->ifindex, &b);
3,518✔
377
        if (r == -ENODATA)
3,518✔
378
                return 0;
379
        if (r < 0)
3,518✔
380
                return r;
381

382
        r = resolve_support_from_string(b);
3,518✔
383
        if (r < 0)
3,518✔
384
                return r;
385

386
        l->mdns_support = r;
3,518✔
387
        return 0;
3,518✔
388
}
389

390
void link_set_dns_over_tls_mode(Link *l, DnsOverTlsMode mode) {
×
391

392
        assert(l);
×
393

394
#if ! ENABLE_DNS_OVER_TLS
395
        if (mode != DNS_OVER_TLS_NO)
396
                log_link_warning(l,
397
                                 "DNS-over-TLS option for the link cannot be enabled or set to opportunistic "
398
                                 "when systemd-resolved is built without DNS-over-TLS support. "
399
                                 "Turning off DNS-over-TLS support.");
400
        return;
401
#endif
402

403
        l->dns_over_tls_mode = mode;
×
404
        l->unicast_scope = dns_scope_free(l->unicast_scope);
×
405
}
×
406

407
static int link_update_dns_over_tls_mode(Link *l) {
3,518✔
408
        _cleanup_free_ char *b = NULL;
3,518✔
409
        int r;
3,518✔
410

411
        assert(l);
3,518✔
412

413
        l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
3,518✔
414

415
        r = sd_network_link_get_dns_over_tls(l->ifindex, &b);
3,518✔
416
        if (r == -ENODATA)
3,518✔
417
                return 0;
418
        if (r < 0)
3✔
419
                return r;
420

421
        r = dns_over_tls_mode_from_string(b);
3✔
422
        if (r < 0)
3✔
423
                return r;
424

425
        l->dns_over_tls_mode = r;
3✔
426
        return 0;
3✔
427
}
428

429
void link_set_dnssec_mode(Link *l, DnssecMode mode) {
61✔
430

431
        assert(l);
61✔
432

433
#if !HAVE_OPENSSL
434
        if (IN_SET(mode, DNSSEC_YES, DNSSEC_ALLOW_DOWNGRADE))
435
                log_link_warning(l,
436
                                 "DNSSEC option for the link cannot be enabled or set to allow-downgrade "
437
                                 "when systemd-resolved is built without openssl. "
438
                                 "Turning off DNSSEC support.");
439
        return;
440
#endif
441

442
        if (l->dnssec_mode == mode)
61✔
443
                return;
444

445
        l->dnssec_mode = mode;
61✔
446
        l->unicast_scope = dns_scope_free(l->unicast_scope);
61✔
447
}
448

449
static int link_update_dnssec_mode(Link *l) {
3,518✔
450
        _cleanup_free_ char *m = NULL;
3,518✔
451
        DnssecMode mode;
3,518✔
452
        int r;
3,518✔
453

454
        assert(l);
3,518✔
455

456
        l->dnssec_mode = _DNSSEC_MODE_INVALID;
3,518✔
457

458
        r = sd_network_link_get_dnssec(l->ifindex, &m);
3,518✔
459
        if (r == -ENODATA)
3,518✔
460
                return 0;
461
        if (r < 0)
61✔
462
                return r;
463

464
        mode = dnssec_mode_from_string(m);
61✔
465
        if (mode < 0)
61✔
466
                return mode;
467

468
        link_set_dnssec_mode(l, mode);
61✔
469
        return 0;
470
}
471

472
static int link_update_dnssec_negative_trust_anchors(Link *l) {
3,518✔
473
        _cleanup_strv_free_ char **ntas = NULL;
3,518✔
474
        _cleanup_set_free_ Set *ns = NULL;
3,518✔
475
        int r;
3,518✔
476

477
        assert(l);
3,518✔
478

479
        l->dnssec_negative_trust_anchors = set_free(l->dnssec_negative_trust_anchors);
3,518✔
480

481
        r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas);
3,518✔
482
        if (r == -ENODATA)
3,518✔
483
                return 0;
484
        if (r < 0)
2✔
485
                return r;
486

487
        r = set_put_strdupv_full(&ns, &dns_name_hash_ops_free, ntas);
1✔
488
        if (r < 0)
1✔
489
                return r;
490

491
        l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
1✔
492
        return 0;
1✔
493
}
494

495
static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
85✔
496
        DnsSearchDomain *d;
85✔
497
        int r;
85✔
498

499
        assert(l);
85✔
500
        assert(name);
85✔
501

502
        r = dns_search_domain_find(l->search_domains, name, &d);
85✔
503
        if (r < 0)
85✔
504
                return r;
85✔
505
        if (r > 0)
85✔
506
                dns_search_domain_move_back_and_unmark(d);
53✔
507
        else {
508
                r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, /* delegate= */ NULL, name);
32✔
509
                if (r < 0)
32✔
510
                        return r;
511
        }
512

513
        d->route_only = route_only;
85✔
514
        return 0;
85✔
515
}
516

517
static int link_update_search_domains(Link *l) {
3,518✔
518
        _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL;
3,518✔
519
        int r, q;
3,518✔
520

521
        assert(l);
3,518✔
522

523
        r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
3,518✔
524
        if (r < 0 && r != -ENODATA)
3,518✔
525
                goto clear;
1✔
526

527
        q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
3,517✔
528
        if (q < 0 && q != -ENODATA) {
3,517✔
529
                r = q;
1✔
530
                goto clear;
1✔
531
        }
532

533
        if (r == -ENODATA && q == -ENODATA) {
3,516✔
534
                /* networkd knows nothing about this interface, and that's fine. */
535
                r = 0;
3,462✔
536
                goto clear;
3,462✔
537
        }
538

539
        dns_search_domain_mark_all(l->search_domains);
54✔
540

541
        STRV_FOREACH(i, sdomains) {
119✔
542
                r = link_update_search_domain_one(l, *i, false);
65✔
543
                if (r < 0)
65✔
544
                        goto clear;
×
545
        }
546

547
        STRV_FOREACH(i, rdomains) {
74✔
548
                r = link_update_search_domain_one(l, *i, true);
20✔
549
                if (r < 0)
20✔
550
                        goto clear;
×
551
        }
552

553
        dns_search_domain_unlink_marked(l->search_domains);
54✔
554
        return 0;
555

556
clear:
3,464✔
557
        dns_search_domain_unlink_all(l->search_domains);
3,464✔
558
        return r;
559
}
560

561
static int link_is_managed(Link *l) {
8,323✔
562
        _cleanup_free_ char *state = NULL;
8,323✔
563
        int r;
8,323✔
564

565
        assert(l);
8,323✔
566

567
        r = sd_network_link_get_setup_state(l->ifindex, &state);
8,323✔
568
        if (r == -ENODATA)
8,323✔
569
                return 0;
570
        if (r < 0)
8,323✔
571
                return r;
572

573
        return !STR_IN_SET(state, "pending", "initialized", "unmanaged");
8,323✔
574
}
575

576
static void link_enter_unmanaged(Link *l) {
11,342✔
577
        assert(l);
11,342✔
578

579
        /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */
580
        if (l->is_managed)
11,342✔
581
                link_flush_settings(l);
81✔
582

583
        l->is_managed = false;
11,342✔
584
}
11,342✔
585

586
static void link_read_settings(Link *l) {
59,960✔
587
        struct stat st;
59,960✔
588
        int r;
59,960✔
589

590
        assert(l);
59,960✔
591

592
        /* Read settings from networkd, except when networkd is not managing this interface. */
593

594
        r = sd_network_link_get_stat(l->ifindex, &st);
59,960✔
595
        if (r == -ENOENT)
59,960✔
596
                return link_enter_unmanaged(l);
56,442✔
597
        if (r < 0)
53,423✔
598
                return (void) log_link_warning_errno(l, r, "Failed to stat() networkd's link state file, ignoring: %m");
×
599

600
        if (stat_inode_unmodified(&l->networkd_state_file_stat, &st))
53,423✔
601
                /* The state file is unmodified. Not necessary to re-read settings. */
602
                return;
603

604
        /* Save the new stat for the next event. */
605
        l->networkd_state_file_stat = st;
8,323✔
606

607
        r = link_is_managed(l);
8,323✔
608
        if (r < 0)
8,323✔
609
                return (void) log_link_warning_errno(l, r, "Failed to determine whether the interface is managed, ignoring: %m");
×
610
        if (r == 0)
8,323✔
611
                return link_enter_unmanaged(l);
4,805✔
612

613
        l->is_managed = true;
3,518✔
614

615
        r = network_link_get_operational_state(l->ifindex, &l->networkd_operstate);
3,518✔
616
        if (r < 0)
3,518✔
UNCOV
617
                log_link_warning_errno(l, r, "Failed to read networkd's link operational state, ignoring: %m");
×
618

619
        r = link_update_dns_servers(l);
3,518✔
620
        if (r < 0)
3,518✔
UNCOV
621
                log_link_warning_errno(l, r, "Failed to read DNS servers for the interface, ignoring: %m");
×
622

623
        r = link_update_llmnr_support(l);
3,518✔
624
        if (r < 0)
3,518✔
UNCOV
625
                log_link_warning_errno(l, r, "Failed to read LLMNR support for the interface, ignoring: %m");
×
626

627
        r = link_update_mdns_support(l);
3,518✔
628
        if (r < 0)
3,518✔
UNCOV
629
                log_link_warning_errno(l, r, "Failed to read mDNS support for the interface, ignoring: %m");
×
630

631
        r = link_update_dns_over_tls_mode(l);
3,518✔
632
        if (r < 0)
3,518✔
UNCOV
633
                log_link_warning_errno(l, r, "Failed to read DNS-over-TLS mode for the interface, ignoring: %m");
×
634

635
        r = link_update_dnssec_mode(l);
3,518✔
636
        if (r < 0)
3,518✔
UNCOV
637
                log_link_warning_errno(l, r, "Failed to read DNSSEC mode for the interface, ignoring: %m");
×
638

639
        r = link_update_dnssec_negative_trust_anchors(l);
3,518✔
640
        if (r < 0)
3,518✔
641
                log_link_warning_errno(l, r, "Failed to read DNSSEC negative trust anchors for the interface, ignoring: %m");
1✔
642

643
        r = link_update_search_domains(l);
3,518✔
644
        if (r < 0)
3,518✔
645
                log_link_warning_errno(l, r, "Failed to read search domains for the interface, ignoring: %m");
2✔
646

647
        r = link_update_default_route(l);
3,518✔
648
        if (r < 0)
3,518✔
649
                log_link_warning_errno(l, r, "Failed to read default route setting for the interface, proceeding anyway: %m");
2✔
650
}
651

652
int link_update(Link *l) {
59,960✔
653
        int r;
59,960✔
654

655
        assert(l);
59,960✔
656

657
        link_read_settings(l);
59,960✔
658
        r = link_load_user(l);
59,960✔
659
        if (r < 0)
59,960✔
660
                return r;
661

662
        if (link_get_llmnr_support(l) != RESOLVE_SUPPORT_NO) {
59,960✔
663
                r = manager_llmnr_start(l->manager);
59,912✔
664
                if (r < 0)
59,912✔
665
                        return r;
666
        }
667

668
        if (link_get_mdns_support(l) != RESOLVE_SUPPORT_NO) {
59,960✔
669
                r = manager_mdns_start(l->manager);
47,990✔
670
                if (r < 0)
47,990✔
671
                        return r;
672
        }
673

674
        link_allocate_scopes(l);
59,960✔
675
        link_add_rrs(l, false);
59,960✔
676

677
        return 0;
59,960✔
678
}
679

680
static bool link_has_link_local_dns(Link *l, int family) {
28,400✔
681

682
        /* Check if the link has a link-local dns server for the specified family */
683

684
        LIST_FOREACH(servers, s, l->dns_servers)
29,269✔
685
                if ((family == AF_UNSPEC || s->family == family) &&
2,024✔
686
                    in_addr_is_link_local(s->family, &s->address))
1,012✔
687
                        return true;
688

689
        return false;
690
}
691

692
bool link_relevant(Link *l, int family, bool local_multicast) {
376,464✔
693
        bool allow_link_local;
376,464✔
694

695
        assert(l);
376,464✔
696

697
        /*
698
         * A link is relevant if:
699
         * - it isn't a loopback device
700
         * - has a link beat
701
         * - for multicast traffic:
702
         *   - can do multicast
703
         *   - has at least one link-local (or better) IP address.
704
         * - for non-multicast traffic:
705
         *   - has at least one address that must be:
706
         *     - At least link-local, if using a link-local dns server to this interface.
707
         *     - Better than link-local.
708
         */
709

710
        if ((l->flags & (IFF_LOOPBACK | IFF_DORMANT)) != 0)
376,464✔
711
                return false;
712

713
        if (!FLAGS_SET(l->flags, IFF_UP | IFF_LOWER_UP))
322,768✔
714
                return false;
715

716
        if (local_multicast &&
92,138✔
717
            !FLAGS_SET(l->flags, IFF_MULTICAST))
56,624✔
718
                return false;
719

720
        if (!netif_has_carrier(l->operstate, l->flags))
60,704✔
721
                return false;
722

723
        if (l->is_managed &&
59,833✔
724
            !IN_SET(l->networkd_operstate, LINK_OPERSTATE_DEGRADED_CARRIER, LINK_OPERSTATE_DEGRADED, LINK_OPERSTATE_ROUTABLE))
57,379✔
725
                return false;
726

727
        allow_link_local = local_multicast || link_has_link_local_dns(l, family);
43,298✔
728

729
        LIST_FOREACH(addresses, a, l->addresses)
68,633✔
730
                if ((family == AF_UNSPEC || a->family == family) &&
106,054✔
731
                    link_address_relevant(a, allow_link_local))
47,057✔
732
                        return true;
733

734
        return false;
735
}
736

737
LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
17,855✔
738
        assert(l);
17,855✔
739

740
        if (!IN_SET(family, AF_INET, AF_INET6))
17,855✔
741
                return NULL;
742

743
        if (!in_addr)
17,855✔
744
                return NULL;
745

746
        LIST_FOREACH(addresses, a, l->addresses)
150,222✔
747
                if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
137,693✔
748
                        return a;
749

750
        return NULL;
751
}
752

753
DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
367✔
754
        assert(l);
367✔
755

756
        if (l->current_dns_server == s)
367✔
757
                return s;
758

759
        if (s)
86✔
760
                log_link_debug(l, "Switching to DNS server %s.", strna(dns_server_string_full(s)));
63✔
761

762
        dns_server_unref(l->current_dns_server);
86✔
763
        l->current_dns_server = dns_server_ref(s);
86✔
764

765
        /* Skip flushing the cache if server stale feature is enabled. */
766
        if (l->unicast_scope && l->manager->stale_retention_usec == 0)
86✔
767
                dns_cache_flush(&l->unicast_scope->cache);
62✔
768

769
        return s;
770
}
771

772
DnsServer *link_get_dns_server(Link *l) {
1,317✔
773
        assert(l);
1,317✔
774

775
        if (!l->current_dns_server)
1,317✔
776
                link_set_dns_server(l, l->dns_servers);
305✔
777

778
        return l->current_dns_server;
1,317✔
779
}
780

781
void link_next_dns_server(Link *l, DnsServer *if_current) {
70✔
782
        assert(l);
70✔
783

784
        /* If the current server of the transaction is specified, and we already are at a different one,
785
         * don't do anything */
786
        if (if_current && l->current_dns_server != if_current)
70✔
787
                return;
788

789
        /* If currently have no DNS server, then don't do anything, we'll pick it lazily the next time a DNS
790
         * server is needed. */
791
        if (!l->current_dns_server)
39✔
792
                return;
793

794
        /* Change to the next one, but make sure to follow the linked list only if this server is actually
795
         * still linked. */
796
        if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
39✔
797
                link_set_dns_server(l, l->current_dns_server->servers_next);
22✔
798
                return;
22✔
799
        }
800

801
        /* Pick the first one again, after we reached the end */
802
        link_set_dns_server(l, l->dns_servers);
17✔
803
}
804

805
void link_set_default_route(Link *l, bool b) {
12✔
806
        assert(l);
12✔
807

808
        if (l->default_route == b)
12✔
809
                return;
810

811
        l->default_route = b;
4✔
812

813
        /* If we are currently using the fallback servers, changing a link to be default-route means
814
         * we should reconsider whether or not the fallback servers are necessary. */
815
        if (b && dns_server_is_fallback(l->manager->current_dns_server))
4✔
816
                manager_set_dns_server(l->manager, NULL);
×
817
}
818

819
DnsOverTlsMode link_get_dns_over_tls_mode(Link *l) {
1,093✔
820
        assert(l);
1,093✔
821

822
        if (l->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID)
1,093✔
823
                return l->dns_over_tls_mode;
824

825
        return manager_get_dns_over_tls_mode(l->manager);
1,080✔
826
}
827

828
DnssecMode link_get_dnssec_mode(Link *l) {
1,774✔
829
        assert(l);
1,774✔
830

831
        if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
1,774✔
832
                return l->dnssec_mode;
833

834
        return manager_get_dnssec_mode(l->manager);
740✔
835
}
836

837
bool link_dnssec_supported(Link *l) {
100✔
838
        DnsServer *server;
100✔
839

840
        assert(l);
100✔
841

842
        if (link_get_dnssec_mode(l) == DNSSEC_NO)
100✔
843
                return false;
844

845
        server = link_get_dns_server(l);
9✔
846
        if (server)
9✔
847
                return dns_server_dnssec_supported(server);
9✔
848

849
        return true;
850
}
851

852
ResolveSupport link_get_llmnr_support(Link *link) {
87,754✔
853
        assert(link);
87,754✔
854
        assert(link->manager);
87,754✔
855

856
        /* This provides the effective LLMNR support level for the link, instead of the 'internal' per-link setting. */
857

858
        return MIN(link->llmnr_support, link->manager->llmnr_support);
87,754✔
859
}
860

861
ResolveSupport link_get_mdns_support(Link *link) {
147,108✔
862
        assert(link);
147,108✔
863
        assert(link->manager);
147,108✔
864

865
        /* This provides the effective mDNS support level for the link, instead of the 'internal' per-link setting. */
866

867
        return MIN(link->mdns_support, link->manager->mdns_support);
147,108✔
868
}
869

870
bool link_get_default_route(Link *l) {
396✔
871
        assert(l);
396✔
872

873
        /* Return what is configured, if there's something configured */
874
        if (l->default_route >= 0)
396✔
875
                return l->default_route;
12✔
876

877
        /* Otherwise report what is in effect */
878
        if (l->unicast_scope)
384✔
879
                return dns_scope_is_default_route(l->unicast_scope);
45✔
880

881
        return false;
882
}
883

884
int link_address_new(Link *l,
2,447✔
885
                LinkAddress **ret,
886
                int family,
887
                const union in_addr_union *in_addr,
888
                const union in_addr_union *in_addr_broadcast) {
889
        LinkAddress *a;
2,447✔
890

891
        assert(l);
2,447✔
892
        assert(in_addr);
2,447✔
893

894
        a = new(LinkAddress, 1);
2,447✔
895
        if (!a)
2,447✔
896
                return -ENOMEM;
897

898
        *a = (LinkAddress) {
2,447✔
899
                .family = family,
900
                .in_addr = *in_addr,
2,447✔
901
                .in_addr_broadcast = *in_addr_broadcast,
2,447✔
902
                .link = l,
903
                .prefixlen = UCHAR_MAX,
904
        };
905

906
        LIST_PREPEND(addresses, l->addresses, a);
2,447✔
907
        l->n_addresses++;
2,447✔
908

909
        if (ret)
2,447✔
910
                *ret = a;
2,447✔
911

912
        return 0;
913
}
914

915
LinkAddress *link_address_free(LinkAddress *a) {
2,489✔
916
        if (!a)
2,489✔
917
                return NULL;
918

919
        if (a->link) {
2,447✔
920
                LIST_REMOVE(addresses, a->link->addresses, a);
2,447✔
921

922
                assert(a->link->n_addresses > 0);
2,447✔
923
                a->link->n_addresses--;
2,447✔
924

925
                if (a->llmnr_address_rr) {
2,447✔
926
                        if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
40✔
927
                                dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
14✔
928
                        else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
26✔
929
                                dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
26✔
930
                }
931

932
                if (a->llmnr_ptr_rr) {
2,447✔
933
                        if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
40✔
934
                                dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
14✔
935
                        else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
26✔
936
                                dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
26✔
937
                }
938

939
                if (a->mdns_address_rr) {
2,447✔
940
                        if (a->family == AF_INET && a->link->mdns_ipv4_scope)
4✔
941
                                dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
3✔
942
                        else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
1✔
943
                                dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
1✔
944
                }
945

946
                if (a->mdns_ptr_rr) {
2,447✔
947
                        if (a->family == AF_INET && a->link->mdns_ipv4_scope)
4✔
948
                                dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
3✔
949
                        else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
1✔
950
                                dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
1✔
951
                }
952
        }
953

954
        dns_resource_record_unref(a->llmnr_address_rr);
2,447✔
955
        dns_resource_record_unref(a->llmnr_ptr_rr);
2,447✔
956
        dns_resource_record_unref(a->mdns_address_rr);
2,447✔
957
        dns_resource_record_unref(a->mdns_ptr_rr);
2,447✔
958

959
        return mfree(a);
2,447✔
960
}
961

962
void link_address_add_rrs(LinkAddress *a, bool force_remove) {
188,982✔
963
        int r;
188,982✔
964

965
        assert(a);
188,982✔
966

967
        if (a->family == AF_INET) {
188,982✔
968

969
                if (!force_remove &&
299,442✔
970
                    link_address_relevant(a, true) &&
149,702✔
971
                    a->link->llmnr_ipv4_scope &&
142,272✔
972
                    link_get_llmnr_support(a->link) == RESOLVE_SUPPORT_YES) {
2,379✔
973

974
                        if (!a->link->manager->llmnr_host_ipv4_key) {
2,379✔
975
                                a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
31✔
976
                                if (!a->link->manager->llmnr_host_ipv4_key) {
31✔
977
                                        r = -ENOMEM;
×
978
                                        goto fail;
×
979
                                }
980
                        }
981

982
                        if (!a->llmnr_address_rr) {
2,379✔
983
                                a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
238✔
984
                                if (!a->llmnr_address_rr) {
238✔
985
                                        r = -ENOMEM;
×
986
                                        goto fail;
×
987
                                }
988

989
                                a->llmnr_address_rr->a.in_addr = a->in_addr.in;
238✔
990
                                a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
238✔
991
                        }
992

993
                        if (!a->llmnr_ptr_rr) {
2,379✔
994
                                r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
238✔
995
                                if (r < 0)
238✔
996
                                        goto fail;
×
997

998
                                a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
238✔
999
                        }
1000

1001
                        r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
2,379✔
1002
                        if (r < 0)
2,379✔
1003
                                log_link_warning_errno(a->link, r, "Failed to add A record to LLMNR zone, ignoring: %m");
×
1004

1005
                        r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
2,379✔
1006
                        if (r < 0)
2,379✔
1007
                                log_link_warning_errno(a->link, r, "Failed to add IPv4 PTR record to LLMNR zone, ignoring: %m");
×
1008
                } else {
1009
                        if (a->llmnr_address_rr) {
147,361✔
1010
                                if (a->link->llmnr_ipv4_scope)
224✔
1011
                                        dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
18✔
1012
                                a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
224✔
1013
                        }
1014

1015
                        if (a->llmnr_ptr_rr) {
147,361✔
1016
                                if (a->link->llmnr_ipv4_scope)
224✔
1017
                                        dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
18✔
1018
                                a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
224✔
1019
                        }
1020
                }
1021

1022
                if (!force_remove &&
299,442✔
1023
                    link_address_relevant(a, true) &&
149,702✔
1024
                    a->link->mdns_ipv4_scope &&
140,098✔
1025
                    link_get_mdns_support(a->link) == RESOLVE_SUPPORT_YES) {
205✔
1026
                        if (!a->link->manager->mdns_host_ipv4_key) {
205✔
1027
                                a->link->manager->mdns_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->mdns_hostname);
9✔
1028
                                if (!a->link->manager->mdns_host_ipv4_key) {
9✔
1029
                                        r = -ENOMEM;
×
1030
                                        goto fail;
×
1031
                                }
1032
                        }
1033

1034
                        if (!a->mdns_address_rr) {
205✔
1035
                                a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv4_key);
32✔
1036
                                if (!a->mdns_address_rr) {
32✔
1037
                                        r = -ENOMEM;
×
1038
                                        goto fail;
×
1039
                                }
1040

1041
                                a->mdns_address_rr->a.in_addr = a->in_addr.in;
32✔
1042
                                a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
32✔
1043
                        }
1044

1045
                        if (!a->mdns_ptr_rr) {
205✔
1046
                                r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
32✔
1047
                                if (r < 0)
32✔
1048
                                        goto fail;
×
1049

1050
                                a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
32✔
1051
                        }
1052

1053
                        r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_address_rr, true);
205✔
1054
                        if (r < 0)
205✔
1055
                                log_link_warning_errno(a->link, r, "Failed to add A record to MDNS zone, ignoring: %m");
×
1056

1057
                        r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_ptr_rr, false);
205✔
1058
                        if (r < 0)
205✔
1059
                                log_link_warning_errno(a->link, r, "Failed to add IPv4 PTR record to MDNS zone, ignoring: %m");
×
1060
                } else {
1061
                        if (a->mdns_address_rr) {
149,535✔
1062
                                if (a->link->mdns_ipv4_scope)
29✔
1063
                                        dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
2✔
1064
                                a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
29✔
1065
                        }
1066

1067
                        if (a->mdns_ptr_rr) {
149,535✔
1068
                                if (a->link->mdns_ipv4_scope)
29✔
1069
                                        dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
2✔
1070
                                a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
29✔
1071
                        }
1072
                }
1073
        }
1074

1075
        if (a->family == AF_INET6) {
188,982✔
1076

1077
                if (!force_remove &&
78,388✔
1078
                    link_address_relevant(a, true) &&
39,146✔
1079
                    a->link->llmnr_ipv6_scope &&
33,257✔
1080
                    link_get_llmnr_support(a->link) == RESOLVE_SUPPORT_YES) {
5,794✔
1081

1082
                        if (!a->link->manager->llmnr_host_ipv6_key) {
5,794✔
1083
                                a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
34✔
1084
                                if (!a->link->manager->llmnr_host_ipv6_key) {
34✔
1085
                                        r = -ENOMEM;
×
1086
                                        goto fail;
×
1087
                                }
1088
                        }
1089

1090
                        if (!a->llmnr_address_rr) {
5,794✔
1091
                                a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
530✔
1092
                                if (!a->llmnr_address_rr) {
530✔
1093
                                        r = -ENOMEM;
×
1094
                                        goto fail;
×
1095
                                }
1096

1097
                                a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
530✔
1098
                                a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
530✔
1099
                        }
1100

1101
                        if (!a->llmnr_ptr_rr) {
5,794✔
1102
                                r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
530✔
1103
                                if (r < 0)
530✔
1104
                                        goto fail;
×
1105

1106
                                a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
530✔
1107
                        }
1108

1109
                        r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
5,794✔
1110
                        if (r < 0)
5,794✔
1111
                                log_link_warning_errno(a->link, r, "Failed to add AAAA record to LLMNR zone, ignoring: %m");
×
1112

1113
                        r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
5,794✔
1114
                        if (r < 0)
5,794✔
1115
                                log_link_warning_errno(a->link, r, "Failed to add IPv6 PTR record to LLMNR zone, ignoring: %m");
×
1116
                } else {
1117
                        if (a->llmnr_address_rr) {
33,448✔
1118
                                if (a->link->llmnr_ipv6_scope)
504✔
1119
                                        dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
50✔
1120
                                a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
504✔
1121
                        }
1122

1123
                        if (a->llmnr_ptr_rr) {
33,448✔
1124
                                if (a->link->llmnr_ipv6_scope)
504✔
1125
                                        dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
50✔
1126
                                a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
504✔
1127
                        }
1128
                }
1129

1130
                if (!force_remove &&
78,388✔
1131
                    link_address_relevant(a, true) &&
39,146✔
1132
                    a->link->mdns_ipv6_scope &&
27,690✔
1133
                    link_get_mdns_support(a->link) == RESOLVE_SUPPORT_YES) {
227✔
1134

1135
                        if (!a->link->manager->mdns_host_ipv6_key) {
227✔
1136
                                a->link->manager->mdns_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->mdns_hostname);
10✔
1137
                                if (!a->link->manager->mdns_host_ipv6_key) {
10✔
1138
                                        r = -ENOMEM;
×
1139
                                        goto fail;
×
1140
                                }
1141
                        }
1142

1143
                        if (!a->mdns_address_rr) {
227✔
1144
                                a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv6_key);
49✔
1145
                                if (!a->mdns_address_rr) {
49✔
1146
                                        r = -ENOMEM;
×
1147
                                        goto fail;
×
1148
                                }
1149

1150
                                a->mdns_address_rr->aaaa.in6_addr = a->in_addr.in6;
49✔
1151
                                a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
49✔
1152
                        }
1153

1154
                        if (!a->mdns_ptr_rr) {
227✔
1155
                                r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
49✔
1156
                                if (r < 0)
49✔
1157
                                        goto fail;
×
1158

1159
                                a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
49✔
1160
                        }
1161

1162
                        r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_address_rr, true);
227✔
1163
                        if (r < 0)
227✔
1164
                                log_link_warning_errno(a->link, r, "Failed to add AAAA record to MDNS zone, ignoring: %m");
×
1165

1166
                        r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_ptr_rr, false);
227✔
1167
                        if (r < 0)
227✔
1168
                                log_link_warning_errno(a->link, r, "Failed to add IPv6 PTR record to MDNS zone, ignoring: %m");
×
1169
                } else {
1170
                        if (a->mdns_address_rr) {
39,015✔
1171
                                if (a->link->mdns_ipv6_scope)
48✔
1172
                                        dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
3✔
1173
                                a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
48✔
1174
                        }
1175

1176
                        if (a->mdns_ptr_rr) {
39,015✔
1177
                                if (a->link->mdns_ipv6_scope)
48✔
1178
                                        dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
3✔
1179
                                a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
48✔
1180
                        }
1181
                }
1182
        }
1183

1184
        return;
1185

1186
fail:
1187
        log_link_debug_errno(a->link, r, "Failed to update address RRs, ignoring: %m");
×
1188
}
1189

1190
int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
3,516✔
1191
        int r;
3,516✔
1192

1193
        assert(a);
3,516✔
1194
        assert(m);
3,516✔
1195

1196
        r = sd_netlink_message_read_u32(m, IFA_FLAGS, &a->flags);
3,516✔
1197
        if (r < 0)
3,516✔
1198
                return r;
1199

1200
        (void) sd_rtnl_message_addr_get_prefixlen(m, &a->prefixlen);
3,516✔
1201
        (void) sd_rtnl_message_addr_get_scope(m, &a->scope);
3,516✔
1202

1203
        link_allocate_scopes(a->link);
3,516✔
1204
        link_add_rrs(a->link, false);
3,516✔
1205

1206
        return 0;
3,516✔
1207
}
1208

1209
bool link_address_relevant(LinkAddress *a, bool allow_link_local) {
424,753✔
1210
        assert(a);
424,753✔
1211

1212
        if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
424,753✔
1213
                return false;
1214

1215
        if (a->scope >= (allow_link_local ? RT_SCOPE_HOST : RT_SCOPE_LINK))
448,914✔
1216
                return false;
46,630✔
1217

1218
        return true;
1219
}
1220

1221
static bool link_needs_save(Link *l) {
39✔
1222
        assert(l);
39✔
1223

1224
        /* Returns true if any of the settings where set different from the default */
1225

1226
        if (l->is_managed)
39✔
1227
                return false;
1228

1229
        if (l->llmnr_support != RESOLVE_SUPPORT_YES ||
39✔
1230
            l->mdns_support != RESOLVE_SUPPORT_YES ||
28✔
1231
            l->dnssec_mode != _DNSSEC_MODE_INVALID ||
25✔
1232
            l->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID)
25✔
1233
                return true;
1234

1235
        if (l->dns_servers ||
25✔
1236
            l->search_domains)
3✔
1237
                return true;
1238

1239
        if (!set_isempty(l->dnssec_negative_trust_anchors))
3✔
1240
                return true;
1241

1242
        if (l->default_route >= 0)
3✔
1243
                return true;
×
1244

1245
        return false;
1246
}
1247

1248
int link_save_user(Link *l) {
39✔
1249
        _cleanup_(unlink_and_freep) char *temp_path = NULL;
×
1250
        _cleanup_fclose_ FILE *f = NULL;
39✔
1251
        const char *v;
39✔
1252
        int r;
39✔
1253

1254
        assert(l);
39✔
1255
        assert(l->state_file);
39✔
1256

1257
        if (!link_needs_save(l)) {
39✔
1258
                (void) unlink(l->state_file);
3✔
1259
                return 0;
3✔
1260
        }
1261

1262
        r = mkdir_parents(l->state_file, 0700);
36✔
1263
        if (r < 0)
36✔
1264
                goto fail;
×
1265

1266
        r = fopen_temporary(l->state_file, &f, &temp_path);
36✔
1267
        if (r < 0)
36✔
1268
                goto fail;
×
1269

1270
        (void) fchmod(fileno(f), 0644);
36✔
1271

1272
        fputs("# This is private data. Do not parse.\n", f);
36✔
1273

1274
        v = resolve_support_to_string(l->llmnr_support);
36✔
1275
        if (v)
36✔
1276
                fprintf(f, "LLMNR=%s\n", v);
36✔
1277

1278
        v = resolve_support_to_string(l->mdns_support);
36✔
1279
        if (v)
36✔
1280
                fprintf(f, "MDNS=%s\n", v);
36✔
1281

1282
        v = dnssec_mode_to_string(l->dnssec_mode);
36✔
1283
        if (v)
36✔
1284
                fprintf(f, "DNSSEC=%s\n", v);
×
1285

1286
        v = dns_over_tls_mode_to_string(l->dns_over_tls_mode);
36✔
1287
        if (v)
36✔
1288
                fprintf(f, "DNSOVERTLS=%s\n", v);
×
1289

1290
        if (l->default_route >= 0)
36✔
1291
                fprintf(f, "DEFAULT_ROUTE=%s\n", yes_no(l->default_route));
11✔
1292

1293
        if (l->dns_servers) {
36✔
1294
                fputs("SERVERS=", f);
22✔
1295
                LIST_FOREACH(servers, server, l->dns_servers) {
60✔
1296

1297
                        if (server != l->dns_servers)
38✔
1298
                                fputc(' ', f);
16✔
1299

1300
                        v = dns_server_string_full(server);
38✔
1301
                        if (!v) {
38✔
1302
                                r = -ENOMEM;
×
1303
                                goto fail;
×
1304
                        }
1305

1306
                        fputs(v, f);
38✔
1307
                }
1308
                fputc('\n', f);
22✔
1309
        }
1310

1311
        if (l->search_domains) {
36✔
1312
                fputs("DOMAINS=", f);
11✔
1313
                LIST_FOREACH(domains, domain, l->search_domains) {
30✔
1314

1315
                        if (domain != l->search_domains)
19✔
1316
                                fputc(' ', f);
8✔
1317

1318
                        if (domain->route_only)
19✔
1319
                                fputc('~', f);
5✔
1320

1321
                        fputs(DNS_SEARCH_DOMAIN_NAME(domain), f);
19✔
1322
                }
1323
                fputc('\n', f);
11✔
1324
        }
1325

1326
        if (!set_isempty(l->dnssec_negative_trust_anchors)) {
36✔
1327
                bool space = false;
×
1328
                char *nta;
×
1329

1330
                fputs("NTAS=", f);
×
1331
                SET_FOREACH(nta, l->dnssec_negative_trust_anchors) {
×
1332

1333
                        if (space)
×
1334
                                fputc(' ', f);
×
1335

1336
                        fputs(nta, f);
×
1337
                        space = true;
1338
                }
1339
                fputc('\n', f);
×
1340
        }
1341

1342
        r = fflush_and_check(f);
36✔
1343
        if (r < 0)
36✔
1344
                goto fail;
×
1345

1346
        if (rename(temp_path, l->state_file) < 0) {
36✔
1347
                r = -errno;
×
1348
                goto fail;
×
1349
        }
1350

1351
        temp_path = mfree(temp_path);
36✔
1352

1353
        return 0;
36✔
1354

1355
fail:
×
1356
        (void) unlink(l->state_file);
×
1357

1358
        return log_link_error_errno(l, r, "Failed to save link data %s: %m", l->state_file);
×
1359
}
1360

1361
int link_load_user(Link *l) {
59,960✔
1362
        _cleanup_free_ char
59,960✔
1363
                *llmnr = NULL,
119,920✔
1364
                *mdns = NULL,
×
1365
                *dnssec = NULL,
×
1366
                *dns_over_tls = NULL,
×
1367
                *servers = NULL,
×
1368
                *domains = NULL,
×
1369
                *ntas = NULL,
×
1370
                *default_route = NULL;
59,960✔
1371

1372
        ResolveSupport s;
59,960✔
1373
        const char *p;
59,960✔
1374
        int r;
59,960✔
1375

1376
        assert(l);
59,960✔
1377
        assert(l->state_file);
59,960✔
1378

1379
        /* Try to load only a single time */
1380
        if (l->loaded)
59,960✔
1381
                return 0;
1382
        l->loaded = true;
1,328✔
1383

1384
        if (l->is_managed)
1,328✔
1385
                return 0; /* if the device is managed, then networkd is our configuration source, not the bus API */
1386

1387
        r = parse_env_file(NULL, l->state_file,
1,313✔
1388
                           "LLMNR", &llmnr,
1389
                           "MDNS", &mdns,
1390
                           "DNSSEC", &dnssec,
1391
                           "DNSOVERTLS", &dns_over_tls,
1392
                           "SERVERS", &servers,
1393
                           "DOMAINS", &domains,
1394
                           "NTAS", &ntas,
1395
                           "DEFAULT_ROUTE", &default_route);
1396
        if (r == -ENOENT)
1,313✔
1397
                return 0;
1398
        if (r < 0)
×
1399
                goto fail;
×
1400

1401
        link_flush_settings(l);
×
1402

1403
        /* If we can't recognize the LLMNR or MDNS setting we don't override the default */
1404
        s = resolve_support_from_string(llmnr);
×
1405
        if (s >= 0)
×
1406
                l->llmnr_support = s;
×
1407

1408
        s = resolve_support_from_string(mdns);
×
1409
        if (s >= 0)
×
1410
                l->mdns_support = s;
×
1411

1412
        r = parse_boolean(default_route);
×
1413
        if (r >= 0)
×
1414
                l->default_route = r;
×
1415

1416
        /* If we can't recognize the DNSSEC setting, then set it to invalid, so that the daemon default is used. */
1417
        l->dnssec_mode = dnssec_mode_from_string(dnssec);
×
1418

1419
        /* Same for DNSOverTLS */
1420
        l->dns_over_tls_mode = dns_over_tls_mode_from_string(dns_over_tls);
×
1421

1422
        for (p = servers;;) {
×
1423
                _cleanup_free_ char *word = NULL;
×
1424

1425
                r = extract_first_word(&p, &word, NULL, 0);
×
1426
                if (r < 0)
×
1427
                        goto fail;
×
1428
                if (r == 0)
×
1429
                        break;
1430

1431
                r = link_update_dns_server_one(l, word);
×
1432
                if (r < 0) {
×
1433
                        log_link_debug_errno(l, r, "Failed to load DNS server '%s', ignoring: %m", word);
×
1434
                        continue;
×
1435
                }
1436
        }
1437

1438
        for (p = domains;;) {
×
1439
                _cleanup_free_ char *word = NULL;
×
1440
                const char *n;
×
1441
                bool is_route;
×
1442

1443
                r = extract_first_word(&p, &word, NULL, 0);
×
1444
                if (r < 0)
×
1445
                        goto fail;
×
1446
                if (r == 0)
×
1447
                        break;
1448

1449
                is_route = word[0] == '~';
×
1450
                n = is_route ? word + 1 : word;
×
1451

1452
                r = link_update_search_domain_one(l, n, is_route);
×
1453
                if (r < 0) {
×
1454
                        log_link_debug_errno(l, r, "Failed to load search domain '%s', ignoring: %m", word);
×
1455
                        continue;
×
1456
                }
1457
        }
1458

1459
        if (ntas) {
×
1460
                _cleanup_set_free_ Set *ns = NULL;
×
1461

1462
                ns = set_new(&dns_name_hash_ops_free);
×
1463
                if (!ns) {
×
1464
                        r = -ENOMEM;
×
1465
                        goto fail;
×
1466
                }
1467

1468
                r = set_put_strsplit(ns, ntas, NULL, 0);
×
1469
                if (r < 0)
×
1470
                        goto fail;
×
1471

1472
                l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
×
1473
        }
1474

1475
        return 0;
1476

1477
fail:
×
1478
        return log_link_error_errno(l, r, "Failed to load link data %s: %m", l->state_file);
×
1479
}
1480

1481
void link_remove_user(Link *l) {
896✔
1482
        assert(l);
896✔
1483
        assert(l->state_file);
896✔
1484

1485
        (void) unlink(l->state_file);
896✔
1486
}
896✔
1487

1488
bool link_negative_trust_anchor_lookup(Link *l, const char *name) {
400✔
1489
        int r;
400✔
1490

1491
        assert(l);
400✔
1492
        assert(name);
400✔
1493

1494
        /* Checks whether the specified domain (or any of its parent domains) are listed as per-link NTA. */
1495

1496
        for (;;) {
1,381✔
1497
                if (set_contains(l->dnssec_negative_trust_anchors, name))
1,381✔
1498
                        return true;
1499

1500
                /* And now, let's look at the parent, and check that too */
1501
                r = dns_name_parent(&name);
1,381✔
1502
                if (r < 0)
1,381✔
1503
                        return r;
1504
                if (r == 0)
1,381✔
1505
                        break;
1506
        }
1507

1508
        return false;
1509
}
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