]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-link-bus.c
resolved: allow access to Set*Link and Revert methods through polkit
[thirdparty/systemd.git] / src / resolve / resolved-link-bus.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
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"
3abaabda
LP
9#include "bus-util.h"
10#include "parse-util.h"
11#include "resolve-util.h"
12#include "resolved-bus.h"
13#include "resolved-link-bus.h"
7207052d 14#include "resolved-resolv-conf.h"
3abaabda 15#include "strv.h"
52aaef0f 16#include "user-util.h"
3abaabda 17
acd380c4
YW
18static BUS_DEFINE_PROPERTY_GET(property_get_dnssec_supported, "b", Link, link_dnssec_supported);
19static BUS_DEFINE_PROPERTY_GET2(property_get_dnssec_mode, "s", Link, link_get_dnssec_mode, dnssec_mode_to_string);
3abaabda 20
c9299be2 21static int property_get_dns_over_tls_mode(
d050561a
IT
22 sd_bus *bus,
23 const char *path,
24 const char *interface,
25 const char *property,
26 sd_bus_message *reply,
27 void *userdata,
28 sd_bus_error *error) {
29
30 Link *l = userdata;
31
32 assert(reply);
33 assert(l);
34
c9299be2 35 return sd_bus_message_append(reply, "s", dns_over_tls_mode_to_string(link_get_dns_over_tls_mode(l)));
d050561a
IT
36}
37
3abaabda
LP
38static int property_get_dns(
39 sd_bus *bus,
40 const char *path,
41 const char *interface,
42 const char *property,
43 sd_bus_message *reply,
44 void *userdata,
45 sd_bus_error *error) {
46
47 Link *l = userdata;
48 DnsServer *s;
49 int r;
50
51 assert(reply);
52 assert(l);
53
54 r = sd_bus_message_open_container(reply, 'a', "(iay)");
55 if (r < 0)
56 return r;
57
58 LIST_FOREACH(servers, s, l->dns_servers) {
59 r = bus_dns_server_append(reply, s, false);
60 if (r < 0)
61 return r;
62 }
63
64 return sd_bus_message_close_container(reply);
65}
66
b7ac92cd
YW
67static int property_get_current_dns_server(
68 sd_bus *bus,
69 const char *path,
70 const char *interface,
71 const char *property,
72 sd_bus_message *reply,
73 void *userdata,
74 sd_bus_error *error) {
75
76 DnsServer *s;
77
78 assert(reply);
79 assert(userdata);
80
81 s = *(DnsServer **) userdata;
82
83 return bus_dns_server_append(reply, s, false);
84}
85
3abaabda
LP
86static int property_get_domains(
87 sd_bus *bus,
88 const char *path,
89 const char *interface,
90 const char *property,
91 sd_bus_message *reply,
92 void *userdata,
93 sd_bus_error *error) {
94
95 Link *l = userdata;
96 DnsSearchDomain *d;
97 int r;
98
99 assert(reply);
100 assert(l);
101
ad44b56b 102 r = sd_bus_message_open_container(reply, 'a', "(sb)");
3abaabda
LP
103 if (r < 0)
104 return r;
105
106 LIST_FOREACH(domains, d, l->search_domains) {
ad44b56b 107 r = sd_bus_message_append(reply, "(sb)", d->name, d->route_only);
3abaabda
LP
108 if (r < 0)
109 return r;
110 }
111
112 return sd_bus_message_close_container(reply);
113}
114
77673795
LP
115static int property_get_default_route(
116 sd_bus *bus,
117 const char *path,
118 const char *interface,
119 const char *property,
120 sd_bus_message *reply,
121 void *userdata,
122 sd_bus_error *error) {
123
124 Link *l = userdata;
125
126 assert(reply);
127 assert(l);
128
129 /* Return what is configured, if there's something configured */
130 if (l->default_route >= 0)
131 return sd_bus_message_append(reply, "b", l->default_route);
132
133 /* Otherwise report what is in effect */
134 if (l->unicast_scope)
135 return sd_bus_message_append(reply, "b", dns_scope_is_default_route(l->unicast_scope));
136
137 return sd_bus_message_append(reply, "b", false);
138}
139
3abaabda
LP
140static int property_get_scopes_mask(
141 sd_bus *bus,
142 const char *path,
143 const char *interface,
144 const char *property,
145 sd_bus_message *reply,
146 void *userdata,
147 sd_bus_error *error) {
148
149 Link *l = userdata;
150 uint64_t mask;
151
152 assert(reply);
153 assert(l);
154
155 mask = (l->unicast_scope ? SD_RESOLVED_DNS : 0) |
156 (l->llmnr_ipv4_scope ? SD_RESOLVED_LLMNR_IPV4 : 0) |
157 (l->llmnr_ipv6_scope ? SD_RESOLVED_LLMNR_IPV6 : 0) |
158 (l->mdns_ipv4_scope ? SD_RESOLVED_MDNS_IPV4 : 0) |
159 (l->mdns_ipv6_scope ? SD_RESOLVED_MDNS_IPV6 : 0);
160
161 return sd_bus_message_append(reply, "t", mask);
162}
163
164static int property_get_ntas(
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 const char *name;
175 Iterator i;
176 int r;
177
178 assert(reply);
179 assert(l);
180
181 r = sd_bus_message_open_container(reply, 'a', "s");
182 if (r < 0)
183 return r;
184
185 SET_FOREACH(name, l->dnssec_negative_trust_anchors, i) {
186 r = sd_bus_message_append(reply, "s", name);
187 if (r < 0)
188 return r;
189 }
190
191 return sd_bus_message_close_container(reply);
192}
193
04b764bf
LP
194static int verify_unmanaged_link(Link *l, sd_bus_error *error) {
195 assert(l);
196
197 if (l->flags & IFF_LOOPBACK)
6ff79f76 198 return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->ifname);
04b764bf 199 if (l->is_managed)
6ff79f76 200 return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is managed.", l->ifname);
04b764bf
LP
201
202 return 0;
203}
204
d2ec6608
LP
205int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
206 _cleanup_free_ struct in_addr_data *dns = NULL;
207 size_t allocated = 0, n = 0;
208 Link *l = userdata;
209 unsigned i;
210 int r;
211
212 assert(message);
213 assert(l);
214
04b764bf
LP
215 r = verify_unmanaged_link(l, error);
216 if (r < 0)
217 return r;
218
d2ec6608
LP
219 r = sd_bus_message_enter_container(message, 'a', "(iay)");
220 if (r < 0)
221 return r;
222
223 for (;;) {
224 int family;
225 size_t sz;
226 const void *d;
227
228 assert_cc(sizeof(int) == sizeof(int32_t));
229
230 r = sd_bus_message_enter_container(message, 'r', "iay");
231 if (r < 0)
232 return r;
233 if (r == 0)
234 break;
235
236 r = sd_bus_message_read(message, "i", &family);
237 if (r < 0)
238 return r;
239
240 if (!IN_SET(family, AF_INET, AF_INET6))
241 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
242
243 r = sd_bus_message_read_array(message, 'y', &d, &sz);
244 if (r < 0)
245 return r;
246 if (sz != FAMILY_ADDRESS_SIZE(family))
247 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
248
b30bf55d
LP
249 if (!dns_server_address_valid(family, d))
250 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address");
251
d2ec6608
LP
252 r = sd_bus_message_exit_container(message);
253 if (r < 0)
254 return r;
255
256 if (!GREEDY_REALLOC(dns, allocated, n+1))
257 return -ENOMEM;
258
259 dns[n].family = family;
260 memcpy(&dns[n].address, d, sz);
261 n++;
262 }
263
264 r = sd_bus_message_exit_container(message);
265 if (r < 0)
266 return r;
267
52aaef0f
ZJS
268 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
269 "org.freedesktop.resolve1.set-dns-servers",
270 NULL, true, UID_INVALID,
271 &l->manager->polkit_registry, error);
272 if (r < 0)
273 return r;
274 if (r == 0)
275 return 1; /* Polkit will call us back */
276
d2ec6608
LP
277 dns_server_mark_all(l->dns_servers);
278
279 for (i = 0; i < n; i++) {
280 DnsServer *s;
281
2817157b 282 s = dns_server_find(l->dns_servers, dns[i].family, &dns[i].address, 0);
d2ec6608
LP
283 if (s)
284 dns_server_move_back_and_unmark(s);
285 else {
2817157b 286 r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address, 0);
d2ec6608
LP
287 if (r < 0)
288 goto clear;
289 }
290
291 }
292
293 dns_server_unlink_marked(l->dns_servers);
294 link_allocate_scopes(l);
295
943ef07c 296 (void) link_save_user(l);
7207052d
LP
297 (void) manager_write_resolv_conf(l->manager);
298
d2ec6608
LP
299 return sd_bus_reply_method_return(message, NULL);
300
301clear:
302 dns_server_unlink_all(l->dns_servers);
303 return r;
304}
305
ee116b54 306int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d2ec6608 307 Link *l = userdata;
d2ec6608
LP
308 int r;
309
310 assert(message);
311 assert(l);
312
04b764bf
LP
313 r = verify_unmanaged_link(l, error);
314 if (r < 0)
315 return r;
316
ad44b56b 317 r = sd_bus_message_enter_container(message, 'a', "(sb)");
d2ec6608
LP
318 if (r < 0)
319 return r;
320
ad44b56b
LP
321 for (;;) {
322 const char *name;
323 int route_only;
d2ec6608 324
ad44b56b 325 r = sd_bus_message_read(message, "(sb)", &name, &route_only);
d2ec6608
LP
326 if (r < 0)
327 return r;
328 if (r == 0)
ad44b56b
LP
329 break;
330
331 r = dns_name_is_valid(name);
332 if (r < 0)
333 return r;
334 if (r == 0)
335 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
336 if (!route_only && dns_name_is_root(name))
d2ec6608
LP
337 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
338 }
339
ad44b56b
LP
340 r = sd_bus_message_rewind(message, false);
341 if (r < 0)
342 return r;
343
52aaef0f
ZJS
344 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
345 "org.freedesktop.resolve1.set-domains",
346 NULL, true, UID_INVALID,
347 &l->manager->polkit_registry, error);
348 if (r < 0)
349 return r;
350 if (r == 0)
351 return 1; /* Polkit will call us back */
352
353 dns_search_domain_mark_all(l->search_domains);
354
ad44b56b 355 for (;;) {
d2ec6608 356 DnsSearchDomain *d;
ad44b56b
LP
357 const char *name;
358 int route_only;
d2ec6608 359
ad44b56b
LP
360 r = sd_bus_message_read(message, "(sb)", &name, &route_only);
361 if (r < 0)
362 goto clear;
363 if (r == 0)
364 break;
365
366 r = dns_search_domain_find(l->search_domains, name, &d);
d2ec6608
LP
367 if (r < 0)
368 goto clear;
369
370 if (r > 0)
371 dns_search_domain_move_back_and_unmark(d);
372 else {
ad44b56b 373 r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
d2ec6608
LP
374 if (r < 0)
375 goto clear;
376 }
ad44b56b
LP
377
378 d->route_only = route_only;
d2ec6608
LP
379 }
380
ad44b56b
LP
381 r = sd_bus_message_exit_container(message);
382 if (r < 0)
383 goto clear;
384
d2ec6608 385 dns_search_domain_unlink_marked(l->search_domains);
7207052d 386
943ef07c 387 (void) link_save_user(l);
7207052d
LP
388 (void) manager_write_resolv_conf(l->manager);
389
d2ec6608
LP
390 return sd_bus_reply_method_return(message, NULL);
391
392clear:
393 dns_search_domain_unlink_all(l->search_domains);
394 return r;
395}
396
77673795
LP
397int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) {
398 Link *l = userdata;
399 int r, b;
400
401 assert(message);
402 assert(l);
403
404 r = verify_unmanaged_link(l, error);
405 if (r < 0)
406 return r;
407
408 r = sd_bus_message_read(message, "b", &b);
409 if (r < 0)
410 return r;
411
52aaef0f
ZJS
412 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
413 "org.freedesktop.resolve1.set-default-route",
414 NULL, true, UID_INVALID,
415 &l->manager->polkit_registry, error);
416 if (r < 0)
417 return r;
418 if (r == 0)
419 return 1; /* Polkit will call us back */
420
77673795
LP
421 if (l->default_route != b) {
422 l->default_route = b;
423
424 (void) link_save_user(l);
425 (void) manager_write_resolv_conf(l->manager);
426 }
427
428 return sd_bus_reply_method_return(message, NULL);
429}
430
d2ec6608
LP
431int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
432 Link *l = userdata;
433 ResolveSupport mode;
434 const char *llmnr;
435 int r;
436
437 assert(message);
438 assert(l);
439
04b764bf
LP
440 r = verify_unmanaged_link(l, error);
441 if (r < 0)
442 return r;
443
d2ec6608
LP
444 r = sd_bus_message_read(message, "s", &llmnr);
445 if (r < 0)
446 return r;
447
448 if (isempty(llmnr))
449 mode = RESOLVE_SUPPORT_YES;
450 else {
451 mode = resolve_support_from_string(llmnr);
452 if (mode < 0)
453 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr);
454 }
455
52aaef0f
ZJS
456 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
457 "org.freedesktop.resolve1.set-llmnr",
458 NULL, true, UID_INVALID,
459 &l->manager->polkit_registry, error);
460 if (r < 0)
461 return r;
462 if (r == 0)
463 return 1; /* Polkit will call us back */
464
d2ec6608
LP
465 l->llmnr_support = mode;
466 link_allocate_scopes(l);
467 link_add_rrs(l, false);
468
943ef07c
LP
469 (void) link_save_user(l);
470
d2ec6608
LP
471 return sd_bus_reply_method_return(message, NULL);
472}
473
474int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
475 Link *l = userdata;
476 ResolveSupport mode;
477 const char *mdns;
478 int r;
479
480 assert(message);
481 assert(l);
482
04b764bf
LP
483 r = verify_unmanaged_link(l, error);
484 if (r < 0)
485 return r;
486
d2ec6608
LP
487 r = sd_bus_message_read(message, "s", &mdns);
488 if (r < 0)
489 return r;
490
491 if (isempty(mdns))
492 mode = RESOLVE_SUPPORT_NO;
493 else {
494 mode = resolve_support_from_string(mdns);
495 if (mode < 0)
496 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns);
497 }
498
52aaef0f
ZJS
499 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
500 "org.freedesktop.resolve1.set-mdns",
501 NULL, true, UID_INVALID,
502 &l->manager->polkit_registry, error);
503 if (r < 0)
504 return r;
505 if (r == 0)
506 return 1; /* Polkit will call us back */
507
d2ec6608
LP
508 l->mdns_support = mode;
509 link_allocate_scopes(l);
510 link_add_rrs(l, false);
511
943ef07c
LP
512 (void) link_save_user(l);
513
d2ec6608
LP
514 return sd_bus_reply_method_return(message, NULL);
515}
516
c9299be2 517int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d050561a 518 Link *l = userdata;
c9299be2
IT
519 const char *dns_over_tls;
520 DnsOverTlsMode mode;
d050561a
IT
521 int r;
522
523 assert(message);
524 assert(l);
525
526 r = verify_unmanaged_link(l, error);
527 if (r < 0)
528 return r;
529
c9299be2 530 r = sd_bus_message_read(message, "s", &dns_over_tls);
d050561a
IT
531 if (r < 0)
532 return r;
533
c9299be2
IT
534 if (isempty(dns_over_tls))
535 mode = _DNS_OVER_TLS_MODE_INVALID;
d050561a 536 else {
c9299be2 537 mode = dns_over_tls_mode_from_string(dns_over_tls);
d050561a 538 if (mode < 0)
c9299be2 539 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSOverTLS setting: %s", dns_over_tls);
d050561a
IT
540 }
541
52aaef0f
ZJS
542 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
543 "org.freedesktop.resolve1.set-dns-over-tls",
544 NULL, true, UID_INVALID,
545 &l->manager->polkit_registry, error);
546 if (r < 0)
547 return r;
548 if (r == 0)
549 return 1; /* Polkit will call us back */
550
c9299be2 551 link_set_dns_over_tls_mode(l, mode);
d050561a
IT
552
553 (void) link_save_user(l);
554
555 return sd_bus_reply_method_return(message, NULL);
556}
557
d2ec6608
LP
558int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
559 Link *l = userdata;
560 const char *dnssec;
561 DnssecMode mode;
562 int r;
563
564 assert(message);
565 assert(l);
566
04b764bf
LP
567 r = verify_unmanaged_link(l, error);
568 if (r < 0)
569 return r;
570
d2ec6608
LP
571 r = sd_bus_message_read(message, "s", &dnssec);
572 if (r < 0)
573 return r;
574
575 if (isempty(dnssec))
576 mode = _DNSSEC_MODE_INVALID;
577 else {
578 mode = dnssec_mode_from_string(dnssec);
579 if (mode < 0)
580 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec);
581 }
582
52aaef0f
ZJS
583 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
584 "org.freedesktop.resolve1.set-dnssec",
585 NULL, true, UID_INVALID,
586 &l->manager->polkit_registry, error);
587 if (r < 0)
588 return r;
589 if (r == 0)
590 return 1; /* Polkit will call us back */
591
d2ec6608
LP
592 link_set_dnssec_mode(l, mode);
593
943ef07c
LP
594 (void) link_save_user(l);
595
d2ec6608
LP
596 return sd_bus_reply_method_return(message, NULL);
597}
598
599int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
600 _cleanup_set_free_free_ Set *ns = NULL;
c6d92582 601 _cleanup_strv_free_ char **ntas = NULL;
d2ec6608
LP
602 Link *l = userdata;
603 int r;
604 char **i;
605
606 assert(message);
607 assert(l);
608
04b764bf
LP
609 r = verify_unmanaged_link(l, error);
610 if (r < 0)
611 return r;
612
ab77c879
ZJS
613 ns = set_new(&dns_name_hash_ops);
614 if (!ns)
615 return -ENOMEM;
616
d2ec6608
LP
617 r = sd_bus_message_read_strv(message, &ntas);
618 if (r < 0)
619 return r;
620
621 STRV_FOREACH(i, ntas) {
622 r = dns_name_is_valid(*i);
623 if (r < 0)
624 return r;
625 if (r == 0)
ab77c879
ZJS
626 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
627 "Invalid negative trust anchor domain: %s", *i);
d2ec6608 628
d2ec6608
LP
629 r = set_put_strdup(ns, *i);
630 if (r < 0)
631 return r;
632 }
633
52aaef0f
ZJS
634 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
635 "org.freedesktop.resolve1.set-dnssec-negative-trust-anchors",
636 NULL, true, UID_INVALID,
637 &l->manager->polkit_registry, error);
638 if (r < 0)
639 return r;
640 if (r == 0)
641 return 1; /* Polkit will call us back */
642
d2ec6608 643 set_free_free(l->dnssec_negative_trust_anchors);
ae2a15bc 644 l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
d2ec6608 645
943ef07c
LP
646 (void) link_save_user(l);
647
d2ec6608
LP
648 return sd_bus_reply_method_return(message, NULL);
649}
650
651int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error) {
652 Link *l = userdata;
04b764bf 653 int r;
d2ec6608
LP
654
655 assert(message);
656 assert(l);
657
04b764bf
LP
658 r = verify_unmanaged_link(l, error);
659 if (r < 0)
660 return r;
661
52aaef0f
ZJS
662 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
663 "org.freedesktop.resolve1.revert",
664 NULL, true, UID_INVALID,
665 &l->manager->polkit_registry, error);
666 if (r < 0)
667 return r;
668 if (r == 0)
669 return 1; /* Polkit will call us back */
670
d2ec6608
LP
671 link_flush_settings(l);
672 link_allocate_scopes(l);
673 link_add_rrs(l, false);
674
943ef07c 675 (void) link_save_user(l);
7207052d
LP
676 (void) manager_write_resolv_conf(l->manager);
677
d2ec6608
LP
678 return sd_bus_reply_method_return(message, NULL);
679}
680
3abaabda
LP
681const sd_bus_vtable link_vtable[] = {
682 SD_BUS_VTABLE_START(0),
683
684 SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0),
685 SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0),
b7ac92cd 686 SD_BUS_PROPERTY("CurrentDNSServer", "(iay)", property_get_current_dns_server, offsetof(Link, current_dns_server), 0),
ad44b56b 687 SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0),
77673795 688 SD_BUS_PROPERTY("DefaultRoute", "b", property_get_default_route, 0, 0),
bf4e5c4c
YW
689 SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Link, llmnr_support), 0),
690 SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Link, mdns_support), 0),
c9299be2 691 SD_BUS_PROPERTY("DNSOverTLS", "s", property_get_dns_over_tls_mode, 0, 0),
a3712979 692 SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, 0, 0),
3abaabda 693 SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0),
c2cf6e0b 694 SD_BUS_PROPERTY("DNSSECSupported", "b", property_get_dnssec_supported, 0, 0),
3abaabda 695
52aaef0f
ZJS
696 SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED),
697 SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_domains, SD_BUS_VTABLE_UNPRIVILEGED),
698 SD_BUS_METHOD("SetDefaultRoute", "b", NULL, bus_link_method_set_default_route, SD_BUS_VTABLE_UNPRIVILEGED),
699 SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, SD_BUS_VTABLE_UNPRIVILEGED),
700 SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, SD_BUS_VTABLE_UNPRIVILEGED),
701 SD_BUS_METHOD("SetDNSOverTLS", "s", NULL, bus_link_method_set_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED),
702 SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, SD_BUS_VTABLE_UNPRIVILEGED),
703 SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED),
704 SD_BUS_METHOD("Revert", NULL, NULL, bus_link_method_revert, SD_BUS_VTABLE_UNPRIVILEGED),
d2ec6608 705
3abaabda
LP
706 SD_BUS_VTABLE_END
707};
708
709int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
710 _cleanup_free_ char *e = NULL;
711 Manager *m = userdata;
712 int ifindex;
713 Link *link;
714 int r;
715
716 assert(bus);
717 assert(path);
718 assert(interface);
719 assert(found);
720 assert(m);
721
722 r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/link", &e);
723 if (r <= 0)
724 return 0;
725
726 r = parse_ifindex(e, &ifindex);
727 if (r < 0)
728 return 0;
729
730 link = hashmap_get(m->links, INT_TO_PTR(ifindex));
731 if (!link)
732 return 0;
733
734 *found = link;
735 return 1;
736}
737
738char *link_bus_path(Link *link) {
739 _cleanup_free_ char *ifindex = NULL;
740 char *p;
741 int r;
742
743 assert(link);
744
745 if (asprintf(&ifindex, "%i", link->ifindex) < 0)
746 return NULL;
747
748 r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifindex, &p);
749 if (r < 0)
750 return NULL;
751
752 return p;
753}
754
755int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
756 _cleanup_strv_free_ char **l = NULL;
757 Manager *m = userdata;
758 Link *link;
759 Iterator i;
760 unsigned c = 0;
761
762 assert(bus);
763 assert(path);
764 assert(m);
765 assert(nodes);
766
767 l = new0(char*, hashmap_size(m->links) + 1);
768 if (!l)
769 return -ENOMEM;
770
771 HASHMAP_FOREACH(link, m->links, i) {
772 char *p;
773
774 p = link_bus_path(link);
775 if (!p)
776 return -ENOMEM;
777
778 l[c++] = p;
779 }
780
781 l[c] = NULL;
ae2a15bc 782 *nodes = TAKE_PTR(l);
3abaabda
LP
783
784 return 1;
785}