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