From 82d05588933a3c765aa8518fe455d6477d640b99 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 9 Feb 1999 08:02:21 +0000 Subject: [PATCH] Pass multiple callbacks in dns_rdatacallbacks_t. Call UNEXPECTED_ERROR() when returning DNS_R_UNEXPECTED. --- bin/tests/master_test.c | 15 +++-- bin/tests/rdata_test.c | 2 +- lib/dns/include/dns/callbacks.h | 37 +++++++++++ lib/dns/include/dns/master.h | 13 ++-- lib/dns/include/dns/rdata.h | 4 +- lib/dns/master.c | 50 ++++++-------- lib/dns/rbtdb.c | 15 +++-- lib/dns/rdata.c | 114 +++++++++++++++++++++++++++++++- 8 files changed, 202 insertions(+), 48 deletions(-) create mode 100644 lib/dns/include/dns/callbacks.h diff --git a/bin/tests/master_test.c b/bin/tests/master_test.c index 8cb79eefb1..13840c1493 100644 --- a/bin/tests/master_test.c +++ b/bin/tests/master_test.c @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -13,18 +14,19 @@ #include #include -dns_result_t print_dataset(dns_name_t *owner, dns_rdataset_t *dataset, - void *private); +dns_result_t print_dataset(dns_rdatacallbacks_t *callbacks, + dns_name_t *owner, dns_rdataset_t *dataset); isc_mem_t *mctx; dns_result_t -print_dataset(dns_name_t *owner, dns_rdataset_t *dataset, void *private) { +print_dataset(dns_rdatacallbacks_t *callbacks, dns_name_t *owner, + dns_rdataset_t *dataset) { char buf[64*1024]; isc_buffer_t target; dns_result_t result; - private = private; + callbacks = callbacks; /*unused*/ isc_buffer_init(&target, buf, 64*1024, ISC_BUFFERTYPE_TEXT); result = dns_rdataset_totext(dataset, owner, ISC_FALSE, &target); @@ -47,6 +49,7 @@ main(int argc, char *argv[]) { unsigned char name_buf[255]; int soacount = 0; int nscount = 0; + dns_rdatacallbacks_t callbacks; argc = argc; @@ -67,10 +70,12 @@ main(int argc, char *argv[]) { exit(1); } + memset(&callbacks, 0, sizeof callbacks); + callbacks.commit = print_dataset; result = dns_master_load(argv[1], &origin, &origin, 1, &soacount, &nscount, - print_dataset, NULL, mctx); + &callbacks, mctx); fprintf(stdout, "dns_master_load: %s\n", dns_result_totext(result)); if (result == DNS_R_SUCCESS) diff --git a/bin/tests/rdata_test.c b/bin/tests/rdata_test.c index 9cc174da51..da8471f218 100644 --- a/bin/tests/rdata_test.c +++ b/bin/tests/rdata_test.c @@ -188,7 +188,7 @@ main(int argc, char *argv[]) { isc_buffer_init(&dbuf, inbuf, sizeof(inbuf), ISC_BUFFERTYPE_BINARY); result = dns_rdata_fromtext(&rdata, class, type, lex, - NULL, ISC_FALSE, &dbuf); + NULL, ISC_FALSE, &dbuf, NULL); if (result != DNS_R_SUCCESS) { fprintf(stdout, "dns_rdata_fromtext returned %s(%d)\n", diff --git a/lib/dns/include/dns/callbacks.h b/lib/dns/include/dns/callbacks.h new file mode 100644 index 0000000000..52d43a5844 --- /dev/null +++ b/lib/dns/include/dns/callbacks.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef DNS_CALLBACKS_H +#define DNS_CALLBACKS_H 1 +#include +#include + +typedef struct dns_rdatacallbacks { + /* dns_load_master calls this when it has rdatasets to commit */ + dns_result_t (*commit)(struct dns_rdatacallbacks *, + dns_name_t *, dns_rdataset_t *); + /* dns_load_master / dns_rdata_fromtext call this to issue a error */ + void (*error)(struct dns_rdatacallbacks *, char *, ...); + /* dns_load_master / dns_rdata_fromtext call this to issue a warning */ + void (*warn)(struct dns_rdatacallbacks *, char *, ...); + /* private data handles for use by the above callback functions */ + void *commit_private; + void *error_private; + void *warn_private; +} dns_rdatacallbacks_t; + +#endif /* DNS_CALLBACKS_H */ diff --git a/lib/dns/include/dns/master.h b/lib/dns/include/dns/master.h index be2f401e40..4886e1052a 100644 --- a/lib/dns/include/dns/master.h +++ b/lib/dns/include/dns/master.h @@ -19,11 +19,13 @@ #define DNS_MASTER_H 1 #include +#include #include #include #include #include +#include dns_result_t dns_master_load(char *master_file, dns_name_t *top, @@ -31,10 +33,13 @@ dns_result_t dns_master_load(char *master_file, dns_rdataclass_t class, int *soacount, int *nscount, - dns_result_t (*callback)(dns_name_t *owner, - dns_rdataset_t *dataset, - void *private), - void *private, + dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx); +/* + * Requires: + * callbacks->commit to point ta a valid function. + * masterfile point to a valid string. + */ + #endif /* DNS_MASTER_H */ diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h index 9641c14fbd..33c3f36286 100644 --- a/lib/dns/include/dns/rdata.h +++ b/lib/dns/include/dns/rdata.h @@ -95,6 +95,7 @@ #include #include +#include /***** ***** RData @@ -253,7 +254,8 @@ dns_result_t dns_rdata_fromtext(dns_rdata_t *rdata, isc_lex_t *lexer, dns_name_t *origin, isc_boolean_t downcase, - isc_buffer_t *target); + 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 diff --git a/lib/dns/master.c b/lib/dns/master.c index b686f5bd39..de516ef793 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: master.c,v 1.9 1999/02/06 01:18:17 halley Exp $ */ + /* $Id: master.c,v 1.10 1999/02/09 08:02:19 marka Exp $ */ #include @@ -38,11 +38,8 @@ typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t; -static dns_result_t commit(rdatalist_head_t *, dns_name_t *, - dns_result_t (*)(dns_name_t *, - dns_rdataset_t *, - void *), - void *); +static dns_result_t commit(dns_rdatacallbacks_t *, rdatalist_head_t *, + dns_name_t *); static isc_boolean_t is_glue(rdatalist_head_t *, dns_name_t *); static dns_rdatalist_t *grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *, @@ -76,9 +73,7 @@ static dns_rdata_t *grow_rdata(int, dns_rdata_t *, int, dns_result_t dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, dns_rdataclass_t zclass, int *soacount, int *nscount, - dns_result_t (*callback)(dns_name_t *, dns_rdataset_t *, - void *private), - void *private, isc_mem_t *mctx) + dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx) { dns_rdataclass_t class; dns_rdatatype_t type; @@ -217,8 +212,7 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, zclass, soacount, nscount, - callback, - private, + callbacks, mctx); if (result != DNS_R_SUCCESS) goto cleanup; @@ -263,8 +257,7 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, zclass, soacount, nscount, - callback, - private, + callbacks, mctx); if (result != DNS_R_SUCCESS) goto cleanup; @@ -276,8 +269,8 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, */ if (in_glue && dns_name_compare(&glue_name, &new_name) != 0) { - result = commit(&glue_list, - &glue_name, callback, private); + result = commit(callbacks, &glue_list, + &glue_name); if (result != DNS_R_SUCCESS) goto cleanup; if (glue_in_use != -1) @@ -302,9 +295,9 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, glue_in_use = new_in_use; name_in_use[glue_in_use] = ISC_TRUE; } else { - result = commit(¤t_list, - ¤t_name, - callback, private); + result = commit(callbacks, + ¤t_list, + ¤t_name); if (result != DNS_R_SUCCESS) goto cleanup; rdcount = 0; @@ -432,19 +425,19 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, rdata = new_rdata; } result = dns_rdata_fromtext(&rdata[rdcount], class, type, - lex, &origin_name, ISC_FALSE, &target); + lex, &origin_name, ISC_FALSE, &target, + callbacks); if (result != DNS_R_SUCCESS) goto cleanup; ISC_LIST_PREPEND(this->rdata, &rdata[rdcount], link); rdcount++; /* We must have at least 64k as rdlen is 16 bits. */ if (target.used > (64*1024)) { - result = commit(¤t_list, ¤t_name, - callback, private); + result = commit(callbacks, ¤t_list, + ¤t_name); if (result != DNS_R_SUCCESS) goto cleanup; - result = commit(&glue_list, &glue_name, - callback, private); + result = commit(callbacks, &glue_list, &glue_name); if (result != DNS_R_SUCCESS) goto cleanup; rdcount = 0; @@ -458,10 +451,10 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, ISC_BUFFERTYPE_BINARY); } } while (!done); - result = commit(¤t_list, ¤t_name, callback, private); + result = commit(callbacks, ¤t_list, ¤t_name); if (result != DNS_R_SUCCESS) goto cleanup; - result = commit(&glue_list, &glue_name, callback, private); + result = commit(callbacks, &glue_list, &glue_name); if (result != DNS_R_SUCCESS) goto cleanup; result = DNS_R_SUCCESS; @@ -587,9 +580,8 @@ grow_rdata(int new_len, dns_rdata_t *old, int old_len, } static dns_result_t -commit(rdatalist_head_t *head, dns_name_t *owner, - dns_result_t (*callback)(dns_name_t *, dns_rdataset_t *, void *), - void *private) +commit(dns_rdatacallbacks_t *callbacks, rdatalist_head_t *head, + dns_name_t *owner) { dns_rdatalist_t *this; dns_rdataset_t dataset; @@ -599,7 +591,7 @@ commit(rdatalist_head_t *head, dns_name_t *owner, dns_rdataset_init(&dataset); dns_rdatalist_tordataset(this, &dataset); - result = ((*callback)(owner, &dataset, private)); + result = ((*callbacks->commit)(callbacks, owner, &dataset)); if (result != DNS_R_SUCCESS) return (result); ISC_LIST_UNLINK(*head, this, link); diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 911009077b..c6ed26a3f3 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -403,10 +403,10 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, } static dns_result_t -add_rdataset_callback(dns_name_t *name, dns_rdataset_t *rdataset, - void *private) +add_rdataset_callback(dns_rdatacallbacks_t *callbacks, dns_name_t *name, + dns_rdataset_t *rdataset) { - dns_rbtdb_t *rbtdb = private; + dns_rbtdb_t *rbtdb = callbacks->commit_private; dns_rbtnode_t *node = NULL; dns_result_t result; isc_region_t region; @@ -450,6 +450,7 @@ static dns_result_t load(dns_db_t *db, char *filename) { dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; int soacount, nscount; + dns_rdatacallbacks_t callbacks; REQUIRE(VALID_RBTDB(rbtdb)); @@ -465,10 +466,14 @@ load(dns_db_t *db, char *filename) { * REQUIRE(!rbtdb->loaded); */ + memset(&callbacks, 0, sizeof callbacks); + callbacks.commit = add_rdataset_callback; + callbacks.commit_private = rbtdb; + return (dns_master_load(filename, &rbtdb->common.base, &rbtdb->common.base, rbtdb->common.class, - &soacount, &nscount, add_rdataset_callback, - rbtdb, rbtdb->common.mctx)); + &soacount, &nscount, &callbacks, + rbtdb->common.mctx)); } static void diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index 3c91d60523..127018713d 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -15,16 +15,18 @@ * SOFTWARE. */ - /* $Id: rdata.c,v 1.29 1999/02/06 01:45:10 halley Exp $ */ + /* $Id: rdata.c,v 1.30 1999/02/09 08:02:20 marka Exp $ */ #include +#include #include #include #include #include #include +#include #include #include @@ -79,6 +81,16 @@ static dns_result_t time_tobuffer(char *source, isc_buffer_t *target); static dns_result_t btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target); static dns_result_t atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target); +static void default_fromtext_callback( + dns_rdatacallbacks_t *callbacks, + char *, ...); + +static void fromtext_error(void (*callback)(dns_rdatacallbacks_t *, + char *, ...), + dns_rdatacallbacks_t *callbacks, + char *name, int line, + isc_token_t *token, + dns_result_t result); static const char hexdigits[] = "0123456789abcdef"; static const char decdigits[] = "0123456789"; @@ -292,7 +304,8 @@ dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t class, dns_rdatatype_t type, isc_lex_t *lexer, dns_name_t *origin, isc_boolean_t downcase, - isc_buffer_t *target) { + isc_buffer_t *target, + dns_rdatacallbacks_t *callbacks) { dns_result_t result = DNS_R_NOTIMPLEMENTED; isc_region_t region; isc_buffer_t st; @@ -300,6 +313,9 @@ dns_rdata_fromtext(dns_rdata_t *rdata, isc_token_t token; unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE; + char *name; + int line; + void (*callback)(dns_rdatacallbacks_t *, char *, ...); st = *target; region.base = (unsigned char *)(target->base) + target->used; @@ -309,20 +325,43 @@ dns_rdata_fromtext(dns_rdata_t *rdata, if (use_default) (void)NULL; + 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); + if (gettoken(lexer, &token, isc_tokentype_string, ISC_TRUE)) if (isc_lex_gettoken(lexer, options, &token) != ISC_R_SUCCESS) { if (result == DNS_R_SUCCESS) result = DNS_R_UNEXPECTED; + 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 == DNS_R_SUCCESS) result = DNS_R_EXTRATOKEN; + if (callback != NULL) { + fromtext_error(callback, callbacks, name, + line, &token, result); + callback = NULL; + } + } else if (result != DNS_R_SUCCESS && callback != NULL) { + fromtext_error(callback, callbacks, name, line, + &token, result); + break; } else break; } while (1); @@ -756,13 +795,23 @@ gettoken(isc_lex_t *lexer, isc_token_t *token, isc_tokentype_t expect, isc_boolean_t eol) { unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE; + isc_result_t result; if (expect == isc_tokentype_qstring) options |= ISC_LEXOPT_QSTRING; if (expect == isc_tokentype_number) options |= ISC_LEXOPT_NUMBER; - if (isc_lex_gettoken(lexer, options, token) != ISC_R_SUCCESS) + switch (result = isc_lex_gettoken(lexer, options, token)) { + case ISC_R_SUCCESS: + break; + case ISC_R_NOSPACE: + return (DNS_R_NOSPACE); + default: + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_lex_gettoken() failed: %s\n", + isc_result_totext(result)); return (DNS_R_UNEXPECTED); + } if (eol && ((token->type == isc_tokentype_eol) || (token->type == isc_tokentype_eof))) return (DNS_R_SUCCESS); @@ -774,6 +823,8 @@ gettoken(isc_lex_t *lexer, isc_token_t *token, isc_tokentype_t expect, if (token->type == isc_tokentype_eol || token->type == isc_tokentype_eof) return(DNS_R_UNEXPECTEDEND); + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_lex_gettoken() returned unexpected token type\n"); return (DNS_R_UNEXPECTED); } return (DNS_R_SUCCESS); @@ -1275,3 +1326,60 @@ btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) { sprintf(buf, "x %d %x %x %x", inbuflen, Ceor, Csum, Crot); return (str_totext(buf, target)); } + + +static void +default_fromtext_callback(dns_rdatacallbacks_t *callbacks, char *fmt, ...) { + va_list ap; + + callbacks = callbacks; /*unused*/ + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static void +fromtext_error(void (*callback)(dns_rdatacallbacks_t *, char *, ...), + dns_rdatacallbacks_t *callbacks, char *name, int line, + isc_token_t *token, dns_result_t result) +{ + if (name == NULL) + name = "UNKNOWN"; + + if (token != NULL) { + switch (token->type) { + case isc_tokentype_eol: + (*callback)(callbacks, "%s: %s:%d: near eol: %s\n", + "dns_rdata_fromtext", name, line, + dns_result_totext(result)); + break; + case isc_tokentype_eof: + (*callback)(callbacks, "%s: %s:%d: near eof: %s\n", + "dns_rdata_fromtext", name, line, + dns_result_totext(result)); + break; + case isc_tokentype_number: + (*callback)(callbacks, "%s: %s:%d: near %lu: %s\n", + "dns_rdata_fromtext", name, line, + token->value.as_ulong, + dns_result_totext(result)); + break; + case isc_tokentype_string: + case isc_tokentype_qstring: + (*callback)(callbacks, "%s: %s:%d: near \"%s\": %s\n", + "dns_rdata_fromtext", name, line, + (char *)token->value.as_pointer, + dns_result_totext(result)); + break; + default: + (*callback)(callbacks, "%s: %s:%d: %s\n", + "dns_rdata_fromtext", name, line, + dns_result_totext(result)); + break; + } + } else { + (*callback)(callbacks, "dns_rdata_fromtext: %s:%d: %s\n", + name, line, dns_result_totext(result)); + } +}