]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-bus.c
tree-wide: use "hostname" spelling everywhere
[thirdparty/systemd.git] / src / resolve / resolved-bus.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
74b2466e 2
b5efdb8a 3#include "alloc-util.h"
96aad8d1 4#include "bus-common-errors.h"
269e4d2d 5#include "bus-polkit.h"
74b2466e 6#include "bus-util.h"
4ad7f276 7#include "dns-domain.h"
0a970718 8#include "memory-util.h"
ef118d00 9#include "missing_capability.h"
39d8db04 10#include "resolved-bus.h"
51323288 11#include "resolved-def.h"
c3be369f 12#include "resolved-dns-synthesize.h"
c3036641 13#include "resolved-dnssd-bus.h"
0a970718 14#include "resolved-dnssd.h"
3abaabda 15#include "resolved-link-bus.h"
5c3fa98d 16#include "socket-netlink.h"
0a6c0745 17#include "stdio-util.h"
5f3340ca 18#include "strv.h"
df957849 19#include "syslog-util.h"
84b0f133 20#include "user-util.h"
c3036641 21#include "utf8.h"
74b2466e 22
bf4e5c4c
YW
23BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_resolve_support, resolve_support, ResolveSupport);
24
ad867662 25static int reply_query_state(DnsQuery *q) {
ad867662
LP
26
27 switch (q->state) {
74b2466e 28
ec2c5e43 29 case DNS_TRANSACTION_NO_SERVERS:
309e9d86 30 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
74b2466e 31
ec2c5e43 32 case DNS_TRANSACTION_TIMEOUT:
ad867662 33 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
74b2466e 34
ec2c5e43 35 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
ad867662
LP
36 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
37
818f766b
LP
38 case DNS_TRANSACTION_INVALID_REPLY:
39 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
40
7cc6ed7b
LP
41 case DNS_TRANSACTION_ERRNO:
42 return sd_bus_reply_method_errnof(q->request, q->answer_errno, "Lookup failed due to system error: %m");
ad867662 43
818f766b
LP
44 case DNS_TRANSACTION_ABORTED:
45 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");
74b2466e 46
547973de 47 case DNS_TRANSACTION_DNSSEC_FAILED:
a761c1ca 48 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s",
019036a4 49 dnssec_result_to_string(q->answer_dnssec_result));
547973de 50
b2b796b8
LP
51 case DNS_TRANSACTION_NO_TRUST_ANCHOR:
52 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known");
53
91adc4db
LP
54 case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
55 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type");
56
edbcc1fd
LP
57 case DNS_TRANSACTION_NETWORK_DOWN:
58 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NETWORK_DOWN, "Network is down");
59
0791110f
LP
60 case DNS_TRANSACTION_NOT_FOUND:
61 /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
62 * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
63 return sd_bus_reply_method_errorf(q->request, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
64
3bbdc31d 65 case DNS_TRANSACTION_RCODE_FAILURE: {
4afd3348 66 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
74b2466e 67
faa133f3 68 if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
23b298bc 69 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
74b2466e
LP
70 else {
71 const char *rc, *n;
3347dd5e 72 char p[DECIMAL_STR_MAX(q->answer_rcode)];
74b2466e 73
faa133f3 74 rc = dns_rcode_to_string(q->answer_rcode);
74b2466e 75 if (!rc) {
0a6c0745 76 xsprintf(p, "%i", q->answer_rcode);
74b2466e
LP
77 rc = p;
78 }
79
63c372cb 80 n = strjoina(_BUS_ERROR_DNS, rc);
23b298bc 81 sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", dns_query_string(q), rc);
74b2466e
LP
82 }
83
ad867662 84 return sd_bus_reply_method_error(q->request, &error);
74b2466e
LP
85 }
86
ec2c5e43
LP
87 case DNS_TRANSACTION_NULL:
88 case DNS_TRANSACTION_PENDING:
ef9fb66c 89 case DNS_TRANSACTION_VALIDATING:
ec2c5e43 90 case DNS_TRANSACTION_SUCCESS:
8ba9fd9c 91 default:
ad867662
LP
92 assert_not_reached("Impossible state");
93 }
94}
74b2466e 95
78c6a153 96static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
8ba9fd9c
LP
97 int r;
98
99 assert(reply);
100 assert(rr);
101
78c6a153
LP
102 r = sd_bus_message_open_container(reply, 'r', "iiay");
103 if (r < 0)
104 return r;
105
106 r = sd_bus_message_append(reply, "i", ifindex);
8ba9fd9c
LP
107 if (r < 0)
108 return r;
109
faa133f3 110 if (rr->key->type == DNS_TYPE_A) {
0dd25fb9 111 r = sd_bus_message_append(reply, "i", AF_INET);
8ba9fd9c
LP
112 if (r < 0)
113 return r;
114
115 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
faa133f3
LP
116
117 } else if (rr->key->type == DNS_TYPE_AAAA) {
0dd25fb9 118 r = sd_bus_message_append(reply, "i", AF_INET6);
8ba9fd9c
LP
119 if (r < 0)
120 return r;
121
122 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
faa133f3
LP
123 } else
124 return -EAFNOSUPPORT;
125
8ba9fd9c
LP
126 if (r < 0)
127 return r;
128
8ba9fd9c
LP
129 r = sd_bus_message_close_container(reply);
130 if (r < 0)
131 return r;
132
133 return 0;
134}
135
ad867662 136static void bus_method_resolve_hostname_complete(DnsQuery *q) {
45ec7efb 137 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
4afd3348 138 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
c77d2612 139 _cleanup_free_ char *normalized = NULL;
ce736ace 140 DnsResourceRecord *rr;
45ec7efb 141 unsigned added = 0;
ce736ace 142 int ifindex, r;
74b2466e 143
ad867662 144 assert(q);
74b2466e 145
ec2c5e43 146 if (q->state != DNS_TRANSACTION_SUCCESS) {
ad867662
LP
147 r = reply_query_state(q);
148 goto finish;
149 }
74b2466e 150
45ec7efb
LP
151 r = dns_query_process_cname(q);
152 if (r == -ELOOP) {
23b298bc 153 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
45ec7efb
LP
154 goto finish;
155 }
156 if (r < 0)
157 goto finish;
7588460a 158 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
45ec7efb
LP
159 return;
160
ad867662
LP
161 r = sd_bus_message_new_method_return(q->request, &reply);
162 if (r < 0)
163 goto finish;
74b2466e 164
78c6a153 165 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
51323288
LP
166 if (r < 0)
167 goto finish;
8ba9fd9c 168
ce736ace
LP
169 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
170 DnsQuestion *question;
23b298bc 171
ce736ace 172 question = dns_query_question_for_protocol(q, q->answer_protocol);
23b298bc 173
ce736ace
LP
174 r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
175 if (r < 0)
176 goto finish;
177 if (r == 0)
178 continue;
74b2466e 179
ce736ace
LP
180 r = append_address(reply, rr, ifindex);
181 if (r < 0)
182 goto finish;
74b2466e 183
ce736ace
LP
184 if (!canonical)
185 canonical = dns_resource_record_ref(rr);
309e9d86 186
313cefa1 187 added++;
8ba9fd9c 188 }
74b2466e 189
45ec7efb 190 if (added <= 0) {
23b298bc 191 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
45ec7efb 192 goto finish;
74b2466e
LP
193 }
194
ad867662
LP
195 r = sd_bus_message_close_container(reply);
196 if (r < 0)
197 goto finish;
198
c77d2612
LP
199 /* The key names are not necessarily normalized, make sure that they are when we return them to our bus
200 * clients. */
7470cc4c 201 r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized);
c77d2612
LP
202 if (r < 0)
203 goto finish;
204
45ec7efb 205 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
309e9d86 206 assert(canonical);
45ec7efb
LP
207 r = sd_bus_message_append(
208 reply, "st",
c77d2612 209 normalized,
28830a64 210 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
309e9d86
LP
211 if (r < 0)
212 goto finish;
213
ad867662 214 r = sd_bus_send(q->manager->bus, reply, NULL);
ad867662 215
74b2466e 216finish:
2d4c5cbc 217 if (r < 0) {
da927ba9 218 log_error_errno(r, "Failed to send hostname reply: %m");
45ec7efb 219 sd_bus_reply_method_errno(q->request, r, NULL);
2d4c5cbc 220 }
74b2466e
LP
221
222 dns_query_free(q);
223}
224
45ec7efb 225static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) {
51323288
LP
226 assert(flags);
227
228 if (ifindex < 0)
229 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
230
45ec7efb 231 if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
51323288
LP
232 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
233
45ec7efb
LP
234 if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
235 *flags |= SD_RESOLVED_PROTOCOLS_ALL;
51323288
LP
236
237 return 0;
238}
239
c3be369f
LP
240static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname, int family, uint64_t flags) {
241 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
242 _cleanup_free_ char *canonical = NULL;
243 union in_addr_union parsed;
94831eae 244 int r, ff, parsed_ifindex = 0;
c3be369f
LP
245
246 /* Check if the hostname is actually already an IP address formatted as string. In that case just parse it,
247 * let's not attempt to look it up. */
248
94831eae 249 r = in_addr_ifindex_from_string_auto(hostname, &ff, &parsed, &parsed_ifindex);
c3be369f
LP
250 if (r < 0) /* not an address */
251 return 0;
252
253 if (family != AF_UNSPEC && ff != family)
254 return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address is not of the requested family.");
94831eae
LP
255 if (ifindex > 0 && parsed_ifindex > 0 && parsed_ifindex != ifindex)
256 return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address interface index does not match requested interface.");
257
258 if (parsed_ifindex > 0)
259 ifindex = parsed_ifindex;
c3be369f
LP
260
261 r = sd_bus_message_new_method_return(m, &reply);
262 if (r < 0)
263 return r;
264
265 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
266 if (r < 0)
267 return r;
268
269 r = sd_bus_message_open_container(reply, 'r', "iiay");
270 if (r < 0)
271 return r;
272
273 r = sd_bus_message_append(reply, "ii", ifindex, ff);
274 if (r < 0)
275 return r;
276
277 r = sd_bus_message_append_array(reply, 'y', &parsed, FAMILY_ADDRESS_SIZE(ff));
278 if (r < 0)
279 return r;
280
281 r = sd_bus_message_close_container(reply);
282 if (r < 0)
283 return r;
284
285 r = sd_bus_message_close_container(reply);
286 if (r < 0)
287 return r;
288
289 /* When an IP address is specified we just return it as canonical name, in order to avoid a DNS
290 * look-up. However, we reformat it to make sure it's in a truly canonical form (i.e. on IPv6 the inner
291 * omissions are always done the same way). */
94831eae 292 r = in_addr_ifindex_to_string(ff, &parsed, ifindex, &canonical);
c3be369f
LP
293 if (r < 0)
294 return r;
295
296 r = sd_bus_message_append(reply, "st", canonical,
297 SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true));
298 if (r < 0)
299 return r;
300
301 return sd_bus_send(sd_bus_message_get_bus(m), reply, NULL);
302}
303
19070062 304static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
23b298bc 305 _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
74b2466e
LP
306 Manager *m = userdata;
307 const char *hostname;
51323288
LP
308 int family, ifindex;
309 uint64_t flags;
74b2466e 310 DnsQuery *q;
74b2466e
LP
311 int r;
312
74b2466e
LP
313 assert(message);
314 assert(m);
315
45ec7efb
LP
316 assert_cc(sizeof(int) == sizeof(int32_t));
317
51323288 318 r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
74b2466e
LP
319 if (r < 0)
320 return r;
321
322 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
0dd25fb9 323 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
74b2466e 324
c3be369f 325 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
7b9f7afc 326 if (r < 0)
45ec7efb 327 return r;
74b2466e 328
c3be369f
LP
329 r = parse_as_address(message, ifindex, hostname, family, flags);
330 if (r != 0)
331 return r;
332
333 r = dns_name_is_valid(hostname);
51323288
LP
334 if (r < 0)
335 return r;
c3be369f
LP
336 if (r == 0)
337 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
51323288 338
23b298bc
LP
339 r = dns_question_new_address(&question_utf8, family, hostname, false);
340 if (r < 0)
341 return r;
342
343 r = dns_question_new_address(&question_idna, family, hostname, true);
ad1f3fe6 344 if (r < 0 && r != -EALREADY)
45ec7efb 345 return r;
74b2466e 346
ad1f3fe6 347 r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, ifindex, flags);
74b2466e
LP
348 if (r < 0)
349 return r;
350
351 q->request = sd_bus_message_ref(message);
352 q->request_family = family;
74b2466e 353 q->complete = bus_method_resolve_hostname_complete;
011696f7 354 q->suppress_unroutable_family = family == AF_UNSPEC;
74b2466e 355
966c66e3 356 r = dns_query_bus_track(q, message);
82bd6ddd 357 if (r < 0)
45ec7efb 358 goto fail;
82bd6ddd 359
322345fd 360 r = dns_query_go(q);
45ec7efb
LP
361 if (r < 0)
362 goto fail;
74b2466e
LP
363
364 return 1;
45ec7efb
LP
365
366fail:
367 dns_query_free(q);
368 return r;
74b2466e
LP
369}
370
371static void bus_method_resolve_address_complete(DnsQuery *q) {
4afd3348 372 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
23b298bc 373 DnsQuestion *question;
45ec7efb
LP
374 DnsResourceRecord *rr;
375 unsigned added = 0;
376 int ifindex, r;
74b2466e
LP
377
378 assert(q);
379
ec2c5e43 380 if (q->state != DNS_TRANSACTION_SUCCESS) {
ad867662
LP
381 r = reply_query_state(q);
382 goto finish;
383 }
74b2466e 384
95d46fca
TG
385 r = dns_query_process_cname(q);
386 if (r == -ELOOP) {
23b298bc 387 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
95d46fca
TG
388 goto finish;
389 }
390 if (r < 0)
391 goto finish;
7588460a 392 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
95d46fca 393 return;
45ec7efb 394
ad867662
LP
395 r = sd_bus_message_new_method_return(q->request, &reply);
396 if (r < 0)
397 goto finish;
74b2466e 398
78c6a153 399 r = sd_bus_message_open_container(reply, 'a', "(is)");
ad867662
LP
400 if (r < 0)
401 goto finish;
74b2466e 402
23b298bc 403 question = dns_query_question_for_protocol(q, q->answer_protocol);
74b2466e 404
23b298bc 405 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
c77d2612
LP
406 _cleanup_free_ char *normalized = NULL;
407
23b298bc
LP
408 r = dns_question_matches_rr(question, rr, NULL);
409 if (r < 0)
410 goto finish;
411 if (r == 0)
412 continue;
74b2466e 413
7470cc4c 414 r = dns_name_normalize(rr->ptr.name, 0, &normalized);
c77d2612
LP
415 if (r < 0)
416 goto finish;
417
418 r = sd_bus_message_append(reply, "(is)", ifindex, normalized);
23b298bc
LP
419 if (r < 0)
420 goto finish;
421
313cefa1 422 added++;
ad867662 423 }
74b2466e 424
45ec7efb 425 if (added <= 0) {
ad867662 426 _cleanup_free_ char *ip = NULL;
74b2466e 427
164d025d
ZJS
428 (void) in_addr_to_string(q->request_family, &q->request_address, &ip);
429 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR,
430 "Address '%s' does not have any RR of requested type", strnull(ip));
ad867662 431 goto finish;
74b2466e
LP
432 }
433
ad867662
LP
434 r = sd_bus_message_close_container(reply);
435 if (r < 0)
436 goto finish;
74b2466e 437
28830a64 438 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
51323288
LP
439 if (r < 0)
440 goto finish;
441
ad867662 442 r = sd_bus_send(q->manager->bus, reply, NULL);
74b2466e
LP
443
444finish:
2d4c5cbc 445 if (r < 0) {
da927ba9 446 log_error_errno(r, "Failed to send address reply: %m");
45ec7efb 447 sd_bus_reply_method_errno(q->request, r, NULL);
2d4c5cbc 448 }
74b2466e
LP
449
450 dns_query_free(q);
451}
452
19070062 453static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
faa133f3 454 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
74b2466e 455 Manager *m = userdata;
faa133f3 456 int family, ifindex;
51323288 457 uint64_t flags;
74b2466e 458 const void *d;
74b2466e
LP
459 DnsQuery *q;
460 size_t sz;
461 int r;
462
74b2466e
LP
463 assert(message);
464 assert(m);
465
45ec7efb
LP
466 assert_cc(sizeof(int) == sizeof(int32_t));
467
51323288 468 r = sd_bus_message_read(message, "ii", &ifindex, &family);
74b2466e
LP
469 if (r < 0)
470 return r;
471
472 if (!IN_SET(family, AF_INET, AF_INET6))
0dd25fb9 473 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
74b2466e
LP
474
475 r = sd_bus_message_read_array(message, 'y', &d, &sz);
476 if (r < 0)
477 return r;
478
0dd25fb9 479 if (sz != FAMILY_ADDRESS_SIZE(family))
74b2466e
LP
480 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
481
51323288
LP
482 r = sd_bus_message_read(message, "t", &flags);
483 if (r < 0)
484 return r;
485
45ec7efb 486 r = check_ifindex_flags(ifindex, &flags, 0, error);
faa133f3
LP
487 if (r < 0)
488 return r;
489
45ec7efb 490 r = dns_question_new_reverse(&question, family, d);
74b2466e
LP
491 if (r < 0)
492 return r;
493
23b298bc 494 r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
74b2466e
LP
495 if (r < 0)
496 return r;
497
498 q->request = sd_bus_message_ref(message);
499 q->request_family = family;
500 memcpy(&q->request_address, d, sz);
501 q->complete = bus_method_resolve_address_complete;
502
966c66e3 503 r = dns_query_bus_track(q, message);
82bd6ddd 504 if (r < 0)
45ec7efb 505 goto fail;
82bd6ddd 506
322345fd 507 r = dns_query_go(q);
45ec7efb
LP
508 if (r < 0)
509 goto fail;
74b2466e
LP
510
511 return 1;
45ec7efb
LP
512
513fail:
514 dns_query_free(q);
515 return r;
516}
517
518static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) {
45ec7efb
LP
519 int r;
520
521 assert(m);
522 assert(rr);
523
524 r = sd_bus_message_open_container(m, 'r', "iqqay");
525 if (r < 0)
526 return r;
527
528 r = sd_bus_message_append(m, "iqq",
529 ifindex,
530 rr->key->class,
531 rr->key->type);
532 if (r < 0)
533 return r;
534
4e2d538f 535 r = dns_resource_record_to_wire_format(rr, false);
45ec7efb
LP
536 if (r < 0)
537 return r;
538
4e2d538f 539 r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size);
45ec7efb
LP
540 if (r < 0)
541 return r;
542
543 return sd_bus_message_close_container(m);
74b2466e
LP
544}
545
2d4c5cbc 546static void bus_method_resolve_record_complete(DnsQuery *q) {
4afd3348 547 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
23b298bc
LP
548 DnsResourceRecord *rr;
549 DnsQuestion *question;
45ec7efb 550 unsigned added = 0;
23b298bc 551 int ifindex;
2d4c5cbc
LP
552 int r;
553
554 assert(q);
555
ec2c5e43 556 if (q->state != DNS_TRANSACTION_SUCCESS) {
2d4c5cbc
LP
557 r = reply_query_state(q);
558 goto finish;
559 }
560
45ec7efb
LP
561 r = dns_query_process_cname(q);
562 if (r == -ELOOP) {
23b298bc 563 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
45ec7efb
LP
564 goto finish;
565 }
566 if (r < 0)
567 goto finish;
7588460a 568 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
45ec7efb
LP
569 return;
570
2d4c5cbc
LP
571 r = sd_bus_message_new_method_return(q->request, &reply);
572 if (r < 0)
573 goto finish;
574
78c6a153 575 r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
2d4c5cbc
LP
576 if (r < 0)
577 goto finish;
578
23b298bc 579 question = dns_query_question_for_protocol(q, q->answer_protocol);
2d4c5cbc 580
23b298bc
LP
581 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
582 r = dns_question_matches_rr(question, rr, NULL);
583 if (r < 0)
584 goto finish;
585 if (r == 0)
586 continue;
2d4c5cbc 587
23b298bc
LP
588 r = bus_message_append_rr(reply, rr, ifindex);
589 if (r < 0)
590 goto finish;
2d4c5cbc 591
313cefa1 592 added++;
2d4c5cbc
LP
593 }
594
595 if (added <= 0) {
23b298bc 596 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Name '%s' does not have any RR of the requested type", dns_query_string(q));
2d4c5cbc
LP
597 goto finish;
598 }
599
600 r = sd_bus_message_close_container(reply);
601 if (r < 0)
602 goto finish;
603
28830a64 604 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
51323288
LP
605 if (r < 0)
606 goto finish;
607
2d4c5cbc
LP
608 r = sd_bus_send(q->manager->bus, reply, NULL);
609
610finish:
611 if (r < 0) {
da927ba9 612 log_error_errno(r, "Failed to send record reply: %m");
45ec7efb 613 sd_bus_reply_method_errno(q->request, r, NULL);
2d4c5cbc
LP
614 }
615
616 dns_query_free(q);
617}
618
19070062 619static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2d4c5cbc
LP
620 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
621 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2d4c5cbc 622 Manager *m = userdata;
2d4c5cbc
LP
623 uint16_t class, type;
624 const char *name;
51323288
LP
625 int r, ifindex;
626 uint64_t flags;
627 DnsQuery *q;
2d4c5cbc 628
2d4c5cbc
LP
629 assert(message);
630 assert(m);
631
45ec7efb
LP
632 assert_cc(sizeof(int) == sizeof(int32_t));
633
51323288 634 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
2d4c5cbc
LP
635 if (r < 0)
636 return r;
637
45ec7efb 638 r = dns_name_is_valid(name);
7b9f7afc 639 if (r < 0)
45ec7efb
LP
640 return r;
641 if (r == 0)
7b9f7afc
LP
642 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
643
c463eb78 644 if (!dns_type_is_valid_query(type))
eee026a7 645 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified resource record type %" PRIu16 " may not be used in a query.", type);
6ebd1e33
LP
646 if (dns_type_is_zone_transer(type))
647 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Zone transfers not permitted via this programming interface.");
d0129ddb 648 if (dns_type_is_obsolete(type))
eee026a7 649 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type);
c463eb78 650
45ec7efb 651 r = check_ifindex_flags(ifindex, &flags, 0, error);
51323288
LP
652 if (r < 0)
653 return r;
654
2d4c5cbc
LP
655 question = dns_question_new(1);
656 if (!question)
657 return -ENOMEM;
658
659 key = dns_resource_key_new(class, type, name);
660 if (!key)
661 return -ENOMEM;
662
663 r = dns_question_add(question, key);
664 if (r < 0)
665 return r;
666
23b298bc 667 r = dns_query_new(m, &q, question, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
2d4c5cbc
LP
668 if (r < 0)
669 return r;
670
17c8de63
LP
671 /* Let's request that the TTL is fixed up for locally cached entries, after all we return it in the wire format
672 * blob */
673 q->clamp_ttl = true;
674
2d4c5cbc 675 q->request = sd_bus_message_ref(message);
2d4c5cbc
LP
676 q->complete = bus_method_resolve_record_complete;
677
966c66e3 678 r = dns_query_bus_track(q, message);
82bd6ddd 679 if (r < 0)
45ec7efb 680 goto fail;
82bd6ddd 681
2d4c5cbc 682 r = dns_query_go(q);
45ec7efb
LP
683 if (r < 0)
684 goto fail;
685
686 return 1;
687
688fail:
689 dns_query_free(q);
690 return r;
691}
692
693static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
694 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
c77d2612 695 _cleanup_free_ char *normalized = NULL;
45ec7efb
LP
696 DnsQuery *aux;
697 int r;
698
699 assert(q);
700 assert(reply);
701 assert(rr);
702 assert(rr->key);
703
704 if (rr->key->type != DNS_TYPE_SRV)
705 return 0;
706
707 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
708 /* First, let's see if we could find an appropriate A or AAAA
709 * record for the SRV record */
710 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
711 DnsResourceRecord *zz;
23b298bc 712 DnsQuestion *question;
45ec7efb
LP
713
714 if (aux->state != DNS_TRANSACTION_SUCCESS)
715 continue;
716 if (aux->auxiliary_result != 0)
717 continue;
718
23b298bc
LP
719 question = dns_query_question_for_protocol(aux, aux->answer_protocol);
720
721 r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
45ec7efb
LP
722 if (r < 0)
723 return r;
724 if (r == 0)
725 continue;
726
727 DNS_ANSWER_FOREACH(zz, aux->answer) {
728
23b298bc 729 r = dns_question_matches_rr(question, zz, NULL);
45ec7efb
LP
730 if (r < 0)
731 return r;
732 if (r == 0)
733 continue;
734
735 canonical = dns_resource_record_ref(zz);
736 break;
737 }
738
739 if (canonical)
740 break;
741 }
742
743 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
744 if (!canonical)
745 return 0;
746 }
747
748 r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
749 if (r < 0)
750 return r;
751
7470cc4c 752 r = dns_name_normalize(rr->srv.name, 0, &normalized);
c77d2612
LP
753 if (r < 0)
754 return r;
755
45ec7efb
LP
756 r = sd_bus_message_append(
757 reply,
758 "qqqs",
c77d2612 759 rr->srv.priority, rr->srv.weight, rr->srv.port, normalized);
45ec7efb
LP
760 if (r < 0)
761 return r;
762
763 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
764 if (r < 0)
765 return r;
766
767 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
768 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
769 DnsResourceRecord *zz;
23b298bc 770 DnsQuestion *question;
45ec7efb
LP
771 int ifindex;
772
773 if (aux->state != DNS_TRANSACTION_SUCCESS)
774 continue;
775 if (aux->auxiliary_result != 0)
776 continue;
777
23b298bc
LP
778 question = dns_query_question_for_protocol(aux, aux->answer_protocol);
779
780 r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
45ec7efb
LP
781 if (r < 0)
782 return r;
783 if (r == 0)
784 continue;
785
786 DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
787
23b298bc 788 r = dns_question_matches_rr(question, zz, NULL);
45ec7efb
LP
789 if (r < 0)
790 return r;
791 if (r == 0)
792 continue;
793
794 r = append_address(reply, zz, ifindex);
795 if (r < 0)
796 return r;
797 }
798 }
799 }
800
801 r = sd_bus_message_close_container(reply);
802 if (r < 0)
803 return r;
804
c77d2612
LP
805 if (canonical) {
806 normalized = mfree(normalized);
807
7470cc4c 808 r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized);
c77d2612
LP
809 if (r < 0)
810 return r;
811 }
812
45ec7efb
LP
813 /* Note that above we appended the hostname as encoded in the
814 * SRV, and here the canonical hostname this maps to. */
c77d2612 815 r = sd_bus_message_append(reply, "s", normalized);
45ec7efb
LP
816 if (r < 0)
817 return r;
818
819 r = sd_bus_message_close_container(reply);
820 if (r < 0)
821 return r;
822
823 return 1;
824}
825
826static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
827 DnsTxtItem *i;
828 int r;
829
830 assert(reply);
831 assert(rr);
832 assert(rr->key);
833
834 if (rr->key->type != DNS_TYPE_TXT)
835 return 0;
836
837 LIST_FOREACH(items, i, rr->txt.items) {
838
839 if (i->length <= 0)
840 continue;
841
842 r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
843 if (r < 0)
844 return r;
845 }
846
847 return 1;
848}
849
850static void resolve_service_all_complete(DnsQuery *q) {
851 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
852 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
853 _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
23b298bc
LP
854 DnsQuestion *question;
855 DnsResourceRecord *rr;
856 unsigned added = 0;
45ec7efb 857 DnsQuery *aux;
45ec7efb
LP
858 int r;
859
860 assert(q);
861
862 if (q->block_all_complete > 0)
863 return;
864
865 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
866 DnsQuery *bad = NULL;
867 bool have_success = false;
868
869 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
870
871 switch (aux->state) {
872
873 case DNS_TRANSACTION_PENDING:
874 /* If an auxiliary query is still pending, let's wait */
875 return;
876
877 case DNS_TRANSACTION_SUCCESS:
878 if (aux->auxiliary_result == 0)
879 have_success = true;
880 else
881 bad = aux;
882 break;
883
884 default:
885 bad = aux;
886 break;
887 }
888 }
889
890 if (!have_success) {
891 /* We can only return one error, hence pick the last error we encountered */
892
893 assert(bad);
894
895 if (bad->state == DNS_TRANSACTION_SUCCESS) {
896 assert(bad->auxiliary_result != 0);
897
898 if (bad->auxiliary_result == -ELOOP) {
23b298bc 899 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad));
45ec7efb
LP
900 goto finish;
901 }
902
903 r = bad->auxiliary_result;
904 goto finish;
905 }
906
907 r = reply_query_state(bad);
908 goto finish;
909 }
910 }
911
912 r = sd_bus_message_new_method_return(q->request, &reply);
913 if (r < 0)
914 goto finish;
915
916 r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
917 if (r < 0)
918 goto finish;
919
23b298bc
LP
920 question = dns_query_question_for_protocol(q, q->answer_protocol);
921 DNS_ANSWER_FOREACH(rr, q->answer) {
922 r = dns_question_matches_rr(question, rr, NULL);
923 if (r < 0)
924 goto finish;
925 if (r == 0)
926 continue;
45ec7efb 927
23b298bc
LP
928 r = append_srv(q, reply, rr);
929 if (r < 0)
930 goto finish;
931 if (r == 0) /* not an SRV record */
932 continue;
45ec7efb 933
23b298bc
LP
934 if (!canonical)
935 canonical = dns_resource_record_ref(rr);
45ec7efb 936
23b298bc 937 added++;
45ec7efb
LP
938 }
939
940 if (added <= 0) {
23b298bc 941 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
45ec7efb
LP
942 goto finish;
943 }
944
945 r = sd_bus_message_close_container(reply);
946 if (r < 0)
947 goto finish;
948
949 r = sd_bus_message_open_container(reply, 'a', "ay");
950 if (r < 0)
951 goto finish;
952
23b298bc
LP
953 DNS_ANSWER_FOREACH(rr, q->answer) {
954 r = dns_question_matches_rr(question, rr, NULL);
955 if (r < 0)
956 goto finish;
957 if (r == 0)
958 continue;
45ec7efb 959
23b298bc
LP
960 r = append_txt(reply, rr);
961 if (r < 0)
962 goto finish;
45ec7efb
LP
963 }
964
965 r = sd_bus_message_close_container(reply);
966 if (r < 0)
967 goto finish;
968
969 assert(canonical);
1c02e7ba 970 r = dns_service_split(dns_resource_key_name(canonical->key), &name, &type, &domain);
45ec7efb
LP
971 if (r < 0)
972 goto finish;
973
974 r = sd_bus_message_append(
975 reply,
976 "ssst",
977 name, type, domain,
28830a64 978 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, dns_query_fully_authenticated(q)));
45ec7efb
LP
979 if (r < 0)
980 goto finish;
981
982 r = sd_bus_send(q->manager->bus, reply, NULL);
983
984finish:
985 if (r < 0) {
986 log_error_errno(r, "Failed to send service reply: %m");
987 sd_bus_reply_method_errno(q->request, r, NULL);
988 }
989
990 dns_query_free(q);
991}
992
993static void resolve_service_hostname_complete(DnsQuery *q) {
994 int r;
995
996 assert(q);
997 assert(q->auxiliary_for);
998
999 if (q->state != DNS_TRANSACTION_SUCCESS) {
1000 resolve_service_all_complete(q->auxiliary_for);
1001 return;
1002 }
1003
1004 r = dns_query_process_cname(q);
7588460a 1005 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
45ec7efb
LP
1006 return;
1007
1008 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
1009 q->auxiliary_result = r;
1010 resolve_service_all_complete(q->auxiliary_for);
1011}
1012
1013static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
1014 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1015 DnsQuery *aux;
1016 int r;
1017
1018 assert(q);
1019 assert(rr);
1020 assert(rr->key);
1021 assert(rr->key->type == DNS_TYPE_SRV);
1022
1023 /* OK, we found an SRV record for the service. Let's resolve
1024 * the hostname included in it */
1025
23b298bc 1026 r = dns_question_new_address(&question, q->request_family, rr->srv.name, false);
45ec7efb
LP
1027 if (r < 0)
1028 return r;
1029
23b298bc 1030 r = dns_query_new(q->manager, &aux, question, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
45ec7efb
LP
1031 if (r < 0)
1032 return r;
1033
1034 aux->request_family = q->request_family;
1035 aux->complete = resolve_service_hostname_complete;
1036
1037 r = dns_query_make_auxiliary(aux, q);
1038 if (r == -EAGAIN) {
1039 /* Too many auxiliary lookups? If so, don't complain,
1040 * let's just not add this one, we already have more
1041 * than enough */
1042
1043 dns_query_free(aux);
1044 return 0;
1045 }
1046 if (r < 0)
1047 goto fail;
1048
1049 /* Note that auxiliary queries do not track the original bus
1050 * client, only the primary request does that. */
1051
1052 r = dns_query_go(aux);
1053 if (r < 0)
1054 goto fail;
1055
1056 return 1;
1057
1058fail:
1059 dns_query_free(aux);
1060 return r;
1061}
1062
1063static void bus_method_resolve_service_complete(DnsQuery *q) {
23b298bc
LP
1064 bool has_root_domain = false;
1065 DnsResourceRecord *rr;
1066 DnsQuestion *question;
45ec7efb 1067 unsigned found = 0;
23b298bc 1068 int ifindex, r;
45ec7efb
LP
1069
1070 assert(q);
1071
1072 if (q->state != DNS_TRANSACTION_SUCCESS) {
1073 r = reply_query_state(q);
1074 goto finish;
1075 }
1076
1077 r = dns_query_process_cname(q);
1078 if (r == -ELOOP) {
23b298bc 1079 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
45ec7efb
LP
1080 goto finish;
1081 }
1082 if (r < 0)
1083 goto finish;
7588460a 1084 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
45ec7efb
LP
1085 return;
1086
23b298bc 1087 question = dns_query_question_for_protocol(q, q->answer_protocol);
45ec7efb 1088
23b298bc
LP
1089 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
1090 r = dns_question_matches_rr(question, rr, NULL);
1091 if (r < 0)
1092 goto finish;
1093 if (r == 0)
1094 continue;
45ec7efb 1095
23b298bc
LP
1096 if (rr->key->type != DNS_TYPE_SRV)
1097 continue;
9a1f0c28 1098
23b298bc
LP
1099 if (dns_name_is_root(rr->srv.name)) {
1100 has_root_domain = true;
1101 continue;
1102 }
45ec7efb 1103
23b298bc 1104 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
313cefa1 1105 q->block_all_complete++;
23b298bc 1106 r = resolve_service_hostname(q, rr, ifindex);
313cefa1 1107 q->block_all_complete--;
45ec7efb 1108
23b298bc
LP
1109 if (r < 0)
1110 goto finish;
45ec7efb 1111 }
9a1f0c28 1112
23b298bc
LP
1113 found++;
1114 }
9a1f0c28 1115
23b298bc
LP
1116 if (has_root_domain && found <= 0) {
1117 /* If there's exactly one SRV RR and it uses
38b38500 1118 * the root domain as hostname, then the
23b298bc
LP
1119 * service is explicitly not offered on the
1120 * domain. Report this as a recognizable
1121 * error. See RFC 2782, Section "Usage
1122 * Rules". */
1123 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_query_string(q));
1124 goto finish;
45ec7efb
LP
1125 }
1126
1127 if (found <= 0) {
23b298bc 1128 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
45ec7efb
LP
1129 goto finish;
1130 }
1131
1132 /* Maybe we are already finished? check now... */
1133 resolve_service_all_complete(q);
1134 return;
1135
1136finish:
2d4c5cbc 1137 if (r < 0) {
45ec7efb
LP
1138 log_error_errno(r, "Failed to send service reply: %m");
1139 sd_bus_reply_method_errno(q->request, r, NULL);
1140 }
1141
1142 dns_query_free(q);
1143}
1144
1145static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
23b298bc
LP
1146 _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
1147 const char *name, *type, *domain;
45ec7efb
LP
1148 Manager *m = userdata;
1149 int family, ifindex;
1150 uint64_t flags;
1151 DnsQuery *q;
1152 int r;
1153
1154 assert(message);
1155 assert(m);
1156
1157 assert_cc(sizeof(int) == sizeof(int32_t));
1158
1159 r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags);
1160 if (r < 0)
2d4c5cbc 1161 return r;
45ec7efb
LP
1162
1163 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
1164 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
1165
1166 if (isempty(name))
1167 name = NULL;
23b298bc
LP
1168 else if (!dns_service_name_is_valid(name))
1169 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name);
2d4c5cbc 1170
45ec7efb
LP
1171 if (isempty(type))
1172 type = NULL;
7e8131e9
LP
1173 else if (!dns_srv_type_is_valid(type))
1174 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type);
45ec7efb
LP
1175
1176 r = dns_name_is_valid(domain);
1177 if (r < 0)
1178 return r;
1179 if (r == 0)
1180 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
1181
1182 if (name && !type)
1183 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
1184
1185 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
1186 if (r < 0)
1187 return r;
1188
23b298bc
LP
1189 r = dns_question_new_service(&question_utf8, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), false);
1190 if (r < 0)
1191 return r;
45ec7efb 1192
23b298bc 1193 r = dns_question_new_service(&question_idna, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), true);
45ec7efb
LP
1194 if (r < 0)
1195 return r;
1196
23b298bc 1197 r = dns_query_new(m, &q, question_utf8, question_idna, ifindex, flags|SD_RESOLVED_NO_SEARCH);
45ec7efb
LP
1198 if (r < 0)
1199 return r;
1200
1201 q->request = sd_bus_message_ref(message);
1202 q->request_family = family;
1203 q->complete = bus_method_resolve_service_complete;
1204
1205 r = dns_query_bus_track(q, message);
1206 if (r < 0)
1207 goto fail;
1208
1209 r = dns_query_go(q);
1210 if (r < 0)
1211 goto fail;
1212
2d4c5cbc 1213 return 1;
45ec7efb
LP
1214
1215fail:
1216 dns_query_free(q);
1217 return r;
2d4c5cbc
LP
1218}
1219
3abaabda 1220int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex) {
7f220d94
LP
1221 int r;
1222
1223 assert(reply);
b7ac92cd
YW
1224
1225 if (!s) {
1226 if (with_ifindex)
1227 return sd_bus_message_append(reply, "(iiay)", 0, AF_UNSPEC, 0);
1228 else
1229 return sd_bus_message_append(reply, "(iay)", AF_UNSPEC, 0);
1230 }
7f220d94 1231
3abaabda 1232 r = sd_bus_message_open_container(reply, 'r', with_ifindex ? "iiay" : "iay");
7f220d94
LP
1233 if (r < 0)
1234 return r;
1235
3abaabda 1236 if (with_ifindex) {
2817157b 1237 r = sd_bus_message_append(reply, "i", dns_server_ifindex(s));
3abaabda
LP
1238 if (r < 0)
1239 return r;
1240 }
1241
1242 r = sd_bus_message_append(reply, "i", s->family);
7f220d94
LP
1243 if (r < 0)
1244 return r;
1245
1246 r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family));
1247 if (r < 0)
1248 return r;
1249
1250 return sd_bus_message_close_container(reply);
1251}
1252
1253static int bus_property_get_dns_servers(
1254 sd_bus *bus,
1255 const char *path,
1256 const char *interface,
1257 const char *property,
1258 sd_bus_message *reply,
1259 void *userdata,
1260 sd_bus_error *error) {
1261
1262 Manager *m = userdata;
7f220d94
LP
1263 DnsServer *s;
1264 Iterator i;
1265 Link *l;
1266 int r;
1267
1268 assert(reply);
1269 assert(m);
1270
1271 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
1272 if (r < 0)
1273 return r;
1274
1275 LIST_FOREACH(servers, s, m->dns_servers) {
3abaabda 1276 r = bus_dns_server_append(reply, s, true);
7f220d94
LP
1277 if (r < 0)
1278 return r;
7f220d94
LP
1279 }
1280
b2c15546 1281 HASHMAP_FOREACH(l, m->links, i)
7f220d94 1282 LIST_FOREACH(servers, s, l->dns_servers) {
3abaabda 1283 r = bus_dns_server_append(reply, s, true);
7f220d94
LP
1284 if (r < 0)
1285 return r;
7f220d94 1286 }
7f220d94 1287
ad32ac53
YW
1288 return sd_bus_message_close_container(reply);
1289}
1290
1291static int bus_property_get_fallback_dns_servers(
1292 sd_bus *bus,
1293 const char *path,
1294 const char *interface,
1295 const char *property,
1296 sd_bus_message *reply,
1297 void *userdata,
1298 sd_bus_error *error) {
1299
1300 DnsServer *s, **f = userdata;
1301 int r;
1302
1303 assert(reply);
1304 assert(f);
1305
1306 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
1307 if (r < 0)
1308 return r;
1309
1310 LIST_FOREACH(servers, s, *f) {
1311 r = bus_dns_server_append(reply, s, true);
1312 if (r < 0)
1313 return r;
7f220d94
LP
1314 }
1315
1316 return sd_bus_message_close_container(reply);
1317}
1318
b7ac92cd
YW
1319static int bus_property_get_current_dns_server(
1320 sd_bus *bus,
1321 const char *path,
1322 const char *interface,
1323 const char *property,
1324 sd_bus_message *reply,
1325 void *userdata,
1326 sd_bus_error *error) {
1327
1328 DnsServer *s;
1329
1330 assert(reply);
1331 assert(userdata);
1332
1333 s = *(DnsServer **) userdata;
1334
1335 return bus_dns_server_append(reply, s, true);
1336}
1337
ee116b54 1338static int bus_property_get_domains(
7f220d94
LP
1339 sd_bus *bus,
1340 const char *path,
1341 const char *interface,
1342 const char *property,
1343 sd_bus_message *reply,
1344 void *userdata,
1345 sd_bus_error *error) {
1346
1347 Manager *m = userdata;
1348 DnsSearchDomain *d;
1349 Iterator i;
1350 Link *l;
1351 int r;
1352
1353 assert(reply);
1354 assert(m);
1355
ad44b56b 1356 r = sd_bus_message_open_container(reply, 'a', "(isb)");
7f220d94
LP
1357 if (r < 0)
1358 return r;
1359
1360 LIST_FOREACH(domains, d, m->search_domains) {
ad44b56b 1361 r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only);
7f220d94
LP
1362 if (r < 0)
1363 return r;
1364 }
1365
1366 HASHMAP_FOREACH(l, m->links, i) {
1367 LIST_FOREACH(domains, d, l->search_domains) {
ad44b56b 1368 r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only);
7f220d94
LP
1369 if (r < 0)
1370 return r;
1371 }
1372 }
1373
1374 return sd_bus_message_close_container(reply);
1375}
1376
a150ff5e
LP
1377static int bus_property_get_transaction_statistics(
1378 sd_bus *bus,
1379 const char *path,
1380 const char *interface,
1381 const char *property,
1382 sd_bus_message *reply,
1383 void *userdata,
1384 sd_bus_error *error) {
1385
1386 Manager *m = userdata;
1387
1388 assert(reply);
1389 assert(m);
1390
1391 return sd_bus_message_append(reply, "(tt)",
1392 (uint64_t) hashmap_size(m->dns_transactions),
1393 (uint64_t) m->n_transactions_total);
1394}
1395
1396static int bus_property_get_cache_statistics(
1397 sd_bus *bus,
1398 const char *path,
1399 const char *interface,
1400 const char *property,
1401 sd_bus_message *reply,
1402 void *userdata,
1403 sd_bus_error *error) {
1404
1405 uint64_t size = 0, hit = 0, miss = 0;
1406 Manager *m = userdata;
1407 DnsScope *s;
1408
1409 assert(reply);
1410 assert(m);
1411
1412 LIST_FOREACH(scopes, s, m->dns_scopes) {
1413 size += dns_cache_size(&s->cache);
1414 hit += s->cache.n_hit;
1415 miss += s->cache.n_miss;
1416 }
1417
1418 return sd_bus_message_append(reply, "(ttt)", size, hit, miss);
1419}
1420
1421static int bus_property_get_dnssec_statistics(
1422 sd_bus *bus,
1423 const char *path,
1424 const char *interface,
1425 const char *property,
1426 sd_bus_message *reply,
1427 void *userdata,
1428 sd_bus_error *error) {
1429
1430 Manager *m = userdata;
1431
1432 assert(reply);
1433 assert(m);
1434
1435 return sd_bus_message_append(reply, "(tttt)",
59c5b597
LP
1436 (uint64_t) m->n_dnssec_verdict[DNSSEC_SECURE],
1437 (uint64_t) m->n_dnssec_verdict[DNSSEC_INSECURE],
1438 (uint64_t) m->n_dnssec_verdict[DNSSEC_BOGUS],
1439 (uint64_t) m->n_dnssec_verdict[DNSSEC_INDETERMINATE]);
a150ff5e
LP
1440}
1441
476798b1
LP
1442static int bus_property_get_ntas(
1443 sd_bus *bus,
1444 const char *path,
1445 const char *interface,
1446 const char *property,
1447 sd_bus_message *reply,
1448 void *userdata,
1449 sd_bus_error *error) {
1450
1451 Manager *m = userdata;
1452 const char *domain;
1453 Iterator i;
1454 int r;
1455
1456 assert(reply);
1457 assert(m);
1458
1459 r = sd_bus_message_open_container(reply, 'a', "s");
1460 if (r < 0)
1461 return r;
1462
1463 SET_FOREACH(domain, m->trust_anchor.negative_by_name, i) {
1464 r = sd_bus_message_append(reply, "s", domain);
1465 if (r < 0)
1466 return r;
1467 }
1468
1469 return sd_bus_message_close_container(reply);
1470}
1471
7ed1565a 1472static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode);
acd380c4
YW
1473static BUS_DEFINE_PROPERTY_GET(bus_property_get_dnssec_supported, "b", Manager, manager_dnssec_supported);
1474static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode, "s", Manager, manager_get_dnssec_mode, dnssec_mode_to_string);
c9299be2 1475static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dns_over_tls_mode, "s", Manager, manager_get_dns_over_tls_mode, dns_over_tls_mode_to_string);
7ed1565a 1476
a150ff5e
LP
1477static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1478 Manager *m = userdata;
1479 DnsScope *s;
1480
1481 assert(message);
1482 assert(m);
1483
1484 LIST_FOREACH(scopes, s, m->dns_scopes)
1485 s->cache.n_hit = s->cache.n_miss = 0;
1486
1487 m->n_transactions_total = 0;
59c5b597 1488 zero(m->n_dnssec_verdict);
a150ff5e
LP
1489
1490 return sd_bus_reply_method_return(message, NULL);
1491}
1492
3abaabda 1493static int get_any_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) {
97e5d693
LP
1494 Link *l;
1495
1496 assert(m);
3abaabda 1497 assert(ret);
97e5d693
LP
1498
1499 if (ifindex <= 0)
1500 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
1501
1502 l = hashmap_get(m->links, INT_TO_PTR(ifindex));
1503 if (!l)
1504 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex);
3abaabda
LP
1505
1506 *ret = l;
1507 return 0;
1508}
1509
d2ec6608 1510static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
97e5d693 1511 int ifindex, r;
97e5d693
LP
1512 Link *l;
1513
97e5d693 1514 assert(m);
97e5d693 1515 assert(message);
d2ec6608 1516 assert(handler);
97e5d693 1517
d2ec6608 1518 assert_cc(sizeof(int) == sizeof(int32_t));
97e5d693
LP
1519 r = sd_bus_message_read(message, "i", &ifindex);
1520 if (r < 0)
1521 return r;
1522
04b764bf 1523 r = get_any_link(m, ifindex, &l, error);
97e5d693
LP
1524 if (r < 0)
1525 return r;
1526
d2ec6608
LP
1527 return handler(message, l, error);
1528}
97e5d693 1529
d2ec6608
LP
1530static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1531 return call_link_method(userdata, message, bus_link_method_set_dns_servers, error);
1532}
97e5d693 1533
ee116b54
LP
1534static int bus_method_set_link_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1535 return call_link_method(userdata, message, bus_link_method_set_domains, error);
97e5d693
LP
1536}
1537
77673795
LP
1538static int bus_method_set_link_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1539 return call_link_method(userdata, message, bus_link_method_set_default_route, error);
1540}
1541
97e5d693 1542static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d2ec6608 1543 return call_link_method(userdata, message, bus_link_method_set_llmnr, error);
97e5d693
LP
1544}
1545
1546static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d2ec6608 1547 return call_link_method(userdata, message, bus_link_method_set_mdns, error);
97e5d693
LP
1548}
1549
c9299be2
IT
1550static int bus_method_set_link_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1551 return call_link_method(userdata, message, bus_link_method_set_dns_over_tls, error);
b761a107
YW
1552}
1553
97e5d693 1554static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d2ec6608 1555 return call_link_method(userdata, message, bus_link_method_set_dnssec, error);
97e5d693
LP
1556}
1557
1558static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d2ec6608 1559 return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error);
97e5d693
LP
1560}
1561
1562static int bus_method_revert_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
d2ec6608 1563 return call_link_method(userdata, message, bus_link_method_revert, error);
97e5d693
LP
1564}
1565
3abaabda
LP
1566static int bus_method_get_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1567 _cleanup_free_ char *p = NULL;
1568 Manager *m = userdata;
1569 int r, ifindex;
1570 Link *l;
1571
1572 assert(message);
1573 assert(m);
1574
1575 assert_cc(sizeof(int) == sizeof(int32_t));
3abaabda
LP
1576 r = sd_bus_message_read(message, "i", &ifindex);
1577 if (r < 0)
1578 return r;
1579
1580 r = get_any_link(m, ifindex, &l, error);
1581 if (r < 0)
1582 return r;
1583
1584 p = link_bus_path(l);
1585 if (!p)
1586 return -ENOMEM;
1587
1588 return sd_bus_reply_method_return(message, "o", p);
1589}
1590
ba35662f
LP
1591static int bus_method_flush_caches(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1592 Manager *m = userdata;
1593
1594 assert(message);
1595 assert(m);
1596
1597 manager_flush_caches(m);
1598
1599 return sd_bus_reply_method_return(message, NULL);
1600}
1601
d55b0463
LP
1602static int bus_method_reset_server_features(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1603 Manager *m = userdata;
1604
1605 assert(message);
1606 assert(m);
1607
1608 manager_reset_server_features(m);
1609
1610 return sd_bus_reply_method_return(message, NULL);
1611}
1612
c3036641
DR
1613static int on_bus_track(sd_bus_track *t, void *userdata) {
1614 DnssdService *s = userdata;
1615
1616 assert(t);
1617 assert(s);
1618
1619 log_debug("Client of active request vanished, destroying DNS-SD service.");
1620 dnssd_service_free(s);
1621
1622 return 0;
1623}
1624
1625static int bus_method_register_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
84b0f133 1626 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
c3036641
DR
1627 _cleanup_(dnssd_service_freep) DnssdService *service = NULL;
1628 _cleanup_(sd_bus_track_unrefp) sd_bus_track *bus_track = NULL;
1629 _cleanup_free_ char *path = NULL;
1630 _cleanup_free_ char *instance_name = NULL;
1631 Manager *m = userdata;
1632 DnssdService *s = NULL;
c3036641
DR
1633 const char *name;
1634 const char *name_template;
1635 const char *type;
84b0f133 1636 uid_t euid;
c3036641
DR
1637 int r;
1638
1639 assert(message);
1640 assert(m);
1641
1642 if (m->mdns_support != RESOLVE_SUPPORT_YES)
1643 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled");
1644
1645 service = new0(DnssdService, 1);
1646 if (!service)
1647 return log_oom();
1648
84b0f133
DR
1649 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1650 if (r < 0)
1651 return r;
1652
1653 r = sd_bus_creds_get_euid(creds, &euid);
1654 if (r < 0)
1655 return r;
1656 service->originator = euid;
1657
c3036641
DR
1658 r = sd_bus_message_read(message, "sssqqq", &name, &name_template, &type,
1659 &service->port, &service->priority,
1660 &service->weight);
1661 if (r < 0)
1662 return r;
1663
1664 s = hashmap_get(m->dnssd_services, name);
1665 if (s)
1666 return sd_bus_error_setf(error, BUS_ERROR_DNSSD_SERVICE_EXISTS, "DNS-SD service '%s' exists already", name);
1667
1668 if (!dnssd_srv_type_is_valid(type))
1669 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DNS-SD service type '%s' is invalid", type);
1670
1671 service->name = strdup(name);
1672 if (!service->name)
1673 return log_oom();
1674
1675 service->name_template = strdup(name_template);
1676 if (!service->name_template)
1677 return log_oom();
1678
1679 service->type = strdup(type);
1680 if (!service->type)
1681 return log_oom();
1682
1683 r = dnssd_render_instance_name(service, &instance_name);
1684 if (r < 0)
1685 return r;
1686
400f54fb 1687 r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "a{say}");
c3036641 1688 if (r < 0)
400f54fb 1689 return r;
c3036641 1690
400f54fb
DR
1691 while ((r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "{say}")) > 0) {
1692 _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
1693 DnsTxtItem *last = NULL;
c3036641 1694
400f54fb
DR
1695 txt_data = new0(DnssdTxtData, 1);
1696 if (!txt_data)
1697 return log_oom();
1698
1699 while ((r = sd_bus_message_enter_container(message, SD_BUS_TYPE_DICT_ENTRY, "say")) > 0) {
1700 const char *key;
1701 const void *value;
1702 size_t size;
1703 DnsTxtItem *i;
1704
1705 r = sd_bus_message_read(message, "s", &key);
1706 if (r < 0)
1707 return r;
1708
1709 if (isempty(key))
1710 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Keys in DNS-SD TXT RRs can't be empty");
c3036641 1711
400f54fb
DR
1712 if (!ascii_is_valid(key))
1713 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TXT key '%s' contains non-ASCII symbols", key);
c3036641 1714
400f54fb
DR
1715 r = sd_bus_message_read_array(message, 'y', &value, &size);
1716 if (r < 0)
1717 return r;
c3036641 1718
400f54fb
DR
1719 r = dnssd_txt_item_new_from_data(key, value, size, &i);
1720 if (r < 0)
1721 return r;
1722
1723 LIST_INSERT_AFTER(items, txt_data->txt, last, i);
1724 last = i;
1725
1726 r = sd_bus_message_exit_container(message);
1727 if (r < 0)
1728 return r;
1729
1730 }
c3036641 1731 if (r < 0)
400f54fb 1732 return r;
c3036641 1733
400f54fb 1734 r = sd_bus_message_exit_container(message);
c3036641 1735 if (r < 0)
400f54fb 1736 return r;
c3036641 1737
400f54fb
DR
1738 if (txt_data->txt) {
1739 LIST_PREPEND(items, service->txt_data_items, txt_data);
1740 txt_data = NULL;
1741 }
c3036641 1742 }
400f54fb
DR
1743 if (r < 0)
1744 return r;
c3036641
DR
1745
1746 r = sd_bus_message_exit_container(message);
1747 if (r < 0)
400f54fb
DR
1748 return r;
1749
1750 if (!service->txt_data_items) {
1751 _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
c3036641 1752
400f54fb
DR
1753 txt_data = new0(DnssdTxtData, 1);
1754 if (!txt_data)
1755 return log_oom();
1756
1757 r = dns_txt_item_new_empty(&txt_data->txt);
c3036641 1758 if (r < 0)
400f54fb
DR
1759 return r;
1760
1761 LIST_PREPEND(items, service->txt_data_items, txt_data);
1762 txt_data = NULL;
c3036641
DR
1763 }
1764
1765 r = sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", service->name, &path);
1766 if (r < 0)
1767 return r;
1768
fd73184f
ZJS
1769 r = bus_verify_polkit_async(message, CAP_SYS_ADMIN,
1770 "org.freedesktop.resolve1.register-service",
1771 NULL, false, UID_INVALID,
1772 &m->polkit_registry, error);
1773 if (r < 0)
1774 return r;
1775 if (r == 0)
1776 return 1; /* Polkit will call us back */
1777
c3036641
DR
1778 r = hashmap_ensure_allocated(&m->dnssd_services, &string_hash_ops);
1779 if (r < 0)
1780 return r;
1781
1782 r = hashmap_put(m->dnssd_services, service->name, service);
1783 if (r < 0)
1784 return r;
1785
1786 r = sd_bus_track_new(sd_bus_message_get_bus(message), &bus_track, on_bus_track, service);
1787 if (r < 0)
1788 return r;
1789
1790 r = sd_bus_track_add_sender(bus_track, message);
1791 if (r < 0)
1792 return r;
1793
1794 service->manager = m;
1795
1796 service = NULL;
1797
1798 manager_refresh_rrs(m);
1799
1800 return sd_bus_reply_method_return(message, "o", path);
1801}
1802
1803static int call_dnssd_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
1804 _cleanup_free_ char *name = NULL;
1805 DnssdService *s = NULL;
1806 const char *path;
1807 int r;
1808
1809 assert(m);
1810 assert(message);
1811 assert(handler);
1812
1813 r = sd_bus_message_read(message, "o", &path);
1814 if (r < 0)
1815 return r;
1816
1817 r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/dnssd", &name);
1818 if (r == 0)
1819 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DNSSD_SERVICE, "DNS-SD service with object path '%s' does not exist", path);
1820 if (r < 0)
1821 return r;
1822
1823 s = hashmap_get(m->dnssd_services, name);
1824 if (!s)
1825 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DNSSD_SERVICE, "DNS-SD service '%s' not known", name);
1826
1827 return handler(message, s, error);
1828}
1829
1830static int bus_method_unregister_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1831 Manager *m = userdata;
1832
1833 assert(message);
1834 assert(m);
1835
1836 return call_dnssd_method(m, message, bus_dnssd_method_unregister, error);
1837}
1838
df957849
ZJS
1839static int property_get_log_level(
1840 sd_bus *bus,
1841 const char *path,
1842 const char *interface,
1843 const char *property,
1844 sd_bus_message *reply,
1845 void *userdata,
1846 sd_bus_error *error) {
1847
1848 _cleanup_free_ char *t = NULL;
1849 int r;
1850
1851 assert(bus);
1852 assert(reply);
1853
1854 r = log_level_to_string_alloc(log_get_max_level(), &t);
1855 if (r < 0)
1856 return r;
1857
1858 return sd_bus_message_append(reply, "s", t);
1859}
1860
1861static int property_set_log_level(
1862 sd_bus *bus,
1863 const char *path,
1864 const char *interface,
1865 const char *property,
1866 sd_bus_message *value,
1867 void *userdata,
1868 sd_bus_error *error) {
1869
1870 const char *t;
1871 int r;
1872
1873 assert(bus);
1874 assert(value);
1875
1876 r = sd_bus_message_read(value, "s", &t);
1877 if (r < 0)
1878 return r;
1879
1880 r = log_level_from_string(t);
1881 if (r < 0)
1882 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid log level '%s'", t);
1883
1884 log_info("Setting log level to %s.", t);
1885 log_set_max_level(r);
1886
1887 return 0;
1888}
1889
74b2466e
LP
1890static const sd_bus_vtable resolve_vtable[] = {
1891 SD_BUS_VTABLE_START(0),
86c0411e 1892 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
bf4e5c4c
YW
1893 SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Manager, llmnr_support), 0),
1894 SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Manager, mdns_support), 0),
c9299be2 1895 SD_BUS_PROPERTY("DNSOverTLS", "s", bus_property_get_dns_over_tls_mode, 0, 0),
5f3340ca 1896 SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
ad32ac53 1897 SD_BUS_PROPERTY("FallbackDNS", "a(iiay)", bus_property_get_fallback_dns_servers, offsetof(Manager, fallback_dns_servers), SD_BUS_VTABLE_PROPERTY_CONST),
4a6f996c 1898 SD_BUS_PROPERTY("CurrentDNSServer", "(iiay)", bus_property_get_current_dns_server, offsetof(Manager, current_dns_server), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
ee116b54 1899 SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains, 0, 0),
a150ff5e
LP
1900 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
1901 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
bf4e5c4c 1902 SD_BUS_PROPERTY("DNSSEC", "s", bus_property_get_dnssec_mode, 0, 0),
a150ff5e 1903 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
593f665c 1904 SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0),
476798b1 1905 SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas, 0, 0),
7ed1565a 1906 SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode, offsetof(Manager, dns_stub_listener_mode), 0),
7f220d94 1907
df957849 1908 SD_BUS_WRITABLE_PROPERTY("LogLevel", "s", property_get_log_level, property_set_log_level, 0, 0),
edc6a803
ZJS
1909
1910 SD_BUS_METHOD_WITH_NAMES("ResolveHostname",
1911 "isit",
1912 SD_BUS_PARAM(ifindex)
1913 SD_BUS_PARAM(name)
1914 SD_BUS_PARAM(family)
1915 SD_BUS_PARAM(flags),
1916 "a(iiay)st",
1917 SD_BUS_PARAM(addresses)
1918 SD_BUS_PARAM(canonical)
1919 SD_BUS_PARAM(flags),
1920 bus_method_resolve_hostname,
1921 SD_BUS_VTABLE_UNPRIVILEGED),
1922 SD_BUS_METHOD_WITH_NAMES("ResolveAddress",
1923 "iiayt",
1924 SD_BUS_PARAM(ifindex)
1925 SD_BUS_PARAM(family)
1926 SD_BUS_PARAM(address)
1927 SD_BUS_PARAM(flags),
1928 "a(is)t",
1929 SD_BUS_PARAM(names)
1930 SD_BUS_PARAM(flags),
1931 bus_method_resolve_address,
1932 SD_BUS_VTABLE_UNPRIVILEGED),
1933 SD_BUS_METHOD_WITH_NAMES("ResolveRecord",
1934 "isqqt",
1935 SD_BUS_PARAM(ifindex)
1936 SD_BUS_PARAM(name)
1937 SD_BUS_PARAM(class)
1938 SD_BUS_PARAM(type)
1939 SD_BUS_PARAM(flags),
1940 "a(iqqay)t",
1941 SD_BUS_PARAM(records)
1942 SD_BUS_PARAM(flags),
1943 bus_method_resolve_record,
1944 SD_BUS_VTABLE_UNPRIVILEGED),
1945 SD_BUS_METHOD_WITH_NAMES("ResolveService",
1946 "isssit",
1947 SD_BUS_PARAM(ifindex)
1948 SD_BUS_PARAM(name)
1949 SD_BUS_PARAM(type)
1950 SD_BUS_PARAM(domain)
1951 SD_BUS_PARAM(family)
1952 SD_BUS_PARAM(flags),
1953 "a(qqqsa(iiay)s)aayssst",
1954 SD_BUS_PARAM(srv_data)
1955 SD_BUS_PARAM(txt_data)
1956 SD_BUS_PARAM(canonical_name)
1957 SD_BUS_PARAM(canonical_type)
1958 SD_BUS_PARAM(canonical_domain)
1959 SD_BUS_PARAM(flags),
1960 bus_method_resolve_service,
1961 SD_BUS_VTABLE_UNPRIVILEGED),
1962 SD_BUS_METHOD_WITH_NAMES("GetLink",
1963 "i",
1964 SD_BUS_PARAM(ifindex),
1965 "o",
1966 SD_BUS_PARAM(path),
1967 bus_method_get_link,
1968 SD_BUS_VTABLE_UNPRIVILEGED),
1969 SD_BUS_METHOD_WITH_NAMES("SetLinkDNS",
1970 "ia(iay)",
1971 SD_BUS_PARAM(ifindex)
1972 SD_BUS_PARAM(addresses),
1973 NULL,,
1974 bus_method_set_link_dns_servers,
1975 SD_BUS_VTABLE_UNPRIVILEGED),
1976 SD_BUS_METHOD_WITH_NAMES("SetLinkDomains",
1977 "ia(sb)",
1978 SD_BUS_PARAM(ifindex)
1979 SD_BUS_PARAM(domains),
1980 NULL,,
1981 bus_method_set_link_domains,
1982 SD_BUS_VTABLE_UNPRIVILEGED),
1983 SD_BUS_METHOD_WITH_NAMES("SetLinkDefaultRoute",
1984 "ib",
1985 SD_BUS_PARAM(ifindex)
1986 SD_BUS_PARAM(enable),
1987 NULL,,
1988 bus_method_set_link_default_route,
1989 SD_BUS_VTABLE_UNPRIVILEGED),
1990 SD_BUS_METHOD_WITH_NAMES("SetLinkLLMNR",
1991 "is",
1992 SD_BUS_PARAM(ifindex)
1993 SD_BUS_PARAM(mode),
1994 NULL,,
1995 bus_method_set_link_llmnr,
1996 SD_BUS_VTABLE_UNPRIVILEGED),
1997 SD_BUS_METHOD_WITH_NAMES("SetLinkMulticastDNS",
1998 "is",
1999 SD_BUS_PARAM(ifindex)
2000 SD_BUS_PARAM(mode),
2001 NULL,,
2002 bus_method_set_link_mdns,
2003 SD_BUS_VTABLE_UNPRIVILEGED),
2004 SD_BUS_METHOD_WITH_NAMES("SetLinkDNSOverTLS",
2005 "is",
2006 SD_BUS_PARAM(ifindex)
2007 SD_BUS_PARAM(mode),
2008 NULL,,
2009 bus_method_set_link_dns_over_tls,
2010 SD_BUS_VTABLE_UNPRIVILEGED),
2011 SD_BUS_METHOD_WITH_NAMES("SetLinkDNSSEC",
2012 "is",
2013 SD_BUS_PARAM(ifindex)
2014 SD_BUS_PARAM(mode),
2015 NULL,,
2016 bus_method_set_link_dnssec,
2017 SD_BUS_VTABLE_UNPRIVILEGED),
2018 SD_BUS_METHOD_WITH_NAMES("SetLinkDNSSECNegativeTrustAnchors",
2019 "ias",
2020 SD_BUS_PARAM(ifindex)
2021 SD_BUS_PARAM(names),
2022 NULL,,
2023 bus_method_set_link_dnssec_negative_trust_anchors,
2024 SD_BUS_VTABLE_UNPRIVILEGED),
2025 SD_BUS_METHOD_WITH_NAMES("RevertLink",
2026 "i",
2027 SD_BUS_PARAM(ifindex),
2028 NULL,,
2029 bus_method_revert_link,
2030 SD_BUS_VTABLE_UNPRIVILEGED),
2031 SD_BUS_METHOD_WITH_NAMES("RegisterService",
2032 "sssqqqaa{say}",
2033 SD_BUS_PARAM(name)
2034 SD_BUS_PARAM(name_template)
2035 SD_BUS_PARAM(type)
2036 SD_BUS_PARAM(service_port)
2037 SD_BUS_PARAM(service_priority)
2038 SD_BUS_PARAM(serwise_weight)
2039 SD_BUS_PARAM(txt_datas),
2040 "o",
2041 SD_BUS_PARAM(service_path),
2042 bus_method_register_service,
2043 SD_BUS_VTABLE_UNPRIVILEGED),
2044 SD_BUS_METHOD_WITH_NAMES("UnregisterService",
2045 "o",
2046 SD_BUS_PARAM(service_path),
2047 NULL,,
2048 bus_method_unregister_service,
2049 SD_BUS_VTABLE_UNPRIVILEGED),
2050
2051 SD_BUS_METHOD("ResetStatistics",
2052 NULL,
2053 NULL,
2054 bus_method_reset_statistics,
2055 SD_BUS_VTABLE_UNPRIVILEGED),
2056 SD_BUS_METHOD("FlushCaches",
2057 NULL,
2058 NULL,
2059 bus_method_flush_caches,
2060 SD_BUS_VTABLE_UNPRIVILEGED),
2061 SD_BUS_METHOD("ResetServerFeatures",
2062 NULL,
2063 NULL,
2064 bus_method_reset_server_features,
2065 SD_BUS_VTABLE_UNPRIVILEGED),
2066
74b2466e
LP
2067 SD_BUS_VTABLE_END,
2068};
2069
19070062 2070static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
902bb5d8
LP
2071 Manager *m = userdata;
2072 int b, r;
2073
19070062
LP
2074 assert(message);
2075 assert(m);
902bb5d8
LP
2076
2077 r = sd_bus_message_read(message, "b", &b);
2078 if (r < 0) {
da927ba9 2079 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
902bb5d8
LP
2080 return 0;
2081 }
2082
2083 if (b)
2084 return 0;
2085
2086 log_debug("Coming back from suspend, verifying all RRs...");
2087
2088 manager_verify_all(m);
2089 return 0;
2090}
2091
74b2466e
LP
2092int manager_connect_bus(Manager *m) {
2093 int r;
2094
2095 assert(m);
2096
2097 if (m->bus)
2098 return 0;
2099
8c6afb77 2100 r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-resolve");
d7afd945
LP
2101 if (r < 0)
2102 return log_error_errno(r, "Failed to connect to system bus: %m");
74b2466e 2103
4d1cf1e2 2104 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
f647962d
MS
2105 if (r < 0)
2106 return log_error_errno(r, "Failed to register object: %m");
74b2466e 2107
3abaabda
LP
2108 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/link", "org.freedesktop.resolve1.Link", link_vtable, link_object_find, m);
2109 if (r < 0)
2110 return log_error_errno(r, "Failed to register link objects: %m");
2111
2112 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/link", link_node_enumerator, m);
2113 if (r < 0)
2114 return log_error_errno(r, "Failed to register link enumerator: %m");
2115
c3036641
DR
2116 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/resolve1/dnssd", "org.freedesktop.resolve1.DnssdService", dnssd_vtable, dnssd_object_find, m);
2117 if (r < 0)
2118 return log_error_errno(r, "Failed to register dnssd objects: %m");
2119
2120 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/resolve1/dnssd", dnssd_node_enumerator, m);
2121 if (r < 0)
2122 return log_error_errno(r, "Failed to register dnssd enumerator: %m");
2123
62fb7e80 2124 r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL, NULL);
f647962d 2125 if (r < 0)
0c0b9306 2126 return log_error_errno(r, "Failed to request name: %m");
74b2466e
LP
2127
2128 r = sd_bus_attach_event(m->bus, m->event, 0);
f647962d
MS
2129 if (r < 0)
2130 return log_error_errno(r, "Failed to attach bus to event loop: %m");
74b2466e 2131
75152a4d
LP
2132 r = sd_bus_match_signal_async(
2133 m->bus,
4b0051b1 2134 NULL,
75152a4d
LP
2135 "org.freedesktop.login1",
2136 "/org/freedesktop/login1",
2137 "org.freedesktop.login1.Manager",
2138 "PrepareForSleep",
2139 match_prepare_for_sleep,
2140 NULL,
2141 m);
2142 if (r < 0)
d7afd945 2143 log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
902bb5d8 2144
74b2466e
LP
2145 return 0;
2146}
5f3340ca
ZJS
2147
2148int _manager_send_changed(Manager *manager, const char *property, ...) {
2149 assert(manager);
2150
2151 char **l = strv_from_stdarg_alloca(property);
2152
2153 int r = sd_bus_emit_properties_changed_strv(
2154 manager->bus,
2155 "/org/freedesktop/resolve1",
2156 "org.freedesktop.resolve1.Manager",
2157 l);
2158 if (r < 0)
2159 log_notice_errno(r, "Failed to emit notification about changed property %s: %m", property);
2160 return r;
2161}