/*! \file */
-#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
*current = tcurrent;
}
-static void
-rdata_to_slabitem(unsigned char **current, dns_rdatatype_t type,
- dns_rdata_t *rdata) {
- unsigned int length = rdata->length;
- unsigned char *data = rdata->data;
- unsigned char *p = *current;
-
- if (type == dns_rdatatype_rrsig) {
- length++;
- data--;
- }
-
- put_uint16(p, length);
- memmove(p, data, length);
- p += length;
-
- *current = p;
-}
-
-typedef struct slabinfo {
- unsigned char *pos;
- dns_rdata_t rdata;
- bool dup;
-} slabinfo_t;
-
-isc_result_t
-dns_rdataslab_merge(dns_slabheader_t *oheader, dns_slabheader_t *nheader,
- isc_mem_t *mctx, dns_rdataclass_t rdclass,
- dns_rdatatype_t type, unsigned int flags,
- uint32_t maxrrperset, dns_slabheader_t **theaderp) {
- isc_result_t result = ISC_R_SUCCESS;
- unsigned char *ocurrent = NULL, *ncurrent = NULL, *tcurrent = NULL;
- unsigned int ocount, ncount, tlength, tcount = 0;
- slabinfo_t *oinfo = NULL, *ninfo = NULL;
- size_t o = 0, n = 0;
-
- REQUIRE(theaderp != NULL && *theaderp == NULL);
- REQUIRE(oheader != NULL && nheader != NULL);
-
- ocurrent = (unsigned char *)oheader + sizeof(dns_slabheader_t);
- ocount = get_uint16(ocurrent);
-
- ncurrent = (unsigned char *)nheader + sizeof(dns_slabheader_t);
- ncount = get_uint16(ncurrent);
-
- INSIST(ocount > 0 && ncount > 0);
-
- if (maxrrperset > 0 && ocount + ncount > maxrrperset) {
- return DNS_R_TOOMANYRECORDS;
- }
-
- /*
- * Figure out the target length. Start with the header,
- * plus 2 octets for the count.
- */
- tlength = sizeof(dns_slabheader_t) + 2;
-
- /*
- * Gather the rdatas in the old slab and add their lengths to
- * the larget length.
- */
- oinfo = isc_mem_cget(mctx, ocount, sizeof(struct slabinfo));
- for (size_t i = 0; i < ocount; i++) {
- oinfo[i].pos = ocurrent;
- dns_rdata_init(&oinfo[i].rdata);
- rdata_from_slabitem(&ocurrent, rdclass, type, &oinfo[i].rdata);
- tlength += ocurrent - oinfo[i].pos;
- }
-
- /*
- * Then add the length of rdatas in the new slab that aren't
- * duplicated in the old slab.
- */
- ninfo = isc_mem_cget(mctx, ncount, sizeof(struct slabinfo));
- for (size_t i = 0; i < ncount; i++) {
- ninfo[i].pos = ncurrent;
- dns_rdata_init(&ninfo[i].rdata);
- rdata_from_slabitem(&ncurrent, rdclass, type, &ninfo[i].rdata);
-
- for (size_t j = 0; j < ocount; j++) {
- if (oinfo[j].dup) {
- /*
- * This was already found to be
- * duplicated; no need to compare
- * it again.
- */
- continue;
- }
-
- if (dns_rdata_compare(&oinfo[j].rdata,
- &ninfo[i].rdata) == 0)
- {
- /*
- * Found a dup. Mark the old copy as a
- * duplicate so we don't check it again;
- * mark the new copy as a duplicate so we
- * don't copy it to the target.
- */
- oinfo[j].dup = ninfo[i].dup = true;
- break;
- }
- }
-
- if (ninfo[i].dup) {
- continue;
- }
-
- /*
- * We will be copying this item to the target, so
- * add its length to tlength and increment tcount.
- */
- tlength += ncurrent - ninfo[i].pos;
- tcount++;
- }
-
- /*
- * If the EXACT flag is set, there can't be any rdata in
- * the new slab that was also in the old. If tcount is less
- * than ncount, then we found such a duplicate.
- */
- if (((flags & DNS_RDATASLAB_EXACT) != 0) && (tcount < ncount)) {
- CLEANUP(DNS_R_NOTEXACT);
- }
-
- /*
- * If nothing's being copied in from the new slab, and the
- * FORCE flag isn't set, we're done.
- */
- if (tcount == 0 && (flags & DNS_RDATASLAB_FORCE) == 0) {
- CLEANUP(DNS_R_UNCHANGED);
- }
-
- /* Add to tcount the total number of items from the old slab. */
- tcount += ocount;
-
- /* Resposition ncurrent at the first item. */
- ncurrent = (unsigned char *)nheader + sizeof(dns_slabheader_t) + 2;
-
- /* Single types can't have more than one RR. */
- if (tcount > 1 && dns_rdatatype_issingleton(type)) {
- CLEANUP(DNS_R_SINGLETON);
- }
-
- if (tcount > 0xffff) {
- CLEANUP(ISC_R_NOSPACE);
- }
-
- /* Allocate the target buffer and copy the new slab's header */
- unsigned char *tstart = isc_mem_get(mctx, tlength);
-
- memmove(tstart, nheader, sizeof(dns_slabheader_t));
- tcurrent = tstart + sizeof(dns_slabheader_t);
-
- /* Write the new count, then start merging the slabs. */
- put_uint16(tcurrent, tcount);
-
- /*
- * Now walk the sets together, adding each item in DNSSEC order,
- * and skipping over any more dups in the new slab.
- */
- while (o < ocount || n < ncount) {
- bool fromold;
-
- /* Skip to the next non-duplicate in the new slab. */
- for (; n < ncount && ninfo[n].dup; n++)
- ;
-
- if (o == ocount) {
- fromold = false;
- } else if (n == ncount) {
- fromold = true;
- } else {
- fromold = dns_rdata_compare(&oinfo[o].rdata,
- &ninfo[n].rdata) < 0;
- }
-
- if (fromold) {
- rdata_to_slabitem(&tcurrent, type, &oinfo[o].rdata);
- if (++o < ocount) {
- /* Skip to the next rdata in the old slab */
- continue;
- }
- } else {
- rdata_to_slabitem(&tcurrent, type, &ninfo[n++].rdata);
- }
- }
-
- INSIST(tcurrent == tstart + tlength);
-
- *theaderp = (dns_slabheader_t *)tstart;
-
-cleanup:
- isc_mem_cput(mctx, oinfo, ocount, sizeof(struct slabinfo));
- isc_mem_cput(mctx, ninfo, ncount, sizeof(struct slabinfo));
-
- return result;
-}
-
-isc_result_t
-dns_rdataslab_subtract(dns_slabheader_t *oheader, dns_slabheader_t *sheader,
- isc_mem_t *mctx, dns_rdataclass_t rdclass,
- dns_rdatatype_t type, unsigned int flags,
- dns_slabheader_t **theaderp) {
- isc_result_t result = ISC_R_SUCCESS;
- unsigned char *ocurrent = NULL, *scurrent = NULL;
- unsigned char *tstart = NULL, *tcurrent = NULL;
- unsigned int ocount, scount, tlength;
- unsigned int tcount = 0, rcount = 0;
- slabinfo_t *oinfo = NULL, *sinfo = NULL;
-
- REQUIRE(theaderp != NULL && *theaderp == NULL);
- REQUIRE(oheader != NULL && sheader != NULL);
-
- ocurrent = (unsigned char *)oheader + sizeof(dns_slabheader_t);
- ocount = get_uint16(ocurrent);
-
- scurrent = (unsigned char *)sheader + sizeof(dns_slabheader_t);
- scount = get_uint16(scurrent);
-
- INSIST(ocount > 0 && scount > 0);
-
- /* Get info about the rdatas being subtracted */
- sinfo = isc_mem_cget(mctx, scount, sizeof(struct slabinfo));
- for (size_t i = 0; i < scount; i++) {
- sinfo[i].pos = scurrent;
- dns_rdata_init(&sinfo[i].rdata);
- rdata_from_slabitem(&scurrent, rdclass, type, &sinfo[i].rdata);
- }
-
- /*
- * Figure out the target length. Start with the header,
- * plus 2 octets for the count.
- */
- tlength = sizeof(dns_slabheader_t) + 2;
-
- /*
- * Add the length of the rdatas in the old slab that
- * aren't being subtracted.
- */
- oinfo = isc_mem_cget(mctx, ocount, sizeof(struct slabinfo));
- for (size_t i = 0; i < ocount; i++) {
- bool matched = false;
-
- oinfo[i].pos = ocurrent;
- dns_rdata_init(&oinfo[i].rdata);
- rdata_from_slabitem(&ocurrent, rdclass, type, &oinfo[i].rdata);
-
- for (size_t j = 0; j < scount; j++) {
- if (sinfo[j].dup) {
- continue;
- } else if (dns_rdata_compare(&oinfo[i].rdata,
- &sinfo[j].rdata) == 0)
- {
- matched = true;
- oinfo[i].dup = sinfo[j].dup = true;
- break;
- }
- }
-
- if (matched) {
- /* This item will be subtracted. */
- rcount++;
- } else {
- /*
- * This rdata wasn't in the slab to be subtracted,
- * so copy it to the target. Add its length to
- * tlength and increment tcount.
- */
- tlength += ocurrent - oinfo[i].pos;
- tcount++;
- }
- }
-
- /*
- * If the EXACT flag wasn't set, check that all the records that
- * were to be subtracted actually did exist in the original slab.
- * (The numeric check works here because rdataslabs do not contain
- * duplicates.)
- */
- if ((flags & DNS_RDATASLAB_EXACT) != 0 && rcount != scount) {
- CLEANUP(DNS_R_NOTEXACT);
- }
-
- /*
- * If the resulting rdataslab would be empty, don't bother to
- * create a new buffer, just return.
- */
- if (tcount == 0) {
- CLEANUP(DNS_R_NXRRSET);
- }
-
- /*
- * If nothing is going to change, stop.
- */
- if (rcount == 0) {
- CLEANUP(DNS_R_UNCHANGED);
- }
-
- /*
- * Allocate the target buffer and copy the old slab's header.
- */
- tstart = isc_mem_get(mctx, tlength);
- memmove(tstart, oheader, sizeof(dns_slabheader_t));
- tcurrent = tstart + sizeof(dns_slabheader_t);
-
- /*
- * Write the new count.
- */
- put_uint16(tcurrent, tcount);
-
- /*
- * Copy the parts of the old slab that didn't have duplicates.
- */
- for (size_t i = 0; i < ocount; i++) {
- if (!oinfo[i].dup) {
- rdata_to_slabitem(&tcurrent, type, &oinfo[i].rdata);
- }
- }
-
- INSIST(tcurrent == tstart + tlength);
-
- *theaderp = (dns_slabheader_t *)tstart;
-
-cleanup:
- isc_mem_cput(mctx, oinfo, ocount, sizeof(struct slabinfo));
- isc_mem_cput(mctx, sinfo, scount, sizeof(struct slabinfo));
-
- return result;
-}
-
bool
dns_rdataslab_equal(dns_slabheader_t *slab1, dns_slabheader_t *slab2) {
unsigned char *current1 = NULL, *current2 = NULL;
return true;
}
-void
-dns_slabheader_setownercase(dns_slabheader_t *header, const dns_name_t *name) {
- REQUIRE(!CASESET(header));
-
- bool casefullylower = true;
-
- /*
- * We do not need to worry about label lengths as they are all
- * less than or equal to 63.
- */
- memset(header->upper, 0, sizeof(header->upper));
- for (size_t i = 0; i < name->length; i++) {
- if (isupper(name->ndata[i])) {
- header->upper[i / 8] |= 1 << (i % 8);
- casefullylower = false;
- }
- }
- if (casefullylower) {
- DNS_SLABHEADER_SETATTR(header,
- DNS_SLABHEADERATTR_CASEFULLYLOWER);
- }
- DNS_SLABHEADER_SETATTR(header, DNS_SLABHEADERATTR_CASESET);
-}
-
-void
-dns_slabheader_copycase(dns_slabheader_t *dest, dns_slabheader_t *src) {
- REQUIRE(!CASESET(dest));
- if (CASESET(src)) {
- memmove(dest->upper, src->upper, sizeof(src->upper));
- if (CASEFULLYLOWER(src)) {
- DNS_SLABHEADER_SETATTR(
- dest, DNS_SLABHEADERATTR_CASEFULLYLOWER);
- }
- DNS_SLABHEADER_SETATTR(dest, DNS_SLABHEADERATTR_CASESET);
- }
-}
-
void
dns_slabheader_reset(dns_slabheader_t *h, dns_dbnode_t *node) {
h->heap_index = 0;