/******************************************************************************
 *                                                                            *
 * Function: evaluate_aggregate                                               *
 *                                                                            *
 * Parameters: item      - [IN] aggregated item                               *
 *             grp_func  - [IN] one of ZBX_GRP_FUNC_*                         *
 *             groups    - [IN] list of comma-separated host groups           *
 *             itemkey   - [IN] item key to aggregate                         *
 *             item_func - [IN] one of ZBX_VALUE_FUNC_*                       *
 *             param     - [IN] item_func parameter (optional)                *
 *                                                                            *
 * Return value: SUCCEED - aggregate item evaluated successfully              *
 *               FAIL - otherwise                                             *
 *                                                                            *
 ******************************************************************************/
static int	evaluate_aggregate(DC_ITEM *item, AGENT_RESULT *res, int grp_func, const char *groups,
		const char *itemkey, int item_func, const char *param)
{
	const char			*__function_name = "evaluate_aggregate";
	zbx_vector_uint64_t		itemids;
	history_value_t			value, item_result;
	zbx_history_record_t		group_value;
	int				ret = FAIL, now, *errcodes = NULL, i, count;
	DC_ITEM				*items = NULL;
	zbx_vector_history_record_t	values, group_values;
	unsigned int			seconds;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() grp_func:%d groups:'%s' itemkey:'%s' item_func:%d param:'%s'",
			__function_name, grp_func, groups, itemkey, item_func, ZBX_NULL2STR(param));

	now = time(NULL);

	zbx_vector_uint64_create(&itemids);
	aggregate_get_items(&itemids, groups, itemkey);

	if (0 == itemids.values_num)
	{
		SET_MSG_RESULT(res, zbx_dsprintf(NULL, "No items for key \"%s\" in group(s) \"%s\".", itemkey, groups));
		goto clean1;
	}

	memset(&value, 0, sizeof(value));
	zbx_history_record_vector_create(&group_values);

	items = zbx_malloc(items, sizeof(DC_ITEM) * itemids.values_num);
	errcodes = zbx_malloc(errcodes, sizeof(int) * itemids.values_num);

	DCconfig_get_items_by_itemids(items, itemids.values, errcodes, itemids.values_num);

	if (ZBX_VALUE_FUNC_LAST == item_func)
	{
		count = 1;
		seconds = 0;
	}
	else
	{
		if (FAIL == is_uint_suffix(param, &seconds))
		{
			SET_MSG_RESULT(res, zbx_strdup(NULL, "Invalid fourth parameter."));
			goto clean2;
		}
		count = 0;
	}

	for (i = 0; i < itemids.values_num; i++)
	{
		if (SUCCEED != errcodes[i])
			continue;

		if (ITEM_STATUS_ACTIVE != items[i].status)
			continue;

		if (HOST_STATUS_MONITORED != items[i].host.status)
			continue;

		if (ITEM_VALUE_TYPE_FLOAT != items[i].value_type && ITEM_VALUE_TYPE_UINT64 != items[i].value_type)
			continue;

		zbx_history_record_vector_create(&values);

		if (SUCCEED == zbx_vc_get_value_range(items[i].itemid, items[i].value_type, &values, seconds,
				count, now) && 0 < values.values_num)
		{
			evaluate_history_func(&values, items[i].value_type, item_func, &item_result);

			if (item->value_type == items[i].value_type)
				group_value.value = item_result;
			else
			{
				if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
					group_value.value.ui64 = (zbx_uint64_t)item_result.dbl;
				else
					group_value.value.dbl = (double)item_result.ui64;
			}

			zbx_vector_history_record_append_ptr(&group_values, &group_value);
		}

		zbx_history_record_vector_destroy(&values, items[i].value_type);
	}

	if (0 == group_values.values_num)
	{
		SET_MSG_RESULT(res, zbx_dsprintf(NULL, "No values for key \"%s\" in group(s) \"%s\"", itemkey, groups));
		goto clean2;
	}

	evaluate_history_func(&group_values, item->value_type, grp_func, &value);

	if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
		SET_DBL_RESULT(res, value.dbl);
	else
		SET_UI64_RESULT(res, value.ui64);

	ret = SUCCEED;
clean2:
	DCconfig_clean_items(items, errcodes, itemids.values_num);

	zbx_free(errcodes);
	zbx_free(items);
	zbx_history_record_vector_destroy(&group_values, item->value_type);
clean1:
	zbx_vector_uint64_destroy(&itemids);

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

	return ret;
}
Beispiel #2
0
void	zbx_mem_create(zbx_mem_info_t **info, key_t shm_key, int lock_name, zbx_uint64_t size,
		const char *descr, const char *param, int allow_oom)
{
	const char	*__function_name = "zbx_mem_create";

	int		shm_id, index;
	void		*base;

	descr = ZBX_NULL2STR(descr);
	param = ZBX_NULL2STR(param);

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() descr:'%s' param:'%s' size:" ZBX_FS_SIZE_T,
			__function_name, descr, param, (zbx_fs_size_t)size);

	/* allocate shared memory */

	if (4 != ZBX_PTR_SIZE && 8 != ZBX_PTR_SIZE)
	{
		zabbix_log(LOG_LEVEL_CRIT, "failed assumption about pointer size (" ZBX_FS_SIZE_T " not in {4, 8})",
				(zbx_fs_size_t)ZBX_PTR_SIZE);
		exit(FAIL);
	}

	if (!(MEM_MIN_SIZE <= size && size <= MEM_MAX_SIZE))
	{
		zabbix_log(LOG_LEVEL_CRIT, "requested size " ZBX_FS_SIZE_T " not within bounds [" ZBX_FS_UI64
				" <= size <= " ZBX_FS_UI64 "]", (zbx_fs_size_t)size, MEM_MIN_SIZE, MEM_MAX_SIZE);
		exit(FAIL);
	}

	if (-1 == (shm_id = zbx_shmget(shm_key, size)))
	{
		zabbix_log(LOG_LEVEL_CRIT, "cannot allocate shared memory for %s", descr);
		exit(FAIL);
	}

	if ((void *)(-1) == (base = shmat(shm_id, NULL, 0)))
	{
		zabbix_log(LOG_LEVEL_CRIT, "cannot attach shared memory for %s: %s", descr, zbx_strerror(errno));
		exit(FAIL);
	}

	/* allocate zbx_mem_info_t structure, its buckets, and description inside shared memory */

	*info = ALIGN8(base);
	(*info)->shm_id = shm_id;
	(*info)->orig_size = size;
	size -= (void *)(*info + 1) - base;
	base = (void *)(*info + 1);

	(*info)->buckets = ALIGNPTR(base);
	memset((*info)->buckets, 0, MEM_BUCKET_COUNT * ZBX_PTR_SIZE);
	size -= (void *)((*info)->buckets + MEM_BUCKET_COUNT) - base;
	base = (void *)((*info)->buckets + MEM_BUCKET_COUNT);

	zbx_strlcpy(base, descr, size);
	(*info)->mem_descr = base;
	size -= strlen(descr) + 1;
	base += strlen(descr) + 1;

	zbx_strlcpy(base, param, size);
	(*info)->mem_param = base;
	size -= strlen(param) + 1;
	base += strlen(param) + 1;

	(*info)->allow_oom = allow_oom;

	/* allocate mutex */

	if (ZBX_NO_MUTEX != lock_name)
	{
		(*info)->use_lock = 1;

		if (ZBX_MUTEX_ERROR == zbx_mutex_create_force(&((*info)->mem_lock), lock_name))
		{
			zabbix_log(LOG_LEVEL_CRIT, "cannot create mutex for %s",
					descr);
			exit(FAIL);
		}
	}
	else
		(*info)->use_lock = 0;

	/* prepare shared memory for further allocation by creating one big chunk */
	(*info)->lo_bound = ALIGN8(base);
	(*info)->hi_bound = ALIGN8(base + size - 8);

	(*info)->total_size = (zbx_uint64_t)((*info)->hi_bound - (*info)->lo_bound - 2 * MEM_SIZE_FIELD);

	index = mem_bucket_by_size((*info)->total_size);
	(*info)->buckets[index] = (*info)->lo_bound;
	mem_set_chunk_size((*info)->buckets[index], (*info)->total_size);
	mem_set_prev_chunk((*info)->buckets[index], NULL);
	mem_set_next_chunk((*info)->buckets[index], NULL);

	(*info)->used_size = 0;
	(*info)->free_size = (*info)->total_size;

	zabbix_log(LOG_LEVEL_DEBUG, "valid user addresses: [%p, %p] total size: " ZBX_FS_SIZE_T,
			(*info)->lo_bound + MEM_SIZE_FIELD,
			(*info)->hi_bound - MEM_SIZE_FIELD,
			(zbx_fs_size_t)(*info)->total_size);

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
}
Beispiel #3
0
/******************************************************************************
 *                                                                            *
 * Function: send_ez_texting                                                  *
 *                                                                            *
 * Purpose: send SMS using Ez Texting API                                     *
 *                                                                            *
 * Parameters:                                                                *
 *                                                                            *
 * Return value: SUCCEED if message has been sent successfully                *
 *               FAIL otherwise                                               *
 *                                                                            *
 * Author: Aleksandrs Saveljevs                                               *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
int	send_ez_texting(const char *username, const char *password, const char *sendto,
		const char *message, const char *limit, char *error, int max_error_len)
{
#ifdef HAVE_LIBCURL

	const char	*__function_name = "send_ez_texting";

	int		ret = FAIL;
	int		max_message_len;
	int		i, len, opt, err;
	char		*sendto_digits = NULL, *message_ascii = NULL;
	char		*username_esc = NULL, *password_esc = NULL, *sendto_esc = NULL, *message_esc = NULL;
	char		postfields[MAX_STRING_LEN];
	CURL		*easy_handle = NULL;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() sendto:'%s' message:'%s'", __function_name, sendto, message);

	assert(error);
	*error = '\0';

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

	/* replace UTF-8 and invalid ASCII characters, and make sure the message is not too long */

	switch (atoi(limit))
	{
		case EZ_TEXTING_LIMIT_USA:
			max_message_len = EZ_TEXTING_LENGTH_USA;
			break;
		case EZ_TEXTING_LIMIT_CANADA:
			max_message_len = EZ_TEXTING_LENGTH_CANADA;
			break;
		default:
			THIS_SHOULD_NEVER_HAPPEN;
			zbx_snprintf(error, max_error_len, "Could not determine proper length limit: [%s]", limit);
			goto clean;
	}

	if (NULL == (message_ascii = zbx_replace_utf8(message)))
	{
		zbx_snprintf(error, max_error_len, "Could not replace UTF-8 characters: [%s]", message);
		goto clean;
	}

	for (i = 0, len = 0; '\0' != message_ascii[i] && len < max_message_len; i++, len++)
	{
		if (' ' == message_ascii[i])
			continue;
		if ('a' <= message_ascii[i] && message_ascii[i] <= 'z')
			continue;
		if ('A' <= message_ascii[i] && message_ascii[i] <= 'Z')
			continue;
		if ('0' <= message_ascii[i] && message_ascii[i] <= '9')
			continue;

		if ('\t' == message_ascii[i])	/* \t is not part of GSM character set */
		{
			message_ascii[i] = ' ';
			continue;
		}
		if ('\r' == message_ascii[i])	/* line end counts as two, regardless of... */
		{
			if ('\n' != message_ascii[i + 1])
				len++;
			continue;
		}
		if ('\n' == message_ascii[i])	/* ... how it is specified: \r, \n, or \r\n */
		{
			if (0 < i && '\r' != message_ascii[i - 1])
				len++;
			continue;
		}
		if (NULL == (strchr(EZ_TEXTING_VALID_CHARS, message_ascii[i])))
		{
			message_ascii[i] = '?';
			continue;
		}
		if (NULL != (strchr(EZ_TEXTING_DOUBLE_CHARS, message_ascii[i])))
		{
			len++;
			continue;
		}
	}

	if (len > max_message_len)
		i--;

	message_ascii[i] = '\0';

	/* prepare and make cURL request to Ez Texting API */

	if (NULL == (easy_handle = curl_easy_init()))
	{
		zbx_snprintf(error, max_error_len, "Could not initialize cURL");
		goto clean;
	}

	sendto_digits = strdup(sendto);
	zbx_remove_chars(sendto_digits, "() -"); /* allow phone numbers to be specified like "(123) 456-7890" */

	if (NULL == (username_esc = curl_easy_escape(easy_handle, username, strlen(username))) ||
			NULL == (password_esc = curl_easy_escape(easy_handle, password, strlen(password))) ||
			NULL == (sendto_esc = curl_easy_escape(easy_handle, sendto_digits, strlen(sendto_digits))) ||
			NULL == (message_esc = curl_easy_escape(easy_handle, message_ascii, strlen(message_ascii))))
	{
		zbx_snprintf(error, max_error_len, "Could not URL encode POST fields");
		goto clean;
	}

	zbx_snprintf(postfields, sizeof(postfields), "user=%s&pass=%s&phonenumber=%s&subject=&message=%s",
			username_esc, password_esc, sendto_esc, message_esc);

	if (CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_USERAGENT, "Zabbix " ZABBIX_VERSION)) ||
			CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_FOLLOWLOCATION, 1L)) ||
			CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_WRITEFUNCTION, WRITEFUNCTION2)) ||
			CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_HEADERFUNCTION, HEADERFUNCTION2)) ||
			CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_SSL_VERIFYPEER, 1L)) ||
			CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_SSL_VERIFYHOST, 2L)) ||
			CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_POSTFIELDS, postfields)) ||
			CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_POST, 1L)) ||
			CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_URL, EZ_TEXTING_API_URL)) ||
			CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_TIMEOUT, (long)EZ_TEXTING_TIMEOUT)))
	{
		zbx_snprintf(error, max_error_len, "Could not set cURL option %d: [%s]", opt, curl_easy_strerror(err));
		goto clean;
	}

	if (NULL != CONFIG_SOURCE_IP)
	{
		if (CURLE_OK != (err = curl_easy_setopt(easy_handle, opt = CURLOPT_INTERFACE, CONFIG_SOURCE_IP)))
		{
			zbx_snprintf(error, max_error_len, "Could not set cURL option %d: [%s]",
					opt, curl_easy_strerror(err));
			goto clean;
		}
	}

	if (CURLE_OK != (err = curl_easy_perform(easy_handle)))
	{
		zbx_snprintf(error, max_error_len, "Error doing curl_easy_perform(): [%s]", curl_easy_strerror(err));
		goto clean;
	}

	/* parse the response */

	if (NULL == page.data || FAIL == is_int_prefix(page.data))
	{
		zbx_snprintf(error, max_error_len, "Did not receive a proper response: [%s]", ZBX_NULL2STR(page.data));
		goto clean;
	}

	switch (atoi(page.data))
	{
		case 1:
			ret = SUCCEED;
			break;
		case -1:
			zbx_snprintf(error, max_error_len, "Invalid user and/or password or API is not allowed");
			break;
		case -2:
			zbx_snprintf(error, max_error_len, "Credit limit reached");
			break;
		case -5:
			zbx_snprintf(error, max_error_len, "Locally opted out phone number");
			break;
		case -7:
			zbx_snprintf(error, max_error_len, "Message too long or contains invalid characters");
			break;
		case -104:
			zbx_snprintf(error, max_error_len, "Globally opted out phone number");
			break;
		case -106:
			zbx_snprintf(error, max_error_len, "Incorrectly formatted phone number");
			break;
		case -10:
			zbx_snprintf(error, max_error_len, "Unknown error (please contact Ez Texting)");
			break;
		default:
			zbx_snprintf(error, max_error_len, "Unknown return value: [%s]", page.data);
			break;
	}
clean:
	if (NULL != message_ascii)
		zbx_free(message_ascii);
	if (NULL != sendto_digits)
		zbx_free(sendto_digits);
	if (NULL != username_esc)
		zbx_free(username_esc);
	if (NULL != password_esc)
		zbx_free(password_esc);
	if (NULL != sendto_esc)
		zbx_free(sendto_esc);
	if (NULL != message_esc)
		zbx_free(message_esc);
	if (NULL != page.data)
		zbx_free(page.data);
	if (NULL != easy_handle)
		curl_easy_cleanup(easy_handle);

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

	return ret;

#else
	zbx_snprintf(error, max_error_len, "cURL library is required for Ez Texting support");
	return FAIL;

#endif	/* HAVE_LIBCURL */
}