/contrib/bind9/lib/dns/ncache.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 738 lines · 537 code · 89 blank · 112 comment · 101 complexity · 1463c58d307e6186306d4d340a2836e0 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004, 2005, 2007, 2008, 2010-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$ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <isc/buffer.h>
  21. #include <isc/util.h>
  22. #include <dns/db.h>
  23. #include <dns/message.h>
  24. #include <dns/ncache.h>
  25. #include <dns/rdata.h>
  26. #include <dns/rdatalist.h>
  27. #include <dns/rdataset.h>
  28. #include <dns/rdatastruct.h>
  29. #define DNS_NCACHE_RDATA 20U
  30. /*
  31. * The format of an ncache rdata is a sequence of zero or more records of
  32. * the following format:
  33. *
  34. * owner name
  35. * type
  36. * trust
  37. * rdata count
  38. * rdata length These two occur 'rdata count'
  39. * rdata times.
  40. *
  41. */
  42. static inline isc_result_t
  43. copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
  44. isc_result_t result;
  45. unsigned int count;
  46. isc_region_t ar, r;
  47. dns_rdata_t rdata = DNS_RDATA_INIT;
  48. /*
  49. * Copy the rdataset count to the buffer.
  50. */
  51. isc_buffer_availableregion(buffer, &ar);
  52. if (ar.length < 2)
  53. return (ISC_R_NOSPACE);
  54. count = dns_rdataset_count(rdataset);
  55. INSIST(count <= 65535);
  56. isc_buffer_putuint16(buffer, (isc_uint16_t)count);
  57. result = dns_rdataset_first(rdataset);
  58. while (result == ISC_R_SUCCESS) {
  59. dns_rdataset_current(rdataset, &rdata);
  60. dns_rdata_toregion(&rdata, &r);
  61. INSIST(r.length <= 65535);
  62. isc_buffer_availableregion(buffer, &ar);
  63. if (ar.length < 2)
  64. return (ISC_R_NOSPACE);
  65. /*
  66. * Copy the rdata length to the buffer.
  67. */
  68. isc_buffer_putuint16(buffer, (isc_uint16_t)r.length);
  69. /*
  70. * Copy the rdata to the buffer.
  71. */
  72. result = isc_buffer_copyregion(buffer, &r);
  73. if (result != ISC_R_SUCCESS)
  74. return (result);
  75. dns_rdata_reset(&rdata);
  76. result = dns_rdataset_next(rdataset);
  77. }
  78. if (result != ISC_R_NOMORE)
  79. return (result);
  80. return (ISC_R_SUCCESS);
  81. }
  82. isc_result_t
  83. dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
  84. dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
  85. dns_rdataset_t *addedrdataset)
  86. {
  87. return (dns_ncache_addoptout(message, cache, node, covers, now, maxttl,
  88. ISC_FALSE, addedrdataset));
  89. }
  90. isc_result_t
  91. dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
  92. dns_dbnode_t *node, dns_rdatatype_t covers,
  93. isc_stdtime_t now, dns_ttl_t maxttl,
  94. isc_boolean_t optout, dns_rdataset_t *addedrdataset)
  95. {
  96. isc_result_t result;
  97. isc_buffer_t buffer;
  98. isc_region_t r;
  99. dns_rdataset_t *rdataset;
  100. dns_rdatatype_t type;
  101. dns_name_t *name;
  102. dns_ttl_t ttl;
  103. dns_trust_t trust;
  104. dns_rdata_t rdata[DNS_NCACHE_RDATA];
  105. dns_rdataset_t ncrdataset;
  106. dns_rdatalist_t ncrdatalist;
  107. unsigned char data[4096];
  108. unsigned int next = 0;
  109. /*
  110. * Convert the authority data from 'message' into a negative cache
  111. * rdataset, and store it in 'cache' at 'node'.
  112. */
  113. REQUIRE(message != NULL);
  114. /*
  115. * We assume that all data in the authority section has been
  116. * validated by the caller.
  117. */
  118. /*
  119. * Initialize the list.
  120. */
  121. ncrdatalist.rdclass = dns_db_class(cache);
  122. ncrdatalist.type = 0;
  123. ncrdatalist.covers = covers;
  124. ncrdatalist.ttl = maxttl;
  125. ISC_LIST_INIT(ncrdatalist.rdata);
  126. ISC_LINK_INIT(&ncrdatalist, link);
  127. /*
  128. * Build an ncache rdatas into buffer.
  129. */
  130. ttl = maxttl;
  131. trust = 0xffff;
  132. isc_buffer_init(&buffer, data, sizeof(data));
  133. if (message->counts[DNS_SECTION_AUTHORITY])
  134. result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
  135. else
  136. result = ISC_R_NOMORE;
  137. while (result == ISC_R_SUCCESS) {
  138. name = NULL;
  139. dns_message_currentname(message, DNS_SECTION_AUTHORITY,
  140. &name);
  141. if ((name->attributes & DNS_NAMEATTR_NCACHE) != 0) {
  142. for (rdataset = ISC_LIST_HEAD(name->list);
  143. rdataset != NULL;
  144. rdataset = ISC_LIST_NEXT(rdataset, link)) {
  145. if ((rdataset->attributes &
  146. DNS_RDATASETATTR_NCACHE) == 0)
  147. continue;
  148. type = rdataset->type;
  149. if (type == dns_rdatatype_rrsig)
  150. type = rdataset->covers;
  151. if (type == dns_rdatatype_soa ||
  152. type == dns_rdatatype_nsec ||
  153. type == dns_rdatatype_nsec3) {
  154. if (ttl > rdataset->ttl)
  155. ttl = rdataset->ttl;
  156. if (trust > rdataset->trust)
  157. trust = rdataset->trust;
  158. /*
  159. * Copy the owner name to the buffer.
  160. */
  161. dns_name_toregion(name, &r);
  162. result = isc_buffer_copyregion(&buffer,
  163. &r);
  164. if (result != ISC_R_SUCCESS)
  165. return (result);
  166. /*
  167. * Copy the type to the buffer.
  168. */
  169. isc_buffer_availableregion(&buffer,
  170. &r);
  171. if (r.length < 3)
  172. return (ISC_R_NOSPACE);
  173. isc_buffer_putuint16(&buffer,
  174. rdataset->type);
  175. isc_buffer_putuint8(&buffer,
  176. (unsigned char)rdataset->trust);
  177. /*
  178. * Copy the rdataset into the buffer.
  179. */
  180. result = copy_rdataset(rdataset,
  181. &buffer);
  182. if (result != ISC_R_SUCCESS)
  183. return (result);
  184. if (next >= DNS_NCACHE_RDATA)
  185. return (ISC_R_NOSPACE);
  186. dns_rdata_init(&rdata[next]);
  187. isc_buffer_remainingregion(&buffer, &r);
  188. rdata[next].data = r.base;
  189. rdata[next].length = r.length;
  190. rdata[next].rdclass =
  191. ncrdatalist.rdclass;
  192. rdata[next].type = 0;
  193. rdata[next].flags = 0;
  194. ISC_LIST_APPEND(ncrdatalist.rdata,
  195. &rdata[next], link);
  196. isc_buffer_forward(&buffer, r.length);
  197. next++;
  198. }
  199. }
  200. }
  201. result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
  202. }
  203. if (result != ISC_R_NOMORE)
  204. return (result);
  205. if (trust == 0xffff) {
  206. if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 &&
  207. message->counts[DNS_SECTION_ANSWER] == 0) {
  208. /*
  209. * The response has aa set and we haven't followed
  210. * any CNAME or DNAME chains.
  211. */
  212. trust = dns_trust_authauthority;
  213. } else
  214. trust = dns_trust_additional;
  215. ttl = 0;
  216. }
  217. INSIST(trust != 0xffff);
  218. ncrdatalist.ttl = ttl;
  219. dns_rdataset_init(&ncrdataset);
  220. RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
  221. == ISC_R_SUCCESS);
  222. ncrdataset.trust = trust;
  223. ncrdataset.attributes |= DNS_RDATASETATTR_NEGATIVE;
  224. if (message->rcode == dns_rcode_nxdomain)
  225. ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN;
  226. if (optout)
  227. ncrdataset.attributes |= DNS_RDATASETATTR_OPTOUT;
  228. return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset,
  229. 0, addedrdataset));
  230. }
  231. isc_result_t
  232. dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
  233. isc_buffer_t *target, unsigned int options,
  234. unsigned int *countp)
  235. {
  236. dns_rdata_t rdata = DNS_RDATA_INIT;
  237. isc_result_t result;
  238. isc_region_t remaining, tavailable;
  239. isc_buffer_t source, savedbuffer, rdlen;
  240. dns_name_t name;
  241. dns_rdatatype_t type;
  242. unsigned int i, rcount, count;
  243. /*
  244. * Convert the negative caching rdataset 'rdataset' to wire format,
  245. * compressing names as specified in 'cctx', and storing the result in
  246. * 'target'.
  247. */
  248. REQUIRE(rdataset != NULL);
  249. REQUIRE(rdataset->type == 0);
  250. REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
  251. savedbuffer = *target;
  252. count = 0;
  253. result = dns_rdataset_first(rdataset);
  254. while (result == ISC_R_SUCCESS) {
  255. dns_rdataset_current(rdataset, &rdata);
  256. isc_buffer_init(&source, rdata.data, rdata.length);
  257. isc_buffer_add(&source, rdata.length);
  258. dns_name_init(&name, NULL);
  259. isc_buffer_remainingregion(&source, &remaining);
  260. dns_name_fromregion(&name, &remaining);
  261. INSIST(remaining.length >= name.length);
  262. isc_buffer_forward(&source, name.length);
  263. remaining.length -= name.length;
  264. INSIST(remaining.length >= 5);
  265. type = isc_buffer_getuint16(&source);
  266. isc_buffer_forward(&source, 1);
  267. rcount = isc_buffer_getuint16(&source);
  268. for (i = 0; i < rcount; i++) {
  269. /*
  270. * Get the length of this rdata and set up an
  271. * rdata structure for it.
  272. */
  273. isc_buffer_remainingregion(&source, &remaining);
  274. INSIST(remaining.length >= 2);
  275. dns_rdata_reset(&rdata);
  276. rdata.length = isc_buffer_getuint16(&source);
  277. isc_buffer_remainingregion(&source, &remaining);
  278. rdata.data = remaining.base;
  279. rdata.type = type;
  280. rdata.rdclass = rdataset->rdclass;
  281. INSIST(remaining.length >= rdata.length);
  282. isc_buffer_forward(&source, rdata.length);
  283. if ((options & DNS_NCACHETOWIRE_OMITDNSSEC) != 0 &&
  284. dns_rdatatype_isdnssec(type))
  285. continue;
  286. /*
  287. * Write the name.
  288. */
  289. dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
  290. result = dns_name_towire(&name, cctx, target);
  291. if (result != ISC_R_SUCCESS)
  292. goto rollback;
  293. /*
  294. * See if we have space for type, class, ttl, and
  295. * rdata length. Write the type, class, and ttl.
  296. */
  297. isc_buffer_availableregion(target, &tavailable);
  298. if (tavailable.length < 10) {
  299. result = ISC_R_NOSPACE;
  300. goto rollback;
  301. }
  302. isc_buffer_putuint16(target, type);
  303. isc_buffer_putuint16(target, rdataset->rdclass);
  304. isc_buffer_putuint32(target, rdataset->ttl);
  305. /*
  306. * Save space for rdata length.
  307. */
  308. rdlen = *target;
  309. isc_buffer_add(target, 2);
  310. /*
  311. * Write the rdata.
  312. */
  313. result = dns_rdata_towire(&rdata, cctx, target);
  314. if (result != ISC_R_SUCCESS)
  315. goto rollback;
  316. /*
  317. * Set the rdata length field to the compressed
  318. * length.
  319. */
  320. INSIST((target->used >= rdlen.used + 2) &&
  321. (target->used - rdlen.used - 2 < 65536));
  322. isc_buffer_putuint16(&rdlen,
  323. (isc_uint16_t)(target->used -
  324. rdlen.used - 2));
  325. count++;
  326. }
  327. INSIST(isc_buffer_remaininglength(&source) == 0);
  328. result = dns_rdataset_next(rdataset);
  329. dns_rdata_reset(&rdata);
  330. }
  331. if (result != ISC_R_NOMORE)
  332. goto rollback;
  333. *countp = count;
  334. return (ISC_R_SUCCESS);
  335. rollback:
  336. INSIST(savedbuffer.used < 65536);
  337. dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
  338. *countp = 0;
  339. *target = savedbuffer;
  340. return (result);
  341. }
  342. static void
  343. rdataset_disassociate(dns_rdataset_t *rdataset) {
  344. UNUSED(rdataset);
  345. }
  346. static isc_result_t
  347. rdataset_first(dns_rdataset_t *rdataset) {
  348. unsigned char *raw = rdataset->private3;
  349. unsigned int count;
  350. count = raw[0] * 256 + raw[1];
  351. if (count == 0) {
  352. rdataset->private5 = NULL;
  353. return (ISC_R_NOMORE);
  354. }
  355. raw += 2;
  356. /*
  357. * The privateuint4 field is the number of rdata beyond the cursor
  358. * position, so we decrement the total count by one before storing
  359. * it.
  360. */
  361. count--;
  362. rdataset->privateuint4 = count;
  363. rdataset->private5 = raw;
  364. return (ISC_R_SUCCESS);
  365. }
  366. static isc_result_t
  367. rdataset_next(dns_rdataset_t *rdataset) {
  368. unsigned int count;
  369. unsigned int length;
  370. unsigned char *raw;
  371. count = rdataset->privateuint4;
  372. if (count == 0)
  373. return (ISC_R_NOMORE);
  374. count--;
  375. rdataset->privateuint4 = count;
  376. raw = rdataset->private5;
  377. length = raw[0] * 256 + raw[1];
  378. raw += length + 2;
  379. rdataset->private5 = raw;
  380. return (ISC_R_SUCCESS);
  381. }
  382. static void
  383. rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
  384. unsigned char *raw = rdataset->private5;
  385. isc_region_t r;
  386. REQUIRE(raw != NULL);
  387. r.length = raw[0] * 256 + raw[1];
  388. raw += 2;
  389. r.base = raw;
  390. dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
  391. }
  392. static void
  393. rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
  394. *target = *source;
  395. /*
  396. * Reset iterator state.
  397. */
  398. target->privateuint4 = 0;
  399. target->private5 = NULL;
  400. }
  401. static unsigned int
  402. rdataset_count(dns_rdataset_t *rdataset) {
  403. unsigned char *raw = rdataset->private3;
  404. unsigned int count;
  405. count = raw[0] * 256 + raw[1];
  406. return (count);
  407. }
  408. static void
  409. rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) {
  410. unsigned char *raw = rdataset->private3;
  411. raw[-1] = (unsigned char)trust;
  412. }
  413. static dns_rdatasetmethods_t rdataset_methods = {
  414. rdataset_disassociate,
  415. rdataset_first,
  416. rdataset_next,
  417. rdataset_current,
  418. rdataset_clone,
  419. rdataset_count,
  420. NULL,
  421. NULL,
  422. NULL,
  423. NULL,
  424. NULL,
  425. NULL,
  426. NULL,
  427. rdataset_settrust,
  428. NULL
  429. };
  430. isc_result_t
  431. dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
  432. dns_rdatatype_t type, dns_rdataset_t *rdataset)
  433. {
  434. isc_result_t result;
  435. dns_rdata_t rdata = DNS_RDATA_INIT;
  436. isc_region_t remaining;
  437. isc_buffer_t source;
  438. dns_name_t tname;
  439. dns_rdatatype_t ttype;
  440. dns_trust_t trust = dns_trust_none;
  441. dns_rdataset_t clone;
  442. REQUIRE(ncacherdataset != NULL);
  443. REQUIRE(ncacherdataset->type == 0);
  444. REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
  445. REQUIRE(name != NULL);
  446. REQUIRE(!dns_rdataset_isassociated(rdataset));
  447. REQUIRE(type != dns_rdatatype_rrsig);
  448. dns_rdataset_init(&clone);
  449. dns_rdataset_clone(ncacherdataset, &clone);
  450. result = dns_rdataset_first(&clone);
  451. while (result == ISC_R_SUCCESS) {
  452. dns_rdataset_current(&clone, &rdata);
  453. isc_buffer_init(&source, rdata.data, rdata.length);
  454. isc_buffer_add(&source, rdata.length);
  455. dns_name_init(&tname, NULL);
  456. isc_buffer_remainingregion(&source, &remaining);
  457. dns_name_fromregion(&tname, &remaining);
  458. INSIST(remaining.length >= tname.length);
  459. isc_buffer_forward(&source, tname.length);
  460. remaining.length -= tname.length;
  461. INSIST(remaining.length >= 3);
  462. ttype = isc_buffer_getuint16(&source);
  463. if (ttype == type && dns_name_equal(&tname, name)) {
  464. trust = isc_buffer_getuint8(&source);
  465. INSIST(trust <= dns_trust_ultimate);
  466. isc_buffer_remainingregion(&source, &remaining);
  467. break;
  468. }
  469. result = dns_rdataset_next(&clone);
  470. dns_rdata_reset(&rdata);
  471. }
  472. dns_rdataset_disassociate(&clone);
  473. if (result == ISC_R_NOMORE)
  474. return (ISC_R_NOTFOUND);
  475. if (result != ISC_R_SUCCESS)
  476. return (result);
  477. INSIST(remaining.length != 0);
  478. rdataset->methods = &rdataset_methods;
  479. rdataset->rdclass = ncacherdataset->rdclass;
  480. rdataset->type = type;
  481. rdataset->covers = 0;
  482. rdataset->ttl = ncacherdataset->ttl;
  483. rdataset->trust = trust;
  484. rdataset->private1 = NULL;
  485. rdataset->private2 = NULL;
  486. rdataset->private3 = remaining.base;
  487. /*
  488. * Reset iterator state.
  489. */
  490. rdataset->privateuint4 = 0;
  491. rdataset->private5 = NULL;
  492. rdataset->private6 = NULL;
  493. return (ISC_R_SUCCESS);
  494. }
  495. isc_result_t
  496. dns_ncache_getsigrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
  497. dns_rdatatype_t covers, dns_rdataset_t *rdataset)
  498. {
  499. dns_name_t tname;
  500. dns_rdata_rrsig_t rrsig;
  501. dns_rdata_t rdata = DNS_RDATA_INIT;
  502. dns_rdataset_t clone;
  503. dns_rdatatype_t type;
  504. dns_trust_t trust = dns_trust_none;
  505. isc_buffer_t source;
  506. isc_region_t remaining, sigregion;
  507. isc_result_t result;
  508. unsigned char *raw;
  509. unsigned int count;
  510. REQUIRE(ncacherdataset != NULL);
  511. REQUIRE(ncacherdataset->type == 0);
  512. REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
  513. REQUIRE(name != NULL);
  514. REQUIRE(!dns_rdataset_isassociated(rdataset));
  515. dns_rdataset_init(&clone);
  516. dns_rdataset_clone(ncacherdataset, &clone);
  517. result = dns_rdataset_first(&clone);
  518. while (result == ISC_R_SUCCESS) {
  519. dns_rdataset_current(&clone, &rdata);
  520. isc_buffer_init(&source, rdata.data, rdata.length);
  521. isc_buffer_add(&source, rdata.length);
  522. dns_name_init(&tname, NULL);
  523. isc_buffer_remainingregion(&source, &remaining);
  524. dns_name_fromregion(&tname, &remaining);
  525. INSIST(remaining.length >= tname.length);
  526. isc_buffer_forward(&source, tname.length);
  527. remaining.length -= tname.length;
  528. remaining.base += tname.length;
  529. INSIST(remaining.length >= 2);
  530. type = isc_buffer_getuint16(&source);
  531. remaining.length -= 2;
  532. remaining.base += 2;
  533. if (type != dns_rdatatype_rrsig ||
  534. !dns_name_equal(&tname, name)) {
  535. result = dns_rdataset_next(&clone);
  536. dns_rdata_reset(&rdata);
  537. continue;
  538. }
  539. INSIST(remaining.length >= 1);
  540. trust = isc_buffer_getuint8(&source);
  541. INSIST(trust <= dns_trust_ultimate);
  542. remaining.length -= 1;
  543. remaining.base += 1;
  544. raw = remaining.base;
  545. count = raw[0] * 256 + raw[1];
  546. INSIST(count > 0);
  547. raw += 2;
  548. sigregion.length = raw[0] * 256 + raw[1];
  549. raw += 2;
  550. sigregion.base = raw;
  551. dns_rdata_reset(&rdata);
  552. dns_rdata_fromregion(&rdata, rdataset->rdclass,
  553. dns_rdatatype_rrsig, &sigregion);
  554. (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
  555. if (rrsig.covered == covers) {
  556. isc_buffer_remainingregion(&source, &remaining);
  557. break;
  558. }
  559. result = dns_rdataset_next(&clone);
  560. dns_rdata_reset(&rdata);
  561. }
  562. dns_rdataset_disassociate(&clone);
  563. if (result == ISC_R_NOMORE)
  564. return (ISC_R_NOTFOUND);
  565. if (result != ISC_R_SUCCESS)
  566. return (result);
  567. INSIST(remaining.length != 0);
  568. rdataset->methods = &rdataset_methods;
  569. rdataset->rdclass = ncacherdataset->rdclass;
  570. rdataset->type = dns_rdatatype_rrsig;
  571. rdataset->covers = covers;
  572. rdataset->ttl = ncacherdataset->ttl;
  573. rdataset->trust = trust;
  574. rdataset->private1 = NULL;
  575. rdataset->private2 = NULL;
  576. rdataset->private3 = remaining.base;
  577. /*
  578. * Reset iterator state.
  579. */
  580. rdataset->privateuint4 = 0;
  581. rdataset->private5 = NULL;
  582. rdataset->private6 = NULL;
  583. return (ISC_R_SUCCESS);
  584. }
  585. void
  586. dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
  587. dns_rdataset_t *rdataset)
  588. {
  589. dns_rdata_t rdata = DNS_RDATA_INIT;
  590. dns_trust_t trust;
  591. isc_region_t remaining, sigregion;
  592. isc_buffer_t source;
  593. dns_name_t tname;
  594. dns_rdatatype_t type;
  595. unsigned int count;
  596. dns_rdata_rrsig_t rrsig;
  597. unsigned char *raw;
  598. REQUIRE(ncacherdataset != NULL);
  599. REQUIRE(ncacherdataset->type == 0);
  600. REQUIRE((ncacherdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0);
  601. REQUIRE(found != NULL);
  602. REQUIRE(!dns_rdataset_isassociated(rdataset));
  603. dns_rdataset_current(ncacherdataset, &rdata);
  604. isc_buffer_init(&source, rdata.data, rdata.length);
  605. isc_buffer_add(&source, rdata.length);
  606. dns_name_init(&tname, NULL);
  607. isc_buffer_remainingregion(&source, &remaining);
  608. dns_name_fromregion(found, &remaining);
  609. INSIST(remaining.length >= found->length);
  610. isc_buffer_forward(&source, found->length);
  611. remaining.length -= found->length;
  612. INSIST(remaining.length >= 5);
  613. type = isc_buffer_getuint16(&source);
  614. trust = isc_buffer_getuint8(&source);
  615. INSIST(trust <= dns_trust_ultimate);
  616. isc_buffer_remainingregion(&source, &remaining);
  617. rdataset->methods = &rdataset_methods;
  618. rdataset->rdclass = ncacherdataset->rdclass;
  619. rdataset->type = type;
  620. if (type == dns_rdatatype_rrsig) {
  621. /*
  622. * Extract covers from RRSIG.
  623. */
  624. raw = remaining.base;
  625. count = raw[0] * 256 + raw[1];
  626. INSIST(count > 0);
  627. raw += 2;
  628. sigregion.length = raw[0] * 256 + raw[1];
  629. raw += 2;
  630. sigregion.base = raw;
  631. dns_rdata_reset(&rdata);
  632. dns_rdata_fromregion(&rdata, rdataset->rdclass,
  633. rdataset->type, &sigregion);
  634. (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
  635. rdataset->covers = rrsig.covered;
  636. } else
  637. rdataset->covers = 0;
  638. rdataset->ttl = ncacherdataset->ttl;
  639. rdataset->trust = trust;
  640. rdataset->private1 = NULL;
  641. rdataset->private2 = NULL;
  642. rdataset->private3 = remaining.base;
  643. /*
  644. * Reset iterator state.
  645. */
  646. rdataset->privateuint4 = 0;
  647. rdataset->private5 = NULL;
  648. rdataset->private6 = NULL;
  649. }