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