1/* 2 * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: lwresd.c,v 1.60 2009/09/02 23:48:01 tbox Exp $ */ 19 20/*! \file 21 * \brief 22 * Main program for the Lightweight Resolver Daemon. 23 * 24 * To paraphrase the old saying about X11, "It's not a lightweight deamon 25 * for resolvers, it's a deamon for lightweight resolvers". 26 */ 27 28#include <config.h> 29 30#include <stdlib.h> 31#include <string.h> 32 33#include <isc/list.h> 34#include <isc/magic.h> 35#include <isc/mem.h> 36#include <isc/once.h> 37#include <isc/print.h> 38#include <isc/socket.h> 39#include <isc/task.h> 40#include <isc/util.h> 41 42#include <isccfg/namedconf.h> 43 44#include <dns/log.h> 45#include <dns/result.h> 46#include <dns/view.h> 47 48#include <named/config.h> 49#include <named/globals.h> 50#include <named/log.h> 51#include <named/lwaddr.h> 52#include <named/lwresd.h> 53#include <named/lwdclient.h> 54#include <named/lwsearch.h> 55#include <named/server.h> 56 57#define LWRESD_MAGIC ISC_MAGIC('L', 'W', 'R', 'D') 58#define VALID_LWRESD(l) ISC_MAGIC_VALID(l, LWRESD_MAGIC) 59 60#define LWRESLISTENER_MAGIC ISC_MAGIC('L', 'W', 'R', 'L') 61#define VALID_LWRESLISTENER(l) ISC_MAGIC_VALID(l, LWRESLISTENER_MAGIC) 62 63/*! 64 * The total number of clients we can handle will be NTASKS * NRECVS. 65 */ 66#define NTASKS 2 /*%< tasks to create to handle lwres queries */ 67#define NRECVS 2 /*%< max clients per task */ 68 69typedef ISC_LIST(ns_lwreslistener_t) ns_lwreslistenerlist_t; 70 71static ns_lwreslistenerlist_t listeners; 72static isc_mutex_t listeners_lock; 73static isc_once_t once = ISC_ONCE_INIT; 74 75 76static void 77initialize_mutex(void) { 78 RUNTIME_CHECK(isc_mutex_init(&listeners_lock) == ISC_R_SUCCESS); 79} 80 81 82/*% 83 * Wrappers around our memory management stuff, for the lwres functions. 84 */ 85void * 86ns__lwresd_memalloc(void *arg, size_t size) { 87 return (isc_mem_get(arg, size)); 88} 89 90void 91ns__lwresd_memfree(void *arg, void *mem, size_t size) { 92 isc_mem_put(arg, mem, size); 93} 94 95 96#define CHECK(op) \ 97 do { result = (op); \ 98 if (result != ISC_R_SUCCESS) goto cleanup; \ 99 } while (0) 100 101static isc_result_t 102buffer_putstr(isc_buffer_t *b, const char *s) { 103 unsigned int len = strlen(s); 104 if (isc_buffer_availablelength(b) <= len) 105 return (ISC_R_NOSPACE); 106 isc_buffer_putmem(b, (const unsigned char *)s, len); 107 return (ISC_R_SUCCESS); 108} 109 110/* 111 * Convert a resolv.conf file into a config structure. 112 */ 113isc_result_t 114ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx, 115 cfg_obj_t **configp) 116{ 117 char text[4096]; 118 char str[16]; 119 isc_buffer_t b; 120 lwres_context_t *lwctx = NULL; 121 lwres_conf_t *lwc = NULL; 122 isc_sockaddr_t sa; 123 isc_netaddr_t na; 124 int i; 125 isc_result_t result; 126 lwres_result_t lwresult; 127 128 lwctx = NULL; 129 lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc, 130 ns__lwresd_memfree, 131 LWRES_CONTEXT_SERVERMODE); 132 if (lwresult != LWRES_R_SUCCESS) { 133 result = ISC_R_NOMEMORY; 134 goto cleanup; 135 } 136 137 lwresult = lwres_conf_parse(lwctx, lwresd_g_resolvconffile); 138 if (lwresult != LWRES_R_SUCCESS) { 139 result = DNS_R_SYNTAX; 140 goto cleanup; 141 } 142 143 lwc = lwres_conf_get(lwctx); 144 INSIST(lwc != NULL); 145 146 isc_buffer_init(&b, text, sizeof(text)); 147 148 CHECK(buffer_putstr(&b, "options {\n")); 149 150 /* 151 * Build the list of forwarders. 152 */ 153 if (lwc->nsnext > 0) { 154 CHECK(buffer_putstr(&b, "\tforwarders {\n")); 155 156 for (i = 0; i < lwc->nsnext; i++) { 157 CHECK(lwaddr_sockaddr_fromlwresaddr( 158 &sa, 159 &lwc->nameservers[i], 160 ns_g_port)); 161 isc_netaddr_fromsockaddr(&na, &sa); 162 CHECK(buffer_putstr(&b, "\t\t")); 163 CHECK(isc_netaddr_totext(&na, &b)); 164 CHECK(buffer_putstr(&b, ";\n")); 165 } 166 CHECK(buffer_putstr(&b, "\t};\n")); 167 } 168 169 /* 170 * Build the sortlist 171 */ 172 if (lwc->sortlistnxt > 0) { 173 CHECK(buffer_putstr(&b, "\tsortlist {\n")); 174 CHECK(buffer_putstr(&b, "\t\t{\n")); 175 CHECK(buffer_putstr(&b, "\t\t\tany;\n")); 176 CHECK(buffer_putstr(&b, "\t\t\t{\n")); 177 for (i = 0; i < lwc->sortlistnxt; i++) { 178 lwres_addr_t *lwaddr = &lwc->sortlist[i].addr; 179 lwres_addr_t *lwmask = &lwc->sortlist[i].mask; 180 unsigned int mask; 181 182 CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwmask, 0)); 183 isc_netaddr_fromsockaddr(&na, &sa); 184 result = isc_netaddr_masktoprefixlen(&na, &mask); 185 if (result != ISC_R_SUCCESS) { 186 char addrtext[ISC_NETADDR_FORMATSIZE]; 187 isc_netaddr_format(&na, addrtext, 188 sizeof(addrtext)); 189 isc_log_write(ns_g_lctx, 190 NS_LOGCATEGORY_GENERAL, 191 NS_LOGMODULE_LWRESD, 192 ISC_LOG_ERROR, 193 "processing sortlist: '%s' is " 194 "not a valid netmask", 195 addrtext); 196 goto cleanup; 197 } 198 199 CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwaddr, 0)); 200 isc_netaddr_fromsockaddr(&na, &sa); 201 202 CHECK(buffer_putstr(&b, "\t\t\t\t")); 203 CHECK(isc_netaddr_totext(&na, &b)); 204 snprintf(str, sizeof(str), "%u", mask); 205 CHECK(buffer_putstr(&b, "/")); 206 CHECK(buffer_putstr(&b, str)); 207 CHECK(buffer_putstr(&b, ";\n")); 208 } 209 CHECK(buffer_putstr(&b, "\t\t\t};\n")); 210 CHECK(buffer_putstr(&b, "\t\t};\n")); 211 CHECK(buffer_putstr(&b, "\t};\n")); 212 } 213 214 CHECK(buffer_putstr(&b, "};\n\n")); 215 216 CHECK(buffer_putstr(&b, "lwres {\n")); 217 218 /* 219 * Build the search path 220 */ 221 if (lwc->searchnxt > 0) { 222 if (lwc->searchnxt > 0) { 223 CHECK(buffer_putstr(&b, "\tsearch {\n")); 224 for (i = 0; i < lwc->searchnxt; i++) { 225 CHECK(buffer_putstr(&b, "\t\t\"")); 226 CHECK(buffer_putstr(&b, lwc->search[i])); 227 CHECK(buffer_putstr(&b, "\";\n")); 228 } 229 CHECK(buffer_putstr(&b, "\t};\n")); 230 } 231 } 232 233 /* 234 * Build the ndots line 235 */ 236 if (lwc->ndots != 1) { 237 CHECK(buffer_putstr(&b, "\tndots ")); 238 snprintf(str, sizeof(str), "%u", lwc->ndots); 239 CHECK(buffer_putstr(&b, str)); 240 CHECK(buffer_putstr(&b, ";\n")); 241 } 242 243 /* 244 * Build the listen-on line 245 */ 246 if (lwc->lwnext > 0) { 247 CHECK(buffer_putstr(&b, "\tlisten-on {\n")); 248 249 for (i = 0; i < lwc->lwnext; i++) { 250 CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, 251 &lwc->lwservers[i], 252 0)); 253 isc_netaddr_fromsockaddr(&na, &sa); 254 CHECK(buffer_putstr(&b, "\t\t")); 255 CHECK(isc_netaddr_totext(&na, &b)); 256 CHECK(buffer_putstr(&b, ";\n")); 257 } 258 CHECK(buffer_putstr(&b, "\t};\n")); 259 } 260 261 CHECK(buffer_putstr(&b, "};\n")); 262 263#if 0 264 printf("%.*s\n", 265 (int)isc_buffer_usedlength(&b), 266 (char *)isc_buffer_base(&b)); 267#endif 268 269 lwres_conf_clear(lwctx); 270 lwres_context_destroy(&lwctx); 271 272 return (cfg_parse_buffer(pctx, &b, &cfg_type_namedconf, configp)); 273 274 cleanup: 275 276 if (lwctx != NULL) { 277 lwres_conf_clear(lwctx); 278 lwres_context_destroy(&lwctx); 279 } 280 281 return (result); 282} 283 284 285/* 286 * Handle lwresd manager objects 287 */ 288isc_result_t 289ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres, 290 ns_lwresd_t **lwresdp) 291{ 292 ns_lwresd_t *lwresd; 293 const char *vname; 294 dns_rdataclass_t vclass; 295 const cfg_obj_t *obj, *viewobj, *searchobj; 296 const cfg_listelt_t *element; 297 isc_result_t result; 298 299 INSIST(lwresdp != NULL && *lwresdp == NULL); 300 301 lwresd = isc_mem_get(mctx, sizeof(ns_lwresd_t)); 302 if (lwresd == NULL) 303 return (ISC_R_NOMEMORY); 304 305 lwresd->mctx = NULL; 306 isc_mem_attach(mctx, &lwresd->mctx); 307 lwresd->view = NULL; 308 lwresd->search = NULL; 309 lwresd->refs = 1; 310 311 obj = NULL; 312 (void)cfg_map_get(lwres, "ndots", &obj); 313 if (obj != NULL) 314 lwresd->ndots = cfg_obj_asuint32(obj); 315 else 316 lwresd->ndots = 1; 317 318 RUNTIME_CHECK(isc_mutex_init(&lwresd->lock) == ISC_R_SUCCESS); 319 320 lwresd->shutting_down = ISC_FALSE; 321 322 viewobj = NULL; 323 (void)cfg_map_get(lwres, "view", &viewobj); 324 if (viewobj != NULL) { 325 vname = cfg_obj_asstring(cfg_tuple_get(viewobj, "name")); 326 obj = cfg_tuple_get(viewobj, "class"); 327 result = ns_config_getclass(obj, dns_rdataclass_in, &vclass); 328 if (result != ISC_R_SUCCESS) 329 goto fail; 330 } else { 331 vname = "_default"; 332 vclass = dns_rdataclass_in; 333 } 334 335 result = dns_viewlist_find(&ns_g_server->viewlist, vname, vclass, 336 &lwresd->view); 337 if (result != ISC_R_SUCCESS) { 338 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 339 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, 340 "couldn't find view %s", vname); 341 goto fail; 342 } 343 344 searchobj = NULL; 345 (void)cfg_map_get(lwres, "search", &searchobj); 346 if (searchobj != NULL) { 347 lwresd->search = NULL; 348 result = ns_lwsearchlist_create(lwresd->mctx, 349 &lwresd->search); 350 if (result != ISC_R_SUCCESS) { 351 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 352 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, 353 "couldn't create searchlist"); 354 goto fail; 355 } 356 for (element = cfg_list_first(searchobj); 357 element != NULL; 358 element = cfg_list_next(element)) 359 { 360 const cfg_obj_t *search; 361 const char *searchstr; 362 isc_buffer_t namebuf; 363 dns_fixedname_t fname; 364 dns_name_t *name; 365 366 search = cfg_listelt_value(element); 367 searchstr = cfg_obj_asstring(search); 368 369 dns_fixedname_init(&fname); 370 name = dns_fixedname_name(&fname); 371 isc_buffer_constinit(&namebuf, searchstr, 372 strlen(searchstr)); 373 isc_buffer_add(&namebuf, strlen(searchstr)); 374 result = dns_name_fromtext(name, &namebuf, 375 dns_rootname, 0, NULL); 376 if (result != ISC_R_SUCCESS) { 377 isc_log_write(ns_g_lctx, 378 NS_LOGCATEGORY_GENERAL, 379 NS_LOGMODULE_LWRESD, 380 ISC_LOG_WARNING, 381 "invalid name %s in searchlist", 382 searchstr); 383 continue; 384 } 385 386 result = ns_lwsearchlist_append(lwresd->search, name); 387 if (result != ISC_R_SUCCESS) { 388 isc_log_write(ns_g_lctx, 389 NS_LOGCATEGORY_GENERAL, 390 NS_LOGMODULE_LWRESD, 391 ISC_LOG_WARNING, 392 "couldn't update searchlist"); 393 goto fail; 394 } 395 } 396 } 397 398 lwresd->magic = LWRESD_MAGIC; 399 400 *lwresdp = lwresd; 401 return (ISC_R_SUCCESS); 402 403 fail: 404 if (lwresd->view != NULL) 405 dns_view_detach(&lwresd->view); 406 if (lwresd->search != NULL) 407 ns_lwsearchlist_detach(&lwresd->search); 408 if (lwresd->mctx != NULL) 409 isc_mem_detach(&lwresd->mctx); 410 isc_mem_put(mctx, lwresd, sizeof(ns_lwresd_t)); 411 return (result); 412} 413 414void 415ns_lwdmanager_attach(ns_lwresd_t *source, ns_lwresd_t **targetp) { 416 INSIST(VALID_LWRESD(source)); 417 INSIST(targetp != NULL && *targetp == NULL); 418 419 LOCK(&source->lock); 420 source->refs++; 421 UNLOCK(&source->lock); 422 423 *targetp = source; 424} 425 426void 427ns_lwdmanager_detach(ns_lwresd_t **lwresdp) { 428 ns_lwresd_t *lwresd; 429 isc_mem_t *mctx; 430 isc_boolean_t done = ISC_FALSE; 431 432 INSIST(lwresdp != NULL && *lwresdp != NULL); 433 INSIST(VALID_LWRESD(*lwresdp)); 434 435 lwresd = *lwresdp; 436 *lwresdp = NULL; 437 438 LOCK(&lwresd->lock); 439 INSIST(lwresd->refs > 0); 440 lwresd->refs--; 441 if (lwresd->refs == 0) 442 done = ISC_TRUE; 443 UNLOCK(&lwresd->lock); 444 445 if (!done) 446 return; 447 448 dns_view_detach(&lwresd->view); 449 if (lwresd->search != NULL) 450 ns_lwsearchlist_detach(&lwresd->search); 451 mctx = lwresd->mctx; 452 lwresd->magic = 0; 453 isc_mem_put(mctx, lwresd, sizeof(*lwresd)); 454 isc_mem_detach(&mctx); 455} 456 457 458/* 459 * Handle listener objects 460 */ 461void 462ns_lwreslistener_attach(ns_lwreslistener_t *source, 463 ns_lwreslistener_t **targetp) 464{ 465 INSIST(VALID_LWRESLISTENER(source)); 466 INSIST(targetp != NULL && *targetp == NULL); 467 468 LOCK(&source->lock); 469 source->refs++; 470 UNLOCK(&source->lock); 471 472 *targetp = source; 473} 474 475void 476ns_lwreslistener_detach(ns_lwreslistener_t **listenerp) { 477 ns_lwreslistener_t *listener; 478 isc_mem_t *mctx; 479 isc_boolean_t done = ISC_FALSE; 480 481 INSIST(listenerp != NULL && *listenerp != NULL); 482 INSIST(VALID_LWRESLISTENER(*listenerp)); 483 484 listener = *listenerp; 485 486 LOCK(&listener->lock); 487 INSIST(listener->refs > 0); 488 listener->refs--; 489 if (listener->refs == 0) 490 done = ISC_TRUE; 491 UNLOCK(&listener->lock); 492 493 if (!done) 494 return; 495 496 if (listener->manager != NULL) 497 ns_lwdmanager_detach(&listener->manager); 498 499 if (listener->sock != NULL) 500 isc_socket_detach(&listener->sock); 501 502 listener->magic = 0; 503 mctx = listener->mctx; 504 isc_mem_put(mctx, listener, sizeof(*listener)); 505 isc_mem_detach(&mctx); 506 listenerp = NULL; 507} 508 509static isc_result_t 510listener_create(isc_mem_t *mctx, ns_lwresd_t *lwresd, 511 ns_lwreslistener_t **listenerp) 512{ 513 ns_lwreslistener_t *listener; 514 isc_result_t result; 515 516 REQUIRE(listenerp != NULL && *listenerp == NULL); 517 518 listener = isc_mem_get(mctx, sizeof(ns_lwreslistener_t)); 519 if (listener == NULL) 520 return (ISC_R_NOMEMORY); 521 522 result = isc_mutex_init(&listener->lock); 523 if (result != ISC_R_SUCCESS) { 524 isc_mem_put(mctx, listener, sizeof(ns_lwreslistener_t)); 525 return (result); 526 } 527 528 listener->magic = LWRESLISTENER_MAGIC; 529 listener->refs = 1; 530 531 listener->sock = NULL; 532 533 listener->manager = NULL; 534 ns_lwdmanager_attach(lwresd, &listener->manager); 535 536 listener->mctx = NULL; 537 isc_mem_attach(mctx, &listener->mctx); 538 539 ISC_LINK_INIT(listener, link); 540 ISC_LIST_INIT(listener->cmgrs); 541 542 *listenerp = listener; 543 return (ISC_R_SUCCESS); 544} 545 546static isc_result_t 547listener_bind(ns_lwreslistener_t *listener, isc_sockaddr_t *address) { 548 isc_socket_t *sock = NULL; 549 isc_result_t result = ISC_R_SUCCESS; 550 int pf; 551 552 pf = isc_sockaddr_pf(address); 553 if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) || 554 (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) 555 return (ISC_R_FAMILYNOSUPPORT); 556 557 listener->address = *address; 558 559 if (isc_sockaddr_getport(&listener->address) == 0) { 560 in_port_t port; 561 port = lwresd_g_listenport; 562 if (port == 0) 563 port = LWRES_UDP_PORT; 564 isc_sockaddr_setport(&listener->address, port); 565 } 566 567 sock = NULL; 568 result = isc_socket_create(ns_g_socketmgr, pf, 569 isc_sockettype_udp, &sock); 570 if (result != ISC_R_SUCCESS) { 571 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 572 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, 573 "failed to create lwres socket: %s", 574 isc_result_totext(result)); 575 return (result); 576 } 577 578 result = isc_socket_bind(sock, &listener->address, 579 ISC_SOCKET_REUSEADDRESS); 580 if (result != ISC_R_SUCCESS) { 581 char socktext[ISC_SOCKADDR_FORMATSIZE]; 582 isc_sockaddr_format(&listener->address, socktext, 583 sizeof(socktext)); 584 isc_socket_detach(&sock); 585 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 586 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, 587 "failed to add lwres socket: %s: %s", 588 socktext, isc_result_totext(result)); 589 return (result); 590 } 591 listener->sock = sock; 592 return (ISC_R_SUCCESS); 593} 594 595static void 596listener_copysock(ns_lwreslistener_t *oldlistener, 597 ns_lwreslistener_t *newlistener) 598{ 599 newlistener->address = oldlistener->address; 600 isc_socket_attach(oldlistener->sock, &newlistener->sock); 601} 602 603static isc_result_t 604listener_startclients(ns_lwreslistener_t *listener) { 605 ns_lwdclientmgr_t *cm; 606 unsigned int i; 607 isc_result_t result; 608 609 /* 610 * Create the client managers. 611 */ 612 result = ISC_R_SUCCESS; 613 for (i = 0; i < NTASKS && result == ISC_R_SUCCESS; i++) 614 result = ns_lwdclientmgr_create(listener, NRECVS, 615 ns_g_taskmgr); 616 617 /* 618 * Ensure that we have created at least one. 619 */ 620 if (ISC_LIST_EMPTY(listener->cmgrs)) 621 return (result); 622 623 /* 624 * Walk the list of clients and start each one up. 625 */ 626 LOCK(&listener->lock); 627 cm = ISC_LIST_HEAD(listener->cmgrs); 628 while (cm != NULL) { 629 result = ns_lwdclient_startrecv(cm); 630 if (result != ISC_R_SUCCESS) 631 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, 632 NS_LOGMODULE_LWRESD, ISC_LOG_ERROR, 633 "could not start lwres " 634 "client handler: %s", 635 isc_result_totext(result)); 636 cm = ISC_LIST_NEXT(cm, link); 637 } 638 UNLOCK(&listener->lock); 639 640 return (ISC_R_SUCCESS); 641} 642 643static void 644listener_shutdown(ns_lwreslistener_t *listener) { 645 ns_lwdclientmgr_t *cm; 646 647 cm = ISC_LIST_HEAD(listener->cmgrs); 648 while (cm != NULL) { 649 isc_task_shutdown(cm->task); 650 cm = ISC_LIST_NEXT(cm, link); 651 } 652} 653 654static isc_result_t 655find_listener(isc_sockaddr_t *address, ns_lwreslistener_t **listenerp) { 656 ns_lwreslistener_t *listener; 657 658 INSIST(listenerp != NULL && *listenerp == NULL); 659 660 for (listener = ISC_LIST_HEAD(listeners); 661 listener != NULL; 662 listener = ISC_LIST_NEXT(listener, link)) 663 { 664 if (!isc_sockaddr_equal(address, &listener->address)) 665 continue; 666 *listenerp = listener; 667 return (ISC_R_SUCCESS); 668 } 669 return (ISC_R_NOTFOUND); 670} 671 672void 673ns_lwreslistener_unlinkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm) 674{ 675 REQUIRE(VALID_LWRESLISTENER(listener)); 676 677 LOCK(&listener->lock); 678 ISC_LIST_UNLINK(listener->cmgrs, cm, link); 679 UNLOCK(&listener->lock); 680} 681 682void 683ns_lwreslistener_linkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm) { 684 REQUIRE(VALID_LWRESLISTENER(listener)); 685 686 /* 687 * This does no locking, since it's called early enough that locking 688 * isn't needed. 689 */ 690 ISC_LIST_APPEND(listener->cmgrs, cm, link); 691} 692 693static isc_result_t 694configure_listener(isc_sockaddr_t *address, ns_lwresd_t *lwresd, 695 isc_mem_t *mctx, ns_lwreslistenerlist_t *newlisteners) 696{ 697 ns_lwreslistener_t *listener, *oldlistener = NULL; 698 char socktext[ISC_SOCKADDR_FORMATSIZE]; 699 isc_result_t result; 700 701 (void)find_listener(address, &oldlistener); 702 listener = NULL; 703 result = listener_create(mctx, lwresd, &listener); 704 if (result != ISC_R_SUCCESS) { 705 isc_sockaddr_format(address, socktext, sizeof(socktext)); 706 isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, 707 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, 708 "lwres failed to configure %s: %s", 709 socktext, isc_result_totext(result)); 710 return (result); 711 } 712 713 /* 714 * If there's already a listener, don't rebind the socket. 715 */ 716 if (oldlistener == NULL) { 717 result = listener_bind(listener, address); 718 if (result != ISC_R_SUCCESS) { 719 ns_lwreslistener_detach(&listener); 720 return (ISC_R_SUCCESS); 721 } 722 } else 723 listener_copysock(oldlistener, listener); 724 725 result = listener_startclients(listener); 726 if (result != ISC_R_SUCCESS) { 727 isc_sockaddr_format(address, socktext, sizeof(socktext)); 728 isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, 729 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, 730 "lwres: failed to start %s: %s", socktext, 731 isc_result_totext(result)); 732 ns_lwreslistener_detach(&listener); 733 return (ISC_R_SUCCESS); 734 } 735 736 if (oldlistener != NULL) { 737 /* 738 * Remove the old listener from the old list and shut it down. 739 */ 740 ISC_LIST_UNLINK(listeners, oldlistener, link); 741 listener_shutdown(oldlistener); 742 ns_lwreslistener_detach(&oldlistener); 743 } else { 744 isc_sockaddr_format(address, socktext, sizeof(socktext)); 745 isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, 746 NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE, 747 "lwres listening on %s", socktext); 748 } 749 750 ISC_LIST_APPEND(*newlisteners, listener, link); 751 return (result); 752} 753 754isc_result_t 755ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) { 756 const cfg_obj_t *lwreslist = NULL; 757 const cfg_obj_t *lwres = NULL; 758 const cfg_obj_t *listenerslist = NULL; 759 const cfg_listelt_t *element = NULL; 760 ns_lwreslistener_t *listener; 761 ns_lwreslistenerlist_t newlisteners; 762 isc_result_t result; 763 char socktext[ISC_SOCKADDR_FORMATSIZE]; 764 isc_sockaddr_t *addrs = NULL; 765 ns_lwresd_t *lwresd = NULL; 766 isc_uint32_t count = 0; 767 768 REQUIRE(mctx != NULL); 769 REQUIRE(config != NULL); 770 771 RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); 772 773 ISC_LIST_INIT(newlisteners); 774 775 result = cfg_map_get(config, "lwres", &lwreslist); 776 if (result != ISC_R_SUCCESS) 777 return (ISC_R_SUCCESS); 778 779 LOCK(&listeners_lock); 780 /* 781 * Run through the new lwres address list, noting sockets that 782 * are already being listened on and moving them to the new list. 783 * 784 * Identifying duplicates addr/port combinations is left to either 785 * the underlying config code, or to the bind attempt getting an 786 * address-in-use error. 787 */ 788 for (element = cfg_list_first(lwreslist); 789 element != NULL; 790 element = cfg_list_next(element)) 791 { 792 in_port_t port; 793 794 lwres = cfg_listelt_value(element); 795 CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd)); 796 797 port = lwresd_g_listenport; 798 if (port == 0) 799 port = LWRES_UDP_PORT; 800 801 listenerslist = NULL; 802 (void)cfg_map_get(lwres, "listen-on", &listenerslist); 803 if (listenerslist == NULL) { 804 struct in_addr localhost; 805 isc_sockaddr_t address; 806 807 localhost.s_addr = htonl(INADDR_LOOPBACK); 808 isc_sockaddr_fromin(&address, &localhost, port); 809 CHECK(configure_listener(&address, lwresd, mctx, 810 &newlisteners)); 811 } else { 812 isc_uint32_t i; 813 814 CHECK(ns_config_getiplist(config, listenerslist, 815 port, mctx, &addrs, &count)); 816 for (i = 0; i < count; i++) 817 CHECK(configure_listener(&addrs[i], lwresd, 818 mctx, &newlisteners)); 819 ns_config_putiplist(mctx, &addrs, count); 820 } 821 ns_lwdmanager_detach(&lwresd); 822 } 823 824 /* 825 * Shutdown everything on the listeners list, and remove them from 826 * the list. Then put all of the new listeners on it. 827 */ 828 829 while (!ISC_LIST_EMPTY(listeners)) { 830 listener = ISC_LIST_HEAD(listeners); 831 ISC_LIST_UNLINK(listeners, listener, link); 832 833 isc_sockaddr_format(&listener->address, 834 socktext, sizeof(socktext)); 835 836 listener_shutdown(listener); 837 ns_lwreslistener_detach(&listener); 838 839 isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, 840 NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE, 841 "lwres no longer listening on %s", socktext); 842 } 843 844 cleanup: 845 ISC_LIST_APPENDLIST(listeners, newlisteners, link); 846 847 if (addrs != NULL) 848 ns_config_putiplist(mctx, &addrs, count); 849 850 if (lwresd != NULL) 851 ns_lwdmanager_detach(&lwresd); 852 853 UNLOCK(&listeners_lock); 854 855 return (result); 856} 857 858void 859ns_lwresd_shutdown(void) { 860 ns_lwreslistener_t *listener; 861 862 RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); 863 864 while (!ISC_LIST_EMPTY(listeners)) { 865 listener = ISC_LIST_HEAD(listeners); 866 ISC_LIST_UNLINK(listeners, listener, link); 867 ns_lwreslistener_detach(&listener); 868 } 869} 870