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