/contrib/bind9/bin/named/lwresd.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 869 lines · 639 code · 145 blank · 85 comment · 149 complexity · 3c669f7465d2206e3b7bd5de3be549bb MD5 · raw file

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