/****************************************************************************** * * * Function: recv_discovery_data * * * * Author: Alexander Vladishev * * * ******************************************************************************/ void recv_discovery_data(zbx_sock_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "recv_discovery_data"; int ret; zbx_uint64_t proxy_hostid; char host[HOST_HOST_LEN_MAX], *error = NULL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (SUCCEED != (ret = get_active_proxy_id(jp, &proxy_hostid, host, &error))) { zabbix_log(LOG_LEVEL_WARNING, "discovery data from active proxy on \"%s\" failed: %s", get_ip_by_socket(sock), error); goto out; } process_dhis_data(jp); out: zbx_send_response(sock, ret, error, CONFIG_TIMEOUT); zbx_free(error); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); }
/****************************************************************************** * * * Function: recv_host_availability * * * * Purpose: update hosts availability, monitored by proxies * * * * Author: Alexander Vladishev * * * ******************************************************************************/ void recv_host_availability(zbx_socket_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "recv_host_availability"; zbx_uint64_t proxy_hostid; char host[HOST_HOST_LEN_MAX], *error = NULL; int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (SUCCEED != (ret = get_active_proxy_id(jp, &proxy_hostid, host, sock, &error))) { zabbix_log(LOG_LEVEL_WARNING, "cannot parse host availability data from active proxy at \"%s\": %s", sock->peer, error); goto out; } if (SUCCEED != (ret = process_host_availability(jp, &error))) { zabbix_log(LOG_LEVEL_WARNING, "received invalid host availability data from proxy \"%s\" at \"%s\": %s", host, sock->peer, error); } out: zbx_send_response(sock, ret, error, CONFIG_TIMEOUT); zbx_free(error); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: recv_proxyhistory * * * * Purpose: processes the received values from active proxies * * * ******************************************************************************/ static void recv_proxyhistory(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_timespec_t *ts) { const char *__function_name = "recv_proxyhistory"; zbx_uint64_t proxy_hostid; char host[HOST_HOST_LEN_MAX], *error = NULL; int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (SUCCEED != (ret = get_active_proxy_id(jp, &proxy_hostid, host, sock, &error))) { zabbix_log(LOG_LEVEL_WARNING, "cannot parse history data from active proxy at \"%s\": %s", sock->peer, error); goto out; } update_proxy_lastaccess(proxy_hostid); ret = process_hist_data(sock, jp, proxy_hostid, ts, &error); out: zbx_send_response(sock, ret, error, CONFIG_TIMEOUT); zbx_free(error); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: get_data_from_proxy * * * * Purpose: get historical data from proxy * * * * Parameters: * * * * Return value: SUCCESS - processed successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static int get_data_from_proxy(DC_PROXY *proxy, const char *request, char **data) { const char *__function_name = "get_data_from_proxy"; zbx_socket_t s; struct zbx_json j; int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s() request:'%s'", __function_name, request); zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); zbx_json_addstring(&j, "request", request, ZBX_JSON_TYPE_STRING); if (SUCCEED == (ret = connect_to_proxy(proxy, &s, CONFIG_TRAPPER_TIMEOUT))) { if (SUCCEED == (ret = send_data_to_proxy(proxy, &s, j.buffer))) if (SUCCEED == (ret = recv_data_from_proxy(proxy, &s))) if (SUCCEED == (ret = zbx_send_response(&s, SUCCEED, NULL, 0))) *data = zbx_strdup(*data, s.buffer); disconnect_proxy(&s); } zbx_json_free(&j); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/****************************************************************************** * * * Function: send_proxyconfig * * * * Purpose: send configuration tables to the proxy from server * * (for active proxies) * * * * Author: Alexander Vladishev * * * ******************************************************************************/ void send_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "send_proxyconfig"; zbx_uint64_t proxy_hostid; char host[HOST_HOST_LEN_MAX], *error = NULL; struct zbx_json j; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (SUCCEED != get_active_proxy_id(jp, &proxy_hostid, host, sock, &error)) { zbx_send_response(sock, FAIL, error, CONFIG_TIMEOUT); zabbix_log(LOG_LEVEL_WARNING, "cannot parse proxy configuration data request from active proxy at" " \"%s\": %s", sock->peer, error); goto out; } update_proxy_lastaccess(proxy_hostid); zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); if (SUCCEED != get_proxyconfig_data(proxy_hostid, &j, &error)) { zbx_send_response(sock, FAIL, error, CONFIG_TIMEOUT); zabbix_log(LOG_LEVEL_WARNING, "cannot collect configuration data for proxy \"%s\" at \"%s\": %s", host, sock->peer, error); goto clean; } zabbix_log(LOG_LEVEL_WARNING, "sending configuration data to proxy \"%s\" at \"%s\", datalen " ZBX_FS_SIZE_T, host, sock->peer, (zbx_fs_size_t)j.buffer_size); zabbix_log(LOG_LEVEL_DEBUG, "%s", j.buffer); if (SUCCEED != zbx_tcp_send_to(sock, j.buffer, CONFIG_TRAPPER_TIMEOUT)) { zabbix_log(LOG_LEVEL_WARNING, "cannot send configuration data to proxy \"%s\" at \"%s\": %s", host, sock->peer, zbx_socket_strerror()); } clean: zbx_json_free(&j); out: zbx_free(error); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
static void active_passive_misconfig(zbx_socket_t *sock) { char *msg = NULL; msg = zbx_dsprintf(msg, "misconfiguration error: the proxy is running in the active mode but server at \"%s\"" " sends requests to it as to proxy in passive mode", sock->peer); zabbix_log(LOG_LEVEL_WARNING, "%s", msg); zbx_send_response(sock, FAIL, msg, CONFIG_TIMEOUT); zbx_free(msg); }
/****************************************************************************** * * * Function: recv_proxyconfig * * * * Purpose: receive configuration tables from server (passive proxies) * * * * Author: Alexander Vladishev * * * ******************************************************************************/ void recv_proxyconfig(zbx_sock_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "recv_proxyconfig"; struct zbx_json_parse jp_data; int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (SUCCEED != (ret = zbx_json_brackets_by_name(jp, ZBX_PROTO_TAG_DATA, &jp_data))) { zabbix_log(LOG_LEVEL_WARNING, "invalid proxy configuration data: %s", zbx_json_strerror()); zbx_send_response(sock, ret, zbx_json_strerror(), CONFIG_TIMEOUT); } else { process_proxyconfig(&jp_data); zbx_send_response(sock, ret, NULL, CONFIG_TIMEOUT); } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: recv_agenthistory * * * * Purpose: process values sent by proxy servers * * * * Parameters: * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static void recv_agenthistory(zbx_sock_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "recv_agenthistory"; char info[128]; int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); ret = process_hist_data(sock, jp, 0, info, sizeof(info)); zbx_send_response(sock, ret, info, CONFIG_TIMEOUT); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: recv_proxyconfig * * * * Purpose: receive configuration tables from server (passive proxies) * * * * Author: Alexander Vladishev * * * ******************************************************************************/ void recv_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "recv_proxyconfig"; struct zbx_json_parse jp_data; int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (SUCCEED != (ret = zbx_json_brackets_by_name(jp, ZBX_PROTO_TAG_DATA, &jp_data))) { zabbix_log(LOG_LEVEL_WARNING, "cannot parse proxy configuration data received from server at" " \"%s\": %s", sock->peer, zbx_json_strerror()); zbx_send_response(sock, ret, zbx_json_strerror(), CONFIG_TIMEOUT); goto out; } if (SUCCEED != check_access_passive_proxy(sock, ZBX_SEND_RESPONSE, "configuration update")) goto out; process_proxyconfig(&jp_data); zbx_send_response(sock, ret, NULL, CONFIG_TIMEOUT); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: recv_agenthistory * * * * Purpose: processes the received values from active agents and senders * * * ******************************************************************************/ static void recv_agenthistory(zbx_socket_t *sock, struct zbx_json_parse *jp, zbx_timespec_t *ts) { const char *__function_name = "recv_agenthistory"; char *info = NULL; int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); ret = process_hist_data(sock, jp, 0, ts, &info); zbx_send_response(sock, ret, info, CONFIG_TIMEOUT); zbx_free(info); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: recv_proxy_heartbeat * * * * Purpose: process heartbeat sent by proxy servers * * * * Parameters: * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static void recv_proxy_heartbeat(zbx_sock_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "recv_proxy_heartbeat"; zbx_uint64_t proxy_hostid; char host[HOST_HOST_LEN_MAX], error[256]; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (FAIL == get_proxy_id(jp, &proxy_hostid, host, error, sizeof(error))) { zabbix_log(LOG_LEVEL_WARNING, "Heartbeat from active proxy on [%s] failed: %s", get_ip_by_socket(sock), error); return; } update_proxy_lastaccess(proxy_hostid); zbx_send_response(sock, SUCCEED, NULL, CONFIG_TIMEOUT); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: recv_discovery_data * * * * Purpose: * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ void recv_discovery_data(zbx_sock_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "recv_discovery_data"; int ret; zbx_uint64_t proxy_hostid; char host[HOST_HOST_LEN_MAX], error[256]; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (FAIL == (ret = get_proxy_id(jp, &proxy_hostid, host, error, sizeof(error)))) { zabbix_log(LOG_LEVEL_WARNING, "Discovery data from active proxy on [%s] failed: %s", get_ip_by_socket(sock), error); goto exit; } process_dhis_data(jp); exit: zbx_send_response(sock, ret, NULL, CONFIG_TIMEOUT); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); }
/****************************************************************************** * * * Function: recv_proxyhistory * * * * Purpose: process values sent by proxy servers * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static void recv_proxyhistory(zbx_sock_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "recv_proxyhistory"; zbx_uint64_t proxy_hostid; char host[HOST_HOST_LEN_MAX], info[128], error[256]; int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (FAIL == (ret = get_proxy_id(jp, &proxy_hostid, host, error, sizeof(error)))) { zabbix_log(LOG_LEVEL_WARNING, "History data from active proxy on [%s] failed: %s", get_ip_by_socket(sock), error); goto exit; } update_proxy_lastaccess(proxy_hostid); ret = process_hist_data(sock, jp, proxy_hostid, info, sizeof(info)); exit: zbx_send_response(sock, ret, info, CONFIG_TIMEOUT); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
static int process_trap(zbx_socket_t *sock, char *s, zbx_timespec_t *ts) { int ret = SUCCEED; zbx_rtrim(s, " \r\n"); zabbix_log(LOG_LEVEL_DEBUG, "trapper got '%s'", s); if ('{' == *s) /* JSON protocol */ { struct zbx_json_parse jp; char value[MAX_STRING_LEN]; if (SUCCEED != zbx_json_open(s, &jp)) { zbx_send_response(sock, FAIL, zbx_json_strerror(), CONFIG_TIMEOUT); zabbix_log(LOG_LEVEL_WARNING, "received invalid JSON object from %s: %s", sock->peer, zbx_json_strerror()); return FAIL; } if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_REQUEST, value, sizeof(value))) { if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_CONFIG)) { if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) { send_proxyconfig(sock, &jp); } else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) { zabbix_log(LOG_LEVEL_WARNING, "received configuration data from server" " at \"%s\", datalen " ZBX_FS_SIZE_T, sock->peer, (zbx_fs_size_t)(jp.end - jp.start + 1)); recv_proxyconfig(sock, &jp); } else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_ACTIVE)) { /* This is a misconfiguration: the proxy is configured in active mode */ /* but server sends requests to it as to a proxy in passive mode. To */ /* prevent logging of this problem for every request we report it */ /* only when the server sends configuration to the proxy and ignore */ /* it for other requests. */ active_passive_misconfig(sock); } } else if (0 == strcmp(value, ZBX_PROTO_VALUE_AGENT_DATA) || 0 == strcmp(value, ZBX_PROTO_VALUE_SENDER_DATA)) { recv_agenthistory(sock, &jp, ts); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_HISTORY_DATA)) { if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) recv_proxyhistory(sock, &jp, ts); else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) send_proxyhistory(sock, ts); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_DISCOVERY_DATA)) { if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) recv_discovery_data(sock, &jp); else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) send_discovery_data(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_AUTO_REGISTRATION_DATA)) { if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) recv_areg_data(sock, &jp); else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) send_areg_data(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_HEARTBEAT)) { if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) recv_proxy_heartbeat(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_ACTIVE_CHECKS)) { ret = send_list_of_active_checks_json(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_HOST_AVAILABILITY)) { if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) recv_host_availability(sock, &jp); else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE)) send_host_availability(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_COMMAND)) { ret = node_process_command(sock, s, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_QUEUE)) { if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER)) ret = recv_getqueue(sock, &jp); } else zabbix_log(LOG_LEVEL_WARNING, "unknown request received [%s]", value); } } else if (0 == strncmp(s, "ZBX_GET_ACTIVE_CHECKS", 21)) /* request for list of active checks */ { ret = send_list_of_active_checks(sock, s); } else { char value_dec[MAX_BUFFER_LEN], lastlogsize[ZBX_MAX_UINT64_LEN], timestamp[11], source[HISTORY_LOG_SOURCE_LEN_MAX], severity[11]; AGENT_VALUE av; memset(&av, 0, sizeof(AGENT_VALUE)); if ('<' == *s) /* XML protocol */ { comms_parse_response(s, av.host_name, sizeof(av.host_name), av.key, sizeof(av.key), value_dec, sizeof(value_dec), lastlogsize, sizeof(lastlogsize), timestamp, sizeof(timestamp), source, sizeof(source), severity, sizeof(severity)); av.value = value_dec; if (SUCCEED != is_uint64(lastlogsize, &av.lastlogsize)) av.lastlogsize = 0; av.timestamp = atoi(timestamp); av.source = source; av.severity = atoi(severity); } else { char *pl, *pr; pl = s; if (NULL == (pr = strchr(pl, ':'))) return FAIL; *pr = '\0'; zbx_strlcpy(av.host_name, pl, sizeof(av.host_name)); *pr = ':'; pl = pr + 1; if (NULL == (pr = strchr(pl, ':'))) return FAIL; *pr = '\0'; zbx_strlcpy(av.key, pl, sizeof(av.key)); *pr = ':'; av.value = pr + 1; av.severity = 0; } zbx_timespec(&av.ts); if (0 == strcmp(av.value, ZBX_NOTSUPPORTED)) av.state = ITEM_STATE_NOTSUPPORTED; process_mass_data(sock, 0, &av, 1, NULL); zbx_alarm_on(CONFIG_TIMEOUT); if (SUCCEED != zbx_tcp_send_raw(sock, "OK")) zabbix_log(LOG_LEVEL_WARNING, "Error sending result back"); zbx_alarm_off(); } return ret; }