• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 14630481637

23 Apr 2025 07:04PM UTC coverage: 72.178% (-0.002%) from 72.18%
14630481637

push

github

DaanDeMeyer
mkosi: Run clangd within the tools tree instead of the build container

Running within the build sandbox has a number of disadvantages:
- We have a separate clangd cache for each distribution/release combo
- It requires to build the full image before clangd can be used
- It breaks every time the image becomes out of date and requires a
  rebuild
- We can't look at system headers as we don't have the knowledge to map
  them from inside the build sandbox to the corresponding path on the host

Instead, let's have mkosi.clangd run clangd within the tools tree. We
already require building systemd for both the host and the target anyway,
and all the dependencies to build systemd are installed in the tools tree
already for that, as well as clangd since it's installed together with the
other clang tooling we install in the tools tree. Unlike the previous approach,
this approach only requires the mkosi tools tree to be built upfront, which has
a much higher chance of not invalidating its cache. We can also trivially map
system header lookups from within the sandbox to the path within mkosi.tools
on the host so that starts working as well.

297054 of 411557 relevant lines covered (72.18%)

686269.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.58
/src/resolve/resolved-bus.c
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-locator.h"
7
#include "bus-log-control-api.h"
8
#include "bus-message-util.h"
9
#include "bus-polkit.h"
10
#include "bus-util.h"
11
#include "dns-domain.h"
12
#include "format-util.h"
13
#include "memory-util.h"
14
#include "path-util.h"
15
#include "resolve-util.h"
16
#include "resolved-bus.h"
17
#include "resolved-def.h"
18
#include "resolved-dns-answer.h"
19
#include "resolved-dns-dnssec.h"
20
#include "resolved-dns-packet.h"
21
#include "resolved-dns-query.h"
22
#include "resolved-dns-question.h"
23
#include "resolved-dns-rr.h"
24
#include "resolved-dns-scope.h"
25
#include "resolved-dns-search-domain.h"
26
#include "resolved-dns-server.h"
27
#include "resolved-dns-stream.h"
28
#include "resolved-dns-stub.h"
29
#include "resolved-dns-synthesize.h"
30
#include "resolved-dns-transaction.h"
31
#include "resolved-dns-trust-anchor.h"
32
#include "resolved-dnssd-bus.h"
33
#include "resolved-dnssd.h"
34
#include "resolved-link.h"
35
#include "resolved-link-bus.h"
36
#include "resolved-manager.h"
37
#include "resolved-resolv-conf.h"
38
#include "socket-netlink.h"
39
#include "stdio-util.h"
40
#include "strv.h"
41
#include "syslog-util.h"
42
#include "user-util.h"
43
#include "utf8.h"
44

45
BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_resolve_support, resolve_support, ResolveSupport);
26✔
46

47
static int dns_query_new_for_bus(
50✔
48
                Manager *m,
49
                DnsQuery **ret,
50
                DnsQuestion *question_utf8,
51
                DnsQuestion *question_idna,
52
                DnsPacket *question_bypass,
53
                int ifindex,
54
                uint64_t flags,
55
                sd_bus_error *error) {
56

57
        int r;
50✔
58

59
        r = dns_query_new(m, ret, question_utf8, question_idna, question_bypass, ifindex, flags);
50✔
60
        if (r == -ENOANO)
50✔
61
                return sd_bus_error_set(error, BUS_ERROR_DNS_REFUSED, "DNS query type refused.");
4✔
62
        return r;
63
}
64

65
static int query_on_bus_track(sd_bus_track *t, void *userdata) {
×
66
        DnsQuery *q = ASSERT_PTR(userdata);
×
67

68
        assert(t);
×
69

70
        if (!DNS_TRANSACTION_IS_LIVE(q->state))
×
71
                return 0;
72

73
        log_debug("Client of active query vanished, aborting query.");
×
74
        dns_query_complete(q, DNS_TRANSACTION_ABORTED);
×
75
        return 0;
×
76
}
77

78
static int dns_query_bus_track(DnsQuery *q, sd_bus_message *m) {
46✔
79
        int r;
46✔
80

81
        assert(q);
46✔
82
        assert(m);
46✔
83

84
        if (!q->bus_track) {
46✔
85
                r = sd_bus_track_new(sd_bus_message_get_bus(m), &q->bus_track, query_on_bus_track, q);
46✔
86
                if (r < 0)
46✔
87
                        return r;
88
        }
89

90
        r = sd_bus_track_add_sender(q->bus_track, m);
46✔
91
        if (r < 0)
46✔
92
                return r;
×
93

94
        return 0;
95
}
96

97
static sd_bus_message *dns_query_steal_request(DnsQuery *q) {
9✔
98
        assert(q);
9✔
99

100
        /* Find the main query, it's the one that owns the message */
101
        while (q->auxiliary_for)
10✔
102
                q = q->auxiliary_for;
103

104
        /* Let's take the request message out of the DnsQuery object, so that we never send requests twice */
105
        return TAKE_PTR(q->bus_request);
9✔
106
}
107

108
_sd_printf_(3, 4) static int reply_method_errorf(
3✔
109
                DnsQuery *query,
110
                const char *error_name,
111
                const char *format,
112
                ...) {
113

114
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
3✔
115
        va_list ap;
3✔
116
        int r;
3✔
117

118
        assert(query);
3✔
119
        assert(format);
3✔
120

121
        req = dns_query_steal_request(query);
3✔
122
        if (!req) /* No bus message set anymore? then we already replied already, let's not answer a second time */
3✔
123
                return 0;
124

125
        va_start(ap, format);
3✔
126
        r = sd_bus_reply_method_errorfv(req, error_name, format, ap);
3✔
127
        va_end(ap);
3✔
128

129
        return r;
3✔
130
}
131

132
_sd_printf_(3, 4) static int reply_method_errnof(
×
133
                DnsQuery *query,
134
                int err,
135
                const char *format,
136
                ...) {
137

138
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
×
139
        int r;
×
140

141
        assert(query);
×
142

143
        req = dns_query_steal_request(query);
×
144
        if (!req) /* No bus message set anymore? then we already replied already, let's not answer a second time */
×
145
                return 0;
146

147
        if (format) {
×
148
                va_list ap;
×
149

150
                va_start(ap, format);
×
151
                r = sd_bus_reply_method_errnofv(req, err, format, ap);
×
152
                va_end(ap);
×
153
        } else
154
                r = sd_bus_reply_method_errno(req, err, NULL);
×
155

156
        return r;
×
157
}
158

159
static int reply_query_state(DnsQuery *q) {
7✔
160
        assert(q);
7✔
161

162
        switch (q->state) {
7✔
163

164
        case DNS_TRANSACTION_NO_SERVERS:
×
165
                return reply_method_errorf(q, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found");
7✔
166

167
        case DNS_TRANSACTION_TIMEOUT:
×
168
                return reply_method_errorf(q, SD_BUS_ERROR_TIMEOUT, "Query timed out");
×
169

170
        case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED:
×
171
                return reply_method_errorf(q, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed");
×
172

173
        case DNS_TRANSACTION_INVALID_REPLY:
×
174
                return reply_method_errorf(q, BUS_ERROR_INVALID_REPLY, "Received invalid reply");
×
175

176
        case DNS_TRANSACTION_ERRNO:
×
177
                return reply_method_errnof(q, q->answer_errno, "Lookup failed due to system error: %m");
×
178

179
        case DNS_TRANSACTION_ABORTED:
×
180
                return reply_method_errorf(q, BUS_ERROR_ABORTED, "Query aborted");
×
181

182
        case DNS_TRANSACTION_DNSSEC_FAILED:
1✔
183
                return reply_method_errorf(q, BUS_ERROR_DNSSEC_FAILED, "DNSSEC validation failed: %s%s%s%s%s%s",
2✔
184
                                           dnssec_result_to_string(q->answer_dnssec_result),
185
                                           q->answer_ede_rcode >= 0 ? " (" : "",
1✔
186
                                           q->answer_ede_rcode >= 0 ? FORMAT_DNS_EDE_RCODE(q->answer_ede_rcode) : "",
1✔
187
                                           (q->answer_ede_rcode >= 0 && !isempty(q->answer_ede_msg)) ? ": " : "",
2✔
188
                                           q->answer_ede_rcode >= 0 ? strempty(q->answer_ede_msg) : "",
1✔
189
                                           q->answer_ede_rcode >= 0 ? ")" : "");
1✔
190

191
        case DNS_TRANSACTION_NO_TRUST_ANCHOR:
×
192
                return reply_method_errorf(q, BUS_ERROR_NO_TRUST_ANCHOR, "No suitable trust anchor known");
×
193

194
        case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
×
195
                return reply_method_errorf(q, BUS_ERROR_RR_TYPE_UNSUPPORTED, "Server does not support requested resource record type");
×
196

197
        case DNS_TRANSACTION_NETWORK_DOWN:
×
198
                return reply_method_errorf(q, BUS_ERROR_NETWORK_DOWN, "Network is down");
×
199

200
        case DNS_TRANSACTION_NOT_FOUND:
×
201
                /* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
202
                 * thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
203
                return reply_method_errorf(q, BUS_ERROR_DNS_NXDOMAIN, "'%s' not found", dns_query_string(q));
×
204

205
        case DNS_TRANSACTION_NO_SOURCE:
×
206
                return reply_method_errorf(q, BUS_ERROR_NO_SOURCE, "All suitable resolution sources turned off");
×
207

208
        case DNS_TRANSACTION_STUB_LOOP:
×
209
                return reply_method_errorf(q, BUS_ERROR_STUB_LOOP, "Configured DNS server loops back to us");
×
210

211
        case DNS_TRANSACTION_RCODE_FAILURE: {
6✔
212
                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
×
213
                _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL;
6✔
214

215
                req = dns_query_steal_request(q);
6✔
216
                if (!req) /* No bus message set anymore? then we already replied already, let's not answer a second time */
6✔
217
                        return 0;
218

219
                if (q->answer_rcode == DNS_RCODE_NXDOMAIN)
6✔
220
                        sd_bus_error_setf(&error, BUS_ERROR_DNS_NXDOMAIN, "Name '%s' not found", dns_query_string(q));
2✔
221
                else {
222
                        const char *rc, *n;
4✔
223

224
                        rc = FORMAT_DNS_RCODE(q->answer_rcode);
4✔
225
                        n = strjoina(_BUS_ERROR_DNS, rc);
20✔
226
                        sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error: %s%s%s%s%s%s",
8✔
227
                                          dns_query_string(q), rc,
228
                                          q->answer_ede_rcode >= 0 ? " (" : "",
4✔
229
                                          q->answer_ede_rcode >= 0 ? FORMAT_DNS_EDE_RCODE(q->answer_ede_rcode) : "",
4✔
230
                                          (q->answer_ede_rcode >= 0 && !isempty(q->answer_ede_msg)) ? ": " : "",
8✔
231
                                          q->answer_ede_rcode >= 0 ? strempty(q->answer_ede_msg) : "",
4✔
232
                                          q->answer_ede_rcode >= 0 ? ")" : "");
4✔
233
                }
234

235
                return sd_bus_reply_method_error(req, &error);
6✔
236
        }
237

238
        case DNS_TRANSACTION_NULL:
×
239
        case DNS_TRANSACTION_PENDING:
240
        case DNS_TRANSACTION_VALIDATING:
241
        case DNS_TRANSACTION_SUCCESS:
242
        default:
243
                assert_not_reached();
×
244
        }
245
}
246

247
static int append_address(sd_bus_message *reply, DnsResourceRecord *rr, int ifindex) {
43✔
248
        int r;
43✔
249

250
        assert(reply);
43✔
251
        assert(rr);
43✔
252

253
        r = sd_bus_message_open_container(reply, 'r', "iiay");
43✔
254
        if (r < 0)
43✔
255
                return r;
256

257
        r = sd_bus_message_append(reply, "i", ifindex);
43✔
258
        if (r < 0)
43✔
259
                return r;
260

261
        if (rr->key->type == DNS_TYPE_A) {
43✔
262
                r = sd_bus_message_append(reply, "i", AF_INET);
25✔
263
                if (r < 0)
25✔
264
                        return r;
265

266
                r = sd_bus_message_append_array(reply, 'y', &rr->a.in_addr, sizeof(struct in_addr));
25✔
267

268
        } else if (rr->key->type == DNS_TYPE_AAAA) {
18✔
269
                r = sd_bus_message_append(reply, "i", AF_INET6);
18✔
270
                if (r < 0)
18✔
271
                        return r;
272

273
                r = sd_bus_message_append_array(reply, 'y', &rr->aaaa.in6_addr, sizeof(struct in6_addr));
18✔
274
        } else
275
                return -EAFNOSUPPORT;
276

277
        if (r < 0)
43✔
278
                return r;
279

280
        r = sd_bus_message_close_container(reply);
43✔
281
        if (r < 0)
43✔
282
                return r;
×
283

284
        return 0;
285
}
286

287
static void bus_method_resolve_hostname_complete(DnsQuery *query) {
23✔
288
        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
×
289
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
23✔
290
        _cleanup_(dns_query_freep) DnsQuery *q = query;
×
291
        _cleanup_free_ char *normalized = NULL;
23✔
292
        DnsQuestion *question;
23✔
293
        DnsResourceRecord *rr;
23✔
294
        unsigned added = 0;
23✔
295
        int ifindex, r;
23✔
296

297
        assert(q);
23✔
298

299
        if (q->state != DNS_TRANSACTION_SUCCESS) {
23✔
300
                r = reply_query_state(q);
6✔
301
                goto finish;
6✔
302
        }
303

304
        r = dns_query_process_cname_many(q);
17✔
305
        if (r == -ELOOP) {
17✔
306
                r = reply_method_errorf(q, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
×
307
                goto finish;
×
308
        }
309
        if (r < 0)
17✔
310
                goto finish;
×
311
        if (r == DNS_QUERY_CNAME) {
17✔
312
                /* This was a cname, and the query was restarted. */
313
                TAKE_PTR(q);
×
314
                return;
×
315
        }
316

317
        r = sd_bus_message_new_method_return(q->bus_request, &reply);
17✔
318
        if (r < 0)
17✔
319
                goto finish;
×
320

321
        r = sd_bus_message_open_container(reply, 'a', "(iiay)");
17✔
322
        if (r < 0)
17✔
323
                goto finish;
×
324

325
        question = dns_query_question_for_protocol(q, q->answer_protocol);
17✔
326

327
        DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
68✔
328

329
                r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain));
51✔
330
                if (r < 0)
51✔
331
                        goto finish;
×
332
                if (r == 0)
51✔
333
                        continue;
16✔
334

335
                r = append_address(reply, rr, ifindex);
35✔
336
                if (r < 0)
35✔
337
                        goto finish;
×
338

339
                if (!canonical)
35✔
340
                        canonical = dns_resource_record_ref(rr);
17✔
341

342
                added++;
35✔
343
        }
344

345
        if (added <= 0) {
17✔
346
                r = reply_method_errorf(q, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
×
347
                goto finish;
×
348
        }
349

350
        r = sd_bus_message_close_container(reply);
17✔
351
        if (r < 0)
17✔
352
                goto finish;
×
353

354
        /* The key names are not necessarily normalized, make sure that they are when we return them to our
355
         * bus clients. */
356
        assert(canonical);
17✔
357
        r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized);
17✔
358
        if (r < 0)
17✔
359
                goto finish;
×
360

361
        /* Return the precise spelling and uppercasing and CNAME target reported by the server */
362
        r = sd_bus_message_append(
17✔
363
                        reply, "st",
364
                        normalized,
365
                        dns_query_reply_flags_make(q));
366
        if (r < 0)
17✔
367
                goto finish;
×
368

369
        q->bus_request = sd_bus_message_unref(q->bus_request);
17✔
370
        r = sd_bus_send(q->manager->bus, reply, NULL);
17✔
371

372
finish:
23✔
373
        if (r < 0) {
23✔
374
                log_error_errno(r, "Failed to send hostname reply: %m");
×
375
                (void) reply_method_errnof(q, r, NULL);
×
376
        }
377
}
378

379
static int parse_as_address(sd_bus_message *m, int ifindex, const char *hostname, int family, uint64_t flags) {
23✔
380
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
23✔
381
        _cleanup_free_ char *canonical = NULL;
23✔
382
        union in_addr_union parsed;
23✔
383
        int r, ff, parsed_ifindex = 0;
23✔
384

385
        /* Check if the hostname is actually already an IP address formatted as string. In that case just parse it,
386
         * let's not attempt to look it up. */
387

388
        r = in_addr_ifindex_from_string_auto(hostname, &ff, &parsed, &parsed_ifindex);
23✔
389
        if (r < 0) /* not an address */
23✔
390
                return 0;
391

392
        if (family != AF_UNSPEC && ff != family)
×
393
                return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address is not of the requested family.");
×
394
        if (ifindex > 0 && parsed_ifindex > 0 && parsed_ifindex != ifindex)
×
395
                return sd_bus_reply_method_errorf(m, BUS_ERROR_NO_SUCH_RR, "The specified address interface index does not match requested interface.");
×
396

397
        if (parsed_ifindex > 0)
×
398
                ifindex = parsed_ifindex;
×
399

400
        r = sd_bus_message_new_method_return(m, &reply);
×
401
        if (r < 0)
×
402
                return r;
403

404
        r = sd_bus_message_open_container(reply, 'a', "(iiay)");
×
405
        if (r < 0)
×
406
                return r;
407

408
        r = sd_bus_message_open_container(reply, 'r', "iiay");
×
409
        if (r < 0)
×
410
                return r;
411

412
        r = sd_bus_message_append(reply, "ii", ifindex, ff);
×
413
        if (r < 0)
×
414
                return r;
415

416
        r = sd_bus_message_append_array(reply, 'y', &parsed, FAMILY_ADDRESS_SIZE(ff));
×
417
        if (r < 0)
×
418
                return r;
419

420
        r = sd_bus_message_close_container(reply);
×
421
        if (r < 0)
×
422
                return r;
423

424
        r = sd_bus_message_close_container(reply);
×
425
        if (r < 0)
×
426
                return r;
427

428
        /* When an IP address is specified we just return it as canonical name, in order to avoid a DNS
429
         * look-up. However, we reformat it to make sure it's in a truly canonical form (i.e. on IPv6 the inner
430
         * omissions are always done the same way). */
431
        r = in_addr_ifindex_to_string(ff, &parsed, ifindex, &canonical);
×
432
        if (r < 0)
×
433
                return r;
434

435
        r = sd_bus_message_append(reply, "st", canonical,
×
436
                                  SD_RESOLVED_FLAGS_MAKE(dns_synthesize_protocol(flags), ff, true, true) |
×
437
                                  SD_RESOLVED_SYNTHETIC);
438
        if (r < 0)
×
439
                return r;
440

441
        return sd_bus_send(sd_bus_message_get_bus(m), reply, NULL);
×
442
}
443

444
void bus_client_log(sd_bus_message *m, const char *what) {
98✔
445
        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
98✔
446
        const char *comm = NULL;
98✔
447
        uid_t uid = UID_INVALID;
98✔
448
        pid_t pid = 0;
98✔
449
        int r;
98✔
450

451
        assert(m);
98✔
452
        assert(what);
98✔
453

454
        if (!DEBUG_LOGGING)
98✔
455
                return;
456

457
        r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds);
98✔
458
        if (r < 0)
98✔
459
                return (void) log_debug_errno(r, "Failed to query client credentials, ignoring: %m");
×
460

461
        (void) sd_bus_creds_get_uid(creds, &uid);
98✔
462
        (void) sd_bus_creds_get_pid(creds, &pid);
98✔
463
        (void) sd_bus_creds_get_comm(creds, &comm);
98✔
464

465
        log_debug("D-Bus %s request from client PID " PID_FMT " (%s) with UID " UID_FMT,
98✔
466
                  what, pid, strna(comm), uid);
467
}
468

469
static int bus_method_resolve_hostname(sd_bus_message *message, void *userdata, sd_bus_error *error) {
23✔
470
        _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
23✔
471
        _cleanup_(dns_query_freep) DnsQuery *q = NULL;
23✔
472
        Manager *m = ASSERT_PTR(userdata);
23✔
473
        const char *hostname;
23✔
474
        int family, ifindex;
23✔
475
        uint64_t flags;
23✔
476
        int r;
23✔
477

478
        assert(message);
23✔
479

480
        assert_cc(sizeof(int) == sizeof(int32_t));
23✔
481

482
        r = sd_bus_message_read(message, "isit", &ifindex, &hostname, &family, &flags);
23✔
483
        if (r < 0)
23✔
484
                return r;
485

486
        if (ifindex < 0)
23✔
487
                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
×
488

489
        if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
23✔
490
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
×
491

492
        if (validate_and_mangle_query_flags(m, &flags, hostname, SD_RESOLVED_NO_SEARCH) < 0)
23✔
493
                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
×
494

495
        r = parse_as_address(message, ifindex, hostname, family, flags);
23✔
496
        if (r != 0)
23✔
497
                return r;
498

499
        r = dns_name_is_valid(hostname);
23✔
500
        if (r < 0)
23✔
501
                return r;
502
        if (r == 0)
23✔
503
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", hostname);
×
504

505
        r = dns_question_new_address(&question_utf8, family, hostname, false);
23✔
506
        if (r < 0)
23✔
507
                return r;
508

509
        r = dns_question_new_address(&question_idna, family, hostname, true);
23✔
510
        if (r < 0 && r != -EALREADY)
23✔
511
                return r;
512

513
        bus_client_log(message, "hostname resolution");
23✔
514

515
        r = dns_query_new_for_bus(m, &q, question_utf8, question_idna ?: question_utf8, NULL, ifindex, flags, error);
23✔
516
        if (r < 0)
23✔
517
                return r;
518

519
        q->bus_request = sd_bus_message_ref(message);
23✔
520
        q->request_family = family;
23✔
521
        q->complete = bus_method_resolve_hostname_complete;
23✔
522

523
        r = dns_query_bus_track(q, message);
23✔
524
        if (r < 0)
23✔
525
                return r;
526

527
        r = dns_query_go(q);
23✔
528
        if (r < 0)
23✔
529
                return r;
530

531
        TAKE_PTR(q);
23✔
532
        return 1;
23✔
533
}
534

535
static void bus_method_resolve_address_complete(DnsQuery *query) {
2✔
536
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2✔
537
        _cleanup_(dns_query_freep) DnsQuery *q = query;
2✔
538
        DnsQuestion *question;
2✔
539
        DnsResourceRecord *rr;
2✔
540
        unsigned added = 0;
2✔
541
        int ifindex, r;
2✔
542

543
        assert(q);
2✔
544

545
        if (q->state != DNS_TRANSACTION_SUCCESS) {
2✔
546
                r = reply_query_state(q);
×
547
                goto finish;
×
548
        }
549

550
        r = dns_query_process_cname_many(q);
2✔
551
        if (r == -ELOOP) {
2✔
552
                r = reply_method_errorf(q, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
×
553
                goto finish;
×
554
        }
555
        if (r < 0)
2✔
556
                goto finish;
×
557
        if (r == DNS_QUERY_CNAME) {
2✔
558
                /* This was a cname, and the query was restarted. */
559
                TAKE_PTR(q);
×
560
                return;
×
561
        }
562

563
        r = sd_bus_message_new_method_return(q->bus_request, &reply);
2✔
564
        if (r < 0)
2✔
565
                goto finish;
×
566

567
        r = sd_bus_message_open_container(reply, 'a', "(is)");
2✔
568
        if (r < 0)
2✔
569
                goto finish;
×
570

571
        question = dns_query_question_for_protocol(q, q->answer_protocol);
2✔
572

573
        DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
4✔
574
                _cleanup_free_ char *normalized = NULL;
2✔
575

576
                r = dns_question_matches_rr(question, rr, NULL);
2✔
577
                if (r < 0)
2✔
578
                        goto finish;
×
579
                if (r == 0)
2✔
580
                        continue;
×
581

582
                r = dns_name_normalize(rr->ptr.name, 0, &normalized);
2✔
583
                if (r < 0)
2✔
584
                        goto finish;
×
585

586
                r = sd_bus_message_append(reply, "(is)", ifindex, normalized);
2✔
587
                if (r < 0)
2✔
588
                        goto finish;
×
589

590
                added++;
2✔
591
        }
592

593
        if (added <= 0) {
2✔
594
                r = reply_method_errorf(q, BUS_ERROR_NO_SUCH_RR,
×
595
                                        "Address %s does not have any RR of requested type",
596
                                        IN_ADDR_TO_STRING(q->request_family, &q->request_address));
×
597
                goto finish;
×
598
        }
599

600
        r = sd_bus_message_close_container(reply);
2✔
601
        if (r < 0)
2✔
602
                goto finish;
×
603

604
        r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
2✔
605
        if (r < 0)
2✔
606
                goto finish;
×
607

608
        q->bus_request = sd_bus_message_unref(q->bus_request);
2✔
609
        r = sd_bus_send(q->manager->bus, reply, NULL);
2✔
610

611
finish:
2✔
612
        if (r < 0) {
2✔
613
                log_error_errno(r, "Failed to send address reply: %m");
×
614
                (void) reply_method_errnof(q, r, NULL);
×
615
        }
616
}
617

618
static int bus_method_resolve_address(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2✔
619
        _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2✔
620
        _cleanup_(dns_query_freep) DnsQuery *q = NULL;
2✔
621
        Manager *m = ASSERT_PTR(userdata);
2✔
622
        union in_addr_union a;
2✔
623
        int family, ifindex;
2✔
624
        uint64_t flags;
2✔
625
        int r;
2✔
626

627
        assert(message);
2✔
628

629
        assert_cc(sizeof(int) == sizeof(int32_t));
2✔
630

631
        r = sd_bus_message_read(message, "i", &ifindex);
2✔
632
        if (r < 0)
2✔
633
                return r;
634

635
        r = bus_message_read_in_addr_auto(message, error, &family, &a);
2✔
636
        if (r < 0)
2✔
637
                return r;
638

639
        r = sd_bus_message_read(message, "t", &flags);
2✔
640
        if (r < 0)
2✔
641
                return r;
642

643
        if (ifindex < 0)
2✔
644
                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
×
645

646
        if (validate_and_mangle_query_flags(m, &flags, /* name = */ NULL, /* ok = */ 0) < 0)
2✔
647
                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
×
648

649
        r = dns_question_new_reverse(&question, family, &a);
2✔
650
        if (r < 0)
2✔
651
                return r;
652

653
        bus_client_log(message, "address resolution");
2✔
654

655
        r = dns_query_new_for_bus(m, &q, question, question, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH, error);
2✔
656
        if (r < 0)
2✔
657
                return r;
658

659
        q->bus_request = sd_bus_message_ref(message);
2✔
660
        q->request_family = family;
2✔
661
        q->request_address = a;
2✔
662
        q->complete = bus_method_resolve_address_complete;
2✔
663

664
        r = dns_query_bus_track(q, message);
2✔
665
        if (r < 0)
2✔
666
                return r;
667

668
        r = dns_query_go(q);
2✔
669
        if (r < 0)
2✔
670
                return r;
671

672
        TAKE_PTR(q);
2✔
673
        return 1;
2✔
674
}
675

676
static int bus_message_append_rr(sd_bus_message *m, DnsResourceRecord *rr, int ifindex) {
12✔
677
        int r;
12✔
678

679
        assert(m);
12✔
680
        assert(rr);
12✔
681

682
        r = sd_bus_message_open_container(m, 'r', "iqqay");
12✔
683
        if (r < 0)
12✔
684
                return r;
685

686
        r = sd_bus_message_append(m, "iqq",
24✔
687
                                  ifindex,
688
                                  rr->key->class,
12✔
689
                                  rr->key->type);
12✔
690
        if (r < 0)
12✔
691
                return r;
692

693
        r = dns_resource_record_to_wire_format(rr, false);
12✔
694
        if (r < 0)
12✔
695
                return r;
696

697
        r = sd_bus_message_append_array(m, 'y', rr->wire_format, rr->wire_format_size);
12✔
698
        if (r < 0)
12✔
699
                return r;
700

701
        return sd_bus_message_close_container(m);
12✔
702
}
703

704
static void bus_method_resolve_record_complete(DnsQuery *query) {
16✔
705
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
16✔
706
        _cleanup_(dns_query_freep) DnsQuery *q = query;
14✔
707
        DnsResourceRecord *rr;
16✔
708
        DnsQuestion *question;
16✔
709
        unsigned added = 0;
16✔
710
        int ifindex;
16✔
711
        int r;
16✔
712

713
        assert(q);
16✔
714

715
        if (q->state != DNS_TRANSACTION_SUCCESS) {
16✔
716
                r = reply_query_state(q);
×
717
                goto finish;
×
718
        }
719

720
        r = dns_query_process_cname_many(q);
16✔
721
        if (r == -ELOOP) {
16✔
722
                r = reply_method_errorf(q, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
×
723
                goto finish;
×
724
        }
725
        if (r < 0)
16✔
726
                goto finish;
×
727
        if (r == DNS_QUERY_CNAME) {
16✔
728
                /* This was a cname, and the query was restarted. */
729
                TAKE_PTR(q);
2✔
730
                return;
2✔
731
        }
732

733
        r = sd_bus_message_new_method_return(q->bus_request, &reply);
14✔
734
        if (r < 0)
14✔
735
                goto finish;
×
736

737
        r = sd_bus_message_open_container(reply, 'a', "(iqqay)");
14✔
738
        if (r < 0)
14✔
739
                goto finish;
×
740

741
        question = dns_query_question_for_protocol(q, q->answer_protocol);
14✔
742

743
        DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
34✔
744
                r = dns_question_matches_rr(question, rr, NULL);
20✔
745
                if (r < 0)
20✔
746
                        goto finish;
×
747
                if (r == 0)
20✔
748
                        continue;
8✔
749

750
                r = bus_message_append_rr(reply, rr, ifindex);
12✔
751
                if (r < 0)
12✔
752
                        goto finish;
×
753

754
                added++;
12✔
755
        }
756

757
        if (added <= 0) {
14✔
758
                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));
2✔
759
                goto finish;
2✔
760
        }
761

762
        r = sd_bus_message_close_container(reply);
12✔
763
        if (r < 0)
12✔
764
                goto finish;
×
765

766
        r = sd_bus_message_append(reply, "t", dns_query_reply_flags_make(q));
12✔
767
        if (r < 0)
12✔
768
                goto finish;
×
769

770
        q->bus_request = sd_bus_message_unref(q->bus_request);
12✔
771
        r = sd_bus_send(q->manager->bus, reply, NULL);
12✔
772

773
finish:
14✔
774
        if (r < 0) {
14✔
775
                log_error_errno(r, "Failed to send record reply: %m");
×
776
                (void) reply_method_errnof(q, r, NULL);
×
777
        }
778
}
779

780
static int bus_method_resolve_record(sd_bus_message *message, void *userdata, sd_bus_error *error) {
18✔
781
        _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
18✔
782
        _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
18✔
783
        _cleanup_(dns_query_freep) DnsQuery *q = NULL;
18✔
784
        Manager *m = ASSERT_PTR(userdata);
18✔
785
        uint16_t class, type;
18✔
786
        const char *name;
18✔
787
        int r, ifindex;
18✔
788
        uint64_t flags;
18✔
789

790
        assert(message);
18✔
791

792
        assert_cc(sizeof(int) == sizeof(int32_t));
18✔
793

794
        r = sd_bus_message_read(message, "isqqt", &ifindex, &name, &class, &type, &flags);
18✔
795
        if (r < 0)
18✔
796
                return r;
797

798
        if (ifindex < 0)
18✔
799
                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
×
800

801
        r = dns_name_is_valid(name);
18✔
802
        if (r < 0)
18✔
803
                return r;
804
        if (r == 0)
18✔
805
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid name '%s'", name);
×
806

807
        if (!dns_type_is_valid_query(type))
18✔
808
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified resource record type %" PRIu16 " may not be used in a query.", type);
×
809
        if (dns_type_is_zone_transfer(type))
18✔
810
                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Zone transfers not permitted via this programming interface.");
×
811
        if (dns_type_is_obsolete(type))
18✔
812
                return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Specified DNS resource record type %" PRIu16 " is obsolete.", type);
×
813

814
        if (validate_and_mangle_query_flags(m, &flags, name, SD_RESOLVED_NO_SEARCH) < 0)
18✔
815
                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
×
816

817
        question = dns_question_new(1);
18✔
818
        if (!question)
18✔
819
                return -ENOMEM;
820

821
        key = dns_resource_key_new(class, type, name);
18✔
822
        if (!key)
18✔
823
                return -ENOMEM;
824

825
        r = dns_question_add(question, key, 0);
18✔
826
        if (r < 0)
18✔
827
                return r;
828

829
        bus_client_log(message, "resource record resolution");
18✔
830

831
        /* Setting SD_RESOLVED_CLAMP_TTL: let's request that the TTL is fixed up for locally cached entries,
832
         * after all we return it in the wire format blob. */
833
        r = dns_query_new_for_bus(m, &q, question, question, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH|SD_RESOLVED_CLAMP_TTL, error);
18✔
834
        if (r < 0)
18✔
835
                return r;
836

837
        q->bus_request = sd_bus_message_ref(message);
14✔
838
        q->complete = bus_method_resolve_record_complete;
14✔
839

840
        r = dns_query_bus_track(q, message);
14✔
841
        if (r < 0)
14✔
842
                return r;
843

844
        r = dns_query_go(q);
14✔
845
        if (r < 0)
14✔
846
                return r;
847

848
        TAKE_PTR(q);
14✔
849
        return 1;
14✔
850
}
851

852
static int append_srv(DnsQuery *q, sd_bus_message *reply, DnsResourceRecord *rr) {
9✔
853
        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
×
854
        _cleanup_free_ char *normalized = NULL;
9✔
855
        int r;
9✔
856

857
        assert(q);
9✔
858
        assert(reply);
9✔
859
        assert(rr);
9✔
860
        assert(rr->key);
9✔
861

862
        if (rr->key->type != DNS_TYPE_SRV)
9✔
863
                return 0;
864

865
        if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
6✔
866
                /* First, let's see if we could find an appropriate A or AAAA
867
                 * record for the SRV record */
868
                LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
5✔
869
                        DnsResourceRecord *zz;
5✔
870
                        DnsQuestion *question;
5✔
871

872
                        if (aux->state != DNS_TRANSACTION_SUCCESS)
5✔
873
                                continue;
×
874
                        if (aux->auxiliary_result != 0)
5✔
875
                                continue;
×
876

877
                        question = dns_query_question_for_protocol(aux, aux->answer_protocol);
5✔
878

879
                        r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
5✔
880
                        if (r < 0)
5✔
881
                                return r;
882
                        if (r == 0)
5✔
883
                                continue;
×
884

885
                        DNS_ANSWER_FOREACH(zz, aux->answer) {
5✔
886

887
                                r = dns_question_matches_rr(question, zz, NULL);
5✔
888
                                if (r < 0)
5✔
889
                                        return r;
×
890
                                if (r == 0)
5✔
891
                                        continue;
×
892

893
                                canonical = dns_resource_record_ref(zz);
5✔
894
                                break;
5✔
895
                        }
896

897
                        if (canonical)
5✔
898
                                break;
899
                }
900

901
                /* Is there are successful A/AAAA lookup for this SRV RR? If not, don't add it */
902
                if (!canonical)
5✔
903
                        return 0;
904
        }
905

906
        r = sd_bus_message_open_container(reply, 'r', "qqqsa(iiay)s");
6✔
907
        if (r < 0)
6✔
908
                return r;
909

910
        r = dns_name_normalize(rr->srv.name, 0, &normalized);
6✔
911
        if (r < 0)
6✔
912
                return r;
913

914
        r = sd_bus_message_append(
12✔
915
                        reply,
916
                        "qqqs",
917
                        rr->srv.priority, rr->srv.weight, rr->srv.port, normalized);
6✔
918
        if (r < 0)
6✔
919
                return r;
920

921
        r = sd_bus_message_open_container(reply, 'a', "(iiay)");
6✔
922
        if (r < 0)
6✔
923
                return r;
924

925
        if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
6✔
926
                LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
10✔
927
                        DnsResourceRecord *zz;
5✔
928
                        DnsQuestion *question;
5✔
929
                        int ifindex;
5✔
930

931
                        if (aux->state != DNS_TRANSACTION_SUCCESS)
5✔
932
                                continue;
×
933
                        if (aux->auxiliary_result != 0)
5✔
934
                                continue;
×
935

936
                        question = dns_query_question_for_protocol(aux, aux->answer_protocol);
5✔
937

938
                        r = dns_name_equal(dns_question_first_name(question), rr->srv.name);
5✔
939
                        if (r < 0)
5✔
940
                                return r;
941
                        if (r == 0)
5✔
942
                                continue;
×
943

944
                        DNS_ANSWER_FOREACH_IFINDEX(zz, ifindex, aux->answer) {
13✔
945

946
                                r = dns_question_matches_rr(question, zz, NULL);
8✔
947
                                if (r < 0)
8✔
948
                                        return r;
×
949
                                if (r == 0)
8✔
950
                                        continue;
×
951

952
                                r = append_address(reply, zz, ifindex);
8✔
953
                                if (r < 0)
8✔
954
                                        return r;
955
                        }
956
                }
957
        }
958

959
        r = sd_bus_message_close_container(reply);
6✔
960
        if (r < 0)
6✔
961
                return r;
962

963
        if (canonical) {
6✔
964
                normalized = mfree(normalized);
5✔
965

966
                r = dns_name_normalize(dns_resource_key_name(canonical->key), 0, &normalized);
5✔
967
                if (r < 0)
5✔
968
                        return r;
969
        }
970

971
        /* Note that above we appended the hostname as encoded in the
972
         * SRV, and here the canonical hostname this maps to. */
973
        r = sd_bus_message_append(reply, "s", normalized);
6✔
974
        if (r < 0)
6✔
975
                return r;
976

977
        r = sd_bus_message_close_container(reply);
6✔
978
        if (r < 0)
6✔
979
                return r;
×
980

981
        return 1;
982
}
983

984
static int append_txt(sd_bus_message *reply, DnsResourceRecord *rr) {
9✔
985
        int r;
9✔
986

987
        assert(reply);
9✔
988
        assert(rr);
9✔
989
        assert(rr->key);
9✔
990

991
        if (rr->key->type != DNS_TYPE_TXT)
9✔
992
                return 0;
993

994
        LIST_FOREACH(items, i, rr->txt.items) {
6✔
995

996
                if (i->length <= 0)
3✔
997
                        continue;
×
998

999
                r = sd_bus_message_append_array(reply, 'y', i->data, i->length);
3✔
1000
                if (r < 0)
3✔
1001
                        return r;
1002
        }
1003

1004
        return 1;
1005
}
1006

1007
static void resolve_service_all_complete(DnsQuery *query) {
13✔
1008
        _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *canonical = NULL;
×
1009
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
13✔
1010
        _cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
13✔
1011
        _cleanup_(dns_query_freep) DnsQuery *q = query;
13✔
1012
        DnsQuestion *question;
13✔
1013
        DnsResourceRecord *rr;
13✔
1014
        unsigned added = 0;
13✔
1015
        int r;
13✔
1016

1017
        assert(q);
13✔
1018

1019
        if (q->block_all_complete > 0) {
13✔
1020
                TAKE_PTR(q);
3✔
1021
                return;
3✔
1022
        }
1023

1024
        if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
10✔
1025
                DnsQuery *bad = NULL;
9✔
1026
                bool have_success = false;
9✔
1027

1028
                LIST_FOREACH(auxiliary_queries, aux, q->auxiliary_queries) {
15✔
1029

1030
                        switch (aux->state) {
9✔
1031

1032
                        case DNS_TRANSACTION_PENDING:
3✔
1033
                                /* If an auxiliary query is still pending, let's wait */
1034
                                TAKE_PTR(q);
3✔
1035
                                return;
3✔
1036

1037
                        case DNS_TRANSACTION_SUCCESS:
5✔
1038
                                if (aux->auxiliary_result == 0)
5✔
1039
                                        have_success = true;
1040
                                else
1041
                                        bad = aux;
×
1042
                                break;
1043

1044
                        default:
1045
                                bad = aux;
1046
                        }
1047
                }
1048

1049
                if (!have_success) {
6✔
1050
                        /* We can only return one error, hence pick the last error we encountered */
1051

1052
                        assert(bad);
1✔
1053

1054
                        if (bad->state == DNS_TRANSACTION_SUCCESS) {
1✔
1055
                                assert(bad->auxiliary_result != 0);
×
1056

1057
                                if (bad->auxiliary_result == -ELOOP) {
×
1058
                                        r = reply_method_errorf(q, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(bad));
×
1059
                                        goto finish;
×
1060
                                }
1061

1062
                                assert(bad->auxiliary_result < 0);
×
1063
                                r = bad->auxiliary_result;
×
1064
                                goto finish;
×
1065
                        }
1066

1067
                        r = reply_query_state(bad);
1✔
1068
                        goto finish;
1✔
1069
                }
1070
        }
1071

1072
        r = sd_bus_message_new_method_return(q->bus_request, &reply);
6✔
1073
        if (r < 0)
6✔
1074
                goto finish;
×
1075

1076
        r = sd_bus_message_open_container(reply, 'a', "(qqqsa(iiay)s)");
6✔
1077
        if (r < 0)
6✔
1078
                goto finish;
×
1079

1080
        question = dns_query_question_for_protocol(q, q->answer_protocol);
6✔
1081

1082
        DNS_ANSWER_FOREACH(rr, q->answer) {
29✔
1083
                r = dns_question_matches_rr(question, rr, NULL);
23✔
1084
                if (r < 0)
23✔
1085
                        goto finish;
×
1086
                if (r == 0)
23✔
1087
                        continue;
14✔
1088

1089
                r = append_srv(q, reply, rr);
9✔
1090
                if (r < 0)
9✔
1091
                        goto finish;
×
1092
                if (r == 0) /* not an SRV record */
9✔
1093
                        continue;
3✔
1094

1095
                if (!canonical)
6✔
1096
                        canonical = dns_resource_record_ref(rr);
6✔
1097

1098
                added++;
6✔
1099
        }
1100

1101
        if (added <= 0) {
6✔
1102
                r = reply_method_errorf(q, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
×
1103
                goto finish;
×
1104
        }
1105

1106
        r = sd_bus_message_close_container(reply);
6✔
1107
        if (r < 0)
6✔
1108
                goto finish;
×
1109

1110
        r = sd_bus_message_open_container(reply, 'a', "ay");
6✔
1111
        if (r < 0)
6✔
1112
                goto finish;
×
1113

1114
        DNS_ANSWER_FOREACH(rr, q->answer) {
29✔
1115
                r = dns_question_matches_rr(question, rr, NULL);
23✔
1116
                if (r < 0)
23✔
1117
                        goto finish;
×
1118
                if (r == 0)
23✔
1119
                        continue;
14✔
1120

1121
                r = append_txt(reply, rr);
9✔
1122
                if (r < 0)
9✔
1123
                        goto finish;
×
1124
        }
1125

1126
        r = sd_bus_message_close_container(reply);
6✔
1127
        if (r < 0)
6✔
1128
                goto finish;
×
1129

1130
        assert(canonical);
6✔
1131
        r = dns_service_split(dns_resource_key_name(canonical->key), &name, &type, &domain);
6✔
1132
        if (r < 0)
6✔
1133
                goto finish;
×
1134

1135
        if (isempty(type)) {
6✔
1136
                r = reply_method_errorf(q, BUS_ERROR_INCONSISTENT_SERVICE_RECORDS, "'%s' does not provide a consistent set of service resource records", dns_query_string(q));
×
1137
                goto finish;
×
1138
        }
1139

1140
        r = sd_bus_message_append(
6✔
1141
                        reply,
1142
                        "ssst",
1143
                        name, type, domain,
1144
                        dns_query_reply_flags_make(q));
1145
        if (r < 0)
6✔
1146
                goto finish;
×
1147

1148
        q->bus_request = sd_bus_message_unref(q->bus_request);
6✔
1149
        r = sd_bus_send(q->manager->bus, reply, NULL);
6✔
1150

1151
finish:
7✔
1152
        if (r < 0) {
7✔
1153
                log_error_errno(r, "Failed to send service reply: %m");
×
1154
                (void) reply_method_errnof(q, r, NULL);
×
1155
        }
1156
}
1157

1158
static void resolve_service_hostname_complete(DnsQuery *q) {
6✔
1159
        int r;
6✔
1160

1161
        assert(q);
6✔
1162
        assert(q->auxiliary_for);
6✔
1163

1164
        if (q->state != DNS_TRANSACTION_SUCCESS) {
6✔
1165
                resolve_service_all_complete(q->auxiliary_for);
1✔
1166
                return;
1✔
1167
        }
1168

1169
        r = dns_query_process_cname_many(q);
5✔
1170
        if (r == DNS_QUERY_CNAME) /* This was a cname, and the query was restarted. */
5✔
1171
                return;
1172

1173
        /* This auxiliary lookup is finished or failed, let's see if all are finished now. */
1174
        q->auxiliary_result = r < 0 ? r : 0;
5✔
1175
        resolve_service_all_complete(q->auxiliary_for);
5✔
1176
}
1177

1178
static int resolve_service_hostname(DnsQuery *q, DnsResourceRecord *rr, int ifindex) {
6✔
1179
        _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
6✔
1180
        _cleanup_(dns_query_freep) DnsQuery *aux = NULL;
6✔
1181
        int r;
6✔
1182

1183
        assert(q);
6✔
1184
        assert(rr);
6✔
1185
        assert(rr->key);
6✔
1186
        assert(rr->key->type == DNS_TYPE_SRV);
6✔
1187

1188
        /* OK, we found an SRV record for the service. Let's resolve
1189
         * the hostname included in it */
1190

1191
        r = dns_question_new_address(&question, q->request_family, rr->srv.name, false);
6✔
1192
        if (r < 0)
6✔
1193
                return r;
1194

1195
        r = dns_query_new(q->manager, &aux, question, question, NULL, ifindex, q->flags|SD_RESOLVED_NO_SEARCH);
6✔
1196
        if (r == -ENOANO)
6✔
1197
                return reply_method_errorf(q, BUS_ERROR_DNS_REFUSED, "DNS query type refused.");
×
1198
        if (r < 0)
6✔
1199
                return r;
1200

1201
        aux->request_family = q->request_family;
6✔
1202
        aux->complete = resolve_service_hostname_complete;
6✔
1203

1204
        r = dns_query_make_auxiliary(aux, q);
6✔
1205
        if (r == -EAGAIN)
6✔
1206
                /* Too many auxiliary lookups? If so, don't complain,
1207
                 * let's just not add this one, we already have more
1208
                 * than enough */
1209
                return 0;
1210
        if (r < 0)
6✔
1211
                return r;
1212

1213
        /* Note that auxiliary queries do not track the original bus
1214
         * client, only the primary request does that. */
1215

1216
        r = dns_query_go(aux);
6✔
1217
        if (r < 0)
6✔
1218
                return r;
1219

1220
        TAKE_PTR(aux);
6✔
1221
        return 1;
6✔
1222
}
1223

1224
static void bus_method_resolve_service_complete(DnsQuery *query) {
7✔
1225
        _cleanup_(dns_query_freep) DnsQuery *q = query;
7✔
1226
        bool has_root_domain = false;
7✔
1227
        DnsResourceRecord *rr;
7✔
1228
        DnsQuestion *question;
7✔
1229
        unsigned found = 0;
7✔
1230
        int ifindex, r;
7✔
1231

1232
        assert(q);
7✔
1233

1234
        if (q->state != DNS_TRANSACTION_SUCCESS) {
7✔
1235
                r = reply_query_state(q);
×
1236
                goto finish;
×
1237
        }
1238

1239
        r = dns_query_process_cname_many(q);
7✔
1240
        if (r == -ELOOP) {
7✔
1241
                r = reply_method_errorf(q, BUS_ERROR_CNAME_LOOP, "CNAME loop detected, or CNAME resolving disabled on '%s'", dns_query_string(q));
×
1242
                goto finish;
×
1243
        }
1244
        if (r < 0)
7✔
1245
                goto finish;
×
1246
        if (r == DNS_QUERY_CNAME) {
7✔
1247
                /* This was a cname, and the query was restarted. */
1248
                TAKE_PTR(q);
×
1249
                return;
×
1250
        }
1251

1252
        question = dns_query_question_for_protocol(q, q->answer_protocol);
7✔
1253

1254
        DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, q->answer) {
33✔
1255
                r = dns_question_matches_rr(question, rr, NULL);
26✔
1256
                if (r < 0)
26✔
1257
                        goto finish;
×
1258
                if (r == 0)
26✔
1259
                        continue;
16✔
1260

1261
                if (rr->key->type != DNS_TYPE_SRV)
10✔
1262
                        continue;
3✔
1263

1264
                if (dns_name_is_root(rr->srv.name)) {
7✔
1265
                        has_root_domain = true;
×
1266
                        continue;
×
1267
                }
1268

1269
                if ((q->flags & SD_RESOLVED_NO_ADDRESS) == 0) {
7✔
1270
                        q->block_all_complete++;
6✔
1271
                        r = resolve_service_hostname(q, rr, ifindex);
6✔
1272
                        q->block_all_complete--;
6✔
1273

1274
                        if (r < 0)
6✔
1275
                                goto finish;
×
1276
                }
1277

1278
                found++;
7✔
1279
        }
1280

1281
        if (has_root_domain && found <= 0) {
7✔
1282
                /* If there's exactly one SRV RR and it uses the root domain as hostname, then the service is
1283
                 * explicitly not offered on the domain. Report this as a recognizable error. See RFC 2782,
1284
                 * Section "Usage Rules". */
1285
                r = reply_method_errorf(q, BUS_ERROR_NO_SUCH_SERVICE, "'%s' does not provide the requested service", dns_query_string(q));
×
1286
                goto finish;
×
1287
        }
1288

1289
        if (found <= 0) {
7✔
1290
                r = reply_method_errorf(q, BUS_ERROR_NO_SUCH_RR, "'%s' does not have any RR of the requested type", dns_query_string(q));
×
1291
                goto finish;
×
1292
        }
1293

1294
        /* Maybe we are already finished? check now... */
1295
        resolve_service_all_complete(TAKE_PTR(q));
7✔
1296
        return;
1297

1298
finish:
×
1299
        if (r < 0) {
×
1300
                log_error_errno(r, "Failed to send service reply: %m");
×
1301
                (void) reply_method_errnof(q, r, NULL);
×
1302
        }
1303
}
1304

1305
static int bus_method_resolve_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9✔
1306
        _cleanup_(dns_question_unrefp) DnsQuestion *question_idna = NULL, *question_utf8 = NULL;
9✔
1307
        _cleanup_(dns_query_freep) DnsQuery *q = NULL;
9✔
1308
        const char *name, *type, *domain;
9✔
1309
        Manager *m = ASSERT_PTR(userdata);
9✔
1310
        int family, ifindex;
9✔
1311
        uint64_t flags;
9✔
1312
        int r;
9✔
1313

1314
        assert(message);
9✔
1315

1316
        assert_cc(sizeof(int) == sizeof(int32_t));
9✔
1317

1318
        r = sd_bus_message_read(message, "isssit", &ifindex, &name, &type, &domain, &family, &flags);
9✔
1319
        if (r < 0)
9✔
1320
                return r;
1321

1322
        if (ifindex < 0)
9✔
1323
                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface index");
×
1324

1325
        if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
9✔
1326
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
×
1327

1328
        if (isempty(name))
9✔
1329
                name = NULL;
9✔
1330
        else if (!dns_service_name_is_valid(name))
×
1331
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service name '%s'", name);
×
1332

1333
        if (isempty(type))
9✔
1334
                type = NULL;
×
1335
        else if (!dns_srv_type_is_valid(type))
9✔
1336
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SRV service type '%s'", type);
×
1337

1338
        r = dns_name_is_valid(domain);
9✔
1339
        if (r < 0)
9✔
1340
                return r;
1341
        if (r == 0)
9✔
1342
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid domain '%s'", domain);
×
1343

1344
        if (name && !type)
9✔
1345
                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Service name cannot be specified without service type.");
×
1346

1347
        if (validate_and_mangle_query_flags(m, &flags, name, SD_RESOLVED_NO_TXT|SD_RESOLVED_NO_ADDRESS) < 0)
9✔
1348
                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
×
1349

1350
        /* Refuse the method if SRV is filtered. */
1351
        if (set_contains(m->refuse_record_types, INT_TO_PTR(DNS_TYPE_SRV)))
9✔
1352
                return sd_bus_error_set(error, BUS_ERROR_DNS_REFUSED, "DNS query type refused.");
2✔
1353

1354
        r = dns_question_new_service(&question_utf8, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), false);
7✔
1355
        if (r < 0)
7✔
1356
                return r;
1357

1358
        r = dns_question_new_service(&question_idna, name, type, domain, !(flags & SD_RESOLVED_NO_TXT), true);
7✔
1359
        if (r < 0)
7✔
1360
                return r;
1361

1362
        bus_client_log(message, "service resolution");
7✔
1363

1364
        r = dns_query_new_for_bus(m, &q, question_utf8, question_idna, NULL, ifindex, flags|SD_RESOLVED_NO_SEARCH, error);
7✔
1365
        if (r < 0)
7✔
1366
                return r;
1367

1368
        q->bus_request = sd_bus_message_ref(message);
7✔
1369
        q->request_family = family;
7✔
1370
        q->complete = bus_method_resolve_service_complete;
7✔
1371

1372
        r = dns_query_bus_track(q, message);
7✔
1373
        if (r < 0)
7✔
1374
                return r;
1375

1376
        r = dns_query_go(q);
7✔
1377
        if (r < 0)
7✔
1378
                return r;
1379

1380
        TAKE_PTR(q);
7✔
1381
        return 1;
7✔
1382
}
1383

1384
int bus_dns_server_append(
9,841✔
1385
                sd_bus_message *reply,
1386
                DnsServer *s,
1387
                bool with_ifindex, /* include "ifindex" field */
1388
                bool extended) {   /* also include port number and server name */
1389
        int r;
9,841✔
1390

1391
        assert(reply);
9,841✔
1392

1393
        if (!s) {
9,841✔
1394
                if (with_ifindex) {
207✔
1395
                        if (extended)
55✔
1396
                                return sd_bus_message_append(reply, "(iiayqs)", 0, AF_UNSPEC, 0, 0, NULL);
3✔
1397
                        else
1398
                                return sd_bus_message_append(reply, "(iiay)", 0, AF_UNSPEC, 0);
52✔
1399
                } else {
1400
                        if (extended)
152✔
1401
                                return sd_bus_message_append(reply, "(iayqs)", AF_UNSPEC, 0, 0, NULL);
76✔
1402
                        else
1403
                                return sd_bus_message_append(reply, "(iay)", AF_UNSPEC, 0);
76✔
1404
                }
1405
        }
1406

1407
        r = sd_bus_message_open_container(
19,268✔
1408
                        reply,
1409
                        'r',
1410
                        with_ifindex ? (extended ? "iiayqs" : "iiay") :
9,456✔
1411
                                       (extended ? "iayqs" : "iay"));
178✔
1412
        if (r < 0)
9,634✔
1413
                return r;
1414

1415
        if (with_ifindex) {
9,634✔
1416
                r = sd_bus_message_append(reply, "i", dns_server_ifindex(s));
9,456✔
1417
                if (r < 0)
9,456✔
1418
                        return r;
1419
        }
1420

1421
        r = sd_bus_message_append(reply, "i", s->family);
9,634✔
1422
        if (r < 0)
9,634✔
1423
                return r;
1424

1425
        r = sd_bus_message_append_array(reply, 'y', &s->address, FAMILY_ADDRESS_SIZE(s->family));
9,634✔
1426
        if (r < 0)
9,634✔
1427
                return r;
1428

1429
        if (extended) {
9,634✔
1430
                r = sd_bus_message_append(reply, "q", s->port);
95✔
1431
                if (r < 0)
95✔
1432
                        return r;
1433

1434
                r = sd_bus_message_append(reply, "s", s->server_name);
95✔
1435
                if (r < 0)
95✔
1436
                        return r;
1437
        }
1438

1439
        return sd_bus_message_close_container(reply);
9,634✔
1440
}
1441

1442
static int bus_property_get_dns_servers_internal(
7,559✔
1443
                sd_bus *bus,
1444
                const char *path,
1445
                const char *interface,
1446
                const char *property,
1447
                sd_bus_message *reply,
1448
                void *userdata,
1449
                sd_bus_error *error,
1450
                bool extended) {
1451

1452
        Manager *m = ASSERT_PTR(userdata);
7,559✔
1453
        Link *l;
7,559✔
1454
        int r;
7,559✔
1455

1456
        assert(reply);
7,559✔
1457

1458
        r = sd_bus_message_open_container(reply, 'a', extended ? "(iiayqs)" : "(iiay)");
15,115✔
1459
        if (r < 0)
7,559✔
1460
                return r;
7,559✔
1461

1462
        LIST_FOREACH(servers, s, m->dns_servers) {
7,603✔
1463
                r = bus_dns_server_append(reply, s, true, extended);
44✔
1464
                if (r < 0)
44✔
1465
                        return r;
1466
        }
1467

1468
        HASHMAP_FOREACH(l, m->links)
56,923✔
1469
                LIST_FOREACH(servers, s, l->dns_servers) {
49,980✔
1470
                        r = bus_dns_server_append(reply, s, true, extended);
616✔
1471
                        if (r < 0)
616✔
1472
                                return r;
×
1473
                }
1474

1475
        return sd_bus_message_close_container(reply);
7,559✔
1476
}
1477

1478
static int bus_property_get_dns_servers(
7,556✔
1479
                sd_bus *bus,
1480
                const char *path,
1481
                const char *interface,
1482
                const char *property,
1483
                sd_bus_message *reply,
1484
                void *userdata,
1485
                sd_bus_error *error) {
1486
        return bus_property_get_dns_servers_internal(bus, path, interface, property, reply, userdata, error, false);
7,556✔
1487
}
1488

1489
static int bus_property_get_dns_servers_ex(
3✔
1490
                sd_bus *bus,
1491
                const char *path,
1492
                const char *interface,
1493
                const char *property,
1494
                sd_bus_message *reply,
1495
                void *userdata,
1496
                sd_bus_error *error) {
1497
        return bus_property_get_dns_servers_internal(bus, path, interface, property, reply, userdata, error, true);
3✔
1498
}
1499

1500
static int bus_property_get_fallback_dns_servers_internal(
6✔
1501
                sd_bus *bus,
1502
                const char *path,
1503
                const char *interface,
1504
                const char *property,
1505
                sd_bus_message *reply,
1506
                void *userdata,
1507
                sd_bus_error *error,
1508
                bool extended) {
1509

1510
        DnsServer **f = ASSERT_PTR(userdata);
6✔
1511
        int r;
6✔
1512

1513
        assert(reply);
6✔
1514

1515
        r = sd_bus_message_open_container(reply, 'a', extended ? "(iiayqs)" : "(iiay)");
9✔
1516
        if (r < 0)
6✔
1517
                return r;
1518

1519
        LIST_FOREACH(servers, s, *f) {
6✔
1520
                r = bus_dns_server_append(reply, s, true, extended);
×
1521
                if (r < 0)
×
1522
                        return r;
1523
        }
1524

1525
        return sd_bus_message_close_container(reply);
6✔
1526
}
1527

1528
static int bus_property_get_fallback_dns_servers(
3✔
1529
                sd_bus *bus,
1530
                const char *path,
1531
                const char *interface,
1532
                const char *property,
1533
                sd_bus_message *reply,
1534
                void *userdata,
1535
                sd_bus_error *error) {
1536
        return bus_property_get_fallback_dns_servers_internal(bus, path, interface, property, reply, userdata, error, false);
3✔
1537
}
1538

1539
static int bus_property_get_fallback_dns_servers_ex(
3✔
1540
                sd_bus *bus,
1541
                const char *path,
1542
                const char *interface,
1543
                const char *property,
1544
                sd_bus_message *reply,
1545
                void *userdata,
1546
                sd_bus_error *error) {
1547
        return bus_property_get_fallback_dns_servers_internal(bus, path, interface, property, reply, userdata, error, true);
3✔
1548
}
1549

1550
static int bus_property_get_current_dns_server_internal(
8,851✔
1551
                sd_bus *bus,
1552
                const char *path,
1553
                const char *interface,
1554
                const char *property,
1555
                sd_bus_message *reply,
1556
                void *userdata,
1557
                sd_bus_error *error,
1558
                bool extended) {
1559

1560
        DnsServer *s;
8,851✔
1561

1562
        assert(reply);
8,851✔
1563
        assert(userdata);
8,851✔
1564

1565
        s = *(DnsServer **) userdata;
8,851✔
1566

1567
        return bus_dns_server_append(reply, s, true, extended);
8,851✔
1568
}
1569

1570
static int bus_property_get_current_dns_server(
8,848✔
1571
                sd_bus *bus,
1572
                const char *path,
1573
                const char *interface,
1574
                const char *property,
1575
                sd_bus_message *reply,
1576
                void *userdata,
1577
                sd_bus_error *error) {
1578
        return bus_property_get_current_dns_server_internal(bus, path, interface, property, reply, userdata, error, false);
8,848✔
1579
}
1580

1581
static int bus_property_get_current_dns_server_ex(
3✔
1582
                sd_bus *bus,
1583
                const char *path,
1584
                const char *interface,
1585
                const char *property,
1586
                sd_bus_message *reply,
1587
                void *userdata,
1588
                sd_bus_error *error) {
1589
        return bus_property_get_current_dns_server_internal(bus, path, interface, property, reply, userdata, error, true);
3✔
1590
}
1591

1592
static int bus_property_get_domains(
3✔
1593
                sd_bus *bus,
1594
                const char *path,
1595
                const char *interface,
1596
                const char *property,
1597
                sd_bus_message *reply,
1598
                void *userdata,
1599
                sd_bus_error *error) {
1600

1601
        Manager *m = ASSERT_PTR(userdata);
3✔
1602
        Link *l;
3✔
1603
        int r;
3✔
1604

1605
        assert(reply);
3✔
1606

1607
        r = sd_bus_message_open_container(reply, 'a', "(isb)");
3✔
1608
        if (r < 0)
3✔
1609
                return r;
3✔
1610

1611
        LIST_FOREACH(domains, d, m->search_domains) {
3✔
1612
                r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only);
×
1613
                if (r < 0)
×
1614
                        return r;
1615
        }
1616

1617
        HASHMAP_FOREACH(l, m->links) {
12✔
1618
                LIST_FOREACH(domains, d, l->search_domains) {
9✔
1619
                        r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only);
×
1620
                        if (r < 0)
×
1621
                                return r;
×
1622
                }
1623
        }
1624

1625
        return sd_bus_message_close_container(reply);
3✔
1626
}
1627

1628
static int bus_property_get_transaction_statistics(
3✔
1629
                sd_bus *bus,
1630
                const char *path,
1631
                const char *interface,
1632
                const char *property,
1633
                sd_bus_message *reply,
1634
                void *userdata,
1635
                sd_bus_error *error) {
1636

1637
        Manager *m = ASSERT_PTR(userdata);
3✔
1638

1639
        assert(reply);
3✔
1640

1641
        return sd_bus_message_append(reply, "(tt)",
9✔
1642
                                     (uint64_t) hashmap_size(m->dns_transactions),
3✔
1643
                                     (uint64_t) m->n_transactions_total);
3✔
1644
}
1645

1646
static int bus_property_get_cache_statistics(
3✔
1647
                sd_bus *bus,
1648
                const char *path,
1649
                const char *interface,
1650
                const char *property,
1651
                sd_bus_message *reply,
1652
                void *userdata,
1653
                sd_bus_error *error) {
1654

1655
        uint64_t size = 0, hit = 0, miss = 0;
3✔
1656
        Manager *m = ASSERT_PTR(userdata);
3✔
1657

1658
        assert(reply);
3✔
1659

1660
        LIST_FOREACH(scopes, s, m->dns_scopes) {
9✔
1661
                size += dns_cache_size(&s->cache);
6✔
1662
                hit += s->cache.n_hit;
6✔
1663
                miss += s->cache.n_miss;
6✔
1664
        }
1665

1666
        return sd_bus_message_append(reply, "(ttt)", size, hit, miss);
3✔
1667
}
1668

1669
static int bus_property_get_dnssec_statistics(
3✔
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 = ASSERT_PTR(userdata);
3✔
1679

1680
        assert(reply);
3✔
1681

1682
        return sd_bus_message_append(reply, "(tttt)",
6✔
1683
                                     (uint64_t) m->n_dnssec_verdict[DNSSEC_SECURE],
3✔
1684
                                     (uint64_t) m->n_dnssec_verdict[DNSSEC_INSECURE],
3✔
1685
                                     (uint64_t) m->n_dnssec_verdict[DNSSEC_BOGUS],
3✔
1686
                                     (uint64_t) m->n_dnssec_verdict[DNSSEC_INDETERMINATE]);
3✔
1687
}
1688

1689
static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode);
85✔
1690
static BUS_DEFINE_PROPERTY_GET(bus_property_get_dnssec_supported, "b", Manager, manager_dnssec_supported);
3✔
1691
static BUS_DEFINE_PROPERTY_GET2(bus_property_get_dnssec_mode, "s", Manager, manager_get_dnssec_mode, dnssec_mode_to_string);
3✔
1692
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);
3✔
1693

1694
static int bus_property_get_resolv_conf_mode(
3✔
1695
                sd_bus *bus,
1696
                const char *path,
1697
                const char *interface,
1698
                const char *property,
1699
                sd_bus_message *reply,
1700
                void *userdata,
1701
                sd_bus_error *error) {
1702

1703
        int r;
3✔
1704

1705
        assert(reply);
3✔
1706

1707
        r = resolv_conf_mode();
3✔
1708
        if (r < 0) {
3✔
1709
                log_warning_errno(r, "Failed to test /etc/resolv.conf mode, ignoring: %m");
×
1710
                return sd_bus_message_append(reply, "s", NULL);
×
1711
        }
1712

1713
        return sd_bus_message_append(reply, "s", resolv_conf_mode_to_string(r));
3✔
1714
}
1715

1716
static int bus_method_reset_statistics(sd_bus_message *message, void *userdata, sd_bus_error *error) {
×
1717
        Manager *m = ASSERT_PTR(userdata);
×
1718

1719
        assert(message);
×
1720

1721
        bus_client_log(message, "statistics reset");
×
1722

1723
        dns_manager_reset_statistics(m);
×
1724

1725
        return sd_bus_reply_method_return(message, NULL);
×
1726
}
1727

1728
static int get_any_link(Manager *m, int ifindex, Link **ret, sd_bus_error *error) {
71✔
1729
        Link *l;
71✔
1730

1731
        assert(m);
71✔
1732
        assert(ret);
71✔
1733

1734
        l = hashmap_get(m->links, INT_TO_PTR(ifindex));
71✔
1735
        if (!l)
71✔
1736
                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex);
×
1737

1738
        *ret = l;
71✔
1739
        return 0;
71✔
1740
}
1741

1742
static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
71✔
1743
        int ifindex, r;
71✔
1744
        Link *l = NULL;  /* avoid false maybe-uninitialized warning */
71✔
1745

1746
        assert(m);
71✔
1747
        assert(message);
71✔
1748
        assert(handler);
71✔
1749

1750
        r = bus_message_read_ifindex(message, error, &ifindex);
71✔
1751
        if (r < 0)
71✔
1752
                return r;
71✔
1753

1754
        r = get_any_link(m, ifindex, &l, error);
71✔
1755
        if (r < 0)
71✔
1756
                return r;
1757

1758
        return handler(message, l, error);
71✔
1759
}
1760

1761
static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
×
1762
        return call_link_method(userdata, message, bus_link_method_set_dns_servers, error);
×
1763
}
1764

1765
static int bus_method_set_link_dns_servers_ex(sd_bus_message *message, void *userdata, sd_bus_error *error) {
18✔
1766
        return call_link_method(userdata, message, bus_link_method_set_dns_servers_ex, error);
18✔
1767
}
1768

1769
static int bus_method_set_link_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
15✔
1770
        return call_link_method(userdata, message, bus_link_method_set_domains, error);
15✔
1771
}
1772

1773
static int bus_method_set_link_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2✔
1774
        return call_link_method(userdata, message, bus_link_method_set_default_route, error);
2✔
1775
}
1776

1777
static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
10✔
1778
        return call_link_method(userdata, message, bus_link_method_set_llmnr, error);
10✔
1779
}
1780

1781
static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
10✔
1782
        return call_link_method(userdata, message, bus_link_method_set_mdns, error);
10✔
1783
}
1784

1785
static int bus_method_set_link_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
×
1786
        return call_link_method(userdata, message, bus_link_method_set_dns_over_tls, error);
×
1787
}
1788

1789
static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1✔
1790
        return call_link_method(userdata, message, bus_link_method_set_dnssec, error);
1✔
1791
}
1792

1793
static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
×
1794
        return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error);
×
1795
}
1796

1797
static int bus_method_revert_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
15✔
1798
        return call_link_method(userdata, message, bus_link_method_revert, error);
15✔
1799
}
1800

1801
static int bus_method_get_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
×
1802
        _cleanup_free_ char *p = NULL;
×
1803
        Manager *m = ASSERT_PTR(userdata);
×
1804
        int r, ifindex;
×
1805
        Link *l = NULL;  /* avoid false maybe-uninitialized warning */
×
1806

1807
        assert(message);
×
1808

1809
        r = bus_message_read_ifindex(message, error, &ifindex);
×
1810
        if (r < 0)
×
1811
                return r;
1812

1813
        r = get_any_link(m, ifindex, &l, error);
×
1814
        if (r < 0)
×
1815
                return r;
1816

1817
        p = link_bus_path(l);
×
1818
        if (!p)
×
1819
                return -ENOMEM;
1820

1821
        return sd_bus_reply_method_return(message, "o", p);
×
1822
}
1823

1824
static int bus_method_flush_caches(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1✔
1825
        Manager *m = ASSERT_PTR(userdata);
1✔
1826

1827
        assert(message);
1✔
1828

1829
        bus_client_log(message, "cache flush");
1✔
1830

1831
        manager_flush_caches(m, LOG_INFO);
1✔
1832

1833
        return sd_bus_reply_method_return(message, NULL);
1✔
1834
}
1835

1836
static int bus_method_reset_server_features(sd_bus_message *message, void *userdata, sd_bus_error *error) {
×
1837
        Manager *m = ASSERT_PTR(userdata);
×
1838

1839
        assert(message);
×
1840

1841
        bus_client_log(message, "server feature reset");
×
1842

1843
        (void) dns_stream_disconnect_all(m);
×
1844
        manager_reset_server_features(m);
×
1845

1846
        return sd_bus_reply_method_return(message, NULL);
×
1847
}
1848

1849
static int dnssd_service_on_bus_track(sd_bus_track *t, void *userdata) {
×
1850
        DnssdService *s = ASSERT_PTR(userdata);
×
1851

1852
        assert(t);
×
1853

1854
        log_debug("Client of active request vanished, destroying DNS-SD service.");
×
1855
        dnssd_service_free(s);
×
1856

1857
        return 0;
×
1858
}
1859

1860
static int bus_method_register_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
×
1861
        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
×
1862
        _cleanup_(dnssd_service_freep) DnssdService *service = NULL;
×
1863
        _cleanup_(sd_bus_track_unrefp) sd_bus_track *bus_track = NULL;
×
1864
        const char *id, *name_template, *type;
×
1865
        _cleanup_free_ char *path = NULL;
×
1866
        DnssdService *s = NULL;
×
1867
        Manager *m = ASSERT_PTR(userdata);
×
1868
        uid_t euid;
×
1869
        int r;
×
1870

1871
        assert(message);
×
1872

1873
        if (m->mdns_support != RESOLVE_SUPPORT_YES)
×
1874
                return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Support for MulticastDNS is disabled");
×
1875

1876
        service = new0(DnssdService, 1);
×
1877
        if (!service)
×
1878
                return log_oom();
×
1879

1880
        r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
×
1881
        if (r < 0)
×
1882
                return r;
1883

1884
        r = sd_bus_creds_get_euid(creds, &euid);
×
1885
        if (r < 0)
×
1886
                return r;
1887
        service->originator = euid;
×
1888
        service->config_source = RESOLVE_CONFIG_SOURCE_DBUS;
×
1889

1890
        r = sd_bus_message_read(message, "sssqqq", &id, &name_template, &type,
×
1891
                                &service->port, &service->priority,
1892
                                &service->weight);
1893
        if (r < 0)
×
1894
                return r;
1895

1896
        if (!filename_part_is_valid(id))
×
1897
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DNS-SD service identifier '%s' is invalid", id);
×
1898

1899
        if (!dnssd_srv_type_is_valid(type))
×
1900
                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DNS-SD service type '%s' is invalid", type);
×
1901

1902
        s = hashmap_get(m->dnssd_services, id);
×
1903
        if (s)
×
1904
                return sd_bus_error_setf(error, BUS_ERROR_DNSSD_SERVICE_EXISTS, "DNS-SD service '%s' exists already", id);
×
1905

1906
        service->id = strdup(id);
×
1907
        if (!service->id)
×
1908
                return log_oom();
×
1909

1910
        service->name_template = strdup(name_template);
×
1911
        if (!service->name_template)
×
1912
                return log_oom();
×
1913

1914
        service->type = strdup(type);
×
1915
        if (!service->type)
×
1916
                return log_oom();
×
1917

1918
        r = dnssd_render_instance_name(m, service, NULL);
×
1919
        if (r < 0)
×
1920
                return r;
1921

1922
        r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "a{say}");
×
1923
        if (r < 0)
×
1924
                return r;
1925

1926
        while ((r = sd_bus_message_enter_container(message, SD_BUS_TYPE_ARRAY, "{say}")) > 0) {
×
1927
                _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
×
1928
                DnsTxtItem *last = NULL;
×
1929

1930
                txt_data = new0(DnssdTxtData, 1);
×
1931
                if (!txt_data)
×
1932
                        return log_oom();
×
1933

1934
                while ((r = sd_bus_message_enter_container(message, SD_BUS_TYPE_DICT_ENTRY, "say")) > 0) {
×
1935
                        const char *key;
×
1936
                        const void *value;
×
1937
                        size_t size;
×
1938
                        DnsTxtItem *i;
×
1939

1940
                        r = sd_bus_message_read(message, "s", &key);
×
1941
                        if (r < 0)
×
1942
                                return r;
×
1943

1944
                        if (isempty(key))
×
1945
                                return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Keys in DNS-SD TXT RRs can't be empty");
×
1946

1947
                        if (!ascii_is_valid(key))
×
1948
                                return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TXT key '%s' contains non-ASCII symbols", key);
×
1949

1950
                        r = sd_bus_message_read_array(message, 'y', &value, &size);
×
1951
                        if (r < 0)
×
1952
                                return r;
1953

1954
                        r = dnssd_txt_item_new_from_data(key, value, size, &i);
×
1955
                        if (r < 0)
×
1956
                                return r;
1957

1958
                        LIST_INSERT_AFTER(items, txt_data->txts, last, i);
×
1959
                        last = i;
×
1960

1961
                        r = sd_bus_message_exit_container(message);
×
1962
                        if (r < 0)
×
1963
                                return r;
1964

1965
                }
1966
                if (r < 0)
×
1967
                        return r;
1968

1969
                r = sd_bus_message_exit_container(message);
×
1970
                if (r < 0)
×
1971
                        return r;
1972

1973
                if (txt_data->txts) {
×
1974
                        LIST_PREPEND(items, service->txt_data_items, txt_data);
×
1975
                        txt_data = NULL;
×
1976
                }
1977
        }
1978
        if (r < 0)
×
1979
                return r;
1980

1981
        r = sd_bus_message_exit_container(message);
×
1982
        if (r < 0)
×
1983
                return r;
1984

1985
        if (!service->txt_data_items) {
×
1986
                _cleanup_(dnssd_txtdata_freep) DnssdTxtData *txt_data = NULL;
×
1987

1988
                txt_data = new0(DnssdTxtData, 1);
×
1989
                if (!txt_data)
×
1990
                        return log_oom();
×
1991

1992
                r = dns_txt_item_new_empty(&txt_data->txts);
×
1993
                if (r < 0)
×
1994
                        return r;
1995

1996
                LIST_PREPEND(items, service->txt_data_items, txt_data);
×
1997
                txt_data = NULL;
×
1998
        }
1999

2000
        r = sd_bus_path_encode("/org/freedesktop/resolve1/dnssd", service->id, &path);
×
2001
        if (r < 0)
×
2002
                return r;
2003

2004
        r = bus_verify_polkit_async(
×
2005
                        message,
2006
                        "org.freedesktop.resolve1.register-service",
2007
                        /* details= */ NULL,
2008
                        &m->polkit_registry,
2009
                        error);
2010
        if (r < 0)
×
2011
                return r;
2012
        if (r == 0)
×
2013
                return 1; /* Polkit will call us back */
2014

2015
        r = hashmap_ensure_put(&m->dnssd_services, &string_hash_ops, service->id, service);
×
2016
        if (r < 0)
×
2017
                return r;
2018

2019
        r = sd_bus_track_new(sd_bus_message_get_bus(message), &bus_track, dnssd_service_on_bus_track, service);
×
2020
        if (r < 0)
×
2021
                return r;
2022

2023
        r = sd_bus_track_add_sender(bus_track, message);
×
2024
        if (r < 0)
×
2025
                return r;
2026

2027
        service->manager = m;
×
2028

2029
        service = NULL;
×
2030

2031
        manager_refresh_rrs(m);
×
2032

2033
        return sd_bus_reply_method_return(message, "o", path);
×
2034
}
2035

2036
static int call_dnssd_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
×
2037
        _cleanup_free_ char *name = NULL;
×
2038
        DnssdService *s = NULL;
×
2039
        const char *path;
×
2040
        int r;
×
2041

2042
        assert(m);
×
2043
        assert(message);
×
2044
        assert(handler);
×
2045

2046
        r = sd_bus_message_read(message, "o", &path);
×
2047
        if (r < 0)
×
2048
                return r;
2049

2050
        r = sd_bus_path_decode(path, "/org/freedesktop/resolve1/dnssd", &name);
×
2051
        if (r == 0)
×
2052
                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DNSSD_SERVICE, "DNS-SD service with object path '%s' does not exist", path);
×
2053
        if (r < 0)
×
2054
                return r;
2055

2056
        s = hashmap_get(m->dnssd_services, name);
×
2057
        if (!s)
×
2058
                return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_DNSSD_SERVICE, "DNS-SD service '%s' not known", name);
×
2059

2060
        return handler(message, s, error);
×
2061
}
2062

2063
static int bus_method_unregister_service(sd_bus_message *message, void *userdata, sd_bus_error *error) {
×
2064
        Manager *m = ASSERT_PTR(userdata);
×
2065

2066
        assert(message);
×
2067

2068
        return call_dnssd_method(m, message, bus_dnssd_method_unregister, error);
×
2069
}
2070

2071
static const sd_bus_vtable resolve_vtable[] = {
2072
        SD_BUS_VTABLE_START(0),
2073
        SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2074
        SD_BUS_PROPERTY("LLMNR", "s", bus_property_get_resolve_support, offsetof(Manager, llmnr_support), 0),
2075
        SD_BUS_PROPERTY("MulticastDNS", "s", bus_property_get_resolve_support, offsetof(Manager, mdns_support), 0),
2076
        SD_BUS_PROPERTY("DNSOverTLS", "s", bus_property_get_dns_over_tls_mode, 0, 0),
2077
        SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2078
        SD_BUS_PROPERTY("DNSEx", "a(iiayqs)", bus_property_get_dns_servers_ex, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2079
        SD_BUS_PROPERTY("FallbackDNS", "a(iiay)", bus_property_get_fallback_dns_servers, offsetof(Manager, fallback_dns_servers), SD_BUS_VTABLE_PROPERTY_CONST),
2080
        SD_BUS_PROPERTY("FallbackDNSEx", "a(iiayqs)", bus_property_get_fallback_dns_servers_ex, offsetof(Manager, fallback_dns_servers), SD_BUS_VTABLE_PROPERTY_CONST),
2081
        SD_BUS_PROPERTY("CurrentDNSServer", "(iiay)", bus_property_get_current_dns_server, offsetof(Manager, current_dns_server), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2082
        SD_BUS_PROPERTY("CurrentDNSServerEx", "(iiayqs)", bus_property_get_current_dns_server_ex, offsetof(Manager, current_dns_server), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2083
        SD_BUS_PROPERTY("Domains", "a(isb)", bus_property_get_domains, 0, 0),
2084
        SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
2085
        SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
2086
        SD_BUS_PROPERTY("DNSSEC", "s", bus_property_get_dnssec_mode, 0, 0),
2087
        SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
2088
        SD_BUS_PROPERTY("DNSSECSupported", "b", bus_property_get_dnssec_supported, 0, 0),
2089
        SD_BUS_PROPERTY("DNSSECNegativeTrustAnchors", "as", bus_property_get_string_set, offsetof(Manager, trust_anchor.negative_by_name), 0),
2090
        SD_BUS_PROPERTY("DNSStubListener", "s", bus_property_get_dns_stub_listener_mode, offsetof(Manager, dns_stub_listener_mode), 0),
2091
        SD_BUS_PROPERTY("ResolvConfMode", "s", bus_property_get_resolv_conf_mode, 0, 0),
2092

2093
        SD_BUS_METHOD_WITH_ARGS("ResolveHostname",
2094
                                SD_BUS_ARGS("i", ifindex, "s", name, "i", family, "t", flags),
2095
                                SD_BUS_RESULT("a(iiay)", addresses, "s", canonical, "t", flags),
2096
                                bus_method_resolve_hostname,
2097
                                SD_BUS_VTABLE_UNPRIVILEGED),
2098
        SD_BUS_METHOD_WITH_ARGS("ResolveAddress",
2099
                                SD_BUS_ARGS("i",  ifindex, "i", family, "ay", address, "t", flags),
2100
                                SD_BUS_RESULT("a(is)", names, "t", flags),
2101
                                bus_method_resolve_address,
2102
                                SD_BUS_VTABLE_UNPRIVILEGED),
2103
        SD_BUS_METHOD_WITH_ARGS("ResolveRecord",
2104
                                SD_BUS_ARGS("i", ifindex, "s", name, "q", class, "q", type, "t", flags),
2105
                                SD_BUS_RESULT("a(iqqay)", records, "t", flags),
2106
                                bus_method_resolve_record,
2107
                                SD_BUS_VTABLE_UNPRIVILEGED),
2108
        SD_BUS_METHOD_WITH_ARGS("ResolveService",
2109
                                SD_BUS_ARGS("i", ifindex,
2110
                                            "s", name,
2111
                                            "s", type,
2112
                                            "s", domain,
2113
                                            "i", family,
2114
                                            "t", flags),
2115
                                SD_BUS_RESULT("a(qqqsa(iiay)s)", srv_data,
2116
                                              "aay", txt_data,
2117
                                              "s", canonical_name,
2118
                                              "s", canonical_type,
2119
                                              "s", canonical_domain,
2120
                                              "t", flags),
2121
                                bus_method_resolve_service,
2122
                                SD_BUS_VTABLE_UNPRIVILEGED),
2123
        SD_BUS_METHOD_WITH_ARGS("GetLink",
2124
                                SD_BUS_ARGS("i", ifindex),
2125
                                SD_BUS_RESULT("o", path),
2126
                                bus_method_get_link,
2127
                                SD_BUS_VTABLE_UNPRIVILEGED),
2128
        SD_BUS_METHOD_WITH_ARGS("SetLinkDNS",
2129
                                SD_BUS_ARGS("i", ifindex, "a(iay)", addresses),
2130
                                SD_BUS_NO_RESULT,
2131
                                bus_method_set_link_dns_servers,
2132
                                SD_BUS_VTABLE_UNPRIVILEGED),
2133
        SD_BUS_METHOD_WITH_ARGS("SetLinkDNSEx",
2134
                                SD_BUS_ARGS("i", ifindex, "a(iayqs)", addresses),
2135
                                SD_BUS_NO_RESULT,
2136
                                bus_method_set_link_dns_servers_ex,
2137
                                SD_BUS_VTABLE_UNPRIVILEGED),
2138
        SD_BUS_METHOD_WITH_ARGS("SetLinkDomains",
2139
                                SD_BUS_ARGS("i", ifindex, "a(sb)", domains),
2140
                                SD_BUS_NO_RESULT,
2141
                                bus_method_set_link_domains,
2142
                                SD_BUS_VTABLE_UNPRIVILEGED),
2143
        SD_BUS_METHOD_WITH_ARGS("SetLinkDefaultRoute",
2144
                                SD_BUS_ARGS("i", ifindex, "b", enable),
2145
                                SD_BUS_NO_RESULT,
2146
                                bus_method_set_link_default_route,
2147
                                SD_BUS_VTABLE_UNPRIVILEGED),
2148
        SD_BUS_METHOD_WITH_ARGS("SetLinkLLMNR",
2149
                                SD_BUS_ARGS("i", ifindex, "s", mode),
2150
                                SD_BUS_NO_RESULT,
2151
                                bus_method_set_link_llmnr,
2152
                                SD_BUS_VTABLE_UNPRIVILEGED),
2153
        SD_BUS_METHOD_WITH_ARGS("SetLinkMulticastDNS",
2154
                                SD_BUS_ARGS("i", ifindex, "s", mode),
2155
                                SD_BUS_NO_RESULT,
2156
                                bus_method_set_link_mdns,
2157
                                SD_BUS_VTABLE_UNPRIVILEGED),
2158
        SD_BUS_METHOD_WITH_ARGS("SetLinkDNSOverTLS",
2159
                                SD_BUS_ARGS("i", ifindex, "s", mode),
2160
                                SD_BUS_NO_RESULT,
2161
                                bus_method_set_link_dns_over_tls,
2162
                                SD_BUS_VTABLE_UNPRIVILEGED),
2163
        SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSEC",
2164
                                SD_BUS_ARGS("i", ifindex, "s", mode),
2165
                                SD_BUS_NO_RESULT,
2166
                                bus_method_set_link_dnssec,
2167
                                SD_BUS_VTABLE_UNPRIVILEGED),
2168
        SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSECNegativeTrustAnchors",
2169
                                SD_BUS_ARGS("i", ifindex, "as", names),
2170
                                SD_BUS_NO_RESULT,
2171
                                bus_method_set_link_dnssec_negative_trust_anchors,
2172
                                SD_BUS_VTABLE_UNPRIVILEGED),
2173
        SD_BUS_METHOD_WITH_ARGS("RevertLink",
2174
                                SD_BUS_ARGS("i", ifindex),
2175
                                SD_BUS_NO_RESULT,
2176
                                bus_method_revert_link,
2177
                                SD_BUS_VTABLE_UNPRIVILEGED),
2178
        SD_BUS_METHOD_WITH_ARGS("RegisterService",
2179
                                SD_BUS_ARGS("s", id,
2180
                                            "s", name_template,
2181
                                            "s", type,
2182
                                            "q", service_port,
2183
                                            "q", service_priority,
2184
                                            "q", service_weight,
2185
                                            "aa{say}", txt_datas),
2186
                                SD_BUS_RESULT("o", service_path),
2187
                                bus_method_register_service,
2188
                                SD_BUS_VTABLE_UNPRIVILEGED),
2189
        SD_BUS_METHOD_WITH_ARGS("UnregisterService",
2190
                                SD_BUS_ARGS("o", service_path),
2191
                                SD_BUS_NO_RESULT,
2192
                                bus_method_unregister_service,
2193
                                SD_BUS_VTABLE_UNPRIVILEGED),
2194
        SD_BUS_METHOD_WITH_ARGS("ResetStatistics",
2195
                                SD_BUS_NO_ARGS,
2196
                                SD_BUS_NO_RESULT,
2197
                                bus_method_reset_statistics,
2198
                                SD_BUS_VTABLE_UNPRIVILEGED),
2199
        SD_BUS_METHOD_WITH_ARGS("FlushCaches",
2200
                                SD_BUS_NO_ARGS,
2201
                                SD_BUS_NO_RESULT,
2202
                                bus_method_flush_caches,
2203
                                SD_BUS_VTABLE_UNPRIVILEGED),
2204
        SD_BUS_METHOD_WITH_ARGS("ResetServerFeatures",
2205
                                SD_BUS_NO_ARGS,
2206
                                SD_BUS_NO_RESULT,
2207
                                bus_method_reset_server_features,
2208
                                SD_BUS_VTABLE_UNPRIVILEGED),
2209

2210
        SD_BUS_VTABLE_END,
2211
};
2212

2213
const BusObjectImplementation manager_object = {
2214
        "/org/freedesktop/resolve1",
2215
        "org.freedesktop.resolve1.Manager",
2216
        .vtables = BUS_VTABLES(resolve_vtable),
2217
        .children = BUS_IMPLEMENTATIONS(&link_object,
2218
                                        &dnssd_object),
2219
};
2220

2221
static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
×
2222
        Manager *m = ASSERT_PTR(userdata);
×
2223
        int b, r;
×
2224

2225
        assert(message);
×
2226

2227
        r = sd_bus_message_read(message, "b", &b);
×
2228
        if (r < 0) {
×
2229
                bus_log_parse_error(r);
×
2230
                return 0;
×
2231
        }
2232

2233
        if (b)
×
2234
                return 0;
2235

2236
        log_debug("Coming back from suspend, closing all TCP connections...");
×
2237
        (void) dns_stream_disconnect_all(m);
×
2238

2239
        log_debug("Coming back from suspend, resetting all probed server features...");
×
2240
        manager_reset_server_features(m);
×
2241

2242
        log_debug("Coming back from suspend, verifying all RRs...");
×
2243
        manager_verify_all(m);
×
2244

2245
        return 0;
2246
}
2247

2248
int manager_connect_bus(Manager *m) {
162✔
2249
        int r;
162✔
2250

2251
        assert(m);
162✔
2252

2253
        if (m->bus)
162✔
2254
                return 0;
2255

2256
        r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-resolve");
162✔
2257
        if (r < 0)
162✔
2258
                return log_error_errno(r, "Failed to connect to system bus: %m");
×
2259

2260
        r = bus_add_implementation(m->bus, &manager_object, m);
162✔
2261
        if (r < 0)
162✔
2262
                return r;
2263

2264
        r = bus_log_control_api_register(m->bus);
162✔
2265
        if (r < 0)
162✔
2266
                return r;
2267

2268
        r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.resolve1", 0, NULL, NULL);
162✔
2269
        if (r < 0)
162✔
2270
                return log_error_errno(r, "Failed to request name: %m");
×
2271

2272
        r = sd_bus_attach_event(m->bus, m->event, 0);
162✔
2273
        if (r < 0)
162✔
2274
                return log_error_errno(r, "Failed to attach bus to event loop: %m");
×
2275

2276
        r = bus_match_signal_async(
162✔
2277
                        m->bus,
2278
                        NULL,
2279
                        bus_login_mgr,
2280
                        "PrepareForSleep",
2281
                        match_prepare_for_sleep,
2282
                        NULL,
2283
                        m);
2284
        if (r < 0)
162✔
2285
                log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
×
2286

2287
        return 0;
2288
}
2289

2290
int _manager_send_changed(Manager *manager, const char *property, ...) {
17,030✔
2291
        assert(manager);
17,030✔
2292

2293
        if (sd_bus_is_ready(manager->bus) <= 0)
17,030✔
2294
                return 0;
2295

2296
        char **l = strv_from_stdarg_alloca(property);
16,410✔
2297

2298
        int r = sd_bus_emit_properties_changed_strv(
16,410✔
2299
                        manager->bus,
2300
                        "/org/freedesktop/resolve1",
2301
                        "org.freedesktop.resolve1.Manager",
2302
                        l);
2303
        if (r < 0)
16,410✔
2304
                log_notice_errno(r, "Failed to emit notification about changed property %s: %m", property);
×
2305
        return r;
2306
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc