client.c revision 254402
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 == (TCP_CLIENT(client) ?
1398				       NS_CLIENTSTATE_READING :
1399				       NS_CLIENTSTATE_READY));
1400
1401	ns_client_requests++;
1402
1403	if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
1404		INSIST(!TCP_CLIENT(client));
1405		sevent = (isc_socketevent_t *)event;
1406		REQUIRE(sevent == client->recvevent);
1407		isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
1408		isc_buffer_add(&tbuffer, sevent->n);
1409		buffer = &tbuffer;
1410		result = sevent->result;
1411		if (result == ISC_R_SUCCESS) {
1412			client->peeraddr = sevent->address;
1413			client->peeraddr_valid = ISC_TRUE;
1414		}
1415		if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1416			client->attributes |= NS_CLIENTATTR_PKTINFO;
1417			client->pktinfo = sevent->pktinfo;
1418		}
1419		if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
1420			client->attributes |= NS_CLIENTATTR_MULTICAST;
1421		client->nrecvs--;
1422	} else {
1423		INSIST(TCP_CLIENT(client));
1424		REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
1425		REQUIRE(event->ev_sender == &client->tcpmsg);
1426		buffer = &client->tcpmsg.buffer;
1427		result = client->tcpmsg.result;
1428		INSIST(client->nreads == 1);
1429		/*
1430		 * client->peeraddr was set when the connection was accepted.
1431		 */
1432		client->nreads--;
1433	}
1434
1435	if (exit_check(client))
1436		goto cleanup;
1437	client->state = client->newstate = NS_CLIENTSTATE_WORKING;
1438
1439	isc_task_getcurrenttime(task, &client->requesttime);
1440	client->now = client->requesttime;
1441
1442	if (result != ISC_R_SUCCESS) {
1443		if (TCP_CLIENT(client)) {
1444			ns_client_next(client, result);
1445		} else {
1446			if  (result != ISC_R_CANCELED)
1447				isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
1448					      NS_LOGMODULE_CLIENT,
1449					      ISC_LOG_ERROR,
1450					      "UDP client handler shutting "
1451					      "down due to fatal receive "
1452					      "error: %s",
1453					      isc_result_totext(result));
1454			isc_task_shutdown(client->task);
1455		}
1456		goto cleanup;
1457	}
1458
1459	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1460
1461#if NS_CLIENT_DROPPORT
1462	if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1463	    DROPPORT_REQUEST) {
1464		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1465			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1466			      "dropped request: suspicious port");
1467		ns_client_next(client, ISC_R_SUCCESS);
1468		goto cleanup;
1469	}
1470#endif
1471
1472	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1473		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1474		      "%s request",
1475		      TCP_CLIENT(client) ? "TCP" : "UDP");
1476
1477	/*
1478	 * Check the blackhole ACL for UDP only, since TCP is done in
1479	 * client_newconn.
1480	 */
1481	if (!TCP_CLIENT(client)) {
1482
1483		if (ns_g_server->blackholeacl != NULL &&
1484		    dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
1485				  &ns_g_server->aclenv,
1486				  &match, NULL) == ISC_R_SUCCESS &&
1487		    match > 0)
1488		{
1489			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1490				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1491				      "blackholed UDP datagram");
1492			ns_client_next(client, ISC_R_SUCCESS);
1493			goto cleanup;
1494		}
1495	}
1496
1497	/*
1498	 * Silently drop multicast requests for the present.
1499	 * XXXMPA revisit this as mDNS spec was published.
1500	 */
1501	if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
1502		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1503			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1504			      "dropping multicast request");
1505		ns_client_next(client, DNS_R_REFUSED);
1506		goto cleanup;
1507	}
1508
1509	result = dns_message_peekheader(buffer, &id, &flags);
1510	if (result != ISC_R_SUCCESS) {
1511		/*
1512		 * There isn't enough header to determine whether
1513		 * this was a request or a response.  Drop it.
1514		 */
1515		ns_client_next(client, result);
1516		goto cleanup;
1517	}
1518
1519	/*
1520	 * The client object handles requests, not responses.
1521	 * If this is a UDP response, forward it to the dispatcher.
1522	 * If it's a TCP response, discard it here.
1523	 */
1524	if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1525		if (TCP_CLIENT(client)) {
1526			CTRACE("unexpected response");
1527			ns_client_next(client, DNS_R_FORMERR);
1528			goto cleanup;
1529		} else {
1530			dns_dispatch_importrecv(client->dispatch, event);
1531			ns_client_next(client, ISC_R_SUCCESS);
1532			goto cleanup;
1533		}
1534	}
1535
1536	/*
1537	 * Update some statistics counters.  Don't count responses.
1538	 */
1539	if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
1540		isc_stats_increment(ns_g_server->nsstats,
1541				    dns_nsstatscounter_requestv4);
1542	} else {
1543		isc_stats_increment(ns_g_server->nsstats,
1544				    dns_nsstatscounter_requestv6);
1545	}
1546	if (TCP_CLIENT(client))
1547		isc_stats_increment(ns_g_server->nsstats,
1548				    dns_nsstatscounter_tcp);
1549
1550	/*
1551	 * It's a request.  Parse it.
1552	 */
1553	result = dns_message_parse(client->message, buffer, 0);
1554	if (result != ISC_R_SUCCESS) {
1555		/*
1556		 * Parsing the request failed.  Send a response
1557		 * (typically FORMERR or SERVFAIL).
1558		 */
1559		ns_client_error(client, result);
1560		goto cleanup;
1561	}
1562
1563	dns_opcodestats_increment(ns_g_server->opcodestats,
1564				  client->message->opcode);
1565	switch (client->message->opcode) {
1566	case dns_opcode_query:
1567	case dns_opcode_update:
1568	case dns_opcode_notify:
1569		notimp = ISC_FALSE;
1570		break;
1571	case dns_opcode_iquery:
1572	default:
1573		notimp = ISC_TRUE;
1574		break;
1575	}
1576
1577	client->message->rcode = dns_rcode_noerror;
1578
1579	/* RFC1123 section 6.1.3.2 */
1580	if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1581		client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1582
1583	/*
1584	 * Deal with EDNS.
1585	 */
1586	opt = dns_message_getopt(client->message);
1587	if (opt != NULL) {
1588		/*
1589		 * Set the client's UDP buffer size.
1590		 */
1591		client->udpsize = opt->rdclass;
1592
1593		/*
1594		 * If the requested UDP buffer size is less than 512,
1595		 * ignore it and use 512.
1596		 */
1597		if (client->udpsize < 512)
1598			client->udpsize = 512;
1599
1600		/*
1601		 * Get the flags out of the OPT record.
1602		 */
1603		client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1604
1605		/*
1606		 * Do we understand this version of EDNS?
1607		 *
1608		 * XXXRTH need library support for this!
1609		 */
1610		client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1611		if (client->ednsversion > 0) {
1612			isc_stats_increment(ns_g_server->nsstats,
1613					    dns_nsstatscounter_badednsver);
1614			result = client_addopt(client);
1615			if (result == ISC_R_SUCCESS)
1616				result = DNS_R_BADVERS;
1617			ns_client_error(client, result);
1618			goto cleanup;
1619		}
1620
1621		/* Check for NSID request */
1622		result = dns_rdataset_first(opt);
1623		if (result == ISC_R_SUCCESS) {
1624			dns_rdata_init(&rdata);
1625			dns_rdataset_current(opt, &rdata);
1626			if (rdata.length >= 2) {
1627				isc_buffer_t nsidbuf;
1628				isc_buffer_init(&nsidbuf,
1629						rdata.data, rdata.length);
1630				isc_buffer_add(&nsidbuf, rdata.length);
1631				optcode = isc_buffer_getuint16(&nsidbuf);
1632				if (optcode == DNS_OPT_NSID)
1633					client->attributes |=
1634						NS_CLIENTATTR_WANTNSID;
1635			}
1636		}
1637
1638		isc_stats_increment(ns_g_server->nsstats,
1639				    dns_nsstatscounter_edns0in);
1640
1641		/*
1642		 * Create an OPT for our reply.
1643		 */
1644		result = client_addopt(client);
1645		if (result != ISC_R_SUCCESS) {
1646			ns_client_error(client, result);
1647			goto cleanup;
1648		}
1649	}
1650
1651	if (client->message->rdclass == 0) {
1652		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1653			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1654			      "message class could not be determined");
1655		ns_client_dumpmessage(client,
1656				      "message class could not be determined");
1657		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1658		goto cleanup;
1659	}
1660
1661	/*
1662	 * Determine the destination address.  If the receiving interface is
1663	 * bound to a specific address, we simply use it regardless of the
1664	 * address family.  All IPv4 queries should fall into this case.
1665	 * Otherwise, if this is a TCP query, get the address from the
1666	 * receiving socket (this needs a system call and can be heavy).
1667	 * For IPv6 UDP queries, we get this from the pktinfo structure (if
1668	 * supported).
1669	 * If all the attempts fail (this can happen due to memory shortage,
1670	 * etc), we regard this as an error for safety.
1671	 */
1672	if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1673		isc_netaddr_fromsockaddr(&client->destaddr,
1674					 &client->interface->addr);
1675	else {
1676		isc_sockaddr_t sockaddr;
1677		result = ISC_R_FAILURE;
1678
1679		if (TCP_CLIENT(client))
1680			result = isc_socket_getsockname(client->tcpsocket,
1681							&sockaddr);
1682		if (result == ISC_R_SUCCESS)
1683			isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
1684		if (result != ISC_R_SUCCESS &&
1685		    client->interface->addr.type.sa.sa_family == AF_INET6 &&
1686		    (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1687			/*
1688			 * XXXJT technically, we should convert the receiving
1689			 * interface ID to a proper scope zone ID.  However,
1690			 * due to the fact there is no standard API for this,
1691			 * we only handle link-local addresses and use the
1692			 * interface index as link ID.  Despite the assumption,
1693			 * it should cover most typical cases.
1694			 */
1695			isc_netaddr_fromin6(&client->destaddr,
1696					    &client->pktinfo.ipi6_addr);
1697			if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1698				isc_netaddr_setzone(&client->destaddr,
1699						client->pktinfo.ipi6_ifindex);
1700			result = ISC_R_SUCCESS;
1701		}
1702		if (result != ISC_R_SUCCESS) {
1703			UNEXPECTED_ERROR(__FILE__, __LINE__,
1704					 "failed to get request's "
1705					 "destination: %s",
1706					 isc_result_totext(result));
1707			ns_client_next(client, ISC_R_SUCCESS);
1708			goto cleanup;
1709		}
1710	}
1711
1712	/*
1713	 * Find a view that matches the client's source address.
1714	 */
1715	for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1716	     view != NULL;
1717	     view = ISC_LIST_NEXT(view, link)) {
1718		if (client->message->rdclass == view->rdclass ||
1719		    client->message->rdclass == dns_rdataclass_any)
1720		{
1721			dns_name_t *tsig = NULL;
1722
1723			sigresult = dns_message_rechecksig(client->message,
1724							   view);
1725			if (sigresult == ISC_R_SUCCESS)
1726				tsig = dns_tsigkey_identity(client->message->tsigkey);
1727
1728			if (allowed(&netaddr, tsig, view->matchclients) &&
1729			    allowed(&client->destaddr, tsig,
1730				    view->matchdestinations) &&
1731			    !((client->message->flags & DNS_MESSAGEFLAG_RD)
1732			      == 0 && view->matchrecursiveonly))
1733			{
1734				dns_view_attach(view, &client->view);
1735				break;
1736			}
1737		}
1738	}
1739
1740	if (view == NULL) {
1741		char classname[DNS_RDATACLASS_FORMATSIZE];
1742
1743		/*
1744		 * Do a dummy TSIG verification attempt so that the
1745		 * response will have a TSIG if the query did, as
1746		 * required by RFC2845.
1747		 */
1748		isc_buffer_t b;
1749		isc_region_t *r;
1750
1751		dns_message_resetsig(client->message);
1752
1753		r = dns_message_getrawmessage(client->message);
1754		isc_buffer_init(&b, r->base, r->length);
1755		isc_buffer_add(&b, r->length);
1756		(void)dns_tsig_verify(&b, client->message, NULL, NULL);
1757
1758		dns_rdataclass_format(client->message->rdclass, classname,
1759				      sizeof(classname));
1760		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1761			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1762			      "no matching view in class '%s'", classname);
1763		ns_client_dumpmessage(client, "no matching view in class");
1764		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1765		goto cleanup;
1766	}
1767
1768	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1769		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1770		      "using view '%s'", view->name);
1771
1772	/*
1773	 * Check for a signature.  We log bad signatures regardless of
1774	 * whether they ultimately cause the request to be rejected or
1775	 * not.  We do not log the lack of a signature unless we are
1776	 * debugging.
1777	 */
1778	client->signer = NULL;
1779	dns_name_init(&client->signername, NULL);
1780	result = dns_message_signer(client->message, &client->signername);
1781	if (result != ISC_R_NOTFOUND) {
1782		signame = NULL;
1783		if (dns_message_gettsig(client->message, &signame) != NULL) {
1784			isc_stats_increment(ns_g_server->nsstats,
1785					    dns_nsstatscounter_tsigin);
1786		} else {
1787			isc_stats_increment(ns_g_server->nsstats,
1788					    dns_nsstatscounter_sig0in);
1789		}
1790
1791	}
1792	if (result == ISC_R_SUCCESS) {
1793		char namebuf[DNS_NAME_FORMATSIZE];
1794		dns_name_format(&client->signername, namebuf, sizeof(namebuf));
1795		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1796			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1797			      "request has valid signature: %s", namebuf);
1798		client->signer = &client->signername;
1799	} else if (result == ISC_R_NOTFOUND) {
1800		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1801			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1802			      "request is not signed");
1803	} else if (result == DNS_R_NOIDENTITY) {
1804		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1805			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1806			      "request is signed by a nonauthoritative key");
1807	} else {
1808		char tsigrcode[64];
1809		isc_buffer_t b;
1810		dns_rcode_t status;
1811		isc_result_t tresult;
1812
1813		/* There is a signature, but it is bad. */
1814		isc_stats_increment(ns_g_server->nsstats,
1815				    dns_nsstatscounter_invalidsig);
1816		signame = NULL;
1817		if (dns_message_gettsig(client->message, &signame) != NULL) {
1818			char namebuf[DNS_NAME_FORMATSIZE];
1819			char cnamebuf[DNS_NAME_FORMATSIZE];
1820			dns_name_format(signame, namebuf, sizeof(namebuf));
1821			status = client->message->tsigstatus;
1822			isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1823			tresult = dns_tsigrcode_totext(status, &b);
1824			INSIST(tresult == ISC_R_SUCCESS);
1825			tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1826			if (client->message->tsigkey->generated) {
1827				dns_name_format(client->message->tsigkey->creator,
1828						cnamebuf, sizeof(cnamebuf));
1829				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1830					      NS_LOGMODULE_CLIENT,
1831					      ISC_LOG_ERROR,
1832					      "request has invalid signature: "
1833					      "TSIG %s (%s): %s (%s)", namebuf,
1834					      cnamebuf,
1835					      isc_result_totext(result),
1836					      tsigrcode);
1837			} else {
1838				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1839					      NS_LOGMODULE_CLIENT,
1840					      ISC_LOG_ERROR,
1841					      "request has invalid signature: "
1842					      "TSIG %s: %s (%s)", namebuf,
1843					      isc_result_totext(result),
1844					      tsigrcode);
1845			}
1846		} else {
1847			status = client->message->sig0status;
1848			isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1849			tresult = dns_tsigrcode_totext(status, &b);
1850			INSIST(tresult == ISC_R_SUCCESS);
1851			tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1852			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1853				      NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1854				      "request has invalid signature: %s (%s)",
1855				      isc_result_totext(result), tsigrcode);
1856		}
1857		/*
1858		 * Accept update messages signed by unknown keys so that
1859		 * update forwarding works transparently through slaves
1860		 * that don't have all the same keys as the master.
1861		 */
1862		if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
1863		      client->message->opcode == dns_opcode_update)) {
1864			ns_client_error(client, sigresult);
1865			goto cleanup;
1866		}
1867	}
1868
1869	/*
1870	 * Decide whether recursive service is available to this client.
1871	 * We do this here rather than in the query code so that we can
1872	 * set the RA bit correctly on all kinds of responses, not just
1873	 * responses to ordinary queries.  Note if you can't query the
1874	 * cache there is no point in setting RA.
1875	 */
1876	ra = ISC_FALSE;
1877	if (client->view->resolver != NULL &&
1878	    client->view->recursion == ISC_TRUE &&
1879	    ns_client_checkaclsilent(client, NULL,
1880				     client->view->recursionacl,
1881				     ISC_TRUE) == ISC_R_SUCCESS &&
1882	    ns_client_checkaclsilent(client, NULL,
1883				     client->view->cacheacl,
1884				     ISC_TRUE) == ISC_R_SUCCESS &&
1885	    ns_client_checkaclsilent(client, &client->destaddr,
1886				     client->view->recursiononacl,
1887				     ISC_TRUE) == ISC_R_SUCCESS &&
1888	    ns_client_checkaclsilent(client, &client->destaddr,
1889				     client->view->cacheonacl,
1890				     ISC_TRUE) == ISC_R_SUCCESS)
1891		ra = ISC_TRUE;
1892
1893	if (ra == ISC_TRUE)
1894		client->attributes |= NS_CLIENTATTR_RA;
1895
1896	ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1897		      ISC_LOG_DEBUG(3), ra ? "recursion available" :
1898					     "recursion not available");
1899
1900	/*
1901	 * Adjust maximum UDP response size for this client.
1902	 */
1903	if (client->udpsize > 512) {
1904		dns_peer_t *peer = NULL;
1905		isc_uint16_t udpsize = view->maxudp;
1906		(void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
1907		if (peer != NULL)
1908			dns_peer_getmaxudp(peer, &udpsize);
1909		if (client->udpsize > udpsize)
1910			client->udpsize = udpsize;
1911	}
1912
1913	/*
1914	 * Dispatch the request.
1915	 */
1916	switch (client->message->opcode) {
1917	case dns_opcode_query:
1918		CTRACE("query");
1919		ns_query_start(client);
1920		break;
1921	case dns_opcode_update:
1922		CTRACE("update");
1923		ns_client_settimeout(client, 60);
1924		ns_update_start(client, sigresult);
1925		break;
1926	case dns_opcode_notify:
1927		CTRACE("notify");
1928		ns_client_settimeout(client, 60);
1929		ns_notify_start(client);
1930		break;
1931	case dns_opcode_iquery:
1932		CTRACE("iquery");
1933		ns_client_error(client, DNS_R_NOTIMP);
1934		break;
1935	default:
1936		CTRACE("unknown opcode");
1937		ns_client_error(client, DNS_R_NOTIMP);
1938	}
1939
1940 cleanup:
1941	return;
1942}
1943
1944static void
1945client_timeout(isc_task_t *task, isc_event_t *event) {
1946	ns_client_t *client;
1947
1948	REQUIRE(event != NULL);
1949	REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
1950		event->ev_type == ISC_TIMEREVENT_IDLE);
1951	client = event->ev_arg;
1952	REQUIRE(NS_CLIENT_VALID(client));
1953	REQUIRE(task == client->task);
1954	REQUIRE(client->timer != NULL);
1955
1956	UNUSED(task);
1957
1958	CTRACE("timeout");
1959
1960	isc_event_free(&event);
1961
1962	if (client->shutdown != NULL) {
1963		(client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
1964		client->shutdown = NULL;
1965		client->shutdown_arg = NULL;
1966	}
1967
1968	if (client->newstate > NS_CLIENTSTATE_READY)
1969		client->newstate = NS_CLIENTSTATE_READY;
1970	(void)exit_check(client);
1971}
1972
1973static isc_result_t
1974get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
1975	isc_mem_t *clientmctx;
1976	isc_result_t result;
1977
1978	/*
1979	 * Caller must be holding the manager lock.
1980	 */
1981	if (ns_g_clienttest) {
1982		result = isc_mem_create(0, 0, mctxp);
1983		if (result == ISC_R_SUCCESS)
1984			isc_mem_setname(*mctxp, "client", NULL);
1985		return (result);
1986	}
1987#if NMCTXS > 0
1988	INSIST(manager->nextmctx < NMCTXS);
1989	clientmctx = manager->mctxpool[manager->nextmctx];
1990	if (clientmctx == NULL) {
1991		result = isc_mem_create(0, 0, &clientmctx);
1992		if (result != ISC_R_SUCCESS)
1993			return (result);
1994		isc_mem_setname(clientmctx, "client", NULL);
1995
1996		manager->mctxpool[manager->nextmctx] = clientmctx;
1997	}
1998	manager->nextmctx++;
1999	if (manager->nextmctx == NMCTXS)
2000		manager->nextmctx = 0;
2001#else
2002	clientmctx = manager->mctx;
2003#endif
2004
2005	isc_mem_attach(clientmctx, mctxp);
2006
2007	return (ISC_R_SUCCESS);
2008}
2009
2010static isc_result_t
2011client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
2012	ns_client_t *client;
2013	isc_result_t result;
2014	isc_mem_t *mctx = NULL;
2015
2016	/*
2017	 * Caller must be holding the manager lock.
2018	 *
2019	 * Note: creating a client does not add the client to the
2020	 * manager's client list or set the client's manager pointer.
2021	 * The caller is responsible for that.
2022	 */
2023
2024	REQUIRE(clientp != NULL && *clientp == NULL);
2025
2026	result = get_clientmctx(manager, &mctx);
2027	if (result != ISC_R_SUCCESS)
2028		return (result);
2029
2030	client = isc_mem_get(mctx, sizeof(*client));
2031	if (client == NULL) {
2032		isc_mem_detach(&mctx);
2033		return (ISC_R_NOMEMORY);
2034	}
2035	client->mctx = mctx;
2036
2037	client->task = NULL;
2038	result = isc_task_create(manager->taskmgr, 0, &client->task);
2039	if (result != ISC_R_SUCCESS)
2040		goto cleanup_client;
2041	isc_task_setname(client->task, "client", client);
2042
2043	client->timer = NULL;
2044	result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
2045				  NULL, NULL, client->task, client_timeout,
2046				  client, &client->timer);
2047	if (result != ISC_R_SUCCESS)
2048		goto cleanup_task;
2049	client->timerset = ISC_FALSE;
2050
2051	client->message = NULL;
2052	result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
2053				    &client->message);
2054	if (result != ISC_R_SUCCESS)
2055		goto cleanup_timer;
2056
2057	/* XXXRTH  Hardwired constants */
2058
2059	client->sendevent = (isc_socketevent_t *)
2060			    isc_event_allocate(client->mctx, client,
2061					       ISC_SOCKEVENT_SENDDONE,
2062					       client_senddone, client,
2063					       sizeof(isc_socketevent_t));
2064	if (client->sendevent == NULL) {
2065		result = ISC_R_NOMEMORY;
2066		goto cleanup_message;
2067	}
2068
2069	client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
2070	if  (client->recvbuf == NULL) {
2071		result = ISC_R_NOMEMORY;
2072		goto cleanup_sendevent;
2073	}
2074
2075	client->recvevent = (isc_socketevent_t *)
2076			    isc_event_allocate(client->mctx, client,
2077					       ISC_SOCKEVENT_RECVDONE,
2078					       client_request, client,
2079					       sizeof(isc_socketevent_t));
2080	if (client->recvevent == NULL) {
2081		result = ISC_R_NOMEMORY;
2082		goto cleanup_recvbuf;
2083	}
2084
2085	client->magic = NS_CLIENT_MAGIC;
2086	client->manager = NULL;
2087	client->state = NS_CLIENTSTATE_INACTIVE;
2088	client->newstate = NS_CLIENTSTATE_MAX;
2089	client->naccepts = 0;
2090	client->nreads = 0;
2091	client->nsends = 0;
2092	client->nrecvs = 0;
2093	client->nupdates = 0;
2094	client->nctls = 0;
2095	client->references = 0;
2096	client->attributes = 0;
2097	client->view = NULL;
2098	client->dispatch = NULL;
2099	client->udpsocket = NULL;
2100	client->tcplistener = NULL;
2101	client->tcpsocket = NULL;
2102	client->tcpmsg_valid = ISC_FALSE;
2103	client->tcpbuf = NULL;
2104	client->opt = NULL;
2105	client->udpsize = 512;
2106	client->extflags = 0;
2107	client->ednsversion = -1;
2108	client->next = NULL;
2109	client->shutdown = NULL;
2110	client->shutdown_arg = NULL;
2111	client->signer = NULL;
2112	dns_name_init(&client->signername, NULL);
2113	client->mortal = ISC_FALSE;
2114	client->tcpquota = NULL;
2115	client->recursionquota = NULL;
2116	client->interface = NULL;
2117	client->peeraddr_valid = ISC_FALSE;
2118#ifdef ALLOW_FILTER_AAAA_ON_V4
2119	client->filter_aaaa = dns_v4_aaaa_ok;
2120#endif
2121	ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
2122		       NS_EVENT_CLIENTCONTROL, client_start, client, client,
2123		       NULL, NULL);
2124	/*
2125	 * Initialize FORMERR cache to sentinel value that will not match
2126	 * any actual FORMERR response.
2127	 */
2128	isc_sockaddr_any(&client->formerrcache.addr);
2129	client->formerrcache.time = 0;
2130	client->formerrcache.id = 0;
2131	ISC_LINK_INIT(client, link);
2132	client->list = NULL;
2133
2134	/*
2135	 * We call the init routines for the various kinds of client here,
2136	 * after we have created an otherwise valid client, because some
2137	 * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
2138	 */
2139	result = ns_query_init(client);
2140	if (result != ISC_R_SUCCESS)
2141		goto cleanup_recvevent;
2142
2143	result = isc_task_onshutdown(client->task, client_shutdown, client);
2144	if (result != ISC_R_SUCCESS)
2145		goto cleanup_query;
2146
2147	client->needshutdown = ns_g_clienttest;
2148
2149	CTRACE("create");
2150
2151	*clientp = client;
2152
2153	return (ISC_R_SUCCESS);
2154
2155 cleanup_query:
2156	ns_query_free(client);
2157
2158 cleanup_recvevent:
2159	isc_event_free((isc_event_t **)&client->recvevent);
2160
2161 cleanup_recvbuf:
2162	isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
2163
2164 cleanup_sendevent:
2165	isc_event_free((isc_event_t **)&client->sendevent);
2166
2167	client->magic = 0;
2168
2169 cleanup_message:
2170	dns_message_destroy(&client->message);
2171
2172 cleanup_timer:
2173	isc_timer_detach(&client->timer);
2174
2175 cleanup_task:
2176	isc_task_detach(&client->task);
2177
2178 cleanup_client:
2179	isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
2180
2181	return (result);
2182}
2183
2184static void
2185client_read(ns_client_t *client) {
2186	isc_result_t result;
2187
2188	CTRACE("read");
2189
2190	result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
2191					client_request, client);
2192	if (result != ISC_R_SUCCESS)
2193		goto fail;
2194
2195	/*
2196	 * Set a timeout to limit the amount of time we will wait
2197	 * for a request on this TCP connection.
2198	 */
2199	ns_client_settimeout(client, 30);
2200
2201	client->state = client->newstate = NS_CLIENTSTATE_READING;
2202	INSIST(client->nreads == 0);
2203	INSIST(client->recursionquota == NULL);
2204	client->nreads++;
2205
2206	return;
2207 fail:
2208	ns_client_next(client, result);
2209}
2210
2211static void
2212client_newconn(isc_task_t *task, isc_event_t *event) {
2213	ns_client_t *client = event->ev_arg;
2214	isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
2215	isc_result_t result;
2216
2217	REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
2218	REQUIRE(NS_CLIENT_VALID(client));
2219	REQUIRE(client->task == task);
2220
2221	UNUSED(task);
2222
2223	INSIST(client->state == NS_CLIENTSTATE_READY);
2224
2225	INSIST(client->naccepts == 1);
2226	client->naccepts--;
2227
2228	LOCK(&client->interface->lock);
2229	INSIST(client->interface->ntcpcurrent > 0);
2230	client->interface->ntcpcurrent--;
2231	UNLOCK(&client->interface->lock);
2232
2233	/*
2234	 * We must take ownership of the new socket before the exit
2235	 * check to make sure it gets destroyed if we decide to exit.
2236	 */
2237	if (nevent->result == ISC_R_SUCCESS) {
2238		client->tcpsocket = nevent->newsocket;
2239		isc_socket_setname(client->tcpsocket, "client-tcp", NULL);
2240		client->state = NS_CLIENTSTATE_READING;
2241		INSIST(client->recursionquota == NULL);
2242
2243		(void)isc_socket_getpeername(client->tcpsocket,
2244					     &client->peeraddr);
2245		client->peeraddr_valid = ISC_TRUE;
2246		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2247			   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2248			   "new TCP connection");
2249	} else {
2250		/*
2251		 * XXXRTH  What should we do?  We're trying to accept but
2252		 *	   it didn't work.  If we just give up, then TCP
2253		 *	   service may eventually stop.
2254		 *
2255		 *	   For now, we just go idle.
2256		 *
2257		 *	   Going idle is probably the right thing if the
2258		 *	   I/O was canceled.
2259		 */
2260		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2261			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2262			      "accept failed: %s",
2263			      isc_result_totext(nevent->result));
2264	}
2265
2266	if (exit_check(client))
2267		goto freeevent;
2268
2269	if (nevent->result == ISC_R_SUCCESS) {
2270		int match;
2271		isc_netaddr_t netaddr;
2272
2273		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2274
2275		if (ns_g_server->blackholeacl != NULL &&
2276		    dns_acl_match(&netaddr, NULL,
2277				  ns_g_server->blackholeacl,
2278				  &ns_g_server->aclenv,
2279				  &match, NULL) == ISC_R_SUCCESS &&
2280		    match > 0)
2281		{
2282			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2283				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2284				      "blackholed connection attempt");
2285			client->newstate = NS_CLIENTSTATE_READY;
2286			(void)exit_check(client);
2287			goto freeevent;
2288		}
2289
2290		INSIST(client->tcpmsg_valid == ISC_FALSE);
2291		dns_tcpmsg_init(client->mctx, client->tcpsocket,
2292				&client->tcpmsg);
2293		client->tcpmsg_valid = ISC_TRUE;
2294
2295		/*
2296		 * Let a new client take our place immediately, before
2297		 * we wait for a request packet.  If we don't,
2298		 * telnetting to port 53 (once per CPU) will
2299		 * deny service to legitimate TCP clients.
2300		 */
2301		result = isc_quota_attach(&ns_g_server->tcpquota,
2302					  &client->tcpquota);
2303		if (result == ISC_R_SUCCESS)
2304			result = ns_client_replace(client);
2305		if (result != ISC_R_SUCCESS) {
2306			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2307				      NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
2308				      "no more TCP clients: %s",
2309				      isc_result_totext(result));
2310		}
2311
2312		client_read(client);
2313	}
2314
2315 freeevent:
2316	isc_event_free(&event);
2317}
2318
2319static void
2320client_accept(ns_client_t *client) {
2321	isc_result_t result;
2322
2323	CTRACE("accept");
2324
2325	result = isc_socket_accept(client->tcplistener, client->task,
2326				   client_newconn, client);
2327	if (result != ISC_R_SUCCESS) {
2328		UNEXPECTED_ERROR(__FILE__, __LINE__,
2329				 "isc_socket_accept() failed: %s",
2330				 isc_result_totext(result));
2331		/*
2332		 * XXXRTH  What should we do?  We're trying to accept but
2333		 *	   it didn't work.  If we just give up, then TCP
2334		 *	   service may eventually stop.
2335		 *
2336		 *	   For now, we just go idle.
2337		 */
2338		return;
2339	}
2340	INSIST(client->naccepts == 0);
2341	client->naccepts++;
2342	LOCK(&client->interface->lock);
2343	client->interface->ntcpcurrent++;
2344	UNLOCK(&client->interface->lock);
2345}
2346
2347static void
2348client_udprecv(ns_client_t *client) {
2349	isc_result_t result;
2350	isc_region_t r;
2351
2352	CTRACE("udprecv");
2353
2354	r.base = client->recvbuf;
2355	r.length = RECV_BUFFER_SIZE;
2356	result = isc_socket_recv2(client->udpsocket, &r, 1,
2357				  client->task, client->recvevent, 0);
2358	if (result != ISC_R_SUCCESS) {
2359		UNEXPECTED_ERROR(__FILE__, __LINE__,
2360				 "isc_socket_recv2() failed: %s",
2361				 isc_result_totext(result));
2362		/*
2363		 * This cannot happen in the current implementation, since
2364		 * isc_socket_recv2() cannot fail if flags == 0.
2365		 *
2366		 * If this does fail, we just go idle.
2367		 */
2368		return;
2369	}
2370	INSIST(client->nrecvs == 0);
2371	client->nrecvs++;
2372}
2373
2374void
2375ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
2376	REQUIRE(NS_CLIENT_VALID(source));
2377	REQUIRE(targetp != NULL && *targetp == NULL);
2378
2379	source->references++;
2380	ns_client_log(source, NS_LOGCATEGORY_CLIENT,
2381		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2382		      "ns_client_attach: ref = %d", source->references);
2383	*targetp = source;
2384}
2385
2386void
2387ns_client_detach(ns_client_t **clientp) {
2388	ns_client_t *client = *clientp;
2389
2390	client->references--;
2391	INSIST(client->references >= 0);
2392	*clientp = NULL;
2393	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2394		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2395		      "ns_client_detach: ref = %d", client->references);
2396	(void)exit_check(client);
2397}
2398
2399isc_boolean_t
2400ns_client_shuttingdown(ns_client_t *client) {
2401	return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
2402}
2403
2404isc_result_t
2405ns_client_replace(ns_client_t *client) {
2406	isc_result_t result;
2407
2408	CTRACE("replace");
2409
2410	REQUIRE(client != NULL);
2411	REQUIRE(client->manager != NULL);
2412
2413	result = ns_clientmgr_createclients(client->manager,
2414					    1, client->interface,
2415					    (TCP_CLIENT(client) ?
2416					     ISC_TRUE : ISC_FALSE));
2417	if (result != ISC_R_SUCCESS)
2418		return (result);
2419
2420	/*
2421	 * The responsibility for listening for new requests is hereby
2422	 * transferred to the new client.  Therefore, the old client
2423	 * should refrain from listening for any more requests.
2424	 */
2425	client->mortal = ISC_TRUE;
2426
2427	return (ISC_R_SUCCESS);
2428}
2429
2430/***
2431 *** Client Manager
2432 ***/
2433
2434static void
2435clientmgr_destroy(ns_clientmgr_t *manager) {
2436#if NMCTXS > 0
2437	int i;
2438#endif
2439
2440	REQUIRE(ISC_LIST_EMPTY(manager->active));
2441	REQUIRE(ISC_LIST_EMPTY(manager->inactive));
2442	REQUIRE(ISC_LIST_EMPTY(manager->recursing));
2443
2444	MTRACE("clientmgr_destroy");
2445
2446#if NMCTXS > 0
2447	for (i = 0; i < NMCTXS; i++) {
2448		if (manager->mctxpool[i] != NULL)
2449			isc_mem_detach(&manager->mctxpool[i]);
2450	}
2451#endif
2452
2453	DESTROYLOCK(&manager->lock);
2454	manager->magic = 0;
2455	isc_mem_put(manager->mctx, manager, sizeof(*manager));
2456}
2457
2458isc_result_t
2459ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2460		    isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
2461{
2462	ns_clientmgr_t *manager;
2463	isc_result_t result;
2464#if NMCTXS > 0
2465	int i;
2466#endif
2467
2468	manager = isc_mem_get(mctx, sizeof(*manager));
2469	if (manager == NULL)
2470		return (ISC_R_NOMEMORY);
2471
2472	result = isc_mutex_init(&manager->lock);
2473	if (result != ISC_R_SUCCESS)
2474		goto cleanup_manager;
2475
2476	manager->mctx = mctx;
2477	manager->taskmgr = taskmgr;
2478	manager->timermgr = timermgr;
2479	manager->exiting = ISC_FALSE;
2480	ISC_LIST_INIT(manager->active);
2481	ISC_LIST_INIT(manager->inactive);
2482	ISC_LIST_INIT(manager->recursing);
2483#if NMCTXS > 0
2484	manager->nextmctx = 0;
2485	for (i = 0; i < NMCTXS; i++)
2486		manager->mctxpool[i] = NULL; /* will be created on-demand */
2487#endif
2488	manager->magic = MANAGER_MAGIC;
2489
2490	MTRACE("create");
2491
2492	*managerp = manager;
2493
2494	return (ISC_R_SUCCESS);
2495
2496 cleanup_manager:
2497	isc_mem_put(manager->mctx, manager, sizeof(*manager));
2498
2499	return (result);
2500}
2501
2502void
2503ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2504	ns_clientmgr_t *manager;
2505	ns_client_t *client;
2506	isc_boolean_t need_destroy = ISC_FALSE;
2507
2508	REQUIRE(managerp != NULL);
2509	manager = *managerp;
2510	REQUIRE(VALID_MANAGER(manager));
2511
2512	MTRACE("destroy");
2513
2514	LOCK(&manager->lock);
2515
2516	manager->exiting = ISC_TRUE;
2517
2518	for (client = ISC_LIST_HEAD(manager->recursing);
2519	     client != NULL;
2520	     client = ISC_LIST_NEXT(client, link))
2521		isc_task_shutdown(client->task);
2522
2523	for (client = ISC_LIST_HEAD(manager->active);
2524	     client != NULL;
2525	     client = ISC_LIST_NEXT(client, link))
2526		isc_task_shutdown(client->task);
2527
2528	for (client = ISC_LIST_HEAD(manager->inactive);
2529	     client != NULL;
2530	     client = ISC_LIST_NEXT(client, link))
2531		isc_task_shutdown(client->task);
2532
2533	if (ISC_LIST_EMPTY(manager->active) &&
2534	    ISC_LIST_EMPTY(manager->inactive) &&
2535	    ISC_LIST_EMPTY(manager->recursing))
2536		need_destroy = ISC_TRUE;
2537
2538	UNLOCK(&manager->lock);
2539
2540	if (need_destroy)
2541		clientmgr_destroy(manager);
2542
2543	*managerp = NULL;
2544}
2545
2546isc_result_t
2547ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
2548			   ns_interface_t *ifp, isc_boolean_t tcp)
2549{
2550	isc_result_t result = ISC_R_SUCCESS;
2551	unsigned int i;
2552	ns_client_t *client;
2553
2554	REQUIRE(VALID_MANAGER(manager));
2555	REQUIRE(n > 0);
2556
2557	MTRACE("createclients");
2558
2559	/*
2560	 * We MUST lock the manager lock for the entire client creation
2561	 * process.  If we didn't do this, then a client could get a
2562	 * shutdown event and disappear out from under us.
2563	 */
2564
2565	LOCK(&manager->lock);
2566
2567	for (i = 0; i < n; i++) {
2568		isc_event_t *ev;
2569		/*
2570		 * Allocate a client.  First try to get a recycled one;
2571		 * if that fails, make a new one.
2572		 */
2573		client = NULL;
2574		if (!ns_g_clienttest)
2575			client = ISC_LIST_HEAD(manager->inactive);
2576		if (client != NULL) {
2577			MTRACE("recycle");
2578			ISC_LIST_UNLINK(manager->inactive, client, link);
2579			client->list = NULL;
2580		} else {
2581			MTRACE("create new");
2582			result = client_create(manager, &client);
2583			if (result != ISC_R_SUCCESS)
2584				break;
2585		}
2586
2587		ns_interface_attach(ifp, &client->interface);
2588		client->state = NS_CLIENTSTATE_READY;
2589		INSIST(client->recursionquota == NULL);
2590
2591		if (tcp) {
2592			client->attributes |= NS_CLIENTATTR_TCP;
2593			isc_socket_attach(ifp->tcpsocket,
2594					  &client->tcplistener);
2595		} else {
2596			isc_socket_t *sock;
2597
2598			dns_dispatch_attach(ifp->udpdispatch,
2599					    &client->dispatch);
2600			sock = dns_dispatch_getsocket(client->dispatch);
2601			isc_socket_attach(sock, &client->udpsocket);
2602		}
2603		client->manager = manager;
2604		ISC_LIST_APPEND(manager->active, client, link);
2605		client->list = &manager->active;
2606
2607		INSIST(client->nctls == 0);
2608		client->nctls++;
2609		ev = &client->ctlevent;
2610		isc_task_send(client->task, &ev);
2611	}
2612	if (i != 0) {
2613		/*
2614		 * We managed to create at least one client, so we
2615		 * declare victory.
2616		 */
2617		result = ISC_R_SUCCESS;
2618	}
2619
2620	UNLOCK(&manager->lock);
2621
2622	return (result);
2623}
2624
2625isc_sockaddr_t *
2626ns_client_getsockaddr(ns_client_t *client) {
2627	return (&client->peeraddr);
2628}
2629
2630isc_result_t
2631ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
2632			 dns_acl_t *acl, isc_boolean_t default_allow)
2633{
2634	isc_result_t result;
2635	isc_netaddr_t tmpnetaddr;
2636	int match;
2637
2638	if (acl == NULL) {
2639		if (default_allow)
2640			goto allow;
2641		else
2642			goto deny;
2643	}
2644
2645	if (netaddr == NULL) {
2646		isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
2647		netaddr = &tmpnetaddr;
2648	}
2649
2650	result = dns_acl_match(netaddr, client->signer, acl,
2651			       &ns_g_server->aclenv, &match, NULL);
2652
2653	if (result != ISC_R_SUCCESS)
2654		goto deny; /* Internal error, already logged. */
2655	if (match > 0)
2656		goto allow;
2657	goto deny; /* Negative match or no match. */
2658
2659 allow:
2660	return (ISC_R_SUCCESS);
2661
2662 deny:
2663	return (DNS_R_REFUSED);
2664}
2665
2666isc_result_t
2667ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
2668		   const char *opname, dns_acl_t *acl,
2669		   isc_boolean_t default_allow, int log_level)
2670{
2671	isc_result_t result;
2672	isc_netaddr_t netaddr;
2673
2674	if (sockaddr != NULL)
2675		isc_netaddr_fromsockaddr(&netaddr, sockaddr);
2676
2677	result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
2678					  acl, default_allow);
2679
2680	if (result == ISC_R_SUCCESS)
2681		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2682			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2683			      "%s approved", opname);
2684	else
2685		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2686			      NS_LOGMODULE_CLIENT,
2687			      log_level, "%s denied", opname);
2688	return (result);
2689}
2690
2691static void
2692ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2693	if (client->peeraddr_valid)
2694		isc_sockaddr_format(&client->peeraddr, peerbuf, len);
2695	else
2696		snprintf(peerbuf, len, "@%p", client);
2697}
2698
2699void
2700ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2701	       isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2702{
2703	char msgbuf[2048];
2704	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2705	const char *name = "";
2706	const char *sep = "";
2707
2708	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2709	ns_client_name(client, peerbuf, sizeof(peerbuf));
2710	if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2711	    strcmp(client->view->name, "_default") != 0) {
2712		name = client->view->name;
2713		sep = ": view ";
2714	}
2715
2716	isc_log_write(ns_g_lctx, category, module, level,
2717		      "client %s%s%s: %s", peerbuf, sep, name, msgbuf);
2718}
2719
2720void
2721ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2722	   isc_logmodule_t *module, int level, const char *fmt, ...)
2723{
2724	va_list ap;
2725
2726	if (! isc_log_wouldlog(ns_g_lctx, level))
2727		return;
2728
2729	va_start(ap, fmt);
2730	ns_client_logv(client, category, module, level, fmt, ap);
2731	va_end(ap);
2732}
2733
2734void
2735ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
2736		 dns_rdataclass_t rdclass, char *buf, size_t len)
2737{
2738	char namebuf[DNS_NAME_FORMATSIZE];
2739	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2740	char classbuf[DNS_RDATACLASS_FORMATSIZE];
2741
2742	dns_name_format(name, namebuf, sizeof(namebuf));
2743	dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2744	dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2745	(void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2746		       classbuf);
2747}
2748
2749static void
2750ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2751	isc_buffer_t buffer;
2752	char *buf = NULL;
2753	int len = 1024;
2754	isc_result_t result;
2755
2756	/*
2757	 * Note that these are multiline debug messages.  We want a newline
2758	 * to appear in the log after each message.
2759	 */
2760
2761	do {
2762		buf = isc_mem_get(client->mctx, len);
2763		if (buf == NULL)
2764			break;
2765		isc_buffer_init(&buffer, buf, len);
2766		result = dns_message_totext(client->message,
2767					    &dns_master_style_debug,
2768					    0, &buffer);
2769		if (result == ISC_R_NOSPACE) {
2770			isc_mem_put(client->mctx, buf, len);
2771			len += 1024;
2772		} else if (result == ISC_R_SUCCESS)
2773			ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
2774				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2775				      "%s\n%.*s", reason,
2776				       (int)isc_buffer_usedlength(&buffer),
2777				       buf);
2778	} while (result == ISC_R_NOSPACE);
2779
2780	if (buf != NULL)
2781		isc_mem_put(client->mctx, buf, len);
2782}
2783
2784void
2785ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2786	ns_client_t *client;
2787	char namebuf[DNS_NAME_FORMATSIZE];
2788	char original[DNS_NAME_FORMATSIZE];
2789	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2790	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2791	char classbuf[DNS_RDATACLASS_FORMATSIZE];
2792	const char *name;
2793	const char *sep;
2794	const char *origfor;
2795	dns_rdataset_t *rdataset;
2796
2797	REQUIRE(VALID_MANAGER(manager));
2798
2799	LOCK(&manager->lock);
2800	client = ISC_LIST_HEAD(manager->recursing);
2801	while (client != NULL) {
2802		ns_client_name(client, peerbuf, sizeof(peerbuf));
2803		if (client->view != NULL &&
2804		    strcmp(client->view->name, "_bind") != 0 &&
2805		    strcmp(client->view->name, "_default") != 0) {
2806			name = client->view->name;
2807			sep = ": view ";
2808		} else {
2809			name = "";
2810			sep = "";
2811		}
2812		dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2813		if (client->query.qname != client->query.origqname &&
2814		    client->query.origqname != NULL) {
2815			origfor = " for ";
2816			dns_name_format(client->query.origqname, original,
2817					sizeof(original));
2818		} else {
2819			origfor = "";
2820			original[0] = '\0';
2821		}
2822		rdataset = ISC_LIST_HEAD(client->query.qname->list);
2823		if (rdataset == NULL && client->query.origqname != NULL)
2824			rdataset = ISC_LIST_HEAD(client->query.origqname->list);
2825		if (rdataset != NULL) {
2826			dns_rdatatype_format(rdataset->type, typebuf,
2827					     sizeof(typebuf));
2828			dns_rdataclass_format(rdataset->rdclass, classbuf,
2829					      sizeof(classbuf));
2830		} else {
2831			strcpy(typebuf, "-");
2832			strcpy(classbuf, "-");
2833		}
2834		fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s "
2835			"requesttime %d\n", peerbuf, sep, name,
2836			client->message->id, namebuf, typebuf, classbuf,
2837			origfor, original, client->requesttime);
2838		client = ISC_LIST_NEXT(client, link);
2839	}
2840	UNLOCK(&manager->lock);
2841}
2842
2843void
2844ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2845
2846	if (client->manager != NULL)
2847		LOCK(&client->manager->lock);
2848	if (client->query.restarts > 0) {
2849		/*
2850		 * client->query.qname was dynamically allocated.
2851		 */
2852		dns_message_puttempname(client->message,
2853					&client->query.qname);
2854	}
2855	client->query.qname = name;
2856	if (client->manager != NULL)
2857		UNLOCK(&client->manager->lock);
2858}
2859