int check_ntp(char *host, unsigned short port, int timeout, int *value_int) { zbx_socket_t s; int ret; char request[NTP_PACKET_SIZE]; ntp_data data; *value_int = 0; if (SUCCEED == (ret = zbx_udp_connect(&s, CONFIG_SOURCE_IP, host, port, timeout))) { make_packet(&data); pack_ntp(&data, (unsigned char *)request, sizeof(request)); if (SUCCEED == (ret = zbx_udp_send(&s, request, sizeof(request), timeout))) { if (SUCCEED == (ret = zbx_udp_recv(&s, timeout))) { *value_int = (SUCCEED == unpack_ntp(&data, (unsigned char *)request, (unsigned char *)s.buffer, s.read_bytes)); } } zbx_udp_close(&s); } if (FAIL == ret) zabbix_log(LOG_LEVEL_DEBUG, "NTP check error: %s", zbx_socket_strerror()); return SYSINFO_RET_OK; }
/****************************************************************************** * * * Function: zbx_send_response * * * * Purpose: send json SUCCEED or FAIL to socket along with an info message * * * * Parameters: sock - [IN] socket descriptor * * result - [IN] SUCCEED or FAIL * * info - [IN] info message * * timeout - [IN] timeout for this operation * * * * Return value: SUCCEED - data successfully transmited * * NETWORK_ERROR - network related error occurred * * * * Author: Alexander Vladishev, Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int zbx_send_response_ext(zbx_socket_t *sock, int result, const char *info, int protocol, int timeout) { const char *__function_name = "zbx_send_response"; struct zbx_json json; const char *resp; int ret = SUCCEED; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN); resp = SUCCEED == result ? ZBX_PROTO_VALUE_SUCCESS : ZBX_PROTO_VALUE_FAILED; zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, resp, ZBX_JSON_TYPE_STRING); if (NULL != info && '\0' != *info) zbx_json_addstring(&json, ZBX_PROTO_TAG_INFO, info, ZBX_JSON_TYPE_STRING); zabbix_log(LOG_LEVEL_DEBUG, "%s() '%s'", __function_name, json.buffer); if (FAIL == (ret = zbx_tcp_send_ext(sock, json.buffer, strlen(json.buffer), protocol, timeout))) { zabbix_log(LOG_LEVEL_DEBUG, "Error sending result back: %s", zbx_socket_strerror()); ret = NETWORK_ERROR; } zbx_json_free(&json); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
static int check_ssh(const char *host, unsigned short port, int timeout, int *value_int) { int ret, major, minor; zbx_socket_t s; char send_buf[MAX_STRING_LEN]; const char *buf; *value_int = 0; if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port, timeout, ZBX_TCP_SEC_UNENCRYPTED, NULL, NULL))) { while (NULL != (buf = zbx_tcp_recv_line(&s))) { /* parse buf for SSH identification string as per RFC 4253, section 4.2 */ if (2 == sscanf(buf, "SSH-%d.%d-%*s", &major, &minor)) { zbx_snprintf(send_buf, sizeof(send_buf), "SSH-%d.%d-zabbix_agent\r\n", major, minor); *value_int = 1; break; } } if (0 == *value_int) strscpy(send_buf, "0\n"); ret = zbx_tcp_send_raw(&s, send_buf); zbx_tcp_close(&s); } if (FAIL == ret) zabbix_log(LOG_LEVEL_DEBUG, "SSH check error: %s", zbx_socket_strerror()); return SYSINFO_RET_OK; }
static int check_telnet(const char *host, unsigned short port, int timeout, int *value_int) { zbx_socket_t s; #ifdef _WINDOWS u_long argp = 1; #else int flags; #endif *value_int = 0; if (SUCCEED == zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port, timeout, ZBX_TCP_SEC_UNENCRYPTED, NULL, NULL)) { #ifdef _WINDOWS ioctlsocket(s.socket, FIONBIO, &argp); /* non-zero value sets the socket to non-blocking */ #else flags = fcntl(s.socket, F_GETFL); if (0 == (flags & O_NONBLOCK)) fcntl(s.socket, F_SETFL, flags | O_NONBLOCK); #endif if (SUCCEED == telnet_test_login(s.socket)) *value_int = 1; else zabbix_log(LOG_LEVEL_DEBUG, "Telnet check error: no login prompt"); zbx_tcp_close(&s); } else zabbix_log(LOG_LEVEL_DEBUG, "%s error: %s", __func__, zbx_socket_strerror()); return SYSINFO_RET_OK; }
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()); } } }
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()); }
/****************************************************************************** * * * Function: zbx_recv_response * * * * Purpose: read a response message (in JSON format) from socket, optionally * * extract "info" value. * * * * Parameters: sock - [IN] socket descriptor * * timeout - [IN] timeout for this operation * * error - [OUT] pointer to error message * * * * Return value: SUCCEED - "response":"success" successfully retrieved * * FAIL - otherwise * * Comments: * * Allocates memory. * * * * If an error occurs, the function allocates dynamic memory for an error * * message and writes its address into location pointed to by "error" * * parameter. * * * * When the "info" value is present in the response message then function * * copies the "info" value into the "error" buffer as additional * * information * * * * IMPORTANT: it is a responsibility of the caller to release the * * "error" memory ! * * * ******************************************************************************/ int zbx_recv_response(zbx_socket_t *sock, int timeout, char **error) { const char *__function_name = "zbx_recv_response"; struct zbx_json_parse jp; char value[16]; int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (SUCCEED != zbx_tcp_recv_to(sock, timeout)) { /* since we have successfully sent data earlier, we assume the other */ /* side is just too busy processing our data if there is no response */ *error = zbx_strdup(*error, zbx_socket_strerror()); goto out; } zabbix_log(LOG_LEVEL_DEBUG, "%s() '%s'", __function_name, sock->buffer); /* deal with empty string here because zbx_json_open() does not produce an error message in this case */ if ('\0' == *sock->buffer) { *error = zbx_strdup(*error, "empty string received"); goto out; } if (SUCCEED != zbx_json_open(sock->buffer, &jp)) { *error = zbx_strdup(*error, zbx_json_strerror()); goto out; } if (SUCCEED != zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_RESPONSE, value, sizeof(value))) { *error = zbx_strdup(*error, "no \"" ZBX_PROTO_TAG_RESPONSE "\" tag"); goto out; } if (0 != strcmp(value, ZBX_PROTO_VALUE_SUCCESS)) { char *info = NULL; size_t info_alloc = 0; if (SUCCEED == zbx_json_value_by_name_dyn(&jp, ZBX_PROTO_TAG_INFO, &info, &info_alloc)) *error = zbx_strdup(*error, info); else *error = zbx_dsprintf(*error, "negative response \"%s\"", value); zbx_free(info); goto out; } ret = SUCCEED; out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/****************************************************************************** * * * Function: send_proxyconfig * * * * Purpose: send configuration tables to the proxy from server * * (for active proxies) * * * * Author: Alexander Vladishev * * * ******************************************************************************/ void send_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp) { char *error = NULL; struct zbx_json j; DC_PROXY proxy; int flags = ZBX_TCP_PROTOCOL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__); if (SUCCEED != get_active_proxy_from_request(jp, &proxy, &error)) { zabbix_log(LOG_LEVEL_WARNING, "cannot parse proxy configuration data request from active proxy at" " \"%s\": %s", sock->peer, error); goto out; } if (SUCCEED != zbx_proxy_check_permissions(&proxy, sock, &error)) { zabbix_log(LOG_LEVEL_WARNING, "cannot accept connection from proxy \"%s\" at \"%s\", allowed address:" " \"%s\": %s", proxy.host, sock->peer, proxy.proxy_address, error); goto out; } zbx_update_proxy_data(&proxy, zbx_get_protocol_version(jp), time(NULL), (0 != (sock->protocol & ZBX_TCP_COMPRESS) ? 1 : 0)); if (0 != proxy.auto_compress) flags |= ZBX_TCP_COMPRESS; zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); if (SUCCEED != get_proxyconfig_data(proxy.hostid, &j, &error)) { zbx_send_response_ext(sock, FAIL, error, NULL, flags, CONFIG_TIMEOUT); zabbix_log(LOG_LEVEL_WARNING, "cannot collect configuration data for proxy \"%s\" at \"%s\": %s", proxy.host, sock->peer, error); goto clean; } zabbix_log(LOG_LEVEL_WARNING, "sending configuration data to proxy \"%s\" at \"%s\", datalen " ZBX_FS_SIZE_T, proxy.host, sock->peer, (zbx_fs_size_t)j.buffer_size); zabbix_log(LOG_LEVEL_DEBUG, "%s", j.buffer); if (SUCCEED != zbx_tcp_send_ext(sock, j.buffer, strlen(j.buffer), flags, CONFIG_TRAPPER_TIMEOUT)) { zabbix_log(LOG_LEVEL_WARNING, "cannot send configuration data to proxy \"%s\" at \"%s\": %s", proxy.host, sock->peer, zbx_socket_strerror()); } clean: zbx_json_free(&j); out: zbx_free(error); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__); }
/****************************************************************************** * * * Function: send_host_availability * * * * Purpose: send hosts availability data from proxy * * * ******************************************************************************/ void send_host_availability(zbx_socket_t *sock) { const char *__function_name = "send_host_availability"; struct zbx_json j; int ret = FAIL, ts; char *error = NULL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (SUCCEED != check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "host availability data request")) { /* do not send any reply to server in this case as the server expects host availability data */ goto out1; } zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); /* if there are no host availability changes we still have to send empty data in response */ if (SUCCEED != get_host_availability_data(&j, &ts)) { zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA); zbx_json_close(&j); } zabbix_log(LOG_LEVEL_DEBUG, "%s() [%s]", __function_name, j.buffer); if (SUCCEED != zbx_tcp_send_to(sock, j.buffer, CONFIG_TIMEOUT)) { error = zbx_strdup(error, zbx_socket_strerror()); goto out; } if (SUCCEED != zbx_recv_response(sock, CONFIG_TIMEOUT, &error)) goto out; zbx_set_availability_diff_ts(ts); ret = SUCCEED; out: if (SUCCEED != ret) { zabbix_log(LOG_LEVEL_WARNING, "cannot send host availability data to server at \"%s\": %s", sock->peer, error); } zbx_json_free(&j); zbx_free(error); out1: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
int tcp_expect(const char *host, unsigned short port, int timeout, const char *request, int (*validate_func)(const char *), const char *sendtoclose, int *value_int) { zbx_socket_t s; const char *buf; int net, val = ZBX_TCP_EXPECT_OK; *value_int = 0; if (SUCCEED != (net = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port, timeout, ZBX_TCP_SEC_UNENCRYPTED, NULL, NULL))) { goto out; } if (NULL != request) net = zbx_tcp_send_raw(&s, request); if (NULL != validate_func && SUCCEED == net) { val = ZBX_TCP_EXPECT_FAIL; while (NULL != (buf = zbx_tcp_recv_line(&s))) { val = validate_func(buf); if (ZBX_TCP_EXPECT_OK == val) break; if (ZBX_TCP_EXPECT_FAIL == val) { zabbix_log(LOG_LEVEL_DEBUG, "TCP expect content error, received [%s]", buf); break; } } } if (NULL != sendtoclose && SUCCEED == net && ZBX_TCP_EXPECT_OK == val) (void)zbx_tcp_send_raw(&s, sendtoclose); if (SUCCEED == net && ZBX_TCP_EXPECT_OK == val) *value_int = 1; zbx_tcp_close(&s); out: if (SUCCEED != net) zabbix_log(LOG_LEVEL_DEBUG, "TCP expect network error: %s", zbx_socket_strerror()); return SYSINFO_RET_OK; }
/****************************************************************************** * * * Function: send_proxyhistory * * * * Purpose: send history data to a Zabbix server * * * ******************************************************************************/ static void send_proxyhistory(zbx_socket_t *sock, zbx_timespec_t *ts) { const char *__function_name = "send_proxyhistory"; struct zbx_json j; zbx_uint64_t lastid; int records, ret = FAIL; char *error = NULL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (SUCCEED != check_access_passive_proxy(sock, ZBX_DO_NOT_SEND_RESPONSE, "history data request")) { /* do not send any reply to server in this case as the server expects history data */ goto out1; } zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); zbx_json_addarray(&j, ZBX_PROTO_TAG_DATA); records = proxy_get_hist_data(&j, &lastid); zbx_json_close(&j); zbx_json_adduint64(&j, ZBX_PROTO_TAG_CLOCK, ts->sec); zbx_json_adduint64(&j, ZBX_PROTO_TAG_NS, ts->ns); if (SUCCEED != zbx_tcp_send_to(sock, j.buffer, CONFIG_TIMEOUT)) { error = zbx_strdup(error, zbx_socket_strerror()); goto out; } if (SUCCEED != zbx_recv_response(sock, CONFIG_TIMEOUT, &error)) goto out; if (0 != records) proxy_set_hist_lastid(lastid); ret = SUCCEED; out: if (SUCCEED != ret) zabbix_log(LOG_LEVEL_WARNING, "cannot send history data to server at \"%s\": %s", sock->peer, error); zbx_json_free(&j); zbx_free(error); out1: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: send_proxyconfig * * * * Purpose: send configuration tables to the proxy from server * * (for active proxies) * * * * Author: Alexander Vladishev * * * ******************************************************************************/ void send_proxyconfig(zbx_socket_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "send_proxyconfig"; zbx_uint64_t proxy_hostid; char host[HOST_HOST_LEN_MAX], *error = NULL; struct zbx_json j; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (SUCCEED != get_active_proxy_id(jp, &proxy_hostid, host, sock, &error)) { zbx_send_response(sock, FAIL, error, CONFIG_TIMEOUT); zabbix_log(LOG_LEVEL_WARNING, "cannot parse proxy configuration data request from active proxy at" " \"%s\": %s", sock->peer, error); goto out; } update_proxy_lastaccess(proxy_hostid); zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN); if (SUCCEED != get_proxyconfig_data(proxy_hostid, &j, &error)) { zbx_send_response(sock, FAIL, error, CONFIG_TIMEOUT); zabbix_log(LOG_LEVEL_WARNING, "cannot collect configuration data for proxy \"%s\" at \"%s\": %s", host, sock->peer, error); goto clean; } zabbix_log(LOG_LEVEL_WARNING, "sending configuration data to proxy \"%s\" at \"%s\", datalen " ZBX_FS_SIZE_T, host, sock->peer, (zbx_fs_size_t)j.buffer_size); zabbix_log(LOG_LEVEL_DEBUG, "%s", j.buffer); if (SUCCEED != zbx_tcp_send_to(sock, j.buffer, CONFIG_TRAPPER_TIMEOUT)) { zabbix_log(LOG_LEVEL_WARNING, "cannot send configuration data to proxy \"%s\" at \"%s\": %s", host, sock->peer, zbx_socket_strerror()); } clean: zbx_json_free(&j); out: zbx_free(error); zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
static int send_data_to_proxy(DC_PROXY *proxy, zbx_socket_t *sock, const char *data) { const char *__function_name = "send_data_to_proxy"; int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s() data:'%s'", __function_name, data); if (FAIL == (ret = zbx_tcp_send(sock, data))) { zabbix_log(LOG_LEVEL_ERR, "cannot send data to proxy \"%s\": %s", proxy->host, zbx_socket_strerror()); ret = NETWORK_ERROR; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
static int connect_to_proxy(DC_PROXY *proxy, zbx_socket_t *sock, int timeout) { const char *__function_name = "connect_to_proxy"; int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s() address:%s port:%hu timeout:%d", __function_name, proxy->addr, proxy->port, timeout); if (FAIL == (ret = zbx_tcp_connect(sock, CONFIG_SOURCE_IP, proxy->addr, proxy->port, timeout))) { zabbix_log(LOG_LEVEL_ERR, "cannot connect to proxy \"%s\": %s", proxy->host, zbx_socket_strerror()); ret = NETWORK_ERROR; } zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
static int recv_data_from_proxy(DC_PROXY *proxy, zbx_socket_t *sock) { const char *__function_name = "recv_data_from_proxy"; int ret; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (FAIL == (ret = zbx_tcp_recv(sock))) { zabbix_log(LOG_LEVEL_ERR, "cannot obtain data from proxy \"%s\": %s", proxy->host, zbx_socket_strerror()); } else zabbix_log(LOG_LEVEL_DEBUG, "obtained data from proxy \"%s\": %s", proxy->host, sock->buffer); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
int MAIN_ZABBIX_ENTRY(int flags) { zbx_socket_t listen_sock; char *error = NULL; int i, db_type; if (0 != (flags & ZBX_TASK_FLAG_FOREGROUND)) { printf("Starting Zabbix Server. Zabbix %s (revision %s).\nPress Ctrl+C to exit.\n\n", ZABBIX_VERSION, ZABBIX_REVISION); } if (SUCCEED != zbx_locks_create(&error)) { zbx_error("cannot create locks: %s", error); zbx_free(error); exit(EXIT_FAILURE); } if (SUCCEED != zabbix_open_log(CONFIG_LOG_TYPE, CONFIG_LOG_LEVEL, CONFIG_LOG_FILE, &error)) { zbx_error("cannot open log: %s", error); zbx_free(error); exit(EXIT_FAILURE); } #ifdef HAVE_NETSNMP # define SNMP_FEATURE_STATUS "YES" #else # define SNMP_FEATURE_STATUS " NO" #endif #ifdef HAVE_OPENIPMI # define IPMI_FEATURE_STATUS "YES" #else # define IPMI_FEATURE_STATUS " NO" #endif #ifdef HAVE_LIBCURL # define LIBCURL_FEATURE_STATUS "YES" #else # define LIBCURL_FEATURE_STATUS " NO" #endif #if defined(HAVE_LIBCURL) && defined(HAVE_LIBXML2) # define VMWARE_FEATURE_STATUS "YES" #else # define VMWARE_FEATURE_STATUS " NO" #endif #ifdef HAVE_SMTP_AUTHENTICATION # define SMTP_AUTH_FEATURE_STATUS "YES" #else # define SMTP_AUTH_FEATURE_STATUS " NO" #endif #ifdef HAVE_JABBER # define JABBER_FEATURE_STATUS "YES" #else # define JABBER_FEATURE_STATUS " NO" #endif #ifdef HAVE_UNIXODBC # define ODBC_FEATURE_STATUS "YES" #else # define ODBC_FEATURE_STATUS " NO" #endif #ifdef HAVE_SSH2 # define SSH2_FEATURE_STATUS "YES" #else # define SSH2_FEATURE_STATUS " NO" #endif #ifdef HAVE_IPV6 # define IPV6_FEATURE_STATUS "YES" #else # define IPV6_FEATURE_STATUS " NO" #endif #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) # define TLS_FEATURE_STATUS "YES" #else # define TLS_FEATURE_STATUS " NO" #endif zabbix_log(LOG_LEVEL_INFORMATION, "Starting Zabbix Server. Zabbix %s (revision %s).", ZABBIX_VERSION, ZABBIX_REVISION); zabbix_log(LOG_LEVEL_INFORMATION, "****** Enabled features ******"); zabbix_log(LOG_LEVEL_INFORMATION, "SNMP monitoring: " SNMP_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "IPMI monitoring: " IPMI_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "Web monitoring: " LIBCURL_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "VMware monitoring: " VMWARE_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "SMTP authentication: " SMTP_AUTH_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "Jabber notifications: " JABBER_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "Ez Texting notifications: " LIBCURL_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "ODBC: " ODBC_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "SSH2 support: " SSH2_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "IPv6 support: " IPV6_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "TLS support: " TLS_FEATURE_STATUS); zabbix_log(LOG_LEVEL_INFORMATION, "******************************"); zabbix_log(LOG_LEVEL_INFORMATION, "using configuration file: %s", CONFIG_FILE); #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) if (SUCCEED != zbx_coredump_disable()) { zabbix_log(LOG_LEVEL_CRIT, "cannot disable core dump, exiting..."); exit(EXIT_FAILURE); } #endif if (FAIL == zbx_load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 1)) { zabbix_log(LOG_LEVEL_CRIT, "loading modules failed, exiting..."); exit(EXIT_FAILURE); } zbx_free_config(); if (SUCCEED != init_database_cache(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot initialize database cache: %s", error); zbx_free(error); exit(EXIT_FAILURE); } if (SUCCEED != init_configuration_cache(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot initialize configuration cache: %s", error); zbx_free(error); exit(EXIT_FAILURE); } if (SUCCEED != init_selfmon_collector(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot initialize self-monitoring: %s", error); zbx_free(error); exit(EXIT_FAILURE); } if (0 != CONFIG_VMWARE_FORKS && SUCCEED != zbx_vmware_init(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot initialize VMware cache: %s", error); zbx_free(error); exit(EXIT_FAILURE); } if (SUCCEED != zbx_vc_init(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot initialize history value cache: %s", error); zbx_free(error); exit(EXIT_FAILURE); } if (SUCCEED != zbx_create_itservices_lock(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot create IT services lock: %s", error); zbx_free(error); exit(EXIT_FAILURE); } if (SUCCEED != zbx_history_init(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot initialize history storage: %s", error); zbx_free(error); exit(EXIT_FAILURE); } if (FAIL == zbx_export_init(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot initialize export: %s", error); zbx_free(error); exit(EXIT_FAILURE); } if (ZBX_DB_UNKNOWN == (db_type = zbx_db_get_database_type())) { zabbix_log(LOG_LEVEL_CRIT, "cannot use database \"%s\": database is not a Zabbix database", CONFIG_DBNAME); exit(EXIT_FAILURE); } else if (ZBX_DB_SERVER != db_type) { zabbix_log(LOG_LEVEL_CRIT, "cannot use database \"%s\": its \"users\" table is empty (is this the" " Zabbix proxy database?)", CONFIG_DBNAME); exit(EXIT_FAILURE); } if (SUCCEED != DBcheck_version()) exit(EXIT_FAILURE); DBconnect(ZBX_DB_CONNECT_NORMAL); /* make initial configuration sync before worker processes are forked */ DCsync_configuration(ZBX_DBSYNC_INIT); if (SUCCEED != zbx_check_postinit_tasks(&error)) { zabbix_log(LOG_LEVEL_CRIT, "cannot complete post initialization tasks: %s", error); zbx_free(error); exit(EXIT_FAILURE); } /* update maintenance states */ zbx_dc_update_maintenances(); DBclose(); zbx_vc_enable(); threads_num = CONFIG_CONFSYNCER_FORKS + CONFIG_POLLER_FORKS + CONFIG_UNREACHABLE_POLLER_FORKS + CONFIG_TRAPPER_FORKS + CONFIG_PINGER_FORKS + CONFIG_ALERTER_FORKS + CONFIG_HOUSEKEEPER_FORKS + CONFIG_TIMER_FORKS + CONFIG_HTTPPOLLER_FORKS + CONFIG_DISCOVERER_FORKS + CONFIG_HISTSYNCER_FORKS + CONFIG_ESCALATOR_FORKS + CONFIG_IPMIPOLLER_FORKS + CONFIG_JAVAPOLLER_FORKS + CONFIG_SNMPTRAPPER_FORKS + CONFIG_PROXYPOLLER_FORKS + CONFIG_SELFMON_FORKS + CONFIG_VMWARE_FORKS + CONFIG_TASKMANAGER_FORKS + CONFIG_IPMIMANAGER_FORKS + CONFIG_ALERTMANAGER_FORKS + CONFIG_PREPROCMAN_FORKS + CONFIG_PREPROCESSOR_FORKS + CONFIG_LLDMANAGER_FORKS + CONFIG_LLDWORKER_FORKS; threads = (pid_t *)zbx_calloc(threads, threads_num, sizeof(pid_t)); if (0 != CONFIG_TRAPPER_FORKS) { if (FAIL == zbx_tcp_listen(&listen_sock, CONFIG_LISTEN_IP, (unsigned short)CONFIG_LISTEN_PORT)) { zabbix_log(LOG_LEVEL_CRIT, "listener failed: %s", zbx_socket_strerror()); exit(EXIT_FAILURE); } } #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_tls_init_parent(); #endif zabbix_log(LOG_LEVEL_INFORMATION, "server #0 started [main process]"); for (i = 0; i < threads_num; i++) { zbx_thread_args_t thread_args; unsigned char poller_type; if (FAIL == get_process_info_by_thread(i + 1, &thread_args.process_type, &thread_args.process_num)) { THIS_SHOULD_NEVER_HAPPEN; exit(EXIT_FAILURE); } thread_args.server_num = i + 1; thread_args.args = NULL; switch (thread_args.process_type) { case ZBX_PROCESS_TYPE_CONFSYNCER: zbx_thread_start(dbconfig_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_POLLER: poller_type = ZBX_POLLER_TYPE_NORMAL; thread_args.args = &poller_type; zbx_thread_start(poller_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_UNREACHABLE: poller_type = ZBX_POLLER_TYPE_UNREACHABLE; thread_args.args = &poller_type; zbx_thread_start(poller_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_TRAPPER: thread_args.args = &listen_sock; zbx_thread_start(trapper_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_PINGER: zbx_thread_start(pinger_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_ALERTER: zbx_thread_start(alerter_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_HOUSEKEEPER: zbx_thread_start(housekeeper_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_TIMER: zbx_thread_start(timer_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_HTTPPOLLER: zbx_thread_start(httppoller_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_DISCOVERER: zbx_thread_start(discoverer_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_HISTSYNCER: zbx_thread_start(dbsyncer_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_ESCALATOR: zbx_thread_start(escalator_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_JAVAPOLLER: poller_type = ZBX_POLLER_TYPE_JAVA; thread_args.args = &poller_type; zbx_thread_start(poller_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_SNMPTRAPPER: zbx_thread_start(snmptrapper_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_PROXYPOLLER: zbx_thread_start(proxypoller_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_SELFMON: zbx_thread_start(selfmon_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_VMWARE: zbx_thread_start(vmware_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_TASKMANAGER: zbx_thread_start(taskmanager_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_PREPROCMAN: zbx_thread_start(preprocessing_manager_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_PREPROCESSOR: zbx_thread_start(preprocessing_worker_thread, &thread_args, &threads[i]); break; #ifdef HAVE_OPENIPMI case ZBX_PROCESS_TYPE_IPMIMANAGER: zbx_thread_start(ipmi_manager_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_IPMIPOLLER: zbx_thread_start(ipmi_poller_thread, &thread_args, &threads[i]); break; #endif case ZBX_PROCESS_TYPE_ALERTMANAGER: zbx_thread_start(alert_manager_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_LLDMANAGER: zbx_thread_start(lld_manager_thread, &thread_args, &threads[i]); break; case ZBX_PROCESS_TYPE_LLDWORKER: zbx_thread_start(lld_worker_thread, &thread_args, &threads[i]); break; } } if (SUCCEED == zbx_is_export_enabled()) { zbx_history_export_init("main-process", 0); zbx_problems_export_init("main-process", 0); } while (-1 == wait(&i)) /* wait for any child to exit */ { if (EINTR != errno) { zabbix_log(LOG_LEVEL_ERR, "failed to wait on child processes: %s", zbx_strerror(errno)); break; } } /* all exiting child processes should be caught by signal handlers */ THIS_SHOULD_NEVER_HAPPEN; zbx_on_exit(); return SUCCEED; }
/****************************************************************************** * * * Function: send_list_of_active_checks_json * * * * Purpose: send list of active checks to the host * * * * Parameters: sock - open socket of server-agent connection * * json - request buffer * * * * Return value: SUCCEED - list of active checks sent successfully * * FAIL - an error occurred * * * * Author: Alexander Vladishev * * * * Comments: * * * ******************************************************************************/ int send_list_of_active_checks_json(zbx_socket_t *sock, struct zbx_json_parse *jp) { const char *__function_name = "send_list_of_active_checks_json"; char host[HOST_HOST_LEN_MAX], tmp[MAX_STRING_LEN], ip[INTERFACE_IP_LEN_MAX], error[MAX_STRING_LEN], *host_metadata = NULL; struct zbx_json json; int ret = FAIL, i; zbx_uint64_t hostid; size_t host_metadata_alloc = 1; /* for at least NUL-termination char */ unsigned short port; zbx_vector_uint64_t itemids; zbx_vector_ptr_t regexps; zbx_vector_str_t names; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); zbx_vector_ptr_create(®exps); zbx_vector_str_create(&names); if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_HOST, host, sizeof(host))) { zbx_snprintf(error, MAX_STRING_LEN, "%s", zbx_json_strerror()); goto error; } host_metadata = zbx_malloc(host_metadata, host_metadata_alloc); if (FAIL == zbx_json_value_by_name_dyn(jp, ZBX_PROTO_TAG_HOST_METADATA, &host_metadata, &host_metadata_alloc)) { *host_metadata = '\0'; } if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_IP, ip, sizeof(ip))) strscpy(ip, sock->peer); if (FAIL == zbx_json_value_by_name(jp, ZBX_PROTO_TAG_PORT, tmp, sizeof(tmp))) *tmp = '\0'; if (FAIL == is_ushort(tmp, &port)) port = ZBX_DEFAULT_AGENT_PORT; if (FAIL == get_hostid_by_host(sock, host, ip, port, host_metadata, &hostid, error)) goto error; zbx_vector_uint64_create(&itemids); get_list_of_active_checks(hostid, &itemids); zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN); zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING); zbx_json_addarray(&json, ZBX_PROTO_TAG_DATA); if (0 != itemids.values_num) { DC_ITEM *dc_items; int *errcodes, now; zbx_config_t cfg; dc_items = zbx_malloc(NULL, sizeof(DC_ITEM) * itemids.values_num); errcodes = zbx_malloc(NULL, sizeof(int) * itemids.values_num); DCconfig_get_items_by_itemids(dc_items, itemids.values, errcodes, itemids.values_num); zbx_config_get(&cfg, ZBX_CONFIG_FLAGS_REFRESH_UNSUPPORTED); now = time(NULL); for (i = 0; i < itemids.values_num; i++) { if (SUCCEED != errcodes[i]) { zabbix_log(LOG_LEVEL_DEBUG, "%s() Item [" ZBX_FS_UI64 "] was not found in the" " server cache. Not sending now.", __function_name, itemids.values[i]); continue; } if (ITEM_STATUS_ACTIVE != dc_items[i].status) continue; if (HOST_STATUS_MONITORED != dc_items[i].host.status) continue; if (ITEM_STATE_NOTSUPPORTED == dc_items[i].state) { if (0 == cfg.refresh_unsupported) continue; if (dc_items[i].lastclock + cfg.refresh_unsupported > now) continue; } dc_items[i].key = zbx_strdup(dc_items[i].key, dc_items[i].key_orig); substitute_key_macros(&dc_items[i].key, NULL, &dc_items[i], NULL, MACRO_TYPE_ITEM_KEY, NULL, 0); zbx_json_addobject(&json, NULL); zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY, dc_items[i].key, ZBX_JSON_TYPE_STRING); if (0 != strcmp(dc_items[i].key, dc_items[i].key_orig)) { zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY_ORIG, dc_items[i].key_orig, ZBX_JSON_TYPE_STRING); } zbx_json_adduint64(&json, ZBX_PROTO_TAG_DELAY, dc_items[i].delay); /* The agent expects ALWAYS to have lastlogsize and mtime tags. */ /* Removing those would cause older agents to fail. */ zbx_json_adduint64(&json, ZBX_PROTO_TAG_LASTLOGSIZE, dc_items[i].lastlogsize); zbx_json_adduint64(&json, ZBX_PROTO_TAG_MTIME, dc_items[i].mtime); zbx_json_close(&json); zbx_itemkey_extract_global_regexps(dc_items[i].key, &names); zbx_free(dc_items[i].key); } zbx_config_clean(&cfg); DCconfig_clean_items(dc_items, errcodes, itemids.values_num); zbx_free(errcodes); zbx_free(dc_items); } zbx_vector_uint64_destroy(&itemids); zbx_json_close(&json); DCget_expressions_by_names(®exps, (const char * const *)names.values, names.values_num); if (0 < regexps.values_num) { char buffer[32]; zbx_json_addarray(&json, ZBX_PROTO_TAG_REGEXP); for (i = 0; i < regexps.values_num; i++) { zbx_expression_t *regexp = regexps.values[i]; zbx_json_addobject(&json, NULL); zbx_json_addstring(&json, "name", regexp->name, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json, "expression", regexp->expression, ZBX_JSON_TYPE_STRING); zbx_snprintf(buffer, sizeof(buffer), "%d", regexp->expression_type); zbx_json_addstring(&json, "expression_type", buffer, ZBX_JSON_TYPE_INT); zbx_snprintf(buffer, sizeof(buffer), "%c", regexp->exp_delimiter); zbx_json_addstring(&json, "exp_delimiter", buffer, ZBX_JSON_TYPE_STRING); zbx_snprintf(buffer, sizeof(buffer), "%d", regexp->case_sensitive); zbx_json_addstring(&json, "case_sensitive", buffer, ZBX_JSON_TYPE_INT); zbx_json_close(&json); } zbx_json_close(&json); } zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __function_name, json.buffer); zbx_alarm_on(CONFIG_TIMEOUT); if (SUCCEED != zbx_tcp_send(sock, json.buffer)) strscpy(error, zbx_socket_strerror()); else ret = SUCCEED; zbx_alarm_off(); zbx_json_free(&json); goto out; error: zabbix_log(LOG_LEVEL_WARNING, "cannot send list of active checks to \"%s\": %s", sock->peer, error); zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN); zbx_json_addstring(&json, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING); zbx_json_addstring(&json, ZBX_PROTO_TAG_INFO, error, ZBX_JSON_TYPE_STRING); zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __function_name, json.buffer); ret = zbx_tcp_send(sock, json.buffer); zbx_json_free(&json); out: for (i = 0; i < names.values_num; i++) zbx_free(names.values[i]); zbx_vector_str_destroy(&names); zbx_regexp_clean_expressions(®exps); zbx_vector_ptr_destroy(®exps); zbx_free(host_metadata); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/****************************************************************************** * * * Function: get_value * * * * Purpose: connect to Zabbix agent, receive and print value * * * * Parameters: host - server name or IP address * * port - port number * * key - item's key * * * ******************************************************************************/ static int get_value(const char *source_ip, const char *host, unsigned short port, const char *key) { zbx_socket_t s; int ret; ssize_t bytes_received = -1; char *tls_arg1, *tls_arg2; switch (configured_tls_connect_mode) { case ZBX_TCP_SEC_UNENCRYPTED: tls_arg1 = NULL; tls_arg2 = NULL; break; #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) case ZBX_TCP_SEC_TLS_CERT: tls_arg1 = CONFIG_TLS_SERVER_CERT_ISSUER; tls_arg2 = CONFIG_TLS_SERVER_CERT_SUBJECT; break; case ZBX_TCP_SEC_TLS_PSK: tls_arg1 = CONFIG_TLS_PSK_IDENTITY; tls_arg2 = NULL; /* zbx_tls_connect() will find PSK */ break; #endif default: THIS_SHOULD_NEVER_HAPPEN; return FAIL; } if (SUCCEED == (ret = zbx_tcp_connect(&s, source_ip, host, port, GET_SENDER_TIMEOUT, configured_tls_connect_mode, tls_arg1, tls_arg2))) { if (SUCCEED == (ret = zbx_tcp_send(&s, key))) { if (0 < (bytes_received = zbx_tcp_recv_ext(&s, 0))) { if (0 == strcmp(s.buffer, ZBX_NOTSUPPORTED) && sizeof(ZBX_NOTSUPPORTED) < s.read_bytes) { zbx_rtrim(s.buffer + sizeof(ZBX_NOTSUPPORTED), "\r\n"); printf("%s: %s\n", s.buffer, s.buffer + sizeof(ZBX_NOTSUPPORTED)); } else { zbx_rtrim(s.buffer, "\r\n"); printf("%s\n", s.buffer); } } else { if (0 == bytes_received) zbx_error("Check access restrictions in Zabbix agent configuration"); ret = FAIL; } } zbx_tcp_close(&s); if (SUCCEED != ret && 0 != bytes_received) { zbx_error("Get value error: %s", zbx_socket_strerror()); zbx_error("Check access restrictions in Zabbix agent configuration"); } } else zbx_error("Get value error: %s", zbx_socket_strerror()); return ret; }
/* example ssh.run["ls /"] */ static int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding) { const char *__function_name = "ssh_run"; zbx_socket_t s; LIBSSH2_SESSION *session; LIBSSH2_CHANNEL *channel; int auth_pw = 0, rc, ret = NOTSUPPORTED, exitcode, bytecount = 0; char buffer[MAX_BUFFER_LEN], buf[16], *userauthlist, *publickey = NULL, *privatekey = NULL, *ssherr; size_t sz; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (FAIL == zbx_tcp_connect(&s, CONFIG_SOURCE_IP, item->interface.addr, item->interface.port, 0, ZBX_TCP_SEC_UNENCRYPTED, NULL, NULL)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot connect to SSH server: %s", zbx_socket_strerror())); goto close; } /* initializes an SSH session object */ if (NULL == (session = libssh2_session_init())) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot initialize SSH session")); goto tcp_close; } /* set blocking mode on session */ libssh2_session_set_blocking(session, 1); /* Create a session instance and start it up. This will trade welcome */ /* banners, exchange keys, and setup crypto, compression, and MAC layers */ if (0 != libssh2_session_startup(session, s.socket)) { libssh2_session_last_error(session, &ssherr, NULL, 0); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot establish SSH session: %s", ssherr)); goto session_free; } /* check what authentication methods are available */ if (NULL != (userauthlist = libssh2_userauth_list(session, item->username, strlen(item->username)))) { if (NULL != strstr(userauthlist, "password")) auth_pw |= 1; if (NULL != strstr(userauthlist, "keyboard-interactive")) auth_pw |= 2; if (NULL != strstr(userauthlist, "publickey")) auth_pw |= 4; } else { libssh2_session_last_error(session, &ssherr, NULL, 0); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain authentication methods: %s", ssherr)); goto session_close; } zabbix_log(LOG_LEVEL_DEBUG, "%s() supported authentication methods:'%s'", __function_name, userauthlist); switch (item->authtype) { case ITEM_AUTHTYPE_PASSWORD: if (auth_pw & 1) { /* we could authenticate via password */ if (0 != libssh2_userauth_password(session, item->username, item->password)) { libssh2_session_last_error(session, &ssherr, NULL, 0); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Password authentication failed: %s", ssherr)); goto session_close; } else zabbix_log(LOG_LEVEL_DEBUG, "%s() password authentication succeeded", __function_name); } else if (auth_pw & 2) { /* or via keyboard-interactive */ password = item->password; if (0 != libssh2_userauth_keyboard_interactive(session, item->username, &kbd_callback)) { libssh2_session_last_error(session, &ssherr, NULL, 0); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Keyboard-interactive authentication" " failed: %s", ssherr)); goto session_close; } else zabbix_log(LOG_LEVEL_DEBUG, "%s() keyboard-interactive authentication succeeded", __function_name); } else { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Unsupported authentication method." " Supported methods: %s", userauthlist)); goto session_close; } break; case ITEM_AUTHTYPE_PUBLICKEY: if (auth_pw & 4) { if (NULL == CONFIG_SSH_KEY_LOCATION) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Authentication by public key failed." " SSHKeyLocation option is not set")); goto session_close; } /* or by public key */ publickey = zbx_dsprintf(publickey, "%s/%s", CONFIG_SSH_KEY_LOCATION, item->publickey); privatekey = zbx_dsprintf(privatekey, "%s/%s", CONFIG_SSH_KEY_LOCATION, item->privatekey); if (SUCCEED != zbx_is_regular_file(publickey)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot access public key file %s", publickey)); goto session_close; } if (SUCCEED != zbx_is_regular_file(privatekey)) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot access private key file %s", privatekey)); goto session_close; } rc = libssh2_userauth_publickey_fromfile(session, item->username, publickey, privatekey, item->password); if (0 != rc) { libssh2_session_last_error(session, &ssherr, NULL, 0); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Public key authentication failed:" " %s", ssherr)); goto session_close; } else zabbix_log(LOG_LEVEL_DEBUG, "%s() authentication by public key succeeded", __function_name); } else { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Unsupported authentication method." " Supported methods: %s", userauthlist)); goto session_close; } break; } /* exec non-blocking on the remove host */ while (NULL == (channel = libssh2_channel_open_session(session))) { switch (libssh2_session_last_error(session, NULL, NULL, 0)) { /* marked for non-blocking I/O but the call would block. */ case LIBSSH2_ERROR_EAGAIN: waitsocket(s.socket, session); continue; default: SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot establish generic session channel")); goto session_close; } } dos2unix(item->params); /* CR+LF (Windows) => LF (Unix) */ /* request a shell on a channel and execute command */ while (0 != (rc = libssh2_channel_exec(channel, item->params))) { switch (rc) { case LIBSSH2_ERROR_EAGAIN: waitsocket(s.socket, session); continue; default: SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot request a shell")); goto channel_close; } } for (;;) { /* loop until we block */ do { if (0 < (rc = libssh2_channel_read(channel, buf, sizeof(buf)))) { sz = (size_t)rc; if (sz > (size_t)(MAX_BUFFER_LEN - (bytecount + 1))) sz = (size_t)(MAX_BUFFER_LEN - (bytecount + 1)); if (0 == sz) continue; memcpy(buffer + bytecount, buf, sz); bytecount += sz; } } while (rc > 0); /* this is due to blocking that would occur otherwise so we loop on * this condition */ if (LIBSSH2_ERROR_EAGAIN == rc) waitsocket(s.socket, session); else if (rc < 0) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot read data from SSH server")); goto channel_close; } else break; } buffer[bytecount] = '\0'; SET_STR_RESULT(result, convert_to_utf8(buffer, bytecount, encoding)); ret = SYSINFO_RET_OK; channel_close: /* close an active data channel */ exitcode = 127; while (LIBSSH2_ERROR_EAGAIN == (rc = libssh2_channel_close(channel))) waitsocket(s.socket, session); if (0 != rc) { libssh2_session_last_error(session, &ssherr, NULL, 0); zabbix_log(LOG_LEVEL_WARNING, "%s() cannot close generic session channel: %s", __function_name, ssherr); } else exitcode = libssh2_channel_get_exit_status(channel); zabbix_log(LOG_LEVEL_DEBUG, "%s() exitcode:%d bytecount:%d", __function_name, exitcode, bytecount); libssh2_channel_free(channel); channel = NULL; session_close: libssh2_session_disconnect(session, "Normal Shutdown"); session_free: libssh2_session_free(session); tcp_close: zbx_tcp_close(&s); close: zbx_free(publickey); zbx_free(privatekey); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
static int send_email_plain(const char *smtp_server, unsigned short smtp_port, const char *smtp_helo, const char *from_display_name, const char *from_angle_addr, const char *to_display_name, const char *to_angle_addr, const char *mailsubject, const char *mailbody, int timeout, char *error, size_t max_error_len) { zbx_socket_t s; int err, ret = FAIL; char cmd[MAX_STRING_LEN], *cmdp = NULL; const char *OK_220 = "220"; const char *OK_250 = "250"; const char *OK_251 = "251"; const char *OK_354 = "354"; const char *response; alarm(timeout); /* connect to and receive an initial greeting from SMTP server */ if (FAIL == zbx_tcp_connect(&s, CONFIG_SOURCE_IP, smtp_server, smtp_port, 0)) { zbx_snprintf(error, max_error_len, "cannot connect to SMTP server \"%s\": %s", smtp_server, zbx_socket_strerror()); goto out; } if (FAIL == smtp_readln(&s, &response)) { zbx_snprintf(error, max_error_len, "error receiving initial string from SMTP server: %s", zbx_strerror(errno)); goto close; } if (0 != strncmp(response, OK_220, strlen(OK_220))) { zbx_snprintf(error, max_error_len, "no welcome message 220* from SMTP server \"%s\"", response); goto close; } /* send HELO */ if ('\0' != *smtp_helo) { zbx_snprintf(cmd, sizeof(cmd), "HELO %s\r\n", smtp_helo); if (-1 == write(s.socket, cmd, strlen(cmd))) { zbx_snprintf(error, max_error_len, "error sending HELO to mailserver: %s", zbx_strerror(errno)); goto close; } if (FAIL == smtp_readln(&s, &response)) { zbx_snprintf(error, max_error_len, "error receiving answer on HELO request: %s", zbx_strerror(errno)); goto close; } if (0 != strncmp(response, OK_250, strlen(OK_250))) { zbx_snprintf(error, max_error_len, "wrong answer on HELO \"%s\"", response); goto close; } } /* send MAIL FROM */ zbx_snprintf(cmd, sizeof(cmd), "MAIL FROM:%s\r\n", from_angle_addr); if (-1 == write(s.socket, cmd, strlen(cmd))) { zbx_snprintf(error, max_error_len, "error sending MAIL FROM to mailserver: %s", zbx_strerror(errno)); goto close; } if (FAIL == smtp_readln(&s, &response)) { zbx_snprintf(error, max_error_len, "error receiving answer on MAIL FROM request: %s", zbx_strerror(errno)); goto close; } if (0 != strncmp(response, OK_250, strlen(OK_250))) { zbx_snprintf(error, max_error_len, "wrong answer on MAIL FROM \"%s\"", response); goto close; } /* send RCPT TO */ zbx_snprintf(cmd, sizeof(cmd), "RCPT TO:%s\r\n", to_angle_addr); if (-1 == write(s.socket, cmd, strlen(cmd))) { zbx_snprintf(error, max_error_len, "error sending RCPT TO to mailserver: %s", zbx_strerror(errno)); goto close; } if (FAIL == smtp_readln(&s, &response)) { zbx_snprintf(error, max_error_len, "error receiving answer on RCPT TO request: %s", zbx_strerror(errno)); goto close; } /* May return 251 as well: User not local; will forward to <forward-path>. See RFC825. */ if (0 != strncmp(response, OK_250, strlen(OK_250)) && 0 != strncmp(response, OK_251, strlen(OK_251))) { zbx_snprintf(error, max_error_len, "wrong answer on RCPT TO \"%s\"", response); goto close; } /* send DATA */ zbx_snprintf(cmd, sizeof(cmd), "DATA\r\n"); if (-1 == write(s.socket, cmd, strlen(cmd))) { zbx_snprintf(error, max_error_len, "error sending DATA to mailserver: %s", zbx_strerror(errno)); goto close; } if (FAIL == smtp_readln(&s, &response)) { zbx_snprintf(error, max_error_len, "error receiving answer on DATA request: %s", zbx_strerror(errno)); goto close; } if (0 != strncmp(response, OK_354, strlen(OK_354))) { zbx_snprintf(error, max_error_len, "wrong answer on DATA \"%s\"", response); goto close; } cmdp = smtp_prepare_payload(from_display_name, from_angle_addr, to_display_name, to_angle_addr, mailsubject, mailbody); err = write(s.socket, cmdp, strlen(cmdp)); zbx_free(cmdp); if (-1 == err) { zbx_snprintf(error, max_error_len, "error sending headers and mail body to mailserver: %s", zbx_strerror(errno)); goto close; } /* send . */ zbx_snprintf(cmd, sizeof(cmd), "\r\n.\r\n"); if (-1 == write(s.socket, cmd, strlen(cmd))) { zbx_snprintf(error, max_error_len, "error sending . to mailserver: %s", zbx_strerror(errno)); goto close; } if (FAIL == smtp_readln(&s, &response)) { zbx_snprintf(error, max_error_len, "error receiving answer on . request: %s", zbx_strerror(errno)); goto close; } if (0 != strncmp(response, OK_250, strlen(OK_250))) { zbx_snprintf(error, max_error_len, "wrong answer on end of data \"%s\"", response); goto close; } /* send QUIT */ zbx_snprintf(cmd, sizeof(cmd), "QUIT\r\n"); if (-1 == write(s.socket, cmd, strlen(cmd))) { zbx_snprintf(error, max_error_len, "error sending QUIT to mailserver: %s", zbx_strerror(errno)); goto close; } ret = SUCCEED; close: zbx_tcp_close(&s); out: alarm(0); return ret; }
/****************************************************************************** * * * Function: get_value_agent * * * * Purpose: retrieve data from Zabbix agent * * * * Parameters: item - item we are interested in * * * * Return value: SUCCEED - data successfully retrieved and stored in result * * and result_str (as string) * * NETWORK_ERROR - network related error occurred * * NOTSUPPORTED - item not supported by the agent * * AGENT_ERROR - uncritical error on agent side occurred * * FAIL - otherwise * * * * Author: Alexei Vladishev * * * * Comments: error will contain error message * * * ******************************************************************************/ int get_value_agent(DC_ITEM *item, AGENT_RESULT *result) { const char *__function_name = "get_value_agent"; zbx_socket_t s; char buffer[MAX_STRING_LEN]; int ret = SUCCEED; ssize_t received_len; zabbix_log(LOG_LEVEL_DEBUG, "In %s() host:'%s' addr:'%s' key:'%s'", __function_name, item->host.host, item->interface.addr, item->key); if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, item->interface.addr, item->interface.port, 0))) { zbx_snprintf(buffer, sizeof(buffer), "%s\n", item->key); zabbix_log(LOG_LEVEL_DEBUG, "Sending [%s]", buffer); /* send requests using old protocol */ if (SUCCEED != zbx_tcp_send_raw(&s, buffer)) ret = NETWORK_ERROR; else if (FAIL != (received_len = zbx_tcp_recv_ext(&s, ZBX_TCP_READ_UNTIL_CLOSE, 0))) ret = SUCCEED; else ret = TIMEOUT_ERROR; } else ret = NETWORK_ERROR; if (SUCCEED == ret) { zbx_rtrim(s.buffer, " \r\n"); zbx_ltrim(s.buffer, " "); zabbix_log(LOG_LEVEL_DEBUG, "get value from agent result: '%s'", s.buffer); if (0 == strcmp(s.buffer, ZBX_NOTSUPPORTED)) { /* 'ZBX_NOTSUPPORTED\0<error message>' */ if (sizeof(ZBX_NOTSUPPORTED) < s.read_bytes) zbx_snprintf(buffer, sizeof(buffer), "%s", s.buffer + sizeof(ZBX_NOTSUPPORTED)); else zbx_snprintf(buffer, sizeof(buffer), "Not supported by Zabbix Agent"); SET_MSG_RESULT(result, strdup(buffer)); ret = NOTSUPPORTED; } else if (0 == strcmp(s.buffer, ZBX_ERROR)) { zbx_snprintf(buffer, sizeof(buffer), "Zabbix Agent non-critical error"); SET_MSG_RESULT(result, strdup(buffer)); ret = AGENT_ERROR; } else if (0 == received_len) { zbx_snprintf(buffer, sizeof(buffer), "Received empty response from Zabbix Agent at [%s]." " Assuming that agent dropped connection because of access permissions.", item->interface.addr); SET_MSG_RESULT(result, strdup(buffer)); ret = NETWORK_ERROR; } else if (SUCCEED != set_result_type(result, item->value_type, item->data_type, s.buffer)) ret = NOTSUPPORTED; } else { zbx_snprintf(buffer, sizeof(buffer), "Get value from agent failed: %s", zbx_socket_strerror()); SET_MSG_RESULT(result, strdup(buffer)); } zbx_tcp_close(&s); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
int zbx_module_nginx_status(AGENT_REQUEST *request, AGENT_RESULT *result) { char *CONFIG_SOURCE_IP = NULL; zbx_socket_t s; char *key; const char *buf; int ret = SYSINFO_RET_FAIL; int find = 0; int net_error = 0; char r[MAX_STRING_LEN]; zbx_uint64_t ac = 0; /* current number of active client connections */ zbx_uint64_t rd = 0; /* current number of connections where nginx is reading the request header */ zbx_uint64_t wr = 0; /* current number of connections where nginx is writing the response back to the client */ zbx_uint64_t wa = 0; /* current number of idle client connections waiting for a request */ if (request->nparam == 1) { key = get_rparam(request, 0); } else { /* set optional error message */ SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters")); return ret; } /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [nginx], func [zbx_module_nginx_status], request key:[%s]", key); */ if (SUCCEED == zbx_tcp_connect(&s, CONFIG_SOURCE_IP, CONFIG_NGINX_HOST, (unsigned short)CONFIG_NGINX_PORT, 0, ZBX_TCP_SEC_UNENCRYPTED, NULL, NULL)) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [nginx], func [zbx_module_nginx_status], connect to [%s:%d] successful", CONFIG_NGINX_HOST, CONFIG_NGINX_PORT); */ if (NULL == CONFIG_NGINX_DOMAIN) { zbx_snprintf(r, sizeof(r), "GET /%s HTTP/1.1\r\n" "Host: %s\r\n" "Connection: close\r\n" "\r\n", CONFIG_NGINX_STATUS_URI, CONFIG_NGINX_HOST); } else { zbx_snprintf(r, sizeof(r), "GET /%s HTTP/1.1\r\n" "Host: %s\r\n" "Connection: close\r\n" "\r\n", CONFIG_NGINX_STATUS_URI, CONFIG_NGINX_DOMAIN); } /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [nginx], func [zbx_module_nginx_status], r:[%s]", r); */ if (SUCCEED == zbx_tcp_send_raw(&s, r)) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [nginx], func [zbx_module_nginx_status], send request successful"); */ while (NULL != (buf = zbx_tcp_recv_line(&s))) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [nginx], func [zbx_module_nginx_status], got [%s]", buf); */ if (0 == strcmp(key, "ac") && 0 == strncmp(buf, "Active connections", 18)) { if(1 == sscanf(buf, "%*s" "%*s" ZBX_FS_UI64, &ac)) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [nginx], func [zbx_module_nginx_status], key:[%s] value:[%d]", key, ac); */ find = 1; SET_UI64_RESULT(result, ac); ret = SYSINFO_RET_OK; } } else if (0 == strcmp(key, "rd") && 3 == sscanf(buf, "%*s" ZBX_FS_UI64 "%*s" ZBX_FS_UI64 "%*s" ZBX_FS_UI64, &rd, &wr, &wa)) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [nginx], func [zbx_module_nginx_status], key:[%s] value:[%d]", key, rd); */ find = 1; SET_UI64_RESULT(result, rd); ret = SYSINFO_RET_OK; } else if (0 == strcmp(key, "wr") && 3 == sscanf(buf, "%*s" ZBX_FS_UI64 "%*s" ZBX_FS_UI64 "%*s" ZBX_FS_UI64, &rd, &wr, &wa)) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [nginx], func [zbx_module_nginx_status], key:[%s] value:[%d]", key, wr); */ find = 1; SET_UI64_RESULT(result, wr); ret = SYSINFO_RET_OK; } else if (0 == strcmp(key, "wa") && 3 == sscanf(buf, "%*s" ZBX_FS_UI64 "%*s" ZBX_FS_UI64 "%*s" ZBX_FS_UI64, &rd, &wr, &wa)) { /* for dev zabbix_log(LOG_LEVEL_INFORMATION, "module [nginx], func [zbx_module_nginx_status], key:[%s] value:[%d]", key, wa); */ find = 1; SET_UI64_RESULT(result, wa); ret = SYSINFO_RET_OK; } } } else { net_error = 1; zabbix_log(LOG_LEVEL_WARNING, "module [nginx], func [zbx_module_nginx_status], get nginx status error: [%s]", zbx_socket_strerror()); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Get nginx status error [%s]", zbx_socket_strerror())); } zbx_tcp_close(&s); } else { net_error = 1; zabbix_log(LOG_LEVEL_WARNING, "module [nginx], func [zbx_module_nginx_status], get nginx status error: [%s]", zbx_socket_strerror()); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Get nginx status error [%s]", zbx_socket_strerror())); } if (1 != find && 0 == net_error) { zabbix_log(LOG_LEVEL_WARNING, "module [nginx], func [zbx_module_nginx_status], not supported key: [%s]", key); SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Not supported key [%s]", key)); } return ret; }
/****************************************************************************** * * * Function: send_list_of_active_checks * * * * Purpose: send list of active checks to the host (older version agent) * * * * Parameters: sock - open socket of server-agent connection * * request - request buffer * * * * Return value: SUCCEED - list of active checks sent successfully * * FAIL - an error occurred * * * * Comments: format of the request: ZBX_GET_ACTIVE_CHECKS\n<host name>\n * * format of the list: key:delay:last_log_size * * * ******************************************************************************/ int send_list_of_active_checks(zbx_socket_t *sock, char *request) { const char *__function_name = "send_list_of_active_checks"; char *host = NULL, *p, *buffer = NULL, error[MAX_STRING_LEN]; size_t buffer_alloc = 8 * ZBX_KIBIBYTE, buffer_offset = 0; int ret = FAIL, i; zbx_uint64_t hostid; zbx_vector_uint64_t itemids; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); if (NULL != (host = strchr(request, '\n'))) { host++; if (NULL != (p = strchr(host, '\n'))) *p = '\0'; } else { zbx_snprintf(error, sizeof(error), "host is null"); goto out; } /* no host metadata in older versions of agent */ if (FAIL == get_hostid_by_host(sock, host, sock->peer, ZBX_DEFAULT_AGENT_PORT, "", &hostid, error)) goto out; zbx_vector_uint64_create(&itemids); get_list_of_active_checks(hostid, &itemids); buffer = zbx_malloc(buffer, buffer_alloc); if (0 != itemids.values_num) { DC_ITEM *dc_items; int *errcodes, now; zbx_config_t cfg; dc_items = zbx_malloc(NULL, sizeof(DC_ITEM) * itemids.values_num); errcodes = zbx_malloc(NULL, sizeof(int) * itemids.values_num); DCconfig_get_items_by_itemids(dc_items, itemids.values, errcodes, itemids.values_num); zbx_config_get(&cfg, ZBX_CONFIG_FLAGS_REFRESH_UNSUPPORTED); now = time(NULL); for (i = 0; i < itemids.values_num; i++) { if (SUCCEED != errcodes[i]) { zabbix_log(LOG_LEVEL_DEBUG, "%s() Item [" ZBX_FS_UI64 "] was not found in the" " server cache. Not sending now.", __function_name, itemids.values[i]); continue; } if (ITEM_STATUS_ACTIVE != dc_items[i].status) continue; if (HOST_STATUS_MONITORED != dc_items[i].host.status) continue; if (ITEM_STATE_NOTSUPPORTED == dc_items[i].state) { if (0 == cfg.refresh_unsupported) continue; if (dc_items[i].lastclock + cfg.refresh_unsupported > now) continue; } zbx_snprintf_alloc(&buffer, &buffer_alloc, &buffer_offset, "%s:%d:" ZBX_FS_UI64 "\n", dc_items[i].key_orig, dc_items[i].delay, dc_items[i].lastlogsize); } zbx_config_clean(&cfg); DCconfig_clean_items(dc_items, errcodes, itemids.values_num); zbx_free(errcodes); zbx_free(dc_items); } zbx_vector_uint64_destroy(&itemids); zbx_strcpy_alloc(&buffer, &buffer_alloc, &buffer_offset, "ZBX_EOF\n"); zabbix_log(LOG_LEVEL_DEBUG, "%s() sending [%s]", __function_name, buffer); zbx_alarm_on(CONFIG_TIMEOUT); if (SUCCEED != zbx_tcp_send_raw(sock, buffer)) zbx_strlcpy(error, zbx_socket_strerror(), MAX_STRING_LEN); else ret = SUCCEED; zbx_alarm_off(); zbx_free(buffer); out: if (FAIL == ret) zabbix_log(LOG_LEVEL_WARNING, "cannot send list of active checks to \"%s\": %s", sock->peer, error); zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
ZBX_THREAD_ENTRY(listener_thread, args) { #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) char *msg = NULL; #endif int ret; zbx_socket_t s; assert(args); assert(((zbx_thread_args_t *)args)->args); 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)); zbx_free(args); #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) zbx_tls_init_child(); #endif while (ZBX_IS_RUNNING()) { zbx_setproctitle("listener #%d [waiting for connection]", process_num); ret = zbx_tcp_accept(&s, configured_tls_accept_modes); zbx_update_env(zbx_time()); if (SUCCEED == ret) { zbx_setproctitle("listener #%d [processing request]", process_num); if ('\0' != *CONFIG_HOSTS_ALLOWED && SUCCEED == (ret = zbx_tcp_check_allowed_peers(&s, CONFIG_HOSTS_ALLOWED))) { #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) if (ZBX_TCP_SEC_TLS_CERT != s.connection_type || SUCCEED == (ret = zbx_check_server_issuer_subject(&s, &msg))) #endif { process_listener(&s); } } zbx_tcp_unaccept(&s); } if (SUCCEED == ret || EINTR == zbx_socket_last_error()) continue; #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL) if (NULL != msg) { zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s", msg); zbx_free(msg); } else #endif { zabbix_log(LOG_LEVEL_WARNING, "failed to accept an incoming connection: %s", zbx_socket_strerror()); } if (ZBX_IS_RUNNING()) zbx_sleep(1); } #ifdef _WINDOWS ZBX_DO_EXIT(); zbx_thread_exit(EXIT_SUCCESS); #endif }