/contrib/bind9/bin/named/zoneconf.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1500 lines · 1200 code · 165 blank · 135 comment · 500 complexity · 6995061632f144c357c2e2c9d3946a7a MD5 · raw 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: zoneconf.c,v 1.170.14.7 2012/01/31 23:46:39 tbox Exp $ */
  18. /*% */
  19. #include <config.h>
  20. #include <isc/buffer.h>
  21. #include <isc/file.h>
  22. #include <isc/mem.h>
  23. #include <isc/print.h>
  24. #include <isc/stats.h>
  25. #include <isc/string.h> /* Required for HP/UX (and others?) */
  26. #include <isc/util.h>
  27. #include <dns/acl.h>
  28. #include <dns/db.h>
  29. #include <dns/fixedname.h>
  30. #include <dns/log.h>
  31. #include <dns/name.h>
  32. #include <dns/rdata.h>
  33. #include <dns/rdatatype.h>
  34. #include <dns/rdataset.h>
  35. #include <dns/rdatalist.h>
  36. #include <dns/result.h>
  37. #include <dns/sdlz.h>
  38. #include <dns/ssu.h>
  39. #include <dns/stats.h>
  40. #include <dns/view.h>
  41. #include <dns/zone.h>
  42. #include <named/client.h>
  43. #include <named/config.h>
  44. #include <named/globals.h>
  45. #include <named/log.h>
  46. #include <named/server.h>
  47. #include <named/zoneconf.h>
  48. /* ACLs associated with zone */
  49. typedef enum {
  50. allow_notify,
  51. allow_query,
  52. allow_transfer,
  53. allow_update,
  54. allow_update_forwarding
  55. } acl_type_t;
  56. #define RETERR(x) do { \
  57. isc_result_t _r = (x); \
  58. if (_r != ISC_R_SUCCESS) \
  59. return (_r); \
  60. } while (0)
  61. #define CHECK(x) do { \
  62. result = (x); \
  63. if (result != ISC_R_SUCCESS) \
  64. goto cleanup; \
  65. } while (0)
  66. /*%
  67. * Convenience function for configuring a single zone ACL.
  68. */
  69. static isc_result_t
  70. configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
  71. const cfg_obj_t *config, acl_type_t acltype,
  72. cfg_aclconfctx_t *actx, dns_zone_t *zone,
  73. void (*setzacl)(dns_zone_t *, dns_acl_t *),
  74. void (*clearzacl)(dns_zone_t *))
  75. {
  76. isc_result_t result;
  77. const cfg_obj_t *maps[5] = {NULL, NULL, NULL, NULL, NULL};
  78. const cfg_obj_t *aclobj = NULL;
  79. int i = 0;
  80. dns_acl_t **aclp = NULL, *acl = NULL;
  81. const char *aclname;
  82. dns_view_t *view;
  83. view = dns_zone_getview(zone);
  84. switch (acltype) {
  85. case allow_notify:
  86. if (view != NULL)
  87. aclp = &view->notifyacl;
  88. aclname = "allow-notify";
  89. break;
  90. case allow_query:
  91. if (view != NULL)
  92. aclp = &view->queryacl;
  93. aclname = "allow-query";
  94. break;
  95. case allow_transfer:
  96. if (view != NULL)
  97. aclp = &view->transferacl;
  98. aclname = "allow-transfer";
  99. break;
  100. case allow_update:
  101. if (view != NULL)
  102. aclp = &view->updateacl;
  103. aclname = "allow-update";
  104. break;
  105. case allow_update_forwarding:
  106. if (view != NULL)
  107. aclp = &view->upfwdacl;
  108. aclname = "allow-update-forwarding";
  109. break;
  110. default:
  111. INSIST(0);
  112. return (ISC_R_FAILURE);
  113. }
  114. /* First check to see if ACL is defined within the zone */
  115. if (zconfig != NULL) {
  116. maps[0] = cfg_tuple_get(zconfig, "options");
  117. (void)ns_config_get(maps, aclname, &aclobj);
  118. if (aclobj != NULL) {
  119. aclp = NULL;
  120. goto parse_acl;
  121. }
  122. }
  123. /* Failing that, see if there's a default ACL already in the view */
  124. if (aclp != NULL && *aclp != NULL) {
  125. (*setzacl)(zone, *aclp);
  126. return (ISC_R_SUCCESS);
  127. }
  128. /* Check for default ACLs that haven't been parsed yet */
  129. if (vconfig != NULL) {
  130. const cfg_obj_t *options = cfg_tuple_get(vconfig, "options");
  131. if (options != NULL)
  132. maps[i++] = options;
  133. }
  134. if (config != NULL) {
  135. const cfg_obj_t *options = NULL;
  136. (void)cfg_map_get(config, "options", &options);
  137. if (options != NULL)
  138. maps[i++] = options;
  139. }
  140. maps[i++] = ns_g_defaults;
  141. maps[i] = NULL;
  142. (void)ns_config_get(maps, aclname, &aclobj);
  143. if (aclobj == NULL) {
  144. (*clearzacl)(zone);
  145. return (ISC_R_SUCCESS);
  146. }
  147. parse_acl:
  148. result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx,
  149. dns_zone_getmctx(zone), 0, &acl);
  150. if (result != ISC_R_SUCCESS)
  151. return (result);
  152. (*setzacl)(zone, acl);
  153. /* Set the view default now */
  154. if (aclp != NULL)
  155. dns_acl_attach(acl, aclp);
  156. dns_acl_detach(&acl);
  157. return (ISC_R_SUCCESS);
  158. }
  159. /*%
  160. * Parse the zone update-policy statement.
  161. */
  162. static isc_result_t
  163. configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
  164. const char *zname)
  165. {
  166. const cfg_obj_t *updatepolicy = NULL;
  167. const cfg_listelt_t *element, *element2;
  168. dns_ssutable_t *table = NULL;
  169. isc_mem_t *mctx = dns_zone_getmctx(zone);
  170. isc_boolean_t autoddns = ISC_FALSE;
  171. isc_result_t result;
  172. (void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
  173. if (updatepolicy == NULL) {
  174. dns_zone_setssutable(zone, NULL);
  175. return (ISC_R_SUCCESS);
  176. }
  177. if (cfg_obj_isstring(updatepolicy) &&
  178. strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) {
  179. autoddns = ISC_TRUE;
  180. updatepolicy = NULL;
  181. }
  182. result = dns_ssutable_create(mctx, &table);
  183. if (result != ISC_R_SUCCESS)
  184. return (result);
  185. for (element = cfg_list_first(updatepolicy);
  186. element != NULL;
  187. element = cfg_list_next(element))
  188. {
  189. const cfg_obj_t *stmt = cfg_listelt_value(element);
  190. const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode");
  191. const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
  192. const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
  193. const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
  194. const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
  195. const char *str;
  196. isc_boolean_t grant = ISC_FALSE;
  197. isc_boolean_t usezone = ISC_FALSE;
  198. unsigned int mtype = DNS_SSUMATCHTYPE_NAME;
  199. dns_fixedname_t fname, fident;
  200. isc_buffer_t b;
  201. dns_rdatatype_t *types;
  202. unsigned int i, n;
  203. str = cfg_obj_asstring(mode);
  204. if (strcasecmp(str, "grant") == 0)
  205. grant = ISC_TRUE;
  206. else if (strcasecmp(str, "deny") == 0)
  207. grant = ISC_FALSE;
  208. else
  209. INSIST(0);
  210. str = cfg_obj_asstring(matchtype);
  211. if (strcasecmp(str, "name") == 0)
  212. mtype = DNS_SSUMATCHTYPE_NAME;
  213. else if (strcasecmp(str, "subdomain") == 0)
  214. mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
  215. else if (strcasecmp(str, "wildcard") == 0)
  216. mtype = DNS_SSUMATCHTYPE_WILDCARD;
  217. else if (strcasecmp(str, "self") == 0)
  218. mtype = DNS_SSUMATCHTYPE_SELF;
  219. else if (strcasecmp(str, "selfsub") == 0)
  220. mtype = DNS_SSUMATCHTYPE_SELFSUB;
  221. else if (strcasecmp(str, "selfwild") == 0)
  222. mtype = DNS_SSUMATCHTYPE_SELFWILD;
  223. else if (strcasecmp(str, "ms-self") == 0)
  224. mtype = DNS_SSUMATCHTYPE_SELFMS;
  225. else if (strcasecmp(str, "krb5-self") == 0)
  226. mtype = DNS_SSUMATCHTYPE_SELFKRB5;
  227. else if (strcasecmp(str, "ms-subdomain") == 0)
  228. mtype = DNS_SSUMATCHTYPE_SUBDOMAINMS;
  229. else if (strcasecmp(str, "krb5-subdomain") == 0)
  230. mtype = DNS_SSUMATCHTYPE_SUBDOMAINKRB5;
  231. else if (strcasecmp(str, "tcp-self") == 0)
  232. mtype = DNS_SSUMATCHTYPE_TCPSELF;
  233. else if (strcasecmp(str, "6to4-self") == 0)
  234. mtype = DNS_SSUMATCHTYPE_6TO4SELF;
  235. else if (strcasecmp(str, "zonesub") == 0) {
  236. mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
  237. usezone = ISC_TRUE;
  238. } else if (strcasecmp(str, "external") == 0)
  239. mtype = DNS_SSUMATCHTYPE_EXTERNAL;
  240. else
  241. INSIST(0);
  242. dns_fixedname_init(&fident);
  243. str = cfg_obj_asstring(identity);
  244. isc_buffer_init(&b, str, strlen(str));
  245. isc_buffer_add(&b, strlen(str));
  246. result = dns_name_fromtext(dns_fixedname_name(&fident), &b,
  247. dns_rootname, 0, NULL);
  248. if (result != ISC_R_SUCCESS) {
  249. cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
  250. "'%s' is not a valid name", str);
  251. goto cleanup;
  252. }
  253. dns_fixedname_init(&fname);
  254. if (usezone) {
  255. result = dns_name_copy(dns_zone_getorigin(zone),
  256. dns_fixedname_name(&fname),
  257. NULL);
  258. if (result != ISC_R_SUCCESS) {
  259. cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
  260. "error copying origin: %s",
  261. isc_result_totext(result));
  262. goto cleanup;
  263. }
  264. } else {
  265. str = cfg_obj_asstring(dname);
  266. isc_buffer_init(&b, str, strlen(str));
  267. isc_buffer_add(&b, strlen(str));
  268. result = dns_name_fromtext(dns_fixedname_name(&fname),
  269. &b, dns_rootname, 0, NULL);
  270. if (result != ISC_R_SUCCESS) {
  271. cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
  272. "'%s' is not a valid name", str);
  273. goto cleanup;
  274. }
  275. }
  276. n = ns_config_listcount(typelist);
  277. if (n == 0)
  278. types = NULL;
  279. else {
  280. types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t));
  281. if (types == NULL) {
  282. result = ISC_R_NOMEMORY;
  283. goto cleanup;
  284. }
  285. }
  286. i = 0;
  287. for (element2 = cfg_list_first(typelist);
  288. element2 != NULL;
  289. element2 = cfg_list_next(element2))
  290. {
  291. const cfg_obj_t *typeobj;
  292. isc_textregion_t r;
  293. INSIST(i < n);
  294. typeobj = cfg_listelt_value(element2);
  295. str = cfg_obj_asstring(typeobj);
  296. DE_CONST(str, r.base);
  297. r.length = strlen(str);
  298. result = dns_rdatatype_fromtext(&types[i++], &r);
  299. if (result != ISC_R_SUCCESS) {
  300. cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
  301. "'%s' is not a valid type", str);
  302. isc_mem_put(mctx, types,
  303. n * sizeof(dns_rdatatype_t));
  304. goto cleanup;
  305. }
  306. }
  307. INSIST(i == n);
  308. result = dns_ssutable_addrule(table, grant,
  309. dns_fixedname_name(&fident),
  310. mtype,
  311. dns_fixedname_name(&fname),
  312. n, types);
  313. if (types != NULL)
  314. isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t));
  315. if (result != ISC_R_SUCCESS) {
  316. goto cleanup;
  317. }
  318. }
  319. /*
  320. * If "update-policy local;" and a session key exists,
  321. * then use the default policy, which is equivalent to:
  322. * update-policy { grant <session-keyname> zonesub any; };
  323. */
  324. if (autoddns) {
  325. dns_rdatatype_t any = dns_rdatatype_any;
  326. if (ns_g_server->session_keyname == NULL) {
  327. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  328. NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
  329. "failed to enable auto DDNS policy "
  330. "for zone %s: session key not found",
  331. zname);
  332. result = ISC_R_NOTFOUND;
  333. goto cleanup;
  334. }
  335. result = dns_ssutable_addrule(table, ISC_TRUE,
  336. ns_g_server->session_keyname,
  337. DNS_SSUMATCHTYPE_SUBDOMAIN,
  338. dns_zone_getorigin(zone),
  339. 1, &any);
  340. if (result != ISC_R_SUCCESS)
  341. goto cleanup;
  342. }
  343. result = ISC_R_SUCCESS;
  344. dns_zone_setssutable(zone, table);
  345. cleanup:
  346. dns_ssutable_detach(&table);
  347. return (result);
  348. }
  349. /*
  350. * This is the TTL used for internally generated RRsets for static-stub zones.
  351. * The value doesn't matter because the mapping is static, but needs to be
  352. * defined for the sake of implementation.
  353. */
  354. #define STATICSTUB_SERVER_TTL 86400
  355. /*%
  356. * Configure an apex NS with glues for a static-stub zone.
  357. * For example, for the zone named "example.com", the following RRs will be
  358. * added to the zone DB:
  359. * example.com. NS example.com.
  360. * example.com. A 192.0.2.1
  361. * example.com. AAAA 2001:db8::1
  362. */
  363. static isc_result_t
  364. configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone,
  365. dns_rdatalist_t *rdatalist_ns,
  366. dns_rdatalist_t *rdatalist_a,
  367. dns_rdatalist_t *rdatalist_aaaa)
  368. {
  369. const cfg_listelt_t *element;
  370. isc_mem_t *mctx = dns_zone_getmctx(zone);
  371. isc_region_t region, sregion;
  372. dns_rdata_t *rdata;
  373. isc_result_t result = ISC_R_SUCCESS;
  374. for (element = cfg_list_first(zconfig);
  375. element != NULL;
  376. element = cfg_list_next(element))
  377. {
  378. const isc_sockaddr_t* sa;
  379. isc_netaddr_t na;
  380. const cfg_obj_t *address = cfg_listelt_value(element);
  381. dns_rdatalist_t *rdatalist;
  382. sa = cfg_obj_assockaddr(address);
  383. if (isc_sockaddr_getport(sa) != 0) {
  384. cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
  385. "port is not configurable for "
  386. "static stub server-addresses");
  387. return (ISC_R_FAILURE);
  388. }
  389. isc_netaddr_fromsockaddr(&na, sa);
  390. if (isc_netaddr_getzone(&na) != 0) {
  391. cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
  392. "scoped address is not allowed "
  393. "for static stub "
  394. "server-addresses");
  395. return (ISC_R_FAILURE);
  396. }
  397. switch (na.family) {
  398. case AF_INET:
  399. region.length = sizeof(na.type.in);
  400. rdatalist = rdatalist_a;
  401. break;
  402. default:
  403. INSIST(na.family == AF_INET6);
  404. region.length = sizeof(na.type.in6);
  405. rdatalist = rdatalist_aaaa;
  406. break;
  407. }
  408. rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length);
  409. if (rdata == NULL)
  410. return (ISC_R_NOMEMORY);
  411. region.base = (unsigned char *)(rdata + 1);
  412. memcpy(region.base, &na.type, region.length);
  413. dns_rdata_init(rdata);
  414. dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
  415. rdatalist->type, &region);
  416. ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  417. }
  418. /*
  419. * If no address is specified (unlikely in this context, but possible),
  420. * there's nothing to do anymore.
  421. */
  422. if (ISC_LIST_EMPTY(rdatalist_a->rdata) &&
  423. ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) {
  424. return (ISC_R_SUCCESS);
  425. }
  426. /* Add to the list an apex NS with the ns name being the origin name */
  427. dns_name_toregion(dns_zone_getorigin(zone), &sregion);
  428. rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
  429. if (rdata == NULL) {
  430. /*
  431. * Already allocated data will be freed in the caller, so
  432. * we can simply return here.
  433. */
  434. return (ISC_R_NOMEMORY);
  435. }
  436. region.length = sregion.length;
  437. region.base = (unsigned char *)(rdata + 1);
  438. memcpy(region.base, sregion.base, region.length);
  439. dns_rdata_init(rdata);
  440. dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
  441. dns_rdatatype_ns, &region);
  442. ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link);
  443. return (result);
  444. }
  445. /*%
  446. * Configure an apex NS with an out-of-zone NS names for a static-stub zone.
  447. * For example, for the zone named "example.com", something like the following
  448. * RRs will be added to the zone DB:
  449. * example.com. NS ns.example.net.
  450. */
  451. static isc_result_t
  452. configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone,
  453. dns_rdatalist_t *rdatalist, const char *zname)
  454. {
  455. const cfg_listelt_t *element;
  456. isc_mem_t *mctx = dns_zone_getmctx(zone);
  457. dns_rdata_t *rdata;
  458. isc_region_t sregion, region;
  459. isc_result_t result = ISC_R_SUCCESS;
  460. for (element = cfg_list_first(zconfig);
  461. element != NULL;
  462. element = cfg_list_next(element))
  463. {
  464. const cfg_obj_t *obj;
  465. const char *str;
  466. dns_fixedname_t fixed_name;
  467. dns_name_t *nsname;
  468. isc_buffer_t b;
  469. obj = cfg_listelt_value(element);
  470. str = cfg_obj_asstring(obj);
  471. dns_fixedname_init(&fixed_name);
  472. nsname = dns_fixedname_name(&fixed_name);
  473. isc_buffer_init(&b, str, strlen(str));
  474. isc_buffer_add(&b, strlen(str));
  475. result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL);
  476. if (result != ISC_R_SUCCESS) {
  477. cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
  478. "server-name '%s' is not a valid "
  479. "name", str);
  480. return (result);
  481. }
  482. if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) {
  483. cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
  484. "server-name '%s' must not be a "
  485. "subdomain of zone name '%s'",
  486. str, zname);
  487. return (ISC_R_FAILURE);
  488. }
  489. dns_name_toregion(nsname, &sregion);
  490. rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
  491. if (rdata == NULL)
  492. return (ISC_R_NOMEMORY);
  493. region.length = sregion.length;
  494. region.base = (unsigned char *)(rdata + 1);
  495. memcpy(region.base, sregion.base, region.length);
  496. dns_rdata_init(rdata);
  497. dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
  498. dns_rdatatype_ns, &region);
  499. ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
  500. }
  501. return (result);
  502. }
  503. /*%
  504. * Configure static-stub zone.
  505. */
  506. static isc_result_t
  507. configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone,
  508. const char *zname, const char *dbtype)
  509. {
  510. int i = 0;
  511. const cfg_obj_t *obj;
  512. isc_mem_t *mctx = dns_zone_getmctx(zone);
  513. dns_db_t *db = NULL;
  514. dns_dbversion_t *dbversion = NULL;
  515. dns_dbnode_t *apexnode = NULL;
  516. dns_name_t apexname;
  517. isc_result_t result;
  518. dns_rdataset_t rdataset;
  519. dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa;
  520. dns_rdatalist_t* rdatalists[] = {
  521. &rdatalist_ns, &rdatalist_a, &rdatalist_aaaa, NULL
  522. };
  523. dns_rdata_t *rdata;
  524. isc_region_t region;
  525. /* Create the DB beforehand */
  526. RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone),
  527. dns_dbtype_stub, dns_zone_getclass(zone),
  528. 0, NULL, &db));
  529. dns_zone_setdb(zone, db);
  530. dns_rdatalist_init(&rdatalist_ns);
  531. rdatalist_ns.rdclass = dns_zone_getclass(zone);
  532. rdatalist_ns.type = dns_rdatatype_ns;
  533. rdatalist_ns.ttl = STATICSTUB_SERVER_TTL;
  534. dns_rdatalist_init(&rdatalist_a);
  535. rdatalist_a.rdclass = dns_zone_getclass(zone);
  536. rdatalist_a.type = dns_rdatatype_a;
  537. rdatalist_a.ttl = STATICSTUB_SERVER_TTL;
  538. dns_rdatalist_init(&rdatalist_aaaa);
  539. rdatalist_aaaa.rdclass = dns_zone_getclass(zone);
  540. rdatalist_aaaa.type = dns_rdatatype_aaaa;
  541. rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL;
  542. /* Prepare zone RRs from the configuration */
  543. obj = NULL;
  544. result = cfg_map_get(zconfig, "server-addresses", &obj);
  545. if (result == ISC_R_SUCCESS) {
  546. INSIST(obj != NULL);
  547. result = configure_staticstub_serveraddrs(obj, zone,
  548. &rdatalist_ns,
  549. &rdatalist_a,
  550. &rdatalist_aaaa);
  551. if (result != ISC_R_SUCCESS)
  552. goto cleanup;
  553. }
  554. obj = NULL;
  555. result = cfg_map_get(zconfig, "server-names", &obj);
  556. if (result == ISC_R_SUCCESS) {
  557. INSIST(obj != NULL);
  558. result = configure_staticstub_servernames(obj, zone,
  559. &rdatalist_ns,
  560. zname);
  561. if (result != ISC_R_SUCCESS)
  562. goto cleanup;
  563. }
  564. /*
  565. * Sanity check: there should be at least one NS RR at the zone apex
  566. * to trigger delegation.
  567. */
  568. if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) {
  569. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  570. NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
  571. "No NS record is configured for a "
  572. "static-stub zone '%s'", zname);
  573. result = ISC_R_FAILURE;
  574. goto cleanup;
  575. }
  576. /*
  577. * Now add NS and glue A/AAAA RRsets to the zone DB.
  578. * First open a new version for the add operation and get a pointer
  579. * to the apex node (all RRs are of the apex name).
  580. */
  581. result = dns_db_newversion(db, &dbversion);
  582. if (result != ISC_R_SUCCESS)
  583. goto cleanup;
  584. dns_name_init(&apexname, NULL);
  585. dns_name_clone(dns_zone_getorigin(zone), &apexname);
  586. result = dns_db_findnode(db, &apexname, ISC_FALSE, &apexnode);
  587. if (result != ISC_R_SUCCESS)
  588. goto cleanup;
  589. /* Add NS RRset */
  590. dns_rdataset_init(&rdataset);
  591. RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset)
  592. == ISC_R_SUCCESS);
  593. result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
  594. 0, NULL);
  595. dns_rdataset_disassociate(&rdataset);
  596. if (result != ISC_R_SUCCESS)
  597. goto cleanup;
  598. /* Add glue A RRset, if any */
  599. if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) {
  600. RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_a, &rdataset)
  601. == ISC_R_SUCCESS);
  602. result = dns_db_addrdataset(db, apexnode, dbversion, 0,
  603. &rdataset, 0, NULL);
  604. dns_rdataset_disassociate(&rdataset);
  605. if (result != ISC_R_SUCCESS)
  606. goto cleanup;
  607. }
  608. /* Add glue AAAA RRset, if any */
  609. if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) {
  610. RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_aaaa,
  611. &rdataset)
  612. == ISC_R_SUCCESS);
  613. result = dns_db_addrdataset(db, apexnode, dbversion, 0,
  614. &rdataset, 0, NULL);
  615. dns_rdataset_disassociate(&rdataset);
  616. if (result != ISC_R_SUCCESS)
  617. goto cleanup;
  618. }
  619. result = ISC_R_SUCCESS;
  620. cleanup:
  621. if (apexnode != NULL)
  622. dns_db_detachnode(db, &apexnode);
  623. if (dbversion != NULL)
  624. dns_db_closeversion(db, &dbversion, ISC_TRUE);
  625. if (db != NULL)
  626. dns_db_detach(&db);
  627. for (i = 0; rdatalists[i] != NULL; i++) {
  628. while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) {
  629. ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link);
  630. dns_rdata_toregion(rdata, &region);
  631. isc_mem_put(mctx, rdata,
  632. sizeof(*rdata) + region.length);
  633. }
  634. }
  635. return (result);
  636. }
  637. /*%
  638. * Convert a config file zone type into a server zone type.
  639. */
  640. static inline dns_zonetype_t
  641. zonetype_fromconfig(const cfg_obj_t *map) {
  642. const cfg_obj_t *obj = NULL;
  643. isc_result_t result;
  644. result = cfg_map_get(map, "type", &obj);
  645. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  646. return (ns_config_getzonetype(obj));
  647. }
  648. /*%
  649. * Helper function for strtoargv(). Pardon the gratuitous recursion.
  650. */
  651. static isc_result_t
  652. strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp,
  653. char ***argvp, unsigned int n)
  654. {
  655. isc_result_t result;
  656. /* Discard leading whitespace. */
  657. while (*s == ' ' || *s == '\t')
  658. s++;
  659. if (*s == '\0') {
  660. /* We have reached the end of the string. */
  661. *argcp = n;
  662. *argvp = isc_mem_get(mctx, n * sizeof(char *));
  663. if (*argvp == NULL)
  664. return (ISC_R_NOMEMORY);
  665. } else {
  666. char *p = s;
  667. while (*p != ' ' && *p != '\t' && *p != '\0')
  668. p++;
  669. if (*p != '\0')
  670. *p++ = '\0';
  671. result = strtoargvsub(mctx, p, argcp, argvp, n + 1);
  672. if (result != ISC_R_SUCCESS)
  673. return (result);
  674. (*argvp)[n] = s;
  675. }
  676. return (ISC_R_SUCCESS);
  677. }
  678. /*%
  679. * Tokenize the string "s" into whitespace-separated words,
  680. * return the number of words in '*argcp' and an array
  681. * of pointers to the words in '*argvp'. The caller
  682. * must free the array using isc_mem_put(). The string
  683. * is modified in-place.
  684. */
  685. static isc_result_t
  686. strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) {
  687. return (strtoargvsub(mctx, s, argcp, argvp, 0));
  688. }
  689. static void
  690. checknames(dns_zonetype_t ztype, const cfg_obj_t **maps,
  691. const cfg_obj_t **objp)
  692. {
  693. const char *zone = NULL;
  694. isc_result_t result;
  695. switch (ztype) {
  696. case dns_zone_slave: zone = "slave"; break;
  697. case dns_zone_master: zone = "master"; break;
  698. default:
  699. INSIST(0);
  700. }
  701. result = ns_checknames_get(maps, zone, objp);
  702. INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL);
  703. }
  704. isc_result_t
  705. ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
  706. const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
  707. dns_zone_t *zone)
  708. {
  709. isc_result_t result;
  710. const char *zname;
  711. dns_rdataclass_t zclass;
  712. dns_rdataclass_t vclass;
  713. const cfg_obj_t *maps[5];
  714. const cfg_obj_t *zoptions = NULL;
  715. const cfg_obj_t *options = NULL;
  716. const cfg_obj_t *obj;
  717. const char *filename = NULL;
  718. dns_notifytype_t notifytype = dns_notifytype_yes;
  719. isc_sockaddr_t *addrs;
  720. dns_name_t **keynames;
  721. isc_uint32_t count;
  722. char *cpval;
  723. unsigned int dbargc;
  724. char **dbargv;
  725. static char default_dbtype[] = "rbt";
  726. isc_mem_t *mctx = dns_zone_getmctx(zone);
  727. dns_dialuptype_t dialup = dns_dialuptype_no;
  728. dns_zonetype_t ztype;
  729. int i;
  730. isc_int32_t journal_size;
  731. isc_boolean_t multi;
  732. isc_boolean_t alt;
  733. dns_view_t *view;
  734. isc_boolean_t check = ISC_FALSE, fail = ISC_FALSE;
  735. isc_boolean_t warn = ISC_FALSE, ignore = ISC_FALSE;
  736. isc_boolean_t ixfrdiff;
  737. dns_masterformat_t masterformat;
  738. isc_stats_t *zoneqrystats;
  739. isc_boolean_t zonestats_on;
  740. int seconds;
  741. i = 0;
  742. if (zconfig != NULL) {
  743. zoptions = cfg_tuple_get(zconfig, "options");
  744. maps[i++] = zoptions;
  745. }
  746. if (vconfig != NULL)
  747. maps[i++] = cfg_tuple_get(vconfig, "options");
  748. if (config != NULL) {
  749. (void)cfg_map_get(config, "options", &options);
  750. if (options != NULL)
  751. maps[i++] = options;
  752. }
  753. maps[i++] = ns_g_defaults;
  754. maps[i] = NULL;
  755. if (vconfig != NULL)
  756. RETERR(ns_config_getclass(cfg_tuple_get(vconfig, "class"),
  757. dns_rdataclass_in, &vclass));
  758. else
  759. vclass = dns_rdataclass_in;
  760. /*
  761. * Configure values common to all zone types.
  762. */
  763. zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
  764. RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
  765. vclass, &zclass));
  766. dns_zone_setclass(zone, zclass);
  767. ztype = zonetype_fromconfig(zoptions);
  768. dns_zone_settype(zone, ztype);
  769. obj = NULL;
  770. result = cfg_map_get(zoptions, "database", &obj);
  771. if (result == ISC_R_SUCCESS)
  772. cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
  773. else
  774. cpval = default_dbtype;
  775. if (cpval == NULL)
  776. return(ISC_R_NOMEMORY);
  777. result = strtoargv(mctx, cpval, &dbargc, &dbargv);
  778. if (result != ISC_R_SUCCESS && cpval != default_dbtype) {
  779. isc_mem_free(mctx, cpval);
  780. return (result);
  781. }
  782. /*
  783. * ANSI C is strange here. There is no logical reason why (char **)
  784. * cannot be promoted automatically to (const char * const *) by the
  785. * compiler w/o generating a warning.
  786. */
  787. result = dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv);
  788. isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv));
  789. if (cpval != default_dbtype)
  790. isc_mem_free(mctx, cpval);
  791. if (result != ISC_R_SUCCESS)
  792. return (result);
  793. obj = NULL;
  794. result = cfg_map_get(zoptions, "file", &obj);
  795. if (result == ISC_R_SUCCESS)
  796. filename = cfg_obj_asstring(obj);
  797. /*
  798. * Unless we're using some alternative database, a master zone
  799. * will be needing a master file.
  800. */
  801. if (ztype == dns_zone_master && cpval == default_dbtype &&
  802. filename == NULL) {
  803. isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
  804. NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
  805. "zone '%s': 'file' not specified",
  806. zname);
  807. return (ISC_R_FAILURE);
  808. }
  809. masterformat = dns_masterformat_text;
  810. obj = NULL;
  811. result= ns_config_get(maps, "masterfile-format", &obj);
  812. if (result == ISC_R_SUCCESS) {
  813. const char *masterformatstr = cfg_obj_asstring(obj);
  814. if (strcasecmp(masterformatstr, "text") == 0)
  815. masterformat = dns_masterformat_text;
  816. else if (strcasecmp(masterformatstr, "raw") == 0)
  817. masterformat = dns_masterformat_raw;
  818. else
  819. INSIST(0);
  820. }
  821. RETERR(dns_zone_setfile2(zone, filename, masterformat));
  822. obj = NULL;
  823. result = cfg_map_get(zoptions, "journal", &obj);
  824. if (result == ISC_R_SUCCESS)
  825. RETERR(dns_zone_setjournal(zone, cfg_obj_asstring(obj)));
  826. if (ztype == dns_zone_slave)
  827. RETERR(configure_zone_acl(zconfig, vconfig, config,
  828. allow_notify, ac, zone,
  829. dns_zone_setnotifyacl,
  830. dns_zone_clearnotifyacl));
  831. /*
  832. * XXXAG This probably does not make sense for stubs.
  833. */
  834. RETERR(configure_zone_acl(zconfig, vconfig, config,
  835. allow_query, ac, zone,
  836. dns_zone_setqueryacl,
  837. dns_zone_clearqueryacl));
  838. obj = NULL;
  839. result = ns_config_get(maps, "dialup", &obj);
  840. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  841. if (cfg_obj_isboolean(obj)) {
  842. if (cfg_obj_asboolean(obj))
  843. dialup = dns_dialuptype_yes;
  844. else
  845. dialup = dns_dialuptype_no;
  846. } else {
  847. const char *dialupstr = cfg_obj_asstring(obj);
  848. if (strcasecmp(dialupstr, "notify") == 0)
  849. dialup = dns_dialuptype_notify;
  850. else if (strcasecmp(dialupstr, "notify-passive") == 0)
  851. dialup = dns_dialuptype_notifypassive;
  852. else if (strcasecmp(dialupstr, "refresh") == 0)
  853. dialup = dns_dialuptype_refresh;
  854. else if (strcasecmp(dialupstr, "passive") == 0)
  855. dialup = dns_dialuptype_passive;
  856. else
  857. INSIST(0);
  858. }
  859. dns_zone_setdialup(zone, dialup);
  860. obj = NULL;
  861. result = ns_config_get(maps, "zone-statistics", &obj);
  862. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  863. zonestats_on = cfg_obj_asboolean(obj);
  864. zoneqrystats = NULL;
  865. if (zonestats_on) {
  866. RETERR(isc_stats_create(mctx, &zoneqrystats,
  867. dns_nsstatscounter_max));
  868. }
  869. dns_zone_setrequeststats(zone, zoneqrystats);
  870. if (zoneqrystats != NULL)
  871. isc_stats_detach(&zoneqrystats);
  872. /*
  873. * Configure master functionality. This applies
  874. * to primary masters (type "master") and slaves
  875. * acting as masters (type "slave"), but not to stubs.
  876. */
  877. if (ztype != dns_zone_stub && ztype != dns_zone_staticstub) {
  878. obj = NULL;
  879. result = ns_config_get(maps, "notify", &obj);
  880. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  881. if (cfg_obj_isboolean(obj)) {
  882. if (cfg_obj_asboolean(obj))
  883. notifytype = dns_notifytype_yes;
  884. else
  885. notifytype = dns_notifytype_no;
  886. } else {
  887. const char *notifystr = cfg_obj_asstring(obj);
  888. if (strcasecmp(notifystr, "explicit") == 0)
  889. notifytype = dns_notifytype_explicit;
  890. else if (strcasecmp(notifystr, "master-only") == 0)
  891. notifytype = dns_notifytype_masteronly;
  892. else
  893. INSIST(0);
  894. }
  895. dns_zone_setnotifytype(zone, notifytype);
  896. obj = NULL;
  897. result = ns_config_get(maps, "also-notify", &obj);
  898. if (result == ISC_R_SUCCESS) {
  899. isc_sockaddr_t *addrs = NULL;
  900. isc_uint32_t addrcount;
  901. result = ns_config_getiplist(config, obj, 0, mctx,
  902. &addrs, &addrcount);
  903. if (result != ISC_R_SUCCESS)
  904. return (result);
  905. result = dns_zone_setalsonotify(zone, addrs,
  906. addrcount);
  907. ns_config_putiplist(mctx, &addrs, addrcount);
  908. if (result != ISC_R_SUCCESS)
  909. return (result);
  910. } else
  911. RETERR(dns_zone_setalsonotify(zone, NULL, 0));
  912. obj = NULL;
  913. result = ns_config_get(maps, "notify-source", &obj);
  914. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  915. RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
  916. ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
  917. obj = NULL;
  918. result = ns_config_get(maps, "notify-source-v6", &obj);
  919. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  920. RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
  921. ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
  922. obj = NULL;
  923. result = ns_config_get(maps, "notify-to-soa", &obj);
  924. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  925. dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA,
  926. cfg_obj_asboolean(obj));
  927. dns_zone_setisself(zone, ns_client_isself, NULL);
  928. RETERR(configure_zone_acl(zconfig, vconfig, config,
  929. allow_transfer, ac, zone,
  930. dns_zone_setxfracl,
  931. dns_zone_clearxfracl));
  932. obj = NULL;
  933. result = ns_config_get(maps, "max-transfer-time-out", &obj);
  934. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  935. dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60);
  936. obj = NULL;
  937. result = ns_config_get(maps, "max-transfer-idle-out", &obj);
  938. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  939. dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60);
  940. obj = NULL;
  941. result = ns_config_get(maps, "max-journal-size", &obj);
  942. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  943. dns_zone_setjournalsize(zone, -1);
  944. if (cfg_obj_isstring(obj)) {
  945. const char *str = cfg_obj_asstring(obj);
  946. INSIST(strcasecmp(str, "unlimited") == 0);
  947. journal_size = ISC_UINT32_MAX / 2;
  948. } else {
  949. isc_resourcevalue_t value;
  950. value = cfg_obj_asuint64(obj);
  951. if (value > ISC_UINT32_MAX / 2) {
  952. cfg_obj_log(obj, ns_g_lctx,
  953. ISC_LOG_ERROR,
  954. "'max-journal-size "
  955. "%" ISC_PRINT_QUADFORMAT "d' "
  956. "is too large",
  957. value);
  958. RETERR(ISC_R_RANGE);
  959. }
  960. journal_size = (isc_uint32_t)value;
  961. }
  962. dns_zone_setjournalsize(zone, journal_size);
  963. obj = NULL;
  964. result = ns_config_get(maps, "ixfr-from-differences", &obj);
  965. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  966. if (cfg_obj_isboolean(obj))
  967. ixfrdiff = cfg_obj_asboolean(obj);
  968. else if (!strcasecmp(cfg_obj_asstring(obj), "master") &&
  969. ztype == dns_zone_master)
  970. ixfrdiff = ISC_TRUE;
  971. else if (!strcasecmp(cfg_obj_asstring(obj), "slave") &&
  972. ztype == dns_zone_slave)
  973. ixfrdiff = ISC_TRUE;
  974. else
  975. ixfrdiff = ISC_FALSE;
  976. dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, ixfrdiff);
  977. checknames(ztype, maps, &obj);
  978. INSIST(obj != NULL);
  979. if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
  980. fail = ISC_FALSE;
  981. check = ISC_TRUE;
  982. } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
  983. fail = check = ISC_TRUE;
  984. } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
  985. fail = check = ISC_FALSE;
  986. } else
  987. INSIST(0);
  988. dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check);
  989. dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, fail);
  990. obj = NULL;
  991. result = ns_config_get(maps, "notify-delay", &obj);
  992. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  993. dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));
  994. obj = NULL;
  995. result = ns_config_get(maps, "check-sibling", &obj);
  996. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  997. dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
  998. cfg_obj_asboolean(obj));
  999. obj = NULL;
  1000. result = ns_config_get(maps, "zero-no-soa-ttl", &obj);
  1001. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1002. dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj));
  1003. obj = NULL;
  1004. result = ns_config_get(maps, "nsec3-test-zone", &obj);
  1005. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1006. dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE,
  1007. cfg_obj_asboolean(obj));
  1008. }
  1009. /*
  1010. * Configure update-related options. These apply to
  1011. * primary masters only.
  1012. */
  1013. if (ztype == dns_zone_master) {
  1014. dns_acl_t *updateacl;
  1015. RETERR(configure_zone_acl(zconfig, vconfig, config,
  1016. allow_update, ac, zone,
  1017. dns_zone_setupdateacl,
  1018. dns_zone_clearupdateacl));
  1019. updateacl = dns_zone_getupdateacl(zone);
  1020. if (updateacl != NULL && dns_acl_isinsecure(updateacl))
  1021. isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
  1022. NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
  1023. "zone '%s' allows updates by IP "
  1024. "address, which is insecure",
  1025. zname);
  1026. RETERR(configure_zone_ssutable(zoptions, zone, zname));
  1027. obj = NULL;
  1028. result = ns_config_get(maps, "sig-validity-interval", &obj);
  1029. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1030. {
  1031. const cfg_obj_t *validity, *resign;
  1032. validity = cfg_tuple_get(obj, "validity");
  1033. seconds = cfg_obj_asuint32(validity) * 86400;
  1034. dns_zone_setsigvalidityinterval(zone, seconds);
  1035. resign = cfg_tuple_get(obj, "re-sign");
  1036. if (cfg_obj_isvoid(resign)) {
  1037. seconds /= 4;
  1038. } else {
  1039. if (seconds > 7 * 86400)
  1040. seconds = cfg_obj_asuint32(resign) *
  1041. 86400;
  1042. else
  1043. seconds = cfg_obj_asuint32(resign) *
  1044. 3600;
  1045. }
  1046. dns_zone_setsigresigninginterval(zone, seconds);
  1047. }
  1048. obj = NULL;
  1049. result = ns_config_get(maps, "key-directory", &obj);
  1050. if (result == ISC_R_SUCCESS) {
  1051. filename = cfg_obj_asstring(obj);
  1052. RETERR(dns_zone_setkeydirectory(zone, filename));
  1053. }
  1054. obj = NULL;
  1055. result = ns_config_get(maps, "sig-signing-signatures", &obj);
  1056. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1057. dns_zone_setsignatures(zone, cfg_obj_asuint32(obj));
  1058. obj = NULL;
  1059. result = ns_config_get(maps, "sig-signing-nodes", &obj);
  1060. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1061. dns_zone_setnodes(zone, cfg_obj_asuint32(obj));
  1062. obj = NULL;
  1063. result = ns_config_get(maps, "sig-signing-type", &obj);
  1064. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1065. dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj));
  1066. obj = NULL;
  1067. result = ns_config_get(maps, "update-check-ksk", &obj);
  1068. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1069. dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
  1070. cfg_obj_asboolean(obj));
  1071. obj = NULL;
  1072. result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj);
  1073. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1074. dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY,
  1075. cfg_obj_asboolean(obj));
  1076. } else if (ztype == dns_zone_slave) {
  1077. RETERR(configure_zone_acl(zconfig, vconfig, config,
  1078. allow_update_forwarding, ac, zone,
  1079. dns_zone_setforwardacl,
  1080. dns_zone_clearforwardacl));
  1081. }
  1082. /*%
  1083. * Primary master functionality.
  1084. */
  1085. if (ztype == dns_zone_master) {
  1086. isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE;
  1087. obj = NULL;
  1088. result = ns_config_get(maps, "check-wildcard", &obj);
  1089. if (result == ISC_R_SUCCESS)
  1090. check = cfg_obj_asboolean(obj);
  1091. else
  1092. check = ISC_FALSE;
  1093. dns_zone_setoption(zone, DNS_ZONEOPT_CHECKWILDCARD, check);
  1094. obj = NULL;
  1095. result = ns_config_get(maps, "check-dup-records", &obj);
  1096. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1097. if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
  1098. fail = ISC_FALSE;
  1099. check = ISC_TRUE;
  1100. } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
  1101. fail = check = ISC_TRUE;
  1102. } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
  1103. fail = check = ISC_FALSE;
  1104. } else
  1105. INSIST(0);
  1106. dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRR, check);
  1107. dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRRFAIL, fail);
  1108. obj = NULL;
  1109. result = ns_config_get(maps, "check-mx", &obj);
  1110. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1111. if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
  1112. fail = ISC_FALSE;
  1113. check = ISC_TRUE;
  1114. } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
  1115. fail = check = ISC_TRUE;
  1116. } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
  1117. fail = check = ISC_FALSE;
  1118. } else
  1119. INSIST(0);
  1120. dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMX, check);
  1121. dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMXFAIL, fail);
  1122. obj = NULL;
  1123. result = ns_config_get(maps, "check-integrity", &obj);
  1124. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1125. dns_zone_setoption(zone, DNS_ZONEOPT_CHECKINTEGRITY,
  1126. cfg_obj_asboolean(obj));
  1127. obj = NULL;
  1128. result = ns_config_get(maps, "check-mx-cname", &obj);
  1129. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1130. if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
  1131. warn = ISC_TRUE;
  1132. ignore = ISC_FALSE;
  1133. } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
  1134. warn = ignore = ISC_FALSE;
  1135. } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
  1136. warn = ignore = ISC_TRUE;
  1137. } else
  1138. INSIST(0);
  1139. dns_zone_setoption(zone, DNS_ZONEOPT_WARNMXCNAME, warn);
  1140. dns_zone_setoption(zone, DNS_ZONEOPT_IGNOREMXCNAME, ignore);
  1141. obj = NULL;
  1142. result = ns_config_get(maps, "check-srv-cname", &obj);
  1143. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1144. if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
  1145. warn = ISC_TRUE;
  1146. ignore = ISC_FALSE;
  1147. } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
  1148. warn = ignore = ISC_FALSE;
  1149. } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
  1150. warn = ignore = ISC_TRUE;
  1151. } else
  1152. INSIST(0);
  1153. dns_zone_setoption(zone, DNS_ZONEOPT_WARNSRVCNAME, warn);
  1154. dns_zone_setoption(zone, DNS_ZONEOPT_IGNORESRVCNAME, ignore);
  1155. obj = NULL;
  1156. result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj);
  1157. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1158. dns_zone_setoption(zone, DNS_ZONEOPT_SECURETOINSECURE,
  1159. cfg_obj_asboolean(obj));
  1160. obj = NULL;
  1161. result = cfg_map_get(zoptions, "auto-dnssec", &obj);
  1162. if (result == ISC_R_SUCCESS) {
  1163. const char *arg = cfg_obj_asstring(obj);
  1164. if (strcasecmp(arg, "allow") == 0)
  1165. allow = ISC_TRUE;
  1166. else if (strcasecmp(arg, "maintain") == 0)
  1167. allow = maint = ISC_TRUE;
  1168. else if (strcasecmp(arg, "off") == 0)
  1169. ;
  1170. else
  1171. INSIST(0);
  1172. dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
  1173. dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
  1174. }
  1175. }
  1176. /*
  1177. * Configure slave functionality.
  1178. */
  1179. switch (ztype) {
  1180. case dns_zone_slave:
  1181. case dns_zone_stub:
  1182. count = 0;
  1183. obj = NULL;
  1184. (void)cfg_map_get(zoptions, "masters", &obj);
  1185. if (obj != NULL) {
  1186. addrs = NULL;
  1187. keynames = NULL;
  1188. RETERR(ns_config_getipandkeylist(config, obj, mctx,
  1189. &addrs, &keynames,
  1190. &count));
  1191. result = dns_zone_setmasterswithkeys(zone, addrs,
  1192. keynames, count);
  1193. if (count != 0)
  1194. ns_config_putipandkeylist(mctx, &addrs,
  1195. &keynames, count);
  1196. else
  1197. INSIST(addrs == NULL && keynames == NULL);
  1198. } else
  1199. result = dns_zone_setmasters(zone, NULL, 0);
  1200. RETERR(result);
  1201. multi = ISC_FALSE;
  1202. if (count > 1) {
  1203. obj = NULL;
  1204. result = ns_config_get(maps, "multi-master", &obj);
  1205. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1206. multi = cfg_obj_asboolean(obj);
  1207. }
  1208. dns_zone_setoption(zone, DNS_ZONEOPT_MULTIMASTER, multi);
  1209. obj = NULL;
  1210. result = ns_config_get(maps, "max-transfer-time-in", &obj);
  1211. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1212. dns_zone_setmaxxfrin(zone, cfg_obj_asuint32(obj) * 60);
  1213. obj = NULL;
  1214. result = ns_config_get(maps, "max-transfer-idle-in", &obj);
  1215. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1216. dns_zone_setidlein(zone, cfg_obj_asuint32(obj) * 60);
  1217. obj = NULL;
  1218. result = ns_config_get(maps, "max-refresh-time", &obj);
  1219. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1220. dns_zone_setmaxrefreshtime(zone, cfg_obj_asuint32(obj));
  1221. obj = NULL;
  1222. result = ns_config_get(maps, "min-refresh-time", &obj);
  1223. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1224. dns_zone_setminrefreshtime(zone, cfg_obj_asuint32(obj));
  1225. obj = NULL;
  1226. result = ns_config_get(maps, "max-retry-time", &obj);
  1227. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1228. dns_zone_setmaxretrytime(zone, cfg_obj_asuint32(obj));
  1229. obj = NULL;
  1230. result = ns_config_get(maps, "min-retry-time", &obj);
  1231. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1232. dns_zone_setminretrytime(zone, cfg_obj_asuint32(obj));
  1233. obj = NULL;
  1234. result = ns_config_get(maps, "transfer-source", &obj);
  1235. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1236. RETERR(dns_zone_setxfrsource4(zone, cfg_obj_assockaddr(obj)));
  1237. ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
  1238. obj = NULL;
  1239. result = ns_config_get(maps, "transfer-source-v6", &obj);
  1240. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1241. RETERR(dns_zone_setxfrsource6(zone, cfg_obj_assockaddr(obj)));
  1242. ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
  1243. obj = NULL;
  1244. result = ns_config_get(maps, "alt-transfer-source", &obj);
  1245. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1246. RETERR(dns_zone_setaltxfrsource4(zone, cfg_obj_assockaddr(obj)));
  1247. obj = NULL;
  1248. result = ns_config_get(maps, "alt-transfer-source-v6", &obj);
  1249. INSIST(result == ISC_R_SUCCESS && obj != NULL);
  1250. RETERR(dns_zone_setaltxfrsource6(zone, cfg_obj_assockaddr(obj)));
  1251. obj = NULL;
  1252. (void)ns_config_get(maps, "use-alt-transfer-source", &obj);
  1253. if (obj == NULL) {
  1254. /*
  1255. * Default off when views are in use otherwise
  1256. * on for BIND 8 compatibility.
  1257. */
  1258. view = dns_zone_getview(zone);
  1259. if (view != NULL && strcmp(view->name, "_default") == 0)
  1260. alt = ISC_TRUE;
  1261. else
  1262. alt = ISC_FALSE;
  1263. } else
  1264. alt = cfg_obj_asboolean(obj);
  1265. dns_zone_setoption(zone, DNS_ZONEOPT_USEALTXFRSRC, alt);
  1266. obj = NULL;
  1267. (void)ns_config_get(maps, "try-tcp-refresh", &obj);
  1268. dns_zone_setoption(zone, DNS_ZONEOPT_TRYTCPREFRESH,
  1269. cfg_obj_asboolean(obj));
  1270. break;
  1271. case dns_zone_staticstub:
  1272. RETERR(configure_staticstub(zoptions, zone, zname,
  1273. default_dbtype));
  1274. break;
  1275. default:
  1276. break;
  1277. }
  1278. return (ISC_R_SUCCESS);
  1279. }
  1280. /*
  1281. * Set up a DLZ zone as writeable
  1282. */
  1283. isc_result_t
  1284. ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
  1285. dns_rdataclass_t rdclass, dns_name_t *name)
  1286. {
  1287. dns_db_t *db = NULL;
  1288. isc_time_t now;
  1289. isc_result_t result;
  1290. TIME_NOW(&now);
  1291. dns_zone_settype(zone, dns_zone_dlz);
  1292. result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db);
  1293. if (result != ISC_R_SUCCESS)
  1294. return result;
  1295. result = dns_zone_dlzpostload(zone, db);
  1296. dns_db_detach(&db);
  1297. return result;
  1298. }
  1299. isc_boolean_t
  1300. ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) {
  1301. const cfg_obj_t *zoptions = NULL;
  1302. const cfg_obj_t *obj = NULL;
  1303. const char *cfilename;
  1304. const char *zfilename;
  1305. zoptions = cfg_tuple_get(zconfig, "options");
  1306. if (zonetype_fromconfig(zoptions) != dns_zone_gettype(zone)) {
  1307. dns_zone_log(zone, ISC_LOG_DEBUG(1),
  1308. "not reusable: type mismatch");
  1309. return (ISC_FALSE);
  1310. }
  1311. /*
  1312. * We always reconfigure a static-stub zone for simplicity, assuming
  1313. * the amount of data to be loaded is small.
  1314. */
  1315. if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) {
  1316. dns_zone_log(zone, ISC_LOG_DEBUG(1),
  1317. "not reusable: staticstub");
  1318. return (ISC_FALSE);
  1319. }
  1320. obj = NULL;
  1321. (void)cfg_map_get(zoptions, "file", &obj);
  1322. if (obj != NULL)
  1323. cfilename = cfg_obj_asstring(obj);
  1324. else
  1325. cfilename = NULL;
  1326. zfilename = dns_zone_getfile(zone);
  1327. if (!((cfilename == NULL && zfilename == NULL) ||
  1328. (cfilename != NULL && zfilename != NULL &&
  1329. strcmp(cfilename, zfilename) == 0))) {
  1330. dns_zone_log(zone, ISC_LOG_DEBUG(1),
  1331. "not reusable: filename mismatch");
  1332. return (ISC_FALSE);
  1333. }
  1334. return (ISC_TRUE);
  1335. }