]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/bin/named/client.c
Update BIND to 9.9.8
[FreeBSD/stable/9.git] / contrib / bind9 / bin / named / client.c
1 /*
2  * Copyright (C) 2004-2015  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
957 #ifdef ALLOW_FILTER_AAAA_ON_V4
958         /*
959          * filter-aaaa-on-v4 yes or break-dnssec option to suppress
960          * AAAA records
961          * We already know that request came via IPv4,
962          * that we have both AAAA and A records,
963          * and that we either have no signatures that the client wants
964          * or we are supposed to break DNSSEC.
965          *
966          * Override preferred glue if necessary.
967          */
968         if ((client->attributes & NS_CLIENTATTR_FILTER_AAAA) != 0) {
969                 render_opts |= DNS_MESSAGERENDER_FILTER_AAAA;
970                 if (preferred_glue == DNS_MESSAGERENDER_PREFER_AAAA)
971                         preferred_glue = DNS_MESSAGERENDER_PREFER_A;
972         }
973 #endif
974
975         /*
976          * XXXRTH  The following doesn't deal with TCP buffer resizing.
977          */
978         result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
979                                      sendbuf, &data);
980         if (result != ISC_R_SUCCESS)
981                 goto done;
982
983         result = dns_compress_init(&cctx, -1, client->mctx);
984         if (result != ISC_R_SUCCESS)
985                 goto done;
986         if (client->peeraddr_valid && client->view != NULL) {
987                 isc_netaddr_t netaddr;
988                 dns_name_t *name = NULL;
989
990                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
991                 if (client->message->tsigkey != NULL)
992                         name = &client->message->tsigkey->name;
993                 if (client->view->nocasecompress == NULL ||
994                     !allowed(&netaddr, name, client->view->nocasecompress))
995                 {
996                         dns_compress_setsensitive(&cctx, ISC_TRUE);
997                 }
998         }
999         cleanup_cctx = ISC_TRUE;
1000
1001         result = dns_message_renderbegin(client->message, &cctx, &buffer);
1002         if (result != ISC_R_SUCCESS)
1003                 goto done;
1004
1005         if (client->opt != NULL) {
1006                 result = dns_message_setopt(client->message, client->opt);
1007                 opt_included = ISC_TRUE;
1008                 client->opt = NULL;
1009                 if (result != ISC_R_SUCCESS)
1010                         goto done;
1011         }
1012         result = dns_message_rendersection(client->message,
1013                                            DNS_SECTION_QUESTION, 0);
1014         if (result == ISC_R_NOSPACE) {
1015                 client->message->flags |= DNS_MESSAGEFLAG_TC;
1016                 goto renderend;
1017         }
1018         if (result != ISC_R_SUCCESS)
1019                 goto done;
1020 #ifdef USE_RRL
1021         /*
1022          * Stop after the question if TC was set for rate limiting.
1023          */
1024         if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
1025                 goto renderend;
1026 #endif /* USE_RRL */
1027         result = dns_message_rendersection(client->message,
1028                                            DNS_SECTION_ANSWER,
1029                                            DNS_MESSAGERENDER_PARTIAL |
1030                                            render_opts);
1031         if (result == ISC_R_NOSPACE) {
1032                 client->message->flags |= DNS_MESSAGEFLAG_TC;
1033                 goto renderend;
1034         }
1035         if (result != ISC_R_SUCCESS)
1036                 goto done;
1037         result = dns_message_rendersection(client->message,
1038                                            DNS_SECTION_AUTHORITY,
1039                                            DNS_MESSAGERENDER_PARTIAL |
1040                                            render_opts);
1041         if (result == ISC_R_NOSPACE) {
1042                 client->message->flags |= DNS_MESSAGEFLAG_TC;
1043                 goto renderend;
1044         }
1045         if (result != ISC_R_SUCCESS)
1046                 goto done;
1047         result = dns_message_rendersection(client->message,
1048                                            DNS_SECTION_ADDITIONAL,
1049                                            preferred_glue | render_opts);
1050         if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
1051                 goto done;
1052  renderend:
1053         result = dns_message_renderend(client->message);
1054
1055         if (result != ISC_R_SUCCESS)
1056                 goto done;
1057
1058         if (cleanup_cctx) {
1059                 dns_compress_invalidate(&cctx);
1060                 cleanup_cctx = ISC_FALSE;
1061         }
1062
1063         if (TCP_CLIENT(client)) {
1064                 isc_buffer_usedregion(&buffer, &r);
1065                 isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
1066                 isc_buffer_add(&tcpbuffer, r.length);
1067                 result = client_sendpkg(client, &tcpbuffer);
1068         } else
1069                 result = client_sendpkg(client, &buffer);
1070
1071         /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
1072         isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_response);
1073         if (opt_included) {
1074                 isc_stats_increment(ns_g_server->nsstats,
1075                                     dns_nsstatscounter_edns0out);
1076         }
1077         if (client->message->tsigkey != NULL) {
1078                 isc_stats_increment(ns_g_server->nsstats,
1079                                     dns_nsstatscounter_tsigout);
1080         }
1081         if (client->message->sig0key != NULL) {
1082                 isc_stats_increment(ns_g_server->nsstats,
1083                                     dns_nsstatscounter_sig0out);
1084         }
1085         if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
1086                 isc_stats_increment(ns_g_server->nsstats,
1087                                     dns_nsstatscounter_truncatedresp);
1088
1089         if (result == ISC_R_SUCCESS)
1090                 return;
1091
1092  done:
1093         if (client->tcpbuf != NULL) {
1094                 isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
1095                 client->tcpbuf = NULL;
1096         }
1097
1098         if (cleanup_cctx)
1099                 dns_compress_invalidate(&cctx);
1100
1101         ns_client_next(client, result);
1102 }
1103
1104 #if NS_CLIENT_DROPPORT
1105 #define DROPPORT_NO             0
1106 #define DROPPORT_REQUEST        1
1107 #define DROPPORT_RESPONSE       2
1108 /*%
1109  * ns_client_dropport determines if certain requests / responses
1110  * should be dropped based on the port number.
1111  *
1112  * Returns:
1113  * \li  0:      Don't drop.
1114  * \li  1:      Drop request.
1115  * \li  2:      Drop (error) response.
1116  */
1117 static int
1118 ns_client_dropport(in_port_t port) {
1119         switch (port) {
1120         case 7: /* echo */
1121         case 13: /* daytime */
1122         case 19: /* chargen */
1123         case 37: /* time */
1124                 return (DROPPORT_REQUEST);
1125         case 464: /* kpasswd */
1126                 return (DROPPORT_RESPONSE);
1127         }
1128         return (DROPPORT_NO);
1129 }
1130 #endif
1131
1132 void
1133 ns_client_error(ns_client_t *client, isc_result_t result) {
1134         dns_rcode_t rcode;
1135         dns_message_t *message;
1136
1137         REQUIRE(NS_CLIENT_VALID(client));
1138
1139         CTRACE("error");
1140
1141         message = client->message;
1142         rcode = dns_result_torcode(result);
1143
1144 #if NS_CLIENT_DROPPORT
1145         /*
1146          * Don't send FORMERR to ports on the drop port list.
1147          */
1148         if (rcode == dns_rcode_formerr &&
1149             ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
1150             DROPPORT_NO) {
1151                 char buf[64];
1152                 isc_buffer_t b;
1153
1154                 isc_buffer_init(&b, buf, sizeof(buf) - 1);
1155                 if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
1156                         isc_buffer_putstr(&b, "UNKNOWN RCODE");
1157                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1158                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1159                               "dropped error (%.*s) response: suspicious port",
1160                               (int)isc_buffer_usedlength(&b), buf);
1161                 ns_client_next(client, ISC_R_SUCCESS);
1162                 return;
1163         }
1164 #endif
1165
1166 #ifdef USE_RRL
1167         /*
1168          * Try to rate limit error responses.
1169          */
1170         if (client->view != NULL && client->view->rrl != NULL) {
1171                 isc_boolean_t wouldlog;
1172                 char log_buf[DNS_RRL_LOG_BUF_LEN];
1173                 dns_rrl_result_t rrl_result;
1174                 int loglevel;
1175
1176                 INSIST(rcode != dns_rcode_noerror &&
1177                        rcode != dns_rcode_nxdomain);
1178                 if (ns_g_server->log_queries)
1179                         loglevel = DNS_RRL_LOG_DROP;
1180                 else
1181                         loglevel = ISC_LOG_DEBUG(1);
1182                 wouldlog = isc_log_wouldlog(ns_g_lctx, loglevel);
1183                 rrl_result = dns_rrl(client->view, &client->peeraddr,
1184                                      TCP_CLIENT(client),
1185                                      dns_rdataclass_in, dns_rdatatype_none,
1186                                      NULL, result, client->now,
1187                                      wouldlog, log_buf, sizeof(log_buf));
1188                 if (rrl_result != DNS_RRL_RESULT_OK) {
1189                         /*
1190                          * Log dropped errors in the query category
1191                          * so that they are not lost in silence.
1192                          * Starts of rate-limited bursts are logged in
1193                          * NS_LOGCATEGORY_RRL.
1194                          */
1195                         if (wouldlog) {
1196                                 ns_client_log(client,
1197                                               NS_LOGCATEGORY_QUERY_EERRORS,
1198                                               NS_LOGMODULE_CLIENT,
1199                                               loglevel,
1200                                               "%s", log_buf);
1201                         }
1202                         /*
1203                          * Some error responses cannot be 'slipped',
1204                          * so don't try to slip any error responses.
1205                          */
1206                         if (!client->view->rrl->log_only) {
1207                                 isc_stats_increment(ns_g_server->nsstats,
1208                                                 dns_nsstatscounter_ratedropped);
1209                                 isc_stats_increment(ns_g_server->nsstats,
1210                                                 dns_nsstatscounter_dropped);
1211                                 ns_client_next(client, DNS_R_DROP);
1212                                 return;
1213                         }
1214                 }
1215         }
1216 #endif /* USE_RRL */
1217
1218         /*
1219          * Message may be an in-progress reply that we had trouble
1220          * with, in which case QR will be set.  We need to clear QR before
1221          * calling dns_message_reply() to avoid triggering an assertion.
1222          */
1223         message->flags &= ~DNS_MESSAGEFLAG_QR;
1224         /*
1225          * AA and AD shouldn't be set.
1226          */
1227         message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
1228         result = dns_message_reply(message, ISC_TRUE);
1229         if (result != ISC_R_SUCCESS) {
1230                 /*
1231                  * It could be that we've got a query with a good header,
1232                  * but a bad question section, so we try again with
1233                  * want_question_section set to ISC_FALSE.
1234                  */
1235                 result = dns_message_reply(message, ISC_FALSE);
1236                 if (result != ISC_R_SUCCESS) {
1237                         ns_client_next(client, result);
1238                         return;
1239                 }
1240         }
1241         message->rcode = rcode;
1242
1243         /*
1244          * FORMERR loop avoidance:  If we sent a FORMERR message
1245          * with the same ID to the same client less than two
1246          * seconds ago, assume that we are in an infinite error
1247          * packet dialog with a server for some protocol whose
1248          * error responses look enough like DNS queries to
1249          * elicit a FORMERR response.  Drop a packet to break
1250          * the loop.
1251          */
1252         if (rcode == dns_rcode_formerr) {
1253                 if (isc_sockaddr_equal(&client->peeraddr,
1254                                        &client->formerrcache.addr) &&
1255                     message->id == client->formerrcache.id &&
1256                     client->requesttime - client->formerrcache.time < 2) {
1257                         /* Drop packet. */
1258                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1259                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1260                                       "possible error packet loop, "
1261                                       "FORMERR dropped");
1262                         ns_client_next(client, result);
1263                         return;
1264                 }
1265                 client->formerrcache.addr = client->peeraddr;
1266                 client->formerrcache.time = client->requesttime;
1267                 client->formerrcache.id = message->id;
1268         }
1269         ns_client_send(client);
1270 }
1271
1272 static inline isc_result_t
1273 client_addopt(ns_client_t *client) {
1274         char nsid[BUFSIZ], *nsidp;
1275         isc_result_t result;
1276         dns_view_t *view;
1277         dns_resolver_t *resolver;
1278         isc_uint16_t udpsize;
1279         dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
1280         int count = 0;
1281         unsigned int flags;
1282
1283         REQUIRE(client->opt == NULL);   /* XXXRTH free old. */
1284
1285         view = client->view;
1286         resolver = (view != NULL) ? view->resolver : NULL;
1287         if (resolver != NULL)
1288                 udpsize = dns_resolver_getudpsize(resolver);
1289         else
1290                 udpsize = ns_g_udpsize;
1291
1292         flags = client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE;
1293
1294         /* Set EDNS options if applicable */
1295         if ((client->attributes & NS_CLIENTATTR_WANTNSID) != 0 &&
1296             (ns_g_server->server_id != NULL ||
1297              ns_g_server->server_usehostname)) {
1298                 if (ns_g_server->server_usehostname) {
1299                         result = ns_os_gethostname(nsid, sizeof(nsid));
1300                         if (result != ISC_R_SUCCESS) {
1301                                 goto no_nsid;
1302                         }
1303                         nsidp = nsid;
1304                 } else
1305                         nsidp = ns_g_server->server_id;
1306
1307                 INSIST(count < DNS_EDNSOPTIONS);
1308                 ednsopts[count].code = DNS_OPT_NSID;
1309                 ednsopts[count].length = strlen(nsidp);
1310                 ednsopts[count].value = (unsigned char *)nsidp;
1311                 count++;
1312         }
1313  no_nsid:
1314         result = dns_message_buildopt(client->message, &client->opt, 0,
1315                                       udpsize, flags, ednsopts, count);
1316         return (result);
1317 }
1318
1319 static inline isc_boolean_t
1320 allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
1321         int match;
1322         isc_result_t result;
1323
1324         if (acl == NULL)
1325                 return (ISC_TRUE);
1326         result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
1327                                &match, NULL);
1328         if (result == ISC_R_SUCCESS && match > 0)
1329                 return (ISC_TRUE);
1330         return (ISC_FALSE);
1331 }
1332
1333 /*
1334  * Callback to see if a non-recursive query coming from 'srcaddr' to
1335  * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
1336  * delivered to 'myview'.
1337  *
1338  * We run this unlocked as both the view list and the interface list
1339  * are updated when the appropriate task has exclusivity.
1340  */
1341 isc_boolean_t
1342 ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
1343                  isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
1344                  dns_rdataclass_t rdclass, void *arg)
1345 {
1346         dns_view_t *view;
1347         dns_tsigkey_t *key = NULL;
1348         dns_name_t *tsig = NULL;
1349         isc_netaddr_t netsrc;
1350         isc_netaddr_t netdst;
1351
1352         UNUSED(arg);
1353
1354         /*
1355          * ns_g_server->interfacemgr is task exclusive locked.
1356          */
1357         if (ns_g_server->interfacemgr == NULL)
1358                 return (ISC_TRUE);
1359
1360         if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
1361                 return (ISC_FALSE);
1362
1363         isc_netaddr_fromsockaddr(&netsrc, srcaddr);
1364         isc_netaddr_fromsockaddr(&netdst, dstaddr);
1365
1366         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1367              view != NULL;
1368              view = ISC_LIST_NEXT(view, link)) {
1369
1370                 if (view->matchrecursiveonly)
1371                         continue;
1372
1373                 if (rdclass != view->rdclass)
1374                         continue;
1375
1376                 if (mykey != NULL) {
1377                         isc_boolean_t match;
1378                         isc_result_t result;
1379
1380                         result = dns_view_gettsig(view, &mykey->name, &key);
1381                         if (result != ISC_R_SUCCESS)
1382                                 continue;
1383                         match = dst_key_compare(mykey->key, key->key);
1384                         dns_tsigkey_detach(&key);
1385                         if (!match)
1386                                 continue;
1387                         tsig = dns_tsigkey_identity(mykey);
1388                 }
1389
1390                 if (allowed(&netsrc, tsig, view->matchclients) &&
1391                     allowed(&netdst, tsig, view->matchdestinations))
1392                         break;
1393         }
1394         return (ISC_TF(view == myview));
1395 }
1396
1397 static isc_result_t
1398 process_opt(ns_client_t *client, dns_rdataset_t *opt) {
1399         dns_rdata_t rdata;
1400         isc_buffer_t optbuf;
1401         isc_result_t result;
1402         isc_uint16_t optcode;
1403         isc_uint16_t optlen;
1404
1405         /*
1406          * Set the client's UDP buffer size.
1407          */
1408         client->udpsize = opt->rdclass;
1409
1410         /*
1411          * If the requested UDP buffer size is less than 512,
1412          * ignore it and use 512.
1413          */
1414         if (client->udpsize < 512)
1415                 client->udpsize = 512;
1416
1417         /*
1418          * Get the flags out of the OPT record.
1419          */
1420         client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
1421
1422         /*
1423          * Do we understand this version of EDNS?
1424          *
1425          * XXXRTH need library support for this!
1426          */
1427         client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
1428         if (client->ednsversion > 0) {
1429                 isc_stats_increment(ns_g_server->nsstats,
1430                                     dns_nsstatscounter_badednsver);
1431                 result = client_addopt(client);
1432                 if (result == ISC_R_SUCCESS)
1433                         result = DNS_R_BADVERS;
1434                 ns_client_error(client, result);
1435                 goto cleanup;
1436         }
1437
1438         /* Check for NSID request */
1439         result = dns_rdataset_first(opt);
1440         if (result == ISC_R_SUCCESS) {
1441                 dns_rdata_init(&rdata);
1442                 dns_rdataset_current(opt, &rdata);
1443                 isc_buffer_init(&optbuf, rdata.data, rdata.length);
1444                 isc_buffer_add(&optbuf, rdata.length);
1445                 while (isc_buffer_remaininglength(&optbuf) >= 4) {
1446                         optcode = isc_buffer_getuint16(&optbuf);
1447                         optlen = isc_buffer_getuint16(&optbuf);
1448                         switch (optcode) {
1449                         case DNS_OPT_NSID:
1450                                 client->attributes |= NS_CLIENTATTR_WANTNSID;
1451                                 isc_buffer_forward(&optbuf, optlen);
1452                                 break;
1453                         default:
1454                                 isc_buffer_forward(&optbuf, optlen);
1455                                 break;
1456                         }
1457                 }
1458         }
1459
1460         isc_stats_increment(ns_g_server->nsstats, dns_nsstatscounter_edns0in);
1461
1462         /*
1463          * Create an OPT for our reply.
1464          */
1465         result = client_addopt(client);
1466         if (result != ISC_R_SUCCESS) {
1467                 ns_client_error(client, result);
1468                 goto cleanup;
1469         }
1470  cleanup:
1471         return (result);
1472 }
1473
1474 /*
1475  * Handle an incoming request event from the socket (UDP case)
1476  * or tcpmsg (TCP case).
1477  */
1478 static void
1479 client_request(isc_task_t *task, isc_event_t *event) {
1480         ns_client_t *client;
1481         isc_socketevent_t *sevent;
1482         isc_result_t result;
1483         isc_result_t sigresult = ISC_R_SUCCESS;
1484         isc_buffer_t *buffer;
1485         isc_buffer_t tbuffer;
1486         dns_view_t *view;
1487         dns_rdataset_t *opt;
1488         dns_name_t *signame;
1489         isc_boolean_t ra;       /* Recursion available. */
1490         isc_netaddr_t netaddr;
1491         int match;
1492         dns_messageid_t id;
1493         unsigned int flags;
1494         isc_boolean_t notimp;
1495
1496         REQUIRE(event != NULL);
1497         client = event->ev_arg;
1498         REQUIRE(NS_CLIENT_VALID(client));
1499         REQUIRE(task == client->task);
1500
1501         INSIST(client->recursionquota == NULL);
1502
1503         INSIST(client->state == (TCP_CLIENT(client) ?
1504                                        NS_CLIENTSTATE_READING :
1505                                        NS_CLIENTSTATE_READY));
1506
1507         ns_client_requests++;
1508
1509         if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
1510                 INSIST(!TCP_CLIENT(client));
1511                 sevent = (isc_socketevent_t *)event;
1512                 REQUIRE(sevent == client->recvevent);
1513                 isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
1514                 isc_buffer_add(&tbuffer, sevent->n);
1515                 buffer = &tbuffer;
1516                 result = sevent->result;
1517                 if (result == ISC_R_SUCCESS) {
1518                         client->peeraddr = sevent->address;
1519                         client->peeraddr_valid = ISC_TRUE;
1520                 }
1521                 if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1522                         client->attributes |= NS_CLIENTATTR_PKTINFO;
1523                         client->pktinfo = sevent->pktinfo;
1524                 }
1525                 if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
1526                         client->attributes |= NS_CLIENTATTR_MULTICAST;
1527                 client->nrecvs--;
1528         } else {
1529                 INSIST(TCP_CLIENT(client));
1530                 REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
1531                 REQUIRE(event->ev_sender == &client->tcpmsg);
1532                 buffer = &client->tcpmsg.buffer;
1533                 result = client->tcpmsg.result;
1534                 INSIST(client->nreads == 1);
1535                 /*
1536                  * client->peeraddr was set when the connection was accepted.
1537                  */
1538                 client->nreads--;
1539         }
1540
1541         if (exit_check(client))
1542                 goto cleanup;
1543         client->state = client->newstate = NS_CLIENTSTATE_WORKING;
1544
1545         isc_task_getcurrenttime(task, &client->requesttime);
1546         client->now = client->requesttime;
1547
1548         if (result != ISC_R_SUCCESS) {
1549                 if (TCP_CLIENT(client)) {
1550                         ns_client_next(client, result);
1551                 } else {
1552                         if  (result != ISC_R_CANCELED)
1553                                 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
1554                                               NS_LOGMODULE_CLIENT,
1555                                               ISC_LOG_ERROR,
1556                                               "UDP client handler shutting "
1557                                               "down due to fatal receive "
1558                                               "error: %s",
1559                                               isc_result_totext(result));
1560                         isc_task_shutdown(client->task);
1561                 }
1562                 goto cleanup;
1563         }
1564
1565         isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
1566
1567 #if NS_CLIENT_DROPPORT
1568         if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
1569             DROPPORT_REQUEST) {
1570                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1571                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1572                               "dropped request: suspicious port");
1573                 ns_client_next(client, ISC_R_SUCCESS);
1574                 goto cleanup;
1575         }
1576 #endif
1577
1578         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1579                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1580                       "%s request",
1581                       TCP_CLIENT(client) ? "TCP" : "UDP");
1582
1583         /*
1584          * Check the blackhole ACL for UDP only, since TCP is done in
1585          * client_newconn.
1586          */
1587         if (!TCP_CLIENT(client)) {
1588
1589                 if (ns_g_server->blackholeacl != NULL &&
1590                     dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
1591                                   &ns_g_server->aclenv,
1592                                   &match, NULL) == ISC_R_SUCCESS &&
1593                     match > 0)
1594                 {
1595                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1596                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
1597                                       "blackholed UDP datagram");
1598                         ns_client_next(client, ISC_R_SUCCESS);
1599                         goto cleanup;
1600                 }
1601         }
1602
1603         /*
1604          * Silently drop multicast requests for the present.
1605          * XXXMPA revisit this as mDNS spec was published.
1606          */
1607         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
1608                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1609                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
1610                               "dropping multicast request");
1611                 ns_client_next(client, DNS_R_REFUSED);
1612                 goto cleanup;
1613         }
1614
1615         result = dns_message_peekheader(buffer, &id, &flags);
1616         if (result != ISC_R_SUCCESS) {
1617                 /*
1618                  * There isn't enough header to determine whether
1619                  * this was a request or a response.  Drop it.
1620                  */
1621                 ns_client_next(client, result);
1622                 goto cleanup;
1623         }
1624
1625         /*
1626          * The client object handles requests, not responses.
1627          * If this is a UDP response, forward it to the dispatcher.
1628          * If it's a TCP response, discard it here.
1629          */
1630         if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
1631                 if (TCP_CLIENT(client)) {
1632                         CTRACE("unexpected response");
1633                         ns_client_next(client, DNS_R_FORMERR);
1634                         goto cleanup;
1635                 } else {
1636                         dns_dispatch_importrecv(client->dispatch, event);
1637                         ns_client_next(client, ISC_R_SUCCESS);
1638                         goto cleanup;
1639                 }
1640         }
1641
1642         /*
1643          * Update some statistics counters.  Don't count responses.
1644          */
1645         if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
1646                 isc_stats_increment(ns_g_server->nsstats,
1647                                     dns_nsstatscounter_requestv4);
1648         } else {
1649                 isc_stats_increment(ns_g_server->nsstats,
1650                                     dns_nsstatscounter_requestv6);
1651         }
1652         if (TCP_CLIENT(client))
1653                 isc_stats_increment(ns_g_server->nsstats,
1654                                     dns_nsstatscounter_requesttcp);
1655
1656         /*
1657          * It's a request.  Parse it.
1658          */
1659         result = dns_message_parse(client->message, buffer, 0);
1660         if (result != ISC_R_SUCCESS) {
1661                 /*
1662                  * Parsing the request failed.  Send a response
1663                  * (typically FORMERR or SERVFAIL).
1664                  */
1665                 if (result == DNS_R_OPTERR)
1666                         (void)client_addopt(client);
1667
1668                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1669                               NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
1670                               "message parsing failed: %s",
1671                               isc_result_totext(result));
1672                 ns_client_error(client, result);
1673                 goto cleanup;
1674         }
1675
1676         dns_opcodestats_increment(ns_g_server->opcodestats,
1677                                   client->message->opcode);
1678         switch (client->message->opcode) {
1679         case dns_opcode_query:
1680         case dns_opcode_update:
1681         case dns_opcode_notify:
1682                 notimp = ISC_FALSE;
1683                 break;
1684         case dns_opcode_iquery:
1685         default:
1686                 notimp = ISC_TRUE;
1687                 break;
1688         }
1689
1690         client->message->rcode = dns_rcode_noerror;
1691
1692         /* RFC1123 section 6.1.3.2 */
1693         if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
1694                 client->message->flags &= ~DNS_MESSAGEFLAG_RD;
1695
1696         /*
1697          * Deal with EDNS.
1698          */
1699         if (ns_g_noedns)
1700                 opt = NULL;
1701         else
1702                 opt = dns_message_getopt(client->message);
1703         if (opt != NULL) {
1704                 /*
1705                  * Are we dropping all EDNS queries?
1706                  */
1707                 if (ns_g_dropedns) {
1708                         ns_client_next(client, ISC_R_SUCCESS);
1709                         goto cleanup;
1710                 }
1711                 result = process_opt(client, opt);
1712                 if (result != ISC_R_SUCCESS)
1713                         goto cleanup;
1714         }
1715
1716         if (client->message->rdclass == 0) {
1717                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1718                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1719                               "message class could not be determined");
1720                 ns_client_dumpmessage(client,
1721                                       "message class could not be determined");
1722                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
1723                 goto cleanup;
1724         }
1725
1726         /*
1727          * Determine the destination address.  If the receiving interface is
1728          * bound to a specific address, we simply use it regardless of the
1729          * address family.  All IPv4 queries should fall into this case.
1730          * Otherwise, if this is a TCP query, get the address from the
1731          * receiving socket (this needs a system call and can be heavy).
1732          * For IPv6 UDP queries, we get this from the pktinfo structure (if
1733          * supported).
1734          * If all the attempts fail (this can happen due to memory shortage,
1735          * etc), we regard this as an error for safety.
1736          */
1737         if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
1738                 isc_netaddr_fromsockaddr(&client->destaddr,
1739                                          &client->interface->addr);
1740         else {
1741                 isc_sockaddr_t sockaddr;
1742                 result = ISC_R_FAILURE;
1743
1744                 if (TCP_CLIENT(client))
1745                         result = isc_socket_getsockname(client->tcpsocket,
1746                                                         &sockaddr);
1747                 if (result == ISC_R_SUCCESS)
1748                         isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
1749                 if (result != ISC_R_SUCCESS &&
1750                     client->interface->addr.type.sa.sa_family == AF_INET6 &&
1751                     (client->attributes & NS_CLIENTATTR_PKTINFO) != 0) {
1752                         /*
1753                          * XXXJT technically, we should convert the receiving
1754                          * interface ID to a proper scope zone ID.  However,
1755                          * due to the fact there is no standard API for this,
1756                          * we only handle link-local addresses and use the
1757                          * interface index as link ID.  Despite the assumption,
1758                          * it should cover most typical cases.
1759                          */
1760                         isc_netaddr_fromin6(&client->destaddr,
1761                                             &client->pktinfo.ipi6_addr);
1762                         if (IN6_IS_ADDR_LINKLOCAL(&client->pktinfo.ipi6_addr))
1763                                 isc_netaddr_setzone(&client->destaddr,
1764                                                 client->pktinfo.ipi6_ifindex);
1765                         result = ISC_R_SUCCESS;
1766                 }
1767                 if (result != ISC_R_SUCCESS) {
1768                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1769                                          "failed to get request's "
1770                                          "destination: %s",
1771                                          isc_result_totext(result));
1772                         ns_client_next(client, ISC_R_SUCCESS);
1773                         goto cleanup;
1774                 }
1775         }
1776
1777         /*
1778          * Find a view that matches the client's source address.
1779          */
1780         for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
1781              view != NULL;
1782              view = ISC_LIST_NEXT(view, link)) {
1783                 if (client->message->rdclass == view->rdclass ||
1784                     client->message->rdclass == dns_rdataclass_any)
1785                 {
1786                         dns_name_t *tsig = NULL;
1787
1788                         sigresult = dns_message_rechecksig(client->message,
1789                                                            view);
1790                         if (sigresult == ISC_R_SUCCESS)
1791                                 tsig = dns_tsigkey_identity(client->message->tsigkey);
1792
1793                         if (allowed(&netaddr, tsig, view->matchclients) &&
1794                             allowed(&client->destaddr, tsig,
1795                                     view->matchdestinations) &&
1796                             !((client->message->flags & DNS_MESSAGEFLAG_RD)
1797                               == 0 && view->matchrecursiveonly))
1798                         {
1799                                 dns_view_attach(view, &client->view);
1800                                 break;
1801                         }
1802                 }
1803         }
1804
1805         if (view == NULL) {
1806                 char classname[DNS_RDATACLASS_FORMATSIZE];
1807
1808                 /*
1809                  * Do a dummy TSIG verification attempt so that the
1810                  * response will have a TSIG if the query did, as
1811                  * required by RFC2845.
1812                  */
1813                 isc_buffer_t b;
1814                 isc_region_t *r;
1815
1816                 dns_message_resetsig(client->message);
1817
1818                 r = dns_message_getrawmessage(client->message);
1819                 isc_buffer_init(&b, r->base, r->length);
1820                 isc_buffer_add(&b, r->length);
1821                 (void)dns_tsig_verify(&b, client->message, NULL, NULL);
1822
1823                 dns_rdataclass_format(client->message->rdclass, classname,
1824                                       sizeof(classname));
1825                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1826                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
1827                               "no matching view in class '%s'", classname);
1828                 ns_client_dumpmessage(client, "no matching view in class");
1829                 ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
1830                 goto cleanup;
1831         }
1832
1833         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
1834                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
1835                       "using view '%s'", view->name);
1836
1837         /*
1838          * Check for a signature.  We log bad signatures regardless of
1839          * whether they ultimately cause the request to be rejected or
1840          * not.  We do not log the lack of a signature unless we are
1841          * debugging.
1842          */
1843         client->signer = NULL;
1844         dns_name_init(&client->signername, NULL);
1845         result = dns_message_signer(client->message, &client->signername);
1846         if (result != ISC_R_NOTFOUND) {
1847                 signame = NULL;
1848                 if (dns_message_gettsig(client->message, &signame) != NULL) {
1849                         isc_stats_increment(ns_g_server->nsstats,
1850                                             dns_nsstatscounter_tsigin);
1851                 } else {
1852                         isc_stats_increment(ns_g_server->nsstats,
1853                                             dns_nsstatscounter_sig0in);
1854                 }
1855
1856         }
1857         if (result == ISC_R_SUCCESS) {
1858                 char namebuf[DNS_NAME_FORMATSIZE];
1859                 dns_name_format(&client->signername, namebuf, sizeof(namebuf));
1860                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1861                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1862                               "request has valid signature: %s", namebuf);
1863                 client->signer = &client->signername;
1864         } else if (result == ISC_R_NOTFOUND) {
1865                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1866                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1867                               "request is not signed");
1868         } else if (result == DNS_R_NOIDENTITY) {
1869                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1870                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
1871                               "request is signed by a nonauthoritative key");
1872         } else {
1873                 char tsigrcode[64];
1874                 isc_buffer_t b;
1875                 dns_rcode_t status;
1876                 isc_result_t tresult;
1877
1878                 /* There is a signature, but it is bad. */
1879                 isc_stats_increment(ns_g_server->nsstats,
1880                                     dns_nsstatscounter_invalidsig);
1881                 signame = NULL;
1882                 if (dns_message_gettsig(client->message, &signame) != NULL) {
1883                         char namebuf[DNS_NAME_FORMATSIZE];
1884                         char cnamebuf[DNS_NAME_FORMATSIZE];
1885                         dns_name_format(signame, namebuf, sizeof(namebuf));
1886                         status = client->message->tsigstatus;
1887                         isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1888                         tresult = dns_tsigrcode_totext(status, &b);
1889                         INSIST(tresult == ISC_R_SUCCESS);
1890                         tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1891                         if (client->message->tsigkey->generated) {
1892                                 dns_name_format(client->message->tsigkey->creator,
1893                                                 cnamebuf, sizeof(cnamebuf));
1894                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1895                                               NS_LOGMODULE_CLIENT,
1896                                               ISC_LOG_ERROR,
1897                                               "request has invalid signature: "
1898                                               "TSIG %s (%s): %s (%s)", namebuf,
1899                                               cnamebuf,
1900                                               isc_result_totext(result),
1901                                               tsigrcode);
1902                         } else {
1903                                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1904                                               NS_LOGMODULE_CLIENT,
1905                                               ISC_LOG_ERROR,
1906                                               "request has invalid signature: "
1907                                               "TSIG %s: %s (%s)", namebuf,
1908                                               isc_result_totext(result),
1909                                               tsigrcode);
1910                         }
1911                 } else {
1912                         status = client->message->sig0status;
1913                         isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
1914                         tresult = dns_tsigrcode_totext(status, &b);
1915                         INSIST(tresult == ISC_R_SUCCESS);
1916                         tsigrcode[isc_buffer_usedlength(&b)] = '\0';
1917                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
1918                                       NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
1919                                       "request has invalid signature: %s (%s)",
1920                                       isc_result_totext(result), tsigrcode);
1921                 }
1922                 /*
1923                  * Accept update messages signed by unknown keys so that
1924                  * update forwarding works transparently through slaves
1925                  * that don't have all the same keys as the master.
1926                  */
1927                 if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
1928                       client->message->opcode == dns_opcode_update)) {
1929                         ns_client_error(client, sigresult);
1930                         goto cleanup;
1931                 }
1932         }
1933
1934         /*
1935          * Decide whether recursive service is available to this client.
1936          * We do this here rather than in the query code so that we can
1937          * set the RA bit correctly on all kinds of responses, not just
1938          * responses to ordinary queries.  Note if you can't query the
1939          * cache there is no point in setting RA.
1940          */
1941         ra = ISC_FALSE;
1942         if (client->view->resolver != NULL &&
1943             client->view->recursion == ISC_TRUE &&
1944             ns_client_checkaclsilent(client, NULL,
1945                                      client->view->recursionacl,
1946                                      ISC_TRUE) == ISC_R_SUCCESS &&
1947             ns_client_checkaclsilent(client, NULL,
1948                                      client->view->cacheacl,
1949                                      ISC_TRUE) == ISC_R_SUCCESS &&
1950             ns_client_checkaclsilent(client, &client->destaddr,
1951                                      client->view->recursiononacl,
1952                                      ISC_TRUE) == ISC_R_SUCCESS &&
1953             ns_client_checkaclsilent(client, &client->destaddr,
1954                                      client->view->cacheonacl,
1955                                      ISC_TRUE) == ISC_R_SUCCESS)
1956                 ra = ISC_TRUE;
1957
1958         if (ra == ISC_TRUE)
1959                 client->attributes |= NS_CLIENTATTR_RA;
1960
1961         ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
1962                       ISC_LOG_DEBUG(3), ra ? "recursion available" :
1963                                              "recursion not available");
1964
1965         /*
1966          * Adjust maximum UDP response size for this client.
1967          */
1968         if (client->udpsize > 512) {
1969                 dns_peer_t *peer = NULL;
1970                 isc_uint16_t udpsize = view->maxudp;
1971                 (void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
1972                 if (peer != NULL)
1973                         dns_peer_getmaxudp(peer, &udpsize);
1974                 if (client->udpsize > udpsize)
1975                         client->udpsize = udpsize;
1976         }
1977
1978         /*
1979          * Dispatch the request.
1980          */
1981         switch (client->message->opcode) {
1982         case dns_opcode_query:
1983                 CTRACE("query");
1984                 ns_query_start(client);
1985                 break;
1986         case dns_opcode_update:
1987                 CTRACE("update");
1988                 ns_client_settimeout(client, 60);
1989                 ns_update_start(client, sigresult);
1990                 break;
1991         case dns_opcode_notify:
1992                 CTRACE("notify");
1993                 ns_client_settimeout(client, 60);
1994                 ns_notify_start(client);
1995                 break;
1996         case dns_opcode_iquery:
1997                 CTRACE("iquery");
1998                 ns_client_error(client, DNS_R_NOTIMP);
1999                 break;
2000         default:
2001                 CTRACE("unknown opcode");
2002                 ns_client_error(client, DNS_R_NOTIMP);
2003         }
2004
2005  cleanup:
2006         return;
2007 }
2008
2009 static void
2010 client_timeout(isc_task_t *task, isc_event_t *event) {
2011         ns_client_t *client;
2012
2013         REQUIRE(event != NULL);
2014         REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
2015                 event->ev_type == ISC_TIMEREVENT_IDLE);
2016         client = event->ev_arg;
2017         REQUIRE(NS_CLIENT_VALID(client));
2018         REQUIRE(task == client->task);
2019         REQUIRE(client->timer != NULL);
2020
2021         UNUSED(task);
2022
2023         CTRACE("timeout");
2024
2025         isc_event_free(&event);
2026
2027         if (client->shutdown != NULL) {
2028                 (client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
2029                 client->shutdown = NULL;
2030                 client->shutdown_arg = NULL;
2031         }
2032
2033         if (client->newstate > NS_CLIENTSTATE_READY)
2034                 client->newstate = NS_CLIENTSTATE_READY;
2035         (void)exit_check(client);
2036 }
2037
2038 static isc_result_t
2039 get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
2040         isc_mem_t *clientmctx;
2041         isc_result_t result;
2042 #if NMCTXS > 0
2043         unsigned int nextmctx;
2044 #endif
2045
2046         MTRACE("clientmctx");
2047
2048         /*
2049          * Caller must be holding the manager lock.
2050          */
2051         if (ns_g_clienttest) {
2052                 result = isc_mem_create(0, 0, mctxp);
2053                 if (result == ISC_R_SUCCESS)
2054                         isc_mem_setname(*mctxp, "client", NULL);
2055                 return (result);
2056         }
2057 #if NMCTXS > 0
2058         nextmctx = manager->nextmctx++;
2059         if (manager->nextmctx == NMCTXS)
2060                 manager->nextmctx = 0;
2061
2062         INSIST(nextmctx < NMCTXS);
2063
2064         clientmctx = manager->mctxpool[nextmctx];
2065         if (clientmctx == NULL) {
2066                 result = isc_mem_create(0, 0, &clientmctx);
2067                 if (result != ISC_R_SUCCESS)
2068                         return (result);
2069                 isc_mem_setname(clientmctx, "client", NULL);
2070
2071                 manager->mctxpool[nextmctx] = clientmctx;
2072         }
2073 #else
2074         clientmctx = manager->mctx;
2075 #endif
2076
2077         isc_mem_attach(clientmctx, mctxp);
2078
2079         return (ISC_R_SUCCESS);
2080 }
2081
2082 static isc_result_t
2083 client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
2084         ns_client_t *client;
2085         isc_result_t result;
2086         isc_mem_t *mctx = NULL;
2087
2088         /*
2089          * Caller must be holding the manager lock.
2090          *
2091          * Note: creating a client does not add the client to the
2092          * manager's client list or set the client's manager pointer.
2093          * The caller is responsible for that.
2094          */
2095
2096         REQUIRE(clientp != NULL && *clientp == NULL);
2097
2098         result = get_clientmctx(manager, &mctx);
2099         if (result != ISC_R_SUCCESS)
2100                 return (result);
2101
2102         client = isc_mem_get(mctx, sizeof(*client));
2103         if (client == NULL) {
2104                 isc_mem_detach(&mctx);
2105                 return (ISC_R_NOMEMORY);
2106         }
2107         client->mctx = mctx;
2108
2109         client->task = NULL;
2110         result = isc_task_create(manager->taskmgr, 0, &client->task);
2111         if (result != ISC_R_SUCCESS)
2112                 goto cleanup_client;
2113         isc_task_setname(client->task, "client", client);
2114
2115         client->timer = NULL;
2116         result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
2117                                   NULL, NULL, client->task, client_timeout,
2118                                   client, &client->timer);
2119         if (result != ISC_R_SUCCESS)
2120                 goto cleanup_task;
2121         client->timerset = ISC_FALSE;
2122
2123         client->message = NULL;
2124         result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
2125                                     &client->message);
2126         if (result != ISC_R_SUCCESS)
2127                 goto cleanup_timer;
2128
2129         /* XXXRTH  Hardwired constants */
2130
2131         client->sendevent = (isc_socketevent_t *)
2132                             isc_event_allocate(client->mctx, client,
2133                                                ISC_SOCKEVENT_SENDDONE,
2134                                                client_senddone, client,
2135                                                sizeof(isc_socketevent_t));
2136         if (client->sendevent == NULL) {
2137                 result = ISC_R_NOMEMORY;
2138                 goto cleanup_message;
2139         }
2140
2141         client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
2142         if  (client->recvbuf == NULL) {
2143                 result = ISC_R_NOMEMORY;
2144                 goto cleanup_sendevent;
2145         }
2146
2147         client->recvevent = (isc_socketevent_t *)
2148                             isc_event_allocate(client->mctx, client,
2149                                                ISC_SOCKEVENT_RECVDONE,
2150                                                client_request, client,
2151                                                sizeof(isc_socketevent_t));
2152         if (client->recvevent == NULL) {
2153                 result = ISC_R_NOMEMORY;
2154                 goto cleanup_recvbuf;
2155         }
2156
2157         client->magic = NS_CLIENT_MAGIC;
2158         client->manager = NULL;
2159         client->state = NS_CLIENTSTATE_INACTIVE;
2160         client->newstate = NS_CLIENTSTATE_MAX;
2161         client->naccepts = 0;
2162         client->nreads = 0;
2163         client->nsends = 0;
2164         client->nrecvs = 0;
2165         client->nupdates = 0;
2166         client->nctls = 0;
2167         client->references = 0;
2168         client->attributes = 0;
2169         client->view = NULL;
2170         client->dispatch = NULL;
2171         client->udpsocket = NULL;
2172         client->tcplistener = NULL;
2173         client->tcpsocket = NULL;
2174         client->tcpmsg_valid = ISC_FALSE;
2175         client->tcpbuf = NULL;
2176         client->opt = NULL;
2177         client->udpsize = 512;
2178         client->extflags = 0;
2179         client->ednsversion = -1;
2180         client->next = NULL;
2181         client->shutdown = NULL;
2182         client->shutdown_arg = NULL;
2183         client->signer = NULL;
2184         dns_name_init(&client->signername, NULL);
2185         client->mortal = ISC_FALSE;
2186         client->tcpquota = NULL;
2187         client->recursionquota = NULL;
2188         client->interface = NULL;
2189         client->peeraddr_valid = ISC_FALSE;
2190 #ifdef ALLOW_FILTER_AAAA_ON_V4
2191         client->filter_aaaa = dns_v4_aaaa_ok;
2192 #endif
2193         client->needshutdown = ns_g_clienttest;
2194
2195         ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
2196                        NS_EVENT_CLIENTCONTROL, client_start, client, client,
2197                        NULL, NULL);
2198         /*
2199          * Initialize FORMERR cache to sentinel value that will not match
2200          * any actual FORMERR response.
2201          */
2202         isc_sockaddr_any(&client->formerrcache.addr);
2203         client->formerrcache.time = 0;
2204         client->formerrcache.id = 0;
2205         ISC_LINK_INIT(client, link);
2206         ISC_LINK_INIT(client, rlink);
2207         ISC_QLINK_INIT(client, ilink);
2208
2209         /*
2210          * We call the init routines for the various kinds of client here,
2211          * after we have created an otherwise valid client, because some
2212          * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
2213          */
2214         result = ns_query_init(client);
2215         if (result != ISC_R_SUCCESS)
2216                 goto cleanup_recvevent;
2217
2218         result = isc_task_onshutdown(client->task, client_shutdown, client);
2219         if (result != ISC_R_SUCCESS)
2220                 goto cleanup_query;
2221
2222         CTRACE("create");
2223
2224         *clientp = client;
2225
2226         return (ISC_R_SUCCESS);
2227
2228  cleanup_query:
2229         ns_query_free(client);
2230
2231  cleanup_recvevent:
2232         isc_event_free((isc_event_t **)&client->recvevent);
2233
2234  cleanup_recvbuf:
2235         isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
2236
2237  cleanup_sendevent:
2238         isc_event_free((isc_event_t **)&client->sendevent);
2239
2240         client->magic = 0;
2241
2242  cleanup_message:
2243         dns_message_destroy(&client->message);
2244
2245  cleanup_timer:
2246         isc_timer_detach(&client->timer);
2247
2248  cleanup_task:
2249         isc_task_detach(&client->task);
2250
2251  cleanup_client:
2252         isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
2253
2254         return (result);
2255 }
2256
2257 static void
2258 client_read(ns_client_t *client) {
2259         isc_result_t result;
2260
2261         CTRACE("read");
2262
2263         result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
2264                                         client_request, client);
2265         if (result != ISC_R_SUCCESS)
2266                 goto fail;
2267
2268         /*
2269          * Set a timeout to limit the amount of time we will wait
2270          * for a request on this TCP connection.
2271          */
2272         ns_client_settimeout(client, 30);
2273
2274         client->state = client->newstate = NS_CLIENTSTATE_READING;
2275         INSIST(client->nreads == 0);
2276         INSIST(client->recursionquota == NULL);
2277         client->nreads++;
2278
2279         return;
2280  fail:
2281         ns_client_next(client, result);
2282 }
2283
2284 static void
2285 client_newconn(isc_task_t *task, isc_event_t *event) {
2286         ns_client_t *client = event->ev_arg;
2287         isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
2288         isc_result_t result;
2289
2290         REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
2291         REQUIRE(NS_CLIENT_VALID(client));
2292         REQUIRE(client->task == task);
2293
2294         UNUSED(task);
2295
2296         INSIST(client->state == NS_CLIENTSTATE_READY);
2297
2298         INSIST(client->naccepts == 1);
2299         client->naccepts--;
2300
2301         LOCK(&client->interface->lock);
2302         INSIST(client->interface->ntcpcurrent > 0);
2303         client->interface->ntcpcurrent--;
2304         UNLOCK(&client->interface->lock);
2305
2306         /*
2307          * We must take ownership of the new socket before the exit
2308          * check to make sure it gets destroyed if we decide to exit.
2309          */
2310         if (nevent->result == ISC_R_SUCCESS) {
2311                 client->tcpsocket = nevent->newsocket;
2312                 isc_socket_setname(client->tcpsocket, "client-tcp", NULL);
2313                 client->state = NS_CLIENTSTATE_READING;
2314                 INSIST(client->recursionquota == NULL);
2315
2316                 (void)isc_socket_getpeername(client->tcpsocket,
2317                                              &client->peeraddr);
2318                 client->peeraddr_valid = ISC_TRUE;
2319                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2320                            NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2321                            "new TCP connection");
2322         } else {
2323                 /*
2324                  * XXXRTH  What should we do?  We're trying to accept but
2325                  *         it didn't work.  If we just give up, then TCP
2326                  *         service may eventually stop.
2327                  *
2328                  *         For now, we just go idle.
2329                  *
2330                  *         Going idle is probably the right thing if the
2331                  *         I/O was canceled.
2332                  */
2333                 ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2334                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2335                               "accept failed: %s",
2336                               isc_result_totext(nevent->result));
2337         }
2338
2339         if (exit_check(client))
2340                 goto freeevent;
2341
2342         if (nevent->result == ISC_R_SUCCESS) {
2343                 int match;
2344                 isc_netaddr_t netaddr;
2345
2346                 isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
2347
2348                 if (ns_g_server->blackholeacl != NULL &&
2349                     dns_acl_match(&netaddr, NULL,
2350                                   ns_g_server->blackholeacl,
2351                                   &ns_g_server->aclenv,
2352                                   &match, NULL) == ISC_R_SUCCESS &&
2353                     match > 0)
2354                 {
2355                         ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2356                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2357                                       "blackholed connection attempt");
2358                         client->newstate = NS_CLIENTSTATE_READY;
2359                         (void)exit_check(client);
2360                         goto freeevent;
2361                 }
2362
2363                 INSIST(client->tcpmsg_valid == ISC_FALSE);
2364                 dns_tcpmsg_init(client->mctx, client->tcpsocket,
2365                                 &client->tcpmsg);
2366                 client->tcpmsg_valid = ISC_TRUE;
2367
2368                 /*
2369                  * Let a new client take our place immediately, before
2370                  * we wait for a request packet.  If we don't,
2371                  * telnetting to port 53 (once per CPU) will
2372                  * deny service to legitimate TCP clients.
2373                  */
2374                 result = isc_quota_attach(&ns_g_server->tcpquota,
2375                                           &client->tcpquota);
2376                 if (result == ISC_R_SUCCESS)
2377                         result = ns_client_replace(client);
2378                 if (result != ISC_R_SUCCESS) {
2379                         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2380                                       NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
2381                                       "no more TCP clients: %s",
2382                                       isc_result_totext(result));
2383                 }
2384
2385                 client_read(client);
2386         }
2387
2388  freeevent:
2389         isc_event_free(&event);
2390 }
2391
2392 static void
2393 client_accept(ns_client_t *client) {
2394         isc_result_t result;
2395
2396         CTRACE("accept");
2397
2398         result = isc_socket_accept(client->tcplistener, client->task,
2399                                    client_newconn, client);
2400         if (result != ISC_R_SUCCESS) {
2401                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2402                                  "isc_socket_accept() failed: %s",
2403                                  isc_result_totext(result));
2404                 /*
2405                  * XXXRTH  What should we do?  We're trying to accept but
2406                  *         it didn't work.  If we just give up, then TCP
2407                  *         service may eventually stop.
2408                  *
2409                  *         For now, we just go idle.
2410                  */
2411                 return;
2412         }
2413         INSIST(client->naccepts == 0);
2414         client->naccepts++;
2415         LOCK(&client->interface->lock);
2416         client->interface->ntcpcurrent++;
2417         UNLOCK(&client->interface->lock);
2418 }
2419
2420 static void
2421 client_udprecv(ns_client_t *client) {
2422         isc_result_t result;
2423         isc_region_t r;
2424
2425         CTRACE("udprecv");
2426
2427         r.base = client->recvbuf;
2428         r.length = RECV_BUFFER_SIZE;
2429         result = isc_socket_recv2(client->udpsocket, &r, 1,
2430                                   client->task, client->recvevent, 0);
2431         if (result != ISC_R_SUCCESS) {
2432                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2433                                  "isc_socket_recv2() failed: %s",
2434                                  isc_result_totext(result));
2435                 /*
2436                  * This cannot happen in the current implementation, since
2437                  * isc_socket_recv2() cannot fail if flags == 0.
2438                  *
2439                  * If this does fail, we just go idle.
2440                  */
2441                 return;
2442         }
2443         INSIST(client->nrecvs == 0);
2444         client->nrecvs++;
2445 }
2446
2447 void
2448 ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
2449         REQUIRE(NS_CLIENT_VALID(source));
2450         REQUIRE(targetp != NULL && *targetp == NULL);
2451
2452         source->references++;
2453         ns_client_log(source, NS_LOGCATEGORY_CLIENT,
2454                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2455                       "ns_client_attach: ref = %d", source->references);
2456         *targetp = source;
2457 }
2458
2459 void
2460 ns_client_detach(ns_client_t **clientp) {
2461         ns_client_t *client = *clientp;
2462
2463         client->references--;
2464         INSIST(client->references >= 0);
2465         *clientp = NULL;
2466         ns_client_log(client, NS_LOGCATEGORY_CLIENT,
2467                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
2468                       "ns_client_detach: ref = %d", client->references);
2469         (void)exit_check(client);
2470 }
2471
2472 isc_boolean_t
2473 ns_client_shuttingdown(ns_client_t *client) {
2474         return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
2475 }
2476
2477 isc_result_t
2478 ns_client_replace(ns_client_t *client) {
2479         isc_result_t result;
2480
2481         CTRACE("replace");
2482
2483         REQUIRE(client != NULL);
2484         REQUIRE(client->manager != NULL);
2485
2486         result = get_client(client->manager, client->interface,
2487                             client->dispatch, TCP_CLIENT(client));
2488         if (result != ISC_R_SUCCESS)
2489                 return (result);
2490
2491         /*
2492          * The responsibility for listening for new requests is hereby
2493          * transferred to the new client.  Therefore, the old client
2494          * should refrain from listening for any more requests.
2495          */
2496         client->mortal = ISC_TRUE;
2497
2498         return (ISC_R_SUCCESS);
2499 }
2500
2501 /***
2502  *** Client Manager
2503  ***/
2504
2505 static void
2506 clientmgr_destroy(ns_clientmgr_t *manager) {
2507 #if NMCTXS > 0
2508         int i;
2509 #endif
2510
2511         REQUIRE(ISC_LIST_EMPTY(manager->clients));
2512
2513         MTRACE("clientmgr_destroy");
2514
2515 #if NMCTXS > 0
2516         for (i = 0; i < NMCTXS; i++) {
2517                 if (manager->mctxpool[i] != NULL)
2518                         isc_mem_detach(&manager->mctxpool[i]);
2519         }
2520 #endif
2521
2522         ISC_QUEUE_DESTROY(manager->inactive);
2523         DESTROYLOCK(&manager->lock);
2524         DESTROYLOCK(&manager->listlock);
2525         DESTROYLOCK(&manager->reclock);
2526         manager->magic = 0;
2527         isc_mem_put(manager->mctx, manager, sizeof(*manager));
2528 }
2529
2530 isc_result_t
2531 ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
2532                     isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
2533 {
2534         ns_clientmgr_t *manager;
2535         isc_result_t result;
2536 #if NMCTXS > 0
2537         int i;
2538 #endif
2539
2540         manager = isc_mem_get(mctx, sizeof(*manager));
2541         if (manager == NULL)
2542                 return (ISC_R_NOMEMORY);
2543
2544         result = isc_mutex_init(&manager->lock);
2545         if (result != ISC_R_SUCCESS)
2546                 goto cleanup_manager;
2547
2548         result = isc_mutex_init(&manager->listlock);
2549         if (result != ISC_R_SUCCESS)
2550                 goto cleanup_lock;
2551
2552         result = isc_mutex_init(&manager->reclock);
2553         if (result != ISC_R_SUCCESS)
2554                 goto cleanup_listlock;
2555
2556         manager->mctx = mctx;
2557         manager->taskmgr = taskmgr;
2558         manager->timermgr = timermgr;
2559         manager->exiting = ISC_FALSE;
2560         ISC_LIST_INIT(manager->clients);
2561         ISC_LIST_INIT(manager->recursing);
2562         ISC_QUEUE_INIT(manager->inactive, ilink);
2563 #if NMCTXS > 0
2564         manager->nextmctx = 0;
2565         for (i = 0; i < NMCTXS; i++)
2566                 manager->mctxpool[i] = NULL; /* will be created on-demand */
2567 #endif
2568         manager->magic = MANAGER_MAGIC;
2569
2570         MTRACE("create");
2571
2572         *managerp = manager;
2573
2574         return (ISC_R_SUCCESS);
2575
2576  cleanup_listlock:
2577         (void) isc_mutex_destroy(&manager->listlock);
2578
2579  cleanup_lock:
2580         (void) isc_mutex_destroy(&manager->lock);
2581
2582  cleanup_manager:
2583         isc_mem_put(manager->mctx, manager, sizeof(*manager));
2584
2585         return (result);
2586 }
2587
2588 void
2589 ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
2590         isc_result_t result;
2591         ns_clientmgr_t *manager;
2592         ns_client_t *client;
2593         isc_boolean_t need_destroy = ISC_FALSE, unlock = ISC_FALSE;
2594
2595         REQUIRE(managerp != NULL);
2596         manager = *managerp;
2597         REQUIRE(VALID_MANAGER(manager));
2598
2599         MTRACE("destroy");
2600
2601         /*
2602          * Check for success because we may already be task-exclusive
2603          * at this point.  Only if we succeed at obtaining an exclusive
2604          * lock now will we need to relinquish it later.
2605          */
2606         result = isc_task_beginexclusive(ns_g_server->task);
2607         if (result == ISC_R_SUCCESS)
2608                 unlock = ISC_TRUE;
2609
2610         manager->exiting = ISC_TRUE;
2611
2612         for (client = ISC_LIST_HEAD(manager->clients);
2613              client != NULL;
2614              client = ISC_LIST_NEXT(client, link))
2615                 isc_task_shutdown(client->task);
2616
2617         if (ISC_LIST_EMPTY(manager->clients))
2618                 need_destroy = ISC_TRUE;
2619
2620         if (unlock)
2621                 isc_task_endexclusive(ns_g_server->task);
2622
2623         if (need_destroy)
2624                 clientmgr_destroy(manager);
2625
2626         *managerp = NULL;
2627 }
2628
2629 static isc_result_t
2630 get_client(ns_clientmgr_t *manager, ns_interface_t *ifp,
2631            dns_dispatch_t *disp, isc_boolean_t tcp)
2632 {
2633         isc_result_t result = ISC_R_SUCCESS;
2634         isc_event_t *ev;
2635         ns_client_t *client;
2636         MTRACE("get client");
2637
2638         REQUIRE(manager != NULL);
2639
2640         if (manager->exiting)
2641                 return (ISC_R_SHUTTINGDOWN);
2642
2643         /*
2644          * Allocate a client.  First try to get a recycled one;
2645          * if that fails, make a new one.
2646          */
2647         client = NULL;
2648         if (!ns_g_clienttest)
2649                 ISC_QUEUE_POP(manager->inactive, ilink, client);
2650
2651         if (client != NULL)
2652                 MTRACE("recycle");
2653         else {
2654                 MTRACE("create new");
2655
2656                 LOCK(&manager->lock);
2657                 result = client_create(manager, &client);
2658                 UNLOCK(&manager->lock);
2659                 if (result != ISC_R_SUCCESS)
2660                         return (result);
2661
2662                 LOCK(&manager->listlock);
2663                 ISC_LIST_APPEND(manager->clients, client, link);
2664                 UNLOCK(&manager->listlock);
2665         }
2666
2667         client->manager = manager;
2668         ns_interface_attach(ifp, &client->interface);
2669         client->state = NS_CLIENTSTATE_READY;
2670         INSIST(client->recursionquota == NULL);
2671
2672         if (tcp) {
2673                 client->attributes |= NS_CLIENTATTR_TCP;
2674                 isc_socket_attach(ifp->tcpsocket,
2675                                   &client->tcplistener);
2676         } else {
2677                 isc_socket_t *sock;
2678
2679                 dns_dispatch_attach(disp, &client->dispatch);
2680                 sock = dns_dispatch_getsocket(client->dispatch);
2681                 isc_socket_attach(sock, &client->udpsocket);
2682         }
2683
2684         INSIST(client->nctls == 0);
2685         client->nctls++;
2686         ev = &client->ctlevent;
2687         isc_task_send(client->task, &ev);
2688
2689         return (ISC_R_SUCCESS);
2690 }
2691
2692 isc_result_t
2693 ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
2694                            ns_interface_t *ifp, isc_boolean_t tcp)
2695 {
2696         isc_result_t result = ISC_R_SUCCESS;
2697         unsigned int disp;
2698
2699         REQUIRE(VALID_MANAGER(manager));
2700         REQUIRE(n > 0);
2701
2702         MTRACE("createclients");
2703
2704         for (disp = 0; disp < n; disp++) {
2705                 result = get_client(manager, ifp, ifp->udpdispatch[disp], tcp);
2706                 if (result != ISC_R_SUCCESS)
2707                         break;
2708         }
2709
2710         return (result);
2711 }
2712
2713 isc_sockaddr_t *
2714 ns_client_getsockaddr(ns_client_t *client) {
2715         return (&client->peeraddr);
2716 }
2717
2718 isc_result_t
2719 ns_client_checkaclsilent(ns_client_t *client, isc_netaddr_t *netaddr,
2720                          dns_acl_t *acl, isc_boolean_t default_allow)
2721 {
2722         isc_result_t result;
2723         isc_netaddr_t tmpnetaddr;
2724         int match;
2725
2726         if (acl == NULL) {
2727                 if (default_allow)
2728                         goto allow;
2729                 else
2730                         goto deny;
2731         }
2732
2733         if (netaddr == NULL) {
2734                 isc_netaddr_fromsockaddr(&tmpnetaddr, &client->peeraddr);
2735                 netaddr = &tmpnetaddr;
2736         }
2737
2738         result = dns_acl_match(netaddr, client->signer, acl,
2739                                &ns_g_server->aclenv, &match, NULL);
2740
2741         if (result != ISC_R_SUCCESS)
2742                 goto deny; /* Internal error, already logged. */
2743         if (match > 0)
2744                 goto allow;
2745         goto deny; /* Negative match or no match. */
2746
2747  allow:
2748         return (ISC_R_SUCCESS);
2749
2750  deny:
2751         return (DNS_R_REFUSED);
2752 }
2753
2754 isc_result_t
2755 ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr,
2756                    const char *opname, dns_acl_t *acl,
2757                    isc_boolean_t default_allow, int log_level)
2758 {
2759         isc_result_t result;
2760         isc_netaddr_t netaddr;
2761
2762         if (sockaddr != NULL)
2763                 isc_netaddr_fromsockaddr(&netaddr, sockaddr);
2764
2765         result = ns_client_checkaclsilent(client, sockaddr ? &netaddr : NULL,
2766                                           acl, default_allow);
2767
2768         if (result == ISC_R_SUCCESS)
2769                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2770                               NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
2771                               "%s approved", opname);
2772         else
2773                 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
2774                               NS_LOGMODULE_CLIENT,
2775                               log_level, "%s denied", opname);
2776         return (result);
2777 }
2778
2779 static void
2780 ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
2781         if (client->peeraddr_valid)
2782                 isc_sockaddr_format(&client->peeraddr, peerbuf,
2783                                     (unsigned int)len);
2784         else
2785                 snprintf(peerbuf, len, "@%p", client);
2786 }
2787
2788 void
2789 ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
2790                isc_logmodule_t *module, int level, const char *fmt, va_list ap)
2791 {
2792         char msgbuf[4096];
2793         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2794         char signerbuf[DNS_NAME_FORMATSIZE], qnamebuf[DNS_NAME_FORMATSIZE];
2795         const char *viewname = "";
2796         const char *sep1 = "", *sep2 = "", *sep3 = "", *sep4 = "";
2797         const char *signer = "", *qname = "";
2798         dns_name_t *q = NULL;
2799
2800         vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
2801
2802         ns_client_name(client, peerbuf, sizeof(peerbuf));
2803
2804         if (client->signer != NULL) {
2805                 dns_name_format(client->signer, signerbuf, sizeof(signerbuf));
2806                 sep1 = "/key ";
2807                 signer = signerbuf;
2808         }
2809
2810         q = client->query.origqname != NULL
2811                 ? client->query.origqname : client->query.qname;
2812         if (q != NULL) {
2813                 dns_name_format(q, qnamebuf, sizeof(qnamebuf));
2814                 sep2 = " (";
2815                 sep3 = ")";
2816                 qname = qnamebuf;
2817         }
2818
2819         if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
2820             strcmp(client->view->name, "_default") != 0) {
2821                 sep4 = ": view ";
2822                 viewname = client->view->name;
2823         }
2824
2825         isc_log_write(ns_g_lctx, category, module, level,
2826                       "client %s%s%s%s%s%s%s%s: %s",
2827                       peerbuf, sep1, signer, sep2, qname, sep3,
2828                       sep4, viewname, msgbuf);
2829 }
2830
2831 void
2832 ns_client_log(ns_client_t *client, isc_logcategory_t *category,
2833            isc_logmodule_t *module, int level, const char *fmt, ...)
2834 {
2835         va_list ap;
2836
2837         if (! isc_log_wouldlog(ns_g_lctx, level))
2838                 return;
2839
2840         va_start(ap, fmt);
2841         ns_client_logv(client, category, module, level, fmt, ap);
2842         va_end(ap);
2843 }
2844
2845 void
2846 ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
2847                  dns_rdataclass_t rdclass, char *buf, size_t len)
2848 {
2849         char namebuf[DNS_NAME_FORMATSIZE];
2850         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2851         char classbuf[DNS_RDATACLASS_FORMATSIZE];
2852
2853         dns_name_format(name, namebuf, sizeof(namebuf));
2854         dns_rdatatype_format(type, typebuf, sizeof(typebuf));
2855         dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
2856         (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
2857                        classbuf);
2858 }
2859
2860 static void
2861 ns_client_dumpmessage(ns_client_t *client, const char *reason) {
2862         isc_buffer_t buffer;
2863         char *buf = NULL;
2864         int len = 1024;
2865         isc_result_t result;
2866
2867         if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(1)))
2868                 return;
2869
2870         /*
2871          * Note that these are multiline debug messages.  We want a newline
2872          * to appear in the log after each message.
2873          */
2874
2875         do {
2876                 buf = isc_mem_get(client->mctx, len);
2877                 if (buf == NULL)
2878                         break;
2879                 isc_buffer_init(&buffer, buf, len);
2880                 result = dns_message_totext(client->message,
2881                                             &dns_master_style_debug,
2882                                             0, &buffer);
2883                 if (result == ISC_R_NOSPACE) {
2884                         isc_mem_put(client->mctx, buf, len);
2885                         len += 1024;
2886                 } else if (result == ISC_R_SUCCESS)
2887                         ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
2888                                       NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
2889                                       "%s\n%.*s", reason,
2890                                        (int)isc_buffer_usedlength(&buffer),
2891                                        buf);
2892         } while (result == ISC_R_NOSPACE);
2893
2894         if (buf != NULL)
2895                 isc_mem_put(client->mctx, buf, len);
2896 }
2897
2898 void
2899 ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
2900         ns_client_t *client;
2901         char namebuf[DNS_NAME_FORMATSIZE];
2902         char original[DNS_NAME_FORMATSIZE];
2903         char peerbuf[ISC_SOCKADDR_FORMATSIZE];
2904         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2905         char classbuf[DNS_RDATACLASS_FORMATSIZE];
2906         const char *name;
2907         const char *sep;
2908         const char *origfor;
2909         dns_rdataset_t *rdataset;
2910
2911         REQUIRE(VALID_MANAGER(manager));
2912
2913         LOCK(&manager->reclock);
2914         client = ISC_LIST_HEAD(manager->recursing);
2915         while (client != NULL) {
2916                 INSIST(client->state == NS_CLIENTSTATE_RECURSING);
2917
2918                 ns_client_name(client, peerbuf, sizeof(peerbuf));
2919                 if (client->view != NULL &&
2920                     strcmp(client->view->name, "_bind") != 0 &&
2921                     strcmp(client->view->name, "_default") != 0) {
2922                         name = client->view->name;
2923                         sep = ": view ";
2924                 } else {
2925                         name = "";
2926                         sep = "";
2927                 }
2928
2929                 LOCK(&client->query.fetchlock);
2930                 INSIST(client->query.qname != NULL);
2931                 dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
2932                 if (client->query.qname != client->query.origqname &&
2933                     client->query.origqname != NULL) {
2934                         origfor = " for ";
2935                         dns_name_format(client->query.origqname, original,
2936                                         sizeof(original));
2937                 } else {
2938                         origfor = "";
2939                         original[0] = '\0';
2940                 }
2941                 rdataset = ISC_LIST_HEAD(client->query.qname->list);
2942                 if (rdataset == NULL && client->query.origqname != NULL)
2943                         rdataset = ISC_LIST_HEAD(client->query.origqname->list);
2944                 if (rdataset != NULL) {
2945                         dns_rdatatype_format(rdataset->type, typebuf,
2946                                              sizeof(typebuf));
2947                         dns_rdataclass_format(rdataset->rdclass, classbuf,
2948                                               sizeof(classbuf));
2949                 } else {
2950                         strcpy(typebuf, "-");
2951                         strcpy(classbuf, "-");
2952                 }
2953                 UNLOCK(&client->query.fetchlock);
2954                 fprintf(f, "; client %s%s%s: id %u '%s/%s/%s'%s%s "
2955                         "requesttime %d\n", peerbuf, sep, name,
2956                         client->message->id, namebuf, typebuf, classbuf,
2957                         origfor, original, client->requesttime);
2958                 client = ISC_LIST_NEXT(client, rlink);
2959         }
2960         UNLOCK(&manager->reclock);
2961 }
2962
2963 void
2964 ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
2965         LOCK(&client->query.fetchlock);
2966         if (client->query.restarts > 0) {
2967                 /*
2968                  * client->query.qname was dynamically allocated.
2969                  */
2970                 dns_message_puttempname(client->message,
2971                                         &client->query.qname);
2972         }
2973         client->query.qname = name;
2974         UNLOCK(&client->query.fetchlock);
2975 }
2976
2977 isc_result_t
2978 ns_client_sourceip(dns_clientinfo_t *ci, isc_sockaddr_t **addrp) {
2979         ns_client_t *client = (ns_client_t *) ci->data;
2980
2981         REQUIRE(NS_CLIENT_VALID(client));
2982         REQUIRE(addrp != NULL);
2983
2984         *addrp = &client->peeraddr;
2985         return (ISC_R_SUCCESS);
2986 }