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