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