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