/* ** Copyright (C) 2001-2025 Zabbix SIA ** ** This program is free software: you can redistribute it and/or modify it under the terms of ** the GNU Affero General Public License as published by the Free Software Foundation, version 3. ** ** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; ** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ** See the GNU Affero General Public License for more details. ** ** You should have received a copy of the GNU Affero General Public License along with this program. ** If not, see <https://www.gnu.org/licenses/>. **/ #include "zbxpoller.h" #include "checks_external.h" #include "checks_internal.h" #include "checks_script.h" #include "checks_browser.h" #include "checks_simple.h" #include "checks_snmp.h" #ifdef HAVE_UNIXODBC # include "checks_db.h" #endif #include "checks_java.h" #include "checks_calculated.h" #include "checks_http.h" #include "zbxexpression.h" #include "zbxalgo.h" #include "zbxcacheconfig.h" #include "zbxdbhigh.h" #include "zbxipcservice.h" #include "zbxstr.h" #include "zbxthreads.h" #include "zbxtimekeeper.h" #include "zbxnix.h" #include "zbxself.h" #include "zbxrtc.h" #include "zbxjson.h" #include "zbxhttp.h" #include "zbxexpr.h" #include "zbxlog.h" #include "zbxavailability.h" #include "zbx_availability_constants.h" #include "zbxcomms.h" #include "zbxnum.h" #include "zbxtime.h" #include "zbx_rtc_constants.h" #include "zbx_item_constants.h" #include "zbxpreproc.h" #include "zbxsysinfo.h" void zbx_free_agent_result_ptr(AGENT_RESULT *result) { zbx_free_agent_result(result); zbx_free(result); } static int get_value(zbx_dc_item_t *item, AGENT_RESULT *result, zbx_vector_agent_result_ptr_t *add_results, const zbx_config_comms_args_t *config_comms, int config_startup_time, unsigned char program_type, zbx_get_config_forks_f get_config_forks, const char *config_java_gateway, int config_java_gateway_port, const char *config_externalscripts, zbx_get_value_internal_ext_f get_value_internal_ext_cb, const char *config_ssh_key_location, const char *config_webdriver_url) { int res = FAIL, version = item->interface.version; zabbix_log(LOG_LEVEL_DEBUG, "In %s() key:'%s'", __func__, item->key_orig); switch (item->type) { case ITEM_TYPE_ZABBIX: res = zbx_agent_get_value(item, config_comms->config_source_ip, program_type, result, &version); break; case ITEM_TYPE_SIMPLE: /* simple checks use their own timeouts */ res = get_value_simple(item, result, add_results, get_config_forks); break; case ITEM_TYPE_INTERNAL: res = get_value_internal(item, result, config_comms, config_startup_time, config_java_gateway, config_java_gateway_port, get_config_forks, get_value_internal_ext_cb, program_type); break; case ITEM_TYPE_DB_MONITOR: #ifdef HAVE_UNIXODBC res = get_value_db(item, result); #else SET_MSG_RESULT(result, zbx_strdup(NULL, "Support for Database monitor checks was not compiled in.")); res = CONFIG_ERROR; #endif break; case ITEM_TYPE_EXTERNAL: /* external checks use their own timeouts */ res = get_value_external(item, config_externalscripts, result); break; case ITEM_TYPE_SSH: #if defined(HAVE_SSH2) || defined(HAVE_SSH) res = zbx_ssh_get_value(item, config_comms->config_source_ip, config_ssh_key_location, result); #else SET_MSG_RESULT(result, zbx_strdup(NULL, "Support for SSH checks was not compiled in.")); res = CONFIG_ERROR; #endif break; case ITEM_TYPE_TELNET: res = zbx_telnet_get_value(item, config_comms->config_source_ip, config_ssh_key_location, result); break; case ITEM_TYPE_CALCULATED: res = get_value_calculated(item, result); break; case ITEM_TYPE_HTTPAGENT: #ifdef HAVE_LIBCURL res = get_value_http(item, config_comms->config_source_ip, config_comms->config_ssl_ca_location, config_comms->config_ssl_cert_location, config_comms->config_ssl_key_location, result); #else SET_MSG_RESULT(result, zbx_strdup(NULL, "Support for HTTP agent checks was not compiled in.")); res = CONFIG_ERROR; #endif break; case ITEM_TYPE_SCRIPT: res = get_value_script(item, config_comms->config_source_ip, result); break; case ITEM_TYPE_BROWSER: res = get_value_browser(item, config_webdriver_url, config_comms->config_source_ip, result); break; default: SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Not supported item type:%d", item->type)); res = CONFIG_ERROR; } if (SUCCEED != res) { if (!ZBX_ISSET_MSG(result)) SET_MSG_RESULT(result, zbx_strdup(NULL, ZBX_NOTSUPPORTED_MSG)); zabbix_log(LOG_LEVEL_DEBUG, "Item [%s:%s] error: %s", item->host.host, item->key_orig, result->msg); } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(res)); return res; } static int parse_query_fields(const zbx_dc_item_t *item, char **query_fields, unsigned char expand_macros) { struct zbx_json_parse jp_array, jp_object; char name[MAX_STRING_LEN], value[MAX_STRING_LEN], *str = NULL; const char *member, *element = NULL; size_t alloc_len, offset; if ('\0' == **query_fields) return SUCCEED; if (SUCCEED != zbx_json_open(*query_fields, &jp_array)) { zabbix_log(LOG_LEVEL_ERR, "cannot parse query fields: %s", zbx_json_strerror()); return FAIL; } if (NULL == (element = zbx_json_next(&jp_array, element))) { zabbix_log(LOG_LEVEL_ERR, "cannot parse query fields: array is empty"); return FAIL; } do { char *data = NULL; if (SUCCEED != zbx_json_brackets_open(element, &jp_object) || NULL == (member = zbx_json_pair_next(&jp_object, NULL, name, sizeof(name))) || NULL == zbx_json_decodevalue(member, value, sizeof(value), NULL)) { zabbix_log(LOG_LEVEL_ERR, "cannot parse query fields: %s", zbx_json_strerror()); zbx_free(str); return FAIL; } if (NULL == str && NULL == strchr(item->url, '?')) zbx_chrcpy_alloc(&str, &alloc_len, &offset, '?'); else zbx_chrcpy_alloc(&str, &alloc_len, &offset, '&'); data = zbx_strdup(data, name); if (ZBX_MACRO_EXPAND_YES == expand_macros) { zbx_substitute_simple_macros(NULL, NULL, NULL,NULL, NULL, &item->host, item, NULL, NULL, NULL, NULL, NULL, &data, ZBX_MACRO_TYPE_HTTP_RAW, NULL, 0); } zbx_url_encode(data, &data); zbx_strcpy_alloc(&str, &alloc_len, &offset, data); zbx_chrcpy_alloc(&str, &alloc_len, &offset, '='); data = zbx_strdup(data, value); if (ZBX_MACRO_EXPAND_YES == expand_macros) { zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL,NULL, NULL, &item->host, item, NULL, NULL, NULL, NULL, NULL, &data, ZBX_MACRO_TYPE_HTTP_RAW, NULL, 0); } zbx_url_encode(data, &data); zbx_strcpy_alloc(&str, &alloc_len, &offset, data); free(data); } while (NULL != (element = zbx_json_next(&jp_array, element))); zbx_free(*query_fields); *query_fields = str; return SUCCEED; } void zbx_prepare_items(zbx_dc_item_t *items, int *errcodes, int num, AGENT_RESULT *results, unsigned char expand_macros) { char *port = NULL, error[ZBX_ITEM_ERROR_LEN_MAX], *timeout = NULL; zbx_dc_um_handle_t *um_handle; zabbix_log(LOG_LEVEL_DEBUG, "In %s() num:%d", __func__, num); if (ZBX_MACRO_EXPAND_YES == expand_macros) um_handle = zbx_dc_open_user_macros(); for (int i = 0; i < num; i++) { zbx_init_agent_result(&results[i]); errcodes[i] = SUCCEED; if (ZBX_MACRO_EXPAND_YES == expand_macros) { ZBX_STRDUP(items[i].key, items[i].key_orig); if (SUCCEED != zbx_substitute_key_macros_unmasked(&items[i].key, NULL, &items[i], NULL, NULL, ZBX_MACRO_TYPE_ITEM_KEY, error, sizeof(error))) { SET_MSG_RESULT(&results[i], zbx_strdup(NULL, error)); errcodes[i] = CONFIG_ERROR; continue; } } switch (items[i].type) { case ITEM_TYPE_ZABBIX: case ITEM_TYPE_SNMP: case ITEM_TYPE_JMX: ZBX_STRDUP(port, items[i].interface.port_orig); if (ZBX_MACRO_EXPAND_YES == expand_macros) { zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &port, ZBX_MACRO_TYPE_COMMON, NULL, 0); } if (FAIL == zbx_is_ushort(port, &items[i].interface.port)) { SET_MSG_RESULT(&results[i], zbx_dsprintf(NULL, "Invalid port number [%s]", items[i].interface.port_orig)); errcodes[i] = CONFIG_ERROR; continue; } break; } switch (items[i].type) { case ITEM_TYPE_ZABBIX: case ITEM_TYPE_ZABBIX_ACTIVE: case ITEM_TYPE_SIMPLE: case ITEM_TYPE_EXTERNAL: case ITEM_TYPE_DB_MONITOR: case ITEM_TYPE_SSH: case ITEM_TYPE_TELNET: case ITEM_TYPE_SNMP: case ITEM_TYPE_SCRIPT: case ITEM_TYPE_BROWSER: case ITEM_TYPE_HTTPAGENT: ZBX_STRDUP(timeout, items[i].timeout_orig); break; } switch (items[i].type) { case ITEM_TYPE_ZABBIX: case ITEM_TYPE_ZABBIX_ACTIVE: case ITEM_TYPE_EXTERNAL: if (ZBX_MACRO_EXPAND_NO == expand_macros) break; zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &timeout, ZBX_MACRO_TYPE_COMMON, NULL, 0); break; case ITEM_TYPE_SNMP: if (ZBX_MACRO_EXPAND_NO == expand_macros) break; if (ZBX_IF_SNMP_VERSION_3 == items[i].snmp_version) { ZBX_STRDUP(items[i].snmpv3_securityname, items[i].snmpv3_securityname_orig); ZBX_STRDUP(items[i].snmpv3_authpassphrase, items[i].snmpv3_authpassphrase_orig); ZBX_STRDUP(items[i].snmpv3_privpassphrase, items[i].snmpv3_privpassphrase_orig); ZBX_STRDUP(items[i].snmpv3_contextname, items[i].snmpv3_contextname_orig); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].snmpv3_securityname, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].snmpv3_authpassphrase, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].snmpv3_privpassphrase, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].snmpv3_contextname, ZBX_MACRO_TYPE_COMMON, NULL, 0); } ZBX_STRDUP(items[i].snmp_community, items[i].snmp_community_orig); ZBX_STRDUP(items[i].snmp_oid, items[i].snmp_oid_orig); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].snmp_community, ZBX_MACRO_TYPE_COMMON, NULL, 0); if (SUCCEED != zbx_substitute_key_macros(&items[i].snmp_oid, &items[i].host.hostid, NULL, NULL, NULL, ZBX_MACRO_TYPE_SNMP_OID, error, sizeof(error))) { SET_MSG_RESULT(&results[i], zbx_strdup(NULL, error)); errcodes[i] = CONFIG_ERROR; zbx_free(timeout); continue; } zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &timeout, ZBX_MACRO_TYPE_COMMON, NULL, 0); break; case ITEM_TYPE_SCRIPT: case ITEM_TYPE_BROWSER: if (ZBX_MACRO_EXPAND_NO == expand_macros) break; zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &timeout, ZBX_MACRO_TYPE_COMMON, NULL, 0); for (int j = 0; j < items[i].script_params.values_num; j++) { zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, NULL, NULL, &items[i], NULL, NULL, NULL, NULL, NULL, (char **)&items[i].script_params.values[j].first, ZBX_MACRO_TYPE_SCRIPT_PARAMS_FIELD, NULL, 0); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, NULL, NULL, &items[i], NULL, NULL, NULL, NULL, NULL, (char **)&items[i].script_params.values[j].second, ZBX_MACRO_TYPE_SCRIPT_PARAMS_FIELD, NULL, 0); } zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].params, ZBX_MACRO_TYPE_COMMON, NULL, 0); break; case ITEM_TYPE_SSH: if (ZBX_MACRO_EXPAND_NO == expand_macros) break; ZBX_STRDUP(items[i].publickey, items[i].publickey_orig); ZBX_STRDUP(items[i].privatekey, items[i].privatekey_orig); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].publickey, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].privatekey, ZBX_MACRO_TYPE_COMMON, NULL, 0); ZBX_FALLTHROUGH; case ITEM_TYPE_TELNET: case ITEM_TYPE_DB_MONITOR: if (ZBX_MACRO_EXPAND_NO == expand_macros) break; zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, NULL, NULL, &items[i], NULL, NULL, NULL, NULL, NULL, &items[i].params, ZBX_MACRO_TYPE_PARAMS_FIELD, NULL, 0); ZBX_FALLTHROUGH; case ITEM_TYPE_SIMPLE: if (ZBX_MACRO_EXPAND_NO == expand_macros) break; items[i].username = zbx_strdup(items[i].username, items[i].username_orig); items[i].password = zbx_strdup(items[i].password, items[i].password_orig); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].username, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].password, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &timeout, ZBX_MACRO_TYPE_COMMON, NULL, 0); break; case ITEM_TYPE_JMX: if (ZBX_MACRO_EXPAND_NO == expand_macros) break; items[i].username = zbx_strdup(items[i].username, items[i].username_orig); items[i].password = zbx_strdup(items[i].password, items[i].password_orig); items[i].jmx_endpoint = zbx_strdup(items[i].jmx_endpoint, items[i].jmx_endpoint_orig); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].username, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].password, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, NULL, &items[i], NULL, NULL, NULL, NULL, NULL, &items[i].jmx_endpoint, ZBX_MACRO_TYPE_JMX_ENDPOINT, NULL, 0); break; case ITEM_TYPE_HTTPAGENT: if (ZBX_MACRO_EXPAND_YES == expand_macros) { ZBX_STRDUP(items[i].url, items[i].url_orig); ZBX_STRDUP(items[i].status_codes, items[i].status_codes_orig); ZBX_STRDUP(items[i].http_proxy, items[i].http_proxy_orig); ZBX_STRDUP(items[i].ssl_cert_file, items[i].ssl_cert_file_orig); ZBX_STRDUP(items[i].ssl_key_file, items[i].ssl_key_file_orig); ZBX_STRDUP(items[i].ssl_key_password, items[i].ssl_key_password_orig); ZBX_STRDUP(items[i].username, items[i].username_orig); ZBX_STRDUP(items[i].password, items[i].password_orig); ZBX_STRDUP(items[i].query_fields, items[i].query_fields_orig); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &timeout, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, NULL, &items[i].host, &items[i], NULL, NULL, NULL, NULL, NULL, &items[i].url, ZBX_MACRO_TYPE_HTTP_RAW, NULL, 0); } if (SUCCEED != zbx_http_punycode_encode_url(&items[i].url)) { SET_MSG_RESULT(&results[i], zbx_strdup(NULL, "Cannot encode URL into punycode")); errcodes[i] = CONFIG_ERROR; zbx_free(timeout); continue; } if (FAIL == parse_query_fields(&items[i], &items[i].query_fields, expand_macros)) { SET_MSG_RESULT(&results[i], zbx_strdup(NULL, "Invalid query fields")); errcodes[i] = CONFIG_ERROR; zbx_free(timeout); continue; } if (ZBX_MACRO_EXPAND_NO == expand_macros) break; switch (items[i].post_type) { case ZBX_POSTTYPE_XML: if (SUCCEED != zbx_substitute_macros_xml_unmasked(&items[i].posts, &items[i], NULL, NULL, error, sizeof(error))) { SET_MSG_RESULT(&results[i], zbx_dsprintf(NULL, "%s.", error)); errcodes[i] = CONFIG_ERROR; zbx_free(timeout); continue; } break; case ZBX_POSTTYPE_JSON: zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL,NULL, NULL, &items[i].host, &items[i], NULL, NULL, NULL, NULL, NULL, &items[i].posts, ZBX_MACRO_TYPE_HTTP_JSON, NULL, 0); break; default: zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL,NULL, NULL, &items[i].host, &items[i], NULL, NULL, NULL, NULL, NULL, &items[i].posts, ZBX_MACRO_TYPE_HTTP_RAW, NULL, 0); break; } zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL,NULL, NULL, &items[i].host, &items[i], NULL, NULL, NULL, NULL, NULL, &items[i].headers, ZBX_MACRO_TYPE_HTTP_RAW, NULL, 0); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].status_codes, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].http_proxy, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros(NULL, NULL, NULL,NULL, NULL, &items[i].host, &items[i], NULL, NULL, NULL, NULL, NULL, &items[i].ssl_cert_file, ZBX_MACRO_TYPE_HTTP_RAW, NULL, 0); zbx_substitute_simple_macros(NULL, NULL, NULL,NULL, NULL, &items[i].host, &items[i], NULL, NULL, NULL, NULL, NULL, &items[i].ssl_key_file, ZBX_MACRO_TYPE_HTTP_RAW, NULL, 0); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].ssl_key_password, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].username, ZBX_MACRO_TYPE_COMMON, NULL, 0); zbx_substitute_simple_macros_unmasked(NULL, NULL, NULL, NULL, &items[i].host.hostid, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &items[i].password, ZBX_MACRO_TYPE_COMMON, NULL, 0); break; } if (NULL != timeout) { int timeout_sec = 0; if (FAIL == zbx_validate_item_timeout(timeout, &timeout_sec, error, sizeof(error))) { SET_MSG_RESULT(&results[i], zbx_strdup(NULL, error)); errcodes[i] = CONFIG_ERROR; } else items[i].timeout = timeout_sec; } zbx_free(timeout); } zbx_free(port); if (ZBX_MACRO_EXPAND_YES == expand_macros) zbx_dc_close_user_macros(um_handle); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } /* Actually this could be called by trapper, without poller being initialized, */ /* so cannot call poller_get_progname(), need progname to be passed directly. */ void zbx_check_items(zbx_dc_item_t *items, int *errcodes, int num, AGENT_RESULT *results, zbx_vector_agent_result_ptr_t *add_results, unsigned char poller_type, const zbx_config_comms_args_t *config_comms, int config_startup_time, unsigned char program_type, const char *progname, zbx_get_config_forks_f get_config_forks, const char *config_java_gateway, int config_java_gateway_port, const char *config_externalscripts, zbx_get_value_internal_ext_f get_value_internal_ext_cb, const char *config_ssh_key_location, const char *config_webdriver_url) { if (ITEM_TYPE_SNMP == items[0].type) { #ifndef HAVE_NETSNMP ZBX_UNUSED(poller_type); ZBX_UNUSED(progname); for (int i = 0; i < num; i++) { if (SUCCEED != errcodes[i]) continue; SET_MSG_RESULT(&results[i], zbx_strdup(NULL, "Support for SNMP checks was not compiled in.")); errcodes[i] = CONFIG_ERROR; } #else /* legacy SNMP checks use config timeout * walk[ and get[ use item timeout */ get_values_snmp(items, results, errcodes, num, poller_type, config_comms->config_source_ip, config_comms->config_timeout, progname); #endif } else if (ITEM_TYPE_JMX == items[0].type) { get_values_java(ZBX_JAVA_GATEWAY_REQUEST_JMX, items, results, errcodes, num, config_comms->config_timeout, config_comms->config_source_ip, config_java_gateway, config_java_gateway_port); } else if (1 == num) { if (SUCCEED == errcodes[0]) { errcodes[0] = get_value(&items[0], &results[0], add_results, config_comms, config_startup_time, program_type, get_config_forks, config_java_gateway, config_java_gateway_port, config_externalscripts, get_value_internal_ext_cb, config_ssh_key_location, config_webdriver_url); } } else THIS_SHOULD_NEVER_HAPPEN; } void zbx_clean_items(zbx_dc_item_t *items, int num, AGENT_RESULT *results) { for (int i = 0; i < num; i++) { zbx_free(items[i].key); switch (items[i].type) { case ITEM_TYPE_SNMP: if (ZBX_IF_SNMP_VERSION_3 == items[i].snmp_version) { zbx_free(items[i].snmpv3_securityname); zbx_free(items[i].snmpv3_authpassphrase); zbx_free(items[i].snmpv3_privpassphrase); zbx_free(items[i].snmpv3_contextname); } zbx_free(items[i].snmp_community); zbx_free(items[i].snmp_oid); break; case ITEM_TYPE_HTTPAGENT: zbx_free(items[i].url); zbx_free(items[i].query_fields); zbx_free(items[i].status_codes); zbx_free(items[i].http_proxy); zbx_free(items[i].ssl_cert_file); zbx_free(items[i].ssl_key_file); zbx_free(items[i].ssl_key_password); zbx_free(items[i].username); zbx_free(items[i].password); break; case ITEM_TYPE_SSH: zbx_free(items[i].publickey); zbx_free(items[i].privatekey); ZBX_FALLTHROUGH; case ITEM_TYPE_TELNET: case ITEM_TYPE_DB_MONITOR: case ITEM_TYPE_SIMPLE: zbx_free(items[i].username); zbx_free(items[i].password); break; case ITEM_TYPE_JMX: zbx_free(items[i].username); zbx_free(items[i].password); zbx_free(items[i].jmx_endpoint); break; } zbx_free_agent_result(&results[i]); } } ZBX_PTR_VECTOR_IMPL(agent_result_ptr, AGENT_RESULT*) /*********************************************************************************** * * * Purpose: retrieves values of metrics from monitored hosts * * * * Parameters: poller_type - [IN] poller type (ZBX_POLLER_TYPE_...) * * nextcheck - [OUT] item nextcheck * * config_comms - [IN] server/proxy configuration for * * communication * * config_startup_time - [IN] program startup time * * config_unavailable_delay - [IN] * * config_unreachable_period - [IN] * * config_unreachable_delay - [IN] * * program_type - [IN] * * progname - [IN] * * get_config_forks - [IN] * * config_java_gateway - [IN] * * config_java_gateway_port - [IN] * * config_externalscripts - [IN] * * get_value_internal_ext_cb - [IN] * * config_ssh_key_location - [IN] * * config_webdriver_url - [IN] * * * * Return value: number of items processed * * * * Comments: Processes single item at a time except for Java, SNMP items, * * see zbx_dc_config_get_poller_items(). * * * **********************************************************************************/ static int get_values(unsigned char poller_type, int *nextcheck, const zbx_config_comms_args_t *config_comms, int config_startup_time, int config_unavailable_delay, int config_unreachable_period, int config_unreachable_delay, unsigned char program_type, const char *progname, zbx_get_config_forks_f get_config_forks, const char *config_java_gateway, int config_java_gateway_port, const char *config_externalscripts, zbx_get_value_internal_ext_f get_value_internal_ext_cb, const char *config_ssh_key_location, const char *config_webdriver_url) { zbx_dc_item_t item, *items; AGENT_RESULT results[ZBX_MAX_POLLER_ITEMS]; int errcodes[ZBX_MAX_POLLER_ITEMS]; zbx_timespec_t timespec; int num, last_available = ZBX_INTERFACE_AVAILABLE_UNKNOWN; zbx_vector_agent_result_ptr_t add_results; unsigned char *data = NULL; size_t data_alloc = 0, data_offset = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); items = &item; num = zbx_dc_config_get_poller_items(poller_type, config_comms->config_timeout, 0, 0, &items); if (0 == num) { *nextcheck = zbx_dc_config_get_poller_nextcheck(poller_type); goto exit; } zbx_vector_agent_result_ptr_create(&add_results); zbx_prepare_items(items, errcodes, num, results, ZBX_MACRO_EXPAND_YES); zbx_check_items(items, errcodes, num, results, &add_results, poller_type, config_comms, config_startup_time, program_type, progname, get_config_forks, config_java_gateway, config_java_gateway_port, config_externalscripts, get_value_internal_ext_cb, config_ssh_key_location, config_webdriver_url); zbx_timespec(×pec); /* process item values */ for (int i = 0; i < num; i++) { switch (errcodes[i]) { case SUCCEED: case NOTSUPPORTED: case AGENT_ERROR: if (ZBX_INTERFACE_AVAILABLE_TRUE != last_available) { zbx_activate_item_interface(×pec, &items[i].interface, items[i].itemid, items[i].type, items[i].host.host, 0, &data, &data_alloc, &data_offset); last_available = ZBX_INTERFACE_AVAILABLE_TRUE; } break; case NETWORK_ERROR: case GATEWAY_ERROR: case TIMEOUT_ERROR: if (ZBX_INTERFACE_AVAILABLE_FALSE != last_available) { zbx_deactivate_item_interface(×pec, &items[i].interface, items[i].itemid, items[i].type, items[i].host.host, items[i].key_orig, &data, &data_alloc, &data_offset, config_unavailable_delay, config_unreachable_period, config_unreachable_delay, results[i].msg); last_available = ZBX_INTERFACE_AVAILABLE_FALSE; } break; case CONFIG_ERROR: /* nothing to do */ break; case SIG_ERROR: /* nothing to do, execution was forcibly interrupted by signal */ break; default: zbx_error("unknown response code returned: %d", errcodes[i]); THIS_SHOULD_NEVER_HAPPEN; } if (SUCCEED == errcodes[i]) { if (0 == add_results.values_num) { items[i].state = ITEM_STATE_NORMAL; zbx_preprocess_item_value(items[i].itemid, items[i].host.hostid, items[i].value_type, items[i].flags, &results[i], ×pec, items[i].state, NULL); } else { /* vmware.eventlog item returns vector of AGENT_RESULT representing events */ zbx_timespec_t ts_tmp = timespec; for (int j = 0; j < add_results.values_num; j++) { AGENT_RESULT *add_result = (AGENT_RESULT *)add_results.values[j]; if (ZBX_ISSET_MSG(add_result)) { items[i].state = ITEM_STATE_NOTSUPPORTED; zbx_preprocess_item_value(items[i].itemid, items[i].host.hostid, items[i].value_type, items[i].flags, NULL, &ts_tmp, items[i].state, add_result->msg); } else { items[i].state = ITEM_STATE_NORMAL; zbx_preprocess_item_value(items[i].itemid, items[i].host.hostid, items[i].value_type, items[i].flags, add_result, &ts_tmp, items[i].state, NULL); } /* ensure that every log item value timestamp is unique */ if (++ts_tmp.ns == 1000000000) { ts_tmp.sec++; ts_tmp.ns = 0; } } } } else if (NOTSUPPORTED == errcodes[i] || AGENT_ERROR == errcodes[i] || CONFIG_ERROR == errcodes[i]) { items[i].state = ITEM_STATE_NOTSUPPORTED; zbx_preprocess_item_value(items[i].itemid, items[i].host.hostid, items[i].value_type, items[i].flags, NULL, ×pec, items[i].state, results[i].msg); } zbx_dc_poller_requeue_items(&items[i].itemid, ×pec.sec, &errcodes[i], 1, poller_type, nextcheck); } zbx_preprocessor_flush(); zbx_clean_items(items, num, results); zbx_dc_config_clean_items(items, NULL, (size_t)num); zbx_vector_agent_result_ptr_clear_ext(&add_results, zbx_free_agent_result_ptr); zbx_vector_agent_result_ptr_destroy(&add_results); if (NULL != data) { zbx_availability_send(ZBX_IPC_AVAILABILITY_REQUEST, data, (zbx_uint32_t)data_offset, NULL); zbx_free(data); } if (items != &item) zbx_free(items); exit: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __func__, num); return num; } ZBX_THREAD_ENTRY(zbx_poller_thread, args) { zbx_thread_poller_args *poller_args_in = (zbx_thread_poller_args *)(((zbx_thread_args_t *)args)->args); int nextcheck, sleeptime = -1, processed = 0, old_processed = 0, server_num = ((zbx_thread_args_t *)args)->info.server_num, process_num = ((zbx_thread_args_t *)args)->info.process_num; double sec, total_sec = 0.0, old_total_sec = 0.0; time_t last_stat_time; unsigned char poller_type; zbx_ipc_async_socket_t rtc; const zbx_thread_info_t *info = &((zbx_thread_args_t *)args)->info; unsigned char process_type = ((zbx_thread_args_t *)args)->info.process_type; zbx_uint32_t rtc_msgs[] = {ZBX_RTC_SNMP_CACHE_RELOAD}; #ifdef HAVE_NETSNMP time_t last_snmp_engineid_hk_time = 0; #endif #define STAT_INTERVAL 5 /* if a process is busy and does not sleep then update status not faster than */ /* once in STAT_INTERVAL seconds */ poller_type = (poller_args_in->poller_type); zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(info->program_type), server_num, get_process_type_string(process_type), process_num); zbx_update_selfmon_counter(info, ZBX_PROCESS_STATE_BUSY); scriptitem_es_engine_init(); #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_tls_init_child(poller_args_in->config_comms->config_tls, poller_args_in->zbx_get_program_type_cb_arg, zbx_dc_get_psk_by_identity); #endif if (ZBX_POLLER_TYPE_HISTORY == poller_type) { zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num); zbx_db_connect(ZBX_DB_CONNECT_NORMAL); } zbx_setproctitle("%s #%d started", get_process_type_string(process_type), process_num); last_stat_time = time(NULL); zbx_rtc_subscribe(process_type, process_num, rtc_msgs, ARRSIZE(rtc_msgs), poller_args_in->config_comms->config_timeout, &rtc); while (ZBX_IS_RUNNING()) { zbx_uint32_t rtc_cmd; unsigned char *rtc_data; sec = zbx_time(); zbx_update_env(get_process_type_string(process_type), sec); if (0 != sleeptime) { zbx_setproctitle("%s #%d [got %d values in " ZBX_FS_DBL " sec, getting values]", get_process_type_string(process_type), process_num, old_processed, old_total_sec); } if (ZBX_POLLER_TYPE_INTERNAL == poller_type || FAIL == zbx_vps_monitor_capped()) { processed += get_values(poller_type, &nextcheck, poller_args_in->config_comms, poller_args_in->config_startup_time, poller_args_in->config_unavailable_delay, poller_args_in->config_unreachable_period, poller_args_in->config_unreachable_delay, info->program_type, poller_args_in->progname, poller_args_in->get_config_forks, poller_args_in->config_java_gateway, poller_args_in->config_java_gateway_port, poller_args_in->config_externalscripts, poller_args_in->zbx_get_value_internal_ext_cb, poller_args_in->config_ssh_key_location, poller_args_in->config_webdriver_url); sleeptime = zbx_calculate_sleeptime(nextcheck, POLLER_DELAY); } else sleeptime = POLLER_DELAY; total_sec += zbx_time() - sec; if (0 != sleeptime || STAT_INTERVAL <= time(NULL) - last_stat_time) { if (0 == sleeptime) { zbx_setproctitle("%s #%d [got %d values in " ZBX_FS_DBL " sec, getting values]", get_process_type_string(process_type), process_num, processed, total_sec); } else { const char *ext; ext = (ZBX_POLLER_TYPE_INTERNAL == poller_type ? "" : zbx_vps_monitor_status()); zbx_setproctitle("%s #%d [got %d values in " ZBX_FS_DBL " sec, idle %d sec%s]", get_process_type_string(process_type), process_num, processed, total_sec, sleeptime, ext); old_processed = processed; old_total_sec = total_sec; } processed = 0; total_sec = 0.0; last_stat_time = time(NULL); } if (SUCCEED == zbx_rtc_wait(&rtc, info, &rtc_cmd, &rtc_data, sleeptime) && 0 != rtc_cmd) { #ifdef HAVE_NETSNMP if (ZBX_RTC_SNMP_CACHE_RELOAD == rtc_cmd) { if (ZBX_POLLER_TYPE_NORMAL == poller_type || ZBX_POLLER_TYPE_UNREACHABLE == poller_type) zbx_clear_cache_snmp(process_type, process_num); } #endif if (ZBX_RTC_SHUTDOWN == rtc_cmd) break; } #ifdef HAVE_NETSNMP #define SNMP_ENGINEID_HK_INTERVAL 86400 if ((ZBX_POLLER_TYPE_NORMAL == poller_type || ZBX_POLLER_TYPE_UNREACHABLE == poller_type) && time(NULL) >= SNMP_ENGINEID_HK_INTERVAL + last_snmp_engineid_hk_time) { last_snmp_engineid_hk_time = time(NULL); zbx_clear_cache_snmp(process_type, process_num); } #undef SNMP_ENGINEID_HK_INTERVAL #endif } scriptitem_es_engine_destroy(); zbx_setproctitle("%s #%d [terminated]", get_process_type_string(process_type), process_num); while (1) zbx_sleep(SEC_PER_MIN); #undef STAT_INTERVAL }