00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <config.h>
00029
00030 #include <stdlib.h>
00031 #include <string.h>
00032
00033 #include <isc/list.h>
00034 #include <isc/magic.h>
00035 #include <isc/mem.h>
00036 #include <isc/once.h>
00037 #include <isc/print.h>
00038 #include <isc/socket.h>
00039 #include <isc/task.h>
00040 #include <isc/util.h>
00041
00042 #include <isccfg/namedconf.h>
00043
00044 #include <dns/log.h>
00045 #include <dns/result.h>
00046 #include <dns/view.h>
00047
00048 #include <named/config.h>
00049 #include <named/globals.h>
00050 #include <named/log.h>
00051 #include <named/lwaddr.h>
00052 #include <named/lwresd.h>
00053 #include <named/lwdclient.h>
00054 #include <named/lwsearch.h>
00055 #include <named/server.h>
00056
00057 #define LWRESD_MAGIC ISC_MAGIC('L', 'W', 'R', 'D')
00058 #define VALID_LWRESD(l) ISC_MAGIC_VALID(l, LWRESD_MAGIC)
00059
00060 #define LWRESLISTENER_MAGIC ISC_MAGIC('L', 'W', 'R', 'L')
00061 #define VALID_LWRESLISTENER(l) ISC_MAGIC_VALID(l, LWRESLISTENER_MAGIC)
00062
00063 #define LWRESD_NCLIENTS_MAX 32768
00064
00065 typedef ISC_LIST(ns_lwreslistener_t) ns_lwreslistenerlist_t;
00066
00067 static ns_lwreslistenerlist_t listeners;
00068 static isc_mutex_t listeners_lock;
00069 static isc_once_t once = ISC_ONCE_INIT;
00070
00071
00072 static void
00073 initialize_mutex(void) {
00074 RUNTIME_CHECK(isc_mutex_init(&listeners_lock) == ISC_R_SUCCESS);
00075 }
00076
00077
00078
00079
00080
00081 void *
00082 ns__lwresd_memalloc(void *arg, size_t size) {
00083 return (isc_mem_get(arg, size));
00084 }
00085
00086 void
00087 ns__lwresd_memfree(void *arg, void *mem, size_t size) {
00088 isc_mem_put(arg, mem, size);
00089 }
00090
00091
00092 #define CHECK(op) \
00093 do { result = (op); \
00094 if (result != ISC_R_SUCCESS) goto cleanup; \
00095 } while (0)
00096
00097 static isc_result_t
00098 buffer_putstr(isc_buffer_t *b, const char *s) {
00099 unsigned int len = strlen(s);
00100 if (isc_buffer_availablelength(b) <= len)
00101 return (ISC_R_NOSPACE);
00102 isc_buffer_putmem(b, (const unsigned char *)s, len);
00103 return (ISC_R_SUCCESS);
00104 }
00105
00106
00107
00108
00109 isc_result_t
00110 ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx,
00111 cfg_obj_t **configp)
00112 {
00113 char text[4096];
00114 char str[16];
00115 isc_buffer_t b;
00116 lwres_context_t *lwctx = NULL;
00117 lwres_conf_t *lwc = NULL;
00118 isc_sockaddr_t sa;
00119 isc_netaddr_t na;
00120 int i;
00121 isc_result_t result;
00122 lwres_result_t lwresult;
00123
00124 lwctx = NULL;
00125 lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc,
00126 ns__lwresd_memfree,
00127 LWRES_CONTEXT_SERVERMODE);
00128 if (lwresult != LWRES_R_SUCCESS) {
00129 result = ISC_R_NOMEMORY;
00130 goto cleanup;
00131 }
00132
00133 lwresult = lwres_conf_parse(lwctx, lwresd_g_resolvconffile);
00134 if (lwresult != LWRES_R_SUCCESS) {
00135 result = DNS_R_SYNTAX;
00136 goto cleanup;
00137 }
00138
00139 lwc = lwres_conf_get(lwctx);
00140 INSIST(lwc != NULL);
00141
00142 isc_buffer_init(&b, text, sizeof(text));
00143
00144 CHECK(buffer_putstr(&b, "options {\n"));
00145
00146
00147
00148
00149 if (lwc->nsnext > 0) {
00150 CHECK(buffer_putstr(&b, "\tforwarders {\n"));
00151
00152 for (i = 0; i < lwc->nsnext; i++) {
00153 CHECK(lwaddr_sockaddr_fromlwresaddr(
00154 &sa,
00155 &lwc->nameservers[i],
00156 ns_g_port));
00157 isc_netaddr_fromsockaddr(&na, &sa);
00158 CHECK(buffer_putstr(&b, "\t\t"));
00159 CHECK(isc_netaddr_totext(&na, &b));
00160 CHECK(buffer_putstr(&b, ";\n"));
00161 }
00162 CHECK(buffer_putstr(&b, "\t};\n"));
00163 }
00164
00165
00166
00167
00168 if (lwc->sortlistnxt > 0) {
00169 CHECK(buffer_putstr(&b, "\tsortlist {\n"));
00170 CHECK(buffer_putstr(&b, "\t\t{\n"));
00171 CHECK(buffer_putstr(&b, "\t\t\tany;\n"));
00172 CHECK(buffer_putstr(&b, "\t\t\t{\n"));
00173 for (i = 0; i < lwc->sortlistnxt; i++) {
00174 lwres_addr_t *lwaddr = &lwc->sortlist[i].addr;
00175 lwres_addr_t *lwmask = &lwc->sortlist[i].mask;
00176 unsigned int mask;
00177
00178 CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwmask, 0));
00179 isc_netaddr_fromsockaddr(&na, &sa);
00180 result = isc_netaddr_masktoprefixlen(&na, &mask);
00181 if (result != ISC_R_SUCCESS) {
00182 char addrtext[ISC_NETADDR_FORMATSIZE];
00183 isc_netaddr_format(&na, addrtext,
00184 sizeof(addrtext));
00185 isc_log_write(ns_g_lctx,
00186 NS_LOGCATEGORY_GENERAL,
00187 NS_LOGMODULE_LWRESD,
00188 ISC_LOG_ERROR,
00189 "processing sortlist: '%s' is "
00190 "not a valid netmask",
00191 addrtext);
00192 goto cleanup;
00193 }
00194
00195 CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwaddr, 0));
00196 isc_netaddr_fromsockaddr(&na, &sa);
00197
00198 CHECK(buffer_putstr(&b, "\t\t\t\t"));
00199 CHECK(isc_netaddr_totext(&na, &b));
00200 snprintf(str, sizeof(str), "%u", mask);
00201 CHECK(buffer_putstr(&b, "/"));
00202 CHECK(buffer_putstr(&b, str));
00203 CHECK(buffer_putstr(&b, ";\n"));
00204 }
00205 CHECK(buffer_putstr(&b, "\t\t\t};\n"));
00206 CHECK(buffer_putstr(&b, "\t\t};\n"));
00207 CHECK(buffer_putstr(&b, "\t};\n"));
00208 }
00209
00210 CHECK(buffer_putstr(&b, "};\n\n"));
00211
00212 CHECK(buffer_putstr(&b, "lwres {\n"));
00213
00214
00215
00216
00217 if (lwc->searchnxt > 0) {
00218 if (lwc->searchnxt > 0) {
00219 CHECK(buffer_putstr(&b, "\tsearch {\n"));
00220 for (i = 0; i < lwc->searchnxt; i++) {
00221 CHECK(buffer_putstr(&b, "\t\t\""));
00222 CHECK(buffer_putstr(&b, lwc->search[i]));
00223 CHECK(buffer_putstr(&b, "\";\n"));
00224 }
00225 CHECK(buffer_putstr(&b, "\t};\n"));
00226 }
00227 }
00228
00229
00230
00231
00232 if (lwc->ndots != 1) {
00233 CHECK(buffer_putstr(&b, "\tndots "));
00234 snprintf(str, sizeof(str), "%u", lwc->ndots);
00235 CHECK(buffer_putstr(&b, str));
00236 CHECK(buffer_putstr(&b, ";\n"));
00237 }
00238
00239
00240
00241
00242 if (lwc->lwnext > 0) {
00243 CHECK(buffer_putstr(&b, "\tlisten-on {\n"));
00244
00245 for (i = 0; i < lwc->lwnext; i++) {
00246 CHECK(lwaddr_sockaddr_fromlwresaddr(&sa,
00247 &lwc->lwservers[i],
00248 0));
00249 isc_netaddr_fromsockaddr(&na, &sa);
00250 CHECK(buffer_putstr(&b, "\t\t"));
00251 CHECK(isc_netaddr_totext(&na, &b));
00252 CHECK(buffer_putstr(&b, ";\n"));
00253 }
00254 CHECK(buffer_putstr(&b, "\t};\n"));
00255 }
00256
00257 CHECK(buffer_putstr(&b, "};\n"));
00258
00259 #if 0
00260 printf("%.*s\n",
00261 (int)isc_buffer_usedlength(&b),
00262 (char *)isc_buffer_base(&b));
00263 #endif
00264
00265 lwres_conf_clear(lwctx);
00266 lwres_context_destroy(&lwctx);
00267
00268 return (cfg_parse_buffer(pctx, &b, &cfg_type_namedconf, configp));
00269
00270 cleanup:
00271
00272 if (lwctx != NULL) {
00273 lwres_conf_clear(lwctx);
00274 lwres_context_destroy(&lwctx);
00275 }
00276
00277 return (result);
00278 }
00279
00280
00281
00282
00283
00284 isc_result_t
00285 ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres,
00286 ns_lwresd_t **lwresdp)
00287 {
00288 ns_lwresd_t *lwresd;
00289 const char *vname;
00290 dns_rdataclass_t vclass;
00291 const cfg_obj_t *obj, *viewobj, *searchobj;
00292 const cfg_listelt_t *element;
00293 isc_result_t result;
00294
00295 INSIST(lwresdp != NULL && *lwresdp == NULL);
00296
00297 lwresd = isc_mem_get(mctx, sizeof(ns_lwresd_t));
00298 if (lwresd == NULL)
00299 return (ISC_R_NOMEMORY);
00300
00301 lwresd->mctx = NULL;
00302 isc_mem_attach(mctx, &lwresd->mctx);
00303 lwresd->view = NULL;
00304 lwresd->search = NULL;
00305 lwresd->refs = 1;
00306
00307 obj = NULL;
00308 (void)cfg_map_get(lwres, "ndots", &obj);
00309 if (obj != NULL)
00310 lwresd->ndots = cfg_obj_asuint32(obj);
00311 else
00312 lwresd->ndots = 1;
00313
00314 RUNTIME_CHECK(isc_mutex_init(&lwresd->lock) == ISC_R_SUCCESS);
00315
00316 lwresd->shutting_down = ISC_FALSE;
00317
00318 viewobj = NULL;
00319 (void)cfg_map_get(lwres, "view", &viewobj);
00320 if (viewobj != NULL) {
00321 vname = cfg_obj_asstring(cfg_tuple_get(viewobj, "name"));
00322 obj = cfg_tuple_get(viewobj, "class");
00323 result = ns_config_getclass(obj, dns_rdataclass_in, &vclass);
00324 if (result != ISC_R_SUCCESS)
00325 goto fail;
00326 } else {
00327 vname = "_default";
00328 vclass = dns_rdataclass_in;
00329 }
00330
00331 result = dns_viewlist_find(&ns_g_server->viewlist, vname, vclass,
00332 &lwresd->view);
00333 if (result != ISC_R_SUCCESS) {
00334 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00335 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
00336 "couldn't find view %s", vname);
00337 goto fail;
00338 }
00339
00340 searchobj = NULL;
00341 (void)cfg_map_get(lwres, "search", &searchobj);
00342 if (searchobj != NULL) {
00343 lwresd->search = NULL;
00344 result = ns_lwsearchlist_create(lwresd->mctx,
00345 &lwresd->search);
00346 if (result != ISC_R_SUCCESS) {
00347 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00348 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
00349 "couldn't create searchlist");
00350 goto fail;
00351 }
00352 for (element = cfg_list_first(searchobj);
00353 element != NULL;
00354 element = cfg_list_next(element))
00355 {
00356 const cfg_obj_t *search;
00357 const char *searchstr;
00358 isc_buffer_t namebuf;
00359 dns_fixedname_t fname;
00360 dns_name_t *name;
00361
00362 search = cfg_listelt_value(element);
00363 searchstr = cfg_obj_asstring(search);
00364
00365 dns_fixedname_init(&fname);
00366 name = dns_fixedname_name(&fname);
00367 isc_buffer_constinit(&namebuf, searchstr,
00368 strlen(searchstr));
00369 isc_buffer_add(&namebuf, strlen(searchstr));
00370 result = dns_name_fromtext(name, &namebuf,
00371 dns_rootname, 0, NULL);
00372 if (result != ISC_R_SUCCESS) {
00373 isc_log_write(ns_g_lctx,
00374 NS_LOGCATEGORY_GENERAL,
00375 NS_LOGMODULE_LWRESD,
00376 ISC_LOG_WARNING,
00377 "invalid name %s in searchlist",
00378 searchstr);
00379 continue;
00380 }
00381
00382 result = ns_lwsearchlist_append(lwresd->search, name);
00383 if (result != ISC_R_SUCCESS) {
00384 isc_log_write(ns_g_lctx,
00385 NS_LOGCATEGORY_GENERAL,
00386 NS_LOGMODULE_LWRESD,
00387 ISC_LOG_WARNING,
00388 "couldn't update searchlist");
00389 goto fail;
00390 }
00391 }
00392 }
00393
00394 obj = NULL;
00395 (void)cfg_map_get(lwres, "lwres-tasks", &obj);
00396 if (obj != NULL)
00397 lwresd->ntasks = cfg_obj_asuint32(obj);
00398 else
00399 lwresd->ntasks = ns_g_cpus;
00400
00401 obj = NULL;
00402 (void)cfg_map_get(lwres, "lwres-clients", &obj);
00403 if (obj != NULL) {
00404 lwresd->nclients = cfg_obj_asuint32(obj);
00405 if (lwresd->nclients > LWRESD_NCLIENTS_MAX)
00406 lwresd->nclients = LWRESD_NCLIENTS_MAX;
00407 } else if (ns_g_lwresdonly)
00408 lwresd->nclients = 1024;
00409 else
00410 lwresd->nclients = 256;
00411
00412 lwresd->magic = LWRESD_MAGIC;
00413
00414 *lwresdp = lwresd;
00415 return (ISC_R_SUCCESS);
00416
00417 fail:
00418 if (lwresd->view != NULL)
00419 dns_view_detach(&lwresd->view);
00420 if (lwresd->search != NULL)
00421 ns_lwsearchlist_detach(&lwresd->search);
00422 if (lwresd->mctx != NULL)
00423 isc_mem_detach(&lwresd->mctx);
00424 isc_mem_put(mctx, lwresd, sizeof(ns_lwresd_t));
00425 return (result);
00426 }
00427
00428 void
00429 ns_lwdmanager_attach(ns_lwresd_t *source, ns_lwresd_t **targetp) {
00430 INSIST(VALID_LWRESD(source));
00431 INSIST(targetp != NULL && *targetp == NULL);
00432
00433 LOCK(&source->lock);
00434 source->refs++;
00435 UNLOCK(&source->lock);
00436
00437 *targetp = source;
00438 }
00439
00440 void
00441 ns_lwdmanager_detach(ns_lwresd_t **lwresdp) {
00442 ns_lwresd_t *lwresd;
00443 isc_mem_t *mctx;
00444 isc_boolean_t done = ISC_FALSE;
00445
00446 INSIST(lwresdp != NULL && *lwresdp != NULL);
00447 INSIST(VALID_LWRESD(*lwresdp));
00448
00449 lwresd = *lwresdp;
00450 *lwresdp = NULL;
00451
00452 LOCK(&lwresd->lock);
00453 INSIST(lwresd->refs > 0);
00454 lwresd->refs--;
00455 if (lwresd->refs == 0)
00456 done = ISC_TRUE;
00457 UNLOCK(&lwresd->lock);
00458
00459 if (!done)
00460 return;
00461
00462 dns_view_detach(&lwresd->view);
00463 if (lwresd->search != NULL)
00464 ns_lwsearchlist_detach(&lwresd->search);
00465 mctx = lwresd->mctx;
00466 lwresd->magic = 0;
00467 isc_mem_put(mctx, lwresd, sizeof(*lwresd));
00468 isc_mem_detach(&mctx);
00469 }
00470
00471
00472
00473
00474
00475 void
00476 ns_lwreslistener_attach(ns_lwreslistener_t *source,
00477 ns_lwreslistener_t **targetp)
00478 {
00479 INSIST(VALID_LWRESLISTENER(source));
00480 INSIST(targetp != NULL && *targetp == NULL);
00481
00482 LOCK(&source->lock);
00483 source->refs++;
00484 UNLOCK(&source->lock);
00485
00486 *targetp = source;
00487 }
00488
00489 void
00490 ns_lwreslistener_detach(ns_lwreslistener_t **listenerp) {
00491 ns_lwreslistener_t *listener;
00492 isc_mem_t *mctx;
00493 isc_boolean_t done = ISC_FALSE;
00494
00495 INSIST(listenerp != NULL && *listenerp != NULL);
00496 INSIST(VALID_LWRESLISTENER(*listenerp));
00497
00498 listener = *listenerp;
00499
00500 LOCK(&listener->lock);
00501 INSIST(listener->refs > 0);
00502 listener->refs--;
00503 if (listener->refs == 0)
00504 done = ISC_TRUE;
00505 UNLOCK(&listener->lock);
00506
00507 if (!done)
00508 return;
00509
00510 if (listener->manager != NULL)
00511 ns_lwdmanager_detach(&listener->manager);
00512
00513 if (listener->sock != NULL)
00514 isc_socket_detach(&listener->sock);
00515
00516 listener->magic = 0;
00517 mctx = listener->mctx;
00518 isc_mem_put(mctx, listener, sizeof(*listener));
00519 isc_mem_detach(&mctx);
00520 listenerp = NULL;
00521 }
00522
00523 static isc_result_t
00524 listener_create(isc_mem_t *mctx, ns_lwresd_t *lwresd,
00525 ns_lwreslistener_t **listenerp)
00526 {
00527 ns_lwreslistener_t *listener;
00528 isc_result_t result;
00529
00530 REQUIRE(listenerp != NULL && *listenerp == NULL);
00531
00532 listener = isc_mem_get(mctx, sizeof(ns_lwreslistener_t));
00533 if (listener == NULL)
00534 return (ISC_R_NOMEMORY);
00535
00536 result = isc_mutex_init(&listener->lock);
00537 if (result != ISC_R_SUCCESS) {
00538 isc_mem_put(mctx, listener, sizeof(ns_lwreslistener_t));
00539 return (result);
00540 }
00541
00542 listener->magic = LWRESLISTENER_MAGIC;
00543 listener->refs = 1;
00544
00545 listener->sock = NULL;
00546
00547 listener->manager = NULL;
00548 ns_lwdmanager_attach(lwresd, &listener->manager);
00549
00550 listener->mctx = NULL;
00551 isc_mem_attach(mctx, &listener->mctx);
00552
00553 ISC_LINK_INIT(listener, link);
00554 ISC_LIST_INIT(listener->cmgrs);
00555
00556 *listenerp = listener;
00557 return (ISC_R_SUCCESS);
00558 }
00559
00560 static isc_result_t
00561 listener_bind(ns_lwreslistener_t *listener, isc_sockaddr_t *address) {
00562 isc_socket_t *sock = NULL;
00563 isc_result_t result = ISC_R_SUCCESS;
00564 int pf;
00565
00566 pf = isc_sockaddr_pf(address);
00567 if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
00568 (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
00569 return (ISC_R_FAMILYNOSUPPORT);
00570
00571 listener->address = *address;
00572
00573 if (isc_sockaddr_getport(&listener->address) == 0) {
00574 in_port_t port;
00575 port = lwresd_g_listenport;
00576 if (port == 0)
00577 port = LWRES_UDP_PORT;
00578 isc_sockaddr_setport(&listener->address, port);
00579 }
00580
00581 sock = NULL;
00582 result = isc_socket_create(ns_g_socketmgr, pf,
00583 isc_sockettype_udp, &sock);
00584 if (result != ISC_R_SUCCESS) {
00585 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00586 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
00587 "failed to create lwres socket: %s",
00588 isc_result_totext(result));
00589 return (result);
00590 }
00591
00592 result = isc_socket_bind(sock, &listener->address,
00593 ISC_SOCKET_REUSEADDRESS);
00594 if (result != ISC_R_SUCCESS) {
00595 char socktext[ISC_SOCKADDR_FORMATSIZE];
00596 isc_sockaddr_format(&listener->address, socktext,
00597 sizeof(socktext));
00598 isc_socket_detach(&sock);
00599 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00600 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
00601 "failed to add lwres socket: %s: %s",
00602 socktext, isc_result_totext(result));
00603 return (result);
00604 }
00605 listener->sock = sock;
00606 return (ISC_R_SUCCESS);
00607 }
00608
00609 static void
00610 listener_copysock(ns_lwreslistener_t *oldlistener,
00611 ns_lwreslistener_t *newlistener)
00612 {
00613 newlistener->address = oldlistener->address;
00614 isc_socket_attach(oldlistener->sock, &newlistener->sock);
00615 }
00616
00617 static isc_result_t
00618 listener_startclients(ns_lwreslistener_t *listener) {
00619 ns_lwdclientmgr_t *cm;
00620 unsigned int i;
00621 isc_result_t result = ISC_R_SUCCESS;
00622
00623 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00624 NS_LOGMODULE_LWRESD, ISC_LOG_DEBUG(6),
00625 "listener_startclients: creating %d "
00626 "managers with %d clients each",
00627 listener->manager->ntasks, listener->manager->nclients);
00628
00629
00630
00631
00632 for (i = 0; i < listener->manager->ntasks; i++) {
00633 result = ns_lwdclientmgr_create(listener,
00634 listener->manager->nclients,
00635 ns_g_taskmgr);
00636 if (result != ISC_R_SUCCESS)
00637 break;
00638 }
00639
00640
00641
00642
00643 if (ISC_LIST_EMPTY(listener->cmgrs))
00644 return (result);
00645
00646
00647
00648
00649 LOCK(&listener->lock);
00650 cm = ISC_LIST_HEAD(listener->cmgrs);
00651 while (cm != NULL) {
00652 result = ns_lwdclient_startrecv(cm);
00653 if (result != ISC_R_SUCCESS)
00654 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
00655 NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
00656 "could not start lwres "
00657 "client handler: %s",
00658 isc_result_totext(result));
00659 cm = ISC_LIST_NEXT(cm, link);
00660 }
00661 UNLOCK(&listener->lock);
00662
00663 return (ISC_R_SUCCESS);
00664 }
00665
00666 static void
00667 listener_shutdown(ns_lwreslistener_t *listener) {
00668 ns_lwdclientmgr_t *cm;
00669
00670 cm = ISC_LIST_HEAD(listener->cmgrs);
00671 while (cm != NULL) {
00672 isc_task_shutdown(cm->task);
00673 cm = ISC_LIST_NEXT(cm, link);
00674 }
00675 }
00676
00677 static isc_result_t
00678 find_listener(isc_sockaddr_t *address, ns_lwreslistener_t **listenerp) {
00679 ns_lwreslistener_t *listener;
00680
00681 INSIST(listenerp != NULL && *listenerp == NULL);
00682
00683 for (listener = ISC_LIST_HEAD(listeners);
00684 listener != NULL;
00685 listener = ISC_LIST_NEXT(listener, link))
00686 {
00687 if (!isc_sockaddr_equal(address, &listener->address))
00688 continue;
00689 *listenerp = listener;
00690 return (ISC_R_SUCCESS);
00691 }
00692 return (ISC_R_NOTFOUND);
00693 }
00694
00695 void
00696 ns_lwreslistener_unlinkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm)
00697 {
00698 REQUIRE(VALID_LWRESLISTENER(listener));
00699
00700 LOCK(&listener->lock);
00701 ISC_LIST_UNLINK(listener->cmgrs, cm, link);
00702 UNLOCK(&listener->lock);
00703 }
00704
00705 void
00706 ns_lwreslistener_linkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm) {
00707 REQUIRE(VALID_LWRESLISTENER(listener));
00708
00709
00710
00711
00712
00713 ISC_LIST_APPEND(listener->cmgrs, cm, link);
00714 }
00715
00716 static isc_result_t
00717 configure_listener(isc_sockaddr_t *address, ns_lwresd_t *lwresd,
00718 isc_mem_t *mctx, ns_lwreslistenerlist_t *newlisteners)
00719 {
00720 ns_lwreslistener_t *listener, *oldlistener = NULL;
00721 char socktext[ISC_SOCKADDR_FORMATSIZE];
00722 isc_result_t result;
00723
00724 (void)find_listener(address, &oldlistener);
00725 listener = NULL;
00726 result = listener_create(mctx, lwresd, &listener);
00727 if (result != ISC_R_SUCCESS) {
00728 isc_sockaddr_format(address, socktext, sizeof(socktext));
00729 isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
00730 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
00731 "lwres failed to configure %s: %s",
00732 socktext, isc_result_totext(result));
00733 return (result);
00734 }
00735
00736
00737
00738
00739 if (oldlistener == NULL) {
00740 result = listener_bind(listener, address);
00741 if (result != ISC_R_SUCCESS) {
00742 ns_lwreslistener_detach(&listener);
00743 return (ISC_R_SUCCESS);
00744 }
00745 } else
00746 listener_copysock(oldlistener, listener);
00747
00748 result = listener_startclients(listener);
00749 if (result != ISC_R_SUCCESS) {
00750 isc_sockaddr_format(address, socktext, sizeof(socktext));
00751 isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
00752 NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
00753 "lwres: failed to start %s: %s", socktext,
00754 isc_result_totext(result));
00755 ns_lwreslistener_detach(&listener);
00756 return (ISC_R_SUCCESS);
00757 }
00758
00759 if (oldlistener != NULL) {
00760
00761
00762
00763 ISC_LIST_UNLINK(listeners, oldlistener, link);
00764 listener_shutdown(oldlistener);
00765 ns_lwreslistener_detach(&oldlistener);
00766 } else {
00767 isc_sockaddr_format(address, socktext, sizeof(socktext));
00768 isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
00769 NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
00770 "lwres listening on %s", socktext);
00771 }
00772
00773 ISC_LIST_APPEND(*newlisteners, listener, link);
00774 return (result);
00775 }
00776
00777 isc_result_t
00778 ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) {
00779 const cfg_obj_t *lwreslist = NULL;
00780 const cfg_obj_t *lwres = NULL;
00781 const cfg_obj_t *listenerslist = NULL;
00782 const cfg_listelt_t *element = NULL;
00783 ns_lwreslistener_t *listener;
00784 ns_lwreslistenerlist_t newlisteners;
00785 isc_result_t result;
00786 char socktext[ISC_SOCKADDR_FORMATSIZE];
00787 isc_sockaddr_t *addrs = NULL;
00788 ns_lwresd_t *lwresd = NULL;
00789 isc_uint32_t count = 0;
00790
00791 REQUIRE(mctx != NULL);
00792 REQUIRE(config != NULL);
00793
00794 RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
00795
00796 ISC_LIST_INIT(newlisteners);
00797
00798 result = cfg_map_get(config, "lwres", &lwreslist);
00799 if (result != ISC_R_SUCCESS)
00800 return (ISC_R_SUCCESS);
00801
00802 LOCK(&listeners_lock);
00803
00804
00805
00806
00807
00808
00809
00810
00811 for (element = cfg_list_first(lwreslist);
00812 element != NULL;
00813 element = cfg_list_next(element))
00814 {
00815 in_port_t port;
00816
00817 lwres = cfg_listelt_value(element);
00818 CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd));
00819
00820 port = lwresd_g_listenport;
00821 if (port == 0)
00822 port = LWRES_UDP_PORT;
00823
00824 listenerslist = NULL;
00825 (void)cfg_map_get(lwres, "listen-on", &listenerslist);
00826 if (listenerslist == NULL) {
00827 struct in_addr localhost;
00828 isc_sockaddr_t address;
00829
00830 localhost.s_addr = htonl(INADDR_LOOPBACK);
00831 isc_sockaddr_fromin(&address, &localhost, port);
00832 CHECK(configure_listener(&address, lwresd, mctx,
00833 &newlisteners));
00834 } else {
00835 isc_uint32_t i;
00836
00837 CHECK(ns_config_getiplist(config, listenerslist,
00838 port, mctx, &addrs, NULL,
00839 &count));
00840 for (i = 0; i < count; i++)
00841 CHECK(configure_listener(&addrs[i], lwresd,
00842 mctx, &newlisteners));
00843 ns_config_putiplist(mctx, &addrs, NULL, count);
00844 }
00845 ns_lwdmanager_detach(&lwresd);
00846 }
00847
00848
00849
00850
00851
00852
00853 while (!ISC_LIST_EMPTY(listeners)) {
00854 listener = ISC_LIST_HEAD(listeners);
00855 ISC_LIST_UNLINK(listeners, listener, link);
00856
00857 isc_sockaddr_format(&listener->address,
00858 socktext, sizeof(socktext));
00859
00860 listener_shutdown(listener);
00861 ns_lwreslistener_detach(&listener);
00862
00863 isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
00864 NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
00865 "lwres no longer listening on %s", socktext);
00866 }
00867
00868 cleanup:
00869 ISC_LIST_APPENDLIST(listeners, newlisteners, link);
00870
00871 if (addrs != NULL)
00872 ns_config_putiplist(mctx, &addrs, NULL, count);
00873
00874 if (lwresd != NULL)
00875 ns_lwdmanager_detach(&lwresd);
00876
00877 UNLOCK(&listeners_lock);
00878
00879 return (result);
00880 }
00881
00882 void
00883 ns_lwresd_shutdown(void) {
00884 ns_lwreslistener_t *listener;
00885
00886 RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
00887
00888 while (!ISC_LIST_EMPTY(listeners)) {
00889 listener = ISC_LIST_HEAD(listeners);
00890 ISC_LIST_UNLINK(listeners, listener, link);
00891 ns_lwreslistener_detach(&listener);
00892 }
00893 }