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 
22 #include "db.h"
23 #include "dbcache.h"
24 #include "daemon.h"
25 #include "zbxserver.h"
26 #include "zbxself.h"
27 #include "preproc.h"
28 #include "../events.h"
29 
30 #include "poller.h"
31 
32 #include "checks_agent.h"
33 #include "checks_external.h"
34 #include "checks_internal.h"
35 #include "checks_script.h"
36 #include "checks_simple.h"
37 #include "checks_snmp.h"
38 #include "checks_db.h"
39 #include "checks_ssh.h"
40 #include "checks_telnet.h"
41 #include "checks_java.h"
42 #include "checks_calculated.h"
43 #include "checks_http.h"
44 #include "zbxcrypto.h"
45 #include "zbxjson.h"
46 #include "zbxhttp.h"
47 #include "avail_protocol.h"
48 #include "zbxavailability.h"
49 
50 extern unsigned char	process_type, program_type;
51 extern int		server_num, process_num;
52 
53 #ifdef HAVE_NETSNMP
54 static volatile sig_atomic_t	snmp_cache_reload_requested;
55 #endif
56 
57 /******************************************************************************
58  *                                                                            *
59  * Function: update_interface_availability                                    *
60  *                                                                            *
61  * Purpose: write interface availability changes into database                *
62  *                                                                            *
63  * Parameters: data        - [IN/OUT] the serialized availability data        *
64  *             data_alloc  - [IN/OUT] the serialized availability data size   *
65  *             data_alloc  - [IN/OUT] the serialized availability data offset *
66  *             ia          - [IN] the interface availability data             *
67  *                                                                            *
68  * Return value: SUCCEED - the availability changes were written into db      *
69  *               FAIL    - no changes in availability data were detected      *
70  *                                                                            *
71  ******************************************************************************/
update_interface_availability(unsigned char ** data,size_t * data_alloc,size_t * data_offset,const zbx_interface_availability_t * ia)72 static int	update_interface_availability(unsigned char **data, size_t *data_alloc, size_t *data_offset,
73 		const zbx_interface_availability_t *ia)
74 {
75 	if (FAIL == zbx_interface_availability_is_set(ia))
76 		return FAIL;
77 
78 	zbx_availability_serialize(data, data_alloc, data_offset, ia);
79 
80 	return SUCCEED;
81 }
82 
83 /******************************************************************************
84  *                                                                            *
85  * Function: interface_get_availability                                       *
86  *                                                                            *
87  * Purpose: get interface availability data                                   *
88  *                                                                            *
89  * Parameters: dc_interface - [IN] the interface                              *
90  *             ia           - [OUT] the interface availability data           *
91  *                                                                            *
92  ******************************************************************************/
interface_get_availability(const DC_INTERFACE * dc_interface,zbx_interface_availability_t * ia)93 static void	interface_get_availability(const DC_INTERFACE *dc_interface, zbx_interface_availability_t *ia)
94 {
95 	zbx_agent_availability_t	*availability = &ia->agent;
96 
97 	availability->flags = ZBX_FLAGS_AGENT_STATUS;
98 
99 	availability->available = dc_interface->available;
100 	availability->error = zbx_strdup(NULL, dc_interface->error);
101 	availability->errors_from = dc_interface->errors_from;
102 	availability->disable_until = dc_interface->disable_until;
103 
104 	ia->interfaceid = dc_interface->interfaceid;
105 }
106 
107 /********************************************************************************
108  *                                                                              *
109  * Function: interface_set_availability                                         *
110  *                                                                              *
111  * Purpose: sets interface availability data                                    *
112  *                                                                              *
113  * Parameters: dc_interface - [IN/OUT] the interface                            *
114  *             ia           - [IN] the interface availability data              *
115  *                                                                              *
116  *******************************************************************************/
interface_set_availability(DC_INTERFACE * dc_interface,const zbx_interface_availability_t * ia)117 static void	interface_set_availability(DC_INTERFACE *dc_interface, const zbx_interface_availability_t *ia)
118 {
119 	const zbx_agent_availability_t	*availability = &ia->agent;
120 	unsigned char			*pavailable;
121 	int				*perrors_from, *pdisable_until;
122 	char				*perror;
123 
124 	pavailable = &dc_interface->available;
125 	perror = dc_interface->error;
126 	perrors_from = &dc_interface->errors_from;
127 	pdisable_until = &dc_interface->disable_until;
128 
129 	if (0 != (availability->flags & ZBX_FLAGS_AGENT_STATUS_AVAILABLE))
130 		*pavailable = availability->available;
131 
132 	if (0 != (availability->flags & ZBX_FLAGS_AGENT_STATUS_ERROR))
133 		zbx_strlcpy(perror, availability->error, INTERFACE_ERROR_LEN_MAX);
134 
135 	if (0 != (availability->flags & ZBX_FLAGS_AGENT_STATUS_ERRORS_FROM))
136 		*perrors_from = availability->errors_from;
137 
138 	if (0 != (availability->flags & ZBX_FLAGS_AGENT_STATUS_DISABLE_UNTIL))
139 		*pdisable_until = availability->disable_until;
140 }
141 
interface_availability_by_item_type(unsigned char item_type,unsigned char interface_type)142 static int	interface_availability_by_item_type(unsigned char item_type, unsigned char interface_type)
143 {
144 	if ((ITEM_TYPE_ZABBIX == item_type && INTERFACE_TYPE_AGENT == interface_type) ||
145 			(ITEM_TYPE_SNMP == item_type && INTERFACE_TYPE_SNMP == interface_type) ||
146 			(ITEM_TYPE_JMX == item_type && INTERFACE_TYPE_JMX == interface_type) ||
147 			(ITEM_TYPE_IPMI == item_type && INTERFACE_TYPE_IPMI == interface_type))
148 		return SUCCEED;
149 
150 	return FAIL;
151 }
152 
153 /********************************************************************************
154  *                                                                              *
155  * Function: zbx_activate_item_interface                                        *
156  *                                                                              *
157  * Purpose: activate item interface                                             *
158  *                                                                              *
159  * Parameters: ts         - [IN] the timestamp                                  *
160  *             item       - [IN/OUT] the item                                   *
161  *             data       - [IN/OUT] the serialized availability data           *
162  *             data_alloc - [IN/OUT] the serialized availability data size      *
163  *             data_alloc - [IN/OUT] the serialized availability data offset    *
164  *             ts         - [IN] the timestamp                                  *
165  *                                                                              *
166  *******************************************************************************/
zbx_activate_item_interface(zbx_timespec_t * ts,DC_ITEM * item,unsigned char ** data,size_t * data_alloc,size_t * data_offset)167 void	zbx_activate_item_interface(zbx_timespec_t *ts, DC_ITEM *item,  unsigned char **data, size_t *data_alloc,
168 		size_t *data_offset)
169 {
170 	zbx_interface_availability_t	in, out;
171 
172 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() interfaceid:" ZBX_FS_UI64 " itemid:" ZBX_FS_UI64 " type:%d",
173 			__func__, item->interface.interfaceid, item->itemid, (int)item->type);
174 
175 	zbx_interface_availability_init(&in, item->interface.interfaceid);
176 	zbx_interface_availability_init(&out, item->interface.interfaceid);
177 
178 	if (FAIL == interface_availability_by_item_type(item->type, item->interface.type))
179 		goto out;
180 
181 	interface_get_availability(&item->interface, &in);
182 
183 	if (FAIL == DCinterface_activate(item->interface.interfaceid, ts, &in.agent, &out.agent))
184 		goto out;
185 
186 	if (FAIL == update_interface_availability(data, data_alloc, data_offset, &out))
187 		goto out;
188 
189 	interface_set_availability(&item->interface, &out);
190 
191 	if (INTERFACE_AVAILABLE_TRUE == in.agent.available)
192 	{
193 		zabbix_log(LOG_LEVEL_WARNING, "resuming %s checks on host \"%s\": connection restored",
194 				zbx_agent_type_string(item->type), item->host.host);
195 	}
196 	else
197 	{
198 		zabbix_log(LOG_LEVEL_WARNING, "enabling %s checks on host \"%s\": interface became available",
199 				zbx_agent_type_string(item->type), item->host.host);
200 	}
201 out:
202 	zbx_interface_availability_clean(&out);
203 	zbx_interface_availability_clean(&in);
204 
205 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
206 }
207 
208 /********************************************************************************
209  *                                                                              *
210  * Function: zbx_deactivate_item_interface                                      *
211  *                                                                              *
212  * Purpose: deactivate item interface                                           *
213  *                                                                              *
214  * Parameters: ts         - [IN] the timestamp                                  *
215  *             item       - [IN/OUT] the item                                   *
216  *             data       - [IN/OUT] the serialized availability data           *
217  *             data_alloc - [IN/OUT] the serialized availability data size      *
218  *             data_alloc - [IN/OUT] the serialized availability data offset    *
219  *             ts         - [IN] the timestamp                                  *
220  *                                                                              *
221  *******************************************************************************/
zbx_deactivate_item_interface(zbx_timespec_t * ts,DC_ITEM * item,unsigned char ** data,size_t * data_alloc,size_t * data_offset,const char * error)222 void	zbx_deactivate_item_interface(zbx_timespec_t *ts, DC_ITEM *item, unsigned char **data, size_t *data_alloc,
223 		size_t *data_offset, const char *error)
224 {
225 	zbx_interface_availability_t	in, out;
226 
227 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() interfaceid:" ZBX_FS_UI64 " itemid:" ZBX_FS_UI64 " type:%d",
228 			__func__, item->interface.interfaceid, item->itemid, (int)item->type);
229 
230 	zbx_interface_availability_init(&in, item->interface.interfaceid);
231 	zbx_interface_availability_init(&out,item->interface.interfaceid);
232 
233 	if (FAIL == interface_availability_by_item_type(item->type, item->interface.type))
234 		goto out;
235 
236 	interface_get_availability(&item->interface, &in);
237 
238 	if (FAIL == DCinterface_deactivate(item->interface.interfaceid, ts, &in.agent, &out.agent, error))
239 		goto out;
240 
241 	if (FAIL == update_interface_availability(data, data_alloc, data_offset, &out))
242 		goto out;
243 
244 	interface_set_availability(&item->interface, &out);
245 
246 	if (0 == in.agent.errors_from)
247 	{
248 		zabbix_log(LOG_LEVEL_WARNING, "%s item \"%s\" on host \"%s\" failed:"
249 				" first network error, wait for %d seconds",
250 				zbx_agent_type_string(item->type), item->key_orig, item->host.host,
251 				out.agent.disable_until - ts->sec);
252 	}
253 	else if (INTERFACE_AVAILABLE_FALSE != in.agent.available)
254 	{
255 		if (INTERFACE_AVAILABLE_FALSE != out.agent.available)
256 		{
257 			zabbix_log(LOG_LEVEL_WARNING, "%s item \"%s\" on host \"%s\" failed:"
258 					" another network error, wait for %d seconds",
259 					zbx_agent_type_string(item->type), item->key_orig, item->host.host,
260 					out.agent.disable_until - ts->sec);
261 		}
262 		else
263 		{
264 			zabbix_log(LOG_LEVEL_WARNING, "temporarily disabling %s checks on host \"%s\":"
265 					" interface unavailable",
266 					zbx_agent_type_string(item->type), item->host.host);
267 		}
268 	}
269 
270 	zabbix_log(LOG_LEVEL_DEBUG, "%s() errors_from:%d available:%d", __func__,
271 			out.agent.errors_from, out.agent.available);
272 out:
273 	zbx_interface_availability_clean(&out);
274 	zbx_interface_availability_clean(&in);
275 
276 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
277 }
278 
zbx_free_result_ptr(AGENT_RESULT * result)279 void	zbx_free_result_ptr(AGENT_RESULT *result)
280 {
281 	free_result(result);
282 	zbx_free(result);
283 }
284 
get_value(DC_ITEM * item,AGENT_RESULT * result,zbx_vector_ptr_t * add_results)285 static int	get_value(DC_ITEM *item, AGENT_RESULT *result, zbx_vector_ptr_t *add_results)
286 {
287 	int	res = FAIL;
288 
289 	zabbix_log(LOG_LEVEL_DEBUG, "In %s() key:'%s'", __func__, item->key_orig);
290 
291 	switch (item->type)
292 	{
293 		case ITEM_TYPE_ZABBIX:
294 			zbx_alarm_on(CONFIG_TIMEOUT);
295 			res = get_value_agent(item, result);
296 			zbx_alarm_off();
297 			break;
298 		case ITEM_TYPE_SIMPLE:
299 			/* simple checks use their own timeouts */
300 			res = get_value_simple(item, result, add_results);
301 			break;
302 		case ITEM_TYPE_INTERNAL:
303 			res = get_value_internal(item, result);
304 			break;
305 		case ITEM_TYPE_DB_MONITOR:
306 #ifdef HAVE_UNIXODBC
307 			res = get_value_db(item, result);
308 #else
309 			SET_MSG_RESULT(result,
310 					zbx_strdup(NULL, "Support for Database monitor checks was not compiled in."));
311 			res = CONFIG_ERROR;
312 #endif
313 			break;
314 		case ITEM_TYPE_EXTERNAL:
315 			/* external checks use their own timeouts */
316 			res = get_value_external(item, result);
317 			break;
318 		case ITEM_TYPE_SSH:
319 #if defined(HAVE_SSH2) || defined(HAVE_SSH)
320 			zbx_alarm_on(CONFIG_TIMEOUT);
321 			res = get_value_ssh(item, result);
322 			zbx_alarm_off();
323 #else
324 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Support for SSH checks was not compiled in."));
325 			res = CONFIG_ERROR;
326 #endif
327 			break;
328 		case ITEM_TYPE_TELNET:
329 			zbx_alarm_on(CONFIG_TIMEOUT);
330 			res = get_value_telnet(item, result);
331 			zbx_alarm_off();
332 			break;
333 		case ITEM_TYPE_CALCULATED:
334 			res = get_value_calculated(item, result);
335 			break;
336 		case ITEM_TYPE_HTTPAGENT:
337 #ifdef HAVE_LIBCURL
338 			res = get_value_http(item, result);
339 #else
340 			SET_MSG_RESULT(result, zbx_strdup(NULL, "Support for HTTP agent checks was not compiled in."));
341 			res = CONFIG_ERROR;
342 #endif
343 			break;
344 		case ITEM_TYPE_SCRIPT:
345 			res = get_value_script(item, result);
346 			break;
347 		default:
348 			SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Not supported item type:%d", item->type));
349 			res = CONFIG_ERROR;
350 	}
351 
352 	if (SUCCEED != res)
353 	{
354 		if (!ISSET_MSG(result))
355 			SET_MSG_RESULT(result, zbx_strdup(NULL, ZBX_NOTSUPPORTED_MSG));
356 
357 		zabbix_log(LOG_LEVEL_DEBUG, "Item [%s:%s] error: %s", item->host.host, item->key_orig, result->msg);
358 	}
359 
360 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(res));
361 
362 	return res;
363 }
364 
parse_query_fields(const DC_ITEM * item,char ** query_fields,unsigned char expand_macros)365 static int	parse_query_fields(const DC_ITEM *item, char **query_fields, unsigned char expand_macros)
366 {
367 	struct zbx_json_parse	jp_array, jp_object;
368 	char			name[MAX_STRING_LEN], value[MAX_STRING_LEN], *str = NULL;
369 	const char		*member, *element = NULL;
370 	size_t			alloc_len, offset;
371 
372 	if ('\0' == **query_fields)
373 		return SUCCEED;
374 
375 	if (SUCCEED != zbx_json_open(*query_fields, &jp_array))
376 	{
377 		zabbix_log(LOG_LEVEL_ERR, "cannot parse query fields: %s", zbx_json_strerror());
378 		return FAIL;
379 	}
380 
381 	if (NULL == (element = zbx_json_next(&jp_array, element)))
382 	{
383 		zabbix_log(LOG_LEVEL_ERR, "cannot parse query fields: array is empty");
384 		return FAIL;
385 	}
386 
387 	do
388 	{
389 		char	*data = NULL;
390 
391 		if (SUCCEED != zbx_json_brackets_open(element, &jp_object) ||
392 				NULL == (member = zbx_json_pair_next(&jp_object, NULL, name, sizeof(name))) ||
393 				NULL == zbx_json_decodevalue(member, value, sizeof(value), NULL))
394 		{
395 			zabbix_log(LOG_LEVEL_ERR, "cannot parse query fields: %s", zbx_json_strerror());
396 			zbx_free(str);
397 			return FAIL;
398 		}
399 
400 		if (NULL == str && NULL == strchr(item->url, '?'))
401 			zbx_chrcpy_alloc(&str, &alloc_len, &offset, '?');
402 		else
403 			zbx_chrcpy_alloc(&str, &alloc_len, &offset, '&');
404 
405 		data = zbx_strdup(data, name);
406 		if (MACRO_EXPAND_YES == expand_macros)
407 		{
408 			substitute_simple_macros(NULL, NULL, NULL,NULL, NULL, &item->host, item, NULL, NULL, NULL,
409 					&data, MACRO_TYPE_HTTP_RAW, NULL, 0);
410 		}
411 		zbx_http_url_encode(data, &data);
412 		zbx_strcpy_alloc(&str, &alloc_len, &offset, data);
413 		zbx_chrcpy_alloc(&str, &alloc_len, &offset, '=');
414 
415 		data = zbx_strdup(data, value);
416 		if (MACRO_EXPAND_YES == expand_macros)
417 		{
418 			substitute_simple_macros_unmasked(NULL, NULL, NULL,NULL, NULL, &item->host, item, NULL, NULL,
419 					NULL, &data, MACRO_TYPE_HTTP_RAW, NULL, 0);
420 		}
421 
422 		zbx_http_url_encode(data, &data);
423 		zbx_strcpy_alloc(&str, &alloc_len, &offset, data);
424 
425 		free(data);
426 	}
427 	while (NULL != (element = zbx_json_next(&jp_array, element)));
428 
429 	zbx_free(*query_fields);
430 	*query_fields = str;
431 
432 	return SUCCEED;
433 }
434 
zbx_prepare_items(DC_ITEM * items,int * errcodes,int num,AGENT_RESULT * results,unsigned char expand_macros)435 void	zbx_prepare_items(DC_ITEM *items, int *errcodes, int num, AGENT_RESULT *results, unsigned char expand_macros)
436 {
437 	int	i;
438 	char	*port = NULL, error[ITEM_ERROR_LEN_MAX];
439 
440 	for (i = 0; i < num; i++)
441 	{
442 		init_result(&results[i]);
443 		errcodes[i] = SUCCEED;
444 
445 		if (MACRO_EXPAND_YES == expand_macros)
446 		{
447 			ZBX_STRDUP(items[i].key, items[i].key_orig);
448 			if (SUCCEED != substitute_key_macros_unmasked(&items[i].key, NULL, &items[i], NULL, NULL,
449 					MACRO_TYPE_ITEM_KEY, error, sizeof(error)))
450 			{
451 				SET_MSG_RESULT(&results[i], zbx_strdup(NULL, error));
452 				errcodes[i] = CONFIG_ERROR;
453 				continue;
454 			}
455 		}
456 
457 		switch (items[i].type)
458 		{
459 			case ITEM_TYPE_ZABBIX:
460 			case ITEM_TYPE_SNMP:
461 			case ITEM_TYPE_JMX:
462 				ZBX_STRDUP(port, items[i].interface.port_orig);
463 				if (MACRO_EXPAND_YES == expand_macros)
464 				{
465 					substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
466 							NULL, NULL, NULL, NULL, &port, MACRO_TYPE_COMMON, NULL, 0);
467 				}
468 
469 				if (FAIL == is_ushort(port, &items[i].interface.port))
470 				{
471 					SET_MSG_RESULT(&results[i], zbx_dsprintf(NULL, "Invalid port number [%s]",
472 								items[i].interface.port_orig));
473 					errcodes[i] = CONFIG_ERROR;
474 					continue;
475 				}
476 				break;
477 		}
478 
479 		switch (items[i].type)
480 		{
481 			case ITEM_TYPE_SNMP:
482 				if (MACRO_EXPAND_NO == expand_macros)
483 					break;
484 
485 				if (ZBX_IF_SNMP_VERSION_3 == items[i].snmp_version)
486 				{
487 					ZBX_STRDUP(items[i].snmpv3_securityname, items[i].snmpv3_securityname_orig);
488 					ZBX_STRDUP(items[i].snmpv3_authpassphrase, items[i].snmpv3_authpassphrase_orig);
489 					ZBX_STRDUP(items[i].snmpv3_privpassphrase, items[i].snmpv3_privpassphrase_orig);
490 					ZBX_STRDUP(items[i].snmpv3_contextname, items[i].snmpv3_contextname_orig);
491 
492 					substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid,
493 							NULL, NULL, NULL, NULL, NULL,
494 							&items[i].snmpv3_securityname, MACRO_TYPE_COMMON, NULL,
495 							0);
496 					substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid,
497 							NULL, NULL, NULL, NULL, NULL,
498 							&items[i].snmpv3_authpassphrase, MACRO_TYPE_COMMON,
499 							NULL, 0);
500 					substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid,
501 							NULL, NULL, NULL, NULL, NULL,
502 							&items[i].snmpv3_privpassphrase, MACRO_TYPE_COMMON,
503 							NULL, 0);
504 					substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid,
505 							NULL, NULL, NULL, NULL, NULL,
506 							&items[i].snmpv3_contextname, MACRO_TYPE_COMMON, NULL,
507 							0);
508 				}
509 
510 				ZBX_STRDUP(items[i].snmp_community, items[i].snmp_community_orig);
511 				ZBX_STRDUP(items[i].snmp_oid, items[i].snmp_oid_orig);
512 
513 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
514 						NULL, NULL, NULL, NULL, &items[i].snmp_community, MACRO_TYPE_COMMON,
515 						NULL, 0);
516 				if (SUCCEED != substitute_key_macros(&items[i].snmp_oid, &items[i].host.hostid,
517 						NULL, NULL, NULL, MACRO_TYPE_SNMP_OID, error, sizeof(error)))
518 				{
519 					SET_MSG_RESULT(&results[i], zbx_strdup(NULL, error));
520 					errcodes[i] = CONFIG_ERROR;
521 					continue;
522 				}
523 				break;
524 			case ITEM_TYPE_SCRIPT:
525 				if (MACRO_EXPAND_NO == expand_macros)
526 					break;
527 
528 				ZBX_STRDUP(items[i].timeout, items[i].timeout_orig);
529 
530 				substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL,
531 						NULL, NULL, NULL, &items[i].timeout, MACRO_TYPE_COMMON , NULL, 0);
532 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, NULL, NULL, &items[i], NULL,
533 						NULL, NULL, &items[i].script_params, MACRO_TYPE_SCRIPT_PARAMS_FIELD,
534 						NULL, 0);
535 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
536 						NULL, NULL, NULL, NULL, &items[i].params, MACRO_TYPE_COMMON, NULL, 0);
537 				break;
538 			case ITEM_TYPE_SSH:
539 				if (MACRO_EXPAND_NO == expand_macros)
540 					break;
541 
542 				ZBX_STRDUP(items[i].publickey, items[i].publickey_orig);
543 				ZBX_STRDUP(items[i].privatekey, items[i].privatekey_orig);
544 
545 				substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL,
546 						NULL, NULL, NULL, &items[i].publickey, MACRO_TYPE_COMMON,
547 						NULL, 0);
548 				substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL,
549 						NULL, NULL, NULL, &items[i].privatekey, MACRO_TYPE_COMMON, NULL, 0);
550 				ZBX_FALLTHROUGH;
551 			case ITEM_TYPE_TELNET:
552 			case ITEM_TYPE_DB_MONITOR:
553 				if (MACRO_EXPAND_NO == expand_macros)
554 					break;
555 
556 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, NULL, NULL, &items[i], NULL,
557 						NULL, NULL, &items[i].params, MACRO_TYPE_PARAMS_FIELD,
558 						NULL, 0);
559 				ZBX_FALLTHROUGH;
560 			case ITEM_TYPE_SIMPLE:
561 				if (MACRO_EXPAND_NO == expand_macros)
562 					break;
563 
564 				items[i].username = zbx_strdup(items[i].username, items[i].username_orig);
565 				items[i].password = zbx_strdup(items[i].password, items[i].password_orig);
566 
567 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
568 						NULL, NULL, NULL, NULL, &items[i].username, MACRO_TYPE_COMMON, NULL, 0);
569 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
570 						NULL, NULL, NULL, NULL, &items[i].password, MACRO_TYPE_COMMON, NULL, 0);
571 				break;
572 			case ITEM_TYPE_JMX:
573 				if (MACRO_EXPAND_NO == expand_macros)
574 					break;
575 
576 				items[i].username = zbx_strdup(items[i].username, items[i].username_orig);
577 				items[i].password = zbx_strdup(items[i].password, items[i].password_orig);
578 				items[i].jmx_endpoint = zbx_strdup(items[i].jmx_endpoint, items[i].jmx_endpoint_orig);
579 
580 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
581 						NULL, NULL, NULL, NULL, &items[i].username, MACRO_TYPE_COMMON, NULL, 0);
582 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
583 						NULL, NULL, NULL, NULL, &items[i].password, MACRO_TYPE_COMMON, NULL, 0);
584 				substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, &items[i],
585 						NULL, NULL, NULL, &items[i].jmx_endpoint, MACRO_TYPE_JMX_ENDPOINT, NULL, 0);
586 				break;
587 			case ITEM_TYPE_HTTPAGENT:
588 				if (MACRO_EXPAND_YES == expand_macros)
589 				{
590 					ZBX_STRDUP(items[i].timeout, items[i].timeout_orig);
591 					ZBX_STRDUP(items[i].url, items[i].url_orig);
592 					ZBX_STRDUP(items[i].status_codes, items[i].status_codes_orig);
593 					ZBX_STRDUP(items[i].http_proxy, items[i].http_proxy_orig);
594 					ZBX_STRDUP(items[i].ssl_cert_file, items[i].ssl_cert_file_orig);
595 					ZBX_STRDUP(items[i].ssl_key_file, items[i].ssl_key_file_orig);
596 					ZBX_STRDUP(items[i].ssl_key_password, items[i].ssl_key_password_orig);
597 					ZBX_STRDUP(items[i].username, items[i].username_orig);
598 					ZBX_STRDUP(items[i].password, items[i].password_orig);
599 					ZBX_STRDUP(items[i].query_fields, items[i].query_fields_orig);
600 
601 					substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
602 							NULL, NULL, NULL, NULL, &items[i].timeout, MACRO_TYPE_COMMON
603 							, NULL, 0);
604 					substitute_simple_macros_unmasked(NULL, NULL, NULL,NULL, NULL, &items[i].host,
605 							&items[i], NULL, NULL, NULL, &items[i].url,
606 							MACRO_TYPE_HTTP_RAW, NULL, 0);
607 				}
608 
609 				if (SUCCEED != zbx_http_punycode_encode_url(&items[i].url))
610 				{
611 					SET_MSG_RESULT(&results[i], zbx_strdup(NULL, "Cannot encode URL into punycode"));
612 					errcodes[i] = CONFIG_ERROR;
613 					continue;
614 				}
615 
616 				if (FAIL == parse_query_fields(&items[i], &items[i].query_fields, expand_macros))
617 				{
618 					SET_MSG_RESULT(&results[i], zbx_strdup(NULL, "Invalid query fields"));
619 					errcodes[i] = CONFIG_ERROR;
620 					continue;
621 				}
622 
623 				if (MACRO_EXPAND_NO == expand_macros)
624 					break;
625 
626 				switch (items[i].post_type)
627 				{
628 					case ZBX_POSTTYPE_XML:
629 						if (SUCCEED != substitute_macros_xml_unmasked(&items[i].posts, &items[i],
630 								NULL, NULL, error, sizeof(error)))
631 						{
632 							SET_MSG_RESULT(&results[i], zbx_dsprintf(NULL, "%s.", error));
633 							errcodes[i] = CONFIG_ERROR;
634 							continue;
635 						}
636 						break;
637 					case ZBX_POSTTYPE_JSON:
638 						substitute_simple_macros_unmasked(NULL, NULL, NULL,NULL, NULL,
639 								&items[i].host, &items[i], NULL, NULL, NULL,
640 								&items[i].posts, MACRO_TYPE_HTTP_JSON, NULL, 0);
641 						break;
642 					default:
643 						substitute_simple_macros_unmasked(NULL, NULL, NULL,NULL, NULL,
644 								&items[i].host, &items[i], NULL, NULL, NULL,
645 								&items[i].posts, MACRO_TYPE_HTTP_RAW, NULL, 0);
646 						break;
647 				}
648 
649 				substitute_simple_macros_unmasked(NULL, NULL, NULL,NULL, NULL, &items[i].host,
650 						&items[i], NULL, NULL, NULL, &items[i].headers, MACRO_TYPE_HTTP_RAW,
651 						NULL, 0);
652 				substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
653 						NULL, NULL, NULL, NULL, &items[i].status_codes, MACRO_TYPE_COMMON, NULL, 0);
654 				substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
655 						NULL, NULL, NULL, NULL, &items[i].http_proxy, MACRO_TYPE_COMMON, NULL, 0);
656 				substitute_simple_macros(NULL, NULL, NULL,NULL, NULL, &items[i].host, &items[i], NULL,
657 						NULL, NULL, &items[i].ssl_cert_file, MACRO_TYPE_HTTP_RAW, NULL, 0);
658 				substitute_simple_macros(NULL, NULL, NULL,NULL, NULL, &items[i].host, &items[i], NULL,
659 						NULL, NULL,&items[i].ssl_key_file, MACRO_TYPE_HTTP_RAW, NULL, 0);
660 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
661 						NULL, NULL, NULL, NULL, &items[i].ssl_key_password, MACRO_TYPE_COMMON,
662 						NULL, 0);
663 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
664 						NULL, NULL, NULL, NULL, &items[i].username, MACRO_TYPE_COMMON, NULL, 0);
665 				substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL,
666 						NULL, NULL, NULL, NULL, &items[i].password, MACRO_TYPE_COMMON, NULL, 0);
667 				break;
668 		}
669 	}
670 
671 	zbx_free(port);
672 }
673 
zbx_check_items(DC_ITEM * items,int * errcodes,int num,AGENT_RESULT * results,zbx_vector_ptr_t * add_results,unsigned char poller_type)674 void	zbx_check_items(DC_ITEM *items, int *errcodes, int num, AGENT_RESULT *results, zbx_vector_ptr_t *add_results,
675 		unsigned char poller_type)
676 {
677 	if (ITEM_TYPE_SNMP == items[0].type)
678 	{
679 #ifndef HAVE_NETSNMP
680 		int	i;
681 
682 		ZBX_UNUSED(poller_type);
683 
684 		for (i = 0; i < num; i++)
685 		{
686 			if (SUCCEED != errcodes[i])
687 				continue;
688 
689 			SET_MSG_RESULT(&results[i], zbx_strdup(NULL, "Support for SNMP checks was not compiled in."));
690 			errcodes[i] = CONFIG_ERROR;
691 		}
692 #else
693 		/* SNMP checks use their own timeouts */
694 		get_values_snmp(items, results, errcodes, num, poller_type);
695 #endif
696 	}
697 	else if (ITEM_TYPE_JMX == items[0].type)
698 	{
699 		zbx_alarm_on(CONFIG_TIMEOUT);
700 		get_values_java(ZBX_JAVA_GATEWAY_REQUEST_JMX, items, results, errcodes, num);
701 		zbx_alarm_off();
702 	}
703 	else if (1 == num)
704 	{
705 		if (SUCCEED == errcodes[0])
706 			errcodes[0] = get_value(&items[0], &results[0], add_results);
707 	}
708 	else
709 		THIS_SHOULD_NEVER_HAPPEN;
710 }
711 
zbx_clean_items(DC_ITEM * items,int num,AGENT_RESULT * results)712 void	zbx_clean_items(DC_ITEM *items, int num, AGENT_RESULT *results)
713 {
714 	int	i;
715 
716 	for (i = 0; i < num; i++)
717 	{
718 		zbx_free(items[i].key);
719 
720 		switch (items[i].type)
721 		{
722 			case ITEM_TYPE_SNMP:
723 				if (ZBX_IF_SNMP_VERSION_3 == items[i].snmp_version)
724 				{
725 					zbx_free(items[i].snmpv3_securityname);
726 					zbx_free(items[i].snmpv3_authpassphrase);
727 					zbx_free(items[i].snmpv3_privpassphrase);
728 					zbx_free(items[i].snmpv3_contextname);
729 				}
730 
731 				zbx_free(items[i].snmp_community);
732 				zbx_free(items[i].snmp_oid);
733 				break;
734 			case ITEM_TYPE_HTTPAGENT:
735 				zbx_free(items[i].timeout);
736 				zbx_free(items[i].url);
737 				zbx_free(items[i].query_fields);
738 				zbx_free(items[i].status_codes);
739 				zbx_free(items[i].http_proxy);
740 				zbx_free(items[i].ssl_cert_file);
741 				zbx_free(items[i].ssl_key_file);
742 				zbx_free(items[i].ssl_key_password);
743 				zbx_free(items[i].username);
744 				zbx_free(items[i].password);
745 				break;
746 			case ITEM_TYPE_SCRIPT:
747 				zbx_free(items[i].timeout);
748 				break;
749 			case ITEM_TYPE_SSH:
750 				zbx_free(items[i].publickey);
751 				zbx_free(items[i].privatekey);
752 				ZBX_FALLTHROUGH;
753 			case ITEM_TYPE_TELNET:
754 			case ITEM_TYPE_DB_MONITOR:
755 			case ITEM_TYPE_SIMPLE:
756 				zbx_free(items[i].username);
757 				zbx_free(items[i].password);
758 				break;
759 			case ITEM_TYPE_JMX:
760 				zbx_free(items[i].username);
761 				zbx_free(items[i].password);
762 				zbx_free(items[i].jmx_endpoint);
763 				break;
764 		}
765 
766 		free_result(&results[i]);
767 	}
768 }
769 
770 /******************************************************************************
771  *                                                                            *
772  * Function: get_values                                                       *
773  *                                                                            *
774  * Purpose: retrieve values of metrics from monitored hosts                   *
775  *                                                                            *
776  * Parameters: poller_type - [IN] poller type (ZBX_POLLER_TYPE_...)           *
777  *             nextcheck   - [OUT] item nextcheck                             *
778  *                                                                            *
779  * Return value: number of items processed                                    *
780  *                                                                            *
781  * Author: Alexei Vladishev                                                   *
782  *                                                                            *
783  * Comments: processes single item at a time except for Java, SNMP items,     *
784  *           see DCconfig_get_poller_items()                                  *
785  *                                                                            *
786  ******************************************************************************/
get_values(unsigned char poller_type,int * nextcheck)787 static int	get_values(unsigned char poller_type, int *nextcheck)
788 {
789 	DC_ITEM			item, *items;
790 	AGENT_RESULT		results[MAX_POLLER_ITEMS];
791 	int			errcodes[MAX_POLLER_ITEMS];
792 	zbx_timespec_t		timespec;
793 	int			i, num, last_available = INTERFACE_AVAILABLE_UNKNOWN;
794 	zbx_vector_ptr_t	add_results;
795 	unsigned char		*data = NULL;
796 	size_t			data_alloc = 0, data_offset = 0;
797 
798 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
799 
800 	items = &item;
801 	num = DCconfig_get_poller_items(poller_type, &items);
802 
803 	if (0 == num)
804 	{
805 		*nextcheck = DCconfig_get_poller_nextcheck(poller_type);
806 		goto exit;
807 	}
808 
809 	zbx_vector_ptr_create(&add_results);
810 
811 	zbx_prepare_items(items, errcodes, num, results, MACRO_EXPAND_YES);
812 	zbx_check_items(items, errcodes, num, results, &add_results, poller_type);
813 
814 	zbx_timespec(&timespec);
815 
816 	/* process item values */
817 	for (i = 0; i < num; i++)
818 	{
819 		switch (errcodes[i])
820 		{
821 			case SUCCEED:
822 			case NOTSUPPORTED:
823 			case AGENT_ERROR:
824 				if (INTERFACE_AVAILABLE_TRUE != last_available)
825 				{
826 					zbx_activate_item_interface(&timespec, &items[i], &data, &data_alloc,
827 							&data_offset);
828 					last_available = INTERFACE_AVAILABLE_TRUE;
829 				}
830 				break;
831 			case NETWORK_ERROR:
832 			case GATEWAY_ERROR:
833 			case TIMEOUT_ERROR:
834 				if (INTERFACE_AVAILABLE_FALSE != last_available)
835 				{
836 					zbx_deactivate_item_interface(&timespec, &items[i], &data, &data_alloc,
837 							&data_offset, results[i].msg);
838 					last_available = INTERFACE_AVAILABLE_FALSE;
839 				}
840 				break;
841 			case CONFIG_ERROR:
842 				/* nothing to do */
843 				break;
844 			default:
845 				zbx_error("unknown response code returned: %d", errcodes[i]);
846 				THIS_SHOULD_NEVER_HAPPEN;
847 		}
848 
849 		if (SUCCEED == errcodes[i])
850 		{
851 			if (0 == add_results.values_num)
852 			{
853 				items[i].state = ITEM_STATE_NORMAL;
854 				zbx_preprocess_item_value(items[i].itemid, items[i].host.hostid, items[i].value_type,
855 						items[i].flags, &results[i], &timespec, items[i].state, NULL);
856 			}
857 			else
858 			{
859 				/* vmware.eventlog item returns vector of AGENT_RESULT representing events */
860 
861 				int		j;
862 				zbx_timespec_t	ts_tmp = timespec;
863 
864 				for (j = 0; j < add_results.values_num; j++)
865 				{
866 					AGENT_RESULT	*add_result = (AGENT_RESULT *)add_results.values[j];
867 
868 					if (ISSET_MSG(add_result))
869 					{
870 						items[i].state = ITEM_STATE_NOTSUPPORTED;
871 						zbx_preprocess_item_value(items[i].itemid, items[i].host.hostid,
872 						items[i].value_type, items[i].flags, NULL, &ts_tmp, items[i].state,
873 								add_result->msg);
874 					}
875 					else
876 					{
877 						items[i].state = ITEM_STATE_NORMAL;
878 						zbx_preprocess_item_value(items[i].itemid, items[i].host.hostid,
879 								items[i].value_type, items[i].flags, add_result,
880 								&ts_tmp, items[i].state, NULL);
881 					}
882 
883 					/* ensure that every log item value timestamp is unique */
884 					if (++ts_tmp.ns == 1000000000)
885 					{
886 						ts_tmp.sec++;
887 						ts_tmp.ns = 0;
888 					}
889 				}
890 			}
891 		}
892 		else if (NOTSUPPORTED == errcodes[i] || AGENT_ERROR == errcodes[i] || CONFIG_ERROR == errcodes[i])
893 		{
894 			items[i].state = ITEM_STATE_NOTSUPPORTED;
895 			zbx_preprocess_item_value(items[i].itemid, items[i].host.hostid, items[i].value_type,
896 					items[i].flags, NULL, &timespec, items[i].state, results[i].msg);
897 		}
898 
899 		DCpoller_requeue_items(&items[i].itemid, &timespec.sec, &errcodes[i], 1, poller_type,
900 				nextcheck);
901 	}
902 
903 	zbx_preprocessor_flush();
904 	zbx_clean_items(items, num, results);
905 	DCconfig_clean_items(items, NULL, num);
906 	zbx_vector_ptr_clear_ext(&add_results, (zbx_mem_free_func_t)zbx_free_result_ptr);
907 	zbx_vector_ptr_destroy(&add_results);
908 
909 	if (NULL != data)
910 	{
911 		zbx_availability_flush(data, data_offset);
912 		zbx_free(data);
913 	}
914 
915 	if (items != &item)
916 		zbx_free(items);
917 exit:
918 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, num);
919 
920 	return num;
921 }
922 
zbx_poller_sigusr_handler(int flags)923 static void	zbx_poller_sigusr_handler(int flags)
924 {
925 #ifdef HAVE_NETSNMP
926 	if (ZBX_RTC_SNMP_CACHE_RELOAD == ZBX_RTC_GET_MSG(flags))
927 		snmp_cache_reload_requested = 1;
928 #else
929 	ZBX_UNUSED(flags);
930 #endif
931 }
932 
ZBX_THREAD_ENTRY(poller_thread,args)933 ZBX_THREAD_ENTRY(poller_thread, args)
934 {
935 	int		nextcheck, sleeptime = -1, processed = 0, old_processed = 0;
936 	double		sec, total_sec = 0.0, old_total_sec = 0.0;
937 	time_t		last_stat_time;
938 	unsigned char	poller_type;
939 
940 #define	STAT_INTERVAL	5	/* if a process is busy and does not sleep then update status not faster than */
941 				/* once in STAT_INTERVAL seconds */
942 
943 	poller_type = *(unsigned char *)((zbx_thread_args_t *)args)->args;
944 	process_type = ((zbx_thread_args_t *)args)->process_type;
945 	server_num = ((zbx_thread_args_t *)args)->server_num;
946 	process_num = ((zbx_thread_args_t *)args)->process_num;
947 
948 	zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
949 			server_num, get_process_type_string(process_type), process_num);
950 
951 	update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);
952 
953 	scriptitem_es_engine_init();
954 
955 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
956 	zbx_tls_init_child();
957 #endif
958 	if (ZBX_POLLER_TYPE_HISTORY == poller_type)
959 	{
960 		zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num);
961 
962 		DBconnect(ZBX_DB_CONNECT_NORMAL);
963 	}
964 	zbx_setproctitle("%s #%d started", get_process_type_string(process_type), process_num);
965 	last_stat_time = time(NULL);
966 
967 	zbx_set_sigusr_handler(zbx_poller_sigusr_handler);
968 
969 	while (ZBX_IS_RUNNING())
970 	{
971 		sec = zbx_time();
972 		zbx_update_env(sec);
973 
974 #ifdef HAVE_NETSNMP
975 		if ((ZBX_POLLER_TYPE_NORMAL == poller_type || ZBX_POLLER_TYPE_UNREACHABLE == poller_type) &&
976 				1 == snmp_cache_reload_requested)
977 		{
978 			zbx_clear_cache_snmp(process_type, process_num);
979 			snmp_cache_reload_requested = 0;
980 		}
981 #endif
982 		if (0 != sleeptime)
983 		{
984 			zbx_setproctitle("%s #%d [got %d values in " ZBX_FS_DBL " sec, getting values]",
985 					get_process_type_string(process_type), process_num, old_processed,
986 					old_total_sec);
987 		}
988 
989 		processed += get_values(poller_type, &nextcheck);
990 		total_sec += zbx_time() - sec;
991 
992 		sleeptime = calculate_sleeptime(nextcheck, POLLER_DELAY);
993 
994 		if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time)
995 		{
996 			if (0 == sleeptime)
997 			{
998 				zbx_setproctitle("%s #%d [got %d values in " ZBX_FS_DBL " sec, getting values]",
999 					get_process_type_string(process_type), process_num, processed, total_sec);
1000 			}
1001 			else
1002 			{
1003 				zbx_setproctitle("%s #%d [got %d values in " ZBX_FS_DBL " sec, idle %d sec]",
1004 					get_process_type_string(process_type), process_num, processed, total_sec,
1005 					sleeptime);
1006 				old_processed = processed;
1007 				old_total_sec = total_sec;
1008 			}
1009 			processed = 0;
1010 			total_sec = 0.0;
1011 			last_stat_time = time(NULL);
1012 		}
1013 
1014 		zbx_sleep_loop(sleeptime);
1015 	}
1016 
1017 	scriptitem_es_engine_destroy();
1018 
1019 	zbx_setproctitle("%s #%d [terminated]", get_process_type_string(process_type), process_num);
1020 
1021 	while (1)
1022 		zbx_sleep(SEC_PER_MIN);
1023 #undef STAT_INTERVAL
1024 }
1025