Exemple #1
0
/******************************************************************************
 *                                                                            *
 * Function: process_trap                                                     *
 *                                                                            *
 * Purpose: process a single trap                                             *
 *                                                                            *
 * Parameters: addr - [IN] address of the target interface(s)                 *
 *             begin - [IN] beginning of the trap message                     *
 *             end - [IN] end of the trap message                             *
 *                                                                            *
 * Author: Rudolfs Kreicbergs                                                 *
 *                                                                            *
 ******************************************************************************/
static void	process_trap(const char *addr, char *begin, char *end)
{
	zbx_timespec_t	ts;
	zbx_uint64_t	*interfaceids = NULL;
	int		count, i, ret = FAIL;
	char		*trap = NULL;

	zbx_timespec(&ts);
	trap = zbx_dsprintf(trap, "%s%s", begin, end);

	count = DCconfig_get_snmp_interfaceids_by_addr(addr, &interfaceids);

	for (i = 0; i < count; i++)
	{
		if (SUCCEED == process_trap_for_interface(interfaceids[i], trap, &ts))
			ret = SUCCEED;
	}

	if (FAIL == ret)
	{
		zbx_config_t	cfg;

		zbx_config_get(&cfg, ZBX_CONFIG_FLAGS_SNMPTRAP_LOGGING);

		if (ZBX_SNMPTRAP_LOGGING_ENABLED == cfg.snmptrap_logging)
			zabbix_log(LOG_LEVEL_WARNING, "unmatched trap received from \"%s\": %s", addr, trap);

		zbx_config_clean(&cfg);
	}

	zbx_free(interfaceids);
	zbx_free(trap);
}
Exemple #2
0
ZBX_THREAD_ENTRY(trapper_thread, args)
{
	double		sec = 0.0;
	zbx_socket_t	s;

	process_type = ((zbx_thread_args_t *)args)->process_type;
	server_num = ((zbx_thread_args_t *)args)->server_num;
	process_num = ((zbx_thread_args_t *)args)->process_num;

	zabbix_log(LOG_LEVEL_INFORMATION, "%s #%d started [%s #%d]", get_program_type_string(program_type),
			server_num, get_process_type_string(process_type), process_num);

	memcpy(&s, (zbx_socket_t *)((zbx_thread_args_t *)args)->args, sizeof(zbx_socket_t));

#if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
	zbx_tls_init_child();
	find_psk_in_cache = DCget_psk_by_identity;
#endif
	zbx_setproctitle("%s #%d [connecting to the database]", get_process_type_string(process_type), process_num);

	DBconnect(ZBX_DB_CONNECT_NORMAL);

	for (;;)
	{
		zbx_handle_log();

		zbx_setproctitle("%s #%d [processed data in " ZBX_FS_DBL " sec, waiting for connection]",
				get_process_type_string(process_type), process_num, sec);

		update_selfmon_counter(ZBX_PROCESS_STATE_IDLE);

		/* Trapper has to accept all types of connections it can accept with the specified configuration. */
		/* Only after receiving data it is known who has sent them and one can decide to accept or discard */
		/* the data. */
		if (SUCCEED == zbx_tcp_accept(&s, ZBX_TCP_SEC_TLS_CERT | ZBX_TCP_SEC_TLS_PSK | ZBX_TCP_SEC_UNENCRYPTED))
		{
			zbx_timespec_t	ts;

			/* get connection timestamp */
			zbx_timespec(&ts);

			update_selfmon_counter(ZBX_PROCESS_STATE_BUSY);

			zbx_setproctitle("%s #%d [processing data]", get_process_type_string(process_type),
					process_num);

			sec = zbx_time();
			process_trapper_child(&s, &ts);
			sec = zbx_time() - sec;

			zbx_tcp_unaccept(&s);
		}
		else if (EINTR != zbx_socket_last_error())
		{
			zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s",
					zbx_socket_strerror());
		}
	}
}
/******************************************************************************
 *                                                                            *
 * Function: get_pinger_hosts                                                 *
 *                                                                            *
 * Purpose: creates buffer which contains list of hosts to ping               *
 *                                                                            *
 * Parameters:                                                                *
 *                                                                            *
 * Return value: SUCCEED - the file was created successfully                  *
 *               FAIL - otherwise                                             *
 *                                                                            *
 * Author: Alexei Vladishev, Alexander Vladishev                              *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
static void	get_pinger_hosts(icmpitem_t **icmp_items, int *icmp_items_alloc, int *icmp_items_count)
{
	const char		*__function_name = "get_pinger_hosts";
	DC_ITEM			items[MAX_ITEMS];
	int			i, num, count, interval, size, timeout, rc;
	char			error[MAX_STRING_LEN], *addr = NULL;
	icmpping_t		icmpping;
	icmppingsec_type_t	type;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

	num = DCconfig_get_poller_items(ZBX_POLLER_TYPE_PINGER, items, MAX_ITEMS);

	for (i = 0; i < num; i++)
	{
		ZBX_STRDUP(items[i].key, items[i].key_orig);
		rc = substitute_key_macros(&items[i].key, &items[i].host, NULL, MACRO_TYPE_ITEM_KEY,
				error, sizeof(error));

		if (SUCCEED == rc)
		{
			items[i].interface.addr = (1 == items[i].interface.useip ?
					items[i].interface.ip_orig : items[i].interface.dns_orig);

			rc = parse_key_params(items[i].key, items[i].interface.addr, &icmpping, &addr, &count,
					&interval, &size, &timeout, &type, error, sizeof(error));
		}

		if (SUCCEED == rc)
		{
			add_icmpping_item(icmp_items, icmp_items_alloc, icmp_items_count, count, interval, size,
				timeout, items[i].itemid, addr, icmpping, type);
		}
		else
		{
			zbx_timespec_t	ts;

			zbx_timespec(&ts);

			dc_add_history(items[i].itemid, items[i].value_type, items[i].flags, NULL, &ts,
					ITEM_STATUS_NOTSUPPORTED, error, 0, NULL, 0, 0, 0, 0);

			DCrequeue_reachable_item(items[i].itemid, ITEM_STATUS_NOTSUPPORTED, ts.sec);
		}

		zbx_free(items[i].key);
	}

	DCconfig_clean_items(items, NULL, num);

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d", __function_name, *icmp_items_count);
}
Exemple #4
0
/******************************************************************************
 *                                                                            *
 * Function: history_sender                                                   *
 *                                                                            *
 * Purpose:                                                                   *
 *                                                                            *
 * Parameters:                                                                *
 *                                                                            *
 * Return value:                                                              *
 *                                                                            *
 * Author: Alexander Vladishev                                                *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
static void	history_sender(struct zbx_json *j, int *records, const char *tag,
		int (*f_get_data)(), void (*f_set_lastid)())
{
	const char	*__function_name = "history_sender";

	zbx_sock_t	sock;
	zbx_uint64_t	lastid;
	zbx_timespec_t	ts;
	int		ret = SUCCEED;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

	zbx_json_clean(j);
	zbx_json_addstring(j, ZBX_PROTO_TAG_REQUEST, tag, ZBX_JSON_TYPE_STRING);
	zbx_json_addstring(j, ZBX_PROTO_TAG_HOST, CONFIG_HOSTNAME, ZBX_JSON_TYPE_STRING);

	zbx_json_addarray(j, ZBX_PROTO_TAG_DATA);

	*records = f_get_data(j, &lastid);

	zbx_json_close(j);

	if (*records > 0)
	{
		char	*error = NULL;

		connect_to_server(&sock, 600, CONFIG_PROXYDATA_FREQUENCY); /* retry till have a connection */

		zbx_timespec(&ts);
		zbx_json_adduint64(j, ZBX_PROTO_TAG_CLOCK, ts.sec);
		zbx_json_adduint64(j, ZBX_PROTO_TAG_NS, ts.ns);

		if (SUCCEED != (ret = put_data_to_server(&sock, j, &error)))
		{
			*records = 0;
			zabbix_log(LOG_LEVEL_WARNING, "sending data to server failed: %s", error);
		}

		zbx_free(error);
		disconnect_server(&sock);
	}

	if (SUCCEED == ret && 0 != lastid)
	{
		DBbegin();
		f_set_lastid(lastid);
		DBcommit();
	}

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
}
Exemple #5
0
/******************************************************************************
 *                                                                            *
 * Function: procstat_get_cpu_util_snapshot_for_pids                          *
 *                                                                            *
 * Purpose: gets cpu utilization data snapshot for the monitored processes    *
 *                                                                            *
 * Parameters: stats - [OUT] current reading of the per-pid cpu usage         *
 *                               statistics (array, items correspond to pids) *
 *             pids  - [IN]  pids (unique) for which to collect data in this  *
 *                               iteration                                    *
 *                                                                            *
 * Return value: timestamp of the snapshot                                    *
 *                                                                            *
 ******************************************************************************/
static zbx_timespec_t	procstat_get_cpu_util_snapshot_for_pids(zbx_procstat_util_t *stats,
				zbx_vector_uint64_t *pids)
{
	zbx_timespec_t			snapshot_timestamp;
	int				i;

	for (i = 0; i < pids->values_num; i++)
		stats[i].pid = pids->values[i];

	zbx_proc_get_process_stats(stats, pids->values_num);

	zbx_timespec(&snapshot_timestamp);

	return snapshot_timestamp;
}
/******************************************************************************
 *                                                                            *
 * Function: process_pinger_hosts                                             *
 *                                                                            *
 * Purpose:                                                                   *
 *                                                                            *
 * Parameters:                                                                *
 *                                                                            *
 * Return value:                                                              *
 *                                                                            *
 * Author: Alexander Vladishev                                                *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
static void	process_pinger_hosts(icmpitem_t *items, int items_count)
{
	const char		*__function_name = "process_pinger_hosts";
	int			i, first_index = 0, ping_result;
	char			error[ITEM_ERROR_LEN_MAX];
	static ZBX_FPING_HOST	*hosts = NULL;
	static int		hosts_alloc = 4;
	int			hosts_count = 0;
	zbx_timespec_t		ts;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

	if (NULL == hosts)
		hosts = zbx_malloc(hosts, sizeof(ZBX_FPING_HOST) * hosts_alloc);

	for (i = 0; i < items_count; i++)
	{
		add_pinger_host(&hosts, &hosts_alloc, &hosts_count, items[i].addr);

		if (i == items_count - 1 || items[i].count != items[i + 1].count || items[i].interval != items[i + 1].interval ||
				items[i].size != items[i + 1].size || items[i].timeout != items[i + 1].timeout)
		{
			zbx_setproctitle("%s [pinging hosts]", get_process_type_string(process_type));

			zbx_timespec(&ts);

			ping_result = do_ping(hosts, hosts_count,
						items[i].count, items[i].interval, items[i].size, items[i].timeout,
						error, sizeof(error));

			process_values(items, first_index, i + 1, hosts, hosts_count, &ts, ping_result, error);

			hosts_count = 0;
			first_index = i + 1;
		}
	}

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
}
Exemple #7
0
/******************************************************************************
 *                                                                            *
 * Function: process_trap                                                     *
 *                                                                            *
 * Purpose: process a single trap                                             *
 *                                                                            *
 * Parameters: addr - [IN] address of the target interface(s)                 *
 *             begin - [IN] beginning of the trap message                     *
 *             end - [IN] end of the trap message                             *
 *                                                                            *
 * Author: Rudolfs Kreicbergs                                                 *
 *                                                                            *
 ******************************************************************************/
static void	process_trap(const char *addr, char *begin, char *end)
{
    zbx_timespec_t	ts;
    zbx_uint64_t	*interfaceids = NULL;
    int		count, i, ret = FAIL;
    char		*trap = NULL;

    zbx_timespec(&ts);
    trap = zbx_dsprintf(trap, "%s%s", begin, end);

    count = DCconfig_get_snmp_interfaceids_by_addr(addr, &interfaceids);

    for (i = 0; i < count; i++)
    {
        if (SUCCEED == process_trap_for_interface(interfaceids[i], trap, &ts))
            ret = SUCCEED;
    }

    if (FAIL == ret && 1 == *(unsigned char *)DCconfig_get_config_data(&i, CONFIG_SNMPTRAP_LOGGING))
        zabbix_log(LOG_LEVEL_WARNING, "unmatched trap received from \"%s\": %s", addr, trap);

    zbx_free(interfaceids);
    zbx_free(trap);
}
Exemple #8
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);
}
Exemple #9
0
static int	process_trap(zbx_sock_t	*sock, char *s, int max_len)
{
	char	*pl, *pr, *data, value_dec[MAX_BUFFER_LEN];
	char	lastlogsize[ZBX_MAX_UINT64_LEN], timestamp[11], source[HISTORY_LOG_SOURCE_LEN_MAX], severity[11];
	int	sender_nodeid, nodeid;
	char	*answer;

	int	ret = SUCCEED, res;
	size_t	datalen;

	struct 		zbx_json_parse jp;
	char		value[MAX_STRING_LEN];
	AGENT_VALUE	av;

	memset(&av, 0, sizeof(AGENT_VALUE));

	zbx_rtrim(s, " \r\n");

	datalen = strlen(s);
	zabbix_log(LOG_LEVEL_DEBUG, "Trapper got [%s] len " ZBX_FS_SIZE_T, s, (zbx_fs_size_t)datalen);

	if (0 == strncmp(s, "ZBX_GET_ACTIVE_CHECKS", 21))	/* request for list of active checks */
	{
		ret = send_list_of_active_checks(sock, s);
	}
	else if (strncmp(s, "ZBX_GET_HISTORY_LAST_ID", 23) == 0) /* request for last IDs */
	{
		send_history_last_id(sock, s);
		return ret;
	}
	else
	{
		if (0 == strncmp(s, "Data", 4))	/* node data exchange */
		{
			node_sync_lock(0);

			res = node_sync(s, &sender_nodeid, &nodeid);
			if (FAIL == res)
			{
				alarm(CONFIG_TIMEOUT);
				send_data_to_node(sender_nodeid, sock, "FAIL");
				alarm(0);
			}
			else
			{
				res = calculate_checksums(nodeid, NULL, 0);
				if (SUCCEED == res && NULL != (data = DMget_config_data(nodeid, ZBX_NODE_SLAVE)))
				{
					zabbix_log( LOG_LEVEL_WARNING, "NODE %d: Sending configuration changes"
							" to slave node %d for node %d datalen " ZBX_FS_SIZE_T,
							CONFIG_NODEID,
							sender_nodeid,
							nodeid,
							(zbx_fs_size_t)strlen(data));
					alarm(CONFIG_TRAPPER_TIMEOUT);
					res = send_data_to_node(sender_nodeid, sock, data);
					zbx_free(data);
					if (SUCCEED == res)
						res = recv_data_from_node(sender_nodeid, sock, &answer);
					if (SUCCEED == res && 0 == strcmp(answer, "OK"))
						res = update_checksums(nodeid, ZBX_NODE_SLAVE, SUCCEED, NULL, 0, NULL);
					alarm(0);
				}
			}

			node_sync_unlock(0);

			return ret;
		}
		else if (0 == strncmp(s, "History", 7))	/* slave node history */
		{
			const char	*reply;

			reply = (SUCCEED == node_history(s, datalen) ? "OK" : "FAIL");

			alarm(CONFIG_TIMEOUT);
			if (SUCCEED != zbx_tcp_send_raw(sock, reply))
				zabbix_log(LOG_LEVEL_WARNING, "Error sending %s to node", reply);
			alarm(0);

			return ret;
		}
		else if (SUCCEED == zbx_json_open(s, &jp))	/* JSON protocol */
		{
			if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_REQUEST, value, sizeof(value)))
			{
				if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_CONFIG))
				{
					if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER))
						send_proxyconfig(sock, &jp);
					else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE))
					{
						zabbix_log(LOG_LEVEL_WARNING, "Received configuration data from server."
								" Datalen " ZBX_FS_SIZE_T, (zbx_fs_size_t)datalen);
						recv_proxyconfig(sock, &jp);
					}
				}
				else if (0 == strcmp(value, ZBX_PROTO_VALUE_AGENT_DATA) ||
					0 == strcmp(value, ZBX_PROTO_VALUE_SENDER_DATA))
				{
					recv_agenthistory(sock, &jp);
				}
				else if (0 == strcmp(value, ZBX_PROTO_VALUE_HISTORY_DATA))
				{
					if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER))
						recv_proxyhistory(sock, &jp);
					else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE))
						send_proxyhistory(sock);
				}
				else if (0 == strcmp(value, ZBX_PROTO_VALUE_DISCOVERY_DATA))
				{
					if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER))
						recv_discovery_data(sock, &jp);
					else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE))
						send_discovery_data(sock);
				}
				else if (0 == strcmp(value, ZBX_PROTO_VALUE_AUTO_REGISTRATION_DATA))
				{
					if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER))
						recv_areg_data(sock, &jp);
					else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE))
						send_areg_data(sock);
				}
				else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_HEARTBEAT))
				{
					if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER))
						recv_proxy_heartbeat(sock, &jp);
				}
				else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_ACTIVE_CHECKS))
				{
					ret = send_list_of_active_checks_json(sock, &jp);
				}
				else if (0 == strcmp(value, ZBX_PROTO_VALUE_HOST_AVAILABILITY))
				{
					if (0 != (daemon_type & ZBX_DAEMON_TYPE_SERVER))
						recv_host_availability(sock, &jp);
					else if (0 != (daemon_type & ZBX_DAEMON_TYPE_PROXY_PASSIVE))
						send_host_availability(sock);
				}
				else if (0 == strcmp(value, ZBX_PROTO_VALUE_COMMAND))
				{
					ret = node_process_command(sock, s, &jp);
				}
				else
					zabbix_log(LOG_LEVEL_WARNING, "unknown request received [%s]", value);
			}
			return ret;
		}
		else if ('<' == *s)	/* XML protocol */
		{
			comms_parse_response(s, av.host_name, sizeof(av.host_name), av.key, sizeof(av.key), value_dec,
					sizeof(value_dec), lastlogsize, sizeof(lastlogsize), timestamp, sizeof(timestamp),
					source, sizeof(source),	severity, sizeof(severity));

			av.value	= value_dec;
			if (SUCCEED != is_uint64(lastlogsize, &av.lastlogsize))
				av.lastlogsize = 0;
			av.timestamp	= atoi(timestamp);
			av.source	= source;
			av.severity	= atoi(severity);
		}
		else
		{
			pl = s;
			if (NULL == (pr = strchr(pl, ':')))
				return FAIL;

			*pr = '\0';
			zbx_strlcpy(av.host_name, pl, sizeof(av.host_name));
			*pr = ':';

			pl = pr + 1;
			if (NULL == (pr = strchr(pl, ':')))
				return FAIL;

			*pr = '\0';
			zbx_strlcpy(av.key, pl, sizeof(av.key));
			*pr = ':';

			av.value	= pr + 1;
			av.severity	= 0;
		}

		zbx_timespec(&av.ts);

		if (0 == strcmp(av.value, ZBX_NOTSUPPORTED))
			av.status = ITEM_STATUS_NOTSUPPORTED;

		process_mass_data(sock, 0, &av, 1, NULL);

		alarm(CONFIG_TIMEOUT);
		if (SUCCEED != zbx_tcp_send_raw(sock, SUCCEED == ret ? "OK" : "NOT OK"))
			zabbix_log(LOG_LEVEL_WARNING, "Error sending result back");
		alarm(0);
	}
	return ret;
}
Exemple #10
0
/******************************************************************************
 *                                                                            *
 * Function: process_value                                                    *
 *                                                                            *
 * Purpose: Buffer new value or send the whole buffer to the server           *
 *                                                                            *
 * Parameters: server      - IP or Hostname of Zabbix server                  *
 *             port        - port of Zabbix server                            *
 *             host        - name of host in Zabbix database                  *
 *             key         - name of metric                                   *
 *             value       - key value                                        *
 *             lastlogsize - size of read logfile                             *
 *             mtime       - time of last file modification                   *
 *             timestamp   - timestamp of read value                          *
 *             source      - name of logged data source                       *
 *             severity    - severity of logged data sources                  *
 *             logeventid  - the application-specific identifier for          *
 *                           the event; used for monitoring of Windows        *
 *                           event logs                                       *
 *             persistent  - do not overwrite old values                      *
 *                                                                            *
 * Return value: returns SUCCEED on successful parsing,                       *
 *               FAIL on other cases                                          *
 *                                                                            *
 * Author: Alexei Vladishev                                                   *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
static int	process_value(
		const char	*server,
		unsigned short	port,
		const char	*host,
		const char	*key,
		const char	*value,
		zbx_uint64_t	*lastlogsize,
		int		*mtime,
		unsigned long	*timestamp,
		const char	*source,
		unsigned short	*severity,
		unsigned long	*logeventid,
		unsigned char	persistent
)
{
	const char			*__function_name = "process_value";
	ZBX_ACTIVE_BUFFER_ELEMENT	*el = NULL;
	int				i, ret = FAIL;
	size_t				sz;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() key:'%s:%s' value:'%s'", __function_name, host, key, value);

	send_buffer(server, port);

	if (0 != persistent && CONFIG_BUFFER_SIZE / 2 <= buffer.pcount)
	{
		zabbix_log(LOG_LEVEL_WARNING, "buffer is full, cannot store persistent value");
		goto out;
	}

	if (CONFIG_BUFFER_SIZE > buffer.count)
	{
		zabbix_log(LOG_LEVEL_DEBUG, "buffer: new element %d", buffer.count);
		el = &buffer.data[buffer.count];
		buffer.count++;
	}
	else
	{
		if (0 == persistent)
		{
			for (i = 0; i < buffer.count; i++)
			{
				el = &buffer.data[i];
				if (0 == strcmp(el->host, host) && 0 == strcmp(el->key, key))
					break;
			}
		}

		if (0 != persistent || i == buffer.count)
		{
			for (i = 0; i < buffer.count; i++)
			{
				el = &buffer.data[i];
				if (0 == el->persistent)
					break;
			}
		}

		zabbix_log(LOG_LEVEL_DEBUG, "remove element [%d] Key:'%s:%s'", i, el->host, el->key);

		zbx_free(el->host);
		zbx_free(el->key);
		zbx_free(el->value);
		zbx_free(el->source);

		sz = (CONFIG_BUFFER_SIZE - i - 1) * sizeof(ZBX_ACTIVE_BUFFER_ELEMENT);
		memmove(&buffer.data[i], &buffer.data[i + 1], sz);

		zabbix_log(LOG_LEVEL_DEBUG, "buffer full: new element %d", buffer.count - 1);

		el = &buffer.data[CONFIG_BUFFER_SIZE - 1];
	}

	memset(el, 0, sizeof(ZBX_ACTIVE_BUFFER_ELEMENT));
	el->host = zbx_strdup(NULL, host);
	el->key = zbx_strdup(NULL, key);
	el->value = (NULL == value) ? NULL : zbx_strdup(NULL, value);

	if (NULL != source)
		el->source = strdup(source);
	if (NULL != severity)
		el->severity = *severity;
	if (NULL != lastlogsize)
		el->lastlogsize = *lastlogsize;
	if (NULL != mtime) /* will be null for "eventlog" and "log" and the value will be 0, only "logrt" matters */
		el->mtime = *mtime;
	if (NULL != timestamp)
		el->timestamp = *timestamp;
	if (NULL != logeventid)
		el->logeventid = (int)*logeventid;

	zbx_timespec(&el->ts);
	el->persistent	= persistent;

	if (0 != persistent)
		buffer.pcount++;

	ret = SUCCEED;
out:
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

	return ret;
}
Exemple #11
0
/******************************************************************************
 *                                                                            *
 * Function: send_buffer                                                      *
 *                                                                            *
 * Purpose: Send value stored in the buffer to Zabbix server                  *
 *                                                                            *
 * Parameters: host - IP or Hostname of Zabbix server                         *
 *             port - port number                                             *
 *                                                                            *
 * Return value: returns SUCCEED on successful parsing,                       *
 *               FAIL on other cases                                          *
 *                                                                            *
 * Author: Alexei Vladishev                                                   *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
static int	send_buffer(const char *host, unsigned short port)
{
	const char			*__function_name = "send_buffer";
	struct zbx_json 		json;
	ZBX_ACTIVE_BUFFER_ELEMENT	*el;
	zbx_sock_t			s;
	char				*buf = NULL;
	int				ret = SUCCEED, i, now;
	zbx_timespec_t			ts;
	const char			*err_send_step = "";

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() host:'%s' port:%d values:%d/%d",
			__function_name, host, port, buffer.count, CONFIG_BUFFER_SIZE);

	if (0 == buffer.count)
		goto ret;

	now = (int)time(NULL);

	if (CONFIG_BUFFER_SIZE / 2 > buffer.pcount && CONFIG_BUFFER_SIZE > buffer.count &&
			CONFIG_BUFFER_SEND > now - buffer.lastsent)
	{
		zabbix_log(LOG_LEVEL_DEBUG, "Will not send now. Now %d lastsent %d < %d",
				now, buffer.lastsent, CONFIG_BUFFER_SEND);
		goto ret;
	}

	zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);
	zbx_json_addstring(&json, ZBX_PROTO_TAG_REQUEST, ZBX_PROTO_VALUE_AGENT_DATA, ZBX_JSON_TYPE_STRING);
	zbx_json_addarray(&json, ZBX_PROTO_TAG_DATA);

	for (i = 0; i < buffer.count; i++)
	{
		el = &buffer.data[i];

		zbx_json_addobject(&json, NULL);
		zbx_json_addstring(&json, ZBX_PROTO_TAG_HOST, el->host, ZBX_JSON_TYPE_STRING);
		zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY, el->key, ZBX_JSON_TYPE_STRING);
		zbx_json_addstring(&json, ZBX_PROTO_TAG_VALUE, el->value, ZBX_JSON_TYPE_STRING);
		if (0 != el->lastlogsize)
			zbx_json_adduint64(&json, ZBX_PROTO_TAG_LOGLASTSIZE, el->lastlogsize);
		if (el->mtime)
			zbx_json_adduint64(&json, ZBX_PROTO_TAG_MTIME, el->mtime);
		if (el->timestamp)
			zbx_json_adduint64(&json, ZBX_PROTO_TAG_LOGTIMESTAMP, el->timestamp);
		if (el->source)
			zbx_json_addstring(&json, ZBX_PROTO_TAG_LOGSOURCE, el->source, ZBX_JSON_TYPE_STRING);
		if (el->severity)
			zbx_json_adduint64(&json, ZBX_PROTO_TAG_LOGSEVERITY, el->severity);
		if (el->logeventid)
			zbx_json_adduint64(&json, ZBX_PROTO_TAG_LOGEVENTID, el->logeventid);
		zbx_json_adduint64(&json, ZBX_PROTO_TAG_CLOCK, el->ts.sec);
		zbx_json_adduint64(&json, ZBX_PROTO_TAG_NS, el->ts.ns);
		zbx_json_close(&json);
	}

	zbx_json_close(&json);

	zbx_timespec(&ts);
	zbx_json_adduint64(&json, ZBX_PROTO_TAG_CLOCK, ts.sec);
	zbx_json_adduint64(&json, ZBX_PROTO_TAG_NS, ts.ns);

	if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port,
					MIN(buffer.count * CONFIG_TIMEOUT, 60))))
	{
		zabbix_log(LOG_LEVEL_DEBUG, "JSON before sending [%s]", json.buffer);

		if (SUCCEED == (ret = zbx_tcp_send(&s, json.buffer)))
		{
			if (SUCCEED == zbx_tcp_recv(&s, &buf))
			{
				zabbix_log(LOG_LEVEL_DEBUG, "JSON back [%s]", buf);

				if (NULL == buf || SUCCEED != check_response(buf))
					zabbix_log(LOG_LEVEL_DEBUG, "NOT OK");
				else
					zabbix_log(LOG_LEVEL_DEBUG, "OK");
			}
			else
				err_send_step = "[recv] ";
		}
		else
			err_send_step = "[send] ";

		zbx_tcp_close(&s);
	}
	else
		err_send_step = "[connect] ";

	zbx_json_free(&json);

	if (SUCCEED == ret)
	{
		/* free buffer */
		for (i = 0; i < buffer.count; i++)
		{
			el = &buffer.data[i];

			zbx_free(el->host);
			zbx_free(el->key);
			zbx_free(el->value);
			zbx_free(el->source);
		}
		buffer.count = 0;
		buffer.pcount = 0;
		buffer.lastsent = now;
		if (0 != buffer.first_error)
		{
			zabbix_log(LOG_LEVEL_WARNING, "active check data upload to [%s:%hu] is working again",
					host, port);
			buffer.first_error = 0;
		}
	}
	else
	{
		if (0 == buffer.first_error)
		{
			zabbix_log(LOG_LEVEL_WARNING, "active check data upload to [%s:%hu] started to fail (%s%s)",
					host, port, err_send_step, zbx_tcp_strerror());
			buffer.first_error = now;
		}
		zabbix_log(LOG_LEVEL_DEBUG, "send value error: %s %s", err_send_step, zbx_tcp_strerror());
	}
ret:
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

	return ret;
}
Exemple #12
0
static int	process_trap(zbx_socket_t *sock, char *s, zbx_timespec_t *ts)
{
	int	ret = SUCCEED;

	zbx_rtrim(s, " \r\n");

	zabbix_log(LOG_LEVEL_DEBUG, "trapper got '%s'", s);

	if ('{' == *s)	/* JSON protocol */
	{
		struct zbx_json_parse	jp;
		char			value[MAX_STRING_LEN];

		if (SUCCEED != zbx_json_open(s, &jp))
		{
			zbx_send_response(sock, FAIL, zbx_json_strerror(), CONFIG_TIMEOUT);
			zabbix_log(LOG_LEVEL_WARNING, "received invalid JSON object from %s: %s",
					sock->peer, zbx_json_strerror());
			return FAIL;
		}

		if (SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_REQUEST, value, sizeof(value)))
		{
			if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_CONFIG))
			{
				if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
				{
					send_proxyconfig(sock, &jp);
				}
				else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
				{
					zabbix_log(LOG_LEVEL_WARNING, "received configuration data from server"
							" at \"%s\", datalen " ZBX_FS_SIZE_T,
							sock->peer, (zbx_fs_size_t)(jp.end - jp.start + 1));
					recv_proxyconfig(sock, &jp);
				}
				else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_ACTIVE))
				{
					/* This is a misconfiguration: the proxy is configured in active mode */
					/* but server sends requests to it as to a proxy in passive mode. To  */
					/* prevent logging of this problem for every request we report it     */
					/* only when the server sends configuration to the proxy and ignore   */
					/* it for other requests.                                             */
					active_passive_misconfig(sock);
				}
			}
			else if (0 == strcmp(value, ZBX_PROTO_VALUE_AGENT_DATA) ||
					0 == strcmp(value, ZBX_PROTO_VALUE_SENDER_DATA))
			{
				recv_agenthistory(sock, &jp, ts);
			}
			else if (0 == strcmp(value, ZBX_PROTO_VALUE_HISTORY_DATA))
			{
				if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
					recv_proxyhistory(sock, &jp, ts);
				else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
					send_proxyhistory(sock, ts);
			}
			else if (0 == strcmp(value, ZBX_PROTO_VALUE_DISCOVERY_DATA))
			{
				if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
					recv_discovery_data(sock, &jp);
				else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
					send_discovery_data(sock);
			}
			else if (0 == strcmp(value, ZBX_PROTO_VALUE_AUTO_REGISTRATION_DATA))
			{
				if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
					recv_areg_data(sock, &jp);
				else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
					send_areg_data(sock);
			}
			else if (0 == strcmp(value, ZBX_PROTO_VALUE_PROXY_HEARTBEAT))
			{
				if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
					recv_proxy_heartbeat(sock, &jp);
			}
			else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_ACTIVE_CHECKS))
			{
				ret = send_list_of_active_checks_json(sock, &jp);
			}
			else if (0 == strcmp(value, ZBX_PROTO_VALUE_HOST_AVAILABILITY))
			{
				if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
					recv_host_availability(sock, &jp);
				else if (0 != (program_type & ZBX_PROGRAM_TYPE_PROXY_PASSIVE))
					send_host_availability(sock);
			}
			else if (0 == strcmp(value, ZBX_PROTO_VALUE_COMMAND))
			{
				ret = node_process_command(sock, s, &jp);
			}
			else if (0 == strcmp(value, ZBX_PROTO_VALUE_GET_QUEUE))
			{
				if (0 != (program_type & ZBX_PROGRAM_TYPE_SERVER))
					ret = recv_getqueue(sock, &jp);
			}
			else
				zabbix_log(LOG_LEVEL_WARNING, "unknown request received [%s]", value);
		}
	}
	else if (0 == strncmp(s, "ZBX_GET_ACTIVE_CHECKS", 21))	/* request for list of active checks */
	{
		ret = send_list_of_active_checks(sock, s);
	}
	else
	{
		char		value_dec[MAX_BUFFER_LEN], lastlogsize[ZBX_MAX_UINT64_LEN], timestamp[11],
				source[HISTORY_LOG_SOURCE_LEN_MAX], severity[11];
		AGENT_VALUE	av;

		memset(&av, 0, sizeof(AGENT_VALUE));

		if ('<' == *s)	/* XML protocol */
		{
			comms_parse_response(s, av.host_name, sizeof(av.host_name), av.key, sizeof(av.key), value_dec,
					sizeof(value_dec), lastlogsize, sizeof(lastlogsize), timestamp,
					sizeof(timestamp), source, sizeof(source), severity, sizeof(severity));

			av.value = value_dec;
			if (SUCCEED != is_uint64(lastlogsize, &av.lastlogsize))
				av.lastlogsize = 0;
			av.timestamp = atoi(timestamp);
			av.source = source;
			av.severity = atoi(severity);
		}
		else
		{
			char	*pl, *pr;

			pl = s;
			if (NULL == (pr = strchr(pl, ':')))
				return FAIL;

			*pr = '\0';
			zbx_strlcpy(av.host_name, pl, sizeof(av.host_name));
			*pr = ':';

			pl = pr + 1;
			if (NULL == (pr = strchr(pl, ':')))
				return FAIL;

			*pr = '\0';
			zbx_strlcpy(av.key, pl, sizeof(av.key));
			*pr = ':';

			av.value = pr + 1;
			av.severity = 0;
		}

		zbx_timespec(&av.ts);

		if (0 == strcmp(av.value, ZBX_NOTSUPPORTED))
			av.state = ITEM_STATE_NOTSUPPORTED;

		process_mass_data(sock, 0, &av, 1, NULL);

		zbx_alarm_on(CONFIG_TIMEOUT);
		if (SUCCEED != zbx_tcp_send_raw(sock, "OK"))
			zabbix_log(LOG_LEVEL_WARNING, "Error sending result back");
		zbx_alarm_off();
	}

	return ret;
}
Exemple #13
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);
}