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