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