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