cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff/*
82ddae820c63b19ff59693771512ae541cc95d63Tinderbox User * Copyright (C) 1999-2016, 2018 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff */
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
28a8f5b0de57d269cf2845c69cb6abe18cbd3b3aMark Andrews/* $Id$ */
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*! \file */
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff#include <config.h>
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington#include <stdlib.h>
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/mem.h>
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff#include <isc/region.h>
6028d1ce0380d0ba7f6c6ecd1ad20b31ddd1becbDavid Lawrence#include <isc/string.h> /* Required for HP/UX (and others?) */
364a82f7c25b62967678027043425201a5e5171aBob Halley#include <isc/util.h>
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff#include <dns/result.h>
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff#include <dns/rdata.h>
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff#include <dns/rdataset.h>
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff#include <dns/rdataslab.h>
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews/*
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * The rdataslab structure allows iteration to occur in both load order
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * and DNSSEC order. The structure is as follows:
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * header (reservelen bytes)
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * record count (2 bytes)
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * offset table (4 x record count bytes in load order)
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * data records
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * data length (2 bytes)
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * order (2 bytes)
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews * meta data (1 byte for RRSIG's)
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * data (data length bytes)
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews * If DNS_RDATASET_FIXED is defined to be zero (0) the format of a
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews * rdataslab is as follows:
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews *
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews * header (reservelen bytes)
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews * record count (2 bytes)
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews * data records
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews * data length (2 bytes)
4a4066453f45c869fc9f91d9807b7b8b25b004a0Mark Andrews * meta data (1 byte for RRSIG's)
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews * data (data length bytes)
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews *
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * Offsets are from the end of the header.
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * Load order traversal is performed by walking the offset table to find
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews * the start of the record (DNS_RDATASET_FIXED = 1).
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * DNSSEC order traversal is performed by walking the data records.
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *
bdfaef63f576f810fab27f64395faccf2fcd9434Francis Dupont * The order is stored with record to allow for efficient reconstruction
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * of the offset table following a merge or subtraction.
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * The iterator methods here currently only support DNSSEC order iteration.
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * The iterator methods in rbtdb support both load order and DNSSEC order
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * iteration.
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * WARNING:
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * rbtdb.c directly interacts with the slab's raw structures. If the
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * structure changes then rbtdb.c also needs to be updated to reflect
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * the changes. See the areas tagged with "RDATASLAB".
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews */
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrewsstruct xrdata {
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews dns_rdata_t rdata;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned int order;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews};
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/*% Note: the "const void *" are just to make qsort happy. */
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellingtonstatic int
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellingtoncompare_rdata(const void *p1, const void *p2) {
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews const struct xrdata *x1 = p1;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews const struct xrdata *x2 = p2;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews return (dns_rdata_compare(&x1->rdata, &x2->rdata));
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews}
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrewsstatic void
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrewsfillin_offsets(unsigned char *offsetbase, unsigned int *offsettable,
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned length)
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews{
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned int i, j;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned char *raw;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews for (i = 0, j = 0; i < length; i++) {
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews if (offsettable[i] == 0)
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews continue;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews /*
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * Fill in offset table.
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews */
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews raw = &offsetbase[j*4 + 2];
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *raw++ = (offsettable[i] & 0xff000000) >> 24;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *raw++ = (offsettable[i] & 0xff0000) >> 16;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *raw++ = (offsettable[i] & 0xff00) >> 8;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *raw = offsettable[i] & 0xff;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews /*
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * Fill in table index.
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews */
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews raw = offsetbase + offsettable[i] + 2;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *raw++ = (j & 0xff00) >> 8;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews *raw = j++ & 0xff;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews }
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington}
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graffdns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff isc_region_t *region, unsigned int reservelen)
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff{
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews /*
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews * Use &removed as a sentinal pointer for duplicate
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews * rdata as rdata.data == NULL is valid.
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews */
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews static unsigned char removed;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews struct xrdata *x;
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff unsigned char *rawbuf;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned char *offsetbase;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff unsigned int buflen;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff isc_result_t result;
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff unsigned int nitems;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned int nalloc;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned int i;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned int *offsettable;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews unsigned int length;
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff buflen = reservelen + 2;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews nitems = dns_rdataset_count(rdataset);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews /*
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews * If there are no rdata then we can just need to allocate a header
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews * with zero a record count.
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews */
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews if (nitems == 0) {
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews if (rdataset->type != 0)
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews return (ISC_R_FAILURE);
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews rawbuf = isc_mem_get(mctx, buflen);
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews if (rawbuf == NULL)
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews return (ISC_R_NOMEMORY);
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews region->base = rawbuf;
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews region->length = buflen;
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews rawbuf += reservelen;
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews *rawbuf++ = 0;
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews *rawbuf = 0;
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews return (ISC_R_SUCCESS);
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews }
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews if (nitems > 0xffff)
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews return (ISC_R_NOSPACE);
784a904bd06c7492361ed09a882d10c636b1291bAutomatic Updater
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews /*
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews * Remember the original number of items.
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews */
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews nalloc = nitems;
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata));
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews if (x == NULL)
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews return (ISC_R_NOMEMORY);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington /*
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington * Save all of the rdata members into an array.
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington */
1b088f46804fd569bf1b2274583d48e83f4f7aebAndreas Gustafsson result = dns_rdataset_first(rdataset);
c1ee8bb4ba3e9ab1463403ed685729631de406b1Mark Andrews if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley goto free_rdatas;
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) {
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington INSIST(result == ISC_R_SUCCESS);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews dns_rdata_init(&x[i].rdata);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews dns_rdataset_current(rdataset, &x[i].rdata);
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews INSIST(x[i].rdata.data != &removed);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews x[i].order = i;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington result = dns_rdataset_next(rdataset);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington }
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews if (i != nalloc || result != ISC_R_NOMORE) {
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley /*
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley * Somehow we iterated over fewer rdatas than
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews * dns_rdataset_count() said there were or there
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews * were more items than dns_rdataset_count said
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews * there were.
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley */
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley result = ISC_R_FAILURE;
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley goto free_rdatas;
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley }
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews /*
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * Put into DNSSEC order.
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews */
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews if (nalloc > 1U)
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews qsort(x, nalloc, sizeof(struct xrdata), compare_rdata);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington /*
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley * Remove duplicates and compute the total storage required.
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley *
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley * If an rdata is not a duplicate, accumulate the storage size
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley * required for the rdata. We do not store the class, type, etc,
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley * just the rdata, so our overhead is 2 bytes for the number of
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * records, and 8 for each rdata, (length(2), offset(4) and order(2))
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * and then the rdata itself.
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington */
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington for (i = 1; i < nalloc; i++) {
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews if (compare_rdata(&x[i-1].rdata, &x[i].rdata) == 0) {
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews x[i-1].rdata.data = &removed;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews /*
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * Preserve the least order so A, B, A -> A, B
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * after duplicate removal.
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews */
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews if (x[i-1].order < x[i].order)
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews x[i].order = x[i-1].order;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington nitems--;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews } else {
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews buflen += (8 + x[i-1].rdata.length);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#else
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews buflen += (2 + x[i-1].rdata.length);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews /*
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews * Provide space to store the per RR meta data.
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews */
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (rdataset->type == dns_rdatatype_rrsig)
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews buflen++;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews }
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington }
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff /*
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley * Don't forget the last item!
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff */
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews buflen += (8 + x[i-1].rdata.length);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#else
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews buflen += (2 + x[i-1].rdata.length);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews /*
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews * Provide space to store the per RR meta data.
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews */
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (rdataset->type == dns_rdatatype_rrsig)
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews buflen++;
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley /*
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley * Ensure that singleton types are actually singletons.
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley */
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley if (nitems > 1 && dns_rdatatype_issingleton(rdataset->type)) {
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley /*
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley * We have a singleton type, but there's more than one
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley * RR in the rdataset.
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley */
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley result = DNS_R_SINGLETON;
383665e42ad838046472e847b16c4e0d3f1aaf76Bob Halley goto free_rdatas;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington }
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff /*
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff * Allocate the memory, set up a buffer, start copying in
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff * data.
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff */
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff rawbuf = isc_mem_get(mctx, buflen);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington if (rawbuf == NULL) {
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson result = ISC_R_NOMEMORY;
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson goto free_rdatas;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington }
e672951ed28b2e9cc7a19c3d7fa4a258382f981cAutomatic Updater
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews /* Allocate temporary offset table. */
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews offsettable = isc_mem_get(mctx, nalloc * sizeof(unsigned int));
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews if (offsettable == NULL) {
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews isc_mem_put(mctx, rawbuf, buflen);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews result = ISC_R_NOMEMORY;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews goto free_rdatas;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews }
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews memset(offsettable, 0, nalloc * sizeof(unsigned int));
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff region->base = rawbuf;
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff region->length = buflen;
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman memset(rawbuf, 0, buflen);
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff rawbuf += reservelen;
929329d2d66a7e1083c70a9c918381935bf12799Mukund Sivaraman
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews offsetbase = rawbuf;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff *rawbuf++ = (nitems & 0xff00) >> 8;
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff *rawbuf++ = (nitems & 0x00ff);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews /* Skip load order table. Filled in later. */
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews rawbuf += nitems * 4;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington for (i = 0; i < nalloc; i++) {
735ca24fa61ad9cd0285776c2fc4c14032f8f194Mark Andrews if (x[i].rdata.data == &removed)
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington continue;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews offsettable[x[i].order] = rawbuf - offsetbase;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews length = x[i].rdata.length;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (rdataset->type == dns_rdatatype_rrsig)
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews length++;
1bbd36c4db2c86762b582db4b0504e6e68a183f6Mark Andrews INSIST(length <= 0xffff);
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews *rawbuf++ = (length & 0xff00) >> 8;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews *rawbuf++ = (length & 0x00ff);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews rawbuf += 2; /* filled in later */
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews /*
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews * Store the per RR meta data.
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews */
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (rdataset->type == dns_rdatatype_rrsig) {
ec29d217ba3a2bf3e617a7b5b6708ae221bee999Mark Andrews *rawbuf++ = (x[i].rdata.flags & DNS_RDATA_OFFLINE) ?
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews DNS_RDATASLAB_OFFLINE : 0;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews }
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(rawbuf, x[i].rdata.data, x[i].rdata.length);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews rawbuf += x[i].rdata.length;
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff }
e672951ed28b2e9cc7a19c3d7fa4a258382f981cAutomatic Updater
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews fillin_offsets(offsetbase, offsettable, nalloc);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews isc_mem_put(mctx, offsettable, nalloc * sizeof(unsigned int));
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson result = ISC_R_SUCCESS;
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson free_rdatas:
27b09ceb12ec95de461bd2780615d4064ccb1419Mark Andrews isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata));
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson return (result);
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff}
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonstatic void
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonrdataset_disassociate(dns_rdataset_t *rdataset) {
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington UNUSED(rdataset);
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington}
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonstatic isc_result_t
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonrdataset_first(dns_rdataset_t *rdataset) {
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington unsigned char *raw = rdataset->private3;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington unsigned int count;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington count = raw[0] * 256 + raw[1];
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington if (count == 0) {
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->private5 = NULL;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington return (ISC_R_NOMORE);
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington }
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews raw += 2 + (4 * count);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#else
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews raw += 2;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington /*
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews * The privateuint4 field is the number of rdata beyond the cursor
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington * position, so we decrement the total count by one before storing
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington * it.
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington */
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington count--;
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews rdataset->privateuint4 = count;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->private5 = raw;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington return (ISC_R_SUCCESS);
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington}
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonstatic isc_result_t
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonrdataset_next(dns_rdataset_t *rdataset) {
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington unsigned int count;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington unsigned int length;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington unsigned char *raw;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews count = rdataset->privateuint4;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington if (count == 0)
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington return (ISC_R_NOMORE);
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington count--;
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews rdataset->privateuint4 = count;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington raw = rdataset->private5;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington length = raw[0] * 256 + raw[1];
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews raw += length + 4;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#else
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews raw += length + 2;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->private5 = raw;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington return (ISC_R_SUCCESS);
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington}
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonstatic void
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonrdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington unsigned char *raw = rdataset->private5;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington isc_region_t r;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews unsigned int length;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews unsigned int flags = 0;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington REQUIRE(raw != NULL);
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews length = raw[0] * 256 + raw[1];
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews raw += 4;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#else
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews raw += 2;
e672951ed28b2e9cc7a19c3d7fa4a258382f981cAutomatic Updater#endif
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (rdataset->type == dns_rdatatype_rrsig) {
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (*raw & DNS_RDATASLAB_OFFLINE)
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews flags |= DNS_RDATA_OFFLINE;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews length--;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews raw++;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews }
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews r.length = length;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington r.base = raw;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews rdata->flags |= flags;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington}
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonstatic void
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonrdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington *target = *source;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington /*
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington * Reset iterator state.
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington */
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews target->privateuint4 = 0;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington target->private5 = NULL;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington}
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonstatic unsigned int
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonrdataset_count(dns_rdataset_t *rdataset) {
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington unsigned char *raw = rdataset->private3;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington unsigned int count;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington count = raw[0] * 256 + raw[1];
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington return (count);
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington}
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonstatic dns_rdatasetmethods_t rdataset_methods = {
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset_disassociate,
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset_first,
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset_next,
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset_current,
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset_clone,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews rdataset_count,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews NULL,
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉 NULL,
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉 NULL,
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉 NULL,
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews NULL,
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews NULL,
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews NULL,
0cae66577c69c89086cd065bb297690072b471b4Mark Andrews NULL,
092d3b76db6b93b8029bd7d083e74fc80fb41858Mark Andrews NULL,
a8da00ef95ba37b9d071c2b8db1a0c967e060106Mark Andrews NULL,
a8da00ef95ba37b9d071c2b8db1a0c967e060106Mark Andrews NULL,
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrews NULL
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington};
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtonvoid
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellingtondns_rdataslab_tordataset(unsigned char *slab, unsigned int reservelen,
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington dns_rdatatype_t covers, dns_ttl_t ttl,
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington dns_rdataset_t *rdataset)
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington{
f9f2e770a992cb0ed2234b2f985162273059c6d3Brian Wellington REQUIRE(slab != NULL);
f9f2e770a992cb0ed2234b2f985162273059c6d3Brian Wellington REQUIRE(!dns_rdataset_isassociated(rdataset));
f9f2e770a992cb0ed2234b2f985162273059c6d3Brian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->methods = &rdataset_methods;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->rdclass = rdclass;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->type = rdtype;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->covers = covers;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->ttl = ttl;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->trust = 0;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->private1 = NULL;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->private2 = NULL;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->private3 = slab + reservelen;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington /*
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington * Reset iterator state.
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington */
80b782f356f0692c11b4e52e8dd46ec41704e5a2Mark Andrews rdataset->privateuint4 = 0;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington rdataset->private5 = NULL;
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington}
8cf24d101a291aa3274e8fd07d1a13cb5fe9976bBrian Wellington
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halleyunsigned int
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halleydns_rdataslab_size(unsigned char *slab, unsigned int reservelen) {
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley unsigned int count, length;
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley unsigned char *current;
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley REQUIRE(slab != NULL);
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley current = slab + reservelen;
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley count = *current++ * 256;
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley count += *current++;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews current += (4 * count);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley while (count > 0) {
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley count--;
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley length = *current++ * 256;
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley length += *current++;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews current += length + 2;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#else
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews current += length;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley }
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
e800570a5a7572a94604815cd7d7e788c0479ed2Bob Halley return ((unsigned int)(current - slab));
cd82aa8fa32698240ecd6634f11e3052ca7a2448Michael Graff}
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrewsunsigned int
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrewsdns_rdataslab_count(unsigned char *slab, unsigned int reservelen) {
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews unsigned int count;
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews unsigned char *current;
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews REQUIRE(slab != NULL);
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews current = slab + reservelen;
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews count = *current++ * 256;
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews count += *current++;
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews return (count);
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews}
744c1db6352c4c3f11c8538e4a2a57c8b0e0d570Mark Andrews
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson/*
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson * Make the dns_rdata_t 'rdata' refer to the slab item
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson * beginning at '*current', which is part of a slab of type
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson * 'type' and class 'rdclass', and advance '*current' to
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson * point to the next item in the slab.
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson */
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafssonstatic inline void
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafssonrdata_from_slab(unsigned char **current,
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson dns_rdataclass_t rdclass, dns_rdatatype_t type,
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson dns_rdata_t *rdata)
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson{
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson unsigned char *tcurrent = *current;
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson isc_region_t region;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews unsigned int length;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews isc_boolean_t offline = ISC_FALSE;
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews length = *tcurrent++ * 256;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews length += *tcurrent++;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (type == dns_rdatatype_rrsig) {
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if ((*tcurrent & DNS_RDATASLAB_OFFLINE) != 0)
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews offline = ISC_TRUE;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews length--;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews tcurrent++;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews }
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews region.length = length;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews tcurrent += 2;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson region.base = tcurrent;
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson tcurrent += region.length;
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson dns_rdata_fromregion(rdata, rdclass, type, &region);
3f42cf2f3e4dc7e740b4609ba7d7430292348f2bMark Andrews if (offline)
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews rdata->flags |= DNS_RDATA_OFFLINE;
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson *current = tcurrent;
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson}
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson/*
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson * Return true iff 'slab' (slab data of type 'type' and class 'rdclass')
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson * contains an rdata identical to 'rdata'. This does case insensitive
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson * comparisons per DNSSEC.
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson */
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellingtonstatic inline isc_boolean_t
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellingtonrdata_in_slab(unsigned char *slab, unsigned int reservelen,
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington dns_rdataclass_t rdclass, dns_rdatatype_t type,
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington dns_rdata_t *rdata)
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington{
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned int count, i;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned char *current;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t trdata = DNS_RDATA_INIT;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews int n;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington current = slab + reservelen;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington count = *current++ * 256;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington count += *current++;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews current += (4 * count);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington for (i = 0; i < count; i++) {
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson rdata_from_slab(&current, rdclass, type, &trdata);
e672951ed28b2e9cc7a19c3d7fa4a258382f981cAutomatic Updater
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews n = dns_rdata_compare(&trdata, rdata);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews if (n == 0)
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington return (ISC_TRUE);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews if (n > 0) /* In DNSSEC order. */
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews break;
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&trdata);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington }
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington return (ISC_FALSE);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington}
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halleydns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley unsigned int reservelen, isc_mem_t *mctx,
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley dns_rdataclass_t rdclass, dns_rdatatype_t type,
9d2c9f789654ace01489c29af64c68cf42c6cb30Mark Andrews unsigned int flags, unsigned char **tslabp)
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley{
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent, *data;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley unsigned int ocount, ncount, count, olength, tlength, tcount, length;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t ordata = DNS_RDATA_INIT;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t nrdata = DNS_RDATA_INIT;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley isc_boolean_t added_something = ISC_FALSE;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned int oadded = 0;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned int nadded = 0;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned int nncount = 0;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned int oncount;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned int norder = 0;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned int oorder = 0;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned char *offsetbase;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned int *offsettable;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley /*
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley * XXX Need parameter to allow "delete rdatasets in nslab" merge,
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley * or perhaps another merge routine for this purpose.
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley REQUIRE(tslabp != NULL && *tslabp == NULL);
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley REQUIRE(oslab != NULL && nslab != NULL);
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley ocurrent = oslab + reservelen;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley ocount = *ocurrent++ * 256;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley ocount += *ocurrent++;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews ocurrent += (4 * ocount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley ostart = ocurrent;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley ncurrent = nslab + reservelen;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley ncount = *ncurrent++ * 256;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley ncount += *ncurrent++;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews ncurrent += (4 * ncount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley INSIST(ocount > 0 && ncount > 0);
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews oncount = ncount;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley /*
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley * Yes, this is inefficient!
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley */
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley /*
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley * Figure out the length of the old slab's data.
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley */
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley olength = 0;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley for (count = 0; count < ocount; count++) {
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley length = *ocurrent++ * 256;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley length += *ocurrent++;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews olength += length + 8;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews ocurrent += length + 2;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#else
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews olength += length + 2;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews ocurrent += length;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley }
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley /*
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley * Start figuring out the target length and count.
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley */
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley tlength = reservelen + 2 + olength;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley tcount = ocount;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley /*
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley * Add in the length of rdata in the new slab that aren't in
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley * the old slab.
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley */
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley do {
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_init(&nrdata);
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews rdata_from_slab(&ncurrent, rdclass, type, &nrdata);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington if (!rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata))
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington {
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley /*
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley * This rdata isn't in the old slab.
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley */
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews tlength += nrdata.length + 8;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#else
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews tlength += nrdata.length + 2;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (type == dns_rdatatype_rrsig)
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews tlength++;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley tcount++;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington nncount++;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley added_something = ISC_TRUE;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley }
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley ncount--;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley } while (ncount > 0);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington ncount = nncount;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
f8abaa0fae7f75d9601c10b6a4af8dd907494d45Mark Andrews if (((flags & DNS_RDATASLAB_EXACT) != 0) &&
f8abaa0fae7f75d9601c10b6a4af8dd907494d45Mark Andrews (tcount != ncount + ocount))
9d2c9f789654ace01489c29af64c68cf42c6cb30Mark Andrews return (DNS_R_NOTEXACT);
9d2c9f789654ace01489c29af64c68cf42c6cb30Mark Andrews
9d2c9f789654ace01489c29af64c68cf42c6cb30Mark Andrews if (!added_something && (flags & DNS_RDATASLAB_FORCE) == 0)
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley return (DNS_R_UNCHANGED);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley /*
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley * Ensure that singleton types are actually singletons.
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley */
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley if (tcount > 1 && dns_rdatatype_issingleton(type)) {
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley /*
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley * We have a singleton type, but there's more than one
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley * RR in the rdataset.
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley */
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley return (DNS_R_SINGLETON);
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley }
bab57cc87ffc890ba1ba3dbc6c022ae1a36726bcBob Halley
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews if (tcount > 0xffff)
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews return (ISC_R_NOSPACE);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley /*
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley * Copy the reserved area from the new slab.
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley */
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley tstart = isc_mem_get(mctx, tlength);
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley if (tstart == NULL)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff return (ISC_R_NOMEMORY);
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(tstart, nslab, reservelen);
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley tcurrent = tstart + reservelen;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews offsetbase = tcurrent;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley /*
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley * Write the new count.
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley */
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley *tcurrent++ = (tcount & 0xff00) >> 8;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley *tcurrent++ = (tcount & 0x00ff);
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews /*
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews * Skip offset table.
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews */
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews tcurrent += (tcount * 4);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews offsettable = isc_mem_get(mctx,
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews (ocount + oncount) * sizeof(unsigned int));
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews if (offsettable == NULL) {
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews isc_mem_put(mctx, tstart, tlength);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews return (ISC_R_NOMEMORY);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews }
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews memset(offsettable, 0, (ocount + oncount) * sizeof(unsigned int));
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley /*
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington * Merge the two slabs.
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley */
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington ocurrent = ostart;
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson INSIST(ocount != 0);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews oorder = ocurrent[2] * 256 + ocurrent[3];
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews INSIST(oorder < ocount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson rdata_from_slab(&ocurrent, rdclass, type, &ordata);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington ncurrent = nslab + reservelen + 2;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews ncurrent += (4 * oncount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington if (ncount > 0) {
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington do {
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&nrdata);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews norder = ncurrent[2] * 256 + ncurrent[3];
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews INSIST(norder < oncount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews rdata_from_slab(&ncurrent, rdclass, type, &nrdata);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington } while (rdata_in_slab(oslab, reservelen, rdclass,
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington type, &nrdata));
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington }
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington while (oadded < ocount || nadded < ncount) {
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington isc_boolean_t fromold;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington if (oadded == ocount)
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington fromold = ISC_FALSE;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington else if (nadded == ncount)
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington fromold = ISC_TRUE;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington else
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington fromold = ISC_TF(compare_rdata(&ordata, &nrdata) < 0);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington if (fromold) {
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews offsettable[oorder] = tcurrent - offsetbase;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington length = ordata.length;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews data = ordata.data;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (type == dns_rdatatype_rrsig) {
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews length++;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews data--;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews }
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington *tcurrent++ = (length & 0xff00) >> 8;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington *tcurrent++ = (length & 0x00ff);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews tcurrent += 2; /* fill in later */
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(tcurrent, data, length);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington tcurrent += length;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington oadded++;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington if (oadded < ocount) {
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&ordata);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews oorder = ocurrent[2] * 256 + ocurrent[3];
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews INSIST(oorder < ocount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews rdata_from_slab(&ocurrent, rdclass, type,
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington &ordata);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington }
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington } else {
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews offsettable[ocount + norder] = tcurrent - offsetbase;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington length = nrdata.length;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews data = nrdata.data;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews if (type == dns_rdatatype_rrsig) {
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews length++;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews data--;
a76b380643a22f23a67a9df284e86cd7ef7608c1Mark Andrews }
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington *tcurrent++ = (length & 0xff00) >> 8;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington *tcurrent++ = (length & 0x00ff);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews tcurrent += 2; /* fill in later */
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(tcurrent, data, length);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington tcurrent += length;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington nadded++;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington if (nadded < ncount) {
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington do {
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&nrdata);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews norder = ncurrent[2] * 256 + ncurrent[3];
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews INSIST(norder < oncount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews rdata_from_slab(&ncurrent, rdclass,
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington type, &nrdata);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington } while (rdata_in_slab(oslab, reservelen,
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington rdclass, type,
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington &nrdata));
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington }
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley }
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington }
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews fillin_offsets(offsetbase, offsettable, ocount + oncount);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews isc_mem_put(mctx, offsettable,
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews (ocount + oncount) * sizeof(unsigned int));
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson INSIST(tcurrent == tstart + tlength);
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley *tslabp = tstart;
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff return (ISC_R_SUCCESS);
5bfea18ff8bfa907b86ba7d17fb38b9cf493ae97Bob Halley}
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffisc_result_t
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halleydns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley unsigned int reservelen, isc_mem_t *mctx,
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley dns_rdataclass_t rdclass, dns_rdatatype_t type,
f8abaa0fae7f75d9601c10b6a4af8dd907494d45Mark Andrews unsigned int flags, unsigned char **tslabp)
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley{
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley unsigned char *mcurrent, *sstart, *scurrent, *tstart, *tcurrent;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned int mcount, scount, rcount ,count, tlength, tcount, i;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t srdata = DNS_RDATA_INIT;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews dns_rdata_t mrdata = DNS_RDATA_INIT;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned char *offsetbase;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned int *offsettable;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews unsigned int order;
2284b84d74cdfd62ecb962feb850de981bbc2196Evan Hunt#endif
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley REQUIRE(tslabp != NULL && *tslabp == NULL);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley REQUIRE(mslab != NULL && sslab != NULL);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley mcurrent = mslab + reservelen;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley mcount = *mcurrent++ * 256;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley mcount += *mcurrent++;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley scurrent = sslab + reservelen;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley scount = *scurrent++ * 256;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley scount += *scurrent++;
0dae46cbc7f31e9ca9700016ae486f709b940bafAndreas Gustafsson INSIST(mcount > 0 && scount > 0);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley /*
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * Yes, this is inefficient!
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley */
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley /*
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * Start figuring out the target length and count.
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley */
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley tlength = reservelen + 2;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley tcount = 0;
b55c30f2de6e1baaa3a9ba69b92f428f2c255ac3Mark Andrews rcount = 0;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews mcurrent += 4 * mcount;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews scurrent += 4 * scount;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews sstart = scurrent;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley /*
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * Add in the length of rdata in the mslab that aren't in
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * the sslab.
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley */
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews for (i = 0; i < mcount; i++) {
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson unsigned char *mrdatabegin = mcurrent;
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson rdata_from_slab(&mcurrent, rdclass, type, &mrdata);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley scurrent = sstart;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley for (count = 0; count < scount; count++) {
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&srdata);
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson rdata_from_slab(&scurrent, rdclass, type, &srdata);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley if (dns_rdata_compare(&mrdata, &srdata) == 0)
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley break;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley }
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley if (count == scount) {
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley /*
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * This rdata isn't in the sslab, and thus isn't
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * being subtracted.
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley */
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews tlength += (unsigned int)(mcurrent - mrdatabegin);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley tcount++;
9b6fd12d8e53afbfc31022c881c16d2ccbe5fc51Bob Halley } else
b55c30f2de6e1baaa3a9ba69b92f428f2c255ac3Mark Andrews rcount++;
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&mrdata);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews }
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews tlength += (4 * tcount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
b55c30f2de6e1baaa3a9ba69b92f428f2c255ac3Mark Andrews /*
b55c30f2de6e1baaa3a9ba69b92f428f2c255ac3Mark Andrews * Check that all the records originally existed. The numeric
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews * check only works as rdataslabs do not contain duplicates.
b55c30f2de6e1baaa3a9ba69b92f428f2c255ac3Mark Andrews */
f8abaa0fae7f75d9601c10b6a4af8dd907494d45Mark Andrews if (((flags & DNS_RDATASLAB_EXACT) != 0) && (rcount != scount))
b55c30f2de6e1baaa3a9ba69b92f428f2c255ac3Mark Andrews return (DNS_R_NOTEXACT);
b55c30f2de6e1baaa3a9ba69b92f428f2c255ac3Mark Andrews
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley /*
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * Don't continue if the new rdataslab would be empty.
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley */
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley if (tcount == 0)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff return (DNS_R_NXRRSET);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
9b6fd12d8e53afbfc31022c881c16d2ccbe5fc51Bob Halley /*
9b6fd12d8e53afbfc31022c881c16d2ccbe5fc51Bob Halley * If nothing is going to change, we can stop.
9b6fd12d8e53afbfc31022c881c16d2ccbe5fc51Bob Halley */
b55c30f2de6e1baaa3a9ba69b92f428f2c255ac3Mark Andrews if (rcount == 0)
9b6fd12d8e53afbfc31022c881c16d2ccbe5fc51Bob Halley return (DNS_R_UNCHANGED);
9b6fd12d8e53afbfc31022c881c16d2ccbe5fc51Bob Halley
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley /*
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * Copy the reserved area from the mslab.
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley */
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley tstart = isc_mem_get(mctx, tlength);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley if (tstart == NULL)
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff return (ISC_R_NOMEMORY);
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(tstart, mslab, reservelen);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley tcurrent = tstart + reservelen;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews offsetbase = tcurrent;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews offsettable = isc_mem_get(mctx, mcount * sizeof(unsigned int));
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews if (offsettable == NULL) {
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews isc_mem_put(mctx, tstart, tlength);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews return (ISC_R_NOMEMORY);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews }
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews memset(offsettable, 0, mcount * sizeof(unsigned int));
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley /*
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * Write the new count.
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley */
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley *tcurrent++ = (tcount & 0xff00) >> 8;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley *tcurrent++ = (tcount & 0x00ff);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews tcurrent += (4 * tcount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley /*
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * Copy the parts of mslab not in sslab.
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley */
0dae46cbc7f31e9ca9700016ae486f709b940bafAndreas Gustafsson mcurrent = mslab + reservelen;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley mcount = *mcurrent++ * 256;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley mcount += *mcurrent++;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews mcurrent += (4 * mcount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews for (i = 0; i < mcount; i++) {
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson unsigned char *mrdatabegin = mcurrent;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews order = mcurrent[2] * 256 + mcurrent[3];
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews INSIST(order < mcount);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson rdata_from_slab(&mcurrent, rdclass, type, &mrdata);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley scurrent = sstart;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley for (count = 0; count < scount; count++) {
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&srdata);
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson rdata_from_slab(&scurrent, rdclass, type, &srdata);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley if (dns_rdata_compare(&mrdata, &srdata) == 0)
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley break;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley }
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley if (count == scount) {
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley /*
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * This rdata isn't in the sslab, and thus should be
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley * copied to the tslab.
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley */
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews unsigned int length;
c3c8823fed039b3a2b8e5ca8bc2f3301d1dd840eMark Andrews length = (unsigned int)(mcurrent - mrdatabegin);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews offsettable[order] = tcurrent - offsetbase;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
e851ea826066ac5a5b01c2c23218faa0273a12e8Evan Hunt memmove(tcurrent, mrdatabegin, length);
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson tcurrent += length;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley }
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews dns_rdata_reset(&mrdata);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews }
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews fillin_offsets(offsetbase, offsettable, mcount);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews isc_mem_put(mctx, offsettable, mcount * sizeof(unsigned int));
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson INSIST(tcurrent == tstart + tlength);
da41917c3f882b6e12c7101b653926830a396b81Andreas Gustafsson
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley *tslabp = tstart;
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff return (ISC_R_SUCCESS);
926cde044f4334f7afd9d1123ab0f01ec93e7e72Bob Halley}
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellingtonisc_boolean_t
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellingtondns_rdataslab_equal(unsigned char *slab1, unsigned char *slab2,
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned int reservelen)
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington{
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned char *current1, *current2;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned int count1, count2;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington unsigned int length1, length2;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington current1 = slab1 + reservelen;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington count1 = *current1++ * 256;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington count1 += *current1++;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington current2 = slab2 + reservelen;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington count2 = *current2++ * 256;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington count2 += *current2++;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington if (count1 != count2)
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington return (ISC_FALSE);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews current1 += (4 * count1);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews current2 += (4 * count2);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington while (count1 > 0) {
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington length1 = *current1++ * 256;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington length1 += *current1++;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington length2 = *current2++ * 256;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington length2 += *current2++;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews current1 += 2;
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews current2 += 2;
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington if (length1 != length2 ||
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington memcmp(current1, current2, length1) != 0)
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington return (ISC_FALSE);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington current1 += length1;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington current2 += length1;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington count1--;
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington }
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington return (ISC_TRUE);
88b9c12a3cbafc3bebedf50a731bec9ce2f99a13Brian Wellington}
6434457b0b380aa43d7159299776959a00269d65Michael Graff
6434457b0b380aa43d7159299776959a00269d65Michael Graffisc_boolean_t
6434457b0b380aa43d7159299776959a00269d65Michael Graffdns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2,
6434457b0b380aa43d7159299776959a00269d65Michael Graff unsigned int reservelen, dns_rdataclass_t rdclass,
6434457b0b380aa43d7159299776959a00269d65Michael Graff dns_rdatatype_t type)
6434457b0b380aa43d7159299776959a00269d65Michael Graff{
6434457b0b380aa43d7159299776959a00269d65Michael Graff unsigned char *current1, *current2;
6434457b0b380aa43d7159299776959a00269d65Michael Graff unsigned int count1, count2;
6434457b0b380aa43d7159299776959a00269d65Michael Graff dns_rdata_t rdata1 = DNS_RDATA_INIT;
6434457b0b380aa43d7159299776959a00269d65Michael Graff dns_rdata_t rdata2 = DNS_RDATA_INIT;
6434457b0b380aa43d7159299776959a00269d65Michael Graff
6434457b0b380aa43d7159299776959a00269d65Michael Graff current1 = slab1 + reservelen;
6434457b0b380aa43d7159299776959a00269d65Michael Graff count1 = *current1++ * 256;
6434457b0b380aa43d7159299776959a00269d65Michael Graff count1 += *current1++;
6434457b0b380aa43d7159299776959a00269d65Michael Graff
6434457b0b380aa43d7159299776959a00269d65Michael Graff current2 = slab2 + reservelen;
6434457b0b380aa43d7159299776959a00269d65Michael Graff count2 = *current2++ * 256;
6434457b0b380aa43d7159299776959a00269d65Michael Graff count2 += *current2++;
6434457b0b380aa43d7159299776959a00269d65Michael Graff
6434457b0b380aa43d7159299776959a00269d65Michael Graff if (count1 != count2)
6434457b0b380aa43d7159299776959a00269d65Michael Graff return (ISC_FALSE);
6434457b0b380aa43d7159299776959a00269d65Michael Graff
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#if DNS_RDATASET_FIXED
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews current1 += (4 * count1);
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews current2 += (4 * count2);
65085946d4f92481699678e276e3ced04bcfdafbMark Andrews#endif
d76ed813a51465e5c47d521ab09ea20c06f1428dMark Andrews
6434457b0b380aa43d7159299776959a00269d65Michael Graff while (count1-- > 0) {
6434457b0b380aa43d7159299776959a00269d65Michael Graff rdata_from_slab(&current1, rdclass, type, &rdata1);
6434457b0b380aa43d7159299776959a00269d65Michael Graff rdata_from_slab(&current2, rdclass, type, &rdata2);
6434457b0b380aa43d7159299776959a00269d65Michael Graff if (dns_rdata_compare(&rdata1, &rdata2) != 0)
6434457b0b380aa43d7159299776959a00269d65Michael Graff return (ISC_FALSE);
6434457b0b380aa43d7159299776959a00269d65Michael Graff dns_rdata_reset(&rdata1);
6434457b0b380aa43d7159299776959a00269d65Michael Graff dns_rdata_reset(&rdata2);
6434457b0b380aa43d7159299776959a00269d65Michael Graff }
6434457b0b380aa43d7159299776959a00269d65Michael Graff return (ISC_TRUE);
6434457b0b380aa43d7159299776959a00269d65Michael Graff}