client.c revision 225361
1/*
2 * Copyright (C) 2004-2011  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.2 2011-07-28 04:30:54 marka 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#ifdef ALLOW_FILTER_AAAA_ON_V4
938	/*
939	 * filter-aaaa-on-v4 yes or break-dnssec option to suppress
940	 * AAAA records
941	 * We already know that request came via IPv4,
942	 * that we have both AAAA and A records,
943	 * and that we either have no signatures that the client wants
944	 * or we are supposed to break DNSSEC.
945	 */
946	if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0)
947		render_opts |= DNS_MESSAGERENDER_FILTER_AAAA;
948#endif
949	preferred_glue = 0;
950	if (client->view != NULL) {
951		if (client->view->preferred_glue == dns_rdatatype_a)
952			preferred_glue = DNS_MESSAGERENDER_PREFER_A;
953		else if (client->view->preferred_glue == dns_rdatatype_aaaa)
954			preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
955	}
956
957	/*
958	 * XXXRTH  The following doesn't deal with TCP buffer resizing.
959	 */
960	result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
961				     sendbuf, &data);
962	if (result != ISC_R_SUCCESS)
963		goto done;
964
965	result = dns_compress_init(&cctx, -1, client->mctx);
966	if (result != ISC_R_SUCCESS)
967		goto done;
968	cleanup_cctx = ISC_TRUE;
969
970	result = dns_message_renderbegin(client->message, &cctx, &buffer);
971	if (result != ISC_R_SUCCESS)
972		goto done;
973
974	if (client->opt != NULL) {
975		result = dns_message_setopt(client->message, client->opt);
976		opt_included = ISC_TRUE;
977		client->opt = NULL;
978		if (result != ISC_R_SUCCESS)
979			goto done;
980	}
981	result = dns_message_rendersection(client->message,
982					   DNS_SECTION_QUESTION, 0);
983	if (result == ISC_R_NOSPACE) {
984		client->message->flags |= DNS_MESSAGEFLAG_TC;
985		goto renderend;
986	}
987	if (result != ISC_R_SUCCESS)
988		goto done;
989	result = dns_message_rendersection(client->message,
990					   DNS_SECTION_ANSWER,
991					   DNS_MESSAGERENDER_PARTIAL |
992					   render_opts);
993	if (result == ISC_R_NOSPACE) {
994		client->message->flags |= DNS_MESSAGEFLAG_TC;
995		goto renderend;
996	}
997	if (result != ISC_R_SUCCESS)
998		goto done;
999	result = dns_message_rendersection(client->message,
1000					   DNS_SECTION_AUTHORITY,
1001					   DNS_MESSAGERENDER_PARTIAL |
1002					   render_opts);
1003	if (result == ISC_R_NOSPACE) {
1004		client->message->flags |= DNS_MESSAGEFLAG_TC;
1005		goto renderend;
1006	}
1007	if (result != ISC_R_SUCCESS)
1008		goto done;
1009	result = dns_message_rendersection(client->message,
1010					   DNS_SECTION_ADDITIONAL,
1011					   preferred_glue | render_opts);
1012	if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
1013		goto done;
1014 renderend:
1015	result = dns_message_renderend(client->message);
1016
1017	if (result != ISC_R_SUCCESS)
1018		goto done;
1019
1020	if (cleanup_cctx) {
1021		dns_compress_invalidate(&cctx);
1022		cleanup_cctx = ISC_FALSE;
1023	}
1024
1025	if (TCP_CLIENT(client)) {
1026		isc_buffer_usedregion(&buffer, &r);
1027		isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
1028		isc_buffer_add(&tcpbuffer, r.length);
1029		result = client_sendpkg(client, &tcpbuffer);
1030	} else
1031		result = client_sendpkg(client, &buffer);
1032
1033	/* update statistics (XXXJT: is it okay to access message->xxxkey?) */
1034	isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response);
1035	if (opt_included) {
1036		isc_stats_increment(ns_g_server->nsstats,
1037				    dns_nsstatscounter_edns0out);
1038	}
1039	if (client->message->tsigkey != NULL) {
1040		isc_stats_increment(ns_g_server->nsstats,
1041				    dns_nsstatscounter_tsigout);
1042	}
1043	if (client->message->sig0key != NULL) {
1044		isc_stats_increment(ns_g_server->nsstats,
1045				    dns_nsstatscounter_sig0out);
1046	}
1047	if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
1048		isc_stats_increment(ns_g_server->nsstats,
1049				    dns_nsstatscounter_truncatedresp);
1050
1051	if (result == ISC_R_SUCCESS)
1052		return;
1053
1054 done:
1055	if (client->tcpbuf != NULL) {
1056		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
1057		client->tcpbuf = NULL;
1058	}
1059
1060	if (cleanup_cctx)
1061		dns_compress_invalidate(&cctx);
1062
1063	ns_client_next(client, result);
1064}
1065
1066#if NS_CLIENT_DROPPORT
1067#define DROPPORT_NO		0
1068#define DROPPORT_REQUEST	1
1069#define DROPPORT_RESPONSE	2
1070/*%
1071 * ns_client_dropport determines if certain requests / responses
1072 * should be dropped based on the port number.
1073 *
1074 * Returns:
1075 * \li	0:	Don't drop.
1076 * \li	1:	Drop request.
1077 * \li	2:	Drop (error) response.
1078 */
1079static int
1080ns_client_dropport(in_port_t port) {
1081	switch (port) {
1082	case 7: /* echo */
1083	case 13: /* daytime */
1084	case 19: /* chargen */
1085	case 37: /* time */
1086		return (DROPPORT_REQUEST);
1087	case 464: /* kpasswd */
1088		return (DROPPORT_RESPONSE);
1089	}
1090	return (DROPPORT_NO);
1091}
1092#endif
1093
1094void
1095ns_client_error(ns_client_t *client, isc_result_t result) {
1096	dns_rcode_t rcode;
1097	dns_message_t *message;
1098
1099	REQUIRE(NS_CLIENT_VALID(client));
1100
1101	CTRACE("error");
1102
1103	message = client->message;
1104	rcode = dns_result_torcode(result);
1105
1106#if NS_CLIENT_DROPPORT
1107	/*
1108	 * Don't send FORMERR to ports on the drop port list.
1109	 */
1110	if (rcode == dns_rcode_formerr &&
1111	    ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
1112	    DROPPORT_NO) {
1113		char buf[64];
1114		isc_buffer_t b;
1115
1116		isc_buffer_init(&b, buf, sizeof(buf) - 1);
1117		if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
1118			isc_buffer_putstr(&b, "UNKNOWN RCODE");
1119		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1120			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1121			      "dropped error (%.*s) response: suspicious port",
1122			      (int)isc_buffer_usedlength(&b), buf);
1123		ns_client_next(client, ISC_R_SUCCESS);
1124		return;
1125	}
1126#endif
1127
1128	/*
1129	 * Message may be an in-progress reply that we had trouble
1130	 * with, in which case QR will be set.  We need to clear QR before
1131	 * calling dns_message_reply() to avoid triggering an assertion.
1132	 */
1133	message->flags &= ~DNS_MESSAGEFLAG_QR;
1134	/*
1135	 * AA and AD shouldn't be set.
1136	 */
1137	message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
1138	result = dns_message_reply(message, ISC_TRUE);
1139	if (result != ISC_R_SUCCESS) {
1140		/*
1141		 * It could be that we've got a query with a good header,
1142		 * but a bad question section, so we try again with
1143		 * want_question_section set to ISC_FALSE.
1144		 */
1145		result = dns_message_reply(message, ISC_FALSE);
1146		if (result != ISC_R_SUCCESS) {
1147			ns_client_next(client, result);
1148			return;
1149		}
1150	}
1151	message->rcode = rcode;
1152
1153	/*
1154	 * FORMERR loop avoidance:  If we sent a FORMERR message
1155	 * with the same ID to the same client less than two
1156	 * seconds ago, assume that we are in an infinite error
1157	 * packet dialog with a server for some protocol whose
1158	 * error responses look enough like DNS queries to
1159	 * elicit a FORMERR response.  Drop a packet to break
1160	 * the loop.
1161	 */
1162	if (rcode == dns_rcode_formerr) {
1163		if (isc_sockaddr_equal(&client->peeraddr,
1164				       &client->formerrcache.addr) &&
1165		    message->id == client->formerrcache.id &&
1166		    client->requesttime - client->formerrcache.time < 2) {
1167			/* Drop packet. */
1168			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1169				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1170				      "possible error packet loop, "
1171				      "FORMERR dropped");
1172			ns_client_next(client, result);
1173			return;
1174		}
1175		client->formerrcache.addr = client->peeraddr;
1176		client->formerrcache.time = client->requesttime;
1177		client->formerrcache.id = message->id;
1178	}
1179	ns_client_send(client);
1180}
1181
1182static inline isc_result_t
1183client_addopt(ns_client_t *client) {
1184	dns_rdataset_t *rdataset;
1185	dns_rdatalist_t *rdatalist;
1186	dns_rdata_t *rdata;
1187	isc_result_t result;
1188	dns_view_t *view;
1189	dns_resolver_t *resolver;
1190	isc_uint16_t udpsize;
1191
1192	REQUIRE(client->opt == NULL);	/* XXXRTH free old. */
1193
1194	rdatalist = NULL;
1195	result = dns_message_gettemprdatalist(client->message, &rdatalist);
1196	if (result != ISC_R_SUCCESS)
1197		return (result);
1198	rdata = NULL;
1199	result = dns_message_gettemprdata(client->message, &rdata);
1200	if (result != ISC_R_SUCCESS)
1201		return (result);
1202	rdataset = NULL;
1203	result = dns_message_gettemprdataset(client->message, &rdataset);
1204	if (result != ISC_R_SUCCESS)
1205		return (result);
1206	dns_rdataset_init(rdataset);
1207
1208	rdatalist->type = dns_rdatatype_opt;
1209	rdatalist->covers = 0;
1210
1211	/*
1212	 * Set the maximum UDP buffer size.
1213	 */
1214	view = client->view;
1215	resolver = (view != NULL) ? view->resolver : NULL;
1216	if (resolver != NULL)
1217		udpsize = dns_resolver_getudpsize(resolver);
1218	else
1219		udpsize = ns_g_udpsize;
1220	rdatalist->rdclass = udpsize;
1221
1222	/*
1223	 * Set EXTENDED-RCODE, VERSION and Z to 0.
1224	 */
1225	rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);
1226
1227	/* Set EDNS options if applicable */
1228	if (client->attributes & NS_CLIENTATTR_WANTNSID &&
1229	    (ns_g_server->server_id != NULL ||
1230	     ns_g_server->server_usehostname)) {
1231		/*
1232		 * Space required for NSID data:
1233		 *   2 bytes for opt code
1234		 * + 2 bytes for NSID length
1235		 * + NSID itself
1236		 */
1237		char nsid[BUFSIZ], *nsidp;
1238		isc_buffer_t *buffer = NULL;
1239
1240		if (ns_g_server->server_usehostname) {
1241			isc_result_t result;
1242			result = ns_os_gethostname(nsid, sizeof(nsid));
1243			if (result != ISC_R_SUCCESS) {
1244				goto no_nsid;
1245			}
1246			nsidp = nsid;
1247		} else
1248			nsidp = ns_g_server->server_id;
1249
1250		rdata->length = strlen(nsidp) + 4;
1251		result = isc_buffer_allocate(client->mctx, &buffer,
1252					     rdata->length);
1253		if (result != ISC_R_SUCCESS)
1254			goto no_nsid;
1255
1256		isc_buffer_putuint16(buffer, DNS_OPT_NSID);
1257		isc_buffer_putuint16(buffer, strlen(nsidp));
1258		isc_buffer_putstr(buffer, nsidp);
1259		rdata->data = buffer->base;
1260		dns_message_takebuffer(client->message, &buffer);
1261	} else {
1262no_nsid:
1263		rdata->data = NULL;
1264		rdata->length = 0;
1265	}
1266
1267	rdata->rdclass = rdatalist->rdclass;
1268	rdata->type = rdatalist->type;
1269	rdata->flags = 0;
1270
1271	ISC_LIST_INIT(rdatalist->rdata);
1272	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1273	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
1274		      == ISC_R_SUCCESS);
1275
1276	client->opt = rdataset;
1277
1278	return (ISC_R_SUCCESS);
1279}
1280
1281static inline isc_boolean_t
1282allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
1283	int match;
1284	isc_result_t result;
1285
1286	if (acl == NULL)
1287		return (ISC_TRUE);
1288	result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
1289			       &match, NULL);
1290	if (result == ISC_R_SUCCESS && match > 0)
1291		return (ISC_TRUE);
1292	return (ISC_FALSE);
1293}
1294
1295/*
1296 * Callback to see if a non-recursive query coming from 'srcaddr' to
1297 * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1298 * delivered to 'myview'.
1299 *
1300 * We run this unlocked as both the view list and the interface list
1301 * are updated when the appropriate task has exclusivity.
1302 */
1303isc_boolean_t
1304ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
1305		 isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
1306		 dns_rdataclass_t rdclass, void *arg)
1307{
1308	dns_view_t *view;
1309	dns_tsigkey_t *key = NULL;
1310	dns_name_t *tsig = NULL;
1311	isc_netaddr_t netsrc;
1312	isc_netaddr_t netdst;
1313
1314	UNUSED(arg);
1315
1316	/*
1317	 * ns_g_server->interfacemgr is task exclusive locked.
1318	 */
1319	if (ns_g_server->interfacemgr == NULL)
1320		return (ISC_TRUE);
1321
1322	if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
1323		return (ISC_FALSE);
1324
1325	isc_netaddr_fromsockaddr(&netsrc, srcaddr);
1326	isc_netaddr_fromsockaddr(&netdst, dstaddr);
1327
1328	for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1329	     view != NULL;
1330	     view = ISC_LIST_NEXT(view, link)) {
1331
1332		if (view->matchrecursiveonly)
1333			continue;
1334
1335		if (rdclass != view->rdclass)
1336			continue;
1337
1338		if (mykey != NULL) {
1339			isc_boolean_t match;
1340			isc_result_t result;
1341
1342			result = dns_view_gettsig(view, &mykey->name, &key);
1343			if (result != ISC_R_SUCCESS)
1344				continue;
1345			match = dst_key_compare(mykey->key, key->key);
1346			dns_tsigkey_detach(&key);
1347			if (!match)
1348				continue;
1349			tsig = dns_tsigkey_identity(mykey);
1350		}
1351
1352		if (allowed(&netsrc, tsig, view->matchclients) &&
1353		    allowed(&netdst, tsig, view->matchdestinations))
1354			break;
1355	}
1356	return (ISC_TF(view == myview));
1357}
1358
1359/*
1360 * Handle an incoming request event from the socket (UDP case)
1361 * or tcpmsg (TCP case).
1362 */
1363static void
1364client_request(isc_task_t *task, isc_event_t *event) {
1365	ns_client_t *client;
1366	isc_socketevent_t *sevent;
1367	isc_result_t result;
1368	isc_result_t sigresult = ISC_R_SUCCESS;
1369	isc_buffer_t *buffer;
1370	isc_buffer_t tbuffer;
1371	dns_view_t *view;
1372	dns_rdataset_t *opt;
1373	dns_name_t *signame;
1374	isc_boolean_t ra;	/* Recursion available. */
1375	isc_netaddr_t netaddr;
1376	int match;
1377	dns_messageid_t id;
1378	unsigned int flags;
1379	isc_boolean_t notimp;
1380	dns_rdata_t rdata;
1381	isc_uint16_t optcode;
1382
1383	REQUIRE(event != NULL);
1384	client = event->ev_arg;
1385	REQUIRE(NS_CLIENT_VALID(client));
1386	REQUIRE(task == client->task);
1387
1388	INSIST(client->recursionquota == NULL);
1389
1390	INSIST(client->state ==
1391	       TCP_CLIENT(client) ?
1392	       NS_CLIENTSTATE_READING :
1393	       NS_CLIENTSTATE_READY);
1394
1395	ns_client_requests++;
1396
1397	if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
1398		INSIST(!TCP_CLIENT(client));
1399		sevent = (isc_socketevent_t *)event;
1400		REQUIRE(sevent == client->recvevent);
1401		isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
1402		isc_buffer_add(&tbuffer, sevent->n);
1403		buffer = &tbuffer;
1404		result = sevent->result;
1405		if (result == ISC_R_SUCCESS) {
1406			client->peeraddr = sevent->address;
1407			client->peeraddr_valid = ISC_TRUE;
1408		}
1409		if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1410			client->attributes |= NS_CLIENTATTR_PKTINFO;
1411			client->pktinfo = sevent->pktinfo;
1412		}
1413		if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
1414			client->attributes |= NS_CLIENTATTR_MULTICAST;
1415		client->nrecvs--;
1416	} else {
1417		INSIST(TCP_CLIENT(client));
1418		REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
1419		REQUIRE(event->ev_sender == &client->tcpmsg);
1420		buffer = &client->tcpmsg.buffer;
1421		result = client->tcpmsg.result;
1422		INSIST(client->nreads == 1);
1423		/*
1424		 * client->peeraddr was set when the connection was accepted.
1425		 */
1426		client->nreads--;
1427	}
1428
1429	if (exit_check(client))
1430		goto cleanup;
1431	client->state = client->newstate = NS_CLIENTSTATE_WORKING;
1432
1433	isc_task_getcurrenttime(task, &client->requesttime);
1434	client->now = client->requesttime;
1435
1436	if (result != ISC_R_SUCCESS) {
1437		if (TCP_CLIENT(client)) {
1438			ns_client_next(client, result);
1439		} else {
1440			if  (result != ISC_R_CANCELED)
1441				isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
1442					      NS_LOGMODULE_CLIENT,
1443					      ISC_LOG_ERROR,
1444					      "UDP client handler shutting "
1445					      "down due to fatal receive "
1446					      "error: %s",
1447					      isc_result_totext(result));
1448			isc_task_shutdown(client->task);
1449		}
1450		goto cleanup;
1451	}
1452
1453	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1454
1455#if NS_CLIENT_DROPPORT
1456	if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1457	    DROPPORT_REQUEST) {
1458		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1459			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1460			      "dropped request: suspicious port");
1461		ns_client_next(client, ISC_R_SUCCESS);
1462		goto cleanup;
1463	}
1464#endif
1465
1466	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1467		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1468		      "%s request",
1469		      TCP_CLIENT(client) ? "TCP" : "UDP");
1470
1471	/*
1472	 * Check the blackhole ACL for UDP only, since TCP is done in
1473	 * client_newconn.
1474	 */
1475	if (!TCP_CLIENT(client)) {
1476
1477		if (ns_g_server->blackholeacl != NULL &&
1478		    dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
1479				  &ns_g_server->aclenv,
1480				  &match, NULL) == ISC_R_SUCCESS &&
1481		    match > 0)
1482		{
1483			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1484				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1485				      "blackholed UDP datagram");
1486			ns_client_next(client, ISC_R_SUCCESS);
1487			goto cleanup;
1488		}
1489	}
1490
1491	/*
1492	 * Silently drop multicast requests for the present.
1493	 * XXXMPA revisit this as mDNS spec was published.
1494	 */
1495	if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
1496		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1497			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1498			      "dropping multicast request");
1499		ns_client_next(client, DNS_R_REFUSED);
1500		goto cleanup;
1501	}
1502
1503	result = dns_message_peekheader(buffer, &id, &flags);
1504	if (result != ISC_R_SUCCESS) {
1505		/*
1506		 * There isn't enough header to determine whether
1507		 * this was a request or a response.  Drop it.
1508		 */
1509		ns_client_next(client, result);
1510		goto cleanup;
1511	}
1512
1513	/*
1514	 * The client object handles requests, not responses.
1515	 * If this is a UDP response, forward it to the dispatcher.
1516	 * If it's a TCP response, discard it here.
1517	 */
1518	if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1519		if (TCP_CLIENT(client)) {
1520			CTRACE("unexpected response");
1521			ns_client_next(client, DNS_R_FORMERR);
1522			goto cleanup;
1523		} else {
1524			dns_dispatch_importrecv(client->dispatch, event);
1525			ns_client_next(client, ISC_R_SUCCESS);
1526			goto cleanup;
1527		}
1528	}
1529
1530	/*
1531	 * Update some statistics counters.  Don't count responses.
1532	 */
1533	if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
1534		isc_stats_increment(ns_g_server->nsstats,
1535				    dns_nsstatscounter_requestv4);
1536	} else {
1537		isc_stats_increment(ns_g_server->nsstats,
1538				    dns_nsstatscounter_requestv6);
1539	}
1540	if (TCP_CLIENT(client))
1541		isc_stats_increment(ns_g_server->nsstats,
1542				    dns_nsstatscounter_tcp);
1543
1544	/*
1545	 * It's a request.  Parse it.
1546	 */
1547	result = dns_message_parse(client->message, buffer, 0);
1548	if (result != ISC_R_SUCCESS) {
1549		/*
1550		 * Parsing the request failed.  Send a response
1551		 * (typically FORMERR or SERVFAIL).
1552		 */
1553		ns_client_error(client, result);
1554		goto cleanup;
1555	}
1556
1557	dns_opcodestats_increment(ns_g_server->opcodestats,
1558				  client->message->opcode);
1559	switch (client->message->opcode) {
1560	case dns_opcode_query:
1561	case dns_opcode_update:
1562	case dns_opcode_notify:
1563		notimp = ISC_FALSE;
1564		break;
1565	case dns_opcode_iquery:
1566	default:
1567		notimp = ISC_TRUE;
1568		break;
1569	}
1570
1571	client->message->rcode = dns_rcode_noerror;
1572
1573	/* RFC1123 section 6.1.3.2 */
1574	if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1575		client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1576
1577	/*
1578	 * Deal with EDNS.
1579	 */
1580	opt = dns_message_getopt(client->message);
1581	if (opt != NULL) {
1582		/*
1583		 * Set the client's UDP buffer size.
1584		 */
1585		client->udpsize = opt->rdclass;
1586
1587		/*
1588		 * If the requested UDP buffer size is less than 512,
1589		 * ignore it and use 512.
1590		 */
1591		if (client->udpsize < 512)
1592			client->udpsize = 512;
1593
1594		/*
1595		 * Get the flags out of the OPT record.
1596		 */
1597		client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1598
1599		/*
1600		 * Do we understand this version of EDNS?
1601		 *
1602		 * XXXRTH need library support for this!
1603		 */
1604		client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1605		if (client->ednsversion > 0) {
1606			isc_stats_increment(ns_g_server->nsstats,
1607					    dns_nsstatscounter_badednsver);
1608			result = client_addopt(client);
1609			if (result == ISC_R_SUCCESS)
1610				result = DNS_R_BADVERS;
1611			ns_client_error(client, result);
1612			goto cleanup;
1613		}
1614
1615		/* Check for NSID request */
1616		result = dns_rdataset_first(opt);
1617		if (result == ISC_R_SUCCESS) {
1618			dns_rdata_init(&rdata);
1619			dns_rdataset_current(opt, &rdata);
1620			if (rdata.length >= 2) {
1621				isc_buffer_t nsidbuf;
1622				isc_buffer_init(&nsidbuf,
1623						rdata.data, rdata.length);
1624				isc_buffer_add(&nsidbuf, rdata.length);
1625				optcode = isc_buffer_getuint16(&nsidbuf);
1626				if (optcode == DNS_OPT_NSID)
1627					client->attributes |=
1628						NS_CLIENTATTR_WANTNSID;
1629			}
1630		}
1631
1632		isc_stats_increment(ns_g_server->nsstats,
1633				    dns_nsstatscounter_edns0in);
1634
1635		/*
1636		 * Create an OPT for our reply.
1637		 */
1638		result = client_addopt(client);
1639		if (result != ISC_R_SUCCESS) {
1640			ns_client_error(client, result);
1641			goto cleanup;
1642		}
1643	}
1644
1645	if (client->message->rdclass == 0) {
1646		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1647			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1648			      "message class could not be determined");
1649		ns_client_dumpmessage(client,
1650				      "message class could not be determined");
1651		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1652		goto cleanup;
1653	}
1654
1655	/*
1656	 * Determine the destination address.  If the receiving interface is
1657	 * bound to a specific address, we simply use it regardless of the
1658	 * address family.  All IPv4 queries should fall into this case.
1659	 * Otherwise, if this is a TCP query, get the address from the
1660	 * receiving socket (this needs a system call and can be heavy).
1661	 * For IPv6 UDP queries, we get this from the pktinfo structure (if
1662	 * supported).
1663	 * If all the attempts fail (this can happen due to memory shortage,
1664	 * etc), we regard this as an error for safety.
1665	 */
1666	if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1667		isc_netaddr_fromsockaddr(&client->destaddr,
1668					 &client->interface->addr);
1669	else {
1670		isc_sockaddr_t sockaddr;
1671		result = ISC_R_FAILURE;
1672
1673		if (TCP_CLIENT(client))
1674			result = isc_socket_getsockname(client->tcpsocket,
1675							&sockaddr);
1676		if (result == ISC_R_SUCCESS)
1677			isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
1678		if (result != ISC_R_SUCCESS &&
1679		    client->interface->addr.type.sa.sa_family == AF_INET6 &&
1680		    (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1681			/*
1682			 * XXXJT technically, we should convert the receiving
1683			 * interface ID to a proper scope zone ID.  However,
1684			 * due to the fact there is no standard API for this,
1685			 * we only handle link-local addresses and use the
1686			 * interface index as link ID.  Despite the assumption,
1687			 * it should cover most typical cases.
1688			 */
1689			isc_netaddr_fromin6(&client->destaddr,
1690					    &client->pktinfo.ipi6_addr);
1691			if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1692				isc_netaddr_setzone(&client->destaddr,
1693						client->pktinfo.ipi6_ifindex);
1694			result = ISC_R_SUCCESS;
1695		}
1696		if (result != ISC_R_SUCCESS) {
1697			UNEXPECTED_ERROR(__FILE__, __LINE__,
1698					 "failed to get request's "
1699					 "destination: %s",
1700					 isc_result_totext(result));
1701			ns_client_next(client, ISC_R_SUCCESS);
1702			goto cleanup;
1703		}
1704	}
1705
1706	/*
1707	 * Find a view that matches the client's source address.
1708	 */
1709	for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1710	     view != NULL;
1711	     view = ISC_LIST_NEXT(view, link)) {
1712		if (client->message->rdclass == view->rdclass ||
1713		    client->message->rdclass == dns_rdataclass_any)
1714		{
1715			dns_name_t *tsig = NULL;
1716
1717			sigresult = dns_message_rechecksig(client->message,
1718							   view);
1719			if (sigresult == ISC_R_SUCCESS)
1720				tsig = dns_tsigkey_identity(client->message->tsigkey);
1721
1722			if (allowed(&netaddr, tsig, view->matchclients) &&
1723			    allowed(&client->destaddr, tsig,
1724				    view->matchdestinations) &&
1725			    !((client->message->flags & DNS_MESSAGEFLAG_RD)
1726			      == 0 && view->matchrecursiveonly))
1727			{
1728				dns_view_attach(view, &client->view);
1729				break;
1730			}
1731		}
1732	}
1733
1734	if (view == NULL) {
1735		char classname[DNS_RDATACLASS_FORMATSIZE];
1736
1737		/*
1738		 * Do a dummy TSIG verification attempt so that the
1739		 * response will have a TSIG if the query did, as
1740		 * required by RFC2845.
1741		 */
1742		isc_buffer_t b;
1743		isc_region_t *r;
1744
1745		dns_message_resetsig(client->message);
1746
1747		r = dns_message_getrawmessage(client->message);
1748		isc_buffer_init(&b, r->base, r->length);
1749		isc_buffer_add(&b, r->length);
1750		(void)dns_tsig_verify(&b, client->message, NULL, NULL);
1751
1752		dns_rdataclass_format(client->message->rdclass, classname,
1753				      sizeof(classname));
1754		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1755			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1756			      "no matching view in class '%s'", classname);
1757		ns_client_dumpmessage(client, "no matching view in class");
1758		ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1759		goto cleanup;
1760	}
1761
1762	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1763		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1764		      "using view '%s'", view->name);
1765
1766	/*
1767	 * Check for a signature.  We log bad signatures regardless of
1768	 * whether they ultimately cause the request to be rejected or
1769	 * not.  We do not log the lack of a signature unless we are
1770	 * debugging.
1771	 */
1772	client->signer = NULL;
1773	dns_name_init(&client->signername, NULL);
1774	result = dns_message_signer(client->message, &client->signername);
1775	if (result != ISC_R_NOTFOUND) {
1776		signame = NULL;
1777		if (dns_message_gettsig(client->message, &signame) != NULL) {
1778			isc_stats_increment(ns_g_server->nsstats,
1779					    dns_nsstatscounter_tsigin);
1780		} else {
1781			isc_stats_increment(ns_g_server->nsstats,
1782					    dns_nsstatscounter_sig0in);
1783		}
1784
1785	}
1786	if (result == ISC_R_SUCCESS) {
1787		char namebuf[DNS_NAME_FORMATSIZE];
1788		dns_name_format(&client->signername, namebuf, sizeof(namebuf));
1789		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1790			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1791			      "request has valid signature: %s", namebuf);
1792		client->signer = &client->signername;
1793	} else if (result == ISC_R_NOTFOUND) {
1794		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1795			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1796			      "request is not signed");
1797	} else if (result == DNS_R_NOIDENTITY) {
1798		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1799			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1800			      "request is signed by a nonauthoritative key");
1801	} else {
1802		char tsigrcode[64];
1803		isc_buffer_t b;
1804		dns_rcode_t status;
1805		isc_result_t tresult;
1806
1807		/* There is a signature, but it is bad. */
1808		isc_stats_increment(ns_g_server->nsstats,
1809				    dns_nsstatscounter_invalidsig);
1810		signame = NULL;
1811		if (dns_message_gettsig(client->message, &signame) != NULL) {
1812			char namebuf[DNS_NAME_FORMATSIZE];
1813			char cnamebuf[DNS_NAME_FORMATSIZE];
1814			dns_name_format(signame, namebuf, sizeof(namebuf));
1815			status = client->message->tsigstatus;
1816			isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1817			tresult = dns_tsigrcode_totext(status, &b);
1818			INSIST(tresult == ISC_R_SUCCESS);
1819			tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1820			if (client->message->tsigkey->generated) {
1821				dns_name_format(client->message->tsigkey->creator,
1822						cnamebuf, sizeof(cnamebuf));
1823				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1824					      NS_LOGMODULE_CLIENT,
1825					      ISC_LOG_ERROR,
1826					      "request has invalid signature: "
1827					      "TSIG %s (%s): %s (%s)", namebuf,
1828					      cnamebuf,
1829					      isc_result_totext(result),
1830					      tsigrcode);
1831			} else {
1832				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1833					      NS_LOGMODULE_CLIENT,
1834					      ISC_LOG_ERROR,
1835					      "request has invalid signature: "
1836					      "TSIG %s: %s (%s)", namebuf,
1837					      isc_result_totext(result),
1838					      tsigrcode);
1839			}
1840		} else {
1841			status = client->message->sig0status;
1842			isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1843			tresult = dns_tsigrcode_totext(status, &b);
1844			INSIST(tresult == ISC_R_SUCCESS);
1845			tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1846			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1847				      NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1848				      "request has invalid signature: %s (%s)",
1849				      isc_result_totext(result), tsigrcode);
1850		}
1851		/*
1852		 * Accept update messages signed by unknown keys so that
1853		 * update forwarding works transparently through slaves
1854		 * that don't have all the same keys as the master.
1855		 */
1856		if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
1857		      client->message->opcode == dns_opcode_update)) {
1858			ns_client_error(client, sigresult);
1859			goto cleanup;
1860		}
1861	}
1862
1863	/*
1864	 * Decide whether recursive service is available to this client.
1865	 * We do this here rather than in the query code so that we can
1866	 * set the RA bit correctly on all kinds of responses, not just
1867	 * responses to ordinary queries.  Note if you can't query the
1868	 * cache there is no point in setting RA.
1869	 */
1870	ra = ISC_FALSE;
1871	if (client->view->resolver != NULL &&
1872	    client->view->recursion == ISC_TRUE &&
1873	    ns_client_checkaclsilent(client, NULL,
1874				     client->view->recursionacl,
1875				     ISC_TRUE) == ISC_R_SUCCESS &&
1876	    ns_client_checkaclsilent(client, NULL,
1877				     client->view->cacheacl,
1878				     ISC_TRUE) == ISC_R_SUCCESS &&
1879	    ns_client_checkaclsilent(client, &client->destaddr,
1880				     client->view->recursiononacl,
1881				     ISC_TRUE) == ISC_R_SUCCESS &&
1882	    ns_client_checkaclsilent(client, &client->destaddr,
1883				     client->view->cacheonacl,
1884				     ISC_TRUE) == ISC_R_SUCCESS)
1885		ra = ISC_TRUE;
1886
1887	if (ra == ISC_TRUE)
1888		client->attributes |= NS_CLIENTATTR_RA;
1889
1890	ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1891		      ISC_LOG_DEBUG(3), ra ? "recursion available" :
1892					     "recursion not available");
1893
1894	/*
1895	 * Adjust maximum UDP response size for this client.
1896	 */
1897	if (client->udpsize > 512) {
1898		dns_peer_t *peer = NULL;
1899		isc_uint16_t udpsize = view->maxudp;
1900		(void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
1901		if (peer != NULL)
1902			dns_peer_getmaxudp(peer, &udpsize);
1903		if (client->udpsize > udpsize)
1904			client->udpsize = udpsize;
1905	}
1906
1907	/*
1908	 * Dispatch the request.
1909	 */
1910	switch (client->message->opcode) {
1911	case dns_opcode_query:
1912		CTRACE("query");
1913		ns_query_start(client);
1914		break;
1915	case dns_opcode_update:
1916		CTRACE("update");
1917		ns_client_settimeout(client, 60);
1918		ns_update_start(client, sigresult);
1919		break;
1920	case dns_opcode_notify:
1921		CTRACE("notify");
1922		ns_client_settimeout(client, 60);
1923		ns_notify_start(client);
1924		break;
1925	case dns_opcode_iquery:
1926		CTRACE("iquery");
1927		ns_client_error(client, DNS_R_NOTIMP);
1928		break;
1929	default:
1930		CTRACE("unknown opcode");
1931		ns_client_error(client, DNS_R_NOTIMP);
1932	}
1933
1934 cleanup:
1935	return;
1936}
1937
1938static void
1939client_timeout(isc_task_t *task, isc_event_t *event) {
1940	ns_client_t *client;
1941
1942	REQUIRE(event != NULL);
1943	REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
1944		event->ev_type == ISC_TIMEREVENT_IDLE);
1945	client = event->ev_arg;
1946	REQUIRE(NS_CLIENT_VALID(client));
1947	REQUIRE(task == client->task);
1948	REQUIRE(client->timer != NULL);
1949
1950	UNUSED(task);
1951
1952	CTRACE("timeout");
1953
1954	isc_event_free(&event);
1955
1956	if (client->shutdown != NULL) {
1957		(client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
1958		client->shutdown = NULL;
1959		client->shutdown_arg = NULL;
1960	}
1961
1962	if (client->newstate > NS_CLIENTSTATE_READY)
1963		client->newstate = NS_CLIENTSTATE_READY;
1964	(void)exit_check(client);
1965}
1966
1967static isc_result_t
1968get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
1969	isc_mem_t *clientmctx;
1970	isc_result_t result;
1971
1972	/*
1973	 * Caller must be holding the manager lock.
1974	 */
1975	if (ns_g_clienttest) {
1976		result = isc_mem_create(0, 0, mctxp);
1977		if (result == ISC_R_SUCCESS)
1978			isc_mem_setname(*mctxp, "client", NULL);
1979		return (result);
1980	}
1981#if NMCTXS > 0
1982	INSIST(manager->nextmctx < NMCTXS);
1983	clientmctx = manager->mctxpool[manager->nextmctx];
1984	if (clientmctx == NULL) {
1985		result = isc_mem_create(0, 0, &clientmctx);
1986		if (result != ISC_R_SUCCESS)
1987			return (result);
1988		isc_mem_setname(clientmctx, "client", NULL);
1989
1990		manager->mctxpool[manager->nextmctx] = clientmctx;
1991	}
1992	manager->nextmctx++;
1993	if (manager->nextmctx == NMCTXS)
1994		manager->nextmctx = 0;
1995#else
1996	clientmctx = manager->mctx;
1997#endif
1998
1999	isc_mem_attach(clientmctx, mctxp);
2000
2001	return (ISC_R_SUCCESS);
2002}
2003
2004static isc_result_t
2005client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
2006	ns_client_t *client;
2007	isc_result_t result;
2008	isc_mem_t *mctx = NULL;
2009
2010	/*
2011	 * Caller must be holding the manager lock.
2012	 *
2013	 * Note: creating a client does not add the client to the
2014	 * manager's client list or set the client's manager pointer.
2015	 * The caller is responsible for that.
2016	 */
2017
2018	REQUIRE(clientp != NULL && *clientp == NULL);
2019
2020	result = get_clientmctx(manager, &mctx);
2021	if (result != ISC_R_SUCCESS)
2022		return (result);
2023
2024	client = isc_mem_get(mctx, sizeof(*client));
2025	if (client == NULL) {
2026		isc_mem_detach(&mctx);
2027		return (ISC_R_NOMEMORY);
2028	}
2029	client->mctx = mctx;
2030
2031	client->task = NULL;
2032	result = isc_task_create(manager->taskmgr, 0, &client->task);
2033	if (result != ISC_R_SUCCESS)
2034		goto cleanup_client;
2035	isc_task_setname(client->task, "client", client);
2036
2037	client->timer = NULL;
2038	result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
2039				  NULL, NULL, client->task, client_timeout,
2040				  client, &client->timer);
2041	if (result != ISC_R_SUCCESS)
2042		goto cleanup_task;
2043	client->timerset = ISC_FALSE;
2044
2045	client->message = NULL;
2046	result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
2047				    &client->message);
2048	if (result != ISC_R_SUCCESS)
2049		goto cleanup_timer;
2050
2051	/* XXXRTH  Hardwired constants */
2052
2053	client->sendevent = (isc_socketevent_t *)
2054			    isc_event_allocate(client->mctx, client,
2055					       ISC_SOCKEVENT_SENDDONE,
2056					       client_senddone, client,
2057					       sizeof(isc_socketevent_t));
2058	if (client->sendevent == NULL) {
2059		result = ISC_R_NOMEMORY;
2060		goto cleanup_message;
2061	}
2062
2063	client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
2064	if  (client->recvbuf == NULL) {
2065		result = ISC_R_NOMEMORY;
2066		goto cleanup_sendevent;
2067	}
2068
2069	client->recvevent = (isc_socketevent_t *)
2070			    isc_event_allocate(client->mctx, client,
2071					       ISC_SOCKEVENT_RECVDONE,
2072					       client_request, client,
2073					       sizeof(isc_socketevent_t));
2074	if (client->recvevent == NULL) {
2075		result = ISC_R_NOMEMORY;
2076		goto cleanup_recvbuf;
2077	}
2078
2079	client->magic = NS_CLIENT_MAGIC;
2080	client->manager = NULL;
2081	client->state = NS_CLIENTSTATE_INACTIVE;
2082	client->newstate = NS_CLIENTSTATE_MAX;
2083	client->naccepts = 0;
2084	client->nreads = 0;
2085	client->nsends = 0;
2086	client->nrecvs = 0;
2087	client->nupdates = 0;
2088	client->nctls = 0;
2089	client->references = 0;
2090	client->attributes = 0;
2091	client->view = NULL;
2092	client->dispatch = NULL;
2093	client->udpsocket = NULL;
2094	client->tcplistener = NULL;
2095	client->tcpsocket = NULL;
2096	client->tcpmsg_valid = ISC_FALSE;
2097	client->tcpbuf = NULL;
2098	client->opt = NULL;
2099	client->udpsize = 512;
2100	client->extflags = 0;
2101	client->ednsversion = -1;
2102	client->next = NULL;
2103	client->shutdown = NULL;
2104	client->shutdown_arg = NULL;
2105	client->signer = NULL;
2106	dns_name_init(&client->signername, NULL);
2107	client->mortal = ISC_FALSE;
2108	client->tcpquota = NULL;
2109	client->recursionquota = NULL;
2110	client->interface = NULL;
2111	client->peeraddr_valid = ISC_FALSE;
2112	ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
2113		       NS_EVENT_CLIENTCONTROL, client_start, client, client,
2114		       NULL, NULL);
2115	/*
2116	 * Initialize FORMERR cache to sentinel value that will not match
2117	 * any actual FORMERR response.
2118	 */
2119	isc_sockaddr_any(&client->formerrcache.addr);
2120	client->formerrcache.time = 0;
2121	client->formerrcache.id = 0;
2122	ISC_LINK_INIT(client, link);
2123	client->list = NULL;
2124
2125	/*
2126	 * We call the init routines for the various kinds of client here,
2127	 * after we have created an otherwise valid client, because some
2128	 * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
2129	 */
2130	result = ns_query_init(client);
2131	if (result != ISC_R_SUCCESS)
2132		goto cleanup_recvevent;
2133
2134	result = isc_task_onshutdown(client->task, client_shutdown, client);
2135	if (result != ISC_R_SUCCESS)
2136		goto cleanup_query;
2137
2138	client->needshutdown = ns_g_clienttest;
2139
2140	CTRACE("create");
2141
2142	*clientp = client;
2143
2144	return (ISC_R_SUCCESS);
2145
2146 cleanup_query:
2147	ns_query_free(client);
2148
2149 cleanup_recvevent:
2150	isc_event_free((isc_event_t **)&client->recvevent);
2151
2152 cleanup_recvbuf:
2153	isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
2154
2155 cleanup_sendevent:
2156	isc_event_free((isc_event_t **)&client->sendevent);
2157
2158	client->magic = 0;
2159
2160 cleanup_message:
2161	dns_message_destroy(&client->message);
2162
2163 cleanup_timer:
2164	isc_timer_detach(&client->timer);
2165
2166 cleanup_task:
2167	isc_task_detach(&client->task);
2168
2169 cleanup_client:
2170	isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
2171
2172	return (result);
2173}
2174
2175static void
2176client_read(ns_client_t *client) {
2177	isc_result_t result;
2178
2179	CTRACE("read");
2180
2181	result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
2182					client_request, client);
2183	if (result != ISC_R_SUCCESS)
2184		goto fail;
2185
2186	/*
2187	 * Set a timeout to limit the amount of time we will wait
2188	 * for a request on this TCP connection.
2189	 */
2190	ns_client_settimeout(client, 30);
2191
2192	client->state = client->newstate = NS_CLIENTSTATE_READING;
2193	INSIST(client->nreads == 0);
2194	INSIST(client->recursionquota == NULL);
2195	client->nreads++;
2196
2197	return;
2198 fail:
2199	ns_client_next(client, result);
2200}
2201
2202static void
2203client_newconn(isc_task_t *task, isc_event_t *event) {
2204	ns_client_t *client = event->ev_arg;
2205	isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
2206	isc_result_t result;
2207
2208	REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
2209	REQUIRE(NS_CLIENT_VALID(client));
2210	REQUIRE(client->task == task);
2211
2212	UNUSED(task);
2213
2214	INSIST(client->state == NS_CLIENTSTATE_READY);
2215
2216	INSIST(client->naccepts == 1);
2217	client->naccepts--;
2218
2219	LOCK(&client->interface->lock);
2220	INSIST(client->interface->ntcpcurrent > 0);
2221	client->interface->ntcpcurrent--;
2222	UNLOCK(&client->interface->lock);
2223
2224	/*
2225	 * We must take ownership of the new socket before the exit
2226	 * check to make sure it gets destroyed if we decide to exit.
2227	 */
2228	if (nevent->result == ISC_R_SUCCESS) {
2229		client->tcpsocket = nevent->newsocket;
2230		isc_socket_setname(client->tcpsocket, "client-tcp", NULL);
2231		client->state = NS_CLIENTSTATE_READING;
2232		INSIST(client->recursionquota == NULL);
2233
2234		(void)isc_socket_getpeername(client->tcpsocket,
2235					     &client->peeraddr);
2236		client->peeraddr_valid = ISC_TRUE;
2237		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2238			   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2239			   "new TCP connection");
2240	} else {
2241		/*
2242		 * XXXRTH  What should we do?  We're trying to accept but
2243		 *	   it didn't work.  If we just give up, then TCP
2244		 *	   service may eventually stop.
2245		 *
2246		 *	   For now, we just go idle.
2247		 *
2248		 *	   Going idle is probably the right thing if the
2249		 *	   I/O was canceled.
2250		 */
2251		ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2252			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2253			      "accept failed: %s",
2254			      isc_result_totext(nevent->result));
2255	}
2256
2257	if (exit_check(client))
2258		goto freeevent;
2259
2260	if (nevent->result == ISC_R_SUCCESS) {
2261		int match;
2262		isc_netaddr_t netaddr;
2263
2264		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2265
2266		if (ns_g_server->blackholeacl != NULL &&
2267		    dns_acl_match(&netaddr, NULL,
2268				  ns_g_server->blackholeacl,
2269				  &ns_g_server->aclenv,
2270				  &match, NULL) == ISC_R_SUCCESS &&
2271		    match > 0)
2272		{
2273			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2274				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2275				      "blackholed connection attempt");
2276			client->newstate = NS_CLIENTSTATE_READY;
2277			(void)exit_check(client);
2278			goto freeevent;
2279		}
2280
2281		INSIST(client->tcpmsg_valid == ISC_FALSE);
2282		dns_tcpmsg_init(client->mctx, client->tcpsocket,
2283				&client->tcpmsg);
2284		client->tcpmsg_valid = ISC_TRUE;
2285
2286		/*
2287		 * Let a new client take our place immediately, before
2288		 * we wait for a request packet.  If we don't,
2289		 * telnetting to port 53 (once per CPU) will
2290		 * deny service to legitimate TCP clients.
2291		 */
2292		result = isc_quota_attach(&ns_g_server->tcpquota,
2293					  &client->tcpquota);
2294		if (result == ISC_R_SUCCESS)
2295			result = ns_client_replace(client);
2296		if (result != ISC_R_SUCCESS) {
2297			ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2298				      NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
2299				      "no more TCP clients: %s",
2300				      isc_result_totext(result));
2301		}
2302
2303		client_read(client);
2304	}
2305
2306 freeevent:
2307	isc_event_free(&event);
2308}
2309
2310static void
2311client_accept(ns_client_t *client) {
2312	isc_result_t result;
2313
2314	CTRACE("accept");
2315
2316	result = isc_socket_accept(client->tcplistener, client->task,
2317				   client_newconn, client);
2318	if (result != ISC_R_SUCCESS) {
2319		UNEXPECTED_ERROR(__FILE__, __LINE__,
2320				 "isc_socket_accept() failed: %s",
2321				 isc_result_totext(result));
2322		/*
2323		 * XXXRTH  What should we do?  We're trying to accept but
2324		 *	   it didn't work.  If we just give up, then TCP
2325		 *	   service may eventually stop.
2326		 *
2327		 *	   For now, we just go idle.
2328		 */
2329		return;
2330	}
2331	INSIST(client->naccepts == 0);
2332	client->naccepts++;
2333	LOCK(&client->interface->lock);
2334	client->interface->ntcpcurrent++;
2335	UNLOCK(&client->interface->lock);
2336}
2337
2338static void
2339client_udprecv(ns_client_t *client) {
2340	isc_result_t result;
2341	isc_region_t r;
2342
2343	CTRACE("udprecv");
2344
2345	r.base = client->recvbuf;
2346	r.length = RECV_BUFFER_SIZE;
2347	result = isc_socket_recv2(client->udpsocket, &r, 1,
2348				  client->task, client->recvevent, 0);
2349	if (result != ISC_R_SUCCESS) {
2350		UNEXPECTED_ERROR(__FILE__, __LINE__,
2351				 "isc_socket_recv2() failed: %s",
2352				 isc_result_totext(result));
2353		/*
2354		 * This cannot happen in the current implementation, since
2355		 * isc_socket_recv2() cannot fail if flags == 0.
2356		 *
2357		 * If this does fail, we just go idle.
2358		 */
2359		return;
2360	}
2361	INSIST(client->nrecvs == 0);
2362	client->nrecvs++;
2363}
2364
2365void
2366ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
2367	REQUIRE(NS_CLIENT_VALID(source));
2368	REQUIRE(targetp != NULL && *targetp == NULL);
2369
2370	source->references++;
2371	ns_client_log(source, NS_LOGCATEGORY_CLIENT,
2372		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2373		      "ns_client_attach: ref = %d", source->references);
2374	*targetp = source;
2375}
2376
2377void
2378ns_client_detach(ns_client_t **clientp) {
2379	ns_client_t *client = *clientp;
2380
2381	client->references--;
2382	INSIST(client->references >= 0);
2383	*clientp = NULL;
2384	ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2385		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2386		      "ns_client_detach: ref = %d", client->references);
2387	(void)exit_check(client);
2388}
2389
2390isc_boolean_t
2391ns_client_shuttingdown(ns_client_t *client) {
2392	return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
2393}
2394
2395isc_result_t
2396ns_client_replace(ns_client_t *client) {
2397	isc_result_t result;
2398
2399	CTRACE("replace");
2400
2401	result = ns_clientmgr_createclients(client->manager,
2402					    1, client->interface,
2403					    (TCP_CLIENT(client) ?
2404					     ISC_TRUE : ISC_FALSE));
2405	if (result != ISC_R_SUCCESS)
2406		return (result);
2407
2408	/*
2409	 * The responsibility for listening for new requests is hereby
2410	 * transferred to the new client.  Therefore, the old client
2411	 * should refrain from listening for any more requests.
2412	 */
2413	client->mortal = ISC_TRUE;
2414
2415	return (ISC_R_SUCCESS);
2416}
2417
2418/***
2419 *** Client Manager
2420 ***/
2421
2422static void
2423clientmgr_destroy(ns_clientmgr_t *manager) {
2424#if NMCTXS > 0
2425	int i;
2426#endif
2427
2428	REQUIRE(ISC_LIST_EMPTY(manager->active));
2429	REQUIRE(ISC_LIST_EMPTY(manager->inactive));
2430	REQUIRE(ISC_LIST_EMPTY(manager->recursing));
2431
2432	MTRACE("clientmgr_destroy");
2433
2434#if NMCTXS > 0
2435	for (i = 0; i < NMCTXS; i++) {
2436		if (manager->mctxpool[i] != NULL)
2437			isc_mem_detach(&manager->mctxpool[i]);
2438	}
2439#endif
2440
2441	DESTROYLOCK(&manager->lock);
2442	manager->magic = 0;
2443	isc_mem_put(manager->mctx, manager, sizeof(*manager));
2444}
2445
2446isc_result_t
2447ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2448		    isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
2449{
2450	ns_clientmgr_t *manager;
2451	isc_result_t result;
2452#if NMCTXS > 0
2453	int i;
2454#endif
2455
2456	manager = isc_mem_get(mctx, sizeof(*manager));
2457	if (manager == NULL)
2458		return (ISC_R_NOMEMORY);
2459
2460	result = isc_mutex_init(&manager->lock);
2461	if (result != ISC_R_SUCCESS)
2462		goto cleanup_manager;
2463
2464	manager->mctx = mctx;
2465	manager->taskmgr = taskmgr;
2466	manager->timermgr = timermgr;
2467	manager->exiting = ISC_FALSE;
2468	ISC_LIST_INIT(manager->active);
2469	ISC_LIST_INIT(manager->inactive);
2470	ISC_LIST_INIT(manager->recursing);
2471#if NMCTXS > 0
2472	manager->nextmctx = 0;
2473	for (i = 0; i < NMCTXS; i++)
2474		manager->mctxpool[i] = NULL; /* will be created on-demand */
2475#endif
2476	manager->magic = MANAGER_MAGIC;
2477
2478	MTRACE("create");
2479
2480	*managerp = manager;
2481
2482	return (ISC_R_SUCCESS);
2483
2484 cleanup_manager:
2485	isc_mem_put(manager->mctx, manager, sizeof(*manager));
2486
2487	return (result);
2488}
2489
2490void
2491ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2492	ns_clientmgr_t *manager;
2493	ns_client_t *client;
2494	isc_boolean_t need_destroy = ISC_FALSE;
2495
2496	REQUIRE(managerp != NULL);
2497	manager = *managerp;
2498	REQUIRE(VALID_MANAGER(manager));
2499
2500	MTRACE("destroy");
2501
2502	LOCK(&manager->lock);
2503
2504	manager->exiting = ISC_TRUE;
2505
2506	for (client = ISC_LIST_HEAD(manager->recursing);
2507	     client != NULL;
2508	     client = ISC_LIST_NEXT(client, link))
2509		isc_task_shutdown(client->task);
2510
2511	for (client = ISC_LIST_HEAD(manager->active);
2512	     client != NULL;
2513	     client = ISC_LIST_NEXT(client, link))
2514		isc_task_shutdown(client->task);
2515
2516	for (client = ISC_LIST_HEAD(manager->inactive);
2517	     client != NULL;
2518	     client = ISC_LIST_NEXT(client, link))
2519		isc_task_shutdown(client->task);
2520
2521	if (ISC_LIST_EMPTY(manager->active) &&
2522	    ISC_LIST_EMPTY(manager->inactive) &&
2523	    ISC_LIST_EMPTY(manager->recursing))
2524		need_destroy = ISC_TRUE;
2525
2526	UNLOCK(&manager->lock);
2527
2528	if (need_destroy)
2529		clientmgr_destroy(manager);
2530
2531	*managerp = NULL;
2532}
2533
2534isc_result_t
2535ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
2536			   ns_interface_t *ifp, isc_boolean_t tcp)
2537{
2538	isc_result_t result = ISC_R_SUCCESS;
2539	unsigned int i;
2540	ns_client_t *client;
2541
2542	REQUIRE(VALID_MANAGER(manager));
2543	REQUIRE(n > 0);
2544
2545	MTRACE("createclients");
2546
2547	/*
2548	 * We MUST lock the manager lock for the entire client creation
2549	 * process.  If we didn't do this, then a client could get a
2550	 * shutdown event and disappear out from under us.
2551	 */
2552
2553	LOCK(&manager->lock);
2554
2555	for (i = 0; i < n; i++) {
2556		isc_event_t *ev;
2557		/*
2558		 * Allocate a client.  First try to get a recycled one;
2559		 * if that fails, make a new one.
2560		 */
2561		client = NULL;
2562		if (!ns_g_clienttest)
2563			client = ISC_LIST_HEAD(manager->inactive);
2564		if (client != NULL) {
2565			MTRACE("recycle");
2566			ISC_LIST_UNLINK(manager->inactive, client, link);
2567			client->list = NULL;
2568		} else {
2569			MTRACE("create new");
2570			result = client_create(manager, &client);
2571			if (result != ISC_R_SUCCESS)
2572				break;
2573		}
2574
2575		ns_interface_attach(ifp, &client->interface);
2576		client->state = NS_CLIENTSTATE_READY;
2577		INSIST(client->recursionquota == NULL);
2578
2579		if (tcp) {
2580			client->attributes |= NS_CLIENTATTR_TCP;
2581			isc_socket_attach(ifp->tcpsocket,
2582					  &client->tcplistener);
2583		} else {
2584			isc_socket_t *sock;
2585
2586			dns_dispatch_attach(ifp->udpdispatch,
2587					    &client->dispatch);
2588			sock = dns_dispatch_getsocket(client->dispatch);
2589			isc_socket_attach(sock, &client->udpsocket);
2590		}
2591		client->manager = manager;
2592		ISC_LIST_APPEND(manager->active, client, link);
2593		client->list = &manager->active;
2594
2595		INSIST(client->nctls == 0);
2596		client->nctls++;
2597		ev = &client->ctlevent;
2598		isc_task_send(client->task, &ev);
2599	}
2600	if (i != 0) {
2601		/*
2602		 * We managed to create at least one client, so we
2603		 * declare victory.
2604		 */
2605		result = ISC_R_SUCCESS;
2606	}
2607
2608	UNLOCK(&manager->lock);
2609
2610	return (result);
2611}
2612
2613isc_sockaddr_t *
2614ns_client_getsockaddr(ns_client_t *client) {
2615	return (&client->peeraddr);
2616}
2617
2618isc_result_t
2619ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
2620			 dns_acl_t *acl, isc_boolean_t default_allow)
2621{
2622	isc_result_t result;
2623	isc_netaddr_t tmpnetaddr;
2624	int match;
2625
2626	if (acl == NULL) {
2627		if (default_allow)
2628			goto allow;
2629		else
2630			goto deny;
2631	}
2632
2633	if (netaddr == NULL) {
2634		isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
2635		netaddr = &tmpnetaddr;
2636	}
2637
2638	result = dns_acl_match(netaddr, client->signer, acl,
2639			       &ns_g_server->aclenv, &match, NULL);
2640
2641	if (result != ISC_R_SUCCESS)
2642		goto deny; /* Internal error, already logged. */
2643	if (match > 0)
2644		goto allow;
2645	goto deny; /* Negative match or no match. */
2646
2647 allow:
2648	return (ISC_R_SUCCESS);
2649
2650 deny:
2651	return (DNS_R_REFUSED);
2652}
2653
2654isc_result_t
2655ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
2656		   const char *opname, dns_acl_t *acl,
2657		   isc_boolean_t default_allow, int log_level)
2658{
2659	isc_result_t result;
2660	isc_netaddr_t netaddr;
2661
2662	if (sockaddr != NULL)
2663		isc_netaddr_fromsockaddr(&netaddr, sockaddr);
2664
2665	result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
2666					  acl, default_allow);
2667
2668	if (result == ISC_R_SUCCESS)
2669		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2670			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2671			      "%s approved", opname);
2672	else
2673		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2674			      NS_LOGMODULE_CLIENT,
2675			      log_level, "%s denied", opname);
2676	return (result);
2677}
2678
2679static void
2680ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2681	if (client->peeraddr_valid)
2682		isc_sockaddr_format(&client->peeraddr, peerbuf, len);
2683	else
2684		snprintf(peerbuf, len, "@%p", client);
2685}
2686
2687void
2688ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2689	       isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2690{
2691	char msgbuf[2048];
2692	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2693	const char *name = "";
2694	const char *sep = "";
2695
2696	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2697	ns_client_name(client, peerbuf, sizeof(peerbuf));
2698	if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2699	    strcmp(client->view->name, "_default") != 0) {
2700		name = client->view->name;
2701		sep = ": view ";
2702	}
2703
2704	isc_log_write(ns_g_lctx, category, module, level,
2705		      "client %s%s%s: %s", peerbuf, sep, name, msgbuf);
2706}
2707
2708void
2709ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2710	   isc_logmodule_t *module, int level, const char *fmt, ...)
2711{
2712	va_list ap;
2713
2714	if (! isc_log_wouldlog(ns_g_lctx, level))
2715		return;
2716
2717	va_start(ap, fmt);
2718	ns_client_logv(client, category, module, level, fmt, ap);
2719	va_end(ap);
2720}
2721
2722void
2723ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
2724		 dns_rdataclass_t rdclass, char *buf, size_t len)
2725{
2726	char namebuf[DNS_NAME_FORMATSIZE];
2727	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2728	char classbuf[DNS_RDATACLASS_FORMATSIZE];
2729
2730	dns_name_format(name, namebuf, sizeof(namebuf));
2731	dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2732	dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2733	(void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2734		       classbuf);
2735}
2736
2737static void
2738ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2739	isc_buffer_t buffer;
2740	char *buf = NULL;
2741	int len = 1024;
2742	isc_result_t result;
2743
2744	/*
2745	 * Note that these are multiline debug messages.  We want a newline
2746	 * to appear in the log after each message.
2747	 */
2748
2749	do {
2750		buf = isc_mem_get(client->mctx, len);
2751		if (buf == NULL)
2752			break;
2753		isc_buffer_init(&buffer, buf, len);
2754		result = dns_message_totext(client->message,
2755					    &dns_master_style_debug,
2756					    0, &buffer);
2757		if (result == ISC_R_NOSPACE) {
2758			isc_mem_put(client->mctx, buf, len);
2759			len += 1024;
2760		} else if (result == ISC_R_SUCCESS)
2761			ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
2762				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2763				      "%s\n%.*s", reason,
2764				       (int)isc_buffer_usedlength(&buffer),
2765				       buf);
2766	} while (result == ISC_R_NOSPACE);
2767
2768	if (buf != NULL)
2769		isc_mem_put(client->mctx, buf, len);
2770}
2771
2772void
2773ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2774	ns_client_t *client;
2775	char namebuf[DNS_NAME_FORMATSIZE];
2776	char original[DNS_NAME_FORMATSIZE];
2777	char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2778	char typebuf[DNS_RDATATYPE_FORMATSIZE];
2779	char classbuf[DNS_RDATACLASS_FORMATSIZE];
2780	const char *name;
2781	const char *sep;
2782	const char *origfor;
2783	dns_rdataset_t *rdataset;
2784
2785	REQUIRE(VALID_MANAGER(manager));
2786
2787	LOCK(&manager->lock);
2788	client = ISC_LIST_HEAD(manager->recursing);
2789	while (client != NULL) {
2790		ns_client_name(client, peerbuf, sizeof(peerbuf));
2791		if (client->view != NULL &&
2792		    strcmp(client->view->name, "_bind") != 0 &&
2793		    strcmp(client->view->name, "_default") != 0) {
2794			name = client->view->name;
2795			sep = ": view ";
2796		} else {
2797			name = "";
2798			sep = "";
2799		}
2800		dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2801		if (client->query.qname != client->query.origqname &&
2802		    client->query.origqname != NULL) {
2803			origfor = " for ";
2804			dns_name_format(client->query.origqname, original,
2805					sizeof(original));
2806		} else {
2807			origfor = "";
2808			original[0] = '\0';
2809		}
2810		rdataset = ISC_LIST_HEAD(client->query.qname->list);
2811		if (rdataset == NULL && client->query.origqname != NULL)
2812			rdataset = ISC_LIST_HEAD(client->query.origqname->list);
2813		if (rdataset != NULL) {
2814			dns_rdatatype_format(rdataset->type, typebuf,
2815					     sizeof(typebuf));
2816			dns_rdataclass_format(rdataset->rdclass, classbuf,
2817					      sizeof(classbuf));
2818		} else {
2819			strcpy(typebuf, "-");
2820			strcpy(classbuf, "-");
2821		}
2822		fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s "
2823			"requesttime %d\n", peerbuf, sep, name,
2824			client->message->id, namebuf, typebuf, classbuf,
2825			origfor, original, client->requesttime);
2826		client = ISC_LIST_NEXT(client, link);
2827	}
2828	UNLOCK(&manager->lock);
2829}
2830
2831void
2832ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2833
2834	if (client->manager != NULL)
2835		LOCK(&client->manager->lock);
2836	if (client->query.restarts > 0) {
2837		/*
2838		 * client->query.qname was dynamically allocated.
2839		 */
2840		dns_message_puttempname(client->message,
2841					&client->query.qname);
2842	}
2843	client->query.qname = name;
2844	if (client->manager != NULL)
2845		UNLOCK(&client->manager->lock);
2846}
2847