Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / contrib / bind-9.3 / bin / named / client.c
1 /*
2  * Copyright (C) 2004-2006  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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.176.2.13.4.31.6.1 2007/06/26 04:14:55 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/print.h>
26 #include <isc/stdio.h>
27 #include <isc/string.h>
28 #include <isc/task.h>
29 #include <isc/timer.h>
30 #include <isc/util.h>
31
32 #include <dns/db.h>
33 #include <dns/dispatch.h>
34 #include <dns/events.h>
35 #include <dns/message.h>
36 #include <dns/rcode.h>
37 #include <dns/resolver.h>
38 #include <dns/rdata.h>
39 #include <dns/rdataclass.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
42 #include <dns/tsig.h>
43 #include <dns/view.h>
44 #include <dns/zone.h>
45
46 #include <named/interfacemgr.h>
47 #include <named/log.h>
48 #include <named/notify.h>
49 #include <named/server.h>
50 #include <named/update.h>
51
52 /***
53  *** Client
54  ***/
55
56 /*
57  * Important note!
58  *
59  * All client state changes, other than that from idle to listening, occur
60  * as a result of events.  This guarantees serialization and avoids the
61  * need for locking.
62  *
63  * If a routine is ever created that allows someone other than the client's
64  * task to change the client, then the client will have to be locked.
65  */
66
67 #define NS_CLIENT_TRACE
68 #ifdef NS_CLIENT_TRACE
69 #define CTRACE(m)       ns_client_log(client, \
70                                       NS_LOGCATEGORY_CLIENT, \
71                                       NS_LOGMODULE_CLIENT, \
72                                       ISC_LOG_DEBUG(3), \
73                                       "%s", (m))
74 #define MTRACE(m)       isc_log_write(ns_g_lctx, \
75                                       NS_LOGCATEGORY_GENERAL, \
76                                       NS_LOGMODULE_CLIENT, \
77                                       ISC_LOG_DEBUG(3), \
78                                       "clientmgr @%p: %s", manager, (m))
79 #else
80 #define CTRACE(m)       ((void)(m))
81 #define MTRACE(m)       ((void)(m))
82 #endif
83
84 #define TCP_CLIENT(c)   (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
85
86 #define TCP_BUFFER_SIZE                 (65535 + 2)
87 #define SEND_BUFFER_SIZE                4096
88 #define RECV_BUFFER_SIZE                4096
89
90 struct ns_clientmgr {
91         /* Unlocked. */
92         unsigned int                    magic;
93         isc_mem_t *                     mctx;
94         isc_taskmgr_t *                 taskmgr;
95         isc_timermgr_t *                timermgr;
96         isc_mutex_t                     lock;
97         /* Locked by lock. */
98         isc_boolean_t                   exiting;
99         client_list_t                   active;         /* Active clients */
100         client_list_t                   recursing;      /* Recursing clients */
101         client_list_t                   inactive;       /* To be recycled */
102 };
103
104 #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
174 static void client_read(ns_client_t *client);
175 static void client_accept(ns_client_t *client);
176 static void client_udprecv(ns_client_t *client);
177 static void clientmgr_destroy(ns_clientmgr_t *manager);
178 static isc_boolean_t exit_check(ns_client_t *client);
179 static void ns_client_endrequest(ns_client_t *client);
180 static void ns_client_checkactive(ns_client_t *client);
181 static void client_start(isc_task_t *task, isc_event_t *event);
182 static void client_request(isc_task_t *task, isc_event_t *event);
183 static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
184
185 void
186 ns_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
196 void
197 ns_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
212 void
213 ns_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  */
236 static isc_boolean_t
237 exit_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  */
517 static void
518 client_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  */
542 static void
543 client_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
568 static void
569 ns_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
606 static void
607 ns_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
640 void
641 ns_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
671 static void
672 client_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
716 static isc_result_t
717 client_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
768 static isc_result_t
769 client_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
820 void
821 ns_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
866 void
867 ns_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  */
1003 static int
1004 ns_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
1018 void
1019 ns_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
1106 static inline isc_result_t
1107 client_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
1170 static inline isc_boolean_t
1171 allowed(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  */
1188 static void
1189 client_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          * Hash the incoming request here as it is after
1353          * dns_dispatch_importrecv().
1354          */
1355         dns_dispatch_hash(&client->now, sizeof(client->now));
1356         dns_dispatch_hash(isc_buffer_base(buffer),
1357                           isc_buffer_usedlength(buffer));
1358
1359         /*
1360          * It's a request.  Parse it.
1361          */
1362         result = dns_message_parse(client->message, buffer, 0);
1363         if (result != ISC_R_SUCCESS) {
1364                 /*
1365                  * Parsing the request failed.  Send a response
1366                  * (typically FORMERR or SERVFAIL).
1367                  */
1368                 ns_client_error(client, result);
1369                 goto cleanup;
1370         }
1371
1372         switch (client->message->opcode) {
1373         case dns_opcode_query:
1374         case dns_opcode_update:
1375         case dns_opcode_notify:
1376                 notimp = ISC_FALSE;
1377                 break;
1378         case dns_opcode_iquery:
1379         default:
1380                 notimp = ISC_TRUE;
1381                 break;
1382         }
1383
1384         client->message->rcode = dns_rcode_noerror;
1385
1386         /* RFC1123 section 6.1.3.2 */
1387         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1388                 client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1389
1390         /*
1391          * Deal with EDNS.
1392          */
1393         opt = dns_message_getopt(client->message);
1394         if (opt != NULL) {
1395                 unsigned int version;
1396
1397                 /*
1398                  * Set the client's UDP buffer size.
1399                  */
1400                 client->udpsize = opt->rdclass;
1401
1402                 /*
1403                  * If the requested UDP buffer size is less than 512,
1404                  * ignore it and use 512.
1405                  */
1406                 if (client->udpsize < 512)
1407                         client->udpsize = 512;
1408
1409                 /*
1410                  * Get the flags out of the OPT record.
1411                  */
1412                 client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1413
1414                 /*
1415                  * Create an OPT for our reply.
1416                  */
1417                 result = client_addopt(client);
1418                 if (result != ISC_R_SUCCESS) {
1419                         ns_client_error(client, result);
1420                         goto cleanup;
1421                 }
1422
1423                 /*
1424                  * Do we understand this version of ENDS?
1425                  *
1426                  * XXXRTH need library support for this!
1427                  */
1428                 version = (opt->ttl & 0x00FF0000) >> 16;
1429                 if (version != 0) {
1430                         ns_client_error(client, DNS_R_BADVERS);
1431                         goto cleanup;
1432                 }
1433         }
1434
1435         if (client->message->rdclass == 0) {
1436                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1437                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1438                               "message class could not be determined");
1439                 ns_client_dumpmessage(client,
1440                                       "message class could not be determined");
1441                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1442                 goto cleanup;
1443         }
1444
1445         /*
1446          * Determine the destination address.  If the receiving interface is
1447          * bound to a specific address, we simply use it regardless of the
1448          * address family.  All IPv4 queries should fall into this case.
1449          * Otherwise, if this is a TCP query, get the address from the
1450          * receiving socket (this needs a system call and can be heavy).
1451          * For IPv6 UDP queries, we get this from the pktinfo structure (if
1452          * supported).
1453          * If all the attempts fail (this can happen due to memory shortage,
1454          * etc), we regard this as an error for safety. 
1455          */
1456         if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1457                 isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr);
1458         else {
1459                 result = ISC_R_FAILURE;
1460
1461                 if (TCP_CLIENT(client)) {
1462                         isc_sockaddr_t destsockaddr;
1463
1464                         result = isc_socket_getsockname(client->tcpsocket,
1465                                                         &destsockaddr);
1466                         if (result == ISC_R_SUCCESS)
1467                                 isc_netaddr_fromsockaddr(&destaddr,
1468                                                          &destsockaddr);
1469                 }
1470                 if (result != ISC_R_SUCCESS &&
1471                     client->interface->addr.type.sa.sa_family == AF_INET6 &&
1472                     (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1473                         isc_uint32_t zone = 0;
1474
1475                         /*
1476                          * XXXJT technically, we should convert the receiving
1477                          * interface ID to a proper scope zone ID.  However,
1478                          * due to the fact there is no standard API for this,
1479                          * we only handle link-local addresses and use the
1480                          * interface index as link ID.  Despite the assumption,
1481                          * it should cover most typical cases.
1482                          */
1483                         if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1484                                 zone = (isc_uint32_t)client->pktinfo.ipi6_ifindex;
1485
1486                         isc_netaddr_fromin6(&destaddr,
1487                                             &client->pktinfo.ipi6_addr);
1488                         isc_netaddr_setzone(&destaddr, zone);
1489                         result = ISC_R_SUCCESS;
1490                 }
1491                 if (result != ISC_R_SUCCESS) {
1492                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1493                                          "failed to get request's "
1494                                          "destination: %s",
1495                                          isc_result_totext(result));
1496                         goto cleanup;
1497                 }
1498         }
1499
1500         /*
1501          * Find a view that matches the client's source address.
1502          */
1503         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1504              view != NULL;
1505              view = ISC_LIST_NEXT(view, link)) {
1506                 if (client->message->rdclass == view->rdclass ||
1507                     client->message->rdclass == dns_rdataclass_any)
1508                 {
1509                         dns_name_t *tsig = NULL;
1510                         sigresult = dns_message_rechecksig(client->message,
1511                                                            view);
1512                         if (sigresult == ISC_R_SUCCESS)
1513                                 tsig = client->message->tsigname;
1514                                 
1515                         if (allowed(&netaddr, tsig, view->matchclients) &&
1516                             allowed(&destaddr, tsig, view->matchdestinations) &&
1517                             !((client->message->flags & DNS_MESSAGEFLAG_RD)
1518                               == 0 && view->matchrecursiveonly))
1519                         {
1520                                 dns_view_attach(view, &client->view);
1521                                 break;
1522                         }
1523                 }
1524         }
1525
1526         if (view == NULL) {
1527                 char classname[DNS_RDATACLASS_FORMATSIZE];
1528
1529                 /*
1530                  * Do a dummy TSIG verification attempt so that the
1531                  * response will have a TSIG if the query did, as
1532                  * required by RFC2845.
1533                  */
1534                 isc_buffer_t b;
1535                 isc_region_t *r;
1536
1537                 dns_message_resetsig(client->message);
1538
1539                 r = dns_message_getrawmessage(client->message);
1540                 isc_buffer_init(&b, r->base, r->length);
1541                 isc_buffer_add(&b, r->length);
1542                 (void)dns_tsig_verify(&b, client->message, NULL, NULL);
1543
1544                 dns_rdataclass_format(client->message->rdclass, classname,
1545                                       sizeof(classname));
1546                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1547                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1548                               "no matching view in class '%s'", classname);
1549                 ns_client_dumpmessage(client, "no matching view in class");
1550                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1551                 goto cleanup;
1552         }
1553
1554         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1555                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1556                       "using view '%s'", view->name);
1557
1558         /*
1559          * Check for a signature.  We log bad signatures regardless of
1560          * whether they ultimately cause the request to be rejected or
1561          * not.  We do not log the lack of a signature unless we are
1562          * debugging.
1563          */
1564         client->signer = NULL;
1565         dns_name_init(&client->signername, NULL);
1566         result = dns_message_signer(client->message, &client->signername);
1567         if (result == ISC_R_SUCCESS) {
1568                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1569                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1570                               "request has valid signature");
1571                 client->signer = &client->signername;
1572         } else if (result == ISC_R_NOTFOUND) {
1573                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1574                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1575                               "request is not signed");
1576         } else if (result == DNS_R_NOIDENTITY) {
1577                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1578                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1579                               "request is signed by a nonauthoritative key");
1580         } else {
1581                 char tsigrcode[64];
1582                 isc_buffer_t b;
1583                 dns_name_t *name = NULL;
1584
1585                 isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1586                 RUNTIME_CHECK(dns_tsigrcode_totext(client->message->tsigstatus,
1587                                                    &b) == ISC_R_SUCCESS);
1588                 tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1589                 /* There is a signature, but it is bad. */
1590                 if (dns_message_gettsig(client->message, &name) != NULL) {
1591                         char namebuf[DNS_NAME_FORMATSIZE];
1592                         dns_name_format(name, namebuf, sizeof(namebuf));
1593                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1594                                       NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1595                                       "request has invalid signature: "
1596                                       "TSIG %s: %s (%s)", namebuf,
1597                                       isc_result_totext(result), tsigrcode);
1598                 } else {
1599                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1600                                       NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1601                                       "request has invalid signature: %s (%s)",
1602                                       isc_result_totext(result), tsigrcode);
1603                 }
1604                 /*
1605                  * Accept update messages signed by unknown keys so that
1606                  * update forwarding works transparently through slaves
1607                  * that don't have all the same keys as the master.
1608                  */
1609                 if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
1610                       client->message->opcode == dns_opcode_update)) {
1611                         ns_client_error(client, sigresult);
1612                         goto cleanup;
1613                 }
1614         }
1615
1616         /*
1617          * Decide whether recursive service is available to this client.
1618          * We do this here rather than in the query code so that we can
1619          * set the RA bit correctly on all kinds of responses, not just
1620          * responses to ordinary queries.  Note if you can't query the
1621          * cache there is no point in setting RA.
1622          */
1623         ra = ISC_FALSE;
1624         if (client->view->resolver != NULL &&
1625             client->view->recursion == ISC_TRUE &&
1626             ns_client_checkaclsilent(client, client->view->recursionacl,
1627                                      ISC_TRUE) == ISC_R_SUCCESS &&
1628             ns_client_checkaclsilent(client, client->view->queryacl,
1629                                      ISC_TRUE) == ISC_R_SUCCESS)
1630                 ra = ISC_TRUE;
1631
1632         if (ra == ISC_TRUE)
1633                 client->attributes |= NS_CLIENTATTR_RA;
1634
1635         ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1636                       ISC_LOG_DEBUG(3), ra ? "recursion available" :
1637                                              "recursion not available");
1638
1639         /*
1640          * Dispatch the request.
1641          */
1642         switch (client->message->opcode) {
1643         case dns_opcode_query:
1644                 CTRACE("query");
1645                 ns_query_start(client);
1646                 break;
1647         case dns_opcode_update:
1648                 CTRACE("update");
1649                 ns_client_settimeout(client, 60);
1650                 ns_update_start(client, sigresult);
1651                 break;
1652         case dns_opcode_notify:
1653                 CTRACE("notify");
1654                 ns_client_settimeout(client, 60);
1655                 ns_notify_start(client);
1656                 break;
1657         case dns_opcode_iquery:
1658                 CTRACE("iquery");
1659                 ns_client_error(client, DNS_R_NOTIMP);
1660                 break;
1661         default:
1662                 CTRACE("unknown opcode");
1663                 ns_client_error(client, DNS_R_NOTIMP);
1664         }
1665
1666  cleanup:
1667         return;
1668 }
1669
1670 static void
1671 client_timeout(isc_task_t *task, isc_event_t *event) {
1672         ns_client_t *client;
1673
1674         REQUIRE(event != NULL);
1675         REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
1676                 event->ev_type == ISC_TIMEREVENT_IDLE);
1677         client = event->ev_arg;
1678         REQUIRE(NS_CLIENT_VALID(client));
1679         REQUIRE(task == client->task);
1680         REQUIRE(client->timer != NULL);
1681
1682         UNUSED(task);
1683
1684         CTRACE("timeout");
1685
1686         isc_event_free(&event);
1687
1688         if (client->shutdown != NULL) {
1689                 (client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
1690                 client->shutdown = NULL;
1691                 client->shutdown_arg = NULL;
1692         }
1693
1694         if (client->newstate > NS_CLIENTSTATE_READY)
1695                 client->newstate = NS_CLIENTSTATE_READY;
1696         (void)exit_check(client);
1697 }
1698
1699 static isc_result_t
1700 client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
1701         ns_client_t *client;
1702         isc_result_t result;
1703
1704         /*
1705          * Caller must be holding the manager lock.
1706          *
1707          * Note: creating a client does not add the client to the
1708          * manager's client list or set the client's manager pointer.
1709          * The caller is responsible for that.
1710          */
1711
1712         REQUIRE(clientp != NULL && *clientp == NULL);
1713
1714         client = isc_mem_get(manager->mctx, sizeof(*client));
1715         if (client == NULL)
1716                 return (ISC_R_NOMEMORY);
1717
1718         client->task = NULL;
1719         result = isc_task_create(manager->taskmgr, 0, &client->task);
1720         if (result != ISC_R_SUCCESS)
1721                 goto cleanup_client;
1722         isc_task_setname(client->task, "client", client);
1723
1724         client->timer = NULL;
1725         result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
1726                                   NULL, NULL, client->task, client_timeout,
1727                                   client, &client->timer);
1728         if (result != ISC_R_SUCCESS)
1729                 goto cleanup_task;
1730         client->timerset = ISC_FALSE;
1731
1732         client->message = NULL;
1733         result = dns_message_create(manager->mctx, DNS_MESSAGE_INTENTPARSE,
1734                                     &client->message);
1735         if (result != ISC_R_SUCCESS)
1736                 goto cleanup_timer;
1737
1738         /* XXXRTH  Hardwired constants */
1739
1740         client->sendevent = (isc_socketevent_t *)
1741                             isc_event_allocate(manager->mctx, client,
1742                                                ISC_SOCKEVENT_SENDDONE,
1743                                                client_senddone, client,
1744                                                sizeof(isc_socketevent_t));
1745         if (client->sendevent == NULL) {
1746                 result = ISC_R_NOMEMORY;
1747                 goto cleanup_message;
1748         }
1749
1750         client->recvbuf = isc_mem_get(manager->mctx, RECV_BUFFER_SIZE);
1751         if  (client->recvbuf == NULL) {
1752                 result = ISC_R_NOMEMORY;
1753                 goto cleanup_sendevent;
1754         }
1755
1756         client->recvevent = (isc_socketevent_t *)
1757                             isc_event_allocate(manager->mctx, client,
1758                                                ISC_SOCKEVENT_RECVDONE,
1759                                                client_request, client,
1760                                                sizeof(isc_socketevent_t));
1761         if (client->recvevent == NULL) {
1762                 result = ISC_R_NOMEMORY;
1763                 goto cleanup_recvbuf;
1764         }
1765
1766         client->magic = NS_CLIENT_MAGIC;
1767         client->mctx = manager->mctx;
1768         client->manager = NULL;
1769         client->state = NS_CLIENTSTATE_INACTIVE;
1770         client->newstate = NS_CLIENTSTATE_MAX;
1771         client->naccepts = 0;
1772         client->nreads = 0;
1773         client->nsends = 0;
1774         client->nrecvs = 0;
1775         client->nupdates = 0;
1776         client->nctls = 0;
1777         client->references = 0;
1778         client->attributes = 0;
1779         client->view = NULL;
1780         client->dispatch = NULL;
1781         client->udpsocket = NULL;
1782         client->tcplistener = NULL;
1783         client->tcpsocket = NULL;
1784         client->tcpmsg_valid = ISC_FALSE;
1785         client->tcpbuf = NULL;
1786         client->opt = NULL;
1787         client->udpsize = 512;
1788         client->extflags = 0;
1789         client->next = NULL;
1790         client->shutdown = NULL;
1791         client->shutdown_arg = NULL;
1792         dns_name_init(&client->signername, NULL);
1793         client->mortal = ISC_FALSE;
1794         client->tcpquota = NULL;
1795         client->recursionquota = NULL;
1796         client->interface = NULL;
1797         client->peeraddr_valid = ISC_FALSE;
1798         ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
1799                        NS_EVENT_CLIENTCONTROL, client_start, client, client,
1800                        NULL, NULL);
1801         /*
1802          * Initialize FORMERR cache to sentinel value that will not match
1803          * any actual FORMERR response.
1804          */
1805         isc_sockaddr_any(&client->formerrcache.addr);
1806         client->formerrcache.time = 0;
1807         client->formerrcache.id = 0;
1808         ISC_LINK_INIT(client, link);
1809         client->list = NULL;
1810
1811         /*
1812          * We call the init routines for the various kinds of client here,
1813          * after we have created an otherwise valid client, because some
1814          * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
1815          */
1816         result = ns_query_init(client);
1817         if (result != ISC_R_SUCCESS)
1818                 goto cleanup_recvevent;
1819
1820         result = isc_task_onshutdown(client->task, client_shutdown, client);
1821         if (result != ISC_R_SUCCESS)
1822                 goto cleanup_query;
1823
1824         CTRACE("create");
1825
1826         *clientp = client;
1827
1828         return (ISC_R_SUCCESS);
1829
1830  cleanup_query:
1831         ns_query_free(client);
1832
1833  cleanup_recvevent:
1834         isc_event_free((isc_event_t **)&client->recvevent);
1835
1836  cleanup_recvbuf:
1837         isc_mem_put(manager->mctx, client->recvbuf, RECV_BUFFER_SIZE);
1838
1839  cleanup_sendevent:
1840         isc_event_free((isc_event_t **)&client->sendevent);
1841
1842         client->magic = 0;
1843
1844  cleanup_message:
1845         dns_message_destroy(&client->message);
1846
1847  cleanup_timer:
1848         isc_timer_detach(&client->timer);
1849
1850  cleanup_task:
1851         isc_task_detach(&client->task);
1852
1853  cleanup_client:
1854         isc_mem_put(manager->mctx, client, sizeof(*client));
1855
1856         return (result);
1857 }
1858
1859 static void
1860 client_read(ns_client_t *client) {
1861         isc_result_t result;
1862
1863         CTRACE("read");
1864
1865         result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
1866                                         client_request, client);
1867         if (result != ISC_R_SUCCESS)
1868                 goto fail;
1869
1870         /*
1871          * Set a timeout to limit the amount of time we will wait
1872          * for a request on this TCP connection.
1873          */
1874         ns_client_settimeout(client, 30);
1875
1876         client->state = client->newstate = NS_CLIENTSTATE_READING;
1877         INSIST(client->nreads == 0);
1878         INSIST(client->recursionquota == NULL);
1879         client->nreads++;
1880
1881         return;
1882  fail:
1883         ns_client_next(client, result);
1884 }
1885
1886 static void
1887 client_newconn(isc_task_t *task, isc_event_t *event) {
1888         ns_client_t *client = event->ev_arg;
1889         isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
1890         isc_result_t result;
1891
1892         REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
1893         REQUIRE(NS_CLIENT_VALID(client));
1894         REQUIRE(client->task == task);
1895
1896         UNUSED(task);
1897
1898         INSIST(client->state == NS_CLIENTSTATE_READY);
1899
1900         INSIST(client->naccepts == 1);
1901         client->naccepts--;
1902
1903         LOCK(&client->interface->lock);
1904         INSIST(client->interface->ntcpcurrent > 0);
1905         client->interface->ntcpcurrent--;
1906         UNLOCK(&client->interface->lock);
1907
1908         /*
1909          * We must take ownership of the new socket before the exit
1910          * check to make sure it gets destroyed if we decide to exit.
1911          */
1912         if (nevent->result == ISC_R_SUCCESS) {
1913                 client->tcpsocket = nevent->newsocket;
1914                 client->state = NS_CLIENTSTATE_READING;
1915                 INSIST(client->recursionquota == NULL);
1916
1917                 (void)isc_socket_getpeername(client->tcpsocket,
1918                                              &client->peeraddr);
1919                 client->peeraddr_valid = ISC_TRUE;
1920                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1921                            NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1922                            "new TCP connection");
1923         } else {
1924                 /*
1925                  * XXXRTH  What should we do?  We're trying to accept but
1926                  *         it didn't work.  If we just give up, then TCP
1927                  *         service may eventually stop.
1928                  *
1929                  *         For now, we just go idle.
1930                  *
1931                  *         Going idle is probably the right thing if the
1932                  *         I/O was canceled.
1933                  */
1934                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1935                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1936                               "accept failed: %s",
1937                               isc_result_totext(nevent->result));
1938         }
1939
1940         if (exit_check(client))
1941                 goto freeevent;
1942
1943         if (nevent->result == ISC_R_SUCCESS) {
1944                 int match;
1945                 isc_netaddr_t netaddr;
1946
1947                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1948
1949                 if (ns_g_server->blackholeacl != NULL &&
1950                     dns_acl_match(&netaddr, NULL,
1951                                   ns_g_server->blackholeacl,
1952                                   &ns_g_server->aclenv,
1953                                   &match, NULL) == ISC_R_SUCCESS &&
1954                     match > 0)
1955                 {
1956                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1957                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1958                                       "blackholed connection attempt");
1959                         client->newstate = NS_CLIENTSTATE_READY;
1960                         (void)exit_check(client);
1961                         goto freeevent;
1962                 }
1963
1964                 INSIST(client->tcpmsg_valid == ISC_FALSE);
1965                 dns_tcpmsg_init(client->mctx, client->tcpsocket,
1966                                 &client->tcpmsg);
1967                 client->tcpmsg_valid = ISC_TRUE;
1968
1969                 /*
1970                  * Let a new client take our place immediately, before
1971                  * we wait for a request packet.  If we don't,
1972                  * telnetting to port 53 (once per CPU) will
1973                  * deny service to legititmate TCP clients.
1974                  */
1975                 result = isc_quota_attach(&ns_g_server->tcpquota,
1976                                           &client->tcpquota);
1977                 if (result == ISC_R_SUCCESS)
1978                         result = ns_client_replace(client);
1979                 if (result != ISC_R_SUCCESS) {
1980                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1981                                       NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
1982                                       "no more TCP clients: %s",
1983                                       isc_result_totext(result));
1984                 }
1985
1986                 client_read(client);
1987         }
1988
1989  freeevent:
1990         isc_event_free(&event);
1991 }
1992
1993 static void
1994 client_accept(ns_client_t *client) {
1995         isc_result_t result;
1996
1997         CTRACE("accept");
1998
1999         result = isc_socket_accept(client->tcplistener, client->task,
2000                                    client_newconn, client);
2001         if (result != ISC_R_SUCCESS) {
2002                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2003                                  "isc_socket_accept() failed: %s",
2004                                  isc_result_totext(result));
2005                 /*
2006                  * XXXRTH  What should we do?  We're trying to accept but
2007                  *         it didn't work.  If we just give up, then TCP
2008                  *         service may eventually stop.
2009                  *
2010                  *         For now, we just go idle.
2011                  */
2012                 return;
2013         }
2014         INSIST(client->naccepts == 0);
2015         client->naccepts++;
2016         LOCK(&client->interface->lock);
2017         client->interface->ntcpcurrent++;
2018         UNLOCK(&client->interface->lock);
2019 }
2020
2021 static void
2022 client_udprecv(ns_client_t *client) {
2023         isc_result_t result;
2024         isc_region_t r;
2025
2026         CTRACE("udprecv");
2027
2028         r.base = client->recvbuf;
2029         r.length = RECV_BUFFER_SIZE;
2030         result = isc_socket_recv2(client->udpsocket, &r, 1,
2031                                   client->task, client->recvevent, 0);
2032         if (result != ISC_R_SUCCESS) {
2033                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2034                                  "isc_socket_recv2() failed: %s",
2035                                  isc_result_totext(result));
2036                 /*
2037                  * This cannot happen in the current implementation, since
2038                  * isc_socket_recv2() cannot fail if flags == 0.
2039                  *
2040                  * If this does fail, we just go idle.
2041                  */
2042                 return;
2043         }
2044         INSIST(client->nrecvs == 0);
2045         client->nrecvs++;
2046 }
2047
2048 void
2049 ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
2050         REQUIRE(NS_CLIENT_VALID(source));
2051         REQUIRE(targetp != NULL && *targetp == NULL);
2052
2053         source->references++;
2054         ns_client_log(source, NS_LOGCATEGORY_CLIENT,
2055                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2056                       "ns_client_attach: ref = %d", source->references);
2057         *targetp = source;
2058 }
2059
2060 void
2061 ns_client_detach(ns_client_t **clientp) {
2062         ns_client_t *client = *clientp;
2063
2064         client->references--;
2065         INSIST(client->references >= 0);
2066         *clientp = NULL;
2067         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2068                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2069                       "ns_client_detach: ref = %d", client->references);
2070         (void)exit_check(client);
2071 }
2072
2073 isc_boolean_t
2074 ns_client_shuttingdown(ns_client_t *client) {
2075         return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
2076 }
2077
2078 isc_result_t
2079 ns_client_replace(ns_client_t *client) {
2080         isc_result_t result;
2081
2082         CTRACE("replace");
2083
2084         result = ns_clientmgr_createclients(client->manager,
2085                                             1, client->interface,
2086                                             (TCP_CLIENT(client) ?
2087                                              ISC_TRUE : ISC_FALSE));
2088         if (result != ISC_R_SUCCESS)
2089                 return (result);
2090
2091         /*
2092          * The responsibility for listening for new requests is hereby
2093          * transferred to the new client.  Therefore, the old client
2094          * should refrain from listening for any more requests.
2095          */
2096         client->mortal = ISC_TRUE;
2097
2098         return (ISC_R_SUCCESS);
2099 }
2100
2101 /***
2102  *** Client Manager
2103  ***/
2104
2105 static void
2106 clientmgr_destroy(ns_clientmgr_t *manager) {
2107         REQUIRE(ISC_LIST_EMPTY(manager->active));
2108         REQUIRE(ISC_LIST_EMPTY(manager->inactive));
2109         REQUIRE(ISC_LIST_EMPTY(manager->recursing));
2110
2111         MTRACE("clientmgr_destroy");
2112
2113         DESTROYLOCK(&manager->lock);
2114         manager->magic = 0;
2115         isc_mem_put(manager->mctx, manager, sizeof(*manager));
2116 }
2117
2118 isc_result_t
2119 ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2120                     isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
2121 {
2122         ns_clientmgr_t *manager;
2123         isc_result_t result;
2124
2125         manager = isc_mem_get(mctx, sizeof(*manager));
2126         if (manager == NULL)
2127                 return (ISC_R_NOMEMORY);
2128
2129         result = isc_mutex_init(&manager->lock);
2130         if (result != ISC_R_SUCCESS)
2131                 goto cleanup_manager;
2132
2133         manager->mctx = mctx;
2134         manager->taskmgr = taskmgr;
2135         manager->timermgr = timermgr;
2136         manager->exiting = ISC_FALSE;
2137         ISC_LIST_INIT(manager->active);
2138         ISC_LIST_INIT(manager->inactive);
2139         ISC_LIST_INIT(manager->recursing);
2140         manager->magic = MANAGER_MAGIC;
2141
2142         MTRACE("create");
2143
2144         *managerp = manager;
2145
2146         return (ISC_R_SUCCESS);
2147
2148  cleanup_manager:
2149         isc_mem_put(manager->mctx, manager, sizeof(*manager));
2150
2151         return (result);
2152 }
2153
2154 void
2155 ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2156         ns_clientmgr_t *manager;
2157         ns_client_t *client;
2158         isc_boolean_t need_destroy = ISC_FALSE;
2159
2160         REQUIRE(managerp != NULL);
2161         manager = *managerp;
2162         REQUIRE(VALID_MANAGER(manager));
2163
2164         MTRACE("destroy");
2165
2166         LOCK(&manager->lock);
2167
2168         manager->exiting = ISC_TRUE;
2169
2170         for (client = ISC_LIST_HEAD(manager->recursing);
2171              client != NULL;
2172              client = ISC_LIST_NEXT(client, link))
2173                 isc_task_shutdown(client->task);
2174
2175         for (client = ISC_LIST_HEAD(manager->active);
2176              client != NULL;
2177              client = ISC_LIST_NEXT(client, link))
2178                 isc_task_shutdown(client->task);
2179
2180         for (client = ISC_LIST_HEAD(manager->inactive);
2181              client != NULL;
2182              client = ISC_LIST_NEXT(client, link))
2183                 isc_task_shutdown(client->task);
2184
2185         if (ISC_LIST_EMPTY(manager->active) &&
2186             ISC_LIST_EMPTY(manager->inactive) &&
2187             ISC_LIST_EMPTY(manager->recursing))
2188                 need_destroy = ISC_TRUE;
2189
2190         UNLOCK(&manager->lock);
2191
2192         if (need_destroy)
2193                 clientmgr_destroy(manager);
2194
2195         *managerp = NULL;
2196 }
2197
2198 isc_result_t
2199 ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
2200                            ns_interface_t *ifp, isc_boolean_t tcp)
2201 {
2202         isc_result_t result = ISC_R_SUCCESS;
2203         unsigned int i;
2204         ns_client_t *client;
2205
2206         REQUIRE(VALID_MANAGER(manager));
2207         REQUIRE(n > 0);
2208
2209         MTRACE("createclients");
2210
2211         /*
2212          * We MUST lock the manager lock for the entire client creation
2213          * process.  If we didn't do this, then a client could get a
2214          * shutdown event and disappear out from under us.
2215          */
2216
2217         LOCK(&manager->lock);
2218
2219         for (i = 0; i < n; i++) {
2220                 isc_event_t *ev;
2221                 /*
2222                  * Allocate a client.  First try to get a recycled one;
2223                  * if that fails, make a new one.
2224                  */
2225                 client = ISC_LIST_HEAD(manager->inactive);
2226                 if (client != NULL) {
2227                         MTRACE("recycle");
2228                         ISC_LIST_UNLINK(manager->inactive, client, link);
2229                         client->list = NULL;
2230                 } else {
2231                         MTRACE("create new");
2232                         result = client_create(manager, &client);
2233                         if (result != ISC_R_SUCCESS)
2234                                 break;
2235                 }
2236
2237                 ns_interface_attach(ifp, &client->interface);
2238                 client->state = NS_CLIENTSTATE_READY;
2239                 INSIST(client->recursionquota == NULL);
2240
2241                 if (tcp) {
2242                         client->attributes |= NS_CLIENTATTR_TCP;
2243                         isc_socket_attach(ifp->tcpsocket,
2244                                           &client->tcplistener);
2245                 } else {
2246                         isc_socket_t *sock;
2247
2248                         dns_dispatch_attach(ifp->udpdispatch,
2249                                             &client->dispatch);
2250                         sock = dns_dispatch_getsocket(client->dispatch);
2251                         isc_socket_attach(sock, &client->udpsocket);
2252                 }
2253                 client->manager = manager;
2254                 ISC_LIST_APPEND(manager->active, client, link);
2255                 client->list = &manager->active;
2256
2257                 INSIST(client->nctls == 0);
2258                 client->nctls++;
2259                 ev = &client->ctlevent;
2260                 isc_task_send(client->task, &ev);
2261         }
2262         if (i != 0) {
2263                 /*
2264                  * We managed to create at least one client, so we
2265                  * declare victory.
2266                  */
2267                 result = ISC_R_SUCCESS;
2268         }
2269
2270         UNLOCK(&manager->lock);
2271
2272         return (result);
2273 }
2274
2275 isc_sockaddr_t *
2276 ns_client_getsockaddr(ns_client_t *client) {
2277         return (&client->peeraddr);
2278 }
2279
2280 isc_result_t
2281 ns_client_checkaclsilent(ns_client_t *client, dns_acl_t *acl,
2282                          isc_boolean_t default_allow)
2283 {
2284         isc_result_t result;
2285         int match;
2286         isc_netaddr_t netaddr;
2287
2288         if (acl == NULL) {
2289                 if (default_allow)
2290                         goto allow;
2291                 else
2292                         goto deny;
2293         }
2294
2295         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2296
2297         result = dns_acl_match(&netaddr, client->signer, acl,
2298                                &ns_g_server->aclenv,
2299                                &match, NULL);
2300         if (result != ISC_R_SUCCESS)
2301                 goto deny; /* Internal error, already logged. */
2302         if (match > 0)
2303                 goto allow;
2304         goto deny; /* Negative match or no match. */
2305
2306  allow:
2307         return (ISC_R_SUCCESS);
2308
2309  deny:
2310         return (DNS_R_REFUSED);
2311 }
2312
2313 isc_result_t
2314 ns_client_checkacl(ns_client_t *client,
2315                    const char *opname, dns_acl_t *acl,
2316                    isc_boolean_t default_allow, int log_level)
2317 {
2318         isc_result_t result =
2319                 ns_client_checkaclsilent(client, acl, default_allow);
2320
2321         if (result == ISC_R_SUCCESS) 
2322                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2323                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2324                               "%s approved", opname);
2325         else
2326                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2327                               NS_LOGMODULE_CLIENT,
2328                               log_level, "%s denied", opname);
2329         return (result);
2330 }
2331
2332 static void
2333 ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2334         if (client->peeraddr_valid)
2335                 isc_sockaddr_format(&client->peeraddr, peerbuf, len);
2336         else
2337                 snprintf(peerbuf, len, "@%p", client);
2338 }
2339
2340 void
2341 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2342            isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2343 {
2344         char msgbuf[2048];
2345         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2346         const char *name = "";
2347         const char *sep = "";
2348
2349         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2350         ns_client_name(client, peerbuf, sizeof(peerbuf));
2351         if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2352             strcmp(client->view->name, "_default") != 0) {
2353                 name = client->view->name;
2354                 sep = ": view ";
2355         }
2356
2357         isc_log_write(ns_g_lctx, category, module, level,
2358                       "client %s%s%s: %s", peerbuf, sep, name, msgbuf);
2359 }
2360
2361 void
2362 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2363            isc_logmodule_t *module, int level, const char *fmt, ...)
2364 {
2365         va_list ap;
2366
2367         if (! isc_log_wouldlog(ns_g_lctx, level))
2368                 return;
2369
2370         va_start(ap, fmt);
2371         ns_client_logv(client, category, module, level, fmt, ap);
2372         va_end(ap);
2373 }
2374
2375 void
2376 ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
2377                  dns_rdataclass_t rdclass, char *buf, size_t len) 
2378 {
2379         char namebuf[DNS_NAME_FORMATSIZE];
2380         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2381         char classbuf[DNS_RDATACLASS_FORMATSIZE];
2382
2383         dns_name_format(name, namebuf, sizeof(namebuf));
2384         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2385         dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2386         (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2387                        classbuf);
2388 }
2389
2390 static void
2391 ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2392         isc_buffer_t buffer;
2393         char *buf = NULL;
2394         int len = 1024;
2395         isc_result_t result;
2396
2397         /*
2398          * Note that these are multiline debug messages.  We want a newline
2399          * to appear in the log after each message.
2400          */
2401
2402         do {
2403                 buf = isc_mem_get(client->mctx, len);
2404                 if (buf == NULL)
2405                         break;
2406                 isc_buffer_init(&buffer, buf, len);
2407                 result = dns_message_totext(client->message,
2408                                             &dns_master_style_debug,
2409                                             0, &buffer);
2410                 if (result == ISC_R_NOSPACE) {
2411                         isc_mem_put(client->mctx, buf, len);
2412                         len += 1024;
2413                 } else if (result == ISC_R_SUCCESS)
2414                         ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
2415                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2416                                       "%s\n%.*s", reason,
2417                                        (int)isc_buffer_usedlength(&buffer),
2418                                        buf);
2419         } while (result == ISC_R_NOSPACE);
2420
2421         if (buf != NULL)
2422                 isc_mem_put(client->mctx, buf, len);
2423 }
2424
2425 void
2426 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2427         ns_client_t *client;
2428         char namebuf[DNS_NAME_FORMATSIZE];
2429         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2430         const char *name;
2431         const char *sep;
2432
2433         REQUIRE(VALID_MANAGER(manager));
2434               
2435         LOCK(&manager->lock);
2436         client = ISC_LIST_HEAD(manager->recursing);
2437         while (client != NULL) {
2438                 ns_client_name(client, peerbuf, sizeof(peerbuf));
2439                 if (client->view != NULL &&
2440                     strcmp(client->view->name, "_bind") != 0 &&
2441                     strcmp(client->view->name, "_default") != 0) {
2442                         name = client->view->name;
2443                         sep = ": view ";
2444                 } else {
2445                         name = "";
2446                         sep = "";
2447                 }
2448                 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2449                 fprintf(f, "; client %s%s%s: '%s' requesttime %d\n",
2450                         peerbuf, sep, name, namebuf, client->requesttime);
2451                 client = ISC_LIST_NEXT(client, link);
2452         }
2453         UNLOCK(&manager->lock);
2454 }
2455
2456 void
2457 ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2458
2459         if (client->manager != NULL)
2460                 LOCK(&client->manager->lock);
2461         if (client->query.restarts > 0) {
2462                 /*
2463                  * client->query.qname was dynamically allocated.
2464                  */
2465                 dns_message_puttempname(client->message,
2466                                         &client->query.qname);
2467         }
2468         client->query.qname = name;
2469         if (client->manager != NULL)
2470                 UNLOCK(&client->manager->lock);
2471 }