ncache.c revision d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3c
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley/*
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 1999-2003 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Permission to use, copy, modify, and distribute this software for any
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * purpose with or without fee is hereby granted, provided that the above
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉/* $Id: ncache.c,v 1.37 2004/12/21 10:45:17 jinmei Exp $ */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <config.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
f1788d67add6bf3d301e91b3f54fa3c90a87328eBrian Wellington#include <isc/buffer.h>
364a82f7c25b62967678027043425201a5e5171aBob Halley#include <isc/util.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <dns/db.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <dns/message.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <dns/ncache.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <dns/rdata.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#include <dns/rdatalist.h>
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <dns/rdataset.h>
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley/*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * The format of an ncache rdata is a sequence of one or more records of
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * the following format:
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley *
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * owner name
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * type
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * rdata count
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * rdata length These two occur 'rdata count'
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * rdata times.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley *
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic inline isc_result_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleycopy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_result_t result;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int count;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_region_t ar, r;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Copy the rdataset count to the buffer.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_availableregion(buffer, &ar);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (ar.length < 2)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_R_NOSPACE);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley count = dns_rdataset_count(rdataset);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley INSIST(count <= 65535);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_buffer_putuint16(buffer, (isc_uint16_t)count);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley result = dns_rdataset_first(rdataset);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley while (result == ISC_R_SUCCESS) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_rdataset_current(rdataset, &rdata);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_rdata_toregion(&rdata, &r);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley INSIST(r.length <= 65535);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_availableregion(buffer, &ar);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (ar.length < 2)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_R_NOSPACE);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Copy the rdata length to the buffer.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_buffer_putuint16(buffer, (isc_uint16_t)r.length);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Copy the rdata to the buffer.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley result = isc_buffer_copyregion(buffer, &r);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (result != ISC_R_SUCCESS)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (result);
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&rdata);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley result = dns_rdataset_next(rdataset);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley }
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (result != ISC_R_NOMORE)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (result);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (ISC_R_SUCCESS);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyisc_result_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
7cd4c3ddd1baf5f2b204562fdba3da37c716cc78Andreas Gustafsson dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_rdataset_t *addedrdataset)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley{
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_result_t result;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_buffer_t buffer;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_region_t r;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_rdataset_t *rdataset;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_rdatatype_t type;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_name_t *name;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_ttl_t ttl;
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley dns_trust_t trust;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley dns_rdataset_t ncrdataset;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley dns_rdatalist_t ncrdatalist;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley unsigned char data[4096];
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Convert the authority data from 'message' into a negative cache
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * rdataset, and store it in 'cache' at 'node'.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley REQUIRE(message != NULL);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * We assume that all data in the authority section has been
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * validated by the caller.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /*
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * First, build an ncache rdata in buffer.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
7cd4c3ddd1baf5f2b204562fdba3da37c716cc78Andreas Gustafsson ttl = maxttl;
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley trust = 0xffff;
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&buffer, data, sizeof(data));
4607e7a9b8dfb1b41c70e51c2b603daaf22cf302Mark Andrews if (message->counts[DNS_SECTION_AUTHORITY])
4607e7a9b8dfb1b41c70e51c2b603daaf22cf302Mark Andrews result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
4607e7a9b8dfb1b41c70e51c2b603daaf22cf302Mark Andrews else
4607e7a9b8dfb1b41c70e51c2b603daaf22cf302Mark Andrews result = ISC_R_NOMORE;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley while (result == ISC_R_SUCCESS) {
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley name = NULL;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_message_currentname(message, DNS_SECTION_AUTHORITY,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley &name);
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley if ((name->attributes & DNS_NAMEATTR_NCACHE) != 0) {
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley for (rdataset = ISC_LIST_HEAD(name->list);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley rdataset != NULL;
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley rdataset = ISC_LIST_NEXT(rdataset, link)) {
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if ((rdataset->attributes &
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley DNS_RDATASETATTR_NCACHE) == 0)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley continue;
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley type = rdataset->type;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (type == dns_rdatatype_rrsig)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley type = rdataset->covers;
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (type == dns_rdatatype_soa ||
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews type == dns_rdatatype_nsec) {
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (ttl > rdataset->ttl)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley ttl = rdataset->ttl;
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley if (trust > rdataset->trust)
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley trust = rdataset->trust;
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley /*
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * Copy the owner name to the buffer.
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley */
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley dns_name_toregion(name, &r);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley result = isc_buffer_copyregion(&buffer,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley &r);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (result != ISC_R_SUCCESS)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley return (result);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley /*
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * Copy the type to the buffer.
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence isc_buffer_availableregion(&buffer,
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence &r);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (r.length < 2)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley return (ISC_R_NOSPACE);
b5fff54fe9335b20c02d749831fc0eaeda97198fBrian Wellington isc_buffer_putuint16(&buffer,
b5fff54fe9335b20c02d749831fc0eaeda97198fBrian Wellington rdataset->type);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley /*
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley * Copy the rdataset into the buffer.
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley */
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley result = copy_rdataset(rdataset,
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley &buffer);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (result != ISC_R_SUCCESS)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley return (result);
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley }
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley }
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley }
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley }
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley if (result != ISC_R_NOMORE)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley return (result);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley if (trust == 0xffff) {
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley /*
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * We didn't find any authority data from which to create a
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * negative cache rdataset. In particular, we have no SOA.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley *
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * We trust that the caller wants negative caching, so this
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * means we have a "type 3 nxdomain" or "type 3 nodata"
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * response (see RFC 2308 for details).
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley *
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * We will now build a suitable negative cache rdataset that
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * will cause zero bytes to be emitted when converted to
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * wire format.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley */
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley /*
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * The ownername must exist, but it doesn't matter what value
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * it has. We use the root name.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley */
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley dns_name_toregion(dns_rootname, &r);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley result = isc_buffer_copyregion(&buffer, &r);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley if (result != ISC_R_SUCCESS)
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley return (result);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley /*
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * Copy the type and a zero rdata count to the buffer.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_availableregion(&buffer, &r);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley if (r.length < 4)
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley return (ISC_R_NOSPACE);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley isc_buffer_putuint16(&buffer, 0);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley isc_buffer_putuint16(&buffer, 0);
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley /*
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * RFC 2308, section 5, says that negative answers without
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * SOAs should not be cached.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley */
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley ttl = 0;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley /*
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * Set trust.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley */
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley if ((message->flags & DNS_MESSAGEFLAG_AA) != 0 &&
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley message->counts[DNS_SECTION_ANSWER] == 0) {
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley /*
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * The response has aa set and we haven't followed
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * any CNAME or DNAME chains.
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley */
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley trust = dns_trust_authauthority;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley } else
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley trust = dns_trust_additional;
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley }
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /*
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley * Now add it to the cache.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley INSIST(trust != 0xffff);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_usedregion(&buffer, &r);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley rdata.data = r.base;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley rdata.length = r.length;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley rdata.rdclass = dns_db_class(cache);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley rdata.type = 0;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews rdata.flags = 0;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley ncrdatalist.rdclass = rdata.rdclass;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley ncrdatalist.type = 0;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley ncrdatalist.covers = covers;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley ncrdatalist.ttl = ttl;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley ISC_LIST_INIT(ncrdatalist.rdata);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley ISC_LINK_INIT(&ncrdatalist, link);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley ISC_LIST_APPEND(ncrdatalist.rdata, &rdata, link);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_rdataset_init(&ncrdataset);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson == ISC_R_SUCCESS);
66b2f0d4bfa342770aa5e26a005a0c0ec5071231Bob Halley ncrdataset.trust = trust;
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews if (message->rcode == dns_rcode_nxdomain)
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
55254a46f91419b92eee0d20dfb958e8dd52526cBob Halley return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset,
08af8bf5ade4131fe44926ad04fd489e64a620bbBob Halley 0, addedrdataset));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyisc_result_t
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleydns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
b2ca6fd3a8293440b4d263723525396059cf2400Brian Wellington isc_buffer_t *target, unsigned int options,
84185d19c7a9ef1ac23cc6236c8773697d4efeb1Brian Wellington unsigned int *countp)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley{
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_result_t result;
8569ab045a4cf6ecd1b5a3354ddb1c93ef34ea57Brian Wellington isc_region_t remaining, tavailable;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_buffer_t source, savedbuffer, rdlen;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dns_name_t name;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dns_rdatatype_t type;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley unsigned int i, rcount, count;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Convert the negative caching rdataset 'rdataset' to wire format,
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * compressing names as specified in 'cctx', and storing the result in
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * 'target'.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
569d094440399b000e059d4cb3434391c2c4d330Michael Graff REQUIRE(rdataset != NULL);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley REQUIRE(rdataset->type == 0);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley result = dns_rdataset_first(rdataset);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley if (result != ISC_R_SUCCESS)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (result);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dns_rdataset_current(rdataset, &rdata);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&source, rdata.data, rdata.length);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_buffer_add(&source, rdata.length);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley savedbuffer = *target;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley count = 0;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley do {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dns_name_init(&name, NULL);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_remainingregion(&source, &remaining);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dns_name_fromregion(&name, &remaining);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley INSIST(remaining.length >= name.length);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_buffer_forward(&source, name.length);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley remaining.length -= name.length;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley INSIST(remaining.length >= 4);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley type = isc_buffer_getuint16(&source);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley rcount = isc_buffer_getuint16(&source);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley for (i = 0; i < rcount; i++) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Get the length of this rdata and set up an
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * rdata structure for it.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_remainingregion(&source, &remaining);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley INSIST(remaining.length >= 2);
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&rdata);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley rdata.length = isc_buffer_getuint16(&source);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_remainingregion(&source, &remaining);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley rdata.data = remaining.base;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley rdata.type = type;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley rdata.rdclass = rdataset->rdclass;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley INSIST(remaining.length >= rdata.length);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_buffer_forward(&source, rdata.length);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
b2ca6fd3a8293440b4d263723525396059cf2400Brian Wellington if ((options & DNS_NCACHETOWIRE_OMITDNSSEC) != 0 &&
b2ca6fd3a8293440b4d263723525396059cf2400Brian Wellington dns_rdatatype_isdnssec(type))
84185d19c7a9ef1ac23cc6236c8773697d4efeb1Brian Wellington continue;
84185d19c7a9ef1ac23cc6236c8773697d4efeb1Brian Wellington
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Write the name.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley */
94a08e09db3dc844b6ee4841c368a2d7074a9c3fAndreas Gustafsson dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley result = dns_name_towire(&name, cctx, target);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff if (result != ISC_R_SUCCESS)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley goto rollback;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * See if we have space for type, class, ttl, and
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * rdata length. Write the type, class, and ttl.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley */
8569ab045a4cf6ecd1b5a3354ddb1c93ef34ea57Brian Wellington isc_buffer_availableregion(target, &tavailable);
8569ab045a4cf6ecd1b5a3354ddb1c93ef34ea57Brian Wellington if (tavailable.length < 10) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley result = ISC_R_NOSPACE;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley goto rollback;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley }
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_buffer_putuint16(target, type);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_buffer_putuint16(target, rdataset->rdclass);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_buffer_putuint32(target, rdataset->ttl);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Save space for rdata length.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley rdlen = *target;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_buffer_add(target, 2);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Write the rdata.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley result = dns_rdata_towire(&rdata, cctx, target);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff if (result != ISC_R_SUCCESS)
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley goto rollback;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley /*
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Set the rdata length field to the compressed
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * length.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley */
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence INSIST((target->used >= rdlen.used + 2) &&
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence (target->used - rdlen.used - 2 < 65536));
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley isc_buffer_putuint16(&rdlen,
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence (isc_uint16_t)(target->used -
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence rdlen.used - 2));
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley count++;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley }
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_remainingregion(&source, &remaining);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley } while (remaining.length > 0);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley *countp = count;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (ISC_R_SUCCESS);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley rollback:
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence INSIST(savedbuffer.used < 65536);
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley *countp = 0;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley *target = savedbuffer;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley return (result);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley}
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsstatic void
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsrdataset_disassociate(dns_rdataset_t *rdataset) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews UNUSED(rdataset);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsstatic isc_result_t
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsrdataset_first(dns_rdataset_t *rdataset) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews unsigned char *raw = rdataset->private3;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews unsigned int count;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews count = raw[0] * 256 + raw[1];
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (count == 0) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->private5 = NULL;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_NOMORE);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews }
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews raw += 2;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews /*
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews * The privateuint4 field is the number of rdata beyond the cursor
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * position, so we decrement the total count by one before storing
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * it.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews */
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews count--;
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews rdataset->privateuint4 = count;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->private5 = raw;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_SUCCESS);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsstatic isc_result_t
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsrdataset_next(dns_rdataset_t *rdataset) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews unsigned int count;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews unsigned int length;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews unsigned char *raw;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews count = rdataset->privateuint4;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (count == 0)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_NOMORE);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews count--;
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews rdataset->privateuint4 = count;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews raw = rdataset->private5;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews length = raw[0] * 256 + raw[1];
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews raw += length + 2;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->private5 = raw;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_SUCCESS);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsstatic void
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsrdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews unsigned char *raw = rdataset->private5;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_region_t r;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(raw != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews r.length = raw[0] * 256 + raw[1];
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews raw += 2;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews r.base = raw;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsstatic void
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsrdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews *target = *source;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews /*
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Reset iterator state.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews */
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews target->privateuint4 = 0;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews target->private5 = NULL;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsstatic unsigned int
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsrdataset_count(dns_rdataset_t *rdataset) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews unsigned char *raw = rdataset->private3;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews unsigned int count;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews count = raw[0] * 256 + raw[1];
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (count);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsstatic dns_rdatasetmethods_t rdataset_methods = {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset_disassociate,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset_first,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset_next,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset_current,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset_clone,
7ac0df532272d803c3f72ff7a109587e92622f5aMark Andrews rdataset_count,
7ac0df532272d803c3f72ff7a109587e92622f5aMark Andrews NULL,
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉 NULL,
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉 NULL,
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉 NULL,
7ac0df532272d803c3f72ff7a109587e92622f5aMark Andrews NULL
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews};
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsisc_result_t
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsdns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_rdatatype_t type, dns_rdataset_t *rdataset)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews{
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_result_t result;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_rdata_t rdata = DNS_RDATA_INIT;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_region_t remaining;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_t source;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_name_t tname;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_rdatatype_t ttype;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews unsigned int i, rcount;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_uint16_t length;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(ncacherdataset != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(ncacherdataset->type == 0);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(name != NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews REQUIRE(!dns_rdataset_isassociated(rdataset));
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews REQUIRE(type != dns_rdatatype_rrsig);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews result = dns_rdataset_first(ncacherdataset);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (result != ISC_R_SUCCESS)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (result);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_rdataset_current(ncacherdataset, &rdata);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews INSIST(dns_rdataset_next(ncacherdataset) == ISC_R_NOMORE);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_init(&source, rdata.data, rdata.length);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_add(&source, rdata.length);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews do {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_name_init(&tname, NULL);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_remainingregion(&source, &remaining);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_name_fromregion(&tname, &remaining);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews INSIST(remaining.length >= tname.length);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_forward(&source, tname.length);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews remaining.length -= tname.length;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews INSIST(remaining.length >= 4);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews ttype = isc_buffer_getuint16(&source);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (ttype == type && dns_name_equal(&tname, name)) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_remainingregion(&source, &remaining);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews break;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews }
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rcount = isc_buffer_getuint16(&source);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews for (i = 0; i < rcount; i++) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_remainingregion(&source, &remaining);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews INSIST(remaining.length >= 2);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews length = isc_buffer_getuint16(&source);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_remainingregion(&source, &remaining);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews INSIST(remaining.length >= length);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_forward(&source, length);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews }
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_remainingregion(&source, &remaining);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews } while (remaining.length > 0);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews if (remaining.length == 0)
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_NOTFOUND);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->methods = &rdataset_methods;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->rdclass = ncacherdataset->rdclass;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->type = type;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->covers = 0;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->ttl = ncacherdataset->ttl;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->trust = ncacherdataset->trust;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->private1 = NULL;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->private2 = NULL;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->private3 = remaining.base;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews /*
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Reset iterator state.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews */
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews rdataset->privateuint4 = 0;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rdataset->private5 = NULL;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews return (ISC_R_SUCCESS);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}