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