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