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