summaryrefslogtreecommitdiffstats
path: root/contrib/bind/bin/named/ns_ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/bin/named/ns_ctl.c')
-rw-r--r--contrib/bind/bin/named/ns_ctl.c1147
1 files changed, 0 insertions, 1147 deletions
diff --git a/contrib/bind/bin/named/ns_ctl.c b/contrib/bind/bin/named/ns_ctl.c
deleted file mode 100644
index ced69d5..0000000
--- a/contrib/bind/bin/named/ns_ctl.c
+++ /dev/null
@@ -1,1147 +0,0 @@
-#if !defined(lint) && !defined(SABER)
-static const char rcsid[] = "$Id: ns_ctl.c,v 8.48 2002/07/29 02:06:56 marka Exp $";
-#endif /* not lint */
-
-/*
- * Copyright (c) 1997-2000 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/* Extern. */
-
-#include "port_before.h"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <arpa/inet.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <resolv.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <time.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include <isc/eventlib.h>
-#include <isc/logging.h>
-#include <isc/memcluster.h>
-
-#include "port_after.h"
-
-#include "named.h"
-
-/* Defs. */
-
-#define CONTROL_FOUND 0x0001 /* for mark and sweep. */
-#define MAX_STR_LEN 500
-
-struct control {
- LINK(struct control) link;
- enum { t_dead, t_inet, t_unix } type;
- struct ctl_sctx *sctx;
- u_int flags;
- union {
- struct {
- struct sockaddr_in in;
- ip_match_list allow;
- } v_inet;
-#ifndef NO_SOCKADDR_UN
- struct {
- struct sockaddr_un un;
- mode_t mode;
- uid_t owner;
- gid_t group;
- } v_unix;
-#endif
- } var;
-};
-
-/* Forward. */
-
-static struct ctl_sctx *mksrvr(control, const struct sockaddr *, size_t);
-static control new_control(void);
-static void free_control(controls *, control);
-static void free_controls(controls *);
-static int match_control(control, control);
-static control find_control(controls, control);
-static void propagate_changes(const control, control);
-static void install(control);
-static void install_inet(control);
-static void install_unix(control);
-static void logger(enum ctl_severity, const char *fmt, ...)
- ISC_FORMAT_PRINTF(2,3);
-static void verb_connect(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void verb_getpid(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void getpid_closure(struct ctl_sctx *, struct ctl_sess *,
- void *);
-static void verb_status(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void status_closure(struct ctl_sctx *, struct ctl_sess *,
- void *);
-static void verb_stop(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void verb_exec(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void exec_closure(struct ctl_sctx *, struct ctl_sess *,
- void *);
-static void verb_reload(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void verb_reconfig(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void verb_dumpdb(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void verb_stats(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void verb_trace(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void trace_closure(struct ctl_sctx *, struct ctl_sess *,
- void *);
-static void verb_notrace(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void verb_querylog(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void verb_help(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void verb_quit(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-static void verb_args(struct ctl_sctx *, struct ctl_sess *,
- const struct ctl_verb *,
- const char *, u_int, const void *, void *);
-
-/* Private data. */
-
-static controls server_controls;
-
-static struct ctl_verb verbs[] = {
- { "", verb_connect, ""},
- { "getpid", verb_getpid, "getpid"},
- { "status", verb_status, "status"},
- { "stop", verb_stop, "stop"},
- { "exec", verb_exec, "exec"},
- { "reload", verb_reload, "reload [zone] ..."},
- { "reconfig", verb_reconfig, "reconfig [-noexpired] (just sees new/gone zones)"},
- { "dumpdb", verb_dumpdb, "dumpdb"},
- { "stats", verb_stats, "stats [clear]"},
- { "trace", verb_trace, "trace [level]"},
- { "notrace", verb_notrace, "notrace"},
- { "querylog", verb_querylog, "querylog"},
- { "qrylog", verb_querylog, "qrylog"},
- { "help", verb_help, "help"},
- { "quit", verb_quit, "quit"},
- { "args", verb_args, "args"},
- { NULL, NULL, NULL}
-};
-
-/* Public functions. */
-
-void
-ns_ctl_initialize(void) {
- INIT_LIST(server_controls);
-}
-
-void
-ns_ctl_shutdown(void) {
- if (!EMPTY(server_controls))
- free_controls(&server_controls);
-}
-
-void
-ns_ctl_defaults(controls *list) {
-#ifdef NO_SOCKADDR_UN
- struct in_addr saddr;
- ip_match_list iml;
- ip_match_element ime;
-
- /*
- * If the operating system does not support local domain sockets,
- * connect with ndc on 127.0.0.1, port 101, and only allow
- * connections from 127.0.0.1.
- */
- saddr.s_addr = htonl (INADDR_LOOPBACK);
- iml = new_ip_match_list();
- ime = new_ip_match_pattern(saddr, 32);
- add_to_ip_match_list(iml, ime);
-
- ns_ctl_add(list, ns_ctl_new_inet(saddr, htons (101), iml));
-#else
-#ifdef NEED_SECURE_DIRECTORY
- ns_ctl_add(list, ns_ctl_new_unix(_PATH_NDCSOCK, 0700, 0, 0));
-#else
- ns_ctl_add(list, ns_ctl_new_unix(_PATH_NDCSOCK, 0600, 0, 0));
-#endif
-#endif /*NO_SOCKADDR_UN*/
-}
-
-void
-ns_ctl_add(controls *list, control new) {
- if (!find_control(*list, new))
- APPEND(*list, new, link);
-}
-
-control
-ns_ctl_new_inet(struct in_addr saddr, u_int sport, ip_match_list allow) {
- control new = new_control();
-
- INIT_LINK(new, link);
- new->type = t_inet;
- memset(&new->var.v_inet.in, 0, sizeof new->var.v_inet.in);
- new->var.v_inet.in.sin_family = AF_INET;
- new->var.v_inet.in.sin_addr = saddr;
- new->var.v_inet.in.sin_port = sport;
- new->var.v_inet.allow = allow;
- return (new);
-}
-
-#ifndef NO_SOCKADDR_UN
-control
-ns_ctl_new_unix(const char *path, mode_t mode, uid_t owner, gid_t group) {
- control new = new_control();
-
- INIT_LINK(new, link);
- new->type = t_unix;
- memset(&new->var.v_unix.un, 0, sizeof new->var.v_unix.un);
- new->var.v_unix.un.sun_family = AF_UNIX;
- strncpy(new->var.v_unix.un.sun_path, path,
- sizeof new->var.v_unix.un.sun_path - 1);
- new->var.v_unix.mode = mode;
- new->var.v_unix.owner = owner;
- new->var.v_unix.group = group;
- return (new);
-}
-#endif
-
-void
-ns_ctl_install(controls *new) {
- control ctl, old, next;
-
- /* Find all the controls which aren't new or deleted. */
- for (ctl = HEAD(server_controls); ctl != NULL; ctl = NEXT(ctl, link))
- ctl->flags &= ~CONTROL_FOUND;
- for (ctl = HEAD(*new); ctl != NULL; ctl = next) {
- next = NEXT(ctl, link);
- old = find_control(server_controls, ctl);
- if (old != NULL) {
- old->flags |= CONTROL_FOUND;
- propagate_changes(ctl, old);
- if (old->sctx == NULL)
- free_control(&server_controls, old);
- free_control(new, ctl);
- }
- }
-
- /* Destroy any old controls which weren't found. */
- for (ctl = HEAD(server_controls); ctl != NULL; ctl = next) {
- next = NEXT(ctl, link);
- if ((ctl->flags & CONTROL_FOUND) == 0)
- free_control(&server_controls, ctl);
- }
-
- /* Add any new controls which were found. */
- for (ctl = HEAD(*new); ctl != NULL; ctl = next) {
- next = NEXT(ctl, link);
- UNLINK(*new, ctl, link);
- APPEND(server_controls, ctl, link);
- install(ctl);
- if (ctl->sctx == NULL)
- free_control(&server_controls, ctl);
- }
-}
-
-/* Private functions. */
-
-static struct ctl_sctx *
-mksrvr(control ctl, const struct sockaddr *sa, size_t salen) {
- return (ctl_server(ev, sa, salen, verbs, 500, 222,
- 600, 5, 10, logger, ctl));
-}
-
-static control
-new_control(void) {
- control new = memget(sizeof *new);
-
- if (new == NULL)
- panic("memget failed in new_control()", NULL);
- new->type = t_dead;
- new->sctx = NULL;
- return (new);
-}
-
-static void
-free_control(controls *list, control this) {
- int was_live = 0;
- struct stat sb;
-
- if (this->sctx != NULL) {
- ctl_endserver(this->sctx);
- this->sctx = NULL;
- was_live = 1;
- }
- switch (this->type) {
- case t_inet:
- if (this->var.v_inet.allow != NULL) {
- free_ip_match_list(this->var.v_inet.allow);
- this->var.v_inet.allow = NULL;
- }
- break;
-#ifndef NO_SOCKADDR_UN
- case t_unix:
- /* XXX Race condition. */
- if (was_live &&
- stat(this->var.v_unix.un.sun_path, &sb) == 0 &&
- (S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) {
- /* XXX Race condition. */
- unlink(this->var.v_unix.un.sun_path);
- }
- break;
-#endif
- default:
- panic("impossible type in free_control", NULL);
- /* NOTREACHED */
- }
- UNLINK(*list, this, link);
- memput(this, sizeof *this);
-}
-
-static void
-free_controls(controls *list) {
- control ctl, next;
-
- for (ctl = HEAD(*list); ctl != NULL; ctl = next) {
- next = NEXT(ctl, link);
- free_control(list, ctl);
- }
- INIT_LIST(*list);
-}
-
-static int
-match_control(control l, control r) {
- int match = 1;
-
- if (l->type != r->type)
- match = 0;
- else
- switch (l->type) {
- case t_inet:
- if (l->var.v_inet.in.sin_family !=
- r->var.v_inet.in.sin_family ||
- l->var.v_inet.in.sin_port !=
- r->var.v_inet.in.sin_port ||
- l->var.v_inet.in.sin_addr.s_addr !=
- r->var.v_inet.in.sin_addr.s_addr)
- match = 0;
- break;
-#ifndef NO_SOCKADDR_UN
- case t_unix:
- if (l->var.v_unix.un.sun_family !=
- r->var.v_unix.un.sun_family ||
- strcmp(l->var.v_unix.un.sun_path,
- r->var.v_unix.un.sun_path) != 0)
- match = 0;
- break;
-#endif
- default:
- panic("impossible type in match_control", NULL);
- /* NOTREACHED */
- }
- ns_debug(ns_log_config, 20, "match_control(): %d", match);
- return (match);
-}
-
-static control
-find_control(controls list, control new) {
- control ctl;
-
- for (ctl = HEAD(list); ctl != NULL; ctl = NEXT(ctl, link))
- if (match_control(ctl, new))
- return (ctl);
- return (NULL);
-}
-
-static void
-propagate_changes(const control diff, control base) {
- int need_install = 0;
-
- switch (base->type) {
- case t_inet:
- if (base->var.v_inet.allow != NULL)
- free_ip_match_list(base->var.v_inet.allow);
- base->var.v_inet.allow = diff->var.v_inet.allow;
- diff->var.v_inet.allow = NULL;
- need_install++;
- break;
-#ifndef NO_SOCKADDR_UN
- case t_unix:
- if (base->var.v_unix.mode != diff->var.v_unix.mode) {
- base->var.v_unix.mode = diff->var.v_unix.mode;
- need_install++;
- }
- if (base->var.v_unix.owner != diff->var.v_unix.owner) {
- base->var.v_unix.owner = diff->var.v_unix.owner;
- need_install++;
- }
- if (base->var.v_unix.group != diff->var.v_unix.group) {
- base->var.v_unix.group = diff->var.v_unix.group;
- need_install++;
- }
- break;
-#endif
- default:
- panic("impossible type in ns_ctl::propagate_changes", NULL);
- /* NOTREACHED */
- }
- if (need_install)
- install(base);
-}
-
-static void
-install(control ctl) {
- switch (ctl->type) {
- case t_inet:
- install_inet(ctl);
- break;
-#ifndef NO_SOCKADDR_UN
- case t_unix:
- install_unix(ctl);
- break;
-#endif
- default:
- panic("impossible type in ns_ctl::install", NULL);
- /* NOTREACHED */
- }
-}
-
-static void
-install_inet(control ctl) {
- if (ctl->sctx == NULL) {
- ctl->sctx = mksrvr(ctl,
- (struct sockaddr *)&ctl->var.v_inet.in,
- sizeof ctl->var.v_inet.in);
- }
-}
-
-#ifndef NO_SOCKADDR_UN
-/*
- * Unattach an old unix domain socket if it exists.
- */
-static void
-unattach(control ctl) {
- int s;
- struct stat sb;
-
- s = socket(AF_UNIX, SOCK_STREAM, 0);
- if (s < 0) {
- ns_warning(ns_log_config,
- "unix control \"%s\" socket failed: %s",
- ctl->var.v_unix.un.sun_path,
- strerror(errno));
- return;
- }
-
- if (stat(ctl->var.v_unix.un.sun_path, &sb) < 0) {
- switch (errno) {
- case ENOENT: /* We exited cleanly last time */
- break;
- default:
- ns_warning(ns_log_config,
- "unix control \"%s\" stat failed: %s",
- ctl->var.v_unix.un.sun_path,
- strerror(errno));
- break;
- }
- goto cleanup;
- }
-
- if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) {
- ns_warning(ns_log_config, "unix control \"%s\" not socket",
- ctl->var.v_unix.un.sun_path);
- goto cleanup;
- }
-
- if (connect(s, (struct sockaddr *)&ctl->var.v_unix.un,
- sizeof ctl->var.v_unix.un) < 0) {
- switch (errno) {
- case ECONNREFUSED:
- case ECONNRESET:
- if (unlink(ctl->var.v_unix.un.sun_path) < 0)
- ns_warning(ns_log_config,
- "unix control \"%s\" unlink failed: %s",
- ctl->var.v_unix.un.sun_path,
- strerror(errno));
- break;
- default:
- ns_warning(ns_log_config,
- "unix control \"%s\" connect failed: %s",
- ctl->var.v_unix.un.sun_path,
- strerror(errno));
- break;
- }
- }
- cleanup:
- close(s);
-}
-
-static void
-install_unix(control ctl) {
- char *path;
-#ifdef NEED_SECURE_DIRECTORY
- char *slash;
-
- path = savestr(ctl->var.v_unix.un.sun_path, 1);
-
- slash = strrchr(path, '/');
- if (slash != NULL) {
- if (slash != path)
- *slash = '\0';
- else {
- (void)freestr(path);
- path = savestr("/", 1);
- }
- } else {
- (void)freestr(path);
- path = savestr(".", 1);
- }
- if (mkdir(path, ctl->var.v_unix.mode) < 0) {
- if (errno != EEXIST) {
- ns_warning(ns_log_config,
- "unix control \"%s\" mkdir failed: %s",
- path, strerror(errno));
- }
- }
-#else
- path = ctl->var.v_unix.un.sun_path;
-#endif
-
- if (ctl->sctx == NULL) {
- unattach(ctl);
- ctl->sctx = mksrvr(ctl,
- (struct sockaddr *)&ctl->var.v_unix.un,
- sizeof ctl->var.v_unix.un);
- }
- if (ctl->sctx != NULL) {
- /* XXX Race condition. */
- if (chmod(path, ctl->var.v_unix.mode) < 0) {
- ns_warning(ns_log_config, "chmod(\"%s\", 0%03o): %s",
- ctl->var.v_unix.un.sun_path,
- ctl->var.v_unix.mode,
- strerror(errno));
- }
- if (chown(path, ctl->var.v_unix.owner,
- ctl->var.v_unix.group) < 0) {
- ns_warning(ns_log_config, "chown(\"%s\", %d, %d): %s",
- ctl->var.v_unix.un.sun_path,
- ctl->var.v_unix.owner,
- ctl->var.v_unix.group,
- strerror(errno));
- }
- }
-#ifdef NEED_SECURE_DIRECTORY
- (void)freestr(path);
-#endif
-}
-#endif
-
-static void
-logger(enum ctl_severity ctlsev, const char *format, ...) {
- va_list args;
- int logsev;
-
- switch (ctlsev) {
- case ctl_debug: logsev = log_debug(5); break;
- case ctl_warning: logsev = log_warning; break;
- case ctl_error: logsev = log_error; break;
- default: logsev = 0;
- panic("invalid ctlsev in logger", NULL);
- }
- if (!log_ctx_valid)
- return;
- va_start(args, format);
- log_vwrite(log_ctx, ns_log_control, logsev, format, args);
- va_end(args);
-}
-
-static void
-verb_connect(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- const struct sockaddr *sa = (const struct sockaddr *)respctx;
- control nsctl = (control)uctx;
-
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(rest);
- UNUSED(respflags);
-
- if (sa->sa_family == AF_INET) {
- const struct sockaddr_in *in = (const struct sockaddr_in *)sa;
- const ip_match_list acl = nsctl->var.v_inet.allow;
-
- if (!ip_address_allowed(acl, in->sin_addr)) {
- ctl_response(sess, 502, "Permission denied.",
- CTL_EXIT, NULL, NULL, NULL, NULL, 0);
- return;
- }
- }
- ctl_response(sess, 220, server_options->version, 0, NULL, NULL, NULL,
- NULL, 0);
-}
-
-static void
-verb_getpid(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- char *msg = memget(MAX_STR_LEN);
-
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(rest);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- if (msg == NULL) {
- ctl_response(sess, 503, "(out of memory)", 0,
- NULL, NULL, NULL, NULL, 0);
- return;
- }
- sprintf(msg, "my pid is <%ld>", (long)getpid());
- ctl_response(sess, 250, msg, 0, NULL, getpid_closure, msg, NULL, 0);
-}
-
-static void
-getpid_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) {
- char *msg = uap;
-
- UNUSED(sctx);
- UNUSED(sess);
-
- memput(msg, MAX_STR_LEN);
-}
-
-enum state {
- e_version = 0,
- e_config,
- e_nzones,
- e_debug,
- e_xfersrun,
- e_xfersdfr,
- e_qserials,
- e_qrylog,
- e_priming,
- e_finito
-};
-
-struct pvt_status {
- enum state state;
- char text[MAX_STR_LEN];
-};
-
-static void
-verb_status(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- struct pvt_status *pvt = ctl_getcsctx(sess);
-
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(rest);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- if (pvt == NULL) {
- pvt = memget(sizeof *pvt);
- if (pvt == NULL) {
- ctl_response(sess, 505, "(out of memory)",
- 0, NULL, NULL, NULL, NULL, 0);
- return;
- }
- pvt->state = (enum state)0;
- (void)ctl_setcsctx(sess, pvt);
- }
- switch (pvt->state++) {
- case e_version:
- strncpy(pvt->text, Version, sizeof pvt->text);
- pvt->text[sizeof pvt->text - 1] = '\0';
- break;
- case e_config:
- sprintf(pvt->text, "config (%s) last loaded at age: %24s",
- conffile, ctime(&confmtime));
- break;
- case e_nzones:
- sprintf(pvt->text, "number of zones allocated: %d", nzones);
- break;
- case e_debug:
- sprintf(pvt->text, "debug level: %d", debug);
- break;
- case e_xfersrun:
- sprintf(pvt->text, "xfers running: %d", xfers_running);
- break;
- case e_xfersdfr:
- sprintf(pvt->text, "xfers deferred: %d", xfers_deferred);
- break;
- case e_qserials:
- sprintf(pvt->text, "soa queries in progress: %d",
- qserials_running);
- break;
- case e_qrylog:
- sprintf(pvt->text, "query logging is %s",
- qrylog ? "ON" : "OFF");
- break;
- case e_priming:
- if (priming)
- sprintf(pvt->text, "server is initialising itself");
- else
- sprintf(pvt->text, "server is up and running");
- break;
- case e_finito:
- return;
- }
- ctl_response(sess, 250, pvt->text,
- (pvt->state == e_finito) ? 0 : CTL_MORE,
- NULL, status_closure, NULL, NULL, 0);
-}
-
-static void
-status_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) {
- struct pvt_status *pvt = ctl_getcsctx(sess);
-
- UNUSED(sctx);
- UNUSED(uap);
-
- memput(pvt, sizeof *pvt);
- ctl_setcsctx(sess, NULL);
-}
-
-static void
-verb_stop(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(rest);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- ns_need(main_need_exit);
- ctl_response(sess, 250, "Shutdown initiated.", 0, NULL, NULL, NULL,
- NULL, 0);
-}
-
-static void
-verb_exec(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- struct stat sb;
-
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- if (rest != NULL && *rest != '\0') {
- if (stat(rest, &sb) < 0) {
- ctl_response(sess, 503, strerror(errno),
- 0, NULL, NULL, NULL, NULL, 0);
- return;
- }
- saved_argv[0] = savestr(rest, 1); /* Never strfreed. */
- }
-
- if (stat(saved_argv[0], &sb) < 0) {
- const char *save = strerror(errno);
-
- ns_warning(ns_log_default, "can't exec, %s: %s",
- saved_argv[0], save);
- ctl_response(sess, 502, save, 0, NULL, NULL, NULL,
- NULL, 0);
- } else if (user_name != NULL || group_name != NULL) {
- ctl_response(sess, 502,
- "can't exec as user or group was specified",
- 0, NULL, NULL, NULL, NULL, 0);
- } else {
- ctl_response(sess, 250, "Restart initiated.", 0, NULL,
- exec_closure, NULL, NULL, 0);
- }
-}
-
-static void
-exec_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) {
-
- UNUSED(sctx);
- UNUSED(sess);
- UNUSED(uap);
- ns_need(main_need_restart);
-}
-
-static void
-verb_reload(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- static const char spaces[] = " \t";
- struct zoneinfo *zp;
- char *tmp = NULL, *x;
- const char *cl;
- const char *msg;
- int class, code, success;
-
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- /* If there are no args, this is a classic reload of the config. */
- if (rest == NULL || *rest == '\0') {
- ns_need(main_need_reload);
- code = 250;
- msg = "Reload initiated.";
- goto respond;
- }
-
- /* Look for optional zclass argument. Default is "in". */
- tmp = savestr(rest, 1);
- x = tmp + strcspn(tmp, spaces);
- if (*x != '\0') {
- *x++ = '\0';
- x += strspn(x, spaces);
- }
- cl = (x == NULL || *x == '\0') ? "in" : x;
- class = res_nametoclass(cl, &success);
- if (!success) {
- code = 507;
- msg = "unrecognized class";
- goto respond;
- }
-
- /* Look for the zone, and do the right thing to it. */
- zp = find_zone(tmp, class);
- if (zp == NULL) {
- code = 506;
- msg = "Zone not found.";
- goto respond;
- }
- switch (zp->z_type) {
- case z_master:
- ns_stopxfrs(zp);
- /*FALLTHROUGH*/
- case z_hint:
- block_signals();
- code = 251;
- msg = deferred_reload_unsafe(zp);
- unblock_signals();
- break;
- case z_slave:
- case z_stub:
- ns_stopxfrs(zp);
- if (zonefile_changed_p(zp))
- zp->z_serial = 0; /* force xfer */
- addxfer(zp);
- code = 251;
- msg = "Slave transfer queued.";
- goto respond;
- case z_forward:
- case z_cache:
- default:
- msg = "Non reloadable zone.";
- code = 507;
- break;
- }
-
- respond:
- ctl_response(sess, code, msg, 0, NULL, NULL, NULL, NULL, 0);
- if (tmp != NULL)
- (void)freestr(tmp);
-}
-
-static void
-verb_reconfig(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- if (strcmp(rest, "-noexpired") != 0)
- ns_need(main_need_reconfig);
- else
- ns_need(main_need_noexpired);
- ctl_response(sess, 250, "Reconfig initiated.",
- 0, NULL, NULL, NULL, NULL, 0);
-}
-
-static void
-verb_dumpdb(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(rest);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- ns_need(main_need_dump);
- ctl_response(sess, 250, "Database dump initiated.", 0, NULL,
- NULL, NULL, NULL, 0);
-}
-
-static void
-verb_stats(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- if (rest != NULL && strcmp(rest, "clear") == 0) {
- ns_need(main_need_statsdumpandclear);
- ctl_response(sess, 250, "Statistics dump and clear initiated.",
- 0, NULL, NULL, NULL, NULL, 0);
- } else {
- ns_need(main_need_statsdump);
- ctl_response(sess, 250, "Statistics dump initiated.",
- 0, NULL, NULL, NULL, NULL, 0);
- }
-}
-
-static void
-verb_trace(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- int i = atoi(rest);
- char *msg = memget(MAX_STR_LEN);
-
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- if (msg == NULL) {
- ctl_response(sess, 503, "(out of memory)", 0,
- NULL, NULL, NULL, NULL, 0);
- return;
- }
- if (isdigit(*(const unsigned char *)rest) && i >= 0)
- desired_debug = i;
- else
- desired_debug++;
- ns_need(main_need_debug);
- if (desired_debug == 0)
- sprintf(msg, "Debugging turned off.");
- else
- sprintf(msg, "Debug level: %d", desired_debug);
- ctl_response(sess, 250, msg, 0, NULL, trace_closure, msg, NULL, 0);
-}
-
-static void
-trace_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) {
- char *msg = uap;
-
- UNUSED(sctx);
- UNUSED(sess);
-
- memput(msg, MAX_STR_LEN);
-}
-
-static void
-verb_notrace(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(rest);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- desired_debug = 0;
- ns_need(main_need_debug);
- ctl_response(sess, 250, "Debugging turned off.",
- 0, NULL, NULL, NULL, NULL, 0);
-}
-
-static void
-verb_querylog(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- static const char on[] = "Query logging is now on.",
- off[] = "Query logging is now off.";
-
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(rest);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- toggle_qrylog();
- ctl_response(sess, 250, qrylog ? on : off,
- 0, NULL, NULL, NULL, NULL, 0);
-}
-
-static void
-verb_help(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(rest);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- ctl_sendhelp(sess, 214);
-}
-
-static void
-verb_quit(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(rest);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- ctl_response(sess, 221, "End of control session.", CTL_EXIT, NULL,
- NULL, NULL, NULL, 0);
-}
-
-static char hex[] = "0123456789abcdef";
-
-struct pvt_args {
- int argc;
- char text[MAX_STR_LEN];
-};
-
-static void
-args_closure(struct ctl_sctx *sctx, struct ctl_sess *sess, void *uap) {
- struct pvt_args *pvt = ctl_getcsctx(sess);
-
- UNUSED(sctx);
- UNUSED(uap);
-
- memput(pvt, sizeof *pvt);
- ctl_setcsctx(sess, NULL);
-}
-
-static void
-verb_args(struct ctl_sctx *ctl, struct ctl_sess *sess,
- const struct ctl_verb *verb, const char *rest,
- u_int respflags, const void *respctx, void *uctx)
-{
- struct pvt_args *pvt = ctl_getcsctx(sess);
- char *cp, *tp;
-
- UNUSED(ctl);
- UNUSED(verb);
- UNUSED(rest);
- UNUSED(respflags);
- UNUSED(respctx);
- UNUSED(uctx);
-
- if (pvt == NULL) {
- unsigned int i = 0;
- pvt = memget(sizeof *pvt);
- if (pvt == NULL) {
- ctl_response(sess, 505, "(out of memory)",
- 0, NULL, NULL, NULL, NULL, 0);
- return;
- }
- pvt->argc = 0;
- ctl_setcsctx(sess, pvt);
-
- /* Send the arguement count. */
- while (saved_argv[i] != NULL)
- i++;
- sprintf(pvt->text, "%u", i);
- ctl_response(sess, 250, pvt->text, CTL_MORE,
- NULL, args_closure, NULL, NULL, 0);
- return;
- }
-
- /*
- * Percent escape arguement.
- */
- cp = saved_argv[pvt->argc++];
- tp = pvt->text;
- while (cp && *cp != '\0')
- if (*cp == '%' || *cp == ' ' ||
- !isprint((unsigned char)*cp)) {
- if (tp >= pvt->text + sizeof(pvt->text) - 4)
- break;
- *tp++ = '%';
- *tp++ = hex[(*cp>>4)&0xf];
- *tp++ = hex[(*cp++)&0xf];
- } else {
- if (tp >= pvt->text + sizeof(pvt->text) - 2)
- break;
- *tp++ = *cp++;
- }
- *tp = '\0';
-
- ctl_response(sess, 250, pvt->text,
- saved_argv[pvt->argc] == NULL ? 0 : CTL_MORE,
- NULL, args_closure, NULL, NULL, 0);
-}
OpenPOWER on IntegriCloud