/* ** 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 "zbx_availability_constants.h" #include "zbxavailability.h" #include "zbxcacheconfig.h" #include "zbxdbhigh.h" #include "zbxtime.h" #include "zbxinterface.h" /****************************************************************************** * * * Purpose: writes interface availability changes into database * * * * Parameters: data - [IN/OUT] serialized availability data * * data_alloc - [IN/OUT] serialized availability data size * * data_offset - [IN/OUT] serialized availability data offset * * ia - [IN] interface availability data * * * * Return value: SUCCEED - availability changes were written into db * * FAIL - no changes in availability data were detected * * * ******************************************************************************/ static int update_interface_availability(unsigned char **data, size_t *data_alloc, size_t *data_offset, const zbx_interface_availability_t *ia) { if (FAIL == zbx_interface_availability_is_set(ia)) return FAIL; zbx_availability_serialize_interface(data, data_alloc, data_offset, ia); return SUCCEED; } /****************************************************************************** * * * Parameters: dc_interface - [IN] interface * * ia - [OUT] interface availability data * * * ******************************************************************************/ static void interface_get_availability(const zbx_dc_interface_t *dc_interface, zbx_interface_availability_t *ia) { zbx_agent_availability_t *availability = &ia->agent; availability->flags = ZBX_FLAGS_AGENT_STATUS; availability->available = dc_interface->available; availability->error = zbx_strdup(NULL, dc_interface->error); availability->errors_from = dc_interface->errors_from; availability->disable_until = dc_interface->disable_until; ia->interfaceid = dc_interface->interfaceid; } /******************************************************************************** * * * Parameters: dc_interface - [IN/OUT] interface * * ia - [IN] interface availability data * * * *******************************************************************************/ static void interface_set_availability(zbx_dc_interface_t *dc_interface, const zbx_interface_availability_t *ia) { const zbx_agent_availability_t *availability = &ia->agent; unsigned char *pavailable; int *perrors_from, *pdisable_until; char *perror; pavailable = &dc_interface->available; perror = dc_interface->error; perrors_from = &dc_interface->errors_from; pdisable_until = &dc_interface->disable_until; if (0 != (availability->flags & ZBX_FLAGS_AGENT_STATUS_AVAILABLE)) *pavailable = availability->available; if (0 != (availability->flags & ZBX_FLAGS_AGENT_STATUS_ERROR)) zbx_strlcpy(perror, availability->error, ZBX_INTERFACE_ERROR_LEN_MAX); if (0 != (availability->flags & ZBX_FLAGS_AGENT_STATUS_ERRORS_FROM)) *perrors_from = availability->errors_from; if (0 != (availability->flags & ZBX_FLAGS_AGENT_STATUS_DISABLE_UNTIL)) *pdisable_until = availability->disable_until; } static int interface_availability_by_item_type(unsigned char item_type, unsigned char interface_type) { if ((ITEM_TYPE_ZABBIX == item_type && INTERFACE_TYPE_AGENT == interface_type) || (ITEM_TYPE_SNMP == item_type && INTERFACE_TYPE_SNMP == interface_type) || (ITEM_TYPE_JMX == item_type && INTERFACE_TYPE_JMX == interface_type) || (ITEM_TYPE_IPMI == item_type && INTERFACE_TYPE_IPMI == interface_type)) return SUCCEED; return FAIL; } static const char *item_type_agent_string(zbx_item_type_t item_type) { switch (item_type) { case ITEM_TYPE_ZABBIX: return "Zabbix agent"; case ITEM_TYPE_SNMP: return "SNMP agent"; case ITEM_TYPE_IPMI: return "IPMI agent"; case ITEM_TYPE_JMX: return "JMX agent"; default: return "generic"; } } /******************************************************************************** * * * Parameters: ts - [IN] timestamp * * interface - [IN] * * itemid - [IN] * * type - [IN] * * host - [IN] * * version - [IN/OUT] interface version * * data - [IN/OUT] serialized availability data * * data_alloc - [IN/OUT] serialized availability data size * * data_offset - [IN/OUT] serialized availability data offset * * * *******************************************************************************/ void zbx_activate_item_interface(zbx_timespec_t *ts, zbx_dc_interface_t *interface, zbx_uint64_t itemid, int type, char *host, int version, unsigned char **data, size_t *data_alloc, size_t *data_offset) { zbx_interface_availability_t in, out; zabbix_log(LOG_LEVEL_DEBUG, "In %s() interfaceid:" ZBX_FS_UI64 " itemid:" ZBX_FS_UI64 " type:%d version:%x", __func__, interface->interfaceid, itemid, (int)type, version); zbx_interface_availability_init(&in, interface->interfaceid); zbx_interface_availability_init(&out, interface->interfaceid); if (FAIL == interface_availability_by_item_type((unsigned char)type, interface->type)) goto out; interface_get_availability(interface, &in); if (INTERFACE_TYPE_AGENT == interface->type && version != interface->version) zbx_dc_set_interface_version(interface->interfaceid, version); if (FAIL == zbx_dc_interface_activate(interface->interfaceid, ts, &in.agent, &out.agent)) goto out; if (FAIL == update_interface_availability(data, data_alloc, data_offset, &out)) goto out; interface_set_availability(interface, &out); if (ZBX_INTERFACE_AVAILABLE_TRUE == in.agent.available) { zabbix_log(LOG_LEVEL_WARNING, "resuming %s checks on host \"%s\": connection restored", item_type_agent_string(type), host); } else { zabbix_log(LOG_LEVEL_WARNING, "enabling %s checks on host \"%s\": interface became available", item_type_agent_string(type), host); } out: zbx_interface_availability_clean(&out); zbx_interface_availability_clean(&in); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); } /*********************************************************************************** * * * Parameters: ts - [IN] timestamp * * interface - [IN] * * itemid - [IN] * * type - [IN] * * host - [IN] * * key_orig - [IN] * * data - [IN/OUT] serialized availability data * * data_alloc - [IN/OUT] serialized availability data size * * data_offset - [IN/OUT] serialized availability data offset * * unavailable_delay - [IN] * * unreachable_period - [IN] * * unreachable_delay - [IN] * * error - [IN/OUT] * * * ***********************************************************************************/ void zbx_deactivate_item_interface(zbx_timespec_t *ts, zbx_dc_interface_t *interface, zbx_uint64_t itemid, int type, char *host, char *key_orig, unsigned char **data, size_t *data_alloc, size_t *data_offset, int unavailable_delay, int unreachable_period, int unreachable_delay, const char *error) { zbx_interface_availability_t in, out; zabbix_log(LOG_LEVEL_DEBUG, "In %s() interfaceid:" ZBX_FS_UI64 " itemid:" ZBX_FS_UI64 " type:%d", __func__, interface->interfaceid, itemid, type); zbx_interface_availability_init(&in, interface->interfaceid); zbx_interface_availability_init(&out, interface->interfaceid); if (FAIL == interface_availability_by_item_type((unsigned char)type, interface->type)) goto out; interface_get_availability(interface, &in); if (FAIL == zbx_dc_interface_deactivate(interface->interfaceid, ts, unavailable_delay, unreachable_period, unreachable_delay, &in.agent, &out.agent, error)) { goto out; } if (FAIL == update_interface_availability(data, data_alloc, data_offset, &out)) goto out; interface_set_availability(interface, &out); if (0 == in.agent.errors_from) { zabbix_log(LOG_LEVEL_WARNING, "%s item \"%s\" on host \"%s\" failed:" " first network error, wait for %d seconds", item_type_agent_string(type), key_orig, host, out.agent.disable_until - ts->sec); } else if (ZBX_INTERFACE_AVAILABLE_FALSE != in.agent.available) { if (ZBX_INTERFACE_AVAILABLE_FALSE != out.agent.available) { zabbix_log(LOG_LEVEL_WARNING, "%s item \"%s\" on host \"%s\" failed:" " another network error, wait for %d seconds", item_type_agent_string(type), key_orig, host, out.agent.disable_until - ts->sec); } else { zabbix_log(LOG_LEVEL_WARNING, "temporarily disabling %s checks on host \"%s\":" " interface unavailable", item_type_agent_string(type), host); } } zabbix_log(LOG_LEVEL_DEBUG, "%s() errors_from:%d available:%d", __func__, out.agent.errors_from, out.agent.available); out: zbx_interface_availability_clean(&out); zbx_interface_availability_clean(&in); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); }