/contrib/bind9/bin/named/server.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 7648 lines · 5910 code · 887 blank · 851 comment · 1790 complexity · 0d51a127a90e8c0853cc6539ac9d6bce MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-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: server.c,v 1.599.8.19 2012/02/22 00:33:32 each Exp $ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <stdlib.h>
  21. #include <unistd.h>
  22. #include <limits.h>
  23. #include <ctype.h>
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <isc/app.h>
  27. #include <isc/base64.h>
  28. #include <isc/dir.h>
  29. #include <isc/entropy.h>
  30. #include <isc/file.h>
  31. #include <isc/hash.h>
  32. #include <isc/httpd.h>
  33. #include <isc/lex.h>
  34. #include <isc/parseint.h>
  35. #include <isc/portset.h>
  36. #include <isc/print.h>
  37. #include <isc/resource.h>
  38. #include <isc/sha2.h>
  39. #include <isc/socket.h>
  40. #include <isc/stat.h>
  41. #include <isc/stats.h>
  42. #include <isc/stdio.h>
  43. #include <isc/string.h>
  44. #include <isc/task.h>
  45. #include <isc/timer.h>
  46. #include <isc/util.h>
  47. #include <isc/xml.h>
  48. #include <isccfg/namedconf.h>
  49. #include <bind9/check.h>
  50. #include <dns/acache.h>
  51. #include <dns/adb.h>
  52. #include <dns/cache.h>
  53. #include <dns/db.h>
  54. #include <dns/dispatch.h>
  55. #include <dns/dlz.h>
  56. #include <dns/dns64.h>
  57. #include <dns/forward.h>
  58. #include <dns/journal.h>
  59. #include <dns/keytable.h>
  60. #include <dns/keyvalues.h>
  61. #include <dns/lib.h>
  62. #include <dns/master.h>
  63. #include <dns/masterdump.h>
  64. #include <dns/order.h>
  65. #include <dns/peer.h>
  66. #include <dns/portlist.h>
  67. #include <dns/rbt.h>
  68. #include <dns/rdataclass.h>
  69. #include <dns/rdataset.h>
  70. #include <dns/rdatastruct.h>
  71. #include <dns/resolver.h>
  72. #include <dns/rootns.h>
  73. #include <dns/secalg.h>
  74. #include <dns/stats.h>
  75. #include <dns/tkey.h>
  76. #include <dns/tsig.h>
  77. #include <dns/view.h>
  78. #include <dns/zone.h>
  79. #include <dns/zt.h>
  80. #include <dst/dst.h>
  81. #include <dst/result.h>
  82. #include <named/client.h>
  83. #include <named/config.h>
  84. #include <named/control.h>
  85. #include <named/interfacemgr.h>
  86. #include <named/log.h>
  87. #include <named/logconf.h>
  88. #include <named/lwresd.h>
  89. #include <named/main.h>
  90. #include <named/os.h>
  91. #include <named/server.h>
  92. #include <named/statschannel.h>
  93. #include <named/tkeyconf.h>
  94. #include <named/tsigconf.h>
  95. #include <named/zoneconf.h>
  96. #ifdef HAVE_LIBSCF
  97. #include <named/ns_smf_globals.h>
  98. #include <stdlib.h>
  99. #endif
  100. #ifndef PATH_MAX
  101. #define PATH_MAX 1024
  102. #endif
  103. /*%
  104. * Check an operation for failure. Assumes that the function
  105. * using it has a 'result' variable and a 'cleanup' label.
  106. */
  107. #define CHECK(op) \
  108. do { result = (op); \
  109. if (result != ISC_R_SUCCESS) goto cleanup; \
  110. } while (0)
  111. #define CHECKM(op, msg) \
  112. do { result = (op); \
  113. if (result != ISC_R_SUCCESS) { \
  114. isc_log_write(ns_g_lctx, \
  115. NS_LOGCATEGORY_GENERAL, \
  116. NS_LOGMODULE_SERVER, \
  117. ISC_LOG_ERROR, \
  118. "%s: %s", msg, \
  119. isc_result_totext(result)); \
  120. goto cleanup; \
  121. } \
  122. } while (0) \
  123. #define CHECKMF(op, msg, file) \
  124. do { result = (op); \
  125. if (result != ISC_R_SUCCESS) { \
  126. isc_log_write(ns_g_lctx, \
  127. NS_LOGCATEGORY_GENERAL, \
  128. NS_LOGMODULE_SERVER, \
  129. ISC_LOG_ERROR, \
  130. "%s '%s': %s", msg, file, \
  131. isc_result_totext(result)); \
  132. goto cleanup; \
  133. } \
  134. } while (0) \
  135. #define CHECKFATAL(op, msg) \
  136. do { result = (op); \
  137. if (result != ISC_R_SUCCESS) \
  138. fatal(msg, result); \
  139. } while (0) \
  140. /*%
  141. * Maximum ADB size for views that share a cache. Use this limit to suppress
  142. * the total of memory footprint, which should be the main reason for sharing
  143. * a cache. Only effective when a finite max-cache-size is specified.
  144. * This is currently defined to be 8MB.
  145. */
  146. #define MAX_ADB_SIZE_FOR_CACHESHARE 8388608
  147. struct ns_dispatch {
  148. isc_sockaddr_t addr;
  149. unsigned int dispatchgen;
  150. dns_dispatch_t *dispatch;
  151. ISC_LINK(struct ns_dispatch) link;
  152. };
  153. struct ns_cache {
  154. dns_cache_t *cache;
  155. dns_view_t *primaryview;
  156. isc_boolean_t needflush;
  157. isc_boolean_t adbsizeadjusted;
  158. ISC_LINK(ns_cache_t) link;
  159. };
  160. struct dumpcontext {
  161. isc_mem_t *mctx;
  162. isc_boolean_t dumpcache;
  163. isc_boolean_t dumpzones;
  164. FILE *fp;
  165. ISC_LIST(struct viewlistentry) viewlist;
  166. struct viewlistentry *view;
  167. struct zonelistentry *zone;
  168. dns_dumpctx_t *mdctx;
  169. dns_db_t *db;
  170. dns_db_t *cache;
  171. isc_task_t *task;
  172. dns_dbversion_t *version;
  173. };
  174. struct viewlistentry {
  175. dns_view_t *view;
  176. ISC_LINK(struct viewlistentry) link;
  177. ISC_LIST(struct zonelistentry) zonelist;
  178. };
  179. struct zonelistentry {
  180. dns_zone_t *zone;
  181. ISC_LINK(struct zonelistentry) link;
  182. };
  183. /*%
  184. * Configuration context to retain for each view that allows
  185. * new zones to be added at runtime.
  186. */
  187. struct cfg_context {
  188. isc_mem_t * mctx;
  189. cfg_parser_t * parser;
  190. cfg_obj_t * config;
  191. cfg_parser_t * nzparser;
  192. cfg_obj_t * nzconfig;
  193. cfg_aclconfctx_t * actx;
  194. };
  195. /*
  196. * These zones should not leak onto the Internet.
  197. */
  198. static const struct {
  199. const char *zone;
  200. isc_boolean_t rfc1918;
  201. } empty_zones[] = {
  202. /* RFC 1918 */
  203. { "10.IN-ADDR.ARPA", ISC_TRUE },
  204. { "16.172.IN-ADDR.ARPA", ISC_TRUE },
  205. { "17.172.IN-ADDR.ARPA", ISC_TRUE },
  206. { "18.172.IN-ADDR.ARPA", ISC_TRUE },
  207. { "19.172.IN-ADDR.ARPA", ISC_TRUE },
  208. { "20.172.IN-ADDR.ARPA", ISC_TRUE },
  209. { "21.172.IN-ADDR.ARPA", ISC_TRUE },
  210. { "22.172.IN-ADDR.ARPA", ISC_TRUE },
  211. { "23.172.IN-ADDR.ARPA", ISC_TRUE },
  212. { "24.172.IN-ADDR.ARPA", ISC_TRUE },
  213. { "25.172.IN-ADDR.ARPA", ISC_TRUE },
  214. { "26.172.IN-ADDR.ARPA", ISC_TRUE },
  215. { "27.172.IN-ADDR.ARPA", ISC_TRUE },
  216. { "28.172.IN-ADDR.ARPA", ISC_TRUE },
  217. { "29.172.IN-ADDR.ARPA", ISC_TRUE },
  218. { "30.172.IN-ADDR.ARPA", ISC_TRUE },
  219. { "31.172.IN-ADDR.ARPA", ISC_TRUE },
  220. { "168.192.IN-ADDR.ARPA", ISC_TRUE },
  221. /* RFC 5735 and RFC 5737 */
  222. { "0.IN-ADDR.ARPA", ISC_FALSE }, /* THIS NETWORK */
  223. { "127.IN-ADDR.ARPA", ISC_FALSE }, /* LOOPBACK */
  224. { "254.169.IN-ADDR.ARPA", ISC_FALSE }, /* LINK LOCAL */
  225. { "2.0.192.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET */
  226. { "100.51.198.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET 2 */
  227. { "113.0.203.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET 3 */
  228. { "255.255.255.255.IN-ADDR.ARPA", ISC_FALSE }, /* BROADCAST */
  229. /* Local IPv6 Unicast Addresses */
  230. { "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
  231. { "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
  232. /* LOCALLY ASSIGNED LOCAL ADDRESS SCOPE */
  233. { "D.F.IP6.ARPA", ISC_FALSE },
  234. { "8.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
  235. { "9.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
  236. { "A.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
  237. { "B.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
  238. /* Example Prefix, RFC 3849. */
  239. { "8.B.D.0.1.0.0.2.IP6.ARPA", ISC_FALSE },
  240. { NULL, ISC_FALSE }
  241. };
  242. ISC_PLATFORM_NORETURN_PRE static void
  243. fatal(const char *msg, isc_result_t result) ISC_PLATFORM_NORETURN_POST;
  244. static void
  245. ns_server_reload(isc_task_t *task, isc_event_t *event);
  246. static isc_result_t
  247. ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
  248. cfg_aclconfctx_t *actx,
  249. isc_mem_t *mctx, ns_listenelt_t **target);
  250. static isc_result_t
  251. ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
  252. cfg_aclconfctx_t *actx,
  253. isc_mem_t *mctx, ns_listenlist_t **target);
  254. static isc_result_t
  255. configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
  256. const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype);
  257. static isc_result_t
  258. configure_alternates(const cfg_obj_t *config, dns_view_t *view,
  259. const cfg_obj_t *alternates);
  260. static isc_result_t
  261. configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
  262. const cfg_obj_t *vconfig, isc_mem_t *mctx, dns_view_t *view,
  263. cfg_aclconfctx_t *aclconf, isc_boolean_t added);
  264. static isc_result_t
  265. add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx);
  266. static void
  267. end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
  268. static void
  269. newzone_cfgctx_destroy(void **cfgp);
  270. /*%
  271. * Configure a single view ACL at '*aclp'. Get its configuration from
  272. * 'vconfig' (for per-view configuration) and maybe from 'config'
  273. */
  274. static isc_result_t
  275. configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config,
  276. const char *aclname, const char *acltuplename,
  277. cfg_aclconfctx_t *actx, isc_mem_t *mctx, dns_acl_t **aclp)
  278. {
  279. isc_result_t result;
  280. const cfg_obj_t *maps[3];
  281. const cfg_obj_t *aclobj = NULL;
  282. int i = 0;
  283. if (*aclp != NULL)
  284. dns_acl_detach(aclp);
  285. if (vconfig != NULL)
  286. maps[i++] = cfg_tuple_get(vconfig, "options");
  287. if (config != NULL) {
  288. const cfg_obj_t *options = NULL;
  289. (void)cfg_map_get(config, "options", &options);
  290. if (options != NULL)
  291. maps[i++] = options;
  292. }
  293. maps[i] = NULL;
  294. (void)ns_config_get(maps, aclname, &aclobj);
  295. if (aclobj == NULL)
  296. /*
  297. * No value available. *aclp == NULL.
  298. */
  299. return (ISC_R_SUCCESS);
  300. if (acltuplename != NULL) {
  301. /*
  302. * If the ACL is given in an optional tuple, retrieve it.
  303. * The parser should have ensured that a valid object be
  304. * returned.
  305. */
  306. aclobj = cfg_tuple_get(aclobj, acltuplename);
  307. }
  308. result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
  309. actx, mctx, 0, aclp);
  310. return (result);
  311. }
  312. /*%
  313. * Configure a sortlist at '*aclp'. Essentially the same as
  314. * configure_view_acl() except it calls cfg_acl_fromconfig with a
  315. * nest_level value of 2.
  316. */
  317. static isc_result_t
  318. configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
  319. cfg_aclconfctx_t *actx, isc_mem_t *mctx,
  320. dns_acl_t **aclp)
  321. {
  322. isc_result_t result;
  323. const cfg_obj_t *maps[3];
  324. const cfg_obj_t *aclobj = NULL;
  325. int i = 0;
  326. if (*aclp != NULL)
  327. dns_acl_detach(aclp);
  328. if (vconfig != NULL)
  329. maps[i++] = cfg_tuple_get(vconfig, "options");
  330. if (config != NULL) {
  331. const cfg_obj_t *options = NULL;
  332. (void)cfg_map_get(config, "options", &options);
  333. if (options != NULL)
  334. maps[i++] = options;
  335. }
  336. maps[i] = NULL;
  337. (void)ns_config_get(maps, "sortlist", &aclobj);
  338. if (aclobj == NULL)
  339. return (ISC_R_SUCCESS);
  340. /*
  341. * Use a nest level of 3 for the "top level" of the sortlist;
  342. * this means each entry in the top three levels will be stored
  343. * as lists of separate, nested ACLs, rather than merged together
  344. * into IP tables as is usually done with ACLs.
  345. */
  346. result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
  347. actx, mctx, 3, aclp);
  348. return (result);
  349. }
  350. static isc_result_t
  351. configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config,
  352. const char *confname, const char *conftuplename,
  353. isc_mem_t *mctx, dns_rbt_t **rbtp)
  354. {
  355. isc_result_t result;
  356. const cfg_obj_t *maps[3];
  357. const cfg_obj_t *obj = NULL;
  358. const cfg_listelt_t *element;
  359. int i = 0;
  360. dns_fixedname_t fixed;
  361. dns_name_t *name;
  362. isc_buffer_t b;
  363. const char *str;
  364. const cfg_obj_t *nameobj;
  365. if (*rbtp != NULL)
  366. dns_rbt_destroy(rbtp);
  367. if (vconfig != NULL)
  368. maps[i++] = cfg_tuple_get(vconfig, "options");
  369. if (config != NULL) {
  370. const cfg_obj_t *options = NULL;
  371. (void)cfg_map_get(config, "options", &options);
  372. if (options != NULL)
  373. maps[i++] = options;
  374. }
  375. maps[i] = NULL;
  376. (void)ns_config_get(maps, confname, &obj);
  377. if (obj == NULL)
  378. /*
  379. * No value available. *rbtp == NULL.
  380. */
  381. return (ISC_R_SUCCESS);
  382. if (conftuplename != NULL) {
  383. obj = cfg_tuple_get(obj, conftuplename);
  384. if (cfg_obj_isvoid(obj))
  385. return (ISC_R_SUCCESS);
  386. }
  387. result = dns_rbt_create(mctx, NULL, NULL, rbtp);
  388. if (result != ISC_R_SUCCESS)
  389. return (result);
  390. dns_fixedname_init(&fixed);
  391. name = dns_fixedname_name(&fixed);
  392. for (element = cfg_list_first(obj);
  393. element != NULL;
  394. element = cfg_list_next(element)) {
  395. nameobj = cfg_listelt_value(element);
  396. str = cfg_obj_asstring(nameobj);
  397. isc_buffer_init(&b, str, strlen(str));
  398. isc_buffer_add(&b, strlen(str));
  399. CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
  400. /*
  401. * We don't need the node data, but need to set dummy data to
  402. * avoid a partial match with an empty node. For example, if
  403. * we have foo.example.com and bar.example.com, we'd get a match
  404. * for baz.example.com, which is not the expected result.
  405. * We simply use (void *)1 as the dummy data.
  406. */
  407. result = dns_rbt_addname(*rbtp, name, (void *)1);
  408. if (result != ISC_R_SUCCESS) {
  409. cfg_obj_log(nameobj, ns_g_lctx, ISC_LOG_ERROR,
  410. "failed to add %s for %s: %s",
  411. str, confname, isc_result_totext(result));
  412. goto cleanup;
  413. }
  414. }
  415. return (result);
  416. cleanup:
  417. dns_rbt_destroy(rbtp);
  418. return (result);
  419. }
  420. static isc_result_t
  421. dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key,
  422. isc_boolean_t managed, dst_key_t **target, isc_mem_t *mctx)
  423. {
  424. dns_rdataclass_t viewclass;
  425. dns_rdata_dnskey_t keystruct;
  426. isc_uint32_t flags, proto, alg;
  427. const char *keystr, *keynamestr;
  428. unsigned char keydata[4096];
  429. isc_buffer_t keydatabuf;
  430. unsigned char rrdata[4096];
  431. isc_buffer_t rrdatabuf;
  432. isc_region_t r;
  433. dns_fixedname_t fkeyname;
  434. dns_name_t *keyname;
  435. isc_buffer_t namebuf;
  436. isc_result_t result;
  437. dst_key_t *dstkey = NULL;
  438. INSIST(target != NULL && *target == NULL);
  439. flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
  440. proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
  441. alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
  442. keyname = dns_fixedname_name(&fkeyname);
  443. keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
  444. if (managed) {
  445. const char *initmethod;
  446. initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init"));
  447. if (strcasecmp(initmethod, "initial-key") != 0) {
  448. cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
  449. "managed key '%s': "
  450. "invalid initialization method '%s'",
  451. keynamestr, initmethod);
  452. result = ISC_R_FAILURE;
  453. goto cleanup;
  454. }
  455. }
  456. if (vconfig == NULL)
  457. viewclass = dns_rdataclass_in;
  458. else {
  459. const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class");
  460. CHECK(ns_config_getclass(classobj, dns_rdataclass_in,
  461. &viewclass));
  462. }
  463. keystruct.common.rdclass = viewclass;
  464. keystruct.common.rdtype = dns_rdatatype_dnskey;
  465. /*
  466. * The key data in keystruct is not dynamically allocated.
  467. */
  468. keystruct.mctx = NULL;
  469. ISC_LINK_INIT(&keystruct.common, link);
  470. if (flags > 0xffff)
  471. CHECKM(ISC_R_RANGE, "key flags");
  472. if (proto > 0xff)
  473. CHECKM(ISC_R_RANGE, "key protocol");
  474. if (alg > 0xff)
  475. CHECKM(ISC_R_RANGE, "key algorithm");
  476. keystruct.flags = (isc_uint16_t)flags;
  477. keystruct.protocol = (isc_uint8_t)proto;
  478. keystruct.algorithm = (isc_uint8_t)alg;
  479. isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
  480. isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
  481. keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
  482. CHECK(isc_base64_decodestring(keystr, &keydatabuf));
  483. isc_buffer_usedregion(&keydatabuf, &r);
  484. keystruct.datalen = r.length;
  485. keystruct.data = r.base;
  486. if ((keystruct.algorithm == DST_ALG_RSASHA1 ||
  487. keystruct.algorithm == DST_ALG_RSAMD5) &&
  488. r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
  489. cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
  490. "%s key '%s' has a weak exponent",
  491. managed ? "managed" : "trusted",
  492. keynamestr);
  493. CHECK(dns_rdata_fromstruct(NULL,
  494. keystruct.common.rdclass,
  495. keystruct.common.rdtype,
  496. &keystruct, &rrdatabuf));
  497. dns_fixedname_init(&fkeyname);
  498. isc_buffer_init(&namebuf, keynamestr, strlen(keynamestr));
  499. isc_buffer_add(&namebuf, strlen(keynamestr));
  500. CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL));
  501. CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
  502. mctx, &dstkey));
  503. *target = dstkey;
  504. return (ISC_R_SUCCESS);
  505. cleanup:
  506. if (result == DST_R_NOCRYPTO) {
  507. cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
  508. "ignoring %s key for '%s': no crypto support",
  509. managed ? "managed" : "trusted",
  510. keynamestr);
  511. } else if (result == DST_R_UNSUPPORTEDALG) {
  512. cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
  513. "skipping %s key for '%s': %s",
  514. managed ? "managed" : "trusted",
  515. keynamestr, isc_result_totext(result));
  516. } else {
  517. cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
  518. "configuring %s key for '%s': %s",
  519. managed ? "managed" : "trusted",
  520. keynamestr, isc_result_totext(result));
  521. result = ISC_R_FAILURE;
  522. }
  523. if (dstkey != NULL)
  524. dst_key_free(&dstkey);
  525. return (result);
  526. }
  527. static isc_result_t
  528. load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig,
  529. dns_view_t *view, isc_boolean_t managed,
  530. dns_name_t *keyname, isc_mem_t *mctx)
  531. {
  532. const cfg_listelt_t *elt, *elt2;
  533. const cfg_obj_t *key, *keylist;
  534. dst_key_t *dstkey = NULL;
  535. isc_result_t result;
  536. dns_keytable_t *secroots = NULL;
  537. CHECK(dns_view_getsecroots(view, &secroots));
  538. for (elt = cfg_list_first(keys);
  539. elt != NULL;
  540. elt = cfg_list_next(elt)) {
  541. keylist = cfg_listelt_value(elt);
  542. for (elt2 = cfg_list_first(keylist);
  543. elt2 != NULL;
  544. elt2 = cfg_list_next(elt2)) {
  545. key = cfg_listelt_value(elt2);
  546. result = dstkey_fromconfig(vconfig, key, managed,
  547. &dstkey, mctx);
  548. if (result == DST_R_UNSUPPORTEDALG) {
  549. result = ISC_R_SUCCESS;
  550. continue;
  551. }
  552. if (result != ISC_R_SUCCESS)
  553. goto cleanup;
  554. /*
  555. * If keyname was specified, we only add that key.
  556. */
  557. if (keyname != NULL &&
  558. !dns_name_equal(keyname, dst_key_name(dstkey)))
  559. {
  560. dst_key_free(&dstkey);
  561. continue;
  562. }
  563. CHECK(dns_keytable_add(secroots, managed, &dstkey));
  564. }
  565. }
  566. cleanup:
  567. if (dstkey != NULL)
  568. dst_key_free(&dstkey);
  569. if (secroots != NULL)
  570. dns_keytable_detach(&secroots);
  571. if (result == DST_R_NOCRYPTO)
  572. result = ISC_R_SUCCESS;
  573. return (result);
  574. }
  575. /*%
  576. * Configure DNSSEC keys for a view.
  577. *
  578. * The per-view configuration values and the server-global defaults are read
  579. * from 'vconfig' and 'config'.
  580. */
  581. static isc_result_t
  582. configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
  583. const cfg_obj_t *config, const cfg_obj_t *bindkeys,
  584. isc_boolean_t auto_dlv, isc_boolean_t auto_root,
  585. isc_mem_t *mctx)
  586. {
  587. isc_result_t result = ISC_R_SUCCESS;
  588. const cfg_obj_t *view_keys = NULL;
  589. const cfg_obj_t *global_keys = NULL;
  590. const cfg_obj_t *view_managed_keys = NULL;
  591. const cfg_obj_t *global_managed_keys = NULL;
  592. const cfg_obj_t *maps[4];
  593. const cfg_obj_t *voptions = NULL;
  594. const cfg_obj_t *options = NULL;
  595. const cfg_obj_t *obj = NULL;
  596. const char *directory;
  597. int i = 0;
  598. /* We don't need trust anchors for the _bind view */
  599. if (strcmp(view->name, "_bind") == 0 &&
  600. view->rdclass == dns_rdataclass_chaos) {
  601. return (ISC_R_SUCCESS);
  602. }
  603. if (vconfig != NULL) {
  604. voptions = cfg_tuple_get(vconfig, "options");
  605. if (voptions != NULL) {
  606. (void) cfg_map_get(voptions, "trusted-keys",
  607. &view_keys);
  608. (void) cfg_map_get(voptions, "managed-keys",
  609. &view_managed_keys);
  610. maps[i++] = voptions;
  611. }
  612. }
  613. if (config != NULL) {
  614. (void)cfg_map_get(config, "trusted-keys", &global_keys);
  615. (void)cfg_map_get(config, "managed-keys", &global_managed_keys);
  616. (void)cfg_map_get(config, "options", &options);
  617. if (options != NULL) {
  618. maps[i++] = options;
  619. }
  620. }
  621. maps[i++] = ns_g_defaults;
  622. maps[i] = NULL;
  623. result = dns_view_initsecroots(view, mctx);
  624. if (result != ISC_R_SUCCESS) {
  625. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  626. NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
  627. "couldn't create keytable");
  628. return (ISC_R_UNEXPECTED);
  629. }
  630. if (auto_dlv && view->rdclass == dns_rdataclass_in) {
  631. const cfg_obj_t *builtin_keys = NULL;
  632. const cfg_obj_t *builtin_managed_keys = NULL;
  633. isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
  634. NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
  635. "using built-in DLV key for view %s",
  636. view->name);
  637. /*
  638. * If bind.keys exists, it overrides the managed-keys
  639. * clause hard-coded in ns_g_config.
  640. */
  641. if (bindkeys != NULL) {
  642. (void)cfg_map_get(bindkeys, "trusted-keys",
  643. &builtin_keys);
  644. (void)cfg_map_get(bindkeys, "managed-keys",
  645. &builtin_managed_keys);
  646. } else {
  647. (void)cfg_map_get(ns_g_config, "trusted-keys",
  648. &builtin_keys);
  649. (void)cfg_map_get(ns_g_config, "managed-keys",
  650. &builtin_managed_keys);
  651. }
  652. if (builtin_keys != NULL)
  653. CHECK(load_view_keys(builtin_keys, vconfig, view,
  654. ISC_FALSE, view->dlv, mctx));
  655. if (builtin_managed_keys != NULL)
  656. CHECK(load_view_keys(builtin_managed_keys, vconfig,
  657. view, ISC_TRUE, view->dlv, mctx));
  658. }
  659. if (auto_root && view->rdclass == dns_rdataclass_in) {
  660. const cfg_obj_t *builtin_keys = NULL;
  661. const cfg_obj_t *builtin_managed_keys = NULL;
  662. isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
  663. NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
  664. "using built-in root key for view %s",
  665. view->name);
  666. /*
  667. * If bind.keys exists, it overrides the managed-keys
  668. * clause hard-coded in ns_g_config.
  669. */
  670. if (bindkeys != NULL) {
  671. (void)cfg_map_get(bindkeys, "trusted-keys",
  672. &builtin_keys);
  673. (void)cfg_map_get(bindkeys, "managed-keys",
  674. &builtin_managed_keys);
  675. } else {
  676. (void)cfg_map_get(ns_g_config, "trusted-keys",
  677. &builtin_keys);
  678. (void)cfg_map_get(ns_g_config, "managed-keys",
  679. &builtin_managed_keys);
  680. }
  681. if (builtin_keys != NULL)
  682. CHECK(load_view_keys(builtin_keys, vconfig, view,
  683. ISC_FALSE, dns_rootname, mctx));
  684. if (builtin_managed_keys != NULL)
  685. CHECK(load_view_keys(builtin_managed_keys, vconfig,
  686. view, ISC_TRUE, dns_rootname,
  687. mctx));
  688. }
  689. CHECK(load_view_keys(view_keys, vconfig, view, ISC_FALSE,
  690. NULL, mctx));
  691. CHECK(load_view_keys(view_managed_keys, vconfig, view, ISC_TRUE,
  692. NULL, mctx));
  693. if (view->rdclass == dns_rdataclass_in) {
  694. CHECK(load_view_keys(global_keys, vconfig, view, ISC_FALSE,
  695. NULL, mctx));
  696. CHECK(load_view_keys(global_managed_keys, vconfig, view,
  697. ISC_TRUE, NULL, mctx));
  698. }
  699. /*
  700. * Add key zone for managed-keys.
  701. */
  702. obj = NULL;
  703. (void)ns_config_get(maps, "managed-keys-directory", &obj);
  704. directory = obj != NULL ? cfg_obj_asstring(obj) : NULL;
  705. CHECK(add_keydata_zone(view, directory, ns_g_mctx));
  706. cleanup:
  707. return (result);
  708. }
  709. static isc_result_t
  710. mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver) {
  711. const cfg_listelt_t *element;
  712. const cfg_obj_t *obj;
  713. const char *str;
  714. dns_fixedname_t fixed;
  715. dns_name_t *name;
  716. isc_boolean_t value;
  717. isc_result_t result;
  718. isc_buffer_t b;
  719. dns_fixedname_init(&fixed);
  720. name = dns_fixedname_name(&fixed);
  721. for (element = cfg_list_first(mbs);
  722. element != NULL;
  723. element = cfg_list_next(element))
  724. {
  725. obj = cfg_listelt_value(element);
  726. str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
  727. isc_buffer_init(&b, str, strlen(str));
  728. isc_buffer_add(&b, strlen(str));
  729. CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
  730. value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
  731. CHECK(dns_resolver_setmustbesecure(resolver, name, value));
  732. }
  733. result = ISC_R_SUCCESS;
  734. cleanup:
  735. return (result);
  736. }
  737. /*%
  738. * Get a dispatch appropriate for the resolver of a given view.
  739. */
  740. static isc_result_t
  741. get_view_querysource_dispatch(const cfg_obj_t **maps,
  742. int af, dns_dispatch_t **dispatchp,
  743. isc_boolean_t is_firstview)
  744. {
  745. isc_result_t result = ISC_R_FAILURE;
  746. dns_dispatch_t *disp;
  747. isc_sockaddr_t sa;
  748. unsigned int attrs, attrmask;
  749. const cfg_obj_t *obj = NULL;
  750. unsigned int maxdispatchbuffers;
  751. switch (af) {
  752. case AF_INET:
  753. result = ns_config_get(maps, "query-source", &obj);
  754. INSIST(result == ISC_R_SUCCESS);
  755. break;
  756. case AF_INET6:
  757. result = ns_config_get(maps, "query-source-v6", &obj);
  758. INSIST(result == ISC_R_SUCCESS);
  759. break;
  760. default:
  761. INSIST(0);
  762. }
  763. sa = *(cfg_obj_assockaddr(obj));
  764. INSIST(isc_sockaddr_pf(&sa) == af);
  765. /*
  766. * If we don't support this address family, we're done!
  767. */
  768. switch (af) {
  769. case AF_INET:
  770. result = isc_net_probeipv4();
  771. break;
  772. case AF_INET6:
  773. result = isc_net_probeipv6();
  774. break;
  775. default:
  776. INSIST(0);
  777. }
  778. if (result != ISC_R_SUCCESS)
  779. return (ISC_R_SUCCESS);
  780. /*
  781. * Try to find a dispatcher that we can share.
  782. */
  783. attrs = 0;
  784. attrs |= DNS_DISPATCHATTR_UDP;
  785. switch (af) {
  786. case AF_INET:
  787. attrs |= DNS_DISPATCHATTR_IPV4;
  788. break;
  789. case AF_INET6:
  790. attrs |= DNS_DISPATCHATTR_IPV6;
  791. break;
  792. }
  793. if (isc_sockaddr_getport(&sa) == 0) {
  794. attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
  795. maxdispatchbuffers = 4096;
  796. } else {
  797. INSIST(obj != NULL);
  798. if (is_firstview) {
  799. cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO,
  800. "using specific query-source port "
  801. "suppresses port randomization and can be "
  802. "insecure.");
  803. }
  804. maxdispatchbuffers = 1000;
  805. }
  806. attrmask = 0;
  807. attrmask |= DNS_DISPATCHATTR_UDP;
  808. attrmask |= DNS_DISPATCHATTR_TCP;
  809. attrmask |= DNS_DISPATCHATTR_IPV4;
  810. attrmask |= DNS_DISPATCHATTR_IPV6;
  811. disp = NULL;
  812. result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
  813. ns_g_taskmgr, &sa, 4096,
  814. maxdispatchbuffers, 32768, 16411, 16433,
  815. attrs, attrmask, &disp);
  816. if (result != ISC_R_SUCCESS) {
  817. isc_sockaddr_t any;
  818. char buf[ISC_SOCKADDR_FORMATSIZE];
  819. switch (af) {
  820. case AF_INET:
  821. isc_sockaddr_any(&any);
  822. break;
  823. case AF_INET6:
  824. isc_sockaddr_any6(&any);
  825. break;
  826. }
  827. if (isc_sockaddr_equal(&sa, &any))
  828. return (ISC_R_SUCCESS);
  829. isc_sockaddr_format(&sa, buf, sizeof(buf));
  830. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  831. NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
  832. "could not get query source dispatcher (%s)",
  833. buf);
  834. return (result);
  835. }
  836. *dispatchp = disp;
  837. return (ISC_R_SUCCESS);
  838. }
  839. static isc_result_t
  840. configure_order(dns_order_t *order, const cfg_obj_t *ent) {
  841. dns_rdataclass_t rdclass;
  842. dns_rdatatype_t rdtype;
  843. const cfg_obj_t *obj;
  844. dns_fixedname_t fixed;
  845. unsigned int mode = 0;
  846. const char *str;
  847. isc_buffer_t b;
  848. isc_result_t result;
  849. isc_boolean_t addroot;
  850. result = ns_config_getclass(cfg_tuple_get(ent, "class"),
  851. dns_rdataclass_any, &rdclass);
  852. if (result != ISC_R_SUCCESS)
  853. return (result);
  854. result = ns_config_gettype(cfg_tuple_get(ent, "type"),
  855. dns_rdatatype_any, &rdtype);
  856. if (result != ISC_R_SUCCESS)
  857. return (result);
  858. obj = cfg_tuple_get(ent, "name");
  859. if (cfg_obj_isstring(obj))
  860. str = cfg_obj_asstring(obj);
  861. else
  862. str = "*";
  863. addroot = ISC_TF(strcmp(str, "*") == 0);
  864. isc_buffer_init(&b, str, strlen(str));
  865. isc_buffer_add(&b, strlen(str));
  866. dns_fixedname_init(&fixed);
  867. result = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
  868. dns_rootname, 0, NULL);
  869. if (result != ISC_R_SUCCESS)
  870. return (result);
  871. obj = cfg_tuple_get(ent, "ordering");
  872. INSIST(cfg_obj_isstring(obj));
  873. str = cfg_obj_asstring(obj);
  874. if (!strcasecmp(str, "fixed"))
  875. mode = DNS_RDATASETATTR_FIXEDORDER;
  876. else if (!strcasecmp(str, "random"))
  877. mode = DNS_RDATASETATTR_RANDOMIZE;
  878. else if (!strcasecmp(str, "cyclic"))
  879. mode = 0;
  880. else
  881. INSIST(0);
  882. /*
  883. * "*" should match everything including the root (BIND 8 compat).
  884. * As dns_name_matcheswildcard(".", "*.") returns FALSE add a
  885. * explicit entry for "." when the name is "*".
  886. */
  887. if (addroot) {
  888. result = dns_order_add(order, dns_rootname,
  889. rdtype, rdclass, mode);
  890. if (result != ISC_R_SUCCESS)
  891. return (result);
  892. }
  893. return (dns_order_add(order, dns_fixedname_name(&fixed),
  894. rdtype, rdclass, mode));
  895. }
  896. static isc_result_t
  897. configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
  898. isc_netaddr_t na;
  899. dns_peer_t *peer;
  900. const cfg_obj_t *obj;
  901. const char *str;
  902. isc_result_t result;
  903. unsigned int prefixlen;
  904. cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen);
  905. peer = NULL;
  906. result = dns_peer_newprefix(mctx, &na, prefixlen, &peer);
  907. if (result != ISC_R_SUCCESS)
  908. return (result);
  909. obj = NULL;
  910. (void)cfg_map_get(cpeer, "bogus", &obj);
  911. if (obj != NULL)
  912. CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj)));
  913. obj = NULL;
  914. (void)cfg_map_get(cpeer, "provide-ixfr", &obj);
  915. if (obj != NULL)
  916. CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)));
  917. obj = NULL;
  918. (void)cfg_map_get(cpeer, "request-ixfr", &obj);
  919. if (obj != NULL)
  920. CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
  921. obj = NULL;
  922. (void)cfg_map_get(cpeer, "request-nsid", &obj);
  923. if (obj != NULL)
  924. CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj)));
  925. obj = NULL;
  926. (void)cfg_map_get(cpeer, "edns", &obj);
  927. if (obj != NULL)
  928. CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)));
  929. obj = NULL;
  930. (void)cfg_map_get(cpeer, "edns-udp-size", &obj);
  931. if (obj != NULL) {
  932. isc_uint32_t udpsize = cfg_obj_asuint32(obj);
  933. if (udpsize < 512)
  934. udpsize = 512;
  935. if (udpsize > 4096)
  936. udpsize = 4096;
  937. CHECK(dns_peer_setudpsize(peer, (isc_uint16_t)udpsize));
  938. }
  939. obj = NULL;
  940. (void)cfg_map_get(cpeer, "max-udp-size", &obj);
  941. if (obj != NULL) {
  942. isc_uint32_t udpsize = cfg_obj_asuint32(obj);
  943. if (udpsize < 512)
  944. udpsize = 512;
  945. if (udpsize > 4096)
  946. udpsize = 4096;
  947. CHECK(dns_peer_setmaxudp(peer, (isc_uint16_t)udpsize));
  948. }
  949. obj = NULL;
  950. (void)cfg_map_get(cpeer, "transfers", &obj);
  951. if (obj != NULL)
  952. CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj)));
  953. obj = NULL;
  954. (void)cfg_map_get(cpeer, "transfer-format", &obj);
  955. if (obj != NULL) {
  956. str = cfg_obj_asstring(obj);
  957. if (strcasecmp(str, "many-answers") == 0)
  958. CHECK(dns_peer_settransferformat(peer,
  959. dns_many_answers));
  960. else if (strcasecmp(str, "one-answer") == 0)
  961. CHECK(dns_peer_settransferformat(peer,
  962. dns_one_answer));
  963. else
  964. INSIST(0);
  965. }
  966. obj = NULL;
  967. (void)cfg_map_get(cpeer, "keys", &obj);
  968. if (obj != NULL) {
  969. result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj));
  970. if (result != ISC_R_SUCCESS)
  971. goto cleanup;
  972. }
  973. obj = NULL;
  974. if (na.family == AF_INET)
  975. (void)cfg_map_get(cpeer, "transfer-source", &obj);
  976. else
  977. (void)cfg_map_get(cpeer, "transfer-source-v6", &obj);
  978. if (obj != NULL) {
  979. result = dns_peer_settransfersource(peer,
  980. cfg_obj_assockaddr(obj));
  981. if (result != ISC_R_SUCCESS)
  982. goto cleanup;
  983. ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
  984. }
  985. obj = NULL;
  986. if (na.family == AF_INET)
  987. (void)cfg_map_get(cpeer, "notify-source", &obj);
  988. else
  989. (void)cfg_map_get(cpeer, "notify-source-v6", &obj);
  990. if (obj != NULL) {
  991. result = dns_peer_setnotifysource(peer,
  992. cfg_obj_assockaddr(obj));
  993. if (result != ISC_R_SUCCESS)
  994. goto cleanup;
  995. ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
  996. }
  997. obj = NULL;
  998. if (na.family == AF_INET)
  999. (void)cfg_map_get(cpeer, "query-source", &obj);
  1000. else
  1001. (void)cfg_map_get(cpeer, "query-source-v6", &obj);
  1002. if (obj != NULL) {
  1003. result = dns_peer_setquerysource(peer,
  1004. cfg_obj_assockaddr(obj));
  1005. if (result != ISC_R_SUCCESS)
  1006. goto cleanup;
  1007. ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
  1008. }
  1009. *peerp = peer;
  1010. return (ISC_R_SUCCESS);
  1011. cleanup:
  1012. dns_peer_detach(&peer);
  1013. return (result);
  1014. }
  1015. static isc_result_t
  1016. disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
  1017. isc_result_t result;
  1018. const cfg_obj_t *algorithms;
  1019. const cfg_listelt_t *element;
  1020. const char *str;
  1021. dns_fixedname_t fixed;
  1022. dns_name_t *name;
  1023. isc_buffer_t b;
  1024. dns_fixedname_init(&fixed);
  1025. name = dns_fixedname_name(&fixed);
  1026. str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
  1027. isc_buffer_init(&b, str, strlen(str));
  1028. isc_buffer_add(&b, strlen(str));
  1029. CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
  1030. algorithms = cfg_tuple_get(disabled, "algorithms");
  1031. for (element = cfg_list_first(algorithms);
  1032. element != NULL;
  1033. element = cfg_list_next(element))
  1034. {
  1035. isc_textregion_t r;
  1036. dns_secalg_t alg;
  1037. DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
  1038. r.length = strlen(r.base);
  1039. result = dns_secalg_fromtext(&alg, &r);
  1040. if (result != ISC_R_SUCCESS) {
  1041. isc_uint8_t ui;
  1042. result = isc_parse_uint8(&ui, r.base, 10);
  1043. alg = ui;
  1044. }
  1045. if (result != ISC_R_SUCCESS) {
  1046. cfg_obj_log(cfg_listelt_value(element),
  1047. ns_g_lctx, ISC_LOG_ERROR,
  1048. "invalid algorithm");
  1049. CHECK(result);
  1050. }
  1051. CHECK(dns_resolver_disable_algorithm(resolver, name, alg));
  1052. }
  1053. cleanup:
  1054. return (result);
  1055. }
  1056. static isc_boolean_t
  1057. on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) {
  1058. const cfg_listelt_t *element;
  1059. dns_fixedname_t fixed;
  1060. dns_name_t *name;
  1061. isc_result_t result;
  1062. const cfg_obj_t *value;
  1063. const char *str;
  1064. isc_buffer_t b;
  1065. dns_fixedname_init(&fixed);
  1066. name = dns_fixedname_name(&fixed);
  1067. for (element = cfg_list_first(disablelist);
  1068. element != NULL;
  1069. element = cfg_list_next(element))
  1070. {
  1071. value = cfg_listelt_value(element);
  1072. str = cfg_obj_asstring(value);
  1073. isc_buffer_init(&b, str, strlen(str));
  1074. isc_buffer_add(&b, strlen(str));
  1075. result = dns_name_fromtext(name, &b, dns_rootname,
  1076. 0, NULL);
  1077. RUNTIME_CHECK(result == ISC_R_SUCCESS);
  1078. if (dns_name_equal(name, zonename))
  1079. return (ISC_TRUE);
  1080. }
  1081. return (ISC_FALSE);
  1082. }
  1083. static void
  1084. check_dbtype(dns_zone_t **zonep, unsigned int dbtypec, const char **dbargv,
  1085. isc_mem_t *mctx)
  1086. {
  1087. char **argv = NULL;
  1088. unsigned int i;
  1089. isc_result_t result;
  1090. result = dns_zone_getdbtype(*zonep, &argv, mctx);
  1091. if (result != ISC_R_SUCCESS) {
  1092. dns_zone_detach(zonep);
  1093. return;
  1094. }
  1095. /*
  1096. * Check that all the arguments match.
  1097. */
  1098. for (i = 0; i < dbtypec; i++)
  1099. if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) {
  1100. dns_zone_detach(zonep);
  1101. break;
  1102. }
  1103. /*
  1104. * Check that there are not extra arguments.
  1105. */
  1106. if (i == dbtypec && argv[i] != NULL)
  1107. dns_zone_detach(zonep);
  1108. isc_mem_free(mctx, argv);
  1109. }
  1110. static isc_result_t
  1111. setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) {
  1112. isc_result_t result;
  1113. isc_stats_t *zoneqrystats;
  1114. zoneqrystats = NULL;
  1115. if (on) {
  1116. result = isc_stats_create(mctx, &zoneqrystats,
  1117. dns_nsstatscounter_max);
  1118. if (result != ISC_R_SUCCESS)
  1119. return (result);
  1120. }
  1121. dns_zone_setrequeststats(zone, zoneqrystats);
  1122. if (zoneqrystats != NULL)
  1123. isc_stats_detach(&zoneqrystats);
  1124. return (ISC_R_SUCCESS);
  1125. }
  1126. static ns_cache_t *
  1127. cachelist_find(ns_cachelist_t *cachelist, const char *cachename) {
  1128. ns_cache_t *nsc;
  1129. for (nsc = ISC_LIST_HEAD(*cachelist);
  1130. nsc != NULL;
  1131. nsc = ISC_LIST_NEXT(nsc, link)) {
  1132. if (strcmp(dns_cache_getname(nsc->cache), cachename) == 0)
  1133. return (nsc);
  1134. }
  1135. return (NULL);
  1136. }
  1137. static isc_boolean_t
  1138. cache_reusable(dns_view_t *originview, dns_view_t *view,
  1139. isc_boolean_t new_zero_no_soattl)
  1140. {
  1141. if (originview->checknames != view->checknames ||
  1142. dns_resolver_getzeronosoattl(originview->resolver) !=
  1143. new_zero_no_soattl ||
  1144. originview->acceptexpired != view->acceptexpired ||
  1145. originview->enablevalidation != view->enablevalidation ||
  1146. originview->maxcachettl != view->maxcachettl ||
  1147. originview->maxncachettl != view->maxncachettl) {
  1148. return (ISC_FALSE);
  1149. }
  1150. return (ISC_TRUE);
  1151. }
  1152. static isc_boolean_t
  1153. cache_sharable(dns_view_t *originview, dns_view_t *view,
  1154. isc_boolean_t new_zero_no_soattl,
  1155. unsigned int new_cleaning_interval,
  1156. isc_uint32_t new_max_cache_size)
  1157. {
  1158. /*
  1159. * If the cache cannot even reused for the same view, it cannot be
  1160. * shared with other views.
  1161. */
  1162. if (!cache_reusable(originview, view, new_zero_no_soattl))
  1163. return (ISC_FALSE);
  1164. /*
  1165. * Check other cache related parameters that must be consistent among
  1166. * the sharing views.
  1167. */
  1168. if (dns_cache_getcleaninginterval(originview->cache) !=
  1169. new_cleaning_interval ||
  1170. dns_cache_getcachesize(originview->cache) != new_max_cache_size) {
  1171. return (ISC_FALSE);
  1172. }
  1173. return (ISC_TRUE);
  1174. }
  1175. /*
  1176. * Callback from DLZ configure when the driver sets up a writeable zone
  1177. */
  1178. static isc_result_t
  1179. dlzconfigure_callback(dns_view_t *view, dns_zone_t *zone) {
  1180. dns_name_t *origin = dns_zone_getorigin(zone);
  1181. dns_rdataclass_t zclass = view->rdclass;
  1182. isc_result_t result;
  1183. result = dns_zonemgr_managezone(ns_g_server->zonemgr, zone);
  1184. if (result != ISC_R_SUCCESS)
  1185. return result;
  1186. dns_zone_setstats(zone, ns_g_server->zonestats);
  1187. return ns_zone_configure_writeable_dlz(view->dlzdatabase,
  1188. zone, zclass, origin);
  1189. }
  1190. static isc_result_t
  1191. dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na,
  1192. unsigned int prefixlen, const char *server,
  1193. const char *contact)
  1194. {
  1195. char *cp;
  1196. char reverse[48+sizeof("ip6.arpa.")];
  1197. const char *dns64_dbtype[4] = { "_dns64", "dns64", ".", "." };
  1198. const char *sep = ": view ";
  1199. const char *viewname = view->name;
  1200. const unsigned char *s6;
  1201. dns_fixedname_t fixed;
  1202. dns_name_t *name;
  1203. dns_zone_t *zone = NULL;
  1204. int dns64_dbtypec = 4;
  1205. isc_buffer_t b;
  1206. isc_result_t result;
  1207. REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 ||
  1208. prefixlen == 56 || prefixlen == 64 || prefixlen == 96);
  1209. if (!strcmp(viewname, "_default")) {
  1210. sep = "";
  1211. viewname = "";
  1212. }
  1213. /*
  1214. * Construct the reverse name of the zone.
  1215. */
  1216. cp = reverse;
  1217. s6 = na->type.in6.s6_addr;
  1218. while (prefixlen > 0) {
  1219. prefixlen -= 8;
  1220. sprintf(cp, "%x.%x.", s6[prefixlen/8] & 0xf,
  1221. (s6[prefixlen/8] >> 4) & 0xf);
  1222. cp += 4;
  1223. }
  1224. strcat(cp, "ip6.arpa.");
  1225. /*
  1226. * Create the actual zone.
  1227. */
  1228. if (server != NULL)
  1229. dns64_dbtype[2] = server;
  1230. if (contact != NULL)
  1231. dns64_dbtype[3] = contact;
  1232. dns_fixedname_init(&fixed);
  1233. name = dns_fixedname_name(&fixed);
  1234. isc_buffer_init(&b, reverse, strlen(reverse));
  1235. isc_buffer_add(&b, strlen(reverse));
  1236. CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
  1237. CHECK(dns_zone_create(&zone, mctx));
  1238. CHECK(dns_zone_setorigin(zone, name));
  1239. dns_zone_setview(zone, view);
  1240. CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
  1241. dns_zone_setclass(zone, view->rdclass);
  1242. dns_zone_settype(zone, dns_zone_master);
  1243. dns_zone_setstats(zone, ns_g_server->zonestats);
  1244. CHECK(dns_zone_setdbtype(zone, dns64_dbtypec, dns64_dbtype));
  1245. if (view->queryacl != NULL)
  1246. dns_zone_setqueryacl(zone, view->queryacl);
  1247. if (view->queryonacl != NULL)
  1248. dns_zone_setqueryonacl(zone, view->queryonacl);
  1249. dns_zone_setdialup(zone, dns_dialuptype_no);
  1250. dns_zone_setnotifytype(zone, dns_notifytype_no);
  1251. dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, ISC_TRUE);
  1252. CHECK(setquerystats(zone, mctx, ISC_FALSE)); /* XXXMPA */
  1253. CHECK(dns_view_addzone(view, zone));
  1254. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
  1255. ISC_LOG_INFO, "dns64 reverse zone%s%s: %s", sep,
  1256. viewname, reverse);
  1257. cleanup:
  1258. if (zone != NULL)
  1259. dns_zone_detach(&zone);
  1260. return (result);
  1261. }
  1262. static isc_result_t
  1263. configure_rpz(dns_view_t *view, const cfg_listelt_t *element) {
  1264. const cfg_obj_t *rpz_obj, *policy_obj;
  1265. const char *str;
  1266. dns_fixedname_t fixed;
  1267. dns_name_t *origin;
  1268. dns_rpz_zone_t *old, *new;
  1269. dns_zone_t *zone = NULL;
  1270. isc_result_t result;
  1271. unsigned int l1, l2;
  1272. new = isc_mem_get(view->mctx, sizeof(*new));
  1273. if (new == NULL) {
  1274. result = ISC_R_NOMEMORY;
  1275. goto cleanup;
  1276. }
  1277. memset(new, 0, sizeof(*new));
  1278. dns_name_init(&new->nsdname, NULL);
  1279. dns_name_init(&new->origin, NULL);
  1280. dns_name_init(&new->cname, NULL);
  1281. ISC_LIST_INITANDAPPEND(view->rpz_zones, new, link);
  1282. rpz_obj = cfg_listelt_value(element);
  1283. policy_obj = cfg_tuple_get(rpz_obj, "policy");
  1284. if (cfg_obj_isvoid(policy_obj)) {
  1285. new->policy = DNS_RPZ_POLICY_GIVEN;
  1286. } else {
  1287. str = cfg_obj_asstring(policy_obj);
  1288. new->policy = dns_rpz_str2policy(str);
  1289. INSIST(new->policy != DNS_RPZ_POLICY_ERROR);
  1290. }
  1291. dns_fixedname_init(&fixed);
  1292. origin = dns_fixedname_name(&fixed);
  1293. str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "name"));
  1294. result = dns_name_fromstring(origin, str, DNS_NAME_DOWNCASE, NULL);
  1295. if (result != ISC_R_SUCCESS) {
  1296. cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
  1297. "invalid zone '%s'", str);
  1298. goto cleanup;
  1299. }
  1300. result = dns_name_fromstring2(&new->nsdname, DNS_RPZ_NSDNAME_ZONE,
  1301. origin, DNS_NAME_DOWNCASE, view->mctx);
  1302. if (result != ISC_R_SUCCESS) {
  1303. cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
  1304. "invalid zone '%s'", str);
  1305. goto cleanup;
  1306. }
  1307. /*
  1308. * The origin is part of 'nsdname' so we don't need to keep it
  1309. * seperately.
  1310. */
  1311. l1 = dns_name_countlabels(&new->nsdname);
  1312. l2 = dns_name_countlabels(origin);
  1313. dns_name_getlabelsequence(&new->nsdname, l1 - l2, l2, &new->origin);
  1314. /*
  1315. * Are we configured to with the reponse policy zone?
  1316. */
  1317. result = dns_view_findzone(view, &new->origin, &zone);
  1318. if (result != ISC_R_SUCCESS) {
  1319. cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
  1320. "unknown zone '%s'", str);
  1321. goto cleanup;
  1322. }
  1323. if (dns_zone_gettype(zone) != dns_zone_master &&
  1324. dns_zone_gettype(zone) != dns_zone_slave) {
  1325. cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
  1326. "zone '%s' is neither master nor slave", str);
  1327. dns_zone_detach(&zone);
  1328. result = DNS_R_NOTMASTER;
  1329. goto cleanup;
  1330. }
  1331. dns_zone_detach(&zone);
  1332. for (old = ISC_LIST_HEAD(view->rpz_zones);
  1333. old != new;
  1334. old = ISC_LIST_NEXT(old, link)) {
  1335. ++new->num;
  1336. if (dns_name_equal(&old->origin, &new->origin)) {
  1337. cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
  1338. "duplicate '%s'", str);
  1339. result = DNS_R_DUPLICATE;
  1340. goto cleanup;
  1341. }
  1342. }
  1343. if (new->policy == DNS_RPZ_POLICY_CNAME) {
  1344. str = cfg_obj_asstring(cfg_tuple_get(rpz_obj, "cname"));
  1345. result = dns_name_fromstring(&new->cname, str, 0, view->mctx);
  1346. if (result != ISC_R_SUCCESS) {
  1347. cfg_obj_log(rpz_obj, ns_g_lctx, DNS_RPZ_ERROR_LEVEL,
  1348. "invalid cname '%s'", str);
  1349. goto cleanup;
  1350. }
  1351. }
  1352. return (ISC_R_SUCCESS);
  1353. cleanup:
  1354. dns_rpz_view_destroy(view);
  1355. return (result);
  1356. }
  1357. /*
  1358. * Configure 'view' according to 'vconfig', taking defaults from 'config'
  1359. * where values are missing in 'vconfig'.
  1360. *
  1361. * When configuring the default view, 'vconfig' will be NULL and the
  1362. * global defaults in 'config' used exclusively.
  1363. */
  1364. static isc_result_t
  1365. configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
  1366. ns_cachelist_t *cachelist, const cfg_obj_t *bindkeys,
  1367. isc_mem_t *mctx, cfg_aclconfctx_t *actx,
  1368. isc_boolean_t need_hints)
  1369. {
  1370. const cfg_obj_t *maps[4];
  1371. const cfg_obj_t *cfgmaps[3];
  1372. const cfg_obj_t *optionmaps[3];
  1373. const cfg_obj_t *options = NULL;
  1374. const cfg_obj_t *voptions = NULL;
  1375. const cfg_obj_t *forwardtype;
  1376. const cfg_obj_t *forwarders;
  1377. const cfg_obj_t *alternates;
  1378. const cfg_obj_t *zonelist;
  1379. const cfg_obj_t *dlz;
  1380. unsigned int dlzargc;
  1381. char **dlzargv;
  1382. const cfg_obj_t *disabled;
  1383. const cfg_obj_t *obj;
  1384. const cfg_listelt_t *element;
  1385. in_port_t port;
  1386. dns_cache_t *cache = NULL;
  1387. isc_result_t result;
  1388. isc_uint32_t max_adb_size;
  1389. unsigned int cleaning_interval;
  1390. isc_uint32_t max_cache_size;
  1391. isc_uint32_t max_acache_size;
  1392. isc_uint32_t lame_ttl;
  1393. dns_tsig_keyring_t *ring = NULL;
  1394. dns_view_t *pview = NULL; /* Production view */
  1395. isc_mem_t *cmctx = NULL, *hmctx = NULL;
  1396. dns_dispatch_t *dispatch4 = NULL;
  1397. dns_dispatch_t *dispatch6 = NULL;
  1398. isc_boolean_t reused_cache = ISC_FALSE;
  1399. isc_boolean_t shared_cache = ISC_FALSE;
  1400. int i = 0, j = 0, k = 0;
  1401. const char *str;
  1402. const char *cachename = NULL;
  1403. dns_order_t *order = NULL;
  1404. isc_uint32_t udpsize;
  1405. unsigned int resopts = 0;
  1406. dns_zone_t *zone = NULL;
  1407. isc_uint32_t max_clients_per_query;
  1408. const char *sep = ": view ";
  1409. const char *viewname = view->name;
  1410. const char *forview = " for view ";
  1411. isc_boolean_t rfc1918;
  1412. isc_boolean_t empty_zones_enable;
  1413. const cfg_obj_t *disablelist = NULL;
  1414. isc_stats_t *resstats = NULL;
  1415. dns_stats_t *resquerystats = NULL;
  1416. isc_boolean_t auto_dlv = ISC_FALSE;
  1417. isc_boolean_t auto_root = ISC_FALSE;
  1418. ns_cache_t *nsc;
  1419. isc_boolean_t zero_no_soattl;
  1420. dns_acl_t *clients = NULL, *mapped = NULL, *excluded = NULL;
  1421. unsigned int query_timeout;
  1422. struct cfg_context *nzctx;
  1423. REQUIRE(DNS_VIEW_VALID(view));
  1424. if (config != NULL)
  1425. (void)cfg_map_get(config, "options", &options);
  1426. /*
  1427. * maps: view options, options, defaults
  1428. * cfgmaps: view options, config
  1429. * optionmaps: view options, options
  1430. */
  1431. if (vconfig != NULL) {
  1432. voptions = cfg_tuple_get(vconfig, "options");
  1433. maps[i++] = voptions;
  1434. optionmaps[j++] = voptions;
  1435. cfgmaps[k++] = voptions;
  1436. }
  1437. if (options != NULL) {
  1438. maps[i++] = options;
  1439. optionmaps[j++] = options;
  1440. }
  1441. maps[i++] = ns_g_defaults;
  1442. maps[i] = NULL;
  1443. optionmaps[j] = NULL;
  1444. if (config != NULL)
  1445. cfgmaps[k++] = config;
  1446. cfgmaps[k] = NULL;
  1447. if (!strcmp(viewname, "_default")) {
  1448. sep = "";
  1449. viewname = "";
  1450. forview = "";
  1451. POST(forview);
  1452. }
  1453. /*
  1454. * Set the view's port number for outgoing queries.
  1455. */
  1456. CHECKM(ns_config_getport(config, &port), "port");
  1457. dns_view_setdstport(view, port);
  1458. /*
  1459. * Create additional cache for this view and zones under the view
  1460. * if explicitly enabled.
  1461. * XXX950 default to on.
  1462. */
  1463. obj = NULL;
  1464. (void)ns_config_get(maps, "acache-enable", &obj);
  1465. if (obj != NULL && cfg_obj_asboolean(obj)) {
  1466. cmctx = NULL;
  1467. CHECK(isc_mem_create(0, 0, &cmctx));
  1468. CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr,
  1469. ns_g_timermgr));
  1470. isc_mem_setname(cmctx, "acache", NULL);
  1471. isc_mem_detach(&cmctx);
  1472. }
  1473. if (view->acache != NULL) {
  1474. obj = NULL;
  1475. result = ns_config_get(maps, "acache-cleaning-interval", &obj);
  1476. INSIST(result == ISC_R_SUCCESS);
  1477. dns_acache_setcleaninginterval(view->acache,
  1478. cfg_obj_asuint32(obj) * 60);
  1479. obj = NULL;
  1480. result = ns_config_get(maps, "max-acache-size", &obj);
  1481. INSIST(result == ISC_R_SUCCESS);
  1482. if (cfg_obj_isstring(obj)) {
  1483. str = cfg_obj_asstring(obj);
  1484. INSIST(strcasecmp(str, "unlimited") == 0);
  1485. max_acache_size = ISC_UINT32_MAX;
  1486. } else {
  1487. isc_resourcevalue_t value;
  1488. value = cfg_obj_asuint64(obj);
  1489. if (value > ISC_UINT32_MAX) {
  1490. cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
  1491. "'max-acache-size "
  1492. "%" ISC_PRINT_QUADFORMAT
  1493. "d' is too large",
  1494. value);
  1495. result = ISC_R_RANGE;
  1496. goto cleanup;
  1497. }
  1498. max_acache_size = (isc_uint32_t)value;
  1499. }
  1500. dns_acache_setcachesize(view->acache, max_acache_size);
  1501. }
  1502. CHECK(configure_view_acl(vconfig, config, "allow-query", NULL, actx,
  1503. ns_g_mctx, &view->queryacl));
  1504. if (view->queryacl == NULL) {
  1505. CHECK(configure_view_acl(NULL, ns_g_config, "allow-query",
  1506. NULL, actx, ns_g_mctx,
  1507. &view->queryacl));
  1508. }
  1509. /*
  1510. * Configure the zones.
  1511. */
  1512. zonelist = NULL;
  1513. if (voptions != NULL)
  1514. (void)cfg_map_get(voptions, "zone", &zonelist);
  1515. else
  1516. (void)cfg_map_get(config, "zone", &zonelist);
  1517. /*
  1518. * Load zone configuration
  1519. */
  1520. for (element = cfg_list_first(zonelist);
  1521. element != NULL;
  1522. element = cfg_list_next(element))
  1523. {
  1524. const cfg_obj_t *zconfig = cfg_listelt_value(element);
  1525. CHECK(configure_zone(config, zconfig, vconfig, mctx, view,
  1526. actx, ISC_FALSE));
  1527. }
  1528. /*
  1529. * If we're allowing added zones, then load zone configuration
  1530. * from the newzone file for zones that were added during previous
  1531. * runs.
  1532. */
  1533. nzctx = view->new_zone_config;
  1534. if (nzctx != NULL && nzctx->nzconfig != NULL) {
  1535. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  1536. NS_LOGMODULE_SERVER, ISC_LOG_INFO,
  1537. "loading additional zones for view '%s'",
  1538. view->name);
  1539. zonelist = NULL;
  1540. cfg_map_get(nzctx->nzconfig, "zone", &zonelist);
  1541. for (element = cfg_list_first(zonelist);
  1542. element != NULL;
  1543. element = cfg_list_next(element))
  1544. {
  1545. const cfg_obj_t *zconfig = cfg_listelt_value(element);
  1546. CHECK(configure_zone(config, zconfig, vconfig,
  1547. mctx, view, actx,
  1548. ISC_TRUE));
  1549. }
  1550. }
  1551. /*
  1552. * Create Dynamically Loadable Zone driver.
  1553. */
  1554. dlz = NULL;
  1555. if (voptions != NULL)
  1556. (void)cfg_map_get(voptions, "dlz", &dlz);
  1557. else
  1558. (void)cfg_map_get(config, "dlz", &dlz);
  1559. obj = NULL;
  1560. if (dlz != NULL) {
  1561. (void)cfg_map_get(cfg_tuple_get(dlz, "options"),
  1562. "database", &obj);
  1563. if (obj != NULL) {
  1564. char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
  1565. if (s == NULL) {
  1566. result = ISC_R_NOMEMORY;
  1567. goto cleanup;
  1568. }
  1569. result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv);
  1570. if (result != ISC_R_SUCCESS) {
  1571. isc_mem_free(mctx, s);
  1572. goto cleanup;
  1573. }
  1574. obj = cfg_tuple_get(dlz, "name");
  1575. result = dns_dlzcreate(mctx, cfg_obj_asstring(obj),
  1576. dlzargv[0], dlzargc, dlzargv,
  1577. &view->dlzdatabase);
  1578. isc_mem_free(mctx, s);
  1579. isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv));
  1580. if (result != ISC_R_SUCCESS)
  1581. goto cleanup;
  1582. /*
  1583. * If the dlz backend supports configuration,
  1584. * then call its configure method now.
  1585. */
  1586. result = dns_dlzconfigure(view, dlzconfigure_callback);
  1587. if (result != ISC_R_SUCCESS)
  1588. goto cleanup;
  1589. }
  1590. }
  1591. /*
  1592. * Obtain configuration parameters that affect the decision of whether
  1593. * we can reuse/share an existing cache.
  1594. */
  1595. obj = NULL;
  1596. result = ns_config_get(maps, "cleaning-interval", &obj);
  1597. INSIST(result == ISC_R_SUCCESS);
  1598. cleaning_interval = cfg_obj_asuint32(obj) * 60;
  1599. obj = NULL;
  1600. result = ns_config_get(maps, "max-cache-size", &obj);
  1601. INSIST(result == ISC_R_SUCCESS);
  1602. if (cfg_obj_isstring(obj)) {
  1603. str = cfg_obj_asstring(obj);
  1604. INSIST(strcasecmp(str, "unlimited") == 0);
  1605. max_cache_size = ISC_UINT32_MAX;
  1606. } else {
  1607. isc_resourcevalue_t value;
  1608. value = cfg_obj_asuint64(obj);
  1609. if (value > ISC_UINT32_MAX) {
  1610. cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
  1611. "'max-cache-size "
  1612. "%" ISC_PRINT_QUADFORMAT "d' is too large",
  1613. value);
  1614. result = ISC_R_RANGE;
  1615. goto cleanup;
  1616. }
  1617. max_cache_size = (isc_uint32_t)value;
  1618. }
  1619. /* Check-names. */
  1620. obj = NULL;
  1621. result = ns_checknames_get(maps, "response", &obj);
  1622. INSIST(result == ISC_R_SUCCESS);
  1623. str = cfg_obj_asstring(obj);
  1624. if (strcasecmp(str, "fail") == 0) {
  1625. resopts |= DNS_RESOLVER_CHECKNAMES |
  1626. DNS_RESOLVER_CHECKNAMESFAIL;
  1627. view->checknames = ISC_TRUE;
  1628. } else if (strcasecmp(str, "warn") == 0) {
  1629. resopts |= DNS_RESOLVER_CHECKNAMES;
  1630. view->checknames = ISC_FALSE;
  1631. } else if (strcasecmp(str, "ignore") == 0) {
  1632. view->chec