Exemple #1
0
/******************************************************************************
 *                                                                            *
 * Function: parse_command_dyn                                                *
 *                                                                            *
 * Purpose: parses item key and splits it into command and parameters         *
 *                                                                            *
 * Return value: ZBX_COMMAND_ERROR - error                                    *
 *               ZBX_COMMAND_WITHOUT_PARAMS - command without parameters      *
 *               ZBX_COMMAND_WITH_PARAMS - command with parameters            *
 *                                                                            *
 ******************************************************************************/
static int	parse_command_dyn(const char *command, char **cmd, char **param)
{
	const char	*pl, *pr;
	size_t		cmd_alloc = 0, param_alloc = 0,
			cmd_offset = 0, param_offset = 0;

	for (pl = command; SUCCEED == is_key_char(*pl); pl++)
		;

	if (pl == command)
		return ZBX_COMMAND_ERROR;

	zbx_strncpy_alloc(cmd, &cmd_alloc, &cmd_offset, command, pl - command);

	if ('\0' == *pl)	/* no parameters specified */
	{
		zbx_strncpy_alloc(param, &param_alloc, &param_offset, "", 0);
		return ZBX_COMMAND_WITHOUT_PARAMS;
	}

	if ('[' != *pl)		/* unsupported character */
		return ZBX_COMMAND_ERROR;

	for (pr = ++pl; '\0' != *pr; pr++)
		;

	if (']' != *--pr)
		return ZBX_COMMAND_ERROR;

	zbx_strncpy_alloc(param, &param_alloc, &param_offset, pl, pr - pl);

	return ZBX_COMMAND_WITH_PARAMS;
}
Exemple #2
0
static void	process_listener(zbx_socket_t *s)
{
	AGENT_RESULT	result;
	char		**value = NULL;
	int		ret;

	if (SUCCEED == (ret = zbx_tcp_recv_to(s, CONFIG_TIMEOUT)))
	{
		zbx_rtrim(s->buffer, "\r\n");

		zabbix_log(LOG_LEVEL_DEBUG, "Requested [%s]", s->buffer);

		init_result(&result);

		if (SUCCEED == process(s->buffer, PROCESS_WITH_ALIAS, &result))
		{
			if (NULL != (value = GET_TEXT_RESULT(&result)))
			{
				zabbix_log(LOG_LEVEL_DEBUG, "Sending back [%s]", *value);
				ret = zbx_tcp_send_to(s, *value, CONFIG_TIMEOUT);
			}
		}
		else
		{
			value = GET_MSG_RESULT(&result);

			if (NULL != value)
			{
				static char	*buffer = NULL;
				static size_t	buffer_alloc = 256;
				size_t		buffer_offset = 0;

				zabbix_log(LOG_LEVEL_DEBUG, "Sending back [" ZBX_NOTSUPPORTED ": %s]", *value);

				if (NULL == buffer)
					buffer = (char *)zbx_malloc(buffer, buffer_alloc);

				zbx_strncpy_alloc(&buffer, &buffer_alloc, &buffer_offset,
						ZBX_NOTSUPPORTED, ZBX_CONST_STRLEN(ZBX_NOTSUPPORTED));
				buffer_offset++;
				zbx_strcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, *value);

				ret = zbx_tcp_send_bytes_to(s, buffer, buffer_offset, CONFIG_TIMEOUT);
			}
			else
			{
				zabbix_log(LOG_LEVEL_DEBUG, "Sending back [" ZBX_NOTSUPPORTED "]");

				ret = zbx_tcp_send_to(s, ZBX_NOTSUPPORTED, CONFIG_TIMEOUT);
			}
		}

		free_result(&result);
	}

	if (FAIL == ret)
		zabbix_log(LOG_LEVEL_DEBUG, "Process listener error: %s", zbx_socket_strerror());
}
static int web_curl_set_url(struct web *opt)
{
	const char *__function_name = "web_curl_set_url";

	char *url = NULL;
	char *curl_err_str = NULL;
	int curl_err;
	size_t alloc;
	size_t offset;

	if (opt->is_https)
		url = zbx_strdup(url, "https://");
	else
		url = zbx_strdup(url, "http://");

	offset = strlen(url);
	alloc = sizeof(char) * offset + 1;

	if (opt->is_ip_hostname) {
		zbx_strncpy_alloc(&url, &alloc, &offset, opt->host, strlen(opt->host));
	} else {
		if (opt->is_ipv6) {
			zbx_strncpy_alloc(&url, &alloc, &offset, "[", 1);
			zbx_strncpy_alloc(&url, &alloc, &offset, opt->ip, strlen(opt->ip));
			zbx_strncpy_alloc(&url, &alloc, &offset, "]", 1);
		} else {
			zbx_strncpy_alloc(&url, &alloc, &offset, opt->ip, strlen(opt->ip));
		}
	}

	zbx_strncpy_alloc(&url, &alloc, &offset, ":", 1);
	zbx_strncpy_alloc(&url, &alloc, &offset, opt->port, strlen(opt->port));

	if (*opt->uri != '/')
		zbx_strncpy_alloc(&url, &alloc, &offset, "/", 1);

	zbx_strncpy_alloc(&url, &alloc, &offset, opt->uri, strlen(opt->uri));

	if ((curl_err = curl_easy_setopt(opt->curl->handler, CURLOPT_URL, url))) {
		curl_err_str = zbx_strdup(curl_err_str, curl_easy_strerror(curl_err));
		zabbix_log(LOG_LEVEL_ERR, "%s(): Could not set cURL option [%d]: %s for key %s",
					  __function_name, CURLOPT_URL, curl_err_str, opt->item->key);
		zbx_free(curl_err_str);
		zbx_free(url);
		return FAIL;
        }

	zbx_free(url);
	return SUCCEED;
}
static int web_curl_set_header(struct web *opt)
{
	const char *__function_name = "web_curl_set_header";

	char *host = NULL;
	char *curl_err_str = NULL;
	int curl_err;
	int i;
	size_t offset;
	size_t alloc;

	if (opt->host) {
		host = zbx_strdup(host, "Host: ");
		offset = strlen(host);
		alloc = sizeof(char) * offset + 1;

		zbx_strncpy_alloc(&host, &alloc, &offset, opt->host, strlen(opt->host));

		if (!(opt->curl->header_lst = curl_slist_append(opt->curl->header_lst, host))) {
				zabbix_log(LOG_LEVEL_ERR, "%s(): Could not append to curl header list for key %s",
							  __function_name, opt->item->key);
				goto failed;
		}
	}

	for (i = 0; i < opt->header_count; i++) {
		if (!(opt->curl->header_lst = curl_slist_append(opt->curl->header_lst, opt->header[i]))) {
			zabbix_log(LOG_LEVEL_ERR, "%s(): Could not append to curl header list for key %s",
						  __function_name, opt->item->key);
			goto failed;
		}
	}


	if (opt->curl->header_lst) {
		if ((curl_err = curl_easy_setopt(opt->curl->handler, CURLOPT_HTTPHEADER, opt->curl->header_lst))) {
			curl_err_str = zbx_strdup(curl_err_str, curl_easy_strerror(curl_err));
			zabbix_log(LOG_LEVEL_ERR, "%s(): Could not set cURL option [%d]: %s for key %s",
						  __function_name, CURLOPT_HTTPHEADER, curl_err_str, opt->item->key);
			goto failed;
		}
	}

	zbx_free(host);
	return SUCCEED;
failed:
	zbx_free(host);
	zbx_free(curl_err_str);
	return FAIL;
}
static size_t web_curl_write(void *contents, size_t size, size_t nmemb, void *userp)
{
	struct web_storage *page = (struct web_storage *)userp;
	size_t read_size = size * nmemb;

	if (!page->buff) {
		page->alloc = MAX(8096, read_size);
		page->offset = 0;
		page->buff = zbx_calloc(page->buff, 1, page->alloc);
	}

	zbx_strncpy_alloc(&page->buff, &page->alloc, &page->offset, contents, read_size);

	return read_size;
}
Exemple #6
0
static size_t	WRITEFUNCTION2(void *ptr, size_t size, size_t nmemb, void *userdata)
{
    size_t	r_size = size * nmemb;

    /* first piece of data */
    if (NULL == page.data)
    {
        page.allocated = MAX(8096, r_size);
        page.offset = 0;
        page.data = zbx_malloc(page.data, page.allocated);
    }

    zbx_strncpy_alloc(&page.data, &page.allocated, &page.offset, ptr, r_size);

    return r_size;
}
Exemple #7
0
static int	replace_param(const char *cmd, AGENT_REQUEST *request, char **out, char *error, int max_error_len)
{
	const char	*pl = cmd, *pr, *tmp;
	size_t		out_alloc = 0, out_offset = 0;
	int		num, ret = SUCCEED;

	while (NULL != (pr = strchr(pl, '$')))
	{
		zbx_strncpy_alloc(out, &out_alloc, &out_offset, pl, pr - pl);

		pr++;

		if ('0' == *pr)
		{
			zbx_strcpy_alloc(out, &out_alloc, &out_offset, cmd);
		}
		else if ('1' <= *pr && *pr <= '9')
		{
			num = (int)(*pr - '0');

			if (request->nparam >= num)
			{
				tmp = get_rparam(request, num - 1);

				if (SUCCEED != (ret = zbx_check_user_parameter(tmp, error, max_error_len)))
					break;

				zbx_strcpy_alloc(out, &out_alloc, &out_offset, tmp);
			}
		}
		else
		{
			if ('$' != *pr)
				zbx_chrcpy_alloc(out, &out_alloc, &out_offset, '$');
			zbx_chrcpy_alloc(out, &out_alloc, &out_offset, *pr);
		}

		pl = pr + 1;
	}

	if (SUCCEED == ret)
		zbx_strcpy_alloc(out, &out_alloc, &out_offset, pl);

	return ret;
}
static int	http_get_macro_value(const char *macros, const char *macro, char **replace_to, size_t *replace_to_alloc)
{
	size_t		sz_macro, replace_to_offset = 0;
	const char	*pm, *pv, *p;
	int		res = FAIL;

	sz_macro = strlen(macro);

	for (pm = macros; NULL != (pm = strstr(pm, macro)); pm += sz_macro)
	{
		if (pm != macros && '\r' != *(pm - 1) && '\n' != *(pm - 1))
			continue;

		pv = pm + sz_macro;

		/* skip white spaces */
		while (' ' == *pv || '\t' == *pv)
			pv++;

		if ('=' != *pv++)
			continue;

		/* skip white spaces */
		while (' ' == *pv || '\t' == *pv)
			pv++;

		for (p = pv; '\0' != *p && '\r' != *p && '\n' != *p; p++)
			;

		/* trim white spaces */
		while (p > pv && (' ' == *(p - 1) || '\t' == *(p - 1)))
			p--;

		zbx_strncpy_alloc(replace_to, replace_to_alloc, &replace_to_offset, pv, p - pv);

		res = SUCCEED;
		break;
	}

	return res;
}
Exemple #9
0
/******************************************************************************
 *                                                                            *
 * Function: zbx_tcp_recv_ext                                                 *
 *                                                                            *
 * Purpose: receive data                                                      *
 *                                                                            *
 * Return value: number of bytes received - success,                          *
 *               FAIL - an error occurred                                     *
 *                                                                            *
 * Author: Eugene Grigorjev                                                   *
 *                                                                            *
 ******************************************************************************/
ssize_t	zbx_tcp_recv_ext(zbx_sock_t *s, char **data, unsigned char flags, int timeout)
{
#define ZBX_BUF_LEN	(ZBX_STAT_BUF_LEN * 8)
	ssize_t		nbytes, left, total_bytes;
	size_t		allocated, offset, read_bytes;
	zbx_uint64_t	expected_len;

	ZBX_TCP_START();

	if (0 != timeout)
		zbx_tcp_timeout_set(s, timeout);

	zbx_free(s->buf_dyn);

	total_bytes = 0;
	read_bytes = 0;
	s->buf_type = ZBX_BUF_TYPE_STAT;

	*data = s->buf_stat;

	left = ZBX_TCP_HEADER_LEN;

	if (ZBX_TCP_ERROR == (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat, left)))
		goto out;

	if (ZBX_TCP_HEADER_LEN == nbytes && 0 == strncmp(s->buf_stat, ZBX_TCP_HEADER, ZBX_TCP_HEADER_LEN))
	{
		total_bytes += nbytes;

		left = sizeof(zbx_uint64_t);
		if (left != (nbytes = ZBX_TCP_READ(s->socket, (void *)&expected_len, left)))
		{
			total_bytes = FAIL;
			goto out;
		}

		expected_len = zbx_letoh_uint64(expected_len);

		if (ZBX_MAX_RECV_DATA_SIZE < expected_len)
		{
			zabbix_log(LOG_LEVEL_WARNING, "Message size " ZBX_FS_UI64 " from %s"
					" exceeds the maximum size " ZBX_FS_UI64 " bytes. Message ignored.",
					expected_len, get_ip_by_socket(s), (zbx_uint64_t)ZBX_MAX_RECV_DATA_SIZE);
			total_bytes = FAIL;
			goto cleanup;
		}

		flags |= ZBX_TCP_READ_UNTIL_CLOSE;
	}
	else
	{
		read_bytes = nbytes;
		expected_len = 16 * ZBX_MEBIBYTE;
	}

	s->buf_stat[read_bytes] = '\0';

	if (0 != (flags & ZBX_TCP_READ_UNTIL_CLOSE))
	{
		if (0 == nbytes)
			goto cleanup;
	}
	else
	{
		if (nbytes < left)
			goto cleanup;
	}

	left = sizeof(s->buf_stat) - read_bytes - 1;

	/* check for an empty socket if exactly ZBX_TCP_HEADER_LEN bytes (without a header) were sent */
	if (0 == read_bytes || '\n' != s->buf_stat[read_bytes - 1])	/* requests to passive agents end with '\n' */
	{
		/* fill static buffer */
		while (read_bytes < expected_len && 0 < left &&
				ZBX_TCP_ERROR != (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat + read_bytes, left)))
		{
			read_bytes += nbytes;

			if (0 != (flags & ZBX_TCP_READ_UNTIL_CLOSE))
			{
				if (0 == nbytes)
					break;
			}
			else
			{
				if (nbytes < left)	/* should we stop reading? */
				{
					/* XML protocol? */
					if (0 == strncmp(s->buf_stat, "<req>", sizeof("<req>") - 1))
					{
						/* closing tag received in the last 10 bytes? */
						s->buf_stat[read_bytes] = '\0';
						if (NULL != strstr(s->buf_stat + read_bytes -
								(10 > read_bytes ? read_bytes : 10), "</req>"))
							break;
					}
					else
						break;
				}
			}

			left -= nbytes;
		}
	}

	s->buf_stat[read_bytes] = '\0';

	if (sizeof(s->buf_stat) - 1 == read_bytes)	/* static buffer is full */
	{
		allocated = ZBX_BUF_LEN;
		s->buf_type = ZBX_BUF_TYPE_DYN;
		s->buf_dyn = zbx_malloc(s->buf_dyn, allocated);

		memcpy(s->buf_dyn, s->buf_stat, sizeof(s->buf_stat));

		offset = read_bytes;

		/* fill dynamic buffer */
		while (read_bytes < expected_len &&
				ZBX_TCP_ERROR != (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat, sizeof(s->buf_stat))))
		{
			zbx_strncpy_alloc(&s->buf_dyn, &allocated, &offset, s->buf_stat, nbytes);
			read_bytes += nbytes;

			if (0 != (flags & ZBX_TCP_READ_UNTIL_CLOSE))
			{
				if (0 == nbytes)
					break;
			}
			else
			{
				if ((size_t)nbytes < sizeof(s->buf_stat) - 1)	/* should we stop reading? */
				{
					/* XML protocol? */
					if (0 == strncmp(s->buf_dyn, "<req>", sizeof("<req>") - 1))
					{
						/* closing tag received in the last 10 bytes? */
						if (NULL != strstr(s->buf_dyn + read_bytes - 10, "</req>"))
							break;
					}
					else
						break;
				}
			}
		}

		*data = s->buf_dyn;
	}
out:
	if (ZBX_TCP_ERROR == nbytes)
	{
		zbx_set_tcp_strerror("ZBX_TCP_READ() failed: %s", strerror_from_system(zbx_sock_last_error()));
		total_bytes = FAIL;
	}
cleanup:
	if (0 != timeout)
		zbx_tcp_timeout_cleanup(s);

	if (FAIL != total_bytes)
		total_bytes += read_bytes;

	return total_bytes;
}
Exemple #10
0
static void	print_backtrace(CONTEXT *pctx)
{
	SymGetLineFromAddrW64_func_t	zbx_SymGetLineFromAddrW64 = NULL;
	SymFromAddr_func_t		zbx_SymFromAddr	= NULL;

	CONTEXT			ctx, ctxcount;
	STACKFRAME64		s, scount;
	PSYMBOL_INFO		pSym = NULL;
	HMODULE			hModule;
	HANDLE			hProcess, hThread;
	DWORD64			offset;
	wchar_t			szProcessName[MAX_PATH];
	char			*process_name = NULL, *process_path = NULL, *frame = NULL;
	size_t			frame_alloc = 0, frame_offset;
	int			nframes = 0;

	ctx = *pctx;

	zabbix_log(LOG_LEVEL_CRIT, "=== Backtrace: ===");

	memset(&s, 0, sizeof(s));

	s.AddrPC.Mode = AddrModeFlat;
	s.AddrFrame.Mode = AddrModeFlat;
	s.AddrStack.Mode = AddrModeFlat;

#ifdef _M_X64
	s.AddrPC.Offset = ctx.Rip;
	s.AddrFrame.Offset = ctx.Rbp;
	s.AddrStack.Offset = ctx.Rsp;
#else
	s.AddrPC.Offset = ctx.Eip;
	s.AddrFrame.Offset = ctx.Ebp;
	s.AddrStack.Offset = ctx.Esp;
#endif
	hProcess = GetCurrentProcess();
	hThread = GetCurrentThread();

	if (0 != GetModuleFileNameEx(hProcess, NULL, szProcessName, ARRSIZE(szProcessName)))
	{
		char	*ptr;
		int	path_alloc = 0, path_offset = 0;

		process_name = zbx_unicode_to_utf8(szProcessName);

		if (NULL != (ptr = strstr(process_name, progname)))
			zbx_strncpy_alloc(&process_path, &path_alloc, &path_offset, process_name, ptr - process_name);
	}

	if (NULL != (hModule = GetModuleHandle(TEXT("DbgHelp.DLL"))))
	{
		zbx_SymGetLineFromAddrW64 = (SymGetLineFromAddrW64_func_t)GetProcAddress(hModule,
				"SymGetLineFromAddr64");
		zbx_SymFromAddr = (SymFromAddr_func_t)GetProcAddress(hModule, "SymFromAddr");
	}

	if (NULL != zbx_SymFromAddr || NULL != zbx_SymGetLineFromAddrW64)
	{
		SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES);

		if (FALSE != SymInitialize(hProcess, process_path, TRUE))
		{
			pSym = (PSYMBOL_INFO) zbx_malloc(NULL, sizeof(SYMBOL_INFO) + MAX_SYM_NAME);
			memset(pSym, 0, sizeof(SYMBOL_INFO) + MAX_SYM_NAME);
			pSym->SizeOfStruct = sizeof(SYMBOL_INFO);
			pSym->MaxNameLen = MAX_SYM_NAME;
		}
	}

	scount = s;
	ctxcount = ctx;

	/* get number of frames, ctxcount may be modified during StackWalk64() calls */
	while (TRUE == StackWalk64(ZBX_IMAGE_FILE_MACHINE, hProcess, hThread, &scount, &ctxcount, NULL, NULL, NULL,
			NULL))
	{
		if (0 == scount.AddrReturn.Offset)
			break;
		nframes++;
	}

	while (TRUE == StackWalk64(ZBX_IMAGE_FILE_MACHINE, hProcess, hThread, &s, &ctx, NULL, NULL, NULL, NULL))
	{
		frame_offset = 0;
		zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, "%d: %s", nframes--,
				NULL == process_name ? "(unknown)" : process_name);

		if (NULL != pSym)
		{
			DWORD		dwDisplacement;
			IMAGEHLP_LINE64	line = {sizeof(IMAGEHLP_LINE64)};

			zbx_chrcpy_alloc(&frame, &frame_alloc, &frame_offset, '(');
			if (NULL != zbx_SymFromAddr &&
					TRUE == zbx_SymFromAddr(hProcess, s.AddrPC.Offset, &offset, pSym))
			{
				zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, "%s+0x%lx", pSym->Name, offset);
			}

			if (NULL != zbx_SymGetLineFromAddrW64 && TRUE == zbx_SymGetLineFromAddrW64(hProcess,
					s.AddrPC.Offset, &dwDisplacement, &line))
			{
				zbx_snprintf_alloc(&frame, &frame_alloc, &frame_offset, " %s:%d", line.FileName,
						line.LineNumber);
			}
			zbx_chrcpy_alloc(&frame, &frame_alloc, &frame_offset, ')');
		}

		zabbix_log(LOG_LEVEL_CRIT, "%s [0x%lx]", frame, s.AddrPC.Offset);

		if (0 == s.AddrReturn.Offset)
			break;
	}

	SymCleanup(hProcess);

	zbx_free(frame);
	zbx_free(process_path);
	zbx_free(process_name);
	zbx_free(pSym);
}
static int	calcitem_parse_expression(DC_ITEM *dc_item, expression_t *exp, char *error, int max_error_len)
{
	const char	*__function_name = "calcitem_parse_expression";
	char		*e, *f, *func = NULL, *params = NULL;
	size_t		exp_alloc = 128, exp_offset = 0, len;
	int		functionid, ret;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() expression:'%s'", __function_name, dc_item->params);

	assert(dc_item);
	assert(exp);

	exp->exp = zbx_malloc(exp->exp, exp_alloc);

	for (e = dc_item->params; '\0' != *e; e++)
	{
		if (SUCCEED != is_function_char(*e))
		{
			zbx_chrcpy_alloc(&exp->exp, &exp_alloc, &exp_offset, *e);
			continue;
		}

		if ((0 == strncmp("and", e, len = 3) || 0 == strncmp("not", e, 3) || 0 == strncmp("or", e, len = 2)) &&
				NULL != strchr("()" ZBX_WHITESPACE, e[len]))
		{
			zbx_strncpy_alloc(&exp->exp, &exp_alloc, &exp_offset, e, len);
			e += len - 1;
			continue;
		}

		f = e;
		if (SUCCEED != parse_function(&e, &func, &params))
		{
			e = f;
			zbx_chrcpy_alloc(&exp->exp, &exp_alloc, &exp_offset, *f);
			continue;
		}
		else
			e--;

		functionid = calcitem_add_function(exp, func, params);

		zabbix_log(LOG_LEVEL_DEBUG, "%s() functionid:%d function:'%s(%s)'",
				__function_name, functionid, func, params);

		func = NULL;
		params = NULL;

		zbx_snprintf_alloc(&exp->exp, &exp_alloc, &exp_offset, "{%d}", functionid);
	}

	zabbix_log(LOG_LEVEL_DEBUG, "%s() expression:'%s'", __function_name, exp->exp);

	if (FAIL == (ret = substitute_simple_macros(NULL, NULL, NULL, NULL, NULL, &dc_item->host, NULL, NULL,
				&exp->exp, MACRO_TYPE_ITEM_EXPRESSION, error, max_error_len)))
		ret = NOTSUPPORTED;

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

	return ret;
}
Exemple #12
0
/******************************************************************************
 *                                                                            *
 * Function: httpmacro_append_pair                                            *
 *                                                                            *
 * Purpose: appends key/value pair to the http test macro cache.              *
 *          If the value format is 'regex:<pattern>', then regular expression *
 *          match is performed against the supplied data value and specified  *
 *          pattern. The first captured group is assigned to the macro value. *
 *                                                                            *
 * Parameters: httptest - [IN/OUT] the http test data                         *
 *             pkey     - [IN] a pointer to the macro name (key) data         *
 *             nkey     - [IN] the macro name (key) size                      *
 *             pvalue   - [IN] a pointer to the macro value data              *
 *             nvalue   - [IN] the value size                                 *
 *             data     - [IN] the data for regexp matching (optional)        *
 *             err_str  - [OUT] the error message (optional)                  *
 *                                                                            *
 * Return value: SUCCEDED - the key/value pair was added successfully         *
 *                   FAIL - key/value pair adding to cache failed.            *
 *                          The failure reason can be either empty key/value, *
 *                          wrong key format or failed regular expression     *
 *                          match.                                            *
 *                                                                            *
 * Author: Andris Zeila                                                       *
 *                                                                            *
 ******************************************************************************/
static int	httpmacro_append_pair(zbx_httptest_t *httptest, const char *pkey, size_t nkey,
			const char *pvalue, size_t nvalue, const char *data, char **err_str)
{
	const char	*__function_name = "httpmacro_append_pair";
	char 		*value_str = NULL;
	size_t		key_size = 0, key_offset = 0, value_size = 0, value_offset = 0;
	zbx_ptr_pair_t	pair = {NULL, NULL};
	int		index, ret = FAIL;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() pkey:'%.*s' pvalue:'%.*s'",
			__function_name, (int)nkey, pkey, (int)nvalue, pvalue);

	if (NULL == data)
	{
		/* Ignore regex variables when no input data is specified. For example,   */
		/* scenario level regex variables don't have input data before the first  */
		/* web scenario step is processed.                                        */
		ret = SUCCEED;
		goto out;
	}

	if (0 == nkey || 0 == nvalue)
	{
		if (0 == nkey && 0 != nvalue)
		{
			zabbix_log(LOG_LEVEL_DEBUG, "%s() missing variable name (only value provided): \"%.*s\"",
					__function_name, (int)nvalue, pvalue);

			if (NULL != err_str && NULL == *err_str)
			{
				*err_str = zbx_dsprintf(*err_str, "missing variable name (only value provided):"
						" \"%.*s\"", (int)nvalue, pvalue);
			}
		}
		else if (0 == nvalue && 0 != nkey)
		{
			zabbix_log(LOG_LEVEL_DEBUG, "%s() missing variable value (only name provided): \"%.*s\"",
					__function_name, (int)nkey, pkey);

			if (NULL != err_str && NULL == *err_str)
			{
				*err_str = zbx_dsprintf(*err_str, "missing variable value (only name provided):"
						" \"%.*s\"", (int)nkey, pkey);
			}
		}

		goto out;
	}

	if ('{' != pkey[0] || '}' != pkey[nkey - 1])
	{
		zabbix_log(LOG_LEVEL_DEBUG, "%s() \"%.*s\" not enclosed in {}", __function_name, (int)nkey, pkey);

		if (NULL != err_str && NULL == *err_str)
			*err_str = zbx_dsprintf(*err_str, "\"%.*s\" not enclosed in {}", (int)nkey, pkey);

		goto out;
	}

	/* get macro value */
	zbx_strncpy_alloc(&value_str, &value_size, &value_offset, pvalue, nvalue);
	if (0 == strncmp(REGEXP_PREFIX, value_str, REGEXP_PREFIX_SIZE))
	{
		int	rc;
		/* The value contains regexp pattern, retrieve the first captured group or fail.  */
		/* The \@ sequence is a special construct to fail if the pattern matches but does */
		/* not contain groups to capture.                                                 */

		rc = zbx_mregexp_sub(data, value_str + REGEXP_PREFIX_SIZE, "\\@", (char **)&pair.second);
		zbx_free(value_str);

		if (SUCCEED != rc || NULL == pair.second)
		{
			zabbix_log(LOG_LEVEL_DEBUG, "%s() cannot extract the value of \"%.*s\" from response",
					__function_name, (int)nkey, pkey);

			if (NULL != err_str && NULL == *err_str)
			{
				*err_str = zbx_dsprintf(*err_str, "cannot extract the value of \"%.*s\""
						" from response", (int)nkey, pkey);
			}

			goto out;
		}
	}
	else
		pair.second = value_str;

	/* get macro name */
	zbx_strncpy_alloc((char**)&pair.first, &key_size, &key_offset, pkey, nkey);

	/* remove existing macro if necessary */
	index = zbx_vector_ptr_pair_search(&httptest->macros, pair, httpmacro_cmp_func);
	if (FAIL != index)
	{
		zbx_ptr_pair_t	*ppair = &httptest->macros.values[index];

		zbx_free(ppair->first);
		zbx_free(ppair->second);
		zbx_vector_ptr_pair_remove_noorder(&httptest->macros, index);
	}
	zbx_vector_ptr_pair_append(&httptest->macros, pair);

	ret = SUCCEED;
out:
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s macro:'%s'='%s'",
			__function_name, zbx_result_string(ret), (char*)pair.first, (char*)pair.second);

	return ret;
}
Exemple #13
0
/*********************************************************************************
 *                                                                               *
 * Function: regexp_sub_replace                                                  *
 *                                                                               *
 * Purpose: Constructs a string from the specified template and regexp match.    *
 *                                                                               *
 * Parameters: text            - [IN] the input string.                          *
 *             output_template - [IN] the output string template. The output     *
 *                                    string is constructed from template by     *
 *                                    replacing \<n> sequences with the captured *
 *                                    regexp group.                              *
 *                                    If the output template is NULL or contains *
 *                                    empty string then a copy of the whole      *
 *                                    input string is returned.                  *
 *             match           - [IN] the captured group data                    *
 *             nmatch          - [IN] the number of items in captured group data *
 *                                                                               *
 * Return value: Allocated string containing output value                        *
 *                                                                               *
 *********************************************************************************/
static char	*regexp_sub_replace(const char *text, const char *output_template, regmatch_t *match, size_t nmatch)
{
	char		*ptr = NULL;
	const char	*pstart = output_template, *pgroup;
	size_t		size = 0, offset = 0, group_index;

	if (NULL == output_template || '\0' == *output_template)
		return zbx_strdup(NULL, text);

	while (NULL != (pgroup = strchr(pstart, '\\')))
	{
		switch (*(++pgroup))
		{
			case '\\':
				zbx_strncpy_alloc(&ptr, &size, &offset, pstart, pgroup - pstart);
				pstart = pgroup + 1;
				continue;

			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				zbx_strncpy_alloc(&ptr, &size, &offset, pstart, pgroup - pstart - 1);
				group_index = *pgroup - '0';
				if (group_index < nmatch && -1 != match[group_index].rm_so)
				{
					zbx_strncpy_alloc(&ptr, &size, &offset, text + match[group_index].rm_so,
							match[group_index].rm_eo - match[group_index].rm_so);
				}
				pstart = pgroup + 1;
				continue;

			case '@':
				/* artificial construct to replace the first captured group or fail */
				/* if the regular expression pattern contains no groups             */
				if (-1 == match[1].rm_so)
				{
					zbx_free(ptr);
					goto out;
				}

				zbx_strncpy_alloc(&ptr, &size, &offset, text + match[1].rm_so,
						match[1].rm_eo - match[1].rm_so);

				pstart = pgroup + 1;
				continue;

			default:
				zbx_strncpy_alloc(&ptr, &size, &offset, pstart, pgroup - pstart);
				pstart = pgroup;
		}
	}

	if ('\0' != *pstart)
		zbx_strcpy_alloc(&ptr, &size, &offset, pstart);
out:
	return ptr;
}
Exemple #14
0
static int	DBpatch_2010101(void)
{
	DB_RESULT	result;
	DB_ROW		row;
	int		ret = SUCCEED;
	char		*key = NULL;
	size_t		key_alloc = 0, key_offset;

	result = DBselect(
			"select i.itemid,i.key_,i.params,h.name"
			" from items i,hosts h"
			" where i.hostid=h.hostid"
				" and i.type=%d",
			ITEM_TYPE_DB_MONITOR);

	while (NULL != (row = DBfetch(result)) && SUCCEED == ret)
	{
		char		*user = NULL, *password = NULL, *dsn = NULL, *sql = NULL, *error_message = NULL;
		zbx_uint64_t	itemid;
		size_t		key_len;

		key_len = strlen(row[1]);

		parse_db_monitor_item_params(row[2], &dsn, &user, &password, &sql);

		if (0 != strncmp(row[1], "db.odbc.select[", 15) || ']' != row[1][key_len - 1])
			error_message = zbx_dsprintf(error_message, "key \"%s\" is invalid", row[1]);
		else if (ITEM_USERNAME_LEN < strlen(user))
			error_message = zbx_dsprintf(error_message, "ODBC username \"%s\" is too long", user);
		else if (ITEM_PASSWORD_LEN < strlen(password))
			error_message = zbx_dsprintf(error_message, "ODBC password \"%s\" is too long", password);
		else
		{
			char	*param = NULL;
			size_t	param_alloc = 0, param_offset = 0;
			int	nparam;

			zbx_strncpy_alloc(&param, &param_alloc, &param_offset, row[1] + 15, key_len - 16);

			if (1 != (nparam = num_param(param)))
				quote_key_param(&param, 0);
			quote_key_param(&dsn, 0);

			key_offset = 0;
			zbx_snprintf_alloc(&key, &key_alloc, &key_offset, "db.odbc.select[%s,%s]", param, dsn);

			zbx_free(param);

			if (255 /* ITEM_KEY_LEN */ < zbx_strlen_utf8(key))
				error_message = zbx_dsprintf(error_message, "key \"%s\" is too long", row[1]);
		}

		if (NULL == error_message)
		{
			char	*username_esc, *password_esc, *params_esc, *key_esc;

			ZBX_STR2UINT64(itemid, row[0]);

			username_esc = DBdyn_escape_string(user);
			password_esc = DBdyn_escape_string(password);
			params_esc = DBdyn_escape_string(sql);
			key_esc = DBdyn_escape_string(key);

			if (ZBX_DB_OK > DBexecute("update items set username='******',password='******',key_='%s',params='%s'"
					" where itemid=" ZBX_FS_UI64,
					username_esc, password_esc, key_esc, params_esc, itemid))
			{
				ret = FAIL;
			}

			zbx_free(username_esc);
			zbx_free(password_esc);
			zbx_free(params_esc);
			zbx_free(key_esc);
		}
		else
		{
			zabbix_log(LOG_LEVEL_WARNING, "Failed to convert host \"%s\" db monitoring item because"
					" %s. See upgrade notes for manual database monitor item conversion.",
					row[3], error_message);
		}

		zbx_free(error_message);
		zbx_free(user);
		zbx_free(password);
		zbx_free(dsn);
		zbx_free(sql);
	}
	DBfree_result(result);

	zbx_free(key);

	return ret;
}
static int	DBpatch_2030095(void)
{
	DB_RESULT	result;
	DB_ROW		row;
	int		ret = SUCCEED;
	char		*p, *q, *params = NULL, *params_esc;
	size_t		params_alloc = 0, params_offset;

	result = DBselect("select itemid,params from items where type=%d", 15 /* ITEM_TYPE_CALCULATED */);

	while (SUCCEED == ret && NULL != (row = DBfetch(result)))
	{
		params_offset = 0;

		for (p = row[1]; '\0' != *p; p++)
		{
			if (NULL != strchr(ZBX_WHITESPACE, *p))
			{
				if (' ' != *p || (0 != params_offset &&
						NULL == strchr(ZBX_WHITESPACE, params[params_offset - 1])))
				{
					zbx_chrcpy_alloc(&params, &params_alloc, &params_offset, *p);
				}

				continue;
			}

			if (NULL != strchr("#&|", *p))
			{
				if ('#' == *p && 0 != params_offset && '{' == params[params_offset - 1])
				{
					zbx_chrcpy_alloc(&params, &params_alloc, &params_offset, *p);
					continue;
				}

				if (('&' == *p || '|' == *p) && 0 != params_offset &&
						NULL == strchr(ZBX_WHITESPACE, params[params_offset - 1]))
				{
					zbx_chrcpy_alloc(&params, &params_alloc, &params_offset, ' ');
				}

				switch (*p)
				{
					case '#':
						zbx_strcpy_alloc(&params, &params_alloc, &params_offset, "<>");
						break;
					case '&':
						zbx_strcpy_alloc(&params, &params_alloc, &params_offset, "and");
						break;
					case '|':
						zbx_strcpy_alloc(&params, &params_alloc, &params_offset, "or");
						break;
				}

				if (('&' == *p || '|' == *p) && NULL == strchr(ZBX_WHITESPACE, *(p + 1)))
					zbx_chrcpy_alloc(&params, &params_alloc, &params_offset, ' ');

				continue;
			}

			q = p;

			if (SUCCEED == parse_function(&q, NULL, NULL))
			{
				zbx_strncpy_alloc(&params, &params_alloc, &params_offset, p, q - p);
				p = q - 1;
				continue;
			}

			zbx_chrcpy_alloc(&params, &params_alloc, &params_offset, *p);
		}

#if defined(HAVE_IBM_DB2) || defined(HAVE_ORACLE)
		if (2048 < params_offset && 2048 /* ITEM_PARAM_LEN */ < zbx_strlen_utf8(params))
#else
		if (65535 < params_offset && 65535 /* ITEM_PARAM_LEN */ < zbx_strlen_utf8(params))
#endif
		{
			zabbix_log(LOG_LEVEL_WARNING, "cannot convert calculated item expression \"%s\":"
					" resulting expression is too long", row[1]);
		}
		else if (0 != strcmp(row[1], params))
		{
			params_esc = DBdyn_escape_string(params);

			if (ZBX_DB_OK > DBexecute("update items set params='%s' where itemid=%s", params_esc, row[0]))
				ret = FAIL;

			zbx_free(params_esc);
		}
	}
	DBfree_result(result);

	zbx_free(params);

	return ret;
}