4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: rdataslab.c,v 1.50 2009/01/17 23:47:43 tbox Exp */
29 #include <isc/region.h>
30 #include <isc/string.h> /* Required for HP/UX (and others?) */
33 #include <dns/result.h>
34 #include <dns/rdata.h>
35 #include <dns/rdataset.h>
36 #include <dns/rdataslab.h>
39 * The rdataslab structure allows iteration to occur in both load order
40 * and DNSSEC order. The structure is as follows:
42 * header (reservelen bytes)
43 * record count (2 bytes)
44 * offset table (4 x record count bytes in load order)
46 * data length (2 bytes)
48 * meta data (1 byte for RRSIG's)
49 * data (data length bytes)
51 * If DNS_RDATASET_FIXED is defined to be zero (0) the format of a
52 * rdataslab is as follows:
54 * header (reservelen bytes)
55 * record count (2 bytes)
57 * data length (2 bytes)
58 * data (data length bytes)
60 * Offsets are from the end of the header.
62 * Load order traversal is performed by walking the offset table to find
63 * the start of the record (DNS_RDATASET_FIXED = 1).
65 * DNSSEC order traversal is performed by walking the data records.
67 * The order is stored with record to allow for efficient reconstruction
68 * of the offset table following a merge or subtraction.
70 * The iterator methods here currently only support DNSSEC order iteration.
72 * The iterator methods in rbtdb support both load order and DNSSEC order
76 * rbtdb.c directly interacts with the slab's raw structures. If the
77 * structure changes then rbtdb.c also needs to be updated to reflect
78 * the changes. See the areas tagged with "RDATASLAB".
86 /*% Note: the "const void *" are just to make qsort happy. */
88 compare_rdata(const void *p1
, const void *p2
) {
89 const struct xrdata
*x1
= p1
;
90 const struct xrdata
*x2
= p2
;
91 return (dns_rdata_compare(&x1
->rdata
, &x2
->rdata
));
94 #if DNS_RDATASET_FIXED
96 fillin_offsets(unsigned char *offsetbase
, unsigned int *offsettable
,
102 for (i
= 0, j
= 0; i
< length
; i
++) {
104 if (offsettable
[i
] == 0)
108 * Fill in offset table.
110 raw
= &offsetbase
[j
*4 + 2];
111 *raw
++ = (offsettable
[i
] & 0xff000000) >> 24;
112 *raw
++ = (offsettable
[i
] & 0xff0000) >> 16;
113 *raw
++ = (offsettable
[i
] & 0xff00) >> 8;
114 *raw
= offsettable
[i
] & 0xff;
117 * Fill in table index.
119 raw
= offsetbase
+ offsettable
[i
] + 2;
120 *raw
++ = (j
& 0xff00) >> 8;
127 dns_rdataslab_fromrdataset(dns_rdataset_t
*rdataset
, isc_mem_t
*mctx
,
128 isc_region_t
*region
, unsigned int reservelen
)
131 unsigned char *rawbuf
;
132 #if DNS_RDATASET_FIXED
133 unsigned char *offsetbase
;
140 #if DNS_RDATASET_FIXED
141 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
);
219 * Provide space to store the per RR meta data.
221 if (rdataset
->type
== dns_rdatatype_rrsig
)
226 * Don't forget the last item!
228 #if DNS_RDATASET_FIXED
229 buflen
+= (8 + x
[i
-1].rdata
.length
);
231 buflen
+= (2 + x
[i
-1].rdata
.length
);
234 * Provide space to store the per RR meta data.
236 if (rdataset
->type
== dns_rdatatype_rrsig
)
240 * Ensure that singleton types are actually singletons.
242 if (nitems
> 1 && dns_rdatatype_issingleton(rdataset
->type
)) {
244 * We have a singleton type, but there's more than one
245 * RR in the rdataset.
247 result
= DNS_R_SINGLETON
;
252 * Allocate the memory, set up a buffer, start copying in
255 rawbuf
= isc_mem_get(mctx
, buflen
);
256 if (rawbuf
== NULL
) {
257 result
= ISC_R_NOMEMORY
;
261 #if DNS_RDATASET_FIXED
262 /* Allocate temporary offset table. */
263 offsettable
= isc_mem_get(mctx
, nalloc
* sizeof(unsigned int));
264 if (offsettable
== NULL
) {
265 isc_mem_put(mctx
, rawbuf
, buflen
);
266 result
= ISC_R_NOMEMORY
;
269 memset(offsettable
, 0, nalloc
* sizeof(unsigned int));
272 region
->base
= rawbuf
;
273 region
->length
= buflen
;
275 rawbuf
+= reservelen
;
276 #if DNS_RDATASET_FIXED
280 *rawbuf
++ = (nitems
& 0xff00) >> 8;
281 *rawbuf
++ = (nitems
& 0x00ff);
283 #if DNS_RDATASET_FIXED
284 /* Skip load order table. Filled in later. */
285 rawbuf
+= nitems
* 4;
288 for (i
= 0; i
< nalloc
; i
++) {
289 if (x
[i
].rdata
.data
== NULL
)
291 #if DNS_RDATASET_FIXED
292 offsettable
[x
[i
].order
] = rawbuf
- offsetbase
;
294 length
= x
[i
].rdata
.length
;
295 if (rdataset
->type
== dns_rdatatype_rrsig
)
297 *rawbuf
++ = (length
& 0xff00) >> 8;
298 *rawbuf
++ = (length
& 0x00ff);
299 #if DNS_RDATASET_FIXED
300 rawbuf
+= 2; /* filled in later */
303 * Store the per RR meta data.
305 if (rdataset
->type
== dns_rdatatype_rrsig
) {
306 *rawbuf
++ |= (x
[i
].rdata
.flags
& DNS_RDATA_OFFLINE
) ?
307 DNS_RDATASLAB_OFFLINE
: 0;
309 memcpy(rawbuf
, x
[i
].rdata
.data
, x
[i
].rdata
.length
);
310 rawbuf
+= x
[i
].rdata
.length
;
313 #if DNS_RDATASET_FIXED
314 fillin_offsets(offsetbase
, offsettable
, nalloc
);
315 isc_mem_put(mctx
, offsettable
, nalloc
* sizeof(unsigned int));
318 result
= ISC_R_SUCCESS
;
321 isc_mem_put(mctx
, x
, nalloc
* sizeof(struct xrdata
));
326 rdataset_disassociate(dns_rdataset_t
*rdataset
) {
331 rdataset_first(dns_rdataset_t
*rdataset
) {
332 unsigned char *raw
= rdataset
->private3
;
335 count
= raw
[0] * 256 + raw
[1];
337 rdataset
->private5
= NULL
;
338 return (ISC_R_NOMORE
);
340 #if DNS_RDATASET_FIXED
341 raw
+= 2 + (4 * count
);
346 * The privateuint4 field is the number of rdata beyond the cursor
347 * position, so we decrement the total count by one before storing
351 rdataset
->privateuint4
= count
;
352 rdataset
->private5
= raw
;
354 return (ISC_R_SUCCESS
);
358 rdataset_next(dns_rdataset_t
*rdataset
) {
363 count
= rdataset
->privateuint4
;
365 return (ISC_R_NOMORE
);
367 rdataset
->privateuint4
= count
;
368 raw
= rdataset
->private5
;
369 length
= raw
[0] * 256 + raw
[1];
370 #if DNS_RDATASET_FIXED
375 rdataset
->private5
= raw
;
377 return (ISC_R_SUCCESS
);
381 rdataset_current(dns_rdataset_t
*rdataset
, dns_rdata_t
*rdata
) {
382 unsigned char *raw
= rdataset
->private5
;
385 unsigned int flags
= 0;
387 REQUIRE(raw
!= NULL
);
389 length
= raw
[0] * 256 + raw
[1];
390 #if DNS_RDATASET_FIXED
395 if (rdataset
->type
== dns_rdatatype_rrsig
) {
396 if (*raw
& DNS_RDATASLAB_OFFLINE
)
397 flags
|= DNS_RDATA_OFFLINE
;
403 dns_rdata_fromregion(rdata
, rdataset
->rdclass
, rdataset
->type
, &r
);
404 rdata
->flags
|= flags
;
408 rdataset_clone(dns_rdataset_t
*source
, dns_rdataset_t
*target
) {
412 * Reset iterator state.
414 target
->privateuint4
= 0;
415 target
->private5
= NULL
;
419 rdataset_count(dns_rdataset_t
*rdataset
) {
420 unsigned char *raw
= rdataset
->private3
;
423 count
= raw
[0] * 256 + raw
[1];
428 static dns_rdatasetmethods_t rdataset_methods
= {
429 rdataset_disassociate
,
445 dns_rdataslab_tordataset(unsigned char *slab
, unsigned int reservelen
,
446 dns_rdataclass_t rdclass
, dns_rdatatype_t rdtype
,
447 dns_rdatatype_t covers
, dns_ttl_t ttl
,
448 dns_rdataset_t
*rdataset
)
450 REQUIRE(slab
!= NULL
);
451 REQUIRE(!dns_rdataset_isassociated(rdataset
));
453 rdataset
->methods
= &rdataset_methods
;
454 rdataset
->rdclass
= rdclass
;
455 rdataset
->type
= rdtype
;
456 rdataset
->covers
= covers
;
459 rdataset
->private1
= NULL
;
460 rdataset
->private2
= NULL
;
461 rdataset
->private3
= slab
+ reservelen
;
464 * Reset iterator state.
466 rdataset
->privateuint4
= 0;
467 rdataset
->private5
= NULL
;
471 dns_rdataslab_size(unsigned char *slab
, unsigned int reservelen
) {
472 unsigned int count
, length
;
473 unsigned char *current
;
475 REQUIRE(slab
!= NULL
);
477 current
= slab
+ reservelen
;
478 count
= *current
++ * 256;
480 #if DNS_RDATASET_FIXED
481 current
+= (4 * count
);
485 length
= *current
++ * 256;
486 length
+= *current
++;
487 #if DNS_RDATASET_FIXED
488 current
+= length
+ 2;
494 return ((unsigned int)(current
- slab
));
498 * Make the dns_rdata_t 'rdata' refer to the slab item
499 * beginning at '*current', which is part of a slab of type
500 * 'type' and class 'rdclass', and advance '*current' to
501 * point to the next item in the slab.
504 rdata_from_slab(unsigned char **current
,
505 dns_rdataclass_t rdclass
, dns_rdatatype_t type
,
508 unsigned char *tcurrent
= *current
;
511 isc_boolean_t offline
= ISC_FALSE
;
513 length
= *tcurrent
++ * 256;
514 length
+= *tcurrent
++;
516 if (type
== dns_rdatatype_rrsig
) {
517 if ((*tcurrent
& DNS_RDATASLAB_OFFLINE
) != 0)
522 region
.length
= length
;
523 #if DNS_RDATASET_FIXED
526 region
.base
= tcurrent
;
527 tcurrent
+= region
.length
;
528 dns_rdata_fromregion(rdata
, rdclass
, type
, ®ion
);
530 rdata
->flags
|= DNS_RDATA_OFFLINE
;
535 * Return true iff 'slab' (slab data of type 'type' and class 'rdclass')
536 * contains an rdata identical to 'rdata'. This does case insensitive
537 * comparisons per DNSSEC.
539 static inline isc_boolean_t
540 rdata_in_slab(unsigned char *slab
, unsigned int reservelen
,
541 dns_rdataclass_t rdclass
, dns_rdatatype_t type
,
544 unsigned int count
, i
;
545 unsigned char *current
;
546 dns_rdata_t trdata
= DNS_RDATA_INIT
;
549 current
= slab
+ reservelen
;
550 count
= *current
++ * 256;
553 #if DNS_RDATASET_FIXED
554 current
+= (4 * count
);
557 for (i
= 0; i
< count
; i
++) {
558 rdata_from_slab(¤t
, rdclass
, type
, &trdata
);
560 n
= dns_rdata_compare(&trdata
, rdata
);
563 if (n
> 0) /* In DNSSEC order. */
565 dns_rdata_reset(&trdata
);
571 dns_rdataslab_merge(unsigned char *oslab
, unsigned char *nslab
,
572 unsigned int reservelen
, isc_mem_t
*mctx
,
573 dns_rdataclass_t rdclass
, dns_rdatatype_t type
,
574 unsigned int flags
, unsigned char **tslabp
)
576 unsigned char *ocurrent
, *ostart
, *ncurrent
, *tstart
, *tcurrent
, *data
;
577 unsigned int ocount
, ncount
, count
, olength
, tlength
, tcount
, length
;
578 dns_rdata_t ordata
= DNS_RDATA_INIT
;
579 dns_rdata_t nrdata
= DNS_RDATA_INIT
;
580 isc_boolean_t added_something
= ISC_FALSE
;
581 unsigned int oadded
= 0;
582 unsigned int nadded
= 0;
583 unsigned int nncount
= 0;
584 #if DNS_RDATASET_FIXED
585 unsigned int oncount
;
586 unsigned int norder
= 0;
587 unsigned int oorder
= 0;
588 unsigned char *offsetbase
;
589 unsigned int *offsettable
;
593 * XXX Need parameter to allow "delete rdatasets in nslab" merge,
594 * or perhaps another merge routine for this purpose.
597 REQUIRE(tslabp
!= NULL
&& *tslabp
== NULL
);
598 REQUIRE(oslab
!= NULL
&& nslab
!= NULL
);
600 ocurrent
= oslab
+ reservelen
;
601 ocount
= *ocurrent
++ * 256;
602 ocount
+= *ocurrent
++;
603 #if DNS_RDATASET_FIXED
604 ocurrent
+= (4 * ocount
);
607 ncurrent
= nslab
+ reservelen
;
608 ncount
= *ncurrent
++ * 256;
609 ncount
+= *ncurrent
++;
610 #if DNS_RDATASET_FIXED
611 ncurrent
+= (4 * ncount
);
613 INSIST(ocount
> 0 && ncount
> 0);
615 #if DNS_RDATASET_FIXED
620 * Yes, this is inefficient!
624 * Figure out the length of the old slab's data.
627 for (count
= 0; count
< ocount
; count
++) {
628 length
= *ocurrent
++ * 256;
629 length
+= *ocurrent
++;
630 #if DNS_RDATASET_FIXED
631 olength
+= length
+ 8;
632 ocurrent
+= length
+ 2;
634 olength
+= length
+ 2;
640 * Start figuring out the target length and count.
642 tlength
= reservelen
+ 2 + olength
;
646 * Add in the length of rdata in the new slab that aren't in
650 dns_rdata_init(&nrdata
);
651 rdata_from_slab(&ncurrent
, rdclass
, type
, &nrdata
);
652 if (!rdata_in_slab(oslab
, reservelen
, rdclass
, type
, &nrdata
))
655 * This rdata isn't in the old slab.
657 #if DNS_RDATASET_FIXED
658 tlength
+= nrdata
.length
+ 8;
660 tlength
+= nrdata
.length
+ 2;
662 if (type
== dns_rdatatype_rrsig
)
666 added_something
= ISC_TRUE
;
669 } while (ncount
> 0);
672 if (((flags
& DNS_RDATASLAB_EXACT
) != 0) &&
673 (tcount
!= ncount
+ ocount
))
674 return (DNS_R_NOTEXACT
);
676 if (!added_something
&& (flags
& DNS_RDATASLAB_FORCE
) == 0)
677 return (DNS_R_UNCHANGED
);
680 * Ensure that singleton types are actually singletons.
682 if (tcount
> 1 && dns_rdatatype_issingleton(type
)) {
684 * We have a singleton type, but there's more than one
685 * RR in the rdataset.
687 return (DNS_R_SINGLETON
);
691 return (ISC_R_NOSPACE
);
694 * Copy the reserved area from the new slab.
696 tstart
= isc_mem_get(mctx
, tlength
);
698 return (ISC_R_NOMEMORY
);
699 memcpy(tstart
, nslab
, reservelen
);
700 tcurrent
= tstart
+ reservelen
;
701 #if DNS_RDATASET_FIXED
702 offsetbase
= tcurrent
;
706 * Write the new count.
708 *tcurrent
++ = (tcount
& 0xff00) >> 8;
709 *tcurrent
++ = (tcount
& 0x00ff);
711 #if DNS_RDATASET_FIXED
715 tcurrent
+= (tcount
* 4);
717 offsettable
= isc_mem_get(mctx
,
718 (ocount
+ oncount
) * sizeof(unsigned int));
719 if (offsettable
== NULL
) {
720 isc_mem_put(mctx
, tstart
, tlength
);
721 return (ISC_R_NOMEMORY
);
723 memset(offsettable
, 0, (ocount
+ oncount
) * sizeof(unsigned int));
727 * Merge the two slabs.
731 #if DNS_RDATASET_FIXED
732 oorder
= ocurrent
[2] * 256 + ocurrent
[3];
733 INSIST(oorder
< ocount
);
735 rdata_from_slab(&ocurrent
, rdclass
, type
, &ordata
);
737 ncurrent
= nslab
+ reservelen
+ 2;
738 #if DNS_RDATASET_FIXED
739 ncurrent
+= (4 * oncount
);
744 dns_rdata_reset(&nrdata
);
745 #if DNS_RDATASET_FIXED
746 norder
= ncurrent
[2] * 256 + ncurrent
[3];
748 INSIST(norder
< oncount
);
750 rdata_from_slab(&ncurrent
, rdclass
, type
, &nrdata
);
751 } while (rdata_in_slab(oslab
, reservelen
, rdclass
,
755 while (oadded
< ocount
|| nadded
< ncount
) {
756 isc_boolean_t fromold
;
757 if (oadded
== ocount
)
759 else if (nadded
== ncount
)
762 fromold
= ISC_TF(compare_rdata(&ordata
, &nrdata
) < 0);
764 #if DNS_RDATASET_FIXED
765 offsettable
[oorder
] = tcurrent
- offsetbase
;
767 length
= ordata
.length
;
769 if (type
== dns_rdatatype_rrsig
) {
773 *tcurrent
++ = (length
& 0xff00) >> 8;
774 *tcurrent
++ = (length
& 0x00ff);
775 #if DNS_RDATASET_FIXED
776 tcurrent
+= 2; /* fill in later */
778 memcpy(tcurrent
, data
, length
);
781 if (oadded
< ocount
) {
782 dns_rdata_reset(&ordata
);
783 #if DNS_RDATASET_FIXED
784 oorder
= ocurrent
[2] * 256 + ocurrent
[3];
785 INSIST(oorder
< ocount
);
787 rdata_from_slab(&ocurrent
, rdclass
, type
,
791 #if DNS_RDATASET_FIXED
792 offsettable
[ocount
+ norder
] = tcurrent
- offsetbase
;
794 length
= nrdata
.length
;
796 if (type
== dns_rdatatype_rrsig
) {
800 *tcurrent
++ = (length
& 0xff00) >> 8;
801 *tcurrent
++ = (length
& 0x00ff);
802 #if DNS_RDATASET_FIXED
803 tcurrent
+= 2; /* fill in later */
805 memcpy(tcurrent
, data
, length
);
808 if (nadded
< ncount
) {
810 dns_rdata_reset(&nrdata
);
811 #if DNS_RDATASET_FIXED
812 norder
= ncurrent
[2] * 256 + ncurrent
[3];
813 INSIST(norder
< oncount
);
815 rdata_from_slab(&ncurrent
, rdclass
,
817 } while (rdata_in_slab(oslab
, reservelen
,
824 #if DNS_RDATASET_FIXED
825 fillin_offsets(offsetbase
, offsettable
, ocount
+ oncount
);
827 isc_mem_put(mctx
, offsettable
,
828 (ocount
+ oncount
) * sizeof(unsigned int));
831 INSIST(tcurrent
== tstart
+ tlength
);
835 return (ISC_R_SUCCESS
);
839 dns_rdataslab_subtract(unsigned char *mslab
, unsigned char *sslab
,
840 unsigned int reservelen
, isc_mem_t
*mctx
,
841 dns_rdataclass_t rdclass
, dns_rdatatype_t type
,
842 unsigned int flags
, unsigned char **tslabp
)
844 unsigned char *mcurrent
, *sstart
, *scurrent
, *tstart
, *tcurrent
;
845 unsigned int mcount
, scount
, rcount
,count
, tlength
, tcount
, i
;
846 dns_rdata_t srdata
= DNS_RDATA_INIT
;
847 dns_rdata_t mrdata
= DNS_RDATA_INIT
;
848 #if DNS_RDATASET_FIXED
849 unsigned char *offsetbase
;
850 unsigned int *offsettable
;
854 REQUIRE(tslabp
!= NULL
&& *tslabp
== NULL
);
855 REQUIRE(mslab
!= NULL
&& sslab
!= NULL
);
857 mcurrent
= mslab
+ reservelen
;
858 mcount
= *mcurrent
++ * 256;
859 mcount
+= *mcurrent
++;
860 scurrent
= sslab
+ reservelen
;
861 scount
= *scurrent
++ * 256;
862 scount
+= *scurrent
++;
863 INSIST(mcount
> 0 && scount
> 0);
866 * Yes, this is inefficient!
870 * Start figuring out the target length and count.
872 tlength
= reservelen
+ 2;
876 #if DNS_RDATASET_FIXED
877 mcurrent
+= 4 * mcount
;
878 scurrent
+= 4 * scount
;
883 * Add in the length of rdata in the mslab that aren't in
886 for (i
= 0; i
< mcount
; i
++) {
887 unsigned char *mrdatabegin
= mcurrent
;
888 rdata_from_slab(&mcurrent
, rdclass
, type
, &mrdata
);
890 for (count
= 0; count
< scount
; count
++) {
891 dns_rdata_reset(&srdata
);
892 rdata_from_slab(&scurrent
, rdclass
, type
, &srdata
);
893 if (dns_rdata_compare(&mrdata
, &srdata
) == 0)
896 if (count
== scount
) {
898 * This rdata isn't in the sslab, and thus isn't
901 tlength
+= mcurrent
- mrdatabegin
;
905 dns_rdata_reset(&mrdata
);
908 #if DNS_RDATASET_FIXED
909 tlength
+= (4 * tcount
);
913 * Check that all the records originally existed. The numeric
914 * check only works as rdataslabs do not contain duplicates.
916 if (((flags
& DNS_RDATASLAB_EXACT
) != 0) && (rcount
!= scount
))
917 return (DNS_R_NOTEXACT
);
920 * Don't continue if the new rdataslab would be empty.
923 return (DNS_R_NXRRSET
);
926 * If nothing is going to change, we can stop.
929 return (DNS_R_UNCHANGED
);
932 * Copy the reserved area from the mslab.
934 tstart
= isc_mem_get(mctx
, tlength
);
936 return (ISC_R_NOMEMORY
);
937 memcpy(tstart
, mslab
, reservelen
);
938 tcurrent
= tstart
+ reservelen
;
939 #if DNS_RDATASET_FIXED
940 offsetbase
= tcurrent
;
942 offsettable
= isc_mem_get(mctx
, mcount
* sizeof(unsigned int));
943 if (offsettable
== NULL
) {
944 isc_mem_put(mctx
, tstart
, tlength
);
945 return (ISC_R_NOMEMORY
);
947 memset(offsettable
, 0, mcount
* sizeof(unsigned int));
951 * Write the new count.
953 *tcurrent
++ = (tcount
& 0xff00) >> 8;
954 *tcurrent
++ = (tcount
& 0x00ff);
956 #if DNS_RDATASET_FIXED
957 tcurrent
+= (4 * tcount
);
961 * Copy the parts of mslab not in sslab.
963 mcurrent
= mslab
+ reservelen
;
964 mcount
= *mcurrent
++ * 256;
965 mcount
+= *mcurrent
++;
966 #if DNS_RDATASET_FIXED
967 mcurrent
+= (4 * mcount
);
969 for (i
= 0; i
< mcount
; i
++) {
970 unsigned char *mrdatabegin
= mcurrent
;
971 #if DNS_RDATASET_FIXED
972 order
= mcurrent
[2] * 256 + mcurrent
[3];
973 INSIST(order
< mcount
);
975 rdata_from_slab(&mcurrent
, rdclass
, type
, &mrdata
);
977 for (count
= 0; count
< scount
; count
++) {
978 dns_rdata_reset(&srdata
);
979 rdata_from_slab(&scurrent
, rdclass
, type
, &srdata
);
980 if (dns_rdata_compare(&mrdata
, &srdata
) == 0)
983 if (count
== scount
) {
985 * This rdata isn't in the sslab, and thus should be
986 * copied to the tslab.
988 unsigned int length
= mcurrent
- mrdatabegin
;
989 #if DNS_RDATASET_FIXED
990 offsettable
[order
] = tcurrent
- offsetbase
;
992 memcpy(tcurrent
, mrdatabegin
, length
);
995 dns_rdata_reset(&mrdata
);
998 #if DNS_RDATASET_FIXED
999 fillin_offsets(offsetbase
, offsettable
, mcount
);
1001 isc_mem_put(mctx
, offsettable
, mcount
* sizeof(unsigned int));
1004 INSIST(tcurrent
== tstart
+ tlength
);
1008 return (ISC_R_SUCCESS
);
1012 dns_rdataslab_equal(unsigned char *slab1
, unsigned char *slab2
,
1013 unsigned int reservelen
)
1015 unsigned char *current1
, *current2
;
1016 unsigned int count1
, count2
;
1017 unsigned int length1
, length2
;
1019 current1
= slab1
+ reservelen
;
1020 count1
= *current1
++ * 256;
1021 count1
+= *current1
++;
1023 current2
= slab2
+ reservelen
;
1024 count2
= *current2
++ * 256;
1025 count2
+= *current2
++;
1027 if (count1
!= count2
)
1030 #if DNS_RDATASET_FIXED
1031 current1
+= (4 * count1
);
1032 current2
+= (4 * count2
);
1035 while (count1
> 0) {
1036 length1
= *current1
++ * 256;
1037 length1
+= *current1
++;
1039 length2
= *current2
++ * 256;
1040 length2
+= *current2
++;
1042 #if DNS_RDATASET_FIXED
1047 if (length1
!= length2
||
1048 memcmp(current1
, current2
, length1
) != 0)
1051 current1
+= length1
;
1052 current2
+= length1
;
1060 dns_rdataslab_equalx(unsigned char *slab1
, unsigned char *slab2
,
1061 unsigned int reservelen
, dns_rdataclass_t rdclass
,
1062 dns_rdatatype_t type
)
1064 unsigned char *current1
, *current2
;
1065 unsigned int count1
, count2
;
1066 dns_rdata_t rdata1
= DNS_RDATA_INIT
;
1067 dns_rdata_t rdata2
= DNS_RDATA_INIT
;
1069 current1
= slab1
+ reservelen
;
1070 count1
= *current1
++ * 256;
1071 count1
+= *current1
++;
1073 current2
= slab2
+ reservelen
;
1074 count2
= *current2
++ * 256;
1075 count2
+= *current2
++;
1077 if (count1
!= count2
)
1080 #if DNS_RDATASET_FIXED
1081 current1
+= (4 * count1
);
1082 current2
+= (4 * count2
);
1085 while (count1
-- > 0) {
1086 rdata_from_slab(¤t1
, rdclass
, type
, &rdata1
);
1087 rdata_from_slab(¤t2
, rdclass
, type
, &rdata2
);
1088 if (dns_rdata_compare(&rdata1
, &rdata2
) != 0)
1090 dns_rdata_reset(&rdata1
);
1091 dns_rdata_reset(&rdata2
);