]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-link-bus.c
strv: make iterator in STRV_FOREACH() declaread in the loop
[thirdparty/systemd.git] / src / resolve / resolved-link-bus.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
3abaabda 2
6ff79f76 3#include <net/if.h>
52aaef0f
ZJS
4#include <netinet/in.h>
5#include <sys/capability.h>
6ff79f76 6
3abaabda 7#include "alloc-util.h"
04b764bf 8#include "bus-common-errors.h"
40af3d02 9#include "bus-get-properties.h"
10d46204 10#include "bus-message-util.h"
269e4d2d 11#include "bus-polkit.h"
0b261ac5 12#include "log-link.h"
3abaabda
LP
13#include "parse-util.h"
14#include "resolve-util.h"
15#include "resolved-bus.h"
16#include "resolved-link-bus.h"
7207052d 17#include "resolved-resolv-conf.h"
95ce1ba8 18#include "socket-netlink.h"
0a6c0745 19#include "stdio-util.h"
3abaabda 20#include "strv.h"
52aaef0f 21#include "user-util.h"
3abaabda 22
acd380c4
YW
23static BUS_DEFINE_PROPERTY_GET(property_get_dnssec_supported, "b", Link, link_dnssec_supported);
24static BUS_DEFINE_PROPERTY_GET2(property_get_dnssec_mode, "s", Link, link_get_dnssec_mode, dnssec_mode_to_string);
3abaabda 25
c9299be2 26static int property_get_dns_over_tls_mode(
d050561a
IT
27 sd_bus *bus,
28 const char *path,
29 const char *interface,
30 const char *property,
31 sd_bus_message *reply,
32 void *userdata,
33 sd_bus_error *error) {
34
35 Link *l = userdata;
36
37 assert(reply);
38 assert(l);
39
c9299be2 40 return sd_bus_message_append(reply, "s", dns_over_tls_mode_to_string(link_get_dns_over_tls_mode(l)));
d050561a
IT
41}
42
8e56ea4c 43static int property_get_dns_internal(
3abaabda
LP
44 sd_bus *bus,
45 const char *path,
46 const char *interface,
47 const char *property,
48 sd_bus_message *reply,
49 void *userdata,
8e56ea4c
YW
50 sd_bus_error *error,
51 bool extended) {
3abaabda
LP
52
53 Link *l = userdata;
3abaabda
LP
54 int r;
55
56 assert(reply);
57 assert(l);
58
8e56ea4c 59 r = sd_bus_message_open_container(reply, 'a', extended ? "(iayqs)" : "(iay)");
3abaabda
LP
60 if (r < 0)
61 return r;
62
63 LIST_FOREACH(servers, s, l->dns_servers) {
8e56ea4c 64 r = bus_dns_server_append(reply, s, false, extended);
3abaabda
LP
65 if (r < 0)
66 return r;
67 }
68
69 return sd_bus_message_close_container(reply);
70}
71
8e56ea4c
YW
72static int property_get_dns(
73 sd_bus *bus,
74 const char *path,
75 const char *interface,
76 const char *property,
77 sd_bus_message *reply,
78 void *userdata,
79 sd_bus_error *error) {
80 return property_get_dns_internal(bus, path, interface, property, reply, userdata, error, false);
81}
82
83static int property_get_dns_ex(
b7ac92cd
YW
84 sd_bus *bus,
85 const char *path,
86 const char *interface,
87 const char *property,
88 sd_bus_message *reply,
89 void *userdata,
90 sd_bus_error *error) {
8e56ea4c
YW
91 return property_get_dns_internal(bus, path, interface, property, reply, userdata, error, true);
92}
93
94static int property_get_current_dns_server_internal(
95 sd_bus *bus,
96 const char *path,
97 const char *interface,
98 const char *property,
99 sd_bus_message *reply,
100 void *userdata,
101 sd_bus_error *error,
102 bool extended) {
b7ac92cd
YW
103
104 DnsServer *s;
105
106 assert(reply);
107 assert(userdata);
108
109 s = *(DnsServer **) userdata;
110
8e56ea4c
YW
111 return bus_dns_server_append(reply, s, false, extended);
112}
113
114static int property_get_current_dns_server(
115 sd_bus *bus,
116 const char *path,
117 const char *interface,
118 const char *property,
119 sd_bus_message *reply,
120 void *userdata,
121 sd_bus_error *error) {
122 return property_get_current_dns_server_internal(bus, path, interface, property, reply, userdata, error, false);
123}
124
125static int property_get_current_dns_server_ex(
126 sd_bus *bus,
127 const char *path,
128 const char *interface,
129 const char *property,
130 sd_bus_message *reply,
131 void *userdata,
132 sd_bus_error *error) {
133 return property_get_current_dns_server_internal(bus, path, interface, property, reply, userdata, error, true);
b7ac92cd
YW
134}
135
3abaabda
LP
136static int property_get_domains(
137 sd_bus *bus,
138 const char *path,
139 const char *interface,
140 const char *property,
141 sd_bus_message *reply,
142 void *userdata,
143 sd_bus_error *error) {
144
145 Link *l = userdata;
3abaabda
LP
146 int r;
147
148 assert(reply);
149 assert(l);
150
ad44b56b 151 r = sd_bus_message_open_container(reply, 'a', "(sb)");
3abaabda
LP
152 if (r < 0)
153 return r;
154
155 LIST_FOREACH(domains, d, l->search_domains) {
ad44b56b 156 r = sd_bus_message_append(reply, "(sb)", d->name, d->route_only);
3abaabda
LP
157 if (r < 0)
158 return r;
159 }
160
161 return sd_bus_message_close_container(reply);
162}
163
77673795
LP
164static int property_get_default_route(
165 sd_bus *bus,
166 const char *path,
167 const char *interface,
168 const char *property,
169 sd_bus_message *reply,
170 void *userdata,
171 sd_bus_error *error) {
172
173 Link *l = userdata;
174
175 assert(reply);
176 assert(l);
177
178 /* Return what is configured, if there's something configured */
179 if (l->default_route >= 0)
180 return sd_bus_message_append(reply, "b", l->default_route);
181
182 /* Otherwise report what is in effect */
183 if (l->unicast_scope)
184 return sd_bus_message_append(reply, "b", dns_scope_is_default_route(l->unicast_scope));
185
186 return sd_bus_message_append(reply, "b", false);
187}
188
3abaabda
LP
189static int property_get_scopes_mask(
190 sd_bus *bus,
191 const char *path,
192 const char *interface,
193 const char *property,
194 sd_bus_message *reply,
195 void *userdata,
196 sd_bus_error *error) {
197
198 Link *l = userdata;
199 uint64_t mask;
200
201 assert(reply);
202 assert(l);
203
204 mask = (l->unicast_scope ? SD_RESOLVED_DNS : 0) |
205 (l->llmnr_ipv4_scope ? SD_RESOLVED_LLMNR_IPV4 : 0) |
206 (l->llmnr_ipv6_scope ? SD_RESOLVED_LLMNR_IPV6 : 0) |
207 (l->mdns_ipv4_scope ? SD_RESOLVED_MDNS_IPV4 : 0) |
208 (l->mdns_ipv6_scope ? SD_RESOLVED_MDNS_IPV6 : 0);
209
210 return sd_bus_message_append(reply, "t", mask);
211}
212
213static int property_get_ntas(
214 sd_bus *bus,
215 const char *path,
216 const char *interface,
217 const char *property,
218 sd_bus_message *reply,
219 void *userdata,
220 sd_bus_error *error) {
221
222 Link *l = userdata;
223 const char *name;
3abaabda
LP
224 int r;
225
226 assert(reply);
227 assert(l);
228
229 r = sd_bus_message_open_container(reply, 'a', "s");
230 if (r < 0)
231 return r;
232
90e74a66 233 SET_FOREACH(name, l->dnssec_negative_trust_anchors) {
3abaabda
LP
234 r = sd_bus_message_append(reply, "s", name);
235 if (r < 0)
236 return r;
237 }
238
239 return sd_bus_message_close_container(reply);
240}
241
04b764bf
LP
242static int verify_unmanaged_link(Link *l, sd_bus_error *error) {
243 assert(l);
244
245 if (l->flags & IFF_LOOPBACK)
6ff79f76 246 return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->ifname);
04b764bf 247 if (l->is_managed)
6ff79f76 248 return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is managed.", l->ifname);
04b764bf
LP
249
250 return 0;
251}
252
95ce1ba8 253static int bus_link_method_set_dns_servers_internal(sd_bus_message *message, void *userdata, sd_bus_error *error, bool extended) {
0b261ac5 254 _cleanup_free_ char *j = NULL;
10d46204 255 struct in_addr_full **dns;
cbf23f38 256 bool changed = false;
d2ec6608 257 Link *l = userdata;
10d46204 258 size_t n;
d2ec6608
LP
259 int r;
260
261 assert(message);
262 assert(l);
263
04b764bf
LP
264 r = verify_unmanaged_link(l, error);
265 if (r < 0)
266 return r;
267
10d46204 268 r = bus_message_read_dns_servers(message, error, extended, &dns, &n);
d2ec6608
LP
269 if (r < 0)
270 return r;
271
52aaef0f
ZJS
272 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
273 "org.freedesktop.resolve1.set-dns-servers",
274 NULL, true, UID_INVALID,
275 &l->manager->polkit_registry, error);
276 if (r < 0)
95ce1ba8
YW
277 goto finalize;
278 if (r == 0) {
279 r = 1; /* Polkit will call us back */
280 goto finalize;
281 }
52aaef0f 282
0b261ac5
LP
283 for (size_t i = 0; i < n; i++) {
284 const char *s;
285
286 s = in_addr_full_to_string(dns[i]);
287 if (!s) {
288 r = -ENOMEM;
289 goto finalize;
290 }
291
c2bc710b 292 if (!strextend_with_separator(&j, ", ", s)) {
0b261ac5
LP
293 r = -ENOMEM;
294 goto finalize;
295 }
296 }
297
1e69eadd
LP
298 bus_client_log(message, "DNS server change");
299
d2ec6608
LP
300 dns_server_mark_all(l->dns_servers);
301
95ce1ba8 302 for (size_t i = 0; i < n; i++) {
d2ec6608
LP
303 DnsServer *s;
304
95ce1ba8 305 s = dns_server_find(l->dns_servers, dns[i]->family, &dns[i]->address, dns[i]->port, 0, dns[i]->server_name);
d2ec6608
LP
306 if (s)
307 dns_server_move_back_and_unmark(s);
308 else {
95ce1ba8
YW
309 r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i]->family, &dns[i]->address, dns[i]->port, 0, dns[i]->server_name);
310 if (r < 0) {
311 dns_server_unlink_all(l->dns_servers);
312 goto finalize;
313 }
cbf23f38
LP
314
315 changed = true;
d2ec6608
LP
316 }
317
318 }
319
cbf23f38
LP
320 changed = dns_server_unlink_marked(l->dns_servers) || changed;
321
322 if (changed) {
323 link_allocate_scopes(l);
d2ec6608 324
cbf23f38
LP
325 (void) link_save_user(l);
326 (void) manager_write_resolv_conf(l->manager);
327 (void) manager_send_changed(l->manager, "DNS");
7207052d 328
cbf23f38
LP
329 if (j)
330 log_link_info(l, "Bus client set DNS server list to: %s", j);
331 else
332 log_link_info(l, "Bus client reset DNS server list.");
333 }
0b261ac5 334
95ce1ba8
YW
335 r = sd_bus_reply_method_return(message, NULL);
336
337finalize:
338 for (size_t i = 0; i < n; i++)
339 in_addr_full_free(dns[i]);
340 free(dns);
d2ec6608 341
d2ec6608
LP
342 return r;
343}
344
95ce1ba8
YW
345int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
346 return bus_link_method_set_dns_servers_internal(message, userdata, error, false);
347}
348
349int bus_link_method_set_dns_servers_ex(sd_bus_message *message, void *userdata, sd_bus_error *error) {
350 return bus_link_method_set_dns_servers_internal(message, userdata, error, true);
351}
352
ee116b54 353int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
0b261ac5 354 _cleanup_free_ char *j = NULL;
d2ec6608 355 Link *l = userdata;
cbf23f38 356 bool changed = false;
d2ec6608
LP
357 int r;
358
359 assert(message);
360 assert(l);
361
04b764bf
LP
362 r = verify_unmanaged_link(l, error);
363 if (r < 0)
364 return r;
365
ad44b56b 366 r = sd_bus_message_enter_container(message, 'a', "(sb)");
d2ec6608
LP
367 if (r < 0)
368 return r;
369
ad44b56b 370 for (;;) {
0b261ac5 371 _cleanup_free_ char *prefixed = NULL;
ad44b56b
LP
372 const char *name;
373 int route_only;
d2ec6608 374
ad44b56b 375 r = sd_bus_message_read(message, "(sb)", &name, &route_only);
d2ec6608
LP
376 if (r < 0)
377 return r;
378 if (r == 0)
ad44b56b
LP
379 break;
380
381 r = dns_name_is_valid(name);
382 if (r < 0)
383 return r;
384 if (r == 0)
385 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
386 if (!route_only && dns_name_is_root(name))
1b09b81c 387 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
0b261ac5
LP
388
389 if (route_only) {
390 prefixed = strjoin("~", name);
391 if (!prefixed)
392 return -ENOMEM;
393
394 name = prefixed;
395 }
396
c2bc710b 397 if (!strextend_with_separator(&j, ", ", name))
0b261ac5 398 return -ENOMEM;
d2ec6608
LP
399 }
400
ad44b56b
LP
401 r = sd_bus_message_rewind(message, false);
402 if (r < 0)
403 return r;
404
52aaef0f
ZJS
405 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
406 "org.freedesktop.resolve1.set-domains",
407 NULL, true, UID_INVALID,
408 &l->manager->polkit_registry, error);
409 if (r < 0)
410 return r;
411 if (r == 0)
412 return 1; /* Polkit will call us back */
413
1e69eadd
LP
414 bus_client_log(message, "dns domains change");
415
52aaef0f
ZJS
416 dns_search_domain_mark_all(l->search_domains);
417
ad44b56b 418 for (;;) {
d2ec6608 419 DnsSearchDomain *d;
ad44b56b
LP
420 const char *name;
421 int route_only;
d2ec6608 422
ad44b56b
LP
423 r = sd_bus_message_read(message, "(sb)", &name, &route_only);
424 if (r < 0)
425 goto clear;
426 if (r == 0)
427 break;
428
429 r = dns_search_domain_find(l->search_domains, name, &d);
d2ec6608
LP
430 if (r < 0)
431 goto clear;
432
433 if (r > 0)
434 dns_search_domain_move_back_and_unmark(d);
435 else {
ad44b56b 436 r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
d2ec6608
LP
437 if (r < 0)
438 goto clear;
cbf23f38
LP
439
440 changed = true;
d2ec6608 441 }
ad44b56b
LP
442
443 d->route_only = route_only;
d2ec6608
LP
444 }
445
ad44b56b
LP
446 r = sd_bus_message_exit_container(message);
447 if (r < 0)
448 goto clear;
449
cbf23f38 450 changed = dns_search_domain_unlink_marked(l->search_domains) || changed;
7207052d 451
cbf23f38
LP
452 if (changed) {
453 (void) link_save_user(l);
454 (void) manager_write_resolv_conf(l->manager);
7207052d 455
cbf23f38
LP
456 if (j)
457 log_link_info(l, "Bus client set search domain list to: %s", j);
458 else
459 log_link_info(l, "Bus client reset search domain list.");
460 }
0b261ac5 461
d2ec6608
LP
462 return sd_bus_reply_method_return(message, NULL);
463
464clear:
465 dns_search_domain_unlink_all(l->search_domains);
466 return r;
467}
468
77673795
LP
469int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) {
470 Link *l = userdata;
471 int r, b;
472
473 assert(message);
474 assert(l);
475
476 r = verify_unmanaged_link(l, error);
477 if (r < 0)
478 return r;
479
480 r = sd_bus_message_read(message, "b", &b);
481 if (r < 0)
482 return r;
483
52aaef0f
ZJS
484 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
485 "org.freedesktop.resolve1.set-default-route",
486 NULL, true, UID_INVALID,
487 &l->manager->polkit_registry, error);
488 if (r < 0)
489 return r;
490 if (r == 0)
491 return 1; /* Polkit will call us back */
492
1e69eadd
LP
493 bus_client_log(message, "dns default route change");
494
77673795
LP
495 if (l->default_route != b) {
496 l->default_route = b;
497
498 (void) link_save_user(l);
499 (void) manager_write_resolv_conf(l->manager);
77673795 500
cbf23f38
LP
501 log_link_info(l, "Bus client set default route setting: %s", yes_no(b));
502 }
0b261ac5 503
77673795
LP
504 return sd_bus_reply_method_return(message, NULL);
505}
506
d2ec6608
LP
507int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
508 Link *l = userdata;
509 ResolveSupport mode;
510 const char *llmnr;
511 int r;
512
513 assert(message);
514 assert(l);
515
04b764bf
LP
516 r = verify_unmanaged_link(l, error);
517 if (r < 0)
518 return r;
519
d2ec6608
LP
520 r = sd_bus_message_read(message, "s", &llmnr);
521 if (r < 0)
522 return r;
523
524 if (isempty(llmnr))
525 mode = RESOLVE_SUPPORT_YES;
526 else {
527 mode = resolve_support_from_string(llmnr);
528 if (mode < 0)
529 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr);
530 }
531
52aaef0f
ZJS
532 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
533 "org.freedesktop.resolve1.set-llmnr",
534 NULL, true, UID_INVALID,
535 &l->manager->polkit_registry, error);
536 if (r < 0)
537 return r;
538 if (r == 0)
539 return 1; /* Polkit will call us back */
540
1e69eadd
LP
541 bus_client_log(message, "LLMNR change");
542
cbf23f38
LP
543 if (l->llmnr_support != mode) {
544 l->llmnr_support = mode;
545 link_allocate_scopes(l);
546 link_add_rrs(l, false);
d2ec6608 547
cbf23f38 548 (void) link_save_user(l);
943ef07c 549
cbf23f38
LP
550 log_link_info(l, "Bus client set LLMNR setting: %s", resolve_support_to_string(mode));
551 }
0b261ac5 552
d2ec6608
LP
553 return sd_bus_reply_method_return(message, NULL);
554}
555
556int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
557 Link *l = userdata;
558 ResolveSupport mode;
559 const char *mdns;
560 int r;
561
562 assert(message);
563 assert(l);
564
04b764bf
LP
565 r = verify_unmanaged_link(l, error);
566 if (r < 0)
567 return r;
568
d2ec6608
LP
569 r = sd_bus_message_read(message, "s", &mdns);
570 if (r < 0)
571 return r;
572
573 if (isempty(mdns))
574 mode = RESOLVE_SUPPORT_NO;
575 else {
576 mode = resolve_support_from_string(mdns);
577 if (mode < 0)
578 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns);
579 }
580
52aaef0f
ZJS
581 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
582 "org.freedesktop.resolve1.set-mdns",
583 NULL, true, UID_INVALID,
584 &l->manager->polkit_registry, error);
585 if (r < 0)
586 return r;
587 if (r == 0)
588 return 1; /* Polkit will call us back */
589
1e69eadd
LP
590 bus_client_log(message, "mDNS change");
591
cbf23f38
LP
592 if (l->mdns_support != mode) {
593 l->mdns_support = mode;
594 link_allocate_scopes(l);
595 link_add_rrs(l, false);
d2ec6608 596
cbf23f38 597 (void) link_save_user(l);
943ef07c 598
cbf23f38
LP
599 log_link_info(l, "Bus client set MulticastDNS setting: %s", resolve_support_to_string(mode));
600 }
0b261ac5 601
d2ec6608
LP
602 return sd_bus_reply_method_return(message, NULL);
603}
604
c9299be2 605int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d050561a 606 Link *l = userdata;
c9299be2
IT
607 const char *dns_over_tls;
608 DnsOverTlsMode mode;
d050561a
IT
609 int r;
610
611 assert(message);
612 assert(l);
613
614 r = verify_unmanaged_link(l, error);
615 if (r < 0)
616 return r;
617
c9299be2 618 r = sd_bus_message_read(message, "s", &dns_over_tls);
d050561a
IT
619 if (r < 0)
620 return r;
621
c9299be2
IT
622 if (isempty(dns_over_tls))
623 mode = _DNS_OVER_TLS_MODE_INVALID;
d050561a 624 else {
c9299be2 625 mode = dns_over_tls_mode_from_string(dns_over_tls);
d050561a 626 if (mode < 0)
c9299be2 627 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSOverTLS setting: %s", dns_over_tls);
d050561a
IT
628 }
629
52aaef0f
ZJS
630 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
631 "org.freedesktop.resolve1.set-dns-over-tls",
632 NULL, true, UID_INVALID,
633 &l->manager->polkit_registry, error);
634 if (r < 0)
635 return r;
636 if (r == 0)
637 return 1; /* Polkit will call us back */
638
1e69eadd
LP
639 bus_client_log(message, "D-o-T change");
640
cbf23f38
LP
641 if (l->dns_over_tls_mode != mode) {
642 link_set_dns_over_tls_mode(l, mode);
d050561a 643
cbf23f38 644 (void) link_save_user(l);
d050561a 645
cbf23f38
LP
646 log_link_info(l, "Bus client set DNSOverTLS setting: %s",
647 mode < 0 ? "default" : dns_over_tls_mode_to_string(mode));
648 }
0b261ac5 649
d050561a
IT
650 return sd_bus_reply_method_return(message, NULL);
651}
652
d2ec6608
LP
653int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
654 Link *l = userdata;
655 const char *dnssec;
656 DnssecMode mode;
657 int r;
658
659 assert(message);
660 assert(l);
661
04b764bf
LP
662 r = verify_unmanaged_link(l, error);
663 if (r < 0)
664 return r;
665
d2ec6608
LP
666 r = sd_bus_message_read(message, "s", &dnssec);
667 if (r < 0)
668 return r;
669
670 if (isempty(dnssec))
671 mode = _DNSSEC_MODE_INVALID;
672 else {
673 mode = dnssec_mode_from_string(dnssec);
674 if (mode < 0)
675 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec);
676 }
677
52aaef0f
ZJS
678 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
679 "org.freedesktop.resolve1.set-dnssec",
680 NULL, true, UID_INVALID,
681 &l->manager->polkit_registry, error);
682 if (r < 0)
683 return r;
684 if (r == 0)
685 return 1; /* Polkit will call us back */
686
1e69eadd
LP
687 bus_client_log(message, "DNSSEC change");
688
cbf23f38
LP
689 if (l->dnssec_mode != mode) {
690 link_set_dnssec_mode(l, mode);
d2ec6608 691
cbf23f38 692 (void) link_save_user(l);
943ef07c 693
cbf23f38
LP
694 log_link_info(l, "Bus client set DNSSEC setting: %s",
695 mode < 0 ? "default" : dnssec_mode_to_string(mode));
696 }
0b261ac5 697
d2ec6608
LP
698 return sd_bus_reply_method_return(message, NULL);
699}
700
701int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
702 _cleanup_set_free_free_ Set *ns = NULL;
c6d92582 703 _cleanup_strv_free_ char **ntas = NULL;
0b261ac5 704 _cleanup_free_ char *j = NULL;
d2ec6608
LP
705 Link *l = userdata;
706 int r;
d2ec6608
LP
707
708 assert(message);
709 assert(l);
710
04b764bf
LP
711 r = verify_unmanaged_link(l, error);
712 if (r < 0)
713 return r;
714
ab77c879
ZJS
715 ns = set_new(&dns_name_hash_ops);
716 if (!ns)
717 return -ENOMEM;
718
d2ec6608
LP
719 r = sd_bus_message_read_strv(message, &ntas);
720 if (r < 0)
721 return r;
722
723 STRV_FOREACH(i, ntas) {
724 r = dns_name_is_valid(*i);
725 if (r < 0)
726 return r;
727 if (r == 0)
ab77c879
ZJS
728 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
729 "Invalid negative trust anchor domain: %s", *i);
d2ec6608 730
be327321 731 r = set_put_strdup(&ns, *i);
d2ec6608
LP
732 if (r < 0)
733 return r;
0b261ac5 734
c2bc710b 735 if (!strextend_with_separator(&j, ", ", *i))
0b261ac5 736 return -ENOMEM;
d2ec6608
LP
737 }
738
52aaef0f
ZJS
739 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
740 "org.freedesktop.resolve1.set-dnssec-negative-trust-anchors",
741 NULL, true, UID_INVALID,
742 &l->manager->polkit_registry, error);
743 if (r < 0)
744 return r;
745 if (r == 0)
746 return 1; /* Polkit will call us back */
747
1e69eadd
LP
748 bus_client_log(message, "DNSSEC NTA change");
749
cbf23f38
LP
750 if (!set_equal(ns, l->dnssec_negative_trust_anchors)) {
751 set_free_free(l->dnssec_negative_trust_anchors);
752 l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
d2ec6608 753
cbf23f38 754 (void) link_save_user(l);
943ef07c 755
cbf23f38
LP
756 if (j)
757 log_link_info(l, "Bus client set NTA list to: %s", j);
758 else
759 log_link_info(l, "Bus client reset NTA list.");
760 }
0b261ac5 761
d2ec6608
LP
762 return sd_bus_reply_method_return(message, NULL);
763}
764
765int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error) {
766 Link *l = userdata;
04b764bf 767 int r;
d2ec6608
LP
768
769 assert(message);
770 assert(l);
771
04b764bf
LP
772 r = verify_unmanaged_link(l, error);
773 if (r < 0)
774 return r;
775
52aaef0f
ZJS
776 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
777 "org.freedesktop.resolve1.revert",
778 NULL, true, UID_INVALID,
779 &l->manager->polkit_registry, error);
780 if (r < 0)
781 return r;
782 if (r == 0)
783 return 1; /* Polkit will call us back */
784
1e69eadd
LP
785 bus_client_log(message, "revert");
786
d2ec6608
LP
787 link_flush_settings(l);
788 link_allocate_scopes(l);
789 link_add_rrs(l, false);
790
943ef07c 791 (void) link_save_user(l);
7207052d 792 (void) manager_write_resolv_conf(l->manager);
5f3340ca 793 (void) manager_send_changed(l->manager, "DNS");
7207052d 794
d2ec6608
LP
795 return sd_bus_reply_method_return(message, NULL);
796}
797
8d128089 798static int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
3abaabda
LP
799 _cleanup_free_ char *e = NULL;
800 Manager *m = userdata;
3abaabda 801 Link *link;
597da51b 802 int ifindex, r;
3abaabda
LP
803
804 assert(bus);
805 assert(path);
806 assert(interface);
807 assert(found);
808 assert(m);
809
810 r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/link", &e);
811 if (r <= 0)
812 return 0;
813
597da51b
ZJS
814 ifindex = parse_ifindex(e);
815 if (ifindex < 0)
3abaabda
LP
816 return 0;
817
818 link = hashmap_get(m->links, INT_TO_PTR(ifindex));
819 if (!link)
820 return 0;
821
822 *found = link;
823 return 1;
824}
825
0a6c0745
ZJS
826char *link_bus_path(const Link *link) {
827 char *p, ifindex[DECIMAL_STR_MAX(link->ifindex)];
3abaabda
LP
828 int r;
829
830 assert(link);
831
0a6c0745 832 xsprintf(ifindex, "%i", link->ifindex);
3abaabda
LP
833
834 r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifindex, &p);
835 if (r < 0)
836 return NULL;
837
838 return p;
839}
840
8d128089 841static int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
3abaabda
LP
842 _cleanup_strv_free_ char **l = NULL;
843 Manager *m = userdata;
844 Link *link;
3abaabda
LP
845 unsigned c = 0;
846
847 assert(bus);
848 assert(path);
849 assert(m);
850 assert(nodes);
851
852 l = new0(char*, hashmap_size(m->links) + 1);
853 if (!l)
854 return -ENOMEM;
855
90e74a66 856 HASHMAP_FOREACH(link, m->links) {
3abaabda
LP
857 char *p;
858
859 p = link_bus_path(link);
860 if (!p)
861 return -ENOMEM;
862
863 l[c++] = p;
864 }
865
866 l[c] = NULL;
ae2a15bc 867 *nodes = TAKE_PTR(l);
3abaabda
LP
868
869 return 1;
870}
8d128089
ZJS
871
872static const sd_bus_vtable link_vtable[] = {
873 SD_BUS_VTABLE_START(0),
874
875 SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0),
876 SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0),
8e56ea4c 877 SD_BUS_PROPERTY("DNSEx", "a(iayqs)", property_get_dns_ex, 0, 0),
8d128089 878 SD_BUS_PROPERTY("CurrentDNSServer", "(iay)", property_get_current_dns_server, offsetof(Link, current_dns_server), 0),
8e56ea4c 879 SD_BUS_PROPERTY("CurrentDNSServerEx", "(iayqs)", property_get_current_dns_server_ex, offsetof(Link, current_dns_server), 0),
8d128089
ZJS
880 SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0),
881 SD_BUS_PROPERTY("DefaultRoute", "b", property_get_default_route, 0, 0),
882 SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Link, llmnr_support), 0),
883 SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Link, mdns_support), 0),
884 SD_BUS_PROPERTY("DNSOverTLS", "s", property_get_dns_over_tls_mode, 0, 0),
885 SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, 0, 0),
886 SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0),
887 SD_BUS_PROPERTY("DNSSECSupported", "b", property_get_dnssec_supported, 0, 0),
888
ba5a389d
ZJS
889 SD_BUS_METHOD_WITH_ARGS("SetDNS",
890 SD_BUS_ARGS("a(iay)", addresses),
891 SD_BUS_NO_RESULT,
892 bus_link_method_set_dns_servers,
893 SD_BUS_VTABLE_UNPRIVILEGED),
95ce1ba8
YW
894 SD_BUS_METHOD_WITH_ARGS("SetDNSEx",
895 SD_BUS_ARGS("a(iayqs)", addresses),
896 SD_BUS_NO_RESULT,
897 bus_link_method_set_dns_servers_ex,
898 SD_BUS_VTABLE_UNPRIVILEGED),
ba5a389d
ZJS
899 SD_BUS_METHOD_WITH_ARGS("SetDomains",
900 SD_BUS_ARGS("a(sb)", domains),
901 SD_BUS_NO_RESULT,
902 bus_link_method_set_domains,
903 SD_BUS_VTABLE_UNPRIVILEGED),
904 SD_BUS_METHOD_WITH_ARGS("SetDefaultRoute",
905 SD_BUS_ARGS("b", enable),
906 SD_BUS_NO_RESULT,
907 bus_link_method_set_default_route,
908 SD_BUS_VTABLE_UNPRIVILEGED),
909 SD_BUS_METHOD_WITH_ARGS("SetLLMNR",
910 SD_BUS_ARGS("s", mode),
911 SD_BUS_NO_RESULT,
912 bus_link_method_set_llmnr,
913 SD_BUS_VTABLE_UNPRIVILEGED),
914 SD_BUS_METHOD_WITH_ARGS("SetMulticastDNS",
915 SD_BUS_ARGS("s", mode),
916 SD_BUS_NO_RESULT,
917 bus_link_method_set_mdns,
918 SD_BUS_VTABLE_UNPRIVILEGED),
919 SD_BUS_METHOD_WITH_ARGS("SetDNSOverTLS",
920 SD_BUS_ARGS("s", mode),
921 SD_BUS_NO_RESULT,
922 bus_link_method_set_dns_over_tls,
923 SD_BUS_VTABLE_UNPRIVILEGED),
924 SD_BUS_METHOD_WITH_ARGS("SetDNSSEC",
925 SD_BUS_ARGS("s", mode),
926 SD_BUS_NO_RESULT,
927 bus_link_method_set_dnssec,
928 SD_BUS_VTABLE_UNPRIVILEGED),
929 SD_BUS_METHOD_WITH_ARGS("SetDNSSECNegativeTrustAnchors",
930 SD_BUS_ARGS("as", names),
931 SD_BUS_NO_RESULT,
932 bus_link_method_set_dnssec_negative_trust_anchors,
933 SD_BUS_VTABLE_UNPRIVILEGED),
934 SD_BUS_METHOD_WITH_ARGS("Revert",
935 SD_BUS_NO_ARGS,
936 SD_BUS_NO_RESULT,
937 bus_link_method_revert,
938 SD_BUS_VTABLE_UNPRIVILEGED),
8d128089
ZJS
939
940 SD_BUS_VTABLE_END
941};
942
943const BusObjectImplementation link_object = {
944 "/org/freedesktop/resolve1/link",
945 "org.freedesktop.resolve1.Link",
946 .fallback_vtables = BUS_FALLBACK_VTABLES({link_vtable, link_object_find}),
947 .node_enumerator = link_node_enumerator,
948};