/****************************************************************************** * * * 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; }
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); }
/****************************************************************************** * * * 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 */ }