xref: /netbsd-src/external/mpl/bind/dist/lib/ns/client.c (revision 2f62cc9c12bc202c40224f32c879f81443fee079)
1 /*	$NetBSD: client.c,v 1.20 2024/02/23 21:09:49 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 #include <inttypes.h>
17 #include <limits.h>
18 #include <stdbool.h>
19 
20 #include <isc/aes.h>
21 #include <isc/atomic.h>
22 #include <isc/formatcheck.h>
23 #include <isc/fuzz.h>
24 #include <isc/hmac.h>
25 #include <isc/log.h>
26 #include <isc/mutex.h>
27 #include <isc/nonce.h>
28 #include <isc/once.h>
29 #include <isc/print.h>
30 #include <isc/random.h>
31 #include <isc/safe.h>
32 #include <isc/serial.h>
33 #include <isc/siphash.h>
34 #include <isc/stats.h>
35 #include <isc/stdio.h>
36 #include <isc/string.h>
37 #include <isc/task.h>
38 #include <isc/thread.h>
39 #include <isc/timer.h>
40 #include <isc/util.h>
41 
42 #include <dns/adb.h>
43 #include <dns/badcache.h>
44 #include <dns/cache.h>
45 #include <dns/db.h>
46 #include <dns/dispatch.h>
47 #include <dns/dnstap.h>
48 #include <dns/edns.h>
49 #include <dns/events.h>
50 #include <dns/message.h>
51 #include <dns/peer.h>
52 #include <dns/rcode.h>
53 #include <dns/rdata.h>
54 #include <dns/rdataclass.h>
55 #include <dns/rdatalist.h>
56 #include <dns/rdataset.h>
57 #include <dns/resolver.h>
58 #include <dns/result.h>
59 #include <dns/stats.h>
60 #include <dns/tsig.h>
61 #include <dns/view.h>
62 #include <dns/zone.h>
63 
64 #include <ns/client.h>
65 #include <ns/interfacemgr.h>
66 #include <ns/log.h>
67 #include <ns/notify.h>
68 #include <ns/server.h>
69 #include <ns/stats.h>
70 #include <ns/update.h>
71 
72 /***
73  *** Client
74  ***/
75 
76 /*! \file
77  * Client Routines
78  *
79  * Important note!
80  *
81  * All client state changes, other than that from idle to listening, occur
82  * as a result of events.  This guarantees serialization and avoids the
83  * need for locking.
84  *
85  * If a routine is ever created that allows someone other than the client's
86  * task to change the client, then the client will have to be locked.
87  */
88 
89 #ifdef NS_CLIENT_TRACE
90 #define CTRACE(m)                                                         \
91 	ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, \
92 		      ISC_LOG_DEBUG(3), "%s", (m))
93 #define MTRACE(m)                                                          \
94 	isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT, \
95 		      ISC_LOG_DEBUG(3), "clientmgr @%p: %s", manager, (m))
96 #else /* ifdef NS_CLIENT_TRACE */
97 #define CTRACE(m) ((void)/*LINTED*/(m))
98 #define MTRACE(m) ((void)/*LINTED*/(m))
99 #endif /* ifdef NS_CLIENT_TRACE */
100 
101 #define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
102 
103 #define COOKIE_SIZE 24U /* 8 + 4 + 4 + 8 */
104 #define ECS_SIZE    20U /* 2 + 1 + 1 + [0..16] */
105 
106 #define WANTNSID(x)	(((x)->attributes & NS_CLIENTATTR_WANTNSID) != 0)
107 #define WANTEXPIRE(x)	(((x)->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0)
108 #define WANTPAD(x)	(((x)->attributes & NS_CLIENTATTR_WANTPAD) != 0)
109 #define USEKEEPALIVE(x) (((x)->attributes & NS_CLIENTATTR_USEKEEPALIVE) != 0)
110 
111 #define MANAGER_MAGIC	 ISC_MAGIC('N', 'S', 'C', 'm')
112 #define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
113 
114 /*
115  * Enable ns_client_dropport() by default.
116  */
117 #ifndef NS_CLIENT_DROPPORT
118 #define NS_CLIENT_DROPPORT 1
119 #endif /* ifndef NS_CLIENT_DROPPORT */
120 
121 #ifdef _LP64
122 atomic_uint_fast64_t ns_client_requests = 0;
123 #else
124 atomic_uint_fast32_t ns_client_requests = 0;
125 #endif
126 
127 static void
128 clientmgr_attach(ns_clientmgr_t *source, ns_clientmgr_t **targetp);
129 static void
130 clientmgr_destroy(ns_clientmgr_t *manager);
131 static void
132 ns_client_endrequest(ns_client_t *client);
133 static void
134 ns_client_dumpmessage(ns_client_t *client, const char *reason);
135 static void
136 compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
137 	       const unsigned char *secret, isc_buffer_t *buf);
138 
139 void
140 ns_client_recursing(ns_client_t *client) {
141 	REQUIRE(NS_CLIENT_VALID(client));
142 	REQUIRE(client->state == NS_CLIENTSTATE_WORKING);
143 
144 	LOCK(&client->manager->reclock);
145 	client->state = NS_CLIENTSTATE_RECURSING;
146 	ISC_LIST_APPEND(client->manager->recursing, client, rlink);
147 	UNLOCK(&client->manager->reclock);
148 }
149 
150 void
151 ns_client_killoldestquery(ns_client_t *client) {
152 	ns_client_t *oldest;
153 	REQUIRE(NS_CLIENT_VALID(client));
154 
155 	LOCK(&client->manager->reclock);
156 	oldest = ISC_LIST_HEAD(client->manager->recursing);
157 	if (oldest != NULL) {
158 		ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink);
159 		ns_query_cancel(oldest);
160 		ns_stats_increment(client->sctx->nsstats,
161 				   ns_statscounter_reclimitdropped);
162 	}
163 	UNLOCK(&client->manager->reclock);
164 }
165 
166 void
167 ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
168 	UNUSED(client);
169 	UNUSED(seconds);
170 	/* XXXWPK TODO use netmgr to set timeout */
171 }
172 
173 static void
174 client_extendederror_reset(ns_client_t *client) {
175 	if (client->ede == NULL) {
176 		return;
177 	}
178 	isc_mem_put(client->mctx, client->ede->value, client->ede->length);
179 	isc_mem_put(client->mctx, client->ede, sizeof(dns_ednsopt_t));
180 	client->ede = NULL;
181 }
182 
183 void
184 ns_client_extendederror(ns_client_t *client, uint16_t code, const char *text) {
185 	unsigned char ede[DNS_EDE_EXTRATEXT_LEN + 2];
186 	isc_buffer_t buf;
187 	uint16_t len = sizeof(uint16_t);
188 
189 	REQUIRE(NS_CLIENT_VALID(client));
190 
191 	if (client->ede != NULL) {
192 		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
193 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
194 			      "already have ede, ignoring %u %s", code,
195 			      text == NULL ? "(null)" : text);
196 		return;
197 	}
198 
199 	ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
200 		      ISC_LOG_DEBUG(1), "set ede: info-code %u extra-text %s",
201 		      code, text == NULL ? "(null)" : text);
202 
203 	isc_buffer_init(&buf, ede, sizeof(ede));
204 	isc_buffer_putuint16(&buf, code);
205 	if (text != NULL && strlen(text) > 0) {
206 		if (strlen(text) < DNS_EDE_EXTRATEXT_LEN) {
207 			isc_buffer_putstr(&buf, text);
208 			len += (uint16_t)(strlen(text));
209 		} else {
210 			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
211 				      NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
212 				      "ede extra-text too long, ignoring");
213 		}
214 	}
215 
216 	client->ede = isc_mem_get(client->mctx, sizeof(dns_ednsopt_t));
217 	client->ede->code = DNS_OPT_EDE;
218 	client->ede->length = len;
219 	client->ede->value = isc_mem_get(client->mctx, len);
220 	memmove(client->ede->value, ede, len);
221 };
222 
223 static void
224 ns_client_endrequest(ns_client_t *client) {
225 	INSIST(client->nupdates == 0);
226 	INSIST(client->state == NS_CLIENTSTATE_WORKING ||
227 	       client->state == NS_CLIENTSTATE_RECURSING);
228 
229 	CTRACE("endrequest");
230 
231 	if (client->state == NS_CLIENTSTATE_RECURSING) {
232 		LOCK(&client->manager->reclock);
233 		if (ISC_LINK_LINKED(client, rlink)) {
234 			ISC_LIST_UNLINK(client->manager->recursing, client,
235 					rlink);
236 		}
237 		UNLOCK(&client->manager->reclock);
238 	}
239 
240 	if (client->cleanup != NULL) {
241 		(client->cleanup)(client);
242 		client->cleanup = NULL;
243 	}
244 
245 	if (client->view != NULL) {
246 #ifdef ENABLE_AFL
247 		if (client->sctx->fuzztype == isc_fuzz_resolver) {
248 			dns_cache_clean(client->view->cache, INT_MAX);
249 			dns_adb_flush(client->view->adb);
250 		}
251 #endif /* ifdef ENABLE_AFL */
252 		dns_view_detach(&client->view);
253 	}
254 	if (client->opt != NULL) {
255 		INSIST(dns_rdataset_isassociated(client->opt));
256 		dns_rdataset_disassociate(client->opt);
257 		dns_message_puttemprdataset(client->message, &client->opt);
258 	}
259 
260 	client_extendederror_reset(client);
261 	client->signer = NULL;
262 	client->udpsize = 512;
263 	client->extflags = 0;
264 	client->ednsversion = -1;
265 	client->additionaldepth = 0;
266 	dns_ecs_init(&client->ecs);
267 	dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
268 
269 	/*
270 	 * Clean up from recursion - normally this would be done in
271 	 * fetch_callback(), but if we're shutting down and canceling then
272 	 * it might not have happened.
273 	 */
274 	if (client->recursionquota != NULL) {
275 		isc_quota_detach(&client->recursionquota);
276 		ns_stats_decrement(client->sctx->nsstats,
277 				   ns_statscounter_recursclients);
278 	}
279 
280 	/*
281 	 * Clear all client attributes that are specific to the request
282 	 */
283 	client->attributes = 0;
284 #ifdef ENABLE_AFL
285 	if (client->sctx->fuzznotify != NULL &&
286 	    (client->sctx->fuzztype == isc_fuzz_client ||
287 	     client->sctx->fuzztype == isc_fuzz_tcpclient ||
288 	     client->sctx->fuzztype == isc_fuzz_resolver))
289 	{
290 		client->sctx->fuzznotify();
291 	}
292 #endif /* ENABLE_AFL */
293 }
294 
295 void
296 ns_client_drop(ns_client_t *client, isc_result_t result) {
297 	REQUIRE(NS_CLIENT_VALID(client));
298 	REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
299 		client->state == NS_CLIENTSTATE_RECURSING);
300 
301 	CTRACE("drop");
302 	if (result != ISC_R_SUCCESS) {
303 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
304 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
305 			      "request failed: %s", isc_result_totext(result));
306 	}
307 }
308 
309 static void
310 client_senddone(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
311 	ns_client_t *client = cbarg;
312 
313 	REQUIRE(client->sendhandle == handle);
314 
315 	CTRACE("senddone");
316 
317 	/*
318 	 * Set sendhandle to NULL, but don't detach it immediately, in
319 	 * case we need to retry the send. If we do resend, then
320 	 * sendhandle will be reattached. Whether or not we resend,
321 	 * we will then detach the handle from *this* send by detaching
322 	 * 'handle' directly below.
323 	 */
324 	client->sendhandle = NULL;
325 
326 	if (result != ISC_R_SUCCESS) {
327 		if (!TCP_CLIENT(client) && result == ISC_R_MAXSIZE) {
328 			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
329 				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
330 				      "send exceeded maximum size: truncating");
331 			client->query.attributes &= ~NS_QUERYATTR_ANSWERED;
332 			client->rcode_override = dns_rcode_noerror;
333 			ns_client_error(client, ISC_R_MAXSIZE);
334 		} else {
335 			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
336 				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
337 				      "send failed: %s",
338 				      isc_result_totext(result));
339 		}
340 	}
341 
342 	isc_nmhandle_detach(&handle);
343 }
344 
345 static void
346 client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
347 		    unsigned char **datap) {
348 	unsigned char *data;
349 	uint32_t bufsize;
350 
351 	REQUIRE(datap != NULL);
352 
353 	if (TCP_CLIENT(client)) {
354 		INSIST(client->tcpbuf == NULL);
355 		client->tcpbuf = isc_mem_get(client->manager->send_mctx,
356 					     NS_CLIENT_TCP_BUFFER_SIZE);
357 		client->tcpbuf_size = NS_CLIENT_TCP_BUFFER_SIZE;
358 		data = client->tcpbuf;
359 		isc_buffer_init(buffer, data, NS_CLIENT_TCP_BUFFER_SIZE);
360 	} else {
361 		data = client->sendbuf;
362 		if ((client->attributes & NS_CLIENTATTR_HAVECOOKIE) == 0) {
363 			if (client->view != NULL) {
364 				bufsize = client->view->nocookieudp;
365 			} else {
366 				bufsize = 512;
367 			}
368 		} else {
369 			bufsize = client->udpsize;
370 		}
371 		if (bufsize > client->udpsize) {
372 			bufsize = client->udpsize;
373 		}
374 		if (bufsize > NS_CLIENT_SEND_BUFFER_SIZE) {
375 			bufsize = NS_CLIENT_SEND_BUFFER_SIZE;
376 		}
377 		isc_buffer_init(buffer, data, bufsize);
378 	}
379 	*datap = data;
380 }
381 
382 static void
383 client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
384 	isc_result_t result;
385 	isc_region_t r;
386 	dns_ttl_t min_ttl = 0;
387 
388 	REQUIRE(client->sendhandle == NULL);
389 
390 	if (isc_buffer_base(buffer) == client->tcpbuf) {
391 		size_t used = isc_buffer_usedlength(buffer);
392 		client->tcpbuf = isc_mem_reget(client->manager->send_mctx,
393 					       client->tcpbuf,
394 					       client->tcpbuf_size, used);
395 		client->tcpbuf_size = used;
396 		r.base = client->tcpbuf;
397 		r.length = used;
398 	} else {
399 		isc_buffer_usedregion(buffer, &r);
400 	}
401 	isc_nmhandle_attach(client->handle, &client->sendhandle);
402 
403 	if (isc_nm_is_http_handle(client->handle)) {
404 		result = dns_message_response_minttl(client->message, &min_ttl);
405 		if (result == ISC_R_SUCCESS) {
406 			isc_nm_set_maxage(client->handle, min_ttl);
407 		}
408 	}
409 	isc_nm_send(client->handle, &r, client_senddone, client);
410 }
411 
412 void
413 ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
414 	isc_result_t result;
415 	unsigned char *data = NULL;
416 	isc_buffer_t buffer;
417 	isc_region_t r;
418 	isc_region_t *mr = NULL;
419 
420 	REQUIRE(NS_CLIENT_VALID(client));
421 
422 	CTRACE("sendraw");
423 
424 	mr = dns_message_getrawmessage(message);
425 	if (mr == NULL) {
426 		result = ISC_R_UNEXPECTEDEND;
427 		goto done;
428 	}
429 
430 	client_allocsendbuf(client, &buffer, &data);
431 
432 	if (mr->length > isc_buffer_length(&buffer)) {
433 		result = ISC_R_NOSPACE;
434 		goto done;
435 	}
436 
437 	/*
438 	 * Copy message to buffer and fixup id.
439 	 */
440 	isc_buffer_availableregion(&buffer, &r);
441 	result = isc_buffer_copyregion(&buffer, mr);
442 	if (result != ISC_R_SUCCESS) {
443 		goto done;
444 	}
445 	r.base[0] = (client->message->id >> 8) & 0xff;
446 	r.base[1] = client->message->id & 0xff;
447 
448 #ifdef HAVE_DNSTAP
449 	if (client->view != NULL) {
450 		bool tcp = TCP_CLIENT(client);
451 		dns_dtmsgtype_t dtmsgtype;
452 		if (client->message->opcode == dns_opcode_update) {
453 			dtmsgtype = DNS_DTTYPE_UR;
454 		} else if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0) {
455 			dtmsgtype = DNS_DTTYPE_CR;
456 		} else {
457 			dtmsgtype = DNS_DTTYPE_AR;
458 		}
459 		dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
460 			    &client->destsockaddr, tcp, NULL,
461 			    &client->requesttime, NULL, &buffer);
462 	}
463 #endif
464 
465 	client_sendpkg(client, &buffer);
466 
467 	return;
468 done:
469 	if (client->tcpbuf != NULL) {
470 		isc_mem_put(client->manager->send_mctx, client->tcpbuf,
471 			    client->tcpbuf_size);
472 	}
473 
474 	ns_client_drop(client, result);
475 }
476 
477 void
478 ns_client_send(ns_client_t *client) {
479 	isc_result_t result;
480 	unsigned char *data = NULL;
481 	isc_buffer_t buffer = { .magic = 0 };
482 	isc_region_t r;
483 	dns_compress_t cctx;
484 	bool cleanup_cctx = false;
485 	unsigned int render_opts;
486 	unsigned int preferred_glue;
487 	bool opt_included = false;
488 	size_t respsize;
489 	dns_aclenv_t *env = NULL;
490 #ifdef HAVE_DNSTAP
491 	unsigned char zone[DNS_NAME_MAXWIRE];
492 	dns_dtmsgtype_t dtmsgtype;
493 	isc_region_t zr;
494 #endif /* HAVE_DNSTAP */
495 
496 	REQUIRE(NS_CLIENT_VALID(client));
497 
498 	if ((client->query.attributes & NS_QUERYATTR_ANSWERED) != 0) {
499 		return;
500 	}
501 
502 	/*
503 	 * XXXWPK TODO
504 	 * Delay the response according to the -T delay option
505 	 */
506 
507 	env = client->manager->aclenv;
508 
509 	CTRACE("send");
510 
511 	if (client->message->opcode == dns_opcode_query &&
512 	    (client->attributes & NS_CLIENTATTR_RA) != 0)
513 	{
514 		client->message->flags |= DNS_MESSAGEFLAG_RA;
515 	}
516 
517 	if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0) {
518 		render_opts = 0;
519 	} else {
520 		render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
521 	}
522 
523 	preferred_glue = 0;
524 	if (client->view != NULL) {
525 		if (client->view->preferred_glue == dns_rdatatype_a) {
526 			preferred_glue = DNS_MESSAGERENDER_PREFER_A;
527 		} else if (client->view->preferred_glue == dns_rdatatype_aaaa) {
528 			preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
529 		}
530 	}
531 	if (preferred_glue == 0) {
532 		if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) {
533 			preferred_glue = DNS_MESSAGERENDER_PREFER_A;
534 		} else {
535 			preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
536 		}
537 	}
538 
539 	/*
540 	 * Create an OPT for our reply.
541 	 */
542 	if ((client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
543 		result = ns_client_addopt(client, client->message,
544 					  &client->opt);
545 		if (result != ISC_R_SUCCESS) {
546 			goto cleanup;
547 		}
548 	}
549 
550 	client_allocsendbuf(client, &buffer, &data);
551 
552 	result = dns_compress_init(&cctx, -1, client->mctx);
553 	if (result != ISC_R_SUCCESS) {
554 		goto cleanup;
555 	}
556 	if (client->peeraddr_valid && client->view != NULL) {
557 		isc_netaddr_t netaddr;
558 		dns_name_t *name = NULL;
559 
560 		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
561 		if (client->message->tsigkey != NULL) {
562 			name = &client->message->tsigkey->name;
563 		}
564 
565 		if (client->view->nocasecompress == NULL ||
566 		    !dns_acl_allowed(&netaddr, name,
567 				     client->view->nocasecompress, env))
568 		{
569 			dns_compress_setsensitive(&cctx, true);
570 		}
571 
572 		if (!client->view->msgcompression) {
573 			dns_compress_disable(&cctx);
574 		}
575 	}
576 	cleanup_cctx = true;
577 
578 	result = dns_message_renderbegin(client->message, &cctx, &buffer);
579 	if (result != ISC_R_SUCCESS) {
580 		goto cleanup;
581 	}
582 
583 	if (client->opt != NULL) {
584 		result = dns_message_setopt(client->message, client->opt);
585 		opt_included = true;
586 		client->opt = NULL;
587 		if (result != ISC_R_SUCCESS) {
588 			goto cleanup;
589 		}
590 	}
591 	result = dns_message_rendersection(client->message,
592 					   DNS_SECTION_QUESTION, 0);
593 	if (result == ISC_R_NOSPACE) {
594 		client->message->flags |= DNS_MESSAGEFLAG_TC;
595 		goto renderend;
596 	}
597 	if (result != ISC_R_SUCCESS) {
598 		goto cleanup;
599 	}
600 	/*
601 	 * Stop after the question if TC was set for rate limiting.
602 	 */
603 	if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0) {
604 		goto renderend;
605 	}
606 	result = dns_message_rendersection(client->message, DNS_SECTION_ANSWER,
607 					   DNS_MESSAGERENDER_PARTIAL |
608 						   render_opts);
609 	if (result == ISC_R_NOSPACE) {
610 		client->message->flags |= DNS_MESSAGEFLAG_TC;
611 		goto renderend;
612 	}
613 	if (result != ISC_R_SUCCESS) {
614 		goto cleanup;
615 	}
616 	result = dns_message_rendersection(
617 		client->message, DNS_SECTION_AUTHORITY,
618 		DNS_MESSAGERENDER_PARTIAL | render_opts);
619 	if (result == ISC_R_NOSPACE) {
620 		client->message->flags |= DNS_MESSAGEFLAG_TC;
621 		goto renderend;
622 	}
623 	if (result != ISC_R_SUCCESS) {
624 		goto cleanup;
625 	}
626 	result = dns_message_rendersection(client->message,
627 					   DNS_SECTION_ADDITIONAL,
628 					   preferred_glue | render_opts);
629 	if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) {
630 		goto cleanup;
631 	}
632 renderend:
633 	result = dns_message_renderend(client->message);
634 	if (result != ISC_R_SUCCESS) {
635 		goto cleanup;
636 	}
637 
638 #ifdef HAVE_DNSTAP
639 	memset(&zr, 0, sizeof(zr));
640 	if (((client->message->flags & DNS_MESSAGEFLAG_AA) != 0) &&
641 	    (client->query.authzone != NULL))
642 	{
643 		isc_result_t eresult;
644 		isc_buffer_t b;
645 		dns_name_t *zo = dns_zone_getorigin(client->query.authzone);
646 
647 		isc_buffer_init(&b, zone, sizeof(zone));
648 		dns_compress_setmethods(&cctx, DNS_COMPRESS_NONE);
649 		eresult = dns_name_towire(zo, &cctx, &b);
650 		if (eresult == ISC_R_SUCCESS) {
651 			isc_buffer_usedregion(&b, &zr);
652 		}
653 	}
654 
655 	if (client->message->opcode == dns_opcode_update) {
656 		dtmsgtype = DNS_DTTYPE_UR;
657 	} else if ((client->message->flags & DNS_MESSAGEFLAG_RD) != 0) {
658 		dtmsgtype = DNS_DTTYPE_CR;
659 	} else {
660 		dtmsgtype = DNS_DTTYPE_AR;
661 	}
662 #endif /* HAVE_DNSTAP */
663 
664 	if (cleanup_cctx) {
665 		dns_compress_invalidate(&cctx);
666 	}
667 
668 	if (client->sendcb != NULL) {
669 		client->sendcb(&buffer);
670 	} else if (TCP_CLIENT(client)) {
671 		isc_buffer_usedregion(&buffer, &r);
672 #ifdef HAVE_DNSTAP
673 		if (client->view != NULL) {
674 			dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
675 				    &client->destsockaddr, true, &zr,
676 				    &client->requesttime, NULL, &buffer);
677 		}
678 #endif /* HAVE_DNSTAP */
679 
680 		respsize = isc_buffer_usedlength(&buffer);
681 
682 		client_sendpkg(client, &buffer);
683 
684 		switch (isc_sockaddr_pf(&client->peeraddr)) {
685 		case AF_INET:
686 			isc_stats_increment(client->sctx->tcpoutstats4,
687 					    ISC_MIN((int)respsize / 16, 256));
688 			break;
689 		case AF_INET6:
690 			isc_stats_increment(client->sctx->tcpoutstats6,
691 					    ISC_MIN((int)respsize / 16, 256));
692 			break;
693 		default:
694 			UNREACHABLE();
695 		}
696 	} else {
697 #ifdef HAVE_DNSTAP
698 		/*
699 		 * Log dnstap data first, because client_sendpkg() may
700 		 * leave client->view set to NULL.
701 		 */
702 		if (client->view != NULL) {
703 			dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
704 				    &client->destsockaddr, false, &zr,
705 				    &client->requesttime, NULL, &buffer);
706 		}
707 #endif /* HAVE_DNSTAP */
708 
709 		respsize = isc_buffer_usedlength(&buffer);
710 
711 		client_sendpkg(client, &buffer);
712 
713 		switch (isc_sockaddr_pf(&client->peeraddr)) {
714 		case AF_INET:
715 			isc_stats_increment(client->sctx->udpoutstats4,
716 					    ISC_MIN((int)respsize / 16, 256));
717 			break;
718 		case AF_INET6:
719 			isc_stats_increment(client->sctx->udpoutstats6,
720 					    ISC_MIN((int)respsize / 16, 256));
721 			break;
722 		default:
723 			UNREACHABLE();
724 		}
725 	}
726 
727 	/* update statistics (XXXJT: is it okay to access message->xxxkey?) */
728 	ns_stats_increment(client->sctx->nsstats, ns_statscounter_response);
729 
730 	dns_rcodestats_increment(client->sctx->rcodestats,
731 				 client->message->rcode);
732 	if (opt_included) {
733 		ns_stats_increment(client->sctx->nsstats,
734 				   ns_statscounter_edns0out);
735 	}
736 	if (client->message->tsigkey != NULL) {
737 		ns_stats_increment(client->sctx->nsstats,
738 				   ns_statscounter_tsigout);
739 	}
740 	if (client->message->sig0key != NULL) {
741 		ns_stats_increment(client->sctx->nsstats,
742 				   ns_statscounter_sig0out);
743 	}
744 	if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0) {
745 		ns_stats_increment(client->sctx->nsstats,
746 				   ns_statscounter_truncatedresp);
747 	}
748 
749 	client->query.attributes |= NS_QUERYATTR_ANSWERED;
750 
751 	return;
752 
753 cleanup:
754 	if (client->tcpbuf != NULL) {
755 		isc_mem_put(client->manager->send_mctx, client->tcpbuf,
756 			    client->tcpbuf_size);
757 	}
758 
759 	if (cleanup_cctx) {
760 		dns_compress_invalidate(&cctx);
761 	}
762 }
763 
764 #if NS_CLIENT_DROPPORT
765 #define DROPPORT_NO	  0
766 #define DROPPORT_REQUEST  1
767 #define DROPPORT_RESPONSE 2
768 /*%
769  * ns_client_dropport determines if certain requests / responses
770  * should be dropped based on the port number.
771  *
772  * Returns:
773  * \li	0:	Don't drop.
774  * \li	1:	Drop request.
775  * \li	2:	Drop (error) response.
776  */
777 static int
778 ns_client_dropport(in_port_t port) {
779 	switch (port) {
780 	case 7:	 /* echo */
781 	case 13: /* daytime */
782 	case 19: /* chargen */
783 	case 37: /* time */
784 		return (DROPPORT_REQUEST);
785 	case 464: /* kpasswd */
786 		return (DROPPORT_RESPONSE);
787 	}
788 	return (DROPPORT_NO);
789 }
790 #endif /* if NS_CLIENT_DROPPORT */
791 
792 void
793 ns_client_error(ns_client_t *client, isc_result_t result) {
794 	dns_message_t *message = NULL;
795 	dns_rcode_t rcode;
796 	bool trunc = false;
797 
798 	REQUIRE(NS_CLIENT_VALID(client));
799 
800 	CTRACE("error");
801 
802 	message = client->message;
803 
804 	if (client->rcode_override == -1) {
805 		rcode = dns_result_torcode(result);
806 	} else {
807 		rcode = (dns_rcode_t)(client->rcode_override & 0xfff);
808 	}
809 
810 	if (result == ISC_R_MAXSIZE) {
811 		trunc = true;
812 	}
813 
814 #if NS_CLIENT_DROPPORT
815 	/*
816 	 * Don't send FORMERR to ports on the drop port list.
817 	 */
818 	if (rcode == dns_rcode_formerr &&
819 	    ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
820 		    DROPPORT_NO)
821 	{
822 		char buf[64];
823 		isc_buffer_t b;
824 
825 		isc_buffer_init(&b, buf, sizeof(buf) - 1);
826 		if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS) {
827 			isc_buffer_putstr(&b, "UNKNOWN RCODE");
828 		}
829 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
830 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
831 			      "dropped error (%.*s) response: suspicious port",
832 			      (int)isc_buffer_usedlength(&b), buf);
833 		ns_client_drop(client, ISC_R_SUCCESS);
834 		return;
835 	}
836 #endif /* if NS_CLIENT_DROPPORT */
837 
838 	/*
839 	 * Try to rate limit error responses.
840 	 */
841 	if (client->view != NULL && client->view->rrl != NULL) {
842 		bool wouldlog;
843 		char log_buf[DNS_RRL_LOG_BUF_LEN];
844 		dns_rrl_result_t rrl_result;
845 		int loglevel;
846 
847 		if ((client->sctx->options & NS_SERVER_LOGQUERIES) != 0) {
848 			loglevel = DNS_RRL_LOG_DROP;
849 		} else {
850 			loglevel = ISC_LOG_DEBUG(1);
851 		}
852 		wouldlog = isc_log_wouldlog(ns_lctx, loglevel);
853 		rrl_result = dns_rrl(client->view, NULL, &client->peeraddr,
854 				     TCP_CLIENT(client), dns_rdataclass_in,
855 				     dns_rdatatype_none, NULL, result,
856 				     client->now, wouldlog, log_buf,
857 				     sizeof(log_buf));
858 		if (rrl_result != DNS_RRL_RESULT_OK) {
859 			/*
860 			 * Log dropped errors in the query category
861 			 * so that they are not lost in silence.
862 			 * Starts of rate-limited bursts are logged in
863 			 * NS_LOGCATEGORY_RRL.
864 			 */
865 			if (wouldlog) {
866 				ns_client_log(client,
867 					      NS_LOGCATEGORY_QUERY_ERRORS,
868 					      NS_LOGMODULE_CLIENT, loglevel,
869 					      "%s", log_buf);
870 			}
871 			/*
872 			 * Some error responses cannot be 'slipped',
873 			 * so don't try to slip any error responses.
874 			 */
875 			if (!client->view->rrl->log_only) {
876 				ns_stats_increment(client->sctx->nsstats,
877 						   ns_statscounter_ratedropped);
878 				ns_stats_increment(client->sctx->nsstats,
879 						   ns_statscounter_dropped);
880 				ns_client_drop(client, DNS_R_DROP);
881 				return;
882 			}
883 		}
884 	}
885 
886 	/*
887 	 * Message may be an in-progress reply that we had trouble
888 	 * with, in which case QR will be set.  We need to clear QR before
889 	 * calling dns_message_reply() to avoid triggering an assertion.
890 	 */
891 	message->flags &= ~DNS_MESSAGEFLAG_QR;
892 	/*
893 	 * AA and AD shouldn't be set.
894 	 */
895 	message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
896 	result = dns_message_reply(message, true);
897 	if (result != ISC_R_SUCCESS) {
898 		/*
899 		 * It could be that we've got a query with a good header,
900 		 * but a bad question section, so we try again with
901 		 * want_question_section set to false.
902 		 */
903 		result = dns_message_reply(message, false);
904 		if (result != ISC_R_SUCCESS) {
905 			ns_client_drop(client, result);
906 			return;
907 		}
908 	}
909 
910 	message->rcode = rcode;
911 	if (trunc) {
912 		message->flags |= DNS_MESSAGEFLAG_TC;
913 	}
914 
915 	if (rcode == dns_rcode_formerr) {
916 		/*
917 		 * FORMERR loop avoidance:  If we sent a FORMERR message
918 		 * with the same ID to the same client less than two
919 		 * seconds ago, assume that we are in an infinite error
920 		 * packet dialog with a server for some protocol whose
921 		 * error responses look enough like DNS queries to
922 		 * elicit a FORMERR response.  Drop a packet to break
923 		 * the loop.
924 		 */
925 		if (isc_sockaddr_equal(&client->peeraddr,
926 				       &client->formerrcache.addr) &&
927 		    message->id == client->formerrcache.id &&
928 		    (isc_time_seconds(&client->requesttime) -
929 		     client->formerrcache.time) < 2)
930 		{
931 			/* Drop packet. */
932 			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
933 				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
934 				      "possible error packet loop, "
935 				      "FORMERR dropped");
936 			ns_client_drop(client, result);
937 			return;
938 		}
939 		client->formerrcache.addr = client->peeraddr;
940 		client->formerrcache.time =
941 			isc_time_seconds(&client->requesttime);
942 		client->formerrcache.id = message->id;
943 	} else if (rcode == dns_rcode_servfail && client->query.qname != NULL &&
944 		   client->view != NULL && client->view->fail_ttl != 0 &&
945 		   ((client->attributes & NS_CLIENTATTR_NOSETFC) == 0))
946 	{
947 		/*
948 		 * SERVFAIL caching: store qname/qtype of failed queries
949 		 */
950 		isc_time_t expire;
951 		isc_interval_t i;
952 		uint32_t flags = 0;
953 
954 		if ((message->flags & DNS_MESSAGEFLAG_CD) != 0) {
955 			flags = NS_FAILCACHE_CD;
956 		}
957 
958 		isc_interval_set(&i, client->view->fail_ttl, 0);
959 		result = isc_time_nowplusinterval(&expire, &i);
960 		if (result == ISC_R_SUCCESS) {
961 			dns_badcache_add(
962 				client->view->failcache, client->query.qname,
963 				client->query.qtype, true, flags, &expire);
964 		}
965 	}
966 
967 	ns_client_send(client);
968 }
969 
970 isc_result_t
971 ns_client_addopt(ns_client_t *client, dns_message_t *message,
972 		 dns_rdataset_t **opt) {
973 	unsigned char ecs[ECS_SIZE];
974 	char nsid[_POSIX_HOST_NAME_MAX + 1], *nsidp = NULL;
975 	unsigned char cookie[COOKIE_SIZE];
976 	isc_result_t result;
977 	dns_view_t *view = NULL;
978 	dns_resolver_t *resolver = NULL;
979 	uint16_t udpsize;
980 	dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
981 	int count = 0;
982 	unsigned int flags;
983 	unsigned char expire[4];
984 	unsigned char advtimo[2];
985 	dns_aclenv_t *env = NULL;
986 
987 	REQUIRE(NS_CLIENT_VALID(client));
988 	REQUIRE(opt != NULL && *opt == NULL);
989 	REQUIRE(message != NULL);
990 
991 	env = client->manager->aclenv;
992 	view = client->view;
993 	resolver = (view != NULL) ? view->resolver : NULL;
994 	if (resolver != NULL) {
995 		udpsize = dns_resolver_getudpsize(resolver);
996 	} else {
997 		udpsize = client->sctx->udpsize;
998 	}
999 
1000 	flags = client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE;
1001 
1002 	/* Set EDNS options if applicable */
1003 	if (WANTNSID(client)) {
1004 		if (client->sctx->server_id != NULL) {
1005 			nsidp = client->sctx->server_id;
1006 		} else if (client->sctx->usehostname) {
1007 			result = gethostname(nsid, sizeof(nsid));
1008 			if (result != ISC_R_SUCCESS) {
1009 				goto no_nsid;
1010 			}
1011 			nsidp = nsid;
1012 		} else {
1013 			goto no_nsid;
1014 		}
1015 
1016 		INSIST(count < DNS_EDNSOPTIONS);
1017 		ednsopts[count].code = DNS_OPT_NSID;
1018 		ednsopts[count].length = (uint16_t)strlen(nsidp);
1019 		ednsopts[count].value = (unsigned char *)nsidp;
1020 		count++;
1021 	}
1022 no_nsid:
1023 	if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0) {
1024 		isc_buffer_t buf;
1025 		isc_stdtime_t now;
1026 		uint32_t nonce;
1027 
1028 		isc_buffer_init(&buf, cookie, sizeof(cookie));
1029 		isc_stdtime_get(&now);
1030 
1031 		isc_random_buf(&nonce, sizeof(nonce));
1032 
1033 		compute_cookie(client, now, nonce, client->sctx->secret, &buf);
1034 
1035 		INSIST(count < DNS_EDNSOPTIONS);
1036 		ednsopts[count].code = DNS_OPT_COOKIE;
1037 		ednsopts[count].length = COOKIE_SIZE;
1038 		ednsopts[count].value = cookie;
1039 		count++;
1040 	}
1041 	if ((client->attributes & NS_CLIENTATTR_HAVEEXPIRE) != 0) {
1042 		isc_buffer_t buf;
1043 
1044 		INSIST(count < DNS_EDNSOPTIONS);
1045 
1046 		isc_buffer_init(&buf, expire, sizeof(expire));
1047 		isc_buffer_putuint32(&buf, client->expire);
1048 		ednsopts[count].code = DNS_OPT_EXPIRE;
1049 		ednsopts[count].length = 4;
1050 		ednsopts[count].value = expire;
1051 		count++;
1052 	}
1053 	if (((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) &&
1054 	    (client->ecs.addr.family == AF_INET ||
1055 	     client->ecs.addr.family == AF_INET6 ||
1056 	     client->ecs.addr.family == AF_UNSPEC))
1057 	{
1058 		isc_buffer_t buf;
1059 		uint8_t addr[16];
1060 		uint32_t plen, addrl;
1061 		uint16_t family = 0;
1062 
1063 		/* Add CLIENT-SUBNET option. */
1064 
1065 		plen = client->ecs.source;
1066 
1067 		/* Round up prefix len to a multiple of 8 */
1068 		addrl = (plen + 7) / 8;
1069 
1070 		switch (client->ecs.addr.family) {
1071 		case AF_UNSPEC:
1072 			INSIST(plen == 0);
1073 			family = 0;
1074 			break;
1075 		case AF_INET:
1076 			INSIST(plen <= 32);
1077 			family = 1;
1078 			memmove(addr, &client->ecs.addr.type, addrl);
1079 			break;
1080 		case AF_INET6:
1081 			INSIST(plen <= 128);
1082 			family = 2;
1083 			memmove(addr, &client->ecs.addr.type, addrl);
1084 			break;
1085 		default:
1086 			UNREACHABLE();
1087 		}
1088 
1089 		isc_buffer_init(&buf, ecs, sizeof(ecs));
1090 		/* family */
1091 		isc_buffer_putuint16(&buf, family);
1092 		/* source prefix-length */
1093 		isc_buffer_putuint8(&buf, client->ecs.source);
1094 		/* scope prefix-length */
1095 		isc_buffer_putuint8(&buf, client->ecs.scope);
1096 
1097 		/* address */
1098 		if (addrl > 0) {
1099 			/* Mask off last address byte */
1100 			if ((plen % 8) != 0) {
1101 				addr[addrl - 1] &= ~0U << (8 - (plen % 8));
1102 			}
1103 			isc_buffer_putmem(&buf, addr, (unsigned)addrl);
1104 		}
1105 
1106 		ednsopts[count].code = DNS_OPT_CLIENT_SUBNET;
1107 		ednsopts[count].length = addrl + 4;
1108 		ednsopts[count].value = ecs;
1109 		count++;
1110 	}
1111 	if (TCP_CLIENT(client) && USEKEEPALIVE(client)) {
1112 		isc_buffer_t buf;
1113 		uint32_t adv;
1114 
1115 		INSIST(count < DNS_EDNSOPTIONS);
1116 
1117 		isc_nm_gettimeouts(isc_nmhandle_netmgr(client->handle), NULL,
1118 				   NULL, NULL, &adv);
1119 		adv /= 100; /* units of 100 milliseconds */
1120 		isc_buffer_init(&buf, advtimo, sizeof(advtimo));
1121 		isc_buffer_putuint16(&buf, (uint16_t)adv);
1122 		ednsopts[count].code = DNS_OPT_TCP_KEEPALIVE;
1123 		ednsopts[count].length = 2;
1124 		ednsopts[count].value = advtimo;
1125 		count++;
1126 	}
1127 
1128 	if (client->ede != NULL) {
1129 		INSIST(count < DNS_EDNSOPTIONS);
1130 		ednsopts[count].code = DNS_OPT_EDE;
1131 		ednsopts[count].length = client->ede->length;
1132 		ednsopts[count].value = client->ede->value;
1133 		count++;
1134 	}
1135 
1136 	/* Padding must be added last */
1137 	if ((view != NULL) && (view->padding > 0) && WANTPAD(client) &&
1138 	    (TCP_CLIENT(client) ||
1139 	     ((client->attributes & NS_CLIENTATTR_HAVECOOKIE) != 0)))
1140 	{
1141 		isc_netaddr_t netaddr;
1142 		int match;
1143 
1144 		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1145 		result = dns_acl_match(&netaddr, NULL, view->pad_acl, env,
1146 				       &match, NULL);
1147 		if (result == ISC_R_SUCCESS && match > 0) {
1148 			INSIST(count < DNS_EDNSOPTIONS);
1149 
1150 			ednsopts[count].code = DNS_OPT_PAD;
1151 			ednsopts[count].length = 0;
1152 			ednsopts[count].value = NULL;
1153 			count++;
1154 
1155 			dns_message_setpadding(message, view->padding);
1156 		}
1157 	}
1158 
1159 	result = dns_message_buildopt(message, opt, 0, udpsize, flags, ednsopts,
1160 				      count);
1161 	return (result);
1162 }
1163 
1164 static void
1165 compute_cookie(ns_client_t *client, uint32_t when, uint32_t nonce,
1166 	       const unsigned char *secret, isc_buffer_t *buf) {
1167 	unsigned char digest[ISC_MAX_MD_SIZE] ISC_NONSTRING = { 0 };
1168 	STATIC_ASSERT(ISC_MAX_MD_SIZE >= ISC_SIPHASH24_TAG_LENGTH, "You need "
1169 								   "to "
1170 								   "increase "
1171 								   "the digest "
1172 								   "buffer.");
1173 	STATIC_ASSERT(ISC_MAX_MD_SIZE >= ISC_AES_BLOCK_LENGTH, "You need to "
1174 							       "increase the "
1175 							       "digest "
1176 							       "buffer.");
1177 
1178 	switch (client->sctx->cookiealg) {
1179 	case ns_cookiealg_siphash24: {
1180 		unsigned char input[16 + 16] ISC_NONSTRING = { 0 };
1181 		size_t inputlen = 0;
1182 		isc_netaddr_t netaddr;
1183 		unsigned char *cp;
1184 
1185 		cp = isc_buffer_used(buf);
1186 		isc_buffer_putmem(buf, client->cookie, 8);
1187 		isc_buffer_putuint8(buf, NS_COOKIE_VERSION_1);
1188 		isc_buffer_putuint24(buf, 0); /* Reserved */
1189 		isc_buffer_putuint32(buf, when);
1190 
1191 		memmove(input, cp, 16);
1192 
1193 		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1194 		switch (netaddr.family) {
1195 		case AF_INET:
1196 			cp = (unsigned char *)&netaddr.type.in;
1197 			memmove(input + 16, cp, 4);
1198 			inputlen = 20;
1199 			break;
1200 		case AF_INET6:
1201 			cp = (unsigned char *)&netaddr.type.in6;
1202 			memmove(input + 16, cp, 16);
1203 			inputlen = 32;
1204 			break;
1205 		default:
1206 			UNREACHABLE();
1207 		}
1208 
1209 		isc_siphash24(secret, input, inputlen, digest);
1210 		isc_buffer_putmem(buf, digest, 8);
1211 		break;
1212 	}
1213 	case ns_cookiealg_aes: {
1214 		unsigned char input[4 + 4 + 16] ISC_NONSTRING = { 0 };
1215 		isc_netaddr_t netaddr;
1216 		unsigned char *cp;
1217 		unsigned int i;
1218 
1219 		cp = isc_buffer_used(buf);
1220 		isc_buffer_putmem(buf, client->cookie, 8);
1221 		isc_buffer_putuint32(buf, nonce);
1222 		isc_buffer_putuint32(buf, when);
1223 		memmove(input, cp, 16);
1224 		isc_aes128_crypt(secret, input, digest);
1225 		for (i = 0; i < 8; i++) {
1226 			input[i] = digest[i] ^ digest[i + 8];
1227 		}
1228 		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1229 		switch (netaddr.family) {
1230 		case AF_INET:
1231 			cp = (unsigned char *)&netaddr.type.in;
1232 			memmove(input + 8, cp, 4);
1233 			memset(input + 12, 0, 4);
1234 			isc_aes128_crypt(secret, input, digest);
1235 			break;
1236 		case AF_INET6:
1237 			cp = (unsigned char *)&netaddr.type.in6;
1238 			memmove(input + 8, cp, 16);
1239 			isc_aes128_crypt(secret, input, digest);
1240 			for (i = 0; i < 8; i++) {
1241 				input[i + 8] = digest[i] ^ digest[i + 8];
1242 			}
1243 			isc_aes128_crypt(client->sctx->secret, input + 8,
1244 					 digest);
1245 			break;
1246 		default:
1247 			UNREACHABLE();
1248 		}
1249 		for (i = 0; i < 8; i++) {
1250 			digest[i] ^= digest[i + 8];
1251 		}
1252 		isc_buffer_putmem(buf, digest, 8);
1253 		break;
1254 	}
1255 
1256 	default:
1257 		UNREACHABLE();
1258 	}
1259 }
1260 
1261 static void
1262 process_cookie(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
1263 	ns_altsecret_t *altsecret;
1264 	unsigned char dbuf[COOKIE_SIZE];
1265 	unsigned char *old;
1266 	isc_stdtime_t now;
1267 	uint32_t when;
1268 	uint32_t nonce;
1269 	isc_buffer_t db;
1270 
1271 	/*
1272 	 * If we have already seen a cookie option skip this cookie option.
1273 	 */
1274 	if ((!client->sctx->answercookie) ||
1275 	    (client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0)
1276 	{
1277 		isc_buffer_forward(buf, (unsigned int)optlen);
1278 		return;
1279 	}
1280 
1281 	client->attributes |= NS_CLIENTATTR_WANTCOOKIE;
1282 
1283 	ns_stats_increment(client->sctx->nsstats, ns_statscounter_cookiein);
1284 
1285 	if (optlen != COOKIE_SIZE) {
1286 		/*
1287 		 * Not our token.
1288 		 */
1289 		INSIST(optlen >= 8U);
1290 		memmove(client->cookie, isc_buffer_current(buf), 8);
1291 		isc_buffer_forward(buf, (unsigned int)optlen);
1292 
1293 		if (optlen == 8U) {
1294 			ns_stats_increment(client->sctx->nsstats,
1295 					   ns_statscounter_cookienew);
1296 		} else {
1297 			ns_stats_increment(client->sctx->nsstats,
1298 					   ns_statscounter_cookiebadsize);
1299 		}
1300 		return;
1301 	}
1302 
1303 	/*
1304 	 * Process all of the incoming buffer.
1305 	 */
1306 	old = isc_buffer_current(buf);
1307 	memmove(client->cookie, old, 8);
1308 	isc_buffer_forward(buf, 8);
1309 	nonce = isc_buffer_getuint32(buf);
1310 	when = isc_buffer_getuint32(buf);
1311 	isc_buffer_forward(buf, 8);
1312 
1313 	/*
1314 	 * Allow for a 5 minute clock skew between servers sharing a secret.
1315 	 * Only accept COOKIE if we have talked to the client in the last hour.
1316 	 */
1317 	isc_stdtime_get(&now);
1318 	if (isc_serial_gt(when, (now + 300)) || /* In the future. */
1319 	    isc_serial_lt(when, (now - 3600)))
1320 	{ /* In the past. */
1321 		ns_stats_increment(client->sctx->nsstats,
1322 				   ns_statscounter_cookiebadtime);
1323 		return;
1324 	}
1325 
1326 	isc_buffer_init(&db, dbuf, sizeof(dbuf));
1327 	compute_cookie(client, when, nonce, client->sctx->secret, &db);
1328 
1329 	if (isc_safe_memequal(old, dbuf, COOKIE_SIZE)) {
1330 		ns_stats_increment(client->sctx->nsstats,
1331 				   ns_statscounter_cookiematch);
1332 		client->attributes |= NS_CLIENTATTR_HAVECOOKIE;
1333 		return;
1334 	}
1335 
1336 	for (altsecret = ISC_LIST_HEAD(client->sctx->altsecrets);
1337 	     altsecret != NULL; altsecret = ISC_LIST_NEXT(altsecret, link))
1338 	{
1339 		isc_buffer_init(&db, dbuf, sizeof(dbuf));
1340 		compute_cookie(client, when, nonce, altsecret->secret, &db);
1341 		if (isc_safe_memequal(old, dbuf, COOKIE_SIZE)) {
1342 			ns_stats_increment(client->sctx->nsstats,
1343 					   ns_statscounter_cookiematch);
1344 			client->attributes |= NS_CLIENTATTR_HAVECOOKIE;
1345 			return;
1346 		}
1347 	}
1348 
1349 	ns_stats_increment(client->sctx->nsstats,
1350 			   ns_statscounter_cookienomatch);
1351 }
1352 
1353 static isc_result_t
1354 process_ecs(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
1355 	uint16_t family;
1356 	uint8_t addrlen, addrbytes, scope, *paddr;
1357 	isc_netaddr_t caddr;
1358 
1359 	/*
1360 	 * If we have already seen a ECS option skip this ECS option.
1361 	 */
1362 	if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
1363 		isc_buffer_forward(buf, (unsigned int)optlen);
1364 		return (ISC_R_SUCCESS);
1365 	}
1366 
1367 	/*
1368 	 * XXXMUKS: Is there any need to repeat these checks here
1369 	 * (except query's scope length) when they are done in the OPT
1370 	 * RDATA fromwire code?
1371 	 */
1372 
1373 	if (optlen < 4U) {
1374 		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1375 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1376 			      "EDNS client-subnet option too short");
1377 		return (DNS_R_FORMERR);
1378 	}
1379 
1380 	family = isc_buffer_getuint16(buf);
1381 	addrlen = isc_buffer_getuint8(buf);
1382 	scope = isc_buffer_getuint8(buf);
1383 	optlen -= 4;
1384 
1385 	if (scope != 0U) {
1386 		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1387 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1388 			      "EDNS client-subnet option: invalid scope");
1389 		return (DNS_R_OPTERR);
1390 	}
1391 
1392 	memset(&caddr, 0, sizeof(caddr));
1393 	switch (family) {
1394 	case 0:
1395 		/*
1396 		 * XXXMUKS: In queries, if FAMILY is set to 0, SOURCE
1397 		 * PREFIX-LENGTH must be 0 and ADDRESS should not be
1398 		 * present as the address and prefix lengths don't make
1399 		 * sense because the family is unknown.
1400 		 */
1401 		if (addrlen != 0U) {
1402 			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1403 				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1404 				      "EDNS client-subnet option: invalid "
1405 				      "address length (%u) for FAMILY=0",
1406 				      addrlen);
1407 			return (DNS_R_OPTERR);
1408 		}
1409 		caddr.family = AF_UNSPEC;
1410 		break;
1411 	case 1:
1412 		if (addrlen > 32U) {
1413 			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1414 				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1415 				      "EDNS client-subnet option: invalid "
1416 				      "address length (%u) for IPv4",
1417 				      addrlen);
1418 			return (DNS_R_OPTERR);
1419 		}
1420 		caddr.family = AF_INET;
1421 		break;
1422 	case 2:
1423 		if (addrlen > 128U) {
1424 			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1425 				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1426 				      "EDNS client-subnet option: invalid "
1427 				      "address length (%u) for IPv6",
1428 				      addrlen);
1429 			return (DNS_R_OPTERR);
1430 		}
1431 		caddr.family = AF_INET6;
1432 		break;
1433 	default:
1434 		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1435 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1436 			      "EDNS client-subnet option: invalid family");
1437 		return (DNS_R_OPTERR);
1438 	}
1439 
1440 	addrbytes = (addrlen + 7) / 8;
1441 	if (isc_buffer_remaininglength(buf) < addrbytes) {
1442 		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1443 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1444 			      "EDNS client-subnet option: address too short");
1445 		return (DNS_R_OPTERR);
1446 	}
1447 
1448 	paddr = (uint8_t *)&caddr.type;
1449 	if (addrbytes != 0U) {
1450 		memmove(paddr, isc_buffer_current(buf), addrbytes);
1451 		isc_buffer_forward(buf, addrbytes);
1452 		optlen -= addrbytes;
1453 
1454 		if ((addrlen % 8) != 0) {
1455 			uint8_t bits = ~0U << (8 - (addrlen % 8));
1456 			bits &= paddr[addrbytes - 1];
1457 			if (bits != paddr[addrbytes - 1]) {
1458 				return (DNS_R_OPTERR);
1459 			}
1460 		}
1461 	}
1462 
1463 	memmove(&client->ecs.addr, &caddr, sizeof(caddr));
1464 	client->ecs.source = addrlen;
1465 	client->ecs.scope = 0;
1466 	client->attributes |= NS_CLIENTATTR_HAVEECS;
1467 
1468 	isc_buffer_forward(buf, (unsigned int)optlen);
1469 	return (ISC_R_SUCCESS);
1470 }
1471 
1472 static isc_result_t
1473 process_keytag(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
1474 	if (optlen == 0 || (optlen % 2) != 0) {
1475 		isc_buffer_forward(buf, (unsigned int)optlen);
1476 		return (DNS_R_OPTERR);
1477 	}
1478 
1479 	/* Silently drop additional keytag options. */
1480 	if (client->keytag != NULL) {
1481 		isc_buffer_forward(buf, (unsigned int)optlen);
1482 		return (ISC_R_SUCCESS);
1483 	}
1484 
1485 	client->keytag = isc_mem_get(client->mctx, optlen);
1486 	{
1487 		client->keytag_len = (uint16_t)optlen;
1488 		memmove(client->keytag, isc_buffer_current(buf), optlen);
1489 	}
1490 	isc_buffer_forward(buf, (unsigned int)optlen);
1491 	return (ISC_R_SUCCESS);
1492 }
1493 
1494 static isc_result_t
1495 process_opt(ns_client_t *client, dns_rdataset_t *opt) {
1496 	dns_rdata_t rdata;
1497 	isc_buffer_t optbuf;
1498 	isc_result_t result;
1499 	uint16_t optcode;
1500 	uint16_t optlen;
1501 
1502 	/*
1503 	 * Set the client's UDP buffer size.
1504 	 */
1505 	client->udpsize = opt->rdclass;
1506 
1507 	/*
1508 	 * If the requested UDP buffer size is less than 512,
1509 	 * ignore it and use 512.
1510 	 */
1511 	if (client->udpsize < 512) {
1512 		client->udpsize = 512;
1513 	}
1514 
1515 	/*
1516 	 * Get the flags out of the OPT record.
1517 	 */
1518 	client->extflags = (uint16_t)(opt->ttl & 0xFFFF);
1519 
1520 	/*
1521 	 * Do we understand this version of EDNS?
1522 	 *
1523 	 * XXXRTH need library support for this!
1524 	 */
1525 	client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1526 	if (client->ednsversion > DNS_EDNS_VERSION) {
1527 		ns_stats_increment(client->sctx->nsstats,
1528 				   ns_statscounter_badednsver);
1529 		result = ns_client_addopt(client, client->message,
1530 					  &client->opt);
1531 		if (result == ISC_R_SUCCESS) {
1532 			result = DNS_R_BADVERS;
1533 		}
1534 		ns_client_error(client, result);
1535 		return (result);
1536 	}
1537 
1538 	/* Check for NSID request */
1539 	result = dns_rdataset_first(opt);
1540 	if (result == ISC_R_SUCCESS) {
1541 		dns_rdata_init(&rdata);
1542 		dns_rdataset_current(opt, &rdata);
1543 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
1544 		isc_buffer_add(&optbuf, rdata.length);
1545 		while (isc_buffer_remaininglength(&optbuf) >= 4) {
1546 			optcode = isc_buffer_getuint16(&optbuf);
1547 			optlen = isc_buffer_getuint16(&optbuf);
1548 			switch (optcode) {
1549 			case DNS_OPT_NSID:
1550 				if (!WANTNSID(client)) {
1551 					ns_stats_increment(
1552 						client->sctx->nsstats,
1553 						ns_statscounter_nsidopt);
1554 				}
1555 				client->attributes |= NS_CLIENTATTR_WANTNSID;
1556 				isc_buffer_forward(&optbuf, optlen);
1557 				break;
1558 			case DNS_OPT_COOKIE:
1559 				process_cookie(client, &optbuf, optlen);
1560 				break;
1561 			case DNS_OPT_EXPIRE:
1562 				if (!WANTEXPIRE(client)) {
1563 					ns_stats_increment(
1564 						client->sctx->nsstats,
1565 						ns_statscounter_expireopt);
1566 				}
1567 				client->attributes |= NS_CLIENTATTR_WANTEXPIRE;
1568 				isc_buffer_forward(&optbuf, optlen);
1569 				break;
1570 			case DNS_OPT_CLIENT_SUBNET:
1571 				result = process_ecs(client, &optbuf, optlen);
1572 				if (result != ISC_R_SUCCESS) {
1573 					ns_client_error(client, result);
1574 					return (result);
1575 				}
1576 				ns_stats_increment(client->sctx->nsstats,
1577 						   ns_statscounter_ecsopt);
1578 				break;
1579 			case DNS_OPT_TCP_KEEPALIVE:
1580 				if (!USEKEEPALIVE(client)) {
1581 					ns_stats_increment(
1582 						client->sctx->nsstats,
1583 						ns_statscounter_keepaliveopt);
1584 				}
1585 				client->attributes |=
1586 					NS_CLIENTATTR_USEKEEPALIVE;
1587 				isc_nmhandle_keepalive(client->handle, true);
1588 				isc_buffer_forward(&optbuf, optlen);
1589 				break;
1590 			case DNS_OPT_PAD:
1591 				client->attributes |= NS_CLIENTATTR_WANTPAD;
1592 				ns_stats_increment(client->sctx->nsstats,
1593 						   ns_statscounter_padopt);
1594 				isc_buffer_forward(&optbuf, optlen);
1595 				break;
1596 			case DNS_OPT_KEY_TAG:
1597 				result = process_keytag(client, &optbuf,
1598 							optlen);
1599 				if (result != ISC_R_SUCCESS) {
1600 					ns_client_error(client, result);
1601 					return (result);
1602 				}
1603 				ns_stats_increment(client->sctx->nsstats,
1604 						   ns_statscounter_keytagopt);
1605 				break;
1606 			default:
1607 				ns_stats_increment(client->sctx->nsstats,
1608 						   ns_statscounter_otheropt);
1609 				isc_buffer_forward(&optbuf, optlen);
1610 				break;
1611 			}
1612 		}
1613 	}
1614 
1615 	ns_stats_increment(client->sctx->nsstats, ns_statscounter_edns0in);
1616 	client->attributes |= NS_CLIENTATTR_WANTOPT;
1617 
1618 	return (result);
1619 }
1620 
1621 void
1622 ns__client_reset_cb(void *client0) {
1623 	ns_client_t *client = client0;
1624 
1625 	ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1626 		      ISC_LOG_DEBUG(3), "reset client");
1627 
1628 	/*
1629 	 * We never started processing this client, possible if we're
1630 	 * shutting down, just exit.
1631 	 */
1632 	if (client->state == NS_CLIENTSTATE_READY) {
1633 		return;
1634 	}
1635 
1636 	ns_client_endrequest(client);
1637 	if (client->tcpbuf != NULL) {
1638 		isc_mem_put(client->manager->send_mctx, client->tcpbuf,
1639 			    client->tcpbuf_size);
1640 	}
1641 
1642 	if (client->keytag != NULL) {
1643 		isc_mem_put(client->mctx, client->keytag, client->keytag_len);
1644 		client->keytag_len = 0;
1645 	}
1646 
1647 	client->state = NS_CLIENTSTATE_READY;
1648 	INSIST(client->recursionquota == NULL);
1649 
1650 #ifdef WANT_SINGLETRACE
1651 	isc_log_setforcelog(false);
1652 #endif /* WANT_SINGLETRACE */
1653 }
1654 
1655 void
1656 ns__client_put_cb(void *client0) {
1657 	ns_client_t *client = client0;
1658 
1659 	ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1660 		      ISC_LOG_DEBUG(3), "freeing client");
1661 
1662 	/*
1663 	 * Call this first because it requires a valid client.
1664 	 */
1665 	ns_query_free(client);
1666 
1667 	client->magic = 0;
1668 	client->shuttingdown = true;
1669 
1670 	isc_mem_put(client->manager->send_mctx, client->sendbuf,
1671 		    NS_CLIENT_SEND_BUFFER_SIZE);
1672 	if (client->opt != NULL) {
1673 		INSIST(dns_rdataset_isassociated(client->opt));
1674 		dns_rdataset_disassociate(client->opt);
1675 		dns_message_puttemprdataset(client->message, &client->opt);
1676 	}
1677 	client_extendederror_reset(client);
1678 
1679 	dns_message_detach(&client->message);
1680 
1681 	ns_clientmgr_detach(&client->manager);
1682 
1683 	/*
1684 	 * Detaching the task must be done after unlinking from
1685 	 * the manager's lists because the manager accesses
1686 	 * client->task.
1687 	 */
1688 	if (client->task != NULL) {
1689 		isc_task_detach(&client->task);
1690 	}
1691 
1692 	/*
1693 	 * Destroy the fetchlock mutex that was created in
1694 	 * ns_query_init().
1695 	 */
1696 	isc_mutex_destroy(&client->query.fetchlock);
1697 
1698 	if (client->sctx != NULL) {
1699 		ns_server_detach(&client->sctx);
1700 	}
1701 
1702 	isc_mem_detach(&client->mctx);
1703 }
1704 
1705 /*
1706  * Handle an incoming request event from the socket (UDP case)
1707  * or tcpmsg (TCP case).
1708  */
1709 void
1710 ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
1711 		   isc_region_t *region, void *arg) {
1712 	ns_client_t *client = NULL;
1713 	isc_result_t result;
1714 	isc_result_t sigresult = ISC_R_SUCCESS;
1715 	isc_buffer_t *buffer = NULL;
1716 	isc_buffer_t tbuffer;
1717 	dns_rdataset_t *opt = NULL;
1718 	const dns_name_t *signame = NULL;
1719 	bool ra; /* Recursion available. */
1720 	isc_netaddr_t netaddr;
1721 	int match;
1722 	dns_messageid_t id;
1723 	unsigned int flags;
1724 	bool notimp;
1725 	size_t reqsize;
1726 	dns_aclenv_t *env = NULL;
1727 #ifdef HAVE_DNSTAP
1728 	dns_dtmsgtype_t dtmsgtype;
1729 #endif /* ifdef HAVE_DNSTAP */
1730 	static const char *ra_reasons[] = {
1731 		"ACLs not processed yet",
1732 		"no resolver in view",
1733 		"recursion not enabled for view",
1734 		"allow-recursion did not match",
1735 		"allow-query-cache did not match",
1736 		"allow-recursion-on did not match",
1737 		"allow-query-cache-on did not match",
1738 	};
1739 	enum refusal_reasons {
1740 		INVALID,
1741 		NO_RESOLVER,
1742 		RECURSION_DISABLED,
1743 		ALLOW_RECURSION,
1744 		ALLOW_QUERY_CACHE,
1745 		ALLOW_RECURSION_ON,
1746 		ALLOW_QUERY_CACHE_ON
1747 	} ra_refusal_reason = INVALID;
1748 
1749 	if (eresult != ISC_R_SUCCESS) {
1750 		return;
1751 	}
1752 
1753 	client = isc_nmhandle_getdata(handle);
1754 	if (client == NULL) {
1755 		ns_interface_t *ifp = (ns_interface_t *)arg;
1756 		ns_clientmgr_t *clientmgr =
1757 			ns_interfacemgr_getclientmgr(ifp->mgr);
1758 
1759 		INSIST(VALID_MANAGER(clientmgr));
1760 
1761 		client = isc_nmhandle_getextra(handle);
1762 
1763 		result = ns__client_setup(client, clientmgr, true);
1764 		if (result != ISC_R_SUCCESS) {
1765 			return;
1766 		}
1767 
1768 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1769 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1770 			      "allocate new client");
1771 	} else {
1772 		result = ns__client_setup(client, NULL, false);
1773 		if (result != ISC_R_SUCCESS) {
1774 			return;
1775 		}
1776 	}
1777 
1778 	client->state = NS_CLIENTSTATE_READY;
1779 
1780 	if (client->handle == NULL) {
1781 		isc_nmhandle_setdata(handle, client, ns__client_reset_cb,
1782 				     ns__client_put_cb);
1783 		client->handle = handle;
1784 	}
1785 
1786 	if (isc_nmhandle_is_stream(handle)) {
1787 		client->attributes |= NS_CLIENTATTR_TCP;
1788 	}
1789 
1790 	INSIST(client->recursionquota == NULL);
1791 
1792 	INSIST(client->state == NS_CLIENTSTATE_READY);
1793 
1794 	(void)atomic_fetch_add_relaxed(&ns_client_requests, 1);
1795 
1796 	isc_buffer_init(&tbuffer, region->base, region->length);
1797 	isc_buffer_add(&tbuffer, region->length);
1798 	buffer = &tbuffer;
1799 
1800 	client->peeraddr = isc_nmhandle_peeraddr(handle);
1801 	client->peeraddr_valid = true;
1802 
1803 	reqsize = isc_buffer_usedlength(buffer);
1804 
1805 	client->state = NS_CLIENTSTATE_WORKING;
1806 
1807 	TIME_NOW(&client->requesttime);
1808 	client->tnow = client->requesttime;
1809 	client->now = isc_time_seconds(&client->tnow);
1810 
1811 	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1812 
1813 #if NS_CLIENT_DROPPORT
1814 	if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1815 	    DROPPORT_REQUEST)
1816 	{
1817 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1818 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1819 			      "dropped request: suspicious port");
1820 		isc_nm_bad_request(handle);
1821 		return;
1822 	}
1823 #endif /* if NS_CLIENT_DROPPORT */
1824 
1825 	env = client->manager->aclenv;
1826 	if (client->sctx->blackholeacl != NULL &&
1827 	    (dns_acl_match(&netaddr, NULL, client->sctx->blackholeacl, env,
1828 			   &match, NULL) == ISC_R_SUCCESS) &&
1829 	    match > 0)
1830 	{
1831 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1832 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1833 			      "dropped request: blackholed peer");
1834 		isc_nm_bad_request(handle);
1835 		return;
1836 	}
1837 
1838 	ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
1839 		      ISC_LOG_DEBUG(3), "%s request",
1840 		      TCP_CLIENT(client) ? "TCP" : "UDP");
1841 
1842 	result = dns_message_peekheader(buffer, &id, &flags);
1843 	if (result != ISC_R_SUCCESS) {
1844 		/*
1845 		 * There isn't enough header to determine whether
1846 		 * this was a request or a response.  Drop it.
1847 		 */
1848 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1849 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1850 			      "dropped request: invalid message header");
1851 		isc_nm_bad_request(handle);
1852 		return;
1853 	}
1854 
1855 #ifdef WANT_SINGLETRACE
1856 	if (id == 0) {
1857 		isc_log_setforcelog(true);
1858 	}
1859 #endif /* WANT_SINGLETRACE */
1860 
1861 	/*
1862 	 * The client object handles requests, not responses.
1863 	 * If this is a UDP response, forward it to the dispatcher.
1864 	 * If it's a TCP response, discard it here.
1865 	 */
1866 	if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1867 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1868 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1869 			      "dropped request: unexpected response");
1870 		isc_nm_bad_request(handle);
1871 		return;
1872 	}
1873 
1874 	/*
1875 	 * Update some statistics counters.  Don't count responses.
1876 	 */
1877 	if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
1878 		ns_stats_increment(client->sctx->nsstats,
1879 				   ns_statscounter_requestv4);
1880 	} else {
1881 		ns_stats_increment(client->sctx->nsstats,
1882 				   ns_statscounter_requestv6);
1883 	}
1884 	if (TCP_CLIENT(client)) {
1885 		ns_stats_increment(client->sctx->nsstats,
1886 				   ns_statscounter_requesttcp);
1887 		switch (isc_sockaddr_pf(&client->peeraddr)) {
1888 		case AF_INET:
1889 			isc_stats_increment(client->sctx->tcpinstats4,
1890 					    ISC_MIN((int)reqsize / 16, 18));
1891 			break;
1892 		case AF_INET6:
1893 			isc_stats_increment(client->sctx->tcpinstats6,
1894 					    ISC_MIN((int)reqsize / 16, 18));
1895 			break;
1896 		default:
1897 			UNREACHABLE();
1898 		}
1899 	} else {
1900 		switch (isc_sockaddr_pf(&client->peeraddr)) {
1901 		case AF_INET:
1902 			isc_stats_increment(client->sctx->udpinstats4,
1903 					    ISC_MIN((int)reqsize / 16, 18));
1904 			break;
1905 		case AF_INET6:
1906 			isc_stats_increment(client->sctx->udpinstats6,
1907 					    ISC_MIN((int)reqsize / 16, 18));
1908 			break;
1909 		default:
1910 			UNREACHABLE();
1911 		}
1912 	}
1913 
1914 	/*
1915 	 * It's a request.  Parse it.
1916 	 */
1917 	result = dns_message_parse(client->message, buffer, 0);
1918 	if (result != ISC_R_SUCCESS) {
1919 		/*
1920 		 * Parsing the request failed.  Send a response
1921 		 * (typically FORMERR or SERVFAIL).
1922 		 */
1923 		if (result == DNS_R_OPTERR) {
1924 			(void)ns_client_addopt(client, client->message,
1925 					       &client->opt);
1926 		}
1927 
1928 		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1929 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1930 			      "message parsing failed: %s",
1931 			      isc_result_totext(result));
1932 		if (result == ISC_R_NOSPACE || result == DNS_R_BADTSIG) {
1933 			result = DNS_R_FORMERR;
1934 		}
1935 		ns_client_error(client, result);
1936 		return;
1937 	}
1938 
1939 	/*
1940 	 * Disable pipelined TCP query processing if necessary.
1941 	 */
1942 	if (TCP_CLIENT(client) &&
1943 	    (client->message->opcode != dns_opcode_query ||
1944 	     (client->sctx->keepresporder != NULL &&
1945 	      dns_acl_allowed(&netaddr, NULL, client->sctx->keepresporder,
1946 			      env))))
1947 	{
1948 		isc_nm_sequential(handle);
1949 	}
1950 
1951 	dns_opcodestats_increment(client->sctx->opcodestats,
1952 				  client->message->opcode);
1953 	switch (client->message->opcode) {
1954 	case dns_opcode_query:
1955 	case dns_opcode_update:
1956 	case dns_opcode_notify:
1957 		notimp = false;
1958 		break;
1959 	case dns_opcode_iquery:
1960 	default:
1961 		notimp = true;
1962 		break;
1963 	}
1964 
1965 	client->message->rcode = dns_rcode_noerror;
1966 	client->ede = NULL;
1967 
1968 	/*
1969 	 * Deal with EDNS.
1970 	 */
1971 	if ((client->sctx->options & NS_SERVER_NOEDNS) != 0) {
1972 		opt = NULL;
1973 	} else {
1974 		opt = dns_message_getopt(client->message);
1975 	}
1976 
1977 	client->ecs.source = 0;
1978 	client->ecs.scope = 0;
1979 
1980 	if (opt != NULL) {
1981 		/*
1982 		 * Are returning FORMERR to all EDNS queries?
1983 		 * Simulate a STD13 compliant server.
1984 		 */
1985 		if ((client->sctx->options & NS_SERVER_EDNSFORMERR) != 0) {
1986 			ns_client_error(client, DNS_R_FORMERR);
1987 			return;
1988 		}
1989 
1990 		/*
1991 		 * Are returning NOTIMP to all EDNS queries?
1992 		 */
1993 		if ((client->sctx->options & NS_SERVER_EDNSNOTIMP) != 0) {
1994 			ns_client_error(client, DNS_R_NOTIMP);
1995 			return;
1996 		}
1997 
1998 		/*
1999 		 * Are returning REFUSED to all EDNS queries?
2000 		 */
2001 		if ((client->sctx->options & NS_SERVER_EDNSREFUSED) != 0) {
2002 			ns_client_error(client, DNS_R_REFUSED);
2003 			return;
2004 		}
2005 
2006 		/*
2007 		 * Are we dropping all EDNS queries?
2008 		 */
2009 		if ((client->sctx->options & NS_SERVER_DROPEDNS) != 0) {
2010 			ns_client_drop(client, ISC_R_SUCCESS);
2011 			return;
2012 		}
2013 
2014 		result = process_opt(client, opt);
2015 		if (result != ISC_R_SUCCESS) {
2016 			return;
2017 		}
2018 	}
2019 
2020 	if (client->message->rdclass == 0) {
2021 		if ((client->attributes & NS_CLIENTATTR_WANTCOOKIE) != 0 &&
2022 		    client->message->opcode == dns_opcode_query &&
2023 		    client->message->counts[DNS_SECTION_QUESTION] == 0U)
2024 		{
2025 			result = dns_message_reply(client->message, true);
2026 			if (result != ISC_R_SUCCESS) {
2027 				ns_client_error(client, result);
2028 				return;
2029 			}
2030 
2031 			if (notimp) {
2032 				client->message->rcode = dns_rcode_notimp;
2033 			}
2034 
2035 			ns_client_send(client);
2036 			return;
2037 		}
2038 
2039 		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2040 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2041 			      "message class could not be determined");
2042 		ns_client_dumpmessage(client, "message class could not be "
2043 					      "determined");
2044 		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
2045 		return;
2046 	}
2047 
2048 	client->destsockaddr = isc_nmhandle_localaddr(handle);
2049 	isc_netaddr_fromsockaddr(&client->destaddr, &client->destsockaddr);
2050 
2051 	result = client->sctx->matchingview(&netaddr, &client->destaddr,
2052 					    client->message, env, &sigresult,
2053 					    &client->view);
2054 	if (result != ISC_R_SUCCESS) {
2055 		char classname[DNS_RDATACLASS_FORMATSIZE];
2056 
2057 		/*
2058 		 * Do a dummy TSIG verification attempt so that the
2059 		 * response will have a TSIG if the query did, as
2060 		 * required by RFC2845.
2061 		 */
2062 		isc_buffer_t b;
2063 		isc_region_t *r;
2064 
2065 		dns_message_resetsig(client->message);
2066 
2067 		r = dns_message_getrawmessage(client->message);
2068 		isc_buffer_init(&b, r->base, r->length);
2069 		isc_buffer_add(&b, r->length);
2070 		(void)dns_tsig_verify(&b, client->message, NULL, NULL);
2071 
2072 		dns_rdataclass_format(client->message->rdclass, classname,
2073 				      sizeof(classname));
2074 		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2075 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2076 			      "no matching view in class '%s'", classname);
2077 		ns_client_dumpmessage(client, "no matching view in class");
2078 		ns_client_extendederror(client, DNS_EDE_PROHIBITED, NULL);
2079 		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
2080 		return;
2081 	}
2082 
2083 	ns_client_log(client, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
2084 		      ISC_LOG_DEBUG(5), "using view '%s'", client->view->name);
2085 
2086 	/*
2087 	 * Check for a signature.  We log bad signatures regardless of
2088 	 * whether they ultimately cause the request to be rejected or
2089 	 * not.  We do not log the lack of a signature unless we are
2090 	 * debugging.
2091 	 */
2092 	client->signer = NULL;
2093 	dns_name_init(&client->signername, NULL);
2094 	result = dns_message_signer(client->message, &client->signername);
2095 	if (result != ISC_R_NOTFOUND) {
2096 		signame = NULL;
2097 		if (dns_message_gettsig(client->message, &signame) != NULL) {
2098 			ns_stats_increment(client->sctx->nsstats,
2099 					   ns_statscounter_tsigin);
2100 		} else {
2101 			ns_stats_increment(client->sctx->nsstats,
2102 					   ns_statscounter_sig0in);
2103 		}
2104 	}
2105 	if (result == ISC_R_SUCCESS) {
2106 		char namebuf[DNS_NAME_FORMATSIZE];
2107 		dns_name_format(&client->signername, namebuf, sizeof(namebuf));
2108 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2109 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2110 			      "request has valid signature: %s", namebuf);
2111 		client->signer = &client->signername;
2112 	} else if (result == ISC_R_NOTFOUND) {
2113 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2114 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2115 			      "request is not signed");
2116 	} else if (result == DNS_R_NOIDENTITY) {
2117 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2118 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2119 			      "request is signed by a nonauthoritative key");
2120 	} else {
2121 		char tsigrcode[64];
2122 		isc_buffer_t b;
2123 		dns_rcode_t status;
2124 		isc_result_t tresult;
2125 
2126 		/* There is a signature, but it is bad. */
2127 		ns_stats_increment(client->sctx->nsstats,
2128 				   ns_statscounter_invalidsig);
2129 		signame = NULL;
2130 		if (dns_message_gettsig(client->message, &signame) != NULL) {
2131 			char namebuf[DNS_NAME_FORMATSIZE];
2132 			char cnamebuf[DNS_NAME_FORMATSIZE];
2133 			dns_name_format(signame, namebuf, sizeof(namebuf));
2134 			status = client->message->tsigstatus;
2135 			isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
2136 			tresult = dns_tsigrcode_totext(status, &b);
2137 			INSIST(tresult == ISC_R_SUCCESS);
2138 			tsigrcode[isc_buffer_usedlength(&b)] = '\0';
2139 			if (client->message->tsigkey->generated) {
2140 				dns_name_format(
2141 					client->message->tsigkey->creator,
2142 					cnamebuf, sizeof(cnamebuf));
2143 				ns_client_log(
2144 					client, DNS_LOGCATEGORY_SECURITY,
2145 					NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
2146 					"request has invalid signature: "
2147 					"TSIG %s (%s): %s (%s)",
2148 					namebuf, cnamebuf,
2149 					isc_result_totext(result), tsigrcode);
2150 			} else {
2151 				ns_client_log(
2152 					client, DNS_LOGCATEGORY_SECURITY,
2153 					NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
2154 					"request has invalid signature: "
2155 					"TSIG %s: %s (%s)",
2156 					namebuf, isc_result_totext(result),
2157 					tsigrcode);
2158 			}
2159 		} else {
2160 			status = client->message->sig0status;
2161 			isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
2162 			tresult = dns_tsigrcode_totext(status, &b);
2163 			INSIST(tresult == ISC_R_SUCCESS);
2164 			tsigrcode[isc_buffer_usedlength(&b)] = '\0';
2165 			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2166 				      NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
2167 				      "request has invalid signature: %s (%s)",
2168 				      isc_result_totext(result), tsigrcode);
2169 		}
2170 
2171 		/*
2172 		 * Accept update messages signed by unknown keys so that
2173 		 * update forwarding works transparently through slaves
2174 		 * that don't have all the same keys as the primary.
2175 		 */
2176 		if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
2177 		      client->message->opcode == dns_opcode_update))
2178 		{
2179 			ns_client_error(client, sigresult);
2180 			return;
2181 		}
2182 	}
2183 
2184 	/*
2185 	 * Decide whether recursive service is available to this client.
2186 	 * We do this here rather than in the query code so that we can
2187 	 * set the RA bit correctly on all kinds of responses, not just
2188 	 * responses to ordinary queries.  Note if you can't query the
2189 	 * cache there is no point in setting RA.
2190 	 */
2191 	ra = false;
2192 
2193 	/* must be initialized before ns_client_log uses it as index */
2194 	if (client->view->resolver == NULL) {
2195 		ra_refusal_reason = NO_RESOLVER;
2196 	} else if (!client->view->recursion) {
2197 		ra_refusal_reason = RECURSION_DISABLED;
2198 	} else if (ns_client_checkaclsilent(client, NULL,
2199 					    client->view->recursionacl,
2200 					    true) != ISC_R_SUCCESS)
2201 	{
2202 		ra_refusal_reason = ALLOW_RECURSION;
2203 	} else if (ns_client_checkaclsilent(client, NULL,
2204 					    client->view->cacheacl,
2205 					    true) != ISC_R_SUCCESS)
2206 	{
2207 		ra_refusal_reason = ALLOW_QUERY_CACHE;
2208 	} else if (ns_client_checkaclsilent(client, &client->destaddr,
2209 					    client->view->recursiononacl,
2210 					    true) != ISC_R_SUCCESS)
2211 	{
2212 		ra_refusal_reason = ALLOW_RECURSION_ON;
2213 	} else if (ns_client_checkaclsilent(client, &client->destaddr,
2214 					    client->view->cacheonacl,
2215 					    true) != ISC_R_SUCCESS)
2216 	{
2217 		ra_refusal_reason = ALLOW_QUERY_CACHE_ON;
2218 	} else {
2219 		ra = true;
2220 		client->attributes |= NS_CLIENTATTR_RA;
2221 	}
2222 
2223 	ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
2224 		      ISC_LOG_DEBUG(3),
2225 		      ra ? "recursion available"
2226 			 : "recursion not available (%s)",
2227 		      ra_reasons[ra_refusal_reason]);
2228 
2229 	/*
2230 	 * Adjust maximum UDP response size for this client.
2231 	 */
2232 	if (client->udpsize > 512) {
2233 		dns_peer_t *peer = NULL;
2234 		uint16_t udpsize = client->view->maxudp;
2235 		(void)dns_peerlist_peerbyaddr(client->view->peers, &netaddr,
2236 					      &peer);
2237 		if (peer != NULL) {
2238 			dns_peer_getmaxudp(peer, &udpsize);
2239 		}
2240 		if (client->udpsize > udpsize) {
2241 			client->udpsize = udpsize;
2242 		}
2243 	}
2244 
2245 	/*
2246 	 * Dispatch the request.
2247 	 */
2248 	switch (client->message->opcode) {
2249 	case dns_opcode_query:
2250 		CTRACE("query");
2251 #ifdef HAVE_DNSTAP
2252 		if (ra && (client->message->flags & DNS_MESSAGEFLAG_RD) != 0) {
2253 			dtmsgtype = DNS_DTTYPE_CQ;
2254 		} else {
2255 			dtmsgtype = DNS_DTTYPE_AQ;
2256 		}
2257 
2258 		dns_dt_send(client->view, dtmsgtype, &client->peeraddr,
2259 			    &client->destsockaddr, TCP_CLIENT(client), NULL,
2260 			    &client->requesttime, NULL, buffer);
2261 #endif /* HAVE_DNSTAP */
2262 
2263 		ns_query_start(client, handle);
2264 		break;
2265 	case dns_opcode_update:
2266 		CTRACE("update");
2267 #ifdef HAVE_DNSTAP
2268 		dns_dt_send(client->view, DNS_DTTYPE_UQ, &client->peeraddr,
2269 			    &client->destsockaddr, TCP_CLIENT(client), NULL,
2270 			    &client->requesttime, NULL, buffer);
2271 #endif /* HAVE_DNSTAP */
2272 		ns_client_settimeout(client, 60);
2273 		ns_update_start(client, handle, sigresult);
2274 		break;
2275 	case dns_opcode_notify:
2276 		CTRACE("notify");
2277 		ns_client_settimeout(client, 60);
2278 		ns_notify_start(client, handle);
2279 		break;
2280 	case dns_opcode_iquery:
2281 		CTRACE("iquery");
2282 		ns_client_error(client, DNS_R_NOTIMP);
2283 		break;
2284 	default:
2285 		CTRACE("unknown opcode");
2286 		ns_client_error(client, DNS_R_NOTIMP);
2287 	}
2288 }
2289 
2290 isc_result_t
2291 ns__client_tcpconn(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
2292 	ns_interface_t *ifp = (ns_interface_t *)arg;
2293 	dns_aclenv_t *env = ns_interfacemgr_getaclenv(ifp->mgr);
2294 	ns_server_t *sctx = ns_interfacemgr_getserver(ifp->mgr);
2295 	unsigned int tcpquota;
2296 	isc_sockaddr_t peeraddr;
2297 	isc_netaddr_t netaddr;
2298 	int match;
2299 
2300 	if (result != ISC_R_SUCCESS) {
2301 		return (result);
2302 	}
2303 
2304 	if (handle != NULL) {
2305 		peeraddr = isc_nmhandle_peeraddr(handle);
2306 		isc_netaddr_fromsockaddr(&netaddr, &peeraddr);
2307 
2308 		if (sctx->blackholeacl != NULL &&
2309 		    (dns_acl_match(&netaddr, NULL, sctx->blackholeacl, env,
2310 				   &match, NULL) == ISC_R_SUCCESS) &&
2311 		    match > 0)
2312 		{
2313 			return (ISC_R_CONNREFUSED);
2314 		}
2315 	}
2316 
2317 	tcpquota = isc_quota_getused(&sctx->tcpquota);
2318 	ns_stats_update_if_greater(sctx->nsstats, ns_statscounter_tcphighwater,
2319 				   tcpquota);
2320 
2321 	return (ISC_R_SUCCESS);
2322 }
2323 
2324 isc_result_t
2325 ns__client_setup(ns_client_t *client, ns_clientmgr_t *mgr, bool new) {
2326 	isc_result_t result;
2327 
2328 	/*
2329 	 * Note: creating a client does not add the client to the
2330 	 * manager's client list, the caller is responsible for that.
2331 	 */
2332 
2333 	if (new) {
2334 		REQUIRE(VALID_MANAGER(mgr));
2335 		REQUIRE(client != NULL);
2336 		REQUIRE(mgr->tid == isc_nm_tid());
2337 
2338 		*client = (ns_client_t){ .magic = 0, .tid = mgr->tid };
2339 
2340 		isc_mem_attach(mgr->mctx, &client->mctx);
2341 		clientmgr_attach(mgr, &client->manager);
2342 		ns_server_attach(mgr->sctx, &client->sctx);
2343 		isc_task_attach(mgr->task, &client->task);
2344 
2345 		dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
2346 				   &client->message);
2347 
2348 		client->sendbuf = isc_mem_get(client->manager->send_mctx,
2349 					      NS_CLIENT_SEND_BUFFER_SIZE);
2350 		/*
2351 		 * Set magic earlier than usual because ns_query_init()
2352 		 * and the functions it calls will require it.
2353 		 */
2354 		client->magic = NS_CLIENT_MAGIC;
2355 		result = ns_query_init(client);
2356 		if (result != ISC_R_SUCCESS) {
2357 			goto cleanup;
2358 		}
2359 	} else {
2360 		REQUIRE(NS_CLIENT_VALID(client));
2361 		REQUIRE(client->tid == isc_nm_tid());
2362 
2363 		ns_clientmgr_t *oldmgr = client->manager;
2364 		ns_server_t *sctx = client->sctx;
2365 		isc_task_t *task = client->task;
2366 		unsigned char *sendbuf = client->sendbuf;
2367 		dns_message_t *message = client->message;
2368 		isc_mem_t *oldmctx = client->mctx;
2369 		ns_query_t query = client->query;
2370 		int tid = client->tid;
2371 
2372 		/*
2373 		 * Retain these values from the existing client, but
2374 		 * zero every thing else.
2375 		 */
2376 		*client = (ns_client_t){ .magic = 0,
2377 					 .mctx = oldmctx,
2378 					 .manager = oldmgr,
2379 					 .sctx = sctx,
2380 					 .task = task,
2381 					 .sendbuf = sendbuf,
2382 					 .message = message,
2383 					 .query = query,
2384 					 .tid = tid };
2385 	}
2386 
2387 	client->query.attributes &= ~NS_QUERYATTR_ANSWERED;
2388 	client->state = NS_CLIENTSTATE_INACTIVE;
2389 	client->udpsize = 512;
2390 	client->ednsversion = -1;
2391 	dns_name_init(&client->signername, NULL);
2392 	dns_ecs_init(&client->ecs);
2393 	isc_sockaddr_any(&client->formerrcache.addr);
2394 	client->formerrcache.time = 0;
2395 	client->formerrcache.id = 0;
2396 	ISC_LINK_INIT(client, rlink);
2397 	client->rcode_override = -1; /* not set */
2398 
2399 	client->magic = NS_CLIENT_MAGIC;
2400 
2401 	CTRACE("client_setup");
2402 
2403 	return (ISC_R_SUCCESS);
2404 
2405 cleanup:
2406 	isc_mem_put(client->manager->send_mctx, client->sendbuf,
2407 		    NS_CLIENT_SEND_BUFFER_SIZE);
2408 	dns_message_detach(&client->message);
2409 	isc_task_detach(&client->task);
2410 	ns_clientmgr_detach(&client->manager);
2411 	isc_mem_detach(&client->mctx);
2412 	ns_server_detach(&client->sctx);
2413 
2414 	return (result);
2415 }
2416 
2417 bool
2418 ns_client_shuttingdown(ns_client_t *client) {
2419 	return (client->shuttingdown);
2420 }
2421 
2422 /***
2423  *** Client Manager
2424  ***/
2425 
2426 static void
2427 clientmgr_attach(ns_clientmgr_t *source, ns_clientmgr_t **targetp) {
2428 	int32_t oldrefs;
2429 
2430 	REQUIRE(VALID_MANAGER(source));
2431 	REQUIRE(targetp != NULL && *targetp == NULL);
2432 
2433 	oldrefs = isc_refcount_increment0(&source->references);
2434 	isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
2435 		      ISC_LOG_DEBUG(3), "clientmgr @%p attach: %d", source,
2436 		      oldrefs + 1);
2437 
2438 	*targetp = source;
2439 }
2440 
2441 void
2442 ns_clientmgr_detach(ns_clientmgr_t **mp) {
2443 	int32_t oldrefs;
2444 	ns_clientmgr_t *mgr = *mp;
2445 	*mp = NULL;
2446 
2447 	oldrefs = isc_refcount_decrement(&mgr->references);
2448 	isc_log_write(ns_lctx, NS_LOGCATEGORY_CLIENT, NS_LOGMODULE_CLIENT,
2449 		      ISC_LOG_DEBUG(3), "clientmgr @%p detach: %d", mgr,
2450 		      oldrefs - 1);
2451 	if (oldrefs == 1) {
2452 		clientmgr_destroy(mgr);
2453 	}
2454 }
2455 
2456 static void
2457 clientmgr_destroy(ns_clientmgr_t *manager) {
2458 	MTRACE("clientmgr_destroy");
2459 
2460 	isc_refcount_destroy(&manager->references);
2461 	manager->magic = 0;
2462 
2463 	dns_aclenv_detach(&manager->aclenv);
2464 
2465 	isc_mutex_destroy(&manager->reclock);
2466 
2467 	isc_task_detach(&manager->task);
2468 	ns_server_detach(&manager->sctx);
2469 
2470 	isc_mem_detach(&manager->send_mctx);
2471 
2472 	isc_mem_putanddetach(&manager->mctx, manager, sizeof(*manager));
2473 }
2474 
2475 isc_result_t
2476 ns_clientmgr_create(ns_server_t *sctx, isc_taskmgr_t *taskmgr,
2477 		    isc_timermgr_t *timermgr, dns_aclenv_t *aclenv, int tid,
2478 		    ns_clientmgr_t **managerp) {
2479 	ns_clientmgr_t *manager = NULL;
2480 	isc_mem_t *mctx = NULL;
2481 	isc_result_t result;
2482 
2483 	isc_mem_create(&mctx);
2484 	isc_mem_setname(mctx, "clientmgr");
2485 
2486 	manager = isc_mem_get(mctx, sizeof(*manager));
2487 	*manager = (ns_clientmgr_t){ .magic = 0, .mctx = mctx };
2488 
2489 	isc_mutex_init(&manager->reclock);
2490 
2491 	manager->taskmgr = taskmgr;
2492 	manager->timermgr = timermgr;
2493 	manager->tid = tid;
2494 
2495 	dns_aclenv_attach(aclenv, &manager->aclenv);
2496 
2497 	result = isc_task_create_bound(manager->taskmgr, 20, &manager->task,
2498 				       manager->tid);
2499 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
2500 	isc_task_setname(manager->task, "clientmgr", NULL);
2501 
2502 	isc_refcount_init(&manager->references, 1);
2503 	manager->sctx = NULL;
2504 	ns_server_attach(sctx, &manager->sctx);
2505 
2506 	ISC_LIST_INIT(manager->recursing);
2507 
2508 	/*
2509 	 * We create specialised per-worker memory context specifically
2510 	 * dedicated and tuned for allocating send buffers as it is a very
2511 	 * common operation. Not doing so may result in excessive memory
2512 	 * use in certain workloads.
2513 	 *
2514 	 * Please see this thread for more details:
2515 	 *
2516 	 * https://github.com/jemalloc/jemalloc/issues/2483
2517 	 *
2518 	 * In particular, this information from the jemalloc developers is
2519 	 * of the most interest:
2520 	 *
2521 	 * https://github.com/jemalloc/jemalloc/issues/2483#issuecomment-1639019699
2522 	 * https://github.com/jemalloc/jemalloc/issues/2483#issuecomment-1698173849
2523 	 *
2524 	 * In essence, we use the following memory management strategy:
2525 	 *
2526 	 * 1. We use a per-worker memory arena for send buffers memory
2527 	 * allocation to reduce lock contention (In reality, we create a
2528 	 * per-client manager arena, but we have one client manager per
2529 	 * worker).
2530 	 *
2531 	 * 2. The automatically created arenas settings remain unchanged
2532 	 * and may be controlled by users (e.g. by setting the
2533 	 * "MALLOC_CONF" variable).
2534 	 *
2535 	 * 3. We attune the arenas to not use dirty pages cache as the
2536 	 * cache would have a poor reuse rate, and that is known to
2537 	 * significantly contribute to excessive memory use.
2538 	 *
2539 	 * 4. There is no strict need for the dirty cache, as there is a
2540 	 * per arena bin for each allocation size, so because we initially
2541 	 * allocate strictly 64K per send buffer (enough for a DNS
2542 	 * message), allocations would get directed to one bin (an "object
2543 	 * pool" or a "slab") maintained within an arena. That is, there
2544 	 * is an object pool already, specifically to optimise for the
2545 	 * case of frequent allocations of objects of the given size. The
2546 	 * object pool should suffice our needs, as we will end up
2547 	 * recycling the objects from there without the need to back it by
2548 	 * an additional layer of dirty pages cache. The dirty pages cache
2549 	 * would have worked better in the case when there are more
2550 	 * allocation bins involved due to a higher reuse rate (the case
2551 	 * of a more "generic" memory management).
2552 	 */
2553 	isc_mem_create_arena(&manager->send_mctx);
2554 	isc_mem_setname(manager->send_mctx, "sendbufs");
2555 	(void)isc_mem_arena_set_dirty_decay_ms(manager->send_mctx, 0);
2556 	/*
2557 	 * Disable muzzy pages cache too, as versions < 5.2.0 have it
2558 	 * enabled by default. The muzzy pages cache goes right below the
2559 	 * dirty pages cache and backs it.
2560 	 */
2561 	(void)isc_mem_arena_set_muzzy_decay_ms(manager->send_mctx, 0);
2562 
2563 	manager->magic = MANAGER_MAGIC;
2564 
2565 	MTRACE("create");
2566 
2567 	*managerp = manager;
2568 
2569 	return (ISC_R_SUCCESS);
2570 }
2571 
2572 void
2573 ns_clientmgr_shutdown(ns_clientmgr_t *manager) {
2574 	ns_client_t *client;
2575 
2576 	REQUIRE(VALID_MANAGER(manager));
2577 
2578 	MTRACE("destroy");
2579 
2580 	LOCK(&manager->reclock);
2581 	for (client = ISC_LIST_HEAD(manager->recursing); client != NULL;
2582 	     client = ISC_LIST_NEXT(client, rlink))
2583 	{
2584 		ns_query_cancel(client);
2585 	}
2586 	UNLOCK(&manager->reclock);
2587 }
2588 
2589 isc_sockaddr_t *
2590 ns_client_getsockaddr(ns_client_t *client) {
2591 	return (&client->peeraddr);
2592 }
2593 
2594 isc_sockaddr_t *
2595 ns_client_getdestaddr(ns_client_t *client) {
2596 	return (&client->destsockaddr);
2597 }
2598 
2599 isc_result_t
2600 ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
2601 			 dns_acl_t *acl, bool default_allow) {
2602 	isc_result_t result;
2603 	dns_aclenv_t *env = client->manager->aclenv;
2604 	isc_netaddr_t tmpnetaddr;
2605 	int match;
2606 	isc_sockaddr_t local;
2607 
2608 	if (acl == NULL) {
2609 		if (default_allow) {
2610 			goto allow;
2611 		} else {
2612 			goto deny;
2613 		}
2614 	}
2615 
2616 	if (netaddr == NULL) {
2617 		isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
2618 		netaddr = &tmpnetaddr;
2619 	}
2620 
2621 	local = isc_nmhandle_localaddr(client->handle);
2622 	result = dns_acl_match_port_transport(
2623 		netaddr, isc_sockaddr_getport(&local),
2624 		isc_nm_socket_type(client->handle),
2625 		isc_nm_has_encryption(client->handle), client->signer, acl, env,
2626 		&match, NULL);
2627 
2628 	if (result != ISC_R_SUCCESS) {
2629 		goto deny; /* Internal error, already logged. */
2630 	}
2631 
2632 	if (match > 0) {
2633 		goto allow;
2634 	}
2635 	goto deny; /* Negative match or no match. */
2636 
2637 allow:
2638 	return (ISC_R_SUCCESS);
2639 
2640 deny:
2641 	return (DNS_R_REFUSED);
2642 }
2643 
2644 isc_result_t
2645 ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
2646 		   const char *opname, dns_acl_t *acl, bool default_allow,
2647 		   int log_level) {
2648 	isc_result_t result;
2649 	isc_netaddr_t netaddr;
2650 
2651 	if (sockaddr != NULL) {
2652 		isc_netaddr_fromsockaddr(&netaddr, sockaddr);
2653 	}
2654 
2655 	result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
2656 					  acl, default_allow);
2657 
2658 	if (result == ISC_R_SUCCESS) {
2659 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2660 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2661 			      "%s approved", opname);
2662 	} else {
2663 		ns_client_extendederror(client, DNS_EDE_PROHIBITED, NULL);
2664 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2665 			      NS_LOGMODULE_CLIENT, log_level, "%s denied",
2666 			      opname);
2667 	}
2668 	return (result);
2669 }
2670 
2671 static void
2672 ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2673 	if (client->peeraddr_valid) {
2674 		isc_sockaddr_format(&client->peeraddr, peerbuf,
2675 				    (unsigned int)len);
2676 	} else {
2677 		snprintf(peerbuf, len, "@%p", client);
2678 	}
2679 }
2680 
2681 void
2682 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2683 	       isc_logmodule_t *module, int level, const char *fmt,
2684 	       va_list ap) {
2685 	char msgbuf[4096];
2686 	char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE];
2687 	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2688 	const char *viewname = "";
2689 	const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = "";
2690 	const char *signer = "", *qname = "";
2691 	dns_name_t *q = NULL;
2692 
2693 	REQUIRE(client != NULL);
2694 
2695 	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2696 
2697 	if (client->signer != NULL) {
2698 		dns_name_format(client->signer, signerbuf, sizeof(signerbuf));
2699 		sep1 = "/key ";
2700 		signer = signerbuf;
2701 	}
2702 
2703 	q = client->query.origqname != NULL ? client->query.origqname
2704 					    : client->query.qname;
2705 	if (q != NULL) {
2706 		dns_name_format(q, qnamebuf, sizeof(qnamebuf));
2707 		sep2 = " (";
2708 		sep3 = ")";
2709 		qname = qnamebuf;
2710 	}
2711 
2712 	if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2713 	    strcmp(client->view->name, "_default") != 0)
2714 	{
2715 		sep4 = ": view ";
2716 		viewname = client->view->name;
2717 	}
2718 
2719 	if (client->peeraddr_valid) {
2720 		isc_sockaddr_format(&client->peeraddr, peerbuf,
2721 				    sizeof(peerbuf));
2722 	} else {
2723 		snprintf(peerbuf, sizeof(peerbuf), "(no-peer)");
2724 	}
2725 
2726 	isc_log_write(ns_lctx, category, module, level,
2727 		      "client @%p %s%s%s%s%s%s%s%s: %s", client, peerbuf, sep1,
2728 		      signer, sep2, qname, sep3, sep4, viewname, msgbuf);
2729 }
2730 
2731 void
2732 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2733 	      isc_logmodule_t *module, int level, const char *fmt, ...) {
2734 	va_list ap;
2735 
2736 	if (!isc_log_wouldlog(ns_lctx, level)) {
2737 		return;
2738 	}
2739 
2740 	va_start(ap, fmt);
2741 	ns_client_logv(client, category, module, level, fmt, ap);
2742 	va_end(ap);
2743 }
2744 
2745 void
2746 ns_client_aclmsg(const char *msg, const dns_name_t *name, dns_rdatatype_t type,
2747 		 dns_rdataclass_t rdclass, char *buf, size_t len) {
2748 	char namebuf[DNS_NAME_FORMATSIZE];
2749 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2750 	char classbuf[DNS_RDATACLASS_FORMATSIZE];
2751 
2752 	dns_name_format(name, namebuf, sizeof(namebuf));
2753 	dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2754 	dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2755 	(void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2756 		       classbuf);
2757 }
2758 
2759 static void
2760 ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2761 	isc_buffer_t buffer;
2762 	char *buf = NULL;
2763 	int len = 1024;
2764 	isc_result_t result;
2765 
2766 	if (!isc_log_wouldlog(ns_lctx, ISC_LOG_DEBUG(1))) {
2767 		return;
2768 	}
2769 
2770 	/*
2771 	 * Note that these are multiline debug messages.  We want a newline
2772 	 * to appear in the log after each message.
2773 	 */
2774 
2775 	do {
2776 		buf = isc_mem_get(client->mctx, len);
2777 		isc_buffer_init(&buffer, buf, len);
2778 		result = dns_message_totext(
2779 			client->message, &dns_master_style_debug, 0, &buffer);
2780 		if (result == ISC_R_NOSPACE) {
2781 			isc_mem_put(client->mctx, buf, len);
2782 			len += 1024;
2783 		} else if (result == ISC_R_SUCCESS) {
2784 			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2785 				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2786 				      "%s\n%.*s", reason,
2787 				      (int)isc_buffer_usedlength(&buffer), buf);
2788 		}
2789 	} while (result == ISC_R_NOSPACE);
2790 
2791 	if (buf != NULL) {
2792 		isc_mem_put(client->mctx, buf, len);
2793 	}
2794 }
2795 
2796 void
2797 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2798 	ns_client_t *client;
2799 	char namebuf[DNS_NAME_FORMATSIZE];
2800 	char original[DNS_NAME_FORMATSIZE];
2801 	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2802 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2803 	char classbuf[DNS_RDATACLASS_FORMATSIZE];
2804 	const char *name;
2805 	const char *sep;
2806 	const char *origfor;
2807 	dns_rdataset_t *rdataset;
2808 
2809 	REQUIRE(VALID_MANAGER(manager));
2810 
2811 	LOCK(&manager->reclock);
2812 	client = ISC_LIST_HEAD(manager->recursing);
2813 	while (client != NULL) {
2814 		INSIST(client->state == NS_CLIENTSTATE_RECURSING);
2815 
2816 		ns_client_name(client, peerbuf, sizeof(peerbuf));
2817 		if (client->view != NULL &&
2818 		    strcmp(client->view->name, "_bind") != 0 &&
2819 		    strcmp(client->view->name, "_default") != 0)
2820 		{
2821 			name = client->view->name;
2822 			sep = ": view ";
2823 		} else {
2824 			name = "";
2825 			sep = "";
2826 		}
2827 
2828 		LOCK(&client->query.fetchlock);
2829 		INSIST(client->query.qname != NULL);
2830 		dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2831 		if (client->query.qname != client->query.origqname &&
2832 		    client->query.origqname != NULL)
2833 		{
2834 			origfor = " for ";
2835 			dns_name_format(client->query.origqname, original,
2836 					sizeof(original));
2837 		} else {
2838 			origfor = "";
2839 			original[0] = '\0';
2840 		}
2841 		rdataset = ISC_LIST_HEAD(client->query.qname->list);
2842 		if (rdataset == NULL && client->query.origqname != NULL) {
2843 			rdataset = ISC_LIST_HEAD(client->query.origqname->list);
2844 		}
2845 		if (rdataset != NULL) {
2846 			dns_rdatatype_format(rdataset->type, typebuf,
2847 					     sizeof(typebuf));
2848 			dns_rdataclass_format(rdataset->rdclass, classbuf,
2849 					      sizeof(classbuf));
2850 		} else {
2851 			strlcpy(typebuf, "-", sizeof(typebuf));
2852 			strlcpy(classbuf, "-", sizeof(classbuf));
2853 		}
2854 		UNLOCK(&client->query.fetchlock);
2855 		fprintf(f,
2856 			"; client %s%s%s: id %u '%s/%s/%s'%s%s "
2857 			"requesttime %u\n",
2858 			peerbuf, sep, name, client->message->id, namebuf,
2859 			typebuf, classbuf, origfor, original,
2860 			isc_time_seconds(&client->requesttime));
2861 		client = ISC_LIST_NEXT(client, rlink);
2862 	}
2863 	UNLOCK(&manager->reclock);
2864 }
2865 
2866 void
2867 ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2868 	LOCK(&client->query.fetchlock);
2869 	if (client->query.restarts > 0) {
2870 		/*
2871 		 * client->query.qname was dynamically allocated.
2872 		 */
2873 		dns_message_puttempname(client->message, &client->query.qname);
2874 	}
2875 	client->query.qname = name;
2876 	client->query.attributes &= ~NS_QUERYATTR_REDIRECT;
2877 	UNLOCK(&client->query.fetchlock);
2878 }
2879 
2880 isc_result_t
2881 ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) {
2882 	ns_client_t *client = (ns_client_t *)ci->data;
2883 
2884 	REQUIRE(NS_CLIENT_VALID(client));
2885 	REQUIRE(addrp != NULL);
2886 
2887 	*addrp = &client->peeraddr;
2888 	return (ISC_R_SUCCESS);
2889 }
2890 
2891 dns_rdataset_t *
2892 ns_client_newrdataset(ns_client_t *client) {
2893 	dns_rdataset_t *rdataset;
2894 	isc_result_t result;
2895 
2896 	REQUIRE(NS_CLIENT_VALID(client));
2897 
2898 	rdataset = NULL;
2899 	result = dns_message_gettemprdataset(client->message, &rdataset);
2900 	if (result != ISC_R_SUCCESS) {
2901 		return (NULL);
2902 	}
2903 
2904 	return (rdataset);
2905 }
2906 
2907 void
2908 ns_client_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
2909 	dns_rdataset_t *rdataset;
2910 
2911 	REQUIRE(NS_CLIENT_VALID(client));
2912 	REQUIRE(rdatasetp != NULL);
2913 
2914 	rdataset = *rdatasetp;
2915 
2916 	if (rdataset != NULL) {
2917 		if (dns_rdataset_isassociated(rdataset)) {
2918 			dns_rdataset_disassociate(rdataset);
2919 		}
2920 		dns_message_puttemprdataset(client->message, rdatasetp);
2921 	}
2922 }
2923 
2924 isc_result_t
2925 ns_client_newnamebuf(ns_client_t *client) {
2926 	isc_buffer_t *dbuf = NULL;
2927 
2928 	CTRACE("ns_client_newnamebuf");
2929 
2930 	isc_buffer_allocate(client->mctx, &dbuf, 1024);
2931 	ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
2932 
2933 	CTRACE("ns_client_newnamebuf: done");
2934 	return (ISC_R_SUCCESS);
2935 }
2936 
2937 dns_name_t *
2938 ns_client_newname(ns_client_t *client, isc_buffer_t *dbuf, isc_buffer_t *nbuf) {
2939 	dns_name_t *name = NULL;
2940 	isc_region_t r;
2941 	isc_result_t result;
2942 
2943 	REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
2944 
2945 	CTRACE("ns_client_newname");
2946 
2947 	result = dns_message_gettempname(client->message, &name);
2948 	if (result != ISC_R_SUCCESS) {
2949 		CTRACE("ns_client_newname: "
2950 		       "dns_message_gettempname failed: done");
2951 		return (NULL);
2952 	}
2953 	isc_buffer_availableregion(dbuf, &r);
2954 	isc_buffer_init(nbuf, r.base, r.length);
2955 	dns_name_setbuffer(name, NULL);
2956 	dns_name_setbuffer(name, nbuf);
2957 	client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
2958 
2959 	CTRACE("ns_client_newname: done");
2960 	return (name);
2961 }
2962 
2963 isc_buffer_t *
2964 ns_client_getnamebuf(ns_client_t *client) {
2965 	isc_buffer_t *dbuf;
2966 	isc_region_t r;
2967 
2968 	CTRACE("ns_client_getnamebuf");
2969 
2970 	/*%
2971 	 * Return a name buffer with space for a maximal name, allocating
2972 	 * a new one if necessary.
2973 	 */
2974 	if (ISC_LIST_EMPTY(client->query.namebufs)) {
2975 		ns_client_newnamebuf(client);
2976 	}
2977 
2978 	dbuf = ISC_LIST_TAIL(client->query.namebufs);
2979 	INSIST(dbuf != NULL);
2980 	isc_buffer_availableregion(dbuf, &r);
2981 	if (r.length < DNS_NAME_MAXWIRE) {
2982 		ns_client_newnamebuf(client);
2983 		dbuf = ISC_LIST_TAIL(client->query.namebufs);
2984 		isc_buffer_availableregion(dbuf, &r);
2985 		INSIST(r.length >= 255);
2986 	}
2987 	CTRACE("ns_client_getnamebuf: done");
2988 	return (dbuf);
2989 }
2990 
2991 void
2992 ns_client_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
2993 	isc_region_t r;
2994 
2995 	CTRACE("ns_client_keepname");
2996 
2997 	/*%
2998 	 * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
2999 	 * adjusted to take account of that.  We do the adjustment.
3000 	 */
3001 	REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0);
3002 
3003 	dns_name_toregion(name, &r);
3004 	isc_buffer_add(dbuf, r.length);
3005 	dns_name_setbuffer(name, NULL);
3006 	client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
3007 }
3008 
3009 void
3010 ns_client_releasename(ns_client_t *client, dns_name_t **namep) {
3011 	/*%
3012 	 * 'name' is no longer needed.  Return it to our pool of temporary
3013 	 * names.  If it is using a name buffer, relinquish its exclusive
3014 	 * rights on the buffer.
3015 	 */
3016 
3017 	CTRACE("ns_client_releasename");
3018 	client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
3019 	dns_message_puttempname(client->message, namep);
3020 	CTRACE("ns_client_releasename: done");
3021 }
3022 
3023 isc_result_t
3024 ns_client_newdbversion(ns_client_t *client, unsigned int n) {
3025 	unsigned int i;
3026 	ns_dbversion_t *dbversion = NULL;
3027 
3028 	for (i = 0; i < n; i++) {
3029 		dbversion = isc_mem_get(client->mctx, sizeof(*dbversion));
3030 		*dbversion = (ns_dbversion_t){ 0 };
3031 		ISC_LIST_INITANDAPPEND(client->query.freeversions, dbversion,
3032 				       link);
3033 	}
3034 
3035 	return (ISC_R_SUCCESS);
3036 }
3037 
3038 static ns_dbversion_t *
3039 client_getdbversion(ns_client_t *client) {
3040 	ns_dbversion_t *dbversion = NULL;
3041 
3042 	if (ISC_LIST_EMPTY(client->query.freeversions)) {
3043 		ns_client_newdbversion(client, 1);
3044 	}
3045 	dbversion = ISC_LIST_HEAD(client->query.freeversions);
3046 	INSIST(dbversion != NULL);
3047 	ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);
3048 
3049 	return (dbversion);
3050 }
3051 
3052 ns_dbversion_t *
3053 ns_client_findversion(ns_client_t *client, dns_db_t *db) {
3054 	ns_dbversion_t *dbversion;
3055 
3056 	for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
3057 	     dbversion != NULL; dbversion = ISC_LIST_NEXT(dbversion, link))
3058 	{
3059 		if (dbversion->db == db) {
3060 			break;
3061 		}
3062 	}
3063 
3064 	if (dbversion == NULL) {
3065 		/*
3066 		 * This is a new zone for this query.  Add it to
3067 		 * the active list.
3068 		 */
3069 		dbversion = client_getdbversion(client);
3070 		if (dbversion == NULL) {
3071 			return (NULL);
3072 		}
3073 		dns_db_attach(db, &dbversion->db);
3074 		dns_db_currentversion(db, &dbversion->version);
3075 		dbversion->acl_checked = false;
3076 		dbversion->queryok = false;
3077 		ISC_LIST_APPEND(client->query.activeversions, dbversion, link);
3078 	}
3079 
3080 	return (dbversion);
3081 }
3082