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