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(×pec);
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(×pec, &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(×pec, &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], ×pec, 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, ×pec, items[i].state, results[i].msg);
897 }
898
899 DCpoller_requeue_items(&items[i].itemid, ×pec.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