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