Coverage Report

Created: 2026-06-09 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/adb.c
Line
Count
Source
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
5
 *
6
 * This Source Code Form is subject to the terms of the Mozilla Public
7
 * License, v. 2.0. If a copy of the MPL was not distributed with this
8
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9
 *
10
 * See the COPYRIGHT file distributed with this work for additional
11
 * information regarding copyright ownership.
12
 */
13
14
/*! \file */
15
16
#include <inttypes.h>
17
#include <limits.h>
18
#include <stdbool.h>
19
20
#include <isc/async.h>
21
#include <isc/atomic.h>
22
#include <isc/attributes.h>
23
#include <isc/hash.h>
24
#include <isc/hashmap.h>
25
#include <isc/list.h>
26
#include <isc/log.h>
27
#include <isc/loop.h>
28
#include <isc/mutex.h>
29
#include <isc/netaddr.h>
30
#include <isc/os.h>
31
#include <isc/random.h>
32
#include <isc/result.h>
33
#include <isc/rwlock.h>
34
#include <isc/sieve.h>
35
#include <isc/stats.h>
36
#include <isc/string.h>
37
#include <isc/tid.h>
38
#include <isc/urcu.h>
39
#include <isc/util.h>
40
41
#include <dns/adb.h>
42
#include <dns/db.h>
43
#include <dns/rdata.h>
44
#include <dns/rdatastruct.h>
45
#include <dns/rdatatype.h>
46
#include <dns/stats.h>
47
#include <dns/transport.h>
48
#include <dns/types.h>
49
50
0
#define DNS_ADB_MAGIC    ISC_MAGIC('D', 'a', 'd', 'b')
51
#define DNS_ADB_VALID(x)   ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
52
0
#define DNS_ADBNAME_MAGIC  ISC_MAGIC('a', 'd', 'b', 'N')
53
#define DNS_ADBNAME_VALID(x)   ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
54
0
#define DNS_ADBNAMEHOOK_MAGIC  ISC_MAGIC('a', 'd', 'N', 'H')
55
#define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
56
0
#define DNS_ADBENTRY_MAGIC   ISC_MAGIC('a', 'd', 'b', 'E')
57
#define DNS_ADBENTRY_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
58
0
#define DNS_ADBFETCH_MAGIC   ISC_MAGIC('a', 'd', 'F', '4')
59
#define DNS_ADBFETCH_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
60
#define DNS_ADBFETCH6_MAGIC  ISC_MAGIC('a', 'd', 'F', '6')
61
#define DNS_ADBFETCH6_VALID(x)   ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
62
63
/*!
64
 * For type 3 negative cache entries, we will remember that the address is
65
 * broken for this long.  XXXMLG This is also used for actual addresses, too.
66
 */
67
0
#define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */
68
69
0
#define ADB_HASH_SIZE (1 << 12)
70
71
/*%
72
 * The period in seconds after which an ADB name entry is regarded as stale
73
 * and forced to be cleaned up.
74
 * TODO: This should probably be configurable at run-time.
75
 */
76
#ifndef ADB_STALE_MARGIN
77
#define ADB_STALE_MARGIN 1800
78
#endif /* ifndef ADB_STALE_MARGIN */
79
80
typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
81
typedef struct dns_adbnamehook dns_adbnamehook_t;
82
typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
83
typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
84
typedef struct dns_adbfetch dns_adbfetch_t;
85
typedef struct dns_adbfetch6 dns_adbfetch6_t;
86
87
typedef struct dns_adblru {
88
  ISC_SIEVE(dns_adbname_t) names;
89
  ISC_SIEVE(dns_adbentry_t) entries;
90
91
  uint8_t __padding[ISC_OS_CACHELINE_SIZE -
92
        (sizeof(ISC_SIEVE(dns_adbname_t)) +
93
         sizeof(ISC_SIEVE(dns_adbentry_t))) %
94
          ISC_OS_CACHELINE_SIZE];
95
} dns_adblru_t;
96
97
/*% dns adb structure */
98
struct dns_adb {
99
  unsigned int magic;
100
  uint32_t nloops;
101
102
  isc_mutex_t lock;
103
  isc_mem_t *mctx;
104
  isc_mem_t *hmctx;
105
  dns_view_t *view;
106
  dns_resolver_t *res;
107
108
  isc_refcount_t references;
109
110
  dns_adblru_t *lru;
111
112
  struct cds_lfht *names_ht;
113
  struct cds_lfht *entries_ht;
114
115
  isc_stats_t *stats;
116
117
  atomic_bool shuttingdown;
118
119
  uint32_t quota;
120
  uint32_t atr_freq;
121
  double atr_low;
122
  double atr_high;
123
  double atr_discount;
124
125
  struct rcu_head rcu_head;
126
};
127
128
/*%
129
 * dns_adbname structure:
130
 *
131
 * This is the structure representing a nameserver name; it can be looked
132
 * up via the adb->names hash table. It holds references to fetches
133
 * for A and AAAA records while they are ongoing (fetch_a, fetch_aaaa), and
134
 * lists of records pointing to address information when the fetches are
135
 * complete (v4, v6).
136
 */
137
struct dns_adbname {
138
  unsigned int magic;
139
  isc_refcount_t references;
140
  dns_adb_t *adb;
141
  dns_fixedname_t fname;
142
  dns_name_t *name;
143
  unsigned int partial_result;
144
  unsigned int flags;
145
  unsigned int type;
146
  isc_stdtime_t expire_v4;
147
  isc_stdtime_t expire_v6;
148
  dns_adbnamehooklist_t v4;
149
  dns_adbnamehooklist_t v6;
150
  dns_adbfetch_t *fetch_a;
151
  dns_adbfetch_t *fetch_aaaa;
152
  unsigned int fetch_err;
153
  unsigned int fetch6_err;
154
  dns_adbfindlist_t finds;
155
  isc_mutex_t lock;
156
157
  /* for LFHT */
158
  struct cds_lfht_node ht_node;
159
160
  /* for LRU-based management */
161
  ISC_LINK(dns_adbname_t) link;
162
  bool visited;
163
164
  isc_loop_t *loop;
165
  struct rcu_head rcu_head;
166
  struct cds_list_head lru_head;
167
};
168
169
#if DNS_ADB_TRACE
170
#define dns_adbname_ref(ptr) dns_adbname__ref(ptr, __func__, __FILE__, __LINE__)
171
#define dns_adbname_unref(ptr) \
172
  dns_adbname__unref(ptr, __func__, __FILE__, __LINE__)
173
#define dns_adbname_attach(ptr, ptrp) \
174
  dns_adbname__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
175
#define dns_adbname_detach(ptrp) \
176
  dns_adbname__detach(ptrp, __func__, __FILE__, __LINE__)
177
ISC_REFCOUNT_TRACE_DECL(dns_adbname);
178
#else
179
ISC_REFCOUNT_DECL(dns_adbname);
180
#endif
181
182
/*%
183
 * dns_adbfetch structure:
184
 * Stores the state for an ongoing A or AAAA fetch.
185
 */
186
struct dns_adbfetch {
187
  unsigned int magic;
188
  dns_fetch_t *fetch;
189
  dns_rdataset_t rdataset;
190
  unsigned int depth;
191
};
192
193
/*%
194
 * dns_adbnamehook structure:
195
 *
196
 * This is a small widget that dangles off a dns_adbname_t.  It contains a
197
 * pointer to the address information about this host, and a link to the next
198
 * namehook that will contain the next address this host has.
199
 */
200
struct dns_adbnamehook {
201
  unsigned int magic;
202
  dns_adbentry_t *entry;
203
  ISC_LINK(dns_adbnamehook_t) name_link;
204
  ISC_LINK(dns_adbnamehook_t) entry_link;
205
};
206
207
/*%
208
 * dns_adbentry structure:
209
 *
210
 * This is the structure representing a nameserver address; it can be looked
211
 * up via the adb->entries hash table. Also, each dns_adbnamehook and
212
 * and dns_adbaddrinfo object will contain a pointer to one of these.
213
 *
214
 * The structure holds quite a bit of information about addresses,
215
 * including edns state (in "flags"), RTT, and of course the address of
216
 * the host.
217
 */
218
struct dns_adbentry {
219
  unsigned int magic;
220
221
  dns_adb_t *adb;
222
223
  isc_mutex_t lock;
224
225
  isc_refcount_t references;
226
  dns_adbnamehooklist_t nhs;
227
228
  atomic_uint flags;
229
  atomic_uint srtt;
230
  unsigned int completed;
231
  unsigned int timeouts;
232
  unsigned char plain;
233
  unsigned char plainto;
234
  unsigned char edns;
235
  unsigned char ednsto;
236
  uint16_t udpsize;
237
238
  uint8_t mode;
239
  atomic_uint_fast32_t quota;
240
  atomic_uint_fast32_t active;
241
  double atr;
242
243
  isc_sockaddr_t sockaddr;
244
  unsigned char *cookie;
245
  uint16_t cookielen;
246
247
  isc_stdtime_t expires;
248
  _Atomic(isc_stdtime_t) lastage;
249
  /*%<
250
   * A nonzero 'expires' field indicates that the entry should
251
   * persist until that time.  This allows entries found
252
   * using dns_adb_findaddrinfo() to persist for a limited time
253
   * even though they are not necessarily associated with a
254
   * entry.
255
   */
256
257
  struct cds_lfht_node ht_node;
258
259
  ISC_LINK(dns_adbentry_t) link;
260
  bool visited;
261
262
  isc_loop_t *loop;
263
  struct rcu_head rcu_head;
264
  struct cds_list_head lru_head;
265
};
266
267
#if DNS_ADB_TRACE
268
#define dns_adbentry_ref(ptr) \
269
  dns_adbentry__ref(ptr, __func__, __FILE__, __LINE__)
270
#define dns_adbentry_unref(ptr) \
271
  dns_adbentry__unref(ptr, __func__, __FILE__, __LINE__)
272
#define dns_adbentry_attach(ptr, ptrp) \
273
  dns_adbentry__attach(ptr, ptrp, __func__, __FILE__, __LINE__)
274
#define dns_adbentry_detach(ptrp) \
275
  dns_adbentry__detach(ptrp, __func__, __FILE__, __LINE__)
276
ISC_REFCOUNT_TRACE_DECL(dns_adbentry);
277
#else
278
ISC_REFCOUNT_DECL(dns_adbentry);
279
#endif
280
281
/*
282
 * ADB settings that can be tweaked with named -T option
283
 */
284
unsigned int dns_adb_entrywindow = 60;
285
unsigned int dns_adb_cachemin = 10;
286
287
/*
288
 * Internal functions (and prototypes).
289
 */
290
static dns_adbname_t *
291
new_adbname(dns_adb_t *adb, const dns_name_t *, unsigned int type);
292
static void
293
destroy_adbname(dns_adbname_t *);
294
static int
295
match_adbname(struct cds_lfht_node *ht_node, const void *key);
296
static uint32_t
297
hash_adbname(const dns_adbname_t *adbname);
298
static dns_adbnamehook_t *
299
new_adbnamehook(dns_adb_t *adb);
300
static void
301
free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehookp);
302
static dns_adbentry_t *
303
new_adbentry(dns_adb_t *adb, const isc_sockaddr_t *addr, isc_stdtime_t now);
304
static void
305
destroy_adbentry(dns_adbentry_t *entry);
306
static int
307
match_adbentry(struct cds_lfht_node *ht_node, const void *key);
308
static dns_adbfind_t *
309
new_adbfind(dns_adb_t *, in_port_t);
310
static void
311
free_adbfind(dns_adbfind_t **);
312
static dns_adbaddrinfo_t *
313
new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *, in_port_t);
314
static dns_adbfetch_t *
315
new_adbfetch(dns_adb_t *);
316
static void
317
free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
318
static void
319
purge_names_overmem(dns_adb_t *adb, size_t requested);
320
static dns_adbname_t *
321
get_attached_and_locked_name(dns_adb_t *, const dns_name_t *, unsigned int type,
322
           isc_stdtime_t now);
323
static void
324
purge_entries_overmem(dns_adb_t *adb, size_t requested);
325
static dns_adbentry_t *
326
get_attached_and_locked_entry(dns_adb_t *adb, isc_stdtime_t now,
327
            const isc_sockaddr_t *addr);
328
static void
329
dump_adb(dns_adb_t *, FILE *, bool debug, isc_stdtime_t);
330
static void
331
print_namehook_list(FILE *, const char *legend, dns_adb_t *adb,
332
        dns_adbnamehooklist_t *list, bool debug, isc_stdtime_t now);
333
static void
334
print_find_list(FILE *, dns_adbname_t *);
335
static void
336
print_fetch_list(FILE *, dns_adbname_t *);
337
static void
338
clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);
339
static void
340
clean_finds_at_name(dns_adbname_t *, dns_adbstatus_t, unsigned int);
341
static void
342
maybe_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
343
static bool
344
name_expired(dns_adbname_t *adbname, isc_stdtime_t now);
345
static bool
346
maybe_expire_name(dns_adbname_t *adbname, isc_stdtime_t now);
347
static void
348
expire_name(dns_adbname_t *adbname, dns_adbstatus_t astat);
349
static bool
350
entry_expired(dns_adbentry_t *adbentry, isc_stdtime_t now);
351
static bool
352
maybe_expire_entry(dns_adbentry_t *adbentry, isc_stdtime_t now);
353
static void
354
expire_entry(dns_adbentry_t *adbentry);
355
static isc_result_t
356
dbfind_name(dns_adbname_t *, isc_stdtime_t, dns_rdatatype_t);
357
static isc_result_t
358
fetch_name(dns_adbname_t *, bool, bool, unsigned int, isc_counter_t *qc,
359
     isc_counter_t *gqc, fetchctx_t *parent, dns_rdatatype_t);
360
static void
361
shutdown_names(dns_adb_t *);
362
static void
363
shutdown_entries(dns_adb_t *);
364
static void
365
dump_entry(FILE *, dns_adb_t *, dns_adbentry_t *, bool, isc_stdtime_t);
366
static void
367
adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor,
368
     isc_stdtime_t now);
369
static void
370
log_quota(dns_adbentry_t *entry, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
371
372
static bool
373
adbentry_overquota(dns_adbentry_t *entry);
374
375
/*
376
 * Private flag(s) for adbfind objects. These are used internally and
377
 * are not meant to be seen or used by the caller; however, we use the
378
 * same flags field as for DNS_ADBFIND_xxx flags, so we must be careful
379
 * that there is no overlap between these values and those. To make it
380
 * easier, we will number these starting from the most significant bit
381
 * instead of the least significant.
382
 */
383
enum {
384
  FIND_EVENT_SENT = 1 << 31,
385
};
386
0
#define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0)
387
388
/*
389
 * Private flag(s) for adbname objects.
390
 */
391
enum {
392
  NAME_IS_ALIAS = 1 << 31,
393
};
394
0
#define NAME_ALIAS(n) (((n)->flags & NAME_IS_ALIAS) != 0)
395
396
/*
397
 * Currently there are no private flags for adbentry objects.
398
 * If we ever use them again, they'll share bit space with the
399
 * addrinfo flags, FCTX_ADDRINFO_xxx, defined in resolver.c, so
400
 * when defining them, they should count back from the most
401
 * significant bit instead of counting up from zero.
402
 */
403
404
/*
405
 * To the name, address classes are all that really exist.  If it has a
406
 * V6 address it doesn't care if it came from a AAAA query.
407
 */
408
0
#define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4))
409
0
#define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6))
410
411
/*
412
 * Fetches are broken out into A and AAAA types.  In some cases,
413
 * however, it makes more sense to test for a particular class of fetches,
414
 * like V4 or V6 above.
415
 */
416
0
#define NAME_FETCH_A(n)    ((n)->fetch_a != NULL)
417
0
#define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL)
418
0
#define NAME_FETCH(n)    (NAME_FETCH_A(n) || NAME_FETCH_AAAA(n))
419
420
/*
421
 * Find options and tests to see if there are addresses on the list.
422
 */
423
0
#define FIND_WANTEVENT(fn)  (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
424
0
#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
425
0
#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) != 0)
426
0
#define FIND_STARTATZONE(fn)  (((fn)->options & DNS_ADBFIND_STARTATZONE) != 0)
427
0
#define FIND_STATICSTUB(fn)   (((fn)->options & DNS_ADBFIND_STATICSTUB) != 0)
428
0
#define FIND_NOVALIDATE(fn)   (((fn)->options & DNS_ADBFIND_NOVALIDATE) != 0)
429
0
#define FIND_HAS_ADDRS(fn)    (!ISC_LIST_EMPTY((fn)->list))
430
0
#define FIND_NOFETCH(fn)      (((fn)->options & DNS_ADBFIND_NOFETCH) != 0)
431
432
#define ADBNAME_TYPE_MASK                                   \
433
0
  (DNS_ADBFIND_STARTATZONE | DNS_ADBFIND_STATICSTUB | \
434
0
   DNS_ADBFIND_NOVALIDATE)
435
436
0
#define ADBNAME_TYPE(options) ((options) & ADBNAME_TYPE_MASK)
437
438
/*
439
 * These are currently used on simple unsigned ints, so they are
440
 * not really associated with any particular type.
441
 */
442
0
#define WANT_INET(x)  (((x) & DNS_ADBFIND_INET) != 0)
443
0
#define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0)
444
445
0
#define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now))
446
447
0
#define ENTER_LEVEL  ISC_LOG_DEBUG(50)
448
#define CLEAN_LEVEL  ISC_LOG_DEBUG(100)
449
0
#define DEF_LEVEL    ISC_LOG_DEBUG(5)
450
0
#define NCACHE_LEVEL ISC_LOG_DEBUG(20)
451
452
#define NCACHE_RESULT(r) \
453
0
  ((r) == DNS_R_NCACHENXDOMAIN || (r) == DNS_R_NCACHENXRRSET)
454
#define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || (r) == DNS_R_NXRRSET)
455
456
/*
457
 * Due to the ttlclamp(), the TTL is never 0 unless the trust is ultimate,
458
 * in which case we need to set the expiration to have immediate effect.
459
 */
460
#define ADJUSTED_EXPIRE(expire, now, ttl)                                    \
461
0
  ((ttl != 0) ? ISC_MIN(expire,                                        \
462
0
            ISC_MAX(now + dns_adb_entrywindow, now + ttl)) \
463
0
        : INT_MAX)
464
465
/*
466
 * Error states.
467
 */
468
enum {
469
  FIND_ERR_SUCCESS = 0,
470
  FIND_ERR_CANCELED,
471
  FIND_ERR_FAILURE,
472
  FIND_ERR_NXDOMAIN,
473
  FIND_ERR_NXRRSET,
474
  FIND_ERR_UNEXPECTED,
475
  FIND_ERR_NOTFOUND,
476
};
477
478
static const char *errnames[] = { "success",  "canceled", "failure",
479
          "nxdomain", "nxrrset",  "unexpected",
480
          "not_found" };
481
482
static isc_result_t find_err_map[] = {
483
  ISC_R_SUCCESS, ISC_R_CANCELED,   ISC_R_FAILURE, DNS_R_NXDOMAIN,
484
  DNS_R_NXRRSET, ISC_R_UNEXPECTED, ISC_R_NOTFOUND /* not YET found */
485
};
486
487
static void
488
DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
489
490
static void
491
0
DP(int level, const char *format, ...) {
492
0
  va_list args;
493
494
0
  va_start(args, format);
495
0
  isc_log_vwrite(DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB, level,
496
0
           format, args);
497
0
  va_end(args);
498
0
}
499
500
/*%
501
 * Increment resolver-related statistics counters.
502
 */
503
static void
504
0
inc_resstats(dns_adb_t *adb, isc_statscounter_t counter) {
505
0
  if (adb->res != NULL) {
506
0
    dns_resolver_incstats(adb->res, counter);
507
0
  }
508
0
}
509
510
/*%
511
 * Set adb-related statistics counters.
512
 */
513
static void
514
0
set_adbstat(dns_adb_t *adb, uint64_t val, isc_statscounter_t counter) {
515
0
  if (adb->stats != NULL) {
516
0
    isc_stats_set(adb->stats, val, counter);
517
0
  }
518
0
}
519
520
static void
521
0
dec_adbstats(dns_adb_t *adb, isc_statscounter_t counter) {
522
0
  if (adb->stats != NULL) {
523
0
    isc_stats_decrement(adb->stats, counter);
524
0
  }
525
0
}
526
527
static void
528
0
inc_adbstats(dns_adb_t *adb, isc_statscounter_t counter) {
529
0
  if (adb->stats != NULL) {
530
0
    isc_stats_increment(adb->stats, counter);
531
0
  }
532
0
}
533
534
static dns_ttl_t
535
0
ttlclamp(dns_ttl_t ttl) {
536
0
  if (ttl < dns_adb_cachemin) {
537
    /*
538
     * Avoid to constantly ask about A/AAAA records if the zone has
539
     * extremely low TTLs.
540
     */
541
0
    ttl = dns_adb_cachemin;
542
0
  }
543
0
  if (ttl > ADB_CACHE_MAXIMUM) {
544
0
    ttl = ADB_CACHE_MAXIMUM;
545
0
  }
546
547
0
  return ttl;
548
0
}
549
550
/*
551
 * Requires the name to be locked and that no entries to be locked.
552
 *
553
 * This code handles A and AAAA rdatasets only.
554
 */
555
static void
556
import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
557
0
    isc_stdtime_t now) {
558
0
  dns_adb_t *adb = NULL;
559
0
  dns_rdatatype_t rdtype;
560
561
0
  REQUIRE(DNS_ADBNAME_VALID(adbname));
562
563
0
  adb = adbname->adb;
564
565
0
  REQUIRE(DNS_ADB_VALID(adb));
566
567
0
  rdtype = rdataset->type;
568
569
0
  REQUIRE(rdataset->rdclass == dns_rdataclass_in);
570
0
  REQUIRE(dns_rdatatype_isaddr(rdtype));
571
572
0
  switch (rdataset->trust) {
573
0
  case dns_trust_glue:
574
0
  case dns_trust_additional:
575
0
  case dns_trust_pending_answer:
576
0
  case dns_trust_pending_additional:
577
    /*
578
     * Avoid to constantly ask about A/AAAA records if the zone has
579
     * extremely low TTLs.
580
     */
581
0
    rdataset->ttl = dns_adb_cachemin;
582
0
    break;
583
0
  case dns_trust_ultimate:
584
0
    rdataset->ttl = 0;
585
0
    break;
586
0
  default:
587
0
    rdataset->ttl = ttlclamp(rdataset->ttl);
588
0
  }
589
590
0
  DNS_RDATASET_FOREACH(rdataset) {
591
    /* FIXME: Move to a separate function */
592
0
    dns_adbnamehooklist_t *hookhead = NULL;
593
0
    dns_adbentry_t *entry = NULL;
594
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
595
0
    isc_sockaddr_t sockaddr;
596
0
    struct in_addr ina;
597
0
    struct in6_addr in6a;
598
599
0
    dns_rdataset_current(rdataset, &rdata);
600
0
    switch (rdtype) {
601
0
    case dns_rdatatype_a:
602
0
      INSIST(rdata.length == 4);
603
0
      memmove(&ina.s_addr, rdata.data, 4);
604
0
      isc_sockaddr_fromin(&sockaddr, &ina, 0);
605
0
      hookhead = &adbname->v4;
606
0
      break;
607
0
    case dns_rdatatype_aaaa:
608
0
      INSIST(rdata.length == 16);
609
0
      memmove(in6a.s6_addr, rdata.data, 16);
610
0
      isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
611
0
      hookhead = &adbname->v6;
612
0
      break;
613
0
    default:
614
0
      UNREACHABLE();
615
0
    }
616
617
0
    entry = get_attached_and_locked_entry(adb, now, &sockaddr);
618
619
0
    bool found = false;
620
0
    ISC_LIST_FOREACH(*hookhead, anh, name_link) {
621
0
      if (anh->entry == entry) {
622
0
        found = true;
623
0
      }
624
0
    }
625
0
    if (!found) {
626
0
      dns_adbnamehook_t *nh = new_adbnamehook(adb);
627
0
      dns_adbentry_attach(entry, &nh->entry);
628
0
      ISC_LIST_APPEND(*hookhead, nh, name_link);
629
0
      ISC_LIST_APPEND(entry->nhs, nh, entry_link);
630
0
    }
631
0
    UNLOCK(&entry->lock);
632
0
    dns_adbentry_detach(&entry);
633
0
  }
634
635
0
  switch (rdtype) {
636
0
  case dns_rdatatype_a:
637
0
    adbname->expire_v4 = ADJUSTED_EXPIRE(adbname->expire_v4, now,
638
0
                 rdataset->ttl);
639
0
    DP(NCACHE_LEVEL, "expire_v4 set to %u import_rdataset",
640
0
       adbname->expire_v4);
641
0
    break;
642
0
  case dns_rdatatype_aaaa:
643
0
    adbname->expire_v6 = ADJUSTED_EXPIRE(adbname->expire_v6, now,
644
0
                 rdataset->ttl);
645
0
    DP(NCACHE_LEVEL, "expire_v6 set to %u import_rdataset",
646
0
       adbname->expire_v6);
647
0
    break;
648
0
  default:
649
0
    UNREACHABLE();
650
0
  }
651
0
}
652
653
static void
654
0
expire_name_async(void *arg) {
655
0
  dns_adbname_t *adbname = arg;
656
0
  dns_adb_t *adb = adbname->adb;
657
658
0
  RUNTIME_CHECK(adbname->loop == isc_loop());
659
660
  /* ... and LRU list */
661
0
  ISC_SIEVE_UNLINK(adb->lru[isc_tid()].names, adbname, link);
662
663
0
  dns_adbname_detach(&adbname);
664
0
}
665
666
/*
667
 * Requires the name to be locked and write lock on adb->names_lock.
668
 */
669
static void
670
0
expire_name(dns_adbname_t *adbname, dns_adbstatus_t astat) {
671
0
  REQUIRE(DNS_ADBNAME_VALID(adbname));
672
673
0
  dns_adb_t *adb = adbname->adb;
674
675
0
  REQUIRE(DNS_ADB_VALID(adb));
676
677
0
  DP(DEF_LEVEL, "killing name %p", adbname);
678
679
  /*
680
   * Clean up the name's various contents.  These functions
681
   * are destructive in that they will always empty the lists
682
   * of finds and namehooks.
683
   */
684
0
  clean_finds_at_name(adbname, astat, DNS_ADBFIND_ADDRESSMASK);
685
0
  clean_namehooks(adb, &adbname->v4);
686
0
  clean_namehooks(adb, &adbname->v6);
687
688
0
  if (NAME_FETCH_A(adbname)) {
689
0
    dns_resolver_cancelfetch(adbname->fetch_a->fetch);
690
0
  }
691
692
0
  if (NAME_FETCH_AAAA(adbname)) {
693
0
    dns_resolver_cancelfetch(adbname->fetch_aaaa->fetch);
694
0
  }
695
696
  /* Remove the adbname from the hashtable... */
697
0
  if (cds_lfht_del(adb->names_ht, &adbname->ht_node) == 0) {
698
0
    if (adbname->loop == isc_loop()) {
699
0
      expire_name_async(adbname);
700
0
    } else {
701
0
      isc_async_run(adbname->loop, expire_name_async,
702
0
              adbname);
703
0
    }
704
0
  }
705
0
}
706
707
/*
708
 * Requires the name to be locked and no entries to be locked.
709
 */
710
static void
711
0
maybe_expire_namehooks(dns_adbname_t *adbname, isc_stdtime_t now) {
712
0
  REQUIRE(DNS_ADBNAME_VALID(adbname));
713
0
  REQUIRE(DNS_ADB_VALID(adbname->adb));
714
715
0
  dns_adb_t *adb = adbname->adb;
716
717
  /*
718
   * Check to see if we need to remove the v4 addresses
719
   */
720
0
  if (!NAME_FETCH_A(adbname) && EXPIRE_OK(adbname->expire_v4, now)) {
721
0
    if (NAME_HAS_V4(adbname)) {
722
0
      DP(DEF_LEVEL, "expiring v4 for name %p", adbname);
723
0
      clean_namehooks(adb, &adbname->v4);
724
0
      adbname->partial_result &= ~DNS_ADBFIND_INET;
725
0
    }
726
0
    adbname->expire_v4 = INT_MAX;
727
0
    adbname->fetch_err = FIND_ERR_UNEXPECTED;
728
0
  }
729
730
  /*
731
   * Check to see if we need to remove the v6 addresses
732
   */
733
0
  if (!NAME_FETCH_AAAA(adbname) && EXPIRE_OK(adbname->expire_v6, now)) {
734
0
    if (NAME_HAS_V6(adbname)) {
735
0
      DP(DEF_LEVEL, "expiring v6 for name %p", adbname);
736
0
      clean_namehooks(adb, &adbname->v6);
737
0
      adbname->partial_result &= ~DNS_ADBFIND_INET6;
738
0
    }
739
0
    adbname->expire_v6 = INT_MAX;
740
0
    adbname->fetch6_err = FIND_ERR_UNEXPECTED;
741
0
  }
742
0
}
743
744
static void
745
0
shutdown_names(dns_adb_t *adb) {
746
0
  dns_adbname_t *adbname = NULL;
747
0
  struct cds_lfht_iter iter;
748
749
0
  cds_lfht_for_each_entry(adb->names_ht, &iter, adbname, ht_node) {
750
0
    dns_adbname_ref(adbname);
751
0
    LOCK(&adbname->lock);
752
    /*
753
     * Run through the list.  For each name, clean up finds
754
     * found there, and cancel any fetches running.  When
755
     * all the fetches are canceled, the name will destroy
756
     * itself.
757
     */
758
0
    expire_name(adbname, DNS_ADB_SHUTTINGDOWN);
759
0
    UNLOCK(&adbname->lock);
760
0
    dns_adbname_detach(&adbname);
761
0
  }
762
0
}
763
764
static void
765
0
shutdown_entries(dns_adb_t *adb) {
766
0
  dns_adbentry_t *adbentry = NULL;
767
0
  struct cds_lfht_iter iter;
768
769
0
  cds_lfht_for_each_entry(adb->entries_ht, &iter, adbentry, ht_node) {
770
0
    dns_adbentry_ref(adbentry);
771
0
    LOCK(&adbentry->lock);
772
0
    expire_entry(adbentry);
773
0
    UNLOCK(&adbentry->lock);
774
0
    dns_adbentry_detach(&adbentry);
775
0
  }
776
0
}
777
778
/*
779
 * The name containing the 'namehooks' list must be locked.
780
 */
781
static void
782
0
clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) {
783
0
  ISC_LIST_FOREACH(*namehooks, namehook, name_link) {
784
0
    INSIST(DNS_ADBNAMEHOOK_VALID(namehook));
785
0
    INSIST(DNS_ADBENTRY_VALID(namehook->entry));
786
787
0
    dns_adbentry_t *adbentry = namehook->entry;
788
0
    namehook->entry = NULL;
789
790
    /*
791
     * Free the namehook
792
     */
793
0
    ISC_LIST_UNLINK(*namehooks, namehook, name_link);
794
795
0
    LOCK(&adbentry->lock);
796
0
    ISC_LIST_UNLINK(adbentry->nhs, namehook, entry_link);
797
0
    UNLOCK(&adbentry->lock);
798
0
    dns_adbentry_detach(&adbentry);
799
800
0
    free_adbnamehook(adb, &namehook);
801
0
  }
802
0
}
803
804
/*
805
 * The name must be locked.
806
 */
807
static void
808
clean_finds_at_name(dns_adbname_t *name, dns_adbstatus_t astat,
809
0
        unsigned int addrs) {
810
0
  dns_adbfind_t *find = NULL, *next = NULL;
811
812
0
  DP(ENTER_LEVEL,
813
0
     "ENTER clean_finds_at_name, name %p, astat %08x, addrs %08x", name,
814
0
     astat, addrs);
815
816
0
  for (find = ISC_LIST_HEAD(name->finds); find != NULL; find = next) {
817
0
    bool process = false;
818
0
    unsigned int wanted, notify;
819
820
0
    LOCK(&find->lock);
821
0
    next = ISC_LIST_NEXT(find, plink);
822
823
0
    wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
824
0
    notify = wanted & addrs;
825
826
0
    switch (astat) {
827
0
    case DNS_ADB_MOREADDRESSES:
828
0
      DP(ISC_LOG_DEBUG(3), "more addresses");
829
0
      if ((notify) != 0) {
830
0
        find->flags &= ~addrs;
831
0
        process = true;
832
0
      }
833
0
      break;
834
0
    case DNS_ADB_NOMOREADDRESSES:
835
0
      DP(ISC_LOG_DEBUG(3), "no more addresses");
836
0
      find->flags &= ~addrs;
837
0
      wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
838
0
      if (wanted == 0) {
839
0
        process = true;
840
0
      }
841
0
      break;
842
0
    default:
843
0
      find->flags &= ~addrs;
844
0
      process = true;
845
0
    }
846
847
0
    if (process) {
848
0
      DP(DEF_LEVEL, "cfan: processing find %p", find);
849
850
      /*
851
       * Unlink the find from the name, letting the caller
852
       * call dns_adb_destroyfind() on it to clean it up
853
       * later.
854
       */
855
0
      ISC_LIST_UNLINK(name->finds, find, plink);
856
0
      find->adbname = NULL;
857
858
0
      INSIST(!FIND_EVENTSENT(find));
859
860
0
      atomic_store(&find->status, astat);
861
862
0
      DP(DEF_LEVEL, "cfan: sending find %p to caller", find);
863
864
0
      isc_async_run(find->loop, find->cb, find);
865
0
      find->flags |= FIND_EVENT_SENT;
866
0
    } else {
867
0
      DP(DEF_LEVEL, "cfan: skipping find %p", find);
868
0
    }
869
870
0
    UNLOCK(&find->lock);
871
0
  }
872
0
  DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
873
0
}
874
875
static dns_adbname_t *
876
0
new_adbname(dns_adb_t *adb, const dns_name_t *dnsname, unsigned int type) {
877
0
  dns_adbname_t *name = NULL;
878
879
0
  name = isc_mem_get(adb->mctx, sizeof(*name));
880
0
  *name = (dns_adbname_t){
881
0
    .adb = dns_adb_ref(adb),
882
0
    .expire_v4 = INT_MAX,
883
0
    .expire_v6 = INT_MAX,
884
0
    .fetch_err = FIND_ERR_UNEXPECTED,
885
0
    .fetch6_err = FIND_ERR_UNEXPECTED,
886
0
    .v4 = ISC_LIST_INITIALIZER,
887
0
    .v6 = ISC_LIST_INITIALIZER,
888
0
    .finds = ISC_LIST_INITIALIZER,
889
0
    .link = ISC_LINK_INITIALIZER,
890
0
    .type = type,
891
0
    .loop = isc_loop_ref(isc_loop()),
892
0
    .magic = DNS_ADBNAME_MAGIC,
893
0
  };
894
895
#if DNS_ADB_TRACE
896
  fprintf(stderr, "dns_adbname__init:%s:%s:%d:%p->references = 1\n",
897
    __func__, __FILE__, __LINE__ + 1, name);
898
#endif
899
0
  isc_refcount_init(&name->references, 1);
900
901
0
  isc_mutex_init(&name->lock);
902
903
0
  name->name = dns_fixedname_initname(&name->fname);
904
0
  dns_name_copy(dnsname, name->name);
905
906
0
  inc_adbstats(adb, dns_adbstats_namescnt);
907
0
  return name;
908
0
}
909
910
#if DNS_ADB_TRACE
911
ISC_REFCOUNT_TRACE_IMPL(dns_adbname, destroy_adbname);
912
#else
913
0
ISC_REFCOUNT_IMPL(dns_adbname, destroy_adbname);
Unexecuted instantiation: dns_adbname_ref
Unexecuted instantiation: dns_adbname_unref
Unexecuted instantiation: dns_adbname_detach
914
0
#endif
915
0
916
0
static void
917
0
destroy_adbname_rcu(struct rcu_head *rcu_head) {
918
0
  dns_adbname_t *adbname = caa_container_of(rcu_head, dns_adbname_t,
919
0
              rcu_head);
920
0
  REQUIRE(DNS_ADBNAME_VALID(adbname));
921
922
0
  dns_adb_t *adb = adbname->adb;
923
924
0
  REQUIRE(!NAME_HAS_V4(adbname));
925
0
  REQUIRE(!NAME_HAS_V6(adbname));
926
0
  REQUIRE(!NAME_FETCH(adbname));
927
0
  REQUIRE(ISC_LIST_EMPTY(adbname->finds));
928
0
  REQUIRE(!ISC_LINK_LINKED(adbname, link));
929
930
0
  adbname->magic = 0;
931
932
0
  isc_mutex_destroy(&adbname->lock);
933
0
  isc_loop_detach(&adbname->loop);
934
935
0
  isc_mem_put(adb->mctx, adbname, sizeof(*adbname));
936
937
0
  dec_adbstats(adb, dns_adbstats_namescnt);
938
939
0
  dns_adb_detach(&adb);
940
0
}
941
942
static void
943
0
destroy_adbname(dns_adbname_t *adbname) {
944
0
  call_rcu(&adbname->rcu_head, destroy_adbname_rcu);
945
0
}
946
947
static dns_adbnamehook_t *
948
0
new_adbnamehook(dns_adb_t *adb) {
949
0
  dns_adbnamehook_t *nh = isc_mem_get(adb->mctx, sizeof(*nh));
950
0
  *nh = (dns_adbnamehook_t){
951
0
    .name_link = ISC_LINK_INITIALIZER,
952
0
    .entry_link = ISC_LINK_INITIALIZER,
953
0
    .magic = DNS_ADBNAMEHOOK_MAGIC,
954
0
  };
955
956
0
  return nh;
957
0
}
958
959
static void
960
0
free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) {
961
0
  dns_adbnamehook_t *nh = NULL;
962
963
0
  REQUIRE(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook));
964
965
0
  nh = *namehook;
966
0
  *namehook = NULL;
967
968
0
  REQUIRE(nh->entry == NULL);
969
0
  REQUIRE(!ISC_LINK_LINKED(nh, name_link));
970
0
  REQUIRE(!ISC_LINK_LINKED(nh, entry_link));
971
972
0
  nh->magic = 0;
973
974
0
  isc_mem_put(adb->mctx, nh, sizeof(*nh));
975
0
}
976
977
static dns_adbentry_t *
978
0
new_adbentry(dns_adb_t *adb, const isc_sockaddr_t *addr, isc_stdtime_t now) {
979
0
  dns_adbentry_t *entry = NULL;
980
981
0
  entry = isc_mem_get(adb->mctx, sizeof(*entry));
982
0
  *entry = (dns_adbentry_t){
983
0
    .srtt = isc_random_uniform(0x1f) + 1,
984
0
    .sockaddr = *addr,
985
0
    .link = ISC_LINK_INITIALIZER,
986
0
    .quota = adb->quota,
987
0
    .references = ISC_REFCOUNT_INITIALIZER(1),
988
0
    .adb = dns_adb_ref(adb),
989
0
    .expires = now + dns_adb_entrywindow,
990
0
    .loop = isc_loop_ref(isc_loop()),
991
0
    .magic = DNS_ADBENTRY_MAGIC,
992
0
  };
993
994
#if DNS_ADB_TRACE
995
  fprintf(stderr, "dns_adbentry__init:%s:%s:%d:%p->references = 1\n",
996
    __func__, __FILE__, __LINE__ + 1, entry);
997
#endif
998
0
  isc_mutex_init(&entry->lock);
999
1000
0
  inc_adbstats(adb, dns_adbstats_entriescnt);
1001
1002
0
  return entry;
1003
0
}
1004
1005
static void
1006
0
destroy_adbentry_rcu(struct rcu_head *rcu_head) {
1007
0
  dns_adbentry_t *adbentry = caa_container_of(rcu_head, dns_adbentry_t,
1008
0
                rcu_head);
1009
1010
0
  REQUIRE(DNS_ADBENTRY_VALID(adbentry));
1011
1012
0
  dns_adb_t *adb = adbentry->adb;
1013
0
  uint_fast32_t active;
1014
1015
0
  adbentry->magic = 0;
1016
1017
0
  INSIST(!ISC_LINK_LINKED(adbentry, link));
1018
1019
0
  INSIST(ISC_LIST_EMPTY(adbentry->nhs));
1020
1021
0
  active = atomic_load_acquire(&adbentry->active);
1022
0
  INSIST(active == 0);
1023
1024
0
  if (adbentry->cookie != NULL) {
1025
0
    isc_mem_put(adb->mctx, adbentry->cookie, adbentry->cookielen);
1026
0
  }
1027
1028
0
  isc_mutex_destroy(&adbentry->lock);
1029
0
  isc_loop_detach(&adbentry->loop);
1030
1031
0
  isc_mem_put(adb->mctx, adbentry, sizeof(*adbentry));
1032
1033
0
  dec_adbstats(adb, dns_adbstats_entriescnt);
1034
1035
0
  dns_adb_detach(&adb);
1036
0
}
1037
1038
static void
1039
0
destroy_adbentry(dns_adbentry_t *adbentry) {
1040
0
  call_rcu(&adbentry->rcu_head, destroy_adbentry_rcu);
1041
0
}
1042
1043
#if DNS_ADB_TRACE
1044
ISC_REFCOUNT_TRACE_IMPL(dns_adbentry, destroy_adbentry);
1045
#else
1046
0
ISC_REFCOUNT_IMPL(dns_adbentry, destroy_adbentry);
Unexecuted instantiation: dns_adbentry_ref
Unexecuted instantiation: dns_adbentry_unref
Unexecuted instantiation: dns_adbentry_detach
1047
0
#endif
1048
0
1049
0
static dns_adbfind_t *
1050
0
new_adbfind(dns_adb_t *adb, in_port_t port) {
1051
0
  dns_adbfind_t *find = NULL;
1052
1053
0
  find = isc_mem_get(adb->hmctx, sizeof(*find));
1054
0
  *find = (dns_adbfind_t){
1055
0
    .port = port,
1056
0
    .result_v4 = ISC_R_UNEXPECTED,
1057
0
    .result_v6 = ISC_R_UNEXPECTED,
1058
0
    .publink = ISC_LINK_INITIALIZER,
1059
0
    .plink = ISC_LINK_INITIALIZER,
1060
0
    .list = ISC_LIST_INITIALIZER,
1061
0
  };
1062
1063
0
  dns_adb_attach(adb, &find->adb);
1064
0
  isc_mutex_init(&find->lock);
1065
1066
0
  find->magic = DNS_ADBFIND_MAGIC;
1067
1068
0
  return find;
1069
0
}
1070
1071
static void
1072
0
free_adbfind(dns_adbfind_t **findp) {
1073
0
  dns_adb_t *adb = NULL;
1074
0
  dns_adbfind_t *find = NULL;
1075
1076
0
  REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp));
1077
1078
0
  find = *findp;
1079
0
  *findp = NULL;
1080
1081
0
  adb = find->adb;
1082
1083
0
  REQUIRE(!FIND_HAS_ADDRS(find));
1084
0
  REQUIRE(!ISC_LINK_LINKED(find, publink));
1085
0
  REQUIRE(!ISC_LINK_LINKED(find, plink));
1086
0
  REQUIRE(find->adbname == NULL);
1087
1088
0
  find->magic = ~DNS_ADBFIND_MAGIC;
1089
1090
0
  isc_mutex_destroy(&find->lock);
1091
1092
0
  isc_mem_put(adb->hmctx, find, sizeof(*find));
1093
0
  dns_adb_detach(&adb);
1094
0
}
1095
1096
static dns_adbfetch_t *
1097
0
new_adbfetch(dns_adb_t *adb) {
1098
0
  dns_adbfetch_t *fetch = NULL;
1099
1100
0
  fetch = isc_mem_get(adb->hmctx, sizeof(*fetch));
1101
0
  *fetch = (dns_adbfetch_t){
1102
0
    .magic = DNS_ADBFETCH_MAGIC,
1103
0
  };
1104
0
  dns_rdataset_init(&fetch->rdataset);
1105
1106
0
  return fetch;
1107
0
}
1108
1109
static void
1110
0
free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetchp) {
1111
0
  dns_adbfetch_t *fetch = NULL;
1112
1113
0
  REQUIRE(fetchp != NULL && DNS_ADBFETCH_VALID(*fetchp));
1114
1115
0
  fetch = *fetchp;
1116
0
  *fetchp = NULL;
1117
1118
0
  fetch->magic = 0;
1119
1120
0
  dns_rdataset_cleanup(&fetch->rdataset);
1121
1122
0
  isc_mem_put(adb->hmctx, fetch, sizeof(*fetch));
1123
0
}
1124
1125
/*
1126
 * Copy bits from an adbentry into a newly allocated adb_addrinfo structure.
1127
 * The entry must be locked, and its reference count must be incremented.
1128
 */
1129
static dns_adbaddrinfo_t *
1130
0
new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
1131
0
  dns_adbaddrinfo_t *ai = NULL;
1132
1133
0
  ai = isc_mem_get(adb->hmctx, sizeof(*ai));
1134
0
  *ai = (dns_adbaddrinfo_t){
1135
0
    .srtt = atomic_load(&entry->srtt),
1136
0
    .flags = atomic_load(&entry->flags),
1137
0
    .publink = ISC_LINK_INITIALIZER,
1138
0
    .sockaddr = entry->sockaddr,
1139
0
    .entry = dns_adbentry_ref(entry),
1140
0
    .magic = DNS_ADBADDRINFO_MAGIC,
1141
0
  };
1142
1143
0
  isc_sockaddr_setport(&ai->sockaddr, port);
1144
1145
0
  return ai;
1146
0
}
1147
1148
static void
1149
0
free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
1150
0
  dns_adbaddrinfo_t *ai = NULL;
1151
1152
0
  REQUIRE(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo));
1153
1154
0
  ai = *ainfo;
1155
0
  *ainfo = NULL;
1156
1157
0
  REQUIRE(!ISC_LINK_LINKED(ai, publink));
1158
1159
0
  ai->magic = 0;
1160
1161
0
  if (ai->transport != NULL) {
1162
0
    dns_transport_detach(&ai->transport);
1163
0
  }
1164
0
  dns_adbentry_detach(&ai->entry);
1165
1166
0
  isc_mem_put(adb->hmctx, ai, sizeof(*ai));
1167
0
}
1168
1169
static int
1170
0
match_adbname(struct cds_lfht_node *ht_node, const void *key) {
1171
0
  const dns_adbname_t *adbname0 = caa_container_of(ht_node, dns_adbname_t,
1172
0
               ht_node);
1173
0
  const dns_adbname_t *adbname1 = key;
1174
1175
0
  if (adbname0->type != adbname1->type) {
1176
0
    return 0;
1177
0
  }
1178
1179
0
  return dns_name_equal(adbname0->name, adbname1->name);
1180
0
}
1181
1182
static uint32_t
1183
0
hash_adbname(const dns_adbname_t *adbname) {
1184
0
  isc_hash32_t hash;
1185
1186
0
  isc_hash32_init(&hash);
1187
0
  isc_hash32_hash(&hash, adbname->name->ndata, adbname->name->length,
1188
0
      false);
1189
0
  isc_hash32_hash(&hash, &adbname->type, sizeof(adbname->type), true);
1190
0
  return isc_hash32_finalize(&hash);
1191
0
}
1192
1193
/*
1194
 * Search for the name in the hash table.
1195
 */
1196
static dns_adbname_t *
1197
get_attached_and_locked_name(dns_adb_t *adb, const dns_name_t *name,
1198
0
           unsigned int type, isc_stdtime_t now) {
1199
0
  dns_adbname_t *adbname = NULL;
1200
0
  dns_adbname_t key = {
1201
0
    .name = UNCONST(name),
1202
0
    .type = type,
1203
0
  };
1204
0
  uint32_t hashval = hash_adbname(&key);
1205
0
  if (isc_mem_isovermem(adb->mctx)) {
1206
0
    purge_names_overmem(adb, 2 * sizeof(*adbname));
1207
0
  }
1208
1209
0
  struct cds_lfht_iter iter;
1210
0
  cds_lfht_lookup(adb->names_ht, hashval, match_adbname, &key, &iter);
1211
1212
0
  adbname = cds_lfht_entry(cds_lfht_iter_get_node(&iter), dns_adbname_t,
1213
0
         ht_node);
1214
1215
0
  if (adbname == NULL) {
1216
0
  create:
1217
0
    adbname = new_adbname(adb, name, key.type);
1218
1219
    /*
1220
     * We need to lock the adbname before inserting it into the
1221
     * hashtable because any other thread could immediately look the
1222
     * newly created adbname after it has been inserted but not yet
1223
     * properly initialized by the caller.
1224
     */
1225
0
    LOCK(&adbname->lock);
1226
1227
0
    struct cds_lfht_node *ht_node = cds_lfht_add_unique(
1228
0
      adb->names_ht, hashval, match_adbname, &key,
1229
0
      &adbname->ht_node);
1230
1231
0
    if (ht_node == &adbname->ht_node) {
1232
      /* Success. */
1233
1234
0
      dns_adbname_ref(adbname);
1235
1236
0
      ISC_SIEVE_INSERT(adb->lru[isc_tid()].names, adbname,
1237
0
           link);
1238
1239
0
      return adbname;
1240
0
    }
1241
1242
    /* Somebody was faster */
1243
0
    UNLOCK(&adbname->lock);
1244
1245
0
    destroy_adbname_rcu(&adbname->rcu_head);
1246
0
    adbname = caa_container_of(ht_node, dns_adbname_t, ht_node);
1247
0
  }
1248
1249
0
  LOCK(&adbname->lock);
1250
1251
0
  if (cds_lfht_is_node_deleted(&adbname->ht_node)) {
1252
0
    UNLOCK(&adbname->lock);
1253
0
    goto create;
1254
0
  }
1255
1256
0
  dns_adbname_ref(adbname);
1257
1258
  /* Is the name we found already expired */
1259
0
  if (maybe_expire_name(adbname, now)) {
1260
0
    UNLOCK(&adbname->lock);
1261
0
    dns_adbname_detach(&adbname);
1262
0
    goto create;
1263
0
  }
1264
1265
0
  ISC_SIEVE_MARK(adbname, visited);
1266
1267
0
  return adbname;
1268
0
}
1269
1270
static int
1271
0
match_adbentry(struct cds_lfht_node *ht_node, const void *key) {
1272
0
  const dns_adbentry_t *adbentry =
1273
0
    caa_container_of(ht_node, dns_adbentry_t, ht_node);
1274
1275
0
  return isc_sockaddr_equal(&adbentry->sockaddr, key);
1276
0
}
1277
1278
/*
1279
 * Find the entry in the adb->entries hashtable.
1280
 */
1281
static dns_adbentry_t *
1282
get_attached_and_locked_entry(dns_adb_t *adb, isc_stdtime_t now,
1283
0
            const isc_sockaddr_t *addr) {
1284
0
  dns_adbentry_t *adbentry = NULL;
1285
0
  uint32_t hashval = isc_sockaddr_hash(addr, true);
1286
1287
0
  if (isc_mem_isovermem(adb->mctx)) {
1288
0
    purge_entries_overmem(adb, 2 * sizeof(*adbentry));
1289
0
  }
1290
1291
0
  struct cds_lfht_iter iter;
1292
0
  cds_lfht_lookup(adb->entries_ht, hashval, match_adbentry,
1293
0
      (const unsigned char *)addr, &iter);
1294
1295
0
  adbentry = cds_lfht_entry(cds_lfht_iter_get_node(&iter), dns_adbentry_t,
1296
0
          ht_node);
1297
1298
0
  if (adbentry == NULL) {
1299
0
  create:
1300
0
    adbentry = new_adbentry(adb, addr, now);
1301
1302
    /*
1303
     * We need to lock the adbentry before inserting it into the
1304
     * hashtable because any other thread could immediately look the
1305
     * newly created adbentry after it has been inserted but not yet
1306
     * properly initialized by the caller.
1307
     */
1308
0
    LOCK(&adbentry->lock);
1309
1310
0
    struct cds_lfht_node *ht_node = cds_lfht_add_unique(
1311
0
      adb->entries_ht, hashval, match_adbentry,
1312
0
      (const unsigned char *)addr, &adbentry->ht_node);
1313
1314
0
    if (ht_node == &adbentry->ht_node) {
1315
      /* Success */
1316
1317
0
      dns_adbentry_ref(adbentry);
1318
1319
0
      ISC_SIEVE_INSERT(adb->lru[isc_tid()].entries, adbentry,
1320
0
           link);
1321
1322
0
      return adbentry;
1323
0
    }
1324
1325
    /* Somebody was faster */
1326
0
    UNLOCK(&adbentry->lock);
1327
1328
0
    destroy_adbentry_rcu(&adbentry->rcu_head);
1329
0
    adbentry = caa_container_of(ht_node, dns_adbentry_t, ht_node);
1330
0
  }
1331
1332
0
  LOCK(&adbentry->lock);
1333
1334
0
  if (cds_lfht_is_node_deleted(&adbentry->ht_node)) {
1335
0
    UNLOCK(&adbentry->lock);
1336
0
    goto create;
1337
0
  }
1338
1339
0
  dns_adbentry_ref(adbentry);
1340
1341
  /* Is the entry we found already expired */
1342
0
  if (maybe_expire_entry(adbentry, now)) {
1343
0
    UNLOCK(&adbentry->lock);
1344
0
    dns_adbentry_detach(&adbentry);
1345
0
    goto create;
1346
0
  }
1347
1348
0
  ISC_SIEVE_MARK(adbentry, visited);
1349
1350
0
  return adbentry;
1351
0
}
1352
1353
static void
1354
0
log_quota(dns_adbentry_t *entry, const char *fmt, ...) {
1355
0
  va_list ap;
1356
0
  char msgbuf[2048];
1357
0
  char addrbuf[ISC_NETADDR_FORMATSIZE];
1358
0
  isc_netaddr_t netaddr;
1359
1360
0
  va_start(ap, fmt);
1361
0
  vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
1362
0
  va_end(ap);
1363
1364
0
  isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
1365
0
  isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
1366
1367
0
  isc_log_write(DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB, ISC_LOG_INFO,
1368
0
          "adb: quota %s (%" PRIuFAST32 "/%" PRIuFAST32 "): %s",
1369
0
          addrbuf, atomic_load_relaxed(&entry->active),
1370
0
          atomic_load_relaxed(&entry->quota), msgbuf);
1371
0
}
1372
1373
static void
1374
copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_adbname_t *name,
1375
0
        size_t maxfindlen, size_t *findlen) {
1376
0
  dns_adbentry_t *entry = NULL;
1377
0
  size_t count = 0;
1378
1379
0
  if ((find->options & DNS_ADBFIND_INET) != 0) {
1380
0
    ISC_LIST_FOREACH(name->v4, namehook, name_link) {
1381
0
      dns_adbaddrinfo_t *addrinfo = NULL;
1382
0
      entry = namehook->entry;
1383
1384
0
      if ((find->options & DNS_ADBFIND_QUOTAEXEMPT) == 0 &&
1385
0
          adbentry_overquota(entry))
1386
0
      {
1387
0
        find->options |= DNS_ADBFIND_OVERQUOTA;
1388
0
        continue;
1389
0
      }
1390
1391
0
      addrinfo = new_adbaddrinfo(adb, entry, find->port);
1392
1393
      /*
1394
       * Found a valid entry.  Add it to the find's list.
1395
       */
1396
0
      ISC_LIST_APPEND(find->list, addrinfo, publink);
1397
1398
0
      count++;
1399
0
      if (maxfindlen - count == 0) {
1400
0
        SET_IF_NOT_NULL(findlen, count);
1401
0
        return;
1402
0
      }
1403
0
    }
1404
0
  }
1405
1406
0
  if ((find->options & DNS_ADBFIND_INET6) != 0) {
1407
0
    ISC_LIST_FOREACH(name->v6, namehook, name_link) {
1408
0
      dns_adbaddrinfo_t *addrinfo = NULL;
1409
0
      entry = namehook->entry;
1410
1411
0
      if ((find->options & DNS_ADBFIND_QUOTAEXEMPT) == 0 &&
1412
0
          adbentry_overquota(entry))
1413
0
      {
1414
0
        find->options |= DNS_ADBFIND_OVERQUOTA;
1415
0
        continue;
1416
0
      }
1417
1418
0
      addrinfo = new_adbaddrinfo(adb, entry, find->port);
1419
1420
      /*
1421
       * Found a valid entry.  Add it to the find's list.
1422
       */
1423
0
      ISC_LIST_APPEND(find->list, addrinfo, publink);
1424
1425
0
      count++;
1426
0
      if (maxfindlen - count == 0) {
1427
0
        SET_IF_NOT_NULL(findlen, count);
1428
0
        return;
1429
0
      }
1430
0
    }
1431
0
  }
1432
1433
0
  SET_IF_NOT_NULL(findlen, count);
1434
0
}
1435
1436
static bool
1437
0
name_expired(dns_adbname_t *adbname, isc_stdtime_t now) {
1438
0
  REQUIRE(DNS_ADBNAME_VALID(adbname));
1439
1440
  /* Leave this name alone if it still has active namehooks... */
1441
0
  if (NAME_HAS_V4(adbname) || NAME_HAS_V6(adbname)) {
1442
0
    return false;
1443
0
  }
1444
1445
  /* ...an active fetch in progres... */
1446
0
  if (NAME_FETCH(adbname)) {
1447
0
    return false;
1448
0
  }
1449
1450
  /* ... or is not yet expired. */
1451
0
  if (!EXPIRE_OK(adbname->expire_v4, now) ||
1452
0
      !EXPIRE_OK(adbname->expire_v6, now))
1453
0
  {
1454
0
    return false;
1455
0
  }
1456
1457
0
  return true;
1458
0
}
1459
1460
/*
1461
 * The name must be locked and write lock on adb->names_lock must be held.
1462
 */
1463
static bool
1464
0
maybe_expire_name(dns_adbname_t *adbname, isc_stdtime_t now) {
1465
0
  if (name_expired(adbname, now)) {
1466
0
    expire_name(adbname, DNS_ADB_EXPIRED);
1467
0
    return true;
1468
0
  }
1469
1470
0
  return false;
1471
0
}
1472
1473
static void
1474
0
expire_entry_async(void *arg) {
1475
0
  dns_adbentry_t *adbentry = arg;
1476
0
  dns_adb_t *adb = adbentry->adb;
1477
1478
0
  REQUIRE(adbentry->loop == isc_loop());
1479
1480
0
  ISC_SIEVE_UNLINK(adb->lru[isc_tid()].entries, adbentry, link);
1481
1482
0
  dns_adbentry_detach(&adbentry);
1483
0
}
1484
1485
static void
1486
0
expire_entry(dns_adbentry_t *adbentry) {
1487
0
  dns_adb_t *adb = adbentry->adb;
1488
1489
0
  if (cds_lfht_del(adb->entries_ht, &adbentry->ht_node) == 0) {
1490
0
    if (adbentry->loop == isc_loop()) {
1491
0
      expire_entry_async(adbentry);
1492
0
    } else {
1493
0
      isc_async_run(adbentry->loop, expire_entry_async,
1494
0
              adbentry);
1495
0
    }
1496
0
  }
1497
0
}
1498
1499
static bool
1500
0
entry_expired(dns_adbentry_t *adbentry, isc_stdtime_t now) {
1501
0
  if (!ISC_LIST_EMPTY(adbentry->nhs)) {
1502
0
    return false;
1503
0
  }
1504
1505
0
  if (!EXPIRE_OK(adbentry->expires, now)) {
1506
0
    return false;
1507
0
  }
1508
1509
0
  return true;
1510
0
}
1511
1512
static bool
1513
0
maybe_expire_entry(dns_adbentry_t *adbentry, isc_stdtime_t now) {
1514
0
  REQUIRE(DNS_ADBENTRY_VALID(adbentry));
1515
1516
0
  if (entry_expired(adbentry, now)) {
1517
0
    expire_entry(adbentry);
1518
0
    return true;
1519
0
  }
1520
1521
0
  return false;
1522
0
}
1523
1524
static void
1525
0
purge_names_overmem(dns_adb_t *adb, size_t requested) {
1526
0
  size_t expired = 0;
1527
1528
0
  do {
1529
0
    dns_adbname_t *adbname = ISC_SIEVE_NEXT(
1530
0
      adb->lru[isc_tid()].names, visited, link);
1531
0
    if (adbname == NULL) {
1532
0
      break;
1533
0
    }
1534
1535
0
    dns_adbname_ref(adbname);
1536
0
    LOCK(&adbname->lock);
1537
1538
    /*
1539
     * Remove the name if it's expired or unused,
1540
     * has no address data.
1541
     */
1542
0
    maybe_expire_namehooks(adbname, INT_MAX);
1543
0
    expire_name(adbname, DNS_ADB_CANCELED);
1544
0
    expired += sizeof(*adbname);
1545
1546
0
    UNLOCK(&adbname->lock);
1547
0
    dns_adbname_detach(&adbname);
1548
0
  } while (expired < requested);
1549
0
}
1550
1551
static void
1552
0
cleanup_names(dns_adb_t *adb, isc_stdtime_t now) {
1553
0
  dns_adbname_t *adbname = NULL;
1554
0
  struct cds_lfht_iter iter;
1555
1556
0
  cds_lfht_for_each_entry(adb->names_ht, &iter, adbname, ht_node) {
1557
0
    dns_adbname_ref(adbname);
1558
0
    LOCK(&adbname->lock);
1559
    /*
1560
     * Name hooks expire after the address record's TTL
1561
     * or 30 minutes, whichever is shorter. If after cleaning
1562
     * those up there are no name hooks left, and no active
1563
     * fetches, we can remove this name from the bucket.
1564
     */
1565
0
    maybe_expire_namehooks(adbname, now);
1566
0
    (void)maybe_expire_name(adbname, now);
1567
0
    UNLOCK(&adbname->lock);
1568
0
    dns_adbname_detach(&adbname);
1569
0
  }
1570
0
}
1571
1572
static void
1573
0
purge_entries_overmem(dns_adb_t *adb, size_t requested) {
1574
0
  size_t expired = 0;
1575
1576
0
  do {
1577
0
    dns_adbentry_t *adbentry = ISC_SIEVE_NEXT(
1578
0
      adb->lru[isc_tid()].entries, visited, link);
1579
0
    if (adbentry == NULL) {
1580
0
      break;
1581
0
    }
1582
1583
0
    dns_adbentry_ref(adbentry);
1584
0
    LOCK(&adbentry->lock);
1585
1586
0
    expire_entry(adbentry);
1587
0
    expired += sizeof(*adbentry);
1588
1589
0
    UNLOCK(&adbentry->lock);
1590
0
    dns_adbentry_detach(&adbentry);
1591
0
  } while (expired < requested);
1592
0
}
1593
1594
static void
1595
0
cleanup_entries(dns_adb_t *adb, isc_stdtime_t now) {
1596
0
  dns_adbentry_t *adbentry = NULL;
1597
0
  struct cds_lfht_iter iter;
1598
1599
0
  cds_lfht_for_each_entry(adb->entries_ht, &iter, adbentry, ht_node) {
1600
0
    dns_adbentry_ref(adbentry);
1601
0
    LOCK(&adbentry->lock);
1602
0
    maybe_expire_entry(adbentry, now);
1603
0
    UNLOCK(&adbentry->lock);
1604
0
    dns_adbentry_detach(&adbentry);
1605
0
  }
1606
0
}
1607
1608
static void
1609
0
dns_adb_destroy(dns_adb_t *adb) {
1610
0
  DP(DEF_LEVEL, "destroying ADB %p", adb);
1611
1612
0
  adb->magic = 0;
1613
1614
0
  RUNTIME_CHECK(!cds_lfht_destroy(adb->names_ht, NULL));
1615
0
  adb->names_ht = NULL;
1616
1617
0
  RUNTIME_CHECK(!cds_lfht_destroy(adb->entries_ht, NULL));
1618
0
  adb->entries_ht = NULL;
1619
1620
0
  isc_mem_cput(adb->hmctx, adb->lru, adb->nloops, sizeof(adb->lru[0]));
1621
1622
0
  isc_mem_detach(&adb->hmctx);
1623
1624
0
  isc_mutex_destroy(&adb->lock);
1625
1626
0
  isc_stats_detach(&adb->stats);
1627
0
  dns_resolver_detach(&adb->res);
1628
0
  dns_view_weakdetach(&adb->view);
1629
0
  isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
1630
0
}
1631
1632
#if DNS_ADB_TRACE
1633
ISC_REFCOUNT_TRACE_IMPL(dns_adb, dns_adb_destroy);
1634
#else
1635
0
ISC_REFCOUNT_IMPL(dns_adb, dns_adb_destroy);
Unexecuted instantiation: dns_adb_ref
Unexecuted instantiation: dns_adb_unref
Unexecuted instantiation: dns_adb_detach
1636
0
#endif
1637
0
1638
0
/*
1639
0
 * Public functions.
1640
0
 */
1641
0
1642
0
void
1643
0
dns_adb_create(isc_mem_t *mem, dns_view_t *view, dns_adb_t **adbp) {
1644
0
  REQUIRE(mem != NULL);
1645
0
  REQUIRE(view != NULL);
1646
0
  REQUIRE(adbp != NULL && *adbp == NULL);
1647
1648
0
  uint32_t nloops = isc_loopmgr_nloops();
1649
0
  dns_adb_t *adb = isc_mem_get(mem, sizeof(dns_adb_t));
1650
0
  *adb = (dns_adb_t){
1651
0
    .references = 1,
1652
0
    .nloops = nloops,
1653
0
    .magic = DNS_ADB_MAGIC,
1654
0
  };
1655
1656
  /*
1657
   * Initialize things here that cannot fail, and especially things
1658
   * that must be NULL for the error return to work properly.
1659
   */
1660
#if DNS_ADB_TRACE
1661
  fprintf(stderr, "dns_adb__init:%s:%s:%d:%p->references = 1\n", __func__,
1662
    __FILE__, __LINE__ + 1, adb);
1663
#endif
1664
0
  dns_view_weakattach(view, &adb->view);
1665
0
  dns_resolver_attach(view->resolver, &adb->res);
1666
0
  isc_mem_attach(mem, &adb->mctx);
1667
1668
0
  isc_mem_create("ADB_dynamic", &adb->hmctx);
1669
1670
0
  adb->names_ht = cds_lfht_new(ADB_HASH_SIZE, ADB_HASH_SIZE, 0,
1671
0
             CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING,
1672
0
             NULL);
1673
0
  INSIST(adb->names_ht != NULL);
1674
1675
0
  adb->entries_ht =
1676
0
    cds_lfht_new(ADB_HASH_SIZE, ADB_HASH_SIZE, 0,
1677
0
           CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
1678
0
  INSIST(adb->entries_ht != NULL);
1679
1680
0
  adb->lru = isc_mem_cget(adb->hmctx, adb->nloops, sizeof(adb->lru[0]));
1681
1682
0
  for (size_t i = 0; i < adb->nloops; i++) {
1683
0
    ISC_SIEVE_INIT(adb->lru[i].names);
1684
0
    ISC_SIEVE_INIT(adb->lru[i].entries);
1685
0
  }
1686
1687
0
  isc_mutex_init(&adb->lock);
1688
1689
0
  isc_stats_create(adb->mctx, &adb->stats, dns_adbstats_max);
1690
1691
0
  set_adbstat(adb, 0, dns_adbstats_nnames);
1692
0
  set_adbstat(adb, 0, dns_adbstats_nentries);
1693
1694
0
  *adbp = adb;
1695
0
}
1696
1697
static void
1698
0
dns_adb_shutdown_async(void *arg) {
1699
0
  dns_adb_t *adb = arg;
1700
1701
0
  synchronize_rcu();
1702
1703
0
  rcu_read_lock();
1704
0
  shutdown_names(adb);
1705
0
  shutdown_entries(adb);
1706
0
  rcu_read_unlock();
1707
1708
0
  dns_adb_detach(&adb);
1709
0
}
1710
1711
void
1712
0
dns_adb_shutdown(dns_adb_t *adb) {
1713
0
  if (!atomic_compare_exchange_strong(&adb->shuttingdown,
1714
0
              &(bool){ false }, true))
1715
0
  {
1716
0
    return;
1717
0
  }
1718
1719
0
  DP(DEF_LEVEL, "shutting down ADB %p", adb);
1720
1721
0
  isc_mem_clearwater(adb->mctx);
1722
1723
  /*
1724
   * dns_adb_shutdown() can get called from call_rcu thread, so we need to
1725
   * pass the control over synchronize_rcu() back to main loop thread when
1726
   * shutting down ADB.
1727
   */
1728
0
  dns_adb_ref(adb);
1729
0
  isc_async_run(isc_loop_main(), dns_adb_shutdown_async, adb);
1730
0
}
1731
1732
static void
1733
findaddrinfo(dns_adb_t *adb, const isc_sockaddr_t *addr,
1734
       dns_adbaddrinfo_t **adbaddrp, isc_stdtime_t now,
1735
0
       unsigned int options) {
1736
0
  dns_adbentry_t *adbentry = get_attached_and_locked_entry(adb, now,
1737
0
                 addr);
1738
0
  if ((options & DNS_ADBFIND_QUOTAEXEMPT) == 0 &&
1739
0
      adbentry_overquota(adbentry))
1740
0
  {
1741
0
    goto out;
1742
0
  }
1743
1744
0
  in_port_t port = isc_sockaddr_getport(addr);
1745
0
  *adbaddrp = new_adbaddrinfo(adb, adbentry, port);
1746
1747
0
out:
1748
0
  UNLOCK(&adbentry->lock);
1749
0
  dns_adbentry_detach(&adbentry);
1750
0
}
1751
1752
void
1753
dns_adb_createaddrinfosfind(dns_adb_t *adb, isc_netaddrlist_t *addrs,
1754
          in_port_t port, unsigned int options,
1755
          isc_stdtime_t now, size_t maxfindlen,
1756
0
          dns_adbfind_t **findp, size_t *findlen) {
1757
0
  dns_adbfind_t *find = NULL;
1758
0
  isc_sockaddr_t sockaddr = {};
1759
1760
0
  REQUIRE(DNS_ADB_VALID(adb));
1761
0
  REQUIRE(addrs != NULL);
1762
0
  REQUIRE(findp != NULL && *findp == NULL);
1763
0
  REQUIRE(maxfindlen > 0);
1764
1765
0
  rcu_read_lock();
1766
1767
0
  if (atomic_load(&adb->shuttingdown)) {
1768
0
    rcu_read_unlock();
1769
0
    return;
1770
0
  }
1771
1772
0
  if (now == 0) {
1773
0
    now = isc_stdtime_now();
1774
0
  }
1775
1776
0
  find = new_adbfind(adb, port);
1777
0
  ISC_LIST_FOREACH(*addrs, addrlink, link) {
1778
0
    dns_adbaddrinfo_t *addrinfo = NULL;
1779
1780
0
    sockaddr.type.sa.sa_family = addrlink->addr.family;
1781
0
    switch (addrlink->addr.family) {
1782
0
    case AF_INET:
1783
0
      if ((options & DNS_ADBFIND_INET) == 0) {
1784
0
        continue;
1785
0
      }
1786
0
      sockaddr.type.sin.sin_addr = addrlink->addr.type.in;
1787
0
      sockaddr.type.sin.sin_port = htons(port);
1788
0
      break;
1789
0
    case AF_INET6:
1790
0
      if ((options & DNS_ADBFIND_INET6) == 0) {
1791
0
        continue;
1792
0
      }
1793
      /*
1794
       * TODO: findaddrinfo() compares the scope, this might
1795
       * be a problem...
1796
       */
1797
0
      sockaddr.type.sin6.sin6_addr = addrlink->addr.type.in6;
1798
0
      sockaddr.type.sin6.sin6_port = htons(port);
1799
1800
0
      break;
1801
0
    default:
1802
0
      UNREACHABLE();
1803
0
    }
1804
1805
0
    findaddrinfo(adb, &sockaddr, &addrinfo, now, options);
1806
0
    if (addrinfo == NULL) {
1807
0
      find->options |= DNS_ADBFIND_OVERQUOTA;
1808
0
      continue;
1809
0
    }
1810
1811
0
    ISC_LIST_APPEND(find->list, addrinfo, publink);
1812
0
    (*findlen)++;
1813
1814
0
    if (maxfindlen - *findlen == 0) {
1815
0
      break;
1816
0
    }
1817
0
  }
1818
1819
0
  *findp = find;
1820
0
  rcu_read_unlock();
1821
0
}
1822
1823
/*
1824
 * Look up the name in our internal database.
1825
 *
1826
 * There are three possibilities. Note that these are not always exclusive.
1827
 *
1828
 * - No name found.  In this case, allocate a new name header and
1829
 *   an initial namehook or two.
1830
 *
1831
 * - Name found, valid addresses present.  Allocate one addrinfo
1832
 *   structure for each found and append it to the linked list
1833
 *   of addresses for this header.
1834
 *
1835
 * - Name found, queries pending.  In this case, if a loop was
1836
 *   passed in, allocate a job id, attach it to the name's job
1837
 *   list and remember to tell the caller that there will be
1838
 *   more info coming later.
1839
 */
1840
isc_result_t
1841
dns_adb_createfind(dns_adb_t *adb, isc_loop_t *loop, isc_job_cb cb, void *cbarg,
1842
       const dns_name_t *name, unsigned int options,
1843
       isc_stdtime_t now, in_port_t port, unsigned int depth,
1844
       isc_counter_t *qc, isc_counter_t *gqc, fetchctx_t *parent,
1845
0
       size_t maxfindlen, dns_adbfind_t **findp, size_t *findlen) {
1846
0
  isc_result_t result = ISC_R_UNEXPECTED;
1847
0
  dns_adbfind_t *find = NULL;
1848
0
  dns_adbname_t *adbname = NULL;
1849
0
  bool want_event = true;
1850
0
  bool start_at_zone = false;
1851
0
  bool alias = false;
1852
0
  bool have_address = false;
1853
0
  unsigned int wanted_addresses = (options & DNS_ADBFIND_ADDRESSMASK);
1854
0
  unsigned int wanted_fetches = 0;
1855
0
  unsigned int query_pending = 0;
1856
0
  char namebuf[DNS_NAME_FORMATSIZE] = { 0 };
1857
1858
0
  REQUIRE(DNS_ADB_VALID(adb));
1859
0
  if (loop != NULL) {
1860
0
    REQUIRE(cb != NULL);
1861
0
  }
1862
0
  REQUIRE(name != NULL);
1863
0
  REQUIRE(findp != NULL && *findp == NULL);
1864
0
  REQUIRE(maxfindlen > 0);
1865
1866
0
  REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0);
1867
1868
0
  rcu_read_lock();
1869
1870
0
  if (atomic_load(&adb->shuttingdown)) {
1871
0
    rcu_read_unlock();
1872
0
    return ISC_R_SHUTTINGDOWN;
1873
0
  }
1874
1875
0
  if (now == 0) {
1876
0
    now = isc_stdtime_now();
1877
0
  }
1878
1879
  /*
1880
   * If STATICSTUB is set we always want to have STARTATZONE set.
1881
   */
1882
0
  if (options & DNS_ADBFIND_STATICSTUB) {
1883
0
    options |= DNS_ADBFIND_STARTATZONE;
1884
0
  }
1885
1886
  /*
1887
   * Remember what types of addresses we are interested in.
1888
   */
1889
0
  find = new_adbfind(adb, port);
1890
0
  find->options = options;
1891
0
  find->flags |= wanted_addresses;
1892
0
  if (FIND_WANTEVENT(find)) {
1893
0
    REQUIRE(loop != NULL);
1894
0
  }
1895
1896
0
  if (isc_log_wouldlog(DEF_LEVEL)) {
1897
0
    dns_name_format(name, namebuf, sizeof(namebuf));
1898
0
  }
1899
1900
  /* Try to see if we know anything about this name at all. */
1901
0
  adbname = get_attached_and_locked_name(
1902
0
    adb, name, ADBNAME_TYPE(find->options), now);
1903
1904
  /*
1905
   * Name hooks expire after the address record's TTL or 30 minutes,
1906
   * whichever is shorter. If there are expired name hooks, remove
1907
   * them so we'll send a new fetch.
1908
   */
1909
0
  maybe_expire_namehooks(adbname, now);
1910
1911
  /*
1912
   * Do we know that the name is an alias?
1913
   */
1914
0
  if (NAME_ALIAS(adbname) && !EXPIRE_OK(adbname->expire_v4, now)) {
1915
    /* Yes, it is. */
1916
0
    DP(DEF_LEVEL,
1917
0
       "dns_adb_createfind: name %s (%p) is an alias (cached)",
1918
0
       namebuf, adbname);
1919
0
    alias = true;
1920
0
    goto post_copy;
1921
0
  }
1922
1923
  /*
1924
   * Try to populate the name from the database and/or
1925
   * start fetches.  First try looking for an A record
1926
   * in the database.
1927
   */
1928
0
  if (!NAME_HAS_V4(adbname) && EXPIRE_OK(adbname->expire_v4, now) &&
1929
0
      WANT_INET(wanted_addresses))
1930
0
  {
1931
0
    result = dbfind_name(adbname, now, dns_rdatatype_a);
1932
0
    switch (result) {
1933
0
    case ISC_R_SUCCESS:
1934
      /* Found an A; now we proceed to check for AAAA */
1935
0
      DP(DEF_LEVEL,
1936
0
         "dns_adb_createfind: found A for name %s (%p) in db",
1937
0
         namebuf, adbname);
1938
0
      break;
1939
1940
0
    case DNS_R_ALIAS:
1941
      /* Got a CNAME or DNAME. */
1942
0
      DP(DEF_LEVEL,
1943
0
         "dns_adb_createfind: name %s (%p) is an alias",
1944
0
         namebuf, adbname);
1945
0
      alias = true;
1946
0
      goto post_copy;
1947
1948
0
    case DNS_R_NXDOMAIN:
1949
0
    case DNS_R_NCACHENXDOMAIN:
1950
      /*
1951
       * If the name doesn't exist at all, don't bother with
1952
       * v6 queries; they won't work.
1953
       */
1954
0
      goto fetch;
1955
1956
0
    case DNS_R_NXRRSET:
1957
0
    case DNS_R_NCACHENXRRSET:
1958
0
    case DNS_R_HINTNXRRSET:
1959
      /*
1960
       * The name does exist but we didn't get our data, go
1961
       * ahead and try AAAA.
1962
       */
1963
0
      break;
1964
1965
0
    default:
1966
      /*
1967
       * Any other result, start a fetch for A, then fall
1968
       * through to AAAA.
1969
       */
1970
0
      if (!NAME_FETCH_A(adbname) && !FIND_STATICSTUB(find)) {
1971
0
        wanted_fetches |= DNS_ADBFIND_INET;
1972
0
      }
1973
0
      break;
1974
0
    }
1975
0
  }
1976
1977
  /*
1978
   * Now look up or start fetches for AAAA.
1979
   */
1980
0
  if (!NAME_HAS_V6(adbname) && EXPIRE_OK(adbname->expire_v6, now) &&
1981
0
      WANT_INET6(wanted_addresses))
1982
0
  {
1983
0
    result = dbfind_name(adbname, now, dns_rdatatype_aaaa);
1984
0
    switch (result) {
1985
0
    case ISC_R_SUCCESS:
1986
0
      DP(DEF_LEVEL,
1987
0
         "dns_adb_createfind: found AAAA for name %s (%p)",
1988
0
         namebuf, adbname);
1989
0
      break;
1990
1991
0
    case DNS_R_ALIAS:
1992
      /* Got a CNAME or DNAME. */
1993
0
      DP(DEF_LEVEL,
1994
0
         "dns_adb_createfind: name %s (%p) is an alias",
1995
0
         namebuf, adbname);
1996
0
      alias = true;
1997
0
      goto post_copy;
1998
1999
0
    case DNS_R_NXDOMAIN:
2000
0
    case DNS_R_NCACHENXDOMAIN:
2001
0
    case DNS_R_NXRRSET:
2002
0
    case DNS_R_NCACHENXRRSET:
2003
      /*
2004
       * Name doens't exist or was found in the negative
2005
       * cache to have no AAAA, don't bother fetching.
2006
       */
2007
0
      break;
2008
2009
0
    default:
2010
      /*
2011
       * Any other result, start a fetch for AAAA.
2012
       */
2013
0
      if (!NAME_FETCH_AAAA(adbname) && !FIND_STATICSTUB(find))
2014
0
      {
2015
0
        wanted_fetches |= DNS_ADBFIND_INET6;
2016
0
      }
2017
0
      break;
2018
0
    }
2019
0
  }
2020
2021
0
fetch:
2022
0
  if ((WANT_INET(wanted_addresses) && NAME_HAS_V4(adbname)) ||
2023
0
      (WANT_INET6(wanted_addresses) && NAME_HAS_V6(adbname)))
2024
0
  {
2025
0
    have_address = true;
2026
0
  } else {
2027
0
    have_address = false;
2028
0
  }
2029
0
  if (wanted_fetches != 0 && !(FIND_AVOIDFETCHES(find) && have_address) &&
2030
0
      !FIND_NOFETCH(find))
2031
0
  {
2032
0
    bool no_validate = FIND_NOVALIDATE(find);
2033
2034
    /*
2035
     * We're missing at least one address family.  Either the
2036
     * caller hasn't instructed us to avoid fetches, or we don't
2037
     * know anything about any of the address families that would
2038
     * be acceptable so we have to launch fetches.
2039
     */
2040
2041
0
    if (FIND_STARTATZONE(find)) {
2042
0
      start_at_zone = true;
2043
0
    }
2044
2045
    /*
2046
     * Start V4.
2047
     */
2048
0
    if (WANT_INET(wanted_fetches) &&
2049
0
        fetch_name(adbname, start_at_zone, no_validate, depth, qc,
2050
0
             gqc, parent, dns_rdatatype_a) == ISC_R_SUCCESS)
2051
0
    {
2052
0
      DP(DEF_LEVEL,
2053
0
         "dns_adb_createfind: "
2054
0
         "started A fetch for name %s (%p)",
2055
0
         namebuf, adbname);
2056
0
    }
2057
2058
    /*
2059
     * Start V6.
2060
     */
2061
0
    if (WANT_INET6(wanted_fetches) &&
2062
0
        fetch_name(adbname, start_at_zone, no_validate, depth, qc,
2063
0
             gqc, parent,
2064
0
             dns_rdatatype_aaaa) == ISC_R_SUCCESS)
2065
0
    {
2066
0
      DP(DEF_LEVEL,
2067
0
         "dns_adb_createfind: "
2068
0
         "started AAAA fetch for name %s (%p)",
2069
0
         namebuf, adbname);
2070
0
    }
2071
0
  }
2072
2073
  /*
2074
   * Run through the name and copy out the bits we are
2075
   * interested in.
2076
   */
2077
0
  copy_namehook_lists(adb, find, adbname, maxfindlen, findlen);
2078
2079
0
post_copy:
2080
0
  if (NAME_FETCH_A(adbname)) {
2081
0
    query_pending |= DNS_ADBFIND_INET;
2082
0
  }
2083
0
  if (NAME_FETCH_AAAA(adbname)) {
2084
0
    query_pending |= DNS_ADBFIND_INET6;
2085
0
  }
2086
2087
  /*
2088
   * Attach to the name's query list if there are queries
2089
   * already running, and we have been asked to.
2090
   */
2091
0
  if (!FIND_WANTEVENT(find)) {
2092
0
    want_event = false;
2093
0
  }
2094
0
  if (FIND_WANTEMPTYEVENT(find) && FIND_HAS_ADDRS(find)) {
2095
0
    want_event = false;
2096
0
  }
2097
0
  if ((wanted_addresses & query_pending) == 0) {
2098
0
    want_event = false;
2099
0
  }
2100
0
  if (alias) {
2101
0
    want_event = false;
2102
0
  }
2103
0
  if (want_event) {
2104
0
    bool empty;
2105
2106
0
    find->adbname = adbname;
2107
0
    empty = ISC_LIST_EMPTY(adbname->finds);
2108
0
    ISC_LIST_APPEND(adbname->finds, find, plink);
2109
0
    find->query_pending = (query_pending & wanted_addresses);
2110
0
    find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
2111
0
    find->flags |= (find->query_pending & DNS_ADBFIND_ADDRESSMASK);
2112
0
    DP(DEF_LEVEL, "createfind: attaching find %p to adbname %p %d",
2113
0
       find, adbname, empty);
2114
0
  } else {
2115
    /*
2116
     * Remove the flag so the caller knows there will never
2117
     * be an event, and set internal flags to fake that
2118
     * the event was sent and freed, so dns_adb_destroyfind() will
2119
     * do the right thing.
2120
     */
2121
0
    find->query_pending = (query_pending & wanted_addresses);
2122
0
    find->options &= ~DNS_ADBFIND_WANTEVENT;
2123
0
    find->flags |= FIND_EVENT_SENT;
2124
0
    find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
2125
0
  }
2126
2127
0
  find->partial_result |= (adbname->partial_result & wanted_addresses);
2128
0
  if (alias) {
2129
0
    result = DNS_R_ALIAS;
2130
0
  } else {
2131
0
    result = ISC_R_SUCCESS;
2132
0
  }
2133
2134
  /*
2135
   * Copy out error flags from the name structure into the find.
2136
   */
2137
0
  find->result_v4 = find_err_map[adbname->fetch_err];
2138
0
  find->result_v6 = find_err_map[adbname->fetch6_err];
2139
2140
0
  if (want_event) {
2141
0
    INSIST((find->flags & DNS_ADBFIND_ADDRESSMASK) != 0);
2142
0
    find->loop = loop;
2143
0
    atomic_store(&find->status, DNS_ADB_UNSET);
2144
0
    find->cb = cb;
2145
0
    find->cbarg = cbarg;
2146
0
  }
2147
2148
0
  if (wanted_fetches) {
2149
0
    find->options |= DNS_ADBFIND_STARTEDFETCH;
2150
0
  }
2151
2152
0
  *findp = find;
2153
2154
0
  UNLOCK(&adbname->lock);
2155
0
  dns_adbname_detach(&adbname);
2156
2157
0
  rcu_read_unlock();
2158
2159
0
  return result;
2160
0
}
2161
2162
void
2163
0
dns_adb_destroyfind(dns_adbfind_t **findp) {
2164
0
  dns_adbfind_t *find = NULL;
2165
0
  dns_adb_t *adb = NULL;
2166
2167
0
  REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp));
2168
2169
0
  find = *findp;
2170
0
  *findp = NULL;
2171
2172
0
  DP(DEF_LEVEL, "dns_adb_destroyfind on find %p", find);
2173
2174
0
  REQUIRE(find->loop == NULL || isc_loop() == find->loop);
2175
2176
0
  adb = find->adb;
2177
2178
0
  LOCK(&find->lock);
2179
2180
0
  REQUIRE(find->adbname == NULL);
2181
2182
  /*
2183
   * Free the addrinfo objects on the find's list. Note that
2184
   * we also need to decrement the reference counter in the
2185
   * associated adbentry every time we remove one from the list.
2186
   */
2187
0
  ISC_LIST_FOREACH(find->list, ai, publink) {
2188
0
    ISC_LIST_UNLINK(find->list, ai, publink);
2189
0
    free_adbaddrinfo(adb, &ai);
2190
0
  }
2191
0
  UNLOCK(&find->lock);
2192
2193
0
  free_adbfind(&find);
2194
0
}
2195
2196
/*
2197
 * Caller must hold find lock.
2198
 */
2199
static void
2200
0
find_sendevent(dns_adbfind_t *find) {
2201
0
  REQUIRE(find->loop != NULL && isc_loop() == find->loop);
2202
2203
0
  if (!FIND_EVENTSENT(find)) {
2204
0
    atomic_store(&find->status, DNS_ADB_CANCELED);
2205
2206
0
    DP(DEF_LEVEL, "sending find %p to caller", find);
2207
2208
0
    isc_async_run(find->loop, find->cb, find);
2209
0
  }
2210
0
}
2211
2212
void
2213
0
dns_adb_cancelfind(dns_adbfind_t *find) {
2214
0
  dns_adbname_t *adbname = NULL;
2215
2216
0
  DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
2217
2218
0
  REQUIRE(DNS_ADBFIND_VALID(find));
2219
0
  REQUIRE(DNS_ADB_VALID(find->adb));
2220
0
  REQUIRE(find->loop != NULL && isc_loop() == find->loop);
2221
2222
0
  LOCK(&find->lock);
2223
0
  REQUIRE(FIND_WANTEVENT(find));
2224
2225
0
  adbname = find->adbname;
2226
2227
0
  if (adbname == NULL) {
2228
0
    find_sendevent(find);
2229
0
    UNLOCK(&find->lock);
2230
0
  } else {
2231
    /*
2232
     * Release the find lock, then acquire the name and find
2233
     * locks in that order, to match locking hierarchy
2234
     * elsewhere.
2235
     */
2236
0
    dns_adbname_ref(adbname);
2237
0
    UNLOCK(&find->lock);
2238
2239
    /*
2240
     * Other thread could cancel the find between the unlock and
2241
     * lock, so we need to recheck whether the adbname is still
2242
     * valid and reference the adbname, so it does not vanish before
2243
     * we have a chance to lock it again.
2244
     */
2245
2246
0
    LOCK(&adbname->lock);
2247
0
    LOCK(&find->lock);
2248
2249
0
    if (find->adbname != NULL) {
2250
0
      ISC_LIST_UNLINK(find->adbname->finds, find, plink);
2251
0
      find->adbname = NULL;
2252
0
    }
2253
2254
0
    find_sendevent(find);
2255
2256
0
    UNLOCK(&find->lock);
2257
0
    UNLOCK(&adbname->lock);
2258
0
    dns_adbname_detach(&adbname);
2259
0
  }
2260
0
}
2261
2262
unsigned int
2263
0
dns_adb_findstatus(dns_adbfind_t *find) {
2264
0
  REQUIRE(DNS_ADBFIND_VALID(find));
2265
2266
0
  return atomic_load(&find->status);
2267
0
}
2268
2269
void
2270
0
dns_adb_dump(dns_adb_t *adb, FILE *f) {
2271
0
  isc_stdtime_t now = isc_stdtime_now();
2272
2273
0
  REQUIRE(DNS_ADB_VALID(adb));
2274
0
  REQUIRE(f != NULL);
2275
2276
0
  rcu_read_lock();
2277
2278
0
  if (atomic_load(&adb->shuttingdown)) {
2279
0
    rcu_read_unlock();
2280
0
    return;
2281
0
  }
2282
2283
0
  dump_adb(adb, f, false, now);
2284
2285
0
  rcu_read_unlock();
2286
0
}
2287
2288
static void
2289
0
dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) {
2290
0
  if (value == INT_MAX) {
2291
0
    return;
2292
0
  }
2293
0
  fprintf(f, " [%s TTL %d]", legend, (int)(value - now));
2294
0
}
2295
2296
/*
2297
 * Both rwlocks for the hash tables need to be held by the caller.
2298
 */
2299
static void
2300
0
dump_adb(dns_adb_t *adb, FILE *f, bool debug, isc_stdtime_t now) {
2301
0
  struct cds_lfht_iter iter;
2302
2303
0
  fprintf(f, ";\n; Address database dump\n;\n");
2304
0
  fprintf(f, "; [edns success/timeout]\n");
2305
0
  fprintf(f, "; [plain success/timeout]\n;\n");
2306
0
  if (debug) {
2307
0
    fprintf(f, "; addr %p, references %" PRIuFAST32 "\n", adb,
2308
0
      isc_refcount_current(&adb->references));
2309
0
  }
2310
2311
  /*
2312
   * Ensure this operation is applied to both hash tables at once.
2313
   */
2314
0
  dns_adbname_t *adbname = NULL;
2315
0
  cds_lfht_for_each_entry(adb->names_ht, &iter, adbname, ht_node) {
2316
0
    dns_adbname_ref(adbname);
2317
0
    LOCK(&adbname->lock);
2318
2319
    /*
2320
     * Lazily expire stale name hooks and names while dumping.
2321
     */
2322
0
    maybe_expire_namehooks(adbname, now);
2323
0
    if (maybe_expire_name(adbname, now)) {
2324
0
      UNLOCK(&adbname->lock);
2325
0
      dns_adbname_detach(&adbname);
2326
0
      continue;
2327
0
    }
2328
2329
    /*
2330
     * Dump the names
2331
     */
2332
0
    if (debug) {
2333
0
      fprintf(f, "; name %p (flags %08x)\n", adbname,
2334
0
        adbname->flags);
2335
0
    }
2336
0
    fprintf(f, "; ");
2337
0
    dns_name_print(adbname->name, f);
2338
2339
0
    dump_ttl(f, "v4", adbname->expire_v4, now);
2340
0
    dump_ttl(f, "v6", adbname->expire_v6, now);
2341
2342
0
    fprintf(f, " [v4 %s] [v6 %s]", errnames[adbname->fetch_err],
2343
0
      errnames[adbname->fetch6_err]);
2344
2345
0
    fprintf(f, "\n");
2346
2347
0
    print_namehook_list(f, "v4", adb, &adbname->v4, debug, now);
2348
0
    print_namehook_list(f, "v6", adb, &adbname->v6, debug, now);
2349
2350
0
    if (debug) {
2351
0
      print_fetch_list(f, adbname);
2352
0
      print_find_list(f, adbname);
2353
0
    }
2354
0
    UNLOCK(&adbname->lock);
2355
0
    dns_adbname_detach(&adbname);
2356
0
  }
2357
2358
0
  dns_adbentry_t *adbentry = NULL;
2359
2360
0
  fprintf(f, ";\n; Unassociated entries\n;\n");
2361
0
  cds_lfht_for_each_entry(adb->entries_ht, &iter, adbentry, ht_node) {
2362
0
    dns_adbentry_ref(adbentry);
2363
0
    LOCK(&adbentry->lock);
2364
0
    if (maybe_expire_entry(adbentry, now)) {
2365
0
      UNLOCK(&adbentry->lock);
2366
0
      dns_adbentry_detach(&adbentry);
2367
0
      continue;
2368
0
    }
2369
0
    if (ISC_LIST_EMPTY(adbentry->nhs)) {
2370
0
      dump_entry(f, adb, adbentry, debug, now);
2371
0
    }
2372
0
    UNLOCK(&adbentry->lock);
2373
0
    dns_adbentry_detach(&adbentry);
2374
0
  }
2375
0
}
2376
2377
static void
2378
dump_entry(FILE *f, dns_adb_t *adb, dns_adbentry_t *entry, bool debug,
2379
0
     isc_stdtime_t now) {
2380
0
  char addrbuf[ISC_NETADDR_FORMATSIZE];
2381
0
  isc_netaddr_t netaddr;
2382
2383
0
  isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
2384
0
  isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
2385
2386
0
  if (debug) {
2387
0
    fprintf(f, ";\t%p: refcnt %" PRIuFAST32 "\n", entry,
2388
0
      isc_refcount_current(&entry->references));
2389
0
  }
2390
2391
0
  fprintf(f,
2392
0
    ";\t%s [srtt %u] [flags %08x] [edns %u/%u] "
2393
0
    "[plain %u/%u]",
2394
0
    addrbuf, atomic_load(&entry->srtt), atomic_load(&entry->flags),
2395
0
    entry->edns, entry->ednsto, entry->plain, entry->plainto);
2396
0
  if (entry->udpsize != 0U) {
2397
0
    fprintf(f, " [udpsize %u]", entry->udpsize);
2398
0
  }
2399
0
  if (entry->cookie != NULL) {
2400
0
    unsigned int i;
2401
0
    fprintf(f, " [cookie=");
2402
0
    for (i = 0; i < entry->cookielen; i++) {
2403
0
      fprintf(f, "%02x", entry->cookie[i]);
2404
0
    }
2405
0
    fprintf(f, "]");
2406
0
  }
2407
0
  fprintf(f, " [ttl %d]", entry->expires - now);
2408
2409
0
  if (adb != NULL && adb->quota != 0 && adb->atr_freq != 0) {
2410
0
    uint_fast32_t quota = atomic_load_relaxed(&entry->quota);
2411
0
    fprintf(f, " [atr %0.2f] [quota %" PRIuFAST32 "]", entry->atr,
2412
0
      quota);
2413
0
  }
2414
2415
0
  fprintf(f, "\n");
2416
0
}
2417
2418
static void
2419
0
dumpfind(dns_adbfind_t *find, FILE *f) {
2420
0
  char tmp[512];
2421
0
  const char *tmpp = NULL;
2422
0
  isc_sockaddr_t *sa = NULL;
2423
2424
  /*
2425
   * Not used currently, in the API Just In Case we
2426
   * want to dump out the name and/or entries too.
2427
   */
2428
2429
0
  LOCK(&find->lock);
2430
2431
0
  fprintf(f, ";Find %p\n", find);
2432
0
  fprintf(f, ";\tqpending %08x partial %08x options %08x flags %08x\n",
2433
0
    find->query_pending, find->partial_result, find->options,
2434
0
    find->flags);
2435
0
  fprintf(f, ";\tname %p\n", find->adbname);
2436
2437
0
  if (!ISC_LIST_EMPTY(find->list)) {
2438
0
    fprintf(f, "\tAddresses:\n");
2439
0
  }
2440
0
  ISC_LIST_FOREACH(find->list, ai, publink) {
2441
0
    sa = &ai->sockaddr;
2442
0
    switch (sa->type.sa.sa_family) {
2443
0
    case AF_INET:
2444
0
      tmpp = inet_ntop(AF_INET, &sa->type.sin.sin_addr, tmp,
2445
0
           sizeof(tmp));
2446
0
      break;
2447
0
    case AF_INET6:
2448
0
      tmpp = inet_ntop(AF_INET6, &sa->type.sin6.sin6_addr,
2449
0
           tmp, sizeof(tmp));
2450
0
      break;
2451
0
    default:
2452
0
      tmpp = "UnkFamily";
2453
0
    }
2454
2455
0
    if (tmpp == NULL) {
2456
0
      tmpp = "BadAddress";
2457
0
    }
2458
2459
0
    fprintf(f,
2460
0
      "\t\tentry %p, flags %08x"
2461
0
      " srtt %u addr %s\n",
2462
0
      ai->entry, ai->flags, ai->srtt, tmpp);
2463
0
  }
2464
2465
0
  UNLOCK(&find->lock);
2466
0
}
2467
2468
static void
2469
print_namehook_list(FILE *f, const char *legend, dns_adb_t *adb,
2470
        dns_adbnamehooklist_t *list, bool debug,
2471
0
        isc_stdtime_t now) {
2472
0
  ISC_LIST_FOREACH(*list, nh, name_link) {
2473
0
    if (debug) {
2474
0
      fprintf(f, ";\tHook(%s) %p\n", legend, nh);
2475
0
    }
2476
0
    LOCK(&nh->entry->lock);
2477
0
    dump_entry(f, adb, nh->entry, debug, now);
2478
0
    UNLOCK(&nh->entry->lock);
2479
0
  }
2480
0
}
2481
2482
static void
2483
0
print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) {
2484
0
  fprintf(f, "\t\tFetch(%s): %p -> { fetch %p }\n", type, ft, ft->fetch);
2485
0
}
2486
2487
static void
2488
0
print_fetch_list(FILE *f, dns_adbname_t *n) {
2489
0
  if (NAME_FETCH_A(n)) {
2490
0
    print_fetch(f, n->fetch_a, "A");
2491
0
  }
2492
0
  if (NAME_FETCH_AAAA(n)) {
2493
0
    print_fetch(f, n->fetch_aaaa, "AAAA");
2494
0
  }
2495
0
}
2496
2497
static void
2498
0
print_find_list(FILE *f, dns_adbname_t *name) {
2499
0
  ISC_LIST_FOREACH(name->finds, find, plink) {
2500
0
    dumpfind(find, f);
2501
0
  }
2502
0
}
2503
2504
static isc_result_t
2505
0
putstr(isc_buffer_t *b, const char *str) {
2506
0
  RETERR(isc_buffer_reserve(b, strlen(str)));
2507
2508
0
  isc_buffer_putstr(b, str);
2509
0
  return ISC_R_SUCCESS;
2510
0
}
2511
2512
isc_result_t
2513
0
dns_adb_dumpquota(dns_adb_t *adb, isc_buffer_t *buf) {
2514
0
  REQUIRE(DNS_ADB_VALID(adb));
2515
2516
0
  dns_adbentry_t *adbentry = NULL;
2517
0
  struct cds_lfht_iter iter;
2518
2519
0
  rcu_read_lock();
2520
0
  if (atomic_load(&adb->shuttingdown)) {
2521
0
    rcu_read_unlock();
2522
0
    return ISC_R_SHUTTINGDOWN;
2523
0
  }
2524
2525
0
  cds_lfht_for_each_entry(adb->entries_ht, &iter, adbentry, ht_node) {
2526
0
    LOCK(&adbentry->lock);
2527
0
    char addrbuf[ISC_NETADDR_FORMATSIZE];
2528
0
    char text[ISC_NETADDR_FORMATSIZE + BUFSIZ];
2529
0
    isc_netaddr_t netaddr;
2530
2531
0
    if (adbentry->atr == 0.0 && adbentry->quota == adb->quota) {
2532
0
      goto unlock;
2533
0
    }
2534
2535
0
    isc_netaddr_fromsockaddr(&netaddr, &adbentry->sockaddr);
2536
0
    isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
2537
2538
0
    snprintf(text, sizeof(text),
2539
0
       "\n- quota %s (%" PRIuFAST32 "/%d) atr %0.2f", addrbuf,
2540
0
       atomic_load_relaxed(&adbentry->quota), adb->quota,
2541
0
       adbentry->atr);
2542
0
    putstr(buf, text);
2543
0
  unlock:
2544
0
    UNLOCK(&adbentry->lock);
2545
0
  }
2546
0
  rcu_read_unlock();
2547
2548
0
  return ISC_R_SUCCESS;
2549
0
}
2550
2551
static isc_result_t
2552
0
dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype) {
2553
0
  isc_result_t result;
2554
0
  dns_rdataset_t rdataset;
2555
0
  dns_adb_t *adb = NULL;
2556
0
  dns_fixedname_t foundname;
2557
0
  dns_name_t *fname = NULL;
2558
0
  unsigned int options = DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK;
2559
2560
0
  REQUIRE(DNS_ADBNAME_VALID(adbname));
2561
2562
0
  adb = adbname->adb;
2563
2564
0
  REQUIRE(DNS_ADB_VALID(adb));
2565
0
  REQUIRE(dns_rdatatype_isaddr(rdtype));
2566
2567
0
  fname = dns_fixedname_initname(&foundname);
2568
0
  dns_rdataset_init(&rdataset);
2569
2570
0
  if (rdtype == dns_rdatatype_a) {
2571
0
    adbname->fetch_err = FIND_ERR_UNEXPECTED;
2572
0
  } else {
2573
0
    adbname->fetch6_err = FIND_ERR_UNEXPECTED;
2574
0
  }
2575
2576
  /*
2577
   * We need to specify whether to search static-stub zones (if
2578
   * configured) depending on whether this is a "start at zone" lookup,
2579
   * i.e., whether it's a "bailiwick" glue.  If it's bailiwick (in which
2580
   * case DNS_ADBFIND_STARTATZONE is set) we need to stop the search at
2581
   * any matching static-stub zone without looking into the cache to honor
2582
   * the configuration on which server we should send queries to.
2583
   */
2584
0
  if ((adbname->type & DNS_ADBFIND_STARTATZONE) != 0) {
2585
0
    options |= DNS_DBFIND_PENDINGOK;
2586
0
  }
2587
0
  result = dns_view_find(adb->view, adbname->name, rdtype, now, options,
2588
0
             true,
2589
0
             (adbname->type & DNS_ADBFIND_STARTATZONE) != 0,
2590
0
             NULL, NULL, fname, &rdataset, NULL);
2591
2592
0
  switch (result) {
2593
0
  case DNS_R_GLUE:
2594
0
  case DNS_R_HINT:
2595
0
    result = ISC_R_SUCCESS;
2596
0
    FALLTHROUGH;
2597
0
  case ISC_R_SUCCESS:
2598
    /*
2599
     * Found in the database.  Even if we can't copy out
2600
     * any information, return success, or else a fetch
2601
     * will be made, which will only make things worse.
2602
     */
2603
0
    if (rdtype == dns_rdatatype_a) {
2604
0
      adbname->fetch_err = FIND_ERR_SUCCESS;
2605
0
    } else {
2606
0
      adbname->fetch6_err = FIND_ERR_SUCCESS;
2607
0
    }
2608
0
    import_rdataset(adbname, &rdataset, now);
2609
0
    break;
2610
0
  case DNS_R_NXDOMAIN:
2611
0
  case DNS_R_NXRRSET:
2612
    /*
2613
     * We're authoritative and the data doesn't exist.
2614
     * Make up a negative cache entry so we don't ask again
2615
     * for a while.
2616
     *
2617
     * XXXRTH  What time should we use?  I'm putting in 30 seconds
2618
     * for now.
2619
     */
2620
0
    if (rdtype == dns_rdatatype_a) {
2621
0
      adbname->expire_v4 = now + 30;
2622
0
      DP(NCACHE_LEVEL,
2623
0
         "adb name %p: Caching auth negative entry for A",
2624
0
         adbname);
2625
0
      if (result == DNS_R_NXDOMAIN) {
2626
0
        adbname->fetch_err = FIND_ERR_NXDOMAIN;
2627
0
      } else {
2628
0
        adbname->fetch_err = FIND_ERR_NXRRSET;
2629
0
      }
2630
0
    } else {
2631
0
      DP(NCACHE_LEVEL,
2632
0
         "adb name %p: Caching auth negative entry for AAAA",
2633
0
         adbname);
2634
0
      adbname->expire_v6 = now + 30;
2635
0
      if (result == DNS_R_NXDOMAIN) {
2636
0
        adbname->fetch6_err = FIND_ERR_NXDOMAIN;
2637
0
      } else {
2638
0
        adbname->fetch6_err = FIND_ERR_NXRRSET;
2639
0
      }
2640
0
    }
2641
0
    break;
2642
0
  case DNS_R_NCACHENXDOMAIN:
2643
0
  case DNS_R_NCACHENXRRSET:
2644
    /*
2645
     * We found a negative cache entry.  Pull the TTL from it
2646
     * so we won't ask again for a while.
2647
     */
2648
0
    rdataset.ttl = ttlclamp(rdataset.ttl);
2649
0
    if (rdtype == dns_rdatatype_a) {
2650
0
      adbname->expire_v4 = rdataset.ttl + now;
2651
0
      if (result == DNS_R_NCACHENXDOMAIN) {
2652
0
        adbname->fetch_err = FIND_ERR_NXDOMAIN;
2653
0
      } else {
2654
0
        adbname->fetch_err = FIND_ERR_NXRRSET;
2655
0
      }
2656
0
      DP(NCACHE_LEVEL,
2657
0
         "adb name %p: Caching negative entry for A (ttl %u)",
2658
0
         adbname, rdataset.ttl);
2659
0
    } else {
2660
0
      DP(NCACHE_LEVEL,
2661
0
         "adb name %p: Caching negative entry for AAAA (ttl "
2662
0
         "%u)",
2663
0
         adbname, rdataset.ttl);
2664
0
      adbname->expire_v6 = rdataset.ttl + now;
2665
0
      if (result == DNS_R_NCACHENXDOMAIN) {
2666
0
        adbname->fetch6_err = FIND_ERR_NXDOMAIN;
2667
0
      } else {
2668
0
        adbname->fetch6_err = FIND_ERR_NXRRSET;
2669
0
      }
2670
0
    }
2671
0
    break;
2672
0
  case DNS_R_CNAME:
2673
0
  case DNS_R_DNAME:
2674
    /*
2675
     * We found a CNAME or DNAME. Mark this as an
2676
     * alias (not to be used) and mark the expiry
2677
     * for both address families so we won't ask again
2678
     * for a while.
2679
     */
2680
0
    rdataset.ttl = ttlclamp(rdataset.ttl);
2681
0
    result = DNS_R_ALIAS;
2682
0
    adbname->flags |= NAME_IS_ALIAS;
2683
0
    adbname->expire_v4 = adbname->expire_v6 =
2684
0
      ADJUSTED_EXPIRE(INT_MAX, now, rdataset.ttl);
2685
0
    if (rdtype == dns_rdatatype_a) {
2686
0
      adbname->fetch_err = FIND_ERR_SUCCESS;
2687
0
    } else {
2688
0
      adbname->fetch6_err = FIND_ERR_SUCCESS;
2689
0
    }
2690
0
    break;
2691
0
  default:
2692
0
    break;
2693
0
  }
2694
2695
0
  dns_rdataset_cleanup(&rdataset);
2696
2697
0
  return result;
2698
0
}
2699
2700
static void
2701
0
fetch_callback(void *arg) {
2702
0
  dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
2703
0
  dns_adbname_t *name = resp->arg;
2704
0
  dns_adb_t *adb = NULL;
2705
0
  dns_adbfetch_t *fetch = NULL;
2706
0
  dns_adbstatus_t astat = DNS_ADB_NOMOREADDRESSES;
2707
0
  isc_stdtime_t now = isc_stdtime_now();
2708
0
  unsigned int address_type;
2709
2710
0
  REQUIRE(DNS_ADBNAME_VALID(name));
2711
0
  dns_adb_attach(name->adb, &adb);
2712
2713
0
  REQUIRE(DNS_ADB_VALID(adb));
2714
2715
0
  rcu_read_lock();
2716
2717
0
  LOCK(&name->lock);
2718
2719
0
  INSIST(NAME_FETCH_A(name) || NAME_FETCH_AAAA(name));
2720
0
  address_type = 0;
2721
0
  if (NAME_FETCH_A(name) && (name->fetch_a->fetch == resp->fetch)) {
2722
0
    address_type = DNS_ADBFIND_INET;
2723
0
    fetch = name->fetch_a;
2724
0
    name->fetch_a = NULL;
2725
0
  } else if (NAME_FETCH_AAAA(name) &&
2726
0
       (name->fetch_aaaa->fetch == resp->fetch))
2727
0
  {
2728
0
    address_type = DNS_ADBFIND_INET6;
2729
0
    fetch = name->fetch_aaaa;
2730
0
    name->fetch_aaaa = NULL;
2731
0
  } else {
2732
0
    fetch = NULL;
2733
0
  }
2734
2735
0
  INSIST(address_type != 0 && fetch != NULL);
2736
2737
  /*
2738
   * Cleanup things we don't care about.
2739
   */
2740
0
  if (resp->node != NULL) {
2741
0
    dns_db_detachnode(&resp->node);
2742
0
  }
2743
0
  if (resp->cache != NULL) {
2744
0
    dns_db_detach(&resp->cache);
2745
0
  }
2746
2747
0
  if (atomic_load(&adb->shuttingdown)) {
2748
0
    astat = DNS_ADB_SHUTTINGDOWN;
2749
0
    goto out;
2750
0
  }
2751
2752
  /*
2753
   * If this name is marked as dead, clean up, throwing away
2754
   * potentially good data.
2755
   */
2756
0
  if (cds_lfht_is_node_deleted(&name->ht_node)) {
2757
0
    astat = DNS_ADB_CANCELED;
2758
0
    goto out;
2759
0
  }
2760
2761
  /*
2762
   * If we got a negative cache response, remember it.
2763
   */
2764
0
  if (NCACHE_RESULT(resp->result)) {
2765
0
    resp->rdataset->ttl = ttlclamp(resp->rdataset->ttl);
2766
0
    if (address_type == DNS_ADBFIND_INET) {
2767
0
      name->expire_v4 = ADJUSTED_EXPIRE(name->expire_v4, now,
2768
0
                resp->rdataset->ttl);
2769
0
      DP(NCACHE_LEVEL,
2770
0
         "adb fetch name %p: "
2771
0
         "caching negative entry for A (ttl %u)",
2772
0
         name, name->expire_v4);
2773
0
      if (resp->result == DNS_R_NCACHENXDOMAIN) {
2774
0
        name->fetch_err = FIND_ERR_NXDOMAIN;
2775
0
      } else {
2776
0
        name->fetch_err = FIND_ERR_NXRRSET;
2777
0
      }
2778
0
      inc_resstats(adb, dns_resstatscounter_gluefetchv4fail);
2779
0
    } else {
2780
0
      name->expire_v6 = ADJUSTED_EXPIRE(name->expire_v6, now,
2781
0
                resp->rdataset->ttl);
2782
0
      DP(NCACHE_LEVEL,
2783
0
         "adb fetch name %p: "
2784
0
         "caching negative entry for AAAA (ttl %u)",
2785
0
         name, name->expire_v6);
2786
0
      if (resp->result == DNS_R_NCACHENXDOMAIN) {
2787
0
        name->fetch6_err = FIND_ERR_NXDOMAIN;
2788
0
      } else {
2789
0
        name->fetch6_err = FIND_ERR_NXRRSET;
2790
0
      }
2791
0
      inc_resstats(adb, dns_resstatscounter_gluefetchv6fail);
2792
0
    }
2793
0
    goto out;
2794
0
  }
2795
2796
  /*
2797
   * Handle CNAME/DNAME.
2798
   */
2799
0
  if (resp->result == DNS_R_CNAME || resp->result == DNS_R_DNAME) {
2800
0
    resp->rdataset->ttl = ttlclamp(resp->rdataset->ttl);
2801
0
    name->flags |= NAME_IS_ALIAS;
2802
0
    name->expire_v4 = name->expire_v6 =
2803
0
      ADJUSTED_EXPIRE(INT_MAX, now, resp->rdataset->ttl);
2804
0
    goto moreaddrs;
2805
0
  }
2806
2807
  /*
2808
   * Did we get back junk?  If so, and there are no more fetches
2809
   * sitting out there, tell all the finds about it.
2810
   */
2811
0
  if (resp->result != ISC_R_SUCCESS) {
2812
0
    char buf[DNS_NAME_FORMATSIZE];
2813
2814
0
    dns_name_format(name->name, buf, sizeof(buf));
2815
0
    DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", buf,
2816
0
       address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
2817
0
       isc_result_totext(resp->result));
2818
    /*
2819
     * Don't record a failure unless this is the initial
2820
     * fetch of a chain.
2821
     */
2822
0
    if (fetch->depth > 1) {
2823
0
      goto out;
2824
0
    }
2825
    /* XXXMLG Don't pound on bad servers. */
2826
0
    if (address_type == DNS_ADBFIND_INET) {
2827
0
      name->expire_v4 = ISC_MIN(name->expire_v4, now + 10);
2828
0
      name->fetch_err = FIND_ERR_FAILURE;
2829
0
      inc_resstats(adb, dns_resstatscounter_gluefetchv4fail);
2830
0
    } else {
2831
0
      name->expire_v6 = ISC_MIN(name->expire_v6, now + 10);
2832
0
      name->fetch6_err = FIND_ERR_FAILURE;
2833
0
      inc_resstats(adb, dns_resstatscounter_gluefetchv6fail);
2834
0
    }
2835
0
    goto out;
2836
0
  }
2837
2838
  /*
2839
   * We got something potentially useful.
2840
   */
2841
0
  import_rdataset(name, &fetch->rdataset, now);
2842
2843
0
moreaddrs:
2844
0
  astat = DNS_ADB_MOREADDRESSES;
2845
0
  if (address_type == DNS_ADBFIND_INET) {
2846
0
    name->fetch_err = FIND_ERR_SUCCESS;
2847
0
  } else {
2848
0
    name->fetch6_err = FIND_ERR_SUCCESS;
2849
0
  }
2850
2851
0
out:
2852
0
  dns_resolver_destroyfetch(&fetch->fetch);
2853
0
  free_adbfetch(adb, &fetch);
2854
0
  dns_resolver_freefresp(&resp);
2855
0
  if (astat != DNS_ADB_CANCELED) {
2856
0
    clean_finds_at_name(name, astat, address_type);
2857
0
  }
2858
0
  UNLOCK(&name->lock);
2859
0
  dns_adbname_detach(&name);
2860
0
  dns_adb_detach(&adb);
2861
2862
0
  rcu_read_unlock();
2863
0
}
2864
2865
static isc_result_t
2866
fetch_name(dns_adbname_t *adbname, bool start_at_zone, bool no_validation,
2867
     unsigned int depth, isc_counter_t *qc, isc_counter_t *gqc,
2868
0
     fetchctx_t *parent, dns_rdatatype_t type) {
2869
0
  isc_result_t result;
2870
0
  dns_adbfetch_t *fetch = NULL;
2871
0
  dns_adb_t *adb = NULL;
2872
0
  dns_fixedname_t fixed;
2873
0
  dns_name_t *name = NULL;
2874
0
  dns_delegset_t *delegset = NULL;
2875
0
  unsigned int options = no_validation ? DNS_FETCHOPT_NOVALIDATE : 0;
2876
2877
0
  REQUIRE(DNS_ADBNAME_VALID(adbname));
2878
2879
0
  adb = adbname->adb;
2880
2881
0
  REQUIRE(DNS_ADB_VALID(adb));
2882
2883
0
  REQUIRE((type == dns_rdatatype_a && !NAME_FETCH_A(adbname)) ||
2884
0
    (type == dns_rdatatype_aaaa && !NAME_FETCH_AAAA(adbname)));
2885
2886
0
  adbname->fetch_err = FIND_ERR_NOTFOUND;
2887
2888
0
  if (start_at_zone) {
2889
0
    DP(ENTER_LEVEL, "fetch_name: starting at zone for name %p",
2890
0
       adbname);
2891
0
    name = dns_fixedname_initname(&fixed);
2892
0
    CHECK(dns_view_bestzonecut(adb->view, adbname->name, name, NULL,
2893
0
             0, 0, true, false, &delegset));
2894
0
    options |= DNS_FETCHOPT_UNSHARED;
2895
0
  } else if (adb->view->qminimization) {
2896
0
    options |= DNS_FETCHOPT_QMINIMIZE | DNS_FETCHOPT_QMIN_SKIP_IP6A;
2897
0
    if (adb->view->qmin_strict) {
2898
0
      options |= DNS_FETCHOPT_QMIN_STRICT;
2899
0
    }
2900
0
  }
2901
2902
0
  fetch = new_adbfetch(adb);
2903
0
  fetch->depth = depth;
2904
2905
  /*
2906
   * We're not minimizing this query, as nothing user-related should
2907
   * be leaked here.
2908
   * However, if we'd ever want to change it we'd have to modify
2909
   * createfetch to find deepest cached name when we're providing
2910
   * domain and nameservers.
2911
   */
2912
0
  dns_adbname_ref(adbname);
2913
0
  result = dns_resolver_createfetch(
2914
0
    adb->res, adbname->name, type, name, delegset, NULL, NULL, 0,
2915
0
    options, depth, qc, gqc, parent, isc_loop(), fetch_callback,
2916
0
    adbname, NULL, &fetch->rdataset, NULL, &fetch->fetch);
2917
0
  if (result != ISC_R_SUCCESS) {
2918
0
    DP(ENTER_LEVEL, "fetch_name: createfetch failed with %s",
2919
0
       isc_result_totext(result));
2920
0
    dns_adbname_unref(adbname);
2921
0
    goto cleanup;
2922
0
  }
2923
2924
0
  if (type == dns_rdatatype_a) {
2925
0
    adbname->fetch_a = fetch;
2926
0
    inc_resstats(adb, dns_resstatscounter_gluefetchv4);
2927
0
  } else {
2928
0
    adbname->fetch_aaaa = fetch;
2929
0
    inc_resstats(adb, dns_resstatscounter_gluefetchv6);
2930
0
  }
2931
0
  fetch = NULL; /* Keep us from cleaning this up below. */
2932
2933
0
cleanup:
2934
0
  if (fetch != NULL) {
2935
0
    free_adbfetch(adb, &fetch);
2936
0
  }
2937
2938
0
  if (delegset != NULL) {
2939
0
    dns_delegset_detach(&delegset);
2940
0
  }
2941
2942
0
  return result;
2943
0
}
2944
2945
void
2946
dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int rtt,
2947
0
       unsigned int factor) {
2948
0
  REQUIRE(DNS_ADB_VALID(adb));
2949
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
2950
0
  REQUIRE(factor <= 10);
2951
2952
0
  isc_stdtime_t now = 0;
2953
0
  if (factor == DNS_ADB_RTTADJAGE) {
2954
0
    now = isc_stdtime_now();
2955
0
  }
2956
2957
0
  adjustsrtt(addr, rtt, factor, now);
2958
0
}
2959
2960
void
2961
0
dns_adb_agesrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now) {
2962
0
  REQUIRE(DNS_ADB_VALID(adb));
2963
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
2964
2965
0
  adjustsrtt(addr, 0, DNS_ADB_RTTADJAGE, now);
2966
0
}
2967
2968
static void
2969
adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor,
2970
0
     isc_stdtime_t now) {
2971
0
  unsigned int new_srtt;
2972
0
  unsigned int old_srtt;
2973
2974
0
  if (factor == DNS_ADB_RTTADJAGE) {
2975
0
    isc_stdtime_t lastage =
2976
0
      atomic_load_acquire(&addr->entry->lastage);
2977
2978
    /* prevent double aging */
2979
0
    if (lastage == now ||
2980
0
        !atomic_compare_exchange_strong_acq_rel(
2981
0
          &addr->entry->lastage, &lastage, now))
2982
0
    {
2983
0
      return;
2984
0
    }
2985
0
  }
2986
2987
  /*
2988
   * Correct CAS aging...
2989
   */
2990
0
  old_srtt = atomic_load_acquire(&addr->entry->srtt);
2991
0
  do {
2992
0
    if (factor == DNS_ADB_RTTADJAGE) {
2993
0
      new_srtt = (uint64_t)old_srtt * 98 / 100;
2994
0
    } else {
2995
0
      new_srtt = ((uint64_t)old_srtt / 10 * factor) +
2996
0
           ((uint64_t)rtt / 10 * (10 - factor));
2997
0
    }
2998
0
  } while (!atomic_compare_exchange_weak_acq_rel(&addr->entry->srtt,
2999
0
                   &old_srtt, new_srtt));
3000
0
  addr->srtt = new_srtt;
3001
0
}
3002
3003
void
3004
dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int bits,
3005
0
        unsigned int mask) {
3006
0
  REQUIRE(DNS_ADB_VALID(adb));
3007
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3008
3009
0
  dns_adbentry_t *entry = addr->entry;
3010
3011
0
  unsigned int flags = atomic_load(&entry->flags);
3012
0
  while (!atomic_compare_exchange_strong(&entry->flags, &flags,
3013
0
                 (flags & ~mask) | (bits & mask)))
3014
0
  {
3015
    /* repeat */
3016
0
  }
3017
3018
  /*
3019
   * Note that we do not update the other bits in addr->flags with
3020
   * the most recent values from addr->entry->flags.
3021
   */
3022
0
  addr->flags = (addr->flags & ~mask) | (bits & mask);
3023
0
}
3024
3025
/*
3026
 * The polynomial backoff curve (10000 / ((10 + n) / 10)^(3/2)) <0..99> drops
3027
 * fairly aggressively at first, then slows down and tails off at around 2-3%.
3028
 *
3029
 * These will be used to make quota adjustments.
3030
 */
3031
static int quota_adj[] = {
3032
  10000, 8668, 7607, 6747, 6037, 5443, 4941, 4512, 4141, 3818, 3536,
3033
  3286,  3065, 2867, 2690, 2530, 2385, 2254, 2134, 2025, 1925, 1832,
3034
  1747,  1668, 1595, 1527, 1464, 1405, 1350, 1298, 1250, 1205, 1162,
3035
  1121,  1083, 1048, 1014, 981,  922,  894,  868,  843,  820,  797,
3036
  775,   755,  735,  716,  698,  680,  664,  648,  632,  618,  603,
3037
  590,   577,  564,  552,  540,  529,  518,  507,  497,  487,  477,
3038
  468,   459,  450,  442,  434,  426,  418,  411,  404,  397,  390,
3039
  383,   377,  370,  364,  358,  353,  347,  342,  336,  331,  326,
3040
  321,   316,  312,  307,  303,  298,  294,  290,  286,  282,  278
3041
};
3042
3043
0
#define QUOTA_ADJ_SIZE (sizeof(quota_adj) / sizeof(quota_adj[0]))
3044
3045
/*
3046
 * The adb entry associated with 'addr' must be locked.
3047
 */
3048
static void
3049
0
maybe_adjust_quota(dns_adb_t *adb, dns_adbaddrinfo_t *addr, bool timeout) {
3050
0
  double tr;
3051
3052
0
  UNUSED(adb);
3053
3054
0
  if (adb->quota == 0 || adb->atr_freq == 0) {
3055
0
    return;
3056
0
  }
3057
3058
0
  if (timeout) {
3059
0
    addr->entry->timeouts++;
3060
0
  }
3061
3062
0
  if (addr->entry->completed++ <= adb->atr_freq) {
3063
0
    return;
3064
0
  }
3065
3066
  /*
3067
   * Calculate an exponential rolling average of the timeout ratio
3068
   *
3069
   * XXX: Integer arithmetic might be better than floating point
3070
   */
3071
0
  tr = (double)addr->entry->timeouts / addr->entry->completed;
3072
0
  addr->entry->timeouts = addr->entry->completed = 0;
3073
0
  INSIST(addr->entry->atr >= 0.0);
3074
0
  INSIST(addr->entry->atr <= 1.0);
3075
0
  INSIST(adb->atr_discount >= 0.0);
3076
0
  INSIST(adb->atr_discount <= 1.0);
3077
0
  addr->entry->atr *= 1.0 - adb->atr_discount;
3078
0
  addr->entry->atr += tr * adb->atr_discount;
3079
0
  addr->entry->atr = ISC_CLAMP(addr->entry->atr, 0.0, 1.0);
3080
3081
0
  if (addr->entry->atr < adb->atr_low && addr->entry->mode > 0) {
3082
0
    uint_fast32_t new_quota =
3083
0
      adb->quota * quota_adj[--addr->entry->mode] / 10000;
3084
0
    atomic_store_release(&addr->entry->quota,
3085
0
             ISC_MAX(1, new_quota));
3086
0
    log_quota(addr->entry,
3087
0
        "atr %0.2f, quota increased to %" PRIuFAST32,
3088
0
        addr->entry->atr, new_quota);
3089
0
  } else if (addr->entry->atr > adb->atr_high &&
3090
0
       addr->entry->mode < (QUOTA_ADJ_SIZE - 1))
3091
0
  {
3092
0
    uint_fast32_t new_quota =
3093
0
      adb->quota * quota_adj[++addr->entry->mode] / 10000;
3094
0
    atomic_store_release(&addr->entry->quota,
3095
0
             ISC_MAX(1, new_quota));
3096
0
    log_quota(addr->entry,
3097
0
        "atr %0.2f, quota decreased to %" PRIuFAST32,
3098
0
        addr->entry->atr, new_quota);
3099
0
  }
3100
0
}
3101
3102
void
3103
0
dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
3104
0
  REQUIRE(DNS_ADB_VALID(adb));
3105
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3106
3107
0
  dns_adbentry_t *entry = addr->entry;
3108
0
  LOCK(&entry->lock);
3109
3110
0
  maybe_adjust_quota(adb, addr, false);
3111
3112
0
  entry->plain++;
3113
0
  if (entry->plain == 0xff) {
3114
0
    entry->edns >>= 1;
3115
0
    entry->ednsto >>= 1;
3116
0
    entry->plain >>= 1;
3117
0
    entry->plainto >>= 1;
3118
0
  }
3119
0
  UNLOCK(&entry->lock);
3120
0
}
3121
3122
void
3123
0
dns_adb_timeout(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
3124
0
  REQUIRE(DNS_ADB_VALID(adb));
3125
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3126
3127
0
  dns_adbentry_t *entry = addr->entry;
3128
0
  LOCK(&entry->lock);
3129
3130
0
  maybe_adjust_quota(adb, addr, true);
3131
3132
0
  addr->entry->plainto++;
3133
0
  if (addr->entry->plainto == 0xff) {
3134
0
    addr->entry->edns >>= 1;
3135
0
    addr->entry->ednsto >>= 1;
3136
0
    addr->entry->plain >>= 1;
3137
0
    addr->entry->plainto >>= 1;
3138
0
  }
3139
0
  UNLOCK(&entry->lock);
3140
0
}
3141
3142
void
3143
0
dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
3144
0
  REQUIRE(DNS_ADB_VALID(adb));
3145
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3146
3147
0
  dns_adbentry_t *entry = addr->entry;
3148
0
  LOCK(&entry->lock);
3149
3150
0
  maybe_adjust_quota(adb, addr, true);
3151
3152
0
  entry->ednsto++;
3153
0
  if (addr->entry->ednsto == 0xff) {
3154
0
    entry->edns >>= 1;
3155
0
    entry->ednsto >>= 1;
3156
0
    entry->plain >>= 1;
3157
0
    entry->plainto >>= 1;
3158
0
  }
3159
0
  UNLOCK(&entry->lock);
3160
0
}
3161
3162
void
3163
0
dns_adb_setudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size) {
3164
0
  REQUIRE(DNS_ADB_VALID(adb));
3165
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3166
3167
0
  dns_adbentry_t *entry = addr->entry;
3168
3169
0
  LOCK(&entry->lock);
3170
0
  if (size < 512U) {
3171
0
    size = 512U;
3172
0
  }
3173
0
  if (size > addr->entry->udpsize) {
3174
0
    addr->entry->udpsize = size;
3175
0
  }
3176
3177
0
  maybe_adjust_quota(adb, addr, false);
3178
3179
0
  entry->edns++;
3180
0
  if (entry->edns == 0xff) {
3181
0
    entry->edns >>= 1;
3182
0
    entry->ednsto >>= 1;
3183
0
    entry->plain >>= 1;
3184
0
    entry->plainto >>= 1;
3185
0
  }
3186
0
  UNLOCK(&entry->lock);
3187
0
}
3188
3189
unsigned int
3190
0
dns_adb_getudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
3191
0
  REQUIRE(DNS_ADB_VALID(adb));
3192
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3193
3194
0
  unsigned int size;
3195
0
  dns_adbentry_t *entry = addr->entry;
3196
3197
0
  LOCK(&entry->lock);
3198
0
  size = entry->udpsize;
3199
0
  UNLOCK(&entry->lock);
3200
3201
0
  return size;
3202
0
}
3203
3204
void
3205
dns_adb_setcookie(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
3206
0
      const unsigned char *cookie, size_t len) {
3207
0
  REQUIRE(DNS_ADB_VALID(adb));
3208
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3209
3210
0
  dns_adbentry_t *entry = addr->entry;
3211
3212
0
  LOCK(&entry->lock);
3213
3214
0
  if (entry->cookie != NULL &&
3215
0
      (cookie == NULL || len != entry->cookielen))
3216
0
  {
3217
0
    isc_mem_put(adb->mctx, entry->cookie, entry->cookielen);
3218
0
    entry->cookielen = 0;
3219
0
  }
3220
3221
0
  if (entry->cookie == NULL && cookie != NULL && len != 0U) {
3222
0
    entry->cookie = isc_mem_get(adb->mctx, len);
3223
0
    entry->cookielen = (uint16_t)len;
3224
0
  }
3225
3226
0
  if (entry->cookie != NULL) {
3227
0
    memmove(entry->cookie, cookie, len);
3228
0
  }
3229
0
  UNLOCK(&entry->lock);
3230
0
}
3231
3232
size_t
3233
0
dns_adb_getcookie(dns_adbaddrinfo_t *addr, unsigned char *cookie, size_t len) {
3234
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3235
3236
0
  dns_adbentry_t *entry = addr->entry;
3237
3238
0
  LOCK(&entry->lock);
3239
0
  if (entry->cookie == NULL) {
3240
0
    len = 0;
3241
0
    goto unlock;
3242
0
  }
3243
0
  if (cookie != NULL) {
3244
0
    if (len < entry->cookielen) {
3245
0
      len = 0;
3246
0
      goto unlock;
3247
0
    }
3248
0
    memmove(cookie, entry->cookie, entry->cookielen);
3249
0
  }
3250
0
  len = entry->cookielen;
3251
3252
0
unlock:
3253
0
  UNLOCK(&entry->lock);
3254
3255
0
  return len;
3256
0
}
3257
3258
isc_result_t
3259
dns_adb_findaddrinfo(dns_adb_t *adb, const isc_sockaddr_t *addr,
3260
0
         dns_adbaddrinfo_t **adbaddrp, isc_stdtime_t now) {
3261
0
  REQUIRE(DNS_ADB_VALID(adb));
3262
0
  REQUIRE(adbaddrp != NULL && *adbaddrp == NULL);
3263
3264
0
  rcu_read_lock();
3265
0
  if (atomic_load(&adb->shuttingdown)) {
3266
0
    rcu_read_unlock();
3267
0
    return ISC_R_SHUTTINGDOWN;
3268
0
  }
3269
3270
0
  findaddrinfo(adb, addr, adbaddrp, now, DNS_ADBFIND_QUOTAEXEMPT);
3271
3272
0
  rcu_read_unlock();
3273
3274
0
  return ISC_R_SUCCESS;
3275
0
}
3276
3277
void
3278
0
dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) {
3279
0
  dns_adbaddrinfo_t *addr = NULL;
3280
0
  dns_adbentry_t *entry = NULL;
3281
3282
0
  REQUIRE(DNS_ADB_VALID(adb));
3283
0
  REQUIRE(addrp != NULL);
3284
3285
0
  addr = *addrp;
3286
0
  *addrp = NULL;
3287
3288
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3289
3290
0
  entry = addr->entry;
3291
3292
0
  REQUIRE(DNS_ADBENTRY_VALID(entry));
3293
3294
0
  free_adbaddrinfo(adb, &addr);
3295
0
}
3296
3297
void
3298
0
dns_adb_flush(dns_adb_t *adb) {
3299
0
  REQUIRE(DNS_ADB_VALID(adb));
3300
3301
0
  rcu_read_lock();
3302
3303
0
  if (atomic_load(&adb->shuttingdown)) {
3304
0
    rcu_read_unlock();
3305
0
    return;
3306
0
  }
3307
3308
0
  cleanup_names(adb, INT_MAX);
3309
0
  cleanup_entries(adb, INT_MAX);
3310
#ifdef DUMP_ADB_AFTER_CLEANING
3311
  dump_adb(adb, stdout, true, INT_MAX);
3312
#endif /* ifdef DUMP_ADB_AFTER_CLEANING */
3313
3314
0
  rcu_read_unlock();
3315
0
}
3316
3317
void
3318
0
dns_adb_flushname(dns_adb_t *adb, const dns_name_t *name) {
3319
0
  dns_adbname_t *adbname = NULL;
3320
0
  bool start_at_zone = false;
3321
0
  bool static_stub = false;
3322
0
  bool novalidate = false;
3323
0
  dns_adbname_t key = { .name = UNCONST(name) };
3324
3325
0
  REQUIRE(DNS_ADB_VALID(adb));
3326
0
  REQUIRE(name != NULL);
3327
3328
0
  rcu_read_lock();
3329
3330
0
  if (atomic_load(&adb->shuttingdown)) {
3331
0
    rcu_read_unlock();
3332
0
    return;
3333
0
  }
3334
0
again:
3335
  /*
3336
   * Delete all entries - with and without DNS_ADBFIND_STARTATZONE set
3337
   * with and without DNS_ADBFIND_STATICSTUB set and with and without
3338
   * DNS_ADBFIND_NOVALIDATE set.
3339
   */
3340
0
  key.type = ((static_stub) ? DNS_ADBFIND_STATICSTUB : 0) |
3341
0
       ((start_at_zone) ? DNS_ADBFIND_STARTATZONE : 0) |
3342
0
       ((novalidate) ? DNS_ADBFIND_NOVALIDATE : 0);
3343
3344
0
  uint32_t hashval = hash_adbname(&key);
3345
0
  struct cds_lfht_iter iter;
3346
0
  cds_lfht_lookup(adb->names_ht, hashval, match_adbname, &key, &iter);
3347
3348
0
  adbname = cds_lfht_entry(cds_lfht_iter_get_node(&iter), dns_adbname_t,
3349
0
         ht_node);
3350
3351
0
  if (adbname != NULL) {
3352
0
    dns_adbname_ref(adbname);
3353
0
    LOCK(&adbname->lock);
3354
0
    if (dns_name_equal(name, adbname->name)) {
3355
0
      expire_name(adbname, DNS_ADB_CANCELED);
3356
0
    }
3357
0
    UNLOCK(&adbname->lock);
3358
0
    dns_adbname_detach(&adbname);
3359
0
  }
3360
0
  if (!start_at_zone) {
3361
0
    start_at_zone = true;
3362
0
    goto again;
3363
0
  }
3364
0
  if (!static_stub) {
3365
0
    static_stub = true;
3366
0
    goto again;
3367
0
  }
3368
0
  if (!novalidate) {
3369
0
    start_at_zone = false;
3370
0
    static_stub = false;
3371
0
    novalidate = true;
3372
0
    goto again;
3373
0
  }
3374
0
  rcu_read_unlock();
3375
0
}
3376
3377
void
3378
0
dns_adb_flushnames(dns_adb_t *adb, const dns_name_t *name) {
3379
0
  REQUIRE(DNS_ADB_VALID(adb));
3380
0
  REQUIRE(name != NULL);
3381
3382
0
  rcu_read_lock();
3383
3384
0
  if (atomic_load(&adb->shuttingdown)) {
3385
0
    rcu_read_unlock();
3386
0
    return;
3387
0
  }
3388
3389
0
  dns_adbname_t *adbname = NULL;
3390
0
  struct cds_lfht_iter iter;
3391
0
  cds_lfht_for_each_entry(adb->names_ht, &iter, adbname, ht_node) {
3392
0
    dns_adbname_ref(adbname);
3393
0
    LOCK(&adbname->lock);
3394
0
    if (dns_name_issubdomain(adbname->name, name)) {
3395
0
      expire_name(adbname, DNS_ADB_CANCELED);
3396
0
    }
3397
0
    UNLOCK(&adbname->lock);
3398
0
    dns_adbname_detach(&adbname);
3399
0
  }
3400
0
  rcu_read_unlock();
3401
0
}
3402
3403
void
3404
0
dns_adb_setadbsize(dns_adb_t *adb, size_t size) {
3405
0
  size_t hiwater, lowater;
3406
3407
0
  REQUIRE(DNS_ADB_VALID(adb));
3408
3409
0
  if (size != 0U && size < DNS_ADB_MINADBSIZE) {
3410
0
    size = DNS_ADB_MINADBSIZE;
3411
0
  }
3412
3413
0
  hiwater = size - (size >> 3); /* Approximately 7/8ths. */
3414
0
  lowater = size - (size >> 2); /* Approximately 3/4ths. */
3415
3416
0
  if (size == 0U || hiwater == 0U || lowater == 0U) {
3417
0
    isc_mem_clearwater(adb->mctx);
3418
0
  } else {
3419
0
    isc_mem_setwater(adb->mctx, hiwater, lowater);
3420
0
  }
3421
0
}
3422
3423
void
3424
dns_adb_setquota(dns_adb_t *adb, uint32_t quota, uint32_t freq, double low,
3425
0
     double high, double discount) {
3426
0
  REQUIRE(DNS_ADB_VALID(adb));
3427
3428
0
  adb->quota = quota;
3429
0
  adb->atr_freq = freq;
3430
0
  adb->atr_low = low;
3431
0
  adb->atr_high = high;
3432
0
  adb->atr_discount = discount;
3433
0
}
3434
3435
void
3436
dns_adb_getquota(dns_adb_t *adb, uint32_t *quotap, uint32_t *freqp,
3437
0
     double *lowp, double *highp, double *discountp) {
3438
0
  REQUIRE(DNS_ADB_VALID(adb));
3439
3440
0
  SET_IF_NOT_NULL(quotap, adb->quota);
3441
3442
0
  SET_IF_NOT_NULL(freqp, adb->atr_freq);
3443
3444
0
  SET_IF_NOT_NULL(lowp, adb->atr_low);
3445
3446
0
  SET_IF_NOT_NULL(highp, adb->atr_high);
3447
3448
0
  SET_IF_NOT_NULL(discountp, adb->atr_discount);
3449
0
}
3450
3451
static bool
3452
0
adbentry_overquota(dns_adbentry_t *entry) {
3453
0
  REQUIRE(DNS_ADBENTRY_VALID(entry));
3454
3455
0
  uint_fast32_t quota = atomic_load_relaxed(&entry->quota);
3456
0
  uint_fast32_t active = atomic_load_acquire(&entry->active);
3457
3458
0
  return quota != 0 && active >= quota;
3459
0
}
3460
3461
bool
3462
0
dns_adb_overquota(dns_adb_t *adb ISC_ATTR_UNUSED, dns_adbaddrinfo_t *addrinfo) {
3463
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addrinfo));
3464
3465
0
  return adbentry_overquota(addrinfo->entry);
3466
0
}
3467
3468
void
3469
0
dns_adb_beginudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
3470
0
  uint_fast32_t active;
3471
3472
0
  REQUIRE(DNS_ADB_VALID(adb));
3473
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3474
3475
0
  active = atomic_fetch_add_relaxed(&addr->entry->active, 1);
3476
0
  INSIST(active != UINT32_MAX);
3477
0
}
3478
3479
void
3480
0
dns_adb_endudpfetch(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
3481
0
  uint_fast32_t active;
3482
3483
0
  REQUIRE(DNS_ADB_VALID(adb));
3484
0
  REQUIRE(DNS_ADBADDRINFO_VALID(addr));
3485
3486
0
  active = atomic_fetch_sub_release(&addr->entry->active, 1);
3487
0
  INSIST(active != 0);
3488
0
}
3489
3490
isc_stats_t *
3491
0
dns_adb_getstats(dns_adb_t *adb) {
3492
0
  REQUIRE(DNS_ADB_VALID(adb));
3493
3494
0
  return adb->stats;
3495
0
}