• 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

76.72
/src/resolve/resolved-dns-server.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <net/if_arp.h>
4

5
#include "sd-messages.h"
6

7
#include "alloc-util.h"
8
#include "dns-domain.h"
9
#include "errno-util.h"
10
#include "fd-util.h"
11
#include "json-util.h"
12
#include "resolved-bus.h"
13
#include "resolved-dns-cache.h"
14
#include "resolved-dns-packet.h"
15
#include "resolved-dns-scope.h"
16
#include "resolved-dns-search-domain.h"
17
#include "resolved-dns-server.h"
18
#include "resolved-dns-stub.h"
19
#include "resolved-link.h"
20
#include "resolved-manager.h"
21
#include "resolved-resolv-conf.h"
22
#include "siphash24.h"
23
#include "socket-netlink.h"
24
#include "socket-util.h"
25
#include "string-table.h"
26
#include "string-util.h"
27

28
/* The amount of time to wait before retrying with a full feature set */
29
#define DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC (6 * USEC_PER_HOUR)
30
#define DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC (5 * USEC_PER_MINUTE)
31

32
/* The number of times we will attempt a certain feature set before degrading */
33
#define DNS_SERVER_FEATURE_RETRY_ATTEMPTS 3
34

35
int dns_server_new(
1,212✔
36
                Manager *m,
37
                DnsServer **ret,
38
                DnsServerType type,
39
                Link *l,
40
                int family,
41
                const union in_addr_union *in_addr,
42
                uint16_t port,
43
                int ifindex,
44
                const char *server_name,
45
                ResolveConfigSource config_source) {
46

47
        _cleanup_free_ char *name = NULL;
2,424✔
48
        DnsServer *s;
1,212✔
49

50
        assert(m);
1,212✔
51
        assert((type == DNS_SERVER_LINK) == !!l);
1,212✔
52
        assert(in_addr);
1,212✔
53

54
        if (!IN_SET(family, AF_INET, AF_INET6))
1,212✔
55
                return -EAFNOSUPPORT;
56

57
        if (l) {
1,212✔
58
                if (l->n_dns_servers >= LINK_DNS_SERVERS_MAX)
165✔
59
                        return -E2BIG;
60
        } else {
61
                if (m->n_dns_servers >= MANAGER_DNS_SERVERS_MAX)
1,047✔
62
                        return -E2BIG;
63
        }
64

65
        if (!isempty(server_name)) {
1,212✔
66
                name = strdup(server_name);
1,064✔
67
                if (!name)
1,064✔
68
                        return -ENOMEM;
69
        }
70

71
        s = new(DnsServer, 1);
1,212✔
72
        if (!s)
1,212✔
73
                return -ENOMEM;
74

75
        *s = (DnsServer) {
1,212✔
76
                .n_ref = 1,
77
                .manager = m,
78
                .type = type,
79
                .family = family,
80
                .address = *in_addr,
1,212✔
81
                .port = port,
82
                .ifindex = ifindex,
83
                .server_name = TAKE_PTR(name),
1,212✔
84
                .config_source = config_source,
85
                .accessible = -1,
86
        };
87

88
        dns_server_reset_features(s);
1,212✔
89

90
        switch (type) {
1,212✔
91

92
        case DNS_SERVER_LINK:
165✔
93
                s->link = l;
165✔
94
                LIST_APPEND(servers, l->dns_servers, s);
226✔
95
                l->n_dns_servers++;
165✔
96
                break;
165✔
97

98
        case DNS_SERVER_SYSTEM:
6✔
99
                LIST_APPEND(servers, m->dns_servers, s);
6✔
100
                m->n_dns_servers++;
6✔
101
                break;
6✔
102

103
        case DNS_SERVER_FALLBACK:
1,041✔
104
                LIST_APPEND(servers, m->fallback_dns_servers, s);
2,771✔
105
                m->n_dns_servers++;
1,041✔
106
                break;
1,041✔
107

108
        default:
×
109
                assert_not_reached();
×
110
        }
111

112
        s->linked = true;
1,212✔
113

114
        /* A new DNS server that isn't fallback is added and the one
115
         * we used so far was a fallback one? Then let's try to pick
116
         * the new one */
117
        if (type != DNS_SERVER_FALLBACK && dns_server_is_fallback(m->current_dns_server))
1,212✔
118
                manager_set_dns_server(m, NULL);
42✔
119

120
        if (ret)
1,212✔
121
                *ret = s;
10✔
122

123
        return 0;
124
}
125

126
static DnsServer* dns_server_free(DnsServer *s)  {
1,211✔
127
        assert(s);
1,211✔
128

129
        dns_server_unref_stream(s);
1,211✔
130

131
#if ENABLE_DNS_OVER_TLS
132
        dnstls_server_free(s);
1,211✔
133
#endif
134

135
        free(s->server_string);
1,211✔
136
        free(s->server_string_full);
1,211✔
137
        free(s->server_name);
1,211✔
138
        return mfree(s);
1,211✔
139
}
140

141
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsServer, dns_server, dns_server_free);
42,342✔
142

143
void dns_server_unlink(DnsServer *s) {
1,202✔
144
        assert(s);
1,202✔
145
        assert(s->manager);
1,202✔
146

147
        /* This removes the specified server from the linked list of
148
         * servers, but any server might still stay around if it has
149
         * refs, for example from an ongoing transaction. */
150

151
        if (!s->linked)
1,202✔
152
                return;
153

154
        switch (s->type) {
1,202✔
155

156
        case DNS_SERVER_LINK:
159✔
157
                assert(s->link);
159✔
158
                assert(s->link->n_dns_servers > 0);
159✔
159
                LIST_REMOVE(servers, s->link->dns_servers, s);
159✔
160
                s->link->n_dns_servers--;
159✔
161
                break;
159✔
162

163
        case DNS_SERVER_SYSTEM:
5✔
164
                assert(s->manager->n_dns_servers > 0);
5✔
165
                LIST_REMOVE(servers, s->manager->dns_servers, s);
5✔
166
                s->manager->n_dns_servers--;
5✔
167
                break;
5✔
168

169
        case DNS_SERVER_FALLBACK:
1,038✔
170
                assert(s->manager->n_dns_servers > 0);
1,038✔
171
                LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
1,038✔
172
                s->manager->n_dns_servers--;
1,038✔
173
                break;
1,038✔
174
        default:
×
175
                assert_not_reached();
×
176
        }
177

178
        s->linked = false;
1,202✔
179

180
        if (s->link && s->link->current_dns_server == s)
1,202✔
181
                link_set_dns_server(s->link, NULL);
21✔
182

183
        if (s->manager->current_dns_server == s)
1,202✔
184
                manager_set_dns_server(s->manager, NULL);
48✔
185

186
        /* No need to keep a default stream around anymore */
187
        dns_server_unref_stream(s);
1,202✔
188

189
        dns_server_unref(s);
1,202✔
190
}
191

192
void dns_server_move_back_and_unmark(DnsServer *s) {
239✔
193
        DnsServer *tail;
239✔
194

195
        assert(s);
239✔
196

197
        if (!s->marked)
239✔
198
                return;
199

200
        s->marked = false;
239✔
201

202
        if (!s->linked || !s->servers_next)
239✔
203
                return;
204

205
        /* Move us to the end of the list, so that the order is
206
         * strictly kept, if we are not at the end anyway. */
207

208
        switch (s->type) {
204✔
209

210
        case DNS_SERVER_LINK:
204✔
211
                assert(s->link);
204✔
212
                tail = LIST_FIND_TAIL(servers, s);
486✔
213
                LIST_REMOVE(servers, s->link->dns_servers, s);
204✔
214
                LIST_INSERT_AFTER(servers, s->link->dns_servers, tail, s);
204✔
215
                break;
216

217
        case DNS_SERVER_SYSTEM:
218
                tail = LIST_FIND_TAIL(servers, s);
×
219
                LIST_REMOVE(servers, s->manager->dns_servers, s);
×
220
                LIST_INSERT_AFTER(servers, s->manager->dns_servers, tail, s);
×
221
                break;
222

223
        case DNS_SERVER_FALLBACK:
224
                tail = LIST_FIND_TAIL(servers, s);
×
225
                LIST_REMOVE(servers, s->manager->fallback_dns_servers, s);
×
226
                LIST_INSERT_AFTER(servers, s->manager->fallback_dns_servers, tail, s);
×
227
                break;
228

229
        default:
×
230
                assert_not_reached();
×
231
        }
232
}
233

234
static void dns_server_verified(DnsServer *s, DnsServerFeatureLevel level) {
108✔
235
        assert(s);
108✔
236

237
        if (s->verified_feature_level > level)
108✔
238
                return;
239

240
        if (s->verified_feature_level != level) {
108✔
241
                log_debug("Verified we get a response at feature level %s from DNS server %s.",
3✔
242
                          dns_server_feature_level_to_string(level),
243
                          strna(dns_server_string_full(s)));
244
                s->verified_feature_level = level;
3✔
245
        }
246

247
        assert_se(sd_event_now(s->manager->event, CLOCK_BOOTTIME, &s->verified_usec) >= 0);
108✔
248
}
249

250
static void dns_server_reset_counters(DnsServer *s) {
6,650✔
251
        assert(s);
6,650✔
252

253
        s->n_failed_udp = 0;
6,650✔
254
        s->n_failed_tcp = 0;
6,650✔
255
        s->n_failed_tls = 0;
6,650✔
256
        s->packet_truncated = false;
6,650✔
257
        s->packet_invalid = false;
6,650✔
258
        s->verified_usec = 0;
6,650✔
259

260
        /* Note that we do not reset s->packet_bad_opt and s->packet_rrsig_missing here. We reset them only when the
261
         * grace period ends, but not when lowering the possible feature level, as a lower level feature level should
262
         * not make RRSIGs appear or OPT appear, but rather make them disappear. If the reappear anyway, then that's
263
         * indication for a differently broken OPT/RRSIG implementation, and we really don't want to support that
264
         * either.
265
         *
266
         * This is particularly important to deal with certain Belkin routers which break OPT for certain lookups (A),
267
         * but pass traffic through for others (AAAA). If we detect the broken behaviour on one lookup we should not
268
         * re-enable it for another, because we cannot validate things anyway, given that the RRSIG/OPT data will be
269
         * incomplete. */
270
}
6,650✔
271

272
void dns_server_packet_received(DnsServer *s, int protocol, DnsServerFeatureLevel level, size_t fragsize) {
108✔
273
        assert(s);
108✔
274

275
        if (protocol == IPPROTO_UDP) {
108✔
276
                if (s->possible_feature_level == level)
108✔
277
                        s->n_failed_udp = 0;
107✔
278
        } else if (protocol == IPPROTO_TCP) {
×
279
                if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(level)) {
×
280
                        if (s->possible_feature_level == level)
×
281
                                s->n_failed_tls = 0;
×
282
                } else {
283
                        if (s->possible_feature_level == level)
×
284
                                s->n_failed_tcp = 0;
×
285

286
                        /* Successful TCP connections are only useful to verify the TCP feature level. */
287
                        level = DNS_SERVER_FEATURE_LEVEL_TCP;
288
                }
289
        }
290

291
        /* If the RRSIG data is missing, then we can only validate EDNS0 at max */
292
        if (s->packet_rrsig_missing && level >= DNS_SERVER_FEATURE_LEVEL_DO)
108✔
293
                level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0;
×
294

295
        /* If the OPT RR got lost, then we can only validate UDP at max */
296
        if (s->packet_bad_opt && level >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
108✔
297
                level = DNS_SERVER_FEATURE_LEVEL_EDNS0 - 1;
2✔
298

299
        dns_server_verified(s, level);
108✔
300

301
        /* Remember the size of the largest UDP packet fragment we received from a server, we know that we
302
         * can always announce support for packets with at least this size. */
303
        if (protocol == IPPROTO_UDP && s->received_udp_fragment_max < fragsize)
108✔
304
                s->received_udp_fragment_max = fragsize;
3✔
305
}
108✔
306

307
void dns_server_packet_lost(DnsServer *s, int protocol, DnsServerFeatureLevel level) {
651✔
308
        assert(s);
651✔
309
        assert(s->manager);
651✔
310

311
        if (s->possible_feature_level != level)
651✔
312
                return;
313

314
        if (protocol == IPPROTO_UDP)
500✔
315
                s->n_failed_udp++;
436✔
316
        else if (protocol == IPPROTO_TCP) {
64✔
317
                if (DNS_SERVER_FEATURE_LEVEL_IS_TLS(level))
64✔
318
                        s->n_failed_tls++;
2✔
319
                else
320
                        s->n_failed_tcp++;
62✔
321
        }
322
}
323

324
void dns_server_packet_truncated(DnsServer *s, DnsServerFeatureLevel level) {
×
325
        assert(s);
×
326

327
        /* Invoked whenever we get a packet with TC bit set. */
328

329
        if (s->possible_feature_level != level)
×
330
                return;
331

332
        s->packet_truncated = true;
×
333
}
334

335
void dns_server_packet_rrsig_missing(DnsServer *s, DnsServerFeatureLevel level) {
×
336
        assert(s);
×
337

338
        if (level < DNS_SERVER_FEATURE_LEVEL_DO)
×
339
                return;
340

341
        /* If the RRSIG RRs are missing, we have to downgrade what we previously verified */
342
        if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_DO)
×
343
                s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN : DNS_SERVER_FEATURE_LEVEL_EDNS0;
×
344

345
        s->packet_rrsig_missing = true;
×
346
}
347

348
void dns_server_packet_bad_opt(DnsServer *s, DnsServerFeatureLevel level) {
6✔
349
        assert(s);
6✔
350

351
        if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0)
6✔
352
                return;
353

354
        /* If the OPT RR got lost, we have to downgrade what we previously verified */
355
        if (s->verified_feature_level >= DNS_SERVER_FEATURE_LEVEL_EDNS0)
2✔
356
                s->verified_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0-1;
1✔
357

358
        s->packet_bad_opt = true;
2✔
359
}
360

361
void dns_server_packet_rcode_downgrade(DnsServer *s, DnsServerFeatureLevel level) {
×
362
        assert(s);
×
363

364
        /* Invoked whenever we got a FORMERR, SERVFAIL or NOTIMP rcode from a server and downgrading the feature level
365
         * for the transaction made it go away. In this case we immediately downgrade to the feature level that made
366
         * things work. */
367

368
        if (s->verified_feature_level > level)
×
369
                s->verified_feature_level = level;
×
370

371
        if (s->possible_feature_level > level) {
×
372
                s->possible_feature_level = level;
×
373
                dns_server_reset_counters(s);
×
374
                log_debug("Downgrading transaction feature level fixed an RCODE error, downgrading server %s too.", strna(dns_server_string_full(s)));
×
375
        }
376
}
×
377

378
void dns_server_packet_invalid(DnsServer *s, DnsServerFeatureLevel level) {
×
379
        assert(s);
×
380

381
        /* Invoked whenever we got a packet we couldn't parse at all */
382

383
        if (s->possible_feature_level != level)
×
384
                return;
385

386
        s->packet_invalid = true;
×
387
}
388

389
void dns_server_packet_do_off(DnsServer *s, DnsServerFeatureLevel level) {
×
390
        assert(s);
×
391

392
        /* Invoked whenever the DO flag was not copied from our request to the response. */
393

394
        if (s->possible_feature_level != level)
×
395
                return;
396

397
        s->packet_do_off = true;
×
398
}
399

400
void dns_server_packet_udp_fragmented(DnsServer *s, size_t fragsize) {
×
401
        assert(s);
×
402

403
        /* Invoked whenever we got a fragmented UDP packet. Let's do two things: keep track of the largest
404
         * fragment we ever received from the server, and remember this, so that we can use it to lower the
405
         * advertised packet size in EDNS0 */
406

407
        if (s->received_udp_fragment_max < fragsize)
×
408
                s->received_udp_fragment_max = fragsize;
×
409

410
        s->packet_fragmented = true;
×
411
}
×
412

413
static bool dns_server_grace_period_expired(DnsServer *s) {
698✔
414
        usec_t ts;
698✔
415

416
        assert(s);
698✔
417
        assert(s->manager);
698✔
418

419
        if (s->verified_usec == 0)
698✔
420
                return false;
698✔
421

422
        assert_se(sd_event_now(s->manager->event, CLOCK_BOOTTIME, &ts) >= 0);
247✔
423

424
        if (s->verified_usec + s->features_grace_period_usec > ts)
247✔
425
                return false;
426

427
        s->features_grace_period_usec = MIN(s->features_grace_period_usec * 2, DNS_SERVER_FEATURE_GRACE_PERIOD_MAX_USEC);
×
428

429
        return true;
×
430
}
431

432
DnsServerFeatureLevel dns_server_possible_feature_level(DnsServer *s) {
10,081✔
433
        DnsServerFeatureLevel best;
10,081✔
434

435
        assert(s);
10,081✔
436

437
        /* Determine the best feature level we care about. If DNSSEC mode is off there's no point in using anything
438
         * better than EDNS0, hence don't even try. */
439
        if (dns_server_get_dnssec_mode(s) != DNSSEC_NO)
10,081✔
440
                best = dns_server_get_dns_over_tls_mode(s) == DNS_OVER_TLS_NO ?
336✔
441
                        DNS_SERVER_FEATURE_LEVEL_DO :
336✔
442
                        DNS_SERVER_FEATURE_LEVEL_TLS_DO;
443
        else
444
                best = dns_server_get_dns_over_tls_mode(s) == DNS_OVER_TLS_NO ?
9,745✔
445
                        DNS_SERVER_FEATURE_LEVEL_EDNS0 :
9,745✔
446
                        DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN;
447

448
        /* Clamp the feature level the highest level we care about. The DNSSEC mode might have changed since the last
449
         * time, hence let's downgrade if we are still at a higher level. */
450
        if (s->possible_feature_level > best)
10,081✔
451
                s->possible_feature_level = best;
451✔
452

453
        if (s->possible_feature_level < best && dns_server_grace_period_expired(s)) {
10,081✔
454

455
                s->possible_feature_level = best;
×
456

457
                dns_server_reset_counters(s);
×
458

459
                s->packet_bad_opt = false;
×
460
                s->packet_rrsig_missing = false;
×
461

462
                log_info("Grace period over, resuming full feature set (%s) for DNS server %s.",
×
463
                         dns_server_feature_level_to_string(s->possible_feature_level),
464
                         strna(dns_server_string_full(s)));
465

466
                dns_server_flush_cache(s);
×
467

468
        } else if (s->possible_feature_level <= s->verified_feature_level)
10,081✔
469
                s->possible_feature_level = s->verified_feature_level;
325✔
470
        else {
471
                DnsServerFeatureLevel p = s->possible_feature_level;
9,756✔
472
                int log_level = LOG_WARNING;
9,756✔
473

474
                if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
9,756✔
475
                    s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_TCP) {
476

477
                        /* We are at the TCP (lowest) level, and we tried a couple of TCP connections, and it didn't
478
                         * work. Upgrade back to UDP again. */
479
                        log_debug("Reached maximum number of failed TCP connection attempts, trying UDP again...");
19✔
480
                        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
19✔
481

482
                } else if (s->n_failed_tls > 0 &&
9,737✔
483
                           DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) &&
4✔
484
                           dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
2✔
485

486
                        /* We tried to connect using DNS-over-TLS, and it didn't work. Downgrade to plaintext UDP
487
                         * if we don't require DNS-over-TLS */
488

489
                        log_debug("Server doesn't support DNS-over-TLS, downgrading protocol...");
2✔
490
                        s->possible_feature_level--;
2✔
491

492
                } else if (s->packet_invalid &&
9,735✔
493
                           s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP &&
×
494
                           s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN) {
495

496
                        /* Downgrade from DO to EDNS0 + from EDNS0 to UDP, from TLS+DO to plain TLS. Or in
497
                         * other words, if we receive a packet we cannot parse jump to the next lower feature
498
                         * level that actually has an influence on the packet layout (and not just the
499
                         * transport). */
500

501
                        log_debug("Got invalid packet from server, downgrading protocol...");
×
502
                        s->possible_feature_level =
×
503
                                s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_TLS_DO  ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN :
×
504
                                DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_EDNS0 :
505
                                                                                                DNS_SERVER_FEATURE_LEVEL_UDP;
506

507
                } else if (s->packet_bad_opt &&
9,735✔
508
                           DNS_SERVER_FEATURE_LEVEL_IS_EDNS0(s->possible_feature_level) &&
2✔
509
                           dns_server_get_dnssec_mode(s) != DNSSEC_YES &&
2✔
510
                           dns_server_get_dns_over_tls_mode(s) != DNS_OVER_TLS_YES) {
1✔
511

512
                        /* A reply to one of our EDNS0 queries didn't carry a valid OPT RR, then downgrade to
513
                         * below EDNS0 levels. After all, some servers generate different responses with and
514
                         * without OPT RR in the request. Example:
515
                         *
516
                         * https://open.nlnetlabs.nl/pipermail/dnssec-trigger/2014-November/000376.html
517
                         *
518
                         * If we are in strict DNSSEC or DoT mode, we don't do this kind of downgrade
519
                         * however, as both modes imply EDNS0 to work (DNSSEC strictly requires it, and DoT
520
                         * only in our implementation). */
521

522
                        log_debug("Server doesn't support EDNS(0) properly, downgrading feature level...");
1✔
523
                        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP;
1✔
524

525
                        /* Users often don't control the DNS server they use so let's not complain too loudly
526
                         * when we can't use EDNS because the DNS server doesn't support it. */
527
                        log_level = LOG_NOTICE;
1✔
528

529
                } else if (s->packet_do_off &&
9,734✔
530
                           DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) &&
×
531
                           dns_server_get_dnssec_mode(s) != DNSSEC_YES) {
×
532

533
                        /* The server didn't copy the DO bit from request to response, thus DNSSEC is not
534
                         * correctly implemented, let's downgrade if that's allowed. */
535

536
                        log_debug("Detected server didn't copy DO flag from request to response, downgrading feature level...");
×
537
                        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN :
×
538
                                                                                                                 DNS_SERVER_FEATURE_LEVEL_EDNS0;
539

540
                } else if (s->packet_rrsig_missing &&
9,734✔
541
                           DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) &&
×
542
                           dns_server_get_dnssec_mode(s) != DNSSEC_YES) {
×
543

544
                        /* RRSIG data was missing on an EDNS0 packet with DO bit set. This means the server
545
                         * doesn't augment responses with DNSSEC RRs. If so, let's better not ask the server
546
                         * for it anymore, after all some servers generate different replies depending if an
547
                         * OPT RR is in the query or not. If we are in strict DNSSEC mode, don't allow such
548
                         * downgrades however, since a DNSSEC feature level is a requirement for strict
549
                         * DNSSEC mode. */
550

551
                        log_debug("Detected server responses lack RRSIG records, downgrading feature level...");
×
552
                        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_IS_TLS(s->possible_feature_level) ? DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN :
×
553
                                                                                                                 DNS_SERVER_FEATURE_LEVEL_EDNS0;
554

555
                } else if (s->n_failed_udp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
9,734✔
556
                           DNS_SERVER_FEATURE_LEVEL_IS_UDP(s->possible_feature_level) &&
45✔
557
                           ((s->possible_feature_level != DNS_SERVER_FEATURE_LEVEL_DO) || dns_server_get_dnssec_mode(s) != DNSSEC_YES)) {
×
558

559
                        /* We lost too many UDP packets in a row, and are on a UDP feature level. If the
560
                         * packets are lost, maybe the server cannot parse them, hence downgrading sounds
561
                         * like a good idea. We might downgrade all the way down to TCP this way.
562
                         *
563
                         * If strict DNSSEC mode is used we won't downgrade below DO level however, as packet loss
564
                         * might have many reasons, a broken DNSSEC implementation being only one reason. And if the
565
                         * user is strict on DNSSEC, then let's assume that DNSSEC is not the fault here. */
566

567
                        log_debug("Lost too many UDP packets, downgrading feature level...");
45✔
568
                        if (s->possible_feature_level == DNS_SERVER_FEATURE_LEVEL_DO) /* skip over TLS_PLAIN */
45✔
569
                                s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0;
×
570
                        else
571
                                s->possible_feature_level--;
45✔
572

573
                } else if (s->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS &&
9,689✔
574
                           s->packet_truncated &&
×
575
                           s->possible_feature_level > DNS_SERVER_FEATURE_LEVEL_UDP &&
×
576
                           DNS_SERVER_FEATURE_LEVEL_IS_UDP(s->possible_feature_level) &&
×
577
                           (!DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level) || dns_server_get_dnssec_mode(s) != DNSSEC_YES)) {
×
578

579
                         /* We got too many TCP connection failures in a row, we had at least one truncated
580
                          * packet, and are on feature level above UDP. By downgrading things and getting rid
581
                          * of DNSSEC or EDNS0 data we hope to make the packet smaller, so that it still
582
                          * works via UDP given that TCP appears not to be a fallback. Note that if we are
583
                          * already at the lowest UDP level, we don't go further down, since that's TCP, and
584
                          * TCP failed too often after all. */
585

586
                        log_debug("Got too many failed TCP connection failures and truncated UDP packets, downgrading feature level...");
×
587

588
                        if (DNS_SERVER_FEATURE_LEVEL_IS_DNSSEC(s->possible_feature_level))
×
589
                                s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_EDNS0; /* Go DNSSEC → EDNS0 */
×
590
                        else
591
                                s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_UDP; /* Go EDNS0 → UDP */
×
592
                }
593

594
                if (p != s->possible_feature_level) {
9,756✔
595

596
                        /* We changed the feature level, reset the counting */
597
                        dns_server_reset_counters(s);
67✔
598

599
                        log_full(log_level, "Using degraded feature set %s instead of %s for DNS server %s.",
67✔
600
                                 dns_server_feature_level_to_string(s->possible_feature_level),
601
                                 dns_server_feature_level_to_string(p), strna(dns_server_string_full(s)));
602
                }
603
        }
604

605
        return s->possible_feature_level;
10,081✔
606
}
607

608
int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeatureLevel level) {
850✔
609
        size_t packet_size, udp_size;
850✔
610
        bool edns_do;
850✔
611
        int r;
850✔
612

613
        assert(server);
850✔
614
        assert(packet);
850✔
615
        assert(packet->protocol == DNS_PROTOCOL_DNS);
850✔
616

617
        /* Fix the OPT field in the packet to match our current feature level. */
618

619
        r = dns_packet_truncate_opt(packet);
850✔
620
        if (r < 0)
850✔
621
                return r;
622

623
        if (level < DNS_SERVER_FEATURE_LEVEL_EDNS0)
850✔
624
                return 0;
625

626
        edns_do = level >= DNS_SERVER_FEATURE_LEVEL_DO;
567✔
627

628
        udp_size = udp_header_size(server->family);
567✔
629

630
        if (in_addr_is_localhost(server->family, &server->address) > 0)
567✔
631
                packet_size = 65536 - udp_size; /* force linux loopback MTU if localhost address */
2✔
632
        else {
633
                /* Use the MTU pointing to the server, subtract the IP/UDP header size */
634
                packet_size = LESS_BY(dns_server_get_mtu(server), udp_size);
565✔
635

636
                /* On the Internet we want to avoid fragmentation for security reasons. If we saw
637
                 * fragmented packets, the above was too large, let's clamp it to the largest
638
                 * fragment we saw */
639
                if (server->packet_fragmented)
565✔
640
                        packet_size = MIN(server->received_udp_fragment_max, packet_size);
×
641

642
                /* Let's not pick ridiculously large sizes, i.e. not more than 4K. No one appears
643
                 * to ever use such large sized on the Internet IRL, hence let's not either. */
644
                packet_size = MIN(packet_size, 4096U);
565✔
645
        }
646

647
        /* Strictly speaking we quite possibly can receive larger datagrams than the MTU (since the
648
         * MTU is for egress, not for ingress), but more often than not the value is symmetric, and
649
         * we want something that does the right thing in the majority of cases, and not just in the
650
         * theoretical edge case. */
651

652
        /* Safety clamp, never advertise less than 512 or more than 65535 */
653
        packet_size = CLAMP(packet_size,
567✔
654
                            DNS_PACKET_UNICAST_SIZE_MAX,
655
                            DNS_PACKET_SIZE_MAX);
656

657
        log_debug("Announcing packet size %zu in egress EDNS(0) packet.", packet_size);
567✔
658

659
        return dns_packet_append_opt(packet, packet_size, edns_do, /* include_rfc6975 = */ true, NULL, 0, NULL);
567✔
660
}
661

662
int dns_server_ifindex(const DnsServer *s) {
20,544✔
663
        assert(s);
20,544✔
664

665
        /* For loopback addresses, go via the loopback interface, regardless which interface this is linked
666
         * to. */
667
        if (in_addr_is_localhost(s->family, &s->address))
20,544✔
668
                return LOOPBACK_IFINDEX;
669

670
        /* The link ifindex always takes precedence */
671
        if (s->link)
20,538✔
672
                return s->link->ifindex;
1,469✔
673

674
        if (s->ifindex > 0)
19,069✔
675
                return s->ifindex;
×
676

677
        return 0;
678
}
679

680
uint16_t dns_server_port(const DnsServer *s) {
62,431✔
681
        assert(s);
62,431✔
682

683
        if (s->port > 0)
62,431✔
684
                return s->port;
15✔
685

686
        return 53;
687
}
688

689
const char* dns_server_string(DnsServer *server) {
105,390✔
690
        assert(server);
105,390✔
691

692
        if (!server->server_string)
105,390✔
693
                (void) in_addr_ifindex_to_string(server->family, &server->address, dns_server_ifindex(server), &server->server_string);
1,148✔
694

695
        return server->server_string;
105,390✔
696
}
697

698
const char* dns_server_string_full(DnsServer *server) {
18,469✔
699
        assert(server);
18,469✔
700

701
        if (!server->server_string_full)
18,469✔
702
                (void) in_addr_port_ifindex_name_to_string(
360✔
703
                                server->family,
704
                                &server->address,
180✔
705
                                server->port,
180✔
706
                                dns_server_ifindex(server),
707
                                server->server_name,
180✔
708
                                &server->server_string_full);
709

710
        return server->server_string_full;
18,469✔
711
}
712

713
bool dns_server_dnssec_supported(DnsServer *server) {
10,010✔
714
        assert(server);
10,010✔
715

716
        /* Returns whether the server supports DNSSEC according to what we know about it */
717

718
        if (dns_server_get_dnssec_mode(server) == DNSSEC_YES) /* If strict DNSSEC mode is enabled, always assume DNSSEC mode is supported. */
10,010✔
719
                return true;
720

721
        if (server->packet_bad_opt)
10,010✔
722
                return false;
723

724
        if (server->packet_rrsig_missing)
9,961✔
725
                return false;
726

727
        if (server->packet_do_off)
9,961✔
728
                return false;
729

730
        /* DNSSEC servers need to support TCP properly (see RFC5966), if they don't, we assume DNSSEC is borked too */
731
        if (server->n_failed_tcp >= DNS_SERVER_FEATURE_RETRY_ATTEMPTS)
9,961✔
732
                return false;
×
733

734
        return true;
735
}
736

737
void dns_server_warn_downgrade(DnsServer *server) {
13✔
738
        assert(server);
13✔
739

740
        if (server->warned_downgrade)
13✔
741
                return;
742

743
        log_struct(LOG_NOTICE,
1✔
744
                   LOG_MESSAGE_ID(SD_MESSAGE_DNSSEC_DOWNGRADE_STR),
745
                   LOG_MESSAGE("Server %s does not support DNSSEC, downgrading to non-DNSSEC mode.",
746
                               strna(dns_server_string_full(server))),
747
                   LOG_ITEM("DNS_SERVER=%s", strna(dns_server_string_full(server))),
748
                   LOG_ITEM("DNS_SERVER_FEATURE_LEVEL=%s", dns_server_feature_level_to_string(server->possible_feature_level)));
749

750
        server->warned_downgrade = true;
1✔
751
}
752

753
size_t dns_server_get_mtu(DnsServer *s) {
565✔
754
        assert(s);
565✔
755

756
        if (s->link && s->link->mtu != 0)
565✔
757
                return s->link->mtu;
151✔
758

759
        return manager_find_mtu(s->manager);
414✔
760
}
761

762
static void dns_server_hash_func(const DnsServer *s, struct siphash *state) {
113,819✔
763
        assert(s);
113,819✔
764

765
        siphash24_compress_typesafe(s->family, state);
113,819✔
766
        in_addr_hash_func(&s->address, s->family, state);
113,819✔
767
        siphash24_compress_typesafe(s->port, state);
113,819✔
768
        siphash24_compress_typesafe(s->ifindex, state);
113,819✔
769
        siphash24_compress_string(s->server_name, state);
113,819✔
770
}
113,819✔
771

772
static int dns_server_compare_func(const DnsServer *x, const DnsServer *y) {
29,037✔
773
        int r;
29,037✔
774

775
        r = CMP(x->family, y->family);
29,037✔
776
        if (r != 0)
15,843✔
777
                return r;
13,194✔
778

779
        r = memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
15,843✔
780
        if (r != 0)
15,843✔
781
                return r;
782

783
        r = CMP(x->port, y->port);
17✔
784
        if (r != 0)
17✔
785
                return r;
×
786

787
        r = CMP(x->ifindex, y->ifindex);
17✔
788
        if (r != 0)
17✔
789
                return r;
×
790

791
        return streq_ptr(x->server_name, y->server_name);
17✔
792
}
793

794
DEFINE_HASH_OPS(dns_server_hash_ops, DnsServer, dns_server_hash_func, dns_server_compare_func);
795

796
void dns_server_unlink_all(DnsServer *first) {
5,688✔
797
        DnsServer *next;
5,688✔
798

799
        if (!first)
5,688✔
800
                return;
801

802
        next = first->servers_next;
1,086✔
803
        dns_server_unlink(first);
1,086✔
804

805
        dns_server_unlink_all(next);
1,086✔
806
}
807

808
void dns_server_unlink_on_reload(DnsServer *server) {
36✔
809
        while (server) {
116✔
810
                DnsServer *next = server->servers_next;
80✔
811

812
                if (server->config_source == RESOLVE_CONFIG_SOURCE_FILE)
80✔
813
                        dns_server_unlink(server);
80✔
814

815
                server = next;
816
        }
817
}
36✔
818

819
bool dns_server_unlink_marked(DnsServer *server) {
224✔
820
        bool changed = false;
224✔
821

822
        while (server) {
658✔
823
                DnsServer *next;
434✔
824

825
                next = server->servers_next;
434✔
826

827
                if (server->marked) {
434✔
828
                        dns_server_unlink(server);
36✔
829
                        changed = true;
36✔
830
                }
831

832
                server = next;
833
        }
834

835
        return changed;
224✔
836
}
837

838
void dns_server_mark_all(DnsServer *server) {
224✔
839
        while (server) {
499✔
840
                server->marked = true;
275✔
841
                server = server->servers_next;
275✔
842
        }
843
}
224✔
844

845
DnsServer *dns_server_find(DnsServer *first, int family, const union in_addr_union *in_addr, uint16_t port, int ifindex, const char *name) {
1,441✔
846
        LIST_FOREACH(servers, s, first)
4,183✔
847
                if (s->family == family &&
4,367✔
848
                    in_addr_equal(family, &s->address, in_addr) > 0 &&
1,386✔
849
                    s->port == port &&
241✔
850
                    s->ifindex == ifindex &&
239✔
851
                    streq_ptr(s->server_name, name))
239✔
852
                        return s;
853

854
        return NULL;
855
}
856

857
static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) {
1,043✔
858
        _cleanup_free_ char *server_name = NULL;
1,043✔
859
        union in_addr_union address;
1,043✔
860
        int family, r, ifindex = 0;
1,043✔
861
        uint16_t port;
1,043✔
862
        DnsServer *s;
1,043✔
863

864
        assert(m);
1,043✔
865
        assert(word);
1,043✔
866

867
        r = in_addr_port_ifindex_name_from_string_auto(word, &family, &address, &port, &ifindex, &server_name);
1,043✔
868
        if (r < 0)
1,043✔
869
                return r;
870

871
        /* Silently filter out 0.0.0.0, 127.0.0.53, 127.0.0.54 (our own stub DNS listener) */
872
        if (!dns_server_address_valid(family, &address))
1,043✔
873
                return 0;
874

875
        /* By default, the port number is determined with the transaction feature level.
876
         * See dns_transaction_port() and dns_server_port(). */
877
        if (IN_SET(port, 53, 853))
1,043✔
878
                port = 0;
×
879

880
        /* Filter out duplicates */
881
        s = dns_server_find(manager_get_first_dns_server(m, type), family, &address, port, ifindex, server_name);
1,043✔
882
        if (s) {
1,043✔
883
                /* Drop the marker. This is used to find the servers that ceased to exist, see
884
                 * manager_mark_dns_servers() and manager_flush_marked_dns_servers(). */
885
                dns_server_move_back_and_unmark(s);
×
886
                return 0;
887
        }
888

889
        return dns_server_new(m, NULL, type, NULL, family, &address, port, ifindex, server_name, RESOLVE_CONFIG_SOURCE_FILE);
1,043✔
890
}
891

892
int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) {
178✔
893
        int r;
178✔
894

895
        assert(m);
178✔
896
        assert(string);
178✔
897

898
        for (;;) {
2,264✔
899
                _cleanup_free_ char *word = NULL;
1,221✔
900

901
                r = extract_first_word(&string, &word, NULL, 0);
1,221✔
902
                if (r <= 0)
1,221✔
903
                        return r;
178✔
904

905
                r = manager_add_dns_server_by_string(m, type, word);
1,043✔
906
                if (r < 0)
1,043✔
907
                        log_warning_errno(r, "Failed to add DNS server address '%s', ignoring: %m", word);
1,043✔
908
        }
909
}
910

911
static int manager_add_search_domain_by_string(Manager *m, const char *domain) {
1✔
912
        DnsSearchDomain *d;
1✔
913
        bool route_only;
1✔
914
        int r;
1✔
915

916
        assert(m);
1✔
917
        assert(domain);
1✔
918

919
        route_only = *domain == '~';
1✔
920
        if (route_only)
1✔
921
                domain++;
×
922

923
        if (dns_name_is_root(domain) || streq(domain, "*")) {
1✔
924
                route_only = true;
×
925
                domain = ".";
×
926
        }
927

928
        r = dns_search_domain_find(m->search_domains, domain, &d);
1✔
929
        if (r < 0)
1✔
930
                return r;
1✔
931
        if (r > 0)
1✔
932
                dns_search_domain_move_back_and_unmark(d);
×
933
        else {
934
                r = dns_search_domain_new(m, &d, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain);
1✔
935
                if (r < 0)
1✔
936
                        return r;
937
        }
938

939
        d->route_only = route_only;
1✔
940
        return 0;
1✔
941
}
942

943
int manager_parse_search_domains_and_warn(Manager *m, const char *string) {
1✔
944
        int r;
1✔
945

946
        assert(m);
1✔
947
        assert(string);
1✔
948

949
        for (;;) {
3✔
950
                _cleanup_free_ char *word = NULL;
2✔
951

952
                r = extract_first_word(&string, &word, NULL, EXTRACT_UNQUOTE);
2✔
953
                if (r <= 0)
2✔
954
                        return r;
1✔
955

956
                r = manager_add_search_domain_by_string(m, word);
1✔
957
                if (r < 0)
1✔
958
                        log_warning_errno(r, "Failed to add search domain '%s', ignoring: %m", word);
1✔
959
        }
960
}
961

962
DnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t) {
1,051✔
963
        assert(m);
1,051✔
964

965
        switch (t) {
1,051✔
966

967
        case DNS_SERVER_SYSTEM:
8✔
968
                return m->dns_servers;
8✔
969

970
        case DNS_SERVER_FALLBACK:
1,043✔
971
                return m->fallback_dns_servers;
1,043✔
972

973
        default:
974
                return NULL;
975
        }
976
}
977

978
DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
9,452✔
979
        assert(m);
9,452✔
980

981
        if (m->current_dns_server == s)
9,452✔
982
                return s;
983

984
        /* Let's log about the server switch, at debug level. Except if we switch from a non-fallback server
985
         * to a fallback server or back, since that is noteworthy and possibly a configuration issue */
986
        if (s)
8,892✔
987
                log_full((s->type == DNS_SERVER_FALLBACK) != (m->current_dns_server && m->current_dns_server->type == DNS_SERVER_FALLBACK) ? LOG_NOTICE : LOG_DEBUG,
17,607✔
988
                         "Switching to %s DNS server %s.", dns_server_type_to_string(s->type), strna(dns_server_string_full(s)));
989

990
        dns_server_unref(m->current_dns_server);
8,892✔
991
        m->current_dns_server = dns_server_ref(s);
8,892✔
992

993
        if (m->unicast_scope)
8,892✔
994
                dns_cache_flush(&m->unicast_scope->cache);
8,889✔
995

996
        (void) manager_send_changed(m, "CurrentDNSServer");
8,892✔
997
        (void) manager_send_dns_configuration_changed(m, NULL, /* reset= */ false);
8,892✔
998

999
        return s;
8,892✔
1000
}
1001

1002
DnsServer *manager_get_dns_server(Manager *m) {
21,782✔
1003
        Link *l;
21,782✔
1004
        assert(m);
21,782✔
1005

1006
        /* Try to read updates resolv.conf */
1007
        manager_read_resolv_conf(m);
21,782✔
1008

1009
        /* If no DNS server was chosen so far, pick the first one */
1010
        if (!m->current_dns_server ||
43,032✔
1011
            /* In case m->current_dns_server != m->dns_servers */
1012
            manager_server_is_stub(m, m->current_dns_server))
21,250✔
1013
                manager_set_dns_server(m, m->dns_servers);
532✔
1014

1015
        while (m->current_dns_server &&
43,035✔
1016
               manager_server_is_stub(m, m->current_dns_server)) {
21,253✔
1017
                manager_next_dns_server(m, NULL);
×
1018
                if (m->current_dns_server == m->dns_servers)
×
1019
                        manager_set_dns_server(m, NULL);
×
1020
        }
1021

1022
        if (!m->current_dns_server) {
21,782✔
1023
                bool found = false;
529✔
1024

1025
                /* No DNS servers configured, let's see if there are
1026
                 * any on any links. If not, we use the fallback
1027
                 * servers */
1028

1029
                HASHMAP_FOREACH(l, m->links)
1,886✔
1030
                        if (l->dns_servers && l->default_route) {
1,771✔
1031
                                found = true;
1032
                                break;
1033
                        }
1034

1035
                if (!found)
529✔
1036
                        manager_set_dns_server(m, m->fallback_dns_servers);
115✔
1037
        }
1038

1039
        return m->current_dns_server;
21,782✔
1040
}
1041

1042
void manager_next_dns_server(Manager *m, DnsServer *if_current) {
8,986✔
1043
        assert(m);
8,986✔
1044

1045
        /* If the DNS server is already a different one than the one specified in 'if_current' don't do anything */
1046
        if (if_current && m->current_dns_server != if_current)
8,986✔
1047
                return;
1048

1049
        /* If there's currently no DNS server set, then the next manager_get_dns_server() will find one */
1050
        if (!m->current_dns_server)
8,709✔
1051
                return;
1052

1053
        /* Change to the next one, but make sure to follow the linked list only if the server is still
1054
         * linked. */
1055
        if (m->current_dns_server->linked && m->current_dns_server->servers_next) {
8,709✔
1056
                manager_set_dns_server(m, m->current_dns_server->servers_next);
7,278✔
1057
                return;
7,278✔
1058
        }
1059

1060
        /* If there was no next one, then start from the beginning of the list */
1061
        if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
1,431✔
1062
                manager_set_dns_server(m, m->fallback_dns_servers);
1,431✔
1063
        else
1064
                manager_set_dns_server(m, m->dns_servers);
×
1065
}
1066

1067
DnssecMode dns_server_get_dnssec_mode(DnsServer *s) {
20,098✔
1068
        assert(s);
20,098✔
1069

1070
        if (s->link)
20,098✔
1071
                return link_get_dnssec_mode(s->link);
1,980✔
1072

1073
        return manager_get_dnssec_mode(s->manager);
18,118✔
1074
}
1075

1076
DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s) {
10,086✔
1077
        assert(s);
10,086✔
1078

1079
        if (s->link)
10,086✔
1080
                return link_get_dns_over_tls_mode(s->link);
1,023✔
1081

1082
        return manager_get_dns_over_tls_mode(s->manager);
9,063✔
1083
}
1084

1085
void dns_server_flush_cache(DnsServer *s) {
×
1086
        DnsServer *current;
×
1087
        DnsScope *scope;
×
1088

1089
        assert(s);
×
1090

1091
        /* Flush the cache of the scope this server belongs to */
1092

1093
        current = s->link ? s->link->current_dns_server : s->manager->current_dns_server;
×
1094
        if (current != s)
×
1095
                return;
1096

1097
        scope = s->link ? s->link->unicast_scope : s->manager->unicast_scope;
×
1098
        if (!scope)
×
1099
                return;
1100

1101
        dns_cache_flush(&scope->cache);
×
1102
}
1103

1104
void dns_server_reset_features(DnsServer *s) {
6,583✔
1105
        assert(s);
6,583✔
1106

1107
        s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
6,583✔
1108
        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST;
6,583✔
1109

1110
        s->received_udp_fragment_max = DNS_PACKET_UNICAST_SIZE_MAX;
6,583✔
1111

1112
        s->packet_bad_opt = false;
6,583✔
1113
        s->packet_rrsig_missing = false;
6,583✔
1114
        s->packet_do_off = false;
6,583✔
1115

1116
        s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC;
6,583✔
1117

1118
        s->warned_downgrade = false;
6,583✔
1119

1120
        dns_server_reset_counters(s);
6,583✔
1121

1122
        /* Let's close the default stream, so that we reprobe with the new features */
1123
        dns_server_unref_stream(s);
6,583✔
1124
}
6,583✔
1125

1126
void dns_server_reset_features_all(DnsServer *s) {
1,869✔
1127
        LIST_FOREACH(servers, i, s)
7,240✔
1128
                dns_server_reset_features(i);
5,371✔
1129
}
1,869✔
1130

1131
void dns_server_dump(DnsServer *s, FILE *f) {
×
1132
        assert(s);
×
1133

1134
        if (!f)
×
1135
                f = stdout;
×
1136

1137
        fputs("[Server ", f);
×
1138
        fputs(strna(dns_server_string_full(s)), f);
×
1139
        fputs(" type=", f);
×
1140
        fputs(dns_server_type_to_string(s->type), f);
×
1141

1142
        if (s->type == DNS_SERVER_LINK) {
×
1143
                assert(s->link);
×
1144

1145
                fputs(" interface=", f);
×
1146
                fputs(s->link->ifname, f);
×
1147
        }
1148

1149
        fputs("]\n", f);
×
1150

1151
        fputs("\tVerified feature level: ", f);
×
1152
        fputs(strna(dns_server_feature_level_to_string(s->verified_feature_level)), f);
×
1153
        fputc('\n', f);
×
1154

1155
        fputs("\tPossible feature level: ", f);
×
1156
        fputs(strna(dns_server_feature_level_to_string(s->possible_feature_level)), f);
×
1157
        fputc('\n', f);
×
1158

1159
        fputs("\tDNSSEC Mode: ", f);
×
1160
        fputs(strna(dnssec_mode_to_string(dns_server_get_dnssec_mode(s))), f);
×
1161
        fputc('\n', f);
×
1162

1163
        fputs("\tCan do DNSSEC: ", f);
×
1164
        fputs(yes_no(dns_server_dnssec_supported(s)), f);
×
1165
        fputc('\n', f);
×
1166

1167
        fprintf(f,
×
1168
                "\tMaximum UDP fragment size received: %zu\n"
1169
                "\tFailed UDP attempts: %u\n"
1170
                "\tFailed TCP attempts: %u\n"
1171
                "\tSeen truncated packet: %s\n"
1172
                "\tSeen OPT RR getting lost: %s\n"
1173
                "\tSeen RRSIG RR missing: %s\n"
1174
                "\tSeen invalid packet: %s\n"
1175
                "\tServer dropped DO flag: %s\n",
1176
                s->received_udp_fragment_max,
1177
                s->n_failed_udp,
1178
                s->n_failed_tcp,
1179
                yes_no(s->packet_truncated),
×
1180
                yes_no(s->packet_bad_opt),
×
1181
                yes_no(s->packet_rrsig_missing),
×
1182
                yes_no(s->packet_invalid),
×
1183
                yes_no(s->packet_do_off));
×
1184
}
×
1185

1186
void dns_server_unref_stream(DnsServer *s) {
9,129✔
1187
        DnsStream *ref;
9,129✔
1188

1189
        assert(s);
9,129✔
1190

1191
        /* Detaches the default stream of this server. Some special care needs to be taken here, as that stream and
1192
         * this server reference each other. First, take the stream out of the server. It's destructor will check if it
1193
         * is registered with us, hence let's invalidate this separately, so that it is already unregistered. */
1194
        ref = TAKE_PTR(s->stream);
9,129✔
1195

1196
        /* And then, unref it */
1197
        dns_stream_unref(ref);
9,129✔
1198
}
9,129✔
1199

1200
DnsScope *dns_server_scope(DnsServer *s) {
52,681✔
1201
        assert(s);
52,681✔
1202
        assert((s->type == DNS_SERVER_LINK) == !!s->link);
52,681✔
1203

1204
        if (s->link)
52,681✔
1205
                return s->link->unicast_scope;
676✔
1206

1207
        return s->manager->unicast_scope;
52,005✔
1208
}
1209

1210
static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = {
1211
        [DNS_SERVER_SYSTEM]   = "system",
1212
        [DNS_SERVER_FALLBACK] = "fallback",
1213
        [DNS_SERVER_LINK]     = "link",
1214
};
1215
DEFINE_STRING_TABLE_LOOKUP(dns_server_type, DnsServerType);
8,808✔
1216

1217
static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVEL_MAX] = {
1218
        [DNS_SERVER_FEATURE_LEVEL_TCP]       = "TCP",
1219
        [DNS_SERVER_FEATURE_LEVEL_UDP]       = "UDP",
1220
        [DNS_SERVER_FEATURE_LEVEL_EDNS0]     = "UDP+EDNS0",
1221
        [DNS_SERVER_FEATURE_LEVEL_TLS_PLAIN] = "TLS+EDNS0",
1222
        [DNS_SERVER_FEATURE_LEVEL_DO]        = "UDP+EDNS0+DO",
1223
        [DNS_SERVER_FEATURE_LEVEL_TLS_DO]    = "TLS+EDNS0+DO",
1224
};
1225
DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level, DnsServerFeatureLevel);
10,021✔
1226

1227
int dns_server_dump_state_to_json(DnsServer *server, sd_json_variant **ret) {
6✔
1228

1229
        assert(server);
6✔
1230
        assert(ret);
6✔
1231

1232
        return sd_json_buildo(
6✔
1233
                        ret,
1234
                        SD_JSON_BUILD_PAIR_STRING("Server", strna(dns_server_string_full(server))),
1235
                        SD_JSON_BUILD_PAIR_STRING("Type", strna(dns_server_type_to_string(server->type))),
1236
                        SD_JSON_BUILD_PAIR_CONDITION(server->type == DNS_SERVER_LINK, "Interface", SD_JSON_BUILD_STRING(server->link ? server->link->ifname : NULL)),
1237
                        SD_JSON_BUILD_PAIR_CONDITION(server->type == DNS_SERVER_LINK, "InterfaceIndex", SD_JSON_BUILD_UNSIGNED(server->link ? server->link->ifindex : 0)),
1238
                        SD_JSON_BUILD_PAIR_STRING("VerifiedFeatureLevel", strna(dns_server_feature_level_to_string(server->verified_feature_level))),
1239
                        SD_JSON_BUILD_PAIR_STRING("PossibleFeatureLevel", strna(dns_server_feature_level_to_string(server->possible_feature_level))),
1240
                        SD_JSON_BUILD_PAIR_STRING("DNSSECMode", strna(dnssec_mode_to_string(dns_server_get_dnssec_mode(server)))),
1241
                        SD_JSON_BUILD_PAIR_BOOLEAN("DNSSECSupported", dns_server_dnssec_supported(server)),
1242
                        SD_JSON_BUILD_PAIR_UNSIGNED("ReceivedUDPFragmentMax", server->received_udp_fragment_max),
1243
                        SD_JSON_BUILD_PAIR_UNSIGNED("FailedUDPAttempts", server->n_failed_udp),
1244
                        SD_JSON_BUILD_PAIR_UNSIGNED("FailedTCPAttempts", server->n_failed_tcp),
1245
                        SD_JSON_BUILD_PAIR_BOOLEAN("PacketTruncated", server->packet_truncated),
1246
                        SD_JSON_BUILD_PAIR_BOOLEAN("PacketBadOpt", server->packet_bad_opt),
1247
                        SD_JSON_BUILD_PAIR_BOOLEAN("PacketRRSIGMissing", server->packet_rrsig_missing),
1248
                        SD_JSON_BUILD_PAIR_BOOLEAN("PacketInvalid", server->packet_invalid),
1249
                        SD_JSON_BUILD_PAIR_BOOLEAN("PacketDoOff", server->packet_do_off));
1250
}
1251

1252
int dns_server_is_accessible(DnsServer *s) {
83✔
1253
        _cleanup_close_ int fd = -EBADF;
83✔
1254
        union sockaddr_union sa;
83✔
1255
        int r;
83✔
1256

1257
        assert(s);
83✔
1258

1259
        if (s->accessible >= 0)
83✔
1260
                return s->accessible;
1261

1262
        r = sockaddr_set_in_addr(&sa, s->family, &s->address, dns_server_port(s));
44✔
1263
        if (r < 0)
44✔
1264
                return r;
1265

1266
        fd = socket(s->family, SOCK_DGRAM|SOCK_CLOEXEC, 0);
44✔
1267
        if (fd < 0)
44✔
1268
                return -errno;
×
1269

1270
        if (s->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &s->address)) {
44✔
1271
                /* Connecting to ipv6 link-local requires binding to an interface. */
1272
                r = socket_bind_to_ifindex(fd, dns_server_ifindex(s));
×
1273
                if (r < 0)
×
1274
                        return r;
1275
        }
1276

1277
        r = RET_NERRNO(connect(fd, &sa.sa, SOCKADDR_LEN(sa)));
44✔
1278
        if (!IN_SET(r,
44✔
1279
                    0,
1280
                    -ENETUNREACH,
1281
                    -EHOSTDOWN,
1282
                    -EHOSTUNREACH,
1283
                    -ENETDOWN,
1284
                    -ENETRESET,
1285
                    -ENONET))
1286
                /* If we did not receive one of the expected return values,
1287
                 * then leave the accessible flag untouched. */
1288
                return r;
1289

1290
        return (s->accessible = r >= 0);
44✔
1291
}
1292

1293
void dns_server_reset_accessible_all(DnsServer *first) {
306✔
1294
        LIST_FOREACH(servers, s, first)
710✔
1295
                dns_server_reset_accessible(s);
404✔
1296
}
306✔
1297

1298
int dns_server_dump_configuration_to_json(DnsServer *server, sd_json_variant **ret) {
83✔
1299
        bool accessible = false;
83✔
1300
        int ifindex, r;
83✔
1301

1302
        assert(server);
83✔
1303
        assert(ret);
83✔
1304

1305
        ifindex = dns_server_ifindex(server);
83✔
1306

1307
        r = dns_server_is_accessible(server);
83✔
1308
        if (r < 0)
83✔
1309
                log_debug_errno(r, "Failed to check if %s is accessible, assume not: %m", dns_server_string_full(server));
×
1310
        else
1311
                accessible = r;
83✔
1312

1313
        return sd_json_buildo(
83✔
1314
                        ret,
1315
                        JSON_BUILD_PAIR_IN_ADDR("address", &server->address, server->family),
1316
                        SD_JSON_BUILD_PAIR_INTEGER("family", server->family),
1317
                        SD_JSON_BUILD_PAIR_UNSIGNED("port", dns_server_port(server)),
1318
                        SD_JSON_BUILD_PAIR_CONDITION(ifindex > 0, "ifindex", SD_JSON_BUILD_UNSIGNED(ifindex)),
1319
                        JSON_BUILD_PAIR_STRING_NON_EMPTY("name", server->server_name),
1320
                        SD_JSON_BUILD_PAIR_BOOLEAN("accessible", accessible));
1321
}
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