ncache.c revision 84185d19c7a9ef1ac23cc6236c8773697d4efeb1
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley/*
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington * Copyright (C) 1999-2001 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 *
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
15a44745412679c30a6d022733925af70a38b715David Lawrence * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
15a44745412679c30a6d022733925af70a38b715David Lawrence * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15a44745412679c30a6d022733925af70a38b715David Lawrence * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley
84185d19c7a9ef1ac23cc6236c8773697d4efeb1Brian Wellington/* $Id: ncache.c,v 1.27 2002/01/22 09:07:22 bwelling 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));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
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;
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (type == dns_rdatatype_sig)
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley type = rdataset->covers;
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley if (type == dns_rdatatype_soa ||
e0df061f35a26d2bbd0986aa889f88b3710b32d4Bob Halley type == dns_rdatatype_nxt) {
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;
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,
84185d19c7a9ef1ac23cc6236c8773697d4efeb1Brian Wellington isc_buffer_t *target, isc_boolean_t omit_dnssec,
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
84185d19c7a9ef1ac23cc6236c8773697d4efeb1Brian Wellington if (omit_dnssec && 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}