/contrib/bind9/bin/named/query.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 7242 lines · 5285 code · 595 blank · 1362 comment · 1873 complexity · 884d102af774a65093406c7039f80ba4 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: query.c,v 1.353.8.24 2012/02/07 01:14:39 marka Exp $ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <string.h>
  21. #include <isc/hex.h>
  22. #include <isc/mem.h>
  23. #include <isc/stats.h>
  24. #include <isc/util.h>
  25. #include <dns/adb.h>
  26. #include <dns/byaddr.h>
  27. #include <dns/db.h>
  28. #include <dns/dlz.h>
  29. #include <dns/dns64.h>
  30. #include <dns/dnssec.h>
  31. #include <dns/events.h>
  32. #include <dns/message.h>
  33. #include <dns/ncache.h>
  34. #include <dns/nsec3.h>
  35. #include <dns/order.h>
  36. #include <dns/rdata.h>
  37. #include <dns/rdataclass.h>
  38. #include <dns/rdatalist.h>
  39. #include <dns/rdataset.h>
  40. #include <dns/rdatasetiter.h>
  41. #include <dns/rdatastruct.h>
  42. #include <dns/rdatatype.h>
  43. #include <dns/resolver.h>
  44. #include <dns/result.h>
  45. #include <dns/stats.h>
  46. #include <dns/tkey.h>
  47. #include <dns/view.h>
  48. #include <dns/zone.h>
  49. #include <dns/zt.h>
  50. #include <named/client.h>
  51. #include <named/globals.h>
  52. #include <named/log.h>
  53. #include <named/server.h>
  54. #include <named/sortlist.h>
  55. #include <named/xfrout.h>
  56. #if 0
  57. /*
  58. * It has been recommended that DNS64 be changed to return excluded
  59. * AAAA addresses if DNS64 synthesis does not occur. This minimises
  60. * the impact on the lookup results. While most DNS AAAA lookups are
  61. * done to send IP packets to a host, not all of them are and filtering
  62. * excluded addresses has a negative impact on those uses.
  63. */
  64. #define dns64_bis_return_excluded_addresses 1
  65. #endif
  66. /*% Partial answer? */
  67. #define PARTIALANSWER(c) (((c)->query.attributes & \
  68. NS_QUERYATTR_PARTIALANSWER) != 0)
  69. /*% Use Cache? */
  70. #define USECACHE(c) (((c)->query.attributes & \
  71. NS_QUERYATTR_CACHEOK) != 0)
  72. /*% Recursion OK? */
  73. #define RECURSIONOK(c) (((c)->query.attributes & \
  74. NS_QUERYATTR_RECURSIONOK) != 0)
  75. /*% Recursing? */
  76. #define RECURSING(c) (((c)->query.attributes & \
  77. NS_QUERYATTR_RECURSING) != 0)
  78. /*% Cache glue ok? */
  79. #define CACHEGLUEOK(c) (((c)->query.attributes & \
  80. NS_QUERYATTR_CACHEGLUEOK) != 0)
  81. /*% Want Recursion? */
  82. #define WANTRECURSION(c) (((c)->query.attributes & \
  83. NS_QUERYATTR_WANTRECURSION) != 0)
  84. /*% Want DNSSEC? */
  85. #define WANTDNSSEC(c) (((c)->attributes & \
  86. NS_CLIENTATTR_WANTDNSSEC) != 0)
  87. /*% No authority? */
  88. #define NOAUTHORITY(c) (((c)->query.attributes & \
  89. NS_QUERYATTR_NOAUTHORITY) != 0)
  90. /*% No additional? */
  91. #define NOADDITIONAL(c) (((c)->query.attributes & \
  92. NS_QUERYATTR_NOADDITIONAL) != 0)
  93. /*% Secure? */
  94. #define SECURE(c) (((c)->query.attributes & \
  95. NS_QUERYATTR_SECURE) != 0)
  96. /*% DNS64 A lookup? */
  97. #define DNS64(c) (((c)->query.attributes & \
  98. NS_QUERYATTR_DNS64) != 0)
  99. #define DNS64EXCLUDE(c) (((c)->query.attributes & \
  100. NS_QUERYATTR_DNS64EXCLUDE) != 0)
  101. /*% No QNAME Proof? */
  102. #define NOQNAME(r) (((r)->attributes & \
  103. DNS_RDATASETATTR_NOQNAME) != 0)
  104. #if 0
  105. #define CTRACE(m) isc_log_write(ns_g_lctx, \
  106. NS_LOGCATEGORY_CLIENT, \
  107. NS_LOGMODULE_QUERY, \
  108. ISC_LOG_DEBUG(3), \
  109. "client %p: %s", client, (m))
  110. #define QTRACE(m) isc_log_write(ns_g_lctx, \
  111. NS_LOGCATEGORY_GENERAL, \
  112. NS_LOGMODULE_QUERY, \
  113. ISC_LOG_DEBUG(3), \
  114. "query %p: %s", query, (m))
  115. #else
  116. #define CTRACE(m) ((void)m)
  117. #define QTRACE(m) ((void)m)
  118. #endif
  119. #define DNS_GETDB_NOEXACT 0x01U
  120. #define DNS_GETDB_NOLOG 0x02U
  121. #define DNS_GETDB_PARTIAL 0x04U
  122. #define DNS_GETDB_IGNOREACL 0x08U
  123. #define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0)
  124. typedef struct client_additionalctx {
  125. ns_client_t *client;
  126. dns_rdataset_t *rdataset;
  127. } client_additionalctx_t;
  128. static isc_result_t
  129. query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
  130. static isc_boolean_t
  131. validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
  132. dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
  133. static void
  134. query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
  135. dns_dbversion_t *version, ns_client_t *client,
  136. dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
  137. dns_name_t *fname, isc_boolean_t exact,
  138. dns_name_t *found);
  139. static inline void
  140. log_queryerror(ns_client_t *client, isc_result_t result, int line, int level);
  141. static void
  142. rpz_st_clear(ns_client_t *client);
  143. /*%
  144. * Increment query statistics counters.
  145. */
  146. static inline void
  147. inc_stats(ns_client_t *client, isc_statscounter_t counter) {
  148. dns_zone_t *zone = client->query.authzone;
  149. isc_stats_increment(ns_g_server->nsstats, counter);
  150. if (zone != NULL) {
  151. isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
  152. if (zonestats != NULL)
  153. isc_stats_increment(zonestats, counter);
  154. }
  155. }
  156. static void
  157. query_send(ns_client_t *client) {
  158. isc_statscounter_t counter;
  159. if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0)
  160. inc_stats(client, dns_nsstatscounter_nonauthans);
  161. else
  162. inc_stats(client, dns_nsstatscounter_authans);
  163. if (client->message->rcode == dns_rcode_noerror) {
  164. if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER])) {
  165. if (client->query.isreferral) {
  166. counter = dns_nsstatscounter_referral;
  167. } else {
  168. counter = dns_nsstatscounter_nxrrset;
  169. }
  170. } else {
  171. counter = dns_nsstatscounter_success;
  172. }
  173. } else if (client->message->rcode == dns_rcode_nxdomain) {
  174. counter = dns_nsstatscounter_nxdomain;
  175. } else {
  176. /* We end up here in case of YXDOMAIN, and maybe others */
  177. counter = dns_nsstatscounter_failure;
  178. }
  179. inc_stats(client, counter);
  180. ns_client_send(client);
  181. }
  182. static void
  183. query_error(ns_client_t *client, isc_result_t result, int line) {
  184. int loglevel = ISC_LOG_DEBUG(3);
  185. switch (result) {
  186. case DNS_R_SERVFAIL:
  187. loglevel = ISC_LOG_DEBUG(1);
  188. inc_stats(client, dns_nsstatscounter_servfail);
  189. break;
  190. case DNS_R_FORMERR:
  191. inc_stats(client, dns_nsstatscounter_formerr);
  192. break;
  193. default:
  194. inc_stats(client, dns_nsstatscounter_failure);
  195. break;
  196. }
  197. log_queryerror(client, result, line, loglevel);
  198. ns_client_error(client, result);
  199. }
  200. static void
  201. query_next(ns_client_t *client, isc_result_t result) {
  202. if (result == DNS_R_DUPLICATE)
  203. inc_stats(client, dns_nsstatscounter_duplicate);
  204. else if (result == DNS_R_DROP)
  205. inc_stats(client, dns_nsstatscounter_dropped);
  206. else
  207. inc_stats(client, dns_nsstatscounter_failure);
  208. ns_client_next(client, result);
  209. }
  210. static inline void
  211. query_freefreeversions(ns_client_t *client, isc_boolean_t everything) {
  212. ns_dbversion_t *dbversion, *dbversion_next;
  213. unsigned int i;
  214. for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0;
  215. dbversion != NULL;
  216. dbversion = dbversion_next, i++)
  217. {
  218. dbversion_next = ISC_LIST_NEXT(dbversion, link);
  219. /*
  220. * If we're not freeing everything, we keep the first three
  221. * dbversions structures around.
  222. */
  223. if (i > 3 || everything) {
  224. ISC_LIST_UNLINK(client->query.freeversions, dbversion,
  225. link);
  226. isc_mem_put(client->mctx, dbversion,
  227. sizeof(*dbversion));
  228. }
  229. }
  230. }
  231. void
  232. ns_query_cancel(ns_client_t *client) {
  233. LOCK(&client->query.fetchlock);
  234. if (client->query.fetch != NULL) {
  235. dns_resolver_cancelfetch(client->query.fetch);
  236. client->query.fetch = NULL;
  237. }
  238. UNLOCK(&client->query.fetchlock);
  239. }
  240. static inline void
  241. query_putrdataset(ns_client_t *client, dns_rdataset_t **rdatasetp) {
  242. dns_rdataset_t *rdataset = *rdatasetp;
  243. CTRACE("query_putrdataset");
  244. if (rdataset != NULL) {
  245. if (dns_rdataset_isassociated(rdataset))
  246. dns_rdataset_disassociate(rdataset);
  247. dns_message_puttemprdataset(client->message, rdatasetp);
  248. }
  249. CTRACE("query_putrdataset: done");
  250. }
  251. static inline void
  252. query_reset(ns_client_t *client, isc_boolean_t everything) {
  253. isc_buffer_t *dbuf, *dbuf_next;
  254. ns_dbversion_t *dbversion, *dbversion_next;
  255. /*%
  256. * Reset the query state of a client to its default state.
  257. */
  258. /*
  259. * Cancel the fetch if it's running.
  260. */
  261. ns_query_cancel(client);
  262. /*
  263. * Cleanup any active versions.
  264. */
  265. for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
  266. dbversion != NULL;
  267. dbversion = dbversion_next) {
  268. dbversion_next = ISC_LIST_NEXT(dbversion, link);
  269. dns_db_closeversion(dbversion->db, &dbversion->version,
  270. ISC_FALSE);
  271. dns_db_detach(&dbversion->db);
  272. ISC_LIST_INITANDAPPEND(client->query.freeversions,
  273. dbversion, link);
  274. }
  275. ISC_LIST_INIT(client->query.activeversions);
  276. if (client->query.authdb != NULL)
  277. dns_db_detach(&client->query.authdb);
  278. if (client->query.authzone != NULL)
  279. dns_zone_detach(&client->query.authzone);
  280. if (client->query.dns64_aaaa != NULL)
  281. query_putrdataset(client, &client->query.dns64_aaaa);
  282. if (client->query.dns64_sigaaaa != NULL)
  283. query_putrdataset(client, &client->query.dns64_sigaaaa);
  284. if (client->query.dns64_aaaaok != NULL) {
  285. isc_mem_put(client->mctx, client->query.dns64_aaaaok,
  286. client->query.dns64_aaaaoklen *
  287. sizeof(isc_boolean_t));
  288. client->query.dns64_aaaaok = NULL;
  289. client->query.dns64_aaaaoklen = 0;
  290. }
  291. query_freefreeversions(client, everything);
  292. for (dbuf = ISC_LIST_HEAD(client->query.namebufs);
  293. dbuf != NULL;
  294. dbuf = dbuf_next) {
  295. dbuf_next = ISC_LIST_NEXT(dbuf, link);
  296. if (dbuf_next != NULL || everything) {
  297. ISC_LIST_UNLINK(client->query.namebufs, dbuf, link);
  298. isc_buffer_free(&dbuf);
  299. }
  300. }
  301. if (client->query.restarts > 0) {
  302. /*
  303. * client->query.qname was dynamically allocated.
  304. */
  305. dns_message_puttempname(client->message,
  306. &client->query.qname);
  307. }
  308. client->query.qname = NULL;
  309. client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
  310. NS_QUERYATTR_CACHEOK |
  311. NS_QUERYATTR_SECURE);
  312. client->query.restarts = 0;
  313. client->query.timerset = ISC_FALSE;
  314. if (client->query.rpz_st != NULL) {
  315. rpz_st_clear(client);
  316. if (everything) {
  317. isc_mem_put(client->mctx, client->query.rpz_st,
  318. sizeof(*client->query.rpz_st));
  319. client->query.rpz_st = NULL;
  320. }
  321. }
  322. client->query.origqname = NULL;
  323. client->query.dboptions = 0;
  324. client->query.fetchoptions = 0;
  325. client->query.gluedb = NULL;
  326. client->query.authdbset = ISC_FALSE;
  327. client->query.isreferral = ISC_FALSE;
  328. client->query.dns64_options = 0;
  329. client->query.dns64_ttl = ISC_UINT32_MAX;
  330. }
  331. static void
  332. query_next_callback(ns_client_t *client) {
  333. query_reset(client, ISC_FALSE);
  334. }
  335. void
  336. ns_query_free(ns_client_t *client) {
  337. query_reset(client, ISC_TRUE);
  338. }
  339. static inline isc_result_t
  340. query_newnamebuf(ns_client_t *client) {
  341. isc_buffer_t *dbuf;
  342. isc_result_t result;
  343. CTRACE("query_newnamebuf");
  344. /*%
  345. * Allocate a name buffer.
  346. */
  347. dbuf = NULL;
  348. result = isc_buffer_allocate(client->mctx, &dbuf, 1024);
  349. if (result != ISC_R_SUCCESS) {
  350. CTRACE("query_newnamebuf: isc_buffer_allocate failed: done");
  351. return (result);
  352. }
  353. ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
  354. CTRACE("query_newnamebuf: done");
  355. return (ISC_R_SUCCESS);
  356. }
  357. static inline isc_buffer_t *
  358. query_getnamebuf(ns_client_t *client) {
  359. isc_buffer_t *dbuf;
  360. isc_result_t result;
  361. isc_region_t r;
  362. CTRACE("query_getnamebuf");
  363. /*%
  364. * Return a name buffer with space for a maximal name, allocating
  365. * a new one if necessary.
  366. */
  367. if (ISC_LIST_EMPTY(client->query.namebufs)) {
  368. result = query_newnamebuf(client);
  369. if (result != ISC_R_SUCCESS) {
  370. CTRACE("query_getnamebuf: query_newnamebuf failed: done");
  371. return (NULL);
  372. }
  373. }
  374. dbuf = ISC_LIST_TAIL(client->query.namebufs);
  375. INSIST(dbuf != NULL);
  376. isc_buffer_availableregion(dbuf, &r);
  377. if (r.length < 255) {
  378. result = query_newnamebuf(client);
  379. if (result != ISC_R_SUCCESS) {
  380. CTRACE("query_getnamebuf: query_newnamebuf failed: done");
  381. return (NULL);
  382. }
  383. dbuf = ISC_LIST_TAIL(client->query.namebufs);
  384. isc_buffer_availableregion(dbuf, &r);
  385. INSIST(r.length >= 255);
  386. }
  387. CTRACE("query_getnamebuf: done");
  388. return (dbuf);
  389. }
  390. static inline void
  391. query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
  392. isc_region_t r;
  393. CTRACE("query_keepname");
  394. /*%
  395. * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
  396. * adjusted to take account of that. We do the adjustment.
  397. */
  398. REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0);
  399. dns_name_toregion(name, &r);
  400. isc_buffer_add(dbuf, r.length);
  401. dns_name_setbuffer(name, NULL);
  402. client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
  403. }
  404. static inline void
  405. query_releasename(ns_client_t *client, dns_name_t **namep) {
  406. dns_name_t *name = *namep;
  407. /*%
  408. * 'name' is no longer needed. Return it to our pool of temporary
  409. * names. If it is using a name buffer, relinquish its exclusive
  410. * rights on the buffer.
  411. */
  412. CTRACE("query_releasename");
  413. if (dns_name_hasbuffer(name)) {
  414. INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED)
  415. != 0);
  416. client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
  417. }
  418. dns_message_puttempname(client->message, namep);
  419. CTRACE("query_releasename: done");
  420. }
  421. static inline dns_name_t *
  422. query_newname(ns_client_t *client, isc_buffer_t *dbuf,
  423. isc_buffer_t *nbuf)
  424. {
  425. dns_name_t *name;
  426. isc_region_t r;
  427. isc_result_t result;
  428. REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
  429. CTRACE("query_newname");
  430. name = NULL;
  431. result = dns_message_gettempname(client->message, &name);
  432. if (result != ISC_R_SUCCESS) {
  433. CTRACE("query_newname: dns_message_gettempname failed: done");
  434. return (NULL);
  435. }
  436. isc_buffer_availableregion(dbuf, &r);
  437. isc_buffer_init(nbuf, r.base, r.length);
  438. dns_name_init(name, NULL);
  439. dns_name_setbuffer(name, nbuf);
  440. client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
  441. CTRACE("query_newname: done");
  442. return (name);
  443. }
  444. static inline dns_rdataset_t *
  445. query_newrdataset(ns_client_t *client) {
  446. dns_rdataset_t *rdataset;
  447. isc_result_t result;
  448. CTRACE("query_newrdataset");
  449. rdataset = NULL;
  450. result = dns_message_gettemprdataset(client->message, &rdataset);
  451. if (result != ISC_R_SUCCESS) {
  452. CTRACE("query_newrdataset: "
  453. "dns_message_gettemprdataset failed: done");
  454. return (NULL);
  455. }
  456. dns_rdataset_init(rdataset);
  457. CTRACE("query_newrdataset: done");
  458. return (rdataset);
  459. }
  460. static inline isc_result_t
  461. query_newdbversion(ns_client_t *client, unsigned int n) {
  462. unsigned int i;
  463. ns_dbversion_t *dbversion;
  464. for (i = 0; i < n; i++) {
  465. dbversion = isc_mem_get(client->mctx, sizeof(*dbversion));
  466. if (dbversion != NULL) {
  467. dbversion->db = NULL;
  468. dbversion->version = NULL;
  469. ISC_LIST_INITANDAPPEND(client->query.freeversions,
  470. dbversion, link);
  471. } else {
  472. /*
  473. * We only return ISC_R_NOMEMORY if we couldn't
  474. * allocate anything.
  475. */
  476. if (i == 0)
  477. return (ISC_R_NOMEMORY);
  478. else
  479. return (ISC_R_SUCCESS);
  480. }
  481. }
  482. return (ISC_R_SUCCESS);
  483. }
  484. static inline ns_dbversion_t *
  485. query_getdbversion(ns_client_t *client) {
  486. isc_result_t result;
  487. ns_dbversion_t *dbversion;
  488. if (ISC_LIST_EMPTY(client->query.freeversions)) {
  489. result = query_newdbversion(client, 1);
  490. if (result != ISC_R_SUCCESS)
  491. return (NULL);
  492. }
  493. dbversion = ISC_LIST_HEAD(client->query.freeversions);
  494. INSIST(dbversion != NULL);
  495. ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);
  496. return (dbversion);
  497. }
  498. isc_result_t
  499. ns_query_init(ns_client_t *client) {
  500. isc_result_t result;
  501. ISC_LIST_INIT(client->query.namebufs);
  502. ISC_LIST_INIT(client->query.activeversions);
  503. ISC_LIST_INIT(client->query.freeversions);
  504. client->query.restarts = 0;
  505. client->query.timerset = ISC_FALSE;
  506. client->query.rpz_st = NULL;
  507. client->query.qname = NULL;
  508. result = isc_mutex_init(&client->query.fetchlock);
  509. if (result != ISC_R_SUCCESS)
  510. return (result);
  511. client->query.fetch = NULL;
  512. client->query.authdb = NULL;
  513. client->query.authzone = NULL;
  514. client->query.authdbset = ISC_FALSE;
  515. client->query.isreferral = ISC_FALSE;
  516. client->query.dns64_aaaa = NULL;
  517. client->query.dns64_sigaaaa = NULL;
  518. client->query.dns64_aaaaok = NULL;
  519. client->query.dns64_aaaaoklen = 0;
  520. query_reset(client, ISC_FALSE);
  521. result = query_newdbversion(client, 3);
  522. if (result != ISC_R_SUCCESS) {
  523. DESTROYLOCK(&client->query.fetchlock);
  524. return (result);
  525. }
  526. result = query_newnamebuf(client);
  527. if (result != ISC_R_SUCCESS)
  528. query_freefreeversions(client, ISC_TRUE);
  529. return (result);
  530. }
  531. static inline ns_dbversion_t *
  532. query_findversion(ns_client_t *client, dns_db_t *db)
  533. {
  534. ns_dbversion_t *dbversion;
  535. /*%
  536. * We may already have done a query related to this
  537. * database. If so, we must be sure to make subsequent
  538. * queries from the same version.
  539. */
  540. for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
  541. dbversion != NULL;
  542. dbversion = ISC_LIST_NEXT(dbversion, link)) {
  543. if (dbversion->db == db)
  544. break;
  545. }
  546. if (dbversion == NULL) {
  547. /*
  548. * This is a new zone for this query. Add it to
  549. * the active list.
  550. */
  551. dbversion = query_getdbversion(client);
  552. if (dbversion == NULL)
  553. return (NULL);
  554. dns_db_attach(db, &dbversion->db);
  555. dns_db_currentversion(db, &dbversion->version);
  556. dbversion->acl_checked = ISC_FALSE;
  557. dbversion->queryok = ISC_FALSE;
  558. ISC_LIST_APPEND(client->query.activeversions,
  559. dbversion, link);
  560. }
  561. return (dbversion);
  562. }
  563. static inline isc_result_t
  564. query_validatezonedb(ns_client_t *client, dns_name_t *name,
  565. dns_rdatatype_t qtype, unsigned int options,
  566. dns_zone_t *zone, dns_db_t *db,
  567. dns_dbversion_t **versionp)
  568. {
  569. isc_result_t result;
  570. dns_acl_t *queryacl;
  571. ns_dbversion_t *dbversion;
  572. REQUIRE(zone != NULL);
  573. REQUIRE(db != NULL);
  574. /*
  575. * This limits our searching to the zone where the first name
  576. * (the query target) was looked for. This prevents following
  577. * CNAMES or DNAMES into other zones and prevents returning
  578. * additional data from other zones.
  579. */
  580. if (!client->view->additionalfromauth &&
  581. client->query.authdbset &&
  582. db != client->query.authdb)
  583. return (DNS_R_REFUSED);
  584. /*
  585. * Non recursive query to a static-stub zone is prohibited; its
  586. * zone content is not public data, but a part of local configuration
  587. * and should not be disclosed.
  588. */
  589. if (dns_zone_gettype(zone) == dns_zone_staticstub &&
  590. !RECURSIONOK(client)) {
  591. return (DNS_R_REFUSED);
  592. }
  593. /*
  594. * If the zone has an ACL, we'll check it, otherwise
  595. * we use the view's "allow-query" ACL. Each ACL is only checked
  596. * once per query.
  597. *
  598. * Also, get the database version to use.
  599. */
  600. /*
  601. * Get the current version of this database.
  602. */
  603. dbversion = query_findversion(client, db);
  604. if (dbversion == NULL)
  605. return (DNS_R_SERVFAIL);
  606. if ((options & DNS_GETDB_IGNOREACL) != 0)
  607. goto approved;
  608. if (dbversion->acl_checked) {
  609. if (!dbversion->queryok)
  610. return (DNS_R_REFUSED);
  611. goto approved;
  612. }
  613. queryacl = dns_zone_getqueryacl(zone);
  614. if (queryacl == NULL) {
  615. queryacl = client->view->queryacl;
  616. if ((client->query.attributes &
  617. NS_QUERYATTR_QUERYOKVALID) != 0) {
  618. /*
  619. * We've evaluated the view's queryacl already. If
  620. * NS_QUERYATTR_QUERYOK is set, then the client is
  621. * allowed to make queries, otherwise the query should
  622. * be refused.
  623. */
  624. dbversion->acl_checked = ISC_TRUE;
  625. if ((client->query.attributes &
  626. NS_QUERYATTR_QUERYOK) == 0) {
  627. dbversion->queryok = ISC_FALSE;
  628. return (DNS_R_REFUSED);
  629. }
  630. dbversion->queryok = ISC_TRUE;
  631. goto approved;
  632. }
  633. }
  634. result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE);
  635. if ((options & DNS_GETDB_NOLOG) == 0) {
  636. char msg[NS_CLIENT_ACLMSGSIZE("query")];
  637. if (result == ISC_R_SUCCESS) {
  638. if (isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(3))) {
  639. ns_client_aclmsg("query", name, qtype,
  640. client->view->rdclass,
  641. msg, sizeof(msg));
  642. ns_client_log(client,
  643. DNS_LOGCATEGORY_SECURITY,
  644. NS_LOGMODULE_QUERY,
  645. ISC_LOG_DEBUG(3),
  646. "%s approved", msg);
  647. }
  648. } else {
  649. ns_client_aclmsg("query", name, qtype,
  650. client->view->rdclass,
  651. msg, sizeof(msg));
  652. ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
  653. NS_LOGMODULE_QUERY, ISC_LOG_INFO,
  654. "%s denied", msg);
  655. }
  656. }
  657. if (queryacl == client->view->queryacl) {
  658. if (result == ISC_R_SUCCESS) {
  659. /*
  660. * We were allowed by the default
  661. * "allow-query" ACL. Remember this so we
  662. * don't have to check again.
  663. */
  664. client->query.attributes |= NS_QUERYATTR_QUERYOK;
  665. }
  666. /*
  667. * We've now evaluated the view's query ACL, and
  668. * the NS_QUERYATTR_QUERYOK attribute is now valid.
  669. */
  670. client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
  671. }
  672. dbversion->acl_checked = ISC_TRUE;
  673. if (result != ISC_R_SUCCESS) {
  674. dbversion->queryok = ISC_FALSE;
  675. return (DNS_R_REFUSED);
  676. }
  677. dbversion->queryok = ISC_TRUE;
  678. approved:
  679. /* Transfer ownership, if necessary. */
  680. if (versionp != NULL)
  681. *versionp = dbversion->version;
  682. return (ISC_R_SUCCESS);
  683. }
  684. static inline isc_result_t
  685. query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
  686. unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
  687. dns_dbversion_t **versionp)
  688. {
  689. isc_result_t result;
  690. unsigned int ztoptions;
  691. dns_zone_t *zone = NULL;
  692. dns_db_t *db = NULL;
  693. isc_boolean_t partial = ISC_FALSE;
  694. REQUIRE(zonep != NULL && *zonep == NULL);
  695. REQUIRE(dbp != NULL && *dbp == NULL);
  696. /*%
  697. * Find a zone database to answer the query.
  698. */
  699. ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ?
  700. DNS_ZTFIND_NOEXACT : 0;
  701. result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
  702. &zone);
  703. if (result == DNS_R_PARTIALMATCH)
  704. partial = ISC_TRUE;
  705. if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
  706. result = dns_zone_getdb(zone, &db);
  707. if (result != ISC_R_SUCCESS)
  708. goto fail;
  709. result = query_validatezonedb(client, name, qtype, options, zone, db,
  710. versionp);
  711. if (result != ISC_R_SUCCESS)
  712. goto fail;
  713. /* Transfer ownership. */
  714. *zonep = zone;
  715. *dbp = db;
  716. if (partial && (options & DNS_GETDB_PARTIAL) != 0)
  717. return (DNS_R_PARTIALMATCH);
  718. return (ISC_R_SUCCESS);
  719. fail:
  720. if (zone != NULL)
  721. dns_zone_detach(&zone);
  722. if (db != NULL)
  723. dns_db_detach(&db);
  724. return (result);
  725. }
  726. static void
  727. rpz_log_rewrite(ns_client_t *client, const char *disabled,
  728. dns_rpz_policy_t policy, dns_rpz_type_t type,
  729. dns_name_t *rpz_qname) {
  730. char qname_buf[DNS_NAME_FORMATSIZE];
  731. char rpz_qname_buf[DNS_NAME_FORMATSIZE];
  732. if (!isc_log_wouldlog(ns_g_lctx, DNS_RPZ_INFO_LEVEL))
  733. return;
  734. dns_name_format(client->query.qname, qname_buf, sizeof(qname_buf));
  735. dns_name_format(rpz_qname, rpz_qname_buf, sizeof(rpz_qname_buf));
  736. ns_client_log(client, DNS_LOGCATEGORY_RPZ, NS_LOGMODULE_QUERY,
  737. DNS_RPZ_INFO_LEVEL, "%srpz %s %s rewrite %s via %s",
  738. disabled,
  739. dns_rpz_type2str(type), dns_rpz_policy2str(policy),
  740. qname_buf, rpz_qname_buf);
  741. }
  742. static void
  743. rpz_log_fail(ns_client_t *client, int level,
  744. dns_rpz_type_t rpz_type, dns_name_t *name,
  745. const char *str, isc_result_t result)
  746. {
  747. char namebuf1[DNS_NAME_FORMATSIZE];
  748. char namebuf2[DNS_NAME_FORMATSIZE];
  749. if (!isc_log_wouldlog(ns_g_lctx, level))
  750. return;
  751. dns_name_format(client->query.qname, namebuf1, sizeof(namebuf1));
  752. dns_name_format(name, namebuf2, sizeof(namebuf2));
  753. ns_client_log(client, NS_LOGCATEGORY_QUERY_EERRORS,
  754. NS_LOGMODULE_QUERY, level,
  755. "rpz %s rewrite %s via %s %sfailed: %s",
  756. dns_rpz_type2str(rpz_type),
  757. namebuf1, namebuf2, str, isc_result_totext(result));
  758. }
  759. /*
  760. * Get a policy rewrite zone database.
  761. */
  762. static isc_result_t
  763. rpz_getdb(ns_client_t *client, dns_rpz_type_t rpz_type, dns_name_t *rpz_qname,
  764. dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp)
  765. {
  766. char namebuf1[DNS_NAME_FORMATSIZE];
  767. char namebuf2[DNS_NAME_FORMATSIZE];
  768. dns_dbversion_t *rpz_version = NULL;
  769. isc_result_t result;
  770. result = query_getzonedb(client, rpz_qname, dns_rdatatype_any,
  771. DNS_GETDB_IGNOREACL, zonep, dbp, &rpz_version);
  772. if (result == ISC_R_SUCCESS) {
  773. if (isc_log_wouldlog(ns_g_lctx, DNS_RPZ_DEBUG_LEVEL2)) {
  774. dns_name_format(client->query.qname, namebuf1,
  775. sizeof(namebuf1));
  776. dns_name_format(rpz_qname, namebuf2, sizeof(namebuf2));
  777. ns_client_log(client, DNS_LOGCATEGORY_RPZ,
  778. NS_LOGMODULE_QUERY, DNS_RPZ_DEBUG_LEVEL2,
  779. "try rpz %s rewrite %s via %s",
  780. dns_rpz_type2str(rpz_type),
  781. namebuf1, namebuf2);
  782. }
  783. *versionp = rpz_version;
  784. return (ISC_R_SUCCESS);
  785. }
  786. rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type, rpz_qname,
  787. "query_getzonedb() ", result);
  788. return (result);
  789. }
  790. static inline isc_result_t
  791. query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
  792. dns_db_t **dbp, unsigned int options)
  793. {
  794. isc_result_t result;
  795. isc_boolean_t check_acl;
  796. dns_db_t *db = NULL;
  797. REQUIRE(dbp != NULL && *dbp == NULL);
  798. /*%
  799. * Find a cache database to answer the query.
  800. * This may fail with DNS_R_REFUSED if the client
  801. * is not allowed to use the cache.
  802. */
  803. if (!USECACHE(client))
  804. return (DNS_R_REFUSED);
  805. dns_db_attach(client->view->cachedb, &db);
  806. if ((client->query.attributes & NS_QUERYATTR_CACHEACLOKVALID) != 0) {
  807. /*
  808. * We've evaluated the view's cacheacl already. If
  809. * NS_QUERYATTR_CACHEACLOK is set, then the client is
  810. * allowed to make queries, otherwise the query should
  811. * be refused.
  812. */
  813. check_acl = ISC_FALSE;
  814. if ((client->query.attributes & NS_QUERYATTR_CACHEACLOK) == 0)
  815. goto refuse;
  816. } else {
  817. /*
  818. * We haven't evaluated the view's queryacl yet.
  819. */
  820. check_acl = ISC_TRUE;
  821. }
  822. if (check_acl) {
  823. isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);
  824. char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];
  825. result = ns_client_checkaclsilent(client, NULL,
  826. client->view->cacheacl,
  827. ISC_TRUE);
  828. if (result == ISC_R_SUCCESS) {
  829. /*
  830. * We were allowed by the "allow-query-cache" ACL.
  831. * Remember this so we don't have to check again.
  832. */
  833. client->query.attributes |=
  834. NS_QUERYATTR_CACHEACLOK;
  835. if (log && isc_log_wouldlog(ns_g_lctx,
  836. ISC_LOG_DEBUG(3)))
  837. {
  838. ns_client_aclmsg("query (cache)", name, qtype,
  839. client->view->rdclass,
  840. msg, sizeof(msg));
  841. ns_client_log(client,
  842. DNS_LOGCATEGORY_SECURITY,
  843. NS_LOGMODULE_QUERY,
  844. ISC_LOG_DEBUG(3),
  845. "%s approved", msg);
  846. }
  847. } else if (log) {
  848. ns_client_aclmsg("query (cache)", name, qtype,
  849. client->view->rdclass, msg,
  850. sizeof(msg));
  851. ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
  852. NS_LOGMODULE_QUERY, ISC_LOG_INFO,
  853. "%s denied", msg);
  854. }
  855. /*
  856. * We've now evaluated the view's query ACL, and
  857. * the NS_QUERYATTR_CACHEACLOKVALID attribute is now valid.
  858. */
  859. client->query.attributes |= NS_QUERYATTR_CACHEACLOKVALID;
  860. if (result != ISC_R_SUCCESS)
  861. goto refuse;
  862. }
  863. /* Approved. */
  864. /* Transfer ownership. */
  865. *dbp = db;
  866. return (ISC_R_SUCCESS);
  867. refuse:
  868. result = DNS_R_REFUSED;
  869. if (db != NULL)
  870. dns_db_detach(&db);
  871. return (result);
  872. }
  873. static inline isc_result_t
  874. query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
  875. unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
  876. dns_dbversion_t **versionp, isc_boolean_t *is_zonep)
  877. {
  878. isc_result_t result;
  879. isc_result_t tresult;
  880. unsigned int namelabels;
  881. unsigned int zonelabels;
  882. dns_zone_t *zone = NULL;
  883. dns_db_t *tdbp;
  884. REQUIRE(zonep != NULL && *zonep == NULL);
  885. tdbp = NULL;
  886. /* Calculate how many labels are in name. */
  887. namelabels = dns_name_countlabels(name);
  888. zonelabels = 0;
  889. /* Try to find name in bind's standard database. */
  890. result = query_getzonedb(client, name, qtype, options, &zone,
  891. dbp, versionp);
  892. /* See how many labels are in the zone's name. */
  893. if (result == ISC_R_SUCCESS && zone != NULL)
  894. zonelabels = dns_name_countlabels(dns_zone_getorigin(zone));
  895. /*
  896. * If # zone labels < # name labels, try to find an even better match
  897. * Only try if a DLZ driver is loaded for this view
  898. */
  899. if (zonelabels < namelabels && client->view->dlzdatabase != NULL) {
  900. tresult = dns_dlzfindzone(client->view, name,
  901. zonelabels, &tdbp);
  902. /* If we successful, we found a better match. */
  903. if (tresult == ISC_R_SUCCESS) {
  904. /*
  905. * If the previous search returned a zone, detach it.
  906. */
  907. if (zone != NULL)
  908. dns_zone_detach(&zone);
  909. /*
  910. * If the previous search returned a database,
  911. * detach it.
  912. */
  913. if (*dbp != NULL)
  914. dns_db_detach(dbp);
  915. /*
  916. * If the previous search returned a version, clear it.
  917. */
  918. *versionp = NULL;
  919. /*
  920. * Get our database version.
  921. */
  922. dns_db_currentversion(tdbp, versionp);
  923. /*
  924. * Be sure to return our database.
  925. */
  926. *dbp = tdbp;
  927. /*
  928. * We return a null zone, No stats for DLZ zones.
  929. */
  930. zone = NULL;
  931. result = tresult;
  932. }
  933. }
  934. /* If successful, Transfer ownership of zone. */
  935. if (result == ISC_R_SUCCESS) {
  936. *zonep = zone;
  937. /*
  938. * If neither attempt above succeeded, return the cache instead
  939. */
  940. *is_zonep = ISC_TRUE;
  941. } else if (result == ISC_R_NOTFOUND) {
  942. result = query_getcachedb(client, name, qtype, dbp, options);
  943. *is_zonep = ISC_FALSE;
  944. }
  945. return (result);
  946. }
  947. static inline isc_boolean_t
  948. query_isduplicate(ns_client_t *client, dns_name_t *name,
  949. dns_rdatatype_t type, dns_name_t **mnamep)
  950. {
  951. dns_section_t section;
  952. dns_name_t *mname = NULL;
  953. isc_result_t result;
  954. CTRACE("query_isduplicate");
  955. for (section = DNS_SECTION_ANSWER;
  956. section <= DNS_SECTION_ADDITIONAL;
  957. section++) {
  958. result = dns_message_findname(client->message, section,
  959. name, type, 0, &mname, NULL);
  960. if (result == ISC_R_SUCCESS) {
  961. /*
  962. * We've already got this RRset in the response.
  963. */
  964. CTRACE("query_isduplicate: true: done");
  965. return (ISC_TRUE);
  966. } else if (result == DNS_R_NXRRSET) {
  967. /*
  968. * The name exists, but the rdataset does not.
  969. */
  970. if (section == DNS_SECTION_ADDITIONAL)
  971. break;
  972. } else
  973. RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
  974. mname = NULL;
  975. }
  976. if (mnamep != NULL)
  977. *mnamep = mname;
  978. CTRACE("query_isduplicate: false: done");
  979. return (ISC_FALSE);
  980. }
  981. static isc_result_t
  982. query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
  983. ns_client_t *client = arg;
  984. isc_result_t result, eresult;
  985. dns_dbnode_t *node;
  986. dns_db_t *db;
  987. dns_name_t *fname, *mname;
  988. dns_rdataset_t *rdataset, *sigrdataset, *trdataset;
  989. isc_buffer_t *dbuf;
  990. isc_buffer_t b;
  991. dns_dbversion_t *version;
  992. isc_boolean_t added_something, need_addname;
  993. dns_zone_t *zone;
  994. dns_rdatatype_t type;
  995. REQUIRE(NS_CLIENT_VALID(client));
  996. REQUIRE(qtype != dns_rdatatype_any);
  997. if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype))
  998. return (ISC_R_SUCCESS);
  999. CTRACE("query_addadditional");
  1000. /*
  1001. * Initialization.
  1002. */
  1003. eresult = ISC_R_SUCCESS;
  1004. fname = NULL;
  1005. rdataset = NULL;
  1006. sigrdataset = NULL;
  1007. trdataset = NULL;
  1008. db = NULL;
  1009. version = NULL;
  1010. node = NULL;
  1011. added_something = ISC_FALSE;
  1012. need_addname = ISC_FALSE;
  1013. zone = NULL;
  1014. /*
  1015. * We treat type A additional section processing as if it
  1016. * were "any address type" additional section processing.
  1017. * To avoid multiple lookups, we do an 'any' database
  1018. * lookup and iterate over the node.
  1019. */
  1020. if (qtype == dns_rdatatype_a)
  1021. type = dns_rdatatype_any;
  1022. else
  1023. type = qtype;
  1024. /*
  1025. * Get some resources.
  1026. */
  1027. dbuf = query_getnamebuf(client);
  1028. if (dbuf == NULL)
  1029. goto cleanup;
  1030. fname = query_newname(client, dbuf, &b);
  1031. rdataset = query_newrdataset(client);
  1032. if (fname == NULL || rdataset == NULL)
  1033. goto cleanup;
  1034. if (WANTDNSSEC(client)) {
  1035. sigrdataset = query_newrdataset(client);
  1036. if (sigrdataset == NULL)
  1037. goto cleanup;
  1038. }
  1039. /*
  1040. * Look for a zone database that might contain authoritative
  1041. * additional data.
  1042. */
  1043. result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
  1044. &zone, &db, &version);
  1045. if (result != ISC_R_SUCCESS)
  1046. goto try_cache;
  1047. CTRACE("query_addadditional: db_find");
  1048. /*
  1049. * Since we are looking for authoritative data, we do not set
  1050. * the GLUEOK flag. Glue will be looked for later, but not
  1051. * necessarily in the same database.
  1052. */
  1053. node = NULL;
  1054. result = dns_db_find(db, name, version, type, client->query.dboptions,
  1055. client->now, &node, fname, rdataset,
  1056. sigrdataset);
  1057. if (result == ISC_R_SUCCESS) {
  1058. if (sigrdataset != NULL && !dns_db_issecure(db) &&
  1059. dns_rdataset_isassociated(sigrdataset))
  1060. dns_rdataset_disassociate(sigrdataset);
  1061. goto found;
  1062. }
  1063. if (dns_rdataset_isassociated(rdataset))
  1064. dns_rdataset_disassociate(rdataset);
  1065. if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
  1066. dns_rdataset_disassociate(sigrdataset);
  1067. if (node != NULL)
  1068. dns_db_detachnode(db, &node);
  1069. version = NULL;
  1070. dns_db_detach(&db);
  1071. /*
  1072. * No authoritative data was found. The cache is our next best bet.
  1073. */
  1074. try_cache:
  1075. result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
  1076. if (result != ISC_R_SUCCESS)
  1077. /*
  1078. * Most likely the client isn't allowed to query the cache.
  1079. */
  1080. goto try_glue;
  1081. /*
  1082. * Attempt to validate glue.
  1083. */
  1084. if (sigrdataset == NULL) {
  1085. sigrdataset = query_newrdataset(client);
  1086. if (sigrdataset == NULL)
  1087. goto cleanup;
  1088. }
  1089. result = dns_db_find(db, name, version, type,
  1090. client->query.dboptions |
  1091. DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK,
  1092. client->now, &node, fname, rdataset,
  1093. sigrdataset);
  1094. if (result == DNS_R_GLUE &&
  1095. validate(client, db, fname, rdataset, sigrdataset))
  1096. result = ISC_R_SUCCESS;
  1097. if (!WANTDNSSEC(client))
  1098. query_putrdataset(client, &sigrdataset);
  1099. if (result == ISC_R_SUCCESS)
  1100. goto found;
  1101. if (dns_rdataset_isassociated(rdataset))
  1102. dns_rdataset_disassociate(rdataset);
  1103. if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
  1104. dns_rdataset_disassociate(sigrdataset);
  1105. if (node != NULL)
  1106. dns_db_detachnode(db, &node);
  1107. dns_db_detach(&db);
  1108. try_glue:
  1109. /*
  1110. * No cached data was found. Glue is our last chance.
  1111. * RFC1035 sayeth:
  1112. *
  1113. * NS records cause both the usual additional section
  1114. * processing to locate a type A record, and, when used
  1115. * in a referral, a special search of the zone in which
  1116. * they reside for glue information.
  1117. *
  1118. * This is the "special search". Note that we must search
  1119. * the zone where the NS record resides, not the zone it
  1120. * points to, and that we only do the search in the delegation
  1121. * case (identified by client->query.gluedb being set).
  1122. */
  1123. if (client->query.gluedb == NULL)
  1124. goto cleanup;
  1125. /*
  1126. * Don't poison caches using the bailiwick protection model.
  1127. */
  1128. if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
  1129. goto cleanup;
  1130. dns_db_attach(client->query.gluedb, &db);
  1131. result = dns_db_find(db, name, version, type,
  1132. client->query.dboptions | DNS_DBFIND_GLUEOK,
  1133. client->now, &node, fname, rdataset,
  1134. sigrdataset);
  1135. if (!(result == ISC_R_SUCCESS ||
  1136. result == DNS_R_ZONECUT ||
  1137. result == DNS_R_GLUE))
  1138. goto cleanup;
  1139. found:
  1140. /*
  1141. * We have found a potential additional data rdataset, or
  1142. * at least a node to iterate over.
  1143. */
  1144. query_keepname(client, fname, dbuf);
  1145. /*
  1146. * If we have an rdataset, add it to the additional data
  1147. * section.
  1148. */
  1149. mname = NULL;
  1150. if (dns_rdataset_isassociated(rdataset) &&
  1151. !query_isduplicate(client, fname, type, &mname)) {
  1152. if (mname != NULL) {
  1153. INSIST(mname != fname);
  1154. query_releasename(client, &fname);
  1155. fname = mname;
  1156. } else
  1157. need_addname = ISC_TRUE;
  1158. ISC_LIST_APPEND(fname->list, rdataset, link);
  1159. trdataset = rdataset;
  1160. rdataset = NULL;
  1161. added_something = ISC_TRUE;
  1162. /*
  1163. * Note: we only add SIGs if we've added the type they cover,
  1164. * so we do not need to check if the SIG rdataset is already
  1165. * in the response.
  1166. */
  1167. if (sigrdataset != NULL &&
  1168. dns_rdataset_isassociated(sigrdataset))
  1169. {
  1170. ISC_LIST_APPEND(fname->list, sigrdataset, link);
  1171. sigrdataset = NULL;
  1172. }
  1173. }
  1174. if (qtype == dns_rdatatype_a) {
  1175. #ifdef ALLOW_FILTER_AAAA_ON_V4
  1176. isc_boolean_t have_a = ISC_FALSE;
  1177. #endif
  1178. /*
  1179. * We now go looking for A and AAAA records, along with
  1180. * their signatures.
  1181. *
  1182. * XXXRTH This code could be more efficient.
  1183. */
  1184. if (rdataset != NULL) {
  1185. if (dns_rdataset_isassociated(rdataset))
  1186. dns_rdataset_disassociate(rdataset);
  1187. } else {
  1188. rdataset = query_newrdataset(client);
  1189. if (rdataset == NULL)
  1190. goto addname;
  1191. }
  1192. if (sigrdataset != NULL) {
  1193. if (dns_rdataset_isassociated(sigrdataset))
  1194. dns_rdataset_disassociate(sigrdataset);
  1195. } else if (WANTDNSSEC(client)) {
  1196. sigrdataset = query_newrdataset(client);
  1197. if (sigrdataset == NULL)
  1198. goto addname;
  1199. }
  1200. if (query_isduplicate(client, fname, dns_rdatatype_a, NULL))
  1201. goto aaaa_lookup;
  1202. result = dns_db_findrdataset(db, node, version,
  1203. dns_rdatatype_a, 0,
  1204. client->now, rdataset,
  1205. sigrdataset);
  1206. if (result == DNS_R_NCACHENXDOMAIN)
  1207. goto addname;
  1208. if (result == DNS_R_NCACHENXRRSET) {
  1209. dns_rdataset_disassociate(rdataset);
  1210. if (sigrdataset != NULL &&
  1211. dns_rdataset_isassociated(sigrdataset))
  1212. dns_rdataset_disassociate(sigrdataset);
  1213. }
  1214. if (result == ISC_R_SUCCESS) {
  1215. mname = NULL;
  1216. #ifdef ALLOW_FILTER_AAAA_ON_V4
  1217. have_a = ISC_TRUE;
  1218. #endif
  1219. if (!query_isduplicate(client, fname,
  1220. dns_rdatatype_a, &mname)) {
  1221. if (mname != fname) {
  1222. if (mname != NULL) {
  1223. query_releasename(client, &fname);
  1224. fname = mname;
  1225. } else
  1226. need_addname = ISC_TRUE;
  1227. }
  1228. ISC_LIST_APPEND(fname->list, rdataset, link);
  1229. added_something = ISC_TRUE;
  1230. if (sigrdataset != NULL &&
  1231. dns_rdataset_isassociated(sigrdataset))
  1232. {
  1233. ISC_LIST_APPEND(fname->list,
  1234. sigrdataset, link);
  1235. sigrdataset =
  1236. query_newrdataset(client);
  1237. }
  1238. rdataset = query_newrdataset(client);
  1239. if (rdataset == NULL)
  1240. goto addname;
  1241. if (WANTDNSSEC(client) && sigrdataset == NULL)
  1242. goto addname;
  1243. } else {
  1244. dns_rdataset_disassociate(rdataset);
  1245. if (sigrdataset != NULL &&
  1246. dns_rdataset_isassociated(sigrdataset))
  1247. dns_rdataset_disassociate(sigrdataset);
  1248. }
  1249. }
  1250. aaaa_lookup:
  1251. if (query_isduplicate(client, fname, dns_rdatatype_aaaa, NULL))
  1252. goto addname;
  1253. result = dns_db_findrdataset(db, node, version,
  1254. dns_rdatatype_aaaa, 0,
  1255. client->now, rdataset,
  1256. sigrdataset);
  1257. if (result == DNS_R_NCACHENXDOMAIN)
  1258. goto addname;
  1259. if (result == DNS_R_NCACHENXRRSET) {
  1260. dns_rdataset_disassociate(rdataset);
  1261. if (sigrdataset != NULL &&
  1262. dns_rdataset_isassociated(sigrdataset))
  1263. dns_rdataset_disassociate(sigrdataset);
  1264. }
  1265. if (result == ISC_R_SUCCESS) {
  1266. mname = NULL;
  1267. /*
  1268. * There's an A; check whether we're filtering AAAA
  1269. */
  1270. #ifdef ALLOW_FILTER_AAAA_ON_V4
  1271. if (have_a &&
  1272. (client->filter_aaaa == dns_v4_aaaa_break_dnssec ||
  1273. (client->filter_aaaa == dns_v4_aaaa_filter &&
  1274. (!WANTDNSSEC(client) || sigrdataset == NULL ||
  1275. !dns_rdataset_isassociated(sigrdataset)))))
  1276. goto addname;
  1277. #endif
  1278. if (!query_isduplicate(client, fname,
  1279. dns_rdatatype_aaaa, &mname)) {
  1280. if (mname != fname) {
  1281. if (mname != NULL) {
  1282. query_releasename(client, &fname);
  1283. fname = mname;
  1284. } else
  1285. need_addname = ISC_TRUE;
  1286. }
  1287. ISC_LIST_APPEND(fname->list, rdataset, link);
  1288. added_something = ISC_TRUE;
  1289. if (sigrdataset != NULL &&
  1290. dns_rdataset_isassociated(sigrdataset))
  1291. {
  1292. ISC_LIST_APPEND(fname->list,
  1293. sigrdataset, link);
  1294. sigrdataset = NULL;
  1295. }
  1296. rdataset = NULL;
  1297. }
  1298. }
  1299. }
  1300. addname:
  1301. CTRACE("query_addadditional: addname");
  1302. /*
  1303. * If we haven't added anything, then we're done.
  1304. */
  1305. if (!added_something)
  1306. goto cleanup;
  1307. /*
  1308. * We may have added our rdatasets to an existing name, if so, then
  1309. * need_addname will be ISC_FALSE. Whether we used an existing name
  1310. * or a new one, we must set fname to NULL to prevent cleanup.
  1311. */
  1312. if (need_addname)
  1313. dns_message_addname(client->message, fname,
  1314. DNS_SECTION_ADDITIONAL);
  1315. fname = NULL;
  1316. /*
  1317. * In a few cases, we want to add additional data for additional
  1318. * data. It's simpler to just deal with special cases here than
  1319. * to try to create a general purpose mechanism and allow the
  1320. * rdata implementations to do it themselves.
  1321. *
  1322. * This involves recursion, but the depth is limited. The
  1323. * most complex case is adding a SRV rdataset, which involves
  1324. * recursing to add address records, which in turn can cause
  1325. * recursion to add KEYs.
  1326. */
  1327. if (type == dns_rdatatype_srv && trdataset != NULL) {
  1328. /*
  1329. * If we're adding SRV records to the additional data
  1330. * section, it's helpful if we add the SRV additional data
  1331. * as well.
  1332. */
  1333. eresult = dns_rdataset_additionaldata(trdataset,
  1334. query_addadditional,
  1335. client);
  1336. }
  1337. cleanup:
  1338. CTRACE("query_addadditional: cleanup");
  1339. query_putrdataset(client, &rdataset);
  1340. if (sigrdataset != NULL)
  1341. query_putrdataset(client, &sigrdataset);
  1342. if (fname != NULL)
  1343. query_releasename(client, &fname);
  1344. if (node != NULL)
  1345. dns_db_detachnode(db, &node);
  1346. if (db != NULL)
  1347. dns_db_detach(&db);
  1348. if (zone != NULL)
  1349. dns_zone_detach(&zone);
  1350. CTRACE("query_addadditional: done");
  1351. return (eresult);
  1352. }
  1353. static inline void
  1354. query_discardcache(ns_client_t *client, dns_rdataset_t *rdataset_base,
  1355. dns_rdatasetadditional_t additionaltype,
  1356. dns_rdatatype_t type, dns_zone_t **zonep, dns_db_t **dbp,
  1357. dns_dbversion_t **versionp, dns_dbnode_t **nodep,
  1358. dns_name_t *fname)
  1359. {
  1360. dns_rdataset_t *rdataset;
  1361. while ((rdataset = ISC_LIST_HEAD(fname->list)) != NULL) {
  1362. ISC_LIST_UNLINK(fname->list, rdataset, link);
  1363. query_putrdataset(client, &rdataset);
  1364. }
  1365. if (*versionp != NULL)
  1366. dns_db_closeversion(*dbp, versionp, ISC_FALSE);
  1367. if (*nodep != NULL)
  1368. dns_db_detachnode(*dbp, nodep);
  1369. if (*dbp != NULL)
  1370. dns_db_detach(dbp);
  1371. if (*zonep != NULL)
  1372. dns_zone_detach(zonep);
  1373. (void)dns_rdataset_putadditional(client->view->acache, rdataset_base,
  1374. additionaltype, type);
  1375. }
  1376. static inline isc_result_t
  1377. query_iscachevalid(dns_zone_t *zone, dns_db_t *db, dns_db_t *db0,
  1378. dns_dbversion_t *version)
  1379. {
  1380. isc_result_t result = ISC_R_SUCCESS;
  1381. dns_dbversion_t *version_current = NULL;
  1382. dns_db_t *db_current = db0;
  1383. if (db_current == NULL) {
  1384. result = dns_zone_getdb(zone, &db_current);
  1385. if (result != ISC_R_SUCCESS)
  1386. return (result);
  1387. }
  1388. dns_db_currentversion(db_current, &version_current);
  1389. if (db_current != db || version_current != version) {
  1390. result = ISC_R_FAILURE;
  1391. goto cleanup;
  1392. }
  1393. cleanup:
  1394. dns_db_closeversion(db_current, &version_current, ISC_FALSE);
  1395. if (db0 == NULL && db_current != NULL)
  1396. dns_db_detach(&db_current);
  1397. return (result);
  1398. }
  1399. static isc_result_t
  1400. query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
  1401. client_additionalctx_t *additionalctx = arg;
  1402. dns_rdataset_t *rdataset_base;
  1403. ns_client_t *client;
  1404. isc_result_t result, eresult;
  1405. dns_dbnode_t *node, *cnode;
  1406. dns_db_t *db, *cdb;
  1407. dns_name_t *fname, *mname0, cfname;
  1408. dns_rdataset_t *rdataset, *sigrdataset;
  1409. dns_rdataset_t *crdataset, *crdataset_next;
  1410. isc_buffer_t *dbuf;
  1411. isc_buffer_t b;
  1412. dns_dbversion_t *version, *cversion;
  1413. isc_boolean_t added_something, need_addname, needadditionalcache;
  1414. isc_boolean_t need_sigrrset;
  1415. dns_zone_t *zone;
  1416. dns_rdatatype_t type;
  1417. dns_rdatasetadditional_t additionaltype;
  1418. /*
  1419. * If we don't have an additional cache call query_addadditional.
  1420. */
  1421. client = additionalctx->client;
  1422. REQUIRE(NS_CLIENT_VALID(client));
  1423. if (qtype != dns_rdatatype_a || client->view->acache == NULL) {
  1424. /*
  1425. * This function is optimized for "address" types. For other
  1426. * types, use a generic routine.
  1427. * XXX: ideally, this function should be generic enough.
  1428. */
  1429. return (query_addadditional(additionalctx->client,
  1430. name, qtype));
  1431. }
  1432. /*
  1433. * Initialization.
  1434. */
  1435. rdataset_base = additionalctx->rdataset;
  1436. eresult = ISC_R_SUCCESS;
  1437. fname = NULL;
  1438. rdataset = NULL;
  1439. sigrdataset = NULL;
  1440. db = NULL;
  1441. cdb = NULL;
  1442. version = NULL;
  1443. cversion = NULL;
  1444. node = NULL;
  1445. cnode = NULL;
  1446. added_something = ISC_FALSE;
  1447. need_addname = ISC_FALSE;
  1448. zone = NULL;
  1449. needadditionalcache = ISC_FALSE;
  1450. POST(needadditionalcache);
  1451. additionaltype = dns_rdatasetadditional_fromauth;
  1452. dns_name_init(&cfname, NULL);
  1453. CTRACE("query_addadditional2");
  1454. /*
  1455. * We treat type A additional section processing as if it
  1456. * were "any address type" additional section processing.
  1457. * To avoid multiple lookups, we do an 'any' database
  1458. * lookup and iterate over the node.
  1459. * XXXJT: this approach can cause a suboptimal result when the cache
  1460. * DB only has partial address types and the glue DB has remaining
  1461. * ones.
  1462. */
  1463. type = dns_rdatatype_any;
  1464. /*
  1465. * Get some resources.
  1466. */
  1467. dbuf = query_getnamebuf(client);
  1468. if (dbuf == NULL)
  1469. goto cleanup;
  1470. fname = query_newname(client, dbuf, &b);
  1471. if (fname == NULL)
  1472. goto cleanup;
  1473. dns_name_setbuffer(&cfname, &b); /* share the buffer */
  1474. /* Check additional cache */
  1475. result = dns_rdataset_getadditional(rdataset_base, additionaltype,
  1476. type, client->view->acache, &zone,
  1477. &cdb, &cversion, &cnode, &cfname,
  1478. client->message, client->now);
  1479. if (result != ISC_R_SUCCESS)
  1480. goto findauthdb;
  1481. if (zone == NULL) {
  1482. CTRACE("query_addadditional2: auth zone not found");
  1483. goto try_cache;
  1484. }
  1485. /* Is the cached DB up-to-date? */
  1486. result = query_iscachevalid(zone, cdb, NULL, cversion);
  1487. if (result != ISC_R_SUCCESS) {
  1488. CTRACE("query_addadditional2: old auth additional cache");
  1489. query_discardcache(client, rdataset_base, additionaltype,
  1490. type, &zone, &cdb, &cversion, &cnode,
  1491. &cfname);
  1492. goto findauthdb;
  1493. }
  1494. if (cnode == NULL) {
  1495. /*
  1496. * We have a negative cache. We don't have to check the zone
  1497. * ACL, since the result (not using this zone) would be same
  1498. * regardless of the result.
  1499. */
  1500. CTRACE("query_addadditional2: negative auth additional cache");
  1501. dns_db_closeversion(cdb, &cversion, ISC_FALSE);
  1502. dns_db_detach(&cdb);
  1503. dns_zone_detach(&zone);
  1504. goto try_cache;
  1505. }
  1506. result = query_validatezonedb(client, name, qtype, DNS_GETDB_NOLOG,
  1507. zone, cdb, NULL);
  1508. if (result != ISC_R_SUCCESS) {
  1509. query_discardcache(client, rdataset_base, additionaltype,
  1510. type, &zone, &cdb, &cversion, &cnode,
  1511. &cfname);
  1512. goto try_cache;
  1513. }
  1514. /* We've got an active cache. */
  1515. CTRACE("query_addadditional2: auth additional cache");
  1516. dns_db_closeversion(cdb, &cversion, ISC_FALSE);
  1517. db = cdb;
  1518. node = cnode;
  1519. dns_name_clone(&cfname, fname);
  1520. query_keepname(client, fname, dbuf);
  1521. goto foundcache;
  1522. /*
  1523. * Look for a zone database that might contain authoritative
  1524. * additional data.
  1525. */
  1526. findauthdb:
  1527. result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
  1528. &zone, &db, &version);
  1529. if (result != ISC_R_SUCCESS) {
  1530. /* Cache the negative result */
  1531. (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
  1532. type, client->view->acache,
  1533. NULL, NULL, NULL, NULL,
  1534. NULL);
  1535. goto try_cache;
  1536. }
  1537. CTRACE("query_addadditional2: db_find");
  1538. /*
  1539. * Since we are looking for authoritative data, we do not set
  1540. * the GLUEOK flag. Glue will be looked for later, but not
  1541. * necessarily in the same database.
  1542. */
  1543. node = NULL;
  1544. result = dns_db_find(db, name, version, type, client->query.dboptions,
  1545. client->now, &node, fname, NULL, NULL);
  1546. if (result == ISC_R_SUCCESS)
  1547. goto found;
  1548. /* Cache the negative result */
  1549. (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
  1550. type, client->view->acache, zone, db,
  1551. version, NULL, fname);
  1552. if (node != NULL)
  1553. dns_db_detachnode(db, &node);
  1554. version = NULL;
  1555. dns_db_detach(&db);
  1556. /*
  1557. * No authoritative data was found. The cache is our next best bet.
  1558. */
  1559. try_cache:
  1560. additionaltype = dns_rdatasetadditional_fromcache;
  1561. result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
  1562. if (result != ISC_R_SUCCESS)
  1563. /*
  1564. * Most likely the client isn't allowed to query the cache.
  1565. */
  1566. goto try_glue;
  1567. result = dns_db_find(db, name, version, type,
  1568. client->query.dboptions |
  1569. DNS_DBFIND_GLUEOK | DNS_DBFIND_ADDITIONALOK,
  1570. client->now, &node, fname, NULL, NULL);
  1571. if (result == ISC_R_SUCCESS)
  1572. goto found;
  1573. if (node != NULL)
  1574. dns_db_detachnode(db, &node);
  1575. dns_db_detach(&db);
  1576. try_glue:
  1577. /*
  1578. * No cached data was found. Glue is our last chance.
  1579. * RFC1035 sayeth:
  1580. *
  1581. * NS records cause both the usual additional section
  1582. * processing to locate a type A record, and, when used
  1583. * in a referral, a special search of the zone in which
  1584. * they reside for glue information.
  1585. *
  1586. * This is the "special search". Note that we must search
  1587. * the zone where the NS record resides, not the zone it
  1588. * points to, and that we only do the search in the delegation
  1589. * case (identified by client->query.gluedb being set).
  1590. */
  1591. if (client->query.gluedb == NULL)
  1592. goto cleanup;
  1593. /*
  1594. * Don't poison caches using the bailiwick protection model.
  1595. */
  1596. if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
  1597. goto cleanup;
  1598. /* Check additional cache */
  1599. additionaltype = dns_rdatasetadditional_fromglue;
  1600. result = dns_rdataset_getadditional(rdataset_base, additionaltype,
  1601. type, client->view->acache, NULL,
  1602. &cdb, &cversion, &cnode, &cfname,
  1603. client->message, client->now);
  1604. if (result != ISC_R_SUCCESS)
  1605. goto findglue;
  1606. result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion);
  1607. if (result != ISC_R_SUCCESS) {
  1608. CTRACE("query_addadditional2: old glue additional cache");
  1609. query_discardcache(client, rdataset_base, additionaltype,
  1610. type, &zone, &cdb, &cversion, &cnode,
  1611. &cfname);
  1612. goto findglue;
  1613. }
  1614. if (cnode == NULL) {
  1615. /* We have a negative cache. */
  1616. CTRACE("query_addadditional2: negative glue additional cache");
  1617. dns_db_closeversi