/****************************************************************************** * * * Function: process_httptest * * * * Purpose: process single scenario of http test * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void process_httptest(DC_HOST *host, zbx_httptest_t *httptest) { const char *__function_name = "process_httptest"; DB_RESULT result; DB_ROW row; DB_HTTPSTEP httpstep; char *err_str = NULL; int lastfailedstep; zbx_timespec_t ts; zbx_httpstat_t stat; double speed_download = 0; int speed_download_num = 0; #ifdef HAVE_LIBCURL int err; char auth[HTTPTEST_HTTP_USER_LEN_MAX + HTTPTEST_HTTP_PASSWORD_LEN_MAX]; CURL *easyhandle = NULL; #endif zabbix_log(LOG_LEVEL_DEBUG, "In %s() httptestid:" ZBX_FS_UI64 " name:'%s'", __function_name, httptest->httptest.httptestid, httptest->httptest.name); lastfailedstep = 0; result = DBselect( "select httpstepid,no,name,url,timeout,posts,required,status_codes,variables" " from httpstep" " where httptestid=" ZBX_FS_UI64 " order by no", httptest->httptest.httptestid); #ifdef HAVE_LIBCURL if (NULL == (easyhandle = curl_easy_init())) { err_str = zbx_strdup(err_str, "cannot initialize cURL library"); goto clean; } if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_PROXY, httptest->httptest.http_proxy)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_COOKIEFILE, "")) || CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_USERAGENT, httptest->httptest.agent)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_FOLLOWLOCATION, 1L)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, WRITEFUNCTION2)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_HEADERFUNCTION, HEADERFUNCTION2)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYPEER, 0L)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYHOST, 0L))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); goto clean; } while (NULL != (row = DBfetch(result))) { /* NOTE: do not break or return from this block! */ /* process_step_data() call is required! */ ZBX_STR2UINT64(httpstep.httpstepid, row[0]); httpstep.httptestid = httptest->httptest.httptestid; httpstep.no = atoi(row[1]); httpstep.name = row[2]; httpstep.url = zbx_strdup(NULL, row[3]); substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, host, NULL, &httpstep.url, MACRO_TYPE_HTTPTEST_FIELD, NULL, 0); httpstep.timeout = atoi(row[4]); httpstep.posts = zbx_strdup(NULL, row[5]); substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, host, NULL, &httpstep.posts, MACRO_TYPE_HTTPTEST_FIELD, NULL, 0); httpstep.required = zbx_strdup(NULL, row[6]); substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, host, NULL, &httpstep.required, MACRO_TYPE_HTTPTEST_FIELD, NULL, 0); httpstep.status_codes = zbx_strdup(NULL, row[7]); substitute_simple_macros(NULL, NULL, NULL, NULL, &host->hostid, NULL, NULL, &httpstep.status_codes, MACRO_TYPE_COMMON, NULL, 0); httpstep.variables = row[8]; memset(&stat, 0, sizeof(stat)); http_substitute_variables(httptest, &httpstep.url); http_substitute_variables(httptest, &httpstep.posts); zabbix_log(LOG_LEVEL_DEBUG, "%s() use step \"%s\"", __function_name, httpstep.name); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_POSTFIELDS, httpstep.posts))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); goto httpstep_error; } if ('\0' != *httpstep.posts) zabbix_log(LOG_LEVEL_DEBUG, "%s() use post \"%s\"", __function_name, httpstep.posts); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_POST, '\0' != *httpstep.posts ? 1L : 0L))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); goto httpstep_error; } if (HTTPTEST_AUTH_NONE != httptest->httptest.authentication) { long curlauth = 0; zabbix_log(LOG_LEVEL_DEBUG, "%s() setting HTTPAUTH [%d]", __function_name, httptest->httptest.authentication); zabbix_log(LOG_LEVEL_DEBUG, "%s() setting USERPWD for authentication", __function_name); switch (httptest->httptest.authentication) { case HTTPTEST_AUTH_BASIC: curlauth = CURLAUTH_BASIC; break; case HTTPTEST_AUTH_NTLM: curlauth = CURLAUTH_NTLM; break; default: THIS_SHOULD_NEVER_HAPPEN; break; } zbx_snprintf(auth, sizeof(auth), "%s:%s", httptest->httptest.http_user, httptest->httptest.http_password); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_HTTPAUTH, curlauth)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_USERPWD, auth))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); goto httpstep_error; } } zabbix_log(LOG_LEVEL_DEBUG, "%s() go to URL \"%s\"", __function_name, httpstep.url); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_TIMEOUT, (long)httpstep.timeout)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, CURLOPT_URL, httpstep.url))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); goto httpstep_error; } /* try to retrieve page several times depending on number of retries */ do { memset(&page, 0, sizeof(page)); if (CURLE_OK == (err = curl_easy_perform(easyhandle))) break; } while (0 != --httptest->httptest.retries); if (CURLE_OK == err) { char *var_err_str = NULL; /* first get the data that is needed even if step fails */ if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_RESPONSE_CODE, &stat.rspcode))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } else if ('\0' != *httpstep.status_codes && FAIL == int_in_list(httpstep.status_codes, stat.rspcode)) { err_str = zbx_strdup(err_str, "status code did not match"); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_TOTAL_TIME, &stat.total_time)) && NULL == err_str) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_SPEED_DOWNLOAD, &stat.speed_download)) && NULL == err_str) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } else { speed_download += stat.speed_download; speed_download_num++; } /* required pattern */ if (NULL == err_str && '\0' != *httpstep.required && NULL == zbx_regexp_match(page.data, httpstep.required, NULL)) { err_str = zbx_strdup(err_str, "required pattern not found"); } /* variables defined in scenario */ if (NULL == err_str && FAIL == http_process_variables(httptest, httptest->httptest.variables, page.data, &var_err_str)) { char *variables; variables = string_replace(httptest->httptest.variables, "\r\n", " "); err_str = zbx_dsprintf(err_str, "error in scenario variables \"%s\": %s", variables, var_err_str); zbx_free(variables); } /* variables defined in a step */ if (NULL == err_str && FAIL == http_process_variables(httptest, httpstep.variables, page.data, &var_err_str)) { char *variables; variables = string_replace(httpstep.variables, "\r\n", " "); err_str = zbx_dsprintf(err_str, "error in step variables \"%s\": %s", variables, var_err_str); zbx_free(variables); } zbx_free(var_err_str); } else err_str = zbx_strdup(err_str, curl_easy_strerror(err)); zbx_free(page.data); httpstep_error: zbx_free(httpstep.status_codes); zbx_free(httpstep.required); zbx_free(httpstep.posts); zbx_free(httpstep.url); zbx_timespec(&ts); process_step_data(httpstep.httpstepid, &stat, &ts); if (NULL != err_str) { lastfailedstep = httpstep.no; break; } } clean: curl_easy_cleanup(easyhandle); #else err_str = zbx_strdup(err_str, "cURL library is required for Web monitoring support"); #endif /* HAVE_LIBCURL */ zbx_timespec(&ts); if (NULL != err_str) { if (0 == lastfailedstep) { /* we are here either because cURL initialization failed */ /* or we have been compiled without cURL library */ lastfailedstep = 1; if (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(httpstep.httpstepid, row[0]); httpstep.name = row[2]; memset(&stat, 0, sizeof(stat)); process_step_data(httpstep.httpstepid, &stat, &ts); } else THIS_SHOULD_NEVER_HAPPEN; } zabbix_log(LOG_LEVEL_WARNING, "cannot process step \"%s\" of web scenario \"%s\" on host \"%s\": %s", httpstep.name, httptest->httptest.name, host->name, err_str); } DBfree_result(result); DBexecute("update httptest set nextcheck=%d+delay where httptestid=" ZBX_FS_UI64, ts.sec, httptest->httptest.httptestid); if (0 != speed_download_num) speed_download /= speed_download_num; process_test_data(httptest->httptest.httptestid, lastfailedstep, speed_download, err_str, &ts); zbx_free(err_str); dc_flush_history(); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: check_discovery_condition * * * * Purpose: check if event matches single condition * * * * Parameters: event - discovery event to check * * (event->source == EVENT_SOURCE_DISCOVERY) * * condition - condition for matching * * * * Return value: SUCCEED - matches, FAIL - otherwise * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int check_discovery_condition(DB_EVENT *event, DB_CONDITION *condition) { const char *__function_name = "check_discovery_condition"; DB_RESULT result; DB_ROW row; zbx_uint64_t condition_value; int tmp_int, now; int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (condition->conditiontype == CONDITION_TYPE_DRULE) { ZBX_STR2UINT64(condition_value, condition->value); if (EVENT_OBJECT_DHOST == event->object) { result = DBselect( "select druleid" " from dhosts" " where druleid=" ZBX_FS_UI64 " and dhostid=" ZBX_FS_UI64, condition_value, event->objectid); } else /* EVENT_OBJECT_DSERVICE */ { result = DBselect( "select h.druleid" " from dhosts h,dservices s" " where h.dhostid=s.dhostid" " and h.druleid=" ZBX_FS_UI64 " and s.dserviceid=" ZBX_FS_UI64, condition_value, event->objectid); } switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (NULL != DBfetch(result)) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (NULL == DBfetch(result)) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } DBfree_result(result); } else if (condition->conditiontype == CONDITION_TYPE_DCHECK) { if (EVENT_OBJECT_DSERVICE == event->object) { ZBX_STR2UINT64(condition_value, condition->value); result = DBselect( "select dcheckid" " from dservices" " where dcheckid=" ZBX_FS_UI64 " and dserviceid=" ZBX_FS_UI64, condition_value, event->objectid); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (NULL != DBfetch(result)) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (NULL == DBfetch(result)) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } DBfree_result(result); } } else if (condition->conditiontype == CONDITION_TYPE_DOBJECT) { condition_value = atoi(condition->value); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (event->object == condition_value) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } else if (condition->conditiontype == CONDITION_TYPE_PROXY) { ZBX_STR2UINT64(condition_value, condition->value); if (EVENT_OBJECT_DHOST == event->object) { result = DBselect( "select r.proxy_hostid" " from drules r,dhosts h" " where r.druleid=h.druleid" " and r.proxy_hostid=" ZBX_FS_UI64 " and h.dhostid=" ZBX_FS_UI64, condition_value, event->objectid); } else /* EVENT_OBJECT_DSERVICE */ { result = DBselect( "select r.proxy_hostid" " from drules r,dhosts h,dservices s" " where r.druleid=h.druleid" " and h.dhostid=s.dhostid" " and r.proxy_hostid=" ZBX_FS_UI64 " and s.dserviceid=" ZBX_FS_UI64, condition_value, event->objectid); } switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (NULL != DBfetch(result)) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (NULL == DBfetch(result)) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } DBfree_result(result); } else if (condition->conditiontype == CONDITION_TYPE_DVALUE) { if (EVENT_OBJECT_DSERVICE == event->object) { result = DBselect( "select value" " from dservices" " where dserviceid=" ZBX_FS_UI64, event->objectid); if (NULL != (row = DBfetch(result))) { switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (0 == strcmp(condition->value, row[0])) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (0 != strcmp(condition->value, row[0])) ret = SUCCEED; break; case CONDITION_OPERATOR_MORE_EQUAL: if (0 <= strcmp(row[0], condition->value)) ret = SUCCEED; break; case CONDITION_OPERATOR_LESS_EQUAL: if (0 >= strcmp(row[0], condition->value)) ret = SUCCEED; break; case CONDITION_OPERATOR_LIKE: if (NULL != strstr(row[0], condition->value)) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_LIKE: if (NULL == strstr(row[0], condition->value)) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } DBfree_result(result); } } else if (condition->conditiontype == CONDITION_TYPE_DHOST_IP) { if (event->object == EVENT_OBJECT_DHOST) { result = DBselect( "select distinct ip" " from dservices" " where dhostid=" ZBX_FS_UI64, event->objectid); } else { result = DBselect( "select ip" " from dservices" " where dserviceid=" ZBX_FS_UI64, event->objectid); } while (NULL != (row = DBfetch(result)) && FAIL == ret) { switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (SUCCEED == ip_in_list(condition->value, row[0])) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (SUCCEED != ip_in_list(condition->value, row[0])) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } DBfree_result(result); } else if (condition->conditiontype == CONDITION_TYPE_DSERVICE_TYPE) { if (EVENT_OBJECT_DSERVICE == event->object) { condition_value = atoi(condition->value); result = DBselect( "select type" " from dservices" " where dserviceid=" ZBX_FS_UI64, event->objectid); if (NULL != (row = DBfetch(result))) { tmp_int = atoi(row[0]); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (condition_value == tmp_int) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (condition_value != tmp_int) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } DBfree_result(result); } } else if (condition->conditiontype == CONDITION_TYPE_DSTATUS) { condition_value = atoi(condition->value); switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (condition_value == event->value) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (condition_value != event->value) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } else if (condition->conditiontype == CONDITION_TYPE_DUPTIME) { condition_value = atoi(condition->value); if (event->object == EVENT_OBJECT_DHOST) { result = DBselect( "select status,lastup,lastdown" " from dhosts" " where dhostid=" ZBX_FS_UI64, event->objectid); } else { result = DBselect( "select status,lastup,lastdown" " from dservices" " where dserviceid=" ZBX_FS_UI64, event->objectid); } if (NULL != (row = DBfetch(result))) { tmp_int = (atoi(row[0]) == DOBJECT_STATUS_UP) ? atoi(row[1]) : atoi(row[2]); now = time(NULL); switch (condition->operator) { case CONDITION_OPERATOR_LESS_EQUAL: if (0 != tmp_int && (now - tmp_int) <= condition_value) ret = SUCCEED; break; case CONDITION_OPERATOR_MORE_EQUAL: if (0 != tmp_int && (now - tmp_int) >= condition_value) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } DBfree_result(result); } else if (condition->conditiontype == CONDITION_TYPE_DSERVICE_PORT) { if (event->object == EVENT_OBJECT_DSERVICE) { result = DBselect( "select port" " from dservices" " where dserviceid=" ZBX_FS_UI64, event->objectid); if (NULL != (row = DBfetch(result))) { switch (condition->operator) { case CONDITION_OPERATOR_EQUAL: if (SUCCEED == int_in_list(condition->value, atoi(row[0]))) ret = SUCCEED; break; case CONDITION_OPERATOR_NOT_EQUAL: if (SUCCEED != int_in_list(condition->value, atoi(row[0]))) ret = SUCCEED; break; default: zabbix_log(LOG_LEVEL_ERR, "Unsupported operator [%d] for condition id [" ZBX_FS_UI64 "]", condition->operator, condition->conditionid); } } DBfree_result(result); } } else { zabbix_log(LOG_LEVEL_ERR, "Unsupported condition type [%d] for condition id [" ZBX_FS_UI64 "]", condition->conditiontype, condition->conditionid); } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/****************************************************************************** * * * Function: process_httptest * * * * Purpose: process single scenario of http test * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void process_httptest(DB_HTTPTEST *httptest) { const char *__function_name = "process_httptest"; DB_RESULT result; DB_ROW row; DB_HTTPSTEP httpstep; char *err_str = NULL, *err_str_esc = NULL; int now, lastfailedstep; ZBX_HTTPSTAT stat; double speed_download = 0; int speed_download_num = 0; #ifdef HAVE_LIBCURL int err, opt; char auth[HTTPTEST_HTTP_USER_LEN_MAX + HTTPTEST_HTTP_PASSWORD_LEN_MAX]; CURL *easyhandle = NULL; #endif zabbix_log(LOG_LEVEL_DEBUG, "In %s() httptestid:" ZBX_FS_UI64 " name:'%s'", __function_name, httptest->httptestid, httptest->name); lastfailedstep = 0; httptest->time = 0; now = time(NULL); DBexecute("update httptest" " set lastcheck=%d" " where httptestid=" ZBX_FS_UI64, now, httptest->httptestid); result = DBselect( "select httpstepid,no,name,url,timeout," "posts,required,status_codes" " from httpstep" " where httptestid=" ZBX_FS_UI64 " order by no", httptest->httptestid); #ifdef HAVE_LIBCURL if (NULL == (easyhandle = curl_easy_init())) { zabbix_log(LOG_LEVEL_ERR, "Web scenario [%s] error: could not init cURL library", httptest->name); err_str = zbx_strdup(err_str, "could not init cURL library"); goto clean; } if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_COOKIEFILE, "")) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_USERAGENT, httptest->agent)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_FOLLOWLOCATION, 1)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_WRITEFUNCTION, WRITEFUNCTION2)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HEADERFUNCTION, HEADERFUNCTION2)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_SSL_VERIFYPEER, 0)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_SSL_VERIFYHOST, 0)) || /* The pointed data are not copied by the library. As a consequence, the data */ /* must be preserved by the calling application until the transfer finishes. */ CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, httpstep.posts))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario [%s] error: could not set cURL option [%d]: %s", httptest->name, opt, curl_easy_strerror(err)); err_str = zbx_strdup(err_str, curl_easy_strerror(err)); goto clean; } while (NULL == err_str && NULL != (row = DBfetch(result))) { /* NOTE: do not use break or return for this block! * process_step_data calling required! */ ZBX_STR2UINT64(httpstep.httpstepid, row[0]); httpstep.httptestid = httptest->httptestid; httpstep.no = atoi(row[1]); httpstep.name = row[2]; strscpy(httpstep.url, row[3]); httpstep.timeout = atoi(row[4]); strscpy(httpstep.posts, row[5]); strscpy(httpstep.required, row[6]); strscpy(httpstep.status_codes, row[7]); DBexecute("update httptest" " set curstep=%d," "curstate=%d" " where httptestid=" ZBX_FS_UI64, httpstep.no, HTTPTEST_STATE_BUSY, httptest->httptestid); memset(&stat, 0, sizeof(stat)); /* Substitute macros */ http_substitute_macros(httptest, httpstep.url, sizeof(httpstep.url)); http_substitute_macros(httptest, httpstep.posts, sizeof(httpstep.posts)); zabbix_log(LOG_LEVEL_DEBUG, "WEBMonitor: use step [%s]", httpstep.name); if ('\0' != *httpstep.posts) { zabbix_log(LOG_LEVEL_DEBUG, "WEBMonitor: use post [%s]", httpstep.posts); curl_easy_setopt(easyhandle, CURLOPT_POST, 1); } else curl_easy_setopt(easyhandle, CURLOPT_POST, 0); if (HTTPTEST_AUTH_NONE != httptest->authentication) { long curlauth = 0; zabbix_log(LOG_LEVEL_DEBUG, "WEBMonitor: Setting HTTPAUTH [%d]", httptest->authentication); zabbix_log(LOG_LEVEL_DEBUG, "WEBMonitor: Setting USERPWD for authentication"); switch (httptest->authentication) { case HTTPTEST_AUTH_BASIC: curlauth = CURLAUTH_BASIC; break; case HTTPTEST_AUTH_NTLM: curlauth = CURLAUTH_NTLM; break; default: THIS_SHOULD_NEVER_HAPPEN; break; } zbx_snprintf(auth, sizeof(auth), "%s:%s", httptest->http_user, httptest->http_password); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HTTPAUTH, curlauth)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_USERPWD, auth))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: could not set cURL option [%d]: %s", httptest->name, httpstep.name, opt, curl_easy_strerror(err)); err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } } if (NULL == err_str) { zabbix_log(LOG_LEVEL_DEBUG, "WEBMonitor: go to URL [%s]", httpstep.url); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_URL, httpstep.url)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_TIMEOUT, httpstep.timeout)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_CONNECTTIMEOUT, httpstep.timeout))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: could not set cURL option [%d]: %s", httptest->name, httpstep.name, opt, curl_easy_strerror(err)); err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } } if (NULL == err_str) { memset(&page, 0, sizeof(page)); if (CURLE_OK != (err = curl_easy_perform(easyhandle))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: error doing curl_easy_perform: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } else { if ('\0' != httpstep.required[0] && NULL == zbx_regexp_match(page.data, httpstep.required, NULL)) { zabbix_log(LOG_LEVEL_DEBUG, "Page did not match [%s]", httpstep.required); err_str = zbx_strdup(err_str, "Page did not match"); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_RESPONSE_CODE, &stat.rspcode))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: error getting CURLINFO_RESPONSE_CODE: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); err_str = (NULL == err_str ? zbx_strdup(err_str, curl_easy_strerror(err)) : err_str); } else if ('\0' != httpstep.status_codes[0] && FAIL == int_in_list(httpstep.status_codes, stat.rspcode)) { zabbix_log(LOG_LEVEL_DEBUG, "Status code did not match [%s]", httpstep.status_codes); err_str = (NULL == err_str ? zbx_strdup(err_str, "Status code did not match") : err_str); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_TOTAL_TIME, &stat.total_time))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: error getting CURLINFO_TOTAL_TIME: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); err_str = (NULL == err_str ? zbx_strdup(err_str, curl_easy_strerror(err)) : err_str); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_SPEED_DOWNLOAD, &stat.speed_download))) { zabbix_log(LOG_LEVEL_ERR, "Web scenario step [%s:%s] error: error getting CURLINFO_SPEED_DOWNLOAD: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); err_str = (NULL == err_str ? zbx_strdup(err_str, curl_easy_strerror(err)) : err_str); } else { speed_download += stat.speed_download; speed_download_num++; } } zbx_free(page.data); } if (NULL != err_str) lastfailedstep = httpstep.no; httptest->time += stat.total_time; process_step_data(httpstep.httpstepid, &stat); } clean: curl_easy_cleanup(easyhandle); #else err_str = zbx_strdup(err_str, "cURL library is required for Web monitoring support"); #endif /* HAVE_LIBCURL */ if (0 == lastfailedstep && NULL != err_str) { /* we are here either because cURL initialization failed before */ /* the first step or we have been compiled without cURL library */ lastfailedstep = 1; if (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(httpstep.httpstepid, row[0]); memset(&stat, 0, sizeof(stat)); process_step_data(httpstep.httpstepid, &stat); } else THIS_SHOULD_NEVER_HAPPEN; } DBfree_result(result); err_str_esc = DBdyn_escape_string_len(err_str, HTTPTEST_ERROR_LEN); DBexecute("update httptest" " set curstep=0," "curstate=%d," "lastcheck=%d," "nextcheck=%d+delay," "lastfailedstep=%d," "time=" ZBX_FS_DBL "," "error='%s'" " where httptestid=" ZBX_FS_UI64, HTTPTEST_STATE_IDLE, now, now, lastfailedstep, httptest->time, err_str_esc, httptest->httptestid); zbx_free(err_str_esc); zbx_free(err_str); stat.test_total_time = httptest->time; stat.test_last_step = lastfailedstep; stat.speed_download = speed_download_num ? speed_download / speed_download_num : 0; process_test_data(httptest->httptestid, &stat); zabbix_log(LOG_LEVEL_DEBUG, "End of %s() total_time:" ZBX_FS_DBL, __function_name, httptest->time); }
/****************************************************************************** * * * Function: process_httptest * * * * Purpose: process single scenario of http test * * * * Parameters: * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void process_httptest(DB_HTTPTEST *httptest) { const char *__function_name = "process_httptest"; DB_RESULT result; DB_ROW row; DB_HTTPSTEP httpstep; char *err_str = NULL; int lastfailedstep; zbx_timespec_t ts; ZBX_HTTPSTAT stat; double speed_download = 0; int speed_download_num = 0; #ifdef HAVE_LIBCURL int err, opt; char auth[HTTPTEST_HTTP_USER_LEN_MAX + HTTPTEST_HTTP_PASSWORD_LEN_MAX]; CURL *easyhandle = NULL; #endif zabbix_log(LOG_LEVEL_DEBUG, "In %s() httptestid:" ZBX_FS_UI64 " name:'%s'", __function_name, httptest->httptestid, httptest->name); lastfailedstep = 0; result = DBselect( "select httpstepid,no,name,url,timeout,posts,cookies,required,status_codes" " from httpstep" " where httptestid=" ZBX_FS_UI64 " order by no", httptest->httptestid); #ifdef HAVE_LIBCURL if (NULL == (easyhandle = curl_easy_init())) { err_str = zbx_strdup(err_str, "could not init cURL library"); zabbix_log(LOG_LEVEL_ERR, "web scenario \"%s\" error: %s", httptest->name, err_str); goto clean; } if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_COOKIEFILE, "")) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_USERAGENT, httptest->agent)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_FOLLOWLOCATION, 1L)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_WRITEFUNCTION, WRITEFUNCTION2)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HEADERFUNCTION, HEADERFUNCTION2)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_SSL_VERIFYPEER, 0L)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_SSL_VERIFYHOST, 0L))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); zabbix_log(LOG_LEVEL_ERR, "web scenario \"%s\" error: could not set cURL option [%d]: %s", httptest->name, opt, err_str); goto clean; } while (NULL != (row = DBfetch(result))) { /* NOTE: do not break or return from this block! */ /* process_step_data() call is required! */ ZBX_STR2UINT64(httpstep.httpstepid, row[0]); httpstep.httptestid = httptest->httptestid; httpstep.no = atoi(row[1]); httpstep.name = row[2]; httpstep.url = zbx_strdup(NULL, row[3]); httpstep.timeout = atoi(row[4]); httpstep.posts = zbx_strdup(NULL, row[5]); httpstep.cookies = zbx_strdup(NULL, row[6]); httpstep.required = row[7]; httpstep.status_codes = row[8]; memset(&stat, 0, sizeof(stat)); http_substitute_macros(httptest->macros, &httpstep.url); http_substitute_macros(httptest->macros, &httpstep.posts); http_substitute_macros(httptest->macros, &httpstep.cookies); zabbix_log(LOG_LEVEL_DEBUG, "%s() use step \"%s\"", __function_name, httpstep.name); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POSTFIELDS, httpstep.posts))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); zabbix_log(LOG_LEVEL_ERR, "web scenario \"%s:%s\" error:" " could not set cURL option [%d]: %s", httptest->name, httpstep.name, opt, err_str); goto httpstep_error; } if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_COOKIE, httpstep.cookies))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); zabbix_log(LOG_LEVEL_ERR, "web scenario \"%s:%s\" error:" " could not set cURL option [%d]: %s", httptest->name, httpstep.name, opt, err_str); goto httpstep_error; } if ('\0' != *httpstep.posts) zabbix_log(LOG_LEVEL_DEBUG, "%s() use post \"%s\"", __function_name, httpstep.posts); if ('\0' != *httpstep.cookies) zabbix_log(LOG_LEVEL_DEBUG, "%s() use cookies \"%s\"", __function_name, httpstep.cookies); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_POST, '\0' != *httpstep.posts ? 1L : 0L))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); zabbix_log(LOG_LEVEL_ERR, "web scenario \"%s:%s\" error:" " could not set cURL option [%d]: %s", httptest->name, httpstep.name, opt, err_str); goto httpstep_error; } if (HTTPTEST_AUTH_NONE != httptest->authentication) { long curlauth = 0; zabbix_log(LOG_LEVEL_DEBUG, "%s() setting HTTPAUTH [%d]", __function_name, httptest->authentication); zabbix_log(LOG_LEVEL_DEBUG, "%s() setting USERPWD for authentication", __function_name); switch (httptest->authentication) { case HTTPTEST_AUTH_BASIC: curlauth = CURLAUTH_BASIC; break; case HTTPTEST_AUTH_NTLM: curlauth = CURLAUTH_NTLM; break; default: THIS_SHOULD_NEVER_HAPPEN; break; } zbx_snprintf(auth, sizeof(auth), "%s:%s", httptest->http_user, httptest->http_password); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_HTTPAUTH, curlauth)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_USERPWD, auth))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); zabbix_log(LOG_LEVEL_ERR, "web scenario step \"%s:%s\" error:" " could not set cURL option [%d]: %s", httptest->name, httpstep.name, opt, err_str); goto httpstep_error; } } zabbix_log(LOG_LEVEL_DEBUG, "%s() go to URL \"%s\"", __function_name, httpstep.url); if (CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_URL, httpstep.url)) || CURLE_OK != (err = curl_easy_setopt(easyhandle, opt = CURLOPT_TIMEOUT, (long)httpstep.timeout))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); zabbix_log(LOG_LEVEL_ERR, "web scenario step \"%s:%s\" error:" " could not set cURL option [%d]: %s", httptest->name, httpstep.name, opt, err_str); goto httpstep_error; } memset(&page, 0, sizeof(page)); if (CURLE_OK != (err = curl_easy_perform(easyhandle))) { err_str = zbx_strdup(err_str, curl_easy_strerror(err)); zabbix_log(LOG_LEVEL_ERR, "web scenario step \"%s:%s\" error:" " error doing curl_easy_perform: %s", httptest->name, httpstep.name, err_str); } else { if ('\0' != *httpstep.required && NULL == zbx_regexp_match(page.data, httpstep.required, NULL)) { zabbix_log(LOG_LEVEL_DEBUG, "%s() required pattern \"%s\" not found on %s", __function_name, httpstep.required, httpstep.url); err_str = zbx_strdup(err_str, "Required pattern not found"); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_RESPONSE_CODE, &stat.rspcode))) { zabbix_log(LOG_LEVEL_ERR, "web scenario step \"%s:%s\" error:" " error getting CURLINFO_RESPONSE_CODE: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); if (NULL == err_str) err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } else if ('\0' != *httpstep.status_codes && FAIL == int_in_list(httpstep.status_codes, stat.rspcode)) { zabbix_log(LOG_LEVEL_DEBUG, "%s() status code did not match [%s]", __function_name, httpstep.status_codes); if (NULL == err_str) err_str = zbx_strdup(err_str, "Status code did not match"); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_TOTAL_TIME, &stat.total_time))) { zabbix_log(LOG_LEVEL_ERR, "web scenario step \"%s:%s\" error:" " error getting CURLINFO_TOTAL_TIME: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); if (NULL == err_str) err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } if (CURLE_OK != (err = curl_easy_getinfo(easyhandle, CURLINFO_SPEED_DOWNLOAD, &stat.speed_download))) { zabbix_log(LOG_LEVEL_ERR, "web scenario step \"%s:%s\" error:" " error getting CURLINFO_SPEED_DOWNLOAD: %s", httptest->name, httpstep.name, curl_easy_strerror(err)); if (NULL == err_str) err_str = zbx_strdup(err_str, curl_easy_strerror(err)); } else { speed_download += stat.speed_download; speed_download_num++; } } zbx_free(page.data); httpstep_error: zbx_free(httpstep.posts); zbx_free(httpstep.cookies); zbx_free(httpstep.url); zbx_timespec(&ts); process_step_data(httpstep.httpstepid, &stat, &ts); if (NULL != err_str) { lastfailedstep = httpstep.no; break; } } clean: curl_easy_cleanup(easyhandle); #else err_str = zbx_strdup(err_str, "cURL library is required for Web monitoring support"); #endif /* HAVE_LIBCURL */ zbx_timespec(&ts); if (0 == lastfailedstep && NULL != err_str) { /* we are here either because cURL initialization failed */ /* or we have been compiled without cURL library */ lastfailedstep = 1; if (NULL != (row = DBfetch(result))) { ZBX_STR2UINT64(httpstep.httpstepid, row[0]); memset(&stat, 0, sizeof(stat)); process_step_data(httpstep.httpstepid, &stat, &ts); } else THIS_SHOULD_NEVER_HAPPEN; } DBfree_result(result); DBexecute("update httptest set nextcheck=%d+delay where httptestid=" ZBX_FS_UI64, ts.sec, httptest->httptestid); if (0 != speed_download_num) speed_download /= speed_download_num; process_test_data(httptest->httptestid, lastfailedstep, speed_download, err_str, &ts); zbx_free(err_str); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }