2 * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: rdataslab.c,v 1.35.18.8 2007/08/28 07:20:05 tbox Exp $ */
27 #include <isc/region.h>
28 #include <isc/string.h> /* Required for HP/UX (and others?) */
31 #include <dns/result.h>
32 #include <dns/rdata.h>
33 #include <dns/rdataset.h>
34 #include <dns/rdataslab.h>
36 #ifndef DNS_RDATASET_FIXED
37 #define DNS_RDATASET_FIXED 1
41 * The rdataslab structure allows iteration to occur in both load order
42 * and DNSSEC order. The structure is as follows:
44 * header (reservelen bytes)
45 * record count (2 bytes)
46 * offset table (4 x record count bytes in load order)
48 * data length (2 bytes)
50 * data (data length bytes)
52 * If DNS_RDATASET_FIXED is defined to be zero (0) the format of a
53 * rdataslab is as follows:
55 * header (reservelen bytes)
56 * record count (2 bytes)
58 * data length (2 bytes)
59 * data (data length bytes)
61 * Offsets are from the end of the header.
63 * Load order traversal is performed by walking the offset table to find
64 * the start of the record (DNS_RDATASET_FIXED = 1).
66 * DNSSEC order traversal is performed by walking the data records.
68 * The order is stored with record to allow for efficient reconstuction of
69 * of the offset table following a merge or subtraction.
71 * The iterator methods here currently only support DNSSEC order iteration.
73 * The iterator methods in rbtdb support both load order and DNSSEC order
77 * rbtdb.c directly interacts with the slab's raw structures. If the
78 * structure changes then rbtdb.c also needs to be updated to reflect
79 * the changes. See the areas tagged with "RDATASLAB".
87 /*% Note: the "const void *" are just to make qsort happy. */
89 compare_rdata(const void *p1, const void *p2) {
90 const struct xrdata *x1 = p1;
91 const struct xrdata *x2 = p2;
92 return (dns_rdata_compare(&x1->rdata, &x2->rdata));
95 #if DNS_RDATASET_FIXED
97 fillin_offsets(unsigned char *offsetbase, unsigned int *offsettable,
103 for (i = 0, j = 0; i < length; i++) {
105 if (offsettable[i] == 0)
109 * Fill in offset table.
111 raw = &offsetbase[j*4 + 2];
112 *raw++ = (offsettable[i] & 0xff000000) >> 24;
113 *raw++ = (offsettable[i] & 0xff0000) >> 16;
114 *raw++ = (offsettable[i] & 0xff00) >> 8;
115 *raw = offsettable[i] & 0xff;
118 * Fill in table index.
120 raw = offsetbase + offsettable[i] + 2;
121 *raw++ = (j & 0xff00) >> 8;
128 dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
129 isc_region_t *region, unsigned int reservelen)
132 unsigned char *rawbuf;
133 #if DNS_RDATASET_FIXED
134 unsigned char *offsetbase;
141 #if DNS_RDATASET_FIXED
142 unsigned int *offsettable;
145 buflen = reservelen + 2;
147 nalloc = dns_rdataset_count(rdataset);
150 return (ISC_R_FAILURE);
153 return (ISC_R_NOSPACE);
155 x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata));
157 return (ISC_R_NOMEMORY);
160 * Save all of the rdata members into an array.
162 result = dns_rdataset_first(rdataset);
163 if (result != ISC_R_SUCCESS)
165 for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) {
166 INSIST(result == ISC_R_SUCCESS);
167 dns_rdata_init(&x[i].rdata);
168 dns_rdataset_current(rdataset, &x[i].rdata);
169 #if DNS_RDATASET_FIXED
172 result = dns_rdataset_next(rdataset);
174 if (result != ISC_R_NOMORE)
178 * Somehow we iterated over fewer rdatas than
179 * dns_rdataset_count() said there were!
181 result = ISC_R_FAILURE;
186 * Put into DNSSEC order.
188 qsort(x, nalloc, sizeof(struct xrdata), compare_rdata);
191 * Remove duplicates and compute the total storage required.
193 * If an rdata is not a duplicate, accumulate the storage size
194 * required for the rdata. We do not store the class, type, etc,
195 * just the rdata, so our overhead is 2 bytes for the number of
196 * records, and 8 for each rdata, (length(2), offset(4) and order(2))
197 * and then the rdata itself.
199 for (i = 1; i < nalloc; i++) {
200 if (compare_rdata(&x[i-1].rdata, &x[i].rdata) == 0) {
201 x[i-1].rdata.data = NULL;
202 x[i-1].rdata.length = 0;
203 #if DNS_RDATASET_FIXED
205 * Preserve the least order so A, B, A -> A, B
206 * after duplicate removal.
208 if (x[i-1].order < x[i].order)
209 x[i].order = x[i-1].order;
213 #if DNS_RDATASET_FIXED
214 buflen += (8 + x[i-1].rdata.length);
216 buflen += (2 + x[i-1].rdata.length);
220 * Don't forget the last item!
222 #if DNS_RDATASET_FIXED
223 buflen += (8 + x[i-1].rdata.length);
225 buflen += (2 + x[i-1].rdata.length);
229 * Ensure that singleton types are actually singletons.
231 if (nitems > 1 && dns_rdatatype_issingleton(rdataset->type)) {
233 * We have a singleton type, but there's more than one
234 * RR in the rdataset.
236 result = DNS_R_SINGLETON;
241 * Allocate the memory, set up a buffer, start copying in
244 rawbuf = isc_mem_get(mctx, buflen);
245 if (rawbuf == NULL) {
246 result = ISC_R_NOMEMORY;
250 #if DNS_RDATASET_FIXED
251 /* Allocate temporary offset table. */
252 offsettable = isc_mem_get(mctx, nalloc * sizeof(unsigned int));
253 if (offsettable == NULL) {
254 isc_mem_put(mctx, rawbuf, buflen);
255 result = ISC_R_NOMEMORY;
258 memset(offsettable, 0, nalloc * sizeof(unsigned int));
261 region->base = rawbuf;
262 region->length = buflen;
264 rawbuf += reservelen;
265 #if DNS_RDATASET_FIXED
269 *rawbuf++ = (nitems & 0xff00) >> 8;
270 *rawbuf++ = (nitems & 0x00ff);
272 #if DNS_RDATASET_FIXED
273 /* Skip load order table. Filled in later. */
274 rawbuf += nitems * 4;
277 for (i = 0; i < nalloc; i++) {
278 if (x[i].rdata.data == NULL)
280 #if DNS_RDATASET_FIXED
281 offsettable[x[i].order] = rawbuf - offsetbase;
283 *rawbuf++ = (x[i].rdata.length & 0xff00) >> 8;
284 *rawbuf++ = (x[i].rdata.length & 0x00ff);
285 #if DNS_RDATASET_FIXED
286 rawbuf += 2; /* filled in later */
288 memcpy(rawbuf, x[i].rdata.data, x[i].rdata.length);
289 rawbuf += x[i].rdata.length;
292 #if DNS_RDATASET_FIXED
293 fillin_offsets(offsetbase, offsettable, nalloc);
294 isc_mem_put(mctx, offsettable, nalloc * sizeof(unsigned int));
297 result = ISC_R_SUCCESS;
300 isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata));
305 rdataset_disassociate(dns_rdataset_t *rdataset) {
310 rdataset_first(dns_rdataset_t *rdataset) {
311 unsigned char *raw = rdataset->private3;
314 count = raw[0] * 256 + raw[1];
316 rdataset->private5 = NULL;
317 return (ISC_R_NOMORE);
319 #if DNS_RDATASET_FIXED
320 raw += 2 + (4 * count);
325 * The privateuint4 field is the number of rdata beyond the cursor
326 * position, so we decrement the total count by one before storing
330 rdataset->privateuint4 = count;
331 rdataset->private5 = raw;
333 return (ISC_R_SUCCESS);
337 rdataset_next(dns_rdataset_t *rdataset) {
342 count = rdataset->privateuint4;
344 return (ISC_R_NOMORE);
346 rdataset->privateuint4 = count;
347 raw = rdataset->private5;
348 length = raw[0] * 256 + raw[1];
349 #if DNS_RDATASET_FIXED
354 rdataset->private5 = raw;
356 return (ISC_R_SUCCESS);
360 rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
361 unsigned char *raw = rdataset->private5;
364 REQUIRE(raw != NULL);
366 r.length = raw[0] * 256 + raw[1];
367 #if DNS_RDATASET_FIXED
373 dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
377 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
381 * Reset iterator state.
383 target->privateuint4 = 0;
384 target->private5 = NULL;
388 rdataset_count(dns_rdataset_t *rdataset) {
389 unsigned char *raw = rdataset->private3;
392 count = raw[0] * 256 + raw[1];
397 static dns_rdatasetmethods_t rdataset_methods = {
398 rdataset_disassociate,
412 dns_rdataslab_tordataset(unsigned char *slab, unsigned int reservelen,
413 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
414 dns_rdatatype_t covers, dns_ttl_t ttl,
415 dns_rdataset_t *rdataset)
417 REQUIRE(slab != NULL);
418 REQUIRE(!dns_rdataset_isassociated(rdataset));
420 rdataset->methods = &rdataset_methods;
421 rdataset->rdclass = rdclass;
422 rdataset->type = rdtype;
423 rdataset->covers = covers;
426 rdataset->private1 = NULL;
427 rdataset->private2 = NULL;
428 rdataset->private3 = slab + reservelen;
431 * Reset iterator state.
433 rdataset->privateuint4 = 0;
434 rdataset->private5 = NULL;
438 dns_rdataslab_size(unsigned char *slab, unsigned int reservelen) {
439 unsigned int count, length;
440 unsigned char *current;
442 REQUIRE(slab != NULL);
444 current = slab + reservelen;
445 count = *current++ * 256;
447 #if DNS_RDATASET_FIXED
448 current += (4 * count);
452 length = *current++ * 256;
453 length += *current++;
454 #if DNS_RDATASET_FIXED
455 current += length + 2;
461 return ((unsigned int)(current - slab));
465 * Make the dns_rdata_t 'rdata' refer to the slab item
466 * beginning at '*current', which is part of a slab of type
467 * 'type' and class 'rdclass', and advance '*current' to
468 * point to the next item in the slab.
471 rdata_from_slab(unsigned char **current,
472 dns_rdataclass_t rdclass, dns_rdatatype_t type,
475 unsigned char *tcurrent = *current;
478 region.length = *tcurrent++ * 256;
479 region.length += *tcurrent++;
480 #if DNS_RDATASET_FIXED
483 region.base = tcurrent;
484 tcurrent += region.length;
485 dns_rdata_fromregion(rdata, rdclass, type, ®ion);
490 * Return true iff 'slab' (slab data of type 'type' and class 'rdclass')
491 * contains an rdata identical to 'rdata'. This does case insensitive
492 * comparisons per DNSSEC.
494 static inline isc_boolean_t
495 rdata_in_slab(unsigned char *slab, unsigned int reservelen,
496 dns_rdataclass_t rdclass, dns_rdatatype_t type,
499 unsigned int count, i;
500 unsigned char *current;
501 dns_rdata_t trdata = DNS_RDATA_INIT;
504 current = slab + reservelen;
505 count = *current++ * 256;
508 #if DNS_RDATASET_FIXED
509 current += (4 * count);
512 for (i = 0; i < count; i++) {
513 rdata_from_slab(¤t, rdclass, type, &trdata);
515 n = dns_rdata_compare(&trdata, rdata);
518 if (n > 0) /* In DNSSEC order. */
520 dns_rdata_reset(&trdata);
526 dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
527 unsigned int reservelen, isc_mem_t *mctx,
528 dns_rdataclass_t rdclass, dns_rdatatype_t type,
529 unsigned int flags, unsigned char **tslabp)
531 unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent;
532 unsigned int ocount, ncount, count, olength, tlength, tcount, length;
533 isc_region_t nregion;
534 dns_rdata_t ordata = DNS_RDATA_INIT;
535 dns_rdata_t nrdata = DNS_RDATA_INIT;
536 isc_boolean_t added_something = ISC_FALSE;
537 unsigned int oadded = 0;
538 unsigned int nadded = 0;
539 unsigned int nncount = 0;
540 #if DNS_RDATASET_FIXED
541 unsigned int oncount;
542 unsigned int norder = 0;
543 unsigned int oorder = 0;
544 unsigned char *offsetbase;
545 unsigned int *offsettable;
549 * XXX Need parameter to allow "delete rdatasets in nslab" merge,
550 * or perhaps another merge routine for this purpose.
553 REQUIRE(tslabp != NULL && *tslabp == NULL);
554 REQUIRE(oslab != NULL && nslab != NULL);
556 ocurrent = oslab + reservelen;
557 ocount = *ocurrent++ * 256;
558 ocount += *ocurrent++;
559 #if DNS_RDATASET_FIXED
560 ocurrent += (4 * ocount);
563 ncurrent = nslab + reservelen;
564 ncount = *ncurrent++ * 256;
565 ncount += *ncurrent++;
566 #if DNS_RDATASET_FIXED
567 ncurrent += (4 * ncount);
569 INSIST(ocount > 0 && ncount > 0);
571 #if DNS_RDATASET_FIXED
576 * Yes, this is inefficient!
580 * Figure out the length of the old slab's data.
583 for (count = 0; count < ocount; count++) {
584 length = *ocurrent++ * 256;
585 length += *ocurrent++;
586 #if DNS_RDATASET_FIXED
587 olength += length + 8;
588 ocurrent += length + 2;
590 olength += length + 2;
596 * Start figuring out the target length and count.
598 tlength = reservelen + 2 + olength;
602 * Add in the length of rdata in the new slab that aren't in
606 nregion.length = *ncurrent++ * 256;
607 nregion.length += *ncurrent++;
608 #if DNS_RDATASET_FIXED
609 ncurrent += 2; /* Skip order. */
611 nregion.base = ncurrent;
612 dns_rdata_init(&nrdata);
613 dns_rdata_fromregion(&nrdata, rdclass, type, &nregion);
614 if (!rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata))
617 * This rdata isn't in the old slab.
619 #if DNS_RDATASET_FIXED
620 tlength += nregion.length + 8;
622 tlength += nregion.length + 2;
626 added_something = ISC_TRUE;
628 ncurrent += nregion.length;
630 } while (ncount > 0);
633 if (((flags & DNS_RDATASLAB_EXACT) != 0) &&
634 (tcount != ncount + ocount))
635 return (DNS_R_NOTEXACT);
637 if (!added_something && (flags & DNS_RDATASLAB_FORCE) == 0)
638 return (DNS_R_UNCHANGED);
641 * Ensure that singleton types are actually singletons.
643 if (tcount > 1 && dns_rdatatype_issingleton(type)) {
645 * We have a singleton type, but there's more than one
646 * RR in the rdataset.
648 return (DNS_R_SINGLETON);
652 return (ISC_R_NOSPACE);
655 * Copy the reserved area from the new slab.
657 tstart = isc_mem_get(mctx, tlength);
659 return (ISC_R_NOMEMORY);
660 memcpy(tstart, nslab, reservelen);
661 tcurrent = tstart + reservelen;
662 #if DNS_RDATASET_FIXED
663 offsetbase = tcurrent;
667 * Write the new count.
669 *tcurrent++ = (tcount & 0xff00) >> 8;
670 *tcurrent++ = (tcount & 0x00ff);
672 #if DNS_RDATASET_FIXED
676 tcurrent += (tcount * 4);
678 offsettable = isc_mem_get(mctx,
679 (ocount + oncount) * sizeof(unsigned int));
680 if (offsettable == NULL) {
681 isc_mem_put(mctx, tstart, tlength);
682 return (ISC_R_NOMEMORY);
684 memset(offsettable, 0, (ocount + oncount) * sizeof(unsigned int));
688 * Merge the two slabs.
692 #if DNS_RDATASET_FIXED
693 oorder = ocurrent[2] * 256 + ocurrent[3];
694 INSIST(oorder < ocount);
696 rdata_from_slab(&ocurrent, rdclass, type, &ordata);
698 ncurrent = nslab + reservelen + 2;
699 #if DNS_RDATASET_FIXED
700 ncurrent += (4 * oncount);
705 dns_rdata_reset(&nrdata);
706 #if DNS_RDATASET_FIXED
707 norder = ncurrent[2] * 256 + ncurrent[3];
709 INSIST(norder < oncount);
711 rdata_from_slab(&ncurrent, rdclass, type, &nrdata);
712 } while (rdata_in_slab(oslab, reservelen, rdclass,
716 while (oadded < ocount || nadded < ncount) {
717 isc_boolean_t fromold;
718 if (oadded == ocount)
720 else if (nadded == ncount)
723 fromold = ISC_TF(compare_rdata(&ordata, &nrdata) < 0);
725 #if DNS_RDATASET_FIXED
726 offsettable[oorder] = tcurrent - offsetbase;
728 length = ordata.length;
729 *tcurrent++ = (length & 0xff00) >> 8;
730 *tcurrent++ = (length & 0x00ff);
731 #if DNS_RDATASET_FIXED
732 tcurrent += 2; /* fill in later */
734 memcpy(tcurrent, ordata.data, length);
737 if (oadded < ocount) {
738 dns_rdata_reset(&ordata);
739 #if DNS_RDATASET_FIXED
740 oorder = ocurrent[2] * 256 + ocurrent[3];
741 INSIST(oorder < ocount);
743 rdata_from_slab(&ocurrent, rdclass, type,
747 #if DNS_RDATASET_FIXED
748 offsettable[ocount + norder] = tcurrent - offsetbase;
750 length = nrdata.length;
751 *tcurrent++ = (length & 0xff00) >> 8;
752 *tcurrent++ = (length & 0x00ff);
753 #if DNS_RDATASET_FIXED
754 tcurrent += 2; /* fill in later */
756 memcpy(tcurrent, nrdata.data, length);
759 if (nadded < ncount) {
761 dns_rdata_reset(&nrdata);
762 #if DNS_RDATASET_FIXED
763 norder = ncurrent[2] * 256 + ncurrent[3];
764 INSIST(norder < oncount);
766 rdata_from_slab(&ncurrent, rdclass,
768 } while (rdata_in_slab(oslab, reservelen,
775 #if DNS_RDATASET_FIXED
776 fillin_offsets(offsetbase, offsettable, ocount + oncount);
778 isc_mem_put(mctx, offsettable,
779 (ocount + oncount) * sizeof(unsigned int));
782 INSIST(tcurrent == tstart + tlength);
786 return (ISC_R_SUCCESS);
790 dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
791 unsigned int reservelen, isc_mem_t *mctx,
792 dns_rdataclass_t rdclass, dns_rdatatype_t type,
793 unsigned int flags, unsigned char **tslabp)
795 unsigned char *mcurrent, *sstart, *scurrent, *tstart, *tcurrent;
796 unsigned int mcount, scount, rcount ,count, tlength, tcount, i;
797 dns_rdata_t srdata = DNS_RDATA_INIT;
798 dns_rdata_t mrdata = DNS_RDATA_INIT;
799 #if DNS_RDATASET_FIXED
800 unsigned char *offsetbase;
801 unsigned int *offsettable;
805 REQUIRE(tslabp != NULL && *tslabp == NULL);
806 REQUIRE(mslab != NULL && sslab != NULL);
808 mcurrent = mslab + reservelen;
809 mcount = *mcurrent++ * 256;
810 mcount += *mcurrent++;
811 scurrent = sslab + reservelen;
812 scount = *scurrent++ * 256;
813 scount += *scurrent++;
814 INSIST(mcount > 0 && scount > 0);
817 * Yes, this is inefficient!
821 * Start figuring out the target length and count.
823 tlength = reservelen + 2;
827 #if DNS_RDATASET_FIXED
828 mcurrent += 4 * mcount;
829 scurrent += 4 * scount;
834 * Add in the length of rdata in the mslab that aren't in
837 for (i = 0; i < mcount; i++) {
838 unsigned char *mrdatabegin = mcurrent;
839 rdata_from_slab(&mcurrent, rdclass, type, &mrdata);
841 for (count = 0; count < scount; count++) {
842 dns_rdata_reset(&srdata);
843 rdata_from_slab(&scurrent, rdclass, type, &srdata);
844 if (dns_rdata_compare(&mrdata, &srdata) == 0)
847 if (count == scount) {
849 * This rdata isn't in the sslab, and thus isn't
852 tlength += mcurrent - mrdatabegin;
856 dns_rdata_reset(&mrdata);
859 #if DNS_RDATASET_FIXED
860 tlength += (4 * tcount);
864 * Check that all the records originally existed. The numeric
865 * check only works as rdataslabs do not contain duplicates.
867 if (((flags & DNS_RDATASLAB_EXACT) != 0) && (rcount != scount))
868 return (DNS_R_NOTEXACT);
871 * Don't continue if the new rdataslab would be empty.
874 return (DNS_R_NXRRSET);
877 * If nothing is going to change, we can stop.
880 return (DNS_R_UNCHANGED);
883 * Copy the reserved area from the mslab.
885 tstart = isc_mem_get(mctx, tlength);
887 return (ISC_R_NOMEMORY);
888 memcpy(tstart, mslab, reservelen);
889 tcurrent = tstart + reservelen;
890 #if DNS_RDATASET_FIXED
891 offsetbase = tcurrent;
893 offsettable = isc_mem_get(mctx, mcount * sizeof(unsigned int));
894 if (offsettable == NULL) {
895 isc_mem_put(mctx, tstart, tlength);
896 return (ISC_R_NOMEMORY);
898 memset(offsettable, 0, mcount * sizeof(unsigned int));
902 * Write the new count.
904 *tcurrent++ = (tcount & 0xff00) >> 8;
905 *tcurrent++ = (tcount & 0x00ff);
907 #if DNS_RDATASET_FIXED
908 tcurrent += (4 * tcount);
912 * Copy the parts of mslab not in sslab.
914 mcurrent = mslab + reservelen;
915 mcount = *mcurrent++ * 256;
916 mcount += *mcurrent++;
917 #if DNS_RDATASET_FIXED
918 mcurrent += (4 * mcount);
920 for (i = 0; i < mcount; i++) {
921 unsigned char *mrdatabegin = mcurrent;
922 #if DNS_RDATASET_FIXED
923 order = mcurrent[2] * 256 + mcurrent[3];
924 INSIST(order < mcount);
926 rdata_from_slab(&mcurrent, rdclass, type, &mrdata);
928 for (count = 0; count < scount; count++) {
929 dns_rdata_reset(&srdata);
930 rdata_from_slab(&scurrent, rdclass, type, &srdata);
931 if (dns_rdata_compare(&mrdata, &srdata) == 0)
934 if (count == scount) {
936 * This rdata isn't in the sslab, and thus should be
937 * copied to the tslab.
939 unsigned int length = mcurrent - mrdatabegin;
940 #if DNS_RDATASET_FIXED
941 offsettable[order] = tcurrent - offsetbase;
943 memcpy(tcurrent, mrdatabegin, length);
946 dns_rdata_reset(&mrdata);
949 #if DNS_RDATASET_FIXED
950 fillin_offsets(offsetbase, offsettable, mcount);
952 isc_mem_put(mctx, offsettable, mcount * sizeof(unsigned int));
955 INSIST(tcurrent == tstart + tlength);
959 return (ISC_R_SUCCESS);
963 dns_rdataslab_equal(unsigned char *slab1, unsigned char *slab2,
964 unsigned int reservelen)
966 unsigned char *current1, *current2;
967 unsigned int count1, count2;
968 unsigned int length1, length2;
970 current1 = slab1 + reservelen;
971 count1 = *current1++ * 256;
972 count1 += *current1++;
974 current2 = slab2 + reservelen;
975 count2 = *current2++ * 256;
976 count2 += *current2++;
978 if (count1 != count2)
981 #if DNS_RDATASET_FIXED
982 current1 += (4 * count1);
983 current2 += (4 * count2);
987 length1 = *current1++ * 256;
988 length1 += *current1++;
990 length2 = *current2++ * 256;
991 length2 += *current2++;
993 #if DNS_RDATASET_FIXED
998 if (length1 != length2 ||
999 memcmp(current1, current2, length1) != 0)
1002 current1 += length1;
1003 current2 += length1;
1011 dns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2,
1012 unsigned int reservelen, dns_rdataclass_t rdclass,
1013 dns_rdatatype_t type)
1015 unsigned char *current1, *current2;
1016 unsigned int count1, count2;
1017 dns_rdata_t rdata1 = DNS_RDATA_INIT;
1018 dns_rdata_t rdata2 = DNS_RDATA_INIT;
1020 current1 = slab1 + reservelen;
1021 count1 = *current1++ * 256;
1022 count1 += *current1++;
1024 current2 = slab2 + reservelen;
1025 count2 = *current2++ * 256;
1026 count2 += *current2++;
1028 if (count1 != count2)
1031 #if DNS_RDATASET_FIXED
1032 current1 += (4 * count1);
1033 current2 += (4 * count2);
1036 while (count1-- > 0) {
1037 rdata_from_slab(¤t1, rdclass, type, &rdata1);
1038 rdata_from_slab(¤t2, rdclass, type, &rdata2);
1039 if (dns_rdata_compare(&rdata1, &rdata2) != 0)
1041 dns_rdata_reset(&rdata1);
1042 dns_rdata_reset(&rdata2);