ncache.c revision 7ac0df532272d803c3f72ff7a109587e92622f5a
/*
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: ncache.c,v 1.35 2004/01/20 14:21:14 marka Exp $ */
#include <config.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
/*
* The format of an ncache rdata is a sequence of one or more records of
* the following format:
*
* owner name
* type
* rdata count
* rdata length These two occur 'rdata count'
* rdata times.
*
*/
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);
}
{
isc_region_t r;
unsigned char data[4096];
/*
* 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.
*/
/*
* First, build an ncache rdata in 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) {
/*
* 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 < 2)
return (ISC_R_NOSPACE);
/*
* Copy the rdataset into the buffer.
*/
&buffer);
if (result != ISC_R_SUCCESS)
return (result);
}
}
}
}
if (result != ISC_R_NOMORE)
return (result);
if (trust == 0xffff) {
/*
* We didn't find any authority data from which to create a
* negative cache rdataset. In particular, we have no SOA.
*
* We trust that the caller wants negative caching, so this
* means we have a "type 3 nxdomain" or "type 3 nodata"
* response (see RFC 2308 for details).
*
* We will now build a suitable negative cache rdataset that
* will cause zero bytes to be emitted when converted to
* wire format.
*/
/*
* The ownername must exist, but it doesn't matter what value
* it has. We use the root name.
*/
if (result != ISC_R_SUCCESS)
return (result);
/*
* Copy the type and a zero rdata count to the buffer.
*/
isc_buffer_availableregion(&buffer, &r);
if (r.length < 4)
return (ISC_R_NOSPACE);
isc_buffer_putuint16(&buffer, 0);
isc_buffer_putuint16(&buffer, 0);
/*
* RFC 2308, section 5, says that negative answers without
* SOAs should not be cached.
*/
ttl = 0;
/*
* Set trust.
*/
/*
* The response has aa set and we haven't followed
* any CNAME or DNAME chains.
*/
} else
}
/*
* Now add it to the cache.
*/
isc_buffer_usedregion(&buffer, &r);
ncrdatalist.type = 0;
== ISC_R_SUCCESS);
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'.
*/
if (result != ISC_R_SUCCESS)
return (result);
savedbuffer = *target;
count = 0;
do {
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++;
}
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 dns_rdatasetmethods_t rdataset_methods = {
NULL,
};
{
unsigned int i, rcount;
if (result != ISC_R_SUCCESS)
return (result);
do {
break;
}
for (i = 0; i < rcount; i++) {
}
return (ISC_R_NOTFOUND);
/*
* Reset iterator state.
*/
rdataset->privateuint4 = 0;
return (ISC_R_SUCCESS);
}