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