xref: /netbsd-src/external/mpl/bind/dist/lib/dns/rrl.c (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 /*	$NetBSD: rrl.c,v 1.9 2024/02/21 22:52:08 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 /*! \file */
17 
18 /*
19  * Rate limit DNS responses.
20  */
21 
22 /* #define ISC_LIST_CHECKINIT */
23 
24 #include <inttypes.h>
25 #include <stdbool.h>
26 
27 #include <isc/mem.h>
28 #include <isc/net.h>
29 #include <isc/netaddr.h>
30 #include <isc/print.h>
31 #include <isc/result.h>
32 #include <isc/util.h>
33 
34 #include <dns/log.h>
35 #include <dns/name.h>
36 #include <dns/rcode.h>
37 #include <dns/rdataclass.h>
38 #include <dns/rdatatype.h>
39 #include <dns/rrl.h>
40 #include <dns/view.h>
41 #include <dns/zone.h>
42 
43 static void
44 log_end(dns_rrl_t *rrl, dns_rrl_entry_t *e, bool early, char *log_buf,
45 	unsigned int log_buf_len);
46 
47 /*
48  * Get a modulus for a hash function that is tolerably likely to be
49  * relatively prime to most inputs.  Of course, we get a prime for for initial
50  * values not larger than the square of the last prime.  We often get a prime
51  * after that.
52  * This works well in practice for hash tables up to at least 100
53  * times the square of the last prime and better than a multiplicative hash.
54  */
55 static int
56 hash_divisor(unsigned int initial) {
57 	static uint16_t primes[] = {
58 		3,
59 		5,
60 		7,
61 		11,
62 		13,
63 		17,
64 		19,
65 		23,
66 		29,
67 		31,
68 		37,
69 		41,
70 		43,
71 		47,
72 		53,
73 		59,
74 		61,
75 		67,
76 		71,
77 		73,
78 		79,
79 		83,
80 		89,
81 		97,
82 #if 0
83 		101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157,
84 		163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
85 		229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
86 		293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367,
87 		373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439,
88 		443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509,
89 		521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599,
90 		601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
91 		673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
92 		757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
93 		839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919,
94 		929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009,
95 #endif /* if 0 */
96 	};
97 	int divisions, tries;
98 	unsigned int result;
99 	uint16_t *pp, p;
100 
101 	result = initial;
102 
103 	if (primes[sizeof(primes) / sizeof(primes[0]) - 1] >= result) {
104 		pp = primes;
105 		while (*pp < result) {
106 			++pp;
107 		}
108 		return (*pp);
109 	}
110 
111 	if ((result & 1) == 0) {
112 		++result;
113 	}
114 
115 	divisions = 0;
116 	tries = 1;
117 	pp = primes;
118 	do {
119 		p = *pp++;
120 		++divisions;
121 		if ((result % p) == 0) {
122 			++tries;
123 			result += 2;
124 			pp = primes;
125 		}
126 	} while (pp < &primes[sizeof(primes) / sizeof(primes[0])]);
127 
128 	if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG3)) {
129 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
130 			      DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DEBUG3,
131 			      "%d hash_divisor() divisions in %d tries"
132 			      " to get %d from %d",
133 			      divisions, tries, result, initial);
134 	}
135 
136 	return (result);
137 }
138 
139 /*
140  * Convert a timestamp to a number of seconds in the past.
141  */
142 static int
143 delta_rrl_time(isc_stdtime_t ts, isc_stdtime_t now) {
144 	int delta;
145 
146 	delta = now - ts;
147 	if (delta >= 0) {
148 		return (delta);
149 	}
150 
151 	/*
152 	 * The timestamp is in the future.  That future might result from
153 	 * re-ordered requests, because we use timestamps on requests
154 	 * instead of consulting a clock.  Timestamps in the distant future are
155 	 * assumed to result from clock changes.  When the clock changes to
156 	 * the past, make existing timestamps appear to be in the past.
157 	 */
158 	if (delta < -DNS_RRL_MAX_TIME_TRAVEL) {
159 		return (DNS_RRL_FOREVER);
160 	}
161 	return (0);
162 }
163 
164 static int
165 get_age(const dns_rrl_t *rrl, const dns_rrl_entry_t *e, isc_stdtime_t now) {
166 	if (!e->ts_valid) {
167 		return (DNS_RRL_FOREVER);
168 	}
169 	return (delta_rrl_time(e->ts + rrl->ts_bases[e->ts_gen], now));
170 }
171 
172 static void
173 set_age(dns_rrl_t *rrl, dns_rrl_entry_t *e, isc_stdtime_t now) {
174 	dns_rrl_entry_t *e_old;
175 	unsigned int ts_gen;
176 	int i, ts;
177 
178 	ts_gen = rrl->ts_gen;
179 	ts = now - rrl->ts_bases[ts_gen];
180 	if (ts < 0) {
181 		if (ts < -DNS_RRL_MAX_TIME_TRAVEL) {
182 			ts = DNS_RRL_FOREVER;
183 		} else {
184 			ts = 0;
185 		}
186 	}
187 
188 	/*
189 	 * Make a new timestamp base if the current base is too old.
190 	 * All entries older than DNS_RRL_MAX_WINDOW seconds are ancient,
191 	 * useless history.  Their timestamps can be treated as if they are
192 	 * all the same.
193 	 * We only do arithmetic on more recent timestamps, so bases for
194 	 * older timestamps can be recycled provided the old timestamps are
195 	 * marked as ancient history.
196 	 * This loop is almost always very short because most entries are
197 	 * recycled after one second and any entries that need to be marked
198 	 * are older than (DNS_RRL_TS_BASES)*DNS_RRL_MAX_TS seconds.
199 	 */
200 	if (ts >= DNS_RRL_MAX_TS) {
201 		ts_gen = (ts_gen + 1) % DNS_RRL_TS_BASES;
202 		for (e_old = ISC_LIST_TAIL(rrl->lru), i = 0;
203 		     e_old != NULL && (e_old->ts_gen == ts_gen ||
204 				       !ISC_LINK_LINKED(e_old, hlink));
205 		     e_old = ISC_LIST_PREV(e_old, lru), ++i)
206 		{
207 			e_old->ts_valid = false;
208 		}
209 		if (i != 0) {
210 			isc_log_write(
211 				dns_lctx, DNS_LOGCATEGORY_RRL,
212 				DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DEBUG1,
213 				"rrl new time base scanned %d entries"
214 				" at %d for %d %d %d %d",
215 				i, now, rrl->ts_bases[ts_gen],
216 				rrl->ts_bases[(ts_gen + 1) % DNS_RRL_TS_BASES],
217 				rrl->ts_bases[(ts_gen + 2) % DNS_RRL_TS_BASES],
218 				rrl->ts_bases[(ts_gen + 3) % DNS_RRL_TS_BASES]);
219 		}
220 		rrl->ts_gen = ts_gen;
221 		rrl->ts_bases[ts_gen] = now;
222 		ts = 0;
223 	}
224 
225 	e->ts_gen = ts_gen;
226 	e->ts = ts;
227 	e->ts_valid = true;
228 }
229 
230 static isc_result_t
231 expand_entries(dns_rrl_t *rrl, int newsize) {
232 	unsigned int bsize;
233 	dns_rrl_block_t *b;
234 	dns_rrl_entry_t *e;
235 	double rate;
236 	int i;
237 
238 	if (rrl->num_entries + newsize >= rrl->max_entries &&
239 	    rrl->max_entries != 0)
240 	{
241 		newsize = rrl->max_entries - rrl->num_entries;
242 		if (newsize <= 0) {
243 			return (ISC_R_SUCCESS);
244 		}
245 	}
246 
247 	/*
248 	 * Log expansions so that the user can tune max-table-size
249 	 * and min-table-size.
250 	 */
251 	if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DROP) && rrl->hash != NULL) {
252 		rate = rrl->probes;
253 		if (rrl->searches != 0) {
254 			rate /= rrl->searches;
255 		}
256 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
257 			      DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DROP,
258 			      "increase from %d to %d RRL entries with"
259 			      " %d bins; average search length %.1f",
260 			      rrl->num_entries, rrl->num_entries + newsize,
261 			      rrl->hash->length, rate);
262 	}
263 
264 	bsize = sizeof(dns_rrl_block_t) +
265 		(newsize - 1) * sizeof(dns_rrl_entry_t);
266 	b = isc_mem_get(rrl->mctx, bsize);
267 	memset(b, 0, bsize);
268 	b->size = bsize;
269 
270 	e = b->entries;
271 	for (i = 0; i < newsize; ++i, ++e) {
272 		ISC_LINK_INIT(e, hlink);
273 		ISC_LIST_INITANDAPPEND(rrl->lru, e, lru);
274 	}
275 	rrl->num_entries += newsize;
276 	ISC_LIST_INITANDAPPEND(rrl->blocks, b, link);
277 
278 	return (ISC_R_SUCCESS);
279 }
280 
281 static dns_rrl_bin_t *
282 get_bin(dns_rrl_hash_t *hash, unsigned int hval) {
283 	INSIST(hash != NULL);
284 	return (&hash->bins[hval % hash->length]);
285 }
286 
287 static void
288 free_old_hash(dns_rrl_t *rrl) {
289 	dns_rrl_hash_t *old_hash;
290 	dns_rrl_bin_t *old_bin;
291 	dns_rrl_entry_t *e, *e_next;
292 
293 	old_hash = rrl->old_hash;
294 	for (old_bin = &old_hash->bins[0];
295 	     old_bin < &old_hash->bins[old_hash->length]; ++old_bin)
296 	{
297 		for (e = ISC_LIST_HEAD(*old_bin); e != NULL; e = e_next) {
298 			e_next = ISC_LIST_NEXT(e, hlink);
299 			ISC_LINK_INIT(e, hlink);
300 		}
301 	}
302 
303 	isc_mem_put(rrl->mctx, old_hash,
304 		    sizeof(*old_hash) +
305 			    (old_hash->length - 1) * sizeof(old_hash->bins[0]));
306 	rrl->old_hash = NULL;
307 }
308 
309 static isc_result_t
310 expand_rrl_hash(dns_rrl_t *rrl, isc_stdtime_t now) {
311 	dns_rrl_hash_t *hash;
312 	int old_bins, new_bins, hsize;
313 	double rate;
314 
315 	if (rrl->old_hash != NULL) {
316 		free_old_hash(rrl);
317 	}
318 
319 	/*
320 	 * Most searches fail and so go to the end of the chain.
321 	 * Use a small hash table load factor.
322 	 */
323 	old_bins = (rrl->hash == NULL) ? 0 : rrl->hash->length;
324 	new_bins = old_bins / 8 + old_bins;
325 	if (new_bins < rrl->num_entries) {
326 		new_bins = rrl->num_entries;
327 	}
328 	new_bins = hash_divisor(new_bins);
329 
330 	hsize = sizeof(dns_rrl_hash_t) + (new_bins - 1) * sizeof(hash->bins[0]);
331 	hash = isc_mem_get(rrl->mctx, hsize);
332 	memset(hash, 0, hsize);
333 	hash->length = new_bins;
334 	rrl->hash_gen ^= 1;
335 	hash->gen = rrl->hash_gen;
336 
337 	if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DROP) && old_bins != 0) {
338 		rate = rrl->probes;
339 		if (rrl->searches != 0) {
340 			rate /= rrl->searches;
341 		}
342 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
343 			      DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DROP,
344 			      "increase from %d to %d RRL bins for"
345 			      " %d entries; average search length %.1f",
346 			      old_bins, new_bins, rrl->num_entries, rate);
347 	}
348 
349 	rrl->old_hash = rrl->hash;
350 	if (rrl->old_hash != NULL) {
351 		rrl->old_hash->check_time = now;
352 	}
353 	rrl->hash = hash;
354 
355 	return (ISC_R_SUCCESS);
356 }
357 
358 static void
359 ref_entry(dns_rrl_t *rrl, dns_rrl_entry_t *e, int probes, isc_stdtime_t now) {
360 	/*
361 	 * Make the entry most recently used.
362 	 */
363 	if (ISC_LIST_HEAD(rrl->lru) != e) {
364 		if (e == rrl->last_logged) {
365 			rrl->last_logged = ISC_LIST_PREV(e, lru);
366 		}
367 		ISC_LIST_UNLINK(rrl->lru, e, lru);
368 		ISC_LIST_PREPEND(rrl->lru, e, lru);
369 	}
370 
371 	/*
372 	 * Expand the hash table if it is time and necessary.
373 	 * This will leave the newly referenced entry in a chain in the
374 	 * old hash table.  It will migrate to the new hash table the next
375 	 * time it is used or be cut loose when the old hash table is destroyed.
376 	 */
377 	rrl->probes += probes;
378 	++rrl->searches;
379 	if (rrl->searches > 100 &&
380 	    delta_rrl_time(rrl->hash->check_time, now) > 1)
381 	{
382 		if (rrl->probes / rrl->searches > 2) {
383 			expand_rrl_hash(rrl, now);
384 		}
385 		rrl->hash->check_time = now;
386 		rrl->probes = 0;
387 		rrl->searches = 0;
388 	}
389 }
390 
391 static bool
392 key_cmp(const dns_rrl_key_t *a, const dns_rrl_key_t *b) {
393 	if (memcmp(a, b, sizeof(dns_rrl_key_t)) == 0) {
394 		return (true);
395 	}
396 	return (false);
397 }
398 
399 static uint32_t
400 hash_key(const dns_rrl_key_t *key) {
401 	uint32_t hval;
402 	int i;
403 
404 	hval = key->w[0];
405 	for (i = sizeof(key->w) / sizeof(key->w[0]) - 1; i >= 0; --i) {
406 		hval = key->w[i] + (hval << 1);
407 	}
408 	return (hval);
409 }
410 
411 /*
412  * Construct the hash table key.
413  * Use a hash of the DNS query name to save space in the database.
414  * Collisions result in legitimate rate limiting responses for one
415  * query name also limiting responses for other names to the
416  * same client.  This is rare and benign enough given the large
417  * space costs compared to keeping the entire name in the database
418  * entry or the time costs of dynamic allocation.
419  */
420 static void
421 make_key(const dns_rrl_t *rrl, dns_rrl_key_t *key,
422 	 const isc_sockaddr_t *client_addr, dns_zone_t *zone,
423 	 dns_rdatatype_t qtype, const dns_name_t *qname,
424 	 dns_rdataclass_t qclass, dns_rrl_rtype_t rtype) {
425 	int i;
426 
427 	memset(key, 0, sizeof(*key));
428 
429 	key->s.rtype = rtype;
430 	if (rtype == DNS_RRL_RTYPE_QUERY) {
431 		key->s.qtype = qtype;
432 		key->s.qclass = qclass & 0xff;
433 	} else if (rtype == DNS_RRL_RTYPE_REFERRAL ||
434 		   rtype == DNS_RRL_RTYPE_NODATA)
435 	{
436 		/*
437 		 * Because there is no qtype in the empty answer sections of
438 		 * referral and NODATA responses, count them as the same.
439 		 */
440 		key->s.qclass = qclass & 0xff;
441 	}
442 
443 	if (qname != NULL && qname->labels != 0) {
444 		dns_name_t *origin = NULL;
445 
446 		if ((qname->attributes & DNS_NAMEATTR_WILDCARD) != 0 &&
447 		    zone != NULL && (origin = dns_zone_getorigin(zone)) != NULL)
448 		{
449 			dns_fixedname_t fixed;
450 			dns_name_t *wild;
451 			isc_result_t result;
452 
453 			/*
454 			 * Put all wildcard names in one bucket using the zone's
455 			 * origin name concatenated to the "*" name.
456 			 */
457 			wild = dns_fixedname_initname(&fixed);
458 			result = dns_name_concatenate(dns_wildcardname, origin,
459 						      wild, NULL);
460 			if (result != ISC_R_SUCCESS) {
461 				/*
462 				 * Fallback to use the zone's origin name
463 				 * instead of the concatenated name.
464 				 */
465 				wild = origin;
466 			}
467 			key->s.qname_hash = dns_name_fullhash(wild, false);
468 		} else {
469 			key->s.qname_hash = dns_name_fullhash(qname, false);
470 		}
471 	}
472 
473 	switch (client_addr->type.sa.sa_family) {
474 	case AF_INET:
475 		key->s.ip[0] = (client_addr->type.sin.sin_addr.s_addr &
476 				rrl->ipv4_mask);
477 		break;
478 	case AF_INET6:
479 		key->s.ipv6 = true;
480 		memmove(key->s.ip, &client_addr->type.sin6.sin6_addr,
481 			sizeof(key->s.ip));
482 		for (i = 0; i < DNS_RRL_MAX_PREFIX / 32; ++i) {
483 			key->s.ip[i] &= rrl->ipv6_mask[i];
484 		}
485 		break;
486 	}
487 }
488 
489 static dns_rrl_rate_t *
490 get_rate(dns_rrl_t *rrl, dns_rrl_rtype_t rtype) {
491 	switch (rtype) {
492 	case DNS_RRL_RTYPE_QUERY:
493 		return (&rrl->responses_per_second);
494 	case DNS_RRL_RTYPE_REFERRAL:
495 		return (&rrl->referrals_per_second);
496 	case DNS_RRL_RTYPE_NODATA:
497 		return (&rrl->nodata_per_second);
498 	case DNS_RRL_RTYPE_NXDOMAIN:
499 		return (&rrl->nxdomains_per_second);
500 	case DNS_RRL_RTYPE_ERROR:
501 		return (&rrl->errors_per_second);
502 	case DNS_RRL_RTYPE_ALL:
503 		return (&rrl->all_per_second);
504 	default:
505 		UNREACHABLE();
506 	}
507 }
508 
509 static int
510 response_balance(dns_rrl_t *rrl, const dns_rrl_entry_t *e, int age) {
511 	dns_rrl_rate_t *ratep;
512 	int balance, rate;
513 
514 	if (e->key.s.rtype == DNS_RRL_RTYPE_TCP) {
515 		rate = 1;
516 	} else {
517 		ratep = get_rate(rrl, e->key.s.rtype);
518 		rate = ratep->scaled;
519 	}
520 
521 	balance = e->responses + age * rate;
522 	if (balance > rate) {
523 		balance = rate;
524 	}
525 	return (balance);
526 }
527 
528 /*
529  * Search for an entry for a response and optionally create it.
530  */
531 static dns_rrl_entry_t *
532 get_entry(dns_rrl_t *rrl, const isc_sockaddr_t *client_addr, dns_zone_t *zone,
533 	  dns_rdataclass_t qclass, dns_rdatatype_t qtype,
534 	  const dns_name_t *qname, dns_rrl_rtype_t rtype, isc_stdtime_t now,
535 	  bool create, char *log_buf, unsigned int log_buf_len) {
536 	dns_rrl_key_t key;
537 	uint32_t hval;
538 	dns_rrl_entry_t *e;
539 	dns_rrl_hash_t *hash;
540 	dns_rrl_bin_t *new_bin, *old_bin;
541 	int probes, age;
542 
543 	make_key(rrl, &key, client_addr, zone, qtype, qname, qclass, rtype);
544 	hval = hash_key(&key);
545 
546 	/*
547 	 * Look for the entry in the current hash table.
548 	 */
549 	new_bin = get_bin(rrl->hash, hval);
550 	probes = 1;
551 	e = ISC_LIST_HEAD(*new_bin);
552 	while (e != NULL) {
553 		if (key_cmp(&e->key, &key)) {
554 			ref_entry(rrl, e, probes, now);
555 			return (e);
556 		}
557 		++probes;
558 		e = ISC_LIST_NEXT(e, hlink);
559 	}
560 
561 	/*
562 	 * Look in the old hash table.
563 	 */
564 	if (rrl->old_hash != NULL) {
565 		old_bin = get_bin(rrl->old_hash, hval);
566 		e = ISC_LIST_HEAD(*old_bin);
567 		while (e != NULL) {
568 			if (key_cmp(&e->key, &key)) {
569 				ISC_LIST_UNLINK(*old_bin, e, hlink);
570 				ISC_LIST_PREPEND(*new_bin, e, hlink);
571 				e->hash_gen = rrl->hash_gen;
572 				ref_entry(rrl, e, probes, now);
573 				return (e);
574 			}
575 			e = ISC_LIST_NEXT(e, hlink);
576 		}
577 
578 		/*
579 		 * Discard previous hash table when all of its entries are old.
580 		 */
581 		age = delta_rrl_time(rrl->old_hash->check_time, now);
582 		if (age > rrl->window) {
583 			free_old_hash(rrl);
584 		}
585 	}
586 
587 	if (!create) {
588 		return (NULL);
589 	}
590 
591 	/*
592 	 * The entry does not exist, so create it by finding a free entry.
593 	 * Keep currently penalized and logged entries.
594 	 * Try to make more entries if none are idle.
595 	 * Steal the oldest entry if we cannot create more.
596 	 */
597 	for (e = ISC_LIST_TAIL(rrl->lru); e != NULL; e = ISC_LIST_PREV(e, lru))
598 	{
599 		if (!ISC_LINK_LINKED(e, hlink)) {
600 			break;
601 		}
602 		age = get_age(rrl, e, now);
603 		if (age <= 1) {
604 			e = NULL;
605 			break;
606 		}
607 		if (!e->logged && response_balance(rrl, e, age) > 0) {
608 			break;
609 		}
610 	}
611 	if (e == NULL) {
612 		expand_entries(rrl, ISC_MIN((rrl->num_entries + 1) / 2, 1000));
613 		e = ISC_LIST_TAIL(rrl->lru);
614 	}
615 	if (e->logged) {
616 		log_end(rrl, e, true, log_buf, log_buf_len);
617 	}
618 	if (ISC_LINK_LINKED(e, hlink)) {
619 		if (e->hash_gen == rrl->hash_gen) {
620 			hash = rrl->hash;
621 		} else {
622 			hash = rrl->old_hash;
623 		}
624 		old_bin = get_bin(hash, hash_key(&e->key));
625 		ISC_LIST_UNLINK(*old_bin, e, hlink);
626 	}
627 	ISC_LIST_PREPEND(*new_bin, e, hlink);
628 	e->hash_gen = rrl->hash_gen;
629 	e->key = key;
630 	e->ts_valid = false;
631 	ref_entry(rrl, e, probes, now);
632 	return (e);
633 }
634 
635 static void
636 debit_log(const dns_rrl_entry_t *e, int age, const char *action) {
637 	char buf[sizeof("age=2147483647")];
638 	const char *age_str;
639 
640 	if (age == DNS_RRL_FOREVER) {
641 		age_str = "";
642 	} else {
643 		snprintf(buf, sizeof(buf), "age=%d", age);
644 		age_str = buf;
645 	}
646 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL, DNS_LOGMODULE_REQUEST,
647 		      DNS_RRL_LOG_DEBUG3, "rrl %08x %6s  responses=%-3d %s",
648 		      hash_key(&e->key), age_str, e->responses, action);
649 }
650 
651 static dns_rrl_result_t
652 debit_rrl_entry(dns_rrl_t *rrl, dns_rrl_entry_t *e, double qps, double scale,
653 		const isc_sockaddr_t *client_addr, isc_stdtime_t now,
654 		char *log_buf, unsigned int log_buf_len) {
655 	int rate, new_rate, slip, new_slip, age, log_secs, min;
656 	dns_rrl_rate_t *ratep;
657 	dns_rrl_entry_t const *credit_e;
658 
659 	/*
660 	 * Pick the rate counter.
661 	 * Optionally adjust the rate by the estimated query/second rate.
662 	 */
663 	ratep = get_rate(rrl, e->key.s.rtype);
664 	rate = ratep->r;
665 	if (rate == 0) {
666 		return (DNS_RRL_RESULT_OK);
667 	}
668 
669 	if (scale < 1.0) {
670 		/*
671 		 * The limit for clients that have used TCP is not scaled.
672 		 */
673 		credit_e = get_entry(
674 			rrl, client_addr, NULL, 0, dns_rdatatype_none, NULL,
675 			DNS_RRL_RTYPE_TCP, now, false, log_buf, log_buf_len);
676 		if (credit_e != NULL) {
677 			age = get_age(rrl, e, now);
678 			if (age < rrl->window) {
679 				scale = 1.0;
680 			}
681 		}
682 	}
683 	if (scale < 1.0) {
684 		new_rate = (int)(rate * scale);
685 		if (new_rate < 1) {
686 			new_rate = 1;
687 		}
688 		if (ratep->scaled != new_rate) {
689 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
690 				      DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DEBUG1,
691 				      "%d qps scaled %s by %.2f"
692 				      " from %d to %d",
693 				      (int)qps, ratep->str, scale, rate,
694 				      new_rate);
695 			rate = new_rate;
696 			ratep->scaled = rate;
697 		}
698 	}
699 
700 	min = -rrl->window * rate;
701 
702 	/*
703 	 * Treat time jumps into the recent past as no time.
704 	 * Treat entries older than the window as if they were just created
705 	 * Credit other entries.
706 	 */
707 	age = get_age(rrl, e, now);
708 	if (age > 0) {
709 		/*
710 		 * Credit tokens earned during elapsed time.
711 		 */
712 		if (age > rrl->window) {
713 			e->responses = rate;
714 			e->slip_cnt = 0;
715 		} else {
716 			e->responses += rate * age;
717 			if (e->responses > rate) {
718 				e->responses = rate;
719 				e->slip_cnt = 0;
720 			}
721 		}
722 		/*
723 		 * Find the seconds since last log message without overflowing
724 		 * small counter.  This counter is reset when an entry is
725 		 * created.  It is not necessarily reset when some requests
726 		 * are answered provided other requests continue to be dropped
727 		 * or slipped.  This can happen when the request rate is just
728 		 * at the limit.
729 		 */
730 		if (e->logged) {
731 			log_secs = e->log_secs;
732 			log_secs += age;
733 			if (log_secs > DNS_RRL_MAX_LOG_SECS || log_secs < 0) {
734 				log_secs = DNS_RRL_MAX_LOG_SECS;
735 			}
736 			e->log_secs = log_secs;
737 		}
738 	}
739 	set_age(rrl, e, now);
740 
741 	/*
742 	 * Debit the entry for this response.
743 	 */
744 	if (--e->responses >= 0) {
745 		if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG3)) {
746 			debit_log(e, age, "");
747 		}
748 		return (DNS_RRL_RESULT_OK);
749 	}
750 
751 	if (e->responses < min) {
752 		e->responses = min;
753 	}
754 
755 	/*
756 	 * Drop this response unless it should slip or leak.
757 	 */
758 	slip = rrl->slip.r;
759 	if (slip > 2 && scale < 1.0) {
760 		new_slip = (int)(slip * scale);
761 		if (new_slip < 2) {
762 			new_slip = 2;
763 		}
764 		if (rrl->slip.scaled != new_slip) {
765 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
766 				      DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DEBUG1,
767 				      "%d qps scaled slip"
768 				      " by %.2f from %d to %d",
769 				      (int)qps, scale, slip, new_slip);
770 			slip = new_slip;
771 			rrl->slip.scaled = slip;
772 		}
773 	}
774 	if (slip != 0 && e->key.s.rtype != DNS_RRL_RTYPE_ALL) {
775 		if (e->slip_cnt++ == 0) {
776 			if ((int)e->slip_cnt >= slip) {
777 				e->slip_cnt = 0;
778 			}
779 			if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG3)) {
780 				debit_log(e, age, "slip");
781 			}
782 			return (DNS_RRL_RESULT_SLIP);
783 		} else if ((int)e->slip_cnt >= slip) {
784 			e->slip_cnt = 0;
785 		}
786 	}
787 
788 	if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG3)) {
789 		debit_log(e, age, "drop");
790 	}
791 	return (DNS_RRL_RESULT_DROP);
792 }
793 
794 static dns_rrl_qname_buf_t *
795 get_qname(dns_rrl_t *rrl, const dns_rrl_entry_t *e) {
796 	dns_rrl_qname_buf_t *qbuf;
797 
798 	qbuf = rrl->qnames[e->log_qname];
799 	if (qbuf == NULL || qbuf->e != e) {
800 		return (NULL);
801 	}
802 	return (qbuf);
803 }
804 
805 static void
806 free_qname(dns_rrl_t *rrl, dns_rrl_entry_t *e) {
807 	dns_rrl_qname_buf_t *qbuf;
808 
809 	qbuf = get_qname(rrl, e);
810 	if (qbuf != NULL) {
811 		qbuf->e = NULL;
812 		ISC_LIST_APPEND(rrl->qname_free, qbuf, link);
813 	}
814 }
815 
816 static void
817 add_log_str(isc_buffer_t *lb, const char *str, unsigned int str_len) {
818 	isc_region_t region;
819 
820 	isc_buffer_availableregion(lb, &region);
821 	if (str_len >= region.length) {
822 		if (region.length == 0U) {
823 			return;
824 		}
825 		str_len = region.length;
826 	}
827 	memmove(region.base, str, str_len);
828 	isc_buffer_add(lb, str_len);
829 }
830 
831 #define ADD_LOG_CSTR(eb, s) add_log_str(eb, s, sizeof(s) - 1)
832 
833 /*
834  * Build strings for the logs
835  */
836 static void
837 make_log_buf(dns_rrl_t *rrl, dns_rrl_entry_t *e, const char *str1,
838 	     const char *str2, bool plural, const dns_name_t *qname,
839 	     bool save_qname, dns_rrl_result_t rrl_result,
840 	     isc_result_t resp_result, char *log_buf,
841 	     unsigned int log_buf_len) {
842 	isc_buffer_t lb;
843 	dns_rrl_qname_buf_t *qbuf;
844 	isc_netaddr_t cidr;
845 	char strbuf[ISC_MAX(sizeof("/123"), sizeof("  (12345678)"))];
846 	const char *rstr;
847 	isc_result_t msg_result;
848 
849 	if (log_buf_len <= 1) {
850 		if (log_buf_len == 1) {
851 			log_buf[0] = '\0';
852 		}
853 		return;
854 	}
855 	isc_buffer_init(&lb, log_buf, log_buf_len - 1);
856 
857 	if (str1 != NULL) {
858 		add_log_str(&lb, str1, strlen(str1));
859 	}
860 	if (str2 != NULL) {
861 		add_log_str(&lb, str2, strlen(str2));
862 	}
863 
864 	switch (rrl_result) {
865 	case DNS_RRL_RESULT_OK:
866 		break;
867 	case DNS_RRL_RESULT_DROP:
868 		ADD_LOG_CSTR(&lb, "drop ");
869 		break;
870 	case DNS_RRL_RESULT_SLIP:
871 		ADD_LOG_CSTR(&lb, "slip ");
872 		break;
873 	default:
874 		UNREACHABLE();
875 	}
876 
877 	switch (e->key.s.rtype) {
878 	case DNS_RRL_RTYPE_QUERY:
879 		break;
880 	case DNS_RRL_RTYPE_REFERRAL:
881 		ADD_LOG_CSTR(&lb, "referral ");
882 		break;
883 	case DNS_RRL_RTYPE_NODATA:
884 		ADD_LOG_CSTR(&lb, "NODATA ");
885 		break;
886 	case DNS_RRL_RTYPE_NXDOMAIN:
887 		ADD_LOG_CSTR(&lb, "NXDOMAIN ");
888 		break;
889 	case DNS_RRL_RTYPE_ERROR:
890 		if (resp_result == ISC_R_SUCCESS) {
891 			ADD_LOG_CSTR(&lb, "error ");
892 		} else {
893 			rstr = isc_result_totext(resp_result);
894 			add_log_str(&lb, rstr, strlen(rstr));
895 			ADD_LOG_CSTR(&lb, " error ");
896 		}
897 		break;
898 	case DNS_RRL_RTYPE_ALL:
899 		ADD_LOG_CSTR(&lb, "all ");
900 		break;
901 	default:
902 		UNREACHABLE();
903 	}
904 
905 	if (plural) {
906 		ADD_LOG_CSTR(&lb, "responses to ");
907 	} else {
908 		ADD_LOG_CSTR(&lb, "response to ");
909 	}
910 
911 	memset(&cidr, 0, sizeof(cidr));
912 	if (e->key.s.ipv6) {
913 		snprintf(strbuf, sizeof(strbuf), "/%d", rrl->ipv6_prefixlen);
914 		cidr.family = AF_INET6;
915 		memset(&cidr.type.in6, 0, sizeof(cidr.type.in6));
916 		memmove(&cidr.type.in6, e->key.s.ip, sizeof(e->key.s.ip));
917 	} else {
918 		snprintf(strbuf, sizeof(strbuf), "/%d", rrl->ipv4_prefixlen);
919 		cidr.family = AF_INET;
920 		cidr.type.in.s_addr = e->key.s.ip[0];
921 	}
922 	msg_result = isc_netaddr_totext(&cidr, &lb);
923 	if (msg_result != ISC_R_SUCCESS) {
924 		ADD_LOG_CSTR(&lb, "?");
925 	}
926 	add_log_str(&lb, strbuf, strlen(strbuf));
927 
928 	if (e->key.s.rtype == DNS_RRL_RTYPE_QUERY ||
929 	    e->key.s.rtype == DNS_RRL_RTYPE_REFERRAL ||
930 	    e->key.s.rtype == DNS_RRL_RTYPE_NODATA ||
931 	    e->key.s.rtype == DNS_RRL_RTYPE_NXDOMAIN)
932 	{
933 		qbuf = get_qname(rrl, e);
934 		if (save_qname && qbuf == NULL && qname != NULL &&
935 		    dns_name_isabsolute(qname))
936 		{
937 			/*
938 			 * Capture the qname for the "stop limiting" message.
939 			 */
940 			qbuf = ISC_LIST_TAIL(rrl->qname_free);
941 			if (qbuf != NULL) {
942 				ISC_LIST_UNLINK(rrl->qname_free, qbuf, link);
943 			} else if (rrl->num_qnames < DNS_RRL_QNAMES) {
944 				qbuf = isc_mem_get(rrl->mctx, sizeof(*qbuf));
945 				{
946 					memset(qbuf, 0, sizeof(*qbuf));
947 					ISC_LINK_INIT(qbuf, link);
948 					qbuf->index = rrl->num_qnames;
949 					rrl->qnames[rrl->num_qnames++] = qbuf;
950 				}
951 			}
952 			if (qbuf != NULL) {
953 				e->log_qname = qbuf->index;
954 				qbuf->e = e;
955 				dns_fixedname_init(&qbuf->qname);
956 				dns_name_copy(qname,
957 					      dns_fixedname_name(&qbuf->qname));
958 			}
959 		}
960 		if (qbuf != NULL) {
961 			qname = dns_fixedname_name(&qbuf->qname);
962 		}
963 		if (qname != NULL) {
964 			ADD_LOG_CSTR(&lb, " for ");
965 			(void)dns_name_totext(qname, true, &lb);
966 		} else {
967 			ADD_LOG_CSTR(&lb, " for (?)");
968 		}
969 		if (e->key.s.rtype != DNS_RRL_RTYPE_NXDOMAIN) {
970 			ADD_LOG_CSTR(&lb, " ");
971 			(void)dns_rdataclass_totext(e->key.s.qclass, &lb);
972 			if (e->key.s.rtype == DNS_RRL_RTYPE_QUERY) {
973 				ADD_LOG_CSTR(&lb, " ");
974 				(void)dns_rdatatype_totext(e->key.s.qtype, &lb);
975 			}
976 		}
977 		snprintf(strbuf, sizeof(strbuf), "  (%08" PRIx32 ")",
978 			 e->key.s.qname_hash);
979 		add_log_str(&lb, strbuf, strlen(strbuf));
980 	}
981 
982 	/*
983 	 * We saved room for '\0'.
984 	 */
985 	log_buf[isc_buffer_usedlength(&lb)] = '\0';
986 }
987 
988 static void
989 log_end(dns_rrl_t *rrl, dns_rrl_entry_t *e, bool early, char *log_buf,
990 	unsigned int log_buf_len) {
991 	if (e->logged) {
992 		make_log_buf(rrl, e, early ? "*" : NULL,
993 			     rrl->log_only ? "would stop limiting "
994 					   : "stop limiting ",
995 			     true, NULL, false, DNS_RRL_RESULT_OK,
996 			     ISC_R_SUCCESS, log_buf, log_buf_len);
997 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
998 			      DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DROP, "%s",
999 			      log_buf);
1000 		free_qname(rrl, e);
1001 		e->logged = false;
1002 		--rrl->num_logged;
1003 	}
1004 }
1005 
1006 /*
1007  * Log messages for streams that have stopped being rate limited.
1008  */
1009 static void
1010 log_stops(dns_rrl_t *rrl, isc_stdtime_t now, int limit, char *log_buf,
1011 	  unsigned int log_buf_len) {
1012 	dns_rrl_entry_t *e;
1013 	int age;
1014 
1015 	for (e = rrl->last_logged; e != NULL; e = ISC_LIST_PREV(e, lru)) {
1016 		if (!e->logged) {
1017 			continue;
1018 		}
1019 		if (now != 0) {
1020 			age = get_age(rrl, e, now);
1021 			if (age < DNS_RRL_STOP_LOG_SECS ||
1022 			    response_balance(rrl, e, age) < 0)
1023 			{
1024 				break;
1025 			}
1026 		}
1027 
1028 		log_end(rrl, e, now == 0, log_buf, log_buf_len);
1029 		if (rrl->num_logged <= 0) {
1030 			break;
1031 		}
1032 
1033 		/*
1034 		 * Too many messages could stall real work.
1035 		 */
1036 		if (--limit < 0) {
1037 			rrl->last_logged = ISC_LIST_PREV(e, lru);
1038 			return;
1039 		}
1040 	}
1041 	if (e == NULL) {
1042 		INSIST(rrl->num_logged == 0);
1043 		rrl->log_stops_time = now;
1044 	}
1045 	rrl->last_logged = e;
1046 }
1047 
1048 /*
1049  * Main rate limit interface.
1050  */
1051 dns_rrl_result_t
1052 dns_rrl(dns_view_t *view, dns_zone_t *zone, const isc_sockaddr_t *client_addr,
1053 	bool is_tcp, dns_rdataclass_t qclass, dns_rdatatype_t qtype,
1054 	const dns_name_t *qname, isc_result_t resp_result, isc_stdtime_t now,
1055 	bool wouldlog, char *log_buf, unsigned int log_buf_len) {
1056 	dns_rrl_t *rrl;
1057 	dns_rrl_rtype_t rtype;
1058 	dns_rrl_entry_t *e;
1059 	isc_netaddr_t netclient;
1060 	int secs;
1061 	double qps, scale;
1062 	int exempt_match;
1063 	isc_result_t result;
1064 	dns_rrl_result_t rrl_result;
1065 
1066 	INSIST(log_buf != NULL && log_buf_len > 0);
1067 
1068 	rrl = view->rrl;
1069 	if (rrl->exempt != NULL) {
1070 		isc_netaddr_fromsockaddr(&netclient, client_addr);
1071 		result = dns_acl_match(&netclient, NULL, rrl->exempt,
1072 				       view->aclenv, &exempt_match, NULL);
1073 		if (result == ISC_R_SUCCESS && exempt_match > 0) {
1074 			return (DNS_RRL_RESULT_OK);
1075 		}
1076 	}
1077 
1078 	LOCK(&rrl->lock);
1079 
1080 	/*
1081 	 * Estimate total query per second rate when scaling by qps.
1082 	 */
1083 	if (rrl->qps_scale == 0) {
1084 		qps = 0.0;
1085 		scale = 1.0;
1086 	} else {
1087 		++rrl->qps_responses;
1088 		secs = delta_rrl_time(rrl->qps_time, now);
1089 		if (secs <= 0) {
1090 			qps = rrl->qps;
1091 		} else {
1092 			qps = (1.0 * rrl->qps_responses) / secs;
1093 			if (secs >= rrl->window) {
1094 				if (isc_log_wouldlog(dns_lctx,
1095 						     DNS_RRL_LOG_DEBUG3))
1096 				{
1097 					isc_log_write(dns_lctx,
1098 						      DNS_LOGCATEGORY_RRL,
1099 						      DNS_LOGMODULE_REQUEST,
1100 						      DNS_RRL_LOG_DEBUG3,
1101 						      "%d responses/%d seconds"
1102 						      " = %d qps",
1103 						      rrl->qps_responses, secs,
1104 						      (int)qps);
1105 				}
1106 				rrl->qps = qps;
1107 				rrl->qps_responses = 0;
1108 				rrl->qps_time = now;
1109 			} else if (qps < rrl->qps) {
1110 				qps = rrl->qps;
1111 			}
1112 		}
1113 		scale = rrl->qps_scale / qps;
1114 	}
1115 
1116 	/*
1117 	 * Do maintenance once per second.
1118 	 */
1119 	if (rrl->num_logged > 0 && rrl->log_stops_time != now) {
1120 		log_stops(rrl, now, 8, log_buf, log_buf_len);
1121 	}
1122 
1123 	/*
1124 	 * Notice TCP responses when scaling limits by qps.
1125 	 * Do not try to rate limit TCP responses.
1126 	 */
1127 	if (is_tcp) {
1128 		if (scale < 1.0) {
1129 			e = get_entry(rrl, client_addr, NULL, 0,
1130 				      dns_rdatatype_none, NULL,
1131 				      DNS_RRL_RTYPE_TCP, now, true, log_buf,
1132 				      log_buf_len);
1133 			if (e != NULL) {
1134 				e->responses = -(rrl->window + 1);
1135 				set_age(rrl, e, now);
1136 			}
1137 		}
1138 		UNLOCK(&rrl->lock);
1139 		return (DNS_RRL_RESULT_OK);
1140 	}
1141 
1142 	/*
1143 	 * Find the right kind of entry, creating it if necessary.
1144 	 * If that is impossible, then nothing more can be done
1145 	 */
1146 	switch (resp_result) {
1147 	case ISC_R_SUCCESS:
1148 		rtype = DNS_RRL_RTYPE_QUERY;
1149 		break;
1150 	case DNS_R_DELEGATION:
1151 		rtype = DNS_RRL_RTYPE_REFERRAL;
1152 		break;
1153 	case DNS_R_NXRRSET:
1154 		rtype = DNS_RRL_RTYPE_NODATA;
1155 		break;
1156 	case DNS_R_NXDOMAIN:
1157 		rtype = DNS_RRL_RTYPE_NXDOMAIN;
1158 		break;
1159 	default:
1160 		rtype = DNS_RRL_RTYPE_ERROR;
1161 		break;
1162 	}
1163 	e = get_entry(rrl, client_addr, zone, qclass, qtype, qname, rtype, now,
1164 		      true, log_buf, log_buf_len);
1165 	if (e == NULL) {
1166 		UNLOCK(&rrl->lock);
1167 		return (DNS_RRL_RESULT_OK);
1168 	}
1169 
1170 	if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG1)) {
1171 		/*
1172 		 * Do not worry about speed or releasing the lock.
1173 		 * This message appears before messages from debit_rrl_entry().
1174 		 */
1175 		make_log_buf(rrl, e, "consider limiting ", NULL, false, qname,
1176 			     false, DNS_RRL_RESULT_OK, resp_result, log_buf,
1177 			     log_buf_len);
1178 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
1179 			      DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DEBUG1, "%s",
1180 			      log_buf);
1181 	}
1182 
1183 	rrl_result = debit_rrl_entry(rrl, e, qps, scale, client_addr, now,
1184 				     log_buf, log_buf_len);
1185 
1186 	if (rrl->all_per_second.r != 0) {
1187 		/*
1188 		 * We must debit the all-per-second token bucket if we have
1189 		 * an all-per-second limit for the IP address.
1190 		 * The all-per-second limit determines the log message
1191 		 * when both limits are hit.
1192 		 * The response limiting must continue if the
1193 		 * all-per-second limiting lapses.
1194 		 */
1195 		dns_rrl_entry_t *e_all;
1196 		dns_rrl_result_t rrl_all_result;
1197 
1198 		e_all = get_entry(rrl, client_addr, zone, 0, dns_rdatatype_none,
1199 				  NULL, DNS_RRL_RTYPE_ALL, now, true, log_buf,
1200 				  log_buf_len);
1201 		if (e_all == NULL) {
1202 			UNLOCK(&rrl->lock);
1203 			return (DNS_RRL_RESULT_OK);
1204 		}
1205 		rrl_all_result = debit_rrl_entry(rrl, e_all, qps, scale,
1206 						 client_addr, now, log_buf,
1207 						 log_buf_len);
1208 		if (rrl_all_result != DNS_RRL_RESULT_OK) {
1209 			e = e_all;
1210 			rrl_result = rrl_all_result;
1211 			if (isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DEBUG1)) {
1212 				make_log_buf(rrl, e,
1213 					     "prefer all-per-second limiting ",
1214 					     NULL, true, qname, false,
1215 					     DNS_RRL_RESULT_OK, resp_result,
1216 					     log_buf, log_buf_len);
1217 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
1218 					      DNS_LOGMODULE_REQUEST,
1219 					      DNS_RRL_LOG_DEBUG1, "%s",
1220 					      log_buf);
1221 			}
1222 		}
1223 	}
1224 
1225 	if (rrl_result == DNS_RRL_RESULT_OK) {
1226 		UNLOCK(&rrl->lock);
1227 		return (DNS_RRL_RESULT_OK);
1228 	}
1229 
1230 	/*
1231 	 * Log occasionally in the rate-limit category.
1232 	 */
1233 	if ((!e->logged || e->log_secs >= DNS_RRL_MAX_LOG_SECS) &&
1234 	    isc_log_wouldlog(dns_lctx, DNS_RRL_LOG_DROP))
1235 	{
1236 		make_log_buf(rrl, e, rrl->log_only ? "would " : NULL,
1237 			     e->logged ? "continue limiting " : "limit ", true,
1238 			     qname, true, DNS_RRL_RESULT_OK, resp_result,
1239 			     log_buf, log_buf_len);
1240 		if (!e->logged) {
1241 			e->logged = true;
1242 			if (++rrl->num_logged <= 1) {
1243 				rrl->last_logged = e;
1244 			}
1245 		}
1246 		e->log_secs = 0;
1247 
1248 		/*
1249 		 * Avoid holding the lock.
1250 		 */
1251 		if (!wouldlog) {
1252 			UNLOCK(&rrl->lock);
1253 			e = NULL;
1254 		}
1255 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RRL,
1256 			      DNS_LOGMODULE_REQUEST, DNS_RRL_LOG_DROP, "%s",
1257 			      log_buf);
1258 	}
1259 
1260 	/*
1261 	 * Make a log message for the caller.
1262 	 */
1263 	if (wouldlog) {
1264 		make_log_buf(rrl, e,
1265 			     rrl->log_only ? "would rate limit "
1266 					   : "rate limit ",
1267 			     NULL, false, qname, false, rrl_result, resp_result,
1268 			     log_buf, log_buf_len);
1269 	}
1270 
1271 	if (e != NULL) {
1272 		/*
1273 		 * Do not save the qname unless we might need it for
1274 		 * the ending log message.
1275 		 */
1276 		if (!e->logged) {
1277 			free_qname(rrl, e);
1278 		}
1279 		UNLOCK(&rrl->lock);
1280 	}
1281 
1282 	return (rrl_result);
1283 }
1284 
1285 void
1286 dns_rrl_view_destroy(dns_view_t *view) {
1287 	dns_rrl_t *rrl;
1288 	dns_rrl_block_t *b;
1289 	dns_rrl_hash_t *h;
1290 	char log_buf[DNS_RRL_LOG_BUF_LEN];
1291 	int i;
1292 
1293 	rrl = view->rrl;
1294 	if (rrl == NULL) {
1295 		return;
1296 	}
1297 	view->rrl = NULL;
1298 
1299 	/*
1300 	 * Assume the caller takes care of locking the view and anything else.
1301 	 */
1302 
1303 	if (rrl->num_logged > 0) {
1304 		log_stops(rrl, 0, INT32_MAX, log_buf, sizeof(log_buf));
1305 	}
1306 
1307 	for (i = 0; i < DNS_RRL_QNAMES; ++i) {
1308 		if (rrl->qnames[i] == NULL) {
1309 			break;
1310 		}
1311 		isc_mem_put(rrl->mctx, rrl->qnames[i], sizeof(*rrl->qnames[i]));
1312 	}
1313 
1314 	if (rrl->exempt != NULL) {
1315 		dns_acl_detach(&rrl->exempt);
1316 	}
1317 
1318 	isc_mutex_destroy(&rrl->lock);
1319 
1320 	while (!ISC_LIST_EMPTY(rrl->blocks)) {
1321 		b = ISC_LIST_HEAD(rrl->blocks);
1322 		ISC_LIST_UNLINK(rrl->blocks, b, link);
1323 		isc_mem_put(rrl->mctx, b, b->size);
1324 	}
1325 
1326 	h = rrl->hash;
1327 	if (h != NULL) {
1328 		isc_mem_put(rrl->mctx, h,
1329 			    sizeof(*h) + (h->length - 1) * sizeof(h->bins[0]));
1330 	}
1331 
1332 	h = rrl->old_hash;
1333 	if (h != NULL) {
1334 		isc_mem_put(rrl->mctx, h,
1335 			    sizeof(*h) + (h->length - 1) * sizeof(h->bins[0]));
1336 	}
1337 
1338 	isc_mem_putanddetach(&rrl->mctx, rrl, sizeof(*rrl));
1339 }
1340 
1341 isc_result_t
1342 dns_rrl_init(dns_rrl_t **rrlp, dns_view_t *view, int min_entries) {
1343 	dns_rrl_t *rrl;
1344 	isc_result_t result;
1345 
1346 	*rrlp = NULL;
1347 
1348 	rrl = isc_mem_get(view->mctx, sizeof(*rrl));
1349 	memset(rrl, 0, sizeof(*rrl));
1350 	isc_mem_attach(view->mctx, &rrl->mctx);
1351 	isc_mutex_init(&rrl->lock);
1352 	isc_stdtime_get(&rrl->ts_bases[0]);
1353 
1354 	view->rrl = rrl;
1355 
1356 	result = expand_entries(rrl, min_entries);
1357 	if (result != ISC_R_SUCCESS) {
1358 		dns_rrl_view_destroy(view);
1359 		return (result);
1360 	}
1361 	result = expand_rrl_hash(rrl, 0);
1362 	if (result != ISC_R_SUCCESS) {
1363 		dns_rrl_view_destroy(view);
1364 		return (result);
1365 	}
1366 
1367 	*rrlp = rrl;
1368 	return (ISC_R_SUCCESS);
1369 }
1370