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