Example #1
0
File: nodecomms.c Project: Shmuma/z
/******************************************************************************
 *                                                                            *
 * Function: send_to_node                                                     *
 *                                                                            *
 * Purpose: send configuration changes to required node                       *
 *                                                                            *
 * Parameters:                                                                *
 *                                                                            *
 * Return value: SUCCESS - processed succesfully                              * 
 *               FAIL - an error occured                                      *
 *                                                                            *
 * Author: Alexei Vladishev                                                   *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
int send_to_node(char *name, int dest_nodeid, int nodeid, char *data)
{
	char	ip[MAX_STRING_LEN];
	int	port;
	int	ret = FAIL;

	DB_RESULT	result;
	DB_ROW		row;

	zbx_sock_t	sock;
	char		*answer;

	zabbix_log( LOG_LEVEL_WARNING, "NODE: Sending %s to node %s:%d datalen %d",
		name,
		CONFIG_MASTER_IP, CONFIG_MASTER_PORT,
		strlen(data));
/*	zabbix_log( LOG_LEVEL_WARNING, "Data [%s]", data);*/

	if( FAIL == zbx_tcp_connect(&sock, CONFIG_MASTER_IP, CONFIG_MASTER_PORT, 0, NULL))
	{
		zabbix_log(LOG_LEVEL_DEBUG, "Unable to connect to Node [%s:%d] error: %s", CONFIG_MASTER_IP, CONFIG_MASTER_PORT, zbx_tcp_strerror());
		return  FAIL;
	}


	if( FAIL == zbx_tcp_send(&sock, data))
	{
		zabbix_log( LOG_LEVEL_WARNING, "Error while sending data to Node [%s:%d]",
			CONFIG_MASTER_IP, CONFIG_MASTER_PORT);
		zbx_tcp_close(&sock);
		return  FAIL;
	}

	if( FAIL == zbx_tcp_recv(&sock, &answer))
	{
		zabbix_log( LOG_LEVEL_WARNING, "Error while receiving answer from Node [%s:%d]",
			CONFIG_MASTER_IP, CONFIG_MASTER_PORT);
		zbx_tcp_close(&sock);
		return  FAIL;
	}

	zabbix_log( LOG_LEVEL_DEBUG, "Answer [%s]",
		answer);

	if(strcmp(answer,"OK") == 0)
	{
		zabbix_log( LOG_LEVEL_DEBUG, "OK");
		ret = SUCCEED;
	}
	else
	{
		zabbix_log( LOG_LEVEL_WARNING, "NOT OK");
	}

	zbx_tcp_close(&sock);

	return ret;
}
/*
 * Example: telnet.run["ls /"]
 */
static int	telnet_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding)
{
	const char	*__function_name = "telnet_run";
	zbx_sock_t	s;
	int		ret = NOTSUPPORTED, flags;

	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))
	{
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "cannot connect to TELNET server: %s", zbx_tcp_strerror()));
		goto close;
	}

	flags = fcntl(s.socket, F_GETFL);
	if (0 == (flags & O_NONBLOCK))
		fcntl(s.socket, F_SETFL, flags | O_NONBLOCK);

	if (FAIL == telnet_login(s.socket, item->username, item->password, result))
		goto tcp_close;

	if (FAIL == telnet_execute(s.socket, item->params, result, encoding))
		goto tcp_close;

	ret = SUCCEED;
tcp_close:
	zbx_tcp_close(&s);
close:
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

	return ret;
}
Example #3
0
static int	check_ssh(const char *host, unsigned short port, int timeout, int *value_int)
{
	int		ret;
	zbx_sock_t	s;
	char		send_buf[MAX_STRING_LEN], *recv_buf, *ssh_server, *ssh_proto;

	*value_int = 0;

	if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port, timeout)))
	{
		if (SUCCEED == (ret = zbx_tcp_recv(&s, &recv_buf)))
		{
			if (0 == strncmp(recv_buf, "SSH", 3))
			{
				ssh_server = ssh_proto = recv_buf + 4;
				ssh_server += strspn(ssh_proto, "0123456789-. ");
				ssh_server[-1] = '\0';

				zbx_snprintf(send_buf, sizeof(send_buf), "SSH-%s-%s\n", ssh_proto, "zabbix_agent");
				*value_int = 1;
			}
			else
				zbx_snprintf(send_buf, sizeof(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_tcp_strerror());

	return SYSINFO_RET_OK;
}
Example #4
0
int	zbx_tcp_connect(zbx_sock_t *s, const char *source_ip, const char *ip, unsigned short port, int timeout)
{
	ZBX_SOCKADDR	servaddr_in, source_addr;
	struct hostent	*hp;

	ZBX_TCP_START();

	zbx_tcp_clean(s);

	if (NULL == (hp = gethostbyname(ip)))
	{
#if defined(_WINDOWS)
		zbx_set_tcp_strerror("gethostbyname() failed for '%s': %s", ip, strerror_from_system(WSAGetLastError()));
#elif defined(HAVE_HSTRERROR)
		zbx_set_tcp_strerror("gethostbyname() failed for '%s': [%d] %s", ip, h_errno, hstrerror(h_errno));
#else
		zbx_set_tcp_strerror("gethostbyname() failed for '%s': [%d]", ip, h_errno);
#endif
		return FAIL;
	}

	servaddr_in.sin_family		= AF_INET;
	servaddr_in.sin_addr.s_addr	= ((struct in_addr *)(hp->h_addr))->s_addr;
	servaddr_in.sin_port		= htons(port);

	if (ZBX_SOCK_ERROR == (s->socket = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)))
	{
		zbx_set_tcp_strerror("cannot create socket [[%s]:%d]: %s", ip, port, strerror_from_system(zbx_sock_last_error()));
		return FAIL;
	}

#if !defined(_WINDOWS) && !SOCK_CLOEXEC
	fcntl(s->socket, F_SETFD, FD_CLOEXEC);
#endif

	if (NULL != source_ip)
	{
		source_addr.sin_family		= AF_INET;
		source_addr.sin_addr.s_addr	= inet_addr(source_ip);
		source_addr.sin_port		= 0;

		if (ZBX_TCP_ERROR == bind(s->socket, (struct sockaddr *)&source_addr, sizeof(source_addr)))
		{
			zbx_set_tcp_strerror("bind() failed: %s", strerror_from_system(zbx_sock_last_error()));
			return FAIL;
		}
	}

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

	if (ZBX_TCP_ERROR == connect(s->socket, (struct sockaddr *)&servaddr_in, sizeof(servaddr_in)))
	{
		zbx_set_tcp_strerror("cannot connect to [[%s]:%d]: %s", ip, port, strerror_from_system(zbx_sock_last_error()));
		zbx_tcp_close(s);
		return FAIL;
	}

	return SUCCEED;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
int	check_ntp(char *host, unsigned short port, int timeout, int *value_int)
{
	zbx_sock_t	s;
	int		ret;
	char		*buf = NULL, packet[NTP_PACKET_MIN];
	ntp_data	data;

	*value_int = 0;

	if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port, timeout)))
	{
		make_packet(&data);

		pack_ntp((unsigned char *)packet, sizeof(packet), &data);

		if (SUCCEED == (ret = zbx_tcp_send_raw(&s, packet)))
		{
			if (SUCCEED == (ret = zbx_tcp_recv(&s, &buf)))
			{
				unpack_ntp(&data, (unsigned char *)buf, (int)strlen(buf));
				*value_int = (0 < data.receive ? (int)(data.receive - ZBX_JAN_1970_IN_SEC) : 0);
			}
		}

		zbx_tcp_close(&s);
	}

	if (FAIL == ret)
		zabbix_log(LOG_LEVEL_DEBUG, "NTP check error: %s", zbx_tcp_strerror());

	return SYSINFO_RET_OK;
}
Example #8
0
static void	disconnect_proxy(zbx_socket_t *sock)
{
	const char	*__function_name = "disconnect_proxy";

	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);

	zbx_tcp_close(sock);

	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
}
Example #9
0
int	zbx_tcp_connect(zbx_sock_t *s, const char *source_ip, const char *ip, unsigned short port, int timeout)
{
	ZBX_SOCKADDR	servaddr_in, source_addr;
	struct hostent	*hp;

	ZBX_TCP_START();

	zbx_tcp_clean(s);

	if (NULL == (hp = zbx_gethost(ip)))
		return FAIL;

	servaddr_in.sin_family		= AF_INET;
	servaddr_in.sin_addr.s_addr	= ((struct in_addr *)(hp->h_addr))->s_addr;
	servaddr_in.sin_port		= htons(port);

	if (ZBX_SOCK_ERROR == (s->socket = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)))
	{
		zbx_set_tcp_strerror("Cannot create socket [%s:%d] [%s]", ip, port, strerror_from_system(zbx_sock_last_error()));
		return FAIL;
	}

#if !defined(_WINDOWS) && defined(HAVE_FCNTL_H) && !SOCK_CLOEXEC
	fcntl(s->socket, F_SETFD, FD_CLOEXEC);
#endif

	if (NULL != source_ip)
	{
		source_addr.sin_family		= AF_INET;
		source_addr.sin_addr.s_addr	= inet_addr(source_ip);
		source_addr.sin_port		= 0;

		if (ZBX_TCP_ERROR == bind(s->socket, (struct sockaddr *)&source_addr, sizeof(ZBX_SOCKADDR)))
		{
			zbx_set_tcp_strerror("bind() failed with error %d: %s\n",
					zbx_sock_last_error(),
					strerror_from_system(zbx_sock_last_error()));
			return FAIL;
		}
	}

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

	if (ZBX_TCP_ERROR == connect(s->socket, (struct sockaddr *)&servaddr_in, sizeof(ZBX_SOCKADDR)))
	{
		zbx_set_tcp_strerror("Cannot connect to [%s:%d] [%s]", ip, port, strerror_from_system(zbx_sock_last_error()));
		zbx_tcp_close(s);
		return FAIL;
	}

	return SUCCEED;
}
Example #10
0
int	zbx_module_unifi_proxy(AGENT_REQUEST *request, AGENT_RESULT *result)
{
        int             ret;
        int 		i, p, np;
        zbx_sock_t	s;
        char		send_buf[MAX_STRING_LEN];
	    
        *send_buf='\0';

        np = request->nparam;
	if (9 < request->nparam)
	{
		/* set optional error message */
		SET_MSG_RESULT(result, strdup("So much parameters given."));
		return SYSINFO_RET_FAIL;
	}
        // make request string by concatenate all params
        for (i=0; i < np; i++) 
          {
            strcat(send_buf, get_rparam(request, i));
            p=strlen(send_buf);
            send_buf[p]=(i < (np-1)) ? ',' : '\n';
            send_buf[p+1]='\0';
          }


        // Connect to UniFi Proxy
        // item_timeout or (item_timeout-1) ?
        if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, UNIFI_PROXY_SERVER, UNIFI_PROXY_PORT, CONFIG_TIMEOUT)))
        {
            // Send request
            if (SUCCEED == (ret = zbx_tcp_send_raw(&s, send_buf)))
               {
                  // Recive answer from UniFi Proxy
                  if (SUCCEED == (ret = zbx_tcp_recv(&s))) {
                        zbx_rtrim(s.buffer, "\r\n");
                        SET_STR_RESULT(result, strdup(s.buffer));
                     }
               }
            zbx_tcp_close(&s);
        }

        if (FAIL == ret)
           {
						
		zabbix_log(LOG_LEVEL_DEBUG, "%s: communication error: %s", ZBX_MODULE_NAME, zbx_tcp_strerror());
		SET_MSG_RESULT(result, strdup(zbx_tcp_strerror()));
                return SYSINFO_RET_FAIL;
           }

	return SYSINFO_RET_OK;
}
Example #11
0
void	zbx_mock_test_entry(void **state)
{
#define ZBX_TCP_HEADER_DATALEN_LEN	13

	char		*buffer;
	zbx_socket_t	s;
	ssize_t		received;
	int		expected_ret;

	ZBX_UNUSED(state);

	zbx_mock_assert_result_eq("zbx_tcp_connect() return code", SUCCEED,
			zbx_tcp_connect(&s, NULL, "127.0.0.1", 10050, 0, ZBX_TCP_SEC_UNENCRYPTED, NULL, NULL));

	expected_ret = zbx_mock_str_to_return_code(zbx_mock_get_parameter_string("out.return"));
	received = zbx_tcp_recv_ext(&s, 0);

	if (FAIL == expected_ret)
	{
		zbx_mock_assert_result_eq("zbx_tcp_recv_ext() return code", FAIL, received);
		zbx_tcp_close(&s);
		return;
	}

	zbx_mock_assert_result_eq("zbx_tcp_recv_ext() return code", SUCCEED, SUCCEED_OR_FAIL(received));
	zbx_mock_assert_uint64_eq("Received bytes", zbx_mock_get_parameter_uint64("out.bytes"), received);

	if (0 == received)
		return;

	buffer = zbx_yaml_assemble_binary_sequence("out.fragments", received);

	if (0 != memcmp(buffer + ZBX_TCP_HEADER_DATALEN_LEN, s.buffer, received - ZBX_TCP_HEADER_DATALEN_LEN))
		fail_msg("Received message mismatch expected");

	zbx_tcp_close(&s);
	zbx_free(buffer);
#undef ZBX_TCP_HEADER_DATALEN_LEN
}
Example #12
0
/*
 * 0 - NOT OK
 * 1 - OK
 * */
int	tcp_expect(
		const char		*host,
		unsigned short		port,
		const char		*request,
		const char		*expect,
		const char		*sendtoclose,
		int			*value_int
	   )
{
	zbx_sock_t	s;
	char		*buf;
	int		ret;

	assert(value_int);

	*value_int = 0;

	if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port, 3/*alarm!!!*/))) {
		if( NULL == request )
		{
			*value_int = 1;
		}
		else if( SUCCEED == (ret = zbx_tcp_send_raw(&s, request)) )
		{
			if( NULL == expect )
			{
				*value_int = 1;
			}
			else if( SUCCEED == (ret = zbx_tcp_recv(&s, &buf)) )
			{
				if( 0 == strncmp(buf, expect, strlen(expect)) )
				{
					*value_int = 1;
				}
			}

			if(SUCCEED == ret && NULL != sendtoclose)
			{
				/* ret = (skip errors) */ zbx_tcp_send_raw(&s, sendtoclose);
			}
		}
	}
	zbx_tcp_close(&s);

	if( FAIL == ret )
	{
		zabbix_log(LOG_LEVEL_DEBUG, "TCP expect error: %s", zbx_tcp_strerror());
	}

	return SYSINFO_RET_OK;
}
Example #13
0
File: net.c Project: zabbix/zabbix
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;
}
Example #14
0
/******************************************************************************
 *                                                                            *
 * Function: send_script                                                      *
 *                                                                            *
 * Purpose: sending command to slave node                                     *
 *                                                                            *
 * Return value:  SUCCEED - processed successfully                            *
 *                FAIL - an error occurred                                    *
 *                                                                            *
 ******************************************************************************/
static int	send_script(int nodeid, const char *data, char **result)
{
	DB_RESULT		db_result;
	DB_ROW			db_row;
	int			ret = FAIL;
	zbx_sock_t		sock;
	char			*answer;

	zabbix_log(LOG_LEVEL_DEBUG, "In send_script(nodeid:%d)", nodeid);

	db_result = DBselect(
			"select ip,port"
			" from nodes"
			" where nodeid=%d",
			nodeid);

	if (NULL != (db_row = DBfetch(db_result)))
	{
		if (SUCCEED == (ret = zbx_tcp_connect(&sock, CONFIG_SOURCE_IP,
				db_row[0], atoi(db_row[1]), CONFIG_TRAPPER_TIMEOUT)))
		{
			if (FAIL == (ret = zbx_tcp_send(&sock, data)))
			{
				*result = zbx_dsprintf(*result, "NODE %d: Error while sending data to Node [%d]: %s.",
						CONFIG_NODEID, nodeid, zbx_tcp_strerror());
				goto exit_sock;
			}

			if (SUCCEED == (ret = zbx_tcp_recv(&sock, &answer)))
				*result = zbx_dsprintf(*result, "%s", answer);
			else
				*result = zbx_dsprintf(*result,
						"NODE %d: Error while receiving data from Node [%d]: %s.",
						CONFIG_NODEID, nodeid, zbx_tcp_strerror());
exit_sock:
			zbx_tcp_close(&sock);
		}
		else
			*result = zbx_dsprintf(*result, "NODE %d: Unable to connect to Node [%d]: %s.",
					CONFIG_NODEID, nodeid, zbx_tcp_strerror());
	}
	else
		*result = zbx_dsprintf(*result, "NODE %d: Unknown Node ID [%d].",
				CONFIG_NODEID, nodeid);

	DBfree_result(db_result);

	return ret;
}
Example #15
0
int	check_ntp(char *host, unsigned short port, int *value_int)
{

	zbx_sock_t	s;

	int		ret;
	char	*buf = NULL;

	ntp_data	data;
	char		packet[NTP_PACKET_MIN];

	assert(value_int);

	*value_int = 0;

	if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port, 0))) {
		make_packet(&data);

		pack_ntp((unsigned char*)packet, sizeof(packet), &data);

		if( SUCCEED == (ret = zbx_tcp_send_raw(&s, packet)) )
		{
			if( SUCCEED == (ret = zbx_tcp_recv(&s, &buf)) )
			{

				unpack_ntp(&data, (unsigned char *)buf, (int)strlen(buf));

#if OFF
			/* local time */	*value_int = time(NULL);
#else
			/* server time */	*value_int = (data.receive > 0) ? (int)(data.receive - ZBX_JAN_1970_IN_SEC) : 0;
#endif
			}
		}
	}
	zbx_tcp_close(&s);

	if( FAIL == ret )
	{
		zabbix_log(LOG_LEVEL_DEBUG, "NTP check error: %s", zbx_tcp_strerror());
	}

	return SYSINFO_RET_OK;
}
Example #16
0
/*
 * 0 - NOT OK
 * 1 - OK
 * */
int	tcp_expect(const char *host, unsigned short port, int timeout, const char *request,
		const char *expect, const char *sendtoclose, int *value_int)
{
	zbx_sock_t	s;
	char		*buf;
	int		net, val = SUCCEED;

	*value_int = 0;

	if (SUCCEED == (net = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port, timeout)))
	{
		if (NULL != request)
			net = zbx_tcp_send_raw(&s, request);

		if (NULL != expect && SUCCEED == net)
		{
			if (SUCCEED == (net = zbx_tcp_recv(&s, &buf)))
			{
				if (0 != strncmp(buf, expect, strlen(expect)))
				{
					val = FAIL;
				}
			}
		}

		if (NULL != sendtoclose && SUCCEED == net && SUCCEED == val)
			zbx_tcp_send_raw(&s, sendtoclose);

		if (SUCCEED == net && SUCCEED == val)
			*value_int = 1;

		zbx_tcp_close(&s);
	}

	if (FAIL == net)
		zabbix_log(LOG_LEVEL_DEBUG, "TCP expect network error: %s", zbx_tcp_strerror());

	if (FAIL == val)
		zabbix_log(LOG_LEVEL_DEBUG, "TCP expect content error: expected [%s] received [%s]", expect, buf);

	return SYSINFO_RET_OK;
}
Example #17
0
static	ZBX_THREAD_ENTRY(send_value, args)
{
	ZBX_THREAD_SENDVAL_ARGS	*sentdval_args;
	zbx_sock_t		sock;
	char			*answer = NULL;
	int			tcp_ret, ret = FAIL;

	assert(args);
	assert(((zbx_thread_args_t *)args)->args);

	sentdval_args = (ZBX_THREAD_SENDVAL_ARGS *)((zbx_thread_args_t *)args)->args;

#if !defined(_WINDOWS)
	signal(SIGINT,  send_signal_handler);
	signal(SIGTERM, send_signal_handler);
	signal(SIGQUIT, send_signal_handler);
	signal(SIGALRM, send_signal_handler);
#endif

	if (SUCCEED == (tcp_ret = zbx_tcp_connect(&sock, CONFIG_SOURCE_IP, sentdval_args->server, sentdval_args->port, GET_SENDER_TIMEOUT)))
	{
		if (SUCCEED == (tcp_ret = zbx_tcp_send(&sock, sentdval_args->json.buffer)))
		{
			if (SUCCEED == (tcp_ret = zbx_tcp_recv(&sock, &answer)))
			{
				zabbix_log(LOG_LEVEL_DEBUG, "answer [%s]", answer);
				if (NULL == answer || SUCCEED != check_response(answer))
					zabbix_log(LOG_LEVEL_WARNING, "incorrect answer from server [%s]", answer);
				else
					ret = SUCCEED;
			}
		}

		zbx_tcp_close(&sock);
	}

	if (FAIL == tcp_ret)
		zabbix_log(LOG_LEVEL_DEBUG, "send value error: %s", zbx_tcp_strerror());

	zbx_thread_exit(ret);
}
Example #18
0
/******************************************************************************
 *                                                                            *
 * Function: refresh_active_checks                                            *
 *                                                                            *
 * Purpose: Retrive from ZABBIX server list of active checks                  *
 *                                                                            *
 * Parameters: host - IP or Hostname of ZABBIX server                         *
 *             port - port of ZABBIX server                                   *
 *                                                                            *
 * Return value: returns SUCCEED on succesfull parsing,                       *
 *               FAIL on other cases                                          *
 *                                                                            *
 * Author: Eugene Grigorjev, Alexei Vladishev (new json protocol)             *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
static int	refresh_active_checks(const char *host, unsigned short port)
{
	zbx_sock_t	s;
	char		*buf;
	int		ret;
	struct zbx_json	json;

	zabbix_log( LOG_LEVEL_DEBUG, "refresh_active_checks('%s',%u)", host, port);

	zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);

	zbx_json_addstring(&json, ZBX_PROTO_TAG_REQUEST, ZBX_PROTO_VALUE_GET_ACTIVE_CHECKS, ZBX_JSON_TYPE_STRING);
	zbx_json_addstring(&json, ZBX_PROTO_TAG_HOST, CONFIG_HOSTNAME, ZBX_JSON_TYPE_STRING);

	if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port, CONFIG_TIMEOUT))) {
		zabbix_log(LOG_LEVEL_DEBUG, "Sending [%s]", json.buffer);

		if (SUCCEED == (ret = zbx_tcp_send(&s, json.buffer)))
		{
			zabbix_log(LOG_LEVEL_DEBUG, "Before read");

			if (SUCCEED == (ret = zbx_tcp_recv_ext(&s, &buf, ZBX_TCP_READ_UNTIL_CLOSE)))
			{
				zabbix_log(LOG_LEVEL_DEBUG, "Got [%s]", buf);
				parse_list_of_checks(buf);
			}
		}
		zbx_tcp_close(&s);
	}

	if (FAIL == ret)
		zabbix_log(LOG_LEVEL_DEBUG, "Get active checks error: %s", zbx_tcp_strerror());

	zbx_json_free(&json);

	return ret;
}
Example #19
0
static int	get_http_page(const char *host, const char *path, unsigned short port, char *buffer, int max_buffer_len)
{
    int		ret;
    char		*recv_buffer;
    char		request[MAX_STRING_LEN];
    zbx_sock_t	s;

    if (SUCCEED == (ret = zbx_tcp_connect(&s, CONFIG_SOURCE_IP, host, port, CONFIG_TIMEOUT)))
    {
        zbx_snprintf(request, sizeof(request),
                     "GET /%s HTTP/1.1\r\n"
                     "Host: %s\r\n"
                     "Connection: close\r\n"
                     "\r\n",
                     path, host);

        if (SUCCEED == (ret = zbx_tcp_send_raw(&s, request)))
        {
            if (SUCCEED == (ret = zbx_tcp_recv_ext(&s, &recv_buffer, ZBX_TCP_READ_UNTIL_CLOSE, 0)))
            {
                if (NULL != buffer)
                    zbx_strlcpy(buffer, recv_buffer, max_buffer_len);
            }
        }

        zbx_tcp_close(&s);
    }

    if (FAIL == ret)
    {
        zabbix_log(LOG_LEVEL_DEBUG, "HTTP get error: %s", zbx_tcp_strerror());
        return SYSINFO_RET_FAIL;
    }

    return SYSINFO_RET_OK;
}
Example #20
0
int	zbx_module_redis_ping(AGENT_REQUEST *request, AGENT_RESULT *result)
{
	char		*CONFIG_SOURCE_IP = NULL;	
	zbx_sock_t	s;
	char		*rs_host, *str_rs_port;
	unsigned int    rs_port;
	const char      *buf;
	char		rv[MAX_STRING_LEN];
	int		rs_status = 0;
	time_t		now;
	char		str_time[MAX_STRING_LEN];
	char		cmd[MAX_STRING_LEN];
	char		hv[MAX_STRING_LEN];
	struct tm	*tm = NULL;


	if (request->nparam == 2)
	{
		rs_host = get_rparam(request, 0);
		str_rs_port = get_rparam(request, 1);
		rs_port = atoi(str_rs_port);
	}
	else if (request->nparam == 1)
	{
		rs_host = REDIS_DEFAULT_INSTANCE_HOST;
		str_rs_port = get_rparam(request, 0);
		rs_port = atoi(str_rs_port);
	}
	else
	{
		/* set optional error message */
		SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid number of parameters"));
		return SYSINFO_RET_FAIL;
	}

	/* for dev
	zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], args:[%s,%d]", rs_host, rs_port);
	*/

	time(&now);
	tm = localtime(&now);
	strftime(str_time, MAX_STRING_LEN, "%Y%m%d%H%M%S", tm);
	/* for dev
	zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], str_time:[%s]", str_time);
	*/

	zbx_snprintf(cmd, MAX_STRING_LEN, "set ZBX_PING %s\r\nget ZBX_PING\r\nquit\r\n",str_time);
	zbx_snprintf(hv, MAX_STRING_LEN, "+OK$%d%s+OK", strlen(str_time), str_time);


	if (SUCCEED == zbx_tcp_connect(&s, CONFIG_SOURCE_IP, rs_host, rs_port, 0))
	{
		/* for dev
		zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], connect to [%s:%d] successful", rs_host, rs_port);
		*/

		if (SUCCEED == zbx_tcp_send_raw(&s, cmd))
		{
			/* for dev
			zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], send request successful");
			*/

			strscpy(rv, "");

			while (NULL != (buf = zbx_tcp_recv_line(&s)))
			{
				/* for dev
				zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], get [%s]", buf);
				*/
				zbx_strlcat(rv, buf, MAX_STRING_LEN);
			}
			/* for dev
			zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], all get [%s]", rv);
			*/
			if (0 == strcmp(rv, hv))
			{
				/* for dev
				zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_ping], redis instance:[%s:%d] is up", rs_host, rs_port);
				*/
				rs_status = 1;
			}
		}

		zbx_tcp_close(&s);
	}

	if (rs_status == 1)
	{
		SET_UI64_RESULT(result, 1);
	}
	else
	{
		SET_UI64_RESULT(result, 0);
	}

	return SYSINFO_RET_OK;
}
Example #21
0
int	zbx_module_redis_status(AGENT_REQUEST *request, AGENT_RESULT *result)
{
	char		*CONFIG_SOURCE_IP = NULL;	
	zbx_sock_t	s;
	char		*rs_host, *str_rs_port, *key;
	unsigned int    rs_port;
	char		rs_st_name[MAX_STRING_LEN];
	zbx_uint64_t 	rs_st_value;
	const char      *buf;
	char		*tmp;
	char		*p;
	int		ret = SYSINFO_RET_FAIL;
	int		find = 0;
	int		net_error = 0;

	if (request->nparam == 3)
	{
		rs_host = get_rparam(request, 0);
		str_rs_port = get_rparam(request, 1);
		rs_port = atoi(str_rs_port);
		key = get_rparam(request, 2);
	}
	else if (request->nparam == 2)
	{
		rs_host = REDIS_DEFAULT_INSTANCE_HOST;
		str_rs_port = get_rparam(request, 0);
		rs_port = atoi(str_rs_port);
		key = get_rparam(request, 1);
	}
	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 [redis], func [zbx_module_redis_status], args:[%s,%d]", rs_host, rs_port);
	*/

	if (SUCCEED == zbx_tcp_connect(&s, CONFIG_SOURCE_IP, rs_host, rs_port, 0))
	{
		/* for dev
		zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_status], connect to [%s:%d] successful", rs_host, rs_port);
		*/

		if (SUCCEED == zbx_tcp_send_raw(&s, "info\r\nquit\r\n"))
		{
			/* for dev
			zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_status], send request successful");
			*/

			while (NULL != (buf = zbx_tcp_recv_line(&s)))
			{
				/* for dev
				zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_status], got [%s]", buf);
				*/

				if (2 == sscanf(buf, "%[^:]:" ZBX_FS_UI64, rs_st_name, &rs_st_value))
				{
					/* for dev
					zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_status], parse result name :[%s] value:[%d]", rs_st_name, rs_st_value);
					*/

					if (0 == strcmp(rs_st_name, key))
					{
						/* for dev
						zabbix_log(LOG_LEVEL_INFORMATION, "module [redis], func [zbx_module_redis_status], args:[%d,%s] value:[%d]", rs_port, key, rs_st_value);
						*/
						find = 1; 
						SET_UI64_RESULT(result, rs_st_value);
						ret = SYSINFO_RET_OK;
						break;
					}
				}
			}
		}
		else
		{
			net_error = 1;
			zabbix_log(LOG_LEVEL_WARNING, "module [redis], func [zbx_module_redis_status],get redis status error: [%s]", zbx_tcp_strerror());
			SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Get redis status error [%s]", zbx_tcp_strerror()));
		}

		zbx_tcp_close(&s);
	}
	else
	{
		net_error = 1;
		zabbix_log(LOG_LEVEL_WARNING, "module [redis], func [zbx_module_redis_status], connect to redis error: [%s]", zbx_tcp_strerror());
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Connect to redis error [%s]", zbx_tcp_strerror()));
	}

	if (find != 1 && net_error == 0)
	{
		zabbix_log(LOG_LEVEL_WARNING, "module [redis], func [zbx_module_redis_status], can't find key: [%s]", key);
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Not supported key [%s]", key));
	}

	return ret;
}
Example #22
0
File: email.c Project: Shmuma/z
/*
 * Send email
 */ 
int	send_email(char *smtp_server,char *smtp_helo,char *smtp_email,char *mailto,char *mailsubject,char *mailbody, char *error, int max_error_len)
{
	int		ret=SUCCEED;
	zbx_sock_t	s;
	int		i,e;
	char		c[MAX_STRING_LEN], *cp = NULL;

	char		str_time[MAX_STRING_LEN];
	struct		tm *local_time = NULL;
	time_t		email_time;

	char		*OK_220="220";
	char		*OK_250="250";
	char		*OK_251="251";
	char		*OK_354="354";

	zabbix_log( LOG_LEVEL_DEBUG, "In send_email[smtp_server:%s]", smtp_server);

	if(FAIL == zbx_tcp_connect(&s, smtp_server, 25, 0, NULL))
	{
		zbx_snprintf(error,max_error_len,"Cannot connect to SMTP server [%s] [%s]", smtp_server, zbx_tcp_strerror());
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s",error);
		ret=FAIL;
		goto out;
	}

	memset(c,0,MAX_STRING_LEN);
	i=read(s.socket,c,MAX_STRING_LEN);
	if(i == -1)
	{
		zbx_snprintf(error,max_error_len,"Error receiving initial string from SMTP server [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}
	if(strncmp(OK_220,c,strlen(OK_220)) != 0)
	{
		zbx_snprintf(error,max_error_len,"No welcome message 220* from SMTP server [%s]", c);
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}

	if(strlen(smtp_helo) != 0)
	{
		memset(c,0,MAX_STRING_LEN);
		zbx_snprintf(c,sizeof(c),"HELO %s\r\n",smtp_helo);
		e=write(s.socket,c,strlen(c)); 
		if(e == -1)
		{
			zbx_snprintf(error,max_error_len,"Error sending HELO to mailserver [%s]", strerror(errno));
			zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
			zabbix_syslog("%s", error);
			ret=FAIL;
			goto out;
		}
				
		memset(c,0,MAX_STRING_LEN);
		i=read(s.socket,c,MAX_STRING_LEN);
		if(i == -1)
		{
			zbx_snprintf(error,max_error_len,"Error receiving answer on HELO request [%s]", strerror(errno));
			zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
			zabbix_syslog("%s", error);
			ret=FAIL;
			goto out;
		}
		if(strncmp(OK_250,c,strlen(OK_250)) != 0)
		{
			zbx_snprintf(error,max_error_len,"Wrong answer on HELO [%s]", c);
			zabbix_log(LOG_LEVEL_DEBUG, "%s",error);
			zabbix_syslog("%s",error);
			ret=FAIL;
			goto out;
		}
	}
			
	memset(c,0,MAX_STRING_LEN);

	zbx_snprintf(c,sizeof(c),"MAIL FROM: <%s>\r\n",smtp_email);

	e=write(s.socket,c,strlen(c)); 
	if(e == -1)
	{
		zbx_snprintf(error,max_error_len,"Error sending MAIL FROM to mailserver [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}

	memset(c,0,MAX_STRING_LEN);
	i=read(s.socket,c,MAX_STRING_LEN);
	if(i == -1)
	{
		zbx_snprintf(error,max_error_len,"Error receiving answer on MAIL FROM request [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}
	if(strncmp(OK_250,c,strlen(OK_250)) != 0)
	{
		zbx_snprintf(error,max_error_len,"Wrong answer on MAIL FROM [%s]", c);
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}
			
	memset(c,0,MAX_STRING_LEN);
	zbx_snprintf(c,sizeof(c),"RCPT TO: <%s>\r\n",mailto);
	e=write(s.socket,c,strlen(c)); 
	if(e == -1)
	{
		zbx_snprintf(error,max_error_len,"Error sending RCPT TO to mailserver [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}
	memset(c,0,MAX_STRING_LEN);
	i=read(s.socket,c,MAX_STRING_LEN);
	if(i == -1)
	{
		zbx_snprintf(error,max_error_len,"Error receiving answer on RCPT TO request [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}
	/* May return 251 as well: User not local; will forward to <forward-path>. See RFC825 */
	if( strncmp(OK_250,c,strlen(OK_250)) != 0 && strncmp(OK_251,c,strlen(OK_251)) != 0)
	{
		zbx_snprintf(error,max_error_len,"Wrong answer on RCPT TO [%s]", c);
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}
	
	memset(c,0,MAX_STRING_LEN);
	zbx_snprintf(c,sizeof(c),"DATA\r\n");
	e=write(s.socket,c,strlen(c)); 
	if(e == -1)
	{
		zbx_snprintf(error,max_error_len,"Error sending DATA to mailserver [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}
	memset(c,0,MAX_STRING_LEN);
	i=read(s.socket,c,MAX_STRING_LEN);
	if(i == -1)
	{
		zbx_snprintf(error,max_error_len,"Error receivng answer on DATA request [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}
	if(strncmp(OK_354,c,strlen(OK_354)) != 0)
	{
		zbx_snprintf(error,max_error_len,"Wrong answer on DATA [%s]", c);
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}

	cp = string_replace(mailsubject, "\r\n", "\n");
	mailsubject = string_replace(cp, "\n", "\r\n");
	zbx_free(cp);

	cp = string_replace(mailbody, "\r\n", "\n");
	mailbody = string_replace(cp, "\n", "\r\n");
	zbx_free(cp);

	memset(c,0,MAX_STRING_LEN);
	time(&email_time);
	local_time = localtime(&email_time);
	strftime( str_time, MAX_STRING_LEN, "%a, %d %b %Y %H:%M:%S %z", local_time );
	cp = zbx_dsprintf(cp,"From:<%s>\r\nTo:<%s>\r\nDate: %s\r\nSubject: %s\r\n\r\n%s",smtp_email,mailto,str_time,mailsubject, mailbody);
	e=write(s.socket,cp,strlen(cp)); 
	zbx_free(cp);
	zbx_free(mailsubject);
	zbx_free(mailbody);
	if(e == -1)
	{
		zbx_snprintf(error,max_error_len,"Error sending mail subject and body to mailserver [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}

	memset(c,0,MAX_STRING_LEN);
	zbx_snprintf(c,sizeof(c),"\r\n.\r\n");
	e=write(s.socket,c,strlen(c)); 
	if(e == -1)
	{
		zbx_snprintf(error,max_error_len,"Error sending . to mailserver [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s",error);
		ret=FAIL;
		goto out;
	}
	memset(c,0,MAX_STRING_LEN);
	i=read(s.socket,c,MAX_STRING_LEN);
	if(i == -1)
	{
		zbx_snprintf(error,max_error_len,"Error receivng answer on . request [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s", error);
		ret=FAIL;
		goto out;
	}
	if(strncmp(OK_250,c,strlen(OK_250)) != 0)
	{
		zbx_snprintf(error,max_error_len,"Wrong answer on end of data [%s]", c);
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s",error);
		ret=FAIL;
		goto out;
	}
	
	memset(c,0,MAX_STRING_LEN);
	zbx_snprintf(c,sizeof(c),"QUIT\r\n");
	e=write(s.socket,c,strlen(c)); 
	if(e == -1)
	{
		zbx_snprintf(error,max_error_len,"Error sending QUIT to mailserver [%s]", strerror(errno));
		zabbix_log(LOG_LEVEL_DEBUG, "%s", error);
		zabbix_syslog("%s",error);
		ret=FAIL;
		goto out;
	}
out:	
	zbx_tcp_close(&s);
	return ret;
}
Example #23
0
void	get_values_java(unsigned char request, DC_ITEM *items, AGENT_RESULT *results, int *errcodes, int num)
{
	const char	*__function_name = "get_values_java";

	zbx_sock_t	s;
	struct zbx_json	json;
	char		error[MAX_STRING_LEN];
	char		*buffer = NULL;
	int		i, j, err = SUCCEED;

	zabbix_log(LOG_LEVEL_DEBUG, "In %s() host:'%s' addr:'%s' num:%d",
			__function_name, items[0].host.host, items[0].interface.addr, num);

	for (j = 0; j < num; j++)	/* locate first supported item */
	{
		if (SUCCEED == errcodes[j])
			break;
	}

	if (j == num)	/* all items already NOTSUPPORTED (with invalid key or port) */
		goto out;

	zbx_json_init(&json, ZBX_JSON_STAT_BUF_LEN);

	if (NULL == CONFIG_JAVA_GATEWAY || '\0' == *CONFIG_JAVA_GATEWAY)
	{
		err = GATEWAY_ERROR;
		strscpy(error, "JavaGateway configuration parameter not set or empty");
		goto exit;
	}

	if (ZBX_JAVA_GATEWAY_REQUEST_INTERNAL == request)
	{
		zbx_json_addstring(&json, ZBX_PROTO_TAG_REQUEST, ZBX_PROTO_VALUE_JAVA_GATEWAY_INTERNAL, ZBX_JSON_TYPE_STRING);
	}
	else if (ZBX_JAVA_GATEWAY_REQUEST_JMX == request)
	{
		for (i = j + 1; i < num; i++)
		{
			if (SUCCEED != errcodes[i])
				continue;

			if (0 != strcmp(items[j].interface.addr, items[i].interface.addr) ||
					items[j].interface.port != items[i].interface.port ||
					0 != strcmp(items[j].username, items[i].username) ||
					0 != strcmp(items[j].password, items[i].password))
			{
				err = GATEWAY_ERROR;
				strscpy(error, "Java poller received items with different connection parameters");
				goto exit;
			}
		}

		zbx_json_addstring(&json, ZBX_PROTO_TAG_REQUEST, ZBX_PROTO_VALUE_JAVA_GATEWAY_JMX, ZBX_JSON_TYPE_STRING);

		zbx_json_addstring(&json, ZBX_PROTO_TAG_CONN, items[j].interface.addr, ZBX_JSON_TYPE_STRING);
		zbx_json_adduint64(&json, ZBX_PROTO_TAG_PORT, items[j].interface.port);
		if ('\0' != *items[j].username)
			zbx_json_addstring(&json, ZBX_PROTO_TAG_USERNAME, items[j].username, ZBX_JSON_TYPE_STRING);
		if ('\0' != *items[j].password)
			zbx_json_addstring(&json, ZBX_PROTO_TAG_PASSWORD, items[j].password, ZBX_JSON_TYPE_STRING);
	}
	else
		assert(0);

	zbx_json_addarray(&json, ZBX_PROTO_TAG_KEYS);
	for (i = 0; i < num; i++)
	{
		if (SUCCEED != errcodes[i])
			continue;

		zbx_json_addstring(&json, NULL, items[i].key, ZBX_JSON_TYPE_STRING);
	}
	zbx_json_close(&json);

	if (SUCCEED == (err = zbx_tcp_connect(&s, CONFIG_SOURCE_IP,
					CONFIG_JAVA_GATEWAY, CONFIG_JAVA_GATEWAY_PORT, CONFIG_TIMEOUT)))
	{
		zabbix_log(LOG_LEVEL_DEBUG, "JSON before sending [%s]", json.buffer);

		if (SUCCEED == (err = zbx_tcp_send(&s, json.buffer)))
		{
			if (SUCCEED == (err = zbx_tcp_recv(&s, &buffer)))
			{
				zabbix_log(LOG_LEVEL_DEBUG, "JSON back [%s]", buffer);

				err = parse_response(items, results, errcodes, num, buffer, error, sizeof(error));
			}
		}

		zbx_tcp_close(&s);
	}

	zbx_json_free(&json);

	if (FAIL == err)
	{
		strscpy(error, zbx_tcp_strerror());
		err = GATEWAY_ERROR;
	}
exit:
	if (NETWORK_ERROR == err || GATEWAY_ERROR == err)
	{
		zabbix_log(LOG_LEVEL_DEBUG, "Getting Java values failed: %s", error);

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

			if (!ISSET_MSG(&results[i]))
			{
				SET_MSG_RESULT(&results[i], zbx_strdup(NULL, error));
				errcodes[i] = err;
			}
		}
	}
out:
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
}
Example #24
0
void	disconnect_server(zbx_sock_t *sock)
{
	zbx_tcp_close(sock);
}
Example #25
0
/******************************************************************************
 *                                                                            *
 * 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;
}
/* example ssh.run["ls /"] */
static int	ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding)
{
	const char	*__function_name = "ssh_run";
	zbx_sock_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))
	{
		SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot connect to SSH server: %s",
				zbx_tcp_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);
				zbx_free(publickey);
				zbx_free(privatekey);

				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 > MAX_BUFFER_LEN - (bytecount + 1))
					sz = 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 (0 != (rc = libssh2_channel_close(channel)))
	{
		switch (rc)
		{
			case LIBSSH2_ERROR_EAGAIN:
				waitsocket(s.socket, session);
				continue;
			default:
				libssh2_session_last_error(session, &ssherr, NULL, 0);
				zabbix_log(LOG_LEVEL_WARNING, "%s() cannot close generic session channel: %s",
						__function_name, ssherr);
				break;
		}
	}

	if (0 == rc)
		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:
	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));

	return ret;
}
Example #27
0
void	disconnect_node(zbx_sock_t *sock)
{
	zbx_tcp_close(sock);
}
Example #28
0
int	zbx_tcp_connect(zbx_sock_t *s, const char *source_ip, const char *ip, unsigned short port, int timeout)
{
	int		ret = FAIL;
	struct addrinfo	*ai = NULL, hints;
	struct addrinfo	*ai_bind = NULL;
	char		service[8];

	ZBX_TCP_START();

	zbx_tcp_clean(s);

	zbx_snprintf(service, sizeof(service), "%d", port);
	memset(&hints, 0x00, sizeof(struct addrinfo));
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;

	if (0 != getaddrinfo(ip, service, &hints, &ai))
	{
		zbx_set_tcp_strerror("cannot resolve [%s]", ip);
		goto out;
	}

	if (ZBX_SOCK_ERROR == (s->socket = socket(ai->ai_family, ai->ai_socktype | SOCK_CLOEXEC, ai->ai_protocol)))
	{
		zbx_set_tcp_strerror("cannot create socket [[%s]:%d]: %s", ip, port, strerror_from_system(zbx_sock_last_error()));
		goto out;
	}

#if !defined(_WINDOWS) && !SOCK_CLOEXEC
	fcntl(s->socket, F_SETFD, FD_CLOEXEC);
#endif

	if (NULL != source_ip)
	{
		memset(&hints, 0x00, sizeof(struct addrinfo));

		hints.ai_family = PF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_flags = AI_NUMERICHOST;

		if (0 != getaddrinfo(source_ip, NULL, &hints, &ai_bind))
		{
			zbx_set_tcp_strerror("invalid source IP address [%s]", source_ip);
			goto out;
		}

		if (ZBX_TCP_ERROR == bind(s->socket, ai_bind->ai_addr, ai_bind->ai_addrlen))
		{
			zbx_set_tcp_strerror("bind() failed: %s", strerror_from_system(zbx_sock_last_error()));
			goto out;
		}
	}

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

	if (ZBX_TCP_ERROR == connect(s->socket, ai->ai_addr, ai->ai_addrlen))
	{
		zbx_set_tcp_strerror("cannot connect to [[%s]:%d]: %s", ip, port, strerror_from_system(zbx_sock_last_error()));
		zbx_tcp_close(s);
		goto out;
	}

	ret = SUCCEED;
out:
	if (NULL != ai)
		freeaddrinfo(ai);

	if (NULL != ai_bind)
		freeaddrinfo(ai_bind);

	return ret;
}
Example #29
0
/******************************************************************************
 *                                                                            *
 * Function: send_buffer                                                      *
 *                                                                            *
 * Purpose: Send value stgored in the buffer to ZABBIX server                 *
 *                                                                            *
 * Parameters: host - IP or Hostname of ZABBIX server                         *
 *             port - port number                                             *
 *                                                                            *
 * Return value: returns SUCCEED on succesfull parsing,                       *
 *               FAIL on other cases                                          *
 *                                                                            *
 * Author: Alexei Vladishev                                                   *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
static int	send_buffer(
		const char		*host,
		unsigned short	port
	)
{
	zbx_sock_t	s;
	char		*buf = NULL;
	int		ret = SUCCEED;
	struct zbx_json json;
	int		i;
	static int	lastsent = 0;
	int		now;

	zabbix_log( LOG_LEVEL_DEBUG, "In send_buffer('%s','%d')",
		host, port);

	zabbix_log( LOG_LEVEL_DEBUG, "Values in the buffer %d Max %d",
		buffer.count,
		CONFIG_BUFFER_SIZE);

	now = (int)time(NULL);
	if(buffer.count < CONFIG_BUFFER_SIZE && now-lastsent < CONFIG_BUFFER_SEND)
	{
		zabbix_log( LOG_LEVEL_DEBUG, "Will not send now. Now %d lastsent %d < %d",
			now,
			lastsent,
			CONFIG_BUFFER_SEND);
		return ret;
	}

	if(buffer.count < 1)
	{
		return 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++)
	{
		zbx_json_addobject(&json, NULL);
		zbx_json_addstring(&json, ZBX_PROTO_TAG_HOST, buffer.data[i].host, ZBX_JSON_TYPE_STRING);
		zbx_json_addstring(&json, ZBX_PROTO_TAG_KEY, buffer.data[i].key, ZBX_JSON_TYPE_STRING);
		zbx_json_addstring(&json, ZBX_PROTO_TAG_VALUE, buffer.data[i].value, ZBX_JSON_TYPE_STRING);
		if (buffer.data[i].lastlogsize)
			zbx_json_adduint64(&json, ZBX_PROTO_TAG_LOGLASTSIZE, buffer.data[i].lastlogsize);
		if (buffer.data[i].timestamp)
			zbx_json_adduint64(&json, ZBX_PROTO_TAG_LOGTIMESTAMP, buffer.data[i].timestamp);
		if (buffer.data[i].source)
			zbx_json_addstring(&json, ZBX_PROTO_TAG_LOGSOURCE, buffer.data[i].source, ZBX_JSON_TYPE_STRING);
		if (buffer.data[i].severity)
			zbx_json_adduint64(&json, ZBX_PROTO_TAG_LOGSEVERITY, buffer.data[i].severity);
		zbx_json_adduint64(&json, ZBX_PROTO_TAG_CLOCK, buffer.data[i].clock);
		zbx_json_close(&json);
	}

	zbx_json_close(&json);

	zbx_json_adduint64(&json, ZBX_PROTO_TAG_CLOCK, (int)time(NULL));

	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);

		ret = zbx_tcp_send(&s, json.buffer);

		if( SUCCEED == ret )
		{
			if( SUCCEED == (ret = zbx_tcp_recv(&s, &buf)) )
			{
				zabbix_log(LOG_LEVEL_DEBUG, "JSON back [%s]",
						buf);
				if( !buf || check_response(buf) != SUCCEED )
				{
					zabbix_log(LOG_LEVEL_DEBUG, "NOT OK");
				}
				else
				{
					zabbix_log(LOG_LEVEL_DEBUG, "OK");
				}
			} else
				zabbix_log(LOG_LEVEL_DEBUG, "Send value error: [recv] %s", zbx_tcp_strerror());
		} else
			zabbix_log(LOG_LEVEL_DEBUG, "Send value error: [send] %s", zbx_tcp_strerror());

		zbx_tcp_close(&s);
	} else
		zabbix_log(LOG_LEVEL_DEBUG, "Send value error: [connect] %s", zbx_tcp_strerror());

	zbx_json_free(&json);

	if(SUCCEED == ret)
	{
		/* free buffer */
		for(i=0;i<buffer.count;i++)
		{
			if(buffer.data[i].host != NULL)		zbx_free(buffer.data[i].host);
			if(buffer.data[i].key != NULL)		zbx_free(buffer.data[i].key);
			if(buffer.data[i].value != NULL)	zbx_free(buffer.data[i].value);
			if(buffer.data[i].source != NULL)	zbx_free(buffer.data[i].source);
		}
		buffer.count = 0;
	}

	if(SUCCEED == ret)	lastsent = now;

	return ret;
}
Example #30
0
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;
}