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