1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include "alloc-util.h"
4 #include "bus-common-errors.h"
5 #include "bus-get-properties.h"
6 #include "bus-log-control-api.h"
7 #include "bus-message-util.h"
8 #include "bus-polkit.h"
9 #include "dns-domain.h"
10 #include "format-util.h"
11 #include "memory-util.h"
12 #include "missing_capability.h"
13 #include "resolved-bus.h"
14 #include "resolved-def.h"
15 #include "resolved-dns-synthesize.h"
16 #include "resolved-dnssd-bus.h"
17 #include "resolved-dnssd.h"
18 #include "resolved-link-bus.h"
19 #include "resolved-resolv-conf.h"
20 #include "socket-netlink.h"
21 #include "stdio-util.h"
22 #include "strv.h"
23 #include "syslog-util.h"
24 #include "user-util.h"
25 #include "utf8.h"
26 
27 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_resolve_support, resolve_support, ResolveSupport);
28 
query_on_bus_track(sd_bus_track * t,void * userdata)29 static 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 
dns_query_bus_track(DnsQuery * q,sd_bus_message * m)43 static 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 
dns_query_steal_request(DnsQuery * q)62 static 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 
reply_method_errorf(DnsQuery * query,const char * error_name,const char * format,...)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 }
96 
reply_method_errnof(DnsQuery * query,int err,const char * format,...)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 
reply_query_state(DnsQuery * q)124 static int reply_query_state(DnsQuery *q) {
125         assert(q);
126 
127         switch (q->state) {
128 
129         case DNS_TRANSACTION_NO_SERVERS:
130                 return reply_method_errorf(q, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
131 
132         case DNS_TRANSACTION_TIMEOUT:
133                 return reply_method_errorf(q, SD_BUS_ERROR_TIMEOUT, "Query timed out");
134 
135         case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
136                 return reply_method_errorf(q, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
137 
138         case DNS_TRANSACTION_INVALID_REPLY:
139                 return reply_method_errorf(q, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
140 
141         case DNS_TRANSACTION_ERRNO:
142                 return reply_method_errnof(q, q->answer_errno, "Lookup failed due to system error: %m");
143 
144         case DNS_TRANSACTION_ABORTED:
145                 return reply_method_errorf(q, BUS_ERROR_ABORTED, "Query aborted");
146 
147         case DNS_TRANSACTION_DNSSEC_FAILED:
148                 return reply_method_errorf(q, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s",
149                                            dnssec_result_to_string(q->answer_dnssec_result));
150 
151         case DNS_TRANSACTION_NO_TRUST_ANCHOR:
152                 return reply_method_errorf(q, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known");
153 
154         case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
155                 return reply_method_errorf(q, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type");
156 
157         case DNS_TRANSACTION_NETWORK_DOWN:
158                 return reply_method_errorf(q, BUS_ERROR_NETWORK_DOWN, "Network is down");
159 
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. */
163                 return reply_method_errorf(q, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
164 
165         case DNS_TRANSACTION_NO_SOURCE:
166                 return reply_method_errorf(q, BUS_ERROR_NO_SOURCE, "All suitable resolution sources turned off");
167 
168         case DNS_TRANSACTION_STUB_LOOP:
169                 return reply_method_errorf(q, BUS_ERROR_STUB_LOOP, "Configured DNS server loops back to us");
170 
171         case DNS_TRANSACTION_RCODE_FAILURE: {
172                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
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;
178 
179                 if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
180                         sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", dns_query_string(q));
181                 else {
182                         const char *rc, *n;
183                         char p[DECIMAL_STR_MAX(q->answer_rcode)];
184 
185                         rc = dns_rcode_to_string(q->answer_rcode);
186                         if (!rc) {
187                                 xsprintf(p, "%i", q->answer_rcode);
188                                 rc = p;
189                         }
190 
191                         n = strjoina(_BUS_ERROR_DNS, rc);
192                         sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", dns_query_string(q), rc);
193                 }
194 
195                 return sd_bus_reply_method_error(req, &error);
196         }
197 
198         case DNS_TRANSACTION_NULL:
199         case DNS_TRANSACTION_PENDING:
200         case DNS_TRANSACTION_VALIDATING:
201         case DNS_TRANSACTION_SUCCESS:
202         default:
203                 assert_not_reached();
204         }
205 }
206 
append_address(sd_bus_message * reply,DnsResourceRecord * rr,int ifindex)207 static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
208         int r;
209 
210         assert(reply);
211         assert(rr);
212 
213         r = sd_bus_message_open_container(reply, 'r', "iiay");
214         if (r < 0)
215                 return r;
216 
217         r = sd_bus_message_append(reply, "i", ifindex);
218         if (r < 0)
219                 return r;
220 
221         if (rr->key->type == DNS_TYPE_A) {
222                 r = sd_bus_message_append(reply, "i", AF_INET);
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));
227 
228         } else if (rr->key->type == DNS_TYPE_AAAA) {
229                 r = sd_bus_message_append(reply, "i", AF_INET6);
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));
234         } else
235                 return -EAFNOSUPPORT;
236 
237         if (r < 0)
238                 return r;
239 
240         r = sd_bus_message_close_container(reply);
241         if (r < 0)
242                 return r;
243 
244         return 0;
245 }
246 
bus_method_resolve_hostname_complete(DnsQuery * query)247 static void bus_method_resolve_hostname_complete(DnsQuery *query) {
248         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
249         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
250         _cleanup_(dns_query_freep) DnsQuery *q = query;
251         _cleanup_free_ char *normalized = NULL;
252         DnsQuestion *question;
253         DnsResourceRecord *rr;
254         unsigned added = 0;
255         int ifindex, r;
256 
257         assert(q);
258 
259         if (q->state != DNS_TRANSACTION_SUCCESS) {
260                 r = reply_query_state(q);
261                 goto finish;
262         }
263 
264         r = dns_query_process_cname_many(q);
265         if (r == -ELOOP) {
266                 r = reply_method_errorf(q, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
267                 goto finish;
268         }
269         if (r < 0)
270                 goto finish;
271         if (r == DNS_QUERY_CNAME) {
272                 /* This was a cname, and the query was restarted. */
273                 TAKE_PTR(q);
274                 return;
275         }
276 
277         r = sd_bus_message_new_method_return(q->bus_request, &reply);
278         if (r < 0)
279                 goto finish;
280 
281         r = sd_bus_message_open_container(reply, 'a', "(iiay)");
282         if (r < 0)
283                 goto finish;
284 
285         question = dns_query_question_for_protocol(q, q->answer_protocol);
286 
287         DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
288 
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;
294 
295                 r = append_address(reply, rr, ifindex);
296                 if (r < 0)
297                         goto finish;
298 
299                 if (!canonical)
300                         canonical = dns_resource_record_ref(rr);
301 
302                 added++;
303         }
304 
305         if (added <= 0) {
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));
307                 goto finish;
308         }
309 
310         r = sd_bus_message_close_container(reply);
311         if (r < 0)
312                 goto finish;
313 
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);
317         r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized);
318         if (r < 0)
319                 goto finish;
320 
321         /* Return the precise spelling and uppercasing and CNAME target reported by the server */
322         r = sd_bus_message_append(
323                         reply, "st",
324                         normalized,
325                         dns_query_reply_flags_make(q));
326         if (r < 0)
327                 goto finish;
328 
329         q->bus_request = sd_bus_message_unref(q->bus_request);
330         r = sd_bus_send(q->manager->bus, reply, NULL);
331 
332 finish:
333         if (r < 0) {
334                 log_error_errno(r, "Failed to send hostname reply: %m");
335                 (void) reply_method_errnof(q, r, NULL);
336         }
337 }
338 
validate_and_mangle_flags(const char * name,uint64_t * flags,uint64_t ok,sd_bus_error * error)339 static int validate_and_mangle_flags(
340                 const char *name,
341                 uint64_t *flags,
342                 uint64_t ok,
343                 sd_bus_error *error) {
344 
345         assert(flags);
346 
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          *
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.
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 
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))
370                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
371 
372         if ((*flags & SD_RESOLVED_PROTOCOLS_ALL) == 0) /* If no protocol is enabled, enable all */
373                 *flags |= SD_RESOLVED_PROTOCOLS_ALL;
374 
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 
379         return 0;
380 }
381 
parse_as_address(sd_bus_message * m,int ifindex,const char * hostname,int family,uint64_t flags)382 static 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;
386         int r, ff, parsed_ifindex = 0;
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 
391         r = in_addr_ifindex_from_string_auto(hostname, &ff, &parsed, &parsed_ifindex);
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.");
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;
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). */
434         r = in_addr_ifindex_to_string(ff, &parsed, ifindex, &canonical);
435         if (r < 0)
436                 return r;
437 
438         r = sd_bus_message_append(reply, "st", canonical,
439                                   SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true, true) |
440                                   SD_RESOLVED_SYNTHETIC);
441         if (r < 0)
442                 return r;
443 
444         return sd_bus_send(sd_bus_message_get_bus(m), reply, NULL);
445 }
446 
bus_client_log(sd_bus_message * m,const char * what)447 void 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 
bus_method_resolve_hostname(sd_bus_message * message,void * userdata,sd_bus_error * error)472 static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
473         _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
474         _cleanup_(dns_query_freep) DnsQuery *q = NULL;
475         Manager *m = userdata;
476         const char *hostname;
477         int family, ifindex;
478         uint64_t flags;
479         int r;
480 
481         assert(message);
482         assert(m);
483 
484         assert_cc(sizeof(int) == sizeof(int32_t));
485 
486         r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
487         if (r < 0)
488                 return r;
489 
490         if (ifindex < 0)
491                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
492 
493         if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
494                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
495 
496         r = validate_and_mangle_flags(hostname, &flags, SD_RESOLVED_NO_SEARCH, error);
497         if (r < 0)
498                 return r;
499 
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);
505         if (r < 0)
506                 return r;
507         if (r == 0)
508                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
509 
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);
515         if (r < 0 && r != -EALREADY)
516                 return r;
517 
518         bus_client_log(message, "hostname resolution");
519 
520         r = dns_query_new(m, &q, question_utf8, question_idna ?: question_utf8, NULL, ifindex, flags);
521         if (r < 0)
522                 return r;
523 
524         q->bus_request = sd_bus_message_ref(message);
525         q->request_family = family;
526         q->complete = bus_method_resolve_hostname_complete;
527 
528         r = dns_query_bus_track(q, message);
529         if (r < 0)
530                 return r;
531 
532         r = dns_query_go(q);
533         if (r < 0)
534                 return r;
535 
536         TAKE_PTR(q);
537         return 1;
538 }
539 
bus_method_resolve_address_complete(DnsQuery * query)540 static void bus_method_resolve_address_complete(DnsQuery *query) {
541         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
542         _cleanup_(dns_query_freep) DnsQuery *q = query;
543         DnsQuestion *question;
544         DnsResourceRecord *rr;
545         unsigned added = 0;
546         int ifindex, r;
547 
548         assert(q);
549 
550         if (q->state != DNS_TRANSACTION_SUCCESS) {
551                 r = reply_query_state(q);
552                 goto finish;
553         }
554 
555         r = dns_query_process_cname_many(q);
556         if (r == -ELOOP) {
557                 r = reply_method_errorf(q, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
558                 goto finish;
559         }
560         if (r < 0)
561                 goto finish;
562         if (r == DNS_QUERY_CNAME) {
563                 /* This was a cname, and the query was restarted. */
564                 TAKE_PTR(q);
565                 return;
566         }
567 
568         r = sd_bus_message_new_method_return(q->bus_request, &reply);
569         if (r < 0)
570                 goto finish;
571 
572         r = sd_bus_message_open_container(reply, 'a', "(is)");
573         if (r < 0)
574                 goto finish;
575 
576         question = dns_query_question_for_protocol(q, q->answer_protocol);
577 
578         DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
579                 _cleanup_free_ char *normalized = NULL;
580 
581                 r = dns_question_matches_rr(question, rr, NULL);
582                 if (r < 0)
583                         goto finish;
584                 if (r == 0)
585                         continue;
586 
587                 r = dns_name_normalize(rr->ptr.name, 0, &normalized);
588                 if (r < 0)
589                         goto finish;
590 
591                 r = sd_bus_message_append(reply, "(is)", ifindex, normalized);
592                 if (r < 0)
593                         goto finish;
594 
595                 added++;
596         }
597 
598         if (added <= 0) {
599                 _cleanup_free_ char *ip = NULL;
600 
601                 (void) in_addr_to_string(q->request_family, &q->request_address, &ip);
602                 r = reply_method_errorf(q, BUS_ERROR_NO_SUCH_RR,
603                                                "Address '%s' does not have any RR of requested type", strnull(ip));
604                 goto finish;
605         }
606 
607         r = sd_bus_message_close_container(reply);
608         if (r < 0)
609                 goto finish;
610 
611         r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
612         if (r < 0)
613                 goto finish;
614 
615         q->bus_request = sd_bus_message_unref(q->bus_request);
616         r = sd_bus_send(q->manager->bus, reply, NULL);
617 
618 finish:
619         if (r < 0) {
620                 log_error_errno(r, "Failed to send address reply: %m");
621                 (void) reply_method_errnof(q, r, NULL);
622         }
623 }
624 
bus_method_resolve_address(sd_bus_message * message,void * userdata,sd_bus_error * error)625 static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
626         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
627         _cleanup_(dns_query_freep) DnsQuery *q = NULL;
628         Manager *m = userdata;
629         union in_addr_union a;
630         int family, ifindex;
631         uint64_t flags;
632         int r;
633 
634         assert(message);
635         assert(m);
636 
637         assert_cc(sizeof(int) == sizeof(int32_t));
638 
639         r = sd_bus_message_read(message, "i", &ifindex);
640         if (r < 0)
641                 return r;
642 
643         r = bus_message_read_in_addr_auto(message, error, &family, &a);
644         if (r < 0)
645                 return r;
646 
647         r = sd_bus_message_read(message, "t", &flags);
648         if (r < 0)
649                 return r;
650 
651         if (ifindex < 0)
652                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
653 
654         r = validate_and_mangle_flags(NULL, &flags, 0, error);
655         if (r < 0)
656                 return r;
657 
658         r = dns_question_new_reverse(&question, family, &a);
659         if (r < 0)
660                 return r;
661 
662         bus_client_log(message, "address resolution");
663 
664         r = dns_query_new(m, &q, question, question, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH);
665         if (r < 0)
666                 return r;
667 
668         q->bus_request = sd_bus_message_ref(message);
669         q->request_family = family;
670         q->request_address = a;
671         q->complete = bus_method_resolve_address_complete;
672 
673         r = dns_query_bus_track(q, message);
674         if (r < 0)
675                 return r;
676 
677         r = dns_query_go(q);
678         if (r < 0)
679                 return r;
680 
681         TAKE_PTR(q);
682         return 1;
683 }
684 
bus_message_append_rr(sd_bus_message * m,DnsResourceRecord * rr,int ifindex)685 static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) {
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 
702         r = dns_resource_record_to_wire_format(rr, false);
703         if (r < 0)
704                 return r;
705 
706         r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size);
707         if (r < 0)
708                 return r;
709 
710         return sd_bus_message_close_container(m);
711 }
712 
bus_method_resolve_record_complete(DnsQuery * query)713 static void bus_method_resolve_record_complete(DnsQuery *query) {
714         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
715         _cleanup_(dns_query_freep) DnsQuery *q = query;
716         DnsResourceRecord *rr;
717         DnsQuestion *question;
718         unsigned added = 0;
719         int ifindex;
720         int r;
721 
722         assert(q);
723 
724         if (q->state != DNS_TRANSACTION_SUCCESS) {
725                 r = reply_query_state(q);
726                 goto finish;
727         }
728 
729         r = dns_query_process_cname_many(q);
730         if (r == -ELOOP) {
731                 r = reply_method_errorf(q, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
732                 goto finish;
733         }
734         if (r < 0)
735                 goto finish;
736         if (r == DNS_QUERY_CNAME) {
737                 /* This was a cname, and the query was restarted. */
738                 TAKE_PTR(q);
739                 return;
740         }
741 
742         r = sd_bus_message_new_method_return(q->bus_request, &reply);
743         if (r < 0)
744                 goto finish;
745 
746         r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
747         if (r < 0)
748                 goto finish;
749 
750         question = dns_query_question_for_protocol(q, q->answer_protocol);
751 
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;
758 
759                 r = bus_message_append_rr(reply, rr, ifindex);
760                 if (r < 0)
761                         goto finish;
762 
763                 added++;
764         }
765 
766         if (added <= 0) {
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));
768                 goto finish;
769         }
770 
771         r = sd_bus_message_close_container(reply);
772         if (r < 0)
773                 goto finish;
774 
775         r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
776         if (r < 0)
777                 goto finish;
778 
779         q->bus_request = sd_bus_message_unref(q->bus_request);
780         r = sd_bus_send(q->manager->bus, reply, NULL);
781 
782 finish:
783         if (r < 0) {
784                 log_error_errno(r, "Failed to send record reply: %m");
785                 (void) reply_method_errnof(q, r, NULL);
786         }
787 }
788 
bus_method_resolve_record(sd_bus_message * message,void * userdata,sd_bus_error * error)789 static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
790         _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
791         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
792         _cleanup_(dns_query_freep) DnsQuery *q = NULL;
793         Manager *m = userdata;
794         uint16_t class, type;
795         const char *name;
796         int r, ifindex;
797         uint64_t flags;
798 
799         assert(message);
800         assert(m);
801 
802         assert_cc(sizeof(int) == sizeof(int32_t));
803 
804         r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
805         if (r < 0)
806                 return r;
807 
808         if (ifindex < 0)
809                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
810 
811         r = dns_name_is_valid(name);
812         if (r < 0)
813                 return r;
814         if (r == 0)
815                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
816 
817         if (!dns_type_is_valid_query(type))
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);
819         if (dns_type_is_zone_transer(type))
820                 return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Zone transfers not permitted via this programming interface.");
821         if (dns_type_is_obsolete(type))
822                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type);
823 
824         r = validate_and_mangle_flags(name, &flags, 0, error);
825         if (r < 0)
826                 return r;
827 
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 
836         r = dns_question_add(question, key, 0);
837         if (r < 0)
838                 return r;
839 
840         bus_client_log(message, "resource record resolution");
841 
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);
845         if (r < 0)
846                 return r;
847 
848         q->bus_request = sd_bus_message_ref(message);
849         q->complete = bus_method_resolve_record_complete;
850 
851         r = dns_query_bus_track(q, message);
852         if (r < 0)
853                 return r;
854 
855         r = dns_query_go(q);
856         if (r < 0)
857                 return r;
858 
859         TAKE_PTR(q);
860         return 1;
861 }
862 
append_srv(DnsQuery * q,sd_bus_message * reply,DnsResourceRecord * rr)863 static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
864         _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
865         _cleanup_free_ char *normalized = NULL;
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;
881                         DnsQuestion *question;
882 
883                         if (aux->state != DNS_TRANSACTION_SUCCESS)
884                                 continue;
885                         if (aux->auxiliary_result != 0)
886                                 continue;
887 
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);
891                         if (r < 0)
892                                 return r;
893                         if (r == 0)
894                                 continue;
895 
896                         DNS_ANSWER_FOREACH(zz, aux->answer) {
897 
898                                 r = dns_question_matches_rr(question, zz, NULL);
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 
921         r = dns_name_normalize(rr->srv.name, 0, &normalized);
922         if (r < 0)
923                 return r;
924 
925         r = sd_bus_message_append(
926                         reply,
927                         "qqqs",
928                         rr->srv.priority, rr->srv.weight, rr->srv.port, normalized);
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;
939                         DnsQuestion *question;
940                         int ifindex;
941 
942                         if (aux->state != DNS_TRANSACTION_SUCCESS)
943                                 continue;
944                         if (aux->auxiliary_result != 0)
945                                 continue;
946 
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);
950                         if (r < 0)
951                                 return r;
952                         if (r == 0)
953                                 continue;
954 
955                         DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
956 
957                                 r = dns_question_matches_rr(question, zz, NULL);
958                                 if (r < 0)
959                                         return r;
960                                 if (r == 0)
961                                         continue;
962 
963                                 r = append_address(reply, zz, ifindex);
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 
974         if (canonical) {
975                 normalized = mfree(normalized);
976 
977                 r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized);
978                 if (r < 0)
979                         return r;
980         }
981 
982         /* Note that above we appended the hostname as encoded in the
983          * SRV, and here the canonical hostname this maps to. */
984         r = sd_bus_message_append(reply, "s", normalized);
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 
append_txt(sd_bus_message * reply,DnsResourceRecord * rr)995 static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
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 
resolve_service_all_complete(DnsQuery * query)1018 static void resolve_service_all_complete(DnsQuery *query) {
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;
1022         _cleanup_(dns_query_freep) DnsQuery *q = query;
1023         DnsQuestion *question;
1024         DnsResourceRecord *rr;
1025         unsigned added = 0;
1026         int r;
1027 
1028         assert(q);
1029 
1030         if (q->block_all_complete > 0) {
1031                 TAKE_PTR(q);
1032                 return;
1033         }
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 */
1045                                 TAKE_PTR(q);
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) {
1070                                         r = reply_method_errorf(q, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad));
1071                                         goto finish;
1072                                 }
1073 
1074                                 assert(bad->auxiliary_result < 0);
1075                                 r = bad->auxiliary_result;
1076                                 goto finish;
1077                         }
1078 
1079                         r = reply_query_state(bad);
1080                         goto finish;
1081                 }
1082         }
1083 
1084         r = sd_bus_message_new_method_return(q->bus_request, &reply);
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 
1092         question = dns_query_question_for_protocol(q, q->answer_protocol);
1093 
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;
1100 
1101                 r = append_srv(q, reply, rr);
1102                 if (r < 0)
1103                         goto finish;
1104                 if (r == 0) /* not an SRV record */
1105                         continue;
1106 
1107                 if (!canonical)
1108                         canonical = dns_resource_record_ref(rr);
1109 
1110                 added++;
1111         }
1112 
1113         if (added <= 0) {
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));
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 
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;
1132 
1133                 r = append_txt(reply, rr);
1134                 if (r < 0)
1135                         goto finish;
1136         }
1137 
1138         r = sd_bus_message_close_container(reply);
1139         if (r < 0)
1140                 goto finish;
1141 
1142         assert(canonical);
1143         r = dns_service_split(dns_resource_key_name(canonical->key), &name, &type, &domain);
1144         if (r < 0)
1145                 goto finish;
1146 
1147         r = sd_bus_message_append(
1148                         reply,
1149                         "ssst",
1150                         name, type, domain,
1151                         dns_query_reply_flags_make(q));
1152         if (r < 0)
1153                 goto finish;
1154 
1155         q->bus_request = sd_bus_message_unref(q->bus_request);
1156         r = sd_bus_send(q->manager->bus, reply, NULL);
1157 
1158 finish:
1159         if (r < 0) {
1160                 log_error_errno(r, "Failed to send service reply: %m");
1161                 (void) reply_method_errnof(q, r, NULL);
1162         }
1163 }
1164 
resolve_service_hostname_complete(DnsQuery * q)1165 static 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 
1176         r = dns_query_process_cname_many(q);
1177         if (r == DNS_QUERY_CNAME) /* This was a cname, and the query was restarted. */
1178                 return;
1179 
1180         /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
1181         q->auxiliary_result = r < 0 ? r : 0;
1182         resolve_service_all_complete(q->auxiliary_for);
1183 }
1184 
resolve_service_hostname(DnsQuery * q,DnsResourceRecord * rr,int ifindex)1185 static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
1186         _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1187         _cleanup_(dns_query_freep) DnsQuery *aux = NULL;
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 
1198         r = dns_question_new_address(&question, q->request_family, rr->srv.name, false);
1199         if (r < 0)
1200                 return r;
1201 
1202         r = dns_query_new(q->manager, &aux, question, question, NULL, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
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);
1210         if (r == -EAGAIN)
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 */
1214                 return 0;
1215         if (r < 0)
1216                 return r;
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)
1223                 return r;
1224 
1225         TAKE_PTR(aux);
1226         return 1;
1227 }
1228 
bus_method_resolve_service_complete(DnsQuery * query)1229 static void bus_method_resolve_service_complete(DnsQuery *query) {
1230         _cleanup_(dns_query_freep) DnsQuery *q = query;
1231         bool has_root_domain = false;
1232         DnsResourceRecord *rr;
1233         DnsQuestion *question;
1234         unsigned found = 0;
1235         int ifindex, r;
1236 
1237         assert(q);
1238 
1239         if (q->state != DNS_TRANSACTION_SUCCESS) {
1240                 r = reply_query_state(q);
1241                 goto finish;
1242         }
1243 
1244         r = dns_query_process_cname_many(q);
1245         if (r == -ELOOP) {
1246                 r = reply_method_errorf(q, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
1247                 goto finish;
1248         }
1249         if (r < 0)
1250                 goto finish;
1251         if (r == DNS_QUERY_CNAME) {
1252                 /* This was a cname, and the query was restarted. */
1253                 TAKE_PTR(q);
1254                 return;
1255         }
1256 
1257         question = dns_query_question_for_protocol(q, q->answer_protocol);
1258 
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;
1265 
1266                 if (rr->key->type != DNS_TYPE_SRV)
1267                         continue;
1268 
1269                 if (dns_name_is_root(rr->srv.name)) {
1270                         has_root_domain = true;
1271                         continue;
1272                 }
1273 
1274                 if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
1275                         q->block_all_complete++;
1276                         r = resolve_service_hostname(q, rr, ifindex);
1277                         q->block_all_complete--;
1278 
1279                         if (r < 0)
1280                                 goto finish;
1281                 }
1282 
1283                 found++;
1284         }
1285 
1286         if (has_root_domain && found <= 0) {
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));
1291                 goto finish;
1292         }
1293 
1294         if (found <= 0) {
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));
1296                 goto finish;
1297         }
1298 
1299         /* Maybe we are already finished? check now... */
1300         resolve_service_all_complete(TAKE_PTR(q));
1301         return;
1302 
1303 finish:
1304         if (r < 0) {
1305                 log_error_errno(r, "Failed to send service reply: %m");
1306                 (void) reply_method_errnof(q, r, NULL);
1307         }
1308 }
1309 
bus_method_resolve_service(sd_bus_message * message,void * userdata,sd_bus_error * error)1310 static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1311         _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
1312         _cleanup_(dns_query_freep) DnsQuery *q = NULL;
1313         const char *name, *type, *domain;
1314         Manager *m = userdata;
1315         int family, ifindex;
1316         uint64_t flags;
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)
1326                 return r;
1327 
1328         if (ifindex < 0)
1329                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
1330 
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;
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);
1338 
1339         if (isempty(type))
1340                 type = NULL;
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);
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)
1351                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
1352 
1353         r = validate_and_mangle_flags(name, &flags, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS, error);
1354         if (r < 0)
1355                 return r;
1356 
1357         r = dns_question_new_service(&question_utf8, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), false);
1358         if (r < 0)
1359                 return r;
1360 
1361         r = dns_question_new_service(&question_idna, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), true);
1362         if (r < 0)
1363                 return r;
1364 
1365         bus_client_log(message, "service resolution");
1366 
1367         r = dns_query_new(m, &q, question_utf8, question_idna, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH);
1368         if (r < 0)
1369                 return r;
1370 
1371         q->bus_request = sd_bus_message_ref(message);
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)
1377                 return r;
1378 
1379         r = dns_query_go(q);
1380         if (r < 0)
1381                 return r;
1382 
1383         TAKE_PTR(q);
1384         return 1;
1385 }
1386 
bus_dns_server_append(sd_bus_message * reply,DnsServer * s,bool with_ifindex,bool extended)1387 int bus_dns_server_append(sd_bus_message *reply, DnsServer *s, bool with_ifindex, bool extended) {
1388         int r;
1389 
1390         assert(reply);
1391 
1392         if (!s) {
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                 }
1404         }
1405 
1406         r = sd_bus_message_open_container(reply, 'r', with_ifindex ? (extended ? "iiayqs" : "iiay") : (extended ? "iayqs" : "iay"));
1407         if (r < 0)
1408                 return r;
1409 
1410         if (with_ifindex) {
1411                 r = sd_bus_message_append(reply, "i", dns_server_ifindex(s));
1412                 if (r < 0)
1413                         return r;
1414         }
1415 
1416         r = sd_bus_message_append(reply, "i", s->family);
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 
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 
1434         return sd_bus_message_close_container(reply);
1435 }
1436 
bus_property_get_dns_servers_internal(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error,bool extended)1437 static int bus_property_get_dns_servers_internal(
1438                 sd_bus *bus,
1439                 const char *path,
1440                 const char *interface,
1441                 const char *property,
1442                 sd_bus_message *reply,
1443                 void *userdata,
1444                 sd_bus_error *error,
1445                 bool extended) {
1446 
1447         Manager *m = userdata;
1448         Link *l;
1449         int r;
1450 
1451         assert(reply);
1452         assert(m);
1453 
1454         r = sd_bus_message_open_container(reply, 'a', extended ? "(iiayqs)" : "(iiay)");
1455         if (r < 0)
1456                 return r;
1457 
1458         LIST_FOREACH(servers, s, m->dns_servers) {
1459                 r = bus_dns_server_append(reply, s, true, extended);
1460                 if (r < 0)
1461                         return r;
1462         }
1463 
1464         HASHMAP_FOREACH(l, m->links)
1465                 LIST_FOREACH(servers, s, l->dns_servers) {
1466                         r = bus_dns_server_append(reply, s, true, extended);
1467                         if (r < 0)
1468                                 return r;
1469                 }
1470 
1471         return sd_bus_message_close_container(reply);
1472 }
1473 
bus_property_get_dns_servers(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1474 static int bus_property_get_dns_servers(
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) {
1482         return bus_property_get_dns_servers_internal(bus, path, interface, property, reply, userdata, error, false);
1483 }
1484 
bus_property_get_dns_servers_ex(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1485 static 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 
bus_property_get_fallback_dns_servers_internal(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error,bool extended)1496 static 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) {
1505 
1506         DnsServer **f = userdata;
1507         int r;
1508 
1509         assert(reply);
1510         assert(f);
1511 
1512         r = sd_bus_message_open_container(reply, 'a', extended ? "(iiayqs)" : "(iiay)");
1513         if (r < 0)
1514                 return r;
1515 
1516         LIST_FOREACH(servers, s, *f) {
1517                 r = bus_dns_server_append(reply, s, true, extended);
1518                 if (r < 0)
1519                         return r;
1520         }
1521 
1522         return sd_bus_message_close_container(reply);
1523 }
1524 
bus_property_get_fallback_dns_servers(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1525 static int bus_property_get_fallback_dns_servers(
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) {
1533         return bus_property_get_fallback_dns_servers_internal(bus, path, interface, property, reply, userdata, error, false);
1534 }
1535 
bus_property_get_fallback_dns_servers_ex(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1536 static 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 
bus_property_get_current_dns_server_internal(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error,bool extended)1547 static 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) {
1556 
1557         DnsServer *s;
1558 
1559         assert(reply);
1560         assert(userdata);
1561 
1562         s = *(DnsServer **) userdata;
1563 
1564         return bus_dns_server_append(reply, s, true, extended);
1565 }
1566 
bus_property_get_current_dns_server(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1567 static 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 
bus_property_get_current_dns_server_ex(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1578 static 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);
1587 }
1588 
bus_property_get_domains(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1589 static int bus_property_get_domains(
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;
1599         Link *l;
1600         int r;
1601 
1602         assert(reply);
1603         assert(m);
1604 
1605         r = sd_bus_message_open_container(reply, 'a', "(isb)");
1606         if (r < 0)
1607                 return r;
1608 
1609         LIST_FOREACH(domains, d, m->search_domains) {
1610                 r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only);
1611                 if (r < 0)
1612                         return r;
1613         }
1614 
1615         HASHMAP_FOREACH(l, m->links) {
1616                 LIST_FOREACH(domains, d, l->search_domains) {
1617                         r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only);
1618                         if (r < 0)
1619                                 return r;
1620                 }
1621         }
1622 
1623         return sd_bus_message_close_container(reply);
1624 }
1625 
bus_property_get_transaction_statistics(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1626 static 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 
bus_property_get_cache_statistics(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1645 static 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;
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 
bus_property_get_dnssec_statistics(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1669 static 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)",
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]);
1688 }
1689 
bus_property_get_ntas(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1690 static 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;
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 
1710         SET_FOREACH(domain, m->trust_anchor.negative_by_name) {
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 
1719 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode);
1720 static BUS_DEFINE_PROPERTY_GET(bus_property_get_dnssec_supported, "b", Manager, manager_dnssec_supported);
1721 static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode, "s", Manager, manager_get_dnssec_mode, dnssec_mode_to_string);
1722 static 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);
1723 
bus_property_get_resolv_conf_mode(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)1724 static 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 
bus_method_reset_statistics(sd_bus_message * message,void * userdata,sd_bus_error * error)1746 static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1747         Manager *m = userdata;
1748 
1749         assert(message);
1750         assert(m);
1751 
1752         bus_client_log(message, "statistics reset");
1753 
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;
1758         zero(m->n_dnssec_verdict);
1759 
1760         return sd_bus_reply_method_return(message, NULL);
1761 }
1762 
get_any_link(Manager * m,int ifindex,Link ** ret,sd_bus_error * error)1763 static int get_any_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) {
1764         Link *l;
1765 
1766         assert(m);
1767         assert(ret);
1768 
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);
1772 
1773         *ret = l;
1774         return 0;
1775 }
1776 
call_link_method(Manager * m,sd_bus_message * message,sd_bus_message_handler_t handler,sd_bus_error * error)1777 static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
1778         int ifindex, r;
1779         Link *l;
1780 
1781         assert(m);
1782         assert(message);
1783         assert(handler);
1784 
1785         r = bus_message_read_ifindex(message, error, &ifindex);
1786         if (r < 0)
1787                 return r;
1788 
1789         r = get_any_link(m, ifindex, &l, error);
1790         if (r < 0)
1791                 return r;
1792 
1793         return handler(message, l, error);
1794 }
1795 
bus_method_set_link_dns_servers(sd_bus_message * message,void * userdata,sd_bus_error * error)1796 static 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 }
1799 
bus_method_set_link_dns_servers_ex(sd_bus_message * message,void * userdata,sd_bus_error * error)1800 static 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 
bus_method_set_link_domains(sd_bus_message * message,void * userdata,sd_bus_error * error)1804 static 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);
1806 }
1807 
bus_method_set_link_default_route(sd_bus_message * message,void * userdata,sd_bus_error * error)1808 static 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 
bus_method_set_link_llmnr(sd_bus_message * message,void * userdata,sd_bus_error * error)1812 static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1813         return call_link_method(userdata, message, bus_link_method_set_llmnr, error);
1814 }
1815 
bus_method_set_link_mdns(sd_bus_message * message,void * userdata,sd_bus_error * error)1816 static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1817         return call_link_method(userdata, message, bus_link_method_set_mdns, error);
1818 }
1819 
bus_method_set_link_dns_over_tls(sd_bus_message * message,void * userdata,sd_bus_error * error)1820 static 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);
1822 }
1823 
bus_method_set_link_dnssec(sd_bus_message * message,void * userdata,sd_bus_error * error)1824 static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1825         return call_link_method(userdata, message, bus_link_method_set_dnssec, error);
1826 }
1827 
bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message * message,void * userdata,sd_bus_error * error)1828 static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1829         return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error);
1830 }
1831 
bus_method_revert_link(sd_bus_message * message,void * userdata,sd_bus_error * error)1832 static int bus_method_revert_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1833         return call_link_method(userdata, message, bus_link_method_revert, error);
1834 }
1835 
bus_method_get_link(sd_bus_message * message,void * userdata,sd_bus_error * error)1836 static 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 
1845         r = bus_message_read_ifindex(message, error, &ifindex);
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 
bus_method_flush_caches(sd_bus_message * message,void * userdata,sd_bus_error * error)1860 static 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 
1866         bus_client_log(message, "cache flush");
1867 
1868         manager_flush_caches(m, LOG_INFO);
1869 
1870         return sd_bus_reply_method_return(message, NULL);
1871 }
1872 
bus_method_reset_server_features(sd_bus_message * message,void * userdata,sd_bus_error * error)1873 static 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 
1879         bus_client_log(message, "server feature reset");
1880 
1881         manager_reset_server_features(m);
1882 
1883         return sd_bus_reply_method_return(message, NULL);
1884 }
1885 
dnssd_service_on_bus_track(sd_bus_track * t,void * userdata)1886 static int dnssd_service_on_bus_track(sd_bus_track *t, void *userdata) {
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 
bus_method_register_service(sd_bus_message * message,void * userdata,sd_bus_error * error)1898 static int bus_method_register_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1899         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1900         _cleanup_(dnssd_service_freep) DnssdService *service = NULL;
1901         _cleanup_(sd_bus_track_unrefp) sd_bus_track *bus_track = NULL;
1902         const char *name, *name_template, *type;
1903         _cleanup_free_ char *path = NULL;
1904         DnssdService *s = NULL;
1905         Manager *m = userdata;
1906         uid_t euid;
1907         int r;
1908 
1909         assert(message);
1910         assert(m);
1911 
1912         if (m->mdns_support != RESOLVE_SUPPORT_YES)
1913                 return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled");
1914 
1915         service = new0(DnssdService, 1);
1916         if (!service)
1917                 return log_oom();
1918 
1919         r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1920         if (r < 0)
1921                 return r;
1922 
1923         r = sd_bus_creds_get_euid(creds, &euid);
1924         if (r < 0)
1925                 return r;
1926         service->originator = euid;
1927 
1928         r = sd_bus_message_read(message, "sssqqq", &name, &name_template, &type,
1929                                 &service->port, &service->priority,
1930                                 &service->weight);
1931         if (r < 0)
1932                 return r;
1933 
1934         s = hashmap_get(m->dnssd_services, name);
1935         if (s)
1936                 return sd_bus_error_setf(error, BUS_ERROR_DNSSD_SERVICE_EXISTS, "DNS-SD service '%s' exists already", name);
1937 
1938         if (!dnssd_srv_type_is_valid(type))
1939                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DNS-SD service type '%s' is invalid", type);
1940 
1941         service->name = strdup(name);
1942         if (!service->name)
1943                 return log_oom();
1944 
1945         service->name_template = strdup(name_template);
1946         if (!service->name_template)
1947                 return log_oom();
1948 
1949         service->type = strdup(type);
1950         if (!service->type)
1951                 return log_oom();
1952 
1953         r = dnssd_render_instance_name(m, service, NULL);
1954         if (r < 0)
1955                 return r;
1956 
1957         r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "a{say}");
1958         if (r < 0)
1959                 return r;
1960 
1961         while ((r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "{say}")) > 0) {
1962                 _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
1963                 DnsTxtItem *last = NULL;
1964 
1965                 txt_data = new0(DnssdTxtData, 1);
1966                 if (!txt_data)
1967                         return log_oom();
1968 
1969                 while ((r = sd_bus_message_enter_container(message, SD_BUS_TYPE_DICT_ENTRY, "say")) > 0) {
1970                         const char *key;
1971                         const void *value;
1972                         size_t size;
1973                         DnsTxtItem *i;
1974 
1975                         r = sd_bus_message_read(message, "s", &key);
1976                         if (r < 0)
1977                                 return r;
1978 
1979                         if (isempty(key))
1980                                 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Keys in DNS-SD TXT RRs can't be empty");
1981 
1982                         if (!ascii_is_valid(key))
1983                                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TXT key '%s' contains non-ASCII symbols", key);
1984 
1985                         r = sd_bus_message_read_array(message, 'y', &value, &size);
1986                         if (r < 0)
1987                                 return r;
1988 
1989                         r = dnssd_txt_item_new_from_data(key, value, size, &i);
1990                         if (r < 0)
1991                                 return r;
1992 
1993                         LIST_INSERT_AFTER(items, txt_data->txt, last, i);
1994                         last = i;
1995 
1996                         r = sd_bus_message_exit_container(message);
1997                         if (r < 0)
1998                                 return r;
1999 
2000                 }
2001                 if (r < 0)
2002                         return r;
2003 
2004                 r = sd_bus_message_exit_container(message);
2005                 if (r < 0)
2006                         return r;
2007 
2008                 if (txt_data->txt) {
2009                         LIST_PREPEND(items, service->txt_data_items, txt_data);
2010                         txt_data = NULL;
2011                 }
2012         }
2013         if (r < 0)
2014                 return r;
2015 
2016         r = sd_bus_message_exit_container(message);
2017         if (r < 0)
2018                 return r;
2019 
2020         if (!service->txt_data_items) {
2021                 _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
2022 
2023                 txt_data = new0(DnssdTxtData, 1);
2024                 if (!txt_data)
2025                         return log_oom();
2026 
2027                 r = dns_txt_item_new_empty(&txt_data->txt);
2028                 if (r < 0)
2029                         return r;
2030 
2031                 LIST_PREPEND(items, service->txt_data_items, txt_data);
2032                 txt_data = NULL;
2033         }
2034 
2035         r = sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", service->name, &path);
2036         if (r < 0)
2037                 return r;
2038 
2039         r = bus_verify_polkit_async(message, CAP_SYS_ADMIN,
2040                                     "org.freedesktop.resolve1.register-service",
2041                                     NULL, false, UID_INVALID,
2042                                     &m->polkit_registry, error);
2043         if (r < 0)
2044                 return r;
2045         if (r == 0)
2046                 return 1; /* Polkit will call us back */
2047 
2048         r = hashmap_ensure_put(&m->dnssd_services, &string_hash_ops, service->name, service);
2049         if (r < 0)
2050                 return r;
2051 
2052         r = sd_bus_track_new(sd_bus_message_get_bus(message), &bus_track, dnssd_service_on_bus_track, service);
2053         if (r < 0)
2054                 return r;
2055 
2056         r = sd_bus_track_add_sender(bus_track, message);
2057         if (r < 0)
2058                 return r;
2059 
2060         service->manager = m;
2061 
2062         service = NULL;
2063 
2064         manager_refresh_rrs(m);
2065 
2066         return sd_bus_reply_method_return(message, "o", path);
2067 }
2068 
call_dnssd_method(Manager * m,sd_bus_message * message,sd_bus_message_handler_t handler,sd_bus_error * error)2069 static int call_dnssd_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
2070         _cleanup_free_ char *name = NULL;
2071         DnssdService *s = NULL;
2072         const char *path;
2073         int r;
2074 
2075         assert(m);
2076         assert(message);
2077         assert(handler);
2078 
2079         r = sd_bus_message_read(message, "o", &path);
2080         if (r < 0)
2081                 return r;
2082 
2083         r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/dnssd", &name);
2084         if (r == 0)
2085                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DNSSD_SERVICE, "DNS-SD service with object path '%s' does not exist", path);
2086         if (r < 0)
2087                 return r;
2088 
2089         s = hashmap_get(m->dnssd_services, name);
2090         if (!s)
2091                 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DNSSD_SERVICE, "DNS-SD service '%s' not known", name);
2092 
2093         return handler(message, s, error);
2094 }
2095 
bus_method_unregister_service(sd_bus_message * message,void * userdata,sd_bus_error * error)2096 static int bus_method_unregister_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2097         Manager *m = userdata;
2098 
2099         assert(message);
2100         assert(m);
2101 
2102         return call_dnssd_method(m, message, bus_dnssd_method_unregister, error);
2103 }
2104 
2105 static const sd_bus_vtable resolve_vtable[] = {
2106         SD_BUS_VTABLE_START(0),
2107         SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2108         SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Manager, llmnr_support), 0),
2109         SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Manager, mdns_support), 0),
2110         SD_BUS_PROPERTY("DNSOverTLS", "s", bus_property_get_dns_over_tls_mode, 0, 0),
2111         SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2112         SD_BUS_PROPERTY("DNSEx", "a(iiayqs)", bus_property_get_dns_servers_ex, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2113         SD_BUS_PROPERTY("FallbackDNS", "a(iiay)", bus_property_get_fallback_dns_servers, offsetof(Manager, fallback_dns_servers), SD_BUS_VTABLE_PROPERTY_CONST),
2114         SD_BUS_PROPERTY("FallbackDNSEx", "a(iiayqs)", bus_property_get_fallback_dns_servers_ex, offsetof(Manager, fallback_dns_servers), SD_BUS_VTABLE_PROPERTY_CONST),
2115         SD_BUS_PROPERTY("CurrentDNSServer", "(iiay)", bus_property_get_current_dns_server, offsetof(Manager, current_dns_server), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2116         SD_BUS_PROPERTY("CurrentDNSServerEx", "(iiayqs)", bus_property_get_current_dns_server_ex, offsetof(Manager, current_dns_server), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2117         SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains, 0, 0),
2118         SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
2119         SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
2120         SD_BUS_PROPERTY("DNSSEC", "s", bus_property_get_dnssec_mode, 0, 0),
2121         SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
2122         SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0),
2123         SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_ntas, 0, 0),
2124         SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode, offsetof(Manager, dns_stub_listener_mode), 0),
2125         SD_BUS_PROPERTY("ResolvConfMode", "s", bus_property_get_resolv_conf_mode, 0, 0),
2126 
2127         SD_BUS_METHOD_WITH_ARGS("ResolveHostname",
2128                                 SD_BUS_ARGS("i", ifindex, "s", name, "i", family, "t", flags),
2129                                 SD_BUS_RESULT("a(iiay)", addresses, "s", canonical, "t", flags),
2130                                 bus_method_resolve_hostname,
2131                                 SD_BUS_VTABLE_UNPRIVILEGED),
2132         SD_BUS_METHOD_WITH_ARGS("ResolveAddress",
2133                                 SD_BUS_ARGS("i",  ifindex, "i", family, "ay", address, "t", flags),
2134                                 SD_BUS_RESULT("a(is)", names, "t", flags),
2135                                 bus_method_resolve_address,
2136                                 SD_BUS_VTABLE_UNPRIVILEGED),
2137         SD_BUS_METHOD_WITH_ARGS("ResolveRecord",
2138                                 SD_BUS_ARGS("i", ifindex, "s", name, "q", class, "q", type, "t", flags),
2139                                 SD_BUS_RESULT("a(iqqay)", records, "t", flags),
2140                                 bus_method_resolve_record,
2141                                 SD_BUS_VTABLE_UNPRIVILEGED),
2142         SD_BUS_METHOD_WITH_ARGS("ResolveService",
2143                                 SD_BUS_ARGS("i", ifindex,
2144                                             "s", name,
2145                                             "s", type,
2146                                             "s", domain,
2147                                             "i", family,
2148                                             "t", flags),
2149                                 SD_BUS_RESULT("a(qqqsa(iiay)s)", srv_data,
2150                                               "aay", txt_data,
2151                                               "s", canonical_name,
2152                                               "s", canonical_type,
2153                                               "s", canonical_domain,
2154                                               "t", flags),
2155                                 bus_method_resolve_service,
2156                                 SD_BUS_VTABLE_UNPRIVILEGED),
2157         SD_BUS_METHOD_WITH_ARGS("GetLink",
2158                                 SD_BUS_ARGS("i", ifindex),
2159                                 SD_BUS_RESULT("o", path),
2160                                 bus_method_get_link,
2161                                 SD_BUS_VTABLE_UNPRIVILEGED),
2162         SD_BUS_METHOD_WITH_ARGS("SetLinkDNS",
2163                                 SD_BUS_ARGS("i", ifindex, "a(iay)", addresses),
2164                                 SD_BUS_NO_RESULT,
2165                                 bus_method_set_link_dns_servers,
2166                                 SD_BUS_VTABLE_UNPRIVILEGED),
2167         SD_BUS_METHOD_WITH_ARGS("SetLinkDNSEx",
2168                                 SD_BUS_ARGS("i", ifindex, "a(iayqs)", addresses),
2169                                 SD_BUS_NO_RESULT,
2170                                 bus_method_set_link_dns_servers_ex,
2171                                 SD_BUS_VTABLE_UNPRIVILEGED),
2172         SD_BUS_METHOD_WITH_ARGS("SetLinkDomains",
2173                                 SD_BUS_ARGS("i", ifindex, "a(sb)", domains),
2174                                 SD_BUS_NO_RESULT,
2175                                 bus_method_set_link_domains,
2176                                 SD_BUS_VTABLE_UNPRIVILEGED),
2177         SD_BUS_METHOD_WITH_ARGS("SetLinkDefaultRoute",
2178                                 SD_BUS_ARGS("i", ifindex, "b", enable),
2179                                 SD_BUS_NO_RESULT,
2180                                 bus_method_set_link_default_route,
2181                                 SD_BUS_VTABLE_UNPRIVILEGED),
2182         SD_BUS_METHOD_WITH_ARGS("SetLinkLLMNR",
2183                                 SD_BUS_ARGS("i", ifindex, "s", mode),
2184                                 SD_BUS_NO_RESULT,
2185                                 bus_method_set_link_llmnr,
2186                                 SD_BUS_VTABLE_UNPRIVILEGED),
2187         SD_BUS_METHOD_WITH_ARGS("SetLinkMulticastDNS",
2188                                 SD_BUS_ARGS("i", ifindex, "s", mode),
2189                                 SD_BUS_NO_RESULT,
2190                                 bus_method_set_link_mdns,
2191                                 SD_BUS_VTABLE_UNPRIVILEGED),
2192         SD_BUS_METHOD_WITH_ARGS("SetLinkDNSOverTLS",
2193                                 SD_BUS_ARGS("i", ifindex, "s", mode),
2194                                 SD_BUS_NO_RESULT,
2195                                 bus_method_set_link_dns_over_tls,
2196                                 SD_BUS_VTABLE_UNPRIVILEGED),
2197         SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSEC",
2198                                 SD_BUS_ARGS("i", ifindex, "s", mode),
2199                                 SD_BUS_NO_RESULT,
2200                                 bus_method_set_link_dnssec,
2201                                 SD_BUS_VTABLE_UNPRIVILEGED),
2202         SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSECNegativeTrustAnchors",
2203                                 SD_BUS_ARGS("i", ifindex, "as", names),
2204                                 SD_BUS_NO_RESULT,
2205                                 bus_method_set_link_dnssec_negative_trust_anchors,
2206                                 SD_BUS_VTABLE_UNPRIVILEGED),
2207         SD_BUS_METHOD_WITH_ARGS("RevertLink",
2208                                 SD_BUS_ARGS("i", ifindex),
2209                                 SD_BUS_NO_RESULT,
2210                                 bus_method_revert_link,
2211                                 SD_BUS_VTABLE_UNPRIVILEGED),
2212         SD_BUS_METHOD_WITH_ARGS("RegisterService",
2213                                 SD_BUS_ARGS("s", name,
2214                                             "s", name_template,
2215                                             "s", type,
2216                                             "q", service_port,
2217                                             "q", service_priority,
2218                                             "q", service_weight,
2219                                             "aa{say}", txt_datas),
2220                                 SD_BUS_RESULT("o", service_path),
2221                                 bus_method_register_service,
2222                                 SD_BUS_VTABLE_UNPRIVILEGED),
2223         SD_BUS_METHOD_WITH_ARGS("UnregisterService",
2224                                 SD_BUS_ARGS("o", service_path),
2225                                 SD_BUS_NO_RESULT,
2226                                 bus_method_unregister_service,
2227                                 SD_BUS_VTABLE_UNPRIVILEGED),
2228         SD_BUS_METHOD_WITH_ARGS("ResetStatistics",
2229                                 SD_BUS_NO_ARGS,
2230                                 SD_BUS_NO_RESULT,
2231                                 bus_method_reset_statistics,
2232                                 SD_BUS_VTABLE_UNPRIVILEGED),
2233         SD_BUS_METHOD_WITH_ARGS("FlushCaches",
2234                                 SD_BUS_NO_ARGS,
2235                                 SD_BUS_NO_RESULT,
2236                                 bus_method_flush_caches,
2237                                 SD_BUS_VTABLE_UNPRIVILEGED),
2238         SD_BUS_METHOD_WITH_ARGS("ResetServerFeatures",
2239                                 SD_BUS_NO_ARGS,
2240                                 SD_BUS_NO_RESULT,
2241                                 bus_method_reset_server_features,
2242                                 SD_BUS_VTABLE_UNPRIVILEGED),
2243 
2244         SD_BUS_VTABLE_END,
2245 };
2246 
2247 const BusObjectImplementation manager_object = {
2248         "/org/freedesktop/resolve1",
2249         "org.freedesktop.resolve1.Manager",
2250         .vtables = BUS_VTABLES(resolve_vtable),
2251         .children = BUS_IMPLEMENTATIONS(&link_object,
2252                                         &dnssd_object),
2253 };
2254 
match_prepare_for_sleep(sd_bus_message * message,void * userdata,sd_bus_error * ret_error)2255 static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
2256         Manager *m = userdata;
2257         int b, r;
2258 
2259         assert(message);
2260         assert(m);
2261 
2262         r = sd_bus_message_read(message, "b", &b);
2263         if (r < 0) {
2264                 bus_log_parse_error(r);
2265                 return 0;
2266         }
2267 
2268         if (b)
2269                 return 0;
2270 
2271         log_debug("Coming back from suspend, verifying all RRs...");
2272 
2273         manager_verify_all(m);
2274         return 0;
2275 }
2276 
manager_connect_bus(Manager * m)2277 int manager_connect_bus(Manager *m) {
2278         int r;
2279 
2280         assert(m);
2281 
2282         if (m->bus)
2283                 return 0;
2284 
2285         r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-resolve");
2286         if (r < 0)
2287                 return log_error_errno(r, "Failed to connect to system bus: %m");
2288 
2289         r = bus_add_implementation(m->bus, &manager_object, m);
2290         if (r < 0)
2291                 return r;
2292 
2293         r = bus_log_control_api_register(m->bus);
2294         if (r < 0)
2295                 return r;
2296 
2297         r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL, NULL);
2298         if (r < 0)
2299                 return log_error_errno(r, "Failed to request name: %m");
2300 
2301         r = sd_bus_attach_event(m->bus, m->event, 0);
2302         if (r < 0)
2303                 return log_error_errno(r, "Failed to attach bus to event loop: %m");
2304 
2305         r = sd_bus_match_signal_async(
2306                         m->bus,
2307                         NULL,
2308                         "org.freedesktop.login1",
2309                         "/org/freedesktop/login1",
2310                         "org.freedesktop.login1.Manager",
2311                         "PrepareForSleep",
2312                         match_prepare_for_sleep,
2313                         NULL,
2314                         m);
2315         if (r < 0)
2316                 log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
2317 
2318         return 0;
2319 }
2320 
_manager_send_changed(Manager * manager,const char * property,...)2321 int _manager_send_changed(Manager *manager, const char *property, ...) {
2322         assert(manager);
2323 
2324         if (sd_bus_is_ready(manager->bus) <= 0)
2325                 return 0;
2326 
2327         char **l = strv_from_stdarg_alloca(property);
2328 
2329         int r = sd_bus_emit_properties_changed_strv(
2330                         manager->bus,
2331                         "/org/freedesktop/resolve1",
2332                         "org.freedesktop.resolve1.Manager",
2333                         l);
2334         if (r < 0)
2335                 log_notice_errno(r, "Failed to emit notification about changed property %s: %m", property);
2336         return r;
2337 }
2338