/contrib/bind9/bin/named/controlconf.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1455 lines · 1118 code · 202 blank · 135 comment · 310 complexity · 779573abca444913f570da32a59aa143 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-2008, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 2001-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: controlconf.c,v 1.60.544.3 2011/12/22 08:10:09 marka Exp $ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <isc/base64.h>
  21. #include <isc/buffer.h>
  22. #include <isc/event.h>
  23. #include <isc/mem.h>
  24. #include <isc/net.h>
  25. #include <isc/netaddr.h>
  26. #include <isc/random.h>
  27. #include <isc/result.h>
  28. #include <isc/stdtime.h>
  29. #include <isc/string.h>
  30. #include <isc/timer.h>
  31. #include <isc/util.h>
  32. #include <isccfg/namedconf.h>
  33. #include <bind9/check.h>
  34. #include <isccc/alist.h>
  35. #include <isccc/cc.h>
  36. #include <isccc/ccmsg.h>
  37. #include <isccc/events.h>
  38. #include <isccc/result.h>
  39. #include <isccc/sexpr.h>
  40. #include <isccc/symtab.h>
  41. #include <isccc/util.h>
  42. #include <dns/result.h>
  43. #include <named/config.h>
  44. #include <named/control.h>
  45. #include <named/log.h>
  46. #include <named/server.h>
  47. /*
  48. * Note: Listeners and connections are not locked. All event handlers are
  49. * executed by the server task, and all callers of exported routines must
  50. * be running under the server task.
  51. */
  52. typedef struct controlkey controlkey_t;
  53. typedef ISC_LIST(controlkey_t) controlkeylist_t;
  54. typedef struct controlconnection controlconnection_t;
  55. typedef ISC_LIST(controlconnection_t) controlconnectionlist_t;
  56. typedef struct controllistener controllistener_t;
  57. typedef ISC_LIST(controllistener_t) controllistenerlist_t;
  58. struct controlkey {
  59. char * keyname;
  60. isc_region_t secret;
  61. ISC_LINK(controlkey_t) link;
  62. };
  63. struct controlconnection {
  64. isc_socket_t * sock;
  65. isccc_ccmsg_t ccmsg;
  66. isc_boolean_t ccmsg_valid;
  67. isc_boolean_t sending;
  68. isc_timer_t * timer;
  69. unsigned char buffer[2048];
  70. controllistener_t * listener;
  71. isc_uint32_t nonce;
  72. ISC_LINK(controlconnection_t) link;
  73. };
  74. struct controllistener {
  75. ns_controls_t * controls;
  76. isc_mem_t * mctx;
  77. isc_task_t * task;
  78. isc_sockaddr_t address;
  79. isc_socket_t * sock;
  80. dns_acl_t * acl;
  81. isc_boolean_t listening;
  82. isc_boolean_t exiting;
  83. controlkeylist_t keys;
  84. controlconnectionlist_t connections;
  85. isc_sockettype_t type;
  86. isc_uint32_t perm;
  87. isc_uint32_t owner;
  88. isc_uint32_t group;
  89. ISC_LINK(controllistener_t) link;
  90. };
  91. struct ns_controls {
  92. ns_server_t *server;
  93. controllistenerlist_t listeners;
  94. isc_boolean_t shuttingdown;
  95. isccc_symtab_t *symtab;
  96. };
  97. static void control_newconn(isc_task_t *task, isc_event_t *event);
  98. static void control_recvmessage(isc_task_t *task, isc_event_t *event);
  99. #define CLOCKSKEW 300
  100. static void
  101. free_controlkey(controlkey_t *key, isc_mem_t *mctx) {
  102. if (key->keyname != NULL)
  103. isc_mem_free(mctx, key->keyname);
  104. if (key->secret.base != NULL)
  105. isc_mem_put(mctx, key->secret.base, key->secret.length);
  106. isc_mem_put(mctx, key, sizeof(*key));
  107. }
  108. static void
  109. free_controlkeylist(controlkeylist_t *keylist, isc_mem_t *mctx) {
  110. while (!ISC_LIST_EMPTY(*keylist)) {
  111. controlkey_t *key = ISC_LIST_HEAD(*keylist);
  112. ISC_LIST_UNLINK(*keylist, key, link);
  113. free_controlkey(key, mctx);
  114. }
  115. }
  116. static void
  117. free_listener(controllistener_t *listener) {
  118. INSIST(listener->exiting);
  119. INSIST(!listener->listening);
  120. INSIST(ISC_LIST_EMPTY(listener->connections));
  121. if (listener->sock != NULL)
  122. isc_socket_detach(&listener->sock);
  123. free_controlkeylist(&listener->keys, listener->mctx);
  124. if (listener->acl != NULL)
  125. dns_acl_detach(&listener->acl);
  126. isc_mem_put(listener->mctx, listener, sizeof(*listener));
  127. }
  128. static void
  129. maybe_free_listener(controllistener_t *listener) {
  130. if (listener->exiting &&
  131. !listener->listening &&
  132. ISC_LIST_EMPTY(listener->connections))
  133. free_listener(listener);
  134. }
  135. static void
  136. maybe_free_connection(controlconnection_t *conn) {
  137. controllistener_t *listener = conn->listener;
  138. if (conn->timer != NULL)
  139. isc_timer_detach(&conn->timer);
  140. if (conn->ccmsg_valid) {
  141. isccc_ccmsg_cancelread(&conn->ccmsg);
  142. return;
  143. }
  144. if (conn->sending) {
  145. isc_socket_cancel(conn->sock, listener->task,
  146. ISC_SOCKCANCEL_SEND);
  147. return;
  148. }
  149. ISC_LIST_UNLINK(listener->connections, conn, link);
  150. isc_mem_put(listener->mctx, conn, sizeof(*conn));
  151. }
  152. static void
  153. shutdown_listener(controllistener_t *listener) {
  154. controlconnection_t *conn;
  155. controlconnection_t *next;
  156. if (!listener->exiting) {
  157. char socktext[ISC_SOCKADDR_FORMATSIZE];
  158. ISC_LIST_UNLINK(listener->controls->listeners, listener, link);
  159. isc_sockaddr_format(&listener->address, socktext,
  160. sizeof(socktext));
  161. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  162. NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
  163. "stopping command channel on %s", socktext);
  164. if (listener->type == isc_sockettype_unix)
  165. isc_socket_cleanunix(&listener->address, ISC_TRUE);
  166. listener->exiting = ISC_TRUE;
  167. }
  168. for (conn = ISC_LIST_HEAD(listener->connections);
  169. conn != NULL;
  170. conn = next)
  171. {
  172. next = ISC_LIST_NEXT(conn, link);
  173. maybe_free_connection(conn);
  174. }
  175. if (listener->listening)
  176. isc_socket_cancel(listener->sock, listener->task,
  177. ISC_SOCKCANCEL_ACCEPT);
  178. maybe_free_listener(listener);
  179. }
  180. static isc_boolean_t
  181. address_ok(isc_sockaddr_t *sockaddr, dns_acl_t *acl) {
  182. isc_netaddr_t netaddr;
  183. isc_result_t result;
  184. int match;
  185. isc_netaddr_fromsockaddr(&netaddr, sockaddr);
  186. result = dns_acl_match(&netaddr, NULL, acl,
  187. &ns_g_server->aclenv, &match, NULL);
  188. if (result != ISC_R_SUCCESS || match <= 0)
  189. return (ISC_FALSE);
  190. else
  191. return (ISC_TRUE);
  192. }
  193. static isc_result_t
  194. control_accept(controllistener_t *listener) {
  195. isc_result_t result;
  196. result = isc_socket_accept(listener->sock,
  197. listener->task,
  198. control_newconn, listener);
  199. if (result != ISC_R_SUCCESS)
  200. UNEXPECTED_ERROR(__FILE__, __LINE__,
  201. "isc_socket_accept() failed: %s",
  202. isc_result_totext(result));
  203. else
  204. listener->listening = ISC_TRUE;
  205. return (result);
  206. }
  207. static isc_result_t
  208. control_listen(controllistener_t *listener) {
  209. isc_result_t result;
  210. result = isc_socket_listen(listener->sock, 0);
  211. if (result != ISC_R_SUCCESS)
  212. UNEXPECTED_ERROR(__FILE__, __LINE__,
  213. "isc_socket_listen() failed: %s",
  214. isc_result_totext(result));
  215. return (result);
  216. }
  217. static void
  218. control_next(controllistener_t *listener) {
  219. (void)control_accept(listener);
  220. }
  221. static void
  222. control_senddone(isc_task_t *task, isc_event_t *event) {
  223. isc_socketevent_t *sevent = (isc_socketevent_t *) event;
  224. controlconnection_t *conn = event->ev_arg;
  225. controllistener_t *listener = conn->listener;
  226. isc_socket_t *sock = (isc_socket_t *)sevent->ev_sender;
  227. isc_result_t result;
  228. REQUIRE(conn->sending);
  229. UNUSED(task);
  230. conn->sending = ISC_FALSE;
  231. if (sevent->result != ISC_R_SUCCESS &&
  232. sevent->result != ISC_R_CANCELED)
  233. {
  234. char socktext[ISC_SOCKADDR_FORMATSIZE];
  235. isc_sockaddr_t peeraddr;
  236. (void)isc_socket_getpeername(sock, &peeraddr);
  237. isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
  238. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  239. NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
  240. "error sending command response to %s: %s",
  241. socktext, isc_result_totext(sevent->result));
  242. }
  243. isc_event_free(&event);
  244. result = isccc_ccmsg_readmessage(&conn->ccmsg, listener->task,
  245. control_recvmessage, conn);
  246. if (result != ISC_R_SUCCESS) {
  247. isc_socket_detach(&conn->sock);
  248. maybe_free_connection(conn);
  249. maybe_free_listener(listener);
  250. }
  251. }
  252. static inline void
  253. log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) {
  254. char socktext[ISC_SOCKADDR_FORMATSIZE];
  255. isc_sockaddr_t peeraddr;
  256. (void)isc_socket_getpeername(ccmsg->sock, &peeraddr);
  257. isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
  258. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  259. NS_LOGMODULE_CONTROL, ISC_LOG_ERROR,
  260. "invalid command from %s: %s",
  261. socktext, isc_result_totext(result));
  262. }
  263. static void
  264. control_recvmessage(isc_task_t *task, isc_event_t *event) {
  265. controlconnection_t *conn;
  266. controllistener_t *listener;
  267. controlkey_t *key;
  268. isccc_sexpr_t *request = NULL;
  269. isccc_sexpr_t *response = NULL;
  270. isccc_region_t ccregion;
  271. isccc_region_t secret;
  272. isc_stdtime_t now;
  273. isc_buffer_t b;
  274. isc_region_t r;
  275. isc_uint32_t len;
  276. isc_buffer_t text;
  277. char textarray[1024];
  278. isc_result_t result;
  279. isc_result_t eresult;
  280. isccc_sexpr_t *_ctrl;
  281. isccc_time_t sent;
  282. isccc_time_t exp;
  283. isc_uint32_t nonce;
  284. REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG);
  285. conn = event->ev_arg;
  286. listener = conn->listener;
  287. secret.rstart = NULL;
  288. /* Is the server shutting down? */
  289. if (listener->controls->shuttingdown)
  290. goto cleanup;
  291. if (conn->ccmsg.result != ISC_R_SUCCESS) {
  292. if (conn->ccmsg.result != ISC_R_CANCELED &&
  293. conn->ccmsg.result != ISC_R_EOF)
  294. log_invalid(&conn->ccmsg, conn->ccmsg.result);
  295. goto cleanup;
  296. }
  297. request = NULL;
  298. for (key = ISC_LIST_HEAD(listener->keys);
  299. key != NULL;
  300. key = ISC_LIST_NEXT(key, link))
  301. {
  302. ccregion.rstart = isc_buffer_base(&conn->ccmsg.buffer);
  303. ccregion.rend = isc_buffer_used(&conn->ccmsg.buffer);
  304. secret.rstart = isc_mem_get(listener->mctx, key->secret.length);
  305. if (secret.rstart == NULL)
  306. goto cleanup;
  307. memcpy(secret.rstart, key->secret.base, key->secret.length);
  308. secret.rend = secret.rstart + key->secret.length;
  309. result = isccc_cc_fromwire(&ccregion, &request, &secret);
  310. if (result == ISC_R_SUCCESS)
  311. break;
  312. isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
  313. log_invalid(&conn->ccmsg, result);
  314. goto cleanup;
  315. }
  316. if (key == NULL) {
  317. log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
  318. goto cleanup;
  319. }
  320. /* We shouldn't be getting a reply. */
  321. if (isccc_cc_isreply(request)) {
  322. log_invalid(&conn->ccmsg, ISC_R_FAILURE);
  323. goto cleanup_request;
  324. }
  325. isc_stdtime_get(&now);
  326. /*
  327. * Limit exposure to replay attacks.
  328. */
  329. _ctrl = isccc_alist_lookup(request, "_ctrl");
  330. if (_ctrl == NULL) {
  331. log_invalid(&conn->ccmsg, ISC_R_FAILURE);
  332. goto cleanup_request;
  333. }
  334. if (isccc_cc_lookupuint32(_ctrl, "_tim", &sent) == ISC_R_SUCCESS) {
  335. if ((sent + CLOCKSKEW) < now || (sent - CLOCKSKEW) > now) {
  336. log_invalid(&conn->ccmsg, ISCCC_R_CLOCKSKEW);
  337. goto cleanup_request;
  338. }
  339. } else {
  340. log_invalid(&conn->ccmsg, ISC_R_FAILURE);
  341. goto cleanup_request;
  342. }
  343. /*
  344. * Expire messages that are too old.
  345. */
  346. if (isccc_cc_lookupuint32(_ctrl, "_exp", &exp) == ISC_R_SUCCESS &&
  347. now > exp) {
  348. log_invalid(&conn->ccmsg, ISCCC_R_EXPIRED);
  349. goto cleanup_request;
  350. }
  351. /*
  352. * Duplicate suppression (required for UDP).
  353. */
  354. isccc_cc_cleansymtab(listener->controls->symtab, now);
  355. result = isccc_cc_checkdup(listener->controls->symtab, request, now);
  356. if (result != ISC_R_SUCCESS) {
  357. if (result == ISC_R_EXISTS)
  358. result = ISCCC_R_DUPLICATE;
  359. log_invalid(&conn->ccmsg, result);
  360. goto cleanup_request;
  361. }
  362. if (conn->nonce != 0 &&
  363. (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS ||
  364. conn->nonce != nonce)) {
  365. log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
  366. goto cleanup_request;
  367. }
  368. /*
  369. * Establish nonce.
  370. */
  371. while (conn->nonce == 0)
  372. isc_random_get(&conn->nonce);
  373. isc_buffer_init(&text, textarray, sizeof(textarray));
  374. eresult = ns_control_docommand(request, &text);
  375. result = isccc_cc_createresponse(request, now, now + 60, &response);
  376. if (result != ISC_R_SUCCESS)
  377. goto cleanup_request;
  378. if (eresult != ISC_R_SUCCESS) {
  379. isccc_sexpr_t *data;
  380. data = isccc_alist_lookup(response, "_data");
  381. if (data != NULL) {
  382. const char *estr = isc_result_totext(eresult);
  383. if (isccc_cc_definestring(data, "err", estr) == NULL)
  384. goto cleanup_response;
  385. }
  386. }
  387. if (isc_buffer_usedlength(&text) > 0) {
  388. isccc_sexpr_t *data;
  389. data = isccc_alist_lookup(response, "_data");
  390. if (data != NULL) {
  391. char *str = (char *)isc_buffer_base(&text);
  392. if (isccc_cc_definestring(data, "text", str) == NULL)
  393. goto cleanup_response;
  394. }
  395. }
  396. _ctrl = isccc_alist_lookup(response, "_ctrl");
  397. if (_ctrl == NULL ||
  398. isccc_cc_defineuint32(_ctrl, "_nonce", conn->nonce) == NULL)
  399. goto cleanup_response;
  400. ccregion.rstart = conn->buffer + 4;
  401. ccregion.rend = conn->buffer + sizeof(conn->buffer);
  402. result = isccc_cc_towire(response, &ccregion, &secret);
  403. if (result != ISC_R_SUCCESS)
  404. goto cleanup_response;
  405. isc_buffer_init(&b, conn->buffer, 4);
  406. len = sizeof(conn->buffer) - REGION_SIZE(ccregion);
  407. isc_buffer_putuint32(&b, len - 4);
  408. r.base = conn->buffer;
  409. r.length = len;
  410. result = isc_socket_send(conn->sock, &r, task, control_senddone, conn);
  411. if (result != ISC_R_SUCCESS)
  412. goto cleanup_response;
  413. conn->sending = ISC_TRUE;
  414. isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
  415. isccc_sexpr_free(&request);
  416. isccc_sexpr_free(&response);
  417. return;
  418. cleanup_response:
  419. isccc_sexpr_free(&response);
  420. cleanup_request:
  421. isccc_sexpr_free(&request);
  422. isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
  423. cleanup:
  424. isc_socket_detach(&conn->sock);
  425. isccc_ccmsg_invalidate(&conn->ccmsg);
  426. conn->ccmsg_valid = ISC_FALSE;
  427. maybe_free_connection(conn);
  428. maybe_free_listener(listener);
  429. }
  430. static void
  431. control_timeout(isc_task_t *task, isc_event_t *event) {
  432. controlconnection_t *conn = event->ev_arg;
  433. UNUSED(task);
  434. isc_timer_detach(&conn->timer);
  435. maybe_free_connection(conn);
  436. isc_event_free(&event);
  437. }
  438. static isc_result_t
  439. newconnection(controllistener_t *listener, isc_socket_t *sock) {
  440. controlconnection_t *conn;
  441. isc_interval_t interval;
  442. isc_result_t result;
  443. conn = isc_mem_get(listener->mctx, sizeof(*conn));
  444. if (conn == NULL)
  445. return (ISC_R_NOMEMORY);
  446. conn->sock = sock;
  447. isccc_ccmsg_init(listener->mctx, sock, &conn->ccmsg);
  448. conn->ccmsg_valid = ISC_TRUE;
  449. conn->sending = ISC_FALSE;
  450. conn->timer = NULL;
  451. isc_interval_set(&interval, 60, 0);
  452. result = isc_timer_create(ns_g_timermgr, isc_timertype_once,
  453. NULL, &interval, listener->task,
  454. control_timeout, conn, &conn->timer);
  455. if (result != ISC_R_SUCCESS)
  456. goto cleanup;
  457. conn->listener = listener;
  458. conn->nonce = 0;
  459. ISC_LINK_INIT(conn, link);
  460. result = isccc_ccmsg_readmessage(&conn->ccmsg, listener->task,
  461. control_recvmessage, conn);
  462. if (result != ISC_R_SUCCESS)
  463. goto cleanup;
  464. isccc_ccmsg_setmaxsize(&conn->ccmsg, 2048);
  465. ISC_LIST_APPEND(listener->connections, conn, link);
  466. return (ISC_R_SUCCESS);
  467. cleanup:
  468. isccc_ccmsg_invalidate(&conn->ccmsg);
  469. if (conn->timer != NULL)
  470. isc_timer_detach(&conn->timer);
  471. isc_mem_put(listener->mctx, conn, sizeof(*conn));
  472. return (result);
  473. }
  474. static void
  475. control_newconn(isc_task_t *task, isc_event_t *event) {
  476. isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
  477. controllistener_t *listener = event->ev_arg;
  478. isc_socket_t *sock;
  479. isc_sockaddr_t peeraddr;
  480. isc_result_t result;
  481. UNUSED(task);
  482. listener->listening = ISC_FALSE;
  483. if (nevent->result != ISC_R_SUCCESS) {
  484. if (nevent->result == ISC_R_CANCELED) {
  485. shutdown_listener(listener);
  486. goto cleanup;
  487. }
  488. goto restart;
  489. }
  490. sock = nevent->newsocket;
  491. isc_socket_setname(sock, "control", NULL);
  492. (void)isc_socket_getpeername(sock, &peeraddr);
  493. if (listener->type == isc_sockettype_tcp &&
  494. !address_ok(&peeraddr, listener->acl)) {
  495. char socktext[ISC_SOCKADDR_FORMATSIZE];
  496. isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
  497. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  498. NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
  499. "rejected command channel message from %s",
  500. socktext);
  501. isc_socket_detach(&sock);
  502. goto restart;
  503. }
  504. result = newconnection(listener, sock);
  505. if (result != ISC_R_SUCCESS) {
  506. char socktext[ISC_SOCKADDR_FORMATSIZE];
  507. isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
  508. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  509. NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
  510. "dropped command channel from %s: %s",
  511. socktext, isc_result_totext(result));
  512. isc_socket_detach(&sock);
  513. goto restart;
  514. }
  515. restart:
  516. control_next(listener);
  517. cleanup:
  518. isc_event_free(&event);
  519. }
  520. static void
  521. controls_shutdown(ns_controls_t *controls) {
  522. controllistener_t *listener;
  523. controllistener_t *next;
  524. for (listener = ISC_LIST_HEAD(controls->listeners);
  525. listener != NULL;
  526. listener = next)
  527. {
  528. /*
  529. * This is asynchronous. As listeners shut down, they will
  530. * call their callbacks.
  531. */
  532. next = ISC_LIST_NEXT(listener, link);
  533. shutdown_listener(listener);
  534. }
  535. }
  536. void
  537. ns_controls_shutdown(ns_controls_t *controls) {
  538. controls_shutdown(controls);
  539. controls->shuttingdown = ISC_TRUE;
  540. }
  541. static isc_result_t
  542. cfgkeylist_find(const cfg_obj_t *keylist, const char *keyname,
  543. const cfg_obj_t **objp)
  544. {
  545. const cfg_listelt_t *element;
  546. const char *str;
  547. const cfg_obj_t *obj;
  548. for (element = cfg_list_first(keylist);
  549. element != NULL;
  550. element = cfg_list_next(element))
  551. {
  552. obj = cfg_listelt_value(element);
  553. str = cfg_obj_asstring(cfg_map_getname(obj));
  554. if (strcasecmp(str, keyname) == 0)
  555. break;
  556. }
  557. if (element == NULL)
  558. return (ISC_R_NOTFOUND);
  559. obj = cfg_listelt_value(element);
  560. *objp = obj;
  561. return (ISC_R_SUCCESS);
  562. }
  563. static isc_result_t
  564. controlkeylist_fromcfg(const cfg_obj_t *keylist, isc_mem_t *mctx,
  565. controlkeylist_t *keyids)
  566. {
  567. const cfg_listelt_t *element;
  568. char *newstr = NULL;
  569. const char *str;
  570. const cfg_obj_t *obj;
  571. controlkey_t *key;
  572. for (element = cfg_list_first(keylist);
  573. element != NULL;
  574. element = cfg_list_next(element))
  575. {
  576. obj = cfg_listelt_value(element);
  577. str = cfg_obj_asstring(obj);
  578. newstr = isc_mem_strdup(mctx, str);
  579. if (newstr == NULL)
  580. goto cleanup;
  581. key = isc_mem_get(mctx, sizeof(*key));
  582. if (key == NULL)
  583. goto cleanup;
  584. key->keyname = newstr;
  585. key->secret.base = NULL;
  586. key->secret.length = 0;
  587. ISC_LINK_INIT(key, link);
  588. ISC_LIST_APPEND(*keyids, key, link);
  589. newstr = NULL;
  590. }
  591. return (ISC_R_SUCCESS);
  592. cleanup:
  593. if (newstr != NULL)
  594. isc_mem_free(mctx, newstr);
  595. free_controlkeylist(keyids, mctx);
  596. return (ISC_R_NOMEMORY);
  597. }
  598. static void
  599. register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist,
  600. controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext)
  601. {
  602. controlkey_t *keyid, *next;
  603. const cfg_obj_t *keydef;
  604. char secret[1024];
  605. isc_buffer_t b;
  606. isc_result_t result;
  607. /*
  608. * Find the keys corresponding to the keyids used by this listener.
  609. */
  610. for (keyid = ISC_LIST_HEAD(*keyids); keyid != NULL; keyid = next) {
  611. next = ISC_LIST_NEXT(keyid, link);
  612. result = cfgkeylist_find(keylist, keyid->keyname, &keydef);
  613. if (result != ISC_R_SUCCESS) {
  614. cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
  615. "couldn't find key '%s' for use with "
  616. "command channel %s",
  617. keyid->keyname, socktext);
  618. ISC_LIST_UNLINK(*keyids, keyid, link);
  619. free_controlkey(keyid, mctx);
  620. } else {
  621. const cfg_obj_t *algobj = NULL;
  622. const cfg_obj_t *secretobj = NULL;
  623. const char *algstr = NULL;
  624. const char *secretstr = NULL;
  625. (void)cfg_map_get(keydef, "algorithm", &algobj);
  626. (void)cfg_map_get(keydef, "secret", &secretobj);
  627. INSIST(algobj != NULL && secretobj != NULL);
  628. algstr = cfg_obj_asstring(algobj);
  629. secretstr = cfg_obj_asstring(secretobj);
  630. if (ns_config_getkeyalgorithm(algstr, NULL, NULL) !=
  631. ISC_R_SUCCESS)
  632. {
  633. cfg_obj_log(control, ns_g_lctx,
  634. ISC_LOG_WARNING,
  635. "unsupported algorithm '%s' in "
  636. "key '%s' for use with command "
  637. "channel %s",
  638. algstr, keyid->keyname, socktext);
  639. ISC_LIST_UNLINK(*keyids, keyid, link);
  640. free_controlkey(keyid, mctx);
  641. continue;
  642. }
  643. isc_buffer_init(&b, secret, sizeof(secret));
  644. result = isc_base64_decodestring(secretstr, &b);
  645. if (result != ISC_R_SUCCESS) {
  646. cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
  647. "secret for key '%s' on "
  648. "command channel %s: %s",
  649. keyid->keyname, socktext,
  650. isc_result_totext(result));
  651. ISC_LIST_UNLINK(*keyids, keyid, link);
  652. free_controlkey(keyid, mctx);
  653. continue;
  654. }
  655. keyid->secret.length = isc_buffer_usedlength(&b);
  656. keyid->secret.base = isc_mem_get(mctx,
  657. keyid->secret.length);
  658. if (keyid->secret.base == NULL) {
  659. cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
  660. "couldn't register key '%s': "
  661. "out of memory", keyid->keyname);
  662. ISC_LIST_UNLINK(*keyids, keyid, link);
  663. free_controlkey(keyid, mctx);
  664. break;
  665. }
  666. memcpy(keyid->secret.base, isc_buffer_base(&b),
  667. keyid->secret.length);
  668. }
  669. }
  670. }
  671. #define CHECK(x) \
  672. do { \
  673. result = (x); \
  674. if (result != ISC_R_SUCCESS) \
  675. goto cleanup; \
  676. } while (0)
  677. static isc_result_t
  678. get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) {
  679. isc_result_t result;
  680. cfg_parser_t *pctx = NULL;
  681. cfg_obj_t *config = NULL;
  682. const cfg_obj_t *key = NULL;
  683. const cfg_obj_t *algobj = NULL;
  684. const cfg_obj_t *secretobj = NULL;
  685. const char *algstr = NULL;
  686. const char *secretstr = NULL;
  687. controlkey_t *keyid = NULL;
  688. char secret[1024];
  689. isc_buffer_t b;
  690. CHECK(cfg_parser_create(mctx, ns_g_lctx, &pctx));
  691. CHECK(cfg_parse_file(pctx, ns_g_keyfile, &cfg_type_rndckey, &config));
  692. CHECK(cfg_map_get(config, "key", &key));
  693. keyid = isc_mem_get(mctx, sizeof(*keyid));
  694. if (keyid == NULL)
  695. CHECK(ISC_R_NOMEMORY);
  696. keyid->keyname = isc_mem_strdup(mctx,
  697. cfg_obj_asstring(cfg_map_getname(key)));
  698. keyid->secret.base = NULL;
  699. keyid->secret.length = 0;
  700. ISC_LINK_INIT(keyid, link);
  701. if (keyid->keyname == NULL)
  702. CHECK(ISC_R_NOMEMORY);
  703. CHECK(bind9_check_key(key, ns_g_lctx));
  704. (void)cfg_map_get(key, "algorithm", &algobj);
  705. (void)cfg_map_get(key, "secret", &secretobj);
  706. INSIST(algobj != NULL && secretobj != NULL);
  707. algstr = cfg_obj_asstring(algobj);
  708. secretstr = cfg_obj_asstring(secretobj);
  709. if (ns_config_getkeyalgorithm(algstr, NULL, NULL) != ISC_R_SUCCESS) {
  710. cfg_obj_log(key, ns_g_lctx,
  711. ISC_LOG_WARNING,
  712. "unsupported algorithm '%s' in "
  713. "key '%s' for use with command "
  714. "channel",
  715. algstr, keyid->keyname);
  716. goto cleanup;
  717. }
  718. isc_buffer_init(&b, secret, sizeof(secret));
  719. result = isc_base64_decodestring(secretstr, &b);
  720. if (result != ISC_R_SUCCESS) {
  721. cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
  722. "secret for key '%s' on command channel: %s",
  723. keyid->keyname, isc_result_totext(result));
  724. goto cleanup;
  725. }
  726. keyid->secret.length = isc_buffer_usedlength(&b);
  727. keyid->secret.base = isc_mem_get(mctx,
  728. keyid->secret.length);
  729. if (keyid->secret.base == NULL) {
  730. cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
  731. "couldn't register key '%s': "
  732. "out of memory", keyid->keyname);
  733. CHECK(ISC_R_NOMEMORY);
  734. }
  735. memcpy(keyid->secret.base, isc_buffer_base(&b),
  736. keyid->secret.length);
  737. ISC_LIST_APPEND(*keyids, keyid, link);
  738. keyid = NULL;
  739. result = ISC_R_SUCCESS;
  740. cleanup:
  741. if (keyid != NULL)
  742. free_controlkey(keyid, mctx);
  743. if (config != NULL)
  744. cfg_obj_destroy(pctx, &config);
  745. if (pctx != NULL)
  746. cfg_parser_destroy(&pctx);
  747. return (result);
  748. }
  749. /*
  750. * Ensures that both '*global_keylistp' and '*control_keylistp' are
  751. * valid or both are NULL.
  752. */
  753. static void
  754. get_key_info(const cfg_obj_t *config, const cfg_obj_t *control,
  755. const cfg_obj_t **global_keylistp,
  756. const cfg_obj_t **control_keylistp)
  757. {
  758. isc_result_t result;
  759. const cfg_obj_t *control_keylist = NULL;
  760. const cfg_obj_t *global_keylist = NULL;
  761. REQUIRE(global_keylistp != NULL && *global_keylistp == NULL);
  762. REQUIRE(control_keylistp != NULL && *control_keylistp == NULL);
  763. control_keylist = cfg_tuple_get(control, "keys");
  764. if (!cfg_obj_isvoid(control_keylist) &&
  765. cfg_list_first(control_keylist) != NULL) {
  766. result = cfg_map_get(config, "key", &global_keylist);
  767. if (result == ISC_R_SUCCESS) {
  768. *global_keylistp = global_keylist;
  769. *control_keylistp = control_keylist;
  770. }
  771. }
  772. }
  773. static void
  774. update_listener(ns_controls_t *cp, controllistener_t **listenerp,
  775. const cfg_obj_t *control, const cfg_obj_t *config,
  776. isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
  777. const char *socktext, isc_sockettype_t type)
  778. {
  779. controllistener_t *listener;
  780. const cfg_obj_t *allow;
  781. const cfg_obj_t *global_keylist = NULL;
  782. const cfg_obj_t *control_keylist = NULL;
  783. dns_acl_t *new_acl = NULL;
  784. controlkeylist_t keys;
  785. isc_result_t result = ISC_R_SUCCESS;
  786. for (listener = ISC_LIST_HEAD(cp->listeners);
  787. listener != NULL;
  788. listener = ISC_LIST_NEXT(listener, link))
  789. if (isc_sockaddr_equal(addr, &listener->address))
  790. break;
  791. if (listener == NULL) {
  792. *listenerp = NULL;
  793. return;
  794. }
  795. /*
  796. * There is already a listener for this sockaddr.
  797. * Update the access list and key information.
  798. *
  799. * First try to deal with the key situation. There are a few
  800. * possibilities:
  801. * (a) It had an explicit keylist and still has an explicit keylist.
  802. * (b) It had an automagic key and now has an explicit keylist.
  803. * (c) It had an explicit keylist and now needs an automagic key.
  804. * (d) It has an automagic key and still needs the automagic key.
  805. *
  806. * (c) and (d) are the annoying ones. The caller needs to know
  807. * that it should use the automagic configuration for key information
  808. * in place of the named.conf configuration.
  809. *
  810. * XXXDCL There is one other hazard that has not been dealt with,
  811. * the problem that if a key change is being caused by a control
  812. * channel reload, then the response will be with the new key
  813. * and not able to be decrypted by the client.
  814. */
  815. if (control != NULL)
  816. get_key_info(config, control, &global_keylist,
  817. &control_keylist);
  818. if (control_keylist != NULL) {
  819. INSIST(global_keylist != NULL);
  820. ISC_LIST_INIT(keys);
  821. result = controlkeylist_fromcfg(control_keylist,
  822. listener->mctx, &keys);
  823. if (result == ISC_R_SUCCESS) {
  824. free_controlkeylist(&listener->keys, listener->mctx);
  825. listener->keys = keys;
  826. register_keys(control, global_keylist, &listener->keys,
  827. listener->mctx, socktext);
  828. }
  829. } else {
  830. free_controlkeylist(&listener->keys, listener->mctx);
  831. result = get_rndckey(listener->mctx, &listener->keys);
  832. }
  833. if (result != ISC_R_SUCCESS && global_keylist != NULL) {
  834. /*
  835. * This message might be a little misleading since the
  836. * "new keys" might in fact be identical to the old ones,
  837. * but tracking whether they are identical just for the
  838. * sake of avoiding this message would be too much trouble.
  839. */
  840. if (control != NULL)
  841. cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
  842. "couldn't install new keys for "
  843. "command channel %s: %s",
  844. socktext, isc_result_totext(result));
  845. else
  846. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  847. NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
  848. "couldn't install new keys for "
  849. "command channel %s: %s",
  850. socktext, isc_result_totext(result));
  851. }
  852. /*
  853. * Now, keep the old access list unless a new one can be made.
  854. */
  855. if (control != NULL && type == isc_sockettype_tcp) {
  856. allow = cfg_tuple_get(control, "allow");
  857. result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
  858. aclconfctx, listener->mctx, 0,
  859. &new_acl);
  860. } else {
  861. result = dns_acl_any(listener->mctx, &new_acl);
  862. }
  863. if (result == ISC_R_SUCCESS) {
  864. dns_acl_detach(&listener->acl);
  865. dns_acl_attach(new_acl, &listener->acl);
  866. dns_acl_detach(&new_acl);
  867. /* XXXDCL say the old acl is still used? */
  868. } else if (control != NULL)
  869. cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
  870. "couldn't install new acl for "
  871. "command channel %s: %s",
  872. socktext, isc_result_totext(result));
  873. else
  874. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  875. NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
  876. "couldn't install new acl for "
  877. "command channel %s: %s",
  878. socktext, isc_result_totext(result));
  879. if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) {
  880. isc_uint32_t perm, owner, group;
  881. perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm"));
  882. owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner"));
  883. group = cfg_obj_asuint32(cfg_tuple_get(control, "group"));
  884. result = ISC_R_SUCCESS;
  885. if (listener->perm != perm || listener->owner != owner ||
  886. listener->group != group)
  887. result = isc_socket_permunix(&listener->address, perm,
  888. owner, group);
  889. if (result == ISC_R_SUCCESS) {
  890. listener->perm = perm;
  891. listener->owner = owner;
  892. listener->group = group;
  893. } else if (control != NULL)
  894. cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
  895. "couldn't update ownership/permission for "
  896. "command channel %s", socktext);
  897. }
  898. *listenerp = listener;
  899. }
  900. static void
  901. add_listener(ns_controls_t *cp, controllistener_t **listenerp,
  902. const cfg_obj_t *control, const cfg_obj_t *config,
  903. isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
  904. const char *socktext, isc_sockettype_t type)
  905. {
  906. isc_mem_t *mctx = cp->server->mctx;
  907. controllistener_t *listener;
  908. const cfg_obj_t *allow;
  909. const cfg_obj_t *global_keylist = NULL;
  910. const cfg_obj_t *control_keylist = NULL;
  911. dns_acl_t *new_acl = NULL;
  912. isc_result_t result = ISC_R_SUCCESS;
  913. listener = isc_mem_get(mctx, sizeof(*listener));
  914. if (listener == NULL)
  915. result = ISC_R_NOMEMORY;
  916. if (result == ISC_R_SUCCESS) {
  917. listener->controls = cp;
  918. listener->mctx = mctx;
  919. listener->task = cp->server->task;
  920. listener->address = *addr;
  921. listener->sock = NULL;
  922. listener->listening = ISC_FALSE;
  923. listener->exiting = ISC_FALSE;
  924. listener->acl = NULL;
  925. listener->type = type;
  926. listener->perm = 0;
  927. listener->owner = 0;
  928. listener->group = 0;
  929. ISC_LINK_INIT(listener, link);
  930. ISC_LIST_INIT(listener->keys);
  931. ISC_LIST_INIT(listener->connections);
  932. /*
  933. * Make the acl.
  934. */
  935. if (control != NULL && type == isc_sockettype_tcp) {
  936. allow = cfg_tuple_get(control, "allow");
  937. result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
  938. aclconfctx, mctx, 0,
  939. &new_acl);
  940. } else {
  941. result = dns_acl_any(mctx, &new_acl);
  942. }
  943. }
  944. if (result == ISC_R_SUCCESS) {
  945. dns_acl_attach(new_acl, &listener->acl);
  946. dns_acl_detach(&new_acl);
  947. if (config != NULL)
  948. get_key_info(config, control, &global_keylist,
  949. &control_keylist);
  950. if (control_keylist != NULL) {
  951. result = controlkeylist_fromcfg(control_keylist,
  952. listener->mctx,
  953. &listener->keys);
  954. if (result == ISC_R_SUCCESS)
  955. register_keys(control, global_keylist,
  956. &listener->keys,
  957. listener->mctx, socktext);
  958. } else
  959. result = get_rndckey(mctx, &listener->keys);
  960. if (result != ISC_R_SUCCESS && control != NULL)
  961. cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
  962. "couldn't install keys for "
  963. "command channel %s: %s",
  964. socktext, isc_result_totext(result));
  965. }
  966. if (result == ISC_R_SUCCESS) {
  967. int pf = isc_sockaddr_pf(&listener->address);
  968. if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
  969. #ifdef ISC_PLATFORM_HAVESYSUNH
  970. (pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) ||
  971. #endif
  972. (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
  973. result = ISC_R_FAMILYNOSUPPORT;
  974. }
  975. if (result == ISC_R_SUCCESS && type == isc_sockettype_unix)
  976. isc_socket_cleanunix(&listener->address, ISC_FALSE);
  977. if (result == ISC_R_SUCCESS)
  978. result = isc_socket_create(ns_g_socketmgr,
  979. isc_sockaddr_pf(&listener->address),
  980. type, &listener->sock);
  981. if (result == ISC_R_SUCCESS)
  982. isc_socket_setname(listener->sock, "control", NULL);
  983. #ifndef ISC_ALLOW_MAPPED
  984. if (result == ISC_R_SUCCESS)
  985. isc_socket_ipv6only(listener->sock, ISC_TRUE);
  986. #endif
  987. if (result == ISC_R_SUCCESS)
  988. result = isc_socket_bind(listener->sock, &listener->address,
  989. ISC_SOCKET_REUSEADDRESS);
  990. if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) {
  991. listener->perm = cfg_obj_asuint32(cfg_tuple_get(control,
  992. "perm"));
  993. listener->owner = cfg_obj_asuint32(cfg_tuple_get(control,
  994. "owner"));
  995. listener->group = cfg_obj_asuint32(cfg_tuple_get(control,
  996. "group"));
  997. result = isc_socket_permunix(&listener->address, listener->perm,
  998. listener->owner, listener->group);
  999. }
  1000. if (result == ISC_R_SUCCESS)
  1001. result = control_listen(listener);
  1002. if (result == ISC_R_SUCCESS)
  1003. result = control_accept(listener);
  1004. if (result == ISC_R_SUCCESS) {
  1005. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  1006. NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
  1007. "command channel listening on %s", socktext);
  1008. *listenerp = listener;
  1009. } else {
  1010. if (listener != NULL) {
  1011. listener->exiting = ISC_TRUE;
  1012. free_listener(listener);
  1013. }
  1014. if (control != NULL)
  1015. cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
  1016. "couldn't add command channel %s: %s",
  1017. socktext, isc_result_totext(result));
  1018. else
  1019. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  1020. NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
  1021. "couldn't add command channel %s: %s",
  1022. socktext, isc_result_totext(result));
  1023. *listenerp = NULL;
  1024. }
  1025. /* XXXDCL return error results? fail hard? */
  1026. }
  1027. isc_result_t
  1028. ns_controls_configure(ns_controls_t *cp, const cfg_obj_t *config,
  1029. cfg_aclconfctx_t *aclconfctx)
  1030. {
  1031. controllistener_t *listener;
  1032. controllistenerlist_t new_listeners;
  1033. const cfg_obj_t *controlslist = NULL;
  1034. const cfg_listelt_t *element, *element2;
  1035. char socktext[ISC_SOCKADDR_FORMATSIZE];
  1036. ISC_LIST_INIT(new_listeners);
  1037. /*
  1038. * Get the list of named.conf 'controls' statements.
  1039. */
  1040. (void)cfg_map_get(config, "controls", &controlslist);
  1041. /*
  1042. * Run through the new control channel list, noting sockets that
  1043. * are already being listened on and moving them to the new list.
  1044. *
  1045. * Identifying duplicate addr/port combinations is left to either
  1046. * the underlying config code, or to the bind attempt getting an
  1047. * address-in-use error.
  1048. */
  1049. if (controlslist != NULL) {
  1050. for (element = cfg_list_first(controlslist);
  1051. element != NULL;
  1052. element = cfg_list_next(element)) {
  1053. const cfg_obj_t *controls;
  1054. const cfg_obj_t *inetcontrols = NULL;
  1055. controls = cfg_listelt_value(element);
  1056. (void)cfg_map_get(controls, "inet", &inetcontrols);
  1057. if (inetcontrols == NULL)
  1058. continue;
  1059. for (element2 = cfg_list_first(inetcontrols);
  1060. element2 != NULL;
  1061. element2 = cfg_list_next(element2)) {
  1062. const cfg_obj_t *control;
  1063. const cfg_obj_t *obj;
  1064. isc_sockaddr_t addr;
  1065. /*
  1066. * The parser handles BIND 8 configuration file
  1067. * syntax, so it allows unix phrases as well
  1068. * inet phrases with no keys{} clause.
  1069. */
  1070. control = cfg_listelt_value(element2);
  1071. obj = cfg_tuple_get(control, "address");
  1072. addr = *cfg_obj_assockaddr(obj);
  1073. if (isc_sockaddr_getport(&addr) == 0)
  1074. isc_sockaddr_setport(&addr,
  1075. NS_CONTROL_PORT);
  1076. isc_sockaddr_format(&addr, socktext,
  1077. sizeof(socktext));
  1078. isc_log_write(ns_g_lctx,
  1079. NS_LOGCATEGORY_GENERAL,
  1080. NS_LOGMODULE_CONTROL,
  1081. ISC_LOG_DEBUG(9),
  1082. "processing control channel %s",
  1083. socktext);
  1084. update_listener(cp, &listener, control, config,
  1085. &addr, aclconfctx, socktext,
  1086. isc_sockettype_tcp);
  1087. if (listener != NULL)
  1088. /*
  1089. * Remove the listener from the old
  1090. * list, so it won't be shut down.
  1091. */
  1092. ISC_LIST_UNLINK(cp->listeners,
  1093. listener, link);
  1094. else
  1095. /*
  1096. * This is a new listener.
  1097. */
  1098. add_listener(cp, &listener, control,
  1099. config, &addr, aclconfctx,
  1100. socktext,
  1101. isc_sockettype_tcp);
  1102. if (listener != NULL)
  1103. ISC_LIST_APPEND(new_listeners,
  1104. listener, link);
  1105. }
  1106. }
  1107. for (element = cfg_list_first(controlslist);
  1108. element != NULL;
  1109. element = cfg_list_next(element)) {
  1110. const cfg_obj_t *controls;
  1111. const cfg_obj_t *unixcontrols = NULL;
  1112. controls = cfg_listelt_value(element);
  1113. (void)cfg_map_get(controls, "unix", &unixcontrols);
  1114. if (unixcontrols == NULL)
  1115. continue;
  1116. for (element2 = cfg_list_first(unixcontrols);
  1117. element2 != NULL;
  1118. element2 = cfg_list_next(element2)) {
  1119. const cfg_obj_t *control;
  1120. const cfg_obj_t *path;
  1121. isc_sockaddr_t addr;
  1122. isc_result_t result;
  1123. /*
  1124. * The parser handles BIND 8 configuration file
  1125. * syntax, so it allows unix phrases as well
  1126. * inet phrases with no keys{} clause.
  1127. */
  1128. control = cfg_listelt_value(element2);
  1129. path = cfg_tuple_get(control, "path");
  1130. result = isc_sockaddr_frompath(&addr,
  1131. cfg_obj_asstring(path));
  1132. if (result != ISC_R_SUCCESS) {
  1133. isc_log_write(ns_g_lctx,
  1134. NS_LOGCATEGORY_GENERAL,
  1135. NS_LOGMODULE_CONTROL,
  1136. ISC_LOG_DEBUG(9),
  1137. "control channel '%s': %s",
  1138. cfg_obj_asstring(path),
  1139. isc_result_totext(result));
  1140. continue;
  1141. }
  1142. isc_log_write(ns_g_lctx,
  1143. NS_LOGCATEGORY_GENERAL,
  1144. NS_LOGMODULE_CONTROL,
  1145. ISC_LOG_DEBUG(9),
  1146. "processing control channel '%s'",
  1147. cfg_obj_asstring(path));
  1148. update_listener(cp, &listener, control, config,
  1149. &addr, aclconfctx,
  1150. cfg_obj_asstring(path),
  1151. isc_sockettype_unix);
  1152. if (listener != NULL)
  1153. /*
  1154. * Remove the listener from the old
  1155. * list, so it won't be shut down.
  1156. */
  1157. ISC_LIST_UNLINK(cp->listeners,
  1158. listener, link);
  1159. else
  1160. /*
  1161. * This is a new listener.
  1162. */
  1163. add_listener(cp, &listener, control,
  1164. config, &addr, aclconfctx,
  1165. cfg_obj_asstring(path),
  1166. isc_sockettype_unix);
  1167. if (listener != NULL)
  1168. ISC_LIST_APPEND(new_listeners,
  1169. listener, link);
  1170. }
  1171. }
  1172. } else {
  1173. int i;
  1174. for (i = 0; i < 2; i++) {
  1175. isc_sockaddr_t addr;
  1176. if (i == 0) {
  1177. struct in_addr localhost;
  1178. if (isc_net_probeipv4() != ISC_R_SUCCESS)
  1179. continue;
  1180. localhost.s_addr = htonl(INADDR_LOOPBACK);
  1181. isc_sockaddr_fromin(&addr, &localhost, 0);
  1182. } else {
  1183. if (isc_net_probeipv6() != ISC_R_SUCCESS)
  1184. continue;
  1185. isc_sockaddr_fromin6(&addr,
  1186. &in6addr_loopback, 0);
  1187. }
  1188. isc_sockaddr_setport(&addr, NS_CONTROL_PORT);
  1189. isc_sockaddr_format(&addr, socktext, sizeof(socktext));
  1190. update_listener(cp, &listener, NULL, NULL,
  1191. &addr, NULL, socktext,
  1192. isc_sockettype_tcp);
  1193. if (listener != NULL)
  1194. /*
  1195. * Remove the listener from the old
  1196. * list, so it won't be shut down.
  1197. */
  1198. ISC_LIST_UNLINK(cp->listeners,
  1199. listener, link);
  1200. else
  1201. /*
  1202. * This is a new listener.
  1203. */
  1204. add_listener(cp, &listener, NULL, NULL,
  1205. &addr, NULL, socktext,
  1206. isc_sockettype_tcp);
  1207. if (listener != NULL)
  1208. ISC_LIST_APPEND(new_listeners,
  1209. listener, link);
  1210. }
  1211. }
  1212. /*
  1213. * ns_control_shutdown() will stop whatever is on the global
  1214. * listeners list, which currently only has whatever sockaddrs
  1215. * were in the previous configuration (if any) that do not
  1216. * remain in the current configuration.
  1217. */
  1218. controls_shutdown(cp);
  1219. /*
  1220. * Put all of the valid listeners on the listeners list.
  1221. * Anything already on listeners in the process of shutting
  1222. * down will be taken care of by listen_done().
  1223. */
  1224. ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link);
  1225. return (ISC_R_SUCCESS);
  1226. }
  1227. isc_result_t
  1228. ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp) {
  1229. isc_mem_t *mctx = server->mctx;
  1230. isc_result_t result;
  1231. ns_controls_t *controls = isc_mem_get(mctx, sizeof(*controls));
  1232. if (controls == NULL)
  1233. return (ISC_R_NOMEMORY);
  1234. controls->server = server;
  1235. ISC_LIST_INIT(controls->listeners);
  1236. controls->shuttingdown = ISC_FALSE;
  1237. controls->symtab = NULL;
  1238. result = isccc_cc_createsymtab(&controls->symtab);
  1239. if (result != ISC_R_SUCCESS) {
  1240. isc_mem_put(server->mctx, controls, sizeof(*controls));
  1241. return (result);
  1242. }
  1243. *ctrlsp = controls;
  1244. return (ISC_R_SUCCESS);
  1245. }
  1246. void
  1247. ns_controls_destroy(ns_controls_t **ctrlsp) {
  1248. ns_controls_t *controls = *ctrlsp;
  1249. REQUIRE(ISC_LIST_EMPTY(controls->listeners));
  1250. isccc_symtab_destroy(&controls->symtab);
  1251. isc_mem_put(controls->server->mctx, controls, sizeof(*controls));
  1252. *ctrlsp = NULL;
  1253. }