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 "common.h"
21 #include "checks_internal.h"
22 #include "checks_java.h"
23 #include "dbcache.h"
24 #include "zbxself.h"
25 #include "valuecache.h"
26 #include "proxy.h"
27 #include "preproc.h"
28 
29 #include "../vmware/vmware.h"
30 #include "../../libs/zbxserver/zabbix_stats.h"
31 #include "../../libs/zbxsysinfo/common/zabbix_stats.h"
32 
33 extern unsigned char	program_type;
34 
compare_interfaces(const void * p1,const void * p2)35 static int	compare_interfaces(const void *p1, const void *p2)
36 {
37 	const DC_INTERFACE2	*i1 = (DC_INTERFACE2 *)p1, *i2 = (DC_INTERFACE2 *)p2;
38 
39 	if (i1->type > i2->type)		/* 1st criterion: 'type' in ascending order */
40 		return 1;
41 
42 	if (i1->type < i2->type)
43 		return -1;
44 
45 	if (i1->main > i2->main)		/* 2nd criterion: 'main' in descending order */
46 		return -1;
47 
48 	if (i1->main < i2->main)
49 		return 1;
50 
51 	if (i1->interfaceid > i2->interfaceid)	/* 3rd criterion: 'interfaceid' in ascending order */
52 		return 1;
53 
54 	if (i1->interfaceid < i2->interfaceid)
55 		return -1;
56 
57 	return 0;
58 }
59 
60 /******************************************************************************
61  *                                                                            *
62  * Function: zbx_host_interfaces_discovery                                    *
63  *                                                                            *
64  * Purpose: get data of all network interfaces for a host from configuration  *
65  *          cache and pack into JSON for LLD                                  *
66  *                                                                            *
67  * Parameter: hostid - [IN] the host identifier                               *
68  *            j      - [OUT] JSON with interface data                         *
69  *            error  - [OUT] error message                                    *
70  *                                                                            *
71  * Return value: SUCCEED - interface data in JSON                             *
72  *               FAIL    - host not found, 'error' message allocated          *
73  *                                                                            *
74  * Comments: if host is found but has no interfaces (should not happen) an    *
75  *           empty JSON {"data":[]} is returned                               *
76  *                                                                            *
77  ******************************************************************************/
zbx_host_interfaces_discovery(zbx_uint64_t hostid,struct zbx_json * j,char ** error)78 static int	zbx_host_interfaces_discovery(zbx_uint64_t hostid, struct zbx_json *j, char **error)
79 {
80 	DC_INTERFACE2	*interfaces = NULL;
81 	int		n = 0;			/* number of interfaces */
82 	int		i;
83 
84 	/* get interface data from configuration cache */
85 
86 	if (SUCCEED != zbx_dc_get_host_interfaces(hostid, &interfaces, &n))
87 	{
88 		*error = zbx_strdup(*error, "host not found in configuration cache");
89 
90 		return FAIL;
91 	}
92 
93 	/* sort results in a predictable order */
94 
95 	if (1 < n)
96 		qsort(interfaces, (size_t)n, sizeof(DC_INTERFACE2), compare_interfaces);
97 
98 	/* repair 'addr' pointers broken by sorting */
99 
100 	for (i = 0; i < n; i++)
101 		interfaces[i].addr = (1 == interfaces[i].useip ? interfaces[i].ip_orig : interfaces[i].dns_orig);
102 
103 	/* pack results into JSON */
104 
105 	zbx_json_init(j, ZBX_JSON_STAT_BUF_LEN);
106 	zbx_json_addarray(j, ZBX_PROTO_TAG_DATA);
107 
108 	for (i = 0; i < n; i++)
109 	{
110 		const char	*p;
111 		char		buf[16];
112 
113 		zbx_json_addobject(j, NULL);
114 		zbx_json_addstring(j, "{#IF.CONN}", interfaces[i].addr, ZBX_JSON_TYPE_STRING);
115 		zbx_json_addstring(j, "{#IF.IP}", interfaces[i].ip_orig, ZBX_JSON_TYPE_STRING);
116 		zbx_json_addstring(j, "{#IF.DNS}", interfaces[i].dns_orig, ZBX_JSON_TYPE_STRING);
117 		zbx_json_addstring(j, "{#IF.PORT}", interfaces[i].port_orig, ZBX_JSON_TYPE_STRING);
118 
119 		switch (interfaces[i].type)
120 		{
121 			case INTERFACE_TYPE_AGENT:
122 				p = "AGENT";
123 				break;
124 			case INTERFACE_TYPE_SNMP:
125 				p = "SNMP";
126 				break;
127 			case INTERFACE_TYPE_IPMI:
128 				p = "IPMI";
129 				break;
130 			case INTERFACE_TYPE_JMX:
131 				p = "JMX";
132 				break;
133 			case INTERFACE_TYPE_UNKNOWN:
134 			default:
135 				p = "UNKNOWN";
136 		}
137 		zbx_json_addstring(j, "{#IF.TYPE}", p, ZBX_JSON_TYPE_STRING);
138 
139 		zbx_snprintf(buf, sizeof(buf), "%hhu", interfaces[i].main);
140 		zbx_json_addstring(j, "{#IF.DEFAULT}", buf, ZBX_JSON_TYPE_INT);
141 
142 		if (INTERFACE_TYPE_SNMP == interfaces[i].type)
143 		{
144 			zbx_snprintf(buf, sizeof(buf), "%hhu", interfaces[i].bulk);
145 			zbx_json_addstring(j, "{#IF.SNMP.BULK}", buf, ZBX_JSON_TYPE_INT);
146 		}
147 
148 		zbx_json_close(j);
149 	}
150 
151 	zbx_json_close(j);
152 
153 	zbx_free(interfaces);
154 
155 	return SUCCEED;
156 }
157 
158 /******************************************************************************
159  *                                                                            *
160  * Function: get_value_internal                                               *
161  *                                                                            *
162  * Purpose: retrieve data from Zabbix server (internally supported items)     *
163  *                                                                            *
164  * Parameters: item - item we are interested in                               *
165  *                                                                            *
166  * Return value: SUCCEED - data successfully retrieved and stored in result   *
167  *               NOTSUPPORTED - requested item is not supported               *
168  *                                                                            *
169  * Author: Alexei Vladishev                                                   *
170  *                                                                            *
171  ******************************************************************************/
get_value_internal(DC_ITEM * item,AGENT_RESULT * result)172 int	get_value_internal(DC_ITEM *item, AGENT_RESULT *result)
173 {
174 	AGENT_REQUEST	request;
175 	int		ret = NOTSUPPORTED, nparams;
176 	const char	*tmp, *tmp1;
177 
178 	init_request(&request);
179 
180 	if (SUCCEED != parse_item_key(item->key, &request))
181 	{
182 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key format."));
183 		goto out;
184 	}
185 
186 	if (0 != strcmp("zabbix", get_rkey(&request)))
187 	{
188 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Unsupported item key for this item type."));
189 		goto out;
190 	}
191 
192 	/* NULL check to silence analyzer warning */
193 	if (0 == (nparams = get_rparams_num(&request)) || NULL == (tmp = get_rparam(&request, 0)))
194 	{
195 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
196 		goto out;
197 	}
198 
199 	if (0 == strcmp(tmp, "triggers"))			/* zabbix["triggers"] */
200 	{
201 		if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
202 			goto out;
203 
204 		if (1 != nparams)
205 		{
206 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
207 			goto out;
208 		}
209 
210 		SET_UI64_RESULT(result, DCget_trigger_count());
211 	}
212 	else if (0 == strcmp(tmp, "items"))			/* zabbix["items"] */
213 	{
214 		if (1 != nparams)
215 		{
216 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
217 			goto out;
218 		}
219 
220 		SET_UI64_RESULT(result, DCget_item_count(0));
221 	}
222 	else if (0 == strcmp(tmp, "items_unsupported"))		/* zabbix["items_unsupported"] */
223 	{
224 		if (1 != nparams)
225 		{
226 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
227 			goto out;
228 		}
229 
230 		SET_UI64_RESULT(result, DCget_item_unsupported_count(0));
231 	}
232 	else if (0 == strcmp(tmp, "hosts"))			/* zabbix["hosts"] */
233 	{
234 		if (1 != nparams)
235 		{
236 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
237 			goto out;
238 		}
239 
240 		SET_UI64_RESULT(result, DCget_host_count());
241 	}
242 	else if (0 == strcmp(tmp, "history") ||			/* zabbix["history"] */
243 			0 == strcmp(tmp, "history_log") ||	/* zabbix["history_log"] */
244 			0 == strcmp(tmp, "history_str") ||	/* zabbix["history_str"] */
245 			0 == strcmp(tmp, "history_text") ||	/* zabbix["history_text"] */
246 			0 == strcmp(tmp, "history_uint"))	/* zabbix["history_uint"] */
247 	{
248 		if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
249 			goto out;
250 
251 		if (1 != nparams)
252 		{
253 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
254 			goto out;
255 		}
256 
257 		SET_UI64_RESULT(result, DBget_row_count(tmp));
258 	}
259 	else if (0 == strcmp(tmp, "trends") ||			/* zabbix["trends"] */
260 			0 == strcmp(tmp, "trends_uint"))	/* zabbix["trends_uint"] */
261 	{
262 		if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
263 			goto out;
264 
265 		if (1 != nparams)
266 		{
267 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
268 			goto out;
269 		}
270 
271 		SET_UI64_RESULT(result, DBget_row_count(tmp));
272 	}
273 	else if (0 == strcmp(tmp, "queue"))			/* zabbix["queue",<from>,<to>] */
274 	{
275 		int	from = ZBX_QUEUE_FROM_DEFAULT, to = ZBX_QUEUE_TO_INFINITY;
276 
277 		if (3 < nparams)
278 		{
279 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
280 			goto out;
281 		}
282 
283 		if (NULL != (tmp = get_rparam(&request, 1)) && '\0' != *tmp &&
284 				FAIL == is_time_suffix(tmp, &from, ZBX_LENGTH_UNLIMITED))
285 		{
286 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
287 			goto out;
288 		}
289 
290 		if (NULL != (tmp = get_rparam(&request, 2)) && '\0' != *tmp &&
291 				FAIL == is_time_suffix(tmp, &to, ZBX_LENGTH_UNLIMITED))
292 		{
293 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
294 			goto out;
295 		}
296 
297 		if (ZBX_QUEUE_TO_INFINITY != to && from > to)
298 		{
299 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Parameters represent an invalid interval."));
300 			goto out;
301 		}
302 
303 		SET_UI64_RESULT(result, DCget_item_queue(NULL, from, to));
304 	}
305 	else if (0 == strcmp(tmp, "requiredperformance"))	/* zabbix["requiredperformance"] */
306 	{
307 		if (1 != nparams)
308 		{
309 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
310 			goto out;
311 		}
312 
313 		SET_DBL_RESULT(result, DCget_required_performance());
314 	}
315 	else if (0 == strcmp(tmp, "uptime"))			/* zabbix["uptime"] */
316 	{
317 		if (1 != nparams)
318 		{
319 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
320 			goto out;
321 		}
322 
323 		SET_UI64_RESULT(result, time(NULL) - CONFIG_SERVER_STARTUP_TIME);
324 	}
325 	else if (0 == strcmp(tmp, "boottime"))			/* zabbix["boottime"] */
326 	{
327 		if (1 != nparams)
328 		{
329 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
330 			goto out;
331 		}
332 
333 		SET_UI64_RESULT(result, CONFIG_SERVER_STARTUP_TIME);
334 	}
335 	else if (0 == strcmp(tmp, "host"))			/* zabbix["host",*] */
336 	{
337 		if (3 != nparams)
338 		{
339 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
340 			goto out;
341 		}
342 
343 		tmp = get_rparam(&request, 2);
344 
345 		if (0 == strcmp(tmp, "available"))		/* zabbix["host",<type>,"available"] */
346 		{
347 			tmp = get_rparam(&request, 1);
348 
349 			if (0 == strcmp(tmp, "agent"))
350 				SET_UI64_RESULT(result, item->host.available);
351 			else if (0 == strcmp(tmp, "snmp"))
352 				SET_UI64_RESULT(result, item->host.snmp_available);
353 			else if (0 == strcmp(tmp, "ipmi"))
354 				SET_UI64_RESULT(result, item->host.ipmi_available);
355 			else if (0 == strcmp(tmp, "jmx"))
356 				SET_UI64_RESULT(result, item->host.jmx_available);
357 			else
358 			{
359 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
360 				goto out;
361 			}
362 
363 			result->ui64 = 2 - result->ui64;
364 		}
365 		else if (0 == strcmp(tmp, "maintenance"))	/* zabbix["host",,"maintenance"] */
366 		{
367 			/* this item is always processed by server */
368 			if (NULL != (tmp = get_rparam(&request, 1)) && '\0' != *tmp)
369 			{
370 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
371 				goto out;
372 			}
373 
374 			if (HOST_MAINTENANCE_STATUS_ON == item->host.maintenance_status)
375 				SET_UI64_RESULT(result, item->host.maintenance_type + 1);
376 			else
377 				SET_UI64_RESULT(result, 0);
378 		}
379 		else if (0 == strcmp(tmp, "items"))	/* zabbix["host",,"items"] */
380 		{
381 			/* this item is always processed by server */
382 			if (NULL != (tmp = get_rparam(&request, 1)) && '\0' != *tmp)
383 			{
384 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
385 				goto out;
386 			}
387 
388 			SET_UI64_RESULT(result, DCget_item_count(item->host.hostid));
389 		}
390 		else if (0 == strcmp(tmp, "items_unsupported"))	/* zabbix["host",,"items_unsupported"] */
391 		{
392 			/* this item is always processed by server */
393 			if (NULL != (tmp = get_rparam(&request, 1)) && '\0' != *tmp)
394 			{
395 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
396 				goto out;
397 			}
398 
399 			SET_UI64_RESULT(result, DCget_item_unsupported_count(item->host.hostid));
400 		}
401 		else if (0 == strcmp(tmp, "interfaces"))	/* zabbix["host","discovery","interfaces"] */
402 		{
403 			struct zbx_json	j;
404 			char		*error = NULL;
405 
406 			/* this item is always processed by server */
407 			if (NULL == (tmp = get_rparam(&request, 1)) || 0 != strcmp(tmp, "discovery"))
408 			{
409 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
410 				goto out;
411 			}
412 
413 			if (SUCCEED != zbx_host_interfaces_discovery(item->host.hostid, &j, &error))
414 			{
415 				SET_MSG_RESULT(result, error);
416 				goto out;
417 			}
418 
419 			SET_STR_RESULT(result, zbx_strdup(NULL, j.buffer));
420 
421 			zbx_json_free(&j);
422 		}
423 		else
424 		{
425 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
426 			goto out;
427 		}
428 	}
429 	else if (0 == strcmp(tmp, "proxy"))			/* zabbix["proxy",<hostname>,"lastaccess"] */
430 	{
431 		int	lastaccess;
432 		char	*error = NULL;
433 
434 		/* this item is always processed by server */
435 
436 		if (3 != nparams)
437 		{
438 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
439 			goto out;
440 		}
441 
442 		tmp = get_rparam(&request, 2);
443 		if ('\0' == *tmp || 0 != strcmp(tmp, "lastaccess"))
444 		{
445 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
446 			goto out;
447 		}
448 
449 		if (FAIL == DBget_proxy_lastaccess(get_rparam(&request, 1), &lastaccess, &error))
450 		{
451 			SET_MSG_RESULT(result, error);
452 			goto out;
453 		}
454 
455 		SET_UI64_RESULT(result, lastaccess);
456 	}
457 	else if (0 == strcmp(tmp, "java"))			/* zabbix["java",...] */
458 	{
459 		int	res;
460 
461 		zbx_alarm_on(CONFIG_TIMEOUT);
462 		res = get_value_java(ZBX_JAVA_GATEWAY_REQUEST_INTERNAL, item, result);
463 		zbx_alarm_off();
464 
465 		if (SUCCEED != res)
466 		{
467 			tmp1 = get_rparam(&request, 2);
468 			/* the default error code "NOTSUPPORTED" renders nodata() trigger function nonfunctional */
469 			if (NULL != tmp1 && 0 == strcmp(tmp1, "ping"))
470 				ret = GATEWAY_ERROR;
471 			goto out;
472 		}
473 	}
474 	else if (0 == strcmp(tmp, "process"))			/* zabbix["process",<type>,<mode>,<state>] */
475 	{
476 		unsigned char	process_type = ZBX_PROCESS_TYPE_UNKNOWN;
477 		int		process_forks;
478 		double		value;
479 
480 		if (2 > nparams || nparams > 4)
481 		{
482 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
483 			goto out;
484 		}
485 
486 		process_type = get_process_type_by_name(get_rparam(&request, 1));
487 
488 		switch (process_type)
489 		{
490 			case ZBX_PROCESS_TYPE_ALERTMANAGER:
491 			case ZBX_PROCESS_TYPE_ALERTER:
492 			case ZBX_PROCESS_TYPE_ESCALATOR:
493 			case ZBX_PROCESS_TYPE_PROXYPOLLER:
494 			case ZBX_PROCESS_TYPE_TIMER:
495 				if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
496 					process_type = ZBX_PROCESS_TYPE_UNKNOWN;
497 				break;
498 			case ZBX_PROCESS_TYPE_DATASENDER:
499 			case ZBX_PROCESS_TYPE_HEARTBEAT:
500 				if (0 == (program_type & ZBX_PROGRAM_TYPE_PROXY))
501 					process_type = ZBX_PROCESS_TYPE_UNKNOWN;
502 				break;
503 		}
504 
505 		if (ZBX_PROCESS_TYPE_UNKNOWN == process_type)
506 		{
507 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
508 			goto out;
509 		}
510 
511 		process_forks = get_process_type_forks(process_type);
512 
513 		if (NULL == (tmp = get_rparam(&request, 2)))
514 			tmp = "";
515 
516 		if (0 == strcmp(tmp, "count"))
517 		{
518 			if (4 == nparams)
519 			{
520 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
521 				goto out;
522 			}
523 
524 			SET_UI64_RESULT(result, process_forks);
525 		}
526 		else
527 		{
528 			unsigned char	aggr_func, state;
529 			unsigned short	process_num = 0;
530 
531 			if ('\0' == *tmp || 0 == strcmp(tmp, "avg"))
532 				aggr_func = ZBX_AGGR_FUNC_AVG;
533 			else if (0 == strcmp(tmp, "max"))
534 				aggr_func = ZBX_AGGR_FUNC_MAX;
535 			else if (0 == strcmp(tmp, "min"))
536 				aggr_func = ZBX_AGGR_FUNC_MIN;
537 			else if (SUCCEED == is_ushort(tmp, &process_num) && 0 < process_num)
538 				aggr_func = ZBX_AGGR_FUNC_ONE;
539 			else
540 			{
541 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
542 				goto out;
543 			}
544 
545 			if (0 == process_forks)
546 			{
547 				SET_MSG_RESULT(result, zbx_dsprintf(NULL, "No \"%s\" processes started.",
548 						get_process_type_string(process_type)));
549 				goto out;
550 			}
551 			else if (process_num > process_forks)
552 			{
553 				SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Process \"%s #%d\" is not started.",
554 						get_process_type_string(process_type), process_num));
555 				goto out;
556 			}
557 
558 			if (NULL == (tmp = get_rparam(&request, 3)) || '\0' == *tmp || 0 == strcmp(tmp, "busy"))
559 				state = ZBX_PROCESS_STATE_BUSY;
560 			else if (0 == strcmp(tmp, "idle"))
561 				state = ZBX_PROCESS_STATE_IDLE;
562 			else
563 			{
564 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fourth parameter."));
565 				goto out;
566 			}
567 
568 			get_selfmon_stats(process_type, aggr_func, process_num, state, &value);
569 
570 			SET_DBL_RESULT(result, value);
571 		}
572 	}
573 	else if (0 == strcmp(tmp, "wcache"))			/* zabbix[wcache,<cache>,<mode>] */
574 	{
575 		if (2 > nparams || nparams > 3)
576 		{
577 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
578 			goto out;
579 		}
580 
581 		tmp = get_rparam(&request, 1);
582 		tmp1 = get_rparam(&request, 2);
583 
584 		if (0 == strcmp(tmp, "values"))
585 		{
586 			if (NULL == tmp1 || '\0' == *tmp1 || 0 == strcmp(tmp1, "all"))
587 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_COUNTER));
588 			else if (0 == strcmp(tmp1, "float"))
589 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_FLOAT_COUNTER));
590 			else if (0 == strcmp(tmp1, "uint"))
591 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_UINT_COUNTER));
592 			else if (0 == strcmp(tmp1, "str"))
593 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_STR_COUNTER));
594 			else if (0 == strcmp(tmp1, "log"))
595 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_LOG_COUNTER));
596 			else if (0 == strcmp(tmp1, "text"))
597 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_TEXT_COUNTER));
598 			else if (0 == strcmp(tmp1, "not supported"))
599 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_NOTSUPPORTED_COUNTER));
600 			else
601 			{
602 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
603 				goto out;
604 			}
605 		}
606 		else if (0 == strcmp(tmp, "history"))
607 		{
608 			if (NULL == tmp1 || '\0' == *tmp1 || 0 == strcmp(tmp1, "pfree"))
609 				SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_HISTORY_PFREE));
610 			else if (0 == strcmp(tmp1, "total"))
611 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_TOTAL));
612 			else if (0 == strcmp(tmp1, "used"))
613 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_USED));
614 			else if (0 == strcmp(tmp1, "free"))
615 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_FREE));
616 			else if (0 == strcmp(tmp1, "pused"))
617 				SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_HISTORY_PUSED));
618 			else
619 			{
620 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
621 				goto out;
622 			}
623 		}
624 		else if (0 == strcmp(tmp, "trend"))
625 		{
626 			if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
627 			{
628 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
629 				goto out;
630 			}
631 
632 			if (NULL == tmp1 || '\0' == *tmp1 || 0 == strcmp(tmp1, "pfree"))
633 				SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_TREND_PFREE));
634 			else if (0 == strcmp(tmp1, "total"))
635 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TREND_TOTAL));
636 			else if (0 == strcmp(tmp1, "used"))
637 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TREND_USED));
638 			else if (0 == strcmp(tmp1, "free"))
639 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_TREND_FREE));
640 			else if (0 == strcmp(tmp1, "pused"))
641 				SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_TREND_PUSED));
642 			else
643 			{
644 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
645 				goto out;
646 			}
647 		}
648 		else if (0 == strcmp(tmp, "index"))
649 		{
650 			if (NULL == tmp1 || '\0' == *tmp1 || 0 == strcmp(tmp1, "pfree"))
651 				SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_HISTORY_INDEX_PFREE));
652 			else if (0 == strcmp(tmp1, "total"))
653 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_INDEX_TOTAL));
654 			else if (0 == strcmp(tmp1, "used"))
655 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_INDEX_USED));
656 			else if (0 == strcmp(tmp1, "free"))
657 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCget_stats(ZBX_STATS_HISTORY_INDEX_FREE));
658 			else if (0 == strcmp(tmp1, "pused"))
659 				SET_DBL_RESULT(result, *(double *)DCget_stats(ZBX_STATS_HISTORY_INDEX_PUSED));
660 			else
661 			{
662 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
663 				goto out;
664 			}
665 		}
666 		else
667 		{
668 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
669 			goto out;
670 		}
671 	}
672 	else if (0 == strcmp(tmp, "rcache"))			/* zabbix[rcache,<cache>,<mode>] */
673 	{
674 		if (2 > nparams || nparams > 3)
675 		{
676 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
677 			goto out;
678 		}
679 
680 		tmp = get_rparam(&request, 1);
681 		tmp1 = get_rparam(&request, 2);
682 
683 		if (0 == strcmp(tmp, "buffer"))
684 		{
685 			if (NULL == tmp1 || '\0' == *tmp1 || 0 == strcmp(tmp1, "pfree"))
686 				SET_DBL_RESULT(result, *(double *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_PFREE));
687 			else if (0 == strcmp(tmp1, "total"))
688 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_TOTAL));
689 			else if (0 == strcmp(tmp1, "used"))
690 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_USED));
691 			else if (0 == strcmp(tmp1, "free"))
692 				SET_UI64_RESULT(result, *(zbx_uint64_t *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_FREE));
693 			else if (0 == strcmp(tmp1, "pused"))
694 				SET_DBL_RESULT(result, *(double *)DCconfig_get_stats(ZBX_CONFSTATS_BUFFER_PUSED));
695 			else
696 			{
697 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
698 				goto out;
699 			}
700 		}
701 		else
702 		{
703 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
704 			goto out;
705 		}
706 	}
707 	else if (0 == strcmp(tmp, "vcache"))
708 	{
709 		zbx_vc_stats_t	stats;
710 
711 		if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
712 			goto out;
713 
714 		if (FAIL == zbx_vc_get_statistics(&stats))
715 		{
716 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Value cache is disabled."));
717 			goto out;
718 		}
719 
720 		if (2 > nparams || nparams > 3)
721 		{
722 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
723 			goto out;
724 		}
725 
726 		tmp = get_rparam(&request, 1);
727 		if (NULL == (tmp1 = get_rparam(&request, 2)))
728 			tmp1 = "";
729 
730 		if (0 == strcmp(tmp, "buffer"))
731 		{
732 			if (0 == strcmp(tmp1, "free"))
733 				SET_UI64_RESULT(result, stats.free_size);
734 			else if (0 == strcmp(tmp1, "pfree"))
735 				SET_DBL_RESULT(result, (double)stats.free_size / stats.total_size * 100);
736 			else if (0 == strcmp(tmp1, "total"))
737 				SET_UI64_RESULT(result, stats.total_size);
738 			else if (0 == strcmp(tmp1, "used"))
739 				SET_UI64_RESULT(result, stats.total_size - stats.free_size);
740 			else if (0 == strcmp(tmp1, "pused"))
741 				SET_DBL_RESULT(result, (double)(stats.total_size - stats.free_size) /
742 						stats.total_size * 100);
743 			else
744 			{
745 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
746 				goto out;
747 			}
748 		}
749 		else if (0 == strcmp(tmp, "cache"))
750 		{
751 			if (0 == strcmp(tmp1, "hits"))
752 				SET_UI64_RESULT(result, stats.hits);
753 			else if (0 == strcmp(tmp1, "requests"))
754 				SET_UI64_RESULT(result, stats.hits + stats.misses);
755 			else if (0 == strcmp(tmp1, "misses"))
756 				SET_UI64_RESULT(result, stats.misses);
757 			else if (0 == strcmp(tmp1, "mode"))
758 				SET_UI64_RESULT(result, stats.mode);
759 			else
760 			{
761 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
762 				goto out;
763 			}
764 		}
765 		else
766 		{
767 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
768 			goto out;
769 		}
770 	}
771 	else if (0 == strcmp(tmp, "proxy_history"))
772 	{
773 		if (0 == (program_type & ZBX_PROGRAM_TYPE_PROXY))
774 			goto out;
775 
776 		if (1 != nparams)
777 		{
778 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
779 			goto out;
780 		}
781 
782 		SET_UI64_RESULT(result, proxy_get_history_count());
783 	}
784 	else if (0 == strcmp(tmp, "vmware"))
785 	{
786 		zbx_vmware_stats_t	stats;
787 
788 		if (FAIL == zbx_vmware_get_statistics(&stats))
789 		{
790 			SET_MSG_RESULT(result, zbx_dsprintf(NULL, "No \"%s\" processes started.",
791 					get_process_type_string(ZBX_PROCESS_TYPE_VMWARE)));
792 			goto out;
793 		}
794 
795 		if (2 > nparams || nparams > 3)
796 		{
797 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
798 			goto out;
799 		}
800 
801 		tmp = get_rparam(&request, 1);
802 		if (NULL == (tmp1 = get_rparam(&request, 2)))
803 			tmp1 = "";
804 
805 		if (0 == strcmp(tmp, "buffer"))
806 		{
807 			if (0 == strcmp(tmp1, "free"))
808 			{
809 				SET_UI64_RESULT(result, stats.memory_total - stats.memory_used);
810 			}
811 			else if (0 == strcmp(tmp1, "pfree"))
812 			{
813 				SET_DBL_RESULT(result, (double)(stats.memory_total - stats.memory_used) /
814 						stats.memory_total * 100);
815 			}
816 			else if (0 == strcmp(tmp1, "total"))
817 			{
818 				SET_UI64_RESULT(result, stats.memory_total);
819 			}
820 			else if (0 == strcmp(tmp1, "used"))
821 			{
822 				SET_UI64_RESULT(result, stats.memory_used);
823 			}
824 			else if (0 == strcmp(tmp1, "pused"))
825 			{
826 				SET_DBL_RESULT(result, (double)stats.memory_used / stats.memory_total * 100);
827 			}
828 			else
829 			{
830 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
831 				goto out;
832 			}
833 		}
834 		else
835 		{
836 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid second parameter."));
837 			goto out;
838 		}
839 	}
840 	else if (0 == strcmp(tmp, "preprocessing_queue"))
841 	{
842 		if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER))
843 			goto out;
844 
845 		if (1 != nparams)
846 		{
847 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
848 			goto out;
849 		}
850 
851 		SET_UI64_RESULT(result, zbx_preprocessor_get_queue_size());
852 	}
853 	else if (0 == strcmp(tmp, "stats"))			/* zabbix[stats,...] */
854 	{
855 		const char	*ip_str, *port_str, *ip;
856 		unsigned short	port_number;
857 		struct zbx_json	json;
858 
859 		if (6 < nparams)
860 		{
861 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters."));
862 			goto out;
863 		}
864 
865 		if (NULL == (ip_str = get_rparam(&request, 1)) || '\0' == *ip_str)
866 			ip = "127.0.0.1";
867 		else
868 			ip = ip_str;
869 
870 		if (NULL == (port_str = get_rparam(&request, 2)) || '\0' == *port_str)
871 		{
872 			port_number = ZBX_DEFAULT_SERVER_PORT;
873 		}
874 		else if (SUCCEED != is_ushort(port_str, &port_number))
875 		{
876 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
877 			goto out;
878 		}
879 
880 		if (3 >= nparams)
881 		{
882 			if ((NULL == ip_str || '\0' == *ip_str) && (NULL == port_str || '\0' == *port_str))
883 			{
884 				zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
885 
886 				/* Adding "data" object to JSON structure to make identical JSONPath expressions */
887 				/* work for both data received from internal and external source. */
888 				zbx_json_addobject(&json, ZBX_PROTO_TAG_DATA);
889 
890 				zbx_get_zabbix_stats(&json);
891 
892 				zbx_json_close(&json);
893 
894 				set_result_type(result, ITEM_VALUE_TYPE_TEXT, json.buffer);
895 
896 				zbx_json_free(&json);
897 			}
898 			else if (SUCCEED != zbx_get_remote_zabbix_stats(ip, port_number, result))
899 				goto out;
900 		}
901 		else
902 		{
903 			tmp1 = get_rparam(&request, 3);
904 
905 			if (0 == strcmp(tmp1, ZBX_PROTO_VALUE_ZABBIX_STATS_QUEUE))
906 			{
907 				tmp = get_rparam(&request, 4);		/* from */
908 				tmp1 = get_rparam(&request, 5);		/* to */
909 
910 				if ((NULL == ip_str || '\0' == *ip_str) && (NULL == port_str || '\0' == *port_str))
911 				{
912 					int	from = ZBX_QUEUE_FROM_DEFAULT, to = ZBX_QUEUE_TO_INFINITY;
913 
914 					if (NULL != tmp && '\0' != *tmp &&
915 							FAIL == is_time_suffix(tmp, &from, ZBX_LENGTH_UNLIMITED))
916 					{
917 						SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter."));
918 						goto out;
919 					}
920 
921 					if (NULL != tmp1 && '\0' != *tmp1 &&
922 							FAIL == is_time_suffix(tmp1, &to, ZBX_LENGTH_UNLIMITED))
923 					{
924 						SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid sixth parameter."));
925 						goto out;
926 					}
927 
928 					if (ZBX_QUEUE_TO_INFINITY != to && from > to)
929 					{
930 						SET_MSG_RESULT(result, zbx_strdup(NULL, "Parameters represent an"
931 								" invalid interval."));
932 						goto out;
933 					}
934 
935 					zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
936 
937 					zbx_json_adduint64(&json, ZBX_PROTO_VALUE_ZABBIX_STATS_QUEUE,
938 							DCget_item_queue(NULL, from, to));
939 
940 					set_result_type(result, ITEM_VALUE_TYPE_TEXT, json.buffer);
941 
942 					zbx_json_free(&json);
943 				}
944 				else if (SUCCEED != zbx_get_remote_zabbix_stats_queue(ip, port_number, tmp, tmp1,
945 						result))
946 				{
947 					goto out;
948 				}
949 			}
950 			else
951 			{
952 				SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid forth parameter."));
953 				goto out;
954 			}
955 		}
956 	}
957 	else
958 	{
959 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid first parameter."));
960 		goto out;
961 	}
962 
963 	ret = SUCCEED;
964 out:
965 	if (NOTSUPPORTED == ret && !ISSET_MSG(result))
966 		SET_MSG_RESULT(result, zbx_strdup(NULL, "Internal check is not supported."));
967 
968 	free_request(&request);
969 
970 	return ret;
971 }
972