00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <stdlib.h>
00025
00026 #include <isc/mem.h>
00027 #include <isc/region.h>
00028 #include <isc/string.h>
00029 #include <isc/util.h>
00030
00031 #include <dns/result.h>
00032 #include <dns/rdata.h>
00033 #include <dns/rdataset.h>
00034 #include <dns/rdataslab.h>
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 struct xrdata {
00081 dns_rdata_t rdata;
00082 unsigned int order;
00083 };
00084
00085
00086 static int
00087 compare_rdata(const void *p1, const void *p2) {
00088 const struct xrdata *x1 = p1;
00089 const struct xrdata *x2 = p2;
00090 return (dns_rdata_compare(&x1->rdata, &x2->rdata));
00091 }
00092
00093 #if DNS_RDATASET_FIXED
00094 static void
00095 fillin_offsets(unsigned char *offsetbase, unsigned int *offsettable,
00096 unsigned length)
00097 {
00098 unsigned int i, j;
00099 unsigned char *raw;
00100
00101 for (i = 0, j = 0; i < length; i++) {
00102
00103 if (offsettable[i] == 0)
00104 continue;
00105
00106
00107
00108
00109 raw = &offsetbase[j*4 + 2];
00110 *raw++ = (offsettable[i] & 0xff000000) >> 24;
00111 *raw++ = (offsettable[i] & 0xff0000) >> 16;
00112 *raw++ = (offsettable[i] & 0xff00) >> 8;
00113 *raw = offsettable[i] & 0xff;
00114
00115
00116
00117
00118 raw = offsetbase + offsettable[i] + 2;
00119 *raw++ = (j & 0xff00) >> 8;
00120 *raw = j++ & 0xff;
00121 }
00122 }
00123 #endif
00124
00125 isc_result_t
00126 dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
00127 isc_region_t *region, unsigned int reservelen)
00128 {
00129
00130
00131
00132
00133 static unsigned char removed;
00134 struct xrdata *x;
00135 unsigned char *rawbuf;
00136 #if DNS_RDATASET_FIXED
00137 unsigned char *offsetbase;
00138 #endif
00139 unsigned int buflen;
00140 isc_result_t result;
00141 unsigned int nitems;
00142 unsigned int nalloc;
00143 unsigned int i;
00144 #if DNS_RDATASET_FIXED
00145 unsigned int *offsettable;
00146 #endif
00147 unsigned int length;
00148
00149 buflen = reservelen + 2;
00150
00151 nitems = dns_rdataset_count(rdataset);
00152
00153
00154
00155
00156
00157 if (nitems == 0) {
00158 if (rdataset->type != 0)
00159 return (ISC_R_FAILURE);
00160 rawbuf = isc_mem_get(mctx, buflen);
00161 if (rawbuf == NULL)
00162 return (ISC_R_NOMEMORY);
00163 region->base = rawbuf;
00164 region->length = buflen;
00165 rawbuf += reservelen;
00166 *rawbuf++ = 0;
00167 *rawbuf = 0;
00168 return (ISC_R_SUCCESS);
00169 }
00170
00171 if (nitems > 0xffff)
00172 return (ISC_R_NOSPACE);
00173
00174
00175
00176
00177 nalloc = nitems;
00178 x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata));
00179 if (x == NULL)
00180 return (ISC_R_NOMEMORY);
00181
00182
00183
00184
00185 result = dns_rdataset_first(rdataset);
00186 if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
00187 goto free_rdatas;
00188 for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) {
00189 INSIST(result == ISC_R_SUCCESS);
00190 dns_rdata_init(&x[i].rdata);
00191 dns_rdataset_current(rdataset, &x[i].rdata);
00192 INSIST(x[i].rdata.data != &removed);
00193 #if DNS_RDATASET_FIXED
00194 x[i].order = i;
00195 #endif
00196 result = dns_rdataset_next(rdataset);
00197 }
00198 if (i != nalloc || result != ISC_R_NOMORE) {
00199
00200
00201
00202
00203
00204
00205 result = ISC_R_FAILURE;
00206 goto free_rdatas;
00207 }
00208
00209
00210
00211
00212 if (nalloc > 1U)
00213 qsort(x, nalloc, sizeof(struct xrdata), compare_rdata);
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 for (i = 1; i < nalloc; i++) {
00225 if (compare_rdata(&x[i-1].rdata, &x[i].rdata) == 0) {
00226 x[i-1].rdata.data = &removed;
00227 #if DNS_RDATASET_FIXED
00228
00229
00230
00231
00232 if (x[i-1].order < x[i].order)
00233 x[i].order = x[i-1].order;
00234 #endif
00235 nitems--;
00236 } else {
00237 #if DNS_RDATASET_FIXED
00238 buflen += (8 + x[i-1].rdata.length);
00239 #else
00240 buflen += (2 + x[i-1].rdata.length);
00241 #endif
00242
00243
00244
00245 if (rdataset->type == dns_rdatatype_rrsig)
00246 buflen++;
00247 }
00248 }
00249
00250
00251
00252
00253 #if DNS_RDATASET_FIXED
00254 buflen += (8 + x[i-1].rdata.length);
00255 #else
00256 buflen += (2 + x[i-1].rdata.length);
00257 #endif
00258
00259
00260
00261 if (rdataset->type == dns_rdatatype_rrsig)
00262 buflen++;
00263
00264
00265
00266
00267 if (nitems > 1 && dns_rdatatype_issingleton(rdataset->type)) {
00268
00269
00270
00271
00272 result = DNS_R_SINGLETON;
00273 goto free_rdatas;
00274 }
00275
00276
00277
00278
00279
00280 rawbuf = isc_mem_get(mctx, buflen);
00281 if (rawbuf == NULL) {
00282 result = ISC_R_NOMEMORY;
00283 goto free_rdatas;
00284 }
00285
00286 #if DNS_RDATASET_FIXED
00287
00288 offsettable = isc_mem_get(mctx, nalloc * sizeof(unsigned int));
00289 if (offsettable == NULL) {
00290 isc_mem_put(mctx, rawbuf, buflen);
00291 result = ISC_R_NOMEMORY;
00292 goto free_rdatas;
00293 }
00294 memset(offsettable, 0, nalloc * sizeof(unsigned int));
00295 #endif
00296
00297 region->base = rawbuf;
00298 region->length = buflen;
00299
00300 rawbuf += reservelen;
00301 #if DNS_RDATASET_FIXED
00302 offsetbase = rawbuf;
00303 #endif
00304
00305 *rawbuf++ = (nitems & 0xff00) >> 8;
00306 *rawbuf++ = (nitems & 0x00ff);
00307
00308 #if DNS_RDATASET_FIXED
00309
00310 rawbuf += nitems * 4;
00311 #endif
00312
00313 for (i = 0; i < nalloc; i++) {
00314 if (x[i].rdata.data == &removed)
00315 continue;
00316 #if DNS_RDATASET_FIXED
00317 offsettable[x[i].order] = rawbuf - offsetbase;
00318 #endif
00319 length = x[i].rdata.length;
00320 if (rdataset->type == dns_rdatatype_rrsig)
00321 length++;
00322 INSIST(length <= 0xffff);
00323 *rawbuf++ = (length & 0xff00) >> 8;
00324 *rawbuf++ = (length & 0x00ff);
00325 #if DNS_RDATASET_FIXED
00326 rawbuf += 2;
00327 #endif
00328
00329
00330
00331 if (rdataset->type == dns_rdatatype_rrsig) {
00332 *rawbuf++ |= (x[i].rdata.flags & DNS_RDATA_OFFLINE) ?
00333 DNS_RDATASLAB_OFFLINE : 0;
00334 }
00335 memmove(rawbuf, x[i].rdata.data, x[i].rdata.length);
00336 rawbuf += x[i].rdata.length;
00337 }
00338
00339 #if DNS_RDATASET_FIXED
00340 fillin_offsets(offsetbase, offsettable, nalloc);
00341 isc_mem_put(mctx, offsettable, nalloc * sizeof(unsigned int));
00342 #endif
00343
00344 result = ISC_R_SUCCESS;
00345
00346 free_rdatas:
00347 isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata));
00348 return (result);
00349 }
00350
00351 static void
00352 rdataset_disassociate(dns_rdataset_t *rdataset) {
00353 UNUSED(rdataset);
00354 }
00355
00356 static isc_result_t
00357 rdataset_first(dns_rdataset_t *rdataset) {
00358 unsigned char *raw = rdataset->private3;
00359 unsigned int count;
00360
00361 count = raw[0] * 256 + raw[1];
00362 if (count == 0) {
00363 rdataset->private5 = NULL;
00364 return (ISC_R_NOMORE);
00365 }
00366 #if DNS_RDATASET_FIXED
00367 raw += 2 + (4 * count);
00368 #else
00369 raw += 2;
00370 #endif
00371
00372
00373
00374
00375
00376 count--;
00377 rdataset->privateuint4 = count;
00378 rdataset->private5 = raw;
00379
00380 return (ISC_R_SUCCESS);
00381 }
00382
00383 static isc_result_t
00384 rdataset_next(dns_rdataset_t *rdataset) {
00385 unsigned int count;
00386 unsigned int length;
00387 unsigned char *raw;
00388
00389 count = rdataset->privateuint4;
00390 if (count == 0)
00391 return (ISC_R_NOMORE);
00392 count--;
00393 rdataset->privateuint4 = count;
00394 raw = rdataset->private5;
00395 length = raw[0] * 256 + raw[1];
00396 #if DNS_RDATASET_FIXED
00397 raw += length + 4;
00398 #else
00399 raw += length + 2;
00400 #endif
00401 rdataset->private5 = raw;
00402
00403 return (ISC_R_SUCCESS);
00404 }
00405
00406 static void
00407 rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
00408 unsigned char *raw = rdataset->private5;
00409 isc_region_t r;
00410 unsigned int length;
00411 unsigned int flags = 0;
00412
00413 REQUIRE(raw != NULL);
00414
00415 length = raw[0] * 256 + raw[1];
00416 #if DNS_RDATASET_FIXED
00417 raw += 4;
00418 #else
00419 raw += 2;
00420 #endif
00421 if (rdataset->type == dns_rdatatype_rrsig) {
00422 if (*raw & DNS_RDATASLAB_OFFLINE)
00423 flags |= DNS_RDATA_OFFLINE;
00424 length--;
00425 raw++;
00426 }
00427 r.length = length;
00428 r.base = raw;
00429 dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
00430 rdata->flags |= flags;
00431 }
00432
00433 static void
00434 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
00435 *target = *source;
00436
00437
00438
00439
00440 target->privateuint4 = 0;
00441 target->private5 = NULL;
00442 }
00443
00444 static unsigned int
00445 rdataset_count(dns_rdataset_t *rdataset) {
00446 unsigned char *raw = rdataset->private3;
00447 unsigned int count;
00448
00449 count = raw[0] * 256 + raw[1];
00450
00451 return (count);
00452 }
00453
00454 static dns_rdatasetmethods_t rdataset_methods = {
00455 rdataset_disassociate,
00456 rdataset_first,
00457 rdataset_next,
00458 rdataset_current,
00459 rdataset_clone,
00460 rdataset_count,
00461 NULL,
00462 NULL,
00463 NULL,
00464 NULL,
00465 NULL,
00466 NULL,
00467 NULL,
00468 NULL,
00469 NULL,
00470 NULL,
00471 NULL,
00472 NULL
00473 };
00474
00475 void
00476 dns_rdataslab_tordataset(unsigned char *slab, unsigned int reservelen,
00477 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
00478 dns_rdatatype_t covers, dns_ttl_t ttl,
00479 dns_rdataset_t *rdataset)
00480 {
00481 REQUIRE(slab != NULL);
00482 REQUIRE(!dns_rdataset_isassociated(rdataset));
00483
00484 rdataset->methods = &rdataset_methods;
00485 rdataset->rdclass = rdclass;
00486 rdataset->type = rdtype;
00487 rdataset->covers = covers;
00488 rdataset->ttl = ttl;
00489 rdataset->trust = 0;
00490 rdataset->private1 = NULL;
00491 rdataset->private2 = NULL;
00492 rdataset->private3 = slab + reservelen;
00493
00494
00495
00496
00497 rdataset->privateuint4 = 0;
00498 rdataset->private5 = NULL;
00499 }
00500
00501 unsigned int
00502 dns_rdataslab_size(unsigned char *slab, unsigned int reservelen) {
00503 unsigned int count, length;
00504 unsigned char *current;
00505
00506 REQUIRE(slab != NULL);
00507
00508 current = slab + reservelen;
00509 count = *current++ * 256;
00510 count += *current++;
00511 #if DNS_RDATASET_FIXED
00512 current += (4 * count);
00513 #endif
00514 while (count > 0) {
00515 count--;
00516 length = *current++ * 256;
00517 length += *current++;
00518 #if DNS_RDATASET_FIXED
00519 current += length + 2;
00520 #else
00521 current += length;
00522 #endif
00523 }
00524
00525 return ((unsigned int)(current - slab));
00526 }
00527
00528
00529
00530
00531
00532
00533
00534 static inline void
00535 rdata_from_slab(unsigned char **current,
00536 dns_rdataclass_t rdclass, dns_rdatatype_t type,
00537 dns_rdata_t *rdata)
00538 {
00539 unsigned char *tcurrent = *current;
00540 isc_region_t region;
00541 unsigned int length;
00542 isc_boolean_t offline = ISC_FALSE;
00543
00544 length = *tcurrent++ * 256;
00545 length += *tcurrent++;
00546
00547 if (type == dns_rdatatype_rrsig) {
00548 if ((*tcurrent & DNS_RDATASLAB_OFFLINE) != 0)
00549 offline = ISC_TRUE;
00550 length--;
00551 tcurrent++;
00552 }
00553 region.length = length;
00554 #if DNS_RDATASET_FIXED
00555 tcurrent += 2;
00556 #endif
00557 region.base = tcurrent;
00558 tcurrent += region.length;
00559 dns_rdata_fromregion(rdata, rdclass, type, ®ion);
00560 if (offline)
00561 rdata->flags |= DNS_RDATA_OFFLINE;
00562 *current = tcurrent;
00563 }
00564
00565
00566
00567
00568
00569
00570 static inline isc_boolean_t
00571 rdata_in_slab(unsigned char *slab, unsigned int reservelen,
00572 dns_rdataclass_t rdclass, dns_rdatatype_t type,
00573 dns_rdata_t *rdata)
00574 {
00575 unsigned int count, i;
00576 unsigned char *current;
00577 dns_rdata_t trdata = DNS_RDATA_INIT;
00578 int n;
00579
00580 current = slab + reservelen;
00581 count = *current++ * 256;
00582 count += *current++;
00583
00584 #if DNS_RDATASET_FIXED
00585 current += (4 * count);
00586 #endif
00587
00588 for (i = 0; i < count; i++) {
00589 rdata_from_slab(¤t, rdclass, type, &trdata);
00590
00591 n = dns_rdata_compare(&trdata, rdata);
00592 if (n == 0)
00593 return (ISC_TRUE);
00594 if (n > 0)
00595 break;
00596 dns_rdata_reset(&trdata);
00597 }
00598 return (ISC_FALSE);
00599 }
00600
00601 isc_result_t
00602 dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
00603 unsigned int reservelen, isc_mem_t *mctx,
00604 dns_rdataclass_t rdclass, dns_rdatatype_t type,
00605 unsigned int flags, unsigned char **tslabp)
00606 {
00607 unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent, *data;
00608 unsigned int ocount, ncount, count, olength, tlength, tcount, length;
00609 dns_rdata_t ordata = DNS_RDATA_INIT;
00610 dns_rdata_t nrdata = DNS_RDATA_INIT;
00611 isc_boolean_t added_something = ISC_FALSE;
00612 unsigned int oadded = 0;
00613 unsigned int nadded = 0;
00614 unsigned int nncount = 0;
00615 #if DNS_RDATASET_FIXED
00616 unsigned int oncount;
00617 unsigned int norder = 0;
00618 unsigned int oorder = 0;
00619 unsigned char *offsetbase;
00620 unsigned int *offsettable;
00621 #endif
00622
00623
00624
00625
00626
00627
00628 REQUIRE(tslabp != NULL && *tslabp == NULL);
00629 REQUIRE(oslab != NULL && nslab != NULL);
00630
00631 ocurrent = oslab + reservelen;
00632 ocount = *ocurrent++ * 256;
00633 ocount += *ocurrent++;
00634 #if DNS_RDATASET_FIXED
00635 ocurrent += (4 * ocount);
00636 #endif
00637 ostart = ocurrent;
00638 ncurrent = nslab + reservelen;
00639 ncount = *ncurrent++ * 256;
00640 ncount += *ncurrent++;
00641 #if DNS_RDATASET_FIXED
00642 ncurrent += (4 * ncount);
00643 #endif
00644 INSIST(ocount > 0 && ncount > 0);
00645
00646 #if DNS_RDATASET_FIXED
00647 oncount = ncount;
00648 #endif
00649
00650
00651
00652
00653
00654
00655
00656
00657 olength = 0;
00658 for (count = 0; count < ocount; count++) {
00659 length = *ocurrent++ * 256;
00660 length += *ocurrent++;
00661 #if DNS_RDATASET_FIXED
00662 olength += length + 8;
00663 ocurrent += length + 2;
00664 #else
00665 olength += length + 2;
00666 ocurrent += length;
00667 #endif
00668 }
00669
00670
00671
00672
00673 tlength = reservelen + 2 + olength;
00674 tcount = ocount;
00675
00676
00677
00678
00679
00680 do {
00681 dns_rdata_init(&nrdata);
00682 rdata_from_slab(&ncurrent, rdclass, type, &nrdata);
00683 if (!rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata))
00684 {
00685
00686
00687
00688 #if DNS_RDATASET_FIXED
00689 tlength += nrdata.length + 8;
00690 #else
00691 tlength += nrdata.length + 2;
00692 #endif
00693 if (type == dns_rdatatype_rrsig)
00694 tlength++;
00695 tcount++;
00696 nncount++;
00697 added_something = ISC_TRUE;
00698 }
00699 ncount--;
00700 } while (ncount > 0);
00701 ncount = nncount;
00702
00703 if (((flags & DNS_RDATASLAB_EXACT) != 0) &&
00704 (tcount != ncount + ocount))
00705 return (DNS_R_NOTEXACT);
00706
00707 if (!added_something && (flags & DNS_RDATASLAB_FORCE) == 0)
00708 return (DNS_R_UNCHANGED);
00709
00710
00711
00712
00713 if (tcount > 1 && dns_rdatatype_issingleton(type)) {
00714
00715
00716
00717
00718 return (DNS_R_SINGLETON);
00719 }
00720
00721 if (tcount > 0xffff)
00722 return (ISC_R_NOSPACE);
00723
00724
00725
00726
00727 tstart = isc_mem_get(mctx, tlength);
00728 if (tstart == NULL)
00729 return (ISC_R_NOMEMORY);
00730 memmove(tstart, nslab, reservelen);
00731 tcurrent = tstart + reservelen;
00732 #if DNS_RDATASET_FIXED
00733 offsetbase = tcurrent;
00734 #endif
00735
00736
00737
00738
00739 *tcurrent++ = (tcount & 0xff00) >> 8;
00740 *tcurrent++ = (tcount & 0x00ff);
00741
00742 #if DNS_RDATASET_FIXED
00743
00744
00745
00746 tcurrent += (tcount * 4);
00747
00748 offsettable = isc_mem_get(mctx,
00749 (ocount + oncount) * sizeof(unsigned int));
00750 if (offsettable == NULL) {
00751 isc_mem_put(mctx, tstart, tlength);
00752 return (ISC_R_NOMEMORY);
00753 }
00754 memset(offsettable, 0, (ocount + oncount) * sizeof(unsigned int));
00755 #endif
00756
00757
00758
00759
00760 ocurrent = ostart;
00761 INSIST(ocount != 0);
00762 #if DNS_RDATASET_FIXED
00763 oorder = ocurrent[2] * 256 + ocurrent[3];
00764 INSIST(oorder < ocount);
00765 #endif
00766 rdata_from_slab(&ocurrent, rdclass, type, &ordata);
00767
00768 ncurrent = nslab + reservelen + 2;
00769 #if DNS_RDATASET_FIXED
00770 ncurrent += (4 * oncount);
00771 #endif
00772
00773 if (ncount > 0) {
00774 do {
00775 dns_rdata_reset(&nrdata);
00776 #if DNS_RDATASET_FIXED
00777 norder = ncurrent[2] * 256 + ncurrent[3];
00778
00779 INSIST(norder < oncount);
00780 #endif
00781 rdata_from_slab(&ncurrent, rdclass, type, &nrdata);
00782 } while (rdata_in_slab(oslab, reservelen, rdclass,
00783 type, &nrdata));
00784 }
00785
00786 while (oadded < ocount || nadded < ncount) {
00787 isc_boolean_t fromold;
00788 if (oadded == ocount)
00789 fromold = ISC_FALSE;
00790 else if (nadded == ncount)
00791 fromold = ISC_TRUE;
00792 else
00793 fromold = ISC_TF(compare_rdata(&ordata, &nrdata) < 0);
00794 if (fromold) {
00795 #if DNS_RDATASET_FIXED
00796 offsettable[oorder] = tcurrent - offsetbase;
00797 #endif
00798 length = ordata.length;
00799 data = ordata.data;
00800 if (type == dns_rdatatype_rrsig) {
00801 length++;
00802 data--;
00803 }
00804 *tcurrent++ = (length & 0xff00) >> 8;
00805 *tcurrent++ = (length & 0x00ff);
00806 #if DNS_RDATASET_FIXED
00807 tcurrent += 2;
00808 #endif
00809 memmove(tcurrent, data, length);
00810 tcurrent += length;
00811 oadded++;
00812 if (oadded < ocount) {
00813 dns_rdata_reset(&ordata);
00814 #if DNS_RDATASET_FIXED
00815 oorder = ocurrent[2] * 256 + ocurrent[3];
00816 INSIST(oorder < ocount);
00817 #endif
00818 rdata_from_slab(&ocurrent, rdclass, type,
00819 &ordata);
00820 }
00821 } else {
00822 #if DNS_RDATASET_FIXED
00823 offsettable[ocount + norder] = tcurrent - offsetbase;
00824 #endif
00825 length = nrdata.length;
00826 data = nrdata.data;
00827 if (type == dns_rdatatype_rrsig) {
00828 length++;
00829 data--;
00830 }
00831 *tcurrent++ = (length & 0xff00) >> 8;
00832 *tcurrent++ = (length & 0x00ff);
00833 #if DNS_RDATASET_FIXED
00834 tcurrent += 2;
00835 #endif
00836 memmove(tcurrent, data, length);
00837 tcurrent += length;
00838 nadded++;
00839 if (nadded < ncount) {
00840 do {
00841 dns_rdata_reset(&nrdata);
00842 #if DNS_RDATASET_FIXED
00843 norder = ncurrent[2] * 256 + ncurrent[3];
00844 INSIST(norder < oncount);
00845 #endif
00846 rdata_from_slab(&ncurrent, rdclass,
00847 type, &nrdata);
00848 } while (rdata_in_slab(oslab, reservelen,
00849 rdclass, type,
00850 &nrdata));
00851 }
00852 }
00853 }
00854
00855 #if DNS_RDATASET_FIXED
00856 fillin_offsets(offsetbase, offsettable, ocount + oncount);
00857
00858 isc_mem_put(mctx, offsettable,
00859 (ocount + oncount) * sizeof(unsigned int));
00860 #endif
00861
00862 INSIST(tcurrent == tstart + tlength);
00863
00864 *tslabp = tstart;
00865
00866 return (ISC_R_SUCCESS);
00867 }
00868
00869 isc_result_t
00870 dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
00871 unsigned int reservelen, isc_mem_t *mctx,
00872 dns_rdataclass_t rdclass, dns_rdatatype_t type,
00873 unsigned int flags, unsigned char **tslabp)
00874 {
00875 unsigned char *mcurrent, *sstart, *scurrent, *tstart, *tcurrent;
00876 unsigned int mcount, scount, rcount ,count, tlength, tcount, i;
00877 dns_rdata_t srdata = DNS_RDATA_INIT;
00878 dns_rdata_t mrdata = DNS_RDATA_INIT;
00879 #if DNS_RDATASET_FIXED
00880 unsigned char *offsetbase;
00881 unsigned int *offsettable;
00882 unsigned int order;
00883 #endif
00884
00885 REQUIRE(tslabp != NULL && *tslabp == NULL);
00886 REQUIRE(mslab != NULL && sslab != NULL);
00887
00888 mcurrent = mslab + reservelen;
00889 mcount = *mcurrent++ * 256;
00890 mcount += *mcurrent++;
00891 scurrent = sslab + reservelen;
00892 scount = *scurrent++ * 256;
00893 scount += *scurrent++;
00894 INSIST(mcount > 0 && scount > 0);
00895
00896
00897
00898
00899
00900
00901
00902
00903 tlength = reservelen + 2;
00904 tcount = 0;
00905 rcount = 0;
00906
00907 #if DNS_RDATASET_FIXED
00908 mcurrent += 4 * mcount;
00909 scurrent += 4 * scount;
00910 #endif
00911 sstart = scurrent;
00912
00913
00914
00915
00916
00917 for (i = 0; i < mcount; i++) {
00918 unsigned char *mrdatabegin = mcurrent;
00919 rdata_from_slab(&mcurrent, rdclass, type, &mrdata);
00920 scurrent = sstart;
00921 for (count = 0; count < scount; count++) {
00922 dns_rdata_reset(&srdata);
00923 rdata_from_slab(&scurrent, rdclass, type, &srdata);
00924 if (dns_rdata_compare(&mrdata, &srdata) == 0)
00925 break;
00926 }
00927 if (count == scount) {
00928
00929
00930
00931
00932 tlength += (unsigned int)(mcurrent - mrdatabegin);
00933 tcount++;
00934 } else
00935 rcount++;
00936 dns_rdata_reset(&mrdata);
00937 }
00938
00939 #if DNS_RDATASET_FIXED
00940 tlength += (4 * tcount);
00941 #endif
00942
00943
00944
00945
00946
00947 if (((flags & DNS_RDATASLAB_EXACT) != 0) && (rcount != scount))
00948 return (DNS_R_NOTEXACT);
00949
00950
00951
00952
00953 if (tcount == 0)
00954 return (DNS_R_NXRRSET);
00955
00956
00957
00958
00959 if (rcount == 0)
00960 return (DNS_R_UNCHANGED);
00961
00962
00963
00964
00965 tstart = isc_mem_get(mctx, tlength);
00966 if (tstart == NULL)
00967 return (ISC_R_NOMEMORY);
00968 memmove(tstart, mslab, reservelen);
00969 tcurrent = tstart + reservelen;
00970 #if DNS_RDATASET_FIXED
00971 offsetbase = tcurrent;
00972
00973 offsettable = isc_mem_get(mctx, mcount * sizeof(unsigned int));
00974 if (offsettable == NULL) {
00975 isc_mem_put(mctx, tstart, tlength);
00976 return (ISC_R_NOMEMORY);
00977 }
00978 memset(offsettable, 0, mcount * sizeof(unsigned int));
00979 #endif
00980
00981
00982
00983
00984 *tcurrent++ = (tcount & 0xff00) >> 8;
00985 *tcurrent++ = (tcount & 0x00ff);
00986
00987 #if DNS_RDATASET_FIXED
00988 tcurrent += (4 * tcount);
00989 #endif
00990
00991
00992
00993
00994 mcurrent = mslab + reservelen;
00995 mcount = *mcurrent++ * 256;
00996 mcount += *mcurrent++;
00997 #if DNS_RDATASET_FIXED
00998 mcurrent += (4 * mcount);
00999 #endif
01000 for (i = 0; i < mcount; i++) {
01001 unsigned char *mrdatabegin = mcurrent;
01002 #if DNS_RDATASET_FIXED
01003 order = mcurrent[2] * 256 + mcurrent[3];
01004 INSIST(order < mcount);
01005 #endif
01006 rdata_from_slab(&mcurrent, rdclass, type, &mrdata);
01007 scurrent = sstart;
01008 for (count = 0; count < scount; count++) {
01009 dns_rdata_reset(&srdata);
01010 rdata_from_slab(&scurrent, rdclass, type, &srdata);
01011 if (dns_rdata_compare(&mrdata, &srdata) == 0)
01012 break;
01013 }
01014 if (count == scount) {
01015
01016
01017
01018
01019 unsigned int length;
01020 length = (unsigned int)(mcurrent - mrdatabegin);
01021 #if DNS_RDATASET_FIXED
01022 offsettable[order] = tcurrent - offsetbase;
01023 #endif
01024 memmove(tcurrent, mrdatabegin, length);
01025 tcurrent += length;
01026 }
01027 dns_rdata_reset(&mrdata);
01028 }
01029
01030 #if DNS_RDATASET_FIXED
01031 fillin_offsets(offsetbase, offsettable, mcount);
01032
01033 isc_mem_put(mctx, offsettable, mcount * sizeof(unsigned int));
01034 #endif
01035
01036 INSIST(tcurrent == tstart + tlength);
01037
01038 *tslabp = tstart;
01039
01040 return (ISC_R_SUCCESS);
01041 }
01042
01043 isc_boolean_t
01044 dns_rdataslab_equal(unsigned char *slab1, unsigned char *slab2,
01045 unsigned int reservelen)
01046 {
01047 unsigned char *current1, *current2;
01048 unsigned int count1, count2;
01049 unsigned int length1, length2;
01050
01051 current1 = slab1 + reservelen;
01052 count1 = *current1++ * 256;
01053 count1 += *current1++;
01054
01055 current2 = slab2 + reservelen;
01056 count2 = *current2++ * 256;
01057 count2 += *current2++;
01058
01059 if (count1 != count2)
01060 return (ISC_FALSE);
01061
01062 #if DNS_RDATASET_FIXED
01063 current1 += (4 * count1);
01064 current2 += (4 * count2);
01065 #endif
01066
01067 while (count1 > 0) {
01068 length1 = *current1++ * 256;
01069 length1 += *current1++;
01070
01071 length2 = *current2++ * 256;
01072 length2 += *current2++;
01073
01074 #if DNS_RDATASET_FIXED
01075 current1 += 2;
01076 current2 += 2;
01077 #endif
01078
01079 if (length1 != length2 ||
01080 memcmp(current1, current2, length1) != 0)
01081 return (ISC_FALSE);
01082
01083 current1 += length1;
01084 current2 += length1;
01085
01086 count1--;
01087 }
01088 return (ISC_TRUE);
01089 }
01090
01091 isc_boolean_t
01092 dns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2,
01093 unsigned int reservelen, dns_rdataclass_t rdclass,
01094 dns_rdatatype_t type)
01095 {
01096 unsigned char *current1, *current2;
01097 unsigned int count1, count2;
01098 dns_rdata_t rdata1 = DNS_RDATA_INIT;
01099 dns_rdata_t rdata2 = DNS_RDATA_INIT;
01100
01101 current1 = slab1 + reservelen;
01102 count1 = *current1++ * 256;
01103 count1 += *current1++;
01104
01105 current2 = slab2 + reservelen;
01106 count2 = *current2++ * 256;
01107 count2 += *current2++;
01108
01109 if (count1 != count2)
01110 return (ISC_FALSE);
01111
01112 #if DNS_RDATASET_FIXED
01113 current1 += (4 * count1);
01114 current2 += (4 * count2);
01115 #endif
01116
01117 while (count1-- > 0) {
01118 rdata_from_slab(¤t1, rdclass, type, &rdata1);
01119 rdata_from_slab(¤t2, rdclass, type, &rdata2);
01120 if (dns_rdata_compare(&rdata1, &rdata2) != 0)
01121 return (ISC_FALSE);
01122 dns_rdata_reset(&rdata1);
01123 dns_rdata_reset(&rdata2);
01124 }
01125 return (ISC_TRUE);
01126 }