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