client.c revision 234010
1/*
2 * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003  Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id: client.c,v 1.271.10.4 2012/01/31 23:46:39 tbox Exp $ */
19
20#include <config.h>
21
22#include <isc/formatcheck.h>
23#include <isc/mutex.h>
24#include <isc/once.h>
25#include <isc/platform.h>
26#include <isc/print.h>
27#include <isc/stats.h>
28#include <isc/stdio.h>
29#include <isc/string.h>
30#include <isc/task.h>
31#include <isc/timer.h>
32#include <isc/util.h>
33
34#include <dns/db.h>
35#include <dns/dispatch.h>
36#include <dns/events.h>
37#include <dns/message.h>
38#include <dns/peer.h>
39#include <dns/rcode.h>
40#include <dns/rdata.h>
41#include <dns/rdataclass.h>
42#include <dns/rdatalist.h>
43#include <dns/rdataset.h>
44#include <dns/resolver.h>
45#include <dns/stats.h>
46#include <dns/tsig.h>
47#include <dns/view.h>
48#include <dns/zone.h>
49
50#include <named/interfacemgr.h>
51#include <named/log.h>
52#include <named/notify.h>
53#include <named/os.h>
54#include <named/server.h>
55#include <named/update.h>
56
57/***
58 *** Client
59 ***/
60
61/*! \file
62 * Client Routines
63 *
64 * Important note!
65 *
66 * All client state changes, other than that from idle to listening, occur
67 * as a result of events.  This guarantees serialization and avoids the
68 * need for locking.
69 *
70 * If a routine is ever created that allows someone other than the client's
71 * task to change the client, then the client will have to be locked.
72 */
73
74#define NS_CLIENT_TRACE
75#ifdef NS_CLIENT_TRACE
76#define CTRACE(m)	ns_client_log(client, \
77				      NS_LOGCATEGORY_CLIENT, \
78				      NS_LOGMODULE_CLIENT, \
79				      ISC_LOG_DEBUG(3), \
80				      "%s", (m))
81#define MTRACE(m)	isc_log_write(ns_g_lctx, \
82				      NS_LOGCATEGORY_GENERAL, \
83				      NS_LOGMODULE_CLIENT, \
84				      ISC_LOG_DEBUG(3), \
85				      "clientmgr @%p: %s", manager, (m))
86#else
87#define CTRACE(m)	((void)(m))
88#define MTRACE(m)	((void)(m))
89#endif
90
91#define TCP_CLIENT(c)	(((c)->attributes & NS_CLIENTATTR_TCP) != 0)
92
93#define TCP_BUFFER_SIZE			(65535 + 2)
94#define SEND_BUFFER_SIZE		4096
95#define RECV_BUFFER_SIZE		4096
96
97#ifdef ISC_PLATFORM_USETHREADS
98#define NMCTXS				100
99/*%<
100 * Number of 'mctx pools' for clients. (Should this be configurable?)
101 * When enabling threads, we use a pool of memory contexts shared by
102 * client objects, since concurrent access to a shared context would cause
103 * heavy contentions.  The above constant is expected to be enough for
104 * completely avoiding contentions among threads for an authoritative-only
105 * server.
106 */
107#else
108#define NMCTXS				0
109/*%<
110 * If named with built without thread, simply share manager's context.  Using
111 * a separate context in this case would simply waste memory.
112 */
113#endif
114
115/*% nameserver client manager structure */
116struct ns_clientmgr {
117	/* Unlocked. */
118	unsigned int			magic;
119	isc_mem_t *			mctx;
120	isc_taskmgr_t *			taskmgr;
121	isc_timermgr_t *		timermgr;
122	isc_mutex_t			lock;
123	/* Locked by lock. */
124	isc_boolean_t			exiting;
125	client_list_t			active;		/*%< Active clients */
126	client_list_t			recursing;	/*%< Recursing clients */
127	client_list_t			inactive;	/*%< To be recycled */
128#if NMCTXS > 0
129	/*%< mctx pool for clients. */
130	unsigned int			nextmctx;
131	isc_mem_t *			mctxpool[NMCTXS];
132#endif
133};
134
135#define MANAGER_MAGIC			ISC_MAGIC('N', 'S', 'C', 'm')
136#define VALID_MANAGER(m)		ISC_MAGIC_VALID(m, MANAGER_MAGIC)
137
138/*!
139 * Client object states.  Ordering is significant: higher-numbered
140 * states are generally "more active", meaning that the client can
141 * have more dynamically allocated data, outstanding events, etc.
142 * In the list below, any such properties listed for state N
143 * also apply to any state > N.
144 *
145 * To force the client into a less active state, set client->newstate
146 * to that state and call exit_check().  This will cause any
147 * activities defined for higher-numbered states to be aborted.
148 */
149
150#define NS_CLIENTSTATE_FREED    0
151/*%<
152 * The client object no longer exists.
153 */
154
155#define NS_CLIENTSTATE_INACTIVE 1
156/*%<
157 * The client object exists and has a task and timer.
158 * Its "query" struct and sendbuf are initialized.
159 * It is on the client manager's list of inactive clients.
160 * It has a message and OPT, both in the reset state.
161 */
162
163#define NS_CLIENTSTATE_READY    2
164/*%<
165 * The client object is either a TCP or a UDP one, and
166 * it is associated with a network interface.  It is on the
167 * client manager's list of active clients.
168 *
169 * If it is a TCP client object, it has a TCP listener socket
170 * and an outstanding TCP listen request.
171 *
172 * If it is a UDP client object, it has a UDP listener socket
173 * and an outstanding UDP receive request.
174 */
175
176#define NS_CLIENTSTATE_READING  3
177/*%<
178 * The client object is a TCP client object that has received
179 * a connection.  It has a tcpsocket, tcpmsg, TCP quota, and an
180 * outstanding TCP read request.  This state is not used for
181 * UDP client objects.
182 */
183
184#define NS_CLIENTSTATE_WORKING  4
185/*%<
186 * The client object has received a request and is working
187 * on it.  It has a view, and it may have any of a non-reset OPT,
188 * recursion quota, and an outstanding write request.
189 */
190
191#define NS_CLIENTSTATE_MAX      9
192/*%<
193 * Sentinel value used to indicate "no state".  When client->newstate
194 * has this value, we are not attempting to exit the current state.
195 * Must be greater than any valid state.
196 */
197
198/*
199 * Enable ns_client_dropport() by default.
200 */
201#ifndef NS_CLIENT_DROPPORT
202#define NS_CLIENT_DROPPORT 1
203#endif
204
205unsigned int ns_client_requests;
206
207static void client_read(ns_client_t *client);
208static void client_accept(ns_client_t *client);
209static void client_udprecv(ns_client_t *client);
210static void clientmgr_destroy(ns_clientmgr_t *manager);
211static isc_boolean_t exit_check(ns_client_t *client);
212static void ns_client_endrequest(ns_client_t *client);
213static void ns_client_checkactive(ns_client_t *client);
214static void client_start(isc_task_t *task, isc_event_t *event);
215static void client_request(isc_task_t *task, isc_event_t *event);
216static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
217
218void
219ns_client_recursing(ns_client_t *client) {
220	REQUIRE(NS_CLIENT_VALID(client));
221
222	LOCK(&client->manager->lock);
223	ISC_LIST_UNLINK(*client->list, client, link);
224	ISC_LIST_APPEND(client->manager->recursing, client, link);
225	client->list = &client->manager->recursing;
226	UNLOCK(&client->manager->lock);
227}
228
229void
230ns_client_killoldestquery(ns_client_t *client) {
231	ns_client_t *oldest;
232	REQUIRE(NS_CLIENT_VALID(client));
233
234	LOCK(&client->manager->lock);
235	oldest = ISC_LIST_HEAD(client->manager->recursing);
236	if (oldest != NULL) {
237		ns_query_cancel(oldest);
238		ISC_LIST_UNLINK(*oldest->list, oldest, link);
239		ISC_LIST_APPEND(client->manager->active, oldest, link);
240		oldest->list = &client->manager->active;
241	}
242	UNLOCK(&client->manager->lock);
243}
244
245void
246ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
247	isc_result_t result;
248	isc_interval_t interval;
249
250	isc_interval_set(&interval, seconds, 0);
251	result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
252				 &interval, ISC_FALSE);
253	client->timerset = ISC_TRUE;
254	if (result != ISC_R_SUCCESS) {
255		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
256			      NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
257			      "setting timeout: %s",
258			      isc_result_totext(result));
259		/* Continue anyway. */
260	}
261}
262
263/*%
264 * Check for a deactivation or shutdown request and take appropriate
265 * action.  Returns ISC_TRUE if either is in progress; in this case
266 * the caller must no longer use the client object as it may have been
267 * freed.
268 */
269static isc_boolean_t
270exit_check(ns_client_t *client) {
271	ns_clientmgr_t *locked_manager = NULL;
272	ns_clientmgr_t *destroy_manager = NULL;
273
274	REQUIRE(NS_CLIENT_VALID(client));
275
276	if (client->state <= client->newstate)
277		return (ISC_FALSE); /* Business as usual. */
278
279	INSIST(client->newstate < NS_CLIENTSTATE_WORKING);
280
281	/*
282	 * We need to detach from the view early when shutting down
283	 * the server to break the following vicious circle:
284	 *
285	 *  - The resolver will not shut down until the view refcount is zero
286	 *  - The view refcount does not go to zero until all clients detach
287	 *  - The client does not detach from the view until references is zero
288	 *  - references does not go to zero until the resolver has shut down
289	 *
290	 * Keep the view attached until any outstanding updates complete.
291	 */
292	if (client->nupdates == 0 &&
293	    client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
294		dns_view_detach(&client->view);
295
296	if (client->state == NS_CLIENTSTATE_WORKING) {
297		INSIST(client->newstate <= NS_CLIENTSTATE_READING);
298		/*
299		 * Let the update processing complete.
300		 */
301		if (client->nupdates > 0)
302			return (ISC_TRUE);
303		/*
304		 * We are trying to abort request processing.
305		 */
306		if (client->nsends > 0) {
307			isc_socket_t *socket;
308			if (TCP_CLIENT(client))
309				socket = client->tcpsocket;
310			else
311				socket = client->udpsocket;
312			isc_socket_cancel(socket, client->task,
313					  ISC_SOCKCANCEL_SEND);
314		}
315
316		if (! (client->nsends == 0 && client->nrecvs == 0 &&
317		       client->references == 0))
318		{
319			/*
320			 * Still waiting for I/O cancel completion.
321			 * or lingering references.
322			 */
323			return (ISC_TRUE);
324		}
325		/*
326		 * I/O cancel is complete.  Burn down all state
327		 * related to the current request.  Ensure that
328		 * the client is on the active list and not the
329		 * recursing list.
330		 */
331		LOCK(&client->manager->lock);
332		if (client->list == &client->manager->recursing) {
333			ISC_LIST_UNLINK(*client->list, client, link);
334			ISC_LIST_APPEND(client->manager->active, client, link);
335			client->list = &client->manager->active;
336		}
337		UNLOCK(&client->manager->lock);
338		ns_client_endrequest(client);
339
340		client->state = NS_CLIENTSTATE_READING;
341		INSIST(client->recursionquota == NULL);
342		if (NS_CLIENTSTATE_READING == client->newstate) {
343			client_read(client);
344			client->newstate = NS_CLIENTSTATE_MAX;
345			return (ISC_TRUE); /* We're done. */
346		}
347	}
348
349	if (client->state == NS_CLIENTSTATE_READING) {
350		/*
351		 * We are trying to abort the current TCP connection,
352		 * if any.
353		 */
354		INSIST(client->recursionquota == NULL);
355		INSIST(client->newstate <= NS_CLIENTSTATE_READY);
356		if (client->nreads > 0)
357			dns_tcpmsg_cancelread(&client->tcpmsg);
358		if (! client->nreads == 0) {
359			/* Still waiting for read cancel completion. */
360			return (ISC_TRUE);
361		}
362
363		if (client->tcpmsg_valid) {
364			dns_tcpmsg_invalidate(&client->tcpmsg);
365			client->tcpmsg_valid = ISC_FALSE;
366		}
367		if (client->tcpsocket != NULL) {
368			CTRACE("closetcp");
369			isc_socket_detach(&client->tcpsocket);
370		}
371
372		if (client->tcpquota != NULL)
373			isc_quota_detach(&client->tcpquota);
374
375		if (client->timerset) {
376			(void)isc_timer_reset(client->timer,
377					      isc_timertype_inactive,
378					      NULL, NULL, ISC_TRUE);
379			client->timerset = ISC_FALSE;
380		}
381
382		client->peeraddr_valid = ISC_FALSE;
383
384		client->state = NS_CLIENTSTATE_READY;
385		INSIST(client->recursionquota == NULL);
386
387		/*
388		 * Now the client is ready to accept a new TCP connection
389		 * or UDP request, but we may have enough clients doing
390		 * that already.  Check whether this client needs to remain
391		 * active and force it to go inactive if not.
392		 */
393		ns_client_checkactive(client);
394
395		if (NS_CLIENTSTATE_READY == client->newstate) {
396			if (TCP_CLIENT(client)) {
397				client_accept(client);
398			} else
399				client_udprecv(client);
400			client->newstate = NS_CLIENTSTATE_MAX;
401			return (ISC_TRUE);
402		}
403	}
404
405	if (client->state == NS_CLIENTSTATE_READY) {
406		INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
407		/*
408		 * We are trying to enter the inactive state.
409		 */
410		if (client->naccepts > 0)
411			isc_socket_cancel(client->tcplistener, client->task,
412					  ISC_SOCKCANCEL_ACCEPT);
413
414		if (! (client->naccepts == 0)) {
415			/* Still waiting for accept cancel completion. */
416			return (ISC_TRUE);
417		}
418		/* Accept cancel is complete. */
419
420		if (client->nrecvs > 0)
421			isc_socket_cancel(client->udpsocket, client->task,
422					  ISC_SOCKCANCEL_RECV);
423		if (! (client->nrecvs == 0)) {
424			/* Still waiting for recv cancel completion. */
425			return (ISC_TRUE);
426		}
427		/* Recv cancel is complete. */
428
429		if (client->nctls > 0) {
430			/* Still waiting for control event to be delivered */
431			return (ISC_TRUE);
432		}
433
434		/* Deactivate the client. */
435		if (client->interface)
436			ns_interface_detach(&client->interface);
437
438		INSIST(client->naccepts == 0);
439		INSIST(client->recursionquota == NULL);
440		if (client->tcplistener != NULL)
441			isc_socket_detach(&client->tcplistener);
442
443		if (client->udpsocket != NULL)
444			isc_socket_detach(&client->udpsocket);
445
446		if (client->dispatch != NULL)
447			dns_dispatch_detach(&client->dispatch);
448
449		client->attributes = 0;
450		client->mortal = ISC_FALSE;
451
452		LOCK(&client->manager->lock);
453		/*
454		 * Put the client on the inactive list.  If we are aiming for
455		 * the "freed" state, it will be removed from the inactive
456		 * list shortly, and we need to keep the manager locked until
457		 * that has been done, lest the manager decide to reactivate
458		 * the dying client inbetween.
459		 */
460		locked_manager = client->manager;
461		ISC_LIST_UNLINK(*client->list, client, link);
462		ISC_LIST_APPEND(client->manager->inactive, client, link);
463		client->list = &client->manager->inactive;
464		client->state = NS_CLIENTSTATE_INACTIVE;
465		INSIST(client->recursionquota == NULL);
466
467		if (client->state == client->newstate) {
468			client->newstate = NS_CLIENTSTATE_MAX;
469			if (client->needshutdown)
470				isc_task_shutdown(client->task);
471			goto unlock;
472		}
473	}
474
475	if (client->state == NS_CLIENTSTATE_INACTIVE) {
476		INSIST(client->newstate == NS_CLIENTSTATE_FREED);
477		/*
478		 * We are trying to free the client.
479		 *
480		 * When "shuttingdown" is true, either the task has received
481		 * its shutdown event or no shutdown event has ever been
482		 * set up.  Thus, we have no outstanding shutdown
483		 * event at this point.
484		 */
485		REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
486
487		INSIST(client->recursionquota == NULL);
488
489		ns_query_free(client);
490		isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
491		isc_event_free((isc_event_t **)&client->sendevent);
492		isc_event_free((isc_event_t **)&client->recvevent);
493		isc_timer_detach(&client->timer);
494
495		if (client->tcpbuf != NULL)
496			isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
497		if (client->opt != NULL) {
498			INSIST(dns_rdataset_isassociated(client->opt));
499			dns_rdataset_disassociate(client->opt);
500			dns_message_puttemprdataset(client->message, &client->opt);
501		}
502		dns_message_destroy(&client->message);
503		if (client->manager != NULL) {
504			ns_clientmgr_t *manager = client->manager;
505			if (locked_manager == NULL) {
506				LOCK(&manager->lock);
507				locked_manager = manager;
508			}
509			ISC_LIST_UNLINK(*client->list, client, link);
510			client->list = NULL;
511			if (manager->exiting &&
512			    ISC_LIST_EMPTY(manager->active) &&
513			    ISC_LIST_EMPTY(manager->inactive) &&
514			    ISC_LIST_EMPTY(manager->recursing))
515				destroy_manager = manager;
516		}
517		/*
518		 * Detaching the task must be done after unlinking from
519		 * the manager's lists because the manager accesses
520		 * client->task.
521		 */
522		if (client->task != NULL)
523			isc_task_detach(&client->task);
524
525		CTRACE("free");
526		client->magic = 0;
527		/*
528		 * Check that there are no other external references to
529		 * the memory context.
530		 */
531		if (ns_g_clienttest && isc_mem_references(client->mctx) != 1) {
532			isc_mem_stats(client->mctx, stderr);
533			INSIST(0);
534		}
535		isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
536
537		goto unlock;
538	}
539
540 unlock:
541	if (locked_manager != NULL) {
542		UNLOCK(&locked_manager->lock);
543		locked_manager = NULL;
544	}
545
546	/*
547	 * Only now is it safe to destroy the client manager (if needed),
548	 * because we have accessed its lock for the last time.
549	 */
550	if (destroy_manager != NULL)
551		clientmgr_destroy(destroy_manager);
552
553	return (ISC_TRUE);
554}
555
556/*%
557 * The client's task has received the client's control event
558 * as part of the startup process.
559 */
560static void
561client_start(isc_task_t *task, isc_event_t *event) {
562	ns_client_t *client = (ns_client_t *) event->ev_arg;
563
564	INSIST(task == client->task);
565
566	UNUSED(task);
567
568	INSIST(client->nctls == 1);
569	client->nctls--;
570
571	if (exit_check(client))
572		return;
573
574	if (TCP_CLIENT(client)) {
575		client_accept(client);
576	} else {
577		client_udprecv(client);
578	}
579}
580
581
582/*%
583 * The client's task has received a shutdown event.
584 */
585static void
586client_shutdown(isc_task_t *task, isc_event_t *event) {
587	ns_client_t *client;
588
589	REQUIRE(event != NULL);
590	REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
591	client = event->ev_arg;
592	REQUIRE(NS_CLIENT_VALID(client));
593	REQUIRE(task == client->task);
594
595	UNUSED(task);
596
597	CTRACE("shutdown");
598
599	isc_event_free(&event);
600
601	if (client->shutdown != NULL) {
602		(client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
603		client->shutdown = NULL;
604		client->shutdown_arg = NULL;
605	}
606
607	client->newstate = NS_CLIENTSTATE_FREED;
608	client->needshutdown = ISC_FALSE;
609	(void)exit_check(client);
610}
611
612static void
613ns_client_endrequest(ns_client_t *client) {
614	INSIST(client->naccepts == 0);
615	INSIST(client->nreads == 0);
616	INSIST(client->nsends == 0);
617	INSIST(client->nrecvs == 0);
618	INSIST(client->nupdates == 0);
619	INSIST(client->state == NS_CLIENTSTATE_WORKING);
620
621	CTRACE("endrequest");
622
623	if (client->next != NULL) {
624		(client->next)(client);
625		client->next = NULL;
626	}
627
628	if (client->view != NULL)
629		dns_view_detach(&client->view);
630	if (client->opt != NULL) {
631		INSIST(dns_rdataset_isassociated(client->opt));
632		dns_rdataset_disassociate(client->opt);
633		dns_message_puttemprdataset(client->message, &client->opt);
634	}
635
636	client->signer = NULL;
637	client->udpsize = 512;
638	client->extflags = 0;
639	client->ednsversion = -1;
640	dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
641
642	if (client->recursionquota != NULL)
643		isc_quota_detach(&client->recursionquota);
644
645	/*
646	 * Clear all client attributes that are specific to
647	 * the request; that's all except the TCP flag.
648	 */
649	client->attributes &= NS_CLIENTATTR_TCP;
650}
651
652static void
653ns_client_checkactive(ns_client_t *client) {
654	if (client->mortal) {
655		/*
656		 * This client object should normally go inactive
657		 * at this point, but if we have fewer active client
658		 * objects than desired due to earlier quota exhaustion,
659		 * keep it active to make up for the shortage.
660		 */
661		isc_boolean_t need_another_client = ISC_FALSE;
662		if (TCP_CLIENT(client) && !ns_g_clienttest) {
663			LOCK(&client->interface->lock);
664			if (client->interface->ntcpcurrent <
665			    client->interface->ntcptarget)
666				need_another_client = ISC_TRUE;
667			UNLOCK(&client->interface->lock);
668		} else {
669			/*
670			 * The UDP client quota is enforced by making
671			 * requests fail rather than by not listening
672			 * for new ones.  Therefore, there is always a
673			 * full set of UDP clients listening.
674			 */
675		}
676		if (! need_another_client) {
677			/*
678			 * We don't need this client object.  Recycle it.
679			 */
680			if (client->newstate >= NS_CLIENTSTATE_INACTIVE)
681				client->newstate = NS_CLIENTSTATE_INACTIVE;
682		}
683	}
684}
685
686void
687ns_client_next(ns_client_t *client, isc_result_t result) {
688	int newstate;
689
690	REQUIRE(NS_CLIENT_VALID(client));
691	REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
692		client->state == NS_CLIENTSTATE_READING);
693
694	CTRACE("next");
695
696	if (result != ISC_R_SUCCESS)
697		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
698			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
699			      "request failed: %s", isc_result_totext(result));
700
701	/*
702	 * An error processing a TCP request may have left
703	 * the connection out of sync.  To be safe, we always
704	 * sever the connection when result != ISC_R_SUCCESS.
705	 */
706	if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
707		newstate = NS_CLIENTSTATE_READING;
708	else
709		newstate = NS_CLIENTSTATE_READY;
710
711	if (client->newstate > newstate)
712		client->newstate = newstate;
713	(void)exit_check(client);
714}
715
716
717static void
718client_senddone(isc_task_t *task, isc_event_t *event) {
719	ns_client_t *client;
720	isc_socketevent_t *sevent = (isc_socketevent_t *) event;
721
722	REQUIRE(sevent != NULL);
723	REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
724	client = sevent->ev_arg;
725	REQUIRE(NS_CLIENT_VALID(client));
726	REQUIRE(task == client->task);
727	REQUIRE(sevent == client->sendevent);
728
729	UNUSED(task);
730
731	CTRACE("senddone");
732
733	if (sevent->result != ISC_R_SUCCESS)
734		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
735			      NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
736			      "error sending response: %s",
737			      isc_result_totext(sevent->result));
738
739	INSIST(client->nsends > 0);
740	client->nsends--;
741
742	if (client->tcpbuf != NULL) {
743		INSIST(TCP_CLIENT(client));
744		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
745		client->tcpbuf = NULL;
746	}
747
748	if (exit_check(client))
749		return;
750
751	ns_client_next(client, ISC_R_SUCCESS);
752}
753
754/*%
755 * We only want to fail with ISC_R_NOSPACE when called from
756 * ns_client_sendraw() and not when called from ns_client_send(),
757 * tcpbuffer is NULL when called from ns_client_sendraw() and
758 * length != 0.  tcpbuffer != NULL when called from ns_client_send()
759 * and length == 0.
760 */
761
762static isc_result_t
763client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
764		    isc_buffer_t *tcpbuffer, isc_uint32_t length,
765		    unsigned char *sendbuf, unsigned char **datap)
766{
767	unsigned char *data;
768	isc_uint32_t bufsize;
769	isc_result_t result;
770
771	INSIST(datap != NULL);
772	INSIST((tcpbuffer == NULL && length != 0) ||
773	       (tcpbuffer != NULL && length == 0));
774
775	if (TCP_CLIENT(client)) {
776		INSIST(client->tcpbuf == NULL);
777		if (length + 2 > TCP_BUFFER_SIZE) {
778			result = ISC_R_NOSPACE;
779			goto done;
780		}
781		client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
782		if (client->tcpbuf == NULL) {
783			result = ISC_R_NOMEMORY;
784			goto done;
785		}
786		data = client->tcpbuf;
787		if (tcpbuffer != NULL) {
788			isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
789			isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
790		} else {
791			isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
792			INSIST(length <= 0xffff);
793			isc_buffer_putuint16(buffer, (isc_uint16_t)length);
794		}
795	} else {
796		data = sendbuf;
797		if (client->udpsize < SEND_BUFFER_SIZE)
798			bufsize = client->udpsize;
799		else
800			bufsize = SEND_BUFFER_SIZE;
801		if (length > bufsize) {
802			result = ISC_R_NOSPACE;
803			goto done;
804		}
805		isc_buffer_init(buffer, data, bufsize);
806	}
807	*datap = data;
808	result = ISC_R_SUCCESS;
809
810 done:
811	return (result);
812}
813
814static isc_result_t
815client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
816	struct in6_pktinfo *pktinfo;
817	isc_result_t result;
818	isc_region_t r;
819	isc_sockaddr_t *address;
820	isc_socket_t *socket;
821	isc_netaddr_t netaddr;
822	int match;
823	unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
824
825	if (TCP_CLIENT(client)) {
826		socket = client->tcpsocket;
827		address = NULL;
828	} else {
829		socket = client->udpsocket;
830		address = &client->peeraddr;
831
832		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
833		if (ns_g_server->blackholeacl != NULL &&
834		    dns_acl_match(&netaddr, NULL,
835				  ns_g_server->blackholeacl,
836				  &ns_g_server->aclenv,
837				  &match, NULL) == ISC_R_SUCCESS &&
838		    match > 0)
839			return (DNS_R_BLACKHOLED);
840		sockflags |= ISC_SOCKFLAG_NORETRY;
841	}
842
843	if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
844	    (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
845		pktinfo = &client->pktinfo;
846	else
847		pktinfo = NULL;
848
849	isc_buffer_usedregion(buffer, &r);
850
851	CTRACE("sendto");
852
853	result = isc_socket_sendto2(socket, &r, client->task,
854				    address, pktinfo,
855				    client->sendevent, sockflags);
856	if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
857		client->nsends++;
858		if (result == ISC_R_SUCCESS)
859			client_senddone(client->task,
860					(isc_event_t *)client->sendevent);
861		result = ISC_R_SUCCESS;
862	}
863	return (result);
864}
865
866void
867ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
868	isc_result_t result;
869	unsigned char *data;
870	isc_buffer_t buffer;
871	isc_region_t r;
872	isc_region_t *mr;
873	unsigned char sendbuf[SEND_BUFFER_SIZE];
874
875	REQUIRE(NS_CLIENT_VALID(client));
876
877	CTRACE("sendraw");
878
879	mr = dns_message_getrawmessage(message);
880	if (mr == NULL) {
881		result = ISC_R_UNEXPECTEDEND;
882		goto done;
883	}
884
885	result = client_allocsendbuf(client, &buffer, NULL, mr->length,
886				     sendbuf, &data);
887	if (result != ISC_R_SUCCESS)
888		goto done;
889
890	/*
891	 * Copy message to buffer and fixup id.
892	 */
893	isc_buffer_availableregion(&buffer, &r);
894	result = isc_buffer_copyregion(&buffer, mr);
895	if (result != ISC_R_SUCCESS)
896		goto done;
897	r.base[0] = (client->message->id >> 8) & 0xff;
898	r.base[1] = client->message->id & 0xff;
899
900	result = client_sendpkg(client, &buffer);
901	if (result == ISC_R_SUCCESS)
902		return;
903
904 done:
905	if (client->tcpbuf != NULL) {
906		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
907		client->tcpbuf = NULL;
908	}
909	ns_client_next(client, result);
910}
911
912void
913ns_client_send(ns_client_t *client) {
914	isc_result_t result;
915	unsigned char *data;
916	isc_buffer_t buffer;
917	isc_buffer_t tcpbuffer;
918	isc_region_t r;
919	dns_compress_t cctx;
920	isc_boolean_t cleanup_cctx = ISC_FALSE;
921	unsigned char sendbuf[SEND_BUFFER_SIZE];
922	unsigned int render_opts;
923	unsigned int preferred_glue;
924	isc_boolean_t opt_included = ISC_FALSE;
925
926	REQUIRE(NS_CLIENT_VALID(client));
927
928	CTRACE("send");
929
930	if ((client->attributes & NS_CLIENTATTR_RA) != 0)
931		client->message->flags |= DNS_MESSAGEFLAG_RA;
932
933	if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
934		render_opts = 0;
935	else
936		render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
937
938	preferred_glue = 0;
939	if (client->view != NULL) {
940		if (client->view->preferred_glue == dns_rdatatype_a)
941			preferred_glue = DNS_MESSAGERENDER_PREFER_A;
942		else if (client->view->preferred_glue == dns_rdatatype_aaaa)
943			preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
944	}
945
946#ifdef ALLOW_FILTER_AAAA_ON_V4
947	/*
948	 * filter-aaaa-on-v4 yes or break-dnssec option to suppress
949	 * AAAA records
950	 * We already know that request came via IPv4,
951	 * that we have both AAAA and A records,
952	 * and that we either have no signatures that the client wants
953	 * or we are supposed to break DNSSEC.
954	 *
955	 * Override preferred glue if necessary.
956	 */
957	if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0) {
958		render_opts |= DNS_MESSAGERENDER_FILTER_AAAA;
959		if (preferred_glue == DNS_MESSAGERENDER_PREFER_AAAA)
960			preferred_glue = DNS_MESSAGERENDER_PREFER_A;
961	}
962#endif
963
964	/*
965	 * XXXRTH  The following doesn't deal with TCP buffer resizing.
966	 */
967	result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
968				     sendbuf, &data);
969	if (result != ISC_R_SUCCESS)
970		goto done;
971
972	result = dns_compress_init(&cctx, -1, client->mctx);
973	if (result != ISC_R_SUCCESS)
974		goto done;
975	cleanup_cctx = ISC_TRUE;
976
977	result = dns_message_renderbegin(client->message, &cctx, &buffer);
978	if (result != ISC_R_SUCCESS)
979		goto done;
980
981	if (client->opt != NULL) {
982		result = dns_message_setopt(client->message, client->opt);
983		opt_included = ISC_TRUE;
984		client->opt = NULL;
985		if (result != ISC_R_SUCCESS)
986			goto done;
987	}
988	result = dns_message_rendersection(client->message,
989					   DNS_SECTION_QUESTION, 0);
990	if (result == ISC_R_NOSPACE) {
991		client->message->flags |= DNS_MESSAGEFLAG_TC;
992		goto renderend;
993	}
994	if (result != ISC_R_SUCCESS)
995		goto done;
996	result = dns_message_rendersection(client->message,
997					   DNS_SECTION_ANSWER,
998					   DNS_MESSAGERENDER_PARTIAL |
999					   render_opts);
1000	if (result == ISC_R_NOSPACE) {
1001		client->message->flags |= DNS_MESSAGEFLAG_TC;
1002		goto renderend;
1003	}
1004	if (result != ISC_R_SUCCESS)
1005		goto done;
1006	result = dns_message_rendersection(client->message,
1007					   DNS_SECTION_AUTHORITY,
1008					   DNS_MESSAGERENDER_PARTIAL |
1009					   render_opts);
1010	if (result == ISC_R_NOSPACE) {
1011		client->message->flags |= DNS_MESSAGEFLAG_TC;
1012		goto renderend;
1013	}
1014	if (result != ISC_R_SUCCESS)
1015		goto done;
1016	result = dns_message_rendersection(client->message,
1017					   DNS_SECTION_ADDITIONAL,
1018					   preferred_glue | render_opts);
1019	if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
1020		goto done;
1021 renderend:
1022	result = dns_message_renderend(client->message);
1023
1024	if (result != ISC_R_SUCCESS)
1025		goto done;
1026
1027	if (cleanup_cctx) {
1028		dns_compress_invalidate(&cctx);
1029		cleanup_cctx = ISC_FALSE;
1030	}
1031
1032	if (TCP_CLIENT(client)) {
1033		isc_buffer_usedregion(&buffer, &r);
1034		isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
1035		isc_buffer_add(&tcpbuffer, r.length);
1036		result = client_sendpkg(client, &tcpbuffer);
1037	} else
1038		result = client_sendpkg(client, &buffer);
1039
1040	/* update statistics (XXXJT: is it okay to access message->xxxkey?) */
1041	isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response);
1042	if (opt_included) {
1043		isc_stats_increment(ns_g_server->nsstats,
1044				    dns_nsstatscounter_edns0out);
1045	}
1046	if (client->message->tsigkey != NULL) {
1047		isc_stats_increment(ns_g_server->nsstats,
1048				    dns_nsstatscounter_tsigout);
1049	}
1050	if (client->message->sig0key != NULL) {
1051		isc_stats_increment(ns_g_server->nsstats,
1052				    dns_nsstatscounter_sig0out);
1053	}
1054	if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
1055		isc_stats_increment(ns_g_server->nsstats,
1056				    dns_nsstatscounter_truncatedresp);
1057
1058	if (result == ISC_R_SUCCESS)
1059		return;
1060
1061 done:
1062	if (client->tcpbuf != NULL) {
1063		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
1064		client->tcpbuf = NULL;
1065	}
1066
1067	if (cleanup_cctx)
1068		dns_compress_invalidate(&cctx);
1069
1070	ns_client_next(client, result);
1071}
1072
1073#if NS_CLIENT_DROPPORT
1074#define DROPPORT_NO		0
1075#define DROPPORT_REQUEST	1
1076#define DROPPORT_RESPONSE	2
1077/*%
1078 * ns_client_dropport determines if certain requests / responses
1079 * should be dropped based on the port number.
1080 *
1081 * Returns:
1082 * \li	0:	Don't drop.
1083 * \li	1:	Drop request.
1084 * \li	2:	Drop (error) response.
1085 */
1086static int
1087ns_client_dropport(in_port_t port) {
1088	switch (port) {
1089	case 7: /* echo */
1090	case 13: /* daytime */
1091	case 19: /* chargen */
1092	case 37: /* time */
1093		return (DROPPORT_REQUEST);
1094	case 464: /* kpasswd */
1095		return (DROPPORT_RESPONSE);
1096	}
1097	return (DROPPORT_NO);
1098}
1099#endif
1100
1101void
1102ns_client_error(ns_client_t *client, isc_result_t result) {
1103	dns_rcode_t rcode;
1104	dns_message_t *message;
1105
1106	REQUIRE(NS_CLIENT_VALID(client));
1107
1108	CTRACE("error");
1109
1110	message = client->message;
1111	rcode = dns_result_torcode(result);
1112
1113#if NS_CLIENT_DROPPORT
1114	/*
1115	 * Don't send FORMERR to ports on the drop port list.
1116	 */
1117	if (rcode == dns_rcode_formerr &&
1118	    ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
1119	    DROPPORT_NO) {
1120		char buf[64];
1121		isc_buffer_t b;
1122
1123		isc_buffer_init(&b, buf, sizeof(buf) - 1);
1124		if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
1125			isc_buffer_putstr(&b, "UNKNOWN RCODE");
1126		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1127			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1128			      "dropped error (%.*s) response: suspicious port",
1129			      (int)isc_buffer_usedlength(&b), buf);
1130		ns_client_next(client, ISC_R_SUCCESS);
1131		return;
1132	}
1133#endif
1134
1135	/*
1136	 * Message may be an in-progress reply that we had trouble
1137	 * with, in which case QR will be set.  We need to clear QR before
1138	 * calling dns_message_reply() to avoid triggering an assertion.
1139	 */
1140	message->flags &= ~DNS_MESSAGEFLAG_QR;
1141	/*
1142	 * AA and AD shouldn't be set.
1143	 */
1144	message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
1145	result = dns_message_reply(message, ISC_TRUE);
1146	if (result != ISC_R_SUCCESS) {
1147		/*
1148		 * It could be that we've got a query with a good header,
1149		 * but a bad question section, so we try again with
1150		 * want_question_section set to ISC_FALSE.
1151		 */
1152		result = dns_message_reply(message, ISC_FALSE);
1153		if (result != ISC_R_SUCCESS) {
1154			ns_client_next(client, result);
1155			return;
1156		}
1157	}
1158	message->rcode = rcode;
1159
1160	/*
1161	 * FORMERR loop avoidance:  If we sent a FORMERR message
1162	 * with the same ID to the same client less than two
1163	 * seconds ago, assume that we are in an infinite error
1164	 * packet dialog with a server for some protocol whose
1165	 * error responses look enough like DNS queries to
1166	 * elicit a FORMERR response.  Drop a packet to break
1167	 * the loop.
1168	 */
1169	if (rcode == dns_rcode_formerr) {
1170		if (isc_sockaddr_equal(&client->peeraddr,
1171				       &client->formerrcache.addr) &&
1172		    message->id == client->formerrcache.id &&
1173		    client->requesttime - client->formerrcache.time < 2) {
1174			/* Drop packet. */
1175			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1176				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1177				      "possible error packet loop, "
1178				      "FORMERR dropped");
1179			ns_client_next(client, result);
1180			return;
1181		}
1182		client->formerrcache.addr = client->peeraddr;
1183		client->formerrcache.time = client->requesttime;
1184		client->formerrcache.id = message->id;
1185	}
1186	ns_client_send(client);
1187}
1188
1189static inline isc_result_t
1190client_addopt(ns_client_t *client) {
1191	dns_rdataset_t *rdataset;
1192	dns_rdatalist_t *rdatalist;
1193	dns_rdata_t *rdata;
1194	isc_result_t result;
1195	dns_view_t *view;
1196	dns_resolver_t *resolver;
1197	isc_uint16_t udpsize;
1198
1199	REQUIRE(client->opt == NULL);	/* XXXRTH free old. */
1200
1201	rdatalist = NULL;
1202	result = dns_message_gettemprdatalist(client->message, &rdatalist);
1203	if (result != ISC_R_SUCCESS)
1204		return (result);
1205	rdata = NULL;
1206	result = dns_message_gettemprdata(client->message, &rdata);
1207	if (result != ISC_R_SUCCESS)
1208		return (result);
1209	rdataset = NULL;
1210	result = dns_message_gettemprdataset(client->message, &rdataset);
1211	if (result != ISC_R_SUCCESS)
1212		return (result);
1213	dns_rdataset_init(rdataset);
1214
1215	rdatalist->type = dns_rdatatype_opt;
1216	rdatalist->covers = 0;
1217
1218	/*
1219	 * Set the maximum UDP buffer size.
1220	 */
1221	view = client->view;
1222	resolver = (view != NULL) ? view->resolver : NULL;
1223	if (resolver != NULL)
1224		udpsize = dns_resolver_getudpsize(resolver);
1225	else
1226		udpsize = ns_g_udpsize;
1227	rdatalist->rdclass = udpsize;
1228
1229	/*
1230	 * Set EXTENDED-RCODE, VERSION and Z to 0.
1231	 */
1232	rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);
1233
1234	/* Set EDNS options if applicable */
1235	if (client->attributes & NS_CLIENTATTR_WANTNSID &&
1236	    (ns_g_server->server_id != NULL ||
1237	     ns_g_server->server_usehostname)) {
1238		/*
1239		 * Space required for NSID data:
1240		 *   2 bytes for opt code
1241		 * + 2 bytes for NSID length
1242		 * + NSID itself
1243		 */
1244		char nsid[BUFSIZ], *nsidp;
1245		isc_buffer_t *buffer = NULL;
1246
1247		if (ns_g_server->server_usehostname) {
1248			isc_result_t result;
1249			result = ns_os_gethostname(nsid, sizeof(nsid));
1250			if (result != ISC_R_SUCCESS) {
1251				goto no_nsid;
1252			}
1253			nsidp = nsid;
1254		} else
1255			nsidp = ns_g_server->server_id;
1256
1257		rdata->length = strlen(nsidp) + 4;
1258		result = isc_buffer_allocate(client->mctx, &buffer,
1259					     rdata->length);
1260		if (result != ISC_R_SUCCESS)
1261			goto no_nsid;
1262
1263		isc_buffer_putuint16(buffer, DNS_OPT_NSID);
1264		isc_buffer_putuint16(buffer, strlen(nsidp));
1265		isc_buffer_putstr(buffer, nsidp);
1266		rdata->data = buffer->base;
1267		dns_message_takebuffer(client->message, &buffer);
1268	} else {
1269no_nsid:
1270		rdata->data = NULL;
1271		rdata->length = 0;
1272	}
1273
1274	rdata->rdclass = rdatalist->rdclass;
1275	rdata->type = rdatalist->type;
1276	rdata->flags = 0;
1277
1278	ISC_LIST_INIT(rdatalist->rdata);
1279	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1280	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
1281		      == ISC_R_SUCCESS);
1282
1283	client->opt = rdataset;
1284
1285	return (ISC_R_SUCCESS);
1286}
1287
1288static inline isc_boolean_t
1289allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
1290	int match;
1291	isc_result_t result;
1292
1293	if (acl == NULL)
1294		return (ISC_TRUE);
1295	result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
1296			       &match, NULL);
1297	if (result == ISC_R_SUCCESS && match > 0)
1298		return (ISC_TRUE);
1299	return (ISC_FALSE);
1300}
1301
1302/*
1303 * Callback to see if a non-recursive query coming from 'srcaddr' to
1304 * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1305 * delivered to 'myview'.
1306 *
1307 * We run this unlocked as both the view list and the interface list
1308 * are updated when the appropriate task has exclusivity.
1309 */
1310isc_boolean_t
1311ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
1312		 isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
1313		 dns_rdataclass_t rdclass, void *arg)
1314{
1315	dns_view_t *view;
1316	dns_tsigkey_t *key = NULL;
1317	dns_name_t *tsig = NULL;
1318	isc_netaddr_t netsrc;
1319	isc_netaddr_t netdst;
1320
1321	UNUSED(arg);
1322
1323	/*
1324	 * ns_g_server->interfacemgr is task exclusive locked.
1325	 */
1326	if (ns_g_server->interfacemgr == NULL)
1327		return (ISC_TRUE);
1328
1329	if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
1330		return (ISC_FALSE);
1331
1332	isc_netaddr_fromsockaddr(&netsrc, srcaddr);
1333	isc_netaddr_fromsockaddr(&netdst, dstaddr);
1334
1335	for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1336	     view != NULL;
1337	     view = ISC_LIST_NEXT(view, link)) {
1338
1339		if (view->matchrecursiveonly)
1340			continue;
1341
1342		if (rdclass != view->rdclass)
1343			continue;
1344
1345		if (mykey != NULL) {
1346			isc_boolean_t match;
1347			isc_result_t result;
1348
1349			result = dns_view_gettsig(view, &mykey->name, &key);
1350			if (result != ISC_R_SUCCESS)
1351				continue;
1352			match = dst_key_compare(mykey->key, key->key);
1353			dns_tsigkey_detach(&key);
1354			if (!match)
1355				continue;
1356			tsig = dns_tsigkey_identity(mykey);
1357		}
1358
1359		if (allowed(&netsrc, tsig, view->matchclients) &&
1360		    allowed(&netdst, tsig, view->matchdestinations))
1361			break;
1362	}
1363	return (ISC_TF(view == myview));
1364}
1365
1366/*
1367 * Handle an incoming request event from the socket (UDP case)
1368 * or tcpmsg (TCP case).
1369 */
1370static void
1371client_request(isc_task_t *task, isc_event_t *event) {
1372	ns_client_t *client;
1373	isc_socketevent_t *sevent;
1374	isc_result_t result;
1375	isc_result_t sigresult = ISC_R_SUCCESS;
1376	isc_buffer_t *buffer;
1377	isc_buffer_t tbuffer;
1378	dns_view_t *view;
1379	dns_rdataset_t *opt;
1380	dns_name_t *signame;
1381	isc_boolean_t ra;	/* Recursion available. */
1382	isc_netaddr_t netaddr;
1383	int match;
1384	dns_messageid_t id;
1385	unsigned int flags;
1386	isc_boolean_t notimp;
1387	dns_rdata_t rdata;
1388	isc_uint16_t optcode;
1389
1390	REQUIRE(event != NULL);
1391	client = event->ev_arg;
1392	REQUIRE(NS_CLIENT_VALID(client));
1393	REQUIRE(task == client->task);
1394
1395	INSIST(client->recursionquota == NULL);
1396
1397	INSIST(client->state ==
1398	       TCP_CLIENT(client) ?
1399	       NS_CLIENTSTATE_READING :
1400	       NS_CLIENTSTATE_READY);
1401
1402	ns_client_requests++;
1403
1404	if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
1405		INSIST(!TCP_CLIENT(client));
1406		sevent = (isc_socketevent_t *)event;
1407		REQUIRE(sevent == client->recvevent);
1408		isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
1409		isc_buffer_add(&tbuffer, sevent->n);
1410		buffer = &tbuffer;
1411		result = sevent->result;
1412		if (result == ISC_R_SUCCESS) {
1413			client->peeraddr = sevent->address;
1414			client->peeraddr_valid = ISC_TRUE;
1415		}
1416		if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1417			client->attributes |= NS_CLIENTATTR_PKTINFO;
1418			client->pktinfo = sevent->pktinfo;
1419		}
1420		if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
1421			client->attributes |= NS_CLIENTATTR_MULTICAST;
1422		client->nrecvs--;
1423	} else {
1424		INSIST(TCP_CLIENT(client));
1425		REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
1426		REQUIRE(event->ev_sender == &client->tcpmsg);
1427		buffer = &client->tcpmsg.buffer;
1428		result = client->tcpmsg.result;
1429		INSIST(client->nreads == 1);
1430		/*
1431		 * client->peeraddr was set when the connection was accepted.
1432		 */
1433		client->nreads--;
1434	}
1435
1436	if (exit_check(client))
1437		goto cleanup;
1438	client->state = client->newstate = NS_CLIENTSTATE_WORKING;
1439
1440	isc_task_getcurrenttime(task, &client->requesttime);
1441	client->now = client->requesttime;
1442
1443	if (result != ISC_R_SUCCESS) {
1444		if (TCP_CLIENT(client)) {
1445			ns_client_next(client, result);
1446		} else {
1447			if  (result != ISC_R_CANCELED)
1448				isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
1449					      NS_LOGMODULE_CLIENT,
1450					      ISC_LOG_ERROR,
1451					      "UDP client handler shutting "
1452					      "down due to fatal receive "
1453					      "error: %s",
1454					      isc_result_totext(result));
1455			isc_task_shutdown(client->task);
1456		}
1457		goto cleanup;
1458	}
1459
1460	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1461
1462#if NS_CLIENT_DROPPORT
1463	if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1464	    DROPPORT_REQUEST) {
1465		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1466			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1467			      "dropped request: suspicious port");
1468		ns_client_next(client, ISC_R_SUCCESS);
1469		goto cleanup;
1470	}
1471#endif
1472
1473	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1474		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1475		      "%s request",
1476		      TCP_CLIENT(client) ? "TCP" : "UDP");
1477
1478	/*
1479	 * Check the blackhole ACL for UDP only, since TCP is done in
1480	 * client_newconn.
1481	 */
1482	if (!TCP_CLIENT(client)) {
1483
1484		if (ns_g_server->blackholeacl != NULL &&
1485		    dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
1486				  &ns_g_server->aclenv,
1487				  &match, NULL) == ISC_R_SUCCESS &&
1488		    match > 0)
1489		{
1490			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1491				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1492				      "blackholed UDP datagram");
1493			ns_client_next(client, ISC_R_SUCCESS);
1494			goto cleanup;
1495		}
1496	}
1497
1498	/*
1499	 * Silently drop multicast requests for the present.
1500	 * XXXMPA revisit this as mDNS spec was published.
1501	 */
1502	if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
1503		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1504			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1505			      "dropping multicast request");
1506		ns_client_next(client, DNS_R_REFUSED);
1507		goto cleanup;
1508	}
1509
1510	result = dns_message_peekheader(buffer, &id, &flags);
1511	if (result != ISC_R_SUCCESS) {
1512		/*
1513		 * There isn't enough header to determine whether
1514		 * this was a request or a response.  Drop it.
1515		 */
1516		ns_client_next(client, result);
1517		goto cleanup;
1518	}
1519
1520	/*
1521	 * The client object handles requests, not responses.
1522	 * If this is a UDP response, forward it to the dispatcher.
1523	 * If it's a TCP response, discard it here.
1524	 */
1525	if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1526		if (TCP_CLIENT(client)) {
1527			CTRACE("unexpected response");
1528			ns_client_next(client, DNS_R_FORMERR);
1529			goto cleanup;
1530		} else {
1531			dns_dispatch_importrecv(client->dispatch, event);
1532			ns_client_next(client, ISC_R_SUCCESS);
1533			goto cleanup;
1534		}
1535	}
1536
1537	/*
1538	 * Update some statistics counters.  Don't count responses.
1539	 */
1540	if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
1541		isc_stats_increment(ns_g_server->nsstats,
1542				    dns_nsstatscounter_requestv4);
1543	} else {
1544		isc_stats_increment(ns_g_server->nsstats,
1545				    dns_nsstatscounter_requestv6);
1546	}
1547	if (TCP_CLIENT(client))
1548		isc_stats_increment(ns_g_server->nsstats,
1549				    dns_nsstatscounter_tcp);
1550
1551	/*
1552	 * It's a request.  Parse it.
1553	 */
1554	result = dns_message_parse(client->message, buffer, 0);
1555	if (result != ISC_R_SUCCESS) {
1556		/*
1557		 * Parsing the request failed.  Send a response
1558		 * (typically FORMERR or SERVFAIL).
1559		 */
1560		ns_client_error(client, result);
1561		goto cleanup;
1562	}
1563
1564	dns_opcodestats_increment(ns_g_server->opcodestats,
1565				  client->message->opcode);
1566	switch (client->message->opcode) {
1567	case dns_opcode_query:
1568	case dns_opcode_update:
1569	case dns_opcode_notify:
1570		notimp = ISC_FALSE;
1571		break;
1572	case dns_opcode_iquery:
1573	default:
1574		notimp = ISC_TRUE;
1575		break;
1576	}
1577
1578	client->message->rcode = dns_rcode_noerror;
1579
1580	/* RFC1123 section 6.1.3.2 */
1581	if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1582		client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1583
1584	/*
1585	 * Deal with EDNS.
1586	 */
1587	opt = dns_message_getopt(client->message);
1588	if (opt != NULL) {
1589		/*
1590		 * Set the client's UDP buffer size.
1591		 */
1592		client->udpsize = opt->rdclass;
1593
1594		/*
1595		 * If the requested UDP buffer size is less than 512,
1596		 * ignore it and use 512.
1597		 */
1598		if (client->udpsize < 512)
1599			client->udpsize = 512;
1600
1601		/*
1602		 * Get the flags out of the OPT record.
1603		 */
1604		client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1605
1606		/*
1607		 * Do we understand this version of EDNS?
1608		 *
1609		 * XXXRTH need library support for this!
1610		 */
1611		client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1612		if (client->ednsversion > 0) {
1613			isc_stats_increment(ns_g_server->nsstats,
1614					    dns_nsstatscounter_badednsver);
1615			result = client_addopt(client);
1616			if (result == ISC_R_SUCCESS)
1617				result = DNS_R_BADVERS;
1618			ns_client_error(client, result);
1619			goto cleanup;
1620		}
1621
1622		/* Check for NSID request */
1623		result = dns_rdataset_first(opt);
1624		if (result == ISC_R_SUCCESS) {
1625			dns_rdata_init(&rdata);
1626			dns_rdataset_current(opt, &rdata);
1627			if (rdata.length >= 2) {
1628				isc_buffer_t nsidbuf;
1629				isc_buffer_init(&nsidbuf,
1630						rdata.data, rdata.length);
1631				isc_buffer_add(&nsidbuf, rdata.length);
1632				optcode = isc_buffer_getuint16(&nsidbuf);
1633				if (optcode == DNS_OPT_NSID)
1634					client->attributes |=
1635						NS_CLIENTATTR_WANTNSID;
1636			}
1637		}
1638
1639		isc_stats_increment(ns_g_server->nsstats,
1640				    dns_nsstatscounter_edns0in);
1641
1642		/*
1643		 * Create an OPT for our reply.
1644		 */
1645		result = client_addopt(client);
1646		if (result != ISC_R_SUCCESS) {
1647			ns_client_error(client, result);
1648			goto cleanup;
1649		}
1650	}
1651
1652	if (client->message->rdclass == 0) {
1653		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1654			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1655			      "message class could not be determined");
1656		ns_client_dumpmessage(client,
1657				      "message class could not be determined");
1658		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1659		goto cleanup;
1660	}
1661
1662	/*
1663	 * Determine the destination address.  If the receiving interface is
1664	 * bound to a specific address, we simply use it regardless of the
1665	 * address family.  All IPv4 queries should fall into this case.
1666	 * Otherwise, if this is a TCP query, get the address from the
1667	 * receiving socket (this needs a system call and can be heavy).
1668	 * For IPv6 UDP queries, we get this from the pktinfo structure (if
1669	 * supported).
1670	 * If all the attempts fail (this can happen due to memory shortage,
1671	 * etc), we regard this as an error for safety.
1672	 */
1673	if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1674		isc_netaddr_fromsockaddr(&client->destaddr,
1675					 &client->interface->addr);
1676	else {
1677		isc_sockaddr_t sockaddr;
1678		result = ISC_R_FAILURE;
1679
1680		if (TCP_CLIENT(client))
1681			result = isc_socket_getsockname(client->tcpsocket,
1682							&sockaddr);
1683		if (result == ISC_R_SUCCESS)
1684			isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
1685		if (result != ISC_R_SUCCESS &&
1686		    client->interface->addr.type.sa.sa_family == AF_INET6 &&
1687		    (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1688			/*
1689			 * XXXJT technically, we should convert the receiving
1690			 * interface ID to a proper scope zone ID.  However,
1691			 * due to the fact there is no standard API for this,
1692			 * we only handle link-local addresses and use the
1693			 * interface index as link ID.  Despite the assumption,
1694			 * it should cover most typical cases.
1695			 */
1696			isc_netaddr_fromin6(&client->destaddr,
1697					    &client->pktinfo.ipi6_addr);
1698			if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1699				isc_netaddr_setzone(&client->destaddr,
1700						client->pktinfo.ipi6_ifindex);
1701			result = ISC_R_SUCCESS;
1702		}
1703		if (result != ISC_R_SUCCESS) {
1704			UNEXPECTED_ERROR(__FILE__, __LINE__,
1705					 "failed to get request's "
1706					 "destination: %s",
1707					 isc_result_totext(result));
1708			ns_client_next(client, ISC_R_SUCCESS);
1709			goto cleanup;
1710		}
1711	}
1712
1713	/*
1714	 * Find a view that matches the client's source address.
1715	 */
1716	for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1717	     view != NULL;
1718	     view = ISC_LIST_NEXT(view, link)) {
1719		if (client->message->rdclass == view->rdclass ||
1720		    client->message->rdclass == dns_rdataclass_any)
1721		{
1722			dns_name_t *tsig = NULL;
1723
1724			sigresult = dns_message_rechecksig(client->message,
1725							   view);
1726			if (sigresult == ISC_R_SUCCESS)
1727				tsig = dns_tsigkey_identity(client->message->tsigkey);
1728
1729			if (allowed(&netaddr, tsig, view->matchclients) &&
1730			    allowed(&client->destaddr, tsig,
1731				    view->matchdestinations) &&
1732			    !((client->message->flags & DNS_MESSAGEFLAG_RD)
1733			      == 0 && view->matchrecursiveonly))
1734			{
1735				dns_view_attach(view, &client->view);
1736				break;
1737			}
1738		}
1739	}
1740
1741	if (view == NULL) {
1742		char classname[DNS_RDATACLASS_FORMATSIZE];
1743
1744		/*
1745		 * Do a dummy TSIG verification attempt so that the
1746		 * response will have a TSIG if the query did, as
1747		 * required by RFC2845.
1748		 */
1749		isc_buffer_t b;
1750		isc_region_t *r;
1751
1752		dns_message_resetsig(client->message);
1753
1754		r = dns_message_getrawmessage(client->message);
1755		isc_buffer_init(&b, r->base, r->length);
1756		isc_buffer_add(&b, r->length);
1757		(void)dns_tsig_verify(&b, client->message, NULL, NULL);
1758
1759		dns_rdataclass_format(client->message->rdclass, classname,
1760				      sizeof(classname));
1761		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1762			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1763			      "no matching view in class '%s'", classname);
1764		ns_client_dumpmessage(client, "no matching view in class");
1765		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1766		goto cleanup;
1767	}
1768
1769	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1770		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1771		      "using view '%s'", view->name);
1772
1773	/*
1774	 * Check for a signature.  We log bad signatures regardless of
1775	 * whether they ultimately cause the request to be rejected or
1776	 * not.  We do not log the lack of a signature unless we are
1777	 * debugging.
1778	 */
1779	client->signer = NULL;
1780	dns_name_init(&client->signername, NULL);
1781	result = dns_message_signer(client->message, &client->signername);
1782	if (result != ISC_R_NOTFOUND) {
1783		signame = NULL;
1784		if (dns_message_gettsig(client->message, &signame) != NULL) {
1785			isc_stats_increment(ns_g_server->nsstats,
1786					    dns_nsstatscounter_tsigin);
1787		} else {
1788			isc_stats_increment(ns_g_server->nsstats,
1789					    dns_nsstatscounter_sig0in);
1790		}
1791
1792	}
1793	if (result == ISC_R_SUCCESS) {
1794		char namebuf[DNS_NAME_FORMATSIZE];
1795		dns_name_format(&client->signername, namebuf, sizeof(namebuf));
1796		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1797			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1798			      "request has valid signature: %s", namebuf);
1799		client->signer = &client->signername;
1800	} else if (result == ISC_R_NOTFOUND) {
1801		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1802			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1803			      "request is not signed");
1804	} else if (result == DNS_R_NOIDENTITY) {
1805		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1806			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1807			      "request is signed by a nonauthoritative key");
1808	} else {
1809		char tsigrcode[64];
1810		isc_buffer_t b;
1811		dns_rcode_t status;
1812		isc_result_t tresult;
1813
1814		/* There is a signature, but it is bad. */
1815		isc_stats_increment(ns_g_server->nsstats,
1816				    dns_nsstatscounter_invalidsig);
1817		signame = NULL;
1818		if (dns_message_gettsig(client->message, &signame) != NULL) {
1819			char namebuf[DNS_NAME_FORMATSIZE];
1820			char cnamebuf[DNS_NAME_FORMATSIZE];
1821			dns_name_format(signame, namebuf, sizeof(namebuf));
1822			status = client->message->tsigstatus;
1823			isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1824			tresult = dns_tsigrcode_totext(status, &b);
1825			INSIST(tresult == ISC_R_SUCCESS);
1826			tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1827			if (client->message->tsigkey->generated) {
1828				dns_name_format(client->message->tsigkey->creator,
1829						cnamebuf, sizeof(cnamebuf));
1830				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1831					      NS_LOGMODULE_CLIENT,
1832					      ISC_LOG_ERROR,
1833					      "request has invalid signature: "
1834					      "TSIG %s (%s): %s (%s)", namebuf,
1835					      cnamebuf,
1836					      isc_result_totext(result),
1837					      tsigrcode);
1838			} else {
1839				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1840					      NS_LOGMODULE_CLIENT,
1841					      ISC_LOG_ERROR,
1842					      "request has invalid signature: "
1843					      "TSIG %s: %s (%s)", namebuf,
1844					      isc_result_totext(result),
1845					      tsigrcode);
1846			}
1847		} else {
1848			status = client->message->sig0status;
1849			isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1850			tresult = dns_tsigrcode_totext(status, &b);
1851			INSIST(tresult == ISC_R_SUCCESS);
1852			tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1853			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1854				      NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1855				      "request has invalid signature: %s (%s)",
1856				      isc_result_totext(result), tsigrcode);
1857		}
1858		/*
1859		 * Accept update messages signed by unknown keys so that
1860		 * update forwarding works transparently through slaves
1861		 * that don't have all the same keys as the master.
1862		 */
1863		if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
1864		      client->message->opcode == dns_opcode_update)) {
1865			ns_client_error(client, sigresult);
1866			goto cleanup;
1867		}
1868	}
1869
1870	/*
1871	 * Decide whether recursive service is available to this client.
1872	 * We do this here rather than in the query code so that we can
1873	 * set the RA bit correctly on all kinds of responses, not just
1874	 * responses to ordinary queries.  Note if you can't query the
1875	 * cache there is no point in setting RA.
1876	 */
1877	ra = ISC_FALSE;
1878	if (client->view->resolver != NULL &&
1879	    client->view->recursion == ISC_TRUE &&
1880	    ns_client_checkaclsilent(client, NULL,
1881				     client->view->recursionacl,
1882				     ISC_TRUE) == ISC_R_SUCCESS &&
1883	    ns_client_checkaclsilent(client, NULL,
1884				     client->view->cacheacl,
1885				     ISC_TRUE) == ISC_R_SUCCESS &&
1886	    ns_client_checkaclsilent(client, &client->destaddr,
1887				     client->view->recursiononacl,
1888				     ISC_TRUE) == ISC_R_SUCCESS &&
1889	    ns_client_checkaclsilent(client, &client->destaddr,
1890				     client->view->cacheonacl,
1891				     ISC_TRUE) == ISC_R_SUCCESS)
1892		ra = ISC_TRUE;
1893
1894	if (ra == ISC_TRUE)
1895		client->attributes |= NS_CLIENTATTR_RA;
1896
1897	ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1898		      ISC_LOG_DEBUG(3), ra ? "recursion available" :
1899					     "recursion not available");
1900
1901	/*
1902	 * Adjust maximum UDP response size for this client.
1903	 */
1904	if (client->udpsize > 512) {
1905		dns_peer_t *peer = NULL;
1906		isc_uint16_t udpsize = view->maxudp;
1907		(void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
1908		if (peer != NULL)
1909			dns_peer_getmaxudp(peer, &udpsize);
1910		if (client->udpsize > udpsize)
1911			client->udpsize = udpsize;
1912	}
1913
1914	/*
1915	 * Dispatch the request.
1916	 */
1917	switch (client->message->opcode) {
1918	case dns_opcode_query:
1919		CTRACE("query");
1920		ns_query_start(client);
1921		break;
1922	case dns_opcode_update:
1923		CTRACE("update");
1924		ns_client_settimeout(client, 60);
1925		ns_update_start(client, sigresult);
1926		break;
1927	case dns_opcode_notify:
1928		CTRACE("notify");
1929		ns_client_settimeout(client, 60);
1930		ns_notify_start(client);
1931		break;
1932	case dns_opcode_iquery:
1933		CTRACE("iquery");
1934		ns_client_error(client, DNS_R_NOTIMP);
1935		break;
1936	default:
1937		CTRACE("unknown opcode");
1938		ns_client_error(client, DNS_R_NOTIMP);
1939	}
1940
1941 cleanup:
1942	return;
1943}
1944
1945static void
1946client_timeout(isc_task_t *task, isc_event_t *event) {
1947	ns_client_t *client;
1948
1949	REQUIRE(event != NULL);
1950	REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
1951		event->ev_type == ISC_TIMEREVENT_IDLE);
1952	client = event->ev_arg;
1953	REQUIRE(NS_CLIENT_VALID(client));
1954	REQUIRE(task == client->task);
1955	REQUIRE(client->timer != NULL);
1956
1957	UNUSED(task);
1958
1959	CTRACE("timeout");
1960
1961	isc_event_free(&event);
1962
1963	if (client->shutdown != NULL) {
1964		(client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
1965		client->shutdown = NULL;
1966		client->shutdown_arg = NULL;
1967	}
1968
1969	if (client->newstate > NS_CLIENTSTATE_READY)
1970		client->newstate = NS_CLIENTSTATE_READY;
1971	(void)exit_check(client);
1972}
1973
1974static isc_result_t
1975get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
1976	isc_mem_t *clientmctx;
1977	isc_result_t result;
1978
1979	/*
1980	 * Caller must be holding the manager lock.
1981	 */
1982	if (ns_g_clienttest) {
1983		result = isc_mem_create(0, 0, mctxp);
1984		if (result == ISC_R_SUCCESS)
1985			isc_mem_setname(*mctxp, "client", NULL);
1986		return (result);
1987	}
1988#if NMCTXS > 0
1989	INSIST(manager->nextmctx < NMCTXS);
1990	clientmctx = manager->mctxpool[manager->nextmctx];
1991	if (clientmctx == NULL) {
1992		result = isc_mem_create(0, 0, &clientmctx);
1993		if (result != ISC_R_SUCCESS)
1994			return (result);
1995		isc_mem_setname(clientmctx, "client", NULL);
1996
1997		manager->mctxpool[manager->nextmctx] = clientmctx;
1998	}
1999	manager->nextmctx++;
2000	if (manager->nextmctx == NMCTXS)
2001		manager->nextmctx = 0;
2002#else
2003	clientmctx = manager->mctx;
2004#endif
2005
2006	isc_mem_attach(clientmctx, mctxp);
2007
2008	return (ISC_R_SUCCESS);
2009}
2010
2011static isc_result_t
2012client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
2013	ns_client_t *client;
2014	isc_result_t result;
2015	isc_mem_t *mctx = NULL;
2016
2017	/*
2018	 * Caller must be holding the manager lock.
2019	 *
2020	 * Note: creating a client does not add the client to the
2021	 * manager's client list or set the client's manager pointer.
2022	 * The caller is responsible for that.
2023	 */
2024
2025	REQUIRE(clientp != NULL && *clientp == NULL);
2026
2027	result = get_clientmctx(manager, &mctx);
2028	if (result != ISC_R_SUCCESS)
2029		return (result);
2030
2031	client = isc_mem_get(mctx, sizeof(*client));
2032	if (client == NULL) {
2033		isc_mem_detach(&mctx);
2034		return (ISC_R_NOMEMORY);
2035	}
2036	client->mctx = mctx;
2037
2038	client->task = NULL;
2039	result = isc_task_create(manager->taskmgr, 0, &client->task);
2040	if (result != ISC_R_SUCCESS)
2041		goto cleanup_client;
2042	isc_task_setname(client->task, "client", client);
2043
2044	client->timer = NULL;
2045	result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
2046				  NULL, NULL, client->task, client_timeout,
2047				  client, &client->timer);
2048	if (result != ISC_R_SUCCESS)
2049		goto cleanup_task;
2050	client->timerset = ISC_FALSE;
2051
2052	client->message = NULL;
2053	result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
2054				    &client->message);
2055	if (result != ISC_R_SUCCESS)
2056		goto cleanup_timer;
2057
2058	/* XXXRTH  Hardwired constants */
2059
2060	client->sendevent = (isc_socketevent_t *)
2061			    isc_event_allocate(client->mctx, client,
2062					       ISC_SOCKEVENT_SENDDONE,
2063					       client_senddone, client,
2064					       sizeof(isc_socketevent_t));
2065	if (client->sendevent == NULL) {
2066		result = ISC_R_NOMEMORY;
2067		goto cleanup_message;
2068	}
2069
2070	client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
2071	if  (client->recvbuf == NULL) {
2072		result = ISC_R_NOMEMORY;
2073		goto cleanup_sendevent;
2074	}
2075
2076	client->recvevent = (isc_socketevent_t *)
2077			    isc_event_allocate(client->mctx, client,
2078					       ISC_SOCKEVENT_RECVDONE,
2079					       client_request, client,
2080					       sizeof(isc_socketevent_t));
2081	if (client->recvevent == NULL) {
2082		result = ISC_R_NOMEMORY;
2083		goto cleanup_recvbuf;
2084	}
2085
2086	client->magic = NS_CLIENT_MAGIC;
2087	client->manager = NULL;
2088	client->state = NS_CLIENTSTATE_INACTIVE;
2089	client->newstate = NS_CLIENTSTATE_MAX;
2090	client->naccepts = 0;
2091	client->nreads = 0;
2092	client->nsends = 0;
2093	client->nrecvs = 0;
2094	client->nupdates = 0;
2095	client->nctls = 0;
2096	client->references = 0;
2097	client->attributes = 0;
2098	client->view = NULL;
2099	client->dispatch = NULL;
2100	client->udpsocket = NULL;
2101	client->tcplistener = NULL;
2102	client->tcpsocket = NULL;
2103	client->tcpmsg_valid = ISC_FALSE;
2104	client->tcpbuf = NULL;
2105	client->opt = NULL;
2106	client->udpsize = 512;
2107	client->extflags = 0;
2108	client->ednsversion = -1;
2109	client->next = NULL;
2110	client->shutdown = NULL;
2111	client->shutdown_arg = NULL;
2112	client->signer = NULL;
2113	dns_name_init(&client->signername, NULL);
2114	client->mortal = ISC_FALSE;
2115	client->tcpquota = NULL;
2116	client->recursionquota = NULL;
2117	client->interface = NULL;
2118	client->peeraddr_valid = ISC_FALSE;
2119#ifdef ALLOW_FILTER_AAAA_ON_V4
2120	client->filter_aaaa = dns_v4_aaaa_ok;
2121#endif
2122	ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
2123		       NS_EVENT_CLIENTCONTROL, client_start, client, client,
2124		       NULL, NULL);
2125	/*
2126	 * Initialize FORMERR cache to sentinel value that will not match
2127	 * any actual FORMERR response.
2128	 */
2129	isc_sockaddr_any(&client->formerrcache.addr);
2130	client->formerrcache.time = 0;
2131	client->formerrcache.id = 0;
2132	ISC_LINK_INIT(client, link);
2133	client->list = NULL;
2134
2135	/*
2136	 * We call the init routines for the various kinds of client here,
2137	 * after we have created an otherwise valid client, because some
2138	 * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
2139	 */
2140	result = ns_query_init(client);
2141	if (result != ISC_R_SUCCESS)
2142		goto cleanup_recvevent;
2143
2144	result = isc_task_onshutdown(client->task, client_shutdown, client);
2145	if (result != ISC_R_SUCCESS)
2146		goto cleanup_query;
2147
2148	client->needshutdown = ns_g_clienttest;
2149
2150	CTRACE("create");
2151
2152	*clientp = client;
2153
2154	return (ISC_R_SUCCESS);
2155
2156 cleanup_query:
2157	ns_query_free(client);
2158
2159 cleanup_recvevent:
2160	isc_event_free((isc_event_t **)&client->recvevent);
2161
2162 cleanup_recvbuf:
2163	isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
2164
2165 cleanup_sendevent:
2166	isc_event_free((isc_event_t **)&client->sendevent);
2167
2168	client->magic = 0;
2169
2170 cleanup_message:
2171	dns_message_destroy(&client->message);
2172
2173 cleanup_timer:
2174	isc_timer_detach(&client->timer);
2175
2176 cleanup_task:
2177	isc_task_detach(&client->task);
2178
2179 cleanup_client:
2180	isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
2181
2182	return (result);
2183}
2184
2185static void
2186client_read(ns_client_t *client) {
2187	isc_result_t result;
2188
2189	CTRACE("read");
2190
2191	result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
2192					client_request, client);
2193	if (result != ISC_R_SUCCESS)
2194		goto fail;
2195
2196	/*
2197	 * Set a timeout to limit the amount of time we will wait
2198	 * for a request on this TCP connection.
2199	 */
2200	ns_client_settimeout(client, 30);
2201
2202	client->state = client->newstate = NS_CLIENTSTATE_READING;
2203	INSIST(client->nreads == 0);
2204	INSIST(client->recursionquota == NULL);
2205	client->nreads++;
2206
2207	return;
2208 fail:
2209	ns_client_next(client, result);
2210}
2211
2212static void
2213client_newconn(isc_task_t *task, isc_event_t *event) {
2214	ns_client_t *client = event->ev_arg;
2215	isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
2216	isc_result_t result;
2217
2218	REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
2219	REQUIRE(NS_CLIENT_VALID(client));
2220	REQUIRE(client->task == task);
2221
2222	UNUSED(task);
2223
2224	INSIST(client->state == NS_CLIENTSTATE_READY);
2225
2226	INSIST(client->naccepts == 1);
2227	client->naccepts--;
2228
2229	LOCK(&client->interface->lock);
2230	INSIST(client->interface->ntcpcurrent > 0);
2231	client->interface->ntcpcurrent--;
2232	UNLOCK(&client->interface->lock);
2233
2234	/*
2235	 * We must take ownership of the new socket before the exit
2236	 * check to make sure it gets destroyed if we decide to exit.
2237	 */
2238	if (nevent->result == ISC_R_SUCCESS) {
2239		client->tcpsocket = nevent->newsocket;
2240		isc_socket_setname(client->tcpsocket, "client-tcp", NULL);
2241		client->state = NS_CLIENTSTATE_READING;
2242		INSIST(client->recursionquota == NULL);
2243
2244		(void)isc_socket_getpeername(client->tcpsocket,
2245					     &client->peeraddr);
2246		client->peeraddr_valid = ISC_TRUE;
2247		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2248			   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2249			   "new TCP connection");
2250	} else {
2251		/*
2252		 * XXXRTH  What should we do?  We're trying to accept but
2253		 *	   it didn't work.  If we just give up, then TCP
2254		 *	   service may eventually stop.
2255		 *
2256		 *	   For now, we just go idle.
2257		 *
2258		 *	   Going idle is probably the right thing if the
2259		 *	   I/O was canceled.
2260		 */
2261		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2262			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2263			      "accept failed: %s",
2264			      isc_result_totext(nevent->result));
2265	}
2266
2267	if (exit_check(client))
2268		goto freeevent;
2269
2270	if (nevent->result == ISC_R_SUCCESS) {
2271		int match;
2272		isc_netaddr_t netaddr;
2273
2274		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2275
2276		if (ns_g_server->blackholeacl != NULL &&
2277		    dns_acl_match(&netaddr, NULL,
2278				  ns_g_server->blackholeacl,
2279				  &ns_g_server->aclenv,
2280				  &match, NULL) == ISC_R_SUCCESS &&
2281		    match > 0)
2282		{
2283			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2284				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2285				      "blackholed connection attempt");
2286			client->newstate = NS_CLIENTSTATE_READY;
2287			(void)exit_check(client);
2288			goto freeevent;
2289		}
2290
2291		INSIST(client->tcpmsg_valid == ISC_FALSE);
2292		dns_tcpmsg_init(client->mctx, client->tcpsocket,
2293				&client->tcpmsg);
2294		client->tcpmsg_valid = ISC_TRUE;
2295
2296		/*
2297		 * Let a new client take our place immediately, before
2298		 * we wait for a request packet.  If we don't,
2299		 * telnetting to port 53 (once per CPU) will
2300		 * deny service to legitimate TCP clients.
2301		 */
2302		result = isc_quota_attach(&ns_g_server->tcpquota,
2303					  &client->tcpquota);
2304		if (result == ISC_R_SUCCESS)
2305			result = ns_client_replace(client);
2306		if (result != ISC_R_SUCCESS) {
2307			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2308				      NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
2309				      "no more TCP clients: %s",
2310				      isc_result_totext(result));
2311		}
2312
2313		client_read(client);
2314	}
2315
2316 freeevent:
2317	isc_event_free(&event);
2318}
2319
2320static void
2321client_accept(ns_client_t *client) {
2322	isc_result_t result;
2323
2324	CTRACE("accept");
2325
2326	result = isc_socket_accept(client->tcplistener, client->task,
2327				   client_newconn, client);
2328	if (result != ISC_R_SUCCESS) {
2329		UNEXPECTED_ERROR(__FILE__, __LINE__,
2330				 "isc_socket_accept() failed: %s",
2331				 isc_result_totext(result));
2332		/*
2333		 * XXXRTH  What should we do?  We're trying to accept but
2334		 *	   it didn't work.  If we just give up, then TCP
2335		 *	   service may eventually stop.
2336		 *
2337		 *	   For now, we just go idle.
2338		 */
2339		return;
2340	}
2341	INSIST(client->naccepts == 0);
2342	client->naccepts++;
2343	LOCK(&client->interface->lock);
2344	client->interface->ntcpcurrent++;
2345	UNLOCK(&client->interface->lock);
2346}
2347
2348static void
2349client_udprecv(ns_client_t *client) {
2350	isc_result_t result;
2351	isc_region_t r;
2352
2353	CTRACE("udprecv");
2354
2355	r.base = client->recvbuf;
2356	r.length = RECV_BUFFER_SIZE;
2357	result = isc_socket_recv2(client->udpsocket, &r, 1,
2358				  client->task, client->recvevent, 0);
2359	if (result != ISC_R_SUCCESS) {
2360		UNEXPECTED_ERROR(__FILE__, __LINE__,
2361				 "isc_socket_recv2() failed: %s",
2362				 isc_result_totext(result));
2363		/*
2364		 * This cannot happen in the current implementation, since
2365		 * isc_socket_recv2() cannot fail if flags == 0.
2366		 *
2367		 * If this does fail, we just go idle.
2368		 */
2369		return;
2370	}
2371	INSIST(client->nrecvs == 0);
2372	client->nrecvs++;
2373}
2374
2375void
2376ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
2377	REQUIRE(NS_CLIENT_VALID(source));
2378	REQUIRE(targetp != NULL && *targetp == NULL);
2379
2380	source->references++;
2381	ns_client_log(source, NS_LOGCATEGORY_CLIENT,
2382		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2383		      "ns_client_attach: ref = %d", source->references);
2384	*targetp = source;
2385}
2386
2387void
2388ns_client_detach(ns_client_t **clientp) {
2389	ns_client_t *client = *clientp;
2390
2391	client->references--;
2392	INSIST(client->references >= 0);
2393	*clientp = NULL;
2394	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2395		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2396		      "ns_client_detach: ref = %d", client->references);
2397	(void)exit_check(client);
2398}
2399
2400isc_boolean_t
2401ns_client_shuttingdown(ns_client_t *client) {
2402	return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
2403}
2404
2405isc_result_t
2406ns_client_replace(ns_client_t *client) {
2407	isc_result_t result;
2408
2409	CTRACE("replace");
2410
2411	result = ns_clientmgr_createclients(client->manager,
2412					    1, client->interface,
2413					    (TCP_CLIENT(client) ?
2414					     ISC_TRUE : ISC_FALSE));
2415	if (result != ISC_R_SUCCESS)
2416		return (result);
2417
2418	/*
2419	 * The responsibility for listening for new requests is hereby
2420	 * transferred to the new client.  Therefore, the old client
2421	 * should refrain from listening for any more requests.
2422	 */
2423	client->mortal = ISC_TRUE;
2424
2425	return (ISC_R_SUCCESS);
2426}
2427
2428/***
2429 *** Client Manager
2430 ***/
2431
2432static void
2433clientmgr_destroy(ns_clientmgr_t *manager) {
2434#if NMCTXS > 0
2435	int i;
2436#endif
2437
2438	REQUIRE(ISC_LIST_EMPTY(manager->active));
2439	REQUIRE(ISC_LIST_EMPTY(manager->inactive));
2440	REQUIRE(ISC_LIST_EMPTY(manager->recursing));
2441
2442	MTRACE("clientmgr_destroy");
2443
2444#if NMCTXS > 0
2445	for (i = 0; i < NMCTXS; i++) {
2446		if (manager->mctxpool[i] != NULL)
2447			isc_mem_detach(&manager->mctxpool[i]);
2448	}
2449#endif
2450
2451	DESTROYLOCK(&manager->lock);
2452	manager->magic = 0;
2453	isc_mem_put(manager->mctx, manager, sizeof(*manager));
2454}
2455
2456isc_result_t
2457ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2458		    isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
2459{
2460	ns_clientmgr_t *manager;
2461	isc_result_t result;
2462#if NMCTXS > 0
2463	int i;
2464#endif
2465
2466	manager = isc_mem_get(mctx, sizeof(*manager));
2467	if (manager == NULL)
2468		return (ISC_R_NOMEMORY);
2469
2470	result = isc_mutex_init(&manager->lock);
2471	if (result != ISC_R_SUCCESS)
2472		goto cleanup_manager;
2473
2474	manager->mctx = mctx;
2475	manager->taskmgr = taskmgr;
2476	manager->timermgr = timermgr;
2477	manager->exiting = ISC_FALSE;
2478	ISC_LIST_INIT(manager->active);
2479	ISC_LIST_INIT(manager->inactive);
2480	ISC_LIST_INIT(manager->recursing);
2481#if NMCTXS > 0
2482	manager->nextmctx = 0;
2483	for (i = 0; i < NMCTXS; i++)
2484		manager->mctxpool[i] = NULL; /* will be created on-demand */
2485#endif
2486	manager->magic = MANAGER_MAGIC;
2487
2488	MTRACE("create");
2489
2490	*managerp = manager;
2491
2492	return (ISC_R_SUCCESS);
2493
2494 cleanup_manager:
2495	isc_mem_put(manager->mctx, manager, sizeof(*manager));
2496
2497	return (result);
2498}
2499
2500void
2501ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2502	ns_clientmgr_t *manager;
2503	ns_client_t *client;
2504	isc_boolean_t need_destroy = ISC_FALSE;
2505
2506	REQUIRE(managerp != NULL);
2507	manager = *managerp;
2508	REQUIRE(VALID_MANAGER(manager));
2509
2510	MTRACE("destroy");
2511
2512	LOCK(&manager->lock);
2513
2514	manager->exiting = ISC_TRUE;
2515
2516	for (client = ISC_LIST_HEAD(manager->recursing);
2517	     client != NULL;
2518	     client = ISC_LIST_NEXT(client, link))
2519		isc_task_shutdown(client->task);
2520
2521	for (client = ISC_LIST_HEAD(manager->active);
2522	     client != NULL;
2523	     client = ISC_LIST_NEXT(client, link))
2524		isc_task_shutdown(client->task);
2525
2526	for (client = ISC_LIST_HEAD(manager->inactive);
2527	     client != NULL;
2528	     client = ISC_LIST_NEXT(client, link))
2529		isc_task_shutdown(client->task);
2530
2531	if (ISC_LIST_EMPTY(manager->active) &&
2532	    ISC_LIST_EMPTY(manager->inactive) &&
2533	    ISC_LIST_EMPTY(manager->recursing))
2534		need_destroy = ISC_TRUE;
2535
2536	UNLOCK(&manager->lock);
2537
2538	if (need_destroy)
2539		clientmgr_destroy(manager);
2540
2541	*managerp = NULL;
2542}
2543
2544isc_result_t
2545ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
2546			   ns_interface_t *ifp, isc_boolean_t tcp)
2547{
2548	isc_result_t result = ISC_R_SUCCESS;
2549	unsigned int i;
2550	ns_client_t *client;
2551
2552	REQUIRE(VALID_MANAGER(manager));
2553	REQUIRE(n > 0);
2554
2555	MTRACE("createclients");
2556
2557	/*
2558	 * We MUST lock the manager lock for the entire client creation
2559	 * process.  If we didn't do this, then a client could get a
2560	 * shutdown event and disappear out from under us.
2561	 */
2562
2563	LOCK(&manager->lock);
2564
2565	for (i = 0; i < n; i++) {
2566		isc_event_t *ev;
2567		/*
2568		 * Allocate a client.  First try to get a recycled one;
2569		 * if that fails, make a new one.
2570		 */
2571		client = NULL;
2572		if (!ns_g_clienttest)
2573			client = ISC_LIST_HEAD(manager->inactive);
2574		if (client != NULL) {
2575			MTRACE("recycle");
2576			ISC_LIST_UNLINK(manager->inactive, client, link);
2577			client->list = NULL;
2578		} else {
2579			MTRACE("create new");
2580			result = client_create(manager, &client);
2581			if (result != ISC_R_SUCCESS)
2582				break;
2583		}
2584
2585		ns_interface_attach(ifp, &client->interface);
2586		client->state = NS_CLIENTSTATE_READY;
2587		INSIST(client->recursionquota == NULL);
2588
2589		if (tcp) {
2590			client->attributes |= NS_CLIENTATTR_TCP;
2591			isc_socket_attach(ifp->tcpsocket,
2592					  &client->tcplistener);
2593		} else {
2594			isc_socket_t *sock;
2595
2596			dns_dispatch_attach(ifp->udpdispatch,
2597					    &client->dispatch);
2598			sock = dns_dispatch_getsocket(client->dispatch);
2599			isc_socket_attach(sock, &client->udpsocket);
2600		}
2601		client->manager = manager;
2602		ISC_LIST_APPEND(manager->active, client, link);
2603		client->list = &manager->active;
2604
2605		INSIST(client->nctls == 0);
2606		client->nctls++;
2607		ev = &client->ctlevent;
2608		isc_task_send(client->task, &ev);
2609	}
2610	if (i != 0) {
2611		/*
2612		 * We managed to create at least one client, so we
2613		 * declare victory.
2614		 */
2615		result = ISC_R_SUCCESS;
2616	}
2617
2618	UNLOCK(&manager->lock);
2619
2620	return (result);
2621}
2622
2623isc_sockaddr_t *
2624ns_client_getsockaddr(ns_client_t *client) {
2625	return (&client->peeraddr);
2626}
2627
2628isc_result_t
2629ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
2630			 dns_acl_t *acl, isc_boolean_t default_allow)
2631{
2632	isc_result_t result;
2633	isc_netaddr_t tmpnetaddr;
2634	int match;
2635
2636	if (acl == NULL) {
2637		if (default_allow)
2638			goto allow;
2639		else
2640			goto deny;
2641	}
2642
2643	if (netaddr == NULL) {
2644		isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
2645		netaddr = &tmpnetaddr;
2646	}
2647
2648	result = dns_acl_match(netaddr, client->signer, acl,
2649			       &ns_g_server->aclenv, &match, NULL);
2650
2651	if (result != ISC_R_SUCCESS)
2652		goto deny; /* Internal error, already logged. */
2653	if (match > 0)
2654		goto allow;
2655	goto deny; /* Negative match or no match. */
2656
2657 allow:
2658	return (ISC_R_SUCCESS);
2659
2660 deny:
2661	return (DNS_R_REFUSED);
2662}
2663
2664isc_result_t
2665ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
2666		   const char *opname, dns_acl_t *acl,
2667		   isc_boolean_t default_allow, int log_level)
2668{
2669	isc_result_t result;
2670	isc_netaddr_t netaddr;
2671
2672	if (sockaddr != NULL)
2673		isc_netaddr_fromsockaddr(&netaddr, sockaddr);
2674
2675	result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
2676					  acl, default_allow);
2677
2678	if (result == ISC_R_SUCCESS)
2679		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2680			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2681			      "%s approved", opname);
2682	else
2683		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2684			      NS_LOGMODULE_CLIENT,
2685			      log_level, "%s denied", opname);
2686	return (result);
2687}
2688
2689static void
2690ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2691	if (client->peeraddr_valid)
2692		isc_sockaddr_format(&client->peeraddr, peerbuf, len);
2693	else
2694		snprintf(peerbuf, len, "@%p", client);
2695}
2696
2697void
2698ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2699	       isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2700{
2701	char msgbuf[2048];
2702	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2703	const char *name = "";
2704	const char *sep = "";
2705
2706	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2707	ns_client_name(client, peerbuf, sizeof(peerbuf));
2708	if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2709	    strcmp(client->view->name, "_default") != 0) {
2710		name = client->view->name;
2711		sep = ": view ";
2712	}
2713
2714	isc_log_write(ns_g_lctx, category, module, level,
2715		      "client %s%s%s: %s", peerbuf, sep, name, msgbuf);
2716}
2717
2718void
2719ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2720	   isc_logmodule_t *module, int level, const char *fmt, ...)
2721{
2722	va_list ap;
2723
2724	if (! isc_log_wouldlog(ns_g_lctx, level))
2725		return;
2726
2727	va_start(ap, fmt);
2728	ns_client_logv(client, category, module, level, fmt, ap);
2729	va_end(ap);
2730}
2731
2732void
2733ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
2734		 dns_rdataclass_t rdclass, char *buf, size_t len)
2735{
2736	char namebuf[DNS_NAME_FORMATSIZE];
2737	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2738	char classbuf[DNS_RDATACLASS_FORMATSIZE];
2739
2740	dns_name_format(name, namebuf, sizeof(namebuf));
2741	dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2742	dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2743	(void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2744		       classbuf);
2745}
2746
2747static void
2748ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2749	isc_buffer_t buffer;
2750	char *buf = NULL;
2751	int len = 1024;
2752	isc_result_t result;
2753
2754	/*
2755	 * Note that these are multiline debug messages.  We want a newline
2756	 * to appear in the log after each message.
2757	 */
2758
2759	do {
2760		buf = isc_mem_get(client->mctx, len);
2761		if (buf == NULL)
2762			break;
2763		isc_buffer_init(&buffer, buf, len);
2764		result = dns_message_totext(client->message,
2765					    &dns_master_style_debug,
2766					    0, &buffer);
2767		if (result == ISC_R_NOSPACE) {
2768			isc_mem_put(client->mctx, buf, len);
2769			len += 1024;
2770		} else if (result == ISC_R_SUCCESS)
2771			ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
2772				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2773				      "%s\n%.*s", reason,
2774				       (int)isc_buffer_usedlength(&buffer),
2775				       buf);
2776	} while (result == ISC_R_NOSPACE);
2777
2778	if (buf != NULL)
2779		isc_mem_put(client->mctx, buf, len);
2780}
2781
2782void
2783ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2784	ns_client_t *client;
2785	char namebuf[DNS_NAME_FORMATSIZE];
2786	char original[DNS_NAME_FORMATSIZE];
2787	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2788	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2789	char classbuf[DNS_RDATACLASS_FORMATSIZE];
2790	const char *name;
2791	const char *sep;
2792	const char *origfor;
2793	dns_rdataset_t *rdataset;
2794
2795	REQUIRE(VALID_MANAGER(manager));
2796
2797	LOCK(&manager->lock);
2798	client = ISC_LIST_HEAD(manager->recursing);
2799	while (client != NULL) {
2800		ns_client_name(client, peerbuf, sizeof(peerbuf));
2801		if (client->view != NULL &&
2802		    strcmp(client->view->name, "_bind") != 0 &&
2803		    strcmp(client->view->name, "_default") != 0) {
2804			name = client->view->name;
2805			sep = ": view ";
2806		} else {
2807			name = "";
2808			sep = "";
2809		}
2810		dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2811		if (client->query.qname != client->query.origqname &&
2812		    client->query.origqname != NULL) {
2813			origfor = " for ";
2814			dns_name_format(client->query.origqname, original,
2815					sizeof(original));
2816		} else {
2817			origfor = "";
2818			original[0] = '\0';
2819		}
2820		rdataset = ISC_LIST_HEAD(client->query.qname->list);
2821		if (rdataset == NULL && client->query.origqname != NULL)
2822			rdataset = ISC_LIST_HEAD(client->query.origqname->list);
2823		if (rdataset != NULL) {
2824			dns_rdatatype_format(rdataset->type, typebuf,
2825					     sizeof(typebuf));
2826			dns_rdataclass_format(rdataset->rdclass, classbuf,
2827					      sizeof(classbuf));
2828		} else {
2829			strcpy(typebuf, "-");
2830			strcpy(classbuf, "-");
2831		}
2832		fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s "
2833			"requesttime %d\n", peerbuf, sep, name,
2834			client->message->id, namebuf, typebuf, classbuf,
2835			origfor, original, client->requesttime);
2836		client = ISC_LIST_NEXT(client, link);
2837	}
2838	UNLOCK(&manager->lock);
2839}
2840
2841void
2842ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2843
2844	if (client->manager != NULL)
2845		LOCK(&client->manager->lock);
2846	if (client->query.restarts > 0) {
2847		/*
2848		 * client->query.qname was dynamically allocated.
2849		 */
2850		dns_message_puttempname(client->message,
2851					&client->query.qname);
2852	}
2853	client->query.qname = name;
2854	if (client->manager != NULL)
2855		UNLOCK(&client->manager->lock);
2856}
2857