1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2016 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include "alloc-util.h"
22 #include "bus-common-errors.h"
24 #include "parse-util.h"
25 #include "resolve-util.h"
26 #include "resolved-bus.h"
27 #include "resolved-link-bus.h"
28 #include "resolved-resolv-conf.h"
31 static int property_get_dnssec_mode(
34 const char *interface
,
36 sd_bus_message
*reply
,
38 sd_bus_error
*error
) {
45 return sd_bus_message_append(reply
, "s", dnssec_mode_to_string(link_get_dnssec_mode(l
)));
48 static int property_get_dns(
51 const char *interface
,
53 sd_bus_message
*reply
,
55 sd_bus_error
*error
) {
64 r
= sd_bus_message_open_container(reply
, 'a', "(iay)");
68 LIST_FOREACH(servers
, s
, l
->dns_servers
) {
69 r
= bus_dns_server_append(reply
, s
, false);
74 return sd_bus_message_close_container(reply
);
77 static int property_get_domains(
80 const char *interface
,
82 sd_bus_message
*reply
,
84 sd_bus_error
*error
) {
93 r
= sd_bus_message_open_container(reply
, 'a', "(sb)");
97 LIST_FOREACH(domains
, d
, l
->search_domains
) {
98 r
= sd_bus_message_append(reply
, "(sb)", d
->name
, d
->route_only
);
103 return sd_bus_message_close_container(reply
);
106 static int property_get_scopes_mask(
109 const char *interface
,
110 const char *property
,
111 sd_bus_message
*reply
,
113 sd_bus_error
*error
) {
121 mask
= (l
->unicast_scope
? SD_RESOLVED_DNS
: 0) |
122 (l
->llmnr_ipv4_scope
? SD_RESOLVED_LLMNR_IPV4
: 0) |
123 (l
->llmnr_ipv6_scope
? SD_RESOLVED_LLMNR_IPV6
: 0) |
124 (l
->mdns_ipv4_scope
? SD_RESOLVED_MDNS_IPV4
: 0) |
125 (l
->mdns_ipv6_scope
? SD_RESOLVED_MDNS_IPV6
: 0);
127 return sd_bus_message_append(reply
, "t", mask
);
130 static int property_get_ntas(
133 const char *interface
,
134 const char *property
,
135 sd_bus_message
*reply
,
137 sd_bus_error
*error
) {
147 r
= sd_bus_message_open_container(reply
, 'a', "s");
151 SET_FOREACH(name
, l
->dnssec_negative_trust_anchors
, i
) {
152 r
= sd_bus_message_append(reply
, "s", name
);
157 return sd_bus_message_close_container(reply
);
160 static int property_get_dnssec_supported(
163 const char *interface
,
164 const char *property
,
165 sd_bus_message
*reply
,
167 sd_bus_error
*error
) {
174 return sd_bus_message_append(reply
, "b", link_dnssec_supported(l
));
177 static int verify_unmanaged_link(Link
*l
, sd_bus_error
*error
) {
180 if (l
->flags
& IFF_LOOPBACK
)
181 return sd_bus_error_setf(error
, BUS_ERROR_LINK_BUSY
, "Link %s is loopback device.", l
->name
);
183 return sd_bus_error_setf(error
, BUS_ERROR_LINK_BUSY
, "Link %s is managed.", l
->name
);
188 int bus_link_method_set_dns_servers(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
189 _cleanup_free_
struct in_addr_data
*dns
= NULL
;
190 size_t allocated
= 0, n
= 0;
198 r
= verify_unmanaged_link(l
, error
);
202 r
= sd_bus_message_enter_container(message
, 'a', "(iay)");
211 assert_cc(sizeof(int) == sizeof(int32_t));
213 r
= sd_bus_message_enter_container(message
, 'r', "iay");
219 r
= sd_bus_message_read(message
, "i", &family
);
223 if (!IN_SET(family
, AF_INET
, AF_INET6
))
224 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown address family %i", family
);
226 r
= sd_bus_message_read_array(message
, 'y', &d
, &sz
);
229 if (sz
!= FAMILY_ADDRESS_SIZE(family
))
230 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid address size");
232 if (!dns_server_address_valid(family
, d
))
233 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid DNS server address");
235 r
= sd_bus_message_exit_container(message
);
239 if (!GREEDY_REALLOC(dns
, allocated
, n
+1))
242 dns
[n
].family
= family
;
243 memcpy(&dns
[n
].address
, d
, sz
);
247 r
= sd_bus_message_exit_container(message
);
251 dns_server_mark_all(l
->dns_servers
);
253 for (i
= 0; i
< n
; i
++) {
256 s
= dns_server_find(l
->dns_servers
, dns
[i
].family
, &dns
[i
].address
, 0);
258 dns_server_move_back_and_unmark(s
);
260 r
= dns_server_new(l
->manager
, NULL
, DNS_SERVER_LINK
, l
, dns
[i
].family
, &dns
[i
].address
, 0);
267 dns_server_unlink_marked(l
->dns_servers
);
268 link_allocate_scopes(l
);
270 (void) link_save_user(l
);
271 (void) manager_write_resolv_conf(l
->manager
);
273 return sd_bus_reply_method_return(message
, NULL
);
276 dns_server_unlink_all(l
->dns_servers
);
280 int bus_link_method_set_domains(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
287 r
= verify_unmanaged_link(l
, error
);
291 r
= sd_bus_message_enter_container(message
, 'a', "(sb)");
299 r
= sd_bus_message_read(message
, "(sb)", &name
, &route_only
);
305 r
= dns_name_is_valid(name
);
309 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid search domain %s", name
);
310 if (!route_only
&& dns_name_is_root(name
))
311 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Root domain is not suitable as search domain");
314 dns_search_domain_mark_all(l
->search_domains
);
316 r
= sd_bus_message_rewind(message
, false);
325 r
= sd_bus_message_read(message
, "(sb)", &name
, &route_only
);
331 r
= dns_search_domain_find(l
->search_domains
, name
, &d
);
336 dns_search_domain_move_back_and_unmark(d
);
338 r
= dns_search_domain_new(l
->manager
, &d
, DNS_SEARCH_DOMAIN_LINK
, l
, name
);
343 d
->route_only
= route_only
;
346 r
= sd_bus_message_exit_container(message
);
350 dns_search_domain_unlink_marked(l
->search_domains
);
352 (void) link_save_user(l
);
353 (void) manager_write_resolv_conf(l
->manager
);
355 return sd_bus_reply_method_return(message
, NULL
);
358 dns_search_domain_unlink_all(l
->search_domains
);
362 int bus_link_method_set_llmnr(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
371 r
= verify_unmanaged_link(l
, error
);
375 r
= sd_bus_message_read(message
, "s", &llmnr
);
380 mode
= RESOLVE_SUPPORT_YES
;
382 mode
= resolve_support_from_string(llmnr
);
384 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid LLMNR setting: %s", llmnr
);
387 l
->llmnr_support
= mode
;
388 link_allocate_scopes(l
);
389 link_add_rrs(l
, false);
391 (void) link_save_user(l
);
393 return sd_bus_reply_method_return(message
, NULL
);
396 int bus_link_method_set_mdns(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
405 r
= verify_unmanaged_link(l
, error
);
409 r
= sd_bus_message_read(message
, "s", &mdns
);
414 mode
= RESOLVE_SUPPORT_NO
;
416 mode
= resolve_support_from_string(mdns
);
418 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid MulticastDNS setting: %s", mdns
);
421 l
->mdns_support
= mode
;
422 link_allocate_scopes(l
);
423 link_add_rrs(l
, false);
425 (void) link_save_user(l
);
427 return sd_bus_reply_method_return(message
, NULL
);
430 int bus_link_method_set_dnssec(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
439 r
= verify_unmanaged_link(l
, error
);
443 r
= sd_bus_message_read(message
, "s", &dnssec
);
448 mode
= _DNSSEC_MODE_INVALID
;
450 mode
= dnssec_mode_from_string(dnssec
);
452 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid DNSSEC setting: %s", dnssec
);
455 link_set_dnssec_mode(l
, mode
);
457 (void) link_save_user(l
);
459 return sd_bus_reply_method_return(message
, NULL
);
462 int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
463 _cleanup_set_free_free_ Set
*ns
= NULL
;
464 _cleanup_strv_free_
char **ntas
= NULL
;
472 r
= verify_unmanaged_link(l
, error
);
476 r
= sd_bus_message_read_strv(message
, &ntas
);
480 STRV_FOREACH(i
, ntas
) {
481 r
= dns_name_is_valid(*i
);
485 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid negative trust anchor domain: %s", *i
);
488 ns
= set_new(&dns_name_hash_ops
);
492 STRV_FOREACH(i
, ntas
) {
493 r
= set_put_strdup(ns
, *i
);
498 set_free_free(l
->dnssec_negative_trust_anchors
);
499 l
->dnssec_negative_trust_anchors
= ns
;
502 (void) link_save_user(l
);
504 return sd_bus_reply_method_return(message
, NULL
);
507 int bus_link_method_revert(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
514 r
= verify_unmanaged_link(l
, error
);
518 link_flush_settings(l
);
519 link_allocate_scopes(l
);
520 link_add_rrs(l
, false);
522 (void) link_save_user(l
);
523 (void) manager_write_resolv_conf(l
->manager
);
525 return sd_bus_reply_method_return(message
, NULL
);
528 const sd_bus_vtable link_vtable
[] = {
529 SD_BUS_VTABLE_START(0),
531 SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask
, 0, 0),
532 SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns
, 0, 0),
533 SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains
, 0, 0),
534 SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support
, offsetof(Link
, llmnr_support
), 0),
535 SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support
, offsetof(Link
, mdns_support
), 0),
536 SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode
, 0, 0),
537 SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", property_get_ntas
, 0, 0),
538 SD_BUS_PROPERTY("DNSSECSupported", "b", property_get_dnssec_supported
, 0, 0),
540 SD_BUS_METHOD("SetDNS", "a(iay)", NULL
, bus_link_method_set_dns_servers
, 0),
541 SD_BUS_METHOD("SetDomains", "a(sb)", NULL
, bus_link_method_set_domains
, 0),
542 SD_BUS_METHOD("SetLLMNR", "s", NULL
, bus_link_method_set_llmnr
, 0),
543 SD_BUS_METHOD("SetMulticastDNS", "s", NULL
, bus_link_method_set_mdns
, 0),
544 SD_BUS_METHOD("SetDNSSEC", "s", NULL
, bus_link_method_set_dnssec
, 0),
545 SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL
, bus_link_method_set_dnssec_negative_trust_anchors
, 0),
546 SD_BUS_METHOD("Revert", NULL
, NULL
, bus_link_method_revert
, 0),
551 int link_object_find(sd_bus
*bus
, const char *path
, const char *interface
, void *userdata
, void **found
, sd_bus_error
*error
) {
552 _cleanup_free_
char *e
= NULL
;
553 Manager
*m
= userdata
;
564 r
= sd_bus_path_decode(path
, "/org/freedesktop/resolve1/link", &e
);
568 r
= parse_ifindex(e
, &ifindex
);
572 link
= hashmap_get(m
->links
, INT_TO_PTR(ifindex
));
580 char *link_bus_path(Link
*link
) {
581 _cleanup_free_
char *ifindex
= NULL
;
587 if (asprintf(&ifindex
, "%i", link
->ifindex
) < 0)
590 r
= sd_bus_path_encode("/org/freedesktop/resolve1/link", ifindex
, &p
);
597 int link_node_enumerator(sd_bus
*bus
, const char *path
, void *userdata
, char ***nodes
, sd_bus_error
*error
) {
598 _cleanup_strv_free_
char **l
= NULL
;
599 Manager
*m
= userdata
;
609 l
= new0(char*, hashmap_size(m
->links
) + 1);
613 HASHMAP_FOREACH(link
, m
->links
, i
) {
616 p
= link_bus_path(link
);