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