From aa20b1b625dc406e1d9c3ff95d2a4af432e119fa Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 3 Mar 2004 23:43:09 +0000 Subject: [PATCH] 1570. [bug] nsupdate failed to handle classes other than IN. New keyword 'class' which sets the default class. [RT #10202] --- CHANGES | 4 +- bin/nsupdate/nsupdate.c | 77 +++++++++++++++++++++++++++++++---- bin/nsupdate/nsupdate.docbook | 38 ++++++++++++++++- 3 files changed, 110 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index e5fe1e1e5b..4834188ccf 100644 --- a/CHANGES +++ b/CHANGES @@ -40,7 +40,9 @@ 1571. [bug] rbt:hash_node() could fail leaving the hash table in an inconsistant state. [RT #10208] -1570. [placeholder] rt10202 +1570. [bug] nsupdate failed to handle classes other than IN. + New keyword 'class' which sets the default class. + [RT #10202] 1569. [placeholder] rt10236 diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 1bb3bb73cd..dac0bb7058 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.126 2004/03/03 22:57:33 marka Exp $ */ +/* $Id: nsupdate.c,v 1.127 2004/03/03 23:43:09 marka Exp $ */ #include @@ -137,6 +137,8 @@ static int requests = 0; static unsigned int timeout = 300; static unsigned int udp_timeout = 3; static unsigned int udp_retries = 3; +static dns_rdataclass_t defaultclass = dns_rdataclass_in; +static dns_rdataclass_t zoneclass = dns_rdataclass_none; typedef struct nsu_requestinfo { dns_message_t *msg; @@ -160,6 +162,23 @@ ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); #define STATUS_QUIT (isc_uint16_t)2 #define STATUS_SYNTAX (isc_uint16_t)3 +static dns_rdataclass_t +getzoneclass(void) { + if (zoneclass == dns_rdataclass_none) + zoneclass = defaultclass; + return (zoneclass); +} + +static isc_boolean_t +setzoneclass(dns_rdataclass_t rdclass) { + if (zoneclass == dns_rdataclass_none || + rdclass == dns_rdataclass_none) + zoneclass = rdclass; + if (zoneclass != rdclass) + return (ISC_FALSE); + return (ISC_TRUE); +} + static void fatal(const char *format, ...) { va_list args; @@ -772,6 +791,10 @@ make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) { region.length = strlen(word); result = dns_rdataclass_fromtext(&rdataclass, ®ion); if (result == ISC_R_SUCCESS) { + if (!setzoneclass(rdataclass)) { + fprintf(stderr, "class mismatch: %s\n", word); + goto failure; + } /* * Now read the type. */ @@ -788,7 +811,7 @@ make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) { goto failure; } } else { - rdataclass = dns_rdataclass_in; + rdataclass = getzoneclass(); result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "invalid type: %s\n", word); @@ -1051,6 +1074,39 @@ evaluate_zone(char *cmdline) { return (STATUS_MORE); } +static isc_uint16_t +evaluate_class(char *cmdline) { + char *word; + isc_textregion_t r; + isc_result_t result; + dns_rdataclass_t rdclass; + + word = nsu_strsep(&cmdline, " \t\r\n"); + if (*word == 0) { + fprintf(stderr, "could not read class name\n"); + return (STATUS_SYNTAX); + } + + r.base = word; + r.length = strlen(word); + result = dns_rdataclass_fromtext(&rdclass, &r); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "could not parse class name: %s\n", word); + return (STATUS_SYNTAX); + } + switch (rdclass) { + case dns_rdataclass_none: + case dns_rdataclass_any: + case dns_rdataclass_reserved0: + fprintf(stderr, "bad default class: %s\n", word); + return (STATUS_SYNTAX); + default: + defaultclass = rdclass; + } + + return (STATUS_MORE); +} + static isc_uint16_t update_addordelete(char *cmdline, isc_boolean_t isdelete) { isc_result_t result; @@ -1140,6 +1196,10 @@ update_addordelete(char *cmdline, isc_boolean_t isdelete) { region.length = strlen(word); result = dns_rdataclass_fromtext(&rdataclass, ®ion); if (result == ISC_R_SUCCESS) { + if (!setzoneclass(rdataclass)) { + fprintf(stderr, "class mismatch: %s\n", word); + goto failure; + } /* * Now read the type. */ @@ -1164,7 +1224,7 @@ update_addordelete(char *cmdline, isc_boolean_t isdelete) { goto failure; } } else { - rdataclass = dns_rdataclass_in; + rdataclass = getzoneclass(); result = dns_rdatatype_fromtext(&rdatatype, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "'%s' is not a valid class or type: " @@ -1307,6 +1367,8 @@ get_next_command(void) { return (evaluate_local(cmdline)); if (strcasecmp(word, "zone") == 0) return (evaluate_zone(cmdline)); + if (strcasecmp(word, "class") == 0) + return (evaluate_class(cmdline)); if (strcasecmp(word, "send") == 0) return (STATUS_SEND); if (strcasecmp(word, "show") == 0) { @@ -1441,8 +1503,7 @@ send_update(dns_name_t *zonename, isc_sockaddr_t *master, dns_name_clone(zonename, name); result = dns_message_gettemprdataset(updatemsg, &rdataset); check_result(result, "dns_message_gettemprdataset"); - dns_rdataset_makequestion(rdataset, dns_rdataclass_in, - dns_rdatatype_soa); + dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); ISC_LIST_INIT(name->list); ISC_LIST_APPEND(name->list, rdataset, link); dns_message_addname(updatemsg, name, DNS_SECTION_ZONE); @@ -1530,6 +1591,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) { sendrequest(localaddr, &servers[ns_inuse], soaquery, &request); isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); isc_event_free(&event); + setzoneclass(dns_rdataclass_none); return; } isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t)); @@ -1687,6 +1749,7 @@ recvsoa(isc_task_t *task, isc_event_t *event) { dns_request_destroy(&request); out: + setzoneclass(dns_rdataclass_none); dns_rdata_freestruct(&soa); dns_message_destroy(&rcvmsg); ddebug("Out of recvsoa"); @@ -1731,6 +1794,7 @@ start_update(void) { if (userzone != NULL && userserver != NULL) { send_update(userzone, userserver, localaddr); + setzoneclass(dns_rdataclass_none); return; } @@ -1746,8 +1810,7 @@ start_update(void) { result = dns_message_gettemprdataset(soaquery, &rdataset); check_result(result, "dns_message_gettemprdataset"); - dns_rdataset_makequestion(rdataset, dns_rdataclass_in, - dns_rdatatype_soa); + dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa); firstname = NULL; dns_message_currentname(updatemsg, DNS_SECTION_UPDATE, &firstname); diff --git a/bin/nsupdate/nsupdate.docbook b/bin/nsupdate/nsupdate.docbook index b1e5298127..676ff7afdc 100644 --- a/bin/nsupdate/nsupdate.docbook +++ b/bin/nsupdate/nsupdate.docbook @@ -16,7 +16,7 @@ - WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. --> - + @@ -265,6 +265,23 @@ statement is provided, nsupdate will attempt determine the correct zone to update based on the rest of the input. + + + + + +class +classname + + + + +Specify the default class. +If no class is specified the default class is +IN. + + + @@ -281,6 +298,8 @@ The key command overrides any key specified on the command line via or . + + @@ -293,6 +312,8 @@ overrides any key specified on the command line via Requires that no resource record of any type exists with name domain-name. + + @@ -307,6 +328,8 @@ Requires that domain-name exists (has as at least one resource record, of any type). + + @@ -326,6 +349,9 @@ and If class is omitted, IN (internet) is assumed. + + + @@ -348,6 +374,8 @@ If class is omitted, IN (internet) is assumed. + + @@ -380,6 +408,8 @@ The are written in the standard text representation of the resource record's RDATA. + + @@ -405,6 +435,8 @@ is not supplied. The ttl is ignored, and is only allowed for compatibility. + + @@ -424,6 +456,8 @@ Adds a new resource record with the specified and data. + + @@ -435,6 +469,8 @@ and Displays the current message, containing all of the prerequisites and updates specified since the last send. + +