/****************************************************************************** * * * Function: get_history_lastid: * * * * Purpose: get last history id from master node * * * * Parameters: * * * * Return value: * * * * Author: Aleksander Vladishev * * * * Comments: * * * ******************************************************************************/ static int get_history_lastid(int master_nodeid, int nodeid, ZBX_TABLE *table, zbx_uint64_t *lastid) { zbx_sock_t sock; char data[MAX_STRING_LEN], *answer; int res = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In get_history_lastid()"); if (SUCCEED == connect_to_node(master_nodeid, &sock)) { zbx_snprintf(data, sizeof(data), "ZBX_GET_HISTORY_LAST_ID%c%d%c%d\n%s%c%s", ZBX_DM_DELIMITER, CONFIG_NODEID, ZBX_DM_DELIMITER, nodeid, table->table, ZBX_DM_DELIMITER, table->recid); if (FAIL == send_data_to_node(master_nodeid, &sock, data)) goto disconnect; if (FAIL == recv_data_from_node(master_nodeid, &sock, &answer)) goto disconnect; if (0 == strncmp(answer, "FAIL", 4)) { zabbix_log( LOG_LEVEL_ERR, "NODE %d: get_history_lastid() FAIL from node %d for node %d", CONFIG_NODEID, master_nodeid, nodeid); goto disconnect; } ZBX_STR2UINT64(*lastid, answer); res = SUCCEED; disconnect: disconnect_node(&sock); } return res; }
/****************************************************************************** * * * Function: send_to_node * * * * Purpose: send configuration changes to required node * * * * Parameters: * * * * Return value: SUCCESS - processed successfully * * FAIL - an error occurred * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int send_to_node(const char *name, int dest_nodeid, int nodeid, char *data) { int ret = FAIL; zbx_sock_t sock; char *answer; zabbix_log(LOG_LEVEL_WARNING, "NODE %d: Sending %s of node %d to node %d datalen " ZBX_FS_SIZE_T, CONFIG_NODEID, name, nodeid, dest_nodeid, (zbx_fs_size_t)strlen(data)); if (FAIL == connect_to_node(dest_nodeid, &sock)) return FAIL; if (FAIL == send_data_to_node(dest_nodeid, &sock, data)) goto disconnect; if (FAIL == recv_data_from_node(dest_nodeid, &sock, &answer)) goto disconnect; if (0 == strcmp(answer, "OK")) { zabbix_log( LOG_LEVEL_DEBUG, "OK"); ret = SUCCEED; } else { zabbix_log( LOG_LEVEL_WARNING, "NOT OK"); } disconnect: disconnect_node(&sock); return ret; }
/****************************************************************************** * * * Function: process_nodes * * * * Purpose: calculates checksums of config data * * * * Parameters: * * * * Return value: * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ void process_nodes() { DB_RESULT result; DB_ROW row; int nodeid; int master_nodeid; char *data, *answer; zbx_sock_t sock; int res; int sender_nodeid; master_nodeid = CONFIG_MASTER_NODEID; if (0 == master_nodeid) return; result = DBselect("select nodeid from nodes"); while (NULL != (row=DBfetch(result))) { nodeid = atoi(row[0]); if (SUCCEED == is_master_node(CONFIG_NODEID, nodeid)) continue; node_sync_lock(nodeid); /* DBbegin();*/ res = calculate_checksums(nodeid, NULL, 0); if (SUCCEED == res && NULL != (data = get_config_data(nodeid, ZBX_NODE_MASTER))) { zabbix_log( LOG_LEVEL_WARNING, "NODE %d: Sending configuration changes to master node %d for node %d datalen %d", CONFIG_NODEID, master_nodeid, nodeid, strlen(data)); if (SUCCEED == (res = connect_to_node(master_nodeid, &sock))) { if (SUCCEED == res) res = send_data_to_node(master_nodeid, &sock, data); if (SUCCEED == res) res = recv_data_from_node(master_nodeid, &sock, &answer); if (SUCCEED == res && 0 == strncmp(answer, "Data", 4)) { res = update_checksums(nodeid, ZBX_NODE_MASTER, SUCCEED, NULL, 0, NULL); if (SUCCEED == res) res = node_sync(answer, &sender_nodeid, &nodeid); send_data_to_node(master_nodeid, &sock, SUCCEED == res ? "OK" : "FAIL"); } disconnect_node(&sock); } zbx_free(data); } /* DBcommit();*/ node_sync_unlock(nodeid); } DBfree_result(result); }
/****************************************************************************** * * * Function: get_trends_lastid: * * * * Purpose: get last history lastid and lastclock from master node * * * * Parameters: * * * * Return value: * * * * Author: Aleksander Vladishev * * * * Comments: * * * ******************************************************************************/ static int get_trends_lastid(int master_nodeid, int nodeid, ZBX_TABLE *table, zbx_uint64_t *lastid, int *lastclock) { zbx_sock_t sock; char data[MAX_STRING_LEN], *answer, *ptr; int res = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In get_trends_lastclock()"); if (SUCCEED == connect_to_node(master_nodeid, &sock)) { zbx_snprintf(data, sizeof(data), "ZBX_GET_TRENDS_LAST_ID%c%d%c%d\n%s", ZBX_DM_DELIMITER, CONFIG_NODEID, ZBX_DM_DELIMITER, nodeid, table->table); if (FAIL == send_data_to_node(master_nodeid, &sock, data)) goto disconnect; if (FAIL == recv_data_from_node(master_nodeid, &sock, &answer)) goto disconnect; if (0 == strncmp(answer, "FAIL", 4)) { zabbix_log( LOG_LEVEL_ERR, "NODE %d: get_trends_lastid() FAIL from node %d for node %d", CONFIG_NODEID, master_nodeid, nodeid); goto disconnect; } if (NULL != (ptr = strchr(answer, ZBX_DM_DELIMITER))) { *ptr++ = '\0'; ZBX_STR2UINT64(*lastid, answer); *lastclock = atoi(ptr); res = SUCCEED; } disconnect: disconnect_node(&sock); } return res; }
static int process_trap(zbx_sock_t *sock, char *s, int max_len) { char *pl, *pr, *data, value_dec[MAX_BUFFER_LEN]; char lastlogsize[11], timestamp[11], source[HISTORY_LOG_SOURCE_LEN_MAX], severity[11]; int sender_nodeid, nodeid; char *answer; int ret = SUCCEED, res; size_t datalen; struct zbx_json_parse jp; char value[MAX_STRING_LEN]; AGENT_VALUE av; memset(&av, 0, sizeof(AGENT_VALUE)); zbx_rtrim(s, " \r\n"); datalen = strlen(s); zabbix_log(LOG_LEVEL_DEBUG, "Trapper got [%s] len " ZBX_FS_SIZE_T, s, (zbx_fs_size_t)datalen); if (0 == strncmp(s, "ZBX_GET_ACTIVE_CHECKS", 21)) /* Request for list of active checks */ { ret = send_list_of_active_checks(sock, s); } else if (strncmp(s, "ZBX_GET_HISTORY_LAST_ID", 23) == 0) /* Request for last ids */ { send_history_last_id(sock, s); return ret; } else /* Process information sent by zabbix_sender */ { /* Node data exchange? */ if (strncmp(s, "Data", 4) == 0) { node_sync_lock(0); res = node_sync(s, &sender_nodeid, &nodeid); if (FAIL == res) { alarm(CONFIG_TIMEOUT); send_data_to_node(sender_nodeid, sock, "FAIL"); alarm(0); } else { res = calculate_checksums(nodeid, NULL, 0); if (SUCCEED == res && NULL != (data = get_config_data(nodeid, ZBX_NODE_SLAVE))) { zabbix_log( LOG_LEVEL_WARNING, "NODE %d: Sending configuration changes" " to slave node %d for node %d datalen " ZBX_FS_SIZE_T, CONFIG_NODEID, sender_nodeid, nodeid, (zbx_fs_size_t)strlen(data)); alarm(CONFIG_TRAPPER_TIMEOUT); res = send_data_to_node(sender_nodeid, sock, data); zbx_free(data); if (SUCCEED == res) res = recv_data_from_node(sender_nodeid, sock, &answer); if (SUCCEED == res && 0 == strcmp(answer, "OK")) res = update_checksums(nodeid, ZBX_NODE_SLAVE, SUCCEED, NULL, 0, NULL); alarm(0); } } node_sync_unlock(0); return ret; } /* Slave node history ? */ if (strncmp(s, "History", 7) == 0) { const char *reply; reply = (SUCCEED == node_history(s, datalen) ? "OK" : "FAIL"); alarm(CONFIG_TIMEOUT); if (SUCCEED != zbx_tcp_send_raw(sock, reply)) { zabbix_log(LOG_LEVEL_WARNING, "Error sending %s to node", reply); zabbix_syslog("Trapper: error sending %s to node", reply); } alarm(0); return ret; } /* JSON protocol? */ else if (SUCCEED == zbx_json_open(s, &jp)) { 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 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) send_proxyconfig(sock, &jp); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) { zabbix_log(LOG_LEVEL_WARNING, "Received configuration data from server." " Datalen " ZBX_FS_SIZE_T, (zbx_fs_size_t)datalen); recv_proxyconfig(sock, &jp); } } else if (0 == strcmp(value, ZBX_PROTO_VALUE_AGENT_DATA) || 0 == strcmp(value, ZBX_PROTO_VALUE_SENDER_DATA)) { recv_agenthistory(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_HISTORY_DATA)) { if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) recv_proxyhistory(sock, &jp); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) send_proxyhistory(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_DISCOVERY_DATA)) { if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) recv_discovery_data(sock, &jp); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) send_discovery_data(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_AUTO_REGISTRATION_DATA)) { if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) recv_areg_data(sock, &jp); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) send_areg_data(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_HEARTBEAT)) { if (0 != (daemon_type & ZBX_DAEMON_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 != (daemon_type & ZBX_DAEMON_TYPE_SERVER)) recv_host_availability(sock, &jp); else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE)) send_host_availability(sock); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_COMMAND)) { ret = node_process_command(sock, s, &jp); } else { zabbix_log(LOG_LEVEL_WARNING, "Unknown request received [%s]", value); } } return ret; } /* XML protocol? */ else if (*s == '<') { 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; av.lastlogsize = atoi(lastlogsize); av.timestamp = atoi(timestamp); av.source = source; av.severity = atoi(severity); } else { 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; } av.clock = time(NULL); process_mass_data(sock, 0, &av, 1, NULL); alarm(CONFIG_TIMEOUT); if (SUCCEED != zbx_tcp_send_raw(sock, SUCCEED == ret ? "OK" : "NOT OK")) { zabbix_log(LOG_LEVEL_WARNING, "Error sending result back"); zabbix_syslog("Trapper: error sending result back"); } alarm(0); } return ret; }
static int process_trap(zbx_sock_t *sock, char *s, int max_len) { char *server,*key,*value_string, *data; char copy[MAX_STRING_LEN]; char host_dec[MAX_STRING_LEN],key_dec[MAX_STRING_LEN],value_dec[MAX_STRING_LEN]; char lastlogsize[MAX_STRING_LEN]; char timestamp[MAX_STRING_LEN]; char source[MAX_STRING_LEN]; char severity[MAX_STRING_LEN]; int sender_nodeid, nodeid; char *answer; int ret=SUCCEED, res; size_t datalen; struct zbx_json_parse jp; char value[MAX_STRING_LEN]; AGENT_VALUE av; zbx_rtrim(s, " \r\n\0"); datalen = strlen(s); zabbix_log( LOG_LEVEL_DEBUG, "Trapper got [%s] len %zd", s, datalen); if (0 == strncmp(s,"ZBX_GET_ACTIVE_CHECKS", 21)) /* Request for list of active checks */ { ret = send_list_of_active_checks(sock, s); /* Request for last ids */ } else if (strncmp(s,"ZBX_GET_HISTORY_LAST_ID", 23) == 0) { send_history_last_id(sock, s); return ret; } else if (strncmp(s,"ZBX_GET_TRENDS_LAST_ID", 22) == 0) { send_trends_last_id(sock, s); return ret; /* Process information sent by zabbix_sender */ } else { /* Command? */ if(strncmp(s,"Command",7) == 0) { node_process_command(sock, s); return ret; } /* Node data exchange? */ if(strncmp(s,"Data",4) == 0) { node_sync_lock(0); /* zabbix_log( LOG_LEVEL_WARNING, "Node data received [len:%d]", strlen(s)); */ res = node_sync(s, &sender_nodeid, &nodeid); if (FAIL == res) send_data_to_node(sender_nodeid, sock, "FAIL"); else { res = calculate_checksums(nodeid, NULL, 0); if (SUCCEED == res && NULL != (data = get_config_data(nodeid, ZBX_NODE_SLAVE))) { res = send_data_to_node(sender_nodeid, sock, data); zbx_free(data); if (SUCCEED == res) res = recv_data_from_node(sender_nodeid, sock, &answer); if (SUCCEED == res && 0 == strcmp(answer, "OK")) res = update_checksums(nodeid, ZBX_NODE_SLAVE, SUCCEED, NULL, 0, NULL); } } node_sync_unlock(0); return ret; } /* Slave node history ? */ if(strncmp(s,"History",7) == 0) { /* zabbix_log( LOG_LEVEL_WARNING, "Slave node history received [len:%d]", strlen(s)); */ if (node_history(s, datalen) == SUCCEED) { if (zbx_tcp_send_raw(sock,"OK") != SUCCEED) { zabbix_log( LOG_LEVEL_WARNING, "Error sending confirmation to node"); zabbix_syslog("Trapper: error sending confirmation to node"); } } return ret; } /* JSON protocol? */ else if (SUCCEED == zbx_json_open(s, &jp)) { if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_REQUEST, value, sizeof(value))) { if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_CONFIG) && zbx_process == ZBX_PROCESS_SERVER) { send_proxyconfig(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_AGENT_DATA) || 0 == strcmp(value, ZBX_PROTO_VALUE_SENDER_DATA)) { ret = process_new_values(sock, &jp, 0); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_HISTORY_DATA) && zbx_process == ZBX_PROCESS_SERVER) { ret = process_proxy_values(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_DISCOVERY_DATA) && zbx_process == ZBX_PROCESS_SERVER) { ret = process_discovery_data(sock, &jp); } else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_HEARTBEAT) && zbx_process == ZBX_PROCESS_SERVER) { ret = process_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 { zabbix_log( LOG_LEVEL_WARNING, "Unknown request received [%s]", value); } } return ret; } /* New XML protocol? */ else if(s[0]=='<') { zabbix_log( LOG_LEVEL_DEBUG, "XML received [%s]", s); comms_parse_response(s,host_dec,key_dec,value_dec,lastlogsize,timestamp,source,severity,sizeof(host_dec)-1); server=host_dec; value_string=value_dec; key=key_dec; } else { strscpy(copy,s); server=(char *)strtok(s,":"); if(NULL == server) { return FAIL; } key=(char *)strtok(NULL,":"); if(NULL == key) { return FAIL; } value_string=strchr(copy,':'); value_string=strchr(value_string+1,':'); if(NULL == value_string) { return FAIL; } /* It points to ':', so have to increment */ value_string++; lastlogsize[0]=0; timestamp[0]=0; source[0]=0; severity[0]=0; } zabbix_log( LOG_LEVEL_DEBUG, "Value [%s]", value_string); av.clock = time(NULL); zbx_strlcpy(av.host_name, server, sizeof(av.host_name)); zbx_strlcpy(av.key, key, sizeof(av.key)); av.value = value_string; av.lastlogsize = atoi(lastlogsize); av.timestamp = atoi(timestamp); av.source = source; av.severity = atoi(severity); process_mass_data(sock, 0, &av, 1, NULL, 0); if( zbx_tcp_send_raw(sock, SUCCEED == ret ? "OK" : "NOT OK") != SUCCEED) { zabbix_log( LOG_LEVEL_WARNING, "Error sending result back"); zabbix_syslog("Trapper: error sending result back"); } zabbix_log( LOG_LEVEL_DEBUG, "After write()"); } return ret; }