1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 **/
19 
20 #include "control.h"
21 #include "zbxdiag.h"
22 
parse_log_level_options(const char * opt,size_t len,unsigned int * scope,unsigned int * data)23 static int	parse_log_level_options(const char *opt, size_t len, unsigned int *scope, unsigned int *data)
24 {
25 	unsigned short	num = 0;
26 	const char	*rtc_options;
27 
28 	rtc_options = opt + len;
29 
30 	if ('\0' == *rtc_options)
31 	{
32 		*scope = ZBX_RTC_LOG_SCOPE_FLAG | ZBX_RTC_LOG_SCOPE_PID;
33 		*data = 0;
34 	}
35 	else if ('=' != *rtc_options)
36 	{
37 		zbx_error("invalid runtime control option: %s", opt);
38 		return FAIL;
39 	}
40 	else if (0 != isdigit(*(++rtc_options)))
41 	{
42 		/* convert PID */
43 		if (FAIL == is_ushort(rtc_options, &num) || 0 == num)
44 		{
45 			zbx_error("invalid log level control target: invalid or unsupported process identifier");
46 			return FAIL;
47 		}
48 
49 		*scope = ZBX_RTC_LOG_SCOPE_FLAG | ZBX_RTC_LOG_SCOPE_PID;
50 		*data = num;
51 	}
52 	else
53 	{
54 		char	*proc_name = NULL, *proc_num;
55 		int	proc_type;
56 
57 		if ('\0' == *rtc_options)
58 		{
59 			zbx_error("invalid log level control target: unspecified process identifier or type");
60 			return FAIL;
61 		}
62 
63 		proc_name = zbx_strdup(proc_name, rtc_options);
64 
65 		if (NULL != (proc_num = strchr(proc_name, ',')))
66 			*proc_num++ = '\0';
67 
68 		if ('\0' == *proc_name)
69 		{
70 			zbx_error("invalid log level control target: unspecified process type");
71 			zbx_free(proc_name);
72 			return FAIL;
73 		}
74 
75 		if (ZBX_PROCESS_TYPE_UNKNOWN == (proc_type = get_process_type_by_name(proc_name)))
76 		{
77 			zbx_error("invalid log level control target: unknown process type \"%s\"", proc_name);
78 			zbx_free(proc_name);
79 			return FAIL;
80 		}
81 
82 		if (NULL != proc_num)
83 		{
84 			if ('\0' == *proc_num)
85 			{
86 				zbx_error("invalid log level control target: unspecified process number");
87 				zbx_free(proc_name);
88 				return FAIL;
89 			}
90 
91 			/* convert Zabbix process number (e.g. "2" in "poller,2") */
92 			if (FAIL == is_ushort(proc_num, &num) || 0 == num)
93 			{
94 				zbx_error("invalid log level control target: invalid or unsupported process number"
95 						" \"%s\"", proc_num);
96 				zbx_free(proc_name);
97 				return FAIL;
98 			}
99 		}
100 
101 		zbx_free(proc_name);
102 
103 		*scope = ZBX_RTC_LOG_SCOPE_PROC | (unsigned int)proc_type;
104 		*data = num;
105 	}
106 
107 	return SUCCEED;
108 }
109 
110 /******************************************************************************
111  *                                                                            *
112  * Function: parse_rtc_options                                                *
113  *                                                                            *
114  * Purpose: parse runtime control options and create a runtime control        *
115  *          message                                                           *
116  *                                                                            *
117  * Parameters: opt          - [IN] the command line argument                  *
118  *             program_type - [IN] the program type                           *
119  *             message      - [OUT] the message containing options for log    *
120  *                                  level change or cache reload              *
121  *                                                                            *
122  * Return value: SUCCEED - the message was created successfully               *
123  *               FAIL    - an error occurred                                  *
124  *                                                                            *
125  ******************************************************************************/
parse_rtc_options(const char * opt,unsigned char program_type,int * message)126 int	parse_rtc_options(const char *opt, unsigned char program_type, int *message)
127 {
128 	unsigned int	scope, data, command;
129 
130 	if (0 == strncmp(opt, ZBX_LOG_LEVEL_INCREASE, ZBX_CONST_STRLEN(ZBX_LOG_LEVEL_INCREASE)))
131 	{
132 		command = ZBX_RTC_LOG_LEVEL_INCREASE;
133 
134 		if (SUCCEED != parse_log_level_options(opt, ZBX_CONST_STRLEN(ZBX_LOG_LEVEL_INCREASE), &scope, &data))
135 			return FAIL;
136 	}
137 	else if (0 == strncmp(opt, ZBX_LOG_LEVEL_DECREASE, ZBX_CONST_STRLEN(ZBX_LOG_LEVEL_DECREASE)))
138 	{
139 		command = ZBX_RTC_LOG_LEVEL_DECREASE;
140 
141 		if (SUCCEED != parse_log_level_options(opt, ZBX_CONST_STRLEN(ZBX_LOG_LEVEL_DECREASE), &scope, &data))
142 			return FAIL;
143 	}
144 	else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER | ZBX_PROGRAM_TYPE_PROXY)) &&
145 			0 == strcmp(opt, ZBX_CONFIG_CACHE_RELOAD))
146 	{
147 		command = ZBX_RTC_CONFIG_CACHE_RELOAD;
148 		scope = 0;
149 		data = 0;
150 	}
151 	else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER | ZBX_PROGRAM_TYPE_PROXY)) &&
152 			0 == strcmp(opt, ZBX_HOUSEKEEPER_EXECUTE))
153 	{
154 		command = ZBX_RTC_HOUSEKEEPER_EXECUTE;
155 		scope = 0;
156 		data = 0;
157 	}
158 	else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER | ZBX_PROGRAM_TYPE_PROXY)) &&
159 			0 == strcmp(opt, ZBX_SNMP_CACHE_RELOAD))
160 	{
161 #ifdef HAVE_NETSNMP
162 		command = ZBX_RTC_SNMP_CACHE_RELOAD;
163 		/* Scope is ignored for SNMP. R/U pollers, trapper, discoverer and taskmanager always get targeted. */
164 		scope = 0;
165 		data = 0;
166 #else
167 		zbx_error("invalid runtime control option: no SNMP support enabled");
168 		return FAIL;
169 #endif
170 	}
171 	else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER | ZBX_PROGRAM_TYPE_PROXY)) &&
172 			0 == strncmp(opt, ZBX_DIAGINFO, ZBX_CONST_STRLEN(ZBX_DIAGINFO)))
173 	{
174 		command = ZBX_RTC_DIAGINFO;
175 		data = 0;
176 		scope = ZBX_DIAGINFO_ALL;
177 
178 		if ('=' == opt[ZBX_CONST_STRLEN(ZBX_DIAGINFO)])
179 		{
180 			const char	*section = opt + ZBX_CONST_STRLEN(ZBX_DIAGINFO) + 1;
181 
182 			if (0 == strcmp(section, ZBX_DIAG_HISTORYCACHE))
183 			{
184 				scope = ZBX_DIAGINFO_HISTORYCACHE;
185 			}
186 			else if (0 == strcmp(section, ZBX_DIAG_PREPROCESSING))
187 			{
188 				scope = ZBX_DIAGINFO_PREPROCESSING;
189 			}
190 			else if (0 == strcmp(section, ZBX_DIAG_LOCKS))
191 			{
192 				scope = ZBX_DIAGINFO_LOCKS;
193 			}
194 			else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER)))
195 			{
196 				if (0 == strcmp(section, ZBX_DIAG_VALUECACHE))
197 					scope = ZBX_DIAGINFO_VALUECACHE;
198 				else if (0 == strcmp(section, ZBX_DIAG_LLD))
199 					scope = ZBX_DIAGINFO_LLD;
200 				else if (0 == strcmp(section, ZBX_DIAG_ALERTING))
201 					scope = ZBX_DIAGINFO_ALERTING;
202 			}
203 
204 			if (0 == scope)
205 			{
206 				zbx_error("invalid diaginfo section: %s", section);
207 				return FAIL;
208 			}
209 		}
210 		else if ('\0' != opt[ZBX_CONST_STRLEN(ZBX_DIAGINFO)])
211 		{
212 			zbx_error("invalid runtime control option: %s", opt);
213 			return FAIL;
214 		}
215 	}
216 	else if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER) && 0 == strcmp(opt, ZBX_SECRETS_RELOAD))
217 	{
218 		command = ZBX_RTC_SECRETS_RELOAD;
219 		scope = 0;
220 		data = 0;
221 	}
222 	else
223 	{
224 		zbx_error("invalid runtime control option: %s", opt);
225 		return FAIL;
226 	}
227 
228 	*message = (int)ZBX_RTC_MAKE_MESSAGE(command, scope, data);
229 
230 	return SUCCEED;
231 }
232