1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <net/if.h>
4 #include <netinet/in.h>
5 #include <sys/capability.h>
6
7 #include "alloc-util.h"
8 #include "bus-common-errors.h"
9 #include "bus-get-properties.h"
10 #include "bus-message-util.h"
11 #include "bus-polkit.h"
12 #include "log-link.h"
13 #include "parse-util.h"
14 #include "resolve-util.h"
15 #include "resolved-bus.h"
16 #include "resolved-link-bus.h"
17 #include "resolved-resolv-conf.h"
18 #include "socket-netlink.h"
19 #include "stdio-util.h"
20 #include "strv.h"
21 #include "user-util.h"
22
23 static BUS_DEFINE_PROPERTY_GET(property_get_dnssec_supported, "b", Link, link_dnssec_supported);
24 static BUS_DEFINE_PROPERTY_GET2(property_get_dnssec_mode, "s", Link, link_get_dnssec_mode, dnssec_mode_to_string);
25
property_get_dns_over_tls_mode(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)26 static int property_get_dns_over_tls_mode(
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
40 return sd_bus_message_append(reply, "s", dns_over_tls_mode_to_string(link_get_dns_over_tls_mode(l)));
41 }
42
property_get_dns_internal(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error,bool extended)43 static int property_get_dns_internal(
44 sd_bus *bus,
45 const char *path,
46 const char *interface,
47 const char *property,
48 sd_bus_message *reply,
49 void *userdata,
50 sd_bus_error *error,
51 bool extended) {
52
53 Link *l = userdata;
54 int r;
55
56 assert(reply);
57 assert(l);
58
59 r = sd_bus_message_open_container(reply, 'a', extended ? "(iayqs)" : "(iay)");
60 if (r < 0)
61 return r;
62
63 LIST_FOREACH(servers, s, l->dns_servers) {
64 r = bus_dns_server_append(reply, s, false, extended);
65 if (r < 0)
66 return r;
67 }
68
69 return sd_bus_message_close_container(reply);
70 }
71
property_get_dns(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)72 static 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
property_get_dns_ex(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)83 static int property_get_dns_ex(
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) {
91 return property_get_dns_internal(bus, path, interface, property, reply, userdata, error, true);
92 }
93
property_get_current_dns_server_internal(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error,bool extended)94 static 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) {
103
104 DnsServer *s;
105
106 assert(reply);
107 assert(userdata);
108
109 s = *(DnsServer **) userdata;
110
111 return bus_dns_server_append(reply, s, false, extended);
112 }
113
property_get_current_dns_server(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)114 static 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
property_get_current_dns_server_ex(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)125 static 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);
134 }
135
property_get_domains(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)136 static 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;
146 int r;
147
148 assert(reply);
149 assert(l);
150
151 r = sd_bus_message_open_container(reply, 'a', "(sb)");
152 if (r < 0)
153 return r;
154
155 LIST_FOREACH(domains, d, l->search_domains) {
156 r = sd_bus_message_append(reply, "(sb)", d->name, d->route_only);
157 if (r < 0)
158 return r;
159 }
160
161 return sd_bus_message_close_container(reply);
162 }
163
property_get_default_route(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)164 static 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
property_get_scopes_mask(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)189 static 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
property_get_ntas(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)213 static 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;
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
233 SET_FOREACH(name, l->dnssec_negative_trust_anchors) {
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
verify_unmanaged_link(Link * l,sd_bus_error * error)242 static int verify_unmanaged_link(Link *l, sd_bus_error *error) {
243 assert(l);
244
245 if (l->flags & IFF_LOOPBACK)
246 return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->ifname);
247 if (l->is_managed)
248 return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is managed.", l->ifname);
249
250 return 0;
251 }
252
bus_link_method_set_dns_servers_internal(sd_bus_message * message,void * userdata,sd_bus_error * error,bool extended)253 static int bus_link_method_set_dns_servers_internal(sd_bus_message *message, void *userdata, sd_bus_error *error, bool extended) {
254 _cleanup_free_ char *j = NULL;
255 struct in_addr_full **dns;
256 bool changed = false;
257 Link *l = userdata;
258 size_t n;
259 int r;
260
261 assert(message);
262 assert(l);
263
264 r = verify_unmanaged_link(l, error);
265 if (r < 0)
266 return r;
267
268 r = bus_message_read_dns_servers(message, error, extended, &dns, &n);
269 if (r < 0)
270 return r;
271
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)
277 goto finalize;
278 if (r == 0) {
279 r = 1; /* Polkit will call us back */
280 goto finalize;
281 }
282
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
292 if (!strextend_with_separator(&j, ", ", s)) {
293 r = -ENOMEM;
294 goto finalize;
295 }
296 }
297
298 bus_client_log(message, "DNS server change");
299
300 dns_server_mark_all(l->dns_servers);
301
302 for (size_t i = 0; i < n; i++) {
303 DnsServer *s;
304
305 s = dns_server_find(l->dns_servers, dns[i]->family, &dns[i]->address, dns[i]->port, 0, dns[i]->server_name);
306 if (s)
307 dns_server_move_back_and_unmark(s);
308 else {
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 }
314
315 changed = true;
316 }
317
318 }
319
320 changed = dns_server_unlink_marked(l->dns_servers) || changed;
321
322 if (changed) {
323 link_allocate_scopes(l);
324
325 (void) link_save_user(l);
326 (void) manager_write_resolv_conf(l->manager);
327 (void) manager_send_changed(l->manager, "DNS");
328
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 }
334
335 r = sd_bus_reply_method_return(message, NULL);
336
337 finalize:
338 for (size_t i = 0; i < n; i++)
339 in_addr_full_free(dns[i]);
340 free(dns);
341
342 return r;
343 }
344
bus_link_method_set_dns_servers(sd_bus_message * message,void * userdata,sd_bus_error * error)345 int 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
bus_link_method_set_dns_servers_ex(sd_bus_message * message,void * userdata,sd_bus_error * error)349 int 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
bus_link_method_set_domains(sd_bus_message * message,void * userdata,sd_bus_error * error)353 int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
354 _cleanup_free_ char *j = NULL;
355 Link *l = userdata;
356 bool changed = false;
357 int r;
358
359 assert(message);
360 assert(l);
361
362 r = verify_unmanaged_link(l, error);
363 if (r < 0)
364 return r;
365
366 r = sd_bus_message_enter_container(message, 'a', "(sb)");
367 if (r < 0)
368 return r;
369
370 for (;;) {
371 _cleanup_free_ char *prefixed = NULL;
372 const char *name;
373 int route_only;
374
375 r = sd_bus_message_read(message, "(sb)", &name, &route_only);
376 if (r < 0)
377 return r;
378 if (r == 0)
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))
387 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
388
389 if (route_only) {
390 prefixed = strjoin("~", name);
391 if (!prefixed)
392 return -ENOMEM;
393
394 name = prefixed;
395 }
396
397 if (!strextend_with_separator(&j, ", ", name))
398 return -ENOMEM;
399 }
400
401 r = sd_bus_message_rewind(message, false);
402 if (r < 0)
403 return r;
404
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
414 bus_client_log(message, "dns domains change");
415
416 dns_search_domain_mark_all(l->search_domains);
417
418 for (;;) {
419 DnsSearchDomain *d;
420 const char *name;
421 int route_only;
422
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);
430 if (r < 0)
431 goto clear;
432
433 if (r > 0)
434 dns_search_domain_move_back_and_unmark(d);
435 else {
436 r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
437 if (r < 0)
438 goto clear;
439
440 changed = true;
441 }
442
443 d->route_only = route_only;
444 }
445
446 r = sd_bus_message_exit_container(message);
447 if (r < 0)
448 goto clear;
449
450 changed = dns_search_domain_unlink_marked(l->search_domains) || changed;
451
452 if (changed) {
453 (void) link_save_user(l);
454 (void) manager_write_resolv_conf(l->manager);
455
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 }
461
462 return sd_bus_reply_method_return(message, NULL);
463
464 clear:
465 dns_search_domain_unlink_all(l->search_domains);
466 return r;
467 }
468
bus_link_method_set_default_route(sd_bus_message * message,void * userdata,sd_bus_error * error)469 int 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
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
493 bus_client_log(message, "dns default route change");
494
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);
500
501 log_link_info(l, "Bus client set default route setting: %s", yes_no(b));
502 }
503
504 return sd_bus_reply_method_return(message, NULL);
505 }
506
bus_link_method_set_llmnr(sd_bus_message * message,void * userdata,sd_bus_error * error)507 int 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
516 r = verify_unmanaged_link(l, error);
517 if (r < 0)
518 return r;
519
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
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
541 bus_client_log(message, "LLMNR change");
542
543 if (l->llmnr_support != mode) {
544 l->llmnr_support = mode;
545 link_allocate_scopes(l);
546 link_add_rrs(l, false);
547
548 (void) link_save_user(l);
549
550 log_link_info(l, "Bus client set LLMNR setting: %s", resolve_support_to_string(mode));
551 }
552
553 return sd_bus_reply_method_return(message, NULL);
554 }
555
bus_link_method_set_mdns(sd_bus_message * message,void * userdata,sd_bus_error * error)556 int 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
565 r = verify_unmanaged_link(l, error);
566 if (r < 0)
567 return r;
568
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
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
590 bus_client_log(message, "mDNS change");
591
592 if (l->mdns_support != mode) {
593 l->mdns_support = mode;
594 link_allocate_scopes(l);
595 link_add_rrs(l, false);
596
597 (void) link_save_user(l);
598
599 log_link_info(l, "Bus client set MulticastDNS setting: %s", resolve_support_to_string(mode));
600 }
601
602 return sd_bus_reply_method_return(message, NULL);
603 }
604
bus_link_method_set_dns_over_tls(sd_bus_message * message,void * userdata,sd_bus_error * error)605 int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
606 Link *l = userdata;
607 const char *dns_over_tls;
608 DnsOverTlsMode mode;
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
618 r = sd_bus_message_read(message, "s", &dns_over_tls);
619 if (r < 0)
620 return r;
621
622 if (isempty(dns_over_tls))
623 mode = _DNS_OVER_TLS_MODE_INVALID;
624 else {
625 mode = dns_over_tls_mode_from_string(dns_over_tls);
626 if (mode < 0)
627 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSOverTLS setting: %s", dns_over_tls);
628 }
629
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
639 bus_client_log(message, "D-o-T change");
640
641 if (l->dns_over_tls_mode != mode) {
642 link_set_dns_over_tls_mode(l, mode);
643 link_allocate_scopes(l);
644
645 (void) link_save_user(l);
646
647 log_link_info(l, "Bus client set DNSOverTLS setting: %s",
648 mode < 0 ? "default" : dns_over_tls_mode_to_string(mode));
649 }
650
651 return sd_bus_reply_method_return(message, NULL);
652 }
653
bus_link_method_set_dnssec(sd_bus_message * message,void * userdata,sd_bus_error * error)654 int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
655 Link *l = userdata;
656 const char *dnssec;
657 DnssecMode mode;
658 int r;
659
660 assert(message);
661 assert(l);
662
663 r = verify_unmanaged_link(l, error);
664 if (r < 0)
665 return r;
666
667 r = sd_bus_message_read(message, "s", &dnssec);
668 if (r < 0)
669 return r;
670
671 if (isempty(dnssec))
672 mode = _DNSSEC_MODE_INVALID;
673 else {
674 mode = dnssec_mode_from_string(dnssec);
675 if (mode < 0)
676 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec);
677 }
678
679 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
680 "org.freedesktop.resolve1.set-dnssec",
681 NULL, true, UID_INVALID,
682 &l->manager->polkit_registry, error);
683 if (r < 0)
684 return r;
685 if (r == 0)
686 return 1; /* Polkit will call us back */
687
688 bus_client_log(message, "DNSSEC change");
689
690 if (l->dnssec_mode != mode) {
691 link_set_dnssec_mode(l, mode);
692 link_allocate_scopes(l);
693
694 (void) link_save_user(l);
695
696 log_link_info(l, "Bus client set DNSSEC setting: %s",
697 mode < 0 ? "default" : dnssec_mode_to_string(mode));
698 }
699
700 return sd_bus_reply_method_return(message, NULL);
701 }
702
bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message * message,void * userdata,sd_bus_error * error)703 int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
704 _cleanup_set_free_free_ Set *ns = NULL;
705 _cleanup_strv_free_ char **ntas = NULL;
706 _cleanup_free_ char *j = NULL;
707 Link *l = userdata;
708 int r;
709
710 assert(message);
711 assert(l);
712
713 r = verify_unmanaged_link(l, error);
714 if (r < 0)
715 return r;
716
717 ns = set_new(&dns_name_hash_ops);
718 if (!ns)
719 return -ENOMEM;
720
721 r = sd_bus_message_read_strv(message, &ntas);
722 if (r < 0)
723 return r;
724
725 STRV_FOREACH(i, ntas) {
726 r = dns_name_is_valid(*i);
727 if (r < 0)
728 return r;
729 if (r == 0)
730 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
731 "Invalid negative trust anchor domain: %s", *i);
732
733 r = set_put_strdup(&ns, *i);
734 if (r < 0)
735 return r;
736
737 if (!strextend_with_separator(&j, ", ", *i))
738 return -ENOMEM;
739 }
740
741 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
742 "org.freedesktop.resolve1.set-dnssec-negative-trust-anchors",
743 NULL, true, UID_INVALID,
744 &l->manager->polkit_registry, error);
745 if (r < 0)
746 return r;
747 if (r == 0)
748 return 1; /* Polkit will call us back */
749
750 bus_client_log(message, "DNSSEC NTA change");
751
752 if (!set_equal(ns, l->dnssec_negative_trust_anchors)) {
753 set_free_free(l->dnssec_negative_trust_anchors);
754 l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
755
756 (void) link_save_user(l);
757
758 if (j)
759 log_link_info(l, "Bus client set NTA list to: %s", j);
760 else
761 log_link_info(l, "Bus client reset NTA list.");
762 }
763
764 return sd_bus_reply_method_return(message, NULL);
765 }
766
bus_link_method_revert(sd_bus_message * message,void * userdata,sd_bus_error * error)767 int bus_link_method_revert(sd_bus_message *message, void *userdata, sd_bus_error *error) {
768 Link *l = userdata;
769 int r;
770
771 assert(message);
772 assert(l);
773
774 r = verify_unmanaged_link(l, error);
775 if (r < 0)
776 return r;
777
778 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
779 "org.freedesktop.resolve1.revert",
780 NULL, true, UID_INVALID,
781 &l->manager->polkit_registry, error);
782 if (r < 0)
783 return r;
784 if (r == 0)
785 return 1; /* Polkit will call us back */
786
787 bus_client_log(message, "revert");
788
789 link_flush_settings(l);
790 link_allocate_scopes(l);
791 link_add_rrs(l, false);
792
793 (void) link_save_user(l);
794 (void) manager_write_resolv_conf(l->manager);
795 (void) manager_send_changed(l->manager, "DNS");
796
797 return sd_bus_reply_method_return(message, NULL);
798 }
799
link_object_find(sd_bus * bus,const char * path,const char * interface,void * userdata,void ** found,sd_bus_error * error)800 static int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
801 _cleanup_free_ char *e = NULL;
802 Manager *m = userdata;
803 Link *link;
804 int ifindex, r;
805
806 assert(bus);
807 assert(path);
808 assert(interface);
809 assert(found);
810 assert(m);
811
812 r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/link", &e);
813 if (r <= 0)
814 return 0;
815
816 ifindex = parse_ifindex(e);
817 if (ifindex < 0)
818 return 0;
819
820 link = hashmap_get(m->links, INT_TO_PTR(ifindex));
821 if (!link)
822 return 0;
823
824 *found = link;
825 return 1;
826 }
827
link_bus_path(const Link * link)828 char *link_bus_path(const Link *link) {
829 char *p, ifindex[DECIMAL_STR_MAX(link->ifindex)];
830 int r;
831
832 assert(link);
833
834 xsprintf(ifindex, "%i", link->ifindex);
835
836 r = sd_bus_path_encode("/org/freedesktop/resolve1/link", ifindex, &p);
837 if (r < 0)
838 return NULL;
839
840 return p;
841 }
842
link_node_enumerator(sd_bus * bus,const char * path,void * userdata,char *** nodes,sd_bus_error * error)843 static int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
844 _cleanup_strv_free_ char **l = NULL;
845 Manager *m = userdata;
846 Link *link;
847 unsigned c = 0;
848
849 assert(bus);
850 assert(path);
851 assert(m);
852 assert(nodes);
853
854 l = new0(char*, hashmap_size(m->links) + 1);
855 if (!l)
856 return -ENOMEM;
857
858 HASHMAP_FOREACH(link, m->links) {
859 char *p;
860
861 p = link_bus_path(link);
862 if (!p)
863 return -ENOMEM;
864
865 l[c++] = p;
866 }
867
868 l[c] = NULL;
869 *nodes = TAKE_PTR(l);
870
871 return 1;
872 }
873
874 static const sd_bus_vtable link_vtable[] = {
875 SD_BUS_VTABLE_START(0),
876
877 SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0),
878 SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0),
879 SD_BUS_PROPERTY("DNSEx", "a(iayqs)", property_get_dns_ex, 0, 0),
880 SD_BUS_PROPERTY("CurrentDNSServer", "(iay)", property_get_current_dns_server, offsetof(Link, current_dns_server), 0),
881 SD_BUS_PROPERTY("CurrentDNSServerEx", "(iayqs)", property_get_current_dns_server_ex, offsetof(Link, current_dns_server), 0),
882 SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0),
883 SD_BUS_PROPERTY("DefaultRoute", "b", property_get_default_route, 0, 0),
884 SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Link, llmnr_support), 0),
885 SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Link, mdns_support), 0),
886 SD_BUS_PROPERTY("DNSOverTLS", "s", property_get_dns_over_tls_mode, 0, 0),
887 SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, 0, 0),
888 SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas, 0, 0),
889 SD_BUS_PROPERTY("DNSSECSupported", "b", property_get_dnssec_supported, 0, 0),
890
891 SD_BUS_METHOD_WITH_ARGS("SetDNS",
892 SD_BUS_ARGS("a(iay)", addresses),
893 SD_BUS_NO_RESULT,
894 bus_link_method_set_dns_servers,
895 SD_BUS_VTABLE_UNPRIVILEGED),
896 SD_BUS_METHOD_WITH_ARGS("SetDNSEx",
897 SD_BUS_ARGS("a(iayqs)", addresses),
898 SD_BUS_NO_RESULT,
899 bus_link_method_set_dns_servers_ex,
900 SD_BUS_VTABLE_UNPRIVILEGED),
901 SD_BUS_METHOD_WITH_ARGS("SetDomains",
902 SD_BUS_ARGS("a(sb)", domains),
903 SD_BUS_NO_RESULT,
904 bus_link_method_set_domains,
905 SD_BUS_VTABLE_UNPRIVILEGED),
906 SD_BUS_METHOD_WITH_ARGS("SetDefaultRoute",
907 SD_BUS_ARGS("b", enable),
908 SD_BUS_NO_RESULT,
909 bus_link_method_set_default_route,
910 SD_BUS_VTABLE_UNPRIVILEGED),
911 SD_BUS_METHOD_WITH_ARGS("SetLLMNR",
912 SD_BUS_ARGS("s", mode),
913 SD_BUS_NO_RESULT,
914 bus_link_method_set_llmnr,
915 SD_BUS_VTABLE_UNPRIVILEGED),
916 SD_BUS_METHOD_WITH_ARGS("SetMulticastDNS",
917 SD_BUS_ARGS("s", mode),
918 SD_BUS_NO_RESULT,
919 bus_link_method_set_mdns,
920 SD_BUS_VTABLE_UNPRIVILEGED),
921 SD_BUS_METHOD_WITH_ARGS("SetDNSOverTLS",
922 SD_BUS_ARGS("s", mode),
923 SD_BUS_NO_RESULT,
924 bus_link_method_set_dns_over_tls,
925 SD_BUS_VTABLE_UNPRIVILEGED),
926 SD_BUS_METHOD_WITH_ARGS("SetDNSSEC",
927 SD_BUS_ARGS("s", mode),
928 SD_BUS_NO_RESULT,
929 bus_link_method_set_dnssec,
930 SD_BUS_VTABLE_UNPRIVILEGED),
931 SD_BUS_METHOD_WITH_ARGS("SetDNSSECNegativeTrustAnchors",
932 SD_BUS_ARGS("as", names),
933 SD_BUS_NO_RESULT,
934 bus_link_method_set_dnssec_negative_trust_anchors,
935 SD_BUS_VTABLE_UNPRIVILEGED),
936 SD_BUS_METHOD_WITH_ARGS("Revert",
937 SD_BUS_NO_ARGS,
938 SD_BUS_NO_RESULT,
939 bus_link_method_revert,
940 SD_BUS_VTABLE_UNPRIVILEGED),
941
942 SD_BUS_VTABLE_END
943 };
944
945 const BusObjectImplementation link_object = {
946 "/org/freedesktop/resolve1/link",
947 "org.freedesktop.resolve1.Link",
948 .fallback_vtables = BUS_FALLBACK_VTABLES({link_vtable, link_object_find}),
949 .node_enumerator = link_node_enumerator,
950 };
951