diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 52253e97c8..fb5cf0e583 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dig.c,v 1.110 2000/10/03 04:29:08 marka Exp $ */ +/* $Id: dig.c,v 1.111 2000/10/11 17:44:00 mws Exp $ */ #include #include @@ -828,10 +828,33 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto invalid_option; } break; - case 'v': /* vc */ - if (!is_batchfile) - lookup->tcp_mode = state; + case 'v': +#ifdef DNS_OPT_NEWCODES + switch (tolower(cmd[1])) { + default: + case 'c': /* vc, and default */ +#endif /* DNS_OPT_NEWCODES */ + if (!is_batchfile) + lookup->tcp_mode = state; + break; +#ifdef DNS_OPT_NEWCODES + case 'i': /* view */ + if (value == NULL) + goto need_value; + if (!state) + goto invalid_option; + strncpy(lookup->viewname, value, MXNAME); + break; + } break; + case 'z': /* zone */ + if (value == NULL) + goto need_value; + if (!state) + goto invalid_option; + strncpy(lookup->zonename, value, MXNAME); + break; +#endif default: invalid_option: need_value: @@ -1287,8 +1310,6 @@ main(int argc, char **argv) { (dig_server_t *)s2, link); isc_mem_free(mctx, s2); } - if (isc_mem_debugging != 0) - isc_mem_stats(mctx, stderr); isc_mem_free(mctx, default_lookup); if (batchname != NULL) { if (batchfp != stdin) diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 5625d989b5..4d552771ff 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dighost.c,v 1.141 2000/10/04 17:14:43 mws Exp $ */ +/* $Id: dighost.c,v 1.142 2000/10/11 17:44:01 mws Exp $ */ /* * Notice to programmers: Do not use this code as an example of how to @@ -36,8 +36,10 @@ extern int h_errno; #endif +#include #include #include +#include #include #include #include @@ -46,6 +48,7 @@ extern int h_errno; #include #include #include + #include #include @@ -317,6 +320,10 @@ make_empty_lookup(void) { looknew->section_authority = ISC_TRUE; looknew->section_additional = ISC_TRUE; looknew->new_search = ISC_FALSE; +#ifdef DNS_OPT_NEWCODES + looknew->zonename[0] = 0; + looknew->viewname[0] = 0; +#endif ISC_LIST_INIT(looknew->q); ISC_LIST_INIT(looknew->my_server_list); return (looknew); @@ -364,6 +371,10 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { looknew->section_authority = lookold->section_authority; looknew->section_additional = lookold->section_additional; looknew->retries = lookold->retries; +#ifdef DNS_OPT_NEWCODES + strncpy(looknew->viewname, lookold-> viewname, MXNAME); + strncpy(looknew->zonename, lookold-> zonename, MXNAME); +#endif /* DNS_OPT_NEWCODES */ if (servers) clone_server_list(lookold->my_server_list, @@ -698,11 +709,18 @@ setup_libs(void) { * option is UDP buffer size. */ static void -add_opt(dns_message_t *msg, isc_uint16_t udpsize) { +add_opt(dns_message_t *msg, isc_uint16_t udpsize, dns_optlist_t optlist) { dns_rdataset_t *rdataset = NULL; dns_rdatalist_t *rdatalist = NULL; dns_rdata_t *rdata = NULL; isc_result_t result; +#ifdef DNS_OPT_NEWCODES + isc_buffer_t *rdatabuf = NULL; + unsigned int i, optsize = 0; +#else /* DNS_OPT_NEWCODES */ + + UNUSED(optlist); +#endif /* DNS_OPT_NEWCODES */ debug("add_opt()"); result = dns_message_gettemprdataset(msg, &rdataset); @@ -720,6 +738,15 @@ add_opt(dns_message_t *msg, isc_uint16_t udpsize) { rdatalist->ttl = 0; rdata->data = NULL; rdata->length = 0; +#ifdef DNS_OPT_NEWCODES + for (i=0; irdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); dns_rdatalist_tordataset(rdatalist, rdataset); @@ -1320,8 +1347,66 @@ setup_lookup(dig_lookup_t *lookup) { isc_buffer_init(&lookup->sendbuf, lookup->sendspace, COMMSIZE); result = dns_message_renderbegin(lookup->sendmsg, &lookup->sendbuf); check_result(result, "dns_message_renderbegin"); - if (lookup->udpsize > 0) - add_opt(lookup->sendmsg, lookup->udpsize); +#ifndef DNS_OPT_NEWCODES + if (lookup->udpsize > 0) { +#else /* DNS_OPT_NEWCODES */ + if (lookup->udpsize > 0 || lookup->zonename[0] !=0 || + lookup->viewname[0] != 0) { + dns_fixedname_t fname; + isc_buffer_t namebuf, *wirebuf = NULL; + dns_compress_t cctx; +#endif /* DNS_OPT_NEWCODES */ + dns_optlist_t optlist; + dns_optattr_t optattr[2]; + + if (lookup->udpsize == 0) + lookup->udpsize = 2048; + optlist.size = 2; + optlist.used = 0; + optlist.next = 0; + optlist.attrs = optattr; + +#ifdef DNS_OPT_NEWCODES + if (lookup->zonename[0] != 0) { + optattr[optlist.used].code = DNS_OPTCODE_ZONE; + dns_fixedname_init(&fname); + isc_buffer_init(&namebuf, lookup->zonename, + strlen(lookup->zonename)); + isc_buffer_add(&namebuf, strlen(lookup->zonename)); + result = dns_name_fromtext(&(fname.name), &namebuf, + dns_rootname, ISC_FALSE, + NULL); + check_result(result, "; illegal zone option"); + result = dns_compress_init(&cctx, 0, mctx); + check_result(result, "dns_compress_init"); + result = isc_buffer_allocate(mctx, &wirebuf, + MXNAME); + check_result(result, "isc_buffer_allocate"); + result = dns_name_towire(&(fname.name), &cctx, + wirebuf); + check_result(result, "dns_name_towire"); + optattr[optlist.used].value.base = + isc_buffer_base(wirebuf); + optattr[optlist.used].value.length = + isc_buffer_usedlength(wirebuf); + optlist.used++; + dns_compress_invalidate(&cctx); + } + if (lookup->viewname[0] != 0) { + optattr[optlist.used].code = DNS_OPTCODE_VIEW; + optattr[optlist.used].value.base = + lookup->viewname; + optattr[optlist.used].value.length = + strlen(lookup->viewname); + optlist.used++; + } +#endif /* DNS_OPT_NEWCODES */ + add_opt(lookup->sendmsg, lookup->udpsize, optlist); +#ifdef DNS_OPT_NEWCODES + if (wirebuf != NULL) + isc_buffer_free(&wirebuf); +#endif /* DNS_OPT_NEWCODES */ + } result = dns_message_rendersection(lookup->sendmsg, DNS_SECTION_QUESTION, 0); diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index 2e8860627a..a7ac8a1d63 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dig.h,v 1.51 2000/09/29 23:42:15 mws Exp $ */ +/* $Id: dig.h,v 1.52 2000/10/11 17:44:03 mws Exp $ */ #ifndef DIG_H #define DIG_H @@ -123,6 +123,10 @@ struct dig_lookup { isc_uint32_t ixfr_serial; isc_buffer_t rdatabuf; char rdatastore[MXNAME]; +#ifdef DNS_OPT_NEWCODES + char zonename[MXNAME]; + char viewname[MXNAME]; +#endif /* DNS_OPT_NEWCODES */ dst_context_t *tsigctx; isc_buffer_t *querysig; isc_uint32_t msgcounter; diff --git a/bin/named/client.c b/bin/named/client.c index e052aa2362..1b054633de 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.117 2000/10/06 18:58:29 bwelling Exp $ */ +/* $Id: client.c,v 1.118 2000/10/11 17:44:04 mws Exp $ */ #include @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -238,6 +239,15 @@ client_free(ns_client_t *client) { dns_rdataset_disassociate(client->opt); dns_message_puttemprdataset(client->message, &client->opt); } +#ifdef DNS_OPT_NEWCODES + if (client->opt_zone != NULL) { + isc_mem_put(client->mctx, client->opt_zone, + sizeof(*client->opt_zone)); + client->opt_zone = NULL; + } + if (client->opt_view != NULL) + isc_buffer_free(&client->opt_view); +#endif /* DNS_OPT_NEWCODES */ dns_message_destroy(&client->message); if (client->task != NULL) isc_task_detach(&client->task); @@ -888,6 +898,75 @@ ns_client_error(ns_client_t *client, isc_result_t result) { ns_client_send(client); } +#ifdef DNS_OPT_NEWCODES +static isc_result_t +client_addoptattrs(ns_client_t *client, dns_rdata_t *rdata) { + isc_result_t result; + isc_buffer_t *zonebuf = NULL, *buf = NULL; + dns_optlist_t attrlist; + dns_optattr_t attrs[CLIENT_NUMATTRS]; + dns_compress_t cctx; + int i, sizeneeded = 0; + + result = dns_compress_init(&cctx, 0, client->mctx); + if (result != ISC_R_SUCCESS) + goto fail1; + dns_compress_setmethods(&cctx, DNS_COMPRESS_NONE); + attrlist.size=2; + attrlist.used=0; + attrlist.attrs=attrs; + for (i=0; iopt_zone != NULL) { + result = isc_buffer_allocate(client->mctx, &zonebuf, + DNS_NAME_MAXWIRE); + if (result != ISC_R_SUCCESS) + goto fail2; + result = dns_name_towire(dns_fixedname_name(client->opt_zone), + &cctx, zonebuf); + if (result != ISC_R_SUCCESS) + goto fail2; + attrs[attrlist.used].code = DNS_OPTCODE_ZONE; + attrs[attrlist.used].value.base = isc_buffer_base(zonebuf); + attrs[attrlist.used].value.length = + isc_buffer_usedlength(zonebuf); + attrlist.used++; + sizeneeded += 4 + isc_buffer_usedlength(zonebuf); + } + if (client->opt_view != NULL) { + attrs[attrlist.used].code = DNS_OPTCODE_VIEW; + attrs[attrlist.used].value.base = + isc_buffer_base(client->opt_view); + attrs[attrlist.used].value.length = + isc_buffer_usedlength(client->opt_view); + attrlist.used++; + sizeneeded += 4 + isc_buffer_usedlength(client->opt_view); + } + if (sizeneeded == 0) { + result = ISC_R_SUCCESS; + goto fail2; + } + result = isc_buffer_allocate(client->mctx, &buf, sizeneeded+1); + if (result != ISC_R_SUCCESS) + goto fail2; + result = dns_opt_add(rdata, &attrlist, buf); + if (result != ISC_R_SUCCESS) + goto fail2; + dns_message_takebuffer(client->message, &buf); + fail2: + dns_compress_invalidate(&cctx); + fail1: + if (buf != NULL) + isc_buffer_free(&buf); + if (zonebuf != NULL) + isc_buffer_free(&zonebuf); + return (result); +} +#endif /* DNS_OPT_NEWCODES */ + static inline isc_result_t client_addopt(ns_client_t *client) { dns_rdataset_t *rdataset; @@ -925,13 +1004,20 @@ client_addopt(ns_client_t *client) { rdatalist->ttl = 0; /* - * No ENDS options. + * No ENDS options in the default case. */ rdata->data = NULL; rdata->length = 0; rdata->rdclass = rdatalist->rdclass; rdata->type = rdatalist->type; +#ifdef DNS_OPT_NEWCODES + /* + * Set the attributes + */ + client_addoptattrs(client, rdata); +#endif /* DNS_OPT_NEWCODES */ + ISC_LIST_INIT(rdatalist->rdata); ISC_LIST_APPEND(rdatalist->rdata, rdata, link); dns_rdatalist_tordataset(rdatalist, rdataset); @@ -941,6 +1027,81 @@ client_addopt(ns_client_t *client) { return (ISC_R_SUCCESS); } +#ifdef DNS_OPT_NEWCODES +static void +client_getoptattrs(ns_client_t *client, dns_rdataset_t *opt) { + dns_optlist_t optlist; + dns_optattr_t optattr; + isc_result_t result, iresult; + isc_buffer_t zonebuf; + dns_decompress_t dctx; + + /* If an old set of opts are still around, free them. */ + if (client->opt_zone != NULL) { + isc_mem_put(client->mctx, client->opt_zone, + sizeof(*client->opt_zone)); + client->opt_zone = NULL; + } + if (client->opt_view != NULL) + isc_buffer_free(&client->opt_view); + + /* + * If there are any options, extract them here + */ + optlist.size = 1; + optlist.used = 0; + optlist.next = 0; + optlist.attrs = &optattr; + do { + result = dns_opt_decodeall(&optlist, opt); + if (result == ISC_R_SUCCESS || + result == DNS_R_MOREDATA) { + switch (optattr.code) { + case DNS_OPTCODE_ZONE: + dns_decompress_init(&dctx, 0, + ISC_FALSE); + client->opt_zone = isc_mem_get( + client->mctx, + sizeof(*client->opt_zone)); + if (client->opt_zone == NULL) + goto zonefail1; + dns_fixedname_init(client->opt_zone); + isc_buffer_init(&zonebuf, + optattr.value.base, + optattr.value.length); + isc_buffer_add(&zonebuf,optattr.value.length); + isc_buffer_setactive(&zonebuf, + optattr.value.length); + iresult = dns_name_fromwire( + dns_fixedname_name( + client->opt_zone), + &zonebuf, + &dctx, ISC_FALSE, + NULL); + if (iresult != ISC_R_SUCCESS) { + dns_fixedname_invalidate( + client->opt_zone); + zonefail1: + dns_decompress_invalidate(&dctx); + } + break; + case DNS_OPTCODE_VIEW: + iresult = isc_buffer_allocate(client->mctx, + &client->opt_view, + optattr.value.length); + if (iresult != ISC_R_SUCCESS) + break; + isc_buffer_putmem(client->opt_view, + optattr.value.base, + optattr.value.length); + break; + } + } + } while (result == DNS_R_MOREDATA); +} +#endif /* DNS_OPT_NEWCODES */ + + /* * Handle an incoming request event from the dispatch (UDP case) * or tcpmsg (TCP case). @@ -1060,6 +1221,19 @@ client_request(isc_task_t *task, isc_event_t *event) { * Set the client's UDP buffer size. */ client->udpsize = opt->rdclass; + +#ifdef DNS_OPT_NEWCODES + /* + * Set up the rest of the opt stuff + */ + client_getoptattrs(client, opt); + /* + * If we're using a fixed zone option (opt_zone), set it to + * allow glue here. + */ + if (client->opt_zone != NULL) + client->query.dboptions |= DNS_DBFIND_GLUEOK; +#endif /* DNS_OPT_NEWCODES */ /* * Create an OPT for our reply. @@ -1342,6 +1516,10 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) client->tcpbuf = NULL; client->opt = NULL; client->udpsize = 512; +#ifdef DNS_OPT_NEWCODES + client->opt_zone = NULL; + client->opt_view = NULL; +#endif DNS_OPT_NEWCODES client->next = NULL; client->shutdown = NULL; client->shutdown_arg = NULL; diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index 9fdc508ff2..51b78a6669 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.h,v 1.43 2000/09/13 01:33:26 marka Exp $ */ +/* $Id: client.h,v 1.44 2000/10/11 17:44:07 mws Exp $ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 @@ -69,6 +69,10 @@ #include #include #include +#ifdef DNS_OPT_NEWCODES +#include +#include +#endif /* DNS_OPT_NEWCODES */ #include #include @@ -107,6 +111,10 @@ struct ns_client { unsigned char * sendbuf; dns_rdataset_t * opt; isc_uint16_t udpsize; +#ifdef DNS_OPT_NEWCODES + dns_fixedname_t * opt_zone; + isc_buffer_t * opt_view; +#endif /* DNS_OPT_NEWCODES */ void (*next)(ns_client_t *); void (*shutdown)(void *arg, isc_result_t result); void *shutdown_arg; @@ -130,6 +138,14 @@ struct ns_client { client_list_t *list; }; +#ifdef DNS_OPT_NEWCODES +/* + * Number of attr fields (opt_zone, opt_view) in above structure. Used in + * client_addoptattrs() + */ +#define CLIENT_NUMATTRS 2 +#endif /* DNS_OPT_NEWCODES */ + #define NS_CLIENT_MAGIC 0x4E534363U /* NSCc */ #define NS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, NS_CLIENT_MAGIC) diff --git a/bin/named/query.c b/bin/named/query.c index fce56c0e97..cd326327b5 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.c,v 1.134 2000/10/07 00:09:16 bwelling Exp $ */ +/* $Id: query.c,v 1.135 2000/10/11 17:44:05 mws Exp $ */ #include @@ -690,6 +690,25 @@ query_getdb(ns_client_t *client, dns_name_t *name, unsigned int options, { isc_result_t result; +#ifdef DNS_OPT_NEWCODES + if (client->opt_zone != NULL) { + result = query_getzonedb(client, &(client->opt_zone->name), + options, zonep, dbp, versionp); + if (result == ISC_R_SUCCESS) + *is_zonep = ISC_TRUE; + else + result = DNS_R_REFUSED; + } else { + result = query_getzonedb(client, name, options, zonep, dbp, + versionp); + if (result == ISC_R_SUCCESS) { + *is_zonep = ISC_TRUE; + } else if (result == ISC_R_NOTFOUND) { + result = query_getcachedb(client, dbp, options); + *is_zonep = ISC_FALSE; + } + } +#else /* DNS_OPT_NEWCODES */ result = query_getzonedb(client, name, options, zonep, dbp, versionp); if (result == ISC_R_SUCCESS) { *is_zonep = ISC_TRUE; @@ -697,7 +716,7 @@ query_getdb(ns_client_t *client, dns_name_t *name, unsigned int options, result = query_getcachedb(client, dbp, options); *is_zonep = ISC_FALSE; } - +#endif /* DNS_OPT_NEWCODES */ return (result); } @@ -2175,7 +2194,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { if (result == DNS_R_REFUSED) QUERY_ERROR(DNS_R_REFUSED); else - QUERY_ERROR(DNS_R_SERVFAIL); + QUERY_ERROR(DNS_R_SERVFAIL); goto cleanup; } @@ -2324,6 +2343,11 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { */ break; case DNS_R_GLUE: +#ifdef DNS_OPT_NEWCODES + if (client->opt_zone != NULL) + break; + /* Fallthrough if we don't have opt_zone */ +#endif DNS_OPT_NEWCODES case DNS_R_ZONECUT: /* * These cases are handled in the main line below. @@ -2332,6 +2356,13 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { authoritative = ISC_FALSE; break; case ISC_R_NOTFOUND: +#ifdef DNS_OPT_NEWCODES + /* + * If we've passed in opt_zone, don't try anything more. + */ + if (client->opt_zone != NULL) + break; +#endif /* DNS_OPT_NEWCODES */ /* * The cache doesn't even have the root NS. Get them from * the hints DB. @@ -2357,6 +2388,14 @@ query_find(ns_client_t *client, dns_fetchevent_t *event) { */ /* FALLTHROUGH */ case DNS_R_DELEGATION: +#ifdef DNS_OPT_NEWCODES + /* + * If we've passed in opt_zone, don't try anything more. + */ + if (client->opt_zone != NULL) { + break; + } +#endif /* DNS_OPT_NEWCODES */ authoritative = ISC_FALSE; if (is_zone) { /* diff --git a/doc/todo/mws/todo b/doc/todo/mws/todo index 8832e8b092..de054dc249 100644 --- a/doc/todo/mws/todo +++ b/doc/todo/mws/todo @@ -31,3 +31,24 @@ Fix wpk's build/tests scripts to - not run if the previous test failed (to keep logs and cores around) - display the date and time of the last run + +Big todo list for dig, from code walkthrough with Brian: + strncpy -> isc_mem_strdup + oname in setup_lookup can be on the stack instead of allocated + Move INSIST in insert_lookup up + Fix -b option in UDP mode (make sure server and bind address are + compatible) + Use symbolic names for exit codes + l->retries-- can be moved out of if/else + +tcp/vc no longer needs to be prohibited in batchfiles + digrc filename print length shouldn't be 132 + bargc should be more than 14 + Split up launch_next_query + 0 should be dns_rcode_noerror + How is data in additional section printer in *XFR + What happens if additional data is after the end of an *XFR + Legality of serial 0 + query point in clear_query should be ** + Opcode 100 spelled wrong in host.c + atoi -> strtol + warning for bufsize and others out of bounds diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index c648234fb9..acb63575e5 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -13,7 +13,7 @@ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# $Id: Makefile.in,v 1.107 2000/10/06 17:08:11 bwelling Exp $ +# $Id: Makefile.in,v 1.108 2000/10/11 17:44:09 mws Exp $ srcdir = @srcdir@ VPATH = @srcdir@ @@ -98,7 +98,7 @@ OBJS = a6.@O@ acl.@O@ aclconf.@O@ adb.@O@ byaddr.@O@ \ db.@O@ dbiterator.@O@ dbtable.@O@ dispatch.@O@ dnssec.@O@ \ forward.@O@ journal.@O@ keytable.@O@ lib.@O@ log.@O@ \ master.@O@ masterdump.@O@ message.@O@ \ - name.@O@ ncache.@O@ nxt.@O@ peer.@O@ \ + name.@O@ ncache.@O@ nxt.@O@ opt.@O@ peer.@O@ \ rbt.@O@ rbtdb.@O@ rbtdb64.@O@ rdata.@O@ rdatalist.@O@ \ rdataset.@O@ rdatasetiter.@O@ rdataslab.@O@ request.@O@ \ resolver.@O@ result.@O@ rootns.@O@ ssu.@O@ \ @@ -119,7 +119,7 @@ SRCS = a6.c acl.c aclconf.c adb.c byaddr.c \ db.c dbiterator.c dbtable.c dispatch.c dnssec.c \ forward.c journal.c keytable.c lib.c log.c \ master.c masterdump.c message.c \ - name.c ncache.c nxt.c peer.c \ + name.c ncache.c nxt.c opt.c peer.c \ rbt.c rbtdb.c rbtdb64.c rdata.c rdatalist.c \ rdataset.c rdatasetiter.c rdataslab.c request.c \ resolver.c result.c rootns.c ssu.c \ diff --git a/lib/dns/include/dns/fixedname.h b/lib/dns/include/dns/fixedname.h index 4b9e0ae921..a7e668ffa0 100644 --- a/lib/dns/include/dns/fixedname.h +++ b/lib/dns/include/dns/fixedname.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: fixedname.h,v 1.10 2000/08/01 01:24:11 tale Exp $ */ +/* $Id: fixedname.h,v 1.11 2000/10/11 17:44:16 mws Exp $ */ #ifndef DNS_FIXEDNAME_H #define DNS_FIXEDNAME_H 1 @@ -64,13 +64,14 @@ struct dns_fixedname { dns_name_t name; dns_offsets_t offsets; isc_buffer_t buffer; - unsigned char data[255]; + unsigned char data[DNS_NAME_MAXWIRE]; }; #define dns_fixedname_init(fn) \ do { \ dns_name_init(&((fn)->name), (fn)->offsets); \ - isc_buffer_init(&((fn)->buffer), (fn)->data, 255); \ + isc_buffer_init(&((fn)->buffer), (fn)->data, \ + DNS_NAME_MAXWIRE); \ dns_name_setbuffer(&((fn)->name), &((fn)->buffer)); \ } while (0) diff --git a/lib/dns/include/dns/name.h b/lib/dns/include/dns/name.h index c6b9d89387..f35a982b2b 100644 --- a/lib/dns/include/dns/name.h +++ b/lib/dns/include/dns/name.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: name.h,v 1.80 2000/08/08 23:20:14 gson Exp $ */ +/* $Id: name.h,v 1.81 2000/10/11 17:44:17 mws Exp $ */ #ifndef DNS_NAME_H #define DNS_NAME_H 1 @@ -214,6 +214,11 @@ struct dns_name { extern dns_name_t *dns_rootname; extern dns_name_t *dns_wildcardname; +/* + * Standard size of a wire format name + */ +#define DNS_NAME_MAXWIRE 255 + /*** *** Initialization ***/ diff --git a/lib/dns/include/dns/opt.h b/lib/dns/include/dns/opt.h new file mode 100644 index 0000000000..3c35875242 --- /dev/null +++ b/lib/dns/include/dns/opt.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +/* $Id: opt.h,v 1.1 2000/10/11 17:44:18 mws Exp $ */ + +#ifndef DNS_OPT_H +#define DNS_OPT_H 1 + +#include +#include +#include +#include +#include + +#include +#include + +/* + * XXX WARNING XXX These codes have not yet been assigned by IANA. + * These are here as placekeepers ONLY. + * Hide these definitions and anything that uses them behind a #define + * which happens only in internal debugging code. + * This #ifdef will go away once these are defined by IANA. + */ +#ifdef DNS_OPT_NEWCODES +#define DNS_OPTCODE_ZONE 0xfff0 +#define DNS_OPTCODE_VIEW 0xfff1 +#endif /* DNS_OPT_NEWCODES */ + +/* + * OPT records contain a series of attributes which contain different types. + * These structures are used for holding the individual attribute + * records. + */ +typedef struct dns_optattr { + isc_uint16_t code; + isc_region_t value; +} dns_optattr_t; + +typedef struct dns_optlist { + unsigned int size; + unsigned int used; + unsigned int next; + dns_optattr_t *attrs; +} dns_optlist_t; + +isc_result_t +dns_opt_decode(dns_optlist_t *optlist, dns_rdataset_t *optset, + isc_uint16_t code); + +isc_result_t +dns_opt_decodeall(dns_optlist_t *optlist, dns_rdataset_t *optset); + +isc_result_t +dns_opt_add(dns_rdata_t *rdata, dns_optlist_t *optlist, + isc_buffer_t *target); + +isc_result_t +dns_opt_attrtotext(dns_optattr_t *attr, isc_buffer_t *target, + dns_messagetextflag_t flags); + +isc_result_t +dns_opt_totext(dns_rdataset_t *opt, isc_buffer_t *target, + dns_messagetextflag_t flags); + +ISC_LANG_ENDDECLS + +#endif /* DNS_OPT_H */ diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h index 23899286c8..fc746ba775 100644 --- a/lib/dns/include/dns/result.h +++ b/lib/dns/include/dns/result.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.h,v 1.66 2000/10/06 18:58:26 bwelling Exp $ */ +/* $Id: result.h,v 1.67 2000/10/11 17:44:18 mws Exp $ */ #ifndef DNS_RESULT_H #define DNS_RESULT_H 1 @@ -100,8 +100,9 @@ #define DNS_R_NOTINSECURE (ISC_RESULTCLASS_DNS + 61) #define DNS_R_ZONETOOLARGE (ISC_RESULTCLASS_DNS + 62) #define DNS_R_RECOVERABLE (ISC_RESULTCLASS_DNS + 63) +#define DNS_R_UNKNOWNOPT (ISC_RESULTCLASS_DNS + 64) -#define DNS_R_NRESULTS 64 /* Number of results */ +#define DNS_R_NRESULTS 65 /* Number of results */ /* * DNS wire format rcodes. diff --git a/lib/dns/message.c b/lib/dns/message.c index 3e012013d3..ee75d33f47 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: message.c,v 1.149 2000/10/07 00:09:21 bwelling Exp $ */ +/* $Id: message.c,v 1.150 2000/10/11 17:44:10 mws Exp $ */ /*** *** Imports @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -2781,7 +2782,6 @@ dns_message_pseudosectiontotext(dns_message_t *msg, dns_rdataset_t *ps = NULL; dns_name_t *name = NULL; isc_result_t result; - char buf[sizeof("1234567890")]; isc_boolean_t omit_final_dot; REQUIRE(DNS_MESSAGE_VALID(msg)); @@ -2795,18 +2795,8 @@ dns_message_pseudosectiontotext(dns_message_t *msg, ps = dns_message_getopt(msg); if (ps == NULL) return (ISC_R_SUCCESS); - if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) - ADD_STRING(target, ";; OPT PSEUDOSECTION:\n"); - ADD_STRING(target, "; EDNS: version: "); - sprintf(buf, "%4u", - (unsigned int)((ps->ttl & - 0x00ff0000 >> 16))); - ADD_STRING(target, buf); - ADD_STRING(target, ", udp="); - sprintf(buf, "%7u\n", - (unsigned int)ps->rdclass); - ADD_STRING(target, buf); - return (ISC_R_SUCCESS); + result = dns_opt_totext(ps, target, flags); + return (result); case DNS_PSEUDOSECTION_TSIG: ps = dns_message_gettsig(msg, &name); if (ps == NULL) diff --git a/lib/dns/name.c b/lib/dns/name.c index 7ae60e3296..1e449b9ae0 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: name.c,v 1.103 2000/08/22 00:46:54 gson Exp $ */ +/* $Id: name.c,v 1.104 2000/10/11 17:44:12 mws Exp $ */ #include @@ -1070,14 +1070,15 @@ dns_name_fromregion(dns_name_t *name, isc_region_t *r) { isc_buffer_clear(name->buffer); isc_buffer_availableregion(name->buffer, &r2); len = (r->length < r2.length) ? r->length : r2.length; - if (len > 255) - len = 255; + if (len > DNS_NAME_MAXWIRE) + len = DNS_NAME_MAXWIRE; 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; + name->length = (r->length <= DNS_NAME_MAXWIRE) ? + r->length : DNS_NAME_MAXWIRE; } if (r->length > 0) @@ -2232,8 +2233,8 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, * maximum legal domain name length (255). */ nmax = isc_buffer_availablelength(target); - if (nmax > 255) - nmax = 255; + if (nmax > DNS_NAME_MAXWIRE) + nmax = DNS_NAME_MAXWIRE; cdata = isc_buffer_current(source); cused = 0; @@ -2372,7 +2373,7 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, return (ISC_R_SUCCESS); full: - if (nmax == 255) + if (nmax == DNS_NAME_MAXWIRE) /* * The name did not fit even though we had a buffer * big enough to fit a maximum-length name. @@ -2531,8 +2532,8 @@ dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name, */ nrem = target->length - target->used; ndata = (unsigned char *)target->base + target->used; - if (nrem > 255) - nrem = 255; + if (nrem > DNS_NAME_MAXWIRE) + nrem = DNS_NAME_MAXWIRE; length = 0; prefix_length = 0; labels = 0; @@ -2545,7 +2546,7 @@ dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name, length += suffix->length; labels += suffix->labels; } - if (length > 255) { + if (length > DNS_NAME_MAXWIRE) { MAKE_EMPTY(name); return (DNS_R_NAMETOOLONG); } diff --git a/lib/dns/opt.c b/lib/dns/opt.c new file mode 100644 index 0000000000..eb5eb8a42a --- /dev/null +++ b/lib/dns/opt.c @@ -0,0 +1,254 @@ +/* + * Copyright (C) 1999, 2000 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. + */ + +/* $Id: opt.c,v 1.1 2000/10/11 17:44:13 mws Exp $ */ + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADD_STRING(b, s, g) {if (strlen(s) >= \ + isc_buffer_availablelength(b)) \ + { result = ISC_R_NOSPACE; \ + goto g; } else \ + isc_buffer_putstr(b, s);} +static isc_result_t +optget(dns_optlist_t *optlist, dns_rdataset_t *optset, + isc_uint16_t code, isc_boolean_t getall) +{ + isc_result_t result; + dns_rdata_t rdata; + unsigned int location; + isc_region_t rdataregion; + isc_buffer_t rdatabuf; + isc_uint16_t thiscode, thislength; + + REQUIRE(DNS_RDATASET_VALID(optset)); + REQUIRE(optset->type == dns_rdatatype_opt); + + result = dns_rdataset_first(optset); + if (result != ISC_R_SUCCESS) + return(result); + dns_rdataset_current(optset, &rdata); + + dns_rdata_toregion(&rdata, &rdataregion); + isc_buffer_init(&rdatabuf, rdataregion.base, rdataregion.length); + isc_buffer_add(&rdatabuf, rdataregion.length); + + optlist->used = 0; + location = 0; + /* + * We don't do the test in the while loop, since I want to + * actually keep searching the list for more data until I reach + * the first one I *can't* fit in. This way, I can correctly + * decide between MOREDATA and SUCCESS. + */ + while (1) { + if (isc_buffer_remaininglength(&rdatabuf) == 0) { + optlist->next = 0; + return (ISC_R_SUCCESS); + } + if (isc_buffer_remaininglength(&rdatabuf) < 4) + return (ISC_R_UNEXPECTEDEND); + thiscode = isc_buffer_getuint16(&rdatabuf); + thislength = isc_buffer_getuint16(&rdatabuf); + if (isc_buffer_remaininglength(&rdatabuf) < thislength) + return (ISC_R_UNEXPECTEDEND); + if ((thiscode == code || getall) && + (location >= optlist->next)) { + if (optlist->used >= optlist->size) { + optlist->next = location; + return(DNS_R_MOREDATA); + } + optlist->attrs[optlist->used].code = thiscode; + optlist->attrs[optlist->used].value.base = + isc_buffer_current(&rdatabuf); + optlist->attrs[optlist->used].value.length = + thislength; + optlist->used++; + } + isc_buffer_forward(&rdatabuf, thislength); + location++; + } + /* This location can never be reached. */ +} + +isc_result_t +dns_opt_decode(dns_optlist_t *optlist, dns_rdataset_t *optset, + isc_uint16_t code) +{ + return (optget(optlist, optset, code, ISC_FALSE)); +} + +isc_result_t +dns_opt_decodeall(dns_optlist_t *optlist, dns_rdataset_t *optset) { + return (optget(optlist, optset, 0, ISC_TRUE)); +} + +isc_result_t +dns_opt_add(dns_rdata_t *rdata, dns_optlist_t *optlist, + isc_buffer_t *target) +{ + char *base; + unsigned int i; + + REQUIRE(rdata->length == 0); + + base = isc_buffer_current(target); + if (optlist != NULL) { + for (i = 0; i < optlist->used; i++) { + rdata->length += optlist->attrs[i].value.length; + rdata->length += 4; + } + if (isc_buffer_availablelength(target) < rdata->length) { + rdata->length = 0; + return (ISC_R_NOSPACE); + } + for (i = 0; i < optlist->used; i++) { + isc_buffer_putuint16(target, optlist->attrs[i].code); + isc_buffer_putuint16(target, + optlist->attrs[i].value.length); + isc_buffer_putmem(target, + optlist->attrs[i].value.base, + optlist->attrs[i].value.length); + } + rdata->data = base; + } + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_opt_attrtotext(dns_optattr_t *attr, isc_buffer_t *target, + dns_messagetextflag_t flags) { + isc_result_t result = ISC_R_SUCCESS; + char store[sizeof("012345678")]; + isc_boolean_t omit_final_dot; +#ifdef DNS_OPT_NEWCODES + dns_decompress_t dctx; + dns_fixedname_t fname; + isc_buffer_t source; + +#else /* DNS_OPT_NEWCODES */ + UNUSED (flags); +#endif /* DNS_OPT_NEWCODES */ + + omit_final_dot = ISC_TF((flags & DNS_MESSAGETEXTFLAG_OMITDOT) != 0); + switch (attr->code) { +#ifdef DNS_OPT_NEWCODES + case DNS_OPTCODE_ZONE: + ADD_STRING(target, "; ZONE attribute: ", zonefail0); + dns_fixedname_init(&fname); + dns_decompress_init(&dctx, 0, ISC_FALSE); + isc_buffer_init(&source, attr->value.base, attr->value.length); + isc_buffer_add(&source, attr->value.length); + isc_buffer_setactive(&source, attr->value.length); + result = dns_name_fromwire(&fname.name, &source, &dctx, + ISC_FALSE, NULL); + if (result != ISC_R_SUCCESS) + goto zonefail1; + result = dns_name_totext(&fname.name, omit_final_dot, + target); + ADD_STRING(target, "\n", zonefail1); + zonefail1: + dns_decompress_invalidate(&dctx); + dns_fixedname_invalidate(&fname); + zonefail0: + return (result); + case DNS_OPTCODE_VIEW: + ADD_STRING(target, "; VIEW attribute: ", viewfail0); + if (attr->value.length >= isc_buffer_availablelength(target)) + return(ISC_R_NOSPACE); + else + isc_buffer_putmem(target, attr->value.base, + attr->value.length); + ADD_STRING(target, "\n", viewfail0); + viewfail0: + return (result); +#endif /* DNS_OPT_NEWCODES */ + /* + * This routine is a placekeeper, awaiting assignment of + * OPT attribute values from IANA. + */ + default: + ADD_STRING(target, "; Unknown EDNS attribute ", deffail); + sprintf(store,"%d",attr->code); + ADD_STRING(target, store, deffail); + ADD_STRING(target, "\n", deffail); + result = DNS_R_UNKNOWNOPT; + deffail: + return (result); + } +} + +isc_result_t +dns_opt_totext(dns_rdataset_t *opt, isc_buffer_t *target, + dns_messagetextflag_t flags) { + isc_result_t result, iresult; + char buf[sizeof("1234567890")]; + isc_boolean_t omit_final_dot; + dns_optattr_t attr; + dns_optlist_t list; + + REQUIRE(DNS_RDATASET_VALID(opt)); + REQUIRE(target != NULL); + + omit_final_dot = ISC_TF((flags & DNS_MESSAGETEXTFLAG_OMITDOT) != 0); + + if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) + ADD_STRING(target, ";; OPT PSEUDOSECTION:\n", fail); + ADD_STRING(target, "; EDNS: version: ", fail); + sprintf(buf, "%4u", + (unsigned int)((opt->ttl & + 0x00ff0000 >> 16))); + ADD_STRING(target, buf, fail); + ADD_STRING(target, ", udp=", fail); + sprintf(buf, "%7u\n", + (unsigned int)opt->rdclass); + ADD_STRING(target, buf, fail); + + list.attrs = &attr; + list.size = 1; + list.used = 0; + list.next = 0; + do { + result = dns_opt_decodeall(&list, opt); + if ((result == ISC_R_SUCCESS || result == DNS_R_MOREDATA) + && list.used != 0) { + iresult = dns_opt_attrtotext(list.attrs, target, + flags); + if (iresult != ISC_R_SUCCESS && + iresult != DNS_R_UNKNOWNOPT) + result = iresult; + } + } while (result == DNS_R_MOREDATA); + fail: + return (result); +} diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index 9198612ae9..bab214c42b 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataset.c,v 1.49 2000/08/11 16:47:32 gson Exp $ */ +/* $Id: rdataset.c,v 1.50 2000/10/11 17:44:13 mws Exp $ */ #include @@ -466,3 +466,4 @@ dns_rdataset_additionaldata(dns_rdataset_t *rdataset, return (ISC_R_SUCCESS); } + diff --git a/lib/dns/result.c b/lib/dns/result.c index 272006a899..07cd4269b3 100644 --- a/lib/dns/result.c +++ b/lib/dns/result.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.c,v 1.72 2000/10/06 18:58:20 bwelling Exp $ */ +/* $Id: result.c,v 1.73 2000/10/11 17:44:14 mws Exp $ */ #include @@ -102,6 +102,7 @@ static const char *text[DNS_R_NRESULTS] = { "not insecure", /* 61 DNS_R_NOTINSECURE */ "zone too large", /* 62 DNS_R_ZONETOOLARGE */ "recoverable error occurred" /* 63 DNS_R_RECOVERABLE */ + "unknown opt attribute record" /* 64 DNS_R_UNKNOWNOPT */ }; static const char *rcode_text[DNS_R_NRCODERESULTS] = {