int regexp_match_ex(zbx_vector_ptr_t *regexps, const char *string, const char *pattern, int case_sensitive) { return regexp_sub_ex(regexps, string, pattern, case_sensitive, NULL, NULL); }
static void process_active_checks(char *server, unsigned short port) { const char *__function_name = "process_active_checks"; register int i, s_count, p_count; char **pvalue; int now, send_err = SUCCEED, ret; char *value = NULL, *item_value = NULL; zbx_uint64_t lastlogsize; int mtime; char params[MAX_STRING_LEN], filename[MAX_STRING_LEN]; char pattern[MAX_STRING_LEN], output_template[MAX_STRING_LEN]; /* checks `log', `eventlog', `logrt' may contain parameter, which overrides CONFIG_MAX_LINES_PER_SECOND */ char maxlines_persec_str[16]; int maxlines_persec; #ifdef _WINDOWS unsigned long timestamp, logeventid; unsigned short severity; char key_severity[MAX_STRING_LEN], str_severity[32] /* for `regex_match_ex' */; char key_source[MAX_STRING_LEN], *provider = NULL, *source = NULL; char key_logeventid[MAX_STRING_LEN], str_logeventid[8] /* for `regex_match_ex' */; OSVERSIONINFO versionInfo; zbx_uint64_t keywords; EVT_HANDLE eventlog6_render_context = NULL; EVT_HANDLE eventlog6_query = NULL; zbx_uint64_t eventlog6_firstid = 0; zbx_uint64_t eventlog6_lastid = 0; #endif char encoding[32]; char tmp[16]; AGENT_RESULT result; zabbix_log(LOG_LEVEL_DEBUG, "In %s('%s',%hu)", __function_name, server, port); init_result(&result); now = (int)time(NULL); for (i = 0; NULL != active_metrics[i].key && SUCCEED == send_err; i++) { if (active_metrics[i].nextcheck > now) continue; if (ITEM_STATE_NORMAL != active_metrics[i].state) continue; /* special processing for log files without rotation */ if (0 == strncmp(active_metrics[i].key, "log[", 4)) { ret = FAIL; do { /* simple try realization */ if (ZBX_COMMAND_WITH_PARAMS != parse_command(active_metrics[i].key, NULL, 0, params, sizeof(params))) { break; } if (6 < num_param(params)) break; if (0 != get_param(params, 1, filename, sizeof(filename))) break; if (0 != get_param(params, 2, pattern, sizeof(pattern))) *pattern = '\0'; if (0 != get_param(params, 3, encoding, sizeof(encoding))) *encoding = '\0'; zbx_strupper(encoding); if (0 != get_param(params, 4, maxlines_persec_str, sizeof(maxlines_persec_str)) || '\0' == *maxlines_persec_str) maxlines_persec = CONFIG_MAX_LINES_PER_SECOND; else if (MIN_VALUE_LINES > (maxlines_persec = atoi(maxlines_persec_str)) || MAX_VALUE_LINES < maxlines_persec) break; if (0 != get_param(params, 5, tmp, sizeof(tmp))) *tmp = '\0'; if ('\0' == *tmp || 0 == strcmp(tmp, "all")) active_metrics[i].skip_old_data = 0; else if (0 != strcmp(tmp, "skip")) break; if (0 != get_param(params, 6, output_template, sizeof(output_template))) *output_template = '\0'; s_count = 0; p_count = 0; lastlogsize = active_metrics[i].lastlogsize; while (SUCCEED == (ret = process_log(filename, &lastlogsize, &value, encoding, active_metrics[i].skip_old_data))) { active_metrics[i].skip_old_data = 0; /* End of file. The file could become empty, must save `lastlogsize'. */ if (NULL == value) { active_metrics[i].lastlogsize = lastlogsize; break; } if (SUCCEED == regexp_sub_ex(®exps, value, pattern, ZBX_CASE_SENSITIVE, output_template, &item_value)) { send_err = process_value(server, port, CONFIG_HOSTNAME, active_metrics[i].key_orig, item_value, &lastlogsize, NULL, NULL, NULL, NULL, NULL, 1); zbx_free(item_value); s_count++; } p_count++; zbx_free(value); if (SUCCEED == send_err) active_metrics[i].lastlogsize = lastlogsize; else { /* buffer is full, stop processing active checks */ /* till the buffer is cleared */ lastlogsize = active_metrics[i].lastlogsize; goto ret; } /* do not flood Zabbix server if file grows too fast */ if (s_count >= (maxlines_persec * active_metrics[i].refresh)) break; /* do not flood local system if file grows too fast */ if (p_count >= (4 * maxlines_persec * active_metrics[i].refresh)) break; } /* while processing a log */ } while (0); /* simple try realization */ if (FAIL == ret) { active_metrics[i].state = ITEM_STATE_NOTSUPPORTED; zabbix_log(LOG_LEVEL_WARNING, "active check \"%s\" is not supported", active_metrics[i].key); process_value(server, port, CONFIG_HOSTNAME, active_metrics[i].key_orig, NULL, &active_metrics[i].lastlogsize, NULL, NULL, NULL, NULL, NULL, 0); } } /* special processing for log files with rotation */ else if (0 == strncmp(active_metrics[i].key, "logrt[", 6)) { ret = FAIL; do { /* simple try realization */ if (ZBX_COMMAND_WITH_PARAMS != parse_command(active_metrics[i].key, NULL, 0, params, sizeof(params))) { break; } if (6 < num_param(params)) break; if (0 != get_param(params, 1, filename, sizeof(filename))) break; if (0 != get_param(params, 2, pattern, sizeof(pattern))) *pattern = '\0'; if (0 != get_param(params, 3, encoding, sizeof(encoding))) *encoding = '\0'; zbx_strupper(encoding); if (0 != get_param(params, 4, maxlines_persec_str, sizeof(maxlines_persec_str)) || '\0' == *maxlines_persec_str) maxlines_persec = CONFIG_MAX_LINES_PER_SECOND; else if (MIN_VALUE_LINES > (maxlines_persec = atoi(maxlines_persec_str)) || MAX_VALUE_LINES < maxlines_persec) break; if (0 != get_param(params, 5, tmp, sizeof(tmp))) *tmp = '\0'; if ('\0' == *tmp || 0 == strcmp(tmp, "all")) active_metrics[i].skip_old_data = 0; else if (0 != strcmp(tmp, "skip")) break; if (0 != get_param(params, 6, output_template, sizeof(output_template))) *output_template = '\0'; s_count = 0; p_count = 0; lastlogsize = active_metrics[i].lastlogsize; mtime = active_metrics[i].mtime; while (SUCCEED == (ret = process_logrt(filename, &lastlogsize, &mtime, &value, encoding, active_metrics[i].skip_old_data))) { active_metrics[i].skip_old_data = 0; /* End of file. The file could become empty,*/ /* must save `lastlogsize' and `mtime'. */ if (NULL == value) { active_metrics[i].lastlogsize = lastlogsize; active_metrics[i].mtime = mtime; break; } if (SUCCEED == regexp_sub_ex(®exps, value, pattern, ZBX_CASE_SENSITIVE, output_template, &item_value)) { send_err = process_value(server, port, CONFIG_HOSTNAME, active_metrics[i].key_orig, item_value, &lastlogsize, &mtime, NULL, NULL, NULL, NULL, 1); zbx_free(item_value); s_count++; } p_count++; zbx_free(value); if (SUCCEED == send_err) { active_metrics[i].lastlogsize = lastlogsize; active_metrics[i].mtime = mtime; } else { /* buffer is full, stop processing active checks */ /* till the buffer is cleared */ lastlogsize = active_metrics[i].lastlogsize; mtime = active_metrics[i].mtime; goto ret; } /* do not flood Zabbix server if file grows too fast */ if (s_count >= (maxlines_persec * active_metrics[i].refresh)) break; /* do not flood local system if file grows too fast */ if (p_count >= (4 * maxlines_persec * active_metrics[i].refresh)) break; } /* while processing a log */ } while (0); /* simple try realization */ if (FAIL == ret) { active_metrics[i].state = ITEM_STATE_NOTSUPPORTED; zabbix_log(LOG_LEVEL_WARNING, "active check \"%s\" is not supported", active_metrics[i].key); process_value(server, port, CONFIG_HOSTNAME, active_metrics[i].key_orig, NULL, &active_metrics[i].lastlogsize, &active_metrics[i].mtime, NULL, NULL, NULL, NULL, 0); } } /* special processing for eventlog */ else if (0 == strncmp(active_metrics[i].key, "eventlog[", 9)) { ret = FAIL; #ifdef _WINDOWS do { /* simple try realization */ if (ZBX_COMMAND_WITH_PARAMS != parse_command(active_metrics[i].key, NULL, 0, params, sizeof(params))) { break; } if (7 < num_param(params)) break; if (0 != get_param(params, 1, filename, sizeof(filename))) break; if (0 != get_param(params, 2, pattern, sizeof(pattern))) *pattern = '\0'; if (0 != get_param(params, 3, key_severity, sizeof(key_severity))) *key_severity = '\0'; if (0 != get_param(params, 4, key_source, sizeof(key_source))) *key_source = '\0'; if (0 != get_param(params, 5, key_logeventid, sizeof(key_logeventid))) *key_logeventid = '\0'; if (0 != get_param(params, 6, maxlines_persec_str, sizeof(maxlines_persec_str)) || '\0' == *maxlines_persec_str) maxlines_persec = CONFIG_MAX_LINES_PER_SECOND; else if (MIN_VALUE_LINES > (maxlines_persec = atoi(maxlines_persec_str)) || MAX_VALUE_LINES < maxlines_persec) break; if (0 != get_param(params, 7, tmp, sizeof(tmp))) *tmp = '\0'; if ('\0' == *tmp || 0 == strcmp(tmp, "all")) active_metrics[i].skip_old_data = 0; else if (0 != strcmp(tmp, "skip")) break; s_count = 0; p_count = 0; lastlogsize = active_metrics[i].lastlogsize; versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&versionInfo); if (versionInfo.dwMajorVersion >= 6) /* Windows Vista, 7 or Server 2008 */ { __try { if (SUCCEED != initialize_eventlog6(filename, &lastlogsize, &eventlog6_firstid, &eventlog6_lastid, &eventlog6_render_context, &eventlog6_query)) { finalize_eventlog6(&eventlog6_render_context, &eventlog6_query); break; } while (SUCCEED == (ret = process_eventlog6(filename, &lastlogsize, ×tamp, &provider, &source, &severity, &value, &logeventid, &eventlog6_firstid, &eventlog6_lastid, &eventlog6_render_context, &eventlog6_query, &keywords, active_metrics[i].skip_old_data))) { active_metrics[i].skip_old_data = 0; /* End of file. */ /* The eventlog could become empty, must save `lastlogsize'. */ if (NULL == value) { active_metrics[i].lastlogsize = lastlogsize; break; } switch (severity) { case WINEVENT_LEVEL_LOG_ALWAYS: case WINEVENT_LEVEL_INFO: if (0 != (keywords & WINEVENT_KEYWORD_AUDIT_FAILURE)) { severity = ITEM_LOGTYPE_FAILURE_AUDIT; strscpy(str_severity, AUDIT_FAILURE); break; } else if (0 != (keywords & WINEVENT_KEYWORD_AUDIT_SUCCESS)) { severity = ITEM_LOGTYPE_SUCCESS_AUDIT; strscpy(str_severity, AUDIT_SUCCESS); break; } else severity = ITEM_LOGTYPE_INFORMATION; strscpy(str_severity, INFORMATION_TYPE); break; case WINEVENT_LEVEL_WARNING: severity = ITEM_LOGTYPE_WARNING; strscpy(str_severity, WARNING_TYPE); break; case WINEVENT_LEVEL_ERROR: severity = ITEM_LOGTYPE_ERROR; strscpy(str_severity, ERROR_TYPE); break; case WINEVENT_LEVEL_CRITICAL: severity = ITEM_LOGTYPE_CRITICAL; strscpy(str_severity, CRITICAL_TYPE); break; case WINEVENT_LEVEL_VERBOSE: severity = ITEM_LOGTYPE_VERBOSE; strscpy(str_severity, VERBOSE_TYPE); break; } zbx_snprintf(str_logeventid, sizeof(str_logeventid), "%lu", logeventid); if (SUCCEED == regexp_match_ex(®exps, value, pattern, ZBX_CASE_SENSITIVE) && SUCCEED == regexp_match_ex(®exps, str_severity, key_severity, ZBX_IGNORE_CASE) && SUCCEED == regexp_match_ex(®exps, provider, key_source, ZBX_IGNORE_CASE) && SUCCEED == regexp_match_ex(®exps, str_logeventid, key_logeventid, ZBX_CASE_SENSITIVE)) { send_err = process_value(server, port, CONFIG_HOSTNAME, active_metrics[i].key_orig, value, &lastlogsize, NULL, ×tamp, provider, &severity, &logeventid, 1); s_count++; } p_count++; zbx_free(source); zbx_free(provider); zbx_free(value); if (SUCCEED == send_err) active_metrics[i].lastlogsize = lastlogsize; else { /* buffer is full, stop processing active checks*/ /* till the buffer is cleared */ lastlogsize = active_metrics[i].lastlogsize; goto ret; } /* do not flood Zabbix server if file grows too fast */ if (s_count >= (maxlines_persec * active_metrics[i].refresh)) break; /* do not flood local system if file grows too fast */ if (p_count >= (4 * maxlines_persec * active_metrics[i].refresh)) break; } /* while processing an eventlog */ finalize_eventlog6(&eventlog6_render_context, &eventlog6_query); } __except (DelayLoadDllExceptionFilter(GetExceptionInformation())) { zabbix_log(LOG_LEVEL_WARNING, "failed to process eventlog"); break; } } else if (versionInfo.dwMajorVersion < 6) /* Windows versions before Vista */ { while (SUCCEED == (ret = process_eventlog(filename, &lastlogsize, ×tamp, &source, &severity, &value, &logeventid, active_metrics[i].skip_old_data))) { active_metrics[i].skip_old_data = 0; /* End of file. */ /* The eventlog could become empty, must save `lastlogsize'. */ if (NULL == value) { active_metrics[i].lastlogsize = lastlogsize; break; } switch (severity) { case EVENTLOG_SUCCESS: case EVENTLOG_INFORMATION_TYPE: severity = ITEM_LOGTYPE_INFORMATION; strscpy(str_severity, INFORMATION_TYPE); break; case EVENTLOG_WARNING_TYPE: severity = ITEM_LOGTYPE_WARNING; strscpy(str_severity, WARNING_TYPE); break; case EVENTLOG_ERROR_TYPE: severity = ITEM_LOGTYPE_ERROR; strscpy(str_severity, ERROR_TYPE); break; case EVENTLOG_AUDIT_FAILURE: severity = ITEM_LOGTYPE_FAILURE_AUDIT; strscpy(str_severity, AUDIT_FAILURE); break; case EVENTLOG_AUDIT_SUCCESS: severity = ITEM_LOGTYPE_SUCCESS_AUDIT; strscpy(str_severity, AUDIT_SUCCESS); break; } zbx_snprintf(str_logeventid, sizeof(str_logeventid), "%lu", logeventid); if (SUCCEED == regexp_match_ex(®exps, value, pattern, ZBX_CASE_SENSITIVE) && SUCCEED == regexp_match_ex(®exps, str_severity, key_severity, ZBX_IGNORE_CASE) && SUCCEED == regexp_match_ex(®exps, source, key_source, ZBX_IGNORE_CASE) && SUCCEED == regexp_match_ex(®exps, str_logeventid, key_logeventid, ZBX_CASE_SENSITIVE)) { send_err = process_value(server, port, CONFIG_HOSTNAME, active_metrics[i].key_orig, value, &lastlogsize, NULL, ×tamp, source, &severity, &logeventid, 1); s_count++; } p_count++; zbx_free(source); zbx_free(value); if (SUCCEED == send_err) active_metrics[i].lastlogsize = lastlogsize; else { /* buffer is full, stop processing active checks */ /* till the buffer is cleared */ lastlogsize = active_metrics[i].lastlogsize; goto ret; } /* do not flood Zabbix server if file grows too fast */ if (s_count >= (maxlines_persec * active_metrics[i].refresh)) break; /* do not flood local system if file grows too fast */ if (p_count >= (4 * maxlines_persec * active_metrics[i].refresh)) break; } /* while processing an eventlog */ } break; } while (0); /* simple try realization */ #endif /* _WINDOWS */ if (FAIL == ret) { active_metrics[i].state = ITEM_STATE_NOTSUPPORTED; zabbix_log(LOG_LEVEL_WARNING, "active check \"%s\" is not supported", active_metrics[i].key); process_value(server, port, CONFIG_HOSTNAME, active_metrics[i].key_orig, NULL, &active_metrics[i].lastlogsize, NULL, NULL, NULL, NULL, NULL, 0); } }