#include <isc/app.h>
#include <isc/event.h>
+#include <isc/lex.h>
#include <isc/mem.h>
#include <isc/string.h>
#include <isc/timer.h>
#include <isccc/result.h>
#include <named/control.h>
+#include <named/globals.h>
#include <named/log.h>
#include <named/os.h>
#include <named/server.h>
#include <named/ns_smf_globals.h>
#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);
}
/*%
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
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.
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.
*/
} 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
/*
*/
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,
#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;
} 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)) {
} 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,
result = DNS_R_UNKNOWNCOMMAND;
}
+ cleanup:
+ if (lex != NULL)
+ isc_lex_destroy(&lex);
+
return (result);
}
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;
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;
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);
if (result != ISC_R_SUCCESS)
snprintf(problem, sizeof(problem),
"no matching zone '%s' in view '%s'",
- zonetxt, viewtxt);
+ zonebuf, viewtxt);
}
/* Partial match? */
* 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;
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);
* 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);
* 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);
* 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;
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);
}
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)
}
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;
const char *sep;
/* Skip the command name. */
- ptr = next_token(&args, " \t");
+ ptr = next_token(lex, NULL);
if (ptr == NULL)
return (ISC_R_UNEXPECTEDEND);
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;
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:
CHECK(add_view_tolist(dctx, view));
}
if (ptr != NULL) {
- ptr = next_token(&args, " \t");
+ ptr = next_token(lex, NULL);
if (ptr != NULL)
goto nextview;
}
}
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;
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) {
CHECK(dns_ntatable_totext(ntatable, text));
}
if (ptr != NULL)
- ptr = next_token(&args, " \t");
+ ptr = next_token(lex, text);
} while (ptr != NULL);
cleanup:
}
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;
}
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);
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);
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));
}
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;
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);
* 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
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);
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);
}
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,
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;
}
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;
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);
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);
}
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;
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
}
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);
* 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)
}
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;
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);
* 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;
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);
}
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)
{
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);
* 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;
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) {
* 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;
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;
}
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;
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;
}
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;
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);
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) {
}
}
} 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));
} 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);
}
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];
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;
}
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];
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);
} 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);
/* 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);
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) {
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 "));
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);
}
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;
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);
}
/* 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) {