ncache.c revision 0c27b3fe77ac1d5094ba3521e8142d9e7973133f
/*
* Copyright (C) 1999-2005, 2007, 2008, 2010-2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/* $Id$ */
/*! \file */
#include <config.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h>
#define DNS_NCACHE_RDATA 20U
/*
* The format of an ncache rdata is a sequence of zero or more records of
* the following format:
*
* owner name
* type
* trust
* rdata count
* rdata length These two occur 'rdata count'
* rdata times.
*
*/
static isc_result_t
static inline isc_result_t
unsigned int count;
isc_region_t ar, r;
/*
* Copy the rdataset count to the buffer.
*/
return (ISC_R_NOSPACE);
while (result == ISC_R_SUCCESS) {
dns_rdata_toregion(&rdata, &r);
return (ISC_R_NOSPACE);
/*
* Copy the rdata length to the buffer.
*/
/*
* Copy the rdata to the buffer.
*/
if (result != ISC_R_SUCCESS)
return (result);
}
if (result != ISC_R_NOMORE)
return (result);
return (ISC_R_SUCCESS);
}
{
}
{
}
static isc_result_t
{
isc_region_t r;
unsigned char data[4096];
unsigned int next = 0;
/*
* Convert the authority data from 'message' into a negative cache
* rdataset, and store it in 'cache' at 'node'.
*/
/*
* We assume that all data in the authority section has been
* validated by the caller.
*/
/*
* Initialize the list.
*/
/*
* Build an ncache rdatas into buffer.
*/
trust = 0xffff;
else
while (result == ISC_R_SUCCESS) {
&name);
if ((rdataset->attributes &
DNS_RDATASETATTR_NCACHE) == 0)
continue;
if (type == dns_rdatatype_rrsig)
if (type == dns_rdatatype_soa ||
type == dns_rdatatype_nsec ||
type == dns_rdatatype_nsec3) {
/*
* Copy the owner name to the buffer.
*/
dns_name_toregion(name, &r);
&r);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Copy the type to the buffer.
*/
&r);
if (r.length < 3)
return (ISC_R_NOSPACE);
/*
* Copy the rdataset into the buffer.
*/
&buffer);
if (result != ISC_R_SUCCESS)
return (result);
if (next >= DNS_NCACHE_RDATA)
return (ISC_R_NOSPACE);
isc_buffer_remainingregion(&buffer, &r);
next++;
}
}
}
}
if (result != ISC_R_NOMORE)
return (result);
if (trust == 0xffff) {
/*
* The response has aa set and we haven't followed
* any CNAME or DNAME chains.
*/
} else
ttl = 0;
}
== ISC_R_SUCCESS);
if (optout)
0, addedrdataset));
}
unsigned int *countp)
{
/*
* Convert the negative caching rdataset 'rdataset' to wire format,
* compressing names as specified in 'cctx', and storing the result in
* 'target'.
*/
savedbuffer = *target;
count = 0;
while (result == ISC_R_SUCCESS) {
for (i = 0; i < rcount; i++) {
/*
* Get the length of this rdata and set up an
* rdata structure for it.
*/
if ((options & DNS_NCACHETOWIRE_OMITDNSSEC) != 0 &&
continue;
/*
* Write the name.
*/
if (result != ISC_R_SUCCESS)
goto rollback;
/*
* See if we have space for type, class, ttl, and
* rdata length. Write the type, class, and ttl.
*/
goto rollback;
}
/*
* Save space for rdata length.
*/
/*
* Write the rdata.
*/
if (result != ISC_R_SUCCESS)
goto rollback;
/*
* Set the rdata length field to the compressed
* length.
*/
count++;
}
}
if (result != ISC_R_NOMORE)
goto rollback;
return (ISC_R_SUCCESS);
*countp = 0;
*target = savedbuffer;
return (result);
}
static void
}
static isc_result_t
unsigned int count;
if (count == 0) {
return (ISC_R_NOMORE);
}
raw += 2;
/*
* The privateuint4 field is the number of rdata beyond the cursor
* position, so we decrement the total count by one before storing
* it.
*/
count--;
return (ISC_R_SUCCESS);
}
static isc_result_t
unsigned int count;
unsigned int length;
unsigned char *raw;
if (count == 0)
return (ISC_R_NOMORE);
count--;
return (ISC_R_SUCCESS);
}
static void
isc_region_t r;
raw += 2;
}
static void
/*
* Reset iterator state.
*/
target->privateuint4 = 0;
}
static unsigned int
unsigned int count;
return (count);
}
static void
}
static dns_rdatasetmethods_t rdataset_methods = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
};
{
while (result == ISC_R_SUCCESS) {
break;
}
}
if (result == ISC_R_NOMORE)
return (ISC_R_NOTFOUND);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Reset iterator state.
*/
rdataset->privateuint4 = 0;
return (ISC_R_SUCCESS);
}
{
unsigned char *raw;
unsigned int count;
while (result == ISC_R_SUCCESS) {
if (type != dns_rdatatype_rrsig ||
continue;
}
raw += 2;
raw += 2;
break;
}
}
if (result == ISC_R_NOMORE)
return (ISC_R_NOTFOUND);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Reset iterator state.
*/
rdataset->privateuint4 = 0;
return (ISC_R_SUCCESS);
}
void
{
unsigned int count;
unsigned char *raw;
if (type == dns_rdatatype_rrsig) {
/*
* Extract covers from RRSIG.
*/
raw += 2;
raw += 2;
} else
/*
* Reset iterator state.
*/
rdataset->privateuint4 = 0;
}