void test_parameters() { int i; char *key = NULL; size_t key_alloc = 0; for (i = 0; NULL != commands[i].key; i++) { if (0 != strcmp(commands[i].key, "__UserPerfCounter")) { size_t key_offset = 0; zbx_strcpy_alloc(&key, &key_alloc, &key_offset, commands[i].key); if (0 == (commands[i].flags & CF_USERPARAMETER) && NULL != commands[i].test_param) { zbx_chrcpy_alloc(&key, &key_alloc, &key_offset, '['); zbx_strcpy_alloc(&key, &key_alloc, &key_offset, commands[i].test_param); zbx_chrcpy_alloc(&key, &key_alloc, &key_offset, ']'); } test_parameter(key); } } zbx_free(key); test_aliases(); }
static int replace_param(const char *cmd, AGENT_REQUEST *request, char **out, char *error, int max_error_len) { const char *pl = cmd, *pr, *tmp; size_t out_alloc = 0, out_offset = 0; int num, ret = SUCCEED; while (NULL != (pr = strchr(pl, '$'))) { zbx_strncpy_alloc(out, &out_alloc, &out_offset, pl, pr - pl); pr++; if ('0' == *pr) { zbx_strcpy_alloc(out, &out_alloc, &out_offset, cmd); } else if ('1' <= *pr && *pr <= '9') { num = (int)(*pr - '0'); if (request->nparam >= num) { tmp = get_rparam(request, num - 1); if (SUCCEED != (ret = zbx_check_user_parameter(tmp, error, max_error_len))) break; zbx_strcpy_alloc(out, &out_alloc, &out_offset, tmp); } } else { if ('$' != *pr) zbx_chrcpy_alloc(out, &out_alloc, &out_offset, '$'); zbx_chrcpy_alloc(out, &out_alloc, &out_offset, *pr); } pl = pr + 1; } if (SUCCEED == ret) zbx_strcpy_alloc(out, &out_alloc, &out_offset, pl); return ret; }
static char *lld_expression_expand(const char *expression, zbx_vector_ptr_t *functions) { const char *__function_name = "lld_expression_expand"; size_t l, r; int i; zbx_uint64_t index; zbx_lld_function_t *function; char *buffer = NULL; size_t buffer_alloc = 64, buffer_offset = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:'%s'", __function_name, expression); buffer = zbx_malloc(buffer, buffer_alloc); *buffer = '\0'; for (l = 0; '\0' != expression[l]; l++) { zbx_chrcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, expression[l]); if ('{' != expression[l]) continue; for (r = l + 1; '\0' != expression[r] && '}' != expression[r]; r++) ; if ('}' != expression[r]) continue; /* ... > 0 | {1} + ... */ /* l r */ if (SUCCEED != is_uint64_n(expression + l + 1, r - l - 1, &index)) continue; for (i = 0; i < functions->values_num; i++) { function = (zbx_lld_function_t *)functions->values[i]; if (function->index != index) continue; zbx_snprintf_alloc(&buffer, &buffer_alloc, &buffer_offset, ZBX_FS_UI64 ":%s(%s)", function->itemid, function->function, function->parameter); break; } l = r - 1; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():'%s'", __function_name, buffer); return buffer; }
void add_if_name(char **if_list, size_t *if_list_alloc, size_t *if_list_offset, const char *name) { if (FAIL == str_in_list(*if_list, name, ZBX_IF_SEP)) { if ('\0' != **if_list) zbx_chrcpy_alloc(if_list, if_list_alloc, if_list_offset, ZBX_IF_SEP); zbx_strcpy_alloc(if_list, if_list_alloc, if_list_offset, name); } }
/****************************************************************************** * * * Function: DMget_table_data * * * * Purpose: get configuration changes to required node for specified table * * * * Parameters: * * * * Return value: SUCCESS - processed successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ static int DMget_table_data(int nodeid, unsigned char dest_nodetype, const ZBX_TABLE *table, char **data, size_t *data_alloc, size_t *data_offset, char **ptbls, size_t *ptbls_alloc, size_t *ptbls_offset) { const char *__function_name = "DMget_table_data"; int f, res = SUCCEED; const ZBX_TABLE *fk_table; zabbix_log(LOG_LEVEL_DEBUG, "In %s() [table:'%s']", __function_name, table->table); if (SUCCEED == str_in_list(*ptbls, table->table, ',')) goto out; if (0 != *ptbls_offset) zbx_chrcpy_alloc(ptbls, ptbls_alloc, ptbls_offset, ','); zbx_strcpy_alloc(ptbls, ptbls_alloc, ptbls_offset, table->table); for (f = 0; NULL != table->fields[f].name; f++) { if (0 == (table->fields[f].flags & ZBX_SYNC)) continue; if (NULL == table->fields[f].fk_table) continue; fk_table = DBget_table(table->fields[f].fk_table); DMget_table_data(nodeid, dest_nodetype, fk_table, data, data_alloc, data_offset, ptbls, ptbls_alloc, ptbls_offset); } DMcollect_table_data(nodeid, dest_nodetype, table, data, data_alloc, data_offset); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res)); return res; }
static int zbx_check_user_parameter(const char *param, char *error, int max_error_len) { const char suppressed_chars[] = "\\'\"`*?[]{}~$!&;()<>|#@\n", *c; char *buf = NULL; size_t buf_alloc = 128, buf_offset = 0; if (0 != CONFIG_UNSAFE_USER_PARAMETERS) return SUCCEED; for (c = suppressed_chars; '\0' != *c; c++) { if (NULL == strchr(param, *c)) continue; buf = zbx_malloc(buf, buf_alloc); for (c = suppressed_chars; '\0' != *c; c++) { if (c != suppressed_chars) zbx_strcpy_alloc(&buf, &buf_alloc, &buf_offset, ", "); if (0 != isprint(*c)) zbx_chrcpy_alloc(&buf, &buf_alloc, &buf_offset, *c); else zbx_snprintf_alloc(&buf, &buf_alloc, &buf_offset, "0x%02x", *c); } zbx_snprintf(error, max_error_len, "special characters \"%s\" are not allowed in the parameters", buf); zbx_free(buf); return FAIL; } return SUCCEED; }
/****************************************************************************** * * * Function: housekeeping_cleanup * * * * Purpose: remove deleted items data * * * * Return value: number of rows deleted * * * * Author: Alexei Vladishev, Dmitry Borovikov * * * * Comments: sqlite3 does not use CONFIG_MAX_HOUSEKEEPER_DELETE, deletes all * * * ******************************************************************************/ static int housekeeping_cleanup() { const char *__function_name = "housekeeping_cleanup"; DB_HOUSEKEEPER housekeeper; DB_RESULT result; DB_ROW row; int d, deleted = 0; zbx_vector_uint64_t housekeeperids; char *sql = NULL, *table_name_esc; size_t sql_alloc = 0, sql_offset = 0; zbx_hk_cleanup_table_t *table; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); /* first handle the trivial case when history and trend housekeeping is disabled */ if (ZBX_HK_OPTION_DISABLED == hk_config.history_mode && ZBX_HK_OPTION_DISABLED == hk_config.trends_mode) goto out; zbx_vector_uint64_create(&housekeeperids); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select housekeeperid,tablename,field,value" " from housekeeper" " where tablename in ("); /* assemble list of tables excluded from housekeeping procedure */ for (table = hk_cleanup_tables; NULL != table->name; table++) { if (ZBX_HK_OPTION_ENABLED != *table->poption_mode) continue; table_name_esc = DBdyn_escape_string(table->name); zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, '\''); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, table_name_esc); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "',"); zbx_free(table_name_esc); } sql_offset--; /* order by tablename to effectively use DB cache */ zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ") order by tablename"); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(housekeeper.housekeeperid, row[0]); housekeeper.tablename = row[1]; housekeeper.field = row[2]; ZBX_STR2UINT64(housekeeper.value, row[3]); if (0 == CONFIG_MAX_HOUSEKEEPER_DELETE) { d = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64, housekeeper.tablename, housekeeper.field, housekeeper.value); } else { #if defined(HAVE_IBM_DB2) || defined(HAVE_ORACLE) d = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64 " and rownum<=%d", housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #elif defined(HAVE_MYSQL) d = DBexecute( "delete from %s" " where %s=" ZBX_FS_UI64 " limit %d", housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #elif defined(HAVE_POSTGRESQL) d = DBexecute( "delete from %s" " where ctid = any(array(select ctid from %s" " where %s=" ZBX_FS_UI64 " limit %d))", housekeeper.tablename, housekeeper.tablename, housekeeper.field, housekeeper.value, CONFIG_MAX_HOUSEKEEPER_DELETE); #elif defined(HAVE_SQLITE3) d = 0; #endif } if (ZBX_DB_OK <= d) { if (0 == CONFIG_MAX_HOUSEKEEPER_DELETE || CONFIG_MAX_HOUSEKEEPER_DELETE > d) zbx_vector_uint64_append(&housekeeperids, housekeeper.housekeeperid); deleted += d; } } DBfree_result(result); if (0 != housekeeperids.values_num) { zbx_vector_uint64_sort(&housekeeperids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); sql_offset = 0; zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from housekeeper where"); DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "housekeeperid", housekeeperids.values, housekeeperids.values_num); DBexecute("%s", sql); } zbx_free(sql); zbx_vector_uint64_destroy(&housekeeperids); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, deleted); return deleted; }
static void print_backtrace(CONTEXT *pctx) { SymGetLineFromAddrW64_func_t zbx_SymGetLineFromAddrW64 = NULL; SymFromAddr_func_t zbx_SymFromAddr = NULL; CONTEXT ctx, ctxcount; STACKFRAME64 s, scount; PSYMBOL_INFO pSym = NULL; HMODULE hModule; HANDLE hProcess, hThread; DWORD64 offset; wchar_t szProcessName[MAX_PATH]; char *process_name = NULL, *process_path = NULL, *frame = NULL; size_t frame_alloc = 0, frame_offset; int nframes = 0; ctx = *pctx; zabbix_log(LOG_LEVEL_CRIT, "=== Backtrace: ==="); memset(&s, 0, sizeof(s)); s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Mode = AddrModeFlat; s.AddrStack.Mode = AddrModeFlat; #ifdef _M_X64 s.AddrPC.Offset = ctx.Rip; s.AddrFrame.Offset = ctx.Rbp; s.AddrStack.Offset = ctx.Rsp; #else s.AddrPC.Offset = ctx.Eip; s.AddrFrame.Offset = ctx.Ebp; s.AddrStack.Offset = ctx.Esp; #endif hProcess = GetCurrentProcess(); hThread = GetCurrentThread(); if (0 != GetModuleFileNameEx(hProcess, NULL, szProcessName, ARRSIZE(szProcessName))) { char *ptr; int path_alloc = 0, path_offset = 0; process_name = zbx_unicode_to_utf8(szProcessName); if (NULL != (ptr = strstr(process_name, progname))) zbx_strncpy_alloc(&process_path, &path_alloc, &path_offset, process_name, ptr - process_name); } if (NULL != (hModule = GetModuleHandle(TEXT("DbgHelp.DLL")))) { zbx_SymGetLineFromAddrW64 = (SymGetLineFromAddrW64_func_t)GetProcAddress(hModule, "SymGetLineFromAddr64"); zbx_SymFromAddr = (SymFromAddr_func_t)GetProcAddress(hModule, "SymFromAddr"); } if (NULL != zbx_SymFromAddr || NULL != zbx_SymGetLineFromAddrW64) { SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES); if (FALSE != SymInitialize(hProcess, process_path, TRUE)) { pSym = (PSYMBOL_INFO) zbx_malloc(NULL, sizeof(SYMBOL_INFO) + MAX_SYM_NAME); memset(pSym, 0, sizeof(SYMBOL_INFO) + MAX_SYM_NAME); pSym->SizeOfStruct = sizeof(SYMBOL_INFO); pSym->MaxNameLen = MAX_SYM_NAME; } } scount = s; ctxcount = ctx; /* get number of frames, ctxcount may be modified during StackWalk64() calls */ while (TRUE == StackWalk64(ZBX_IMAGE_FILE_MACHINE, hProcess, hThread, &scount, &ctxcount, NULL, NULL, NULL, NULL)) { if (0 == scount.AddrReturn.Offset) break; nframes++; } while (TRUE == StackWalk64(ZBX_IMAGE_FILE_MACHINE, hProcess, hThread, &s, &ctx, NULL, NULL, NULL, NULL)) { frame_offset = 0; zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, "%d: %s", nframes--, NULL == process_name ? "(unknown)" : process_name); if (NULL != pSym) { DWORD dwDisplacement; IMAGEHLP_LINE64 line = {sizeof(IMAGEHLP_LINE64)}; zbx_chrcpy_alloc(&frame, &frame_alloc, &frame_offset, '('); if (NULL != zbx_SymFromAddr && TRUE == zbx_SymFromAddr(hProcess, s.AddrPC.Offset, &offset, pSym)) { zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, "%s+0x%lx", pSym->Name, offset); } if (NULL != zbx_SymGetLineFromAddrW64 && TRUE == zbx_SymGetLineFromAddrW64(hProcess, s.AddrPC.Offset, &dwDisplacement, &line)) { zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, " %s:%d", line.FileName, line.LineNumber); } zbx_chrcpy_alloc(&frame, &frame_alloc, &frame_offset, ')'); } zabbix_log(LOG_LEVEL_CRIT, "%s [0x%lx]", frame, s.AddrPC.Offset); if (0 == s.AddrReturn.Offset) break; } SymCleanup(hProcess); zbx_free(frame); zbx_free(process_path); zbx_free(process_name); zbx_free(pSym); }
static int calcitem_parse_expression(DC_ITEM *dc_item, expression_t *exp, char *error, int max_error_len) { const char *__function_name = "calcitem_parse_expression"; char *e, *f, *func = NULL, *params = NULL; size_t exp_alloc = 128, exp_offset = 0, len; int functionid, ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:'%s'", __function_name, dc_item->params); assert(dc_item); assert(exp); exp->exp = zbx_malloc(exp->exp, exp_alloc); for (e = dc_item->params; '\0' != *e; e++) { if (SUCCEED != is_function_char(*e)) { zbx_chrcpy_alloc(&exp->exp, &exp_alloc, &exp_offset, *e); continue; } if ((0 == strncmp("and", e, len = 3) || 0 == strncmp("not", e, 3) || 0 == strncmp("or", e, len = 2)) && NULL != strchr("()" ZBX_WHITESPACE, e[len])) { zbx_strncpy_alloc(&exp->exp, &exp_alloc, &exp_offset, e, len); e += len - 1; continue; } f = e; if (SUCCEED != parse_function(&e, &func, ¶ms)) { e = f; zbx_chrcpy_alloc(&exp->exp, &exp_alloc, &exp_offset, *f); continue; } else e--; functionid = calcitem_add_function(exp, func, params); zabbix_log(LOG_LEVEL_DEBUG, "%s() functionid:%d function:'%s(%s)'", __function_name, functionid, func, params); func = NULL; params = NULL; zbx_snprintf_alloc(&exp->exp, &exp_alloc, &exp_offset, "{%d}", functionid); } zabbix_log(LOG_LEVEL_DEBUG, "%s() expression:'%s'", __function_name, exp->exp); if (FAIL == (ret = substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &dc_item->host, NULL, NULL, &exp->exp, MACRO_TYPE_ITEM_EXPRESSION, error, max_error_len))) ret = NOTSUPPORTED; zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/****************************************************************************** * * * Function: process_record * * * * Purpose: process record update * * * * Parameters: * * * * Return value: SUCCEED - processed successfully * * FAIL - an error occurred * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int process_record(char **sql, size_t *sql_alloc, size_t *sql_offset, int sender_nodeid, int nodeid, const ZBX_TABLE *table, const char *record, int lastrecord, int acknowledges, zbx_vector_uint64_t *ack_eventids) { const char *r; int f, res = FAIL; char *value_esc; zabbix_log(LOG_LEVEL_DEBUG, "In process_record()"); if (0 == *sql_offset) { DBbegin_multiple_update(sql, sql_alloc, sql_offset); #ifdef HAVE_MULTIROW_INSERT begin_history_sql(sql, sql_alloc, sql_offset, table); #endif } #if !defined(HAVE_MULTIROW_INSERT) begin_history_sql(sql, sql_alloc, sql_offset, table); #endif zbx_chrcpy_alloc(sql, sql_alloc, sql_offset, '('); if (0 != (table->flags & ZBX_HISTORY_SYNC)) zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%d,", nodeid); for (r = record, f = 0; table->fields[f].name != 0; f++) { if (0 != (table->flags & ZBX_HISTORY_SYNC) && 0 == (table->fields[f].flags & ZBX_HISTORY_SYNC)) continue; if (NULL == r) goto error; zbx_get_next_field(&r, &buffer, &buffer_alloc, ZBX_DM_DELIMITER); if (0 != acknowledges && 0 == strcmp(table->fields[f].name, "eventid")) { zbx_uint64_t eventid; ZBX_STR2UINT64(eventid, buffer); zbx_vector_uint64_append(ack_eventids, eventid); } if (table->fields[f].type == ZBX_TYPE_INT || table->fields[f].type == ZBX_TYPE_UINT || table->fields[f].type == ZBX_TYPE_ID || table->fields[f].type == ZBX_TYPE_FLOAT) { zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%s,", buffer); } else if (table->fields[f].type == ZBX_TYPE_BLOB) { if ('\0' == *buffer) zbx_strcpy_alloc(sql, sql_alloc, sql_offset, "'',"); else { #ifdef HAVE_POSTGRESQL size_t len; len = zbx_hex2binary(buffer); zbx_pg_escape_bytea((u_char *)buffer, len, &tmp, &tmp_alloc); zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "'%s',", tmp); #else zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "0x%s,", buffer); #endif } } else /* ZBX_TYPE_TEXT, ZBX_TYPE_CHAR */ { zbx_hex2binary(buffer); value_esc = DBdyn_escape_string(buffer); zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "'%s',", value_esc); zbx_free(value_esc); } } (*sql_offset)--; #ifdef HAVE_MULTIROW_INSERT zbx_strcpy_alloc(sql, sql_alloc, sql_offset, "),"); #else zbx_strcpy_alloc(sql, sql_alloc, sql_offset, ");\n"); #endif if (0 != lastrecord || *sql_offset > ZBX_MAX_SQL_SIZE) { #ifdef HAVE_MULTIROW_INSERT (*sql_offset)--; zbx_strcpy_alloc(sql, sql_alloc, sql_offset, ";\n"); #endif DBend_multiple_update(sql, sql_alloc, sql_offset); if (ZBX_DB_OK <= DBexecute("%s", *sql)) res = SUCCEED; *sql_offset = 0; if (SUCCEED == res && 0 != lastrecord && 0 != acknowledges && 0 != ack_eventids->values_num) { zbx_vector_uint64_sort(ack_eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_vector_uint64_uniq(ack_eventids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zbx_strcpy_alloc(sql, sql_alloc, sql_offset, "update events" " set acknowledged=1" " where"); DBadd_condition_alloc(sql, sql_alloc, sql_offset, "eventid", ack_eventids->values, ack_eventids->values_num); if (ZBX_DB_OK > DBexecute("%s", *sql)) res = FAIL; *sql_offset = 0; } } else res = SUCCEED; return res; error: zabbix_log(LOG_LEVEL_ERR, "NODE %d: Received invalid record from node %d for node %d [%s]", CONFIG_NODEID, sender_nodeid, nodeid, record); return FAIL; }
static int DBpatch_2030094(void) { DB_RESULT result; DB_ROW row; int ret = SUCCEED; char *p, *expr = NULL, *expr_esc; size_t expr_alloc = 0, expr_offset; result = DBselect("select triggerid,expression from triggers"); while (SUCCEED == ret && NULL != (row = DBfetch(result))) { expr_offset = 0; for (p = row[1]; '\0' != *p; p++) { if (NULL == strchr("#&|", *p)) { if (' ' != *p || (0 != expr_offset && ' ' != expr[expr_offset - 1])) zbx_chrcpy_alloc(&expr, &expr_alloc, &expr_offset, *p); continue; } if ('#' == *p && 0 != expr_offset && '{' == expr[expr_offset - 1]) { zbx_chrcpy_alloc(&expr, &expr_alloc, &expr_offset, *p); continue; } if (('&' == *p || '|' == *p) && 0 != expr_offset && ' ' != expr[expr_offset - 1]) zbx_chrcpy_alloc(&expr, &expr_alloc, &expr_offset, ' '); switch (*p) { case '#': zbx_strcpy_alloc(&expr, &expr_alloc, &expr_offset, "<>"); break; case '&': zbx_strcpy_alloc(&expr, &expr_alloc, &expr_offset, "and"); break; case '|': zbx_strcpy_alloc(&expr, &expr_alloc, &expr_offset, "or"); break; } if (('&' == *p || '|' == *p) && ' ' != *(p + 1)) zbx_chrcpy_alloc(&expr, &expr_alloc, &expr_offset, ' '); } if (2048 < expr_offset && 2048 /* TRIGGER_EXPRESSION_LEN */ < zbx_strlen_utf8(expr)) { zabbix_log(LOG_LEVEL_WARNING, "cannot convert trigger expression \"%s\":" " resulting expression is too long", row[1]); } else if (0 != strcmp(row[1], expr)) { expr_esc = DBdyn_escape_string(expr); if (ZBX_DB_OK > DBexecute("update triggers set expression='%s' where triggerid=%s", expr_esc, row[0])) { ret = FAIL; } zbx_free(expr_esc); } } DBfree_result(result); zbx_free(expr); return ret; }
/****************************************************************************** * * * Function: send_list_of_active_checks_json * * * * Purpose: send list of active checks to the host * * * * Parameters: sock - open socket of server-agent connection * * json - request buffer * * * * Return value: SUCCEED - list of active checks sent successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ int send_list_of_active_checks_json(zbx_sock_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "send_list_of_active_checks_json"; char host[HOST_HOST_LEN_MAX], *name_esc, params[MAX_STRING_LEN], pattern[MAX_STRING_LEN], tmp[32], key_severity[MAX_STRING_LEN], key_logeventid[MAX_STRING_LEN], ip[INTERFACE_IP_LEN_MAX]; DB_RESULT result; DB_ROW row; struct zbx_json json; int res = FAIL, refresh_unsupported, now; zbx_uint64_t hostid; char error[MAX_STRING_LEN], *key = NULL; DC_ITEM dc_item; unsigned short port; char **regexp = NULL; int regexp_alloc = 0; int regexp_num = 0, n; char *sql = NULL; size_t sql_alloc = 2 * ZBX_KIBIBYTE, sql_offset = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_HOST, host, sizeof(host))) { zbx_snprintf(error, MAX_STRING_LEN, "%s", zbx_json_strerror()); goto error; } if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_IP, ip, sizeof(ip))) strscpy(ip, get_ip_by_socket(sock)); if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_PORT, tmp, sizeof(tmp))) *tmp = '\0'; if (FAIL == is_ushort(tmp, &port)) port = ZBX_DEFAULT_AGENT_PORT; if (FAIL == get_hostid_by_host(host, ip, port, &hostid, error)) goto error; DCconfig_get_config_data(&refresh_unsupported, CONFIG_REFRESH_UNSUPPORTED); now = time(NULL); sql = zbx_malloc(sql, sql_alloc); name_esc = DBdyn_escape_string(host); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select i.key_,i.delay,i.lastlogsize,i.mtime" " from items i,hosts h" " where i.hostid=h.hostid" " and h.status=%d" " and i.type=%d" " and i.flags<>%d" " and h.hostid=" ZBX_FS_UI64 " and h.proxy_hostid is null", HOST_STATUS_MONITORED, ITEM_TYPE_ZABBIX_ACTIVE, ZBX_FLAG_DISCOVERY_CHILD, hostid); zbx_free(name_esc); zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN); zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING); zbx_json_addarray(&json, ZBX_PROTO_TAG_DATA); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { if (FAIL == DCconfig_get_item_by_key(&dc_item, (zbx_uint64_t)0, host, row[0])) { zabbix_log(LOG_LEVEL_DEBUG, "%s() Item '%s' was not found in the server cache. Not sending now.", __function_name, row[0]); continue; } if (ITEM_STATUS_NOTSUPPORTED == dc_item.status) { if (0 == refresh_unsupported || dc_item.lastclock + refresh_unsupported > now) { DCconfig_clean_items(&dc_item, NULL, 1); continue; } } zabbix_log(LOG_LEVEL_DEBUG, "%s() Item '%s' was successfully found in the server cache. Sending.", __function_name, row[0]); ZBX_STRDUP(key, row[0]); substitute_key_macros(&key, NULL, &dc_item, NULL, MACRO_TYPE_ITEM_KEY, NULL, 0); DCconfig_clean_items(&dc_item, NULL, 1); zbx_json_addobject(&json, NULL); zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY, key, ZBX_JSON_TYPE_STRING); if (0 != strcmp(key, row[0])) zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY_ORIG, row[0], ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json, ZBX_PROTO_TAG_DELAY, row[1], ZBX_JSON_TYPE_INT); /* The agent expects ALWAYS to have lastlogsize and mtime tags. Removing those would cause older agents to fail. */ zbx_json_addstring(&json, ZBX_PROTO_TAG_LOGLASTSIZE, row[2], ZBX_JSON_TYPE_INT); zbx_json_addstring(&json, ZBX_PROTO_TAG_MTIME, row[3], ZBX_JSON_TYPE_INT); zbx_json_close(&json); /* special processing for log[] and logrt[] items */ do { /* simple try realization */ /* log[filename,pattern,encoding,maxlinespersec] */ /* logrt[filename_format,pattern,encoding,maxlinespersec] */ if (0 != strncmp(key, "log[", 4) && 0 != strncmp(key, "logrt[", 6)) break; if (2 != parse_command(key, NULL, 0, params, sizeof(params))) break; /* dealing with `pattern' parameter */ if (0 == get_param(params, 2, pattern, sizeof(pattern)) && *pattern == '@') add_regexp_name(®exp, ®exp_alloc, ®exp_num, pattern + 1); } while (0); /* simple try realization */ /* special processing for eventlog[] items */ do { /* simple try realization */ /* eventlog[filename,pattern,severity,source,logeventid,maxlinespersec] */ if (0 != strncmp(key, "eventlog[", 9)) break; if (2 != parse_command(key, NULL, 0, params, sizeof(params))) break; /* dealing with `pattern' parameter */ if (0 == get_param(params, 2, pattern, sizeof(pattern)) && *pattern == '@') add_regexp_name(®exp, ®exp_alloc, ®exp_num, pattern + 1); /* dealing with `severity' parameter */ if (0 == get_param(params, 3, key_severity, sizeof(key_severity)) && *key_severity == '@') add_regexp_name(®exp, ®exp_alloc, ®exp_num, key_severity + 1); /* dealing with `logeventid' parameter */ if (0 == get_param(params, 5, key_logeventid, sizeof(key_logeventid)) && *key_logeventid == '@') add_regexp_name(®exp, ®exp_alloc, ®exp_num, key_logeventid + 1); } while (0); /* simple try realization */ zbx_free(key); } zbx_json_close(&json); DBfree_result(result); if (0 != regexp_num) { zbx_json_addarray(&json, ZBX_PROTO_TAG_REGEXP); sql_offset = 0; zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select r.name,e.expression,e.expression_type,e.exp_delimiter,e.case_sensitive" " from regexps r,expressions e" " where r.regexpid=e.regexpid" " and r.name in ("); for (n = 0; n < regexp_num; n++) { name_esc = DBdyn_escape_string(regexp[n]); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%s'%s'", n == 0 ? "" : ",", name_esc); zbx_free(name_esc); zbx_free(regexp[n]); } zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ')'); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, DB_NODE, DBnode_local("r.regexpid")); result = DBselect("%s", sql); while (NULL != (row = DBfetch(result))) { zbx_json_addobject(&json, NULL); zbx_json_addstring(&json, "name", row[0], ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json, "expression", row[1], ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json, "expression_type", row[2], ZBX_JSON_TYPE_INT); zbx_json_addstring(&json, "exp_delimiter", row[3], ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json, "case_sensitive", row[4], ZBX_JSON_TYPE_INT); zbx_json_close(&json); } DBfree_result(result); } zbx_free(regexp); zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __function_name, json.buffer); alarm(CONFIG_TIMEOUT); if (SUCCEED != zbx_tcp_send(sock, json.buffer)) strscpy(error, zbx_tcp_strerror()); else res = SUCCEED; alarm(0); zbx_json_free(&json); zbx_free(sql); goto out; error: zabbix_log(LOG_LEVEL_WARNING, "cannot send list of active checks to [%s]: %s", get_ip_by_socket(sock), error); zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN); zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json, ZBX_PROTO_TAG_INFO, error, ZBX_JSON_TYPE_STRING); zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __function_name, json.buffer); res = zbx_tcp_send(sock, json.buffer); zbx_json_free(&json); out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res)); return res; }
/****************************************************************************** * * * Function: process_checksum * * * * Author: Alexander Vladishev * * * ******************************************************************************/ static void process_checksum(int nodeid, char *data, unsigned char sender_nodetype) { const char *__function_name = "process_checksum"; char *r, *lf; size_t tmp_offset; const ZBX_TABLE *table = NULL; zbx_uint64_t recid; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); for (r = data; '\0' != *r;) { if (NULL != (lf = strchr(r, '\n'))) *lf = '\0'; zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* table name */ if (NULL == table || 0 != strcmp(table->table, buf)) { if (NULL == (table = DBget_table(buf))) { zabbix_log(LOG_LEVEL_DEBUG, "%s(): cannot find table [%s]", __function_name, buf); goto next; } } zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* record id */ ZBX_STR2UINT64(recid, buf); zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* operation type */ if ('0' == *buf) /* NODE_CONFIGLOG_OP_UPDATE */ { *tmp = '\0'; tmp_offset = 0; while (NULL != r) { /* field name */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); if (0 != tmp_offset) zbx_chrcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, ','); zbx_strcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, buf); /* field type */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); /* value */ zbx_get_next_field((const char **)&r, &buf, &buf_alloc, ZBX_DM_DELIMITER); } if (SUCCEED == calculate_checksums(nodeid, table->table, recid)) update_checksums(nodeid, sender_nodetype, SUCCEED, table->table, recid, tmp); } next: if (NULL != lf) { *lf++ = '\n'; r = lf; } else break; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
static int DBpatch_2030095(void) { DB_RESULT result; DB_ROW row; int ret = SUCCEED; char *p, *q, *params = NULL, *params_esc; size_t params_alloc = 0, params_offset; result = DBselect("select itemid,params from items where type=%d", 15 /* ITEM_TYPE_CALCULATED */); while (SUCCEED == ret && NULL != (row = DBfetch(result))) { params_offset = 0; for (p = row[1]; '\0' != *p; p++) { if (NULL != strchr(ZBX_WHITESPACE, *p)) { if (' ' != *p || (0 != params_offset && NULL == strchr(ZBX_WHITESPACE, params[params_offset - 1]))) { zbx_chrcpy_alloc(¶ms, ¶ms_alloc, ¶ms_offset, *p); } continue; } if (NULL != strchr("#&|", *p)) { if ('#' == *p && 0 != params_offset && '{' == params[params_offset - 1]) { zbx_chrcpy_alloc(¶ms, ¶ms_alloc, ¶ms_offset, *p); continue; } if (('&' == *p || '|' == *p) && 0 != params_offset && NULL == strchr(ZBX_WHITESPACE, params[params_offset - 1])) { zbx_chrcpy_alloc(¶ms, ¶ms_alloc, ¶ms_offset, ' '); } switch (*p) { case '#': zbx_strcpy_alloc(¶ms, ¶ms_alloc, ¶ms_offset, "<>"); break; case '&': zbx_strcpy_alloc(¶ms, ¶ms_alloc, ¶ms_offset, "and"); break; case '|': zbx_strcpy_alloc(¶ms, ¶ms_alloc, ¶ms_offset, "or"); break; } if (('&' == *p || '|' == *p) && NULL == strchr(ZBX_WHITESPACE, *(p + 1))) zbx_chrcpy_alloc(¶ms, ¶ms_alloc, ¶ms_offset, ' '); continue; } q = p; if (SUCCEED == parse_function(&q, NULL, NULL)) { zbx_strncpy_alloc(¶ms, ¶ms_alloc, ¶ms_offset, p, q - p); p = q - 1; continue; } zbx_chrcpy_alloc(¶ms, ¶ms_alloc, ¶ms_offset, *p); } #if defined(HAVE_IBM_DB2) || defined(HAVE_ORACLE) if (2048 < params_offset && 2048 /* ITEM_PARAM_LEN */ < zbx_strlen_utf8(params)) #else if (65535 < params_offset && 65535 /* ITEM_PARAM_LEN */ < zbx_strlen_utf8(params)) #endif { zabbix_log(LOG_LEVEL_WARNING, "cannot convert calculated item expression \"%s\":" " resulting expression is too long", row[1]); } else if (0 != strcmp(row[1], params)) { params_esc = DBdyn_escape_string(params); if (ZBX_DB_OK > DBexecute("update items set params='%s' where itemid=%s", params_esc, row[0])) ret = FAIL; zbx_free(params_esc); } } DBfree_result(result); zbx_free(params); return ret; }
/****************************************************************************** * * * Function: calculate_checksums * * * * Purpose: calculate checksums of configuration data * * * * Parameters: * * * * Return value: SUCCESS - calculated successfully * * FAIL - an error occurred * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int calculate_checksums(int nodeid, const char *tablename, const zbx_uint64_t recordid) { const char *__function_name = "calculate_checksums"; char *sql = NULL; size_t sql_alloc = 2 * ZBX_KIBIBYTE, sql_offset = 0; int t, f, res = SUCCEED; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); sql = zbx_malloc(sql, sql_alloc); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from node_cksum" " where nodeid=%d" " and cksumtype=%d", nodeid, NODE_CKSUM_TYPE_NEW); if (NULL != tablename) zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " and tablename='%s'", tablename); if (0 != recordid) zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " and recordid=" ZBX_FS_UI64, recordid); if (ZBX_DB_OK > DBexecute("%s", sql)) res = FAIL; for (t = 0; NULL != tables[t].table; t++) { if (0 == (tables[t].flags & ZBX_SYNC)) continue; if (NULL != tablename && 0 != strcmp(tablename, tables[t].table)) continue; sql_offset = 0; zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "insert into node_cksum (nodeid,tablename,recordid,cksumtype,cksum)" " select %d,'%s',%s,%d,", nodeid, tables[t].table, tables[t].recid, NODE_CKSUM_TYPE_NEW); #ifdef HAVE_MYSQL zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "concat_ws(',',"); #endif for (f = 0; NULL != tables[t].fields[f].name; f++) { const ZBX_FIELD *field = &tables[t].fields[f]; if (0 == (field->flags & ZBX_SYNC)) continue; if (field->flags & ZBX_NOTNULL) { switch (field->type) { case ZBX_TYPE_ID: case ZBX_TYPE_INT: case ZBX_TYPE_UINT: zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, field->name); break; case ZBX_TYPE_FLOAT: zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "md5(cast(%s as char))", field->name); break; default: zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "md5(%s)", field->name); break; } } else { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "case when %s is null then 'NULL'", field->name); switch (field->type) { case ZBX_TYPE_ID: case ZBX_TYPE_INT: case ZBX_TYPE_UINT: zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " else cast(%s as char) end", field->name); break; case ZBX_TYPE_FLOAT: zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " else md5(cast(%s as char)) end", field->name); break; default: zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " else md5(%s) end", field->name); break; } } #ifdef HAVE_MYSQL zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ','); #else zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "||','||"); #endif } /* remove last delimiter */ if (f > 0) { #ifdef HAVE_MYSQL sql_offset--; zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ')'); #else sql_offset -= 7; #endif } zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " from %s", tables[t].table); if (0 != recordid) { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where %s=" ZBX_FS_UI64, tables[t].recid, recordid); } else { zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where 1=1" DB_NODE, DBnode(tables[t].recid, nodeid)); } if (ZBX_DB_OK > DBexecute("%s", sql)) { res = FAIL; break; } } zbx_free(sql); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res)); return res; }
/****************************************************************************** * * * Function: aggregate_get_items * * * * Purpose: get array of items specified by key for selected groups * * * * Parameters: itemids - [OUT] list of item ids * * groups - [IN] list of comma-separated host groups * * itemkey - [IN] item key to aggregate * * * ******************************************************************************/ static void aggregate_get_items(zbx_vector_uint64_t *itemids, const char *groups, const char *itemkey) { const char *__function_name = "aggregate_get_items"; char *group, *esc; DB_RESULT result; DB_ROW row; zbx_uint64_t itemid; char *sql = NULL; size_t sql_alloc = ZBX_KIBIBYTE, sql_offset = 0; int num, n; zabbix_log(LOG_LEVEL_DEBUG, "In %s() groups:'%s' itemkey:'%s'", __function_name, groups, itemkey); sql = zbx_malloc(sql, sql_alloc); esc = DBdyn_escape_string(itemkey); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select distinct i.itemid" " from items i,hosts h,hosts_groups hg,groups g" " where i.hostid=h.hostid" " and h.hostid=hg.hostid" " and hg.groupid=g.groupid" " and i.key_='%s'" " and i.status=%d" " and h.status=%d", esc, ITEM_STATUS_ACTIVE, HOST_STATUS_MONITORED); zbx_free(esc); num = num_param(groups); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and g.name in ("); for (n = 1; n <= num; n++) { if (NULL == (group = get_param_dyn(groups, n))) continue; esc = DBdyn_escape_string(group); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "'%s'", esc); if (n != num) zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ','); zbx_free(esc); zbx_free(group); } zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, ")" DB_NODE, DBnode_local("h.hostid")); result = DBselect("%s", sql); zbx_free(sql); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(itemid, row[0]); zbx_vector_uint64_append(itemids, itemid); } DBfree_result(result); zbx_vector_uint64_sort(itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: aggregate_get_items * * * * Purpose: get array of items specified by key for selected groups * * * * Parameters: ids - result, list of items * * groups - list of comma-separated host groups * * itemkey - item key to aggregate * * * ******************************************************************************/ static void aggregate_get_items(zbx_uint64_t **ids, int *ids_alloc, int *ids_num, const char *groups, const char *itemkey) { char *group, *esc; DB_RESULT result; DB_ROW row; zbx_uint64_t itemid; char *sql = NULL; size_t sql_alloc = ZBX_KIBIBYTE, sql_offset = 0; int num, n; sql = zbx_malloc(sql, sql_alloc); esc = DBdyn_escape_string(itemkey); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select i.itemid" " from items i,hosts_groups hg,hosts h,groups g" " where hg.groupid=g.groupid" " and i.hostid=h.hostid" " and hg.hostid=h.hostid" " and i.key_='%s'" " and i.status=%d" " and h.status=%d", esc, ITEM_STATUS_ACTIVE, HOST_STATUS_MONITORED); zbx_free(esc); num = num_param(groups); zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and g.name in ("); for (n = 1; n <= num; n++) { if (NULL == (group = get_param_dyn(groups, n))) continue; esc = DBdyn_escape_string(group); zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "'%s'", esc); if (n != num) zbx_chrcpy_alloc(&sql, &sql_alloc, &sql_offset, ','); zbx_free(esc); zbx_free(group); } zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, ")" DB_NODE, DBnode_local("h.hostid")); result = DBselect("%s", sql); zbx_free(sql); while (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(itemid, row[0]); uint64_array_add(ids, ids_alloc, ids_num, itemid, 64); } DBfree_result(result); }