diff --git a/CHANGES b/CHANGES index b7b7377131..c8c4fb4513 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4256. [bug] Allow rndc command arguments to be quoted so as + to allow spaces. [RT #36665] + 4255. [func] Add 'message-compression' option to disable DNS compression in responses. [RT #40726] diff --git a/bin/named/control.c b/bin/named/control.c index aaf9dd42ea..ca6c0f2b7b 100644 --- a/bin/named/control.c +++ b/bin/named/control.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include #include +#include #include #include #include @@ -43,15 +45,30 @@ #include #endif -static isc_boolean_t -command_compare(const char *text, const char *command) { - unsigned int commandlen = strlen(command); - if (strncasecmp(text, command, commandlen) == 0 && - (text[commandlen] == '\0' || - text[commandlen] == ' ' || - text[commandlen] == '\t')) - return (ISC_TRUE); - return (ISC_FALSE); +static isc_result_t +getcommand(isc_lex_t *lex, char **cmdp) { + isc_result_t result; + isc_token_t token; + + REQUIRE(cmdp != NULL && *cmdp == NULL); + + result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF, &token); + if (result != ISC_R_SUCCESS) + return (result); + + isc_lex_ungettoken(lex, &token); + + if (token.type != isc_tokentype_string) + return (ISC_R_FAILURE); + + *cmdp = token.value.as_textregion.base; + + return (ISC_R_SUCCESS); +} + +static inline isc_boolean_t +command_compare(const char *str, const char *command) { + return ISC_TF(strcasecmp(str, command) == 0); } /*% @@ -61,9 +78,12 @@ command_compare(const char *text, const char *command) { isc_result_t ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) { isccc_sexpr_t *data; + char *cmdline = NULL; char *command = NULL; isc_result_t result; int log_level; + isc_buffer_t src; + isc_lex_t *lex = NULL; #ifdef HAVE_LIBSCF ns_smf_want_disable = 0; #endif @@ -76,7 +96,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) { return (ISC_R_FAILURE); } - result = isccc_cc_lookupstring(data, "type", &command); + result = isccc_cc_lookupstring(data, "type", &cmdline); if (result != ISC_R_SUCCESS) { /* * We have no idea what this is. @@ -84,6 +104,20 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) { return (result); } + result = isc_lex_create(ns_g_mctx, strlen(cmdline), &lex); + if (result != ISC_R_SUCCESS) + return (result); + + isc_buffer_init(&src, cmdline, strlen(cmdline)); + isc_buffer_add(&src, strlen(cmdline)); + result = isc_lex_openbuffer(lex, &src); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = getcommand(lex, &command); + if (result != ISC_R_SUCCESS) + goto cleanup; + /* * Compare the 'command' parameter against all known control commands. */ @@ -93,20 +127,21 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) { } else { log_level = ISC_LOG_INFO; } + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, log_level, "received control channel command '%s'", command); if (command_compare(command, NS_COMMAND_RELOAD)) { - result = ns_server_reloadcommand(ns_g_server, command, text); + result = ns_server_reloadcommand(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_RECONFIG)) { result = ns_server_reconfigcommand(ns_g_server); } else if (command_compare(command, NS_COMMAND_REFRESH)) { - result = ns_server_refreshcommand(ns_g_server, command, text); + result = ns_server_refreshcommand(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_RETRANSFER)) { result = ns_server_retransfercommand(ns_g_server, - command, text); + lex, text); } else if (command_compare(command, NS_COMMAND_HALT)) { #ifdef HAVE_LIBSCF /* @@ -116,7 +151,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) { */ if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) { result = ns_smf_add_message(text); - return (result); + goto cleanup; } /* * If we are managed by smf(5) but not in chroot, @@ -143,7 +178,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) { #ifdef HAVE_LIBSCF if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) { result = ns_smf_add_message(text); - return (result); + goto cleanup; } if (ns_smf_got_instance == 1 && ns_smf_chroot == 0) ns_smf_want_disable = 1; @@ -155,42 +190,42 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) { } else if (command_compare(command, NS_COMMAND_DUMPSTATS)) { result = ns_server_dumpstats(ns_g_server); } else if (command_compare(command, NS_COMMAND_QUERYLOG)) { - result = ns_server_togglequerylog(ns_g_server, command); + result = ns_server_togglequerylog(ns_g_server, lex); } else if (command_compare(command, NS_COMMAND_DUMPDB)) { - ns_server_dumpdb(ns_g_server, command); + ns_server_dumpdb(ns_g_server, lex); result = ISC_R_SUCCESS; } else if (command_compare(command, NS_COMMAND_SECROOTS)) { - result = ns_server_dumpsecroots(ns_g_server, command, text); + result = ns_server_dumpsecroots(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_TRACE)) { - result = ns_server_setdebuglevel(ns_g_server, command); + result = ns_server_setdebuglevel(ns_g_server, lex); } else if (command_compare(command, NS_COMMAND_NOTRACE)) { ns_g_debuglevel = 0; isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel); result = ISC_R_SUCCESS; } else if (command_compare(command, NS_COMMAND_FLUSH)) { - result = ns_server_flushcache(ns_g_server, command); + result = ns_server_flushcache(ns_g_server, lex); } else if (command_compare(command, NS_COMMAND_FLUSHNAME)) { - result = ns_server_flushnode(ns_g_server, command, ISC_FALSE); + result = ns_server_flushnode(ns_g_server, lex, ISC_FALSE); } else if (command_compare(command, NS_COMMAND_FLUSHTREE)) { - result = ns_server_flushnode(ns_g_server, command, ISC_TRUE); + result = ns_server_flushnode(ns_g_server, lex, ISC_TRUE); } else if (command_compare(command, NS_COMMAND_STATUS)) { result = ns_server_status(ns_g_server, text); } else if (command_compare(command, NS_COMMAND_TSIGLIST)) { result = ns_server_tsiglist(ns_g_server, text); } else if (command_compare(command, NS_COMMAND_TSIGDELETE)) { - result = ns_server_tsigdelete(ns_g_server, command, text); + result = ns_server_tsigdelete(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_FREEZE)) { - result = ns_server_freeze(ns_g_server, ISC_TRUE, command, + result = ns_server_freeze(ns_g_server, ISC_TRUE, lex, text); } else if (command_compare(command, NS_COMMAND_UNFREEZE) || command_compare(command, NS_COMMAND_THAW)) { - result = ns_server_freeze(ns_g_server, ISC_FALSE, command, + result = ns_server_freeze(ns_g_server, ISC_FALSE, lex, text); } else if (command_compare(command, NS_COMMAND_SCAN)) { result = ISC_R_SUCCESS; ns_server_scan_interfaces(ns_g_server); } else if (command_compare(command, NS_COMMAND_SYNC)) { - result = ns_server_sync(ns_g_server, command, text); + result = ns_server_sync(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_RECURSING)) { result = ns_server_dumprecursing(ns_g_server); } else if (command_compare(command, NS_COMMAND_TIMERPOKE)) { @@ -199,29 +234,29 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) { } else if (command_compare(command, NS_COMMAND_NULL)) { result = ISC_R_SUCCESS; } else if (command_compare(command, NS_COMMAND_NOTIFY)) { - result = ns_server_notifycommand(ns_g_server, command, text); + result = ns_server_notifycommand(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_VALIDATION)) { - result = ns_server_validation(ns_g_server, command, text); + result = ns_server_validation(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_SIGN) || command_compare(command, NS_COMMAND_LOADKEYS)) { - result = ns_server_rekey(ns_g_server, command, text); + result = ns_server_rekey(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_ADDZONE) || command_compare(command, NS_COMMAND_MODZONE)) { - result = ns_server_changezone(ns_g_server, command, text); + result = ns_server_changezone(ns_g_server, cmdline, text); } else if (command_compare(command, NS_COMMAND_DELZONE)) { - result = ns_server_delzone(ns_g_server, command, text); + result = ns_server_delzone(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_SHOWZONE)) { - result = ns_server_showzone(ns_g_server, command, text); + result = ns_server_showzone(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_SIGNING)) { - result = ns_server_signing(ns_g_server, command, text); + result = ns_server_signing(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_ZONESTATUS)) { - result = ns_server_zonestatus(ns_g_server, command, text); + result = ns_server_zonestatus(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_NTA)) { - result = ns_server_nta(ns_g_server, command, text); + result = ns_server_nta(ns_g_server, lex, text); } else if (command_compare(command, NS_COMMAND_TESTGEN)) { - result = ns_server_testgen(command, text); + result = ns_server_testgen(lex, text); } else if (command_compare(command, NS_COMMAND_MKEYS)) { - result = ns_server_mkeys(ns_g_server, command, text); + result = ns_server_mkeys(ns_g_server, lex, text); } else { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, @@ -230,5 +265,9 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) { result = DNS_R_UNKNOWNCOMMAND; } + cleanup: + if (lex != NULL) + isc_lex_destroy(&lex); + return (result); } diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index e1d354ddbb..d6b220a99c 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -534,7 +534,8 @@ ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush); */ isc_result_t -ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_reloadcommand(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); /*%< * Act on a "reload" command from the command channel. */ @@ -546,26 +547,28 @@ ns_server_reconfigcommand(ns_server_t *server); */ isc_result_t -ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_notifycommand(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); /*%< * Act on a "notify" command from the command channel. */ isc_result_t -ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_refreshcommand(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); /*%< * Act on a "refresh" command from the command channel. */ isc_result_t -ns_server_retransfercommand(ns_server_t *server, char *args, +ns_server_retransfercommand(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*%< * Act on a "retransfer" command from the command channel. */ isc_result_t -ns_server_togglequerylog(ns_server_t *server, char *args); +ns_server_togglequerylog(ns_server_t *server, isc_lex_t *lex); /*%< * Enable/disable logging of queries. (Takes "yes" or "no" argument, * but can also be used as a toggle for backward comptibility.) @@ -593,25 +596,26 @@ ns_server_dumpstats(ns_server_t *server); * Dump the current cache to the dump file. */ isc_result_t -ns_server_dumpdb(ns_server_t *server, char *args); +ns_server_dumpdb(ns_server_t *server, isc_lex_t *lex); /*% * Dump the current security roots to the secroots file. */ isc_result_t -ns_server_dumpsecroots(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_dumpsecroots(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); /*% * Change or increment the server debug level. */ isc_result_t -ns_server_setdebuglevel(ns_server_t *server, char *args); +ns_server_setdebuglevel(ns_server_t *server, isc_lex_t *lex); /*% * Flush the server's cache(s) */ isc_result_t -ns_server_flushcache(ns_server_t *server, char *args); +ns_server_flushcache(ns_server_t *server, isc_lex_t *lex); /*% * Flush a particular name from the server's cache. If 'tree' is false, @@ -619,7 +623,8 @@ ns_server_flushcache(ns_server_t *server, char *args); * flush all the names under the specified name. */ isc_result_t -ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree); +ns_server_flushnode(ns_server_t *server, isc_lex_t *lex, + isc_boolean_t tree); /*% * Report the server's status. @@ -637,20 +642,21 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t **text); * Delete a specific key (with optional view). */ isc_result_t -ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t **text); +ns_server_tsigdelete(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text); /*% * Enable or disable updates for a zone. */ isc_result_t -ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, - isc_buffer_t **text); +ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, + isc_lex_t *lex, isc_buffer_t **text); /*% * Dump zone updates to disk, optionally removing the journal file */ isc_result_t -ns_server_sync(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_sync(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Update a zone's DNSKEY set from the key repository. If @@ -660,7 +666,7 @@ ns_server_sync(ns_server_t *server, char *args, isc_buffer_t **text); * take place incrementally. */ isc_result_t -ns_server_rekey(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_rekey(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Dump the current recursive queries. @@ -678,57 +684,57 @@ ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr); * Enable or disable dnssec validation. */ isc_result_t -ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_validation(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Add a zone to a running process, or modify an existing zone */ isc_result_t -ns_server_changezone(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_changezone(ns_server_t *server, char *command, isc_buffer_t **text); /*% * Deletes a zone from a running process */ isc_result_t -ns_server_delzone(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_delzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Show current configuration for a given zone */ isc_result_t -ns_server_showzone(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_showzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Lists the status of the signing records for a given zone. */ isc_result_t -ns_server_signing(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_signing(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Lists status information for a given zone (e.g., name, type, files, * load time, expiry, etc). */ isc_result_t -ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_zonestatus(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Adds a Negative Trust Anchor (NTA) for a specified name and * duration, in a particular view if specified, or in all views. */ isc_result_t -ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_nta(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); /*% * Generates a test sequence that is only for use in system tests. The * argument is the size of required output in bytes. */ isc_result_t -ns_server_testgen(char *args, isc_buffer_t **text); +ns_server_testgen(isc_lex_t *lex, isc_buffer_t **text); /*% * Force fefresh or print status for managed keys zones. */ isc_result_t -ns_server_mkeys(ns_server_t *server, char *args, isc_buffer_t **text); +ns_server_mkeys(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text); #endif /* NAMED_SERVER_H */ diff --git a/bin/named/server.c b/bin/named/server.c index 0e88fef90d..e850db8855 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -7620,34 +7620,71 @@ ns_server_scan_interfaces(ns_server_t *server) { isc_task_endexclusive(server->task); } +/* + * Get the next token from lexer 'lex'. + * + * NOTE: the token value for string tokens always uses the same pointer + * value. Multiple calls to this function on the same lexer will always + * return either that value (lex->data) or NULL. It is necessary to copy + * the token into local storage if it needs to be referenced after the next + * call to next_token(). + */ static char * -next_token(char **stringp, const char *delim) { - char *res; +next_token(isc_lex_t *lex, isc_buffer_t **text) { + isc_result_t result; + isc_token_t token; - do { - res = strsep(stringp, delim); - if (res == NULL) - break; - } while (*res == '\0'); - return (res); + token.type = isc_tokentype_unknown; + result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF|ISC_LEXOPT_QSTRING, + &token); + + switch (result) { + case ISC_R_NOMORE: + (void) isc_lex_close(lex); + break; + case ISC_R_SUCCESS: + if (token.type == isc_tokentype_eof) + (void) isc_lex_close(lex); + break; + case ISC_R_NOSPACE: + if (text != NULL) { + (void) putstr(text, "token too large"); + (void) putnull(text); + } + return (NULL); + default: + if (text != NULL) { + (void) putstr(text, isc_result_totext(result)); + (void) putnull(text); + } + return (NULL); + } + + if (token.type == isc_tokentype_string || + token.type == isc_tokentype_qstring) + return (token.value.as_textregion.base); + + return (NULL); } /* - * Find the zone specified in the control channel command 'args', - * if any. If a zone is specified, point '*zonep' at it, otherwise - * set '*zonep' to NULL. + * Find the zone specified in the control channel command, if any. + * If a zone is specified, point '*zonep' at it, otherwise + * set '*zonep' to NULL, and f 'zonename' is not NULL, copy + * the zone name into it (N.B. 'zonename' must have space to hold + * a full DNS name). * * If 'zonetxt' is set, the caller has already pulled a token - * off the command line that is to be used as the zone name. (This - * is done when it's necessary to check for an optional argument - * before the zone name, as in "rndc sync [-clean] zone".) + * off the command line that is to be used as the zone name. (This + * is sometimes done when it's necessary to check for an optional + * argument before the zone name, as in "rndc sync [-clean] zone".) */ static isc_result_t -zone_from_args(ns_server_t *server, char *args, const char *zonetxt, - dns_zone_t **zonep, const char **zonename, +zone_from_args(ns_server_t *server, isc_lex_t *lex, const char *zonetxt, + dns_zone_t **zonep, char *zonename, isc_buffer_t **text, isc_boolean_t skip) { - char *input, *ptr; + char *ptr; char *classtxt; const char *viewtxt = NULL; dns_fixedname_t fname; @@ -7656,43 +7693,42 @@ zone_from_args(ns_server_t *server, char *args, const char *zonetxt, dns_view_t *view = NULL; dns_rdataclass_t rdclass; char problem[DNS_NAME_FORMATSIZE + 500] = ""; + char zonebuf[DNS_NAME_FORMATSIZE]; REQUIRE(zonep != NULL && *zonep == NULL); - REQUIRE(zonename == NULL || *zonename == NULL); - - input = args; if (skip) { /* Skip the command name. */ - ptr = next_token(&input, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); } /* Look for the zone name. */ if (zonetxt == NULL) - zonetxt = next_token(&input, " \t"); + zonetxt = next_token(lex, text); if (zonetxt == NULL) return (ISC_R_SUCCESS); - if (zonename != NULL) - *zonename = zonetxt; - /* Look for the optional class name. */ - classtxt = next_token(&input, " \t"); - if (classtxt != NULL) { - /* Look for the optional view name. */ - viewtxt = next_token(&input, " \t"); - } + /* Copy zonetxt because it'll be overwritten by next_token() */ + strlcpy(zonebuf, zonetxt, DNS_NAME_FORMATSIZE); + if (zonename != NULL) + strlcpy(zonename, zonetxt, DNS_NAME_FORMATSIZE); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); - CHECK(dns_name_fromstring(name, zonetxt, 0, NULL)); + CHECK(dns_name_fromstring(name, zonebuf, 0, NULL)); + /* Look for the optional class name. */ + classtxt = next_token(lex, text); if (classtxt != NULL) { isc_textregion_t r; r.base = classtxt; r.length = strlen(classtxt); CHECK(dns_rdataclass_fromtext(&rdclass, &r)); + + /* Look for the optional view name. */ + viewtxt = next_token(lex, text); } else rdclass = dns_rdataclass_in; @@ -7703,11 +7739,11 @@ zone_from_args(ns_server_t *server, char *args, const char *zonetxt, if (result == ISC_R_NOTFOUND) snprintf(problem, sizeof(problem), "no matching zone '%s' in any view", - zonetxt); + zonebuf); else if (result == ISC_R_MULTIPLE) snprintf(problem, sizeof(problem), "zone '%s' was found in multiple views", - zonetxt); + zonebuf); } else { result = dns_viewlist_find(&server->viewlist, viewtxt, rdclass, &view); @@ -7721,7 +7757,7 @@ zone_from_args(ns_server_t *server, char *args, const char *zonetxt, if (result != ISC_R_SUCCESS) snprintf(problem, sizeof(problem), "no matching zone '%s' in view '%s'", - zonetxt, viewtxt); + zonebuf, viewtxt); } /* Partial match? */ @@ -7749,7 +7785,7 @@ zone_from_args(ns_server_t *server, char *args, const char *zonetxt, * Act on a "retransfer" command from the command channel. */ isc_result_t -ns_server_retransfercommand(ns_server_t *server, char *args, +ns_server_retransfercommand(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; @@ -7757,7 +7793,7 @@ ns_server_retransfercommand(ns_server_t *server, char *args, dns_zone_t *raw = NULL; dns_zonetype_t type; - result = zone_from_args(server, args, NULL, &zone, NULL, + result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); @@ -7782,13 +7818,15 @@ ns_server_retransfercommand(ns_server_t *server, char *args, * Act on a "reload" command from the command channel. */ isc_result_t -ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_reloadcommand(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) +{ isc_result_t result; dns_zone_t *zone = NULL; dns_zonetype_t type; const char *msg = NULL; - result = zone_from_args(server, args, NULL, &zone, NULL, + result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); @@ -7857,12 +7895,14 @@ cleanup: * Act on a "notify" command from the command channel. */ isc_result_t -ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_notifycommand(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) +{ isc_result_t result; dns_zone_t *zone = NULL; const char msg[] = "zone notify queued"; - result = zone_from_args(server, args, NULL, &zone, NULL, + result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); @@ -7881,7 +7921,8 @@ ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t **text) { * Act on a "refresh" command from the command channel. */ isc_result_t -ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t **text) +ns_server_refreshcommand(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) { isc_result_t result; dns_zone_t *zone = NULL, *raw = NULL; @@ -7889,7 +7930,7 @@ ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t **text) const char msg2[] = "not a slave or stub zone"; dns_zonetype_t type; - result = zone_from_args(server, args, NULL, &zone, NULL, + result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); @@ -7919,16 +7960,16 @@ ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t **text) } isc_result_t -ns_server_togglequerylog(ns_server_t *server, char *args) { +ns_server_togglequerylog(ns_server_t *server, isc_lex_t *lex) { isc_boolean_t value; char *ptr; /* Skip the command name. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); if (ptr == NULL) value = server->log_queries ? ISC_FALSE : ISC_TRUE; else if (strcasecmp(ptr, "yes") == 0 || strcasecmp(ptr, "on") == 0) @@ -8281,7 +8322,7 @@ dumpdone(void *arg, isc_result_t result) { } isc_result_t -ns_server_dumpdb(ns_server_t *server, char *args) { +ns_server_dumpdb(ns_server_t *server, isc_lex_t *lex) { struct dumpcontext *dctx = NULL; dns_view_t *view; isc_result_t result; @@ -8289,7 +8330,7 @@ ns_server_dumpdb(ns_server_t *server, char *args) { const char *sep; /* Skip the command name. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); @@ -8318,19 +8359,19 @@ ns_server_dumpdb(ns_server_t *server, char *args) { CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp), "could not open dump file", server->dumpfile); - sep = (args == NULL) ? "" : ": "; + ptr = next_token(lex, NULL); + sep = (ptr == NULL) ? "" : ": "; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, - "dumpdb started%s%s", sep, (args != NULL) ? args : ""); + "dumpdb started%s%s", sep, (ptr != NULL) ? ptr : ""); - ptr = next_token(&args, " \t"); if (ptr != NULL && strcmp(ptr, "-all") == 0) { /* also dump zones */ dctx->dumpzones = ISC_TRUE; - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) { /* this is the default */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) { /* only dump zones, suppress caches */ dctx->dumpadb = ISC_FALSE; @@ -8338,25 +8379,25 @@ ns_server_dumpdb(ns_server_t *server, char *args) { dctx->dumpcache = ISC_FALSE; dctx->dumpfail = ISC_FALSE; dctx->dumpzones = ISC_TRUE; - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); } else if (ptr != NULL && strcmp(ptr, "-adb") == 0) { /* only dump adb, suppress other caches */ dctx->dumpbad = ISC_FALSE; dctx->dumpcache = ISC_FALSE; dctx->dumpfail = ISC_FALSE; - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); } else if (ptr != NULL && strcmp(ptr, "-bad") == 0) { /* only dump badcache, suppress other caches */ dctx->dumpadb = ISC_FALSE; dctx->dumpcache = ISC_FALSE; dctx->dumpfail = ISC_FALSE; - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); } else if (ptr != NULL && strcmp(ptr, "-fail") == 0) { /* only dump servfail cache, suppress other caches */ dctx->dumpadb = ISC_FALSE; dctx->dumpbad = ISC_FALSE; dctx->dumpcache = ISC_FALSE; - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); } nextview: @@ -8369,7 +8410,7 @@ ns_server_dumpdb(ns_server_t *server, char *args) { CHECK(add_view_tolist(dctx, view)); } if (ptr != NULL) { - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); if (ptr != NULL) goto nextview; } @@ -8383,7 +8424,9 @@ ns_server_dumpdb(ns_server_t *server, char *args) { } isc_result_t -ns_server_dumpsecroots(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_dumpsecroots(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) +{ dns_view_t *view; dns_keytable_t *secroots = NULL; dns_ntatable_t *ntatable = NULL; @@ -8394,14 +8437,14 @@ ns_server_dumpsecroots(ns_server_t *server, char *args, isc_buffer_t **text) { char tbuf[64]; /* Skip the command name. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* "-" here means print the output instead of dumping to file */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr != NULL && strcmp(ptr, "-") == 0) - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); else { result = isc_stdio_open(server->secrootsfile, "w", &fp); if (result != ISC_R_SUCCESS) { @@ -8448,7 +8491,7 @@ ns_server_dumpsecroots(ns_server_t *server, char *args, isc_buffer_t **text) { CHECK(dns_ntatable_totext(ntatable, text)); } if (ptr != NULL) - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); } while (ptr != NULL); cleanup: @@ -8519,26 +8562,25 @@ ns_server_dumprecursing(ns_server_t *server) { } isc_result_t -ns_server_setdebuglevel(ns_server_t *server, char *args) { +ns_server_setdebuglevel(ns_server_t *server, isc_lex_t *lex) { char *ptr; - char *levelstr; char *endp; long newlevel; UNUSED(server); /* Skip the command name. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Look for the new level name. */ - levelstr = next_token(&args, " \t"); - if (levelstr == NULL) { + ptr = next_token(lex, NULL); + if (ptr == NULL) { if (ns_g_debuglevel < 99) ns_g_debuglevel++; } else { - newlevel = strtol(levelstr, &endp, 10); + newlevel = strtol(ptr, &endp, 10); if (*endp != '\0' || newlevel < 0 || newlevel > 99) return (ISC_R_RANGE); ns_g_debuglevel = (unsigned int)newlevel; @@ -8551,20 +8593,22 @@ ns_server_setdebuglevel(ns_server_t *server, char *args) { } isc_result_t -ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text) { - char *ptr, *viewname; +ns_server_validation(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) +{ + char *ptr; dns_view_t *view; isc_boolean_t changed = ISC_FALSE; isc_result_t result; isc_boolean_t enable = ISC_TRUE, set = ISC_TRUE, first = ISC_TRUE; /* Skip the command name. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Find out what we are to do. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); @@ -8580,7 +8624,7 @@ ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text) { return (DNS_R_SYNTAX); /* Look for the view name. */ - viewname = next_token(&args, " \t"); + ptr = next_token(lex, text); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -8588,7 +8632,7 @@ ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text) { view != NULL; view = ISC_LIST_NEXT(view, link)) { - if (viewname != NULL && strcasecmp(viewname, view->name) != 0) + if (ptr != NULL && strcasecmp(ptr, view->name) != 0) continue; CHECK(dns_view_flushcache(view)); @@ -8621,8 +8665,8 @@ ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text) { } isc_result_t -ns_server_flushcache(ns_server_t *server, char *args) { - char *ptr, *viewname; +ns_server_flushcache(ns_server_t *server, isc_lex_t *lex) { + char *ptr; dns_view_t *view; isc_boolean_t flushed; isc_boolean_t found; @@ -8630,12 +8674,12 @@ ns_server_flushcache(ns_server_t *server, char *args) { ns_cache_t *nsc; /* Skip the command name. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, NULL); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Look for the view name. */ - viewname = next_token(&args, " \t"); + ptr = next_token(lex, NULL); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -8648,7 +8692,7 @@ ns_server_flushcache(ns_server_t *server, char *args) { * list, flush these caches, and then update other views that refer to * the flushed cache DB. */ - if (viewname != NULL) { + if (ptr != NULL) { /* * Mark caches that need to be flushed. This is an O(#view^2) * operation in the very worst case, but should be normally @@ -8659,7 +8703,7 @@ ns_server_flushcache(ns_server_t *server, char *args) { view != NULL; view = ISC_LIST_NEXT(view, link)) { - if (strcasecmp(viewname, view->name) != 0) + if (strcasecmp(ptr, view->name) != 0) continue; found = ISC_TRUE; for (nsc = ISC_LIST_HEAD(server->cachelist); @@ -8678,7 +8722,7 @@ ns_server_flushcache(ns_server_t *server, char *args) { for (nsc = ISC_LIST_HEAD(server->cachelist); nsc != NULL; nsc = ISC_LIST_NEXT(nsc, link)) { - if (viewname != NULL && !nsc->needflush) + if (ptr != NULL && !nsc->needflush) continue; nsc->needflush = ISC_TRUE; result = dns_view_flushcache2(nsc->primaryview, ISC_FALSE); @@ -8732,11 +8776,11 @@ ns_server_flushcache(ns_server_t *server, char *args) { } if (flushed && found) { - if (viewname != NULL) + if (ptr != NULL) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "flushing cache in view '%s' succeeded", - viewname); + ptr); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, @@ -8747,7 +8791,7 @@ ns_server_flushcache(ns_server_t *server, char *args) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "flushing cache in view '%s' failed: " - "view not found", viewname); + "view not found", ptr); result = ISC_R_NOTFOUND; } else result = ISC_R_FAILURE; @@ -8757,8 +8801,9 @@ ns_server_flushcache(ns_server_t *server, char *args) { } isc_result_t -ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree) { - char *target, *viewname; +ns_server_flushnode(ns_server_t *server, isc_lex_t *lex, isc_boolean_t tree) { + char *ptr, *viewname; + char target[DNS_NAME_FORMATSIZE]; dns_view_t *view; isc_boolean_t flushed; isc_boolean_t found; @@ -8768,15 +8813,16 @@ ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree) { dns_name_t *name; /* Skip the command name. */ - target = next_token(&args, " \t"); - if (target == NULL) + ptr = next_token(lex, NULL); + if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Find the domain name to flush. */ - target = next_token(&args, " \t"); - if (target == NULL) + ptr = next_token(lex, NULL); + if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); + strlcpy(target, ptr, DNS_NAME_FORMATSIZE); isc_buffer_constinit(&b, target, strlen(target)); isc_buffer_add(&b, strlen(target)); dns_fixedname_init(&fixed); @@ -8786,7 +8832,7 @@ ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree) { return (result); /* Look for the view name. */ - viewname = next_token(&args, " \t"); + viewname = next_token(lex, NULL); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -8945,7 +8991,7 @@ ns_server_status(ns_server_t *server, isc_buffer_t **text) { } isc_result_t -ns_server_testgen(char *args, isc_buffer_t **text) { +ns_server_testgen(isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; char *ptr; unsigned long count; @@ -8953,11 +8999,11 @@ ns_server_testgen(char *args, isc_buffer_t **text) { const unsigned char chars[] = "abcdefghijklmnopqrstuvwxyz0123456789"; /* Skip the command name. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) count = 26; else @@ -9037,18 +9083,24 @@ delete_keynames(dns_tsig_keyring_t *ring, char *target, } isc_result_t -ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t **text) { +ns_server_tsigdelete(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) +{ isc_result_t result; dns_view_t *view; unsigned int foundkeys = 0; - char *target, *viewname; + char *ptr, *viewname; + char target[DNS_NAME_FORMATSIZE]; char fbuf[16]; - (void)next_token(&command, " \t"); /* skip command name */ - target = next_token(&command, " \t"); - if (target == NULL) + (void)next_token(lex, text); /* skip command name */ + + ptr = next_token(lex, text); + if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); - viewname = next_token(&command, " \t"); + strlcpy(target, ptr, DNS_NAME_FORMATSIZE); + + viewname = next_token(lex, text); result = isc_task_beginexclusive(server->task); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -9201,18 +9253,20 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t **text) { * Act on a "sign" or "loadkeys" command from the command channel. */ isc_result_t -ns_server_rekey(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_rekey(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; dns_zone_t *zone = NULL; dns_zonetype_t type; isc_uint16_t keyopts; isc_boolean_t fullsign = ISC_FALSE; + char *ptr; - if (strncasecmp(args, NS_COMMAND_SIGN, strlen(NS_COMMAND_SIGN)) == 0) - fullsign = ISC_TRUE; + ptr = next_token(lex, text); + if (strcasecmp(ptr, NS_COMMAND_SIGN) == 0) + fullsign = ISC_TRUE; - result = zone_from_args(server, args, NULL, &zone, NULL, - text, ISC_TRUE); + result = zone_from_args(server, lex, NULL, &zone, NULL, + text, ISC_FALSE); if (result != ISC_R_SUCCESS) return (result); if (zone == NULL) @@ -9267,7 +9321,7 @@ synczone(dns_zone_t *zone, void *uap) { } isc_result_t -ns_server_sync(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_sync(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result, tresult; dns_view_t *view; dns_zone_t *zone = NULL; @@ -9276,16 +9330,16 @@ ns_server_sync(ns_server_t *server, char *args, isc_buffer_t **text) { const char *vname, *sep, *arg; isc_boolean_t cleanup = ISC_FALSE; - (void) next_token(&args, " \t"); + (void) next_token(lex, text); - arg = next_token(&args, " \t"); + arg = next_token(lex, text); if (arg != NULL && (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0)) { cleanup = ISC_TRUE; - arg = next_token(&args, " \t"); + arg = next_token(lex, text); } - result = zone_from_args(server, args, arg, &zone, NULL, + result = zone_from_args(server, lex, arg, &zone, NULL, text, ISC_FALSE); if (result != ISC_R_SUCCESS) return (result); @@ -9345,8 +9399,8 @@ ns_server_sync(ns_server_t *server, char *args, isc_buffer_t **text) { * Act on a "freeze" or "thaw" command from the command channel. */ isc_result_t -ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, - isc_buffer_t **text) +ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, + isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result, tresult; dns_zone_t *zone = NULL, *raw = NULL; @@ -9358,7 +9412,7 @@ ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args, isc_boolean_t frozen; const char *msg = NULL; - result = zone_from_args(server, args, NULL, &zone, NULL, + result = zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_TRUE); if (result != ISC_R_SUCCESS) return (result); @@ -9646,7 +9700,7 @@ nzf_append(FILE *fp, const char *viewname, const cfg_obj_t *zconfig) { } static isc_result_t -newzone_parse(ns_server_t *server, char *args, dns_view_t **viewp, +newzone_parse(ns_server_t *server, char *command, dns_view_t **viewp, cfg_obj_t **zoneconfp, const cfg_obj_t **zoneobjp, isc_buffer_t **text) { @@ -9664,12 +9718,12 @@ newzone_parse(ns_server_t *server, char *args, dns_view_t **viewp, REQUIRE(viewp != NULL && *viewp == NULL); /* Try to parse the argument string */ - isc_buffer_init(&argbuf, args, (unsigned int) strlen(args)); - isc_buffer_add(&argbuf, strlen(args)); + isc_buffer_init(&argbuf, command, (unsigned int) strlen(command)); + isc_buffer_add(&argbuf, strlen(command)); - if (strncasecmp(args, "add", 3) == 0) + if (strncasecmp(command, "add", 3) == 0) bn = "addzone"; - else if (strncasecmp(args, "mod", 3) == 0) + else if (strncasecmp(command, "mod", 3) == 0) bn = "modzone"; else INSIST(0); @@ -10001,7 +10055,7 @@ do_modzone(ns_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, * Act on an "addzone" or "modzone" command from the command channel. */ isc_result_t -ns_server_changezone(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_changezone(ns_server_t *server, char *command, isc_buffer_t **text) { isc_result_t result; isc_boolean_t addzone; ns_cfgctx_t *cfg = NULL; @@ -10013,14 +10067,14 @@ ns_server_changezone(ns_server_t *server, char *args, isc_buffer_t **text) { dns_fixedname_t fname; dns_name_t *dnsname; - if (strncasecmp(args, "add", 3) == 0) + if (strncasecmp(command, "add", 3) == 0) addzone = ISC_TRUE; else { - INSIST(strncasecmp(args, "mod", 3) == 0); + INSIST(strncasecmp(command, "mod", 3) == 0); addzone = ISC_FALSE; } - CHECK(newzone_parse(server, args, &view, &zoneconf, &zoneobj, text)); + CHECK(newzone_parse(server, command, &view, &zoneconf, &zoneobj, text)); /* Are we accepting new zones in this view? */ if (view->new_zone_file == NULL) { @@ -10093,7 +10147,7 @@ inuse(const char* file, isc_boolean_t first, isc_buffer_t **text) { * Act on a "delzone" command from the command channel. */ isc_result_t -ns_server_delzone(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_delzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result, tresult; ns_cfgctx_t *cfg = NULL; dns_zone_t *zone = NULL; @@ -10101,28 +10155,28 @@ ns_server_delzone(ns_server_t *server, char *args, isc_buffer_t **text) { dns_zone_t *mayberaw; dns_view_t *view = NULL; dns_db_t *dbp = NULL; - const char *zonename = NULL; + char zonename[DNS_NAME_FORMATSIZE]; isc_boolean_t exclusive = ISC_FALSE; isc_boolean_t cleanup = ISC_FALSE; - const char *file, *arg; + const char *file, *ptr; isc_boolean_t added; /* Skip the command name. */ - arg = next_token(&args, " \t"); - if (arg == NULL) + ptr = next_token(lex, text); + if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Find out what we are to do. */ - arg = next_token(&args, " \t"); - if (arg == NULL) + ptr = next_token(lex, text); + if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); - if (strcmp(arg, "-clean") == 0 || strcmp(arg, "-clear") == 0) { + if (strcmp(ptr, "-clean") == 0 || strcmp(ptr, "-clear") == 0) { cleanup = ISC_TRUE; - arg = next_token(&args, " \t"); + ptr = next_token(lex, text); } - CHECK(zone_from_args(server, args, arg, &zone, &zonename, + CHECK(zone_from_args(server, lex, ptr, &zone, zonename, text, ISC_FALSE)); if (zone == NULL) { result = ISC_R_UNEXPECTEDEND; @@ -10277,10 +10331,10 @@ emitzone(void *arg, const char *buf, int len) { } isc_result_t -ns_server_showzone(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_showzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result; const cfg_obj_t *vconfig = NULL, *zconfig = NULL; - const char *zonename = NULL; + char zonename[DNS_NAME_FORMATSIZE]; const cfg_obj_t *map; dns_view_t *view = NULL; dns_zone_t *zone = NULL; @@ -10288,7 +10342,7 @@ ns_server_showzone(ns_server_t *server, char *args, isc_buffer_t **text) { isc_boolean_t exclusive = ISC_FALSE; /* Parse parameters */ - CHECK(zone_from_args(server, args, NULL, &zone, &zonename, + CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, ISC_TRUE)); if (zone == NULL) { result = ISC_R_UNEXPECTEDEND; @@ -10404,7 +10458,7 @@ generate_salt(unsigned char *salt, size_t saltlen) { } isc_result_t -ns_server_signing(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_signing(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { isc_result_t result = ISC_R_SUCCESS; dns_zone_t *zone = NULL; dns_name_t *origin; @@ -10427,43 +10481,51 @@ ns_server_signing(ns_server_t *server, char *args, isc_buffer_t **text) { dns_rdataset_init(&privset); /* Skip the command name. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); /* Find out what we are to do. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); if (strcasecmp(ptr, "-list") == 0) list = ISC_TRUE; else if ((strcasecmp(ptr, "-clear") == 0) || - (strcasecmp(ptr, "-clean") == 0)) { + (strcasecmp(ptr, "-clean") == 0)) + { clear = ISC_TRUE; - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); strlcpy(keystr, ptr, sizeof(keystr)); } else if (strcasecmp(ptr, "-nsec3param") == 0) { - const char *hashstr, *flagstr, *iterstr; - char nbuf[512]; + char hashbuf[64], flagbuf[64], iterbuf[64]; + char nbuf[256]; chain = ISC_TRUE; - hashstr = next_token(&args, " \t"); - if (hashstr == NULL) + ptr = next_token(lex, text); + if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); - if (strcasecmp(hashstr, "none") == 0) + if (strcasecmp(ptr, "none") == 0) hash = 0; else { - flagstr = next_token(&args, " \t"); - iterstr = next_token(&args, " \t"); - if (flagstr == NULL || iterstr == NULL) + strlcpy(hashbuf, ptr, sizeof(hashbuf)); + + ptr = next_token(lex, text); + if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); + strlcpy(flagbuf, ptr, sizeof(flagbuf)); + + ptr = next_token(lex, text); + if (ptr == NULL) + return (ISC_R_UNEXPECTEDEND); + strlcpy(iterbuf, ptr, sizeof(iterbuf)); n = snprintf(nbuf, sizeof(nbuf), "%s %s %s", - hashstr, flagstr, iterstr); + hashbuf, flagbuf, iterbuf); if (n == sizeof(nbuf)) return (ISC_R_NOSPACE); n = sscanf(nbuf, "%hu %hu %hu", &hash, &flags, &iter); @@ -10473,7 +10535,7 @@ ns_server_signing(ns_server_t *server, char *args, isc_buffer_t **text) { if (hash > 0xffU || flags > 0xffU) return (ISC_R_RANGE); - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) { return (ISC_R_UNEXPECTEDEND); } else if (strcasecmp(ptr, "auto") == 0) { @@ -10494,7 +10556,7 @@ ns_server_signing(ns_server_t *server, char *args, isc_buffer_t **text) { } } } else if (strcasecmp(ptr, "-serial") == 0) { - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); CHECK(isc_parse_uint32(&serial, ptr, 10)); @@ -10502,7 +10564,7 @@ ns_server_signing(ns_server_t *server, char *args, isc_buffer_t **text) { } else CHECK(DNS_R_SYNTAX); - CHECK(zone_from_args(server, args, NULL, &zone, NULL, + CHECK(zone_from_args(server, lex, NULL, &zone, NULL, text, ISC_FALSE)); if (zone == NULL) CHECK(ISC_R_UNEXPECTEDEND); @@ -10613,10 +10675,13 @@ putnull(isc_buffer_t **b) { } isc_result_t -ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_zonestatus(ns_server_t *server, isc_lex_t *lex, + isc_buffer_t **text) +{ isc_result_t result = ISC_R_SUCCESS; dns_zone_t *zone = NULL, *raw = NULL; - const char *type, *file, *zonename = NULL; + const char *type, *file; + char zonename[DNS_NAME_FORMATSIZE]; isc_uint32_t serial, signed_serial, nodes; char serbuf[16], sserbuf[16], nodebuf[16], resignbuf[512]; char lbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; @@ -10640,7 +10705,7 @@ ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t **text) { isc_time_settoepoch(&refreshkeytime); isc_time_settoepoch(&resigntime); - CHECK(zone_from_args(server, args, NULL, &zone, &zonename, + CHECK(zone_from_args(server, lex, NULL, &zone, zonename, text, ISC_TRUE)); if (zone == NULL) { result = ISC_R_UNEXPECTEDEND; @@ -10892,11 +10957,12 @@ argcheck(char *cmd, const char *full) { } isc_result_t -ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_nta(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { dns_view_t *view; dns_ntatable_t *ntatable = NULL; isc_result_t result = ISC_R_SUCCESS; char *ptr, *nametext = NULL, *viewname; + char namebuf[DNS_NAME_FORMATSIZE]; isc_stdtime_t now, when; isc_time_t t; char tbuf[64]; @@ -10913,13 +10979,13 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text) { ntaname = dns_fixedname_name(&fn); /* Skip the command name. */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); for (;;) { /* Check for options */ - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) return (ISC_R_UNEXPECTEDEND); @@ -10934,7 +11000,7 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text) { } else if (argcheck(ptr, "lifetime")) { isc_textregion_t tr; - ptr = next_token(&args, " \t"); + ptr = next_token(lex, text); if (ptr == NULL) { msg = "No lifetime specified"; CHECK(ISC_R_UNEXPECTEDEND); @@ -10983,21 +11049,24 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text) { /* Get the NTA name. */ if (nametext == NULL) - nametext = next_token(&args, " \t"); + nametext = next_token(lex, text); if (nametext == NULL) return (ISC_R_UNEXPECTEDEND); - if (strcmp(nametext, ".") == 0) + /* Copy nametext as it'll be overwritten by next_token() */ + strlcpy(namebuf, nametext, DNS_NAME_FORMATSIZE); + + if (strcmp(namebuf, ".") == 0) ntaname = dns_rootname; else { isc_buffer_t b; - isc_buffer_init(&b, nametext, strlen(nametext)); - isc_buffer_add(&b, strlen(nametext)); + isc_buffer_init(&b, namebuf, strlen(namebuf)); + isc_buffer_add(&b, strlen(namebuf)); CHECK(dns_name_fromtext(ntaname, &b, dns_rootname, 0, NULL)); } /* Look for the view name. */ - viewname = next_token(&args, " \t"); + viewname = next_token(lex, text); isc_stdtime_get(&now); @@ -11031,7 +11100,7 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "flush tree '%s' in cache view '%s': %s", - nametext, view->name, + namebuf, view->name, isc_result_totext(result)); if (ntattl != 0) { @@ -11043,7 +11112,7 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text) { isc_time_formattimestamp(&t, tbuf, sizeof(tbuf)); CHECK(putstr(text, "Negative trust anchor added: ")); - CHECK(putstr(text, nametext)); + CHECK(putstr(text, namebuf)); CHECK(putstr(text, "/")); CHECK(putstr(text, view->name)); CHECK(putstr(text, ", expires ")); @@ -11052,19 +11121,19 @@ ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "added NTA '%s' (%d sec) in view '%s'", - nametext, ntattl, view->name); + namebuf, ntattl, view->name); } else { CHECK(dns_ntatable_delete(ntatable, ntaname)); CHECK(putstr(text, "Negative trust anchor removed: ")); - CHECK(putstr(text, nametext)); + CHECK(putstr(text, namebuf)); CHECK(putstr(text, "/")); CHECK(putstr(text, view->name)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_INFO, "removed NTA '%s' in view %s", - nametext, view->name); + namebuf, view->name); } result = dns_view_saventa(view); @@ -11298,7 +11367,7 @@ mkey_status(dns_view_t *view, isc_buffer_t **text) { } isc_result_t -ns_server_mkeys(ns_server_t *server, char *args, isc_buffer_t **text) { +ns_server_mkeys(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text) { char *cmd, *classtxt, *viewtxt = NULL; isc_result_t result = ISC_R_SUCCESS; dns_view_t *view = NULL; @@ -11309,12 +11378,12 @@ ns_server_mkeys(ns_server_t *server, char *args, isc_buffer_t **text) { isc_boolean_t first = ISC_TRUE; /* Skip rndc command name */ - cmd = next_token(&args, " \t"); + cmd = next_token(lex, text); if (cmd == NULL) return (ISC_R_UNEXPECTEDEND); /* Get managed-keys subcommand */ - cmd = next_token(&args, " \t"); + cmd = next_token(lex, text); if (cmd == NULL) return (ISC_R_UNEXPECTEDEND); @@ -11332,10 +11401,10 @@ ns_server_mkeys(ns_server_t *server, char *args, isc_buffer_t **text) { } /* Look for the optional class name. */ - classtxt = next_token(&args, " \t"); + classtxt = next_token(lex, text); if (classtxt != NULL) { /* Look for the optional view name. */ - viewtxt = next_token(&args, " \t"); + viewtxt = next_token(lex, text); } if (classtxt == NULL) { diff --git a/bin/tests/system/rndc/ns4/named.conf.in b/bin/tests/system/rndc/ns4/named.conf.in index 1eb442e230..51d0491865 100644 --- a/bin/tests/system/rndc/ns4/named.conf.in +++ b/bin/tests/system/rndc/ns4/named.conf.in @@ -14,8 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - controls { /* empty */ }; options { @@ -26,3 +24,10 @@ options { recursion yes; }; +view normal { + match-clients { any; }; +}; + +view "view with a space" { + match-clients { none; }; +}; diff --git a/bin/tests/system/rndc/tests.sh b/bin/tests/system/rndc/tests.sh index cc3ad4eac8..4492ceb85e 100644 --- a/bin/tests/system/rndc/tests.sh +++ b/bin/tests/system/rndc/tests.sh @@ -344,7 +344,7 @@ status=`expr $status + $ret` echo "I:testing automatic zones are reported" ret=0 $RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf status > rndc.status || ret=1 -grep "number of zones: 99 (98 automatic)" rndc.status > /dev/null || ret=1 +grep "number of zones: 198 (196 automatic)" rndc.status > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -411,6 +411,13 @@ grep "ISC_R_SUCCESS 0" rndc.output > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +echo "I:testing rndc with a token containing a space" +ret=0 +$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf -r flush '"view with a space"' 2>&1 > rndc.output || ret=1 +grep "not found" rndc.output > /dev/null && ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:test 'rndc reconfig' with a broken config" ret=0 $RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf reconfig > /dev/null || ret=1