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