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 
22 #include "threads.h"
23 #include "comms.h"
24 #include "cfg.h"
25 #include "log.h"
26 #include "zbxgetopt.h"
27 #include "zbxjson.h"
28 #include "mutexs.h"
29 #include "zbxcrypto.h"
30 #if defined(_WINDOWS)
31 #	include "../libs/zbxcrypto/tls.h"
32 #else
33 #	include "zbxnix.h"
34 #endif
35 
36 const char	*progname = NULL;
37 const char	title_message[] = "zabbix_sender";
38 const char	syslog_app_name[] = "zabbix_sender";
39 
40 const char	*usage_message[] = {
41 	"[-v]", "-z server", "[-p port]", "[-I IP-address]", "-s host", "-k key", "-o value", NULL,
42 	"[-v]", "-z server", "[-p port]", "[-I IP-address]", "[-s host]", "[-T]", "[-N]", "[-r]", "-i input-file",
43 	NULL,
44 	"[-v]", "-c config-file", "[-z server]", "[-p port]", "[-I IP-address]", "[-s host]", "-k key", "-o value",
45 	NULL,
46 	"[-v]", "-c config-file", "[-z server]", "[-p port]", "[-I IP-address]", "[-s host]", "[-T]", "[-N]", "[-r]",
47 	"-i input-file", NULL,
48 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
49 	"[-v]", "-z server", "[-p port]", "[-I IP-address]", "-s host", "--tls-connect cert", "--tls-ca-file CA-file",
50 	"[--tls-crl-file CRL-file]", "[--tls-server-cert-issuer cert-issuer]",
51 	"[--tls-server-cert-subject cert-subject]", "--tls-cert-file cert-file", "--tls-key-file key-file",
52 #if defined(HAVE_OPENSSL)
53 	"[--tls-cipher13 cipher-string]",
54 #endif
55 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
56 	"[--tls-cipher cipher-string]",
57 #endif
58 	"-k key", "-o value", NULL,
59 	"[-v]", "-z server", "[-p port]", "[-I IP-address]", "[-s host]", "--tls-connect cert", "--tls-ca-file CA-file",
60 	"[--tls-crl-file CRL-file]", "[--tls-server-cert-issuer cert-issuer]",
61 	"[--tls-server-cert-subject cert-subject]", "--tls-cert-file cert-file", "--tls-key-file key-file",
62 #if defined(HAVE_OPENSSL)
63 	"[--tls-cipher13] cipher-string",
64 #endif
65 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
66 	"[--tls-cipher cipher-string]",
67 #endif
68 	"[-T]", "[-N]", "[-r]", "-i input-file", NULL,
69 	"[-v]", "-c config-file [-z server]", "[-p port]", "[-I IP-address]", "[-s host]", "--tls-connect cert",
70 	"--tls-ca-file CA-file", "[--tls-crl-file CRL-file]", "[--tls-server-cert-issuer cert-issuer]",
71 	"[--tls-server-cert-subject cert-subject]", "--tls-cert-file cert-file", "--tls-key-file key-file",
72 #if defined(HAVE_OPENSSL)
73 	"[--tls-cipher13 cipher-string]",
74 #endif
75 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
76 	"[--tls-cipher cipher-string]",
77 #endif
78 	"-k key", "-o value", NULL,
79 	"[-v]", "-c config-file", "[-z server]", "[-p port]", "[-I IP-address]", "[-s host]", "--tls-connect cert",
80 	"--tls-ca-file CA-file", "[--tls-crl-file CRL-file]", "[--tls-server-cert-issuer cert-issuer]",
81 	"[--tls-server-cert-subject cert-subject]", "--tls-cert-file cert-file", "--tls-key-file key-file",
82 #if defined(HAVE_OPENSSL)
83 	"[--tls-cipher13 cipher-string]",
84 #endif
85 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
86 	"[--tls-cipher cipher-string]",
87 #endif
88 	"[-T]", "[-N]", "[-r]", "-i input-file", NULL,
89 	"[-v]", "-z server", "[-p port]", "[-I IP-address]", "-s host", "--tls-connect psk",
90 	"--tls-psk-identity PSK-identity", "--tls-psk-file PSK-file",
91 #if defined(HAVE_OPENSSL)
92 	"[--tls-cipher13 cipher-string]",
93 #endif
94 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
95 	"[--tls-cipher cipher-string]",
96 #endif
97 	"-k key", "-o value", NULL,
98 	"[-v]", "-z server", "[-p port]", "[-I IP-address]", "[-s host]", "--tls-connect psk",
99 	"--tls-psk-identity PSK-identity", "--tls-psk-file PSK-file",
100 #if defined(HAVE_OPENSSL)
101 	"[--tls-cipher13 cipher-string]",
102 #endif
103 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
104 	"[--tls-cipher cipher-string]",
105 #endif
106 	"[-T]", "[-N]", "[-r]", "-i input-file", NULL,
107 	"[-v]", "-c config-file", "[-z server]", "[-p port]", "[-I IP-address]", "[-s host]", "--tls-connect psk",
108 	"--tls-psk-identity PSK-identity", "--tls-psk-file PSK-file",
109 #if defined(HAVE_OPENSSL)
110 	"[--tls-cipher13 cipher-string]",
111 #endif
112 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
113 	"[--tls-cipher cipher-string]",
114 #endif
115 	"-k key", "-o value", NULL,
116 	"[-v]", "-c config-file", "[-z server]", "[-p port]", "[-I IP-address]", "[-s host]", "--tls-connect psk",
117 	"--tls-psk-identity PSK-identity", "--tls-psk-file PSK-file",
118 #if defined(HAVE_OPENSSL)
119 	"[--tls-cipher13 cipher-string]",
120 #endif
121 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
122 	"[--tls-cipher cipher-string]",
123 #endif
124 	"[-T]", "[-N]", "[-r]", "-i input-file", NULL,
125 #endif
126 	"-h", NULL,
127 	"-V", NULL,
128 	NULL	/* end of text */
129 };
130 
131 unsigned char	program_type	= ZBX_PROGRAM_TYPE_SENDER;
132 
133 const char	*help_message[] = {
134 	"Utility for sending monitoring data to Zabbix server or proxy.",
135 	"",
136 	"General options:",
137 	"  -c --config config-file    Path to Zabbix agentd configuration file",
138 	"",
139 	"  -z --zabbix-server server  Hostname or IP address of Zabbix server or proxy",
140 	"                             to send data to. When used together with --config,",
141 	"                             overrides the first entry of \"ServerActive\"",
142 	"                             parameter specified in agentd configuration file",
143 	"",
144 	"  -p --port port             Specify port number of trapper process of Zabbix",
145 	"                             server or proxy. When used together with --config,",
146 	"                             overrides the port of the first entry of",
147 	"                             \"ServerActive\" parameter specified in agentd",
148 	"                             configuration file (default: " ZBX_DEFAULT_SERVER_PORT_STR ")",
149 	"",
150 	"  -I --source-address IP-address   Specify source IP address. When used",
151 	"                             together with --config, overrides \"SourceIP\"",
152 	"                             parameter specified in agentd configuration file",
153 	"",
154 	"  -s --host host             Specify host name the item belongs to (as",
155 	"                             registered in Zabbix frontend). Host IP address",
156 	"                             and DNS name will not work. When used together",
157 	"                             with --config, overrides \"Hostname\" parameter",
158 	"                             specified in agentd configuration file",
159 	"",
160 	"  -k --key key               Specify item key",
161 	"  -o --value value           Specify item value",
162 	"",
163 	"  -i --input-file input-file   Load values from input file. Specify - for",
164 	"                             standard input. Each line of file contains",
165 	"                             whitespace delimited: <host> <key> <value>.",
166 	"                             Specify - in <host> to use hostname from",
167 	"                             configuration file or --host argument",
168 	"",
169 	"  -T --with-timestamps       Each line of file contains whitespace delimited:",
170 	"                             <host> <key> <timestamp> <value>. This can be used",
171 	"                             with --input-file option. Timestamp should be",
172 	"                             specified in Unix timestamp format",
173 	"",
174 	"  -N --with-ns               Each line of file contains whitespace delimited:",
175 	"                             <host> <key> <timestamp> <ns> <value>. This can be used",
176 	"                             with --with-timestamps option",
177 	"",
178 	"  -r --real-time             Send metrics one by one as soon as they are",
179 	"                             received. This can be used when reading from",
180 	"                             standard input",
181 	"",
182 	"  -v --verbose               Verbose mode, -vv for more details",
183 	"",
184 	"  -h --help                  Display this help message",
185 	"  -V --version               Display version number",
186 	"",
187 	"TLS connection options:",
188 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
189 	"  --tls-connect value        How to connect to server or proxy. Values:",
190 	"                               unencrypted - connect without encryption",
191 	"                                             (default)",
192 	"                               psk         - connect using TLS and a pre-shared",
193 	"                                             key",
194 	"                               cert        - connect using TLS and a",
195 	"                                             certificate",
196 	"",
197 	"  --tls-ca-file CA-file      Full pathname of a file containing the top-level",
198 	"                             CA(s) certificates for peer certificate",
199 	"                             verification",
200 	"",
201 	"  --tls-crl-file CRL-file    Full pathname of a file containing revoked",
202 	"                             certificates",
203 	"",
204 	"  --tls-server-cert-issuer cert-issuer   Allowed server certificate issuer",
205 	"",
206 	"  --tls-server-cert-subject cert-subject   Allowed server certificate subject",
207 	"",
208 	"  --tls-cert-file cert-file  Full pathname of a file containing the certificate",
209 	"                             or certificate chain",
210 	"",
211 	"  --tls-key-file key-file    Full pathname of a file containing the private key",
212 	"",
213 	"  --tls-psk-identity PSK-identity   Unique, case sensitive string used to",
214 	"                             identify the pre-shared key",
215 	"",
216 	"  --tls-psk-file PSK-file    Full pathname of a file containing the pre-shared",
217 	"                             key",
218 #if defined(HAVE_OPENSSL)
219 	"",
220 	"  --tls-cipher13             Cipher string for OpenSSL 1.1.1 or newer for",
221 	"                             TLS 1.3. Override the default ciphersuite",
222 	"                             selection criteria. This option is not available",
223 	"                             if OpenSSL version is less than 1.1.1",
224 #endif
225 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
226 	"",
227 	"  --tls-cipher               GnuTLS priority string (for TLS 1.2 and up) or",
228 	"                             OpenSSL cipher string (only for TLS 1.2).",
229 	"                             Override the default ciphersuite selection",
230 	"                             criteria",
231 #endif
232 #else
233 	"  Not available. This Zabbix sender was compiled without TLS support",
234 #endif
235 	"",
236 	"Example(s):",
237 	"  zabbix_sender -z 127.0.0.1 -s \"Linux DB3\" -k db.connections -o 43",
238 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
239 	"",
240 	"  zabbix_sender -z 127.0.0.1 -s \"Linux DB3\" -k db.connections -o 43 \\",
241 	"    --tls-connect cert --tls-ca-file /home/zabbix/zabbix_ca_file \\",
242 	"    --tls-server-cert-issuer \\",
243 	"    \"CN=Signing CA,OU=IT operations,O=Example Corp,DC=example,DC=com\" \\",
244 	"    --tls-server-cert-subject \\",
245 	"    \"CN=Zabbix proxy,OU=IT operations,O=Example Corp,DC=example,DC=com\" \\",
246 	"    --tls-cert-file /home/zabbix/zabbix_agentd.crt \\",
247 	"    --tls-key-file /home/zabbix/zabbix_agentd.key",
248 	"",
249 	"  zabbix_sender -z 127.0.0.1 -s \"Linux DB3\" -k db.connections -o 43 \\",
250 	"    --tls-connect psk --tls-psk-identity \"PSK ID Zabbix agentd\" \\",
251 	"    --tls-psk-file /home/zabbix/zabbix_agentd.psk",
252 #endif
253 	NULL	/* end of text */
254 };
255 
256 /* TLS parameters */
257 unsigned int	configured_tls_connect_mode = ZBX_TCP_SEC_UNENCRYPTED;
258 unsigned int	configured_tls_accept_modes = ZBX_TCP_SEC_UNENCRYPTED;	/* not used in zabbix_sender, just for */
259 									/* linking with tls.c */
260 char	*CONFIG_TLS_CONNECT		= NULL;
261 char	*CONFIG_TLS_ACCEPT		= NULL;	/* not used in zabbix_sender, just for linking with tls.c */
262 char	*CONFIG_TLS_CA_FILE		= NULL;
263 char	*CONFIG_TLS_CRL_FILE		= NULL;
264 char	*CONFIG_TLS_SERVER_CERT_ISSUER	= NULL;
265 char	*CONFIG_TLS_SERVER_CERT_SUBJECT	= NULL;
266 char	*CONFIG_TLS_CERT_FILE		= NULL;
267 char	*CONFIG_TLS_KEY_FILE		= NULL;
268 char	*CONFIG_TLS_PSK_IDENTITY	= NULL;
269 char	*CONFIG_TLS_PSK_FILE		= NULL;
270 
271 char	*CONFIG_TLS_CIPHER_CERT13	= NULL;	/* parameter 'TLSCipherCert13' from agent config file */
272 char	*CONFIG_TLS_CIPHER_CERT		= NULL;	/* parameter 'TLSCipherCert' from agent config file */
273 char	*CONFIG_TLS_CIPHER_PSK13	= NULL;	/* parameter 'TLSCipherPSK13' from agent config file */
274 char	*CONFIG_TLS_CIPHER_PSK		= NULL;	/* parameter 'TLSCipherPSK' from agent config file */
275 char	*CONFIG_TLS_CIPHER_ALL13	= NULL;	/* not used in zabbix_sender, just for linking with tls.c */
276 char	*CONFIG_TLS_CIPHER_ALL		= NULL;	/* not used in zabbix_sender, just for linking with tls.c */
277 char	*CONFIG_TLS_CIPHER_CMD13	= NULL;	/* parameter '--tls-cipher13' from sender command line */
278 char	*CONFIG_TLS_CIPHER_CMD		= NULL;	/* parameter '--tls-cipher' from sender command line */
279 
280 int	CONFIG_PASSIVE_FORKS		= 0;	/* not used in zabbix_sender, just for linking with tls.c */
281 int	CONFIG_ACTIVE_FORKS		= 0;	/* not used in zabbix_sender, just for linking with tls.c */
282 
283 int	CONFIG_TCP_MAX_BACKLOG_SIZE	= SOMAXCONN;
284 
285 /* COMMAND LINE OPTIONS */
286 
287 /* long options */
288 static struct zbx_option	longopts[] =
289 {
290 	{"config",			1,	NULL,	'c'},
291 	{"zabbix-server",		1,	NULL,	'z'},
292 	{"port",			1,	NULL,	'p'},
293 	{"host",			1,	NULL,	's'},
294 	{"source-address",		1,	NULL,	'I'},
295 	{"key",				1,	NULL,	'k'},
296 	{"value",			1,	NULL,	'o'},
297 	{"input-file",			1,	NULL,	'i'},
298 	{"with-timestamps",		0,	NULL,	'T'},
299 	{"with-ns",			0,	NULL,	'N'},
300 	{"real-time",			0,	NULL,	'r'},
301 	{"verbose",			0,	NULL,	'v'},
302 	{"help",			0,	NULL,	'h'},
303 	{"version",			0,	NULL,	'V'},
304 	{"tls-connect",			1,	NULL,	'1'},
305 	{"tls-ca-file",			1,	NULL,	'2'},
306 	{"tls-crl-file",		1,	NULL,	'3'},
307 	{"tls-server-cert-issuer",	1,	NULL,	'4'},
308 	{"tls-server-cert-subject",	1,	NULL,	'5'},
309 	{"tls-cert-file",		1,	NULL,	'6'},
310 	{"tls-key-file",		1,	NULL,	'7'},
311 	{"tls-psk-identity",		1,	NULL,	'8'},
312 	{"tls-psk-file",		1,	NULL,	'9'},
313 	{"tls-cipher13",		1,	NULL,	'A'},
314 	{"tls-cipher",			1,	NULL,	'B'},
315 	{NULL}
316 };
317 
318 /* short options */
319 static char	shortopts[] = "c:I:z:p:s:k:o:TNi:rvhV";
320 
321 /* end of COMMAND LINE OPTIONS */
322 
323 static int	CONFIG_LOG_LEVEL = LOG_LEVEL_CRIT;
324 
325 static char	*INPUT_FILE = NULL;
326 static int	WITH_TIMESTAMPS = 0;
327 static int	WITH_NS = 0;
328 static int	REAL_TIME = 0;
329 
330 static char	*CONFIG_SOURCE_IP = NULL;
331 static char	*ZABBIX_SERVER = NULL;
332 static char	*ZABBIX_SERVER_PORT = NULL;
333 static char	*ZABBIX_HOSTNAME = NULL;
334 static char	*ZABBIX_KEY = NULL;
335 static char	*ZABBIX_KEY_VALUE = NULL;
336 
337 typedef struct
338 {
339 	char			*host;
340 	unsigned short		port;
341 	ZBX_THREAD_HANDLE	*thread;
342 }
343 zbx_send_destinations_t;
344 
345 static zbx_send_destinations_t	*destinations = NULL;		/* list of servers to send data to */
346 static int			destinations_count = 0;
347 
348 volatile sig_atomic_t	sig_exiting = 0;
349 
350 #if !defined(_WINDOWS)
sender_signal_handler(int sig)351 static void	sender_signal_handler(int sig)
352 {
353 #define CASE_LOG_WARNING(signal) \
354 	case signal:							\
355 		zabbix_log(LOG_LEVEL_WARNING, "interrupted by signal " #signal " while executing operation"); \
356 		break
357 
358 	switch (sig)
359 	{
360 		CASE_LOG_WARNING(SIGALRM);
361 		CASE_LOG_WARNING(SIGINT);
362 		CASE_LOG_WARNING(SIGQUIT);
363 		CASE_LOG_WARNING(SIGTERM);
364 		CASE_LOG_WARNING(SIGHUP);
365 		CASE_LOG_WARNING(SIGPIPE);
366 		default:
367 			zabbix_log(LOG_LEVEL_WARNING, "signal %d while executing operation", sig);
368 	}
369 #undef CASE_LOG_WARNING
370 
371 	/* Calling _exit() to terminate the process immediately is important. See ZBX-5732 for details. */
372 	/* Return FAIL instead of EXIT_FAILURE to keep return signals consistent for send_value() */
373 	_exit(FAIL);
374 }
375 
main_signal_handler(int sig)376 static void	main_signal_handler(int sig)
377 {
378 	if (0 == sig_exiting)
379 	{
380 		int	i;
381 
382 		sig_exiting = 1;
383 
384 		for (i = 0; i < destinations_count; i++)
385 		{
386 			pid_t	child = *(destinations[i].thread);
387 
388 			if (ZBX_THREAD_HANDLE_NULL != child)
389 				kill(child, sig);
390 		}
391 	}
392 }
393 #endif
394 
395 typedef struct
396 {
397 	char		*server;
398 	unsigned short	port;
399 	struct zbx_json	json;
400 #if defined(_WINDOWS) && (defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL))
401 	ZBX_THREAD_SENDVAL_TLS_ARGS	tls_vars;
402 #endif
403 	int		sync_timestamp;
404 }
405 ZBX_THREAD_SENDVAL_ARGS;
406 
407 #define SUCCEED_PARTIAL	2
408 
409 /******************************************************************************
410  *                                                                            *
411  * Function: sender_threads_wait                                              *
412  *                                                                            *
413  * Purpose: waits until the "threads" are in the signalled state and manages  *
414  *          exit status updates                                               *
415  *                                                                            *
416  * Parameters:                                                                *
417  *      threads -     [IN] thread handles                                     *
418  *      threads_num - [IN] thread count                                       *
419  *      old_status  - [IN] previous status                                    *
420  *                                                                            *
421  * Return value:  SUCCEED - success with all values at all destinations       *
422  *                FAIL - an error occurred                                    *
423  *                SUCCEED_PARTIAL - data sending was completed successfully   *
424  *                to at least one destination or processing of at least one   *
425  *                value at least at one destination failed                    *
426  *                                                                            *
427  * Comments: SUCCEED_PARTIAL status should be sticky in the sense that        *
428  *           SUCCEED statuses that come after should not overwrite it         *
429  *                                                                            *
430  ******************************************************************************/
sender_threads_wait(ZBX_THREAD_HANDLE * threads,int threads_num,const int old_status)431 static int	sender_threads_wait(ZBX_THREAD_HANDLE *threads, int threads_num, const int old_status)
432 {
433 	int		i, sp_count = 0, fail_count = 0;
434 #if defined(_WINDOWS)
435 	/* wait for threads to finish */
436 	WaitForMultipleObjectsEx(threads_num, threads, TRUE, INFINITE, FALSE);
437 #endif
438 	for (i = 0; i < threads_num; i++)
439 	{
440 		int	new_status;
441 
442 		if (SUCCEED_PARTIAL == (new_status = zbx_thread_wait(threads[i])))
443 				sp_count++;
444 
445 		if (SUCCEED != new_status && SUCCEED_PARTIAL != new_status)
446 		{
447 			int	j;
448 
449 			for (fail_count++, j = 0; j < destinations_count; j++)
450 			{
451 				if (destinations[j].thread == &threads[i])
452 				{
453 					zbx_free(destinations[j].host);
454 					destinations[j] = destinations[--destinations_count];
455 					break;
456 				}
457 			}
458 		}
459 
460 		threads[i] = ZBX_THREAD_HANDLE_NULL;
461 	}
462 
463 	if (threads_num == fail_count)
464 		return FAIL;
465 	else if (SUCCEED_PARTIAL == old_status || 0 != sp_count || 0 != fail_count)
466 		return SUCCEED_PARTIAL;
467 	else
468 		return SUCCEED;
469 }
470 
471 /******************************************************************************
472  *                                                                            *
473  * Function: get_string                                                       *
474  *                                                                            *
475  * Purpose: get current string from the quoted or unquoted string list,       *
476  *          delimited by blanks                                               *
477  *                                                                            *
478  * Parameters:                                                                *
479  *      p       - [IN] parameter list, delimited by blanks (' ' or '\t')      *
480  *      buf     - [OUT] output buffer                                         *
481  *      bufsize - [IN] output buffer size                                     *
482  *                                                                            *
483  * Return value: pointer to the next string                                   *
484  *                                                                            *
485  ******************************************************************************/
get_string(const char * p,char * buf,size_t bufsize)486 static const char	*get_string(const char *p, char *buf, size_t bufsize)
487 {
488 /* 0 - init, 1 - inside quoted param, 2 - inside unquoted param */
489 	int	state;
490 	size_t	buf_i = 0;
491 
492 	bufsize--;	/* '\0' */
493 
494 	for (state = 0; '\0' != *p; p++)
495 	{
496 		switch (state)
497 		{
498 			/* init state */
499 			case 0:
500 				if (' ' == *p || '\t' == *p)
501 				{
502 					/* skipping the leading spaces */;
503 				}
504 				else if ('"' == *p)
505 				{
506 					state = 1;
507 				}
508 				else
509 				{
510 					state = 2;
511 					p--;
512 				}
513 				break;
514 			/* quoted */
515 			case 1:
516 				if ('"' == *p)
517 				{
518 					if (' ' != p[1] && '\t' != p[1] && '\0' != p[1])
519 						return NULL;	/* incorrect syntax */
520 
521 					while (' ' == p[1] || '\t' == p[1])
522 						p++;
523 
524 					buf[buf_i] = '\0';
525 					return ++p;
526 				}
527 				else if ('\\' == *p && ('"' == p[1] || '\\' == p[1]))
528 				{
529 					p++;
530 					if (buf_i < bufsize)
531 						buf[buf_i++] = *p;
532 				}
533 				else if ('\\' == *p && 'n' == p[1])
534 				{
535 					p++;
536 					if (buf_i < bufsize)
537 						buf[buf_i++] = '\n';
538 				}
539 				else if (buf_i < bufsize)
540 				{
541 					buf[buf_i++] = *p;
542 				}
543 				break;
544 			/* unquoted */
545 			case 2:
546 				if (' ' == *p || '\t' == *p)
547 				{
548 					while (' ' == *p || '\t' == *p)
549 						p++;
550 
551 					buf[buf_i] = '\0';
552 					return p;
553 				}
554 				else if (buf_i < bufsize)
555 				{
556 					buf[buf_i++] = *p;
557 				}
558 				break;
559 		}
560 	}
561 
562 	/* missing terminating '"' character */
563 	if (1 == state)
564 		return NULL;
565 
566 	buf[buf_i] = '\0';
567 
568 	return p;
569 }
570 
571 /******************************************************************************
572  *                                                                            *
573  * Function: check_response                                                   *
574  *                                                                            *
575  * Purpose: Check whether JSON response is SUCCEED                            *
576  *                                                                            *
577  * Parameters: JSON response from Zabbix trapper                              *
578  *                                                                            *
579  * Return value:  SUCCEED - processed successfully                            *
580  *                FAIL - an error occurred                                    *
581  *                SUCCEED_PARTIAL - the sending operation was completed       *
582  *                successfully, but processing of at least one value failed   *
583  *                                                                            *
584  * Author: Alexei Vladishev                                                   *
585  *                                                                            *
586  * Comments: active agent has almost the same function!                       *
587  *                                                                            *
588  ******************************************************************************/
check_response(char * response,const char * server,unsigned short port)589 static int	check_response(char *response, const char *server, unsigned short port)
590 {
591 	struct zbx_json_parse	jp;
592 	char			value[MAX_STRING_LEN];
593 	char			info[MAX_STRING_LEN];
594 	int			ret;
595 
596 	ret = zbx_json_open(response, &jp);
597 
598 	if (SUCCEED == ret)
599 		ret = zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_RESPONSE, value, sizeof(value), NULL);
600 
601 	if (SUCCEED == ret && 0 != strcmp(value, ZBX_PROTO_VALUE_SUCCESS))
602 		ret = FAIL;
603 
604 	if (SUCCEED == ret && SUCCEED == zbx_json_value_by_name(&jp, ZBX_PROTO_TAG_INFO, info, sizeof(info), NULL))
605 	{
606 		int	failed;
607 
608 		printf("Response from \"%s:%hu\": \"%s\"\n", server, port, info);
609 		fflush(stdout);
610 
611 		if (1 == sscanf(info, "processed: %*d; failed: %d", &failed) && 0 < failed)
612 			ret = SUCCEED_PARTIAL;
613 	}
614 
615 	return ret;
616 }
617 
ZBX_THREAD_ENTRY(send_value,args)618 static	ZBX_THREAD_ENTRY(send_value, args)
619 {
620 	ZBX_THREAD_SENDVAL_ARGS	*sendval_args = (ZBX_THREAD_SENDVAL_ARGS *)((zbx_thread_args_t *)args)->args;
621 	int			tcp_ret, ret = FAIL;
622 	char			*tls_arg1, *tls_arg2;
623 	zbx_socket_t		sock;
624 
625 #if !defined(_WINDOWS)
626 	signal(SIGINT, sender_signal_handler);
627 	signal(SIGQUIT, sender_signal_handler);
628 	signal(SIGTERM, sender_signal_handler);
629 	signal(SIGHUP, sender_signal_handler);
630 	signal(SIGALRM, sender_signal_handler);
631 	signal(SIGPIPE, sender_signal_handler);
632 #endif
633 
634 #if defined(_WINDOWS) && (defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL))
635 	if (ZBX_TCP_SEC_UNENCRYPTED != configured_tls_connect_mode)
636 	{
637 		/* take TLS data passed from 'main' thread */
638 		zbx_tls_take_vars(&sendval_args->tls_vars);
639 	}
640 #endif
641 	switch (configured_tls_connect_mode)
642 	{
643 		case ZBX_TCP_SEC_UNENCRYPTED:
644 			tls_arg1 = NULL;
645 			tls_arg2 = NULL;
646 			break;
647 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
648 		case ZBX_TCP_SEC_TLS_CERT:
649 			tls_arg1 = CONFIG_TLS_SERVER_CERT_ISSUER;
650 			tls_arg2 = CONFIG_TLS_SERVER_CERT_SUBJECT;
651 			break;
652 		case ZBX_TCP_SEC_TLS_PSK:
653 			tls_arg1 = CONFIG_TLS_PSK_IDENTITY;
654 			tls_arg2 = NULL;	/* zbx_tls_connect() will find PSK */
655 			break;
656 #endif
657 		default:
658 			THIS_SHOULD_NEVER_HAPPEN;
659 			goto out;
660 	}
661 
662 	if (SUCCEED == (tcp_ret = zbx_tcp_connect(&sock, CONFIG_SOURCE_IP, sendval_args->server, sendval_args->port,
663 			GET_SENDER_TIMEOUT, configured_tls_connect_mode, tls_arg1, tls_arg2)))
664 	{
665 		if (1 == sendval_args->sync_timestamp)
666 		{
667 			zbx_timespec_t	ts;
668 
669 			zbx_timespec(&ts);
670 
671 			zbx_json_adduint64(&sendval_args->json, ZBX_PROTO_TAG_CLOCK, ts.sec);
672 			zbx_json_adduint64(&sendval_args->json, ZBX_PROTO_TAG_NS, ts.ns);
673 		}
674 
675 		if (SUCCEED == (tcp_ret = zbx_tcp_send(&sock, sendval_args->json.buffer)))
676 		{
677 			if (SUCCEED == (tcp_ret = zbx_tcp_recv(&sock)))
678 			{
679 				zabbix_log(LOG_LEVEL_DEBUG, "answer [%s]", sock.buffer);
680 
681 				if (FAIL == (ret = check_response(sock.buffer, sendval_args->server,
682 						sendval_args->port)))
683 				{
684 					zabbix_log(LOG_LEVEL_WARNING, "incorrect answer from \"%s:%hu\": [%s]",
685 							sendval_args->server, sendval_args->port, sock.buffer);
686 				}
687 			}
688 		}
689 
690 		zbx_tcp_close(&sock);
691 	}
692 
693 	if (FAIL == tcp_ret)
694 		zabbix_log(LOG_LEVEL_DEBUG, "send value error: %s", zbx_socket_strerror());
695 out:
696 	zbx_thread_exit(ret);
697 }
698 
699 /******************************************************************************
700  *                                                                            *
701  * Function: perform_data_sending                                             *
702  *                                                                            *
703  * Purpose: Send data to all destinations each in a separate thread and wait  *
704  *          till threads have completed their task                            *
705  *                                                                            *
706  * Parameters:                                                                *
707  *      sendval_args - [IN] arguments for thread function                     *
708  *      old_status   - [IN] previous status                                   *
709  *                                                                            *
710  * Return value:  SUCCEED - success with all values at all destinations       *
711  *                FAIL - an error occurred                                    *
712  *                SUCCEED_PARTIAL - data sending was completed successfully   *
713  *                to at least one destination or processing of at least one   *
714  *                value at least at one destination failed                    *
715  *                                                                            *
716  ******************************************************************************/
perform_data_sending(ZBX_THREAD_SENDVAL_ARGS * sendval_args,int old_status)717 static int	perform_data_sending(ZBX_THREAD_SENDVAL_ARGS *sendval_args, int old_status)
718 {
719 	int			i, ret;
720 	ZBX_THREAD_HANDLE	*threads = NULL;
721 
722 	threads = (ZBX_THREAD_HANDLE *)zbx_calloc(threads, destinations_count, sizeof(ZBX_THREAD_HANDLE));
723 
724 	for (i = 0; i < destinations_count; i++)
725 	{
726 		zbx_thread_args_t	*thread_args;
727 
728 		thread_args = (zbx_thread_args_t *)zbx_malloc(NULL, sizeof(zbx_thread_args_t));
729 
730 		thread_args->args = &sendval_args[i];
731 
732 		sendval_args[i].server = destinations[i].host;
733 		sendval_args[i].port = destinations[i].port;
734 
735 		if (0 != i)
736 		{
737 			sendval_args[i].json = sendval_args[0].json;
738 #if defined(_WINDOWS) && (defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL))
739 			sendval_args[i].tls_vars = sendval_args[0].tls_vars;
740 #endif
741 			sendval_args[i].sync_timestamp = sendval_args[0].sync_timestamp;
742 		}
743 
744 		destinations[i].thread = &threads[i];
745 
746 		zbx_thread_start(send_value, thread_args, &threads[i]);
747 #ifndef _WINDOWS
748 		zbx_free(thread_args);
749 #endif
750 	}
751 
752 	ret = sender_threads_wait(threads, destinations_count, old_status);
753 
754 	zbx_free(threads);
755 
756 	return ret;
757 }
758 
759 /******************************************************************************
760  *                                                                            *
761  * Function: sender_add_serveractive_host_cb                                  *
762  *                                                                            *
763  * Purpose: add server or proxy to the list of destinations                   *
764  *                                                                            *
765  * Parameters:                                                                *
766  *      host - [IN] IP or hostname                                            *
767  *      port - [IN] port number                                               *
768  *                                                                            *
769  * Return value:  SUCCEED - destination added successfully                    *
770  *                FAIL - destination has been already added                   *
771  *                                                                            *
772  ******************************************************************************/
sender_add_serveractive_host_cb(const char * host,unsigned short port)773 static int	sender_add_serveractive_host_cb(const char *host, unsigned short port)
774 {
775 	int	i;
776 
777 	for (i = 0; i < destinations_count; i++)
778 	{
779 		if (0 == strcmp(destinations[i].host, host) && destinations[i].port == port)
780 			return FAIL;
781 	}
782 
783 	destinations_count++;
784 #if defined(_WINDOWS)
785 	if (MAXIMUM_WAIT_OBJECTS < destinations_count)
786 	{
787 		zbx_error("error parsing the \"ServerActive\" parameter: maximum destination limit of %d has been"
788 				" exceeded", MAXIMUM_WAIT_OBJECTS);
789 		exit(EXIT_FAILURE);
790 	}
791 #endif
792 	destinations = (zbx_send_destinations_t *)zbx_realloc(destinations,
793 			sizeof(zbx_send_destinations_t) * destinations_count);
794 
795 	destinations[destinations_count - 1].host = zbx_strdup(NULL, host);
796 	destinations[destinations_count - 1].port = port;
797 
798 	return SUCCEED;
799 }
800 
zbx_fill_from_config_file(char ** dst,char * src)801 static void	zbx_fill_from_config_file(char **dst, char *src)
802 {
803 	/* helper function, only for TYPE_STRING configuration parameters */
804 
805 	if (NULL != src)
806 	{
807 		if (NULL == *dst)
808 			*dst = zbx_strdup(*dst, src);
809 
810 		zbx_free(src);
811 	}
812 }
813 
zbx_load_config(const char * config_file)814 static void	zbx_load_config(const char *config_file)
815 {
816 	char	*cfg_source_ip = NULL, *cfg_active_hosts = NULL, *cfg_hostname = NULL, *cfg_tls_connect = NULL,
817 		*cfg_tls_ca_file = NULL, *cfg_tls_crl_file = NULL, *cfg_tls_server_cert_issuer = NULL,
818 		*cfg_tls_server_cert_subject = NULL, *cfg_tls_cert_file = NULL, *cfg_tls_key_file = NULL,
819 		*cfg_tls_psk_file = NULL, *cfg_tls_psk_identity = NULL,
820 		*cfg_tls_cipher_cert13 = NULL, *cfg_tls_cipher_cert = NULL,
821 		*cfg_tls_cipher_psk13 = NULL, *cfg_tls_cipher_psk = NULL;
822 
823 	struct cfg_line	cfg[] =
824 	{
825 		/* PARAMETER,			VAR,					TYPE,
826 			MANDATORY,	MIN,			MAX */
827 		{"SourceIP",			&cfg_source_ip,				TYPE_STRING,
828 			PARM_OPT,	0,			0},
829 		{"ServerActive",		&cfg_active_hosts,			TYPE_STRING_LIST,
830 			PARM_OPT,	0,			0},
831 		{"Hostname",			&cfg_hostname,				TYPE_STRING,
832 			PARM_OPT,	0,			0},
833 		{"TLSConnect",			&cfg_tls_connect,			TYPE_STRING,
834 			PARM_OPT,	0,			0},
835 		{"TLSCAFile",			&cfg_tls_ca_file,			TYPE_STRING,
836 			PARM_OPT,	0,			0},
837 		{"TLSCRLFile",			&cfg_tls_crl_file,			TYPE_STRING,
838 			PARM_OPT,	0,			0},
839 		{"TLSServerCertIssuer",		&cfg_tls_server_cert_issuer,		TYPE_STRING,
840 			PARM_OPT,	0,			0},
841 		{"TLSServerCertSubject",	&cfg_tls_server_cert_subject,		TYPE_STRING,
842 			PARM_OPT,	0,			0},
843 		{"TLSCertFile",			&cfg_tls_cert_file,			TYPE_STRING,
844 			PARM_OPT,	0,			0},
845 		{"TLSKeyFile",			&cfg_tls_key_file,			TYPE_STRING,
846 			PARM_OPT,	0,			0},
847 		{"TLSPSKIdentity",		&cfg_tls_psk_identity,			TYPE_STRING,
848 			PARM_OPT,	0,			0},
849 		{"TLSPSKFile",			&cfg_tls_psk_file,			TYPE_STRING,
850 			PARM_OPT,	0,			0},
851 		{"TLSCipherCert13",		&cfg_tls_cipher_cert13,			TYPE_STRING,
852 			PARM_OPT,	0,			0},
853 		{"TLSCipherCert",		&cfg_tls_cipher_cert,			TYPE_STRING,
854 			PARM_OPT,	0,			0},
855 		{"TLSCipherPSK13",		&cfg_tls_cipher_psk13,			TYPE_STRING,
856 			PARM_OPT,	0,			0},
857 		{"TLSCipherPSK",		&cfg_tls_cipher_psk,			TYPE_STRING,
858 			PARM_OPT,	0,			0},
859 		{"ListenBacklog",		&CONFIG_TCP_MAX_BACKLOG_SIZE,		TYPE_INT,
860 			PARM_OPT,	0,			INT_MAX},
861 		{NULL}
862 	};
863 
864 	/* do not complain about unknown parameters in agent configuration file */
865 	parse_cfg_file(config_file, cfg, ZBX_CFG_FILE_REQUIRED, ZBX_CFG_NOT_STRICT);
866 
867 	zbx_fill_from_config_file(&CONFIG_SOURCE_IP, cfg_source_ip);
868 
869 	if (NULL == ZABBIX_SERVER)
870 	{
871 		if (NULL != cfg_active_hosts && '\0' != *cfg_active_hosts)
872 			zbx_set_data_destination_hosts(cfg_active_hosts, sender_add_serveractive_host_cb);
873 	}
874 	zbx_free(cfg_active_hosts);
875 
876 	zbx_fill_from_config_file(&ZABBIX_HOSTNAME, cfg_hostname);
877 
878 	zbx_fill_from_config_file(&CONFIG_TLS_CONNECT, cfg_tls_connect);
879 	zbx_fill_from_config_file(&CONFIG_TLS_CA_FILE, cfg_tls_ca_file);
880 	zbx_fill_from_config_file(&CONFIG_TLS_CRL_FILE, cfg_tls_crl_file);
881 	zbx_fill_from_config_file(&CONFIG_TLS_SERVER_CERT_ISSUER, cfg_tls_server_cert_issuer);
882 	zbx_fill_from_config_file(&CONFIG_TLS_SERVER_CERT_SUBJECT, cfg_tls_server_cert_subject);
883 	zbx_fill_from_config_file(&CONFIG_TLS_CERT_FILE, cfg_tls_cert_file);
884 	zbx_fill_from_config_file(&CONFIG_TLS_KEY_FILE, cfg_tls_key_file);
885 	zbx_fill_from_config_file(&CONFIG_TLS_PSK_IDENTITY, cfg_tls_psk_identity);
886 	zbx_fill_from_config_file(&CONFIG_TLS_PSK_FILE, cfg_tls_psk_file);
887 
888 	zbx_fill_from_config_file(&CONFIG_TLS_CIPHER_CERT13, cfg_tls_cipher_cert13);
889 	zbx_fill_from_config_file(&CONFIG_TLS_CIPHER_CERT, cfg_tls_cipher_cert);
890 	zbx_fill_from_config_file(&CONFIG_TLS_CIPHER_PSK13, cfg_tls_cipher_psk13);
891 	zbx_fill_from_config_file(&CONFIG_TLS_CIPHER_PSK, cfg_tls_cipher_psk);
892 }
893 
parse_commandline(int argc,char ** argv)894 static void	parse_commandline(int argc, char **argv)
895 {
896 /* Minimum and maximum port numbers Zabbix sender can connect to. */
897 /* Do not forget to modify port number validation below if MAX_ZABBIX_PORT is ever changed. */
898 #define MIN_ZABBIX_PORT 1u
899 #define MAX_ZABBIX_PORT 65535u
900 
901 	int		i, fatal = 0;
902 	char		ch;
903 	unsigned int	opt_mask = 0;
904 	unsigned short	opt_count[256] = {0};
905 
906 	/* parse the command-line */
907 	while ((char)EOF != (ch = (char)zbx_getopt_long(argc, argv, shortopts, longopts, NULL)))
908 	{
909 		opt_count[(unsigned char)ch]++;
910 
911 		switch (ch)
912 		{
913 			case 'c':
914 				if (NULL == CONFIG_FILE)
915 					CONFIG_FILE = zbx_strdup(CONFIG_FILE, zbx_optarg);
916 				break;
917 			case 'h':
918 				help();
919 				exit(EXIT_SUCCESS);
920 				break;
921 			case 'V':
922 				version();
923 				exit(EXIT_SUCCESS);
924 				break;
925 			case 'I':
926 				if (NULL == CONFIG_SOURCE_IP)
927 					CONFIG_SOURCE_IP = zbx_strdup(CONFIG_SOURCE_IP, zbx_optarg);
928 				break;
929 			case 'z':
930 				if (NULL == ZABBIX_SERVER)
931 					ZABBIX_SERVER = zbx_strdup(ZABBIX_SERVER, zbx_optarg);
932 				break;
933 			case 'p':
934 				if (NULL == ZABBIX_SERVER_PORT)
935 					ZABBIX_SERVER_PORT = zbx_strdup(ZABBIX_SERVER_PORT, zbx_optarg);
936 				break;
937 			case 's':
938 				if (NULL == ZABBIX_HOSTNAME)
939 					ZABBIX_HOSTNAME = zbx_strdup(ZABBIX_HOSTNAME, zbx_optarg);
940 				break;
941 			case 'k':
942 				if (NULL == ZABBIX_KEY)
943 					ZABBIX_KEY = zbx_strdup(ZABBIX_KEY, zbx_optarg);
944 				break;
945 			case 'o':
946 				if (NULL == ZABBIX_KEY_VALUE)
947 					ZABBIX_KEY_VALUE = zbx_strdup(ZABBIX_KEY_VALUE, zbx_optarg);
948 				break;
949 			case 'i':
950 				if (NULL == INPUT_FILE)
951 					INPUT_FILE = zbx_strdup(INPUT_FILE, zbx_optarg);
952 				break;
953 			case 'T':
954 				WITH_TIMESTAMPS = 1;
955 				break;
956 			case 'N':
957 				WITH_NS = 1;
958 				break;
959 			case 'r':
960 				REAL_TIME = 1;
961 				break;
962 			case 'v':
963 				if (LOG_LEVEL_WARNING > CONFIG_LOG_LEVEL)
964 					CONFIG_LOG_LEVEL = LOG_LEVEL_WARNING;
965 				else if (LOG_LEVEL_DEBUG > CONFIG_LOG_LEVEL)
966 					CONFIG_LOG_LEVEL = LOG_LEVEL_DEBUG;
967 				break;
968 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
969 			case '1':
970 				CONFIG_TLS_CONNECT = zbx_strdup(CONFIG_TLS_CONNECT, zbx_optarg);
971 				break;
972 			case '2':
973 				CONFIG_TLS_CA_FILE = zbx_strdup(CONFIG_TLS_CA_FILE, zbx_optarg);
974 				break;
975 			case '3':
976 				CONFIG_TLS_CRL_FILE = zbx_strdup(CONFIG_TLS_CRL_FILE, zbx_optarg);
977 				break;
978 			case '4':
979 				CONFIG_TLS_SERVER_CERT_ISSUER = zbx_strdup(CONFIG_TLS_SERVER_CERT_ISSUER, zbx_optarg);
980 				break;
981 			case '5':
982 				CONFIG_TLS_SERVER_CERT_SUBJECT = zbx_strdup(CONFIG_TLS_SERVER_CERT_SUBJECT, zbx_optarg);
983 				break;
984 			case '6':
985 				CONFIG_TLS_CERT_FILE = zbx_strdup(CONFIG_TLS_CERT_FILE, zbx_optarg);
986 				break;
987 			case '7':
988 				CONFIG_TLS_KEY_FILE = zbx_strdup(CONFIG_TLS_KEY_FILE, zbx_optarg);
989 				break;
990 			case '8':
991 				CONFIG_TLS_PSK_IDENTITY = zbx_strdup(CONFIG_TLS_PSK_IDENTITY, zbx_optarg);
992 				break;
993 			case '9':
994 				CONFIG_TLS_PSK_FILE = zbx_strdup(CONFIG_TLS_PSK_FILE, zbx_optarg);
995 				break;
996 			case 'A':
997 #if defined(HAVE_OPENSSL)
998 				CONFIG_TLS_CIPHER_CMD13 = zbx_strdup(CONFIG_TLS_CIPHER_CMD13, zbx_optarg);
999 #elif defined(HAVE_GNUTLS)
1000 				zbx_error("parameter \"--tls-cipher13\" can be used with OpenSSL 1.1.1 or newer."
1001 						" Zabbix sender was compiled with GnuTLS");
1002 				exit(EXIT_FAILURE);
1003 #endif
1004 				break;
1005 			case 'B':
1006 				CONFIG_TLS_CIPHER_CMD = zbx_strdup(CONFIG_TLS_CIPHER_CMD, zbx_optarg);
1007 				break;
1008 #else
1009 			case '1':
1010 			case '2':
1011 			case '3':
1012 			case '4':
1013 			case '5':
1014 			case '6':
1015 			case '7':
1016 			case '8':
1017 			case '9':
1018 			case 'A':
1019 			case 'B':
1020 				zbx_error("TLS parameters cannot be used: Zabbix sender was compiled without TLS"
1021 						" support");
1022 				exit(EXIT_FAILURE);
1023 				break;
1024 #endif
1025 			default:
1026 				usage();
1027 				exit(EXIT_FAILURE);
1028 				break;
1029 		}
1030 	}
1031 
1032 	if (NULL != ZABBIX_SERVER)
1033 	{
1034 		unsigned short	port;
1035 
1036 		if (NULL != ZABBIX_SERVER_PORT)
1037 		{
1038 			if (SUCCEED != is_ushort(ZABBIX_SERVER_PORT, &port) || MIN_ZABBIX_PORT > port)
1039 			{
1040 				zbx_error("option \"-p\" used with invalid port number \"%s\", valid port numbers are"
1041 						" %d-%d", ZABBIX_SERVER_PORT, (int)MIN_ZABBIX_PORT,
1042 						(int)MAX_ZABBIX_PORT);
1043 				exit(EXIT_FAILURE);
1044 			}
1045 		}
1046 		else
1047 			port = (unsigned short)ZBX_DEFAULT_SERVER_PORT;
1048 
1049 		sender_add_serveractive_host_cb(ZABBIX_SERVER, port);
1050 	}
1051 
1052 	/* every option may be specified only once */
1053 
1054 	for (i = 0; NULL != longopts[i].name; i++)
1055 	{
1056 		ch = longopts[i].val;
1057 
1058 		if ('v' == ch && 2 < opt_count[(unsigned char)ch])	/* '-v' or '-vv' can be specified */
1059 		{
1060 			zbx_error("option \"-v\" or \"--verbose\" specified more than 2 times");
1061 
1062 			fatal = 1;
1063 			continue;
1064 		}
1065 
1066 		if ('v' != ch && 1 < opt_count[(unsigned char)ch])
1067 		{
1068 			if (NULL == strchr(shortopts, ch))
1069 				zbx_error("option \"--%s\" specified multiple times", longopts[i].name);
1070 			else
1071 				zbx_error("option \"-%c\" or \"--%s\" specified multiple times", ch, longopts[i].name);
1072 
1073 			fatal = 1;
1074 		}
1075 	}
1076 
1077 	if (1 == fatal)
1078 		exit(EXIT_FAILURE);
1079 
1080 	/* check for mutually exclusive options    */
1081 
1082 	/* Allowed option combinations.                                */
1083 	/* Option 'v' is always optional.                              */
1084 	/*   c  z  s  k  o  i  N  T  r  p  I opt_mask comment          */
1085 	/* --------------------------------- -------- -------          */
1086 	/*   -  z  -  -  -  i  -  -  -  -  -  0x220   !c i             */
1087 	/*   -  z  -  -  -  i  -  -  -  -  I  0x221                    */
1088 	/*   -  z  -  -  -  i  -  -  -  p  -  0x222                    */
1089 	/*   -  z  -  -  -  i  -  -  -  p  I  0x223                    */
1090 	/*   -  z  -  -  -  i  -  -  r  -  -  0x224                    */
1091 	/*   -  z  -  -  -  i  -  -  r  -  I  0x225                    */
1092 	/*   -  z  -  -  -  i  -  -  r  p  -  0x226                    */
1093 	/*   -  z  -  -  -  i  -  -  r  p  I  0x227                    */
1094 	/*   -  z  -  -  -  i  -  T  -  -  -  0x228                    */
1095 	/*   -  z  -  -  -  i  -  T  -  -  I  0x229                    */
1096 	/*   -  z  -  -  -  i  -  T  -  p  -  0x22a                    */
1097 	/*   -  z  -  -  -  i  -  T  -  p  I  0x22b                    */
1098 	/*   -  z  -  -  -  i  -  T  r  -  -  0x22c                    */
1099 	/*   -  z  -  -  -  i  -  T  r  -  I  0x22d                    */
1100 	/*   -  z  -  -  -  i  -  T  r  p  -  0x22e                    */
1101 	/*   -  z  -  -  -  i  -  T  r  p  I  0x22f                    */
1102 	/*   -  z  -  -  -  i  N  T  -  -  -  0x238                    */
1103 	/*   -  z  -  -  -  i  N  T  -  -  I  0x239                    */
1104 	/*   -  z  -  -  -  i  N  T  -  p  -  0x23a                    */
1105 	/*   -  z  -  -  -  i  N  T  -  p  I  0x23b                    */
1106 	/*   -  z  -  -  -  i  N  T  r  -  -  0x23c                    */
1107 	/*   -  z  -  -  -  i  N  T  r  -  I  0x23d                    */
1108 	/*   -  z  -  -  -  i  N  T  r  p  -  0x23e                    */
1109 	/*   -  z  -  -  -  i  N  T  r  p  I  0x23f                    */
1110 	/*   -  z  s  -  -  i  -  -  -  -  -  0x320                    */
1111 	/*   -  z  s  -  -  i  -  -  -  -  I  0x321                    */
1112 	/*   -  z  s  -  -  i  -  -  -  p  -  0x322                    */
1113 	/*   -  z  s  -  -  i  -  -  -  p  I  0x323                    */
1114 	/*   -  z  s  -  -  i  -  -  r  -  -  0x324                    */
1115 	/*   -  z  s  -  -  i  -  -  r  -  I  0x325                    */
1116 	/*   -  z  s  -  -  i  -  -  r  p  -  0x326                    */
1117 	/*   -  z  s  -  -  i  -  -  r  p  I  0x327                    */
1118 	/*   -  z  s  -  -  i  -  T  -  -  -  0x328                    */
1119 	/*   -  z  s  -  -  i  -  T  -  -  I  0x329                    */
1120 	/*   -  z  s  -  -  i  -  T  -  p  -  0x32a                    */
1121 	/*   -  z  s  -  -  i  -  T  -  p  I  0x32b                    */
1122 	/*   -  z  s  -  -  i  -  T  r  -  -  0x32c                    */
1123 	/*   -  z  s  -  -  i  -  T  r  -  I  0x32d                    */
1124 	/*   -  z  s  -  -  i  -  T  r  p  -  0x32e                    */
1125 	/*   -  z  s  -  -  i  -  T  r  p  I  0x32f                    */
1126 	/*   -  z  s  -  -  i  N  T  -  -  -  0x338                    */
1127 	/*   -  z  s  -  -  i  N  T  -  -  I  0x339                    */
1128 	/*   -  z  s  -  -  i  N  T  -  p  -  0x33a                    */
1129 	/*   -  z  s  -  -  i  N  T  -  p  I  0x33b                    */
1130 	/*   -  z  s  -  -  i  N  T  r  -  -  0x33c                    */
1131 	/*   -  z  s  -  -  i  N  T  r  -  I  0x33d                    */
1132 	/*   -  z  s  -  -  i  N  T  r  p  -  0x33e                    */
1133 	/*   -  z  s  -  -  i  N  T  r  p  I  0x33f                    */
1134 	/*                                                             */
1135 	/*   -  z  s  k  o  -  -  -  -  -  -  0x3c0   !c !i            */
1136 	/*   -  z  s  k  o  -  -  -  -  -  I  0x3c1                    */
1137 	/*   -  z  s  k  o  -  -  -  -  p  -  0x3c2                    */
1138 	/*   -  z  s  k  o  -  -  -  -  p  I  0x3c3                    */
1139 	/*                                                             */
1140 	/*   c  -  -  -  -  i  -  -  -  -  -  0x420   c i              */
1141 	/*   c  -  -  -  -  i  -  -  -  -  I  0x421                    */
1142 	/*   c  -  -  -  -  i  -  -  -  p  -  0x422                    */
1143 	/*   c  -  -  -  -  i  -  -  -  p  I  0x423                    */
1144 	/*   c  -  -  -  -  i  -  -  r  -  -  0x424                    */
1145 	/*   c  -  -  -  -  i  -  -  r  -  I  0x425                    */
1146 	/*   c  -  -  -  -  i  -  -  r  p  -  0x426                    */
1147 	/*   c  -  -  -  -  i  -  -  r  p  I  0x427                    */
1148 	/*   c  -  -  -  -  i  -  T  -  -  -  0x428                    */
1149 	/*   c  -  -  -  -  i  -  T  -  -  I  0x429                    */
1150 	/*   c  -  -  -  -  i  -  T  -  p  -  0x42a                    */
1151 	/*   c  -  -  -  -  i  -  T  -  p  I  0x42b                    */
1152 	/*   c  -  -  -  -  i  -  T  r  -  -  0x42c                    */
1153 	/*   c  -  -  -  -  i  -  T  r  -  I  0x42d                    */
1154 	/*   c  -  -  -  -  i  -  T  r  p  -  0x42e                    */
1155 	/*   c  -  -  -  -  i  -  T  r  p  I  0x42f                    */
1156 	/*   c  -  -  -  -  i  N  T  -  -  -  0x438                    */
1157 	/*   c  -  -  -  -  i  N  T  -  -  I  0x439                    */
1158 	/*   c  -  -  -  -  i  N  T  -  p  -  0x43a                    */
1159 	/*   c  -  -  -  -  i  N  T  -  p  I  0x43b                    */
1160 	/*   c  -  -  -  -  i  N  T  r  -  -  0x43c                    */
1161 	/*   c  -  -  -  -  i  N  T  r  -  I  0x43d                    */
1162 	/*   c  -  -  -  -  i  N  T  r  p  -  0x43e                    */
1163 	/*   c  -  -  -  -  i  N  T  r  p  I  0x43f                    */
1164 	/*                                                             */
1165 	/*   c  -  -  k  o  -  -  -  -  -  -  0x4c0   c !i             */
1166 	/*   c  -  -  k  o  -  -  -  -  -  I  0x4c1                    */
1167 	/*   c  -  -  k  o  -  -  -  -  p  -  0x4c2                    */
1168 	/*   c  -  -  k  o  -  -  -  -  p  I  0x4c3                    */
1169 	/*   c  -  s  k  o  -  -  -  -  -  -  0x5c0                    */
1170 	/*   c  -  s  k  o  -  -  -  -  -  I  0x5c1                    */
1171 	/*   c  -  s  k  o  -  -  -  -  p  -  0x5c2                    */
1172 	/*   c  -  s  k  o  -  -  -  -  p  I  0x5c3                    */
1173 	/*                                                             */
1174 	/*   c  -  s  -  -  i  -  -  -  -  -  0x520   c i (continues)  */
1175 	/*   c  -  s  -  -  i  -  -  -  -  I  0x521                    */
1176 	/*   c  -  s  -  -  i  -  -  -  p  -  0x522                    */
1177 	/*   c  -  s  -  -  i  -  -  -  p  I  0x523                    */
1178 	/*   c  -  s  -  -  i  -  -  r  -  -  0x524                    */
1179 	/*   c  -  s  -  -  i  -  -  r  -  I  0x525                    */
1180 	/*   c  -  s  -  -  i  -  -  r  p  -  0x526                    */
1181 	/*   c  -  s  -  -  i  -  -  r  p  I  0x527                    */
1182 	/*   c  -  s  -  -  i  -  T  -  -  -  0x528                    */
1183 	/*   c  -  s  -  -  i  -  T  -  -  I  0x529                    */
1184 	/*   c  -  s  -  -  i  -  T  -  p  -  0x52a                    */
1185 	/*   c  -  s  -  -  i  -  T  -  p  I  0x52b                    */
1186 	/*   c  -  s  -  -  i  -  T  r  -  -  0x52c                    */
1187 	/*   c  -  s  -  -  i  -  T  r  -  I  0x52d                    */
1188 	/*   c  -  s  -  -  i  -  T  r  p  -  0x52e                    */
1189 	/*   c  -  s  -  -  i  -  T  r  p  I  0x52f                    */
1190 	/*   c  -  s  -  -  i  N  T  -  -  -  0x538                    */
1191 	/*   c  -  s  -  -  i  N  T  -  -  I  0x539                    */
1192 	/*   c  -  s  -  -  i  N  T  -  p  -  0x53a                    */
1193 	/*   c  -  s  -  -  i  N  T  -  p  I  0x53b                    */
1194 	/*   c  -  s  -  -  i  N  T  r  -  -  0x53c                    */
1195 	/*   c  -  s  -  -  i  N  T  r  -  I  0x53d                    */
1196 	/*   c  -  s  -  -  i  N  T  r  p  -  0x53e                    */
1197 	/*   c  -  s  -  -  i  N  T  r  p  I  0x53f                    */
1198 	/*   c  z  -  -  -  i  -  -  -  -  -  0x620                    */
1199 	/*   c  z  -  -  -  i  -  -  -  -  I  0x621                    */
1200 	/*   c  z  -  -  -  i  -  -  -  p  -  0x622                    */
1201 	/*   c  z  -  -  -  i  -  -  -  p  I  0x623                    */
1202 	/*   c  z  -  -  -  i  -  -  r  -  -  0x624                    */
1203 	/*   c  z  -  -  -  i  -  -  r  -  I  0x625                    */
1204 	/*   c  z  -  -  -  i  -  -  r  p  -  0x626                    */
1205 	/*   c  z  -  -  -  i  -  -  r  p  I  0x627                    */
1206 	/*   c  z  -  -  -  i  -  T  -  -  -  0x628                    */
1207 	/*   c  z  -  -  -  i  -  T  -  -  I  0x629                    */
1208 	/*   c  z  -  -  -  i  -  T  -  p  -  0x62a                    */
1209 	/*   c  z  -  -  -  i  -  T  -  p  I  0x62b                    */
1210 	/*   c  z  -  -  -  i  -  T  r  -  -  0x62c                    */
1211 	/*   c  z  -  -  -  i  -  T  r  -  I  0x62d                    */
1212 	/*   c  z  -  -  -  i  -  T  r  p  -  0x62e                    */
1213 	/*   c  z  -  -  -  i  -  T  r  p  I  0x62f                    */
1214 	/*   c  z  -  -  -  i  N  T  -  -  -  0x638                    */
1215 	/*   c  z  -  -  -  i  N  T  -  -  I  0x639                    */
1216 	/*   c  z  -  -  -  i  N  T  -  p  -  0x63a                    */
1217 	/*   c  z  -  -  -  i  N  T  -  p  I  0x63b                    */
1218 	/*   c  z  -  -  -  i  N  T  r  -  -  0x63c                    */
1219 	/*   c  z  -  -  -  i  N  T  r  -  I  0x63d                    */
1220 	/*   c  z  -  -  -  i  N  T  r  p  -  0x63e                    */
1221 	/*   c  z  -  -  -  i  N  T  r  p  I  0x63f                    */
1222 	/*   c  z  s  -  -  i  -  -  -  -  -  0x720                    */
1223 	/*   c  z  s  -  -  i  -  -  -  -  I  0x721                    */
1224 	/*   c  z  s  -  -  i  -  -  -  p  -  0x722                    */
1225 	/*   c  z  s  -  -  i  -  -  -  p  I  0x723                    */
1226 	/*   c  z  s  -  -  i  -  -  r  -  -  0x724                    */
1227 	/*   c  z  s  -  -  i  -  -  r  -  I  0x725                    */
1228 	/*   c  z  s  -  -  i  -  -  r  p  -  0x726                    */
1229 	/*   c  z  s  -  -  i  -  -  r  p  I  0x727                    */
1230 	/*   c  z  s  -  -  i  -  T  -  -  -  0x728                    */
1231 	/*   c  z  s  -  -  i  -  T  -  -  I  0x729                    */
1232 	/*   c  z  s  -  -  i  -  T  -  p  -  0x72a                    */
1233 	/*   c  z  s  -  -  i  -  T  -  p  I  0x72b                    */
1234 	/*   c  z  s  -  -  i  -  T  r  -  -  0x72c                    */
1235 	/*   c  z  s  -  -  i  -  T  r  -  I  0x72d                    */
1236 	/*   c  z  s  -  -  i  -  T  r  p  -  0x72e                    */
1237 	/*   c  z  s  -  -  i  -  T  r  p  I  0x72f                    */
1238 	/*   c  z  s  -  -  i  N  T  -  -  -  0x738                    */
1239 	/*   c  z  s  -  -  i  N  T  -  -  I  0x739                    */
1240 	/*   c  z  s  -  -  i  N  T  -  p  -  0x73a                    */
1241 	/*   c  z  s  -  -  i  N  T  -  p  I  0x73b                    */
1242 	/*   c  z  s  -  -  i  N  T  r  -  -  0x73c                    */
1243 	/*   c  z  s  -  -  i  N  T  r  -  I  0x73d                    */
1244 	/*   c  z  s  -  -  i  N  T  r  p  -  0x73e                    */
1245 	/*   c  z  s  -  -  i  N  T  r  p  I  0x73f                    */
1246 	/*                                                             */
1247 	/*   c  z  -  k  o  -  -  -  -  -  -  0x6c0   c !i (continues) */
1248 	/*   c  z  -  k  o  -  -  -  -  -  I  0x6c1                    */
1249 	/*   c  z  -  k  o  -  -  -  -  p  -  0x6c2                    */
1250 	/*   c  z  -  k  o  -  -  -  -  p  I  0x6c3                    */
1251 	/*   c  z  s  k  o  -  -  -  -  -  -  0x7c0                    */
1252 	/*   c  z  s  k  o  -  -  -  -  -  I  0x7c1                    */
1253 	/*   c  z  s  k  o  -  -  -  -  p  -  0x7c2                    */
1254 	/*   c  z  s  k  o  -  -  -  -  p  I  0x7c3                    */
1255 
1256 	if (0 == opt_count['c'] + opt_count['z'])
1257 	{
1258 		zbx_error("either '-c' or '-z' option must be specified");
1259 		usage();
1260 		printf("Try '%s --help' for more information.\n", progname);
1261 		exit(EXIT_FAILURE);
1262 	}
1263 
1264 	if (0 < opt_count['c'])
1265 		opt_mask |= 0x400;
1266 	if (0 < opt_count['z'])
1267 		opt_mask |= 0x200;
1268 	if (0 < opt_count['s'])
1269 		opt_mask |= 0x100;
1270 	if (0 < opt_count['k'])
1271 		opt_mask |= 0x80;
1272 	if (0 < opt_count['o'])
1273 		opt_mask |= 0x40;
1274 	if (0 < opt_count['i'])
1275 		opt_mask |= 0x20;
1276 	if (0 < opt_count['N'])
1277 		opt_mask |= 0x10;
1278 	if (0 < opt_count['T'])
1279 		opt_mask |= 0x08;
1280 	if (0 < opt_count['r'])
1281 		opt_mask |= 0x04;
1282 	if (0 < opt_count['p'])
1283 		opt_mask |= 0x02;
1284 	if (0 < opt_count['I'])
1285 		opt_mask |= 0x01;
1286 
1287 	if (
1288 			(0 == opt_count['c'] && 1 == opt_count['i'] &&	/* !c i */
1289 					!((0x220 <= opt_mask && opt_mask <= 0x22f) ||
1290 					(0x238 <= opt_mask && opt_mask <= 0x23f) ||
1291 					(0x320 <= opt_mask && opt_mask <= 0x32f) ||
1292 					(0x338 <= opt_mask && opt_mask <= 0x33f))) ||
1293 			(0 == opt_count['c'] && 0 == opt_count['i'] &&	/* !c !i */
1294 					!(0x3c0 <= opt_mask && opt_mask <= 0x3c3)) ||
1295 			(1 == opt_count['c'] && 1 == opt_count['i'] &&	/* c i */
1296 					!((0x420 <= opt_mask && opt_mask <= 0x42f) ||
1297 					(0x438 <= opt_mask && opt_mask <= 0x43f) ||
1298 					(0x620 <= opt_mask && opt_mask <= 0x62f) ||
1299 					(0x638 <= opt_mask && opt_mask <= 0x63f) ||
1300 					(0x520 <= opt_mask && opt_mask <= 0x52f) ||
1301 					(0x538 <= opt_mask && opt_mask <= 0x53f) ||
1302 					(0x720 <= opt_mask && opt_mask <= 0x72f) ||
1303 					(0x738 <= opt_mask && opt_mask <= 0x73f))) ||
1304 			(1 == opt_count['c'] && 0 == opt_count['i'] &&	/* c !i */
1305 					!((0x4c0 <= opt_mask && opt_mask <= 0x4c3) ||
1306 					(0x5c0 <= opt_mask && opt_mask <= 0x5c3) ||
1307 					(0x6c0 <= opt_mask && opt_mask <= 0x6c3) ||
1308 					(0x7c0 <= opt_mask && opt_mask <= 0x7c3))))
1309 	{
1310 		zbx_error("too few or mutually exclusive options used");
1311 		usage();
1312 		exit(EXIT_FAILURE);
1313 	}
1314 
1315 	/* Parameters which are not option values are invalid. The check relies on zbx_getopt_internal() which */
1316 	/* always permutes command line arguments regardless of POSIXLY_CORRECT environment variable. */
1317 	if (argc > zbx_optind)
1318 	{
1319 		for (i = zbx_optind; i < argc; i++)
1320 			zbx_error("invalid parameter \"%s\"", argv[i]);
1321 
1322 		exit(EXIT_FAILURE);
1323 	}
1324 }
1325 
1326 /******************************************************************************
1327  *                                                                            *
1328  * Function: zbx_fgets_alloc                                                  *
1329  *                                                                            *
1330  * Purpose: reads a line from file                                            *
1331  *                                                                            *
1332  * Parameters: buffer       - [IN/OUT] the output buffer                      *
1333  *             buffer_alloc - [IN/OUT] the buffer size                        *
1334  *             fp           - [IN] the file to read                           *
1335  *                                                                            *
1336  * Return value: Pointer to the line or NULL.                                 *
1337  *                                                                            *
1338  * Comments: This is a fgets() function wrapper with dynamically reallocated  *
1339  *           buffer.                                                          *
1340  *                                                                            *
1341  ******************************************************************************/
zbx_fgets_alloc(char ** buffer,size_t * buffer_alloc,FILE * fp)1342 static char	*zbx_fgets_alloc(char **buffer, size_t *buffer_alloc, FILE *fp)
1343 {
1344 	char	tmp[MAX_BUFFER_LEN];
1345 	size_t	buffer_offset = 0, len;
1346 
1347 	do
1348 	{
1349 		if (NULL == fgets(tmp, sizeof(tmp), fp))
1350 			return (0 != buffer_offset ? *buffer : NULL);
1351 
1352 		len = strlen(tmp);
1353 
1354 		if (*buffer_alloc - buffer_offset < len + 1)
1355 		{
1356 			*buffer_alloc = (buffer_offset + len + 1) * 3 / 2;
1357 			*buffer = (char *)zbx_realloc(*buffer, *buffer_alloc);
1358 		}
1359 
1360 		memcpy(*buffer + buffer_offset, tmp, len);
1361 		buffer_offset += len;
1362 		(*buffer)[buffer_offset] = '\0';
1363 	}
1364 	while (MAX_BUFFER_LEN - 1 == len && '\n' != tmp[len - 1]);
1365 
1366 	return *buffer;
1367 }
1368 
1369 /* sending a huge amount of values in a single connection is likely to */
1370 /* take long and hit timeout, so we limit values to 250 per connection */
1371 #define VALUES_MAX	250
1372 
main(int argc,char ** argv)1373 int	main(int argc, char **argv)
1374 {
1375 	char			*error = NULL;
1376 	int			total_count = 0, succeed_count = 0, ret = FAIL, timestamp, ns;
1377 	ZBX_THREAD_SENDVAL_ARGS	*sendval_args = NULL;
1378 
1379 	progname = get_program_name(argv[0]);
1380 
1381 	parse_commandline(argc, argv);
1382 
1383 	if (NULL != CONFIG_FILE)
1384 		zbx_load_config(CONFIG_FILE);
1385 
1386 #ifndef _WINDOWS
1387 	if (SUCCEED != zbx_locks_create(&error))
1388 	{
1389 		zbx_error("cannot create locks: %s", error);
1390 		zbx_free(error);
1391 		exit(EXIT_FAILURE);
1392 	}
1393 #endif
1394 	if (SUCCEED != zabbix_open_log(LOG_TYPE_UNDEFINED, CONFIG_LOG_LEVEL, NULL, &error))
1395 	{
1396 		zbx_error("cannot open log: %s", error);
1397 		zbx_free(error);
1398 		exit(EXIT_FAILURE);
1399 	}
1400 #if defined(_WINDOWS)
1401 	if (SUCCEED != zbx_socket_start(&error))
1402 	{
1403 		zbx_error(error);
1404 		zbx_free(error);
1405 		exit(EXIT_FAILURE);
1406 	}
1407 #endif
1408 #if !defined(_WINDOWS) && (defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL))
1409 	if (SUCCEED != zbx_coredump_disable())
1410 	{
1411 		zabbix_log(LOG_LEVEL_CRIT, "cannot disable core dump, exiting...");
1412 		goto exit;
1413 	}
1414 #endif
1415 	if (0 == destinations_count)
1416 	{
1417 		zabbix_log(LOG_LEVEL_CRIT, "'ServerActive' parameter required");
1418 		goto exit;
1419 	}
1420 #if !defined(_WINDOWS)
1421 	signal(SIGINT, main_signal_handler);
1422 	signal(SIGQUIT, main_signal_handler);
1423 	signal(SIGTERM, main_signal_handler);
1424 	signal(SIGHUP, main_signal_handler);
1425 	signal(SIGALRM, main_signal_handler);
1426 	signal(SIGPIPE, main_signal_handler);
1427 #endif
1428 	if (NULL != CONFIG_TLS_CONNECT || NULL != CONFIG_TLS_CA_FILE || NULL != CONFIG_TLS_CRL_FILE ||
1429 			NULL != CONFIG_TLS_SERVER_CERT_ISSUER || NULL != CONFIG_TLS_SERVER_CERT_SUBJECT ||
1430 			NULL != CONFIG_TLS_CERT_FILE || NULL != CONFIG_TLS_KEY_FILE ||
1431 			NULL != CONFIG_TLS_PSK_IDENTITY || NULL != CONFIG_TLS_PSK_FILE ||
1432 			NULL != CONFIG_TLS_CIPHER_CERT13 || NULL != CONFIG_TLS_CIPHER_CERT ||
1433 			NULL != CONFIG_TLS_CIPHER_PSK13 || NULL != CONFIG_TLS_CIPHER_PSK ||
1434 			NULL != CONFIG_TLS_CIPHER_CMD13 || NULL != CONFIG_TLS_CIPHER_CMD)
1435 	{
1436 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1437 		zbx_tls_validate_config();
1438 
1439 		if (ZBX_TCP_SEC_UNENCRYPTED != configured_tls_connect_mode)
1440 		{
1441 #if defined(_WINDOWS)
1442 			zbx_tls_init_parent();
1443 #endif
1444 			zbx_tls_init_child();
1445 		}
1446 #else
1447 		zabbix_log(LOG_LEVEL_CRIT, "TLS parameters cannot be used: Zabbix sender was compiled without TLS"
1448 				" support");
1449 		goto exit;
1450 #endif
1451 	}
1452 
1453 	sendval_args = (ZBX_THREAD_SENDVAL_ARGS *)zbx_calloc(sendval_args, destinations_count,
1454 			sizeof(ZBX_THREAD_SENDVAL_ARGS));
1455 
1456 #if defined(_WINDOWS) && (defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL))
1457 	if (ZBX_TCP_SEC_UNENCRYPTED != configured_tls_connect_mode)
1458 	{
1459 		/* prepare to pass necessary TLS data to 'send_value' thread (to be started soon) */
1460 		zbx_tls_pass_vars(&sendval_args->tls_vars);
1461 	}
1462 #endif
1463 	zbx_json_init(&sendval_args->json, ZBX_JSON_STAT_BUF_LEN);
1464 	zbx_json_addstring(&sendval_args->json, ZBX_PROTO_TAG_REQUEST, ZBX_PROTO_VALUE_SENDER_DATA, ZBX_JSON_TYPE_STRING);
1465 	zbx_json_addarray(&sendval_args->json, ZBX_PROTO_TAG_DATA);
1466 
1467 	if (INPUT_FILE)
1468 	{
1469 		FILE	*in;
1470 		char	*in_line = NULL, *key = NULL, *key_value = NULL;
1471 		int	buffer_count = 0;
1472 		size_t	key_alloc = 0, in_line_alloc = MAX_BUFFER_LEN;
1473 		double	last_send = 0;
1474 
1475 		if (0 == strcmp(INPUT_FILE, "-"))
1476 		{
1477 			in = stdin;
1478 			if (1 == REAL_TIME)
1479 			{
1480 				/* set line buffering on stdin */
1481 				setvbuf(stdin, (char *)NULL, _IOLBF, 1024);
1482 			}
1483 		}
1484 		else if (NULL == (in = fopen(INPUT_FILE, "r")))
1485 		{
1486 			zabbix_log(LOG_LEVEL_CRIT, "cannot open [%s]: %s", INPUT_FILE, zbx_strerror(errno));
1487 			goto free;
1488 		}
1489 
1490 		sendval_args->sync_timestamp = WITH_TIMESTAMPS;
1491 		in_line = (char *)zbx_malloc(NULL, in_line_alloc);
1492 
1493 		ret = SUCCEED;
1494 
1495 		while (0 == sig_exiting && (SUCCEED == ret || SUCCEED_PARTIAL == ret) &&
1496 				NULL != zbx_fgets_alloc(&in_line, &in_line_alloc, in))
1497 		{
1498 			char		hostname[MAX_STRING_LEN], clock[32];
1499 			int		read_more = 0;
1500 			size_t		key_value_alloc = 0;
1501 			const char	*p;
1502 
1503 			/* line format: <hostname> <key> [<timestamp>] [<ns>] <value> */
1504 
1505 			total_count++; /* also used as inputline */
1506 
1507 			zbx_rtrim(in_line, "\r\n");
1508 
1509 			p = in_line;
1510 
1511 			if ('\0' == *p || NULL == (p = get_string(p, hostname, sizeof(hostname))) || '\0' == *hostname)
1512 			{
1513 				zabbix_log(LOG_LEVEL_CRIT, "[line %d] 'Hostname' required", total_count);
1514 				ret = FAIL;
1515 				break;
1516 			}
1517 
1518 			if (0 == strcmp(hostname, "-"))
1519 			{
1520 				if (NULL == ZABBIX_HOSTNAME)
1521 				{
1522 					zabbix_log(LOG_LEVEL_CRIT, "[line %d] '-' encountered as 'Hostname',"
1523 							" but no default hostname was specified", total_count);
1524 					ret = FAIL;
1525 					break;
1526 				}
1527 				else
1528 					zbx_strlcpy(hostname, ZABBIX_HOSTNAME, sizeof(hostname));
1529 			}
1530 
1531 			if (key_alloc != in_line_alloc)
1532 			{
1533 				key_alloc = in_line_alloc;
1534 				key = (char *)zbx_realloc(key, key_alloc);
1535 			}
1536 
1537 			if ('\0' == *p || NULL == (p = get_string(p, key, key_alloc)) || '\0' == *key)
1538 			{
1539 				zabbix_log(LOG_LEVEL_CRIT, "[line %d] 'Key' required", total_count);
1540 				ret = FAIL;
1541 				break;
1542 			}
1543 
1544 			if (1 == WITH_TIMESTAMPS)
1545 			{
1546 				if ('\0' == *p || NULL == (p = get_string(p, clock, sizeof(clock))) || '\0' == *clock)
1547 				{
1548 					zabbix_log(LOG_LEVEL_CRIT, "[line %d] 'Timestamp' required", total_count);
1549 					ret = FAIL;
1550 					break;
1551 				}
1552 
1553 				if (FAIL == is_uint31(clock, &timestamp))
1554 				{
1555 					zabbix_log(LOG_LEVEL_WARNING, "[line %d] invalid 'Timestamp' value detected",
1556 							total_count);
1557 					ret = FAIL;
1558 					break;
1559 				}
1560 
1561 				if (1 == WITH_NS)
1562 				{
1563 					if ('\0' == *p || NULL == (p = get_string(p, clock, sizeof(clock))) ||
1564 							'\0' == *clock)
1565 					{
1566 						zabbix_log(LOG_LEVEL_CRIT, "[line %d] 'Nanoseconds' required",
1567 								total_count);
1568 						ret = FAIL;
1569 						break;
1570 					}
1571 
1572 					if (FAIL == is_uint_n_range(clock, sizeof(clock), &ns, sizeof(ns),
1573 							0LL, 999999999LL))
1574 					{
1575 						zabbix_log(LOG_LEVEL_WARNING,
1576 								"[line %d] invalid 'Nanoseconds' value detected",
1577 								total_count);
1578 						ret = FAIL;
1579 						break;
1580 					}
1581 				}
1582 			}
1583 
1584 			if (key_value_alloc != in_line_alloc)
1585 			{
1586 				key_value_alloc = in_line_alloc;
1587 				key_value = (char *)zbx_realloc(key_value, key_value_alloc);
1588 			}
1589 
1590 			if ('\0' != *p && '"' != *p)
1591 			{
1592 				zbx_strlcpy(key_value, p, key_value_alloc);
1593 			}
1594 			else if ('\0' == *p || NULL == (p = get_string(p, key_value, key_value_alloc)))
1595 			{
1596 				zabbix_log(LOG_LEVEL_CRIT, "[line %d] 'Key value' required", total_count);
1597 				ret = FAIL;
1598 				break;
1599 			}
1600 			else if ('\0' != *p)
1601 			{
1602 				zabbix_log(LOG_LEVEL_CRIT, "[line %d] too many parameters", total_count);
1603 				ret = FAIL;
1604 				break;
1605 			}
1606 
1607 			zbx_json_addobject(&sendval_args->json, NULL);
1608 			zbx_json_addstring(&sendval_args->json, ZBX_PROTO_TAG_HOST, hostname, ZBX_JSON_TYPE_STRING);
1609 			zbx_json_addstring(&sendval_args->json, ZBX_PROTO_TAG_KEY, key, ZBX_JSON_TYPE_STRING);
1610 			zbx_json_addstring(&sendval_args->json, ZBX_PROTO_TAG_VALUE, key_value, ZBX_JSON_TYPE_STRING);
1611 
1612 			if (1 == WITH_TIMESTAMPS)
1613 			{
1614 				zbx_json_adduint64(&sendval_args->json, ZBX_PROTO_TAG_CLOCK, timestamp);
1615 
1616 				if (1 == WITH_NS)
1617 					zbx_json_adduint64(&sendval_args->json, ZBX_PROTO_TAG_NS, ns);
1618 			}
1619 
1620 			zbx_json_close(&sendval_args->json);
1621 
1622 			succeed_count++;
1623 			buffer_count++;
1624 
1625 			if (stdin == in && 1 == REAL_TIME)
1626 			{
1627 				/* if there is nothing on standard input after 1/5 seconds, we send what we have */
1628 				/* otherwise, we keep reading, but we should send data at least once per second */
1629 
1630 				struct timeval	tv;
1631 				fd_set		read_set;
1632 
1633 				tv.tv_sec = 0;
1634 				tv.tv_usec = 200000;
1635 
1636 				FD_ZERO(&read_set);
1637 				FD_SET(0, &read_set);	/* stdin is file descriptor 0 */
1638 
1639 				if (-1 == (read_more = select(1, &read_set, NULL, NULL, &tv)))
1640 				{
1641 					zabbix_log(LOG_LEVEL_WARNING, "select() failed: %s", zbx_strerror(errno));
1642 				}
1643 				else if (1 <= read_more)
1644 				{
1645 					if (0 == last_send)
1646 						last_send = zbx_time();
1647 					else if (zbx_time() - last_send >= 1)
1648 						read_more = 0;
1649 				}
1650 			}
1651 
1652 			if (VALUES_MAX == buffer_count || (stdin == in && 1 == REAL_TIME && 0 >= read_more))
1653 			{
1654 				zbx_json_close(&sendval_args->json);
1655 
1656 				last_send = zbx_time();
1657 
1658 				ret = perform_data_sending(sendval_args, ret);
1659 
1660 				buffer_count = 0;
1661 				zbx_json_clean(&sendval_args->json);
1662 				zbx_json_addstring(&sendval_args->json, ZBX_PROTO_TAG_REQUEST,
1663 						ZBX_PROTO_VALUE_SENDER_DATA, ZBX_JSON_TYPE_STRING);
1664 				zbx_json_addarray(&sendval_args->json, ZBX_PROTO_TAG_DATA);
1665 			}
1666 		}
1667 
1668 		if (FAIL != ret && 0 != buffer_count)
1669 		{
1670 			zbx_json_close(&sendval_args->json);
1671 			ret = perform_data_sending(sendval_args, ret);
1672 		}
1673 
1674 		if (in != stdin)
1675 			fclose(in);
1676 
1677 		zbx_free(key);
1678 		zbx_free(key_value);
1679 		zbx_free(in_line);
1680 	}
1681 	else
1682 	{
1683 		sendval_args->sync_timestamp = 0;
1684 		total_count++;
1685 
1686 		do /* try block simulation */
1687 		{
1688 			if (NULL == ZABBIX_HOSTNAME)
1689 			{
1690 				zabbix_log(LOG_LEVEL_WARNING, "'Hostname' parameter required");
1691 				break;
1692 			}
1693 			if (NULL == ZABBIX_KEY)
1694 			{
1695 				zabbix_log(LOG_LEVEL_WARNING, "Key required");
1696 				break;
1697 			}
1698 			if (NULL == ZABBIX_KEY_VALUE)
1699 			{
1700 				zabbix_log(LOG_LEVEL_WARNING, "Key value required");
1701 				break;
1702 			}
1703 
1704 			ret = SUCCEED;
1705 
1706 			zbx_json_addobject(&sendval_args->json, NULL);
1707 			zbx_json_addstring(&sendval_args->json, ZBX_PROTO_TAG_HOST, ZABBIX_HOSTNAME, ZBX_JSON_TYPE_STRING);
1708 			zbx_json_addstring(&sendval_args->json, ZBX_PROTO_TAG_KEY, ZABBIX_KEY, ZBX_JSON_TYPE_STRING);
1709 			zbx_json_addstring(&sendval_args->json, ZBX_PROTO_TAG_VALUE, ZABBIX_KEY_VALUE, ZBX_JSON_TYPE_STRING);
1710 			zbx_json_close(&sendval_args->json);
1711 
1712 			succeed_count++;
1713 
1714 			ret = perform_data_sending(sendval_args, ret);
1715 		}
1716 		while (0); /* try block simulation */
1717 	}
1718 free:
1719 	zbx_json_free(&sendval_args->json);
1720 	zbx_free(sendval_args);
1721 exit:
1722 	if (FAIL != ret)
1723 	{
1724 		printf("sent: %d; skipped: %d; total: %d\n", succeed_count, total_count - succeed_count, total_count);
1725 	}
1726 	else
1727 	{
1728 		printf("Sending failed.%s\n", CONFIG_LOG_LEVEL != LOG_LEVEL_DEBUG ?
1729 				" Use option -vv for more detailed output." : "");
1730 	}
1731 
1732 #if defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
1733 	if (ZBX_TCP_SEC_UNENCRYPTED != configured_tls_connect_mode)
1734 	{
1735 		zbx_tls_free();
1736 #if defined(_WINDOWS)
1737 		zbx_tls_library_deinit();
1738 #endif
1739 	}
1740 #endif
1741 	zabbix_close_log();
1742 #if defined(_WINDOWS)
1743 	while (0 == WSACleanup())
1744 		;
1745 #endif
1746 #if !defined(_WINDOWS) && defined(HAVE_PTHREAD_PROCESS_SHARED)
1747 	zbx_locks_disable();
1748 #endif
1749 	if (FAIL == ret)
1750 		ret = EXIT_FAILURE;
1751 
1752 	return ret;
1753 }
1754