diff --git a/bin/tests/compress_test.c b/bin/tests/compress_test.c index 1dcc24aae0..c1cd21f604 100644 --- a/bin/tests/compress_test.c +++ b/bin/tests/compress_test.c @@ -26,11 +26,13 @@ #include #include -unsigned char plain1[] = "\003foo"; -unsigned char plain2[] = "\003bar\003foo"; +unsigned char plain1[] = "\003yyy\003foo"; +unsigned char plain2[] = "\003bar\003yyy\003foo"; unsigned char plain3[] = "\003xxx\003bar\003foo"; unsigned char plain[] = - "\003foo\0\003bar\003foo\0\003bar\003foo\0\003xxx\003bar\003foo"; + "\003yyy\003foo\0\003bar\003yyy\003foo\0\003bar\003yyy\003foo\0\003xxx\003bar\003foo"; + +/* result concatenate (plain1, plain2, plain2, plain3) */ unsigned char bit1[] = "\101\010b"; unsigned char bit2[] = "\101\014b\260"; @@ -50,13 +52,9 @@ main(int argc, char *argv[]) { dns_name_t name3; isc_region_t region; int c; - int bitstrings = 0; - while ((c = getopt(argc, argv, "brv")) != -1) { + while ((c = getopt(argc, argv, "rv")) != -1) { switch (c) { - case 'b': - bitstrings++; - break; case 'r': raw++; break; @@ -103,12 +101,6 @@ main(int argc, char *argv[]) { region.length = sizeof bit3; dns_name_fromregion(&name3, ®ion); - if (bitstrings == 0) { - fprintf(stdout, "Bit string tests not performed."); - fprintf(stdout, " Awaiting RBT support\n"); - exit (0); - } - test(DNS_COMPRESS_NONE, &name1, &name2, &name3, bit, sizeof bit); test(DNS_COMPRESS_GLOBAL14, &name1, &name2, &name3, bit, sizeof bit); test(DNS_COMPRESS_GLOBAL, &name1, &name2, &name3, bit, sizeof bit); @@ -207,6 +199,7 @@ test(unsigned int allowed, dns_name_t *name1, dns_name_t *name2, fputs(" ", stdout); } fputs("\n", stdout); + fflush(stdout); } RUNTIME_CHECK(target.used == length); diff --git a/lib/dns/compress.c b/lib/dns/compress.c index 8a02f7b97b..3a0312408a 100644 --- a/lib/dns/compress.c +++ b/lib/dns/compress.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: compress.c,v 1.12 1999/04/14 17:40:22 halley Exp $ */ + /* $Id: compress.c,v 1.13 1999/04/28 03:03:55 marka Exp $ */ #include #include @@ -42,6 +42,12 @@ void compress_add(dns_rbt_t *root, dns_name_t *prefix, dns_name_t *suffix, isc_uint16_t offset, isc_boolean_t global16, isc_mem_t *mctx); +#undef MPADRC +#ifdef MPADRC +isc_buffer_t x; +char xxxx[1024]; +#endif + /*** *** Compression ***/ @@ -87,7 +93,6 @@ dns_compress_localinit(dns_compress_t *cctx, dns_name_t *owner, isc_buffer_t t; isc_region_t region; - REQUIRE(VALID_CCTX(cctx)); REQUIRE(cctx->local == NULL); REQUIRE(dns_name_isabsolute(owner) == ISC_TRUE); @@ -124,6 +129,16 @@ dns_compress_localinit(dns_compress_t *cctx, dns_name_t *owner, if (data == NULL) return (DNS_R_SUCCESS); *data = ll; + +#ifdef MPADRC + isc_buffer_init(&x, xxxx, sizeof xxxx, + ISC_BUFFERTYPE_TEXT); + dns_name_totext(&name, ISC_FALSE, &x); + fprintf(stdout, + "dns_rbt_addname(local, \"%.*s\", %d)\n", + (int)x.used, (char*)x.base, *data); +#endif + result = dns_rbt_addname(cctx->local, &name, data); if (result != DNS_R_SUCCESS) { isc_mem_put(cctx->mctx, data, sizeof *data); @@ -151,11 +166,11 @@ dns_compress_localinit(dns_compress_t *cctx, dns_name_t *owner, * Adding 'bits' to 'll' may exceed the maximum logical * offset index. Throw away bits until ll <= 254. */ - ll += bits; + ll += bits - 1; while (ll > 254 && bits > 0) { /* clear bit */ - buf[2 + bits / 8] &= ~(1 << (7 - (bits % 8))); bits--; + buf[2 + bits / 8] &= ~(1 << (7 - (bits % 8))); ll--; } /* @@ -175,14 +190,25 @@ dns_compress_localinit(dns_compress_t *cctx, dns_name_t *owner, if (data == NULL) return (DNS_R_SUCCESS); *data = ll; + +#ifdef MPADRC + isc_buffer_init(&x, xxxx, sizeof xxxx, + ISC_BUFFERTYPE_TEXT); + dns_name_totext(&name, ISC_FALSE, &x); + fprintf(stdout, + "dns_rbt_addname(local, \"%.*s\", %d)\n", + (int)x.used, (char *)x.base, + *data); +#endif + result = dns_rbt_addname(cctx->local, &name, data); if (result != DNS_R_SUCCESS) { isc_mem_put(cctx->mctx, data, sizeof *data); return (DNS_R_SUCCESS); } /* clear bit */ - buf[2 + bits / 8] &= ~(1 << (7 - (bits % 8))); bits--; + buf[2 + bits / 8] &= ~(1 << (7 - (bits % 8))); ll--; } while (bits > 0); wl++; @@ -249,6 +275,15 @@ dns_compress_findglobal(dns_compress_t *cctx, dns_name_t *name, REQUIRE(dns_name_isabsolute(name) == ISC_TRUE); REQUIRE(offset != NULL); + +#ifdef MPADRC + isc_buffer_init(&x, xxxx, sizeof xxxx, + ISC_BUFFERTYPE_TEXT); + dns_name_totext(name, ISC_FALSE, &x); + fprintf(stdout, "compress_find(global, name \"%.*s\", ...)\n", + (int)x.used, (char*)x.base); +#endif + return (compress_find(cctx->global, name, prefix, suffix, offset, workspace)); } @@ -264,6 +299,16 @@ dns_compress_findlocal(dns_compress_t *cctx, dns_name_t *name, if (cctx->local == NULL) return (ISC_FALSE); + +#ifdef MPADRC + isc_buffer_init(&x, xxxx, sizeof xxxx, + ISC_BUFFERTYPE_TEXT); + dns_name_totext(name, ISC_FALSE, &x); + fprintf(stdout, "compress_find(local, name \"%.*s\", ...)\n", + (int)x.used, (char*)x.base); +#endif + + return (compress_find(cctx->local, name, prefix, suffix, offset, workspace)); } @@ -279,12 +324,19 @@ dns_compress_add(dns_compress_t *cctx, dns_name_t *prefix, if (cctx->local != NULL && (cctx->allowed & DNS_COMPRESS_LOCAL) != 0) { REQUIRE(cctx->rdata <= offset); localoffset = offset - cctx->rdata + 256; +#ifdef MPADRC + fprintf(stdout, "compress_add(local, ...)\n"); +#endif compress_add(cctx->local, prefix, suffix, localoffset, ISC_TRUE, cctx->mctx); } - if ((cctx->edns > -1) || !local) + if ((cctx->edns > -1) || !local) { +#ifdef MPADRC + fprintf(stdout, "compress_add(global, ...)\n"); +#endif compress_add(cctx->global, prefix, suffix, offset, cctx->global16, cctx->mctx); + } } void @@ -424,6 +476,16 @@ compress_add(dns_rbt_t *root, dns_name_t *prefix, dns_name_t *suffix, if (data == NULL) return; *data = offset; + +#ifdef MPADRC + isc_buffer_init(&x, xxxx, sizeof xxxx, + ISC_BUFFERTYPE_TEXT); + dns_name_totext(&full, ISC_FALSE, &x); + fprintf(stdout, + "dns_rbt_addname(root, \"%.*s\", %d)\n", + (int)x.used, (char*)x.base, *data); +#endif + result = dns_rbt_addname(root, &full, data); if (result != DNS_R_SUCCESS) { isc_mem_put(mctx, data, sizeof *data); @@ -474,10 +536,19 @@ compress_find(dns_rbt_t *root, dns_name_t *name, dns_name_t *prefix, return (ISC_FALSE); if (data == NULL) /* root label */ return (ISC_FALSE); + +#ifdef MPADRC + isc_buffer_init(&x, xxxx, sizeof xxxx, + ISC_BUFFERTYPE_TEXT); + dns_name_totext(foundname, ISC_FALSE, &x); + fprintf(stdout, "foundname \"%.*s\" %d\n", + (int)x.used, (char*)x.base, *data); +#endif + /* * Do we have to do bit string processing? */ - dns_name_getlabel(dns_fixedname_name(&found), 0, &foundlabel); + dns_name_getlabel(foundname, 0, &foundlabel); foundlabels = dns_name_countlabels(foundname); INSIST(foundlabels > 1); /* root labels are not added to tree */ namelabels = dns_name_countlabels(name); @@ -499,6 +570,24 @@ compress_find(dns_rbt_t *root, dns_name_t *name, dns_name_t *prefix, dns_name_getlabelsequence(name, 0, prefixlen, prefix); dns_name_getlabelsequence(foundname, 0, foundlabels, suffix); *offset = *data; + +#ifdef MPADRC + if (prefixlen != 0) { + isc_buffer_init(&x, xxxx, sizeof xxxx, + ISC_BUFFERTYPE_TEXT); + dns_name_totext(prefix, ISC_FALSE, &x); + fprintf(stdout, "prefix \"%.*s\"\n", + (int)x.used, (char*)x.base); + } else + fprintf(stdout, "prefix \n"); + + isc_buffer_init(&x, xxxx, sizeof xxxx, + ISC_BUFFERTYPE_TEXT); + dns_name_totext(suffix, ISC_FALSE, &x); + fprintf(stdout, "suffix \"%.*s\"\n", + (int)x.used, (char*)x.base); +#endif + return (ISC_TRUE); } /* XXX MPA needs to be tested */ @@ -525,7 +614,6 @@ compress_find(dns_rbt_t *root, dns_name_t *name, dns_name_t *prefix, */ while (j < bits) { bit = dns_label_getbit(&namelabel, foundbits + j); - j++; if (bit) buf[2 + j / 8] |= (1 << (7 - (j % 8))); j++; @@ -533,12 +621,27 @@ compress_find(dns_rbt_t *root, dns_name_t *name, dns_name_t *prefix, buf[0] = DNS_LABELTYPE_BITSTRING; buf[1] = j; region.base = buf; - region.length = 2 + j / 8; + region.length = 2 + (j + 7) / 8; dns_name_fromregion(&tmpsuffix, ®ion); result = dns_name_concatenate(&tmpprefix, &tmpsuffix, prefix, workspace); if (result != DNS_R_SUCCESS) return (ISC_FALSE); *offset = *data; + +#ifdef MPADRC + isc_buffer_init(&x, xxxx, sizeof xxxx, + ISC_BUFFERTYPE_TEXT); + dns_name_totext(prefix, ISC_FALSE, &x); + fprintf(stdout, "prefix \"%.*s\"\n", + (int)x.used, (char*)x.base); + + isc_buffer_init(&x, xxxx, sizeof xxxx, + ISC_BUFFERTYPE_TEXT); + dns_name_totext(suffix, ISC_FALSE, &x); + fprintf(stdout, "suffix \"%.*s\"\n", + (int)x.used, (char*)x.base); +#endif + return (ISC_TRUE); } diff --git a/lib/dns/name.c b/lib/dns/name.c index d896810dbf..3d0bf60333 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -33,6 +33,8 @@ #define NAME_MAGIC 0x444E536EU /* DNSn. */ #define VALID_NAME(n) ((n) != NULL && \ (n)->magic == NAME_MAGIC) +isc_buffer_t x; +char xxxx[1024]; typedef enum { ft_init = 0, @@ -806,6 +808,8 @@ void dns_name_fromregion(dns_name_t *name, isc_region_t *r) { unsigned char *offsets; dns_offsets_t odata; + unsigned int len; + isc_region_t r2; /* * Make 'name' refer to region 'r'. @@ -813,13 +817,23 @@ dns_name_fromregion(dns_name_t *name, isc_region_t *r) { REQUIRE(VALID_NAME(name)); REQUIRE(r != NULL); - REQUIRE(r->length <= 255); REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0); INIT_OFFSETS(name, offsets, odata); - name->ndata = r->base; - name->length = r->length; + if (name->buffer != NULL) { + isc_buffer_clear(name->buffer); + isc_buffer_available(name->buffer, &r2); + len = (r->length < r2.length) ? r->length : r2.length; + if (len > 255) + len = 255; + memcpy(r2.base, r->base, len); + name->ndata = r2.base; + name->length = len; + } else { + name->ndata = r->base; + name->length = (r->length <= 255) ? r->length : 255; + } if (r->length > 0) set_offsets(name, offsets, ISC_TRUE, ISC_TRUE, ISC_TRUE); @@ -827,6 +841,9 @@ dns_name_fromregion(dns_name_t *name, isc_region_t *r) { name->labels = 0; name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; } + + if (name->buffer != NULL) + isc_buffer_add(name->buffer, name->length); } void @@ -1921,9 +1938,9 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, ll = 0; /* * Work down owner label from TLD until we - * have found 'new_current' logical labels. + * have found 'new_current + 1' logical labels. */ - while (i < lcount && ll < new_current) { + while (i <= lcount && ll <= new_current) { dns_name_getlabel(&dctx->owner_name, lcount - i - 1, &label); @@ -1934,7 +1951,6 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, ll++; continue; } - /* XXX MPA test */ INSIST(labeltype == dns_labeltype_bitstring); bits = dns_label_countbits(&label); @@ -1949,30 +1965,38 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, */ break; } - if (i == lcount) + if (i > lcount) return (DNS_R_BADPOINTER); - bits = new_current - ll; - if (bits != 0) { - /* XXX MPA test */ + if (ll <= new_current) { + dns_name_getlabel(&dctx->owner_name, + lcount - i - 1, + &label); + bits = new_current + 1 - ll; if (nrem < 2 + (bits + 7) / 8) return (DNS_R_NOSPACE); *ndata++ = DNS_LABELTYPE_BITSTRING; *ndata++ = bits; - ndata[bits/8] = 0; - while (bits) { + /* + * Zero all bits of last octet of + * label. + */ + ndata[(bits - 1) / 8] = 0; + do { + bits--; bit = dns_label_getbit(&label, bits); set_bit(ndata, bits, bit); - bits--; - } - ndata += (new_current - ll + 7) / 8; + } while (bits != 0); labels++; - i++; + bits = new_current + 1 - ll; + ndata += (bits + 7) / 8; + nused += (bits + 7) / 8 + 2; + nrem -= (bits + 7) / 8 - 2; } dns_name_init(&suffix, NULL); dns_name_getlabelsequence(&dctx->owner_name, - lcount - i - 1, - i + 2, &suffix); + lcount - i, + i + 1, &suffix); if (suffix.length > nrem) return (DNS_R_NOSPACE); memcpy(ndata, suffix.ndata, suffix.length); @@ -2074,9 +2098,20 @@ dns_name_towire(dns_name_t *name, dns_compress_t *cctx, else lf = ISC_FALSE; - /* find the best compression */ + /* + * Will the compression pointer reduce the message size? + */ + if (lf && (lp.length + ((lo < 16384) ? 2 : 3)) >= name->length) + lf = ISC_FALSE; + if (gf && (gp.length + ((go < 16384) ? 2 : 3)) >= name->length) + gf = ISC_FALSE; + + /* + * + */ if (lf && gf) { - if (lp.length < gp.length) + if ((lp.length + ((lo < 16384) ? 2 : 3)) < + (gp.length + ((go < 16384) ? 2 : 3))) gf = ISC_FALSE; else lf = ISC_FALSE; @@ -2517,12 +2552,13 @@ dns_name_split(dns_name_t *name, /* * XXX DCL better way to decide memcpy vs memmove? */ - if (len > 0) + if (len > 0) { if ((dst <= src && dst + len > src) || (src <= dst && src + len > dst)) memmove(dst, src, len); else memcpy(dst, src, len); + } suffix->buffer->used = suffix->length; suffix->ndata = suffix->buffer->base;