Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <linux/if.h>
4 : : #include <unistd.h>
5 : :
6 : : #include "sd-network.h"
7 : :
8 : : #include "alloc-util.h"
9 : : #include "env-file.h"
10 : : #include "fd-util.h"
11 : : #include "fileio.h"
12 : : #include "log-link.h"
13 : : #include "mkdir.h"
14 : : #include "parse-util.h"
15 : : #include "resolved-link.h"
16 : : #include "resolved-llmnr.h"
17 : : #include "resolved-mdns.h"
18 : : #include "string-util.h"
19 : : #include "strv.h"
20 : : #include "tmpfile-util.h"
21 : :
22 : 0 : int link_new(Manager *m, Link **ret, int ifindex) {
23 : 0 : _cleanup_(link_freep) Link *l = NULL;
24 : : int r;
25 : :
26 [ # # ]: 0 : assert(m);
27 [ # # ]: 0 : assert(ifindex > 0);
28 : :
29 : 0 : r = hashmap_ensure_allocated(&m->links, NULL);
30 [ # # ]: 0 : if (r < 0)
31 : 0 : return r;
32 : :
33 : 0 : l = new(Link, 1);
34 [ # # ]: 0 : if (!l)
35 : 0 : return -ENOMEM;
36 : :
37 : 0 : *l = (Link) {
38 : : .ifindex = ifindex,
39 : : .default_route = -1,
40 : : .llmnr_support = RESOLVE_SUPPORT_YES,
41 : : .mdns_support = RESOLVE_SUPPORT_NO,
42 : : .dnssec_mode = _DNSSEC_MODE_INVALID,
43 : : .dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID,
44 : : .operstate = IF_OPER_UNKNOWN,
45 : : };
46 : :
47 [ # # ]: 0 : if (asprintf(&l->state_file, "/run/systemd/resolve/netif/%i", ifindex) < 0)
48 : 0 : return -ENOMEM;
49 : :
50 : 0 : r = hashmap_put(m->links, INT_TO_PTR(ifindex), l);
51 [ # # ]: 0 : if (r < 0)
52 : 0 : return r;
53 : :
54 : 0 : l->manager = m;
55 : :
56 [ # # ]: 0 : if (ret)
57 : 0 : *ret = l;
58 : 0 : l = NULL;
59 : :
60 : 0 : return 0;
61 : : }
62 : :
63 : 0 : void link_flush_settings(Link *l) {
64 [ # # ]: 0 : assert(l);
65 : :
66 : 0 : l->default_route = -1;
67 : 0 : l->llmnr_support = RESOLVE_SUPPORT_YES;
68 : 0 : l->mdns_support = RESOLVE_SUPPORT_NO;
69 : 0 : l->dnssec_mode = _DNSSEC_MODE_INVALID;
70 : 0 : l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
71 : :
72 : 0 : dns_server_unlink_all(l->dns_servers);
73 : 0 : dns_search_domain_unlink_all(l->search_domains);
74 : :
75 : 0 : l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
76 : 0 : }
77 : :
78 : 0 : Link *link_free(Link *l) {
79 [ # # ]: 0 : if (!l)
80 : 0 : return NULL;
81 : :
82 : : /* Send goodbye messages. */
83 : 0 : dns_scope_announce(l->mdns_ipv4_scope, true);
84 : 0 : dns_scope_announce(l->mdns_ipv6_scope, true);
85 : :
86 : 0 : link_flush_settings(l);
87 : :
88 [ # # ]: 0 : while (l->addresses)
89 : 0 : (void) link_address_free(l->addresses);
90 : :
91 [ # # ]: 0 : if (l->manager)
92 : 0 : hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex));
93 : :
94 : 0 : dns_scope_free(l->unicast_scope);
95 : 0 : dns_scope_free(l->llmnr_ipv4_scope);
96 : 0 : dns_scope_free(l->llmnr_ipv6_scope);
97 : 0 : dns_scope_free(l->mdns_ipv4_scope);
98 : 0 : dns_scope_free(l->mdns_ipv6_scope);
99 : :
100 : 0 : free(l->state_file);
101 : 0 : free(l->ifname);
102 : :
103 : 0 : return mfree(l);
104 : : }
105 : :
106 : 0 : void link_allocate_scopes(Link *l) {
107 : : bool unicast_relevant;
108 : : int r;
109 : :
110 [ # # ]: 0 : assert(l);
111 : :
112 : : /* If a link that used to be relevant is no longer, or a link that did not use to be relevant now becomes
113 : : * relevant, let's reinit the learnt global DNS server information, since we might talk to different servers
114 : : * now, even if they have the same addresses as before. */
115 : :
116 : 0 : unicast_relevant = link_relevant(l, AF_UNSPEC, false);
117 [ # # ]: 0 : if (unicast_relevant != l->unicast_relevant) {
118 : 0 : l->unicast_relevant = unicast_relevant;
119 : :
120 : 0 : dns_server_reset_features_all(l->manager->fallback_dns_servers);
121 : 0 : dns_server_reset_features_all(l->manager->dns_servers);
122 : :
123 : : /* Also, flush the global unicast scope, to deal with split horizon setups, where talking through one
124 : : * interface reveals different DNS zones than through others. */
125 [ # # ]: 0 : if (l->manager->unicast_scope)
126 : 0 : dns_cache_flush(&l->manager->unicast_scope->cache);
127 : : }
128 : :
129 : : /* And now, allocate all scopes that makes sense now if we didn't have them yet, and drop those which we don't
130 : : * need anymore */
131 : :
132 [ # # # # ]: 0 : if (unicast_relevant && l->dns_servers) {
133 [ # # ]: 0 : if (!l->unicast_scope) {
134 : 0 : dns_server_reset_features_all(l->dns_servers);
135 : :
136 : 0 : r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
137 [ # # ]: 0 : if (r < 0)
138 [ # # ]: 0 : log_warning_errno(r, "Failed to allocate DNS scope: %m");
139 : : }
140 : : } else
141 : 0 : l->unicast_scope = dns_scope_free(l->unicast_scope);
142 : :
143 [ # # ]: 0 : if (link_relevant(l, AF_INET, true) &&
144 [ # # ]: 0 : l->llmnr_support != RESOLVE_SUPPORT_NO &&
145 [ # # ]: 0 : l->manager->llmnr_support != RESOLVE_SUPPORT_NO) {
146 [ # # ]: 0 : if (!l->llmnr_ipv4_scope) {
147 : 0 : r = dns_scope_new(l->manager, &l->llmnr_ipv4_scope, l, DNS_PROTOCOL_LLMNR, AF_INET);
148 [ # # ]: 0 : if (r < 0)
149 [ # # ]: 0 : log_warning_errno(r, "Failed to allocate LLMNR IPv4 scope: %m");
150 : : }
151 : : } else
152 : 0 : l->llmnr_ipv4_scope = dns_scope_free(l->llmnr_ipv4_scope);
153 : :
154 [ # # ]: 0 : if (link_relevant(l, AF_INET6, true) &&
155 [ # # ]: 0 : l->llmnr_support != RESOLVE_SUPPORT_NO &&
156 [ # # # # ]: 0 : l->manager->llmnr_support != RESOLVE_SUPPORT_NO &&
157 : 0 : socket_ipv6_is_supported()) {
158 [ # # ]: 0 : if (!l->llmnr_ipv6_scope) {
159 : 0 : r = dns_scope_new(l->manager, &l->llmnr_ipv6_scope, l, DNS_PROTOCOL_LLMNR, AF_INET6);
160 [ # # ]: 0 : if (r < 0)
161 [ # # ]: 0 : log_warning_errno(r, "Failed to allocate LLMNR IPv6 scope: %m");
162 : : }
163 : : } else
164 : 0 : l->llmnr_ipv6_scope = dns_scope_free(l->llmnr_ipv6_scope);
165 : :
166 [ # # ]: 0 : if (link_relevant(l, AF_INET, true) &&
167 [ # # ]: 0 : l->mdns_support != RESOLVE_SUPPORT_NO &&
168 [ # # ]: 0 : l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
169 [ # # ]: 0 : if (!l->mdns_ipv4_scope) {
170 : 0 : r = dns_scope_new(l->manager, &l->mdns_ipv4_scope, l, DNS_PROTOCOL_MDNS, AF_INET);
171 [ # # ]: 0 : if (r < 0)
172 [ # # ]: 0 : log_warning_errno(r, "Failed to allocate mDNS IPv4 scope: %m");
173 : : }
174 : : } else
175 : 0 : l->mdns_ipv4_scope = dns_scope_free(l->mdns_ipv4_scope);
176 : :
177 [ # # ]: 0 : if (link_relevant(l, AF_INET6, true) &&
178 [ # # ]: 0 : l->mdns_support != RESOLVE_SUPPORT_NO &&
179 [ # # ]: 0 : l->manager->mdns_support != RESOLVE_SUPPORT_NO) {
180 [ # # ]: 0 : if (!l->mdns_ipv6_scope) {
181 : 0 : r = dns_scope_new(l->manager, &l->mdns_ipv6_scope, l, DNS_PROTOCOL_MDNS, AF_INET6);
182 [ # # ]: 0 : if (r < 0)
183 [ # # ]: 0 : log_warning_errno(r, "Failed to allocate mDNS IPv6 scope: %m");
184 : : }
185 : : } else
186 : 0 : l->mdns_ipv6_scope = dns_scope_free(l->mdns_ipv6_scope);
187 : 0 : }
188 : :
189 : 0 : void link_add_rrs(Link *l, bool force_remove) {
190 : : LinkAddress *a;
191 : : int r;
192 : :
193 [ # # ]: 0 : LIST_FOREACH(addresses, a, l->addresses)
194 : 0 : link_address_add_rrs(a, force_remove);
195 : :
196 [ # # ]: 0 : if (!force_remove &&
197 [ # # ]: 0 : l->mdns_support == RESOLVE_SUPPORT_YES &&
198 [ # # ]: 0 : l->manager->mdns_support == RESOLVE_SUPPORT_YES) {
199 : :
200 [ # # ]: 0 : if (l->mdns_ipv4_scope) {
201 : 0 : r = dns_scope_add_dnssd_services(l->mdns_ipv4_scope);
202 [ # # ]: 0 : if (r < 0)
203 [ # # ]: 0 : log_warning_errno(r, "Failed to add IPv4 DNS-SD services: %m");
204 : : }
205 : :
206 [ # # ]: 0 : if (l->mdns_ipv6_scope) {
207 : 0 : r = dns_scope_add_dnssd_services(l->mdns_ipv6_scope);
208 [ # # ]: 0 : if (r < 0)
209 [ # # ]: 0 : log_warning_errno(r, "Failed to add IPv6 DNS-SD services: %m");
210 : : }
211 : :
212 : : } else {
213 : :
214 [ # # ]: 0 : if (l->mdns_ipv4_scope) {
215 : 0 : r = dns_scope_remove_dnssd_services(l->mdns_ipv4_scope);
216 [ # # ]: 0 : if (r < 0)
217 [ # # ]: 0 : log_warning_errno(r, "Failed to remove IPv4 DNS-SD services: %m");
218 : : }
219 : :
220 [ # # ]: 0 : if (l->mdns_ipv6_scope) {
221 : 0 : r = dns_scope_remove_dnssd_services(l->mdns_ipv6_scope);
222 [ # # ]: 0 : if (r < 0)
223 [ # # ]: 0 : log_warning_errno(r, "Failed to remove IPv6 DNS-SD services: %m");
224 : : }
225 : : }
226 : 0 : }
227 : :
228 : 0 : int link_process_rtnl(Link *l, sd_netlink_message *m) {
229 : 0 : const char *n = NULL;
230 : : int r;
231 : :
232 [ # # ]: 0 : assert(l);
233 [ # # ]: 0 : assert(m);
234 : :
235 : 0 : r = sd_rtnl_message_link_get_flags(m, &l->flags);
236 [ # # ]: 0 : if (r < 0)
237 : 0 : return r;
238 : :
239 : 0 : (void) sd_netlink_message_read_u32(m, IFLA_MTU, &l->mtu);
240 : 0 : (void) sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &l->operstate);
241 : :
242 [ # # ]: 0 : if (sd_netlink_message_read_string(m, IFLA_IFNAME, &n) >= 0) {
243 : 0 : r = free_and_strdup(&l->ifname, n);
244 [ # # ]: 0 : if (r < 0)
245 : 0 : return r;
246 : : }
247 : :
248 : 0 : link_allocate_scopes(l);
249 : 0 : link_add_rrs(l, false);
250 : :
251 : 0 : return 0;
252 : : }
253 : :
254 : 0 : static int link_update_dns_server_one(Link *l, const char *name) {
255 : : union in_addr_union a;
256 : : DnsServer *s;
257 : : int family, r;
258 : :
259 [ # # ]: 0 : assert(l);
260 [ # # ]: 0 : assert(name);
261 : :
262 : 0 : r = in_addr_from_string_auto(name, &family, &a);
263 [ # # ]: 0 : if (r < 0)
264 : 0 : return r;
265 : :
266 : 0 : s = dns_server_find(l->dns_servers, family, &a, 0);
267 [ # # ]: 0 : if (s) {
268 : 0 : dns_server_move_back_and_unmark(s);
269 : 0 : return 0;
270 : : }
271 : :
272 : 0 : return dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, 0);
273 : : }
274 : :
275 : 0 : static int link_update_dns_servers(Link *l) {
276 : 0 : _cleanup_strv_free_ char **nameservers = NULL;
277 : : char **nameserver;
278 : : int r;
279 : :
280 [ # # ]: 0 : assert(l);
281 : :
282 : 0 : r = sd_network_link_get_dns(l->ifindex, &nameservers);
283 [ # # ]: 0 : if (r == -ENODATA) {
284 : 0 : r = 0;
285 : 0 : goto clear;
286 : : }
287 [ # # ]: 0 : if (r < 0)
288 : 0 : goto clear;
289 : :
290 : 0 : dns_server_mark_all(l->dns_servers);
291 : :
292 [ # # # # ]: 0 : STRV_FOREACH(nameserver, nameservers) {
293 : 0 : r = link_update_dns_server_one(l, *nameserver);
294 [ # # ]: 0 : if (r < 0)
295 : 0 : goto clear;
296 : : }
297 : :
298 : 0 : dns_server_unlink_marked(l->dns_servers);
299 : 0 : return 0;
300 : :
301 : 0 : clear:
302 : 0 : dns_server_unlink_all(l->dns_servers);
303 : 0 : return r;
304 : : }
305 : :
306 : 0 : static int link_update_default_route(Link *l) {
307 : : int r;
308 : :
309 [ # # ]: 0 : assert(l);
310 : :
311 : 0 : r = sd_network_link_get_dns_default_route(l->ifindex);
312 [ # # ]: 0 : if (r == -ENODATA) {
313 : 0 : r = 0;
314 : 0 : goto clear;
315 : : }
316 [ # # ]: 0 : if (r < 0)
317 : 0 : goto clear;
318 : :
319 : 0 : l->default_route = r > 0;
320 : 0 : return 0;
321 : :
322 : 0 : clear:
323 : 0 : l->default_route = -1;
324 : 0 : return r;
325 : : }
326 : :
327 : 0 : static int link_update_llmnr_support(Link *l) {
328 : 0 : _cleanup_free_ char *b = NULL;
329 : : int r;
330 : :
331 [ # # ]: 0 : assert(l);
332 : :
333 : 0 : r = sd_network_link_get_llmnr(l->ifindex, &b);
334 [ # # ]: 0 : if (r == -ENODATA) {
335 : 0 : r = 0;
336 : 0 : goto clear;
337 : : }
338 [ # # ]: 0 : if (r < 0)
339 : 0 : goto clear;
340 : :
341 : 0 : l->llmnr_support = resolve_support_from_string(b);
342 [ # # ]: 0 : if (l->llmnr_support < 0) {
343 : 0 : r = -EINVAL;
344 : 0 : goto clear;
345 : : }
346 : :
347 : 0 : return 0;
348 : :
349 : 0 : clear:
350 : 0 : l->llmnr_support = RESOLVE_SUPPORT_YES;
351 : 0 : return r;
352 : : }
353 : :
354 : 0 : static int link_update_mdns_support(Link *l) {
355 : 0 : _cleanup_free_ char *b = NULL;
356 : : int r;
357 : :
358 [ # # ]: 0 : assert(l);
359 : :
360 : 0 : r = sd_network_link_get_mdns(l->ifindex, &b);
361 [ # # ]: 0 : if (r == -ENODATA) {
362 : 0 : r = 0;
363 : 0 : goto clear;
364 : : }
365 [ # # ]: 0 : if (r < 0)
366 : 0 : goto clear;
367 : :
368 : 0 : l->mdns_support = resolve_support_from_string(b);
369 [ # # ]: 0 : if (l->mdns_support < 0) {
370 : 0 : r = -EINVAL;
371 : 0 : goto clear;
372 : : }
373 : :
374 : 0 : return 0;
375 : :
376 : 0 : clear:
377 : 0 : l->mdns_support = RESOLVE_SUPPORT_NO;
378 : 0 : return r;
379 : : }
380 : :
381 : 0 : void link_set_dns_over_tls_mode(Link *l, DnsOverTlsMode mode) {
382 : :
383 [ # # ]: 0 : assert(l);
384 : :
385 : : #if ! ENABLE_DNS_OVER_TLS
386 : : if (mode != DNS_OVER_TLS_NO)
387 : : log_warning("DNS-over-TLS option for the link cannot be enabled or set to opportunistic when systemd-resolved is built without DNS-over-TLS support. Turning off DNS-over-TLS support.");
388 : : return;
389 : : #endif
390 : :
391 : 0 : l->dns_over_tls_mode = mode;
392 : 0 : }
393 : :
394 : 0 : static int link_update_dns_over_tls_mode(Link *l) {
395 : 0 : _cleanup_free_ char *b = NULL;
396 : : int r;
397 : :
398 [ # # ]: 0 : assert(l);
399 : :
400 : 0 : r = sd_network_link_get_dns_over_tls(l->ifindex, &b);
401 [ # # ]: 0 : if (r == -ENODATA) {
402 : 0 : r = 0;
403 : 0 : goto clear;
404 : : }
405 [ # # ]: 0 : if (r < 0)
406 : 0 : goto clear;
407 : :
408 : 0 : l->dns_over_tls_mode = dns_over_tls_mode_from_string(b);
409 [ # # ]: 0 : if (l->dns_over_tls_mode < 0) {
410 : 0 : r = -EINVAL;
411 : 0 : goto clear;
412 : : }
413 : :
414 : 0 : return 0;
415 : :
416 : 0 : clear:
417 : 0 : l->dns_over_tls_mode = _DNS_OVER_TLS_MODE_INVALID;
418 : 0 : return r;
419 : : }
420 : :
421 : 0 : void link_set_dnssec_mode(Link *l, DnssecMode mode) {
422 : :
423 [ # # ]: 0 : assert(l);
424 : :
425 : : #if ! HAVE_GCRYPT
426 : : if (IN_SET(mode, DNSSEC_YES, DNSSEC_ALLOW_DOWNGRADE))
427 : : log_warning("DNSSEC option for the link cannot be enabled or set to allow-downgrade when systemd-resolved is built without gcrypt support. Turning off DNSSEC support.");
428 : : return;
429 : : #endif
430 : :
431 [ # # ]: 0 : if (l->dnssec_mode == mode)
432 : 0 : return;
433 : :
434 [ # # ]: 0 : if ((l->dnssec_mode == _DNSSEC_MODE_INVALID) ||
435 [ # # # # ]: 0 : (l->dnssec_mode == DNSSEC_NO && mode != DNSSEC_NO) ||
436 [ # # # # ]: 0 : (l->dnssec_mode == DNSSEC_ALLOW_DOWNGRADE && mode == DNSSEC_YES)) {
437 : :
438 : : /* When switching from non-DNSSEC mode to DNSSEC mode, flush the cache. Also when switching from the
439 : : * allow-downgrade mode to full DNSSEC mode, flush it too. */
440 [ # # ]: 0 : if (l->unicast_scope)
441 : 0 : dns_cache_flush(&l->unicast_scope->cache);
442 : : }
443 : :
444 : 0 : l->dnssec_mode = mode;
445 : : }
446 : :
447 : 0 : static int link_update_dnssec_mode(Link *l) {
448 : 0 : _cleanup_free_ char *m = NULL;
449 : : DnssecMode mode;
450 : : int r;
451 : :
452 [ # # ]: 0 : assert(l);
453 : :
454 : 0 : r = sd_network_link_get_dnssec(l->ifindex, &m);
455 [ # # ]: 0 : if (r == -ENODATA) {
456 : 0 : r = 0;
457 : 0 : goto clear;
458 : : }
459 [ # # ]: 0 : if (r < 0)
460 : 0 : goto clear;
461 : :
462 : 0 : mode = dnssec_mode_from_string(m);
463 [ # # ]: 0 : if (mode < 0) {
464 : 0 : r = -EINVAL;
465 : 0 : goto clear;
466 : : }
467 : :
468 : 0 : link_set_dnssec_mode(l, mode);
469 : :
470 : 0 : return 0;
471 : :
472 : 0 : clear:
473 : 0 : l->dnssec_mode = _DNSSEC_MODE_INVALID;
474 : 0 : return r;
475 : : }
476 : :
477 : 0 : static int link_update_dnssec_negative_trust_anchors(Link *l) {
478 : 0 : _cleanup_strv_free_ char **ntas = NULL;
479 : 0 : _cleanup_set_free_free_ Set *ns = NULL;
480 : : int r;
481 : :
482 [ # # ]: 0 : assert(l);
483 : :
484 : 0 : r = sd_network_link_get_dnssec_negative_trust_anchors(l->ifindex, &ntas);
485 [ # # ]: 0 : if (r == -ENODATA) {
486 : 0 : r = 0;
487 : 0 : goto clear;
488 : : }
489 [ # # ]: 0 : if (r < 0)
490 : 0 : goto clear;
491 : :
492 : 0 : ns = set_new(&dns_name_hash_ops);
493 [ # # ]: 0 : if (!ns)
494 : 0 : return -ENOMEM;
495 : :
496 : 0 : r = set_put_strdupv(ns, ntas);
497 [ # # ]: 0 : if (r < 0)
498 : 0 : return r;
499 : :
500 : 0 : set_free_free(l->dnssec_negative_trust_anchors);
501 : 0 : l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
502 : :
503 : 0 : return 0;
504 : :
505 : 0 : clear:
506 : 0 : l->dnssec_negative_trust_anchors = set_free_free(l->dnssec_negative_trust_anchors);
507 : 0 : return r;
508 : : }
509 : :
510 : 0 : static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
511 : : DnsSearchDomain *d;
512 : : int r;
513 : :
514 [ # # ]: 0 : assert(l);
515 [ # # ]: 0 : assert(name);
516 : :
517 : 0 : r = dns_search_domain_find(l->search_domains, name, &d);
518 [ # # ]: 0 : if (r < 0)
519 : 0 : return r;
520 [ # # ]: 0 : if (r > 0)
521 : 0 : dns_search_domain_move_back_and_unmark(d);
522 : : else {
523 : 0 : r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
524 [ # # ]: 0 : if (r < 0)
525 : 0 : return r;
526 : : }
527 : :
528 : 0 : d->route_only = route_only;
529 : 0 : return 0;
530 : : }
531 : :
532 : 0 : static int link_update_search_domains(Link *l) {
533 : 0 : _cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL;
534 : : char **i;
535 : : int r, q;
536 : :
537 [ # # ]: 0 : assert(l);
538 : :
539 : 0 : r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
540 [ # # # # ]: 0 : if (r < 0 && r != -ENODATA)
541 : 0 : goto clear;
542 : :
543 : 0 : q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
544 [ # # # # ]: 0 : if (q < 0 && q != -ENODATA) {
545 : 0 : r = q;
546 : 0 : goto clear;
547 : : }
548 : :
549 [ # # # # ]: 0 : if (r == -ENODATA && q == -ENODATA) {
550 : : /* networkd knows nothing about this interface, and that's fine. */
551 : 0 : r = 0;
552 : 0 : goto clear;
553 : : }
554 : :
555 : 0 : dns_search_domain_mark_all(l->search_domains);
556 : :
557 [ # # # # ]: 0 : STRV_FOREACH(i, sdomains) {
558 : 0 : r = link_update_search_domain_one(l, *i, false);
559 [ # # ]: 0 : if (r < 0)
560 : 0 : goto clear;
561 : : }
562 : :
563 [ # # # # ]: 0 : STRV_FOREACH(i, rdomains) {
564 : 0 : r = link_update_search_domain_one(l, *i, true);
565 [ # # ]: 0 : if (r < 0)
566 : 0 : goto clear;
567 : : }
568 : :
569 : 0 : dns_search_domain_unlink_marked(l->search_domains);
570 : 0 : return 0;
571 : :
572 : 0 : clear:
573 : 0 : dns_search_domain_unlink_all(l->search_domains);
574 : 0 : return r;
575 : : }
576 : :
577 : 0 : static int link_is_managed(Link *l) {
578 : 0 : _cleanup_free_ char *state = NULL;
579 : : int r;
580 : :
581 [ # # ]: 0 : assert(l);
582 : :
583 : 0 : r = sd_network_link_get_setup_state(l->ifindex, &state);
584 [ # # ]: 0 : if (r == -ENODATA)
585 : 0 : return 0;
586 [ # # ]: 0 : if (r < 0)
587 : 0 : return r;
588 : :
589 : 0 : return !STR_IN_SET(state, "pending", "unmanaged");
590 : : }
591 : :
592 : 0 : static void link_read_settings(Link *l) {
593 : : int r;
594 : :
595 [ # # ]: 0 : assert(l);
596 : :
597 : : /* Read settings from networkd, except when networkd is not managing this interface. */
598 : :
599 : 0 : r = link_is_managed(l);
600 [ # # ]: 0 : if (r < 0) {
601 [ # # # # ]: 0 : log_link_warning_errno(l, r, "Failed to determine whether the interface is managed: %m");
602 : 0 : return;
603 : : }
604 [ # # ]: 0 : if (r == 0) {
605 : :
606 : : /* If this link used to be managed, but is now unmanaged, flush all our settings — but only once. */
607 [ # # ]: 0 : if (l->is_managed)
608 : 0 : link_flush_settings(l);
609 : :
610 : 0 : l->is_managed = false;
611 : 0 : return;
612 : : }
613 : :
614 : 0 : l->is_managed = true;
615 : :
616 : 0 : r = link_update_dns_servers(l);
617 [ # # ]: 0 : if (r < 0)
618 [ # # # # ]: 0 : log_link_warning_errno(l, r, "Failed to read DNS servers for the interface, ignoring: %m");
619 : :
620 : 0 : r = link_update_llmnr_support(l);
621 [ # # ]: 0 : if (r < 0)
622 [ # # # # ]: 0 : log_link_warning_errno(l, r, "Failed to read LLMNR support for the interface, ignoring: %m");
623 : :
624 : 0 : r = link_update_mdns_support(l);
625 [ # # ]: 0 : if (r < 0)
626 [ # # # # ]: 0 : log_link_warning_errno(l, r, "Failed to read mDNS support for the interface, ignoring: %m");
627 : :
628 : 0 : r = link_update_dns_over_tls_mode(l);
629 [ # # ]: 0 : if (r < 0)
630 [ # # # # ]: 0 : log_link_warning_errno(l, r, "Failed to read DNS-over-TLS mode for the interface, ignoring: %m");
631 : :
632 : 0 : r = link_update_dnssec_mode(l);
633 [ # # ]: 0 : if (r < 0)
634 [ # # # # ]: 0 : log_link_warning_errno(l, r, "Failed to read DNSSEC mode for the interface, ignoring: %m");
635 : :
636 : 0 : r = link_update_dnssec_negative_trust_anchors(l);
637 [ # # ]: 0 : if (r < 0)
638 [ # # # # ]: 0 : log_link_warning_errno(l, r, "Failed to read DNSSEC negative trust anchors for the interface, ignoring: %m");
639 : :
640 : 0 : r = link_update_search_domains(l);
641 [ # # ]: 0 : if (r < 0)
642 [ # # # # ]: 0 : log_link_warning_errno(l, r, "Failed to read search domains for the interface, ignoring: %m");
643 : :
644 : 0 : r = link_update_default_route(l);
645 [ # # ]: 0 : if (r < 0)
646 [ # # # # ]: 0 : log_link_warning_errno(l, r, "Failed to read default route setting for the interface, proceeding anyway: %m");
647 : : }
648 : :
649 : 0 : int link_update(Link *l) {
650 : : int r;
651 : :
652 [ # # ]: 0 : assert(l);
653 : :
654 : 0 : link_read_settings(l);
655 : 0 : link_load_user(l);
656 : :
657 [ # # ]: 0 : if (l->llmnr_support != RESOLVE_SUPPORT_NO) {
658 : 0 : r = manager_llmnr_start(l->manager);
659 [ # # ]: 0 : if (r < 0)
660 : 0 : return r;
661 : : }
662 : :
663 [ # # ]: 0 : if (l->mdns_support != RESOLVE_SUPPORT_NO) {
664 : 0 : r = manager_mdns_start(l->manager);
665 [ # # ]: 0 : if (r < 0)
666 : 0 : return r;
667 : : }
668 : :
669 : 0 : link_allocate_scopes(l);
670 : 0 : link_add_rrs(l, false);
671 : :
672 : 0 : return 0;
673 : : }
674 : :
675 : 0 : bool link_relevant(Link *l, int family, bool local_multicast) {
676 : 0 : _cleanup_free_ char *state = NULL;
677 : : LinkAddress *a;
678 : :
679 [ # # ]: 0 : assert(l);
680 : :
681 : : /* A link is relevant for local multicast traffic if it isn't a loopback device, has a link
682 : : * beat, can do multicast and has at least one link-local (or better) IP address.
683 : : *
684 : : * A link is relevant for non-multicast traffic if it isn't a loopback device, has a link beat, and has at
685 : : * least one routable address. */
686 : :
687 [ # # ]: 0 : if (l->flags & (IFF_LOOPBACK|IFF_DORMANT))
688 : 0 : return false;
689 : :
690 [ # # ]: 0 : if ((l->flags & (IFF_UP|IFF_LOWER_UP)) != (IFF_UP|IFF_LOWER_UP))
691 : 0 : return false;
692 : :
693 [ # # ]: 0 : if (local_multicast) {
694 [ # # ]: 0 : if ((l->flags & IFF_MULTICAST) != IFF_MULTICAST)
695 : 0 : return false;
696 : : }
697 : :
698 : : /* Check kernel operstate
699 : : * https://www.kernel.org/doc/Documentation/networking/operstates.txt */
700 [ # # # # ]: 0 : if (!IN_SET(l->operstate, IF_OPER_UNKNOWN, IF_OPER_UP))
701 : 0 : return false;
702 : :
703 : 0 : (void) sd_network_link_get_operational_state(l->ifindex, &state);
704 [ # # # # ]: 0 : if (state && !STR_IN_SET(state, "unknown", "degraded", "degraded-carrier", "routable"))
705 : 0 : return false;
706 : :
707 [ # # ]: 0 : LIST_FOREACH(addresses, a, l->addresses)
708 [ # # # # : 0 : if ((family == AF_UNSPEC || a->family == family) && link_address_relevant(a, local_multicast))
# # ]
709 : 0 : return true;
710 : :
711 : 0 : return false;
712 : : }
713 : :
714 : 0 : LinkAddress *link_find_address(Link *l, int family, const union in_addr_union *in_addr) {
715 : : LinkAddress *a;
716 : :
717 [ # # ]: 0 : assert(l);
718 : :
719 [ # # ]: 0 : LIST_FOREACH(addresses, a, l->addresses)
720 [ # # # # ]: 0 : if (a->family == family && in_addr_equal(family, &a->in_addr, in_addr))
721 : 0 : return a;
722 : :
723 : 0 : return NULL;
724 : : }
725 : :
726 : 0 : DnsServer* link_set_dns_server(Link *l, DnsServer *s) {
727 [ # # ]: 0 : assert(l);
728 : :
729 [ # # ]: 0 : if (l->current_dns_server == s)
730 : 0 : return s;
731 : :
732 [ # # ]: 0 : if (s)
733 [ # # ]: 0 : log_debug("Switching to DNS server %s for interface %s.", dns_server_string(s), l->ifname);
734 : :
735 : 0 : dns_server_unref(l->current_dns_server);
736 : 0 : l->current_dns_server = dns_server_ref(s);
737 : :
738 [ # # ]: 0 : if (l->unicast_scope)
739 : 0 : dns_cache_flush(&l->unicast_scope->cache);
740 : :
741 : 0 : return s;
742 : : }
743 : :
744 : 0 : DnsServer *link_get_dns_server(Link *l) {
745 [ # # ]: 0 : assert(l);
746 : :
747 [ # # ]: 0 : if (!l->current_dns_server)
748 : 0 : link_set_dns_server(l, l->dns_servers);
749 : :
750 : 0 : return l->current_dns_server;
751 : : }
752 : :
753 : 0 : void link_next_dns_server(Link *l) {
754 [ # # ]: 0 : assert(l);
755 : :
756 [ # # ]: 0 : if (!l->current_dns_server)
757 : 0 : return;
758 : :
759 : : /* Change to the next one, but make sure to follow the linked
760 : : * list only if this server is actually still linked. */
761 [ # # # # ]: 0 : if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
762 : 0 : link_set_dns_server(l, l->current_dns_server->servers_next);
763 : 0 : return;
764 : : }
765 : :
766 : 0 : link_set_dns_server(l, l->dns_servers);
767 : : }
768 : :
769 : 0 : DnsOverTlsMode link_get_dns_over_tls_mode(Link *l) {
770 [ # # ]: 0 : assert(l);
771 : :
772 [ # # ]: 0 : if (l->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID)
773 : 0 : return l->dns_over_tls_mode;
774 : :
775 : 0 : return manager_get_dns_over_tls_mode(l->manager);
776 : : }
777 : :
778 : 0 : DnssecMode link_get_dnssec_mode(Link *l) {
779 [ # # ]: 0 : assert(l);
780 : :
781 [ # # ]: 0 : if (l->dnssec_mode != _DNSSEC_MODE_INVALID)
782 : 0 : return l->dnssec_mode;
783 : :
784 : 0 : return manager_get_dnssec_mode(l->manager);
785 : : }
786 : :
787 : 0 : bool link_dnssec_supported(Link *l) {
788 : : DnsServer *server;
789 : :
790 [ # # ]: 0 : assert(l);
791 : :
792 [ # # ]: 0 : if (link_get_dnssec_mode(l) == DNSSEC_NO)
793 : 0 : return false;
794 : :
795 : 0 : server = link_get_dns_server(l);
796 [ # # ]: 0 : if (server)
797 : 0 : return dns_server_dnssec_supported(server);
798 : :
799 : 0 : return true;
800 : : }
801 : :
802 : 0 : int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr_union *in_addr) {
803 : : LinkAddress *a;
804 : :
805 [ # # ]: 0 : assert(l);
806 [ # # ]: 0 : assert(in_addr);
807 : :
808 : 0 : a = new0(LinkAddress, 1);
809 [ # # ]: 0 : if (!a)
810 : 0 : return -ENOMEM;
811 : :
812 : 0 : a->family = family;
813 : 0 : a->in_addr = *in_addr;
814 : :
815 : 0 : a->link = l;
816 [ # # # # ]: 0 : LIST_PREPEND(addresses, l->addresses, a);
817 : 0 : l->n_addresses++;
818 : :
819 [ # # ]: 0 : if (ret)
820 : 0 : *ret = a;
821 : :
822 : 0 : return 0;
823 : : }
824 : :
825 : 0 : LinkAddress *link_address_free(LinkAddress *a) {
826 [ # # ]: 0 : if (!a)
827 : 0 : return NULL;
828 : :
829 [ # # ]: 0 : if (a->link) {
830 [ # # # # : 0 : LIST_REMOVE(addresses, a->link->addresses, a);
# # # # ]
831 : :
832 [ # # ]: 0 : assert(a->link->n_addresses > 0);
833 : 0 : a->link->n_addresses--;
834 : :
835 [ # # ]: 0 : if (a->llmnr_address_rr) {
836 [ # # # # ]: 0 : if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
837 : 0 : dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
838 [ # # # # ]: 0 : else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
839 : 0 : dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
840 : : }
841 : :
842 [ # # ]: 0 : if (a->llmnr_ptr_rr) {
843 [ # # # # ]: 0 : if (a->family == AF_INET && a->link->llmnr_ipv4_scope)
844 : 0 : dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
845 [ # # # # ]: 0 : else if (a->family == AF_INET6 && a->link->llmnr_ipv6_scope)
846 : 0 : dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
847 : : }
848 : :
849 [ # # ]: 0 : if (a->mdns_address_rr) {
850 [ # # # # ]: 0 : if (a->family == AF_INET && a->link->mdns_ipv4_scope)
851 : 0 : dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
852 [ # # # # ]: 0 : else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
853 : 0 : dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
854 : : }
855 : :
856 [ # # ]: 0 : if (a->mdns_ptr_rr) {
857 [ # # # # ]: 0 : if (a->family == AF_INET && a->link->mdns_ipv4_scope)
858 : 0 : dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
859 [ # # # # ]: 0 : else if (a->family == AF_INET6 && a->link->mdns_ipv6_scope)
860 : 0 : dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
861 : : }
862 : : }
863 : :
864 : 0 : dns_resource_record_unref(a->llmnr_address_rr);
865 : 0 : dns_resource_record_unref(a->llmnr_ptr_rr);
866 : 0 : dns_resource_record_unref(a->mdns_address_rr);
867 : 0 : dns_resource_record_unref(a->mdns_ptr_rr);
868 : :
869 : 0 : return mfree(a);
870 : : }
871 : :
872 : 0 : void link_address_add_rrs(LinkAddress *a, bool force_remove) {
873 : : int r;
874 : :
875 [ # # ]: 0 : assert(a);
876 : :
877 [ # # ]: 0 : if (a->family == AF_INET) {
878 : :
879 [ # # # # ]: 0 : if (!force_remove &&
880 : 0 : link_address_relevant(a, true) &&
881 [ # # ]: 0 : a->link->llmnr_ipv4_scope &&
882 [ # # ]: 0 : a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
883 [ # # ]: 0 : a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
884 : :
885 [ # # ]: 0 : if (!a->link->manager->llmnr_host_ipv4_key) {
886 : 0 : a->link->manager->llmnr_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->llmnr_hostname);
887 [ # # ]: 0 : if (!a->link->manager->llmnr_host_ipv4_key) {
888 : 0 : r = -ENOMEM;
889 : 0 : goto fail;
890 : : }
891 : : }
892 : :
893 [ # # ]: 0 : if (!a->llmnr_address_rr) {
894 : 0 : a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv4_key);
895 [ # # ]: 0 : if (!a->llmnr_address_rr) {
896 : 0 : r = -ENOMEM;
897 : 0 : goto fail;
898 : : }
899 : :
900 : 0 : a->llmnr_address_rr->a.in_addr = a->in_addr.in;
901 : 0 : a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
902 : : }
903 : :
904 [ # # ]: 0 : if (!a->llmnr_ptr_rr) {
905 : 0 : r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
906 [ # # ]: 0 : if (r < 0)
907 : 0 : goto fail;
908 : :
909 : 0 : a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
910 : : }
911 : :
912 : 0 : r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_address_rr, true);
913 [ # # ]: 0 : if (r < 0)
914 [ # # ]: 0 : log_warning_errno(r, "Failed to add A record to LLMNR zone: %m");
915 : :
916 : 0 : r = dns_zone_put(&a->link->llmnr_ipv4_scope->zone, a->link->llmnr_ipv4_scope, a->llmnr_ptr_rr, false);
917 [ # # ]: 0 : if (r < 0)
918 [ # # ]: 0 : log_warning_errno(r, "Failed to add IPv4 PTR record to LLMNR zone: %m");
919 : : } else {
920 [ # # ]: 0 : if (a->llmnr_address_rr) {
921 [ # # ]: 0 : if (a->link->llmnr_ipv4_scope)
922 : 0 : dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_address_rr);
923 : 0 : a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
924 : : }
925 : :
926 [ # # ]: 0 : if (a->llmnr_ptr_rr) {
927 [ # # ]: 0 : if (a->link->llmnr_ipv4_scope)
928 : 0 : dns_zone_remove_rr(&a->link->llmnr_ipv4_scope->zone, a->llmnr_ptr_rr);
929 : 0 : a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
930 : : }
931 : : }
932 : :
933 [ # # # # ]: 0 : if (!force_remove &&
934 : 0 : link_address_relevant(a, true) &&
935 [ # # ]: 0 : a->link->mdns_ipv4_scope &&
936 [ # # ]: 0 : a->link->mdns_support == RESOLVE_SUPPORT_YES &&
937 [ # # ]: 0 : a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
938 [ # # ]: 0 : if (!a->link->manager->mdns_host_ipv4_key) {
939 : 0 : a->link->manager->mdns_host_ipv4_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, a->link->manager->mdns_hostname);
940 [ # # ]: 0 : if (!a->link->manager->mdns_host_ipv4_key) {
941 : 0 : r = -ENOMEM;
942 : 0 : goto fail;
943 : : }
944 : : }
945 : :
946 [ # # ]: 0 : if (!a->mdns_address_rr) {
947 : 0 : a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv4_key);
948 [ # # ]: 0 : if (!a->mdns_address_rr) {
949 : 0 : r = -ENOMEM;
950 : 0 : goto fail;
951 : : }
952 : :
953 : 0 : a->mdns_address_rr->a.in_addr = a->in_addr.in;
954 : 0 : a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
955 : : }
956 : :
957 [ # # ]: 0 : if (!a->mdns_ptr_rr) {
958 : 0 : r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
959 [ # # ]: 0 : if (r < 0)
960 : 0 : goto fail;
961 : :
962 : 0 : a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
963 : : }
964 : :
965 : 0 : r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_address_rr, true);
966 [ # # ]: 0 : if (r < 0)
967 [ # # ]: 0 : log_warning_errno(r, "Failed to add A record to MDNS zone: %m");
968 : :
969 : 0 : r = dns_zone_put(&a->link->mdns_ipv4_scope->zone, a->link->mdns_ipv4_scope, a->mdns_ptr_rr, false);
970 [ # # ]: 0 : if (r < 0)
971 [ # # ]: 0 : log_warning_errno(r, "Failed to add IPv4 PTR record to MDNS zone: %m");
972 : : } else {
973 [ # # ]: 0 : if (a->mdns_address_rr) {
974 [ # # ]: 0 : if (a->link->mdns_ipv4_scope)
975 : 0 : dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_address_rr);
976 : 0 : a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
977 : : }
978 : :
979 [ # # ]: 0 : if (a->mdns_ptr_rr) {
980 [ # # ]: 0 : if (a->link->mdns_ipv4_scope)
981 : 0 : dns_zone_remove_rr(&a->link->mdns_ipv4_scope->zone, a->mdns_ptr_rr);
982 : 0 : a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
983 : : }
984 : : }
985 : : }
986 : :
987 [ # # ]: 0 : if (a->family == AF_INET6) {
988 : :
989 [ # # # # ]: 0 : if (!force_remove &&
990 : 0 : link_address_relevant(a, true) &&
991 [ # # ]: 0 : a->link->llmnr_ipv6_scope &&
992 [ # # ]: 0 : a->link->llmnr_support == RESOLVE_SUPPORT_YES &&
993 [ # # ]: 0 : a->link->manager->llmnr_support == RESOLVE_SUPPORT_YES) {
994 : :
995 [ # # ]: 0 : if (!a->link->manager->llmnr_host_ipv6_key) {
996 : 0 : a->link->manager->llmnr_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->llmnr_hostname);
997 [ # # ]: 0 : if (!a->link->manager->llmnr_host_ipv6_key) {
998 : 0 : r = -ENOMEM;
999 : 0 : goto fail;
1000 : : }
1001 : : }
1002 : :
1003 [ # # ]: 0 : if (!a->llmnr_address_rr) {
1004 : 0 : a->llmnr_address_rr = dns_resource_record_new(a->link->manager->llmnr_host_ipv6_key);
1005 [ # # ]: 0 : if (!a->llmnr_address_rr) {
1006 : 0 : r = -ENOMEM;
1007 : 0 : goto fail;
1008 : : }
1009 : :
1010 : 0 : a->llmnr_address_rr->aaaa.in6_addr = a->in_addr.in6;
1011 : 0 : a->llmnr_address_rr->ttl = LLMNR_DEFAULT_TTL;
1012 : : }
1013 : :
1014 [ # # ]: 0 : if (!a->llmnr_ptr_rr) {
1015 : 0 : r = dns_resource_record_new_reverse(&a->llmnr_ptr_rr, a->family, &a->in_addr, a->link->manager->llmnr_hostname);
1016 [ # # ]: 0 : if (r < 0)
1017 : 0 : goto fail;
1018 : :
1019 : 0 : a->llmnr_ptr_rr->ttl = LLMNR_DEFAULT_TTL;
1020 : : }
1021 : :
1022 : 0 : r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_address_rr, true);
1023 [ # # ]: 0 : if (r < 0)
1024 [ # # ]: 0 : log_warning_errno(r, "Failed to add AAAA record to LLMNR zone: %m");
1025 : :
1026 : 0 : r = dns_zone_put(&a->link->llmnr_ipv6_scope->zone, a->link->llmnr_ipv6_scope, a->llmnr_ptr_rr, false);
1027 [ # # ]: 0 : if (r < 0)
1028 [ # # ]: 0 : log_warning_errno(r, "Failed to add IPv6 PTR record to LLMNR zone: %m");
1029 : : } else {
1030 [ # # ]: 0 : if (a->llmnr_address_rr) {
1031 [ # # ]: 0 : if (a->link->llmnr_ipv6_scope)
1032 : 0 : dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_address_rr);
1033 : 0 : a->llmnr_address_rr = dns_resource_record_unref(a->llmnr_address_rr);
1034 : : }
1035 : :
1036 [ # # ]: 0 : if (a->llmnr_ptr_rr) {
1037 [ # # ]: 0 : if (a->link->llmnr_ipv6_scope)
1038 : 0 : dns_zone_remove_rr(&a->link->llmnr_ipv6_scope->zone, a->llmnr_ptr_rr);
1039 : 0 : a->llmnr_ptr_rr = dns_resource_record_unref(a->llmnr_ptr_rr);
1040 : : }
1041 : : }
1042 : :
1043 [ # # # # ]: 0 : if (!force_remove &&
1044 : 0 : link_address_relevant(a, true) &&
1045 [ # # ]: 0 : a->link->mdns_ipv6_scope &&
1046 [ # # ]: 0 : a->link->mdns_support == RESOLVE_SUPPORT_YES &&
1047 [ # # ]: 0 : a->link->manager->mdns_support == RESOLVE_SUPPORT_YES) {
1048 : :
1049 [ # # ]: 0 : if (!a->link->manager->mdns_host_ipv6_key) {
1050 : 0 : a->link->manager->mdns_host_ipv6_key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, a->link->manager->mdns_hostname);
1051 [ # # ]: 0 : if (!a->link->manager->mdns_host_ipv6_key) {
1052 : 0 : r = -ENOMEM;
1053 : 0 : goto fail;
1054 : : }
1055 : : }
1056 : :
1057 [ # # ]: 0 : if (!a->mdns_address_rr) {
1058 : 0 : a->mdns_address_rr = dns_resource_record_new(a->link->manager->mdns_host_ipv6_key);
1059 [ # # ]: 0 : if (!a->mdns_address_rr) {
1060 : 0 : r = -ENOMEM;
1061 : 0 : goto fail;
1062 : : }
1063 : :
1064 : 0 : a->mdns_address_rr->aaaa.in6_addr = a->in_addr.in6;
1065 : 0 : a->mdns_address_rr->ttl = MDNS_DEFAULT_TTL;
1066 : : }
1067 : :
1068 [ # # ]: 0 : if (!a->mdns_ptr_rr) {
1069 : 0 : r = dns_resource_record_new_reverse(&a->mdns_ptr_rr, a->family, &a->in_addr, a->link->manager->mdns_hostname);
1070 [ # # ]: 0 : if (r < 0)
1071 : 0 : goto fail;
1072 : :
1073 : 0 : a->mdns_ptr_rr->ttl = MDNS_DEFAULT_TTL;
1074 : : }
1075 : :
1076 : 0 : r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_address_rr, true);
1077 [ # # ]: 0 : if (r < 0)
1078 [ # # ]: 0 : log_warning_errno(r, "Failed to add AAAA record to MDNS zone: %m");
1079 : :
1080 : 0 : r = dns_zone_put(&a->link->mdns_ipv6_scope->zone, a->link->mdns_ipv6_scope, a->mdns_ptr_rr, false);
1081 [ # # ]: 0 : if (r < 0)
1082 [ # # ]: 0 : log_warning_errno(r, "Failed to add IPv6 PTR record to MDNS zone: %m");
1083 : : } else {
1084 [ # # ]: 0 : if (a->mdns_address_rr) {
1085 [ # # ]: 0 : if (a->link->mdns_ipv6_scope)
1086 : 0 : dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_address_rr);
1087 : 0 : a->mdns_address_rr = dns_resource_record_unref(a->mdns_address_rr);
1088 : : }
1089 : :
1090 [ # # ]: 0 : if (a->mdns_ptr_rr) {
1091 [ # # ]: 0 : if (a->link->mdns_ipv6_scope)
1092 : 0 : dns_zone_remove_rr(&a->link->mdns_ipv6_scope->zone, a->mdns_ptr_rr);
1093 : 0 : a->mdns_ptr_rr = dns_resource_record_unref(a->mdns_ptr_rr);
1094 : : }
1095 : : }
1096 : : }
1097 : :
1098 : 0 : return;
1099 : :
1100 : 0 : fail:
1101 [ # # ]: 0 : log_debug_errno(r, "Failed to update address RRs: %m");
1102 : : }
1103 : :
1104 : 0 : int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) {
1105 : : int r;
1106 [ # # ]: 0 : assert(a);
1107 [ # # ]: 0 : assert(m);
1108 : :
1109 : 0 : r = sd_rtnl_message_addr_get_flags(m, &a->flags);
1110 [ # # ]: 0 : if (r < 0)
1111 : 0 : return r;
1112 : :
1113 : 0 : sd_rtnl_message_addr_get_scope(m, &a->scope);
1114 : :
1115 : 0 : link_allocate_scopes(a->link);
1116 : 0 : link_add_rrs(a->link, false);
1117 : :
1118 : 0 : return 0;
1119 : : }
1120 : :
1121 : 0 : bool link_address_relevant(LinkAddress *a, bool local_multicast) {
1122 [ # # ]: 0 : assert(a);
1123 : :
1124 [ # # ]: 0 : if (a->flags & (IFA_F_DEPRECATED|IFA_F_TENTATIVE))
1125 : 0 : return false;
1126 : :
1127 [ # # # # ]: 0 : if (a->scope >= (local_multicast ? RT_SCOPE_HOST : RT_SCOPE_LINK))
1128 : 0 : return false;
1129 : :
1130 : 0 : return true;
1131 : : }
1132 : :
1133 : 0 : static bool link_needs_save(Link *l) {
1134 [ # # ]: 0 : assert(l);
1135 : :
1136 : : /* Returns true if any of the settings where set different from the default */
1137 : :
1138 [ # # ]: 0 : if (l->is_managed)
1139 : 0 : return false;
1140 : :
1141 [ # # ]: 0 : if (l->llmnr_support != RESOLVE_SUPPORT_YES ||
1142 [ # # ]: 0 : l->mdns_support != RESOLVE_SUPPORT_NO ||
1143 [ # # ]: 0 : l->dnssec_mode != _DNSSEC_MODE_INVALID ||
1144 [ # # ]: 0 : l->dns_over_tls_mode != _DNS_OVER_TLS_MODE_INVALID)
1145 : 0 : return true;
1146 : :
1147 [ # # ]: 0 : if (l->dns_servers ||
1148 [ # # ]: 0 : l->search_domains)
1149 : 0 : return true;
1150 : :
1151 [ # # ]: 0 : if (!set_isempty(l->dnssec_negative_trust_anchors))
1152 : 0 : return true;
1153 : :
1154 [ # # ]: 0 : if (l->default_route >= 0)
1155 : 0 : return true;
1156 : :
1157 : 0 : return false;
1158 : : }
1159 : :
1160 : 0 : int link_save_user(Link *l) {
1161 : 0 : _cleanup_free_ char *temp_path = NULL;
1162 : 0 : _cleanup_fclose_ FILE *f = NULL;
1163 : : const char *v;
1164 : : int r;
1165 : :
1166 [ # # ]: 0 : assert(l);
1167 [ # # ]: 0 : assert(l->state_file);
1168 : :
1169 [ # # ]: 0 : if (!link_needs_save(l)) {
1170 : 0 : (void) unlink(l->state_file);
1171 : 0 : return 0;
1172 : : }
1173 : :
1174 : 0 : r = mkdir_parents(l->state_file, 0700);
1175 [ # # ]: 0 : if (r < 0)
1176 : 0 : goto fail;
1177 : :
1178 : 0 : r = fopen_temporary(l->state_file, &f, &temp_path);
1179 [ # # ]: 0 : if (r < 0)
1180 : 0 : goto fail;
1181 : :
1182 : 0 : (void) fchmod(fileno(f), 0644);
1183 : :
1184 : 0 : fputs("# This is private data. Do not parse.\n", f);
1185 : :
1186 : 0 : v = resolve_support_to_string(l->llmnr_support);
1187 [ # # ]: 0 : if (v)
1188 : 0 : fprintf(f, "LLMNR=%s\n", v);
1189 : :
1190 : 0 : v = resolve_support_to_string(l->mdns_support);
1191 [ # # ]: 0 : if (v)
1192 : 0 : fprintf(f, "MDNS=%s\n", v);
1193 : :
1194 : 0 : v = dnssec_mode_to_string(l->dnssec_mode);
1195 [ # # ]: 0 : if (v)
1196 : 0 : fprintf(f, "DNSSEC=%s\n", v);
1197 : :
1198 [ # # ]: 0 : if (l->default_route >= 0)
1199 : 0 : fprintf(f, "DEFAULT_ROUTE=%s\n", yes_no(l->default_route));
1200 : :
1201 [ # # ]: 0 : if (l->dns_servers) {
1202 : : DnsServer *server;
1203 : :
1204 : 0 : fputs("SERVERS=", f);
1205 [ # # ]: 0 : LIST_FOREACH(servers, server, l->dns_servers) {
1206 : :
1207 [ # # ]: 0 : if (server != l->dns_servers)
1208 : 0 : fputc(' ', f);
1209 : :
1210 : 0 : v = dns_server_string(server);
1211 [ # # ]: 0 : if (!v) {
1212 : 0 : r = -ENOMEM;
1213 : 0 : goto fail;
1214 : : }
1215 : :
1216 : 0 : fputs(v, f);
1217 : : }
1218 : 0 : fputc('\n', f);
1219 : : }
1220 : :
1221 [ # # ]: 0 : if (l->search_domains) {
1222 : : DnsSearchDomain *domain;
1223 : :
1224 : 0 : fputs("DOMAINS=", f);
1225 [ # # ]: 0 : LIST_FOREACH(domains, domain, l->search_domains) {
1226 : :
1227 [ # # ]: 0 : if (domain != l->search_domains)
1228 : 0 : fputc(' ', f);
1229 : :
1230 [ # # ]: 0 : if (domain->route_only)
1231 : 0 : fputc('~', f);
1232 : :
1233 : 0 : fputs(DNS_SEARCH_DOMAIN_NAME(domain), f);
1234 : : }
1235 : 0 : fputc('\n', f);
1236 : : }
1237 : :
1238 [ # # ]: 0 : if (!set_isempty(l->dnssec_negative_trust_anchors)) {
1239 : 0 : bool space = false;
1240 : : Iterator i;
1241 : : char *nta;
1242 : :
1243 : 0 : fputs("NTAS=", f);
1244 [ # # ]: 0 : SET_FOREACH(nta, l->dnssec_negative_trust_anchors, i) {
1245 : :
1246 [ # # ]: 0 : if (space)
1247 : 0 : fputc(' ', f);
1248 : :
1249 : 0 : fputs(nta, f);
1250 : 0 : space = true;
1251 : : }
1252 : 0 : fputc('\n', f);
1253 : : }
1254 : :
1255 : 0 : r = fflush_and_check(f);
1256 [ # # ]: 0 : if (r < 0)
1257 : 0 : goto fail;
1258 : :
1259 [ # # ]: 0 : if (rename(temp_path, l->state_file) < 0) {
1260 : 0 : r = -errno;
1261 : 0 : goto fail;
1262 : : }
1263 : :
1264 : 0 : return 0;
1265 : :
1266 : 0 : fail:
1267 : 0 : (void) unlink(l->state_file);
1268 : :
1269 [ # # ]: 0 : if (temp_path)
1270 : 0 : (void) unlink(temp_path);
1271 : :
1272 [ # # ]: 0 : return log_error_errno(r, "Failed to save link data %s: %m", l->state_file);
1273 : : }
1274 : :
1275 : 0 : int link_load_user(Link *l) {
1276 : : _cleanup_free_ char
1277 : 0 : *llmnr = NULL,
1278 : 0 : *mdns = NULL,
1279 : 0 : *dnssec = NULL,
1280 : 0 : *servers = NULL,
1281 : 0 : *domains = NULL,
1282 : 0 : *ntas = NULL,
1283 : 0 : *default_route = NULL;
1284 : :
1285 : : ResolveSupport s;
1286 : : const char *p;
1287 : : int r;
1288 : :
1289 [ # # ]: 0 : assert(l);
1290 [ # # ]: 0 : assert(l->state_file);
1291 : :
1292 : : /* Try to load only a single time */
1293 [ # # ]: 0 : if (l->loaded)
1294 : 0 : return 0;
1295 : 0 : l->loaded = true;
1296 : :
1297 [ # # ]: 0 : if (l->is_managed)
1298 : 0 : return 0; /* if the device is managed, then networkd is our configuration source, not the bus API */
1299 : :
1300 : 0 : r = parse_env_file(NULL, l->state_file,
1301 : : "LLMNR", &llmnr,
1302 : : "MDNS", &mdns,
1303 : : "DNSSEC", &dnssec,
1304 : : "SERVERS", &servers,
1305 : : "DOMAINS", &domains,
1306 : : "NTAS", &ntas,
1307 : : "DEFAULT_ROUTE", &default_route);
1308 [ # # ]: 0 : if (r == -ENOENT)
1309 : 0 : return 0;
1310 [ # # ]: 0 : if (r < 0)
1311 : 0 : goto fail;
1312 : :
1313 : 0 : link_flush_settings(l);
1314 : :
1315 : : /* If we can't recognize the LLMNR or MDNS setting we don't override the default */
1316 : 0 : s = resolve_support_from_string(llmnr);
1317 [ # # ]: 0 : if (s >= 0)
1318 : 0 : l->llmnr_support = s;
1319 : :
1320 : 0 : s = resolve_support_from_string(mdns);
1321 [ # # ]: 0 : if (s >= 0)
1322 : 0 : l->mdns_support = s;
1323 : :
1324 : 0 : r = parse_boolean(default_route);
1325 [ # # ]: 0 : if (r >= 0)
1326 : 0 : l->default_route = r;
1327 : :
1328 : : /* If we can't recognize the DNSSEC setting, then set it to invalid, so that the daemon default is used. */
1329 : 0 : l->dnssec_mode = dnssec_mode_from_string(dnssec);
1330 : :
1331 : 0 : for (p = servers;;) {
1332 [ # # # # ]: 0 : _cleanup_free_ char *word = NULL;
1333 : :
1334 : 0 : r = extract_first_word(&p, &word, NULL, 0);
1335 [ # # ]: 0 : if (r < 0)
1336 : 0 : goto fail;
1337 [ # # ]: 0 : if (r == 0)
1338 : 0 : break;
1339 : :
1340 : 0 : r = link_update_dns_server_one(l, word);
1341 [ # # ]: 0 : if (r < 0) {
1342 [ # # ]: 0 : log_debug_errno(r, "Failed to load DNS server '%s', ignoring: %m", word);
1343 : 0 : continue;
1344 : : }
1345 : : }
1346 : :
1347 : 0 : for (p = domains;;) {
1348 [ # # # # ]: 0 : _cleanup_free_ char *word = NULL;
1349 : : const char *n;
1350 : : bool is_route;
1351 : :
1352 : 0 : r = extract_first_word(&p, &word, NULL, 0);
1353 [ # # ]: 0 : if (r < 0)
1354 : 0 : goto fail;
1355 [ # # ]: 0 : if (r == 0)
1356 : 0 : break;
1357 : :
1358 : 0 : is_route = word[0] == '~';
1359 [ # # ]: 0 : n = is_route ? word + 1 : word;
1360 : :
1361 : 0 : r = link_update_search_domain_one(l, n, is_route);
1362 [ # # ]: 0 : if (r < 0) {
1363 [ # # ]: 0 : log_debug_errno(r, "Failed to load search domain '%s', ignoring: %m", word);
1364 : 0 : continue;
1365 : : }
1366 : : }
1367 : :
1368 [ # # ]: 0 : if (ntas) {
1369 [ # # ]: 0 : _cleanup_set_free_free_ Set *ns = NULL;
1370 : :
1371 : 0 : ns = set_new(&dns_name_hash_ops);
1372 [ # # ]: 0 : if (!ns) {
1373 : 0 : r = -ENOMEM;
1374 : 0 : goto fail;
1375 : : }
1376 : :
1377 : 0 : r = set_put_strsplit(ns, ntas, NULL, 0);
1378 [ # # ]: 0 : if (r < 0)
1379 : 0 : goto fail;
1380 : :
1381 : 0 : l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
1382 : : }
1383 : :
1384 : 0 : return 0;
1385 : :
1386 : 0 : fail:
1387 [ # # ]: 0 : return log_error_errno(r, "Failed to load link data %s: %m", l->state_file);
1388 : : }
1389 : :
1390 : 0 : void link_remove_user(Link *l) {
1391 [ # # ]: 0 : assert(l);
1392 [ # # ]: 0 : assert(l->state_file);
1393 : :
1394 : 0 : (void) unlink(l->state_file);
1395 : 0 : }
|