]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-bus.c
resolved: log about reasons for switching to TCP
[thirdparty/systemd.git] / src / resolve / resolved-bus.c
CommitLineData
74b2466e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
b5efdb8a 22#include "alloc-util.h"
96aad8d1 23#include "bus-common-errors.h"
74b2466e 24#include "bus-util.h"
4ad7f276 25#include "dns-domain.h"
39d8db04 26#include "resolved-bus.h"
51323288 27#include "resolved-def.h"
74b2466e 28
ad867662
LP
29static int reply_query_state(DnsQuery *q) {
30 _cleanup_free_ char *ip = NULL;
31 const char *name;
74b2466e
LP
32 int r;
33
45ec7efb 34 if (q->request_address_valid) {
ad867662
LP
35 r = in_addr_to_string(q->request_family, &q->request_address, &ip);
36 if (r < 0)
37 return r;
74b2466e 38
ad867662 39 name = ip;
45ec7efb 40 } else
703e4f5e 41 name = dns_question_first_name(q->question);
ad867662
LP
42
43 switch (q->state) {
74b2466e 44
ec2c5e43 45 case DNS_TRANSACTION_NO_SERVERS:
309e9d86 46 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
74b2466e 47
ec2c5e43 48 case DNS_TRANSACTION_TIMEOUT:
ad867662 49 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out");
74b2466e 50
ec2c5e43 51 case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
ad867662
LP
52 return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
53
818f766b
LP
54 case DNS_TRANSACTION_INVALID_REPLY:
55 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
56
ec2c5e43 57 case DNS_TRANSACTION_RESOURCES:
ad867662
LP
58 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources");
59
818f766b
LP
60 case DNS_TRANSACTION_ABORTED:
61 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted");
74b2466e 62
547973de 63 case DNS_TRANSACTION_DNSSEC_FAILED:
a761c1ca 64 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s",
019036a4 65 dnssec_result_to_string(q->answer_dnssec_result));
547973de 66
b2b796b8
LP
67 case DNS_TRANSACTION_NO_TRUST_ANCHOR:
68 return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known");
69
3bbdc31d 70 case DNS_TRANSACTION_RCODE_FAILURE: {
4afd3348 71 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
74b2466e 72
faa133f3 73 if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
ad867662 74 sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name);
74b2466e
LP
75 else {
76 const char *rc, *n;
ad867662 77 char p[3]; /* the rcode is 4 bits long */
74b2466e 78
faa133f3 79 rc = dns_rcode_to_string(q->answer_rcode);
74b2466e 80 if (!rc) {
faa133f3 81 sprintf(p, "%i", q->answer_rcode);
74b2466e
LP
82 rc = p;
83 }
84
63c372cb 85 n = strjoina(_BUS_ERROR_DNS, rc);
ad867662 86 sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc);
74b2466e
LP
87 }
88
ad867662 89 return sd_bus_reply_method_error(q->request, &error);
74b2466e
LP
90 }
91
ec2c5e43
LP
92 case DNS_TRANSACTION_NULL:
93 case DNS_TRANSACTION_PENDING:
94 case DNS_TRANSACTION_SUCCESS:
8ba9fd9c 95 default:
ad867662
LP
96 assert_not_reached("Impossible state");
97 }
98}
74b2466e 99
78c6a153 100static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
8ba9fd9c
LP
101 int r;
102
103 assert(reply);
104 assert(rr);
105
78c6a153
LP
106 r = sd_bus_message_open_container(reply, 'r', "iiay");
107 if (r < 0)
108 return r;
109
110 r = sd_bus_message_append(reply, "i", ifindex);
8ba9fd9c
LP
111 if (r < 0)
112 return r;
113
faa133f3 114 if (rr->key->type == DNS_TYPE_A) {
0dd25fb9 115 r = sd_bus_message_append(reply, "i", AF_INET);
8ba9fd9c
LP
116 if (r < 0)
117 return r;
118
119 r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
faa133f3
LP
120
121 } else if (rr->key->type == DNS_TYPE_AAAA) {
0dd25fb9 122 r = sd_bus_message_append(reply, "i", AF_INET6);
8ba9fd9c
LP
123 if (r < 0)
124 return r;
125
126 r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
faa133f3
LP
127 } else
128 return -EAFNOSUPPORT;
129
8ba9fd9c
LP
130 if (r < 0)
131 return r;
132
8ba9fd9c
LP
133 r = sd_bus_message_close_container(reply);
134 if (r < 0)
135 return r;
136
137 return 0;
138}
139
ad867662 140static void bus_method_resolve_hostname_complete(DnsQuery *q) {
45ec7efb 141 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
4afd3348 142 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
45ec7efb 143 unsigned added = 0;
51323288 144 int r;
74b2466e 145
ad867662 146 assert(q);
74b2466e 147
ec2c5e43 148 if (q->state != DNS_TRANSACTION_SUCCESS) {
ad867662
LP
149 r = reply_query_state(q);
150 goto finish;
151 }
74b2466e 152
45ec7efb
LP
153 r = dns_query_process_cname(q);
154 if (r == -ELOOP) {
703e4f5e 155 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
45ec7efb
LP
156 goto finish;
157 }
158 if (r < 0)
159 goto finish;
7588460a 160 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
45ec7efb
LP
161 return;
162
ad867662
LP
163 r = sd_bus_message_new_method_return(q->request, &reply);
164 if (r < 0)
165 goto finish;
74b2466e 166
78c6a153 167 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
51323288
LP
168 if (r < 0)
169 goto finish;
8ba9fd9c 170
3339cb71 171 if (q->answer) {
45ec7efb
LP
172 DnsResourceRecord *rr;
173 int ifindex;
3339cb71 174
45ec7efb 175 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
801ad6a6 176 r = dns_question_matches_rr(q->question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
8ba9fd9c 177 if (r < 0)
2d4c5cbc 178 goto finish;
45ec7efb 179 if (r == 0)
3339cb71 180 continue;
74b2466e 181
45ec7efb 182 r = append_address(reply, rr, ifindex);
3339cb71
LP
183 if (r < 0)
184 goto finish;
74b2466e 185
3339cb71 186 if (!canonical)
45ec7efb 187 canonical = dns_resource_record_ref(rr);
309e9d86 188
3339cb71
LP
189 added ++;
190 }
8ba9fd9c 191 }
74b2466e 192
45ec7efb 193 if (added <= 0) {
703e4f5e 194 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
45ec7efb 195 goto finish;
74b2466e
LP
196 }
197
ad867662
LP
198 r = sd_bus_message_close_container(reply);
199 if (r < 0)
200 goto finish;
201
45ec7efb 202 /* Return the precise spelling and uppercasing and CNAME target reported by the server */
309e9d86 203 assert(canonical);
45ec7efb
LP
204 r = sd_bus_message_append(
205 reply, "st",
206 DNS_RESOURCE_KEY_NAME(canonical->key),
931851e8 207 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
309e9d86
LP
208 if (r < 0)
209 goto finish;
210
ad867662 211 r = sd_bus_send(q->manager->bus, reply, NULL);
ad867662 212
74b2466e 213finish:
2d4c5cbc 214 if (r < 0) {
da927ba9 215 log_error_errno(r, "Failed to send hostname reply: %m");
45ec7efb 216 sd_bus_reply_method_errno(q->request, r, NULL);
2d4c5cbc 217 }
74b2466e
LP
218
219 dns_query_free(q);
220}
221
45ec7efb 222static int check_ifindex_flags(int ifindex, uint64_t *flags, uint64_t ok, sd_bus_error *error) {
51323288
LP
223 assert(flags);
224
225 if (ifindex < 0)
226 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
227
45ec7efb 228 if (*flags & ~(SD_RESOLVED_PROTOCOLS_ALL|SD_RESOLVED_NO_CNAME|ok))
51323288
LP
229 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
230
45ec7efb
LP
231 if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
232 *flags |= SD_RESOLVED_PROTOCOLS_ALL;
51323288
LP
233
234 return 0;
235}
236
19070062 237static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
faa133f3 238 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
74b2466e
LP
239 Manager *m = userdata;
240 const char *hostname;
51323288
LP
241 int family, ifindex;
242 uint64_t flags;
74b2466e 243 DnsQuery *q;
74b2466e
LP
244 int r;
245
74b2466e
LP
246 assert(message);
247 assert(m);
248
45ec7efb
LP
249 assert_cc(sizeof(int) == sizeof(int32_t));
250
51323288 251 r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
74b2466e
LP
252 if (r < 0)
253 return r;
254
255 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
0dd25fb9 256 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
74b2466e 257
45ec7efb 258 r = dns_name_is_valid(hostname);
7b9f7afc 259 if (r < 0)
45ec7efb
LP
260 return r;
261 if (r == 0)
74b2466e
LP
262 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
263
801ad6a6 264 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_SEARCH, error);
51323288
LP
265 if (r < 0)
266 return r;
267
45ec7efb
LP
268 r = dns_question_new_address(&question, family, hostname);
269 if (r < 0)
270 return r;
74b2466e 271
51323288 272 r = dns_query_new(m, &q, question, ifindex, flags);
74b2466e
LP
273 if (r < 0)
274 return r;
275
276 q->request = sd_bus_message_ref(message);
277 q->request_family = family;
74b2466e
LP
278 q->complete = bus_method_resolve_hostname_complete;
279
966c66e3 280 r = dns_query_bus_track(q, message);
82bd6ddd 281 if (r < 0)
45ec7efb 282 goto fail;
82bd6ddd 283
322345fd 284 r = dns_query_go(q);
45ec7efb
LP
285 if (r < 0)
286 goto fail;
74b2466e
LP
287
288 return 1;
45ec7efb
LP
289
290fail:
291 dns_query_free(q);
292 return r;
74b2466e
LP
293}
294
295static void bus_method_resolve_address_complete(DnsQuery *q) {
4afd3348 296 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
45ec7efb
LP
297 DnsResourceRecord *rr;
298 unsigned added = 0;
299 int ifindex, r;
74b2466e
LP
300
301 assert(q);
302
ec2c5e43 303 if (q->state != DNS_TRANSACTION_SUCCESS) {
ad867662
LP
304 r = reply_query_state(q);
305 goto finish;
306 }
74b2466e 307
95d46fca
TG
308 r = dns_query_process_cname(q);
309 if (r == -ELOOP) {
039a8725 310 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
95d46fca
TG
311 goto finish;
312 }
313 if (r < 0)
314 goto finish;
7588460a 315 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
95d46fca 316 return;
45ec7efb 317
ad867662
LP
318 r = sd_bus_message_new_method_return(q->request, &reply);
319 if (r < 0)
320 goto finish;
74b2466e 321
78c6a153 322 r = sd_bus_message_open_container(reply, 'a', "(is)");
ad867662
LP
323 if (r < 0)
324 goto finish;
74b2466e 325
3339cb71 326 if (q->answer) {
45ec7efb 327 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
801ad6a6 328 r = dns_question_matches_rr(q->question, rr, NULL);
3339cb71 329 if (r < 0)
2d4c5cbc 330 goto finish;
3339cb71
LP
331 if (r == 0)
332 continue;
74b2466e 333
45ec7efb 334 r = sd_bus_message_append(reply, "(is)", ifindex, rr->ptr.name);
3339cb71
LP
335 if (r < 0)
336 goto finish;
74b2466e 337
3339cb71
LP
338 added ++;
339 }
ad867662 340 }
74b2466e 341
45ec7efb 342 if (added <= 0) {
ad867662 343 _cleanup_free_ char *ip = NULL;
74b2466e 344
ad867662 345 in_addr_to_string(q->request_family, &q->request_address, &ip);
45ec7efb 346 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "Address '%s' does not have any RR of requested type", strna(ip));
ad867662 347 goto finish;
74b2466e
LP
348 }
349
ad867662
LP
350 r = sd_bus_message_close_container(reply);
351 if (r < 0)
352 goto finish;
74b2466e 353
931851e8 354 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
51323288
LP
355 if (r < 0)
356 goto finish;
357
ad867662 358 r = sd_bus_send(q->manager->bus, reply, NULL);
74b2466e
LP
359
360finish:
2d4c5cbc 361 if (r < 0) {
da927ba9 362 log_error_errno(r, "Failed to send address reply: %m");
45ec7efb 363 sd_bus_reply_method_errno(q->request, r, NULL);
2d4c5cbc 364 }
74b2466e
LP
365
366 dns_query_free(q);
367}
368
19070062 369static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
faa133f3 370 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
74b2466e 371 Manager *m = userdata;
faa133f3 372 int family, ifindex;
51323288 373 uint64_t flags;
74b2466e 374 const void *d;
74b2466e
LP
375 DnsQuery *q;
376 size_t sz;
377 int r;
378
74b2466e
LP
379 assert(message);
380 assert(m);
381
45ec7efb
LP
382 assert_cc(sizeof(int) == sizeof(int32_t));
383
51323288 384 r = sd_bus_message_read(message, "ii", &ifindex, &family);
74b2466e
LP
385 if (r < 0)
386 return r;
387
388 if (!IN_SET(family, AF_INET, AF_INET6))
0dd25fb9 389 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
74b2466e
LP
390
391 r = sd_bus_message_read_array(message, 'y', &d, &sz);
392 if (r < 0)
393 return r;
394
0dd25fb9 395 if (sz != FAMILY_ADDRESS_SIZE(family))
74b2466e
LP
396 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
397
51323288
LP
398 r = sd_bus_message_read(message, "t", &flags);
399 if (r < 0)
400 return r;
401
45ec7efb 402 r = check_ifindex_flags(ifindex, &flags, 0, error);
faa133f3
LP
403 if (r < 0)
404 return r;
405
45ec7efb 406 r = dns_question_new_reverse(&question, family, d);
74b2466e
LP
407 if (r < 0)
408 return r;
409
801ad6a6 410 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
74b2466e
LP
411 if (r < 0)
412 return r;
413
414 q->request = sd_bus_message_ref(message);
415 q->request_family = family;
416 memcpy(&q->request_address, d, sz);
417 q->complete = bus_method_resolve_address_complete;
418
966c66e3 419 r = dns_query_bus_track(q, message);
82bd6ddd 420 if (r < 0)
45ec7efb 421 goto fail;
82bd6ddd 422
322345fd 423 r = dns_query_go(q);
45ec7efb
LP
424 if (r < 0)
425 goto fail;
74b2466e
LP
426
427 return 1;
45ec7efb
LP
428
429fail:
430 dns_query_free(q);
431 return r;
432}
433
434static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) {
45ec7efb
LP
435 int r;
436
437 assert(m);
438 assert(rr);
439
440 r = sd_bus_message_open_container(m, 'r', "iqqay");
441 if (r < 0)
442 return r;
443
444 r = sd_bus_message_append(m, "iqq",
445 ifindex,
446 rr->key->class,
447 rr->key->type);
448 if (r < 0)
449 return r;
450
4e2d538f 451 r = dns_resource_record_to_wire_format(rr, false);
45ec7efb
LP
452 if (r < 0)
453 return r;
454
4e2d538f 455 r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size);
45ec7efb
LP
456 if (r < 0)
457 return r;
458
459 return sd_bus_message_close_container(m);
74b2466e
LP
460}
461
2d4c5cbc 462static void bus_method_resolve_record_complete(DnsQuery *q) {
4afd3348 463 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
45ec7efb 464 unsigned added = 0;
2d4c5cbc
LP
465 int r;
466
467 assert(q);
468
ec2c5e43 469 if (q->state != DNS_TRANSACTION_SUCCESS) {
2d4c5cbc
LP
470 r = reply_query_state(q);
471 goto finish;
472 }
473
45ec7efb
LP
474 r = dns_query_process_cname(q);
475 if (r == -ELOOP) {
703e4f5e 476 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
45ec7efb
LP
477 goto finish;
478 }
479 if (r < 0)
480 goto finish;
7588460a 481 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
45ec7efb
LP
482 return;
483
2d4c5cbc
LP
484 r = sd_bus_message_new_method_return(q->request, &reply);
485 if (r < 0)
486 goto finish;
487
78c6a153 488 r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
2d4c5cbc
LP
489 if (r < 0)
490 goto finish;
491
492 if (q->answer) {
45ec7efb
LP
493 DnsResourceRecord *rr;
494 int ifindex;
2d4c5cbc 495
45ec7efb 496 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
801ad6a6 497 r = dns_question_matches_rr(q->question, rr, NULL);
2d4c5cbc
LP
498 if (r < 0)
499 goto finish;
500 if (r == 0)
501 continue;
502
45ec7efb 503 r = bus_message_append_rr(reply, rr, ifindex);
2d4c5cbc
LP
504 if (r < 0)
505 goto finish;
506
507 added ++;
508 }
509 }
510
511 if (added <= 0) {
703e4f5e 512 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_question_first_name(q->question));
2d4c5cbc
LP
513 goto finish;
514 }
515
516 r = sd_bus_message_close_container(reply);
517 if (r < 0)
518 goto finish;
519
931851e8 520 r = sd_bus_message_append(reply, "t", SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
51323288
LP
521 if (r < 0)
522 goto finish;
523
2d4c5cbc
LP
524 r = sd_bus_send(q->manager->bus, reply, NULL);
525
526finish:
527 if (r < 0) {
da927ba9 528 log_error_errno(r, "Failed to send record reply: %m");
45ec7efb 529 sd_bus_reply_method_errno(q->request, r, NULL);
2d4c5cbc
LP
530 }
531
532 dns_query_free(q);
533}
534
19070062 535static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2d4c5cbc
LP
536 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
537 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2d4c5cbc 538 Manager *m = userdata;
2d4c5cbc
LP
539 uint16_t class, type;
540 const char *name;
51323288
LP
541 int r, ifindex;
542 uint64_t flags;
543 DnsQuery *q;
2d4c5cbc 544
2d4c5cbc
LP
545 assert(message);
546 assert(m);
547
45ec7efb
LP
548 assert_cc(sizeof(int) == sizeof(int32_t));
549
51323288 550 r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
2d4c5cbc
LP
551 if (r < 0)
552 return r;
553
45ec7efb 554 r = dns_name_is_valid(name);
7b9f7afc 555 if (r < 0)
45ec7efb
LP
556 return r;
557 if (r == 0)
7b9f7afc
LP
558 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
559
c463eb78
LP
560 if (!dns_type_is_valid_query(type))
561 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid RR type for query %" PRIu16, type);
562
45ec7efb 563 r = check_ifindex_flags(ifindex, &flags, 0, error);
51323288
LP
564 if (r < 0)
565 return r;
566
2d4c5cbc
LP
567 question = dns_question_new(1);
568 if (!question)
569 return -ENOMEM;
570
571 key = dns_resource_key_new(class, type, name);
572 if (!key)
573 return -ENOMEM;
574
575 r = dns_question_add(question, key);
576 if (r < 0)
577 return r;
578
801ad6a6 579 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
2d4c5cbc
LP
580 if (r < 0)
581 return r;
582
583 q->request = sd_bus_message_ref(message);
2d4c5cbc
LP
584 q->complete = bus_method_resolve_record_complete;
585
966c66e3 586 r = dns_query_bus_track(q, message);
82bd6ddd 587 if (r < 0)
45ec7efb 588 goto fail;
82bd6ddd 589
2d4c5cbc 590 r = dns_query_go(q);
45ec7efb
LP
591 if (r < 0)
592 goto fail;
593
594 return 1;
595
596fail:
597 dns_query_free(q);
598 return r;
599}
600
601static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
602 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
603 DnsQuery *aux;
604 int r;
605
606 assert(q);
607 assert(reply);
608 assert(rr);
609 assert(rr->key);
610
611 if (rr->key->type != DNS_TYPE_SRV)
612 return 0;
613
614 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
615 /* First, let's see if we could find an appropriate A or AAAA
616 * record for the SRV record */
617 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
618 DnsResourceRecord *zz;
619
620 if (aux->state != DNS_TRANSACTION_SUCCESS)
621 continue;
622 if (aux->auxiliary_result != 0)
623 continue;
624
703e4f5e 625 r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
45ec7efb
LP
626 if (r < 0)
627 return r;
628 if (r == 0)
629 continue;
630
631 DNS_ANSWER_FOREACH(zz, aux->answer) {
632
801ad6a6 633 r = dns_question_matches_rr(aux->question, zz, NULL);
45ec7efb
LP
634 if (r < 0)
635 return r;
636 if (r == 0)
637 continue;
638
639 canonical = dns_resource_record_ref(zz);
640 break;
641 }
642
643 if (canonical)
644 break;
645 }
646
647 /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
648 if (!canonical)
649 return 0;
650 }
651
652 r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
653 if (r < 0)
654 return r;
655
656 r = sd_bus_message_append(
657 reply,
658 "qqqs",
659 rr->srv.priority, rr->srv.weight, rr->srv.port, rr->srv.name);
660 if (r < 0)
661 return r;
662
663 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
664 if (r < 0)
665 return r;
666
667 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
668 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
669 DnsResourceRecord *zz;
670 int ifindex;
671
672 if (aux->state != DNS_TRANSACTION_SUCCESS)
673 continue;
674 if (aux->auxiliary_result != 0)
675 continue;
676
703e4f5e 677 r = dns_name_equal(dns_question_first_name(aux->question), rr->srv.name);
45ec7efb
LP
678 if (r < 0)
679 return r;
680 if (r == 0)
681 continue;
682
683 DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
684
801ad6a6 685 r = dns_question_matches_rr(aux->question, zz, NULL);
45ec7efb
LP
686 if (r < 0)
687 return r;
688 if (r == 0)
689 continue;
690
691 r = append_address(reply, zz, ifindex);
692 if (r < 0)
693 return r;
694 }
695 }
696 }
697
698 r = sd_bus_message_close_container(reply);
699 if (r < 0)
700 return r;
701
702 /* Note that above we appended the hostname as encoded in the
703 * SRV, and here the canonical hostname this maps to. */
704 r = sd_bus_message_append(reply, "s", canonical ? DNS_RESOURCE_KEY_NAME(canonical->key) : rr->srv.name);
705 if (r < 0)
706 return r;
707
708 r = sd_bus_message_close_container(reply);
709 if (r < 0)
710 return r;
711
712 return 1;
713}
714
715static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
716 DnsTxtItem *i;
717 int r;
718
719 assert(reply);
720 assert(rr);
721 assert(rr->key);
722
723 if (rr->key->type != DNS_TYPE_TXT)
724 return 0;
725
726 LIST_FOREACH(items, i, rr->txt.items) {
727
728 if (i->length <= 0)
729 continue;
730
731 r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
732 if (r < 0)
733 return r;
734 }
735
736 return 1;
737}
738
739static void resolve_service_all_complete(DnsQuery *q) {
740 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
741 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
742 _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
743 DnsQuery *aux;
744 unsigned added = false;
745 int r;
746
747 assert(q);
748
749 if (q->block_all_complete > 0)
750 return;
751
752 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
753 DnsQuery *bad = NULL;
754 bool have_success = false;
755
756 LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
757
758 switch (aux->state) {
759
760 case DNS_TRANSACTION_PENDING:
761 /* If an auxiliary query is still pending, let's wait */
762 return;
763
764 case DNS_TRANSACTION_SUCCESS:
765 if (aux->auxiliary_result == 0)
766 have_success = true;
767 else
768 bad = aux;
769 break;
770
771 default:
772 bad = aux;
773 break;
774 }
775 }
776
777 if (!have_success) {
778 /* We can only return one error, hence pick the last error we encountered */
779
780 assert(bad);
781
782 if (bad->state == DNS_TRANSACTION_SUCCESS) {
783 assert(bad->auxiliary_result != 0);
784
785 if (bad->auxiliary_result == -ELOOP) {
703e4f5e 786 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(bad->question));
45ec7efb
LP
787 goto finish;
788 }
789
790 r = bad->auxiliary_result;
791 goto finish;
792 }
793
794 r = reply_query_state(bad);
795 goto finish;
796 }
797 }
798
799 r = sd_bus_message_new_method_return(q->request, &reply);
800 if (r < 0)
801 goto finish;
802
803 r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
804 if (r < 0)
805 goto finish;
806
807 if (q->answer) {
808 DnsResourceRecord *rr;
809
810 DNS_ANSWER_FOREACH(rr, q->answer) {
801ad6a6 811 r = dns_question_matches_rr(q->question, rr, NULL);
45ec7efb
LP
812 if (r < 0)
813 goto finish;
814 if (r == 0)
815 continue;
816
817 r = append_srv(q, reply, rr);
818 if (r < 0)
819 goto finish;
820 if (r == 0) /* not an SRV record */
821 continue;
822
823 if (!canonical)
824 canonical = dns_resource_record_ref(rr);
825
826 added++;
827 }
828 }
829
830 if (added <= 0) {
703e4f5e 831 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
45ec7efb
LP
832 goto finish;
833 }
834
835 r = sd_bus_message_close_container(reply);
836 if (r < 0)
837 goto finish;
838
839 r = sd_bus_message_open_container(reply, 'a', "ay");
840 if (r < 0)
841 goto finish;
842
843 if (q->answer) {
844 DnsResourceRecord *rr;
845
846 DNS_ANSWER_FOREACH(rr, q->answer) {
801ad6a6 847 r = dns_question_matches_rr(q->question, rr, NULL);
45ec7efb
LP
848 if (r < 0)
849 goto finish;
850 if (r == 0)
851 continue;
852
853 r = append_txt(reply, rr);
854 if (r < 0)
855 goto finish;
856 }
857 }
858
859 r = sd_bus_message_close_container(reply);
860 if (r < 0)
861 goto finish;
862
863 assert(canonical);
864 r = dns_service_split(DNS_RESOURCE_KEY_NAME(canonical->key), &name, &type, &domain);
865 if (r < 0)
866 goto finish;
867
868 r = sd_bus_message_append(
869 reply,
870 "ssst",
871 name, type, domain,
931851e8 872 SD_RESOLVED_FLAGS_MAKE(q->answer_protocol, q->answer_family, q->answer_authenticated));
45ec7efb
LP
873 if (r < 0)
874 goto finish;
875
876 r = sd_bus_send(q->manager->bus, reply, NULL);
877
878finish:
879 if (r < 0) {
880 log_error_errno(r, "Failed to send service reply: %m");
881 sd_bus_reply_method_errno(q->request, r, NULL);
882 }
883
884 dns_query_free(q);
885}
886
887static void resolve_service_hostname_complete(DnsQuery *q) {
888 int r;
889
890 assert(q);
891 assert(q->auxiliary_for);
892
893 if (q->state != DNS_TRANSACTION_SUCCESS) {
894 resolve_service_all_complete(q->auxiliary_for);
895 return;
896 }
897
898 r = dns_query_process_cname(q);
7588460a 899 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
45ec7efb
LP
900 return;
901
902 /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
903 q->auxiliary_result = r;
904 resolve_service_all_complete(q->auxiliary_for);
905}
906
907static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
908 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
909 DnsQuery *aux;
910 int r;
911
912 assert(q);
913 assert(rr);
914 assert(rr->key);
915 assert(rr->key->type == DNS_TYPE_SRV);
916
917 /* OK, we found an SRV record for the service. Let's resolve
918 * the hostname included in it */
919
920 r = dns_question_new_address(&question, q->request_family, rr->srv.name);
921 if (r < 0)
922 return r;
923
801ad6a6 924 r = dns_query_new(q->manager, &aux, question, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
45ec7efb
LP
925 if (r < 0)
926 return r;
927
928 aux->request_family = q->request_family;
929 aux->complete = resolve_service_hostname_complete;
930
931 r = dns_query_make_auxiliary(aux, q);
932 if (r == -EAGAIN) {
933 /* Too many auxiliary lookups? If so, don't complain,
934 * let's just not add this one, we already have more
935 * than enough */
936
937 dns_query_free(aux);
938 return 0;
939 }
940 if (r < 0)
941 goto fail;
942
943 /* Note that auxiliary queries do not track the original bus
944 * client, only the primary request does that. */
945
946 r = dns_query_go(aux);
947 if (r < 0)
948 goto fail;
949
950 return 1;
951
952fail:
953 dns_query_free(aux);
954 return r;
955}
956
957static void bus_method_resolve_service_complete(DnsQuery *q) {
958 unsigned found = 0;
959 int r;
960
961 assert(q);
962
963 if (q->state != DNS_TRANSACTION_SUCCESS) {
964 r = reply_query_state(q);
965 goto finish;
966 }
967
968 r = dns_query_process_cname(q);
969 if (r == -ELOOP) {
703e4f5e 970 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_question_first_name(q->question));
45ec7efb
LP
971 goto finish;
972 }
973 if (r < 0)
974 goto finish;
7588460a 975 if (r == DNS_QUERY_RESTARTED) /* This was a cname, and the query was restarted. */
45ec7efb
LP
976 return;
977
978 if (q->answer) {
9a1f0c28 979 bool has_root_domain = false;
45ec7efb
LP
980 DnsResourceRecord *rr;
981 int ifindex;
982
983 DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
801ad6a6 984 r = dns_question_matches_rr(q->question, rr, NULL);
45ec7efb
LP
985 if (r < 0)
986 goto finish;
987 if (r == 0)
988 continue;
989
990 if (rr->key->type != DNS_TYPE_SRV)
991 continue;
992
9a1f0c28
LP
993 if (dns_name_is_root(rr->srv.name)) {
994 has_root_domain = true;
995 continue;
996 }
997
45ec7efb
LP
998 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
999 q->block_all_complete ++;
1000 r = resolve_service_hostname(q, rr, ifindex);
1001 q->block_all_complete --;
1002
1003 if (r < 0)
1004 goto finish;
1005 }
1006
1007 found++;
1008 }
9a1f0c28
LP
1009
1010 if (has_root_domain && found == 0) {
1011 /* If there's exactly one SRV RR and it uses
1012 * the root domain as host name, then the
1013 * service is explicitly not offered on the
1014 * domain. Report this as a recognizable
1015 * error. See RFC 2782, Section "Usage
1016 * Rules". */
1017 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_question_first_name(q->question));
1018 goto finish;
1019 }
1020
45ec7efb
LP
1021 }
1022
1023 if (found <= 0) {
703e4f5e 1024 r = sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_question_first_name(q->question));
45ec7efb
LP
1025 goto finish;
1026 }
1027
1028 /* Maybe we are already finished? check now... */
1029 resolve_service_all_complete(q);
1030 return;
1031
1032finish:
2d4c5cbc 1033 if (r < 0) {
45ec7efb
LP
1034 log_error_errno(r, "Failed to send service reply: %m");
1035 sd_bus_reply_method_errno(q->request, r, NULL);
1036 }
1037
1038 dns_query_free(q);
1039}
1040
1041static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
45ec7efb
LP
1042 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1043 const char *name, *type, *domain, *joined;
1044 _cleanup_free_ char *n = NULL;
1045 Manager *m = userdata;
1046 int family, ifindex;
1047 uint64_t flags;
1048 DnsQuery *q;
1049 int r;
1050
1051 assert(message);
1052 assert(m);
1053
1054 assert_cc(sizeof(int) == sizeof(int32_t));
1055
1056 r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags);
1057 if (r < 0)
2d4c5cbc 1058 return r;
45ec7efb
LP
1059
1060 if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
1061 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
1062
1063 if (isempty(name))
1064 name = NULL;
1065 else {
1066 if (!dns_service_name_is_valid(name))
1067 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name);
2d4c5cbc
LP
1068 }
1069
45ec7efb
LP
1070 if (isempty(type))
1071 type = NULL;
7e8131e9
LP
1072 else if (!dns_srv_type_is_valid(type))
1073 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type);
45ec7efb
LP
1074
1075 r = dns_name_is_valid(domain);
1076 if (r < 0)
1077 return r;
1078 if (r == 0)
1079 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
1080
1081 if (name && !type)
1082 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
1083
1084 r = check_ifindex_flags(ifindex, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
1085 if (r < 0)
1086 return r;
1087
1088 if (type) {
1089 /* If the type is specified, we generate the full domain name to look up ourselves */
1090 r = dns_service_join(name, type, domain, &n);
1091 if (r < 0)
1092 return r;
1093
1094 joined = n;
1095 } else
1096 /* If no type is specified, we assume the domain
1097 * contains the full domain name to lookup already */
1098 joined = domain;
1099
1100 r = dns_question_new_service(&question, joined, !(flags & SD_RESOLVED_NO_TXT));
1101 if (r < 0)
1102 return r;
1103
801ad6a6 1104 r = dns_query_new(m, &q, question, ifindex, flags|SD_RESOLVED_NO_SEARCH);
45ec7efb
LP
1105 if (r < 0)
1106 return r;
1107
1108 q->request = sd_bus_message_ref(message);
1109 q->request_family = family;
1110 q->complete = bus_method_resolve_service_complete;
1111
1112 r = dns_query_bus_track(q, message);
1113 if (r < 0)
1114 goto fail;
1115
1116 r = dns_query_go(q);
1117 if (r < 0)
1118 goto fail;
1119
2d4c5cbc 1120 return 1;
45ec7efb
LP
1121
1122fail:
1123 dns_query_free(q);
1124 return r;
2d4c5cbc
LP
1125}
1126
7f220d94
LP
1127static int append_dns_server(sd_bus_message *reply, DnsServer *s) {
1128 int r;
1129
1130 assert(reply);
1131 assert(s);
1132
1133 r = sd_bus_message_open_container(reply, 'r', "iiay");
1134 if (r < 0)
1135 return r;
1136
1137 r = sd_bus_message_append(reply, "ii", s->link ? s->link->ifindex : 0, s->family);
1138 if (r < 0)
1139 return r;
1140
1141 r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family));
1142 if (r < 0)
1143 return r;
1144
1145 return sd_bus_message_close_container(reply);
1146}
1147
1148static int bus_property_get_dns_servers(
1149 sd_bus *bus,
1150 const char *path,
1151 const char *interface,
1152 const char *property,
1153 sd_bus_message *reply,
1154 void *userdata,
1155 sd_bus_error *error) {
1156
1157 Manager *m = userdata;
1158 unsigned c = 0;
1159 DnsServer *s;
1160 Iterator i;
1161 Link *l;
1162 int r;
1163
1164 assert(reply);
1165 assert(m);
1166
1167 r = sd_bus_message_open_container(reply, 'a', "(iiay)");
1168 if (r < 0)
1169 return r;
1170
1171 LIST_FOREACH(servers, s, m->dns_servers) {
1172 r = append_dns_server(reply, s);
1173 if (r < 0)
1174 return r;
1175
1176 c++;
1177 }
1178
1179 HASHMAP_FOREACH(l, m->links, i) {
1180 LIST_FOREACH(servers, s, l->dns_servers) {
1181 r = append_dns_server(reply, s);
1182 if (r < 0)
1183 return r;
1184 c++;
1185 }
1186 }
1187
1188 if (c == 0) {
1189 LIST_FOREACH(servers, s, m->fallback_dns_servers) {
1190 r = append_dns_server(reply, s);
1191 if (r < 0)
1192 return r;
1193 }
1194 }
1195
1196 return sd_bus_message_close_container(reply);
1197}
1198
1199static int bus_property_get_search_domains(
1200 sd_bus *bus,
1201 const char *path,
1202 const char *interface,
1203 const char *property,
1204 sd_bus_message *reply,
1205 void *userdata,
1206 sd_bus_error *error) {
1207
1208 Manager *m = userdata;
1209 DnsSearchDomain *d;
1210 Iterator i;
1211 Link *l;
1212 int r;
1213
1214 assert(reply);
1215 assert(m);
1216
1217 r = sd_bus_message_open_container(reply, 'a', "(is)");
1218 if (r < 0)
1219 return r;
1220
1221 LIST_FOREACH(domains, d, m->search_domains) {
1222 r = sd_bus_message_append(reply, "(is)", 0, d->name);
1223 if (r < 0)
1224 return r;
1225 }
1226
1227 HASHMAP_FOREACH(l, m->links, i) {
1228 LIST_FOREACH(domains, d, l->search_domains) {
1229 r = sd_bus_message_append(reply, "is", l->ifindex, d->name);
1230 if (r < 0)
1231 return r;
1232 }
1233 }
1234
1235 return sd_bus_message_close_container(reply);
1236}
1237
a150ff5e
LP
1238static int bus_property_get_transaction_statistics(
1239 sd_bus *bus,
1240 const char *path,
1241 const char *interface,
1242 const char *property,
1243 sd_bus_message *reply,
1244 void *userdata,
1245 sd_bus_error *error) {
1246
1247 Manager *m = userdata;
1248
1249 assert(reply);
1250 assert(m);
1251
1252 return sd_bus_message_append(reply, "(tt)",
1253 (uint64_t) hashmap_size(m->dns_transactions),
1254 (uint64_t) m->n_transactions_total);
1255}
1256
1257static int bus_property_get_cache_statistics(
1258 sd_bus *bus,
1259 const char *path,
1260 const char *interface,
1261 const char *property,
1262 sd_bus_message *reply,
1263 void *userdata,
1264 sd_bus_error *error) {
1265
1266 uint64_t size = 0, hit = 0, miss = 0;
1267 Manager *m = userdata;
1268 DnsScope *s;
1269
1270 assert(reply);
1271 assert(m);
1272
1273 LIST_FOREACH(scopes, s, m->dns_scopes) {
1274 size += dns_cache_size(&s->cache);
1275 hit += s->cache.n_hit;
1276 miss += s->cache.n_miss;
1277 }
1278
1279 return sd_bus_message_append(reply, "(ttt)", size, hit, miss);
1280}
1281
1282static int bus_property_get_dnssec_statistics(
1283 sd_bus *bus,
1284 const char *path,
1285 const char *interface,
1286 const char *property,
1287 sd_bus_message *reply,
1288 void *userdata,
1289 sd_bus_error *error) {
1290
1291 Manager *m = userdata;
1292
1293 assert(reply);
1294 assert(m);
1295
1296 return sd_bus_message_append(reply, "(tttt)",
1297 (uint64_t) m->n_dnssec_secure,
1298 (uint64_t) m->n_dnssec_insecure,
1299 (uint64_t) m->n_dnssec_bogus,
1300 (uint64_t) m->n_dnssec_indeterminate);
1301}
1302
1303static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1304 Manager *m = userdata;
1305 DnsScope *s;
1306
1307 assert(message);
1308 assert(m);
1309
1310 LIST_FOREACH(scopes, s, m->dns_scopes)
1311 s->cache.n_hit = s->cache.n_miss = 0;
1312
1313 m->n_transactions_total = 0;
1314 m->n_dnssec_secure = m->n_dnssec_insecure = m->n_dnssec_bogus = m->n_dnssec_indeterminate = 0;
1315
1316 return sd_bus_reply_method_return(message, NULL);
1317}
1318
74b2466e
LP
1319static const sd_bus_vtable resolve_vtable[] = {
1320 SD_BUS_VTABLE_START(0),
7f220d94
LP
1321 SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
1322 SD_BUS_PROPERTY("DNSServers", "a(iiay)", bus_property_get_dns_servers, 0, 0),
1323 SD_BUS_PROPERTY("SearchDomains", "a(is)", bus_property_get_search_domains, 0, 0),
a150ff5e
LP
1324 SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
1325 SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
1326 SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
7f220d94 1327
78c6a153
LP
1328 SD_BUS_METHOD("ResolveHostname", "isit", "a(iiay)st", bus_method_resolve_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
1329 SD_BUS_METHOD("ResolveAddress", "iiayt", "a(is)t", bus_method_resolve_address, SD_BUS_VTABLE_UNPRIVILEGED),
1330 SD_BUS_METHOD("ResolveRecord", "isqqt", "a(iqqay)t", bus_method_resolve_record, SD_BUS_VTABLE_UNPRIVILEGED),
45ec7efb 1331 SD_BUS_METHOD("ResolveService", "isssit", "a(qqqsa(iiay)s)aayssst", bus_method_resolve_service, SD_BUS_VTABLE_UNPRIVILEGED),
a150ff5e 1332 SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0),
74b2466e
LP
1333 SD_BUS_VTABLE_END,
1334};
1335
1336static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
1337 Manager *m = userdata;
1338
1339 assert(s);
1340 assert(m);
1341
1342 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
1343
1344 manager_connect_bus(m);
1345 return 0;
1346}
1347
19070062 1348static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
902bb5d8
LP
1349 Manager *m = userdata;
1350 int b, r;
1351
19070062
LP
1352 assert(message);
1353 assert(m);
902bb5d8
LP
1354
1355 r = sd_bus_message_read(message, "b", &b);
1356 if (r < 0) {
da927ba9 1357 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
902bb5d8
LP
1358 return 0;
1359 }
1360
1361 if (b)
1362 return 0;
1363
1364 log_debug("Coming back from suspend, verifying all RRs...");
1365
1366 manager_verify_all(m);
1367 return 0;
1368}
1369
74b2466e
LP
1370int manager_connect_bus(Manager *m) {
1371 int r;
1372
1373 assert(m);
1374
1375 if (m->bus)
1376 return 0;
1377
1378 r = sd_bus_default_system(&m->bus);
1379 if (r < 0) {
1380 /* We failed to connect? Yuck, we must be in early
1381 * boot. Let's try in 5s again. As soon as we have
1382 * kdbus we can stop doing this... */
1383
da927ba9 1384 log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
74b2466e
LP
1385
1386 r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
f647962d
MS
1387 if (r < 0)
1388 return log_error_errno(r, "Failed to install bus reconnect time event: %m");
74b2466e 1389
aa4a9deb 1390 (void) sd_event_source_set_description(m->bus_retry_event_source, "bus-retry");
74b2466e
LP
1391 return 0;
1392 }
1393
4d1cf1e2 1394 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", resolve_vtable, m);
f647962d
MS
1395 if (r < 0)
1396 return log_error_errno(r, "Failed to register object: %m");
74b2466e
LP
1397
1398 r = sd_bus_request_name(m->bus, "org.freedesktop.resolve1", 0);
f647962d
MS
1399 if (r < 0)
1400 return log_error_errno(r, "Failed to register name: %m");
74b2466e
LP
1401
1402 r = sd_bus_attach_event(m->bus, m->event, 0);
f647962d
MS
1403 if (r < 0)
1404 return log_error_errno(r, "Failed to attach bus to event loop: %m");
74b2466e 1405
902bb5d8
LP
1406 r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
1407 "type='signal',"
1408 "sender='org.freedesktop.login1',"
1409 "interface='org.freedesktop.login1.Manager',"
1410 "member='PrepareForSleep',"
1411 "path='/org/freedesktop/login1'",
1412 match_prepare_for_sleep,
1413 m);
1414 if (r < 0)
da927ba9 1415 log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
902bb5d8 1416
74b2466e
LP
1417 return 0;
1418}