xref: /minix3/external/bsd/bind/dist/bin/named/control.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1 /*	$NetBSD: control.c,v 1.8 2014/12/10 04:37:51 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004-2007, 2009-2014  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 2001-2003  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id: control.c,v 1.49 2012/01/31 23:47:31 tbox Exp  */
21 
22 /*! \file */
23 
24 #include <config.h>
25 
26 
27 #include <isc/app.h>
28 #include <isc/event.h>
29 #include <isc/mem.h>
30 #include <isc/string.h>
31 #include <isc/timer.h>
32 #include <isc/util.h>
33 
34 #include <dns/result.h>
35 
36 #include <isccc/alist.h>
37 #include <isccc/cc.h>
38 #include <isccc/result.h>
39 
40 #include <named/control.h>
41 #include <named/log.h>
42 #include <named/os.h>
43 #include <named/server.h>
44 #ifdef HAVE_LIBSCF
45 #include <named/ns_smf_globals.h>
46 #endif
47 
48 static isc_boolean_t
command_compare(const char * text,const char * command)49 command_compare(const char *text, const char *command) {
50 	unsigned int commandlen = strlen(command);
51 	if (strncasecmp(text, command, commandlen) == 0 &&
52 	    (text[commandlen] == '\0' ||
53 	     text[commandlen] == ' ' ||
54 	     text[commandlen] == '\t'))
55 		return (ISC_TRUE);
56 	return (ISC_FALSE);
57 }
58 
59 /*%
60  * This function is called to process the incoming command
61  * when a control channel message is received.
62  */
63 isc_result_t
ns_control_docommand(isccc_sexpr_t * message,isc_buffer_t * text)64 ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
65 	isccc_sexpr_t *data;
66 	char *command = NULL;
67 	isc_result_t result;
68 	int log_level;
69 #ifdef HAVE_LIBSCF
70 	ns_smf_want_disable = 0;
71 #endif
72 
73 	data = isccc_alist_lookup(message, "_data");
74 	if (data == NULL) {
75 		/*
76 		 * No data section.
77 		 */
78 		return (ISC_R_FAILURE);
79 	}
80 
81 	result = isccc_cc_lookupstring(data, "type", &command);
82 	if (result != ISC_R_SUCCESS) {
83 		/*
84 		 * We have no idea what this is.
85 		 */
86 		return (result);
87 	}
88 
89 	/*
90 	 * Compare the 'command' parameter against all known control commands.
91 	 */
92 	if (command_compare(command, NS_COMMAND_NULL) ||
93 	    command_compare(command, NS_COMMAND_STATUS)) {
94 		log_level = ISC_LOG_DEBUG(1);
95 	} else {
96 		log_level = ISC_LOG_INFO;
97 	}
98 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
99 		      NS_LOGMODULE_CONTROL, log_level,
100 		      "received control channel command '%s'",
101 		      command);
102 
103 	if (command_compare(command, NS_COMMAND_RELOAD)) {
104 		result = ns_server_reloadcommand(ns_g_server, command, text);
105 	} else if (command_compare(command, NS_COMMAND_RECONFIG)) {
106 		result = ns_server_reconfigcommand(ns_g_server, command);
107 	} else if (command_compare(command, NS_COMMAND_REFRESH)) {
108 		result = ns_server_refreshcommand(ns_g_server, command, text);
109 	} else if (command_compare(command, NS_COMMAND_RETRANSFER)) {
110 		result = ns_server_retransfercommand(ns_g_server,
111 						     command, text);
112 	} else if (command_compare(command, NS_COMMAND_HALT)) {
113 #ifdef HAVE_LIBSCF
114 		/*
115 		 * If we are managed by smf(5), AND in chroot, then
116 		 * we cannot connect to the smf repository, so just
117 		 * return with an appropriate message back to rndc.
118 		 */
119 		if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
120 			result = ns_smf_add_message(text);
121 			return (result);
122 		}
123 		/*
124 		 * If we are managed by smf(5) but not in chroot,
125 		 * try to disable ourselves the smf way.
126 		 */
127 		if (ns_smf_got_instance == 1 && ns_smf_chroot == 0)
128 			ns_smf_want_disable = 1;
129 		/*
130 		 * If ns_smf_got_instance = 0, ns_smf_chroot
131 		 * is not relevant and we fall through to
132 		 * isc_app_shutdown below.
133 		 */
134 #endif
135 		/* Do not flush master files */
136 		ns_server_flushonshutdown(ns_g_server, ISC_FALSE);
137 		ns_os_shutdownmsg(command, text);
138 		isc_app_shutdown();
139 		result = ISC_R_SUCCESS;
140 	} else if (command_compare(command, NS_COMMAND_STOP)) {
141 		/*
142 		 * "stop" is the same as "halt" except it does
143 		 * flush master files.
144 		 */
145 #ifdef HAVE_LIBSCF
146 		if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
147 			result = ns_smf_add_message(text);
148 			return (result);
149 		}
150 		if (ns_smf_got_instance == 1 && ns_smf_chroot == 0)
151 			ns_smf_want_disable = 1;
152 #endif
153 		ns_server_flushonshutdown(ns_g_server, ISC_TRUE);
154 		ns_os_shutdownmsg(command, text);
155 		isc_app_shutdown();
156 		result = ISC_R_SUCCESS;
157 	} else if (command_compare(command, NS_COMMAND_DUMPSTATS)) {
158 		result = ns_server_dumpstats(ns_g_server);
159 	} else if (command_compare(command, NS_COMMAND_QUERYLOG)) {
160 		result = ns_server_togglequerylog(ns_g_server, command);
161 	} else if (command_compare(command, NS_COMMAND_DUMPDB)) {
162 		ns_server_dumpdb(ns_g_server, command);
163 		result = ISC_R_SUCCESS;
164 	} else if (command_compare(command, NS_COMMAND_SECROOTS)) {
165 		result = ns_server_dumpsecroots(ns_g_server, command);
166 	} else if (command_compare(command, NS_COMMAND_TRACE)) {
167 		result = ns_server_setdebuglevel(ns_g_server, command);
168 	} else if (command_compare(command, NS_COMMAND_NOTRACE)) {
169 		ns_g_debuglevel = 0;
170 		isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
171 		result = ISC_R_SUCCESS;
172 	} else if (command_compare(command, NS_COMMAND_FLUSH)) {
173 		result = ns_server_flushcache(ns_g_server, command);
174 	} else if (command_compare(command, NS_COMMAND_FLUSHNAME)) {
175 		result = ns_server_flushnode(ns_g_server, command, ISC_FALSE);
176 	} else if (command_compare(command, NS_COMMAND_FLUSHTREE)) {
177 		result = ns_server_flushnode(ns_g_server, command, ISC_TRUE);
178 	} else if (command_compare(command, NS_COMMAND_STATUS)) {
179 		result = ns_server_status(ns_g_server, text);
180 	} else if (command_compare(command, NS_COMMAND_TSIGLIST)) {
181 		result = ns_server_tsiglist(ns_g_server, text);
182 	} else if (command_compare(command, NS_COMMAND_TSIGDELETE)) {
183 		result = ns_server_tsigdelete(ns_g_server, command, text);
184 	} else if (command_compare(command, NS_COMMAND_FREEZE)) {
185 		result = ns_server_freeze(ns_g_server, ISC_TRUE, command,
186 					  text);
187 	} else if (command_compare(command, NS_COMMAND_UNFREEZE) ||
188 		   command_compare(command, NS_COMMAND_THAW)) {
189 		result = ns_server_freeze(ns_g_server, ISC_FALSE, command,
190 					  text);
191 	} else if (command_compare(command, NS_COMMAND_SCAN)) {
192 		result = ISC_R_SUCCESS;
193 		ns_server_scan_interfaces(ns_g_server);
194 	} else if (command_compare(command, NS_COMMAND_SYNC)) {
195 		result = ns_server_sync(ns_g_server, command, text);
196 	} else if (command_compare(command, NS_COMMAND_RECURSING)) {
197 		result = ns_server_dumprecursing(ns_g_server);
198 	} else if (command_compare(command, NS_COMMAND_TIMERPOKE)) {
199 		result = ISC_R_SUCCESS;
200 		isc_timermgr_poke(ns_g_timermgr);
201 	} else if (command_compare(command, NS_COMMAND_NULL)) {
202 		result = ISC_R_SUCCESS;
203 	} else if (command_compare(command, NS_COMMAND_NOTIFY)) {
204 		result = ns_server_notifycommand(ns_g_server, command, text);
205 	} else if (command_compare(command, NS_COMMAND_VALIDATION)) {
206 		result = ns_server_validation(ns_g_server, command, text);
207 	} else if (command_compare(command, NS_COMMAND_SIGN) ||
208 		   command_compare(command, NS_COMMAND_LOADKEYS)) {
209 		result = ns_server_rekey(ns_g_server, command, text);
210 	} else if (command_compare(command, NS_COMMAND_ADDZONE)) {
211 		result = ns_server_add_zone(ns_g_server, command, text);
212 	} else if (command_compare(command, NS_COMMAND_DELZONE)) {
213 		result = ns_server_del_zone(ns_g_server, command, text);
214 	} else if (command_compare(command, NS_COMMAND_SIGNING)) {
215 		result = ns_server_signing(ns_g_server, command, text);
216 	} else if (command_compare(command, NS_COMMAND_ZONESTATUS)) {
217 		result = ns_server_zonestatus(ns_g_server, command, text);
218 	} else {
219 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
220 			      NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
221 			      "unknown control channel command '%s'",
222 			      command);
223 		result = DNS_R_UNKNOWNCOMMAND;
224 	}
225 
226 	return (result);
227 }
228