From ebfcb6cf66283096ebda1503b6cc042ce86b6bed Mon Sep 17 00:00:00 2001 From: Brian Wellington Date: Thu, 9 Nov 2000 23:55:05 +0000 Subject: [PATCH] 550. [func] Support unknown rdata types and classes. --- CHANGES | 2 + bin/nsupdate/nsupdate.c | 6 +- bin/tests/rdata_test.c | 5 +- lib/dns/gen.c | 4 +- lib/dns/include/dns/rdata.h | 9 +- lib/dns/include/dns/rdataclass.h | 3 +- lib/dns/include/dns/rdatatype.h | 3 +- lib/dns/master.c | 8 +- lib/dns/rdata.c | 194 +++++++++++-------------------- lib/dns/sdb.c | 4 +- lib/dns/sec/dst/dst_api.c | 4 +- 11 files changed, 93 insertions(+), 149 deletions(-) diff --git a/CHANGES b/CHANGES index 2ba56e8682..12e3727b7b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,6 @@ + 550. [func] Support unknown rdata types and classes. + 549. [bug] "make" did not immediately abort the build when a subdirectory make failed [RT #450]. diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 8c0fa6ea44..f4e9187648 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsupdate.c,v 1.59 2000/11/08 00:55:26 bwelling Exp $ */ +/* $Id: nsupdate.c,v 1.60 2000/11/09 23:54:53 bwelling Exp $ */ #include @@ -625,8 +625,8 @@ parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass, check_result(result, "isc_buffer_allocate"); result = dns_rdata_fromtext(rdata, rdataclass, rdatatype, - lex, rn, ISC_FALSE, buf, - &callbacks); + lex, rn, ISC_FALSE, mctx, + buf, &callbacks); bufsz *= 2; isc_lex_destroy(&lex); } while (result == ISC_R_NOSPACE); diff --git a/bin/tests/rdata_test.c b/bin/tests/rdata_test.c index 47d8b1d5ec..fb631d0034 100644 --- a/bin/tests/rdata_test.c +++ b/bin/tests/rdata_test.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdata_test.c,v 1.31 2000/08/01 01:13:16 tale Exp $ */ +/* $Id: rdata_test.c,v 1.32 2000/11/09 23:54:55 bwelling Exp $ */ #include @@ -929,7 +929,8 @@ main(int argc, char *argv[]) { dns_rdata_init(&rdata); isc_buffer_init(&dbuf, inbuf, sizeof(inbuf)); result = dns_rdata_fromtext(&rdata, class, type, lex, - NULL, ISC_FALSE, &dbuf, NULL); + NULL, ISC_FALSE, mctx, &dbuf, + NULL); if (result != ISC_R_SUCCESS) { fprintf(stdout, "dns_rdata_fromtext returned %s(%d)\n", diff --git a/lib/dns/gen.c b/lib/dns/gen.c index 67ca1ec683..b478f17ebe 100644 --- a/lib/dns/gen.c +++ b/lib/dns/gen.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: gen.c,v 1.56 2000/11/09 03:03:47 bwelling Exp $ */ +/* $Id: gen.c,v 1.57 2000/11/09 23:54:56 bwelling Exp $ */ #include @@ -37,7 +37,7 @@ #define FROMTEXTARGS "rdclass, type, lexer, origin, downcase, target" #define FROMTEXTCLASS "rdclass" #define FROMTEXTTYPE "type" -#define FROMTEXTDEF "use_default = ISC_TRUE" +#define FROMTEXTDEF "result = DNS_R_UNKNOWN" #define TOTEXTARGS "rdata, tctx, target" #define TOTEXTCLASS "rdata->rdclass" diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h index 92e3bd15a2..6508b2f126 100644 --- a/lib/dns/include/dns/rdata.h +++ b/lib/dns/include/dns/rdata.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdata.h,v 1.47 2000/11/09 19:33:48 gson Exp $ */ +/* $Id: rdata.h,v 1.48 2000/11/09 23:55:01 bwelling Exp $ */ #ifndef DNS_RDATA_H #define DNS_RDATA_H 1 @@ -294,8 +294,8 @@ dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx, isc_result_t dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass, dns_rdatatype_t type, isc_lex_t *lexer, dns_name_t *origin, - isc_boolean_t downcase, isc_buffer_t *target, - dns_rdatacallbacks_t *callbacks); + isc_boolean_t downcase, isc_mem_t *mctx, + isc_buffer_t *target, dns_rdatacallbacks_t *callbacks); /* * Convert the textual representation of a DNS rdata into uncompressed wire * form stored in the target region. Tokens constituting the text of the rdata @@ -314,6 +314,8 @@ dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass, * * 'lexer' is a valid isc_lex_t. * + * 'mctx' is a valid isc_mem_t. + * * 'target' is a valid region. * * 'origin' if non NULL it must be absolute. @@ -333,6 +335,7 @@ dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass, * * Bad Form: Input too short * Resource Limit: Not enough space + * Resource Limit: Not enough memory */ isc_result_t diff --git a/lib/dns/include/dns/rdataclass.h b/lib/dns/include/dns/rdataclass.h index 04e0a99649..cfefea1a81 100644 --- a/lib/dns/include/dns/rdataclass.h +++ b/lib/dns/include/dns/rdataclass.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataclass.h,v 1.14 2000/08/01 01:24:31 tale Exp $ */ +/* $Id: rdataclass.h,v 1.15 2000/11/09 23:55:02 bwelling Exp $ */ #ifndef DNS_RDATACLASS_H #define DNS_RDATACLASS_H 1 @@ -39,7 +39,6 @@ dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source); * Returns: * ISC_R_SUCCESS on success * DNS_R_UNKNOWN class is unknown - * ISC_R_NOTIMPLEMENTED class is known, but not implemented */ isc_result_t diff --git a/lib/dns/include/dns/rdatatype.h b/lib/dns/include/dns/rdatatype.h index a3d0d0e280..f37ec3049b 100644 --- a/lib/dns/include/dns/rdatatype.h +++ b/lib/dns/include/dns/rdatatype.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdatatype.h,v 1.13 2000/08/01 01:24:37 tale Exp $ */ +/* $Id: rdatatype.h,v 1.14 2000/11/09 23:55:03 bwelling Exp $ */ #ifndef DNS_RDATATYPE_H #define DNS_RDATATYPE_H 1 @@ -39,7 +39,6 @@ dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source); * Returns: * ISC_R_SUCCESS on success * DNS_R_UNKNOWN type is unknown - * ISC_R_NOTIMPLEMENTED type is known, but not implemented */ isc_result_t diff --git a/lib/dns/master.c b/lib/dns/master.c index 35debd0d42..097e9c6415 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: master.c,v 1.78 2000/11/08 00:18:18 gson Exp $ */ +/* $Id: master.c,v 1.79 2000/11/09 23:54:57 bwelling Exp $ */ #include @@ -639,7 +639,7 @@ generate(dns_loadctx_t *ctx, char *range, char *lhs, char *gtype, char *rhs) { isc_buffer_init(&target, target_mem, target_size); result = dns_rdata_fromtext(&rdata, ctx->zclass, type, ctx->lex, ctx->origin, ISC_FALSE, - &target, callbacks); + ctx->mctx, &target, callbacks); isc_lex_close(ctx->lex); if (result != ISC_R_SUCCESS) goto error_cleanup; @@ -1295,8 +1295,8 @@ load(dns_loadctx_t **ctxp) { */ dns_rdata_init(&rdata[rdcount]); result = dns_rdata_fromtext(&rdata[rdcount], ctx->zclass, type, - ctx->lex, ctx->origin, ISC_FALSE, &target, - callbacks); + ctx->lex, ctx->origin, ISC_FALSE, ctx->mctx, + &target, callbacks); if (result != ISC_R_SUCCESS) goto insist_and_cleanup; if (type == dns_rdatatype_sig) diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index c5dd911b2b..74b51c5aed 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -15,12 +15,13 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdata.c,v 1.119 2000/11/09 00:20:47 bwelling Exp $ */ +/* $Id: rdata.c,v 1.120 2000/11/09 23:54:59 bwelling Exp $ */ #include #include #include +#include #include #include #include @@ -533,115 +534,36 @@ dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx, } isc_result_t -dns_rdata_fromtextgeneric(dns_rdata_t *rdata, dns_rdataclass_t rdclass, - dns_rdatatype_t type, isc_lex_t *lexer, - isc_buffer_t *target, - dns_rdatacallbacks_t *callbacks) +rdata_valid(isc_buffer_t *buf, dns_rdataclass_t rdclass, dns_rdatatype_t type, + isc_mem_t *mctx) { - isc_result_t result = ISC_R_NOTIMPLEMENTED; - isc_region_t region; - isc_buffer_t st; - isc_token_t token; - unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | - ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; - char *name; - unsigned long line; - void (*callback)(dns_rdatacallbacks_t *, const char *, ...); - isc_result_t iresult; + isc_buffer_t *tbuf = NULL; + dns_decompress_t dctx; + dns_rdata_t rdata; + isc_result_t result; - if (rdata != NULL) { - REQUIRE(DNS_RDATA_INITIALIZED(rdata)); - REQUIRE(DNS_RDATA_VALIDFLAGS(rdata)); + dns_decompress_init(&dctx, -1, ISC_TRUE); + dns_rdata_init(&rdata); + result = isc_buffer_allocate(mctx, &tbuf, isc_buffer_length(buf)); + if (result == ISC_R_SUCCESS) { + result = dns_rdata_fromwire(&rdata, rdclass, type, buf, &dctx, + ISC_FALSE, &tbuf); + isc_buffer_free(tbuf); } + dns_decompress_invalidate(&dctx); - st = *target; - region.base = (unsigned char *)(target->base) + target->used; - - result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, - ISC_FALSE); - if (result == ISC_R_SUCCESS && token.value.as_ulong > 65535) - result = ISC_R_RANGE; - if (result == ISC_R_SUCCESS) - result = isc_base64_tobuffer(lexer, target, - token.value.as_ulong); - - if (callbacks == NULL) - callback = NULL; - else - callback = callbacks->error; - - if (callback == NULL) - callback = default_fromtext_callback; - /* - * Consume to end of line / file. - * If not at end of line initially set error code. - * Call callback via fromtext_error once if there was an error. - */ - do { - name = isc_lex_getsourcename(lexer); - line = isc_lex_getsourceline(lexer); - iresult = isc_lex_gettoken(lexer, options, &token); - if (iresult != ISC_R_SUCCESS) { - if (result == ISC_R_SUCCESS) { - switch (iresult) { - case ISC_R_NOMEMORY: - result = ISC_R_NOMEMORY; - break; - case ISC_R_NOSPACE: - result = ISC_R_NOSPACE; - break; - default: - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_lex_gettoken() failed: %s", - isc_result_totext(result)); - result = ISC_R_UNEXPECTED; - break; - } - } - if (callback != NULL) - fromtext_error(callback, callbacks, name, - line, NULL, result); - break; - } else if (token.type != isc_tokentype_eol && - token.type != isc_tokentype_eof) { - if (result == ISC_R_SUCCESS) - result = DNS_R_EXTRATOKEN; - if (callback != NULL) { - fromtext_error(callback, callbacks, name, - line, &token, result); - callback = NULL; - } - } else if (result != ISC_R_SUCCESS && callback != NULL) { - fromtext_error(callback, callbacks, name, line, - &token, result); - break; - } else { - if (token.type == isc_tokentype_eof) - fromtext_warneof(lexer, callbacks); - break; - } - } while (1); - - if (rdata != NULL && result == ISC_R_SUCCESS) { - region.length = target->used - st.used; - dns_rdata_fromregion(rdata, rdclass, type, ®ion); - } - if (result != ISC_R_SUCCESS) { - *target = st; - } return (result); } isc_result_t dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass, dns_rdatatype_t type, isc_lex_t *lexer, - dns_name_t *origin, isc_boolean_t downcase, + dns_name_t *origin, isc_boolean_t downcase, isc_mem_t *mctx, isc_buffer_t *target, dns_rdatacallbacks_t *callbacks) { isc_result_t result = ISC_R_NOTIMPLEMENTED; isc_region_t region; isc_buffer_t st; - isc_boolean_t use_default = ISC_FALSE; isc_token_t token; unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE; @@ -659,17 +581,25 @@ dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass, st = *target; region.base = (unsigned char *)(target->base) + target->used; - FROMTEXTSWITCH - - if (use_default) { + result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, + ISC_FALSE); + if (result != ISC_R_SUCCESS) + return (result); + if (strcmp((char *)token.value.as_pointer, "\\#") == 0) { result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, ISC_FALSE); if (result == ISC_R_SUCCESS && token.value.as_ulong > 65535) result = ISC_R_RANGE; if (result == ISC_R_SUCCESS) - result = isc_base64_tobuffer(lexer, target, - token.value.as_ulong); + result = isc_hex_tobuffer(lexer, target, + token.value.as_ulong); + if (result == ISC_R_SUCCESS && dns_rdatatype_isknown(type)) + result = rdata_valid(target, rdclass, type, mctx); + } else { + isc_lex_ungettoken(lexer, &token); + + FROMTEXTSWITCH } if (callbacks == NULL) @@ -763,6 +693,8 @@ rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, TOTEXTSWITCH if (use_default) { + sprintf(buf, "\\# "); + result = str_totext(buf, target); dns_rdata_toregion(rdata, &sr); INSIST(sr.length < 65536); sprintf(buf, "%u", sr.length); @@ -773,9 +705,9 @@ rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, else result = str_totext(" ", target); if (result == ISC_R_SUCCESS) - result = isc_base64_totext(&sr, tctx->width - 2, - tctx->linebreak, - target); + result = isc_hex_totext(&sr, tctx->width - 2, + tctx->linebreak, + target); if (result == ISC_R_SUCCESS && (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) result = str_totext(" )", target); @@ -820,7 +752,7 @@ dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin, tctx.width = width; tctx.linebreak = linebreak; } else { - tctx.width = 60; /* Used for base64 word length only. */ + tctx.width = 60; /* Used for hex word length only. */ tctx.linebreak = " "; } return (rdata_totext(rdata, &tctx, target)); @@ -1009,27 +941,16 @@ dns_mnemonic_totext(unsigned int value, isc_buffer_t *target, */ isc_result_t dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source) { - unsigned int attrs; - - /* - * Note: attrs is set and then used in the bit test with RESERVED - * because testing "(flags & RESERVED) != 0" generates - * warnings on IRIX about how the test always has the same value - * because it is all constants. - */ -#define COMPARE(string, flags, type) \ +#define COMPARE(string, rdclass) \ if (((sizeof(string) - 1) == source->length) \ && (strcasecmp(source->base, string) == 0)) { \ - *classp = type; \ - attrs = flags; \ - if ((attrs & RESERVED) != 0) \ - return (ISC_R_NOTIMPLEMENTED); \ + *classp = rdclass; \ return (ISC_R_SUCCESS); \ } switch (tolower((unsigned char)source->base[0])) { case 'a': - COMPARE("any", META, dns_rdataclass_any); + COMPARE("any", dns_rdataclass_any); break; case 'c': /* @@ -1037,20 +958,30 @@ dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source) { * but historical BIND practice is to call it CHAOS. * We will accept both forms, but only generate CH. */ - COMPARE("ch", 0, dns_rdataclass_chaos); - COMPARE("chaos", 0, dns_rdataclass_chaos); + COMPARE("ch", dns_rdataclass_chaos); + COMPARE("chaos", dns_rdataclass_chaos); + if (source->length > 5 && + strncasecmp("class", source->base, 5) == 0) + { + char *endp; + int val = strtol(source->base + 5, &endp, 10); + if (*endp == '\0' && val >= 0 && val <= 0xffff) { + *classp = (dns_rdataclass_t)val; + return (ISC_R_SUCCESS); + } + } break; case 'h': - COMPARE("hs", 0, dns_rdataclass_hs); + COMPARE("hs", dns_rdataclass_hs); break; case 'i': - COMPARE("in", 0, dns_rdataclass_in); + COMPARE("in", dns_rdataclass_in); break; case 'n': - COMPARE("none", META, dns_rdataclass_none); + COMPARE("none", dns_rdataclass_none); break; case 'r': - COMPARE("reserved0", META|RESERVED, dns_rdataclass_reserved0); + COMPARE("reserved0", dns_rdataclass_reserved0); break; } @@ -1061,7 +992,7 @@ dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source) { isc_result_t dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target) { - char buf[sizeof("RDCLASS4294967296")]; + char buf[sizeof("CLASS65536")]; switch (rdclass) { case dns_rdataclass_any: @@ -1077,7 +1008,7 @@ dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target) { case dns_rdataclass_reserved0: return (str_totext("RESERVED0", target)); default: - sprintf(buf, "RDCLASS%u", rdclass); + sprintf(buf, "CLASS%u", rdclass); return (str_totext(buf, target)); } @@ -1106,12 +1037,21 @@ dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) { */ RDATATYPE_FROMTEXT_SW(hash, source->base, typep); + if (source->length > 4 && strncasecmp("type", source->base, 4) == 0) { + char *endp; + int val = strtol(source->base + 4, &endp, 10); + if (*endp == '\0' && val >= 0 && val <= 0xffff) { + *typep = (dns_rdatatype_t)val; + return (ISC_R_SUCCESS); + } + } + return (DNS_R_UNKNOWN); } isc_result_t dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) { - char buf[sizeof "TYPE4294967296"]; + char buf[sizeof "TYPE65536"]; if (type > 255) { sprintf(buf, "TYPE%u", type); diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c index b11b097d8e..46b9c0c44e 100644 --- a/lib/dns/sdb.c +++ b/lib/dns/sdb.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdb.c,v 1.12 2000/10/18 23:53:27 marka Exp $ */ +/* $Id: sdb.c,v 1.13 2000/11/09 23:55:00 bwelling Exp $ */ /* NOMINUM_PUBLIC_DELETE */ @@ -322,7 +322,7 @@ dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl, result = dns_rdata_fromtext(rdata, rdatalist->rdclass, rdatalist->type, lex, origin, ISC_FALSE, - rdatabuf, NULL); + mctx, rdatabuf, NULL); if (result != ISC_R_SUCCESS) isc_buffer_free(&rdatabuf); size *= 2; diff --git a/lib/dns/sec/dst/dst_api.c b/lib/dns/sec/dst/dst_api.c index 18094d7509..2f0519a9c2 100644 --- a/lib/dns/sec/dst/dst_api.c +++ b/lib/dns/sec/dst/dst_api.c @@ -19,7 +19,7 @@ /* * Principal Author: Brian Wellington - * $Id: dst_api.c,v 1.65 2000/11/01 00:17:17 bwelling Exp $ + * $Id: dst_api.c,v 1.66 2000/11/09 23:55:05 bwelling Exp $ */ #include @@ -929,7 +929,7 @@ read_public_key(const char *filename, isc_mem_t *mctx, dst_key_t **keyp) { isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf)); ret = dns_rdata_fromtext(&rdata, rdclass, dns_rdatatype_key, - lex, NULL, ISC_FALSE, &b, NULL); + lex, NULL, ISC_FALSE, mctx, &b, NULL); if (ret != ISC_R_SUCCESS) goto cleanup;