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