1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 **/
19 
20 #include "common.h"
21 #include "comms.h"
22 #include "log.h"
23 #include "../zbxcrypto/tls_tcp.h"
24 #include "zbxcompress.h"
25 
26 #ifdef _WINDOWS
27 #	ifndef _WIN32_WINNT_WIN7
28 #		define _WIN32_WINNT_WIN7		0x0601	/* allow compilation on older Windows systems */
29 #	endif
30 #	ifndef WSA_FLAG_NO_HANDLE_INHERIT
31 #		define WSA_FLAG_NO_HANDLE_INHERIT	0x80	/* allow compilation on older Windows systems */
32 #	endif
33 #endif
34 
35 #define IPV4_MAX_CIDR_PREFIX	32	/* max number of bits in IPv4 CIDR prefix */
36 #define IPV6_MAX_CIDR_PREFIX	128	/* max number of bits in IPv6 CIDR prefix */
37 
38 #ifndef ZBX_SOCKLEN_T
39 #	define ZBX_SOCKLEN_T socklen_t
40 #endif
41 
42 #ifndef SOCK_CLOEXEC
43 #	define SOCK_CLOEXEC 0	/* SOCK_CLOEXEC is Linux-specific, available since 2.6.23 */
44 #endif
45 
46 #ifdef HAVE_OPENSSL
47 extern ZBX_THREAD_LOCAL char	info_buf[256];
48 #endif
49 
50 extern int	CONFIG_TIMEOUT;
51 
52 /******************************************************************************
53  *                                                                            *
54  * Function: zbx_socket_strerror                                              *
55  *                                                                            *
56  * Purpose: return string describing tcp error                                *
57  *                                                                            *
58  * Return value: pointer to the null terminated string                        *
59  *                                                                            *
60  * Author: Eugene Grigorjev                                                   *
61  *                                                                            *
62  ******************************************************************************/
63 
64 #define ZBX_SOCKET_STRERROR_LEN	512
65 
66 static char	zbx_socket_strerror_message[ZBX_SOCKET_STRERROR_LEN];
67 
zbx_socket_strerror(void)68 const char	*zbx_socket_strerror(void)
69 {
70 	zbx_socket_strerror_message[ZBX_SOCKET_STRERROR_LEN - 1] = '\0';	/* force null termination */
71 	return zbx_socket_strerror_message;
72 }
73 
74 __zbx_attr_format_printf(1, 2)
zbx_set_socket_strerror(const char * fmt,...)75 static void	zbx_set_socket_strerror(const char *fmt, ...)
76 {
77 	va_list args;
78 
79 	va_start(args, fmt);
80 
81 	zbx_vsnprintf(zbx_socket_strerror_message, sizeof(zbx_socket_strerror_message), fmt, args);
82 
83 	va_end(args);
84 }
85 
86 /******************************************************************************
87  *                                                                            *
88  * Function: zbx_socket_peer_ip_save                                          *
89  *                                                                            *
90  * Purpose: get peer IP address info from a socket early while it is          *
91  *          connected. Connection can be terminated due to various errors at  *
92  *          any time and peer IP address will not be available anymore.       *
93  *                                                                            *
94  * Return value: SUCCEED or FAIL                                              *
95  *                                                                            *
96  ******************************************************************************/
zbx_socket_peer_ip_save(zbx_socket_t * s)97 static int	zbx_socket_peer_ip_save(zbx_socket_t *s)
98 {
99 	ZBX_SOCKADDR	sa;
100 	ZBX_SOCKLEN_T	sz = sizeof(sa);
101 	char		*error_message = NULL;
102 
103 	if (ZBX_PROTO_ERROR == getpeername(s->socket, (struct sockaddr *)&sa, &sz))
104 	{
105 		error_message = strerror_from_system(zbx_socket_last_error());
106 		zbx_set_socket_strerror("connection rejected, getpeername() failed: %s", error_message);
107 		return FAIL;
108 	}
109 
110 	/* store getpeername() result to have IP address in numerical form for security check */
111 	memcpy(&s->peer_info, &sa, (size_t)sz);
112 
113 	/* store IP address as a text string for error reporting */
114 
115 #ifdef HAVE_IPV6
116 	if (0 != zbx_getnameinfo((struct sockaddr *)&sa, s->peer, sizeof(s->peer), NULL, 0, NI_NUMERICHOST))
117 	{
118 		error_message = strerror_from_system(zbx_socket_last_error());
119 		zbx_set_socket_strerror("connection rejected, getnameinfo() failed: %s", error_message);
120 		return FAIL;
121 	}
122 #else
123 	strscpy(s->peer, inet_ntoa(sa.sin_addr));
124 #endif
125 	return SUCCEED;
126 }
127 
128 #ifndef _WINDOWS
129 /******************************************************************************
130  *                                                                            *
131  * Function: zbx_gethost_by_ip                                                *
132  *                                                                            *
133  * Purpose: retrieve 'hostent' by IP address                                  *
134  *                                                                            *
135  * Author: Alexei Vladishev                                                   *
136  *                                                                            *
137  ******************************************************************************/
138 #ifdef HAVE_IPV6
zbx_gethost_by_ip(const char * ip,char * host,size_t hostlen)139 void	zbx_gethost_by_ip(const char *ip, char *host, size_t hostlen)
140 {
141 	struct addrinfo	hints, *ai = NULL;
142 
143 	assert(ip);
144 
145 	memset(&hints, 0, sizeof(hints));
146 	hints.ai_family = PF_UNSPEC;
147 
148 	if (0 != getaddrinfo(ip, NULL, &hints, &ai))
149 	{
150 		host[0] = '\0';
151 		goto out;
152 	}
153 
154 	if (0 != getnameinfo(ai->ai_addr, ai->ai_addrlen, host, hostlen, NULL, 0, NI_NAMEREQD))
155 	{
156 		host[0] = '\0';
157 		goto out;
158 	}
159 out:
160 	if (NULL != ai)
161 		freeaddrinfo(ai);
162 }
163 #else
zbx_gethost_by_ip(const char * ip,char * host,size_t hostlen)164 void	zbx_gethost_by_ip(const char *ip, char *host, size_t hostlen)
165 {
166 	struct in_addr	addr;
167 	struct hostent  *hst;
168 
169 	assert(ip);
170 
171 	if (0 == inet_aton(ip, &addr))
172 	{
173 		host[0] = '\0';
174 		return;
175 	}
176 
177 	if (NULL == (hst = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET)))
178 	{
179 		host[0] = '\0';
180 		return;
181 	}
182 
183 	zbx_strlcpy(host, hst->h_name, hostlen);
184 }
185 #endif	/* HAVE_IPV6 */
186 #endif	/* _WINDOWS */
187 
188 #ifdef _WINDOWS
189 /******************************************************************************
190  *                                                                            *
191  * Function: zbx_is_win_ver_or_greater                                        *
192  *                                                                            *
193  * Purpose: check Windows version                                             *
194  *                                                                            *
195  * Parameters: major    - [IN] major windows version                          *
196  *             minor    - [IN] minor windows version                          *
197  *             servpack - [IN] service pack version                           *
198  *                                                                            *
199  * Return value: SUCCEED - Windows version matches input parameters           *
200  *                         or greater                                         *
201  *               FAIL    - Windows version is older                           *
202  *                                                                            *
203  * Comments: This is reimplementation of IsWindowsVersionOrGreater() from     *
204  *           Version Helper API. We need it because the original function is  *
205  *           only available in newer Windows toolchains (VS2013+)             *
206  *                                                                            *
207  ******************************************************************************/
zbx_is_win_ver_or_greater(zbx_uint32_t major,zbx_uint32_t minor,zbx_uint32_t servpack)208 static int zbx_is_win_ver_or_greater(zbx_uint32_t major, zbx_uint32_t minor, zbx_uint32_t servpack)
209 {
210 	OSVERSIONINFOEXW vi = { sizeof(vi), major, minor, 0, 0, { 0 }, servpack, 0 };
211 
212 	/* no need to test for an error, check VersionHelpers.h and usage examples */
213 
214 	return VerifyVersionInfoW(&vi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR,
215 			VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(0,
216 			VER_MAJORVERSION, VER_GREATER_EQUAL),
217 			VER_MINORVERSION, VER_GREATER_EQUAL),
218 			VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL)) ? SUCCEED : FAIL;
219 }
220 #endif
221 
222 /******************************************************************************
223  *                                                                            *
224  * Function: zbx_socket_start                                                 *
225  *                                                                            *
226  * Purpose: Initialize Windows Sockets APIs                                   *
227  *                                                                            *
228  * Parameters: error - [OUT] the error message                                *
229  *                                                                            *
230  * Return value: SUCCEED or FAIL - an error occurred                          *
231  *                                                                            *
232  * Author: Eugene Grigorjev                                                   *
233  *                                                                            *
234  ******************************************************************************/
235 #ifdef _WINDOWS
zbx_socket_start(char ** error)236 int	zbx_socket_start(char **error)
237 {
238 	WSADATA	sockInfo;
239 	int	ret;
240 
241 	if (0 != (ret = WSAStartup(MAKEWORD(2, 2), &sockInfo)))
242 	{
243 		*error = zbx_dsprintf(*error, "Cannot initialize Winsock DLL: %s", strerror_from_system(ret));
244 		return FAIL;
245 	}
246 
247 	return SUCCEED;
248 }
249 #endif
250 
251 /******************************************************************************
252  *                                                                            *
253  * Function: zbx_socket_clean                                                 *
254  *                                                                            *
255  * Purpose: initialize socket                                                 *
256  *                                                                            *
257  * Author: Alexei Vladishev                                                   *
258  *                                                                            *
259  ******************************************************************************/
zbx_socket_clean(zbx_socket_t * s)260 static void	zbx_socket_clean(zbx_socket_t *s)
261 {
262 	memset(s, 0, sizeof(zbx_socket_t));
263 
264 	s->buf_type = ZBX_BUF_TYPE_STAT;
265 }
266 
267 /******************************************************************************
268  *                                                                            *
269  * Function: zbx_socket_free                                                  *
270  *                                                                            *
271  * Purpose: free socket's dynamic buffer                                      *
272  *                                                                            *
273  * Author: Alexei Vladishev                                                   *
274  *                                                                            *
275  ******************************************************************************/
zbx_socket_free(zbx_socket_t * s)276 static void	zbx_socket_free(zbx_socket_t *s)
277 {
278 	if (ZBX_BUF_TYPE_DYN == s->buf_type)
279 		zbx_free(s->buffer);
280 }
281 
282 /******************************************************************************
283  *                                                                            *
284  * Function: zbx_socket_timeout_set                                           *
285  *                                                                            *
286  * Purpose: set timeout for socket operations                                 *
287  *                                                                            *
288  * Parameters: s       - [IN] socket descriptor                               *
289  *             timeout - [IN] timeout, in seconds                             *
290  *                                                                            *
291  * Author: Alexander Vladishev                                                *
292  *                                                                            *
293  ******************************************************************************/
zbx_socket_timeout_set(zbx_socket_t * s,int timeout)294 static void	zbx_socket_timeout_set(zbx_socket_t *s, int timeout)
295 {
296 	s->timeout = timeout;
297 #ifdef _WINDOWS
298 	timeout *= 1000;
299 
300 	if (ZBX_PROTO_ERROR == setsockopt(s->socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)))
301 	{
302 		zabbix_log(LOG_LEVEL_WARNING, "setsockopt() failed for SO_RCVTIMEO: %s",
303 				strerror_from_system(zbx_socket_last_error()));
304 	}
305 
306 	if (ZBX_PROTO_ERROR == setsockopt(s->socket, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)))
307 	{
308 		zabbix_log(LOG_LEVEL_WARNING, "setsockopt() failed for SO_SNDTIMEO: %s",
309 				strerror_from_system(zbx_socket_last_error()));
310 	}
311 #else
312 	zbx_alarm_on(timeout);
313 #endif
314 }
315 
316 /******************************************************************************
317  *                                                                            *
318  * Function: zbx_socket_timeout_cleanup                                       *
319  *                                                                            *
320  * Purpose: clean up timeout for socket operations                            *
321  *                                                                            *
322  * Parameters: s - [OUT] socket descriptor                                    *
323  *                                                                            *
324  * Author: Alexander Vladishev                                                *
325  *                                                                            *
326  ******************************************************************************/
zbx_socket_timeout_cleanup(zbx_socket_t * s)327 static void	zbx_socket_timeout_cleanup(zbx_socket_t *s)
328 {
329 #ifndef _WINDOWS
330 	if (0 != s->timeout)
331 	{
332 		zbx_alarm_off();
333 		s->timeout = 0;
334 	}
335 #endif
336 }
337 
338 /******************************************************************************
339  *                                                                            *
340  * Function: zbx_socket_connect                                               *
341  *                                                                            *
342  * Purpose: connect to the specified address with an optional timeout value   *
343  *                                                                            *
344  * Parameters: s       - [IN] socket descriptor                               *
345  *             addr    - [IN] the address                                     *
346  *             addrlen - [IN] the length of addr structure                    *
347  *             timeout - [IN] the connection timeout (0 - system default)     *
348  *             error   - [OUT] the error message                              *
349  *                                                                            *
350  * Return value: SUCCEED - connected successfully                             *
351  *               FAIL - an error occurred                                     *
352  *                                                                            *
353  * Comments: Windows connect implementation uses internal timeouts which      *
354  *           cannot be changed. Because of that in Windows use nonblocking    *
355  *           connect, then wait for connection the specified timeout period   *
356  *           and if successful change socket back to blocking mode.           *
357  *                                                                            *
358  ******************************************************************************/
zbx_socket_connect(zbx_socket_t * s,const struct sockaddr * addr,socklen_t addrlen,int timeout,char ** error)359 static int	zbx_socket_connect(zbx_socket_t *s, const struct sockaddr *addr, socklen_t addrlen, int timeout,
360 		char **error)
361 {
362 #ifdef _WINDOWS
363 	u_long		mode = 1;
364 	FD_SET		fdw, fde;
365 	int		res;
366 	struct timeval	tv, *ptv;
367 #endif
368 	if (0 != timeout)
369 		zbx_socket_timeout_set(s, timeout);
370 
371 #ifdef _WINDOWS
372 	if (0 != ioctlsocket(s->socket, FIONBIO, &mode))
373 	{
374 		*error = zbx_strdup(*error, strerror_from_system(zbx_socket_last_error()));
375 		return FAIL;
376 	}
377 
378 	FD_ZERO(&fdw);
379 	FD_SET(s->socket, &fdw);
380 
381 	FD_ZERO(&fde);
382 	FD_SET(s->socket, &fde);
383 
384 	if (0 != timeout)
385 	{
386 		tv.tv_sec = timeout;
387 		tv.tv_usec = 0;
388 		ptv = &tv;
389 	}
390 	else
391 		ptv = NULL;
392 
393 	if (ZBX_PROTO_ERROR == connect(s->socket, addr, addrlen) && WSAEWOULDBLOCK != zbx_socket_last_error())
394 	{
395 		*error = zbx_strdup(*error, strerror_from_system(zbx_socket_last_error()));
396 		return FAIL;
397 	}
398 
399 	if (-1 == (res = select(0, NULL, &fdw, &fde, ptv)))
400 	{
401 		*error = zbx_strdup(*error, strerror_from_system(zbx_socket_last_error()));
402 		return FAIL;
403 	}
404 
405 	if (0 == FD_ISSET(s->socket, &fdw))
406 	{
407 		if (0 != FD_ISSET(s->socket, &fde))
408 		{
409 			int socket_error = 0;
410 			int socket_error_len = sizeof(int);
411 
412 			if (ZBX_PROTO_ERROR != getsockopt(s->socket, SOL_SOCKET,
413 				SO_ERROR, (char *)&socket_error, &socket_error_len))
414 			{
415 				if (socket_error == WSAECONNREFUSED)
416 					*error = zbx_strdup(*error, "Connection refused.");
417 				else if (socket_error == WSAETIMEDOUT)
418 					*error = zbx_strdup(*error, "A connection timeout occurred.");
419 				else
420 					*error = zbx_strdup(*error, strerror_from_system(socket_error));
421 			}
422 			else
423 			{
424 				*error = zbx_dsprintf(*error, "Cannot obtain error code: %s",
425 						strerror_from_system(zbx_socket_last_error()));
426 			}
427 		}
428 
429 		return FAIL;
430 	}
431 
432 	mode = 0;
433 	if (0 != ioctlsocket(s->socket, FIONBIO, &mode))
434 	{
435 		*error = zbx_strdup(*error, strerror_from_system(zbx_socket_last_error()));
436 		return FAIL;
437 	}
438 #else
439 	if (ZBX_PROTO_ERROR == connect(s->socket, addr, addrlen))
440 	{
441 		*error = zbx_strdup(*error, strerror_from_system(zbx_socket_last_error()));
442 		return FAIL;
443 	}
444 #endif
445 	s->connection_type = ZBX_TCP_SEC_UNENCRYPTED;
446 
447 	return SUCCEED;
448 }
449 
450 /******************************************************************************
451  *                                                                            *
452  * Function: zbx_socket_create                                                *
453  *                                                                            *
454  * Purpose: connect the socket of the specified type to external host         *
455  *                                                                            *
456  * Parameters: s - [OUT] socket descriptor                                    *
457  *                                                                            *
458  * Return value: SUCCEED - connected successfully                             *
459  *               FAIL - an error occurred                                     *
460  *                                                                            *
461  * Author: Alexei Vladishev                                                   *
462  *                                                                            *
463  ******************************************************************************/
464 #ifdef HAVE_IPV6
zbx_socket_create(zbx_socket_t * s,int type,const char * source_ip,const char * ip,unsigned short port,int timeout,unsigned int tls_connect,const char * tls_arg1,const char * tls_arg2)465 static int	zbx_socket_create(zbx_socket_t *s, int type, const char *source_ip, const char *ip, unsigned short port,
466 		int timeout, unsigned int tls_connect, const char *tls_arg1, const char *tls_arg2)
467 {
468 	int		ret = FAIL;
469 	struct addrinfo	*ai = NULL, hints;
470 	struct addrinfo	*ai_bind = NULL;
471 	char		service[8], *error = NULL;
472 	void		(*func_socket_close)(zbx_socket_t *s);
473 
474 	zbx_socket_clean(s);
475 
476 	if (SOCK_DGRAM == type && (ZBX_TCP_SEC_TLS_CERT == tls_connect || ZBX_TCP_SEC_TLS_PSK == tls_connect))
477 	{
478 		THIS_SHOULD_NEVER_HAPPEN;
479 		return FAIL;
480 	}
481 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
482 	if (ZBX_TCP_SEC_TLS_PSK == tls_connect && '\0' == *tls_arg1)
483 	{
484 		zbx_set_socket_strerror("cannot connect with PSK: PSK not available");
485 		return FAIL;
486 	}
487 #else
488 	if (ZBX_TCP_SEC_TLS_CERT == tls_connect || ZBX_TCP_SEC_TLS_PSK == tls_connect)
489 	{
490 		zbx_set_socket_strerror("support for TLS was not compiled in");
491 		return FAIL;
492 	}
493 #endif
494 
495 	zbx_snprintf(service, sizeof(service), "%hu", port);
496 	memset(&hints, 0x00, sizeof(struct addrinfo));
497 	hints.ai_family = PF_UNSPEC;
498 	hints.ai_socktype = type;
499 
500 	if (0 != getaddrinfo(ip, service, &hints, &ai))
501 	{
502 		zbx_set_socket_strerror("cannot resolve [%s]", ip);
503 		goto out;
504 	}
505 
506 	if (ZBX_SOCKET_ERROR == (s->socket = socket(ai->ai_family, ai->ai_socktype | SOCK_CLOEXEC, ai->ai_protocol)))
507 	{
508 		zbx_set_socket_strerror("cannot create socket [[%s]:%hu]: %s",
509 				ip, port, strerror_from_system(zbx_socket_last_error()));
510 		goto out;
511 	}
512 
513 #if !defined(_WINDOWS) && !SOCK_CLOEXEC
514 	fcntl(s->socket, F_SETFD, FD_CLOEXEC);
515 #endif
516 	func_socket_close = (SOCK_STREAM == type ? zbx_tcp_close : zbx_udp_close);
517 
518 	if (NULL != source_ip)
519 	{
520 		memset(&hints, 0x00, sizeof(struct addrinfo));
521 
522 		hints.ai_family = PF_UNSPEC;
523 		hints.ai_socktype = type;
524 		hints.ai_flags = AI_NUMERICHOST;
525 
526 		if (0 != getaddrinfo(source_ip, NULL, &hints, &ai_bind))
527 		{
528 			zbx_set_socket_strerror("invalid source IP address [%s]", source_ip);
529 			func_socket_close(s);
530 			goto out;
531 		}
532 
533 		if (ZBX_PROTO_ERROR == zbx_bind(s->socket, ai_bind->ai_addr, ai_bind->ai_addrlen))
534 		{
535 			zbx_set_socket_strerror("bind() failed: %s", strerror_from_system(zbx_socket_last_error()));
536 			func_socket_close(s);
537 			goto out;
538 		}
539 	}
540 
541 	if (SUCCEED != zbx_socket_connect(s, ai->ai_addr, (socklen_t)ai->ai_addrlen, timeout, &error))
542 	{
543 		func_socket_close(s);
544 		zbx_set_socket_strerror("cannot connect to [[%s]:%hu]: %s", ip, port, error);
545 		zbx_free(error);
546 		goto out;
547 	}
548 
549 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
550 	if ((ZBX_TCP_SEC_TLS_CERT == tls_connect || ZBX_TCP_SEC_TLS_PSK == tls_connect) &&
551 			SUCCEED != zbx_tls_connect(s, tls_connect, tls_arg1, tls_arg2, &error))
552 	{
553 		zbx_tcp_close(s);
554 		zbx_set_socket_strerror("TCP successful, cannot establish TLS to [[%s]:%hu]: %s", ip, port, error);
555 		zbx_free(error);
556 		goto out;
557 	}
558 #else
559 	ZBX_UNUSED(tls_arg1);
560 	ZBX_UNUSED(tls_arg2);
561 #endif
562 	zbx_strlcpy(s->peer, ip, sizeof(s->peer));
563 
564 	ret = SUCCEED;
565 out:
566 	if (NULL != ai)
567 		freeaddrinfo(ai);
568 
569 	if (NULL != ai_bind)
570 		freeaddrinfo(ai_bind);
571 
572 	return ret;
573 }
574 #else
zbx_socket_create(zbx_socket_t * s,int type,const char * source_ip,const char * ip,unsigned short port,int timeout,unsigned int tls_connect,const char * tls_arg1,const char * tls_arg2)575 static int	zbx_socket_create(zbx_socket_t *s, int type, const char *source_ip, const char *ip, unsigned short port,
576 		int timeout, unsigned int tls_connect, const char *tls_arg1, const char *tls_arg2)
577 {
578 	ZBX_SOCKADDR	servaddr_in;
579 	struct addrinfo	hints, *ai;
580 	char		*error = NULL;
581 	void		(*func_socket_close)(zbx_socket_t *s);
582 
583 	if (SOCK_DGRAM == type && (ZBX_TCP_SEC_TLS_CERT == tls_connect || ZBX_TCP_SEC_TLS_PSK == tls_connect))
584 	{
585 		THIS_SHOULD_NEVER_HAPPEN;
586 		return FAIL;
587 	}
588 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
589 	if (ZBX_TCP_SEC_TLS_PSK == tls_connect && '\0' == *tls_arg1)
590 	{
591 		zbx_set_socket_strerror("cannot connect with PSK: PSK not available");
592 		return FAIL;
593 	}
594 #else
595 	if (ZBX_TCP_SEC_TLS_CERT == tls_connect || ZBX_TCP_SEC_TLS_PSK == tls_connect)
596 	{
597 		zbx_set_socket_strerror("support for TLS was not compiled in");
598 		return FAIL;
599 	}
600 #endif
601 	zbx_socket_clean(s);
602 
603 	memset(&hints, 0, sizeof(hints));
604 	hints.ai_family = AF_INET;
605 	hints.ai_socktype = type;
606 
607 	if (0 != getaddrinfo(ip, NULL, &hints, &ai))
608 	{
609 #ifdef _WINDOWS
610 		zbx_set_socket_strerror("getaddrinfo() failed for '%s': %s",
611 				ip, strerror_from_system(WSAGetLastError()));
612 #else
613 #ifdef HAVE_HSTRERROR
614 		zbx_set_socket_strerror("getaddrinfo() failed for '%s': [%d] %s",
615 				ip, h_errno, hstrerror(h_errno));
616 #else
617 		zbx_set_socket_strerror("getaddrinfo() failed for '%s': [%d]",
618 				ip, h_errno);
619 #endif
620 #endif
621 		return FAIL;
622 	}
623 
624 	servaddr_in.sin_family = AF_INET;
625 	servaddr_in.sin_addr = ((struct sockaddr_in *)ai->ai_addr)->sin_addr;
626 	servaddr_in.sin_port = htons(port);
627 
628 	freeaddrinfo(ai);
629 
630 	if (ZBX_SOCKET_ERROR == (s->socket = socket(AF_INET, type | SOCK_CLOEXEC, 0)))
631 	{
632 		zbx_set_socket_strerror("cannot create socket [[%s]:%hu]: %s",
633 				ip, port, strerror_from_system(zbx_socket_last_error()));
634 		return FAIL;
635 	}
636 
637 #if !defined(_WINDOWS) && !SOCK_CLOEXEC
638 	fcntl(s->socket, F_SETFD, FD_CLOEXEC);
639 #endif
640 	func_socket_close = (SOCK_STREAM == type ? zbx_tcp_close : zbx_udp_close);
641 
642 	if (NULL != source_ip)
643 	{
644 		ZBX_SOCKADDR	source_addr;
645 
646 		memset(&source_addr, 0, sizeof(source_addr));
647 
648 		source_addr.sin_family = AF_INET;
649 		source_addr.sin_addr.s_addr = inet_addr(source_ip);
650 		source_addr.sin_port = 0;
651 
652 		if (ZBX_PROTO_ERROR == bind(s->socket, (struct sockaddr *)&source_addr, sizeof(source_addr)))
653 		{
654 			zbx_set_socket_strerror("bind() failed: %s", strerror_from_system(zbx_socket_last_error()));
655 			func_socket_close(s);
656 			return FAIL;
657 		}
658 	}
659 
660 	if (SUCCEED != zbx_socket_connect(s, (struct sockaddr *)&servaddr_in, sizeof(servaddr_in), timeout, &error))
661 	{
662 		func_socket_close(s);
663 		zbx_set_socket_strerror("cannot connect to [[%s]:%hu]: %s", ip, port, error);
664 		zbx_free(error);
665 		return FAIL;
666 	}
667 
668 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
669 	if ((ZBX_TCP_SEC_TLS_CERT == tls_connect || ZBX_TCP_SEC_TLS_PSK == tls_connect) &&
670 			SUCCEED != zbx_tls_connect(s, tls_connect, tls_arg1, tls_arg2, &error))
671 	{
672 		zbx_tcp_close(s);
673 		zbx_set_socket_strerror("TCP successful, cannot establish TLS to [[%s]:%hu]: %s", ip, port, error);
674 		zbx_free(error);
675 		return FAIL;
676 	}
677 #else
678 	ZBX_UNUSED(tls_arg1);
679 	ZBX_UNUSED(tls_arg2);
680 #endif
681 	zbx_strlcpy(s->peer, ip, sizeof(s->peer));
682 
683 	return SUCCEED;
684 }
685 #endif	/* HAVE_IPV6 */
686 
zbx_tcp_connect(zbx_socket_t * s,const char * source_ip,const char * ip,unsigned short port,int timeout,unsigned int tls_connect,const char * tls_arg1,const char * tls_arg2)687 int	zbx_tcp_connect(zbx_socket_t *s, const char *source_ip, const char *ip, unsigned short port, int timeout,
688 		unsigned int tls_connect, const char *tls_arg1, const char *tls_arg2)
689 {
690 	if (ZBX_TCP_SEC_UNENCRYPTED != tls_connect && ZBX_TCP_SEC_TLS_CERT != tls_connect &&
691 			ZBX_TCP_SEC_TLS_PSK != tls_connect)
692 	{
693 		THIS_SHOULD_NEVER_HAPPEN;
694 		return FAIL;
695 	}
696 
697 	return zbx_socket_create(s, SOCK_STREAM, source_ip, ip, port, timeout, tls_connect, tls_arg1, tls_arg2);
698 }
699 
zbx_tcp_write(zbx_socket_t * s,const char * buf,size_t len)700 static ssize_t	zbx_tcp_write(zbx_socket_t *s, const char *buf, size_t len)
701 {
702 	ssize_t	res;
703 	int	err;
704 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
705 	char	*error = NULL;
706 #endif
707 #ifdef _WINDOWS
708 	double	sec;
709 #endif
710 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
711 	if (NULL != s->tls_ctx)	/* TLS connection */
712 	{
713 		if (ZBX_PROTO_ERROR == (res = zbx_tls_write(s, buf, len, &error)))
714 		{
715 			zbx_set_socket_strerror("%s", error);
716 			zbx_free(error);
717 		}
718 
719 		return res;
720 	}
721 #endif
722 #ifdef _WINDOWS
723 	zbx_alarm_flag_clear();
724 	sec = zbx_time();
725 #endif
726 	do
727 	{
728 		res = ZBX_TCP_WRITE(s->socket, buf, len);
729 #ifdef _WINDOWS
730 		if (s->timeout < zbx_time() - sec)
731 			zbx_alarm_flag_set();
732 #endif
733 		if (SUCCEED == zbx_alarm_timed_out())
734 		{
735 			zbx_set_socket_strerror("ZBX_TCP_WRITE() timed out");
736 			return ZBX_PROTO_ERROR;
737 		}
738 	}
739 	while (ZBX_PROTO_ERROR == res && ZBX_PROTO_AGAIN == (err = zbx_socket_last_error()));
740 
741 	if (ZBX_PROTO_ERROR == res)
742 		zbx_set_socket_strerror("ZBX_TCP_WRITE() failed: %s", strerror_from_system(err));
743 
744 	return res;
745 }
746 
747 /******************************************************************************
748  *                                                                            *
749  * Function: zbx_tcp_send_ext                                                 *
750  *                                                                            *
751  * Purpose: send data                                                         *
752  *                                                                            *
753  * Return value: SUCCEED - success                                            *
754  *               FAIL - an error occurred                                     *
755  *                                                                            *
756  * Author: Eugene Grigorjev                                                   *
757  *                                                                            *
758  * Comments:                                                                  *
759  *     RFC 5246 "The Transport Layer Security (TLS) Protocol. Version 1.2"    *
760  *     says: "The record layer fragments information blocks into TLSPlaintext *
761  *     records carrying data in chunks of 2^14 bytes or less.".               *
762  *                                                                            *
763  *     This function combines sending of Zabbix protocol header (5 bytes),    *
764  *     data length (8 bytes) and at least part of the message into one block  *
765  *     of up to 16384 bytes for efficiency. The same is applied for sending   *
766  *     unencrypted messages.                                                  *
767  *                                                                            *
768  ******************************************************************************/
769 
770 #define ZBX_TCP_HEADER_DATA	"ZBXD"
771 #define ZBX_TCP_HEADER		ZBX_TCP_HEADER_DATA ZBX_TCP_HEADER_VERSION
772 #define ZBX_TCP_HEADER_LEN	ZBX_CONST_STRLEN(ZBX_TCP_HEADER_DATA)
773 
zbx_tcp_send_ext(zbx_socket_t * s,const char * data,size_t len,unsigned char flags,int timeout)774 int	zbx_tcp_send_ext(zbx_socket_t *s, const char *data, size_t len, unsigned char flags, int timeout)
775 {
776 #define ZBX_TLS_MAX_REC_LEN	16384
777 
778 	ssize_t		bytes_sent, written = 0;
779 	size_t		send_bytes, offset, send_len = len, reserved = 0;
780 	int		ret = SUCCEED;
781 	char		*compressed_data = NULL;
782 	zbx_uint32_t	len32_le;
783 
784 	if (0 != timeout)
785 		zbx_socket_timeout_set(s, timeout);
786 
787 	if (0 != (flags & ZBX_TCP_PROTOCOL))
788 	{
789 		size_t	take_bytes;
790 		char	header_buf[ZBX_TLS_MAX_REC_LEN];	/* Buffer is allocated on stack with a hope that it   */
791 								/* will be short-lived in CPU cache. Static buffer is */
792 								/* not used on purpose.				      */
793 
794 		if (0 != (flags & ZBX_TCP_COMPRESS))
795 		{
796 			if (SUCCEED != zbx_compress(data, len, &compressed_data, &send_len))
797 			{
798 				zbx_set_socket_strerror("cannot compress data: %s", zbx_compress_strerror());
799 				ret = FAIL;
800 				goto cleanup;
801 			}
802 
803 			data = compressed_data;
804 			reserved = len;
805 		}
806 
807 		memcpy(header_buf, ZBX_TCP_HEADER_DATA, ZBX_CONST_STRLEN(ZBX_TCP_HEADER_DATA));
808 		offset = ZBX_CONST_STRLEN(ZBX_TCP_HEADER_DATA);
809 
810 		header_buf[offset++] = flags;
811 
812 		len32_le = zbx_htole_uint32((zbx_uint32_t)send_len);
813 		memcpy(header_buf + offset, &len32_le, sizeof(len32_le));
814 		offset += sizeof(len32_le);
815 
816 		len32_le = zbx_htole_uint32((zbx_uint32_t)reserved);
817 		memcpy(header_buf + offset, &len32_le, sizeof(len32_le));
818 		offset += sizeof(len32_le);
819 
820 		take_bytes = MIN(send_len, ZBX_TLS_MAX_REC_LEN - offset);
821 		memcpy(header_buf + offset, data, take_bytes);
822 
823 		send_bytes = offset + take_bytes;
824 
825 		while (written < (ssize_t)send_bytes)
826 		{
827 			if (ZBX_PROTO_ERROR == (bytes_sent = zbx_tcp_write(s, header_buf + written,
828 					send_bytes - (size_t)written)))
829 			{
830 				ret = FAIL;
831 				goto cleanup;
832 			}
833 			written += bytes_sent;
834 		}
835 
836 		written -= offset;
837 	}
838 
839 	while (written < (ssize_t)send_len)
840 	{
841 		if (ZBX_TCP_SEC_UNENCRYPTED == s->connection_type)
842 			send_bytes = send_len - (size_t)written;
843 		else
844 			send_bytes = MIN(ZBX_TLS_MAX_REC_LEN, send_len - (size_t)written);
845 
846 		if (ZBX_PROTO_ERROR == (bytes_sent = zbx_tcp_write(s, data + written, send_bytes)))
847 		{
848 			ret = FAIL;
849 			goto cleanup;
850 		}
851 		written += bytes_sent;
852 	}
853 cleanup:
854 	zbx_free(compressed_data);
855 
856 	if (0 != timeout)
857 		zbx_socket_timeout_cleanup(s);
858 
859 	return ret;
860 
861 #undef ZBX_TLS_MAX_REC_LEN
862 }
863 
864 /******************************************************************************
865  *                                                                            *
866  * Function: zbx_tcp_close                                                    *
867  *                                                                            *
868  * Purpose: close open TCP socket                                             *
869  *                                                                            *
870  * Author: Alexei Vladishev                                                   *
871  *                                                                            *
872  ******************************************************************************/
zbx_tcp_close(zbx_socket_t * s)873 void	zbx_tcp_close(zbx_socket_t *s)
874 {
875 	zbx_tcp_unaccept(s);
876 
877 	zbx_socket_timeout_cleanup(s);
878 
879 	zbx_socket_free(s);
880 	zbx_socket_close(s->socket);
881 }
882 
883 /******************************************************************************
884  *                                                                            *
885  * Function: get_address_family                                               *
886  *                                                                            *
887  * Purpose: return address family                                             *
888  *                                                                            *
889  * Parameters: addr - [IN] address or hostname                                *
890  *             family - [OUT] address family                                  *
891  *             error - [OUT] error string                                     *
892  *             max_error_len - [IN] error string length                       *
893  *                                                                            *
894  * Return value: SUCCEED - success                                            *
895  *               FAIL - an error occurred                                     *
896  *                                                                            *
897  * Author: Alexander Vladishev                                                *
898  *                                                                            *
899  ******************************************************************************/
900 #ifdef HAVE_IPV6
get_address_family(const char * addr,int * family,char * error,int max_error_len)901 int	get_address_family(const char *addr, int *family, char *error, int max_error_len)
902 {
903 	struct addrinfo	hints, *ai = NULL;
904 	int		err, res = FAIL;
905 
906 	memset(&hints, 0, sizeof(hints));
907 	hints.ai_family = PF_UNSPEC;
908 	hints.ai_flags = 0;
909 	hints.ai_socktype = SOCK_STREAM;
910 
911 	if (0 != (err = getaddrinfo(addr, NULL, &hints, &ai)))
912 	{
913 		zbx_snprintf(error, max_error_len, "%s: [%d] %s", addr, err, gai_strerror(err));
914 		goto out;
915 	}
916 
917 	if (PF_INET != ai->ai_family && PF_INET6 != ai->ai_family)
918 	{
919 		zbx_snprintf(error, max_error_len, "%s: unsupported address family", addr);
920 		goto out;
921 	}
922 
923 	*family = (int)ai->ai_family;
924 
925 	res = SUCCEED;
926 out:
927 	if (NULL != ai)
928 		freeaddrinfo(ai);
929 
930 	return res;
931 }
932 #endif	/* HAVE_IPV6 */
933 
934 /******************************************************************************
935  *                                                                            *
936  * Function: zbx_tcp_listen                                                   *
937  *                                                                            *
938  * Purpose: create socket for listening                                       *
939  *                                                                            *
940  * Return value: SUCCEED - success                                            *
941  *               FAIL - an error occurred                                     *
942  *                                                                            *
943  * Author: Alexei Vladishev, Aleksandrs Saveljevs                             *
944  *                                                                            *
945  ******************************************************************************/
946 #ifdef HAVE_IPV6
zbx_tcp_listen(zbx_socket_t * s,const char * listen_ip,unsigned short listen_port)947 int	zbx_tcp_listen(zbx_socket_t *s, const char *listen_ip, unsigned short listen_port)
948 {
949 	struct addrinfo	hints, *ai = NULL, *current_ai;
950 	char		port[8], *ip, *ips, *delim;
951 	int		i, err, on, ret = FAIL;
952 #ifdef _WINDOWS
953 	/* WSASocket() option to prevent inheritance is available on */
954 	/* Windows Server 2008 R2 SP1 or newer and on Windows 7 SP1 or newer */
955 	static int	no_inherit_wsapi = -1;
956 
957 	if (-1 == no_inherit_wsapi)
958 	{
959 		/* Both Windows 7 and Windows 2008 R2 are 0x0601 */
960 		no_inherit_wsapi = zbx_is_win_ver_or_greater((_WIN32_WINNT_WIN7 >> 8) & 0xff,
961 				_WIN32_WINNT_WIN7 & 0xff, 1) == SUCCEED;
962 	}
963 #endif
964 
965 	zbx_socket_clean(s);
966 
967 	memset(&hints, 0, sizeof(hints));
968 	hints.ai_family = PF_UNSPEC;
969 	hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
970 	hints.ai_socktype = SOCK_STREAM;
971 	zbx_snprintf(port, sizeof(port), "%hu", listen_port);
972 
973 	ip = ips = (NULL == listen_ip ? NULL : strdup(listen_ip));
974 
975 	while (1)
976 	{
977 		delim = (NULL == ip ? NULL : strchr(ip, ','));
978 		if (NULL != delim)
979 			*delim = '\0';
980 
981 		if (0 != (err = getaddrinfo(ip, port, &hints, &ai)))
982 		{
983 			zbx_set_socket_strerror("cannot resolve address [[%s]:%s]: [%d] %s",
984 					ip ? ip : "-", port, err, gai_strerror(err));
985 			goto out;
986 		}
987 
988 		for (current_ai = ai; NULL != current_ai; current_ai = current_ai->ai_next)
989 		{
990 			if (ZBX_SOCKET_COUNT == s->num_socks)
991 			{
992 				zbx_set_socket_strerror("not enough space for socket [[%s]:%s]",
993 						ip ? ip : "-", port);
994 				goto out;
995 			}
996 
997 			if (PF_INET != current_ai->ai_family && PF_INET6 != current_ai->ai_family)
998 				continue;
999 
1000 #ifdef _WINDOWS
1001 			/* WSA_FLAG_NO_HANDLE_INHERIT prevents socket inheritance if we call CreateProcess() */
1002 			/* later on. If it's not available we still try to avoid inheritance by calling  */
1003 			/* SetHandleInformation() below. WSA_FLAG_OVERLAPPED is not mandatory but strongly */
1004 			/* recommended for every socket */
1005 			s->sockets[s->num_socks] = WSASocket(current_ai->ai_family, current_ai->ai_socktype,
1006 					current_ai->ai_protocol, NULL, 0,
1007 					(0 != no_inherit_wsapi ? WSA_FLAG_NO_HANDLE_INHERIT : 0) |
1008 					WSA_FLAG_OVERLAPPED);
1009 			if (ZBX_SOCKET_ERROR == s->sockets[s->num_socks])
1010 			{
1011 				zbx_set_socket_strerror("WSASocket() for [[%s]:%s] failed: %s",
1012 						ip ? ip : "-", port, strerror_from_system(zbx_socket_last_error()));
1013 				if (WSAEAFNOSUPPORT == zbx_socket_last_error())
1014 #else
1015 			if (ZBX_SOCKET_ERROR == (s->sockets[s->num_socks] =
1016 					socket(current_ai->ai_family, current_ai->ai_socktype | SOCK_CLOEXEC,
1017 					current_ai->ai_protocol)))
1018 			{
1019 				zbx_set_socket_strerror("socket() for [[%s]:%s] failed: %s",
1020 						ip ? ip : "-", port, strerror_from_system(zbx_socket_last_error()));
1021 				if (EAFNOSUPPORT == zbx_socket_last_error())
1022 #endif
1023 					continue;
1024 				else
1025 					goto out;
1026 			}
1027 
1028 #if !defined(_WINDOWS) && !SOCK_CLOEXEC
1029 			fcntl(s->sockets[s->num_socks], F_SETFD, FD_CLOEXEC);
1030 #endif
1031 			on = 1;
1032 #ifdef _WINDOWS
1033 			/* If WSA_FLAG_NO_HANDLE_INHERIT not available, prevent listening socket from */
1034 			/* inheritance with the old API. Disabling handle inheritance in WSASocket() instead of */
1035 			/* SetHandleInformation() is preferred because it provides atomicity and gets the job done */
1036 			/* on systems with non-IFS LSPs installed. So there is a chance that the socket will be still */
1037 			/* inherited on Windows XP with 3rd party firewall/antivirus installed */
1038 			if (0 == no_inherit_wsapi && 0 == SetHandleInformation((HANDLE)s->sockets[s->num_socks],
1039 					HANDLE_FLAG_INHERIT, 0))
1040 			{
1041 				zabbix_log(LOG_LEVEL_WARNING, "SetHandleInformation() failed: %s",
1042 						strerror_from_system(GetLastError()));
1043 			}
1044 
1045 			/* prevent other processes from binding to the same port */
1046 			/* SO_EXCLUSIVEADDRUSE is mutually exclusive with SO_REUSEADDR */
1047 			/* on Windows SO_REUSEADDR has different semantics than on Unix */
1048 			/* https://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx */
1049 			if (ZBX_PROTO_ERROR == setsockopt(s->sockets[s->num_socks], SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
1050 					(void *)&on, sizeof(on)))
1051 			{
1052 				zbx_set_socket_strerror("setsockopt() with %s for [[%s]:%s] failed: %s",
1053 						"SO_EXCLUSIVEADDRUSE", ip ? ip : "-", port,
1054 						strerror_from_system(zbx_socket_last_error()));
1055 			}
1056 #else
1057 			/* enable address reuse */
1058 			/* this is to immediately use the address even if it is in TIME_WAIT state */
1059 			/* http://www-128.ibm.com/developerworks/linux/library/l-sockpit/index.html */
1060 			if (ZBX_PROTO_ERROR == setsockopt(s->sockets[s->num_socks], SOL_SOCKET, SO_REUSEADDR,
1061 					(void *)&on, sizeof(on)))
1062 			{
1063 				zbx_set_socket_strerror("setsockopt() with %s for [[%s]:%s] failed: %s",
1064 						"SO_REUSEADDR", ip ? ip : "-", port,
1065 						strerror_from_system(zbx_socket_last_error()));
1066 			}
1067 #endif
1068 
1069 #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
1070 			if (PF_INET6 == current_ai->ai_family &&
1071 					ZBX_PROTO_ERROR == setsockopt(s->sockets[s->num_socks], IPPROTO_IPV6,
1072 					IPV6_V6ONLY, (void *)&on, sizeof(on)))
1073 			{
1074 				zbx_set_socket_strerror("setsockopt() with %s for [[%s]:%s] failed: %s",
1075 						"IPV6_V6ONLY", ip ? ip : "-", port,
1076 						strerror_from_system(zbx_socket_last_error()));
1077 			}
1078 #endif
1079 			if (ZBX_PROTO_ERROR == zbx_bind(s->sockets[s->num_socks], current_ai->ai_addr,
1080 					current_ai->ai_addrlen))
1081 			{
1082 				zbx_set_socket_strerror("bind() for [[%s]:%s] failed: %s",
1083 						ip ? ip : "-", port, strerror_from_system(zbx_socket_last_error()));
1084 				zbx_socket_close(s->sockets[s->num_socks]);
1085 #ifdef _WINDOWS
1086 				if (WSAEADDRINUSE == zbx_socket_last_error())
1087 #else
1088 				if (EADDRINUSE == zbx_socket_last_error())
1089 #endif
1090 					continue;
1091 				else
1092 					goto out;
1093 			}
1094 
1095 			if (ZBX_PROTO_ERROR == listen(s->sockets[s->num_socks], SOMAXCONN))
1096 			{
1097 				zbx_set_socket_strerror("listen() for [[%s]:%s] failed: %s",
1098 						ip ? ip : "-", port, strerror_from_system(zbx_socket_last_error()));
1099 				zbx_socket_close(s->sockets[s->num_socks]);
1100 				goto out;
1101 			}
1102 
1103 			s->num_socks++;
1104 		}
1105 
1106 		if (NULL != ai)
1107 		{
1108 			freeaddrinfo(ai);
1109 			ai = NULL;
1110 		}
1111 
1112 		if (NULL == ip || NULL == delim)
1113 			break;
1114 
1115 		*delim = ',';
1116 		ip = delim + 1;
1117 	}
1118 
1119 	if (0 == s->num_socks)
1120 	{
1121 		zbx_set_socket_strerror("zbx_tcp_listen() fatal error: unable to serve on any address [[%s]:%hu]",
1122 				listen_ip ? listen_ip : "-", listen_port);
1123 		goto out;
1124 	}
1125 
1126 	ret = SUCCEED;
1127 out:
1128 	if (NULL != ips)
1129 		zbx_free(ips);
1130 
1131 	if (NULL != ai)
1132 		freeaddrinfo(ai);
1133 
1134 	if (SUCCEED != ret)
1135 	{
1136 		for (i = 0; i < s->num_socks; i++)
1137 			zbx_socket_close(s->sockets[i]);
1138 	}
1139 
1140 	return ret;
1141 }
1142 #else
1143 int	zbx_tcp_listen(zbx_socket_t *s, const char *listen_ip, unsigned short listen_port)
1144 {
1145 	ZBX_SOCKADDR	serv_addr;
1146 	char		*ip, *ips, *delim;
1147 	int		i, on, ret = FAIL;
1148 #ifdef _WINDOWS
1149 	/* WSASocket() option to prevent inheritance is available on */
1150 	/* Windows Server 2008 R2 or newer and on Windows 7 SP1 or newer */
1151 	static int	no_inherit_wsapi = -1;
1152 
1153 	if (-1 == no_inherit_wsapi)
1154 	{
1155 		/* Both Windows 7 and Windows 2008 R2 are 0x0601 */
1156 		no_inherit_wsapi = zbx_is_win_ver_or_greater((_WIN32_WINNT_WIN7 >> 8) & 0xff,
1157 				_WIN32_WINNT_WIN7 & 0xff, 1) == SUCCEED;
1158 	}
1159 #endif
1160 
1161 	zbx_socket_clean(s);
1162 
1163 	ip = ips = (NULL == listen_ip ? NULL : strdup(listen_ip));
1164 
1165 	while (1)
1166 	{
1167 		delim = (NULL == ip ? NULL : strchr(ip, ','));
1168 		if (NULL != delim)
1169 			*delim = '\0';
1170 
1171 		if (NULL != ip && FAIL == is_ip4(ip))
1172 		{
1173 			zbx_set_socket_strerror("incorrect IPv4 address [%s]", ip);
1174 			goto out;
1175 		}
1176 
1177 		if (ZBX_SOCKET_COUNT == s->num_socks)
1178 		{
1179 			zbx_set_socket_strerror("not enough space for socket [[%s]:%hu]",
1180 					ip ? ip : "-", listen_port);
1181 			goto out;
1182 		}
1183 
1184 #ifdef _WINDOWS
1185 		/* WSA_FLAG_NO_HANDLE_INHERIT prevents socket inheritance if we call CreateProcess() */
1186 		/* later on. If it's not available we still try to avoid inheritance by calling  */
1187 		/* SetHandleInformation() below. WSA_FLAG_OVERLAPPED is not mandatory but strongly */
1188 		/* recommended for every socket */
1189 		s->sockets[s->num_socks] = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
1190 				(0 != no_inherit_wsapi ? WSA_FLAG_NO_HANDLE_INHERIT : 0) | WSA_FLAG_OVERLAPPED);
1191 		if (ZBX_SOCKET_ERROR == s->sockets[s->num_socks])
1192 		{
1193 			zbx_set_socket_strerror("WSASocket() for [[%s]:%hu] failed: %s",
1194 					ip ? ip : "-", listen_port, strerror_from_system(zbx_socket_last_error()));
1195 #else
1196 		if (ZBX_SOCKET_ERROR == (s->sockets[s->num_socks] = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)))
1197 		{
1198 			zbx_set_socket_strerror("socket() for [[%s]:%hu] failed: %s",
1199 					ip ? ip : "-", listen_port, strerror_from_system(zbx_socket_last_error()));
1200 #endif
1201 			goto out;
1202 		}
1203 
1204 #if !defined(_WINDOWS) && !SOCK_CLOEXEC
1205 		fcntl(s->sockets[s->num_socks], F_SETFD, FD_CLOEXEC);
1206 #endif
1207 		on = 1;
1208 #ifdef _WINDOWS
1209 		/* If WSA_FLAG_NO_HANDLE_INHERIT not available, prevent listening socket from */
1210 		/* inheritance with the old API. Disabling handle inheritance in WSASocket() instead of */
1211 		/* SetHandleInformation() is preferred because it provides atomicity and gets the job done */
1212 		/* on systems with non-IFS LSPs installed. So there is a chance that the socket will be still */
1213 		/* inherited on Windows XP with 3rd party firewall/antivirus installed */
1214 		if (0 == no_inherit_wsapi && 0 == SetHandleInformation((HANDLE)s->sockets[s->num_socks],
1215 				HANDLE_FLAG_INHERIT, 0))
1216 		{
1217 			zabbix_log(LOG_LEVEL_WARNING, "SetHandleInformation() failed: %s",
1218 					strerror_from_system(GetLastError()));
1219 		}
1220 
1221 		/* prevent other processes from binding to the same port */
1222 		/* SO_EXCLUSIVEADDRUSE is mutually exclusive with SO_REUSEADDR */
1223 		/* on Windows SO_REUSEADDR has different semantics than on Unix */
1224 		/* https://msdn.microsoft.com/en-us/library/windows/desktop/ms740621(v=vs.85).aspx */
1225 		if (ZBX_PROTO_ERROR == setsockopt(s->sockets[s->num_socks], SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
1226 				(void *)&on, sizeof(on)))
1227 		{
1228 			zbx_set_socket_strerror("setsockopt() with %s for [[%s]:%hu] failed: %s", "SO_EXCLUSIVEADDRUSE",
1229 					ip ? ip : "-", listen_port, strerror_from_system(zbx_socket_last_error()));
1230 		}
1231 #else
1232 		/* enable address reuse */
1233 		/* this is to immediately use the address even if it is in TIME_WAIT state */
1234 		/* http://www-128.ibm.com/developerworks/linux/library/l-sockpit/index.html */
1235 		if (ZBX_PROTO_ERROR == setsockopt(s->sockets[s->num_socks], SOL_SOCKET, SO_REUSEADDR,
1236 				(void *)&on, sizeof(on)))
1237 		{
1238 			zbx_set_socket_strerror("setsockopt() with %s for [[%s]:%hu] failed: %s", "SO_REUSEADDR",
1239 					ip ? ip : "-", listen_port, strerror_from_system(zbx_socket_last_error()));
1240 		}
1241 #endif
1242 		memset(&serv_addr, 0, sizeof(serv_addr));
1243 
1244 		serv_addr.sin_family = AF_INET;
1245 		serv_addr.sin_addr.s_addr = (NULL != ip ? inet_addr(ip) : htonl(INADDR_ANY));
1246 		serv_addr.sin_port = htons((unsigned short)listen_port);
1247 
1248 		if (ZBX_PROTO_ERROR == bind(s->sockets[s->num_socks], (struct sockaddr *)&serv_addr, sizeof(serv_addr)))
1249 		{
1250 			zbx_set_socket_strerror("bind() for [[%s]:%hu] failed: %s",
1251 					ip ? ip : "-", listen_port, strerror_from_system(zbx_socket_last_error()));
1252 			zbx_socket_close(s->sockets[s->num_socks]);
1253 			goto out;
1254 		}
1255 
1256 		if (ZBX_PROTO_ERROR == listen(s->sockets[s->num_socks], SOMAXCONN))
1257 		{
1258 			zbx_set_socket_strerror("listen() for [[%s]:%hu] failed: %s",
1259 					ip ? ip : "-", listen_port, strerror_from_system(zbx_socket_last_error()));
1260 			zbx_socket_close(s->sockets[s->num_socks]);
1261 			goto out;
1262 		}
1263 
1264 		s->num_socks++;
1265 
1266 		if (NULL == ip || NULL == delim)
1267 			break;
1268 		*delim = ',';
1269 		ip = delim + 1;
1270 	}
1271 
1272 	if (0 == s->num_socks)
1273 	{
1274 		zbx_set_socket_strerror("zbx_tcp_listen() fatal error: unable to serve on any address [[%s]:%hu]",
1275 				listen_ip ? listen_ip : "-", listen_port);
1276 		goto out;
1277 	}
1278 
1279 	ret = SUCCEED;
1280 out:
1281 	if (NULL != ips)
1282 		zbx_free(ips);
1283 
1284 	if (SUCCEED != ret)
1285 	{
1286 		for (i = 0; i < s->num_socks; i++)
1287 			zbx_socket_close(s->sockets[i]);
1288 	}
1289 
1290 	return ret;
1291 }
1292 #endif	/* HAVE_IPV6 */
1293 
1294 /******************************************************************************
1295  *                                                                            *
1296  * Function: zbx_tcp_accept                                                   *
1297  *                                                                            *
1298  * Purpose: permits an incoming connection attempt on a socket                *
1299  *                                                                            *
1300  * Return value: SUCCEED - success                                            *
1301  *               FAIL - an error occurred                                     *
1302  *                                                                            *
1303  * Author: Eugene Grigorjev, Aleksandrs Saveljevs                             *
1304  *                                                                            *
1305  ******************************************************************************/
1306 int	zbx_tcp_accept(zbx_socket_t *s, unsigned int tls_accept)
1307 {
1308 	ZBX_SOCKADDR	serv_addr;
1309 	fd_set		sock_set;
1310 	ZBX_SOCKET	accepted_socket;
1311 	ZBX_SOCKLEN_T	nlen;
1312 	int		i, n = 0, ret = FAIL;
1313 	ssize_t		res;
1314 	unsigned char	buf;	/* 1 byte buffer */
1315 
1316 	zbx_tcp_unaccept(s);
1317 
1318 	FD_ZERO(&sock_set);
1319 
1320 	for (i = 0; i < s->num_socks; i++)
1321 	{
1322 		FD_SET(s->sockets[i], &sock_set);
1323 #ifndef _WINDOWS
1324 		if (s->sockets[i] > n)
1325 			n = s->sockets[i];
1326 #endif
1327 	}
1328 
1329 	if (ZBX_PROTO_ERROR == select(n + 1, &sock_set, NULL, NULL, NULL))
1330 	{
1331 		zbx_set_socket_strerror("select() failed: %s", strerror_from_system(zbx_socket_last_error()));
1332 		return ret;
1333 	}
1334 
1335 	for (i = 0; i < s->num_socks; i++)
1336 	{
1337 		if (FD_ISSET(s->sockets[i], &sock_set))
1338 			break;
1339 	}
1340 
1341 	/* Since this socket was returned by select(), we know we have */
1342 	/* a connection waiting and that this accept() will not block. */
1343 	nlen = sizeof(serv_addr);
1344 	if (ZBX_SOCKET_ERROR == (accepted_socket = (ZBX_SOCKET)accept(s->sockets[i], (struct sockaddr *)&serv_addr,
1345 			&nlen)))
1346 	{
1347 		zbx_set_socket_strerror("accept() failed: %s", strerror_from_system(zbx_socket_last_error()));
1348 		return ret;
1349 	}
1350 
1351 	s->socket_orig = s->socket;	/* remember main socket */
1352 	s->socket = accepted_socket;	/* replace socket to accepted */
1353 	s->accepted = 1;
1354 
1355 	if (SUCCEED != zbx_socket_peer_ip_save(s))
1356 	{
1357 		/* cannot get peer IP address */
1358 		zbx_tcp_unaccept(s);
1359 		goto out;
1360 	}
1361 
1362 	zbx_socket_timeout_set(s, CONFIG_TIMEOUT);
1363 
1364 	if (ZBX_SOCKET_ERROR == (res = recv(s->socket, &buf, 1, MSG_PEEK)))
1365 	{
1366 		zbx_set_socket_strerror("from %s: reading first byte from connection failed: %s", s->peer,
1367 				strerror_from_system(zbx_socket_last_error()));
1368 		zbx_tcp_unaccept(s);
1369 		goto out;
1370 	}
1371 
1372 	/* if the 1st byte is 0x16 then assume it's a TLS connection */
1373 	if (1 == res && '\x16' == buf)
1374 	{
1375 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1376 		if (0 != (tls_accept & (ZBX_TCP_SEC_TLS_CERT | ZBX_TCP_SEC_TLS_PSK)))
1377 		{
1378 			char	*error = NULL;
1379 
1380 			if (SUCCEED != zbx_tls_accept(s, tls_accept, &error))
1381 			{
1382 				zbx_set_socket_strerror("from %s: %s", s->peer, error);
1383 				zbx_tcp_unaccept(s);
1384 				zbx_free(error);
1385 				goto out;
1386 			}
1387 		}
1388 		else
1389 		{
1390 			zbx_set_socket_strerror("from %s: TLS connections are not allowed", s->peer);
1391 			zbx_tcp_unaccept(s);
1392 			goto out;
1393 		}
1394 #else
1395 		zbx_set_socket_strerror("from %s: support for TLS was not compiled in", s->peer);
1396 		zbx_tcp_unaccept(s);
1397 		goto out;
1398 #endif
1399 	}
1400 	else
1401 	{
1402 		if (0 == (tls_accept & ZBX_TCP_SEC_UNENCRYPTED))
1403 		{
1404 			zbx_set_socket_strerror("from %s: unencrypted connections are not allowed", s->peer);
1405 			zbx_tcp_unaccept(s);
1406 			goto out;
1407 		}
1408 
1409 		s->connection_type = ZBX_TCP_SEC_UNENCRYPTED;
1410 	}
1411 
1412 	ret = SUCCEED;
1413 out:
1414 	zbx_socket_timeout_cleanup(s);
1415 
1416 	return ret;
1417 }
1418 
1419 /******************************************************************************
1420  *                                                                            *
1421  * Function: zbx_tcp_unaccept                                                 *
1422  *                                                                            *
1423  * Purpose: close accepted connection                                         *
1424  *                                                                            *
1425  * Author: Eugene Grigorjev                                                   *
1426  *                                                                            *
1427  ******************************************************************************/
1428 void	zbx_tcp_unaccept(zbx_socket_t *s)
1429 {
1430 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1431 	zbx_tls_close(s);
1432 #endif
1433 	if (!s->accepted) return;
1434 
1435 	shutdown(s->socket, 2);
1436 
1437 	zbx_socket_close(s->socket);
1438 
1439 	s->socket = s->socket_orig;	/* restore main socket */
1440 	s->socket_orig = ZBX_SOCKET_ERROR;
1441 	s->accepted = 0;
1442 }
1443 
1444 /******************************************************************************
1445  *                                                                            *
1446  * Function: zbx_socket_find_line                                             *
1447  *                                                                            *
1448  * Purpose: finds the next line in socket data buffer                         *
1449  *                                                                            *
1450  * Parameters: s - [IN] the socket                                            *
1451  *                                                                            *
1452  * Return value: A pointer to the next line or NULL if the socket data buffer *
1453  *               contains no more lines.                                      *
1454  *                                                                            *
1455  ******************************************************************************/
1456 static const char	*zbx_socket_find_line(zbx_socket_t *s)
1457 {
1458 	char	*ptr, *line = NULL;
1459 
1460 	if (NULL == s->next_line)
1461 		return NULL;
1462 
1463 	/* check if the buffer contains the next line */
1464 	if ((size_t)(s->next_line - s->buffer) <= s->read_bytes && NULL != (ptr = strchr(s->next_line, '\n')))
1465 	{
1466 		line = s->next_line;
1467 		s->next_line = ptr + 1;
1468 
1469 		if (ptr > line && '\r' == *(ptr - 1))
1470 			ptr--;
1471 
1472 		*ptr = '\0';
1473 	}
1474 
1475 	return line;
1476 }
1477 
1478 /******************************************************************************
1479  *                                                                            *
1480  * Function: zbx_tcp_recv_line                                                *
1481  *                                                                            *
1482  * Purpose: reads next line from a socket                                     *
1483  *                                                                            *
1484  * Parameters: s - [IN] the socket                                            *
1485  *                                                                            *
1486  * Return value: a pointer to the line in socket buffer or NULL if there are  *
1487  *               no more lines (socket was closed or an error occurred)       *
1488  *                                                                            *
1489  * Comments: Lines larger than 64KB are truncated.                            *
1490  *                                                                            *
1491  ******************************************************************************/
1492 const char	*zbx_tcp_recv_line(zbx_socket_t *s)
1493 {
1494 #define ZBX_TCP_LINE_LEN	(64 * ZBX_KIBIBYTE)
1495 
1496 	char		buffer[ZBX_STAT_BUF_LEN], *ptr = NULL;
1497 	const char	*line;
1498 	ssize_t		nbytes;
1499 	size_t		alloc = 0, offset = 0, line_length, left;
1500 
1501 	/* check if the buffer already contains the next line */
1502 	if (NULL != (line = zbx_socket_find_line(s)))
1503 		return line;
1504 
1505 	/* Find the size of leftover data from the last read line operation and copy */
1506 	/* the leftover data to the static buffer and reset the dynamic buffer.      */
1507 	/* Because we are reading data in ZBX_STAT_BUF_LEN chunks the leftover       */
1508 	/* data will always fit the static buffer.                                   */
1509 	if (NULL != s->next_line)
1510 	{
1511 		left = s->read_bytes - (s->next_line - s->buffer);
1512 		memmove(s->buf_stat, s->next_line, left);
1513 	}
1514 	else
1515 		left = 0;
1516 
1517 	s->read_bytes = left;
1518 	s->next_line = s->buf_stat;
1519 
1520 	zbx_socket_free(s);
1521 	s->buf_type = ZBX_BUF_TYPE_STAT;
1522 	s->buffer = s->buf_stat;
1523 
1524 	/* read more data into static buffer */
1525 	if (ZBX_PROTO_ERROR == (nbytes = ZBX_TCP_READ(s->socket, s->buf_stat + left, ZBX_STAT_BUF_LEN - left - 1)))
1526 		goto out;
1527 
1528 	s->buf_stat[left + nbytes] = '\0';
1529 
1530 	if (0 == nbytes)
1531 	{
1532 		/* Socket was closed before newline was found. If we have data in buffer  */
1533 		/* return it with success. Otherwise return failure.                      */
1534 		line = 0 != s->read_bytes ? s->next_line : NULL;
1535 		s->next_line += s->read_bytes;
1536 
1537 		goto out;
1538 	}
1539 
1540 	s->read_bytes += nbytes;
1541 
1542 	/* check if the static buffer now contains the next line */
1543 	if (NULL != (line = zbx_socket_find_line(s)))
1544 		goto out;
1545 
1546 	/* copy the static buffer data into dynamic buffer */
1547 	s->buf_type = ZBX_BUF_TYPE_DYN;
1548 	s->buffer = NULL;
1549 	zbx_strncpy_alloc(&s->buffer, &alloc, &offset, s->buf_stat, s->read_bytes);
1550 	line_length = s->read_bytes;
1551 
1552 	/* Read data into dynamic buffer until newline has been found. */
1553 	/* Lines larger than ZBX_TCP_LINE_LEN bytes will be truncated. */
1554 	do
1555 	{
1556 		if (ZBX_PROTO_ERROR == (nbytes = ZBX_TCP_READ(s->socket, buffer, ZBX_STAT_BUF_LEN - 1)))
1557 			goto out;
1558 
1559 		if (0 == nbytes)
1560 		{
1561 			/* socket was closed before newline was found, just return the data we have */
1562 			line = 0 != s->read_bytes ? s->buffer : NULL;
1563 			s->next_line = s->buffer + s->read_bytes;
1564 
1565 			goto out;
1566 		}
1567 
1568 		buffer[nbytes] = '\0';
1569 		ptr = strchr(buffer, '\n');
1570 
1571 		if (s->read_bytes + nbytes < ZBX_TCP_LINE_LEN && s->read_bytes == line_length)
1572 		{
1573 			zbx_strncpy_alloc(&s->buffer, &alloc, &offset, buffer, nbytes);
1574 			s->read_bytes += nbytes;
1575 		}
1576 		else
1577 		{
1578 			if (0 != (left = (NULL == ptr ? ZBX_TCP_LINE_LEN - s->read_bytes :
1579 					MIN(ZBX_TCP_LINE_LEN - s->read_bytes, (size_t)(ptr - buffer)))))
1580 			{
1581 				/* fill the string to the defined limit */
1582 				zbx_strncpy_alloc(&s->buffer, &alloc, &offset, buffer, left);
1583 				s->read_bytes += left;
1584 			}
1585 
1586 			/* if the line exceeds the defined limit then truncate it by skipping data until the newline */
1587 			if (NULL != ptr)
1588 			{
1589 				zbx_strncpy_alloc(&s->buffer, &alloc, &offset, ptr, nbytes - (ptr - buffer));
1590 				s->read_bytes += nbytes - (ptr - buffer);
1591 			}
1592 		}
1593 
1594 		line_length += nbytes;
1595 
1596 	}
1597 	while (NULL == ptr);
1598 
1599 	s->next_line = s->buffer;
1600 	line = zbx_socket_find_line(s);
1601 out:
1602 	return line;
1603 }
1604 
1605 static ssize_t	zbx_tcp_read(zbx_socket_t *s, char *buf, size_t len)
1606 {
1607 	ssize_t	res;
1608 	int	err;
1609 #ifdef _WINDOWS
1610 	double	sec;
1611 #endif
1612 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1613 	if (NULL != s->tls_ctx)	/* TLS connection */
1614 	{
1615 		char	*error = NULL;
1616 
1617 		if (ZBX_PROTO_ERROR == (res = zbx_tls_read(s, buf, len, &error)))
1618 		{
1619 			zbx_set_socket_strerror("%s", error);
1620 			zbx_free(error);
1621 		}
1622 
1623 		return res;
1624 	}
1625 #endif
1626 #ifdef _WINDOWS
1627 	zbx_alarm_flag_clear();
1628 	sec = zbx_time();
1629 #endif
1630 	do
1631 	{
1632 		res = ZBX_TCP_READ(s->socket, buf, len);
1633 #ifdef _WINDOWS
1634 		if (s->timeout < zbx_time() - sec)
1635 			zbx_alarm_flag_set();
1636 #endif
1637 		if (SUCCEED == zbx_alarm_timed_out())
1638 		{
1639 			zbx_set_socket_strerror("ZBX_TCP_READ() timed out");
1640 			return ZBX_PROTO_ERROR;
1641 		}
1642 	}
1643 	while (ZBX_PROTO_ERROR == res && ZBX_PROTO_AGAIN == (err = zbx_socket_last_error()));
1644 
1645 	if (ZBX_PROTO_ERROR == res)
1646 		zbx_set_socket_strerror("ZBX_TCP_READ() failed: %s", strerror_from_system(err));
1647 
1648 	return res;
1649 }
1650 
1651 /******************************************************************************
1652  *                                                                            *
1653  * Function: zbx_tcp_recv_ext                                                 *
1654  *                                                                            *
1655  * Purpose: receive data                                                      *
1656  *                                                                            *
1657  * Return value: number of bytes received - success,                          *
1658  *               FAIL - an error occurred                                     *
1659  *                                                                            *
1660  * Author: Eugene Grigorjev                                                   *
1661  *                                                                            *
1662  ******************************************************************************/
1663 ssize_t	zbx_tcp_recv_ext(zbx_socket_t *s, int timeout)
1664 {
1665 #define ZBX_TCP_EXPECT_HEADER		1
1666 #define ZBX_TCP_EXPECT_VERSION		2
1667 #define ZBX_TCP_EXPECT_VERSION_VALIDATE	3
1668 #define ZBX_TCP_EXPECT_LENGTH		4
1669 #define ZBX_TCP_EXPECT_SIZE		5
1670 
1671 	const char	*__function_name = "zbx_tcp_recv_ext";
1672 
1673 	ssize_t		nbytes;
1674 	size_t		buf_dyn_bytes = 0, buf_stat_bytes = 0, offset = 0;
1675 	zbx_uint32_t	expected_len = 16 * ZBX_MEBIBYTE, reserved = 0;
1676 	unsigned char	expect = ZBX_TCP_EXPECT_HEADER;
1677 	int		protocol_version;
1678 
1679 	if (0 != timeout)
1680 		zbx_socket_timeout_set(s, timeout);
1681 
1682 	zbx_socket_free(s);
1683 
1684 	s->buf_type = ZBX_BUF_TYPE_STAT;
1685 	s->buffer = s->buf_stat;
1686 
1687 	while (0 != (nbytes = zbx_tcp_read(s, s->buf_stat + buf_stat_bytes, sizeof(s->buf_stat) - buf_stat_bytes)))
1688 	{
1689 		if (ZBX_PROTO_ERROR == nbytes)
1690 			goto out;
1691 
1692 		if (ZBX_BUF_TYPE_STAT == s->buf_type)
1693 			buf_stat_bytes += nbytes;
1694 		else
1695 		{
1696 			if (buf_dyn_bytes + nbytes <= expected_len)
1697 				memcpy(s->buffer + buf_dyn_bytes, s->buf_stat, nbytes);
1698 			buf_dyn_bytes += nbytes;
1699 		}
1700 
1701 		if (buf_stat_bytes + buf_dyn_bytes >= expected_len)
1702 			break;
1703 
1704 		if (ZBX_TCP_EXPECT_HEADER == expect)
1705 		{
1706 			if (ZBX_TCP_HEADER_LEN > buf_stat_bytes)
1707 			{
1708 				if (0 == strncmp(s->buf_stat, ZBX_TCP_HEADER_DATA, buf_stat_bytes))
1709 					continue;
1710 
1711 				break;
1712 			}
1713 			else
1714 			{
1715 				if (0 != strncmp(s->buf_stat, ZBX_TCP_HEADER_DATA, ZBX_TCP_HEADER_LEN))
1716 				{
1717 					/* invalid header, abort receiving */
1718 					break;
1719 				}
1720 
1721 				expect = ZBX_TCP_EXPECT_VERSION;
1722 				offset += ZBX_TCP_HEADER_LEN;
1723 			}
1724 		}
1725 
1726 		if (ZBX_TCP_EXPECT_VERSION == expect)
1727 		{
1728 			if (offset + 1 > buf_stat_bytes)
1729 				continue;
1730 
1731 			expect = ZBX_TCP_EXPECT_VERSION_VALIDATE;
1732 			protocol_version = s->buf_stat[ZBX_TCP_HEADER_LEN];
1733 
1734 			if (0 == (protocol_version & ZBX_TCP_PROTOCOL) ||
1735 					protocol_version > (ZBX_TCP_PROTOCOL | ZBX_TCP_COMPRESS))
1736 			{
1737 				/* invalid protocol version, abort receiving */
1738 				break;
1739 			}
1740 			s->protocol = protocol_version;
1741 			expect = ZBX_TCP_EXPECT_LENGTH;
1742 			offset++;
1743 		}
1744 
1745 		if (ZBX_TCP_EXPECT_LENGTH == expect)
1746 		{
1747 			if (offset + 2 * sizeof(zbx_uint32_t) > buf_stat_bytes)
1748 				continue;
1749 
1750 			memcpy(&expected_len, s->buf_stat + offset, sizeof(zbx_uint32_t));
1751 			offset += sizeof(zbx_uint32_t);
1752 			expected_len = zbx_letoh_uint32(expected_len);
1753 
1754 			memcpy(&reserved, s->buf_stat + offset, sizeof(zbx_uint32_t));
1755 			offset += sizeof(zbx_uint32_t);
1756 			reserved = zbx_letoh_uint32(reserved);
1757 
1758 			if (ZBX_MAX_RECV_DATA_SIZE < expected_len)
1759 			{
1760 				zabbix_log(LOG_LEVEL_WARNING, "Message size " ZBX_FS_UI64 " from %s exceeds the "
1761 						"maximum size " ZBX_FS_UI64 " bytes. Message ignored.",
1762 						(zbx_uint64_t)expected_len, s->peer,
1763 						(zbx_uint64_t)ZBX_MAX_RECV_DATA_SIZE);
1764 				nbytes = ZBX_PROTO_ERROR;
1765 				goto out;
1766 			}
1767 
1768 			/* compressed protocol stores uncompressed packet size in the reserved data */
1769 			if (0 != (protocol_version & ZBX_TCP_COMPRESS) && ZBX_MAX_RECV_DATA_SIZE < reserved)
1770 			{
1771 				zabbix_log(LOG_LEVEL_WARNING, "Uncompressed message size " ZBX_FS_UI64
1772 						" from %s exceeds the maximum size " ZBX_FS_UI64
1773 						" bytes. Message ignored.", (zbx_uint64_t)reserved, s->peer,
1774 						(zbx_uint64_t)ZBX_MAX_RECV_DATA_SIZE);
1775 				nbytes = ZBX_PROTO_ERROR;
1776 				goto out;
1777 			}
1778 
1779 			if (sizeof(s->buf_stat) > expected_len)
1780 			{
1781 				buf_stat_bytes -= offset;
1782 				memmove(s->buf_stat, s->buf_stat + offset, buf_stat_bytes);
1783 			}
1784 			else
1785 			{
1786 				s->buf_type = ZBX_BUF_TYPE_DYN;
1787 				s->buffer = (char *)zbx_malloc(NULL, expected_len + 1);
1788 				buf_dyn_bytes = buf_stat_bytes - offset;
1789 				buf_stat_bytes = 0;
1790 				memcpy(s->buffer, s->buf_stat + offset, buf_dyn_bytes);
1791 			}
1792 
1793 			expect = ZBX_TCP_EXPECT_SIZE;
1794 
1795 			if (buf_stat_bytes + buf_dyn_bytes >= expected_len)
1796 				break;
1797 		}
1798 	}
1799 
1800 	if (ZBX_TCP_EXPECT_SIZE == expect)
1801 	{
1802 		if (buf_stat_bytes + buf_dyn_bytes == expected_len)
1803 		{
1804 			if (0 != (protocol_version & ZBX_TCP_COMPRESS))
1805 			{
1806 				char	*out;
1807 				size_t	out_size = reserved;
1808 
1809 				out = (char *)zbx_malloc(NULL, reserved + 1);
1810 				if (FAIL == zbx_uncompress(s->buffer, buf_stat_bytes + buf_dyn_bytes, out, &out_size))
1811 				{
1812 					zbx_free(out);
1813 					zbx_set_socket_strerror("cannot uncompress data: %s", zbx_compress_strerror());
1814 					nbytes = ZBX_PROTO_ERROR;
1815 					goto out;
1816 				}
1817 
1818 				if (out_size != reserved)
1819 				{
1820 					zbx_free(out);
1821 					zbx_set_socket_strerror("size of uncompressed data is less than expected");
1822 					nbytes = ZBX_PROTO_ERROR;
1823 					goto out;
1824 				}
1825 
1826 				if (ZBX_BUF_TYPE_DYN == s->buf_type)
1827 					zbx_free(s->buffer);
1828 
1829 				s->buf_type = ZBX_BUF_TYPE_DYN;
1830 				s->buffer = out;
1831 				s->read_bytes = reserved;
1832 
1833 				zabbix_log(LOG_LEVEL_TRACE, "%s(): received " ZBX_FS_SIZE_T " bytes with"
1834 						" compression ratio %.1f", __function_name,
1835 						(zbx_fs_size_t)(buf_stat_bytes + buf_dyn_bytes),
1836 						(double)reserved / (buf_stat_bytes + buf_dyn_bytes));
1837 			}
1838 			else
1839 				s->read_bytes = buf_stat_bytes + buf_dyn_bytes;
1840 
1841 			s->buffer[s->read_bytes] = '\0';
1842 		}
1843 		else
1844 		{
1845 			if (buf_stat_bytes + buf_dyn_bytes < expected_len)
1846 			{
1847 				zabbix_log(LOG_LEVEL_WARNING, "Message from %s is shorter than expected " ZBX_FS_UI64
1848 						" bytes. Message ignored.", s->peer, (zbx_uint64_t)expected_len);
1849 			}
1850 			else
1851 			{
1852 				zabbix_log(LOG_LEVEL_WARNING, "Message from %s is longer than expected " ZBX_FS_UI64
1853 						" bytes. Message ignored.", s->peer, (zbx_uint64_t)expected_len);
1854 			}
1855 
1856 			nbytes = ZBX_PROTO_ERROR;
1857 		}
1858 	}
1859 	else if (ZBX_TCP_EXPECT_LENGTH == expect)
1860 	{
1861 		zabbix_log(LOG_LEVEL_WARNING, "Message from %s is missing data length. Message ignored.", s->peer);
1862 		nbytes = ZBX_PROTO_ERROR;
1863 	}
1864 	else if (ZBX_TCP_EXPECT_VERSION == expect)
1865 	{
1866 		zabbix_log(LOG_LEVEL_WARNING, "Message from %s is missing protocol version. Message ignored.",
1867 				s->peer);
1868 		nbytes = ZBX_PROTO_ERROR;
1869 	}
1870 	else if (ZBX_TCP_EXPECT_VERSION_VALIDATE == expect)
1871 	{
1872 		zabbix_log(LOG_LEVEL_WARNING, "Message from %s is using unsupported protocol version \"%d\"."
1873 				" Message ignored.", s->peer, protocol_version);
1874 		nbytes = ZBX_PROTO_ERROR;
1875 	}
1876 	else if (0 != buf_stat_bytes)
1877 	{
1878 		zabbix_log(LOG_LEVEL_WARNING, "Message from %s is missing header. Message ignored.", s->peer);
1879 		nbytes = ZBX_PROTO_ERROR;
1880 	}
1881 	else
1882 	{
1883 		s->read_bytes = 0;
1884 		s->buffer[s->read_bytes] = '\0';
1885 	}
1886 out:
1887 	if (0 != timeout)
1888 		zbx_socket_timeout_cleanup(s);
1889 
1890 	return (ZBX_PROTO_ERROR == nbytes ? FAIL : (ssize_t)(s->read_bytes + offset));
1891 
1892 #undef ZBX_TCP_EXPECT_HEADER
1893 #undef ZBX_TCP_EXPECT_LENGTH
1894 #undef ZBX_TCP_EXPECT_SIZE
1895 }
1896 
1897 /******************************************************************************
1898  *                                                                            *
1899  * Function: zbx_tcp_recv_raw_ext                                             *
1900  *                                                                            *
1901  * Purpose: receive data till connection is closed                            *
1902  *                                                                            *
1903  * Return value: number of bytes received - success,                          *
1904  *               FAIL - an error occurred                                     *
1905  *                                                                            *
1906  ******************************************************************************/
1907 ssize_t	zbx_tcp_recv_raw_ext(zbx_socket_t *s, int timeout)
1908 {
1909 	ssize_t		nbytes;
1910 	size_t		allocated = 8 * ZBX_STAT_BUF_LEN, buf_dyn_bytes = 0, buf_stat_bytes = 0;
1911 	zbx_uint64_t	expected_len = 16 * ZBX_MEBIBYTE;
1912 
1913 	if (0 != timeout)
1914 		zbx_socket_timeout_set(s, timeout);
1915 
1916 	zbx_socket_free(s);
1917 
1918 	s->buf_type = ZBX_BUF_TYPE_STAT;
1919 	s->buffer = s->buf_stat;
1920 
1921 	while (0 != (nbytes = zbx_tcp_read(s, s->buf_stat + buf_stat_bytes, sizeof(s->buf_stat) - buf_stat_bytes)))
1922 	{
1923 		if (ZBX_PROTO_ERROR == nbytes)
1924 			goto out;
1925 
1926 		if (ZBX_BUF_TYPE_STAT == s->buf_type)
1927 			buf_stat_bytes += nbytes;
1928 		else
1929 		{
1930 			if (buf_dyn_bytes + nbytes >= allocated)
1931 			{
1932 				while (buf_dyn_bytes + nbytes >= allocated)
1933 					allocated *= 2;
1934 				s->buffer = (char *)zbx_realloc(s->buffer, allocated);
1935 			}
1936 
1937 			memcpy(s->buffer + buf_dyn_bytes, s->buf_stat, nbytes);
1938 			buf_dyn_bytes += nbytes;
1939 		}
1940 
1941 		if (buf_stat_bytes + buf_dyn_bytes >= expected_len)
1942 			break;
1943 
1944 		if (sizeof(s->buf_stat) == buf_stat_bytes)
1945 		{
1946 			s->buf_type = ZBX_BUF_TYPE_DYN;
1947 			s->buffer = (char *)zbx_malloc(NULL, allocated);
1948 			buf_dyn_bytes = sizeof(s->buf_stat);
1949 			buf_stat_bytes = 0;
1950 			memcpy(s->buffer, s->buf_stat, sizeof(s->buf_stat));
1951 		}
1952 	}
1953 
1954 	if (buf_stat_bytes + buf_dyn_bytes >= expected_len)
1955 	{
1956 		zabbix_log(LOG_LEVEL_WARNING, "Message from %s is longer than " ZBX_FS_UI64 " bytes allowed for"
1957 				" plain text. Message ignored.", s->peer, expected_len);
1958 		nbytes = ZBX_PROTO_ERROR;
1959 		goto out;
1960 	}
1961 
1962 	s->read_bytes = buf_stat_bytes + buf_dyn_bytes;
1963 	s->buffer[s->read_bytes] = '\0';
1964 out:
1965 	if (0 != timeout)
1966 		zbx_socket_timeout_cleanup(s);
1967 
1968 	return (ZBX_PROTO_ERROR == nbytes ? FAIL : (ssize_t)(s->read_bytes));
1969 }
1970 
1971 static int	subnet_match(int af, unsigned int prefix_size, const void *address1, const void *address2)
1972 {
1973 	unsigned char	netmask[16] = {0};
1974 	int		i, j, bytes;
1975 
1976 	if (af == AF_INET)
1977 	{
1978 		if (prefix_size > IPV4_MAX_CIDR_PREFIX)
1979 			return FAIL;
1980 		bytes = 4;
1981 	}
1982 	else
1983 	{
1984 		if (prefix_size > IPV6_MAX_CIDR_PREFIX)
1985 			return FAIL;
1986 		bytes = 16;
1987 	}
1988 
1989 	/* CIDR notation to subnet mask */
1990 	for (i = (int)prefix_size, j = 0; i > 0 && j < bytes; i -= 8, j++)
1991 		netmask[j] = i >= 8 ? 0xFF : ~((1 << (8 - i)) - 1);
1992 
1993 	/* The result of the bitwise AND operation of IP address and the subnet mask is the network prefix. */
1994 	/* All hosts on a subnetwork have the same network prefix. */
1995 	for (i = 0; i < bytes; i++)
1996 	{
1997 		if ((((const unsigned char *)address1)[i] & netmask[i]) !=
1998 				(((const unsigned char *)address2)[i] & netmask[i]))
1999 		{
2000 			return FAIL;
2001 		}
2002 	}
2003 
2004 	return SUCCEED;
2005 }
2006 
2007 #ifndef HAVE_IPV6
2008 static int	zbx_ip_cmp(unsigned int prefix_size, const struct addrinfo *current_ai, ZBX_SOCKADDR name)
2009 {
2010 	struct sockaddr_in	*name4 = (struct sockaddr_in *)&name,
2011 				*ai_addr4 = (struct sockaddr_in *)current_ai->ai_addr;
2012 
2013 	return subnet_match(current_ai->ai_family, prefix_size, &name4->sin_addr.s_addr, &ai_addr4->sin_addr.s_addr);
2014 }
2015 #else
2016 static int	zbx_ip_cmp(unsigned int prefix_size, const struct addrinfo *current_ai, ZBX_SOCKADDR name)
2017 {
2018 	/* Network Byte Order is ensured */
2019 	/* IPv4-compatible, the first 96 bits are zeros */
2020 	const unsigned char	ipv4_compat_mask[12] = {0};
2021 	/* IPv4-mapped, the first 80 bits are zeros, 16 next - ones */
2022 	const unsigned char	ipv4_mapped_mask[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255};
2023 
2024 	struct sockaddr_in	*name4 = (struct sockaddr_in *)&name,
2025 				*ai_addr4 = (struct sockaddr_in *)current_ai->ai_addr;
2026 	struct sockaddr_in6	*name6 = (struct sockaddr_in6 *)&name,
2027 				*ai_addr6 = (struct sockaddr_in6 *)current_ai->ai_addr;
2028 
2029 #ifdef HAVE_SOCKADDR_STORAGE_SS_FAMILY
2030 	if (current_ai->ai_family == name.ss_family)
2031 #else
2032 	if (current_ai->ai_family == name.__ss_family)
2033 #endif
2034 	{
2035 		switch (current_ai->ai_family)
2036 		{
2037 			case AF_INET:
2038 				if (SUCCEED == subnet_match(current_ai->ai_family, prefix_size, &name4->sin_addr.s_addr,
2039 						&ai_addr4->sin_addr.s_addr))
2040 				{
2041 					return SUCCEED;
2042 				}
2043 				break;
2044 			case AF_INET6:
2045 				if (SUCCEED == subnet_match(current_ai->ai_family, prefix_size, name6->sin6_addr.s6_addr,
2046 						ai_addr6->sin6_addr.s6_addr))
2047 				{
2048 					return SUCCEED;
2049 				}
2050 				break;
2051 		}
2052 	}
2053 	else
2054 	{
2055 		unsigned char	ipv6_compat_address[16], ipv6_mapped_address[16];
2056 
2057 		switch (current_ai->ai_family)
2058 		{
2059 			case AF_INET:
2060 				/* incoming AF_INET6, must see whether it is compatible or mapped */
2061 				if ((0 == memcmp(name6->sin6_addr.s6_addr, ipv4_compat_mask, 12) ||
2062 						0 == memcmp(name6->sin6_addr.s6_addr, ipv4_mapped_mask, 12)) &&
2063 						SUCCEED == subnet_match(AF_INET, prefix_size,
2064 						&name6->sin6_addr.s6_addr[12], &ai_addr4->sin_addr.s_addr))
2065 				{
2066 					return SUCCEED;
2067 				}
2068 				break;
2069 			case AF_INET6:
2070 				/* incoming AF_INET, must see whether the given is compatible or mapped */
2071 				memcpy(ipv6_compat_address, ipv4_compat_mask, sizeof(ipv4_compat_mask));
2072 				memcpy(&ipv6_compat_address[sizeof(ipv4_compat_mask)], &name4->sin_addr.s_addr, 4);
2073 
2074 				memcpy(ipv6_mapped_address, ipv4_mapped_mask, sizeof(ipv4_mapped_mask));
2075 				memcpy(&ipv6_mapped_address[sizeof(ipv4_mapped_mask)], &name4->sin_addr.s_addr, 4);
2076 
2077 				if (SUCCEED == subnet_match(AF_INET6, prefix_size,
2078 						&ai_addr6->sin6_addr.s6_addr, ipv6_compat_address) ||
2079 						SUCCEED == subnet_match(AF_INET6, prefix_size,
2080 						&ai_addr6->sin6_addr.s6_addr, ipv6_mapped_address))
2081 				{
2082 					return SUCCEED;
2083 				}
2084 				break;
2085 		}
2086 	}
2087 	return FAIL;
2088 }
2089 #endif
2090 
2091 static int	validate_cidr(const char *ip, const char *cidr, void *value)
2092 {
2093 	if (SUCCEED == is_ip4(ip))
2094 		return is_uint_range(cidr, value, 0, IPV4_MAX_CIDR_PREFIX);
2095 #ifdef HAVE_IPV6
2096 	if (SUCCEED == is_ip6(ip))
2097 		return is_uint_range(cidr, value, 0, IPV6_MAX_CIDR_PREFIX);
2098 #endif
2099 	return FAIL;
2100 }
2101 
2102 int	zbx_validate_peer_list(const char *peer_list, char **error)
2103 {
2104 	char	*start, *end, *cidr_sep;
2105 	char	tmp[MAX_STRING_LEN];
2106 
2107 	strscpy(tmp, peer_list);
2108 
2109 	for (start = tmp; '\0' != *start;)
2110 	{
2111 		if (NULL != (end = strchr(start, ',')))
2112 			*end = '\0';
2113 
2114 		if (NULL != (cidr_sep = strchr(start, '/')))
2115 		{
2116 			*cidr_sep = '\0';
2117 
2118 			if (FAIL == validate_cidr(start, cidr_sep + 1, NULL))
2119 			{
2120 				*cidr_sep = '/';
2121 				*error = zbx_dsprintf(NULL, "\"%s\"", start);
2122 				return FAIL;
2123 			}
2124 		}
2125 		else if (FAIL == is_supported_ip(start) && FAIL == zbx_validate_hostname(start))
2126 		{
2127 			*error = zbx_dsprintf(NULL, "\"%s\"", start);
2128 			return FAIL;
2129 		}
2130 
2131 		if (NULL != end)
2132 			start = end + 1;
2133 		else
2134 			break;
2135 	}
2136 
2137 	return SUCCEED;
2138 }
2139 
2140 /******************************************************************************
2141  *                                                                            *
2142  * Function: zbx_tcp_check_allowed_peers                                      *
2143  *                                                                            *
2144  * Purpose: check if connection initiator is in list of peers                 *
2145  *                                                                            *
2146  * Parameters: s         - [IN] socket descriptor                             *
2147  *             peer_list - [IN] comma-delimited list of allowed peers.        *
2148  *                              NULL not allowed. Empty string results in     *
2149  *                              return value FAIL.                            *
2150  *                                                                            *
2151  * Return value: SUCCEED - connection allowed                                 *
2152  *               FAIL - connection is not allowed                             *
2153  *                                                                            *
2154  * Author: Alexei Vladishev, Dmitry Borovikov                                 *
2155  *                                                                            *
2156  * Comments: standard, compatible and IPv4-mapped addresses are treated       *
2157  *           the same: 127.0.0.1 == ::127.0.0.1 == ::ffff:127.0.0.1           *
2158  *                                                                            *
2159  ******************************************************************************/
2160 int	zbx_tcp_check_allowed_peers(const zbx_socket_t *s, const char *peer_list)
2161 {
2162 	char	*start = NULL, *end = NULL, *cidr_sep, tmp[MAX_STRING_LEN];
2163 	int	prefix_size;
2164 
2165 	/* examine list of allowed peers which may include DNS names, IPv4/6 addresses and addresses in CIDR notation */
2166 
2167 	strscpy(tmp, peer_list);
2168 
2169 	for (start = tmp; '\0' != *start;)
2170 	{
2171 		struct addrinfo	hints, *ai = NULL, *current_ai;
2172 
2173 		prefix_size = -1;
2174 
2175 		if (NULL != (end = strchr(start, ',')))
2176 			*end = '\0';
2177 
2178 		if (NULL != (cidr_sep = strchr(start, '/')))
2179 		{
2180 			*cidr_sep = '\0';
2181 
2182 			/* validate_cidr() may overwrite 'prefix_size' */
2183 			if (SUCCEED != validate_cidr(start, cidr_sep + 1, &prefix_size))
2184 				*cidr_sep = '/';	/* CIDR is only supported for IP */
2185 		}
2186 
2187 		memset(&hints, 0, sizeof(hints));
2188 		hints.ai_family = AF_UNSPEC;
2189 		hints.ai_socktype = SOCK_STREAM;
2190 		hints.ai_protocol = IPPROTO_TCP;
2191 
2192 		if (0 == getaddrinfo(start, NULL, &hints, &ai))
2193 		{
2194 			for (current_ai = ai; NULL != current_ai; current_ai = current_ai->ai_next)
2195 			{
2196 				int	prefix_size_current = prefix_size;
2197 
2198 				if (-1 == prefix_size_current)
2199 				{
2200 					prefix_size_current = (current_ai->ai_family == AF_INET ?
2201 							IPV4_MAX_CIDR_PREFIX : IPV6_MAX_CIDR_PREFIX);
2202 				}
2203 
2204 				if (SUCCEED == zbx_ip_cmp(prefix_size_current, current_ai, s->peer_info))
2205 				{
2206 					freeaddrinfo(ai);
2207 					return SUCCEED;
2208 				}
2209 			}
2210 			freeaddrinfo(ai);
2211 		}
2212 
2213 		if (NULL != end)
2214 			start = end + 1;
2215 		else
2216 			break;
2217 	}
2218 
2219 	zbx_set_socket_strerror("connection from \"%s\" rejected, allowed hosts: \"%s\"", s->peer, peer_list);
2220 
2221 	return FAIL;
2222 }
2223 
2224 /******************************************************************************
2225  *                                                                            *
2226  * Function: zbx_tcp_connection_type_name                                     *
2227  *                                                                            *
2228  * Purpose: translate connection type code to name                            *
2229  *                                                                            *
2230  ******************************************************************************/
2231 const char	*zbx_tcp_connection_type_name(unsigned int type)
2232 {
2233 	switch (type)
2234 	{
2235 		case ZBX_TCP_SEC_UNENCRYPTED:
2236 			return "unencrypted";
2237 		case ZBX_TCP_SEC_TLS_CERT:
2238 			return "TLS with certificate";
2239 		case ZBX_TCP_SEC_TLS_PSK:
2240 			return "TLS with PSK";
2241 		default:
2242 			return "unknown";
2243 	}
2244 }
2245 
2246 int	zbx_udp_connect(zbx_socket_t *s, const char *source_ip, const char *ip, unsigned short port, int timeout)
2247 {
2248 	return zbx_socket_create(s, SOCK_DGRAM, source_ip, ip, port, timeout, ZBX_TCP_SEC_UNENCRYPTED, NULL, NULL);
2249 }
2250 
2251 int	zbx_udp_send(zbx_socket_t *s, const char *data, size_t data_len, int timeout)
2252 {
2253 	int	ret = SUCCEED;
2254 
2255 	if (0 != timeout)
2256 		zbx_socket_timeout_set(s, timeout);
2257 
2258 	if (ZBX_PROTO_ERROR == zbx_sendto(s->socket, data, data_len, 0, NULL, 0))
2259 	{
2260 		zbx_set_socket_strerror("sendto() failed: %s", strerror_from_system(zbx_socket_last_error()));
2261 		ret = FAIL;
2262 	}
2263 
2264 	if (0 != timeout)
2265 		zbx_socket_timeout_cleanup(s);
2266 
2267 	return ret;
2268 }
2269 
2270 int	zbx_udp_recv(zbx_socket_t *s, int timeout)
2271 {
2272 	char	buffer[65508];	/* maximum payload for UDP over IPv4 is 65507 bytes */
2273 	ssize_t	read_bytes;
2274 
2275 	zbx_socket_free(s);
2276 
2277 	if (0 != timeout)
2278 		zbx_socket_timeout_set(s, timeout);
2279 
2280 	if (ZBX_PROTO_ERROR == (read_bytes = recvfrom(s->socket, buffer, sizeof(buffer) - 1, 0, NULL, NULL)))
2281 		zbx_set_socket_strerror("recvfrom() failed: %s", strerror_from_system(zbx_socket_last_error()));
2282 
2283 	if (0 != timeout)
2284 		zbx_socket_timeout_cleanup(s);
2285 
2286 	if (ZBX_PROTO_ERROR == read_bytes)
2287 		return FAIL;
2288 
2289 	if (sizeof(s->buf_stat) > (size_t)read_bytes)
2290 	{
2291 		s->buf_type = ZBX_BUF_TYPE_STAT;
2292 		s->buffer = s->buf_stat;
2293 	}
2294 	else
2295 	{
2296 		s->buf_type = ZBX_BUF_TYPE_DYN;
2297 		s->buffer = (char *)zbx_malloc(s->buffer, read_bytes + 1);
2298 	}
2299 
2300 	buffer[read_bytes] = '\0';
2301 	memcpy(s->buffer, buffer, read_bytes + 1);
2302 
2303 	s->read_bytes = (size_t)read_bytes;
2304 
2305 	return SUCCEED;
2306 }
2307 
2308 void	zbx_udp_close(zbx_socket_t *s)
2309 {
2310 	zbx_socket_timeout_cleanup(s);
2311 
2312 	zbx_socket_free(s);
2313 	zbx_socket_close(s->socket);
2314 }
2315