Example #1
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 #2
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 #3
0
int	zbx_tcp_send_ext(zbx_sock_t *s, const char *data, unsigned char flags, int timeout)
{
	zbx_uint64_t	len64;

	ssize_t		i = 0, written = 0;
	int		ret = SUCCEED;

	ZBX_TCP_START();

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

	if( flags & ZBX_TCP_NEW_PROTOCOL )
	{
		/* Write header */
		if( ZBX_TCP_ERROR == ZBX_TCP_WRITE(s->socket, ZBX_TCP_HEADER, ZBX_TCP_HEADER_LEN))
		{
			zbx_set_tcp_strerror("ZBX_TCP_WRITE() failed [%s]", strerror_from_system(zbx_sock_last_error()));
			ret = FAIL;
			goto cleanup;
		}

		len64 = (zbx_uint64_t)strlen(data);
		len64 = zbx_htole_uint64(len64);

		/* Write data length */
		if( ZBX_TCP_ERROR == ZBX_TCP_WRITE(s->socket, (char *) &len64, sizeof(len64)) )
		{
			zbx_set_tcp_strerror("ZBX_TCP_WRITE() failed [%s]", strerror_from_system(zbx_sock_last_error()));
			ret = FAIL;
			goto cleanup;
		}
	}

	while(written < (ssize_t)strlen(data))
	{
		if( ZBX_TCP_ERROR == (i = ZBX_TCP_WRITE(s->socket, data+written,(int)(strlen(data)-written))) )
		{
			zbx_set_tcp_strerror("ZBX_TCP_WRITE() failed [%s]", strerror_from_system(zbx_sock_last_error()));
			ret = FAIL;
			goto cleanup;
		}
		written += i;
	}
cleanup:
	if (0 != timeout)
		zbx_tcp_timeout_cleanup(s);

	return ret;
}
Example #4
0
/******************************************************************************
 *                                                                            *
 * Function: zbx_tcp_recv_ext                                                 *
 *                                                                            *
 * Purpose: receive data                                                      *
 *                                                                            *
 * Return value: number of bytes received - success,                          *
 *               FAIL - an error occurred                                     *
 *                                                                            *
 * Author: Eugene Grigorjev                                                   *
 *                                                                            *
 ******************************************************************************/
ssize_t	zbx_tcp_recv_ext(zbx_sock_t *s, char **data, unsigned char flags, int timeout)
{
#define ZBX_BUF_LEN	(ZBX_STAT_BUF_LEN * 8)
	ssize_t		nbytes, left, total_bytes;
	size_t		allocated, offset, read_bytes;
	zbx_uint64_t	expected_len;

	ZBX_TCP_START();

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

	zbx_free(s->buf_dyn);

	total_bytes = 0;
	read_bytes = 0;
	s->buf_type = ZBX_BUF_TYPE_STAT;

	*data = s->buf_stat;

	left = ZBX_TCP_HEADER_LEN;

	if (ZBX_TCP_ERROR == (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat, left)))
		goto out;

	if (ZBX_TCP_HEADER_LEN == nbytes && 0 == strncmp(s->buf_stat, ZBX_TCP_HEADER, ZBX_TCP_HEADER_LEN))
	{
		total_bytes += nbytes;

		left = sizeof(zbx_uint64_t);
		if (left != (nbytes = ZBX_TCP_READ(s->socket, (void *)&expected_len, left)))
		{
			total_bytes = FAIL;
			goto out;
		}

		expected_len = zbx_letoh_uint64(expected_len);

		if (ZBX_MAX_RECV_DATA_SIZE < expected_len)
		{
			zabbix_log(LOG_LEVEL_WARNING, "Message size " ZBX_FS_UI64 " from %s"
					" exceeds the maximum size " ZBX_FS_UI64 " bytes. Message ignored.",
					expected_len, get_ip_by_socket(s), (zbx_uint64_t)ZBX_MAX_RECV_DATA_SIZE);
			total_bytes = FAIL;
			goto cleanup;
		}

		flags |= ZBX_TCP_READ_UNTIL_CLOSE;
	}
	else
	{
		read_bytes = nbytes;
		expected_len = 16 * ZBX_MEBIBYTE;
	}

	s->buf_stat[read_bytes] = '\0';

	if (0 != (flags & ZBX_TCP_READ_UNTIL_CLOSE))
	{
		if (0 == nbytes)
			goto cleanup;
	}
	else
	{
		if (nbytes < left)
			goto cleanup;
	}

	left = sizeof(s->buf_stat) - read_bytes - 1;

	/* check for an empty socket if exactly ZBX_TCP_HEADER_LEN bytes (without a header) were sent */
	if (0 == read_bytes || '\n' != s->buf_stat[read_bytes - 1])	/* requests to passive agents end with '\n' */
	{
		/* fill static buffer */
		while (read_bytes < expected_len && 0 < left &&
				ZBX_TCP_ERROR != (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat + read_bytes, left)))
		{
			read_bytes += nbytes;

			if (0 != (flags & ZBX_TCP_READ_UNTIL_CLOSE))
			{
				if (0 == nbytes)
					break;
			}
			else
			{
				if (nbytes < left)	/* should we stop reading? */
				{
					/* XML protocol? */
					if (0 == strncmp(s->buf_stat, "<req>", sizeof("<req>") - 1))
					{
						/* closing tag received in the last 10 bytes? */
						s->buf_stat[read_bytes] = '\0';
						if (NULL != strstr(s->buf_stat + read_bytes -
								(10 > read_bytes ? read_bytes : 10), "</req>"))
							break;
					}
					else
						break;
				}
			}

			left -= nbytes;
		}
	}

	s->buf_stat[read_bytes] = '\0';

	if (sizeof(s->buf_stat) - 1 == read_bytes)	/* static buffer is full */
	{
		allocated = ZBX_BUF_LEN;
		s->buf_type = ZBX_BUF_TYPE_DYN;
		s->buf_dyn = zbx_malloc(s->buf_dyn, allocated);

		memcpy(s->buf_dyn, s->buf_stat, sizeof(s->buf_stat));

		offset = read_bytes;

		/* fill dynamic buffer */
		while (read_bytes < expected_len &&
				ZBX_TCP_ERROR != (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat, sizeof(s->buf_stat))))
		{
			zbx_strncpy_alloc(&s->buf_dyn, &allocated, &offset, s->buf_stat, nbytes);
			read_bytes += nbytes;

			if (0 != (flags & ZBX_TCP_READ_UNTIL_CLOSE))
			{
				if (0 == nbytes)
					break;
			}
			else
			{
				if ((size_t)nbytes < sizeof(s->buf_stat) - 1)	/* should we stop reading? */
				{
					/* XML protocol? */
					if (0 == strncmp(s->buf_dyn, "<req>", sizeof("<req>") - 1))
					{
						/* closing tag received in the last 10 bytes? */
						if (NULL != strstr(s->buf_dyn + read_bytes - 10, "</req>"))
							break;
					}
					else
						break;
				}
			}
		}

		*data = s->buf_dyn;
	}
out:
	if (ZBX_TCP_ERROR == nbytes)
	{
		zbx_set_tcp_strerror("ZBX_TCP_READ() failed: %s", strerror_from_system(zbx_sock_last_error()));
		total_bytes = FAIL;
	}
cleanup:
	if (0 != timeout)
		zbx_tcp_timeout_cleanup(s);

	if (FAIL != total_bytes)
		total_bytes += read_bytes;

	return total_bytes;
}
Example #5
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 #6
0
/******************************************************************************
 *                                                                            *
 * Function: zbx_tcp_recv                                                     *
 *                                                                            *
 * Purpose: receive data                                                      *
 *                                                                            *
 * Parameters:                                                                *
 *                                                                            *
 * Return value: SUCCEED - success                                            *
 *               FAIL - an error occurred                                     *
 *                                                                            *
 * Author: Eugene Grigorjev                                                   *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
int	zbx_tcp_recv_ext(zbx_sock_t *s, char **data, unsigned char flags, int timeout)
{
#define ZBX_BUF_LEN	ZBX_STAT_BUF_LEN*8

	ssize_t		nbytes, left;
	ssize_t		read_bytes;

	int		allocated, offset;
	int		ret = SUCCEED;
	zbx_uint64_t	expected_len;

	ZBX_TCP_START();

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

	zbx_free(s->buf_dyn);

	memset(s->buf_stat, 0, sizeof(s->buf_stat));
	*data = s->buf_stat;

	read_bytes = 0;
	s->buf_type = ZBX_BUF_TYPE_STAT;

	left = ZBX_TCP_HEADER_LEN;
	nbytes = ZBX_TCP_READ(s->socket, s->buf_stat, left);

	if( ZBX_TCP_HEADER_LEN == nbytes && 0 == strncmp(s->buf_stat, ZBX_TCP_HEADER, ZBX_TCP_HEADER_LEN) )
	{

		left = sizeof(zbx_uint64_t);
		nbytes = ZBX_TCP_READ(s->socket, (void *)&expected_len, left);
		expected_len = zbx_letoh_uint64(expected_len);

		/* The rest was already cleared */
		memset(s->buf_stat, 0, ZBX_TCP_HEADER_LEN);

		flags |= ZBX_TCP_READ_UNTIL_CLOSE;
	}
	else if( ZBX_TCP_ERROR != nbytes )
	{
		read_bytes	= nbytes;
		expected_len	= 16*1024*1024;
	}

	if( ZBX_TCP_ERROR != nbytes )
	{
		if( flags & ZBX_TCP_READ_UNTIL_CLOSE ) {
			if(nbytes == 0)		goto cleanup;
		} else {
			if(nbytes < left)	goto cleanup;
		}

		left = sizeof(s->buf_stat) - read_bytes - 1;

		/* fill static buffer */
		if ( s->buf_stat[ read_bytes - 1 ] != '\n' ) /* Don't try to read from an empty socket. */
		{
			while(	read_bytes < expected_len && left > 0
				&& ZBX_TCP_ERROR != (nbytes = ZBX_TCP_READ( s->socket, s->buf_stat + read_bytes, left)))
			{
				read_bytes += nbytes;

				if( flags & ZBX_TCP_READ_UNTIL_CLOSE )
				{
					if(nbytes == 0)	break;
				}
				else
				{
					if(nbytes < left) break;
				}

				left -= nbytes;
			}
		}

		s->buf_stat[read_bytes] = '\0';
		if( (sizeof(s->buf_stat) - 1) == read_bytes) /* static buffer is full */
		{
			allocated		= ZBX_BUF_LEN;

			s->buf_type		= ZBX_BUF_TYPE_DYN;
			s->buf_dyn		= zbx_malloc(s->buf_dyn, allocated);

			memset(s->buf_dyn, 0, allocated);
			memcpy(s->buf_dyn, s->buf_stat, sizeof(s->buf_stat));

			offset = read_bytes;
			/* fill dynamic buffer */
			while( read_bytes < expected_len && ZBX_TCP_ERROR != (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat, sizeof(s->buf_stat)-1)) )
			{
				s->buf_stat[nbytes] = '\0';
				zbx_snprintf_alloc(&(s->buf_dyn), &allocated, &offset, sizeof(s->buf_stat), "%s", s->buf_stat);
				read_bytes += nbytes;

				if( flags & ZBX_TCP_READ_UNTIL_CLOSE ) {
					if(nbytes == 0)	break;
				} else {
					if(nbytes < sizeof(s->buf_stat) - 1) break;
				}
			}

			*data = s->buf_dyn;
		}
	}

	if( ZBX_TCP_ERROR == nbytes )
	{
		zbx_set_tcp_strerror("ZBX_TCP_READ() failed [%s]", strerror_from_system(zbx_sock_last_error()));
		ret = FAIL;
	}
cleanup:
	if (0 != timeout)
		zbx_tcp_timeout_cleanup(s);

	return ret;
}