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