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