Example #1
0
/******************************************************************************
 *                                                                            *
 * 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);
}
Example #2
0
/******************************************************************************
 *                                                                            *
 * 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;
}
Example #3
0
/******************************************************************************
 *                                                                            *
 * 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);
}
Example #4
0
/******************************************************************************
 *                                                                            *
 * 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);
}