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