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