]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/bin/named/client.c
MFC r363988:
[FreeBSD/stable/9.git] / contrib / bind9 / bin / named / client.c
1 /*
2  * Copyright (C) 2004-2016  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 #include <config.h>
19
20 #include <isc/formatcheck.h>
21 #include <isc/mutex.h>
22 #include <isc/once.h>
23 #include <isc/platform.h>
24 #include <isc/print.h>
25 #include <isc/queue.h>
26 #include <isc/random.h>
27 #include <isc/stats.h>
28 #include <isc/stdio.h>
29 #include <isc/string.h>
30 #include <isc/task.h>
31 #include <isc/timer.h>
32 #include <isc/util.h>
33
34 #include <dns/db.h>
35 #include <dns/dispatch.h>
36 #include <dns/events.h>
37 #include <dns/message.h>
38 #include <dns/peer.h>
39 #include <dns/rcode.h>
40 #include <dns/rdata.h>
41 #include <dns/rdataclass.h>
42 #include <dns/rdatalist.h>
43 #include <dns/rdataset.h>
44 #include <dns/resolver.h>
45 #include <dns/stats.h>
46 #include <dns/tsig.h>
47 #include <dns/view.h>
48 #include <dns/zone.h>
49
50 #include <named/interfacemgr.h>
51 #include <named/log.h>
52 #include <named/notify.h>
53 #include <named/os.h>
54 #include <named/server.h>
55 #include <named/update.h>
56
57 /***
58  *** Client
59  ***/
60
61 /*! \file
62  * Client Routines
63  *
64  * Important note!
65  *
66  * All client state changes, other than that from idle to listening, occur
67  * as a result of events.  This guarantees serialization and avoids the
68  * need for locking.
69  *
70  * If a routine is ever created that allows someone other than the client's
71  * task to change the client, then the client will have to be locked.
72  */
73
74 #define NS_CLIENT_TRACE
75 #ifdef NS_CLIENT_TRACE
76 #define CTRACE(m)       ns_client_log(client, \
77                                       NS_LOGCATEGORY_CLIENT, \
78                                       NS_LOGMODULE_CLIENT, \
79                                       ISC_LOG_DEBUG(3), \
80                                       "%s", (m))
81 #define MTRACE(m)       isc_log_write(ns_g_lctx, \
82                                       NS_LOGCATEGORY_GENERAL, \
83                                       NS_LOGMODULE_CLIENT, \
84                                       ISC_LOG_DEBUG(3), \
85                                       "clientmgr @%p: %s", manager, (m))
86 #else
87 #define CTRACE(m)       ((void)(m))
88 #define MTRACE(m)       ((void)(m))
89 #endif
90
91 #define TCP_CLIENT(c)   (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
92
93 #define TCP_BUFFER_SIZE                 (65535 + 2)
94 #define SEND_BUFFER_SIZE                4096
95 #define RECV_BUFFER_SIZE                4096
96
97 #ifdef ISC_PLATFORM_USETHREADS
98 #define NMCTXS                          100
99 /*%<
100  * Number of 'mctx pools' for clients. (Should this be configurable?)
101  * When enabling threads, we use a pool of memory contexts shared by
102  * client objects, since concurrent access to a shared context would cause
103  * heavy contentions.  The above constant is expected to be enough for
104  * completely avoiding contentions among threads for an authoritative-only
105  * server.
106  */
107 #else
108 #define NMCTXS                          0
109 /*%<
110  * If named with built without thread, simply share manager's context.  Using
111  * a separate context in this case would simply waste memory.
112  */
113 #endif
114
115
116 /*% nameserver client manager structure */
117 struct ns_clientmgr {
118         /* Unlocked. */
119         unsigned int                    magic;
120
121         /* The queue object has its own locks */
122         client_queue_t                  inactive;     /*%< To be recycled */
123
124         isc_mem_t *                     mctx;
125         isc_taskmgr_t *                 taskmgr;
126         isc_timermgr_t *                timermgr;
127
128         /* Lock covers manager state. */
129         isc_mutex_t                     lock;
130         isc_boolean_t                   exiting;
131
132         /* Lock covers the clients list */
133         isc_mutex_t                     listlock;
134         client_list_t                   clients;      /*%< All active clients */
135
136         /* Lock covers the recursing list */
137         isc_mutex_t                     reclock;
138         client_list_t                   recursing;    /*%< Recursing clients */
139
140 #if NMCTXS > 0
141         /*%< mctx pool for clients. */
142         unsigned int                    nextmctx;
143         isc_mem_t *                     mctxpool[NMCTXS];
144 #endif
145 };
146
147 #define MANAGER_MAGIC                   ISC_MAGIC('N', 'S', 'C', 'm')
148 #define VALID_MANAGER(m)                ISC_MAGIC_VALID(m, MANAGER_MAGIC)
149
150 /*!
151  * Client object states.  Ordering is significant: higher-numbered
152  * states are generally "more active", meaning that the client can
153  * have more dynamically allocated data, outstanding events, etc.
154  * In the list below, any such properties listed for state N
155  * also apply to any state > N.
156  *
157  * To force the client into a less active state, set client->newstate
158  * to that state and call exit_check().  This will cause any
159  * activities defined for higher-numbered states to be aborted.
160  */
161
162 #define NS_CLIENTSTATE_FREED    0
163 /*%<
164  * The client object no longer exists.
165  */
166
167 #define NS_CLIENTSTATE_INACTIVE 1
168 /*%<
169  * The client object exists and has a task and timer.
170  * Its "query" struct and sendbuf are initialized.
171  * It is on the client manager's list of inactive clients.
172  * It has a message and OPT, both in the reset state.
173  */
174
175 #define NS_CLIENTSTATE_READY    2
176 /*%<
177  * The client object is either a TCP or a UDP one, and
178  * it is associated with a network interface.  It is on the
179  * client manager's list of active clients.
180  *
181  * If it is a TCP client object, it has a TCP listener socket
182  * and an outstanding TCP listen request.
183  *
184  * If it is a UDP client object, it has a UDP listener socket
185  * and an outstanding UDP receive request.
186  */
187
188 #define NS_CLIENTSTATE_READING  3
189 /*%<
190  * The client object is a TCP client object that has received
191  * a connection.  It has a tcpsocket, tcpmsg, TCP quota, and an
192  * outstanding TCP read request.  This state is not used for
193  * UDP client objects.
194  */
195
196 #define NS_CLIENTSTATE_WORKING  4
197 /*%<
198  * The client object has received a request and is working
199  * on it.  It has a view, and it may have any of a non-reset OPT,
200  * recursion quota, and an outstanding write request.
201  */
202
203 #define NS_CLIENTSTATE_RECURSING  5
204 /*%<
205  * The client object is recursing.  It will be on the 'recursing'
206  * list.
207  */
208
209 #define NS_CLIENTSTATE_MAX      9
210 /*%<
211  * Sentinel value used to indicate "no state".  When client->newstate
212  * has this value, we are not attempting to exit the current state.
213  * Must be greater than any valid state.
214  */
215
216 /*
217  * Enable ns_client_dropport() by default.
218  */
219 #ifndef NS_CLIENT_DROPPORT
220 #define NS_CLIENT_DROPPORT 1
221 #endif
222
223 unsigned int ns_client_requests;
224
225 static void client_read(ns_client_t *client);
226 static void client_accept(ns_client_t *client);
227 static void client_udprecv(ns_client_t *client);
228 static void clientmgr_destroy(ns_clientmgr_t *manager);
229 static isc_boolean_t exit_check(ns_client_t *client);
230 static void ns_client_endrequest(ns_client_t *client);
231 static void client_start(isc_task_t *task, isc_event_t *event);
232 static void client_request(isc_task_t *task, isc_event_t *event);
233 static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
234 static isc_result_t get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
235                                dns_dispatch_t *disp, isc_boolean_t tcp);
236 static inline isc_boolean_t
237 allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl);
238
239 void
240 ns_client_recursing(ns_client_t *client) {
241         REQUIRE(NS_CLIENT_VALID(client));
242         REQUIRE(client->state == NS_CLIENTSTATE_WORKING);
243
244         LOCK(&client->manager->reclock);
245         client->newstate = client->state = NS_CLIENTSTATE_RECURSING;
246         ISC_LIST_APPEND(client->manager->recursing, client, rlink);
247         UNLOCK(&client->manager->reclock);
248 }
249
250 void
251 ns_client_killoldestquery(ns_client_t *client) {
252         ns_client_t *oldest;
253         REQUIRE(NS_CLIENT_VALID(client));
254
255         LOCK(&client->manager->reclock);
256         oldest = ISC_LIST_HEAD(client->manager->recursing);
257         if (oldest != NULL) {
258                 ISC_LIST_UNLINK(client->manager->recursing, oldest, rlink);
259                 UNLOCK(&client->manager->reclock);
260                 ns_query_cancel(oldest);
261         } else
262                 UNLOCK(&client->manager->reclock);
263 }
264
265 void
266 ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
267         isc_result_t result;
268         isc_interval_t interval;
269
270         isc_interval_set(&interval, seconds, 0);
271         result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
272                                  &interval, ISC_FALSE);
273         client->timerset = ISC_TRUE;
274         if (result != ISC_R_SUCCESS) {
275                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
276                               NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
277                               "setting timeout: %s",
278                               isc_result_totext(result));
279                 /* Continue anyway. */
280         }
281 }
282
283 /*%
284  * Check for a deactivation or shutdown request and take appropriate
285  * action.  Returns ISC_TRUE if either is in progress; in this case
286  * the caller must no longer use the client object as it may have been
287  * freed.
288  */
289 static isc_boolean_t
290 exit_check(ns_client_t *client) {
291         isc_boolean_t destroy_manager = ISC_FALSE;
292         ns_clientmgr_t *manager = NULL;
293
294         REQUIRE(NS_CLIENT_VALID(client));
295         manager = client->manager;
296
297         if (client->state <= client->newstate)
298                 return (ISC_FALSE); /* Business as usual. */
299
300         INSIST(client->newstate < NS_CLIENTSTATE_RECURSING);
301
302         /*
303          * We need to detach from the view early when shutting down
304          * the server to break the following vicious circle:
305          *
306          *  - The resolver will not shut down until the view refcount is zero
307          *  - The view refcount does not go to zero until all clients detach
308          *  - The client does not detach from the view until references is zero
309          *  - references does not go to zero until the resolver has shut down
310          *
311          * Keep the view attached until any outstanding updates complete.
312          */
313         if (client->nupdates == 0 &&
314             client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
315                 dns_view_detach(&client->view);
316
317         if (client->state == NS_CLIENTSTATE_WORKING ||
318             client->state == NS_CLIENTSTATE_RECURSING)
319         {
320                 INSIST(client->newstate <= NS_CLIENTSTATE_READING);
321                 /*
322                  * Let the update processing complete.
323                  */
324                 if (client->nupdates > 0)
325                         return (ISC_TRUE);
326
327                 /*
328                  * We are trying to abort request processing.
329                  */
330                 if (client->nsends > 0) {
331                         isc_socket_t *sock;
332                         if (TCP_CLIENT(client))
333                                 sock = client->tcpsocket;
334                         else
335                                 sock = client->udpsocket;
336                         isc_socket_cancel(sock, client->task,
337                                           ISC_SOCKCANCEL_SEND);
338                 }
339
340                 if (! (client->nsends == 0 && client->nrecvs == 0 &&
341                        client->references == 0))
342                 {
343                         /*
344                          * Still waiting for I/O cancel completion.
345                          * or lingering references.
346                          */
347                         return (ISC_TRUE);
348                 }
349
350                 /*
351                  * I/O cancel is complete.  Burn down all state
352                  * related to the current request.  Ensure that
353                  * the client is no longer on the recursing list.
354                  *
355                  * We need to check whether the client is still linked,
356                  * because it may already have been removed from the
357                  * recursing list by ns_client_killoldestquery()
358                  */
359                 if (client->state == NS_CLIENTSTATE_RECURSING) {
360                         LOCK(&manager->reclock);
361                         if (ISC_LINK_LINKED(client, rlink))
362                                 ISC_LIST_UNLINK(manager->recursing,
363                                                 client, rlink);
364                         UNLOCK(&manager->reclock);
365                 }
366                 ns_client_endrequest(client);
367
368                 client->state = NS_CLIENTSTATE_READING;
369                 INSIST(client->recursionquota == NULL);
370
371                 if (NS_CLIENTSTATE_READING == client->newstate) {
372                         client_read(client);
373                         client->newstate = NS_CLIENTSTATE_MAX;
374                         return (ISC_TRUE); /* We're done. */
375                 }
376         }
377
378         if (client->state == NS_CLIENTSTATE_READING) {
379                 /*
380                  * We are trying to abort the current TCP connection,
381                  * if any.
382                  */
383                 INSIST(client->recursionquota == NULL);
384                 INSIST(client->newstate <= NS_CLIENTSTATE_READY);
385                 if (client->nreads > 0)
386                         dns_tcpmsg_cancelread(&client->tcpmsg);
387                 if (! client->nreads == 0) {
388                         /* Still waiting for read cancel completion. */
389                         return (ISC_TRUE);
390                 }
391
392                 if (client->tcpmsg_valid) {
393                         dns_tcpmsg_invalidate(&client->tcpmsg);
394                         client->tcpmsg_valid = ISC_FALSE;
395                 }
396                 if (client->tcpsocket != NULL) {
397                         CTRACE("closetcp");
398                         isc_socket_detach(&client->tcpsocket);
399                 }
400
401                 if (client->tcpquota != NULL)
402                         isc_quota_detach(&client->tcpquota);
403
404                 if (client->timerset) {
405                         (void)isc_timer_reset(client->timer,
406                                               isc_timertype_inactive,
407                                               NULL, NULL, ISC_TRUE);
408                         client->timerset = ISC_FALSE;
409                 }
410
411                 client->peeraddr_valid = ISC_FALSE;
412
413                 client->state = NS_CLIENTSTATE_READY;
414                 INSIST(client->recursionquota == NULL);
415
416                 /*
417                  * Now the client is ready to accept a new TCP connection
418                  * or UDP request, but we may have enough clients doing
419                  * that already.  Check whether this client needs to remain
420                  * active and force it to go inactive if not.
421                  *
422                  * UDP clients go inactive at this point, but TCP clients
423                  * may remain active if we have fewer active TCP client
424                  * objects than desired due to an earlier quota exhaustion.
425                  */
426                 if (client->mortal && TCP_CLIENT(client) && !ns_g_clienttest) {
427                         LOCK(&client->interface->lock);
428                         if (client->interface->ntcpcurrent <
429                                     client->interface->ntcptarget)
430                                 client->mortal = ISC_FALSE;
431                         UNLOCK(&client->interface->lock);
432                 }
433
434                 /*
435                  * We don't need the client; send it to the inactive
436                  * queue for recycling.
437                  */
438                 if (client->mortal) {
439                         if (client->newstate > NS_CLIENTSTATE_INACTIVE)
440                                 client->newstate = NS_CLIENTSTATE_INACTIVE;
441                 }
442
443                 if (NS_CLIENTSTATE_READY == client->newstate) {
444                         if (TCP_CLIENT(client)) {
445                                 client_accept(client);
446                         } else
447                                 client_udprecv(client);
448                         client->newstate = NS_CLIENTSTATE_MAX;
449                         return (ISC_TRUE);
450                 }
451         }
452
453         if (client->state == NS_CLIENTSTATE_READY) {
454                 INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
455
456                 /*
457                  * We are trying to enter the inactive state.
458                  */
459                 if (client->naccepts > 0)
460                         isc_socket_cancel(client->tcplistener, client->task,
461                                           ISC_SOCKCANCEL_ACCEPT);
462
463                 /* Still waiting for accept cancel completion. */
464                 if (! (client->naccepts == 0))
465                         return (ISC_TRUE);
466
467                 /* Accept cancel is complete. */
468                 if (client->nrecvs > 0)
469                         isc_socket_cancel(client->udpsocket, client->task,
470                                           ISC_SOCKCANCEL_RECV);
471
472                 /* Still waiting for recv cancel completion. */
473                 if (! (client->nrecvs == 0))
474                         return (ISC_TRUE);
475
476                 /* Still waiting for control event to be delivered */
477                 if (client->nctls > 0)
478                         return (ISC_TRUE);
479
480                 /* Deactivate the client. */
481                 if (client->interface)
482                         ns_interface_detach(&client->interface);
483
484                 INSIST(client->naccepts == 0);
485                 INSIST(client->recursionquota == NULL);
486                 if (client->tcplistener != NULL)
487                         isc_socket_detach(&client->tcplistener);
488
489                 if (client->udpsocket != NULL)
490                         isc_socket_detach(&client->udpsocket);
491
492                 if (client->dispatch != NULL)
493                         dns_dispatch_detach(&client->dispatch);
494
495                 client->attributes = 0;
496                 client->mortal = ISC_FALSE;
497
498                 /*
499                  * Put the client on the inactive list.  If we are aiming for
500                  * the "freed" state, it will be removed from the inactive
501                  * list shortly, and we need to keep the manager locked until
502                  * that has been done, lest the manager decide to reactivate
503                  * the dying client inbetween.
504                  */
505                 client->state = NS_CLIENTSTATE_INACTIVE;
506                 INSIST(client->recursionquota == NULL);
507
508                 if (client->state == client->newstate) {
509                         client->newstate = NS_CLIENTSTATE_MAX;
510                         if (!ns_g_clienttest && manager != NULL &&
511                             !manager->exiting)
512                                 ISC_QUEUE_PUSH(manager->inactive, client,
513                                                ilink);
514                         if (client->needshutdown)
515                                 isc_task_shutdown(client->task);
516                         return (ISC_TRUE);
517                 }
518         }
519
520         if (client->state == NS_CLIENTSTATE_INACTIVE) {
521                 INSIST(client->newstate == NS_CLIENTSTATE_FREED);
522                 /*
523                  * We are trying to free the client.
524                  *
525                  * When "shuttingdown" is true, either the task has received
526                  * its shutdown event or no shutdown event has ever been
527                  * set up.  Thus, we have no outstanding shutdown
528                  * event at this point.
529                  */
530                 REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
531
532                 INSIST(client->recursionquota == NULL);
533                 INSIST(!ISC_QLINK_LINKED(client, ilink));
534
535                 if (manager != NULL) {
536                         LOCK(&manager->listlock);
537                         ISC_LIST_UNLINK(manager->clients, client, link);
538                         LOCK(&manager->lock);
539                         if (manager->exiting &&
540                             ISC_LIST_EMPTY(manager->clients))
541                                 destroy_manager = ISC_TRUE;
542                         UNLOCK(&manager->lock);
543                         UNLOCK(&manager->listlock);
544                 }
545
546                 ns_query_free(client);
547                 isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
548                 isc_event_free((isc_event_t **)&client->sendevent);
549                 isc_event_free((isc_event_t **)&client->recvevent);
550                 isc_timer_detach(&client->timer);
551
552                 if (client->tcpbuf != NULL)
553                         isc_mem_put(client->mctx, client->tcpbuf,
554                                     TCP_BUFFER_SIZE);
555                 if (client->opt != NULL) {
556                         INSIST(dns_rdataset_isassociated(client->opt));
557                         dns_rdataset_disassociate(client->opt);
558                         dns_message_puttemprdataset(client->message,
559                                                     &client->opt);
560                 }
561
562                 dns_message_destroy(&client->message);
563
564                 /*
565                  * Detaching the task must be done after unlinking from
566                  * the manager's lists because the manager accesses
567                  * client->task.
568                  */
569                 if (client->task != NULL)
570                         isc_task_detach(&client->task);
571
572                 CTRACE("free");
573                 client->magic = 0;
574
575                 /*
576                  * Check that there are no other external references to
577                  * the memory context.
578                  */
579                 if (ns_g_clienttest && isc_mem_references(client->mctx) != 1) {
580                         isc_mem_stats(client->mctx, stderr);
581                         INSIST(0);
582                 }
583
584                 /*
585                  * Destroy the fetchlock mutex that was created in
586                  * ns_query_init().
587                  */
588                 DESTROYLOCK(&client->query.fetchlock);
589
590                 isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
591         }
592
593         if (destroy_manager && manager != NULL)
594                 clientmgr_destroy(manager);
595
596         return (ISC_TRUE);
597 }
598
599 /*%
600  * The client's task has received the client's control event
601  * as part of the startup process.
602  */
603 static void
604 client_start(isc_task_t *task, isc_event_t *event) {
605         ns_client_t *client = (ns_client_t *) event->ev_arg;
606
607         INSIST(task == client->task);
608
609         UNUSED(task);
610
611         INSIST(client->nctls == 1);
612         client->nctls--;
613
614         if (exit_check(client))
615                 return;
616
617         if (TCP_CLIENT(client)) {
618                 client_accept(client);
619         } else {
620                 client_udprecv(client);
621         }
622 }
623
624
625 /*%
626  * The client's task has received a shutdown event.
627  */
628 static void
629 client_shutdown(isc_task_t *task, isc_event_t *event) {
630         ns_client_t *client;
631
632         REQUIRE(event != NULL);
633         REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
634         client = event->ev_arg;
635         REQUIRE(NS_CLIENT_VALID(client));
636         REQUIRE(task == client->task);
637
638         UNUSED(task);
639
640         CTRACE("shutdown");
641
642         isc_event_free(&event);
643
644         if (client->shutdown != NULL) {
645                 (client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
646                 client->shutdown = NULL;
647                 client->shutdown_arg = NULL;
648         }
649
650         if (ISC_QLINK_LINKED(client, ilink))
651                 ISC_QUEUE_UNLINK(client->manager->inactive, client, ilink);
652
653         client->newstate = NS_CLIENTSTATE_FREED;
654         client->needshutdown = ISC_FALSE;
655         (void)exit_check(client);
656 }
657
658 static void
659 ns_client_endrequest(ns_client_t *client) {
660         INSIST(client->naccepts == 0);
661         INSIST(client->nreads == 0);
662         INSIST(client->nsends == 0);
663         INSIST(client->nrecvs == 0);
664         INSIST(client->nupdates == 0);
665         INSIST(client->state == NS_CLIENTSTATE_WORKING ||
666                client->state == NS_CLIENTSTATE_RECURSING);
667
668         CTRACE("endrequest");
669
670         if (client->next != NULL) {
671                 (client->next)(client);
672                 client->next = NULL;
673         }
674
675         if (client->view != NULL)
676                 dns_view_detach(&client->view);
677         if (client->opt != NULL) {
678                 INSIST(dns_rdataset_isassociated(client->opt));
679                 dns_rdataset_disassociate(client->opt);
680                 dns_message_puttemprdataset(client->message, &client->opt);
681         }
682
683         client->signer = NULL;
684         client->udpsize = 512;
685         client->extflags = 0;
686         client->ednsversion = -1;
687         dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
688
689         if (client->recursionquota != NULL)
690                 isc_quota_detach(&client->recursionquota);
691
692         /*
693          * Clear all client attributes that are specific to
694          * the request; that's all except the TCP flag.
695          */
696         client->attributes &= NS_CLIENTATTR_TCP;
697 }
698
699 void
700 ns_client_next(ns_client_t *client, isc_result_t result) {
701         int newstate;
702
703         REQUIRE(NS_CLIENT_VALID(client));
704         REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
705                 client->state == NS_CLIENTSTATE_RECURSING ||
706                 client->state == NS_CLIENTSTATE_READING);
707
708         CTRACE("next");
709
710         if (result != ISC_R_SUCCESS)
711                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
712                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
713                               "request failed: %s", isc_result_totext(result));
714
715         /*
716          * An error processing a TCP request may have left
717          * the connection out of sync.  To be safe, we always
718          * sever the connection when result != ISC_R_SUCCESS.
719          */
720         if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
721                 newstate = NS_CLIENTSTATE_READING;
722         else
723                 newstate = NS_CLIENTSTATE_READY;
724
725         if (client->newstate > newstate)
726                 client->newstate = newstate;
727         (void)exit_check(client);
728 }
729
730
731 static void
732 client_senddone(isc_task_t *task, isc_event_t *event) {
733         ns_client_t *client;
734         isc_socketevent_t *sevent = (isc_socketevent_t *) event;
735
736         REQUIRE(sevent != NULL);
737         REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
738         client = sevent->ev_arg;
739         REQUIRE(NS_CLIENT_VALID(client));
740         REQUIRE(task == client->task);
741         REQUIRE(sevent == client->sendevent);
742
743         UNUSED(task);
744
745         CTRACE("senddone");
746
747         if (sevent->result != ISC_R_SUCCESS)
748                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
749                               NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
750                               "error sending response: %s",
751                               isc_result_totext(sevent->result));
752
753         INSIST(client->nsends > 0);
754         client->nsends--;
755
756         if (client->tcpbuf != NULL) {
757                 INSIST(TCP_CLIENT(client));
758                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
759                 client->tcpbuf = NULL;
760         }
761
762         ns_client_next(client, ISC_R_SUCCESS);
763 }
764
765 /*%
766  * We only want to fail with ISC_R_NOSPACE when called from
767  * ns_client_sendraw() and not when called from ns_client_send(),
768  * tcpbuffer is NULL when called from ns_client_sendraw() and
769  * length != 0.  tcpbuffer != NULL when called from ns_client_send()
770  * and length == 0.
771  */
772
773 static isc_result_t
774 client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
775                     isc_buffer_t *tcpbuffer, isc_uint32_t length,
776                     unsigned char *sendbuf, unsigned char **datap)
777 {
778         unsigned char *data;
779         isc_uint32_t bufsize;
780         isc_result_t result;
781
782         INSIST(datap != NULL);
783         INSIST((tcpbuffer == NULL && length != 0) ||
784                (tcpbuffer != NULL && length == 0));
785
786         if (TCP_CLIENT(client)) {
787                 INSIST(client->tcpbuf == NULL);
788                 if (length + 2 > TCP_BUFFER_SIZE) {
789                         result = ISC_R_NOSPACE;
790                         goto done;
791                 }
792                 client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
793                 if (client->tcpbuf == NULL) {
794                         result = ISC_R_NOMEMORY;
795                         goto done;
796                 }
797                 data = client->tcpbuf;
798                 if (tcpbuffer != NULL) {
799                         isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
800                         isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
801                 } else {
802                         isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
803                         INSIST(length <= 0xffff);
804                         isc_buffer_putuint16(buffer, (isc_uint16_t)length);
805                 }
806         } else {
807                 data = sendbuf;
808                 if (client->udpsize < SEND_BUFFER_SIZE)
809                         bufsize = client->udpsize;
810                 else
811                         bufsize = SEND_BUFFER_SIZE;
812                 if (length > bufsize) {
813                         result = ISC_R_NOSPACE;
814                         goto done;
815                 }
816                 isc_buffer_init(buffer, data, bufsize);
817         }
818         *datap = data;
819         result = ISC_R_SUCCESS;
820
821  done:
822         return (result);
823 }
824
825 static isc_result_t
826 client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
827         struct in6_pktinfo *pktinfo;
828         isc_result_t result;
829         isc_region_t r;
830         isc_sockaddr_t *address;
831         isc_socket_t *sock;
832         isc_netaddr_t netaddr;
833         int match;
834         unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
835
836         if (TCP_CLIENT(client)) {
837                 sock = client->tcpsocket;
838                 address = NULL;
839         } else {
840                 sock = client->udpsocket;
841                 address = &client->peeraddr;
842
843                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
844                 if (ns_g_server->blackholeacl != NULL &&
845                     dns_acl_match(&netaddr, NULL,
846                                   ns_g_server->blackholeacl,
847                                   &ns_g_server->aclenv,
848                                   &match, NULL) == ISC_R_SUCCESS &&
849                     match > 0)
850                         return (DNS_R_BLACKHOLED);
851                 sockflags |= ISC_SOCKFLAG_NORETRY;
852         }
853
854         if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
855             (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
856                 pktinfo = &client->pktinfo;
857         else
858                 pktinfo = NULL;
859
860         isc_buffer_usedregion(buffer, &r);
861
862         CTRACE("sendto");
863
864         result = isc_socket_sendto2(sock, &r, client->task,
865                                     address, pktinfo,
866                                     client->sendevent, sockflags);
867         if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
868                 client->nsends++;
869                 if (result == ISC_R_SUCCESS)
870                         client_senddone(client->task,
871                                         (isc_event_t *)client->sendevent);
872                 result = ISC_R_SUCCESS;
873         }
874         return (result);
875 }
876
877 void
878 ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
879         isc_result_t result;
880         unsigned char *data;
881         isc_buffer_t buffer;
882         isc_region_t r;
883         isc_region_t *mr;
884         unsigned char sendbuf[SEND_BUFFER_SIZE];
885
886         REQUIRE(NS_CLIENT_VALID(client));
887
888         CTRACE("sendraw");
889
890         mr = dns_message_getrawmessage(message);
891         if (mr == NULL) {
892                 result = ISC_R_UNEXPECTEDEND;
893                 goto done;
894         }
895
896         result = client_allocsendbuf(client, &buffer, NULL, mr->length,
897                                      sendbuf, &data);
898         if (result != ISC_R_SUCCESS)
899                 goto done;
900
901         /*
902          * Copy message to buffer and fixup id.
903          */
904         isc_buffer_availableregion(&buffer, &r);
905         result = isc_buffer_copyregion(&buffer, mr);
906         if (result != ISC_R_SUCCESS)
907                 goto done;
908         r.base[0] = (client->message->id >> 8) & 0xff;
909         r.base[1] = client->message->id & 0xff;
910
911         result = client_sendpkg(client, &buffer);
912         if (result == ISC_R_SUCCESS)
913                 return;
914
915  done:
916         if (client->tcpbuf != NULL) {
917                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
918                 client->tcpbuf = NULL;
919         }
920         ns_client_next(client, result);
921 }
922
923 void
924 ns_client_send(ns_client_t *client) {
925         isc_result_t result;
926         unsigned char *data;
927         isc_buffer_t buffer;
928         isc_buffer_t tcpbuffer;
929         isc_region_t r;
930         dns_compress_t cctx;
931         isc_boolean_t cleanup_cctx = ISC_FALSE;
932         unsigned char sendbuf[SEND_BUFFER_SIZE];
933         unsigned int render_opts;
934         unsigned int preferred_glue;
935         isc_boolean_t opt_included = ISC_FALSE;
936
937         REQUIRE(NS_CLIENT_VALID(client));
938
939         CTRACE("send");
940
941         if ((client->attributes & NS_CLIENTATTR_RA) != 0)
942                 client->message->flags |= DNS_MESSAGEFLAG_RA;
943
944         if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
945                 render_opts = 0;
946         else
947                 render_opts = DNS_MESSAGERENDER_OMITDNSSEC;
948
949         preferred_glue = 0;
950         if (client->view != NULL) {
951                 if (client->view->preferred_glue == dns_rdatatype_a)
952                         preferred_glue = DNS_MESSAGERENDER_PREFER_A;
953                 else if (client->view->preferred_glue == dns_rdatatype_aaaa)
954                         preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
955         }
956         if (preferred_glue == 0) {
957                 if (isc_sockaddr_pf(&client->peeraddr) == AF_INET)
958                         preferred_glue = DNS_MESSAGERENDER_PREFER_A;
959                 else
960                         preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
961         }
962
963 #ifdef ALLOW_FILTER_AAAA_ON_V4
964         /*
965          * filter-aaaa-on-v4 yes or break-dnssec option to suppress
966          * AAAA records
967          * We already know that request came via IPv4,
968          * that we have both AAAA and A records,
969          * and that we either have no signatures that the client wants
970          * or we are supposed to break DNSSEC.
971          *
972          * Override preferred glue if necessary.
973          */
974         if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0) {
975                 render_opts |= DNS_MESSAGERENDER_FILTER_AAAA;
976                 if (preferred_glue == DNS_MESSAGERENDER_PREFER_AAAA)
977                         preferred_glue = DNS_MESSAGERENDER_PREFER_A;
978         }
979 #endif
980
981         /*
982          * XXXRTH  The following doesn't deal with TCP buffer resizing.
983          */
984         result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
985                                      sendbuf, &data);
986         if (result != ISC_R_SUCCESS)
987                 goto done;
988
989         result = dns_compress_init(&cctx, -1, client->mctx);
990         if (result != ISC_R_SUCCESS)
991                 goto done;
992         if (client->peeraddr_valid && client->view != NULL) {
993                 isc_netaddr_t netaddr;
994                 dns_name_t *name = NULL;
995
996                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
997                 if (client->message->tsigkey != NULL)
998                         name = &client->message->tsigkey->name;
999                 if (client->view->nocasecompress == NULL ||
1000                     !allowed(&netaddr, name, client->view->nocasecompress))
1001                 {
1002                         dns_compress_setsensitive(&cctx, ISC_TRUE);
1003                 }
1004         }
1005         cleanup_cctx = ISC_TRUE;
1006
1007         result = dns_message_renderbegin(client->message, &cctx, &buffer);
1008         if (result != ISC_R_SUCCESS)
1009                 goto done;
1010
1011         if (client->opt != NULL) {
1012                 result = dns_message_setopt(client->message, client->opt);
1013                 opt_included = ISC_TRUE;
1014                 client->opt = NULL;
1015                 if (result != ISC_R_SUCCESS)
1016                         goto done;
1017         }
1018         result = dns_message_rendersection(client->message,
1019                                            DNS_SECTION_QUESTION, 0);
1020         if (result == ISC_R_NOSPACE) {
1021                 client->message->flags |= DNS_MESSAGEFLAG_TC;
1022                 goto renderend;
1023         }
1024         if (result != ISC_R_SUCCESS)
1025                 goto done;
1026 #ifdef USE_RRL
1027         /*
1028          * Stop after the question if TC was set for rate limiting.
1029          */
1030         if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
1031                 goto renderend;
1032 #endif /* USE_RRL */
1033         result = dns_message_rendersection(client->message,
1034                                            DNS_SECTION_ANSWER,
1035                                            DNS_MESSAGERENDER_PARTIAL |
1036                                            render_opts);
1037         if (result == ISC_R_NOSPACE) {
1038                 client->message->flags |= DNS_MESSAGEFLAG_TC;
1039                 goto renderend;
1040         }
1041         if (result != ISC_R_SUCCESS)
1042                 goto done;
1043         result = dns_message_rendersection(client->message,
1044                                            DNS_SECTION_AUTHORITY,
1045                                            DNS_MESSAGERENDER_PARTIAL |
1046                                            render_opts);
1047         if (result == ISC_R_NOSPACE) {
1048                 client->message->flags |= DNS_MESSAGEFLAG_TC;
1049                 goto renderend;
1050         }
1051         if (result != ISC_R_SUCCESS)
1052                 goto done;
1053         result = dns_message_rendersection(client->message,
1054                                            DNS_SECTION_ADDITIONAL,
1055                                            preferred_glue | render_opts);
1056         if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
1057                 goto done;
1058  renderend:
1059         result = dns_message_renderend(client->message);
1060
1061         if (result != ISC_R_SUCCESS)
1062                 goto done;
1063
1064         if (cleanup_cctx) {
1065                 dns_compress_invalidate(&cctx);
1066                 cleanup_cctx = ISC_FALSE;
1067         }
1068
1069         if (TCP_CLIENT(client)) {
1070                 isc_buffer_usedregion(&buffer, &r);
1071                 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
1072                 isc_buffer_add(&tcpbuffer, r.length);
1073                 result = client_sendpkg(client, &tcpbuffer);
1074         } else
1075                 result = client_sendpkg(client, &buffer);
1076
1077         /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
1078         isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response);
1079         if (opt_included) {
1080                 isc_stats_increment(ns_g_server->nsstats,
1081                                     dns_nsstatscounter_edns0out);
1082         }
1083         if (client->message->tsigkey != NULL) {
1084                 isc_stats_increment(ns_g_server->nsstats,
1085                                     dns_nsstatscounter_tsigout);
1086         }
1087         if (client->message->sig0key != NULL) {
1088                 isc_stats_increment(ns_g_server->nsstats,
1089                                     dns_nsstatscounter_sig0out);
1090         }
1091         if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
1092                 isc_stats_increment(ns_g_server->nsstats,
1093                                     dns_nsstatscounter_truncatedresp);
1094
1095         if (result == ISC_R_SUCCESS)
1096                 return;
1097
1098  done:
1099         if (client->tcpbuf != NULL) {
1100                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
1101                 client->tcpbuf = NULL;
1102         }
1103
1104         if (cleanup_cctx)
1105                 dns_compress_invalidate(&cctx);
1106
1107         ns_client_next(client, result);
1108 }
1109
1110 #if NS_CLIENT_DROPPORT
1111 #define DROPPORT_NO             0
1112 #define DROPPORT_REQUEST        1
1113 #define DROPPORT_RESPONSE       2
1114 /*%
1115  * ns_client_dropport determines if certain requests / responses
1116  * should be dropped based on the port number.
1117  *
1118  * Returns:
1119  * \li  0:      Don't drop.
1120  * \li  1:      Drop request.
1121  * \li  2:      Drop (error) response.
1122  */
1123 static int
1124 ns_client_dropport(in_port_t port) {
1125         switch (port) {
1126         case 7: /* echo */
1127         case 13: /* daytime */
1128         case 19: /* chargen */
1129         case 37: /* time */
1130                 return (DROPPORT_REQUEST);
1131         case 464: /* kpasswd */
1132                 return (DROPPORT_RESPONSE);
1133         }
1134         return (DROPPORT_NO);
1135 }
1136 #endif
1137
1138 void
1139 ns_client_error(ns_client_t *client, isc_result_t result) {
1140         dns_rcode_t rcode;
1141         dns_message_t *message;
1142
1143         REQUIRE(NS_CLIENT_VALID(client));
1144
1145         CTRACE("error");
1146
1147         message = client->message;
1148         rcode = dns_result_torcode(result);
1149
1150 #if NS_CLIENT_DROPPORT
1151         /*
1152          * Don't send FORMERR to ports on the drop port list.
1153          */
1154         if (rcode == dns_rcode_formerr &&
1155             ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
1156             DROPPORT_NO) {
1157                 char buf[64];
1158                 isc_buffer_t b;
1159
1160                 isc_buffer_init(&b, buf, sizeof(buf) - 1);
1161                 if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
1162                         isc_buffer_putstr(&b, "UNKNOWN RCODE");
1163                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1164                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1165                               "dropped error (%.*s) response: suspicious port",
1166                               (int)isc_buffer_usedlength(&b), buf);
1167                 ns_client_next(client, ISC_R_SUCCESS);
1168                 return;
1169         }
1170 #endif
1171
1172 #ifdef USE_RRL
1173         /*
1174          * Try to rate limit error responses.
1175          */
1176         if (client->view != NULL && client->view->rrl != NULL) {
1177                 isc_boolean_t wouldlog;
1178                 char log_buf[DNS_RRL_LOG_BUF_LEN];
1179                 dns_rrl_result_t rrl_result;
1180                 int loglevel;
1181
1182                 INSIST(rcode != dns_rcode_noerror &&
1183                        rcode != dns_rcode_nxdomain);
1184                 if (ns_g_server->log_queries)
1185                         loglevel = DNS_RRL_LOG_DROP;
1186                 else
1187                         loglevel = ISC_LOG_DEBUG(1);
1188                 wouldlog = isc_log_wouldlog(ns_g_lctx, loglevel);
1189                 rrl_result = dns_rrl(client->view, &client->peeraddr,
1190                                      TCP_CLIENT(client),
1191                                      dns_rdataclass_in, dns_rdatatype_none,
1192                                      NULL, result, client->now,
1193                                      wouldlog, log_buf, sizeof(log_buf));
1194                 if (rrl_result != DNS_RRL_RESULT_OK) {
1195                         /*
1196                          * Log dropped errors in the query category
1197                          * so that they are not lost in silence.
1198                          * Starts of rate-limited bursts are logged in
1199                          * NS_LOGCATEGORY_RRL.
1200                          */
1201                         if (wouldlog) {
1202                                 ns_client_log(client,
1203                                               NS_LOGCATEGORY_QUERY_ERRORS,
1204                                               NS_LOGMODULE_CLIENT,
1205                                               loglevel,
1206                                               "%s", log_buf);
1207                         }
1208                         /*
1209                          * Some error responses cannot be 'slipped',
1210                          * so don't try to slip any error responses.
1211                          */
1212                         if (!client->view->rrl->log_only) {
1213                                 isc_stats_increment(ns_g_server->nsstats,
1214                                                 dns_nsstatscounter_ratedropped);
1215                                 isc_stats_increment(ns_g_server->nsstats,
1216                                                 dns_nsstatscounter_dropped);
1217                                 ns_client_next(client, DNS_R_DROP);
1218                                 return;
1219                         }
1220                 }
1221         }
1222 #endif /* USE_RRL */
1223
1224         /*
1225          * Message may be an in-progress reply that we had trouble
1226          * with, in which case QR will be set.  We need to clear QR before
1227          * calling dns_message_reply() to avoid triggering an assertion.
1228          */
1229         message->flags &= ~DNS_MESSAGEFLAG_QR;
1230         /*
1231          * AA and AD shouldn't be set.
1232          */
1233         message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
1234         result = dns_message_reply(message, ISC_TRUE);
1235         if (result != ISC_R_SUCCESS) {
1236                 /*
1237                  * It could be that we've got a query with a good header,
1238                  * but a bad question section, so we try again with
1239                  * want_question_section set to ISC_FALSE.
1240                  */
1241                 result = dns_message_reply(message, ISC_FALSE);
1242                 if (result != ISC_R_SUCCESS) {
1243                         ns_client_next(client, result);
1244                         return;
1245                 }
1246         }
1247         message->rcode = rcode;
1248
1249         /*
1250          * FORMERR loop avoidance:  If we sent a FORMERR message
1251          * with the same ID to the same client less than two
1252          * seconds ago, assume that we are in an infinite error
1253          * packet dialog with a server for some protocol whose
1254          * error responses look enough like DNS queries to
1255          * elicit a FORMERR response.  Drop a packet to break
1256          * the loop.
1257          */
1258         if (rcode == dns_rcode_formerr) {
1259                 if (isc_sockaddr_equal(&client->peeraddr,
1260                                        &client->formerrcache.addr) &&
1261                     message->id == client->formerrcache.id &&
1262                     client->requesttime - client->formerrcache.time < 2) {
1263                         /* Drop packet. */
1264                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1265                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1266                                       "possible error packet loop, "
1267                                       "FORMERR dropped");
1268                         ns_client_next(client, result);
1269                         return;
1270                 }
1271                 client->formerrcache.addr = client->peeraddr;
1272                 client->formerrcache.time = client->requesttime;
1273                 client->formerrcache.id = message->id;
1274         }
1275         ns_client_send(client);
1276 }
1277
1278 static inline isc_result_t
1279 client_addopt(ns_client_t *client) {
1280         char nsid[BUFSIZ], *nsidp;
1281         isc_result_t result;
1282         dns_view_t *view;
1283         dns_resolver_t *resolver;
1284         isc_uint16_t udpsize;
1285         dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
1286         int count = 0;
1287         unsigned int flags;
1288
1289         REQUIRE(client->opt == NULL);   /* XXXRTH free old. */
1290
1291         view = client->view;
1292         resolver = (view != NULL) ? view->resolver : NULL;
1293         if (resolver != NULL)
1294                 udpsize = dns_resolver_getudpsize(resolver);
1295         else
1296                 udpsize = ns_g_udpsize;
1297
1298         flags = client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE;
1299
1300         /* Set EDNS options if applicable */
1301         if ((client->attributes & NS_CLIENTATTR_WANTNSID) != 0 &&
1302             (ns_g_server->server_id != NULL ||
1303              ns_g_server->server_usehostname)) {
1304                 if (ns_g_server->server_usehostname) {
1305                         result = ns_os_gethostname(nsid, sizeof(nsid));
1306                         if (result != ISC_R_SUCCESS) {
1307                                 goto no_nsid;
1308                         }
1309                         nsidp = nsid;
1310                 } else
1311                         nsidp = ns_g_server->server_id;
1312
1313                 INSIST(count < DNS_EDNSOPTIONS);
1314                 ednsopts[count].code = DNS_OPT_NSID;
1315                 ednsopts[count].length = strlen(nsidp);
1316                 ednsopts[count].value = (unsigned char *)nsidp;
1317                 count++;
1318         }
1319  no_nsid:
1320         result = dns_message_buildopt(client->message, &client->opt, 0,
1321                                       udpsize, flags, ednsopts, count);
1322         return (result);
1323 }
1324
1325 static inline isc_boolean_t
1326 allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
1327         int match;
1328         isc_result_t result;
1329
1330         if (acl == NULL)
1331                 return (ISC_TRUE);
1332         result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
1333                                &match, NULL);
1334         if (result == ISC_R_SUCCESS && match > 0)
1335                 return (ISC_TRUE);
1336         return (ISC_FALSE);
1337 }
1338
1339 /*
1340  * Callback to see if a non-recursive query coming from 'srcaddr' to
1341  * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1342  * delivered to 'myview'.
1343  *
1344  * We run this unlocked as both the view list and the interface list
1345  * are updated when the appropriate task has exclusivity.
1346  */
1347 isc_boolean_t
1348 ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
1349                  isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
1350                  dns_rdataclass_t rdclass, void *arg)
1351 {
1352         dns_view_t *view;
1353         dns_tsigkey_t *key = NULL;
1354         dns_name_t *tsig = NULL;
1355         isc_netaddr_t netsrc;
1356         isc_netaddr_t netdst;
1357
1358         UNUSED(arg);
1359
1360         /*
1361          * ns_g_server->interfacemgr is task exclusive locked.
1362          */
1363         if (ns_g_server->interfacemgr == NULL)
1364                 return (ISC_TRUE);
1365
1366         if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
1367                 return (ISC_FALSE);
1368
1369         isc_netaddr_fromsockaddr(&netsrc, srcaddr);
1370         isc_netaddr_fromsockaddr(&netdst, dstaddr);
1371
1372         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1373              view != NULL;
1374              view = ISC_LIST_NEXT(view, link)) {
1375
1376                 if (view->matchrecursiveonly)
1377                         continue;
1378
1379                 if (rdclass != view->rdclass)
1380                         continue;
1381
1382                 if (mykey != NULL) {
1383                         isc_boolean_t match;
1384                         isc_result_t result;
1385
1386                         result = dns_view_gettsig(view, &mykey->name, &key);
1387                         if (result != ISC_R_SUCCESS)
1388                                 continue;
1389                         match = dst_key_compare(mykey->key, key->key);
1390                         dns_tsigkey_detach(&key);
1391                         if (!match)
1392                                 continue;
1393                         tsig = dns_tsigkey_identity(mykey);
1394                 }
1395
1396                 if (allowed(&netsrc, tsig, view->matchclients) &&
1397                     allowed(&netdst, tsig, view->matchdestinations))
1398                         break;
1399         }
1400         return (ISC_TF(view == myview));
1401 }
1402
1403 static isc_result_t
1404 process_opt(ns_client_t *client, dns_rdataset_t *opt) {
1405         dns_rdata_t rdata;
1406         isc_buffer_t optbuf;
1407         isc_result_t result;
1408         isc_uint16_t optcode;
1409         isc_uint16_t optlen;
1410
1411         /*
1412          * Set the client's UDP buffer size.
1413          */
1414         client->udpsize = opt->rdclass;
1415
1416         /*
1417          * If the requested UDP buffer size is less than 512,
1418          * ignore it and use 512.
1419          */
1420         if (client->udpsize < 512)
1421                 client->udpsize = 512;
1422
1423         /*
1424          * Get the flags out of the OPT record.
1425          */
1426         client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1427
1428         /*
1429          * Do we understand this version of EDNS?
1430          *
1431          * XXXRTH need library support for this!
1432          */
1433         client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1434         if (client->ednsversion > 0) {
1435                 isc_stats_increment(ns_g_server->nsstats,
1436                                     dns_nsstatscounter_badednsver);
1437                 result = client_addopt(client);
1438                 if (result == ISC_R_SUCCESS)
1439                         result = DNS_R_BADVERS;
1440                 ns_client_error(client, result);
1441                 goto cleanup;
1442         }
1443
1444         /* Check for NSID request */
1445         result = dns_rdataset_first(opt);
1446         if (result == ISC_R_SUCCESS) {
1447                 dns_rdata_init(&rdata);
1448                 dns_rdataset_current(opt, &rdata);
1449                 isc_buffer_init(&optbuf, rdata.data, rdata.length);
1450                 isc_buffer_add(&optbuf, rdata.length);
1451                 while (isc_buffer_remaininglength(&optbuf) >= 4) {
1452                         optcode = isc_buffer_getuint16(&optbuf);
1453                         optlen = isc_buffer_getuint16(&optbuf);
1454                         switch (optcode) {
1455                         case DNS_OPT_NSID:
1456                                 client->attributes |= NS_CLIENTATTR_WANTNSID;
1457                                 isc_buffer_forward(&optbuf, optlen);
1458                                 break;
1459                         default:
1460                                 isc_buffer_forward(&optbuf, optlen);
1461                                 break;
1462                         }
1463                 }
1464         }
1465
1466         isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_edns0in);
1467
1468         /*
1469          * Create an OPT for our reply.
1470          */
1471         result = client_addopt(client);
1472         if (result != ISC_R_SUCCESS) {
1473                 ns_client_error(client, result);
1474                 goto cleanup;
1475         }
1476  cleanup:
1477         return (result);
1478 }
1479
1480 /*
1481  * Handle an incoming request event from the socket (UDP case)
1482  * or tcpmsg (TCP case).
1483  */
1484 static void
1485 client_request(isc_task_t *task, isc_event_t *event) {
1486         ns_client_t *client;
1487         isc_socketevent_t *sevent;
1488         isc_result_t result;
1489         isc_result_t sigresult = ISC_R_SUCCESS;
1490         isc_buffer_t *buffer;
1491         isc_buffer_t tbuffer;
1492         dns_view_t *view;
1493         dns_rdataset_t *opt;
1494         dns_name_t *signame;
1495         isc_boolean_t ra;       /* Recursion available. */
1496         isc_netaddr_t netaddr;
1497         int match;
1498         dns_messageid_t id;
1499         unsigned int flags;
1500         isc_boolean_t notimp;
1501
1502         REQUIRE(event != NULL);
1503         client = event->ev_arg;
1504         REQUIRE(NS_CLIENT_VALID(client));
1505         REQUIRE(task == client->task);
1506
1507         INSIST(client->recursionquota == NULL);
1508
1509         INSIST(client->state == (TCP_CLIENT(client) ?
1510                                        NS_CLIENTSTATE_READING :
1511                                        NS_CLIENTSTATE_READY));
1512
1513         ns_client_requests++;
1514
1515         if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
1516                 INSIST(!TCP_CLIENT(client));
1517                 sevent = (isc_socketevent_t *)event;
1518                 REQUIRE(sevent == client->recvevent);
1519                 isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
1520                 isc_buffer_add(&tbuffer, sevent->n);
1521                 buffer = &tbuffer;
1522                 result = sevent->result;
1523                 if (result == ISC_R_SUCCESS) {
1524                         client->peeraddr = sevent->address;
1525                         client->peeraddr_valid = ISC_TRUE;
1526                 }
1527                 if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1528                         client->attributes |= NS_CLIENTATTR_PKTINFO;
1529                         client->pktinfo = sevent->pktinfo;
1530                 }
1531                 if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
1532                         client->attributes |= NS_CLIENTATTR_MULTICAST;
1533                 client->nrecvs--;
1534         } else {
1535                 INSIST(TCP_CLIENT(client));
1536                 REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
1537                 REQUIRE(event->ev_sender == &client->tcpmsg);
1538                 buffer = &client->tcpmsg.buffer;
1539                 result = client->tcpmsg.result;
1540                 INSIST(client->nreads == 1);
1541                 /*
1542                  * client->peeraddr was set when the connection was accepted.
1543                  */
1544                 client->nreads--;
1545         }
1546
1547         if (exit_check(client))
1548                 goto cleanup;
1549         client->state = client->newstate = NS_CLIENTSTATE_WORKING;
1550
1551         isc_task_getcurrenttime(task, &client->requesttime);
1552         client->now = client->requesttime;
1553
1554         if (result != ISC_R_SUCCESS) {
1555                 if (TCP_CLIENT(client)) {
1556                         ns_client_next(client, result);
1557                 } else {
1558                         if  (result != ISC_R_CANCELED)
1559                                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
1560                                               NS_LOGMODULE_CLIENT,
1561                                               ISC_LOG_ERROR,
1562                                               "UDP client handler shutting "
1563                                               "down due to fatal receive "
1564                                               "error: %s",
1565                                               isc_result_totext(result));
1566                         isc_task_shutdown(client->task);
1567                 }
1568                 goto cleanup;
1569         }
1570
1571         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1572
1573 #if NS_CLIENT_DROPPORT
1574         if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1575             DROPPORT_REQUEST) {
1576                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1577                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1578                               "dropped request: suspicious port");
1579                 ns_client_next(client, ISC_R_SUCCESS);
1580                 goto cleanup;
1581         }
1582 #endif
1583
1584         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1585                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1586                       "%s request",
1587                       TCP_CLIENT(client) ? "TCP" : "UDP");
1588
1589         /*
1590          * Check the blackhole ACL for UDP only, since TCP is done in
1591          * client_newconn.
1592          */
1593         if (!TCP_CLIENT(client)) {
1594
1595                 if (ns_g_server->blackholeacl != NULL &&
1596                     dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
1597                                   &ns_g_server->aclenv,
1598                                   &match, NULL) == ISC_R_SUCCESS &&
1599                     match > 0)
1600                 {
1601                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1602                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1603                                       "blackholed UDP datagram");
1604                         ns_client_next(client, ISC_R_SUCCESS);
1605                         goto cleanup;
1606                 }
1607         }
1608
1609         /*
1610          * Silently drop multicast requests for the present.
1611          * XXXMPA revisit this as mDNS spec was published.
1612          */
1613         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
1614                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1615                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1616                               "dropping multicast request");
1617                 ns_client_next(client, DNS_R_REFUSED);
1618                 goto cleanup;
1619         }
1620
1621         result = dns_message_peekheader(buffer, &id, &flags);
1622         if (result != ISC_R_SUCCESS) {
1623                 /*
1624                  * There isn't enough header to determine whether
1625                  * this was a request or a response.  Drop it.
1626                  */
1627                 ns_client_next(client, result);
1628                 goto cleanup;
1629         }
1630
1631         /*
1632          * The client object handles requests, not responses.
1633          * If this is a UDP response, forward it to the dispatcher.
1634          * If it's a TCP response, discard it here.
1635          */
1636         if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1637                 if (TCP_CLIENT(client)) {
1638                         CTRACE("unexpected response");
1639                         ns_client_next(client, DNS_R_FORMERR);
1640                         goto cleanup;
1641                 } else {
1642                         dns_dispatch_importrecv(client->dispatch, event);
1643                         ns_client_next(client, ISC_R_SUCCESS);
1644                         goto cleanup;
1645                 }
1646         }
1647
1648         /*
1649          * Update some statistics counters.  Don't count responses.
1650          */
1651         if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
1652                 isc_stats_increment(ns_g_server->nsstats,
1653                                     dns_nsstatscounter_requestv4);
1654         } else {
1655                 isc_stats_increment(ns_g_server->nsstats,
1656                                     dns_nsstatscounter_requestv6);
1657         }
1658         if (TCP_CLIENT(client))
1659                 isc_stats_increment(ns_g_server->nsstats,
1660                                     dns_nsstatscounter_requesttcp);
1661
1662         /*
1663          * It's a request.  Parse it.
1664          */
1665         result = dns_message_parse(client->message, buffer, 0);
1666         if (result != ISC_R_SUCCESS) {
1667                 /*
1668                  * Parsing the request failed.  Send a response
1669                  * (typically FORMERR or SERVFAIL).
1670                  */
1671                 if (result == DNS_R_OPTERR)
1672                         (void)client_addopt(client);
1673
1674                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1675                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1676                               "message parsing failed: %s",
1677                               isc_result_totext(result));
1678                 ns_client_error(client, result);
1679                 goto cleanup;
1680         }
1681
1682         dns_opcodestats_increment(ns_g_server->opcodestats,
1683                                   client->message->opcode);
1684         switch (client->message->opcode) {
1685         case dns_opcode_query:
1686         case dns_opcode_update:
1687         case dns_opcode_notify:
1688                 notimp = ISC_FALSE;
1689                 break;
1690         case dns_opcode_iquery:
1691         default:
1692                 notimp = ISC_TRUE;
1693                 break;
1694         }
1695
1696         client->message->rcode = dns_rcode_noerror;
1697
1698         /* RFC1123 section 6.1.3.2 */
1699         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1700                 client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1701
1702         /*
1703          * Deal with EDNS.
1704          */
1705         if (ns_g_noedns)
1706                 opt = NULL;
1707         else
1708                 opt = dns_message_getopt(client->message);
1709         if (opt != NULL) {
1710                 /*
1711                  * Are we dropping all EDNS queries?
1712                  */
1713                 if (ns_g_dropedns) {
1714                         ns_client_next(client, ISC_R_SUCCESS);
1715                         goto cleanup;
1716                 }
1717                 result = process_opt(client, opt);
1718                 if (result != ISC_R_SUCCESS)
1719                         goto cleanup;
1720         }
1721
1722         if (client->message->rdclass == 0) {
1723                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1724                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1725                               "message class could not be determined");
1726                 ns_client_dumpmessage(client,
1727                                       "message class could not be determined");
1728                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1729                 goto cleanup;
1730         }
1731
1732         /*
1733          * Determine the destination address.  If the receiving interface is
1734          * bound to a specific address, we simply use it regardless of the
1735          * address family.  All IPv4 queries should fall into this case.
1736          * Otherwise, if this is a TCP query, get the address from the
1737          * receiving socket (this needs a system call and can be heavy).
1738          * For IPv6 UDP queries, we get this from the pktinfo structure (if
1739          * supported).
1740          * If all the attempts fail (this can happen due to memory shortage,
1741          * etc), we regard this as an error for safety.
1742          */
1743         if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1744                 isc_netaddr_fromsockaddr(&client->destaddr,
1745                                          &client->interface->addr);
1746         else {
1747                 isc_sockaddr_t sockaddr;
1748                 result = ISC_R_FAILURE;
1749
1750                 if (TCP_CLIENT(client))
1751                         result = isc_socket_getsockname(client->tcpsocket,
1752                                                         &sockaddr);
1753                 if (result == ISC_R_SUCCESS)
1754                         isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
1755                 if (result != ISC_R_SUCCESS &&
1756                     client->interface->addr.type.sa.sa_family == AF_INET6 &&
1757                     (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1758                         /*
1759                          * XXXJT technically, we should convert the receiving
1760                          * interface ID to a proper scope zone ID.  However,
1761                          * due to the fact there is no standard API for this,
1762                          * we only handle link-local addresses and use the
1763                          * interface index as link ID.  Despite the assumption,
1764                          * it should cover most typical cases.
1765                          */
1766                         isc_netaddr_fromin6(&client->destaddr,
1767                                             &client->pktinfo.ipi6_addr);
1768                         if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1769                                 isc_netaddr_setzone(&client->destaddr,
1770                                                 client->pktinfo.ipi6_ifindex);
1771                         result = ISC_R_SUCCESS;
1772                 }
1773                 if (result != ISC_R_SUCCESS) {
1774                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1775                                          "failed to get request's "
1776                                          "destination: %s",
1777                                          isc_result_totext(result));
1778                         ns_client_next(client, ISC_R_SUCCESS);
1779                         goto cleanup;
1780                 }
1781         }
1782
1783         /*
1784          * Find a view that matches the client's source address.
1785          */
1786         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1787              view != NULL;
1788              view = ISC_LIST_NEXT(view, link)) {
1789                 if (client->message->rdclass == view->rdclass ||
1790                     client->message->rdclass == dns_rdataclass_any)
1791                 {
1792                         dns_name_t *tsig = NULL;
1793
1794                         sigresult = dns_message_rechecksig(client->message,
1795                                                            view);
1796                         if (sigresult == ISC_R_SUCCESS)
1797                                 tsig = dns_tsigkey_identity(client->message->tsigkey);
1798
1799                         if (allowed(&netaddr, tsig, view->matchclients) &&
1800                             allowed(&client->destaddr, tsig,
1801                                     view->matchdestinations) &&
1802                             !((client->message->flags & DNS_MESSAGEFLAG_RD)
1803                               == 0 && view->matchrecursiveonly))
1804                         {
1805                                 dns_view_attach(view, &client->view);
1806                                 break;
1807                         }
1808                 }
1809         }
1810
1811         if (view == NULL) {
1812                 char classname[DNS_RDATACLASS_FORMATSIZE];
1813
1814                 /*
1815                  * Do a dummy TSIG verification attempt so that the
1816                  * response will have a TSIG if the query did, as
1817                  * required by RFC2845.
1818                  */
1819                 isc_buffer_t b;
1820                 isc_region_t *r;
1821
1822                 dns_message_resetsig(client->message);
1823
1824                 r = dns_message_getrawmessage(client->message);
1825                 isc_buffer_init(&b, r->base, r->length);
1826                 isc_buffer_add(&b, r->length);
1827                 (void)dns_tsig_verify(&b, client->message, NULL, NULL);
1828
1829                 dns_rdataclass_format(client->message->rdclass, classname,
1830                                       sizeof(classname));
1831                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1832                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1833                               "no matching view in class '%s'", classname);
1834                 ns_client_dumpmessage(client, "no matching view in class");
1835                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1836                 goto cleanup;
1837         }
1838
1839         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1840                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1841                       "using view '%s'", view->name);
1842
1843         /*
1844          * Check for a signature.  We log bad signatures regardless of
1845          * whether they ultimately cause the request to be rejected or
1846          * not.  We do not log the lack of a signature unless we are
1847          * debugging.
1848          */
1849         client->signer = NULL;
1850         dns_name_init(&client->signername, NULL);
1851         result = dns_message_signer(client->message, &client->signername);
1852         if (result != ISC_R_NOTFOUND) {
1853                 signame = NULL;
1854                 if (dns_message_gettsig(client->message, &signame) != NULL) {
1855                         isc_stats_increment(ns_g_server->nsstats,
1856                                             dns_nsstatscounter_tsigin);
1857                 } else {
1858                         isc_stats_increment(ns_g_server->nsstats,
1859                                             dns_nsstatscounter_sig0in);
1860                 }
1861
1862         }
1863         if (result == ISC_R_SUCCESS) {
1864                 char namebuf[DNS_NAME_FORMATSIZE];
1865                 dns_name_format(&client->signername, namebuf, sizeof(namebuf));
1866                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1867                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1868                               "request has valid signature: %s", namebuf);
1869                 client->signer = &client->signername;
1870         } else if (result == ISC_R_NOTFOUND) {
1871                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1872                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1873                               "request is not signed");
1874         } else if (result == DNS_R_NOIDENTITY) {
1875                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1876                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1877                               "request is signed by a nonauthoritative key");
1878         } else {
1879                 char tsigrcode[64];
1880                 isc_buffer_t b;
1881                 dns_rcode_t status;
1882                 isc_result_t tresult;
1883
1884                 /* There is a signature, but it is bad. */
1885                 isc_stats_increment(ns_g_server->nsstats,
1886                                     dns_nsstatscounter_invalidsig);
1887                 signame = NULL;
1888                 if (dns_message_gettsig(client->message, &signame) != NULL) {
1889                         char namebuf[DNS_NAME_FORMATSIZE];
1890                         char cnamebuf[DNS_NAME_FORMATSIZE];
1891                         dns_name_format(signame, namebuf, sizeof(namebuf));
1892                         status = client->message->tsigstatus;
1893                         isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1894                         tresult = dns_tsigrcode_totext(status, &b);
1895                         INSIST(tresult == ISC_R_SUCCESS);
1896                         tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1897                         if (client->message->tsigkey->generated) {
1898                                 dns_name_format(client->message->tsigkey->creator,
1899                                                 cnamebuf, sizeof(cnamebuf));
1900                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1901                                               NS_LOGMODULE_CLIENT,
1902                                               ISC_LOG_ERROR,
1903                                               "request has invalid signature: "
1904                                               "TSIG %s (%s): %s (%s)", namebuf,
1905                                               cnamebuf,
1906                                               isc_result_totext(result),
1907                                               tsigrcode);
1908                         } else {
1909                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1910                                               NS_LOGMODULE_CLIENT,
1911                                               ISC_LOG_ERROR,
1912                                               "request has invalid signature: "
1913                                               "TSIG %s: %s (%s)", namebuf,
1914                                               isc_result_totext(result),
1915                                               tsigrcode);
1916                         }
1917                 } else {
1918                         status = client->message->sig0status;
1919                         isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1920                         tresult = dns_tsigrcode_totext(status, &b);
1921                         INSIST(tresult == ISC_R_SUCCESS);
1922                         tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1923                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1924                                       NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1925                                       "request has invalid signature: %s (%s)",
1926                                       isc_result_totext(result), tsigrcode);
1927                 }
1928                 /*
1929                  * Accept update messages signed by unknown keys so that
1930                  * update forwarding works transparently through slaves
1931                  * that don't have all the same keys as the master.
1932                  */
1933                 if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
1934                       client->message->opcode == dns_opcode_update)) {
1935                         ns_client_error(client, sigresult);
1936                         goto cleanup;
1937                 }
1938         }
1939
1940         /*
1941          * Decide whether recursive service is available to this client.
1942          * We do this here rather than in the query code so that we can
1943          * set the RA bit correctly on all kinds of responses, not just
1944          * responses to ordinary queries.  Note if you can't query the
1945          * cache there is no point in setting RA.
1946          */
1947         ra = ISC_FALSE;
1948         if (client->view->resolver != NULL &&
1949             client->view->recursion == ISC_TRUE &&
1950             ns_client_checkaclsilent(client, NULL,
1951                                      client->view->recursionacl,
1952                                      ISC_TRUE) == ISC_R_SUCCESS &&
1953             ns_client_checkaclsilent(client, NULL,
1954                                      client->view->cacheacl,
1955                                      ISC_TRUE) == ISC_R_SUCCESS &&
1956             ns_client_checkaclsilent(client, &client->destaddr,
1957                                      client->view->recursiononacl,
1958                                      ISC_TRUE) == ISC_R_SUCCESS &&
1959             ns_client_checkaclsilent(client, &client->destaddr,
1960                                      client->view->cacheonacl,
1961                                      ISC_TRUE) == ISC_R_SUCCESS)
1962                 ra = ISC_TRUE;
1963
1964         if (ra == ISC_TRUE)
1965                 client->attributes |= NS_CLIENTATTR_RA;
1966
1967         ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1968                       ISC_LOG_DEBUG(3), ra ? "recursion available" :
1969                                              "recursion not available");
1970
1971         /*
1972          * Adjust maximum UDP response size for this client.
1973          */
1974         if (client->udpsize > 512) {
1975                 dns_peer_t *peer = NULL;
1976                 isc_uint16_t udpsize = view->maxudp;
1977                 (void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
1978                 if (peer != NULL)
1979                         dns_peer_getmaxudp(peer, &udpsize);
1980                 if (client->udpsize > udpsize)
1981                         client->udpsize = udpsize;
1982         }
1983
1984         /*
1985          * Dispatch the request.
1986          */
1987         switch (client->message->opcode) {
1988         case dns_opcode_query:
1989                 CTRACE("query");
1990                 ns_query_start(client);
1991                 break;
1992         case dns_opcode_update:
1993                 CTRACE("update");
1994                 ns_client_settimeout(client, 60);
1995                 ns_update_start(client, sigresult);
1996                 break;
1997         case dns_opcode_notify:
1998                 CTRACE("notify");
1999                 ns_client_settimeout(client, 60);
2000                 ns_notify_start(client);
2001                 break;
2002         case dns_opcode_iquery:
2003                 CTRACE("iquery");
2004                 ns_client_error(client, DNS_R_NOTIMP);
2005                 break;
2006         default:
2007                 CTRACE("unknown opcode");
2008                 ns_client_error(client, DNS_R_NOTIMP);
2009         }
2010
2011  cleanup:
2012         return;
2013 }
2014
2015 static void
2016 client_timeout(isc_task_t *task, isc_event_t *event) {
2017         ns_client_t *client;
2018
2019         REQUIRE(event != NULL);
2020         REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
2021                 event->ev_type == ISC_TIMEREVENT_IDLE);
2022         client = event->ev_arg;
2023         REQUIRE(NS_CLIENT_VALID(client));
2024         REQUIRE(task == client->task);
2025         REQUIRE(client->timer != NULL);
2026
2027         UNUSED(task);
2028
2029         CTRACE("timeout");
2030
2031         isc_event_free(&event);
2032
2033         if (client->shutdown != NULL) {
2034                 (client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
2035                 client->shutdown = NULL;
2036                 client->shutdown_arg = NULL;
2037         }
2038
2039         if (client->newstate > NS_CLIENTSTATE_READY)
2040                 client->newstate = NS_CLIENTSTATE_READY;
2041         (void)exit_check(client);
2042 }
2043
2044 static isc_result_t
2045 get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
2046         isc_mem_t *clientmctx;
2047         isc_result_t result;
2048 #if NMCTXS > 0
2049         unsigned int nextmctx;
2050 #endif
2051
2052         MTRACE("clientmctx");
2053
2054         /*
2055          * Caller must be holding the manager lock.
2056          */
2057         if (ns_g_clienttest) {
2058                 result = isc_mem_create(0, 0, mctxp);
2059                 if (result == ISC_R_SUCCESS)
2060                         isc_mem_setname(*mctxp, "client", NULL);
2061                 return (result);
2062         }
2063 #if NMCTXS > 0
2064         nextmctx = manager->nextmctx++;
2065         if (manager->nextmctx == NMCTXS)
2066                 manager->nextmctx = 0;
2067
2068         INSIST(nextmctx < NMCTXS);
2069
2070         clientmctx = manager->mctxpool[nextmctx];
2071         if (clientmctx == NULL) {
2072                 result = isc_mem_create(0, 0, &clientmctx);
2073                 if (result != ISC_R_SUCCESS)
2074                         return (result);
2075                 isc_mem_setname(clientmctx, "client", NULL);
2076
2077                 manager->mctxpool[nextmctx] = clientmctx;
2078         }
2079 #else
2080         clientmctx = manager->mctx;
2081 #endif
2082
2083         isc_mem_attach(clientmctx, mctxp);
2084
2085         return (ISC_R_SUCCESS);
2086 }
2087
2088 static isc_result_t
2089 client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
2090         ns_client_t *client;
2091         isc_result_t result;
2092         isc_mem_t *mctx = NULL;
2093
2094         /*
2095          * Caller must be holding the manager lock.
2096          *
2097          * Note: creating a client does not add the client to the
2098          * manager's client list or set the client's manager pointer.
2099          * The caller is responsible for that.
2100          */
2101
2102         REQUIRE(clientp != NULL && *clientp == NULL);
2103
2104         result = get_clientmctx(manager, &mctx);
2105         if (result != ISC_R_SUCCESS)
2106                 return (result);
2107
2108         client = isc_mem_get(mctx, sizeof(*client));
2109         if (client == NULL) {
2110                 isc_mem_detach(&mctx);
2111                 return (ISC_R_NOMEMORY);
2112         }
2113         client->mctx = mctx;
2114
2115         client->task = NULL;
2116         result = isc_task_create(manager->taskmgr, 0, &client->task);
2117         if (result != ISC_R_SUCCESS)
2118                 goto cleanup_client;
2119         isc_task_setname(client->task, "client", client);
2120
2121         client->timer = NULL;
2122         result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
2123                                   NULL, NULL, client->task, client_timeout,
2124                                   client, &client->timer);
2125         if (result != ISC_R_SUCCESS)
2126                 goto cleanup_task;
2127         client->timerset = ISC_FALSE;
2128
2129         client->message = NULL;
2130         result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
2131                                     &client->message);
2132         if (result != ISC_R_SUCCESS)
2133                 goto cleanup_timer;
2134
2135         /* XXXRTH  Hardwired constants */
2136
2137         client->sendevent = (isc_socketevent_t *)
2138                             isc_event_allocate(client->mctx, client,
2139                                                ISC_SOCKEVENT_SENDDONE,
2140                                                client_senddone, client,
2141                                                sizeof(isc_socketevent_t));
2142         if (client->sendevent == NULL) {
2143                 result = ISC_R_NOMEMORY;
2144                 goto cleanup_message;
2145         }
2146
2147         client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
2148         if  (client->recvbuf == NULL) {
2149                 result = ISC_R_NOMEMORY;
2150                 goto cleanup_sendevent;
2151         }
2152
2153         client->recvevent = (isc_socketevent_t *)
2154                             isc_event_allocate(client->mctx, client,
2155                                                ISC_SOCKEVENT_RECVDONE,
2156                                                client_request, client,
2157                                                sizeof(isc_socketevent_t));
2158         if (client->recvevent == NULL) {
2159                 result = ISC_R_NOMEMORY;
2160                 goto cleanup_recvbuf;
2161         }
2162
2163         client->magic = NS_CLIENT_MAGIC;
2164         client->manager = NULL;
2165         client->state = NS_CLIENTSTATE_INACTIVE;
2166         client->newstate = NS_CLIENTSTATE_MAX;
2167         client->naccepts = 0;
2168         client->nreads = 0;
2169         client->nsends = 0;
2170         client->nrecvs = 0;
2171         client->nupdates = 0;
2172         client->nctls = 0;
2173         client->references = 0;
2174         client->attributes = 0;
2175         client->view = NULL;
2176         client->dispatch = NULL;
2177         client->udpsocket = NULL;
2178         client->tcplistener = NULL;
2179         client->tcpsocket = NULL;
2180         client->tcpmsg_valid = ISC_FALSE;
2181         client->tcpbuf = NULL;
2182         client->opt = NULL;
2183         client->udpsize = 512;
2184         client->extflags = 0;
2185         client->ednsversion = -1;
2186         client->next = NULL;
2187         client->shutdown = NULL;
2188         client->shutdown_arg = NULL;
2189         client->signer = NULL;
2190         dns_name_init(&client->signername, NULL);
2191         client->mortal = ISC_FALSE;
2192         client->tcpquota = NULL;
2193         client->recursionquota = NULL;
2194         client->interface = NULL;
2195         client->peeraddr_valid = ISC_FALSE;
2196 #ifdef ALLOW_FILTER_AAAA_ON_V4
2197         client->filter_aaaa = dns_v4_aaaa_ok;
2198 #endif
2199         client->needshutdown = ns_g_clienttest;
2200
2201         ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
2202                        NS_EVENT_CLIENTCONTROL, client_start, client, client,
2203                        NULL, NULL);
2204         /*
2205          * Initialize FORMERR cache to sentinel value that will not match
2206          * any actual FORMERR response.
2207          */
2208         isc_sockaddr_any(&client->formerrcache.addr);
2209         client->formerrcache.time = 0;
2210         client->formerrcache.id = 0;
2211         ISC_LINK_INIT(client, link);
2212         ISC_LINK_INIT(client, rlink);
2213         ISC_QLINK_INIT(client, ilink);
2214
2215         /*
2216          * We call the init routines for the various kinds of client here,
2217          * after we have created an otherwise valid client, because some
2218          * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
2219          */
2220         result = ns_query_init(client);
2221         if (result != ISC_R_SUCCESS)
2222                 goto cleanup_recvevent;
2223
2224         result = isc_task_onshutdown(client->task, client_shutdown, client);
2225         if (result != ISC_R_SUCCESS)
2226                 goto cleanup_query;
2227
2228         CTRACE("create");
2229
2230         *clientp = client;
2231
2232         return (ISC_R_SUCCESS);
2233
2234  cleanup_query:
2235         ns_query_free(client);
2236
2237  cleanup_recvevent:
2238         isc_event_free((isc_event_t **)&client->recvevent);
2239
2240  cleanup_recvbuf:
2241         isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
2242
2243  cleanup_sendevent:
2244         isc_event_free((isc_event_t **)&client->sendevent);
2245
2246         client->magic = 0;
2247
2248  cleanup_message:
2249         dns_message_destroy(&client->message);
2250
2251  cleanup_timer:
2252         isc_timer_detach(&client->timer);
2253
2254  cleanup_task:
2255         isc_task_detach(&client->task);
2256
2257  cleanup_client:
2258         isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
2259
2260         return (result);
2261 }
2262
2263 static void
2264 client_read(ns_client_t *client) {
2265         isc_result_t result;
2266
2267         CTRACE("read");
2268
2269         result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
2270                                         client_request, client);
2271         if (result != ISC_R_SUCCESS)
2272                 goto fail;
2273
2274         /*
2275          * Set a timeout to limit the amount of time we will wait
2276          * for a request on this TCP connection.
2277          */
2278         ns_client_settimeout(client, 30);
2279
2280         client->state = client->newstate = NS_CLIENTSTATE_READING;
2281         INSIST(client->nreads == 0);
2282         INSIST(client->recursionquota == NULL);
2283         client->nreads++;
2284
2285         return;
2286  fail:
2287         ns_client_next(client, result);
2288 }
2289
2290 static void
2291 client_newconn(isc_task_t *task, isc_event_t *event) {
2292         ns_client_t *client = event->ev_arg;
2293         isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
2294         isc_result_t result;
2295
2296         REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
2297         REQUIRE(NS_CLIENT_VALID(client));
2298         REQUIRE(client->task == task);
2299
2300         UNUSED(task);
2301
2302         INSIST(client->state == NS_CLIENTSTATE_READY);
2303
2304         INSIST(client->naccepts == 1);
2305         client->naccepts--;
2306
2307         LOCK(&client->interface->lock);
2308         INSIST(client->interface->ntcpcurrent > 0);
2309         client->interface->ntcpcurrent--;
2310         UNLOCK(&client->interface->lock);
2311
2312         /*
2313          * We must take ownership of the new socket before the exit
2314          * check to make sure it gets destroyed if we decide to exit.
2315          */
2316         if (nevent->result == ISC_R_SUCCESS) {
2317                 client->tcpsocket = nevent->newsocket;
2318                 isc_socket_setname(client->tcpsocket, "client-tcp", NULL);
2319                 client->state = NS_CLIENTSTATE_READING;
2320                 INSIST(client->recursionquota == NULL);
2321
2322                 (void)isc_socket_getpeername(client->tcpsocket,
2323                                              &client->peeraddr);
2324                 client->peeraddr_valid = ISC_TRUE;
2325                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2326                            NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2327                            "new TCP connection");
2328         } else {
2329                 /*
2330                  * XXXRTH  What should we do?  We're trying to accept but
2331                  *         it didn't work.  If we just give up, then TCP
2332                  *         service may eventually stop.
2333                  *
2334                  *         For now, we just go idle.
2335                  *
2336                  *         Going idle is probably the right thing if the
2337                  *         I/O was canceled.
2338                  */
2339                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2340                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2341                               "accept failed: %s",
2342                               isc_result_totext(nevent->result));
2343         }
2344
2345         if (exit_check(client))
2346                 goto freeevent;
2347
2348         if (nevent->result == ISC_R_SUCCESS) {
2349                 int match;
2350                 isc_netaddr_t netaddr;
2351
2352                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2353
2354                 if (ns_g_server->blackholeacl != NULL &&
2355                     dns_acl_match(&netaddr, NULL,
2356                                   ns_g_server->blackholeacl,
2357                                   &ns_g_server->aclenv,
2358                                   &match, NULL) == ISC_R_SUCCESS &&
2359                     match > 0)
2360                 {
2361                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2362                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2363                                       "blackholed connection attempt");
2364                         client->newstate = NS_CLIENTSTATE_READY;
2365                         (void)exit_check(client);
2366                         goto freeevent;
2367                 }
2368
2369                 INSIST(client->tcpmsg_valid == ISC_FALSE);
2370                 dns_tcpmsg_init(client->mctx, client->tcpsocket,
2371                                 &client->tcpmsg);
2372                 client->tcpmsg_valid = ISC_TRUE;
2373
2374                 /*
2375                  * Let a new client take our place immediately, before
2376                  * we wait for a request packet.  If we don't,
2377                  * telnetting to port 53 (once per CPU) will
2378                  * deny service to legitimate TCP clients.
2379                  */
2380                 result = isc_quota_attach(&ns_g_server->tcpquota,
2381                                           &client->tcpquota);
2382                 if (result == ISC_R_SUCCESS)
2383                         result = ns_client_replace(client);
2384                 if (result != ISC_R_SUCCESS) {
2385                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2386                                       NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
2387                                       "no more TCP clients: %s",
2388                                       isc_result_totext(result));
2389                 }
2390
2391                 client_read(client);
2392         }
2393
2394  freeevent:
2395         isc_event_free(&event);
2396 }
2397
2398 static void
2399 client_accept(ns_client_t *client) {
2400         isc_result_t result;
2401
2402         CTRACE("accept");
2403
2404         result = isc_socket_accept(client->tcplistener, client->task,
2405                                    client_newconn, client);
2406         if (result != ISC_R_SUCCESS) {
2407                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2408                                  "isc_socket_accept() failed: %s",
2409                                  isc_result_totext(result));
2410                 /*
2411                  * XXXRTH  What should we do?  We're trying to accept but
2412                  *         it didn't work.  If we just give up, then TCP
2413                  *         service may eventually stop.
2414                  *
2415                  *         For now, we just go idle.
2416                  */
2417                 return;
2418         }
2419         INSIST(client->naccepts == 0);
2420         client->naccepts++;
2421         LOCK(&client->interface->lock);
2422         client->interface->ntcpcurrent++;
2423         UNLOCK(&client->interface->lock);
2424 }
2425
2426 static void
2427 client_udprecv(ns_client_t *client) {
2428         isc_result_t result;
2429         isc_region_t r;
2430
2431         CTRACE("udprecv");
2432
2433         r.base = client->recvbuf;
2434         r.length = RECV_BUFFER_SIZE;
2435         result = isc_socket_recv2(client->udpsocket, &r, 1,
2436                                   client->task, client->recvevent, 0);
2437         if (result != ISC_R_SUCCESS) {
2438                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2439                                  "isc_socket_recv2() failed: %s",
2440                                  isc_result_totext(result));
2441                 /*
2442                  * This cannot happen in the current implementation, since
2443                  * isc_socket_recv2() cannot fail if flags == 0.
2444                  *
2445                  * If this does fail, we just go idle.
2446                  */
2447                 return;
2448         }
2449         INSIST(client->nrecvs == 0);
2450         client->nrecvs++;
2451 }
2452
2453 void
2454 ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
2455         REQUIRE(NS_CLIENT_VALID(source));
2456         REQUIRE(targetp != NULL && *targetp == NULL);
2457
2458         source->references++;
2459         ns_client_log(source, NS_LOGCATEGORY_CLIENT,
2460                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2461                       "ns_client_attach: ref = %d", source->references);
2462         *targetp = source;
2463 }
2464
2465 void
2466 ns_client_detach(ns_client_t **clientp) {
2467         ns_client_t *client = *clientp;
2468
2469         client->references--;
2470         INSIST(client->references >= 0);
2471         *clientp = NULL;
2472         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2473                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2474                       "ns_client_detach: ref = %d", client->references);
2475         (void)exit_check(client);
2476 }
2477
2478 isc_boolean_t
2479 ns_client_shuttingdown(ns_client_t *client) {
2480         return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
2481 }
2482
2483 isc_result_t
2484 ns_client_replace(ns_client_t *client) {
2485         isc_result_t result;
2486
2487         CTRACE("replace");
2488
2489         REQUIRE(client != NULL);
2490         REQUIRE(client->manager != NULL);
2491
2492         result = get_client(client->manager, client->interface,
2493                             client->dispatch, TCP_CLIENT(client));
2494         if (result != ISC_R_SUCCESS)
2495                 return (result);
2496
2497         /*
2498          * The responsibility for listening for new requests is hereby
2499          * transferred to the new client.  Therefore, the old client
2500          * should refrain from listening for any more requests.
2501          */
2502         client->mortal = ISC_TRUE;
2503
2504         return (ISC_R_SUCCESS);
2505 }
2506
2507 /***
2508  *** Client Manager
2509  ***/
2510
2511 static void
2512 clientmgr_destroy(ns_clientmgr_t *manager) {
2513 #if NMCTXS > 0
2514         int i;
2515 #endif
2516
2517         REQUIRE(ISC_LIST_EMPTY(manager->clients));
2518
2519         MTRACE("clientmgr_destroy");
2520
2521 #if NMCTXS > 0
2522         for (i = 0; i < NMCTXS; i++) {
2523                 if (manager->mctxpool[i] != NULL)
2524                         isc_mem_detach(&manager->mctxpool[i]);
2525         }
2526 #endif
2527
2528         ISC_QUEUE_DESTROY(manager->inactive);
2529         DESTROYLOCK(&manager->lock);
2530         DESTROYLOCK(&manager->listlock);
2531         DESTROYLOCK(&manager->reclock);
2532         manager->magic = 0;
2533         isc_mem_put(manager->mctx, manager, sizeof(*manager));
2534 }
2535
2536 isc_result_t
2537 ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2538                     isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
2539 {
2540         ns_clientmgr_t *manager;
2541         isc_result_t result;
2542 #if NMCTXS > 0
2543         int i;
2544 #endif
2545
2546         manager = isc_mem_get(mctx, sizeof(*manager));
2547         if (manager == NULL)
2548                 return (ISC_R_NOMEMORY);
2549
2550         result = isc_mutex_init(&manager->lock);
2551         if (result != ISC_R_SUCCESS)
2552                 goto cleanup_manager;
2553
2554         result = isc_mutex_init(&manager->listlock);
2555         if (result != ISC_R_SUCCESS)
2556                 goto cleanup_lock;
2557
2558         result = isc_mutex_init(&manager->reclock);
2559         if (result != ISC_R_SUCCESS)
2560                 goto cleanup_listlock;
2561
2562         manager->mctx = mctx;
2563         manager->taskmgr = taskmgr;
2564         manager->timermgr = timermgr;
2565         manager->exiting = ISC_FALSE;
2566         ISC_LIST_INIT(manager->clients);
2567         ISC_LIST_INIT(manager->recursing);
2568         ISC_QUEUE_INIT(manager->inactive, ilink);
2569 #if NMCTXS > 0
2570         manager->nextmctx = 0;
2571         for (i = 0; i < NMCTXS; i++)
2572                 manager->mctxpool[i] = NULL; /* will be created on-demand */
2573 #endif
2574         manager->magic = MANAGER_MAGIC;
2575
2576         MTRACE("create");
2577
2578         *managerp = manager;
2579
2580         return (ISC_R_SUCCESS);
2581
2582  cleanup_listlock:
2583         (void) isc_mutex_destroy(&manager->listlock);
2584
2585  cleanup_lock:
2586         (void) isc_mutex_destroy(&manager->lock);
2587
2588  cleanup_manager:
2589         isc_mem_put(manager->mctx, manager, sizeof(*manager));
2590
2591         return (result);
2592 }
2593
2594 void
2595 ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2596         isc_result_t result;
2597         ns_clientmgr_t *manager;
2598         ns_client_t *client;
2599         isc_boolean_t need_destroy = ISC_FALSE, unlock = ISC_FALSE;
2600
2601         REQUIRE(managerp != NULL);
2602         manager = *managerp;
2603         REQUIRE(VALID_MANAGER(manager));
2604
2605         MTRACE("destroy");
2606
2607         /*
2608          * Check for success because we may already be task-exclusive
2609          * at this point.  Only if we succeed at obtaining an exclusive
2610          * lock now will we need to relinquish it later.
2611          */
2612         result = isc_task_beginexclusive(ns_g_server->task);
2613         if (result == ISC_R_SUCCESS)
2614                 unlock = ISC_TRUE;
2615
2616         manager->exiting = ISC_TRUE;
2617
2618         for (client = ISC_LIST_HEAD(manager->clients);
2619              client != NULL;
2620              client = ISC_LIST_NEXT(client, link))
2621                 isc_task_shutdown(client->task);
2622
2623         if (ISC_LIST_EMPTY(manager->clients))
2624                 need_destroy = ISC_TRUE;
2625
2626         if (unlock)
2627                 isc_task_endexclusive(ns_g_server->task);
2628
2629         if (need_destroy)
2630                 clientmgr_destroy(manager);
2631
2632         *managerp = NULL;
2633 }
2634
2635 static isc_result_t
2636 get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
2637            dns_dispatch_t *disp, isc_boolean_t tcp)
2638 {
2639         isc_result_t result = ISC_R_SUCCESS;
2640         isc_event_t *ev;
2641         ns_client_t *client;
2642         MTRACE("get client");
2643
2644         REQUIRE(manager != NULL);
2645
2646         if (manager->exiting)
2647                 return (ISC_R_SHUTTINGDOWN);
2648
2649         /*
2650          * Allocate a client.  First try to get a recycled one;
2651          * if that fails, make a new one.
2652          */
2653         client = NULL;
2654         if (!ns_g_clienttest)
2655                 ISC_QUEUE_POP(manager->inactive, ilink, client);
2656
2657         if (client != NULL)
2658                 MTRACE("recycle");
2659         else {
2660                 MTRACE("create new");
2661
2662                 LOCK(&manager->lock);
2663                 result = client_create(manager, &client);
2664                 UNLOCK(&manager->lock);
2665                 if (result != ISC_R_SUCCESS)
2666                         return (result);
2667
2668                 LOCK(&manager->listlock);
2669                 ISC_LIST_APPEND(manager->clients, client, link);
2670                 UNLOCK(&manager->listlock);
2671         }
2672
2673         client->manager = manager;
2674         ns_interface_attach(ifp, &client->interface);
2675         client->state = NS_CLIENTSTATE_READY;
2676         INSIST(client->recursionquota == NULL);
2677
2678         if (tcp) {
2679                 client->attributes |= NS_CLIENTATTR_TCP;
2680                 isc_socket_attach(ifp->tcpsocket,
2681                                   &client->tcplistener);
2682         } else {
2683                 isc_socket_t *sock;
2684
2685                 dns_dispatch_attach(disp, &client->dispatch);
2686                 sock = dns_dispatch_getsocket(client->dispatch);
2687                 isc_socket_attach(sock, &client->udpsocket);
2688         }
2689
2690         INSIST(client->nctls == 0);
2691         client->nctls++;
2692         ev = &client->ctlevent;
2693         isc_task_send(client->task, &ev);
2694
2695         return (ISC_R_SUCCESS);
2696 }
2697
2698 isc_result_t
2699 ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
2700                            ns_interface_t *ifp, isc_boolean_t tcp)
2701 {
2702         isc_result_t result = ISC_R_SUCCESS;
2703         unsigned int disp;
2704
2705         REQUIRE(VALID_MANAGER(manager));
2706         REQUIRE(n > 0);
2707
2708         MTRACE("createclients");
2709
2710         for (disp = 0; disp < n; disp++) {
2711                 result = get_client(manager, ifp, ifp->udpdispatch[disp], tcp);
2712                 if (result != ISC_R_SUCCESS)
2713                         break;
2714         }
2715
2716         return (result);
2717 }
2718
2719 isc_sockaddr_t *
2720 ns_client_getsockaddr(ns_client_t *client) {
2721         return (&client->peeraddr);
2722 }
2723
2724 isc_result_t
2725 ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
2726                          dns_acl_t *acl, isc_boolean_t default_allow)
2727 {
2728         isc_result_t result;
2729         isc_netaddr_t tmpnetaddr;
2730         int match;
2731
2732         if (acl == NULL) {
2733                 if (default_allow)
2734                         goto allow;
2735                 else
2736                         goto deny;
2737         }
2738
2739         if (netaddr == NULL) {
2740                 isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
2741                 netaddr = &tmpnetaddr;
2742         }
2743
2744         result = dns_acl_match(netaddr, client->signer, acl,
2745                                &ns_g_server->aclenv, &match, NULL);
2746
2747         if (result != ISC_R_SUCCESS)
2748                 goto deny; /* Internal error, already logged. */
2749         if (match > 0)
2750                 goto allow;
2751         goto deny; /* Negative match or no match. */
2752
2753  allow:
2754         return (ISC_R_SUCCESS);
2755
2756  deny:
2757         return (DNS_R_REFUSED);
2758 }
2759
2760 isc_result_t
2761 ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
2762                    const char *opname, dns_acl_t *acl,
2763                    isc_boolean_t default_allow, int log_level)
2764 {
2765         isc_result_t result;
2766         isc_netaddr_t netaddr;
2767
2768         if (sockaddr != NULL)
2769                 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
2770
2771         result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
2772                                           acl, default_allow);
2773
2774         if (result == ISC_R_SUCCESS)
2775                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2776                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2777                               "%s approved", opname);
2778         else
2779                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2780                               NS_LOGMODULE_CLIENT,
2781                               log_level, "%s denied", opname);
2782         return (result);
2783 }
2784
2785 static void
2786 ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2787         if (client->peeraddr_valid)
2788                 isc_sockaddr_format(&client->peeraddr, peerbuf,
2789                                     (unsigned int)len);
2790         else
2791                 snprintf(peerbuf, len, "@%p", client);
2792 }
2793
2794 void
2795 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2796                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2797 {
2798         char msgbuf[4096];
2799         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2800         char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE];
2801         const char *viewname = "";
2802         const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = "";
2803         const char *signer = "", *qname = "";
2804         dns_name_t *q = NULL;
2805
2806         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2807
2808         ns_client_name(client, peerbuf, sizeof(peerbuf));
2809
2810         if (client->signer != NULL) {
2811                 dns_name_format(client->signer, signerbuf, sizeof(signerbuf));
2812                 sep1 = "/key ";
2813                 signer = signerbuf;
2814         }
2815
2816         q = client->query.origqname != NULL
2817                 ? client->query.origqname : client->query.qname;
2818         if (q != NULL) {
2819                 dns_name_format(q, qnamebuf, sizeof(qnamebuf));
2820                 sep2 = " (";
2821                 sep3 = ")";
2822                 qname = qnamebuf;
2823         }
2824
2825         if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2826             strcmp(client->view->name, "_default") != 0) {
2827                 sep4 = ": view ";
2828                 viewname = client->view->name;
2829         }
2830
2831         isc_log_write(ns_g_lctx, category, module, level,
2832                       "client %s%s%s%s%s%s%s%s: %s",
2833                       peerbuf, sep1, signer, sep2, qname, sep3,
2834                       sep4, viewname, msgbuf);
2835 }
2836
2837 void
2838 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2839            isc_logmodule_t *module, int level, const char *fmt, ...)
2840 {
2841         va_list ap;
2842
2843         if (! isc_log_wouldlog(ns_g_lctx, level))
2844                 return;
2845
2846         va_start(ap, fmt);
2847         ns_client_logv(client, category, module, level, fmt, ap);
2848         va_end(ap);
2849 }
2850
2851 void
2852 ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
2853                  dns_rdataclass_t rdclass, char *buf, size_t len)
2854 {
2855         char namebuf[DNS_NAME_FORMATSIZE];
2856         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2857         char classbuf[DNS_RDATACLASS_FORMATSIZE];
2858
2859         dns_name_format(name, namebuf, sizeof(namebuf));
2860         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2861         dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2862         (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2863                        classbuf);
2864 }
2865
2866 static void
2867 ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2868         isc_buffer_t buffer;
2869         char *buf = NULL;
2870         int len = 1024;
2871         isc_result_t result;
2872
2873         if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1)))
2874                 return;
2875
2876         /*
2877          * Note that these are multiline debug messages.  We want a newline
2878          * to appear in the log after each message.
2879          */
2880
2881         do {
2882                 buf = isc_mem_get(client->mctx, len);
2883                 if (buf == NULL)
2884                         break;
2885                 isc_buffer_init(&buffer, buf, len);
2886                 result = dns_message_totext(client->message,
2887                                             &dns_master_style_debug,
2888                                             0, &buffer);
2889                 if (result == ISC_R_NOSPACE) {
2890                         isc_mem_put(client->mctx, buf, len);
2891                         len += 1024;
2892                 } else if (result == ISC_R_SUCCESS)
2893                         ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
2894                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2895                                       "%s\n%.*s", reason,
2896                                        (int)isc_buffer_usedlength(&buffer),
2897                                        buf);
2898         } while (result == ISC_R_NOSPACE);
2899
2900         if (buf != NULL)
2901                 isc_mem_put(client->mctx, buf, len);
2902 }
2903
2904 void
2905 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2906         ns_client_t *client;
2907         char namebuf[DNS_NAME_FORMATSIZE];
2908         char original[DNS_NAME_FORMATSIZE];
2909         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2910         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2911         char classbuf[DNS_RDATACLASS_FORMATSIZE];
2912         const char *name;
2913         const char *sep;
2914         const char *origfor;
2915         dns_rdataset_t *rdataset;
2916
2917         REQUIRE(VALID_MANAGER(manager));
2918
2919         LOCK(&manager->reclock);
2920         client = ISC_LIST_HEAD(manager->recursing);
2921         while (client != NULL) {
2922                 INSIST(client->state == NS_CLIENTSTATE_RECURSING);
2923
2924                 ns_client_name(client, peerbuf, sizeof(peerbuf));
2925                 if (client->view != NULL &&
2926                     strcmp(client->view->name, "_bind") != 0 &&
2927                     strcmp(client->view->name, "_default") != 0) {
2928                         name = client->view->name;
2929                         sep = ": view ";
2930                 } else {
2931                         name = "";
2932                         sep = "";
2933                 }
2934
2935                 LOCK(&client->query.fetchlock);
2936                 INSIST(client->query.qname != NULL);
2937                 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2938                 if (client->query.qname != client->query.origqname &&
2939                     client->query.origqname != NULL) {
2940                         origfor = " for ";
2941                         dns_name_format(client->query.origqname, original,
2942                                         sizeof(original));
2943                 } else {
2944                         origfor = "";
2945                         original[0] = '\0';
2946                 }
2947                 rdataset = ISC_LIST_HEAD(client->query.qname->list);
2948                 if (rdataset == NULL && client->query.origqname != NULL)
2949                         rdataset = ISC_LIST_HEAD(client->query.origqname->list);
2950                 if (rdataset != NULL) {
2951                         dns_rdatatype_format(rdataset->type, typebuf,
2952                                              sizeof(typebuf));
2953                         dns_rdataclass_format(rdataset->rdclass, classbuf,
2954                                               sizeof(classbuf));
2955                 } else {
2956                         strcpy(typebuf, "-");
2957                         strcpy(classbuf, "-");
2958                 }
2959                 UNLOCK(&client->query.fetchlock);
2960                 fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s "
2961                         "requesttime %d\n", peerbuf, sep, name,
2962                         client->message->id, namebuf, typebuf, classbuf,
2963                         origfor, original, client->requesttime);
2964                 client = ISC_LIST_NEXT(client, rlink);
2965         }
2966         UNLOCK(&manager->reclock);
2967 }
2968
2969 void
2970 ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2971         LOCK(&client->query.fetchlock);
2972         if (client->query.restarts > 0) {
2973                 /*
2974                  * client->query.qname was dynamically allocated.
2975                  */
2976                 dns_message_puttempname(client->message,
2977                                         &client->query.qname);
2978         }
2979         client->query.qname = name;
2980         UNLOCK(&client->query.fetchlock);
2981 }
2982
2983 isc_result_t
2984 ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) {
2985         ns_client_t *client = (ns_client_t *) ci->data;
2986
2987         REQUIRE(NS_CLIENT_VALID(client));
2988         REQUIRE(addrp != NULL);
2989
2990         *addrp = &client->peeraddr;
2991         return (ISC_R_SUCCESS);
2992 }