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 "sysinfo.h"
22
23 #include "cfg.h"
24 #include "log.h"
25 #include "zbxconf.h"
26 #include "zbxgetopt.h"
27 #include "zbxself.h"
28
29 #ifndef _WINDOWS
30 # include "../libs/zbxnix/control.h"
31 # include "zbxmodules.h"
32 #endif
33
34 #include "comms.h"
35 #include "alias.h"
36
37 #include "stats.h"
38 #ifdef _WINDOWS
39 # include "perfstat.h"
40 #else
41 # include "zbxnix.h"
42 # include "sighandler.h"
43 #endif
44 #include "active.h"
45 #include "listener.h"
46
47 #include "symbols.h"
48
49 #if defined(ZABBIX_SERVICE)
50 # include "service.h"
51 #elif defined(ZABBIX_DAEMON)
52 # include "daemon.h"
53 #endif
54
55 #include "setproctitle.h"
56 #include "../libs/zbxcrypto/tls.h"
57
58 const char *progname = NULL;
59
60 /* default config file location */
61 #ifdef _WINDOWS
62 # define DEFAULT_CONFIG_FILE "C:\\zabbix_agentd.conf"
63 #else
64 # define DEFAULT_CONFIG_FILE SYSCONFDIR "/zabbix_agentd.conf"
65 #endif
66
67 /* application TITLE */
68 const char title_message[] = "zabbix_agentd"
69 #if defined(_WIN64)
70 " Win64"
71 #elif defined(_WIN32)
72 " Win32"
73 #endif
74 #if defined(ZABBIX_SERVICE)
75 " (service)"
76 #elif defined(ZABBIX_DAEMON)
77 " (daemon)"
78 #endif
79 ;
80 /* end of application TITLE */
81
82 const char syslog_app_name[] = "zabbix_agentd";
83
84 /* application USAGE message */
85 const char *usage_message[] = {
86 "[-c config-file]", NULL,
87 "[-c config-file]", "-p", NULL,
88 "[-c config-file]", "-t item-key", NULL,
89 #ifdef _WINDOWS
90 "[-c config-file]", "-i", "[-m]", NULL,
91 "[-c config-file]", "-d", "[-m]", NULL,
92 "[-c config-file]", "-s", "[-m]", NULL,
93 "[-c config-file]", "-x", "[-m]", NULL,
94 #else
95 "[-c config-file]", "-R runtime-option", NULL,
96 #endif
97 "-h", NULL,
98 "-V", NULL,
99 NULL /* end of text */
100 };
101 /* end of application USAGE message */
102
103 /* application HELP message */
104 const char *help_message[] = {
105 "A Zabbix daemon for monitoring of various server parameters.",
106 "",
107 "Options:",
108 " -c --config config-file Absolute path to the configuration file",
109 " (default: \"" DEFAULT_CONFIG_FILE "\")",
110 " -f --foreground Run Zabbix agent in foreground",
111 " -p --print Print known items and exit",
112 " -t --test item-key Test specified item and exit",
113 #ifdef _WINDOWS
114 " -m --multiple-agents For -i -d -s -x functions service name will",
115 " include Hostname parameter specified in",
116 " configuration file",
117 "Functions:",
118 "",
119 " -i --install Install Zabbix agent as service",
120 " -d --uninstall Uninstall Zabbix agent from service",
121
122 " -s --start Start Zabbix agent service",
123 " -x --stop Stop Zabbix agent service",
124 #else
125 " -R --runtime-control runtime-option Perform administrative functions",
126 "",
127 " Runtime control options:",
128 " " ZBX_LOG_LEVEL_INCREASE "=target Increase log level, affects all processes if",
129 " target is not specified",
130 " " ZBX_LOG_LEVEL_DECREASE "=target Decrease log level, affects all processes if",
131 " target is not specified",
132 "",
133 " Log level control targets:",
134 " process-type All processes of specified type (e.g.,",
135 " listener)",
136 " process-type,N Process type and number (e.g., listener,3)",
137 " pid Process identifier, up to 65535. For larger",
138 " values specify target as \"process-type,N\"",
139 #endif
140 "",
141 " -h --help Display this help message",
142 " -V --version Display version number",
143 "",
144 #ifdef _WINDOWS
145 "Example: zabbix_agentd -c C:\\zabbix\\zabbix_agentd.conf",
146 #else
147 "Example: zabbix_agentd -c /usr/local/etc/zabbix3/zabbix_agentd.conf",
148 #endif
149 NULL /* end of text */
150 };
151 /* end of application HELP message */
152
153 /* COMMAND LINE OPTIONS */
154 static struct zbx_option longopts[] =
155 {
156 {"config", 1, NULL, 'c'},
157 {"foreground", 0, NULL, 'f'},
158 {"help", 0, NULL, 'h'},
159 {"version", 0, NULL, 'V'},
160 {"print", 0, NULL, 'p'},
161 {"test", 1, NULL, 't'},
162 #ifndef _WINDOWS
163 {"runtime-control", 1, NULL, 'R'},
164 #else
165 {"install", 0, NULL, 'i'},
166 {"uninstall", 0, NULL, 'd'},
167
168 {"start", 0, NULL, 's'},
169 {"stop", 0, NULL, 'x'},
170
171 {"multiple-agents", 0, NULL, 'm'},
172 #endif
173 {NULL}
174 };
175
176 static char shortopts[] =
177 "c:hVpt:f"
178 #ifndef _WINDOWS
179 "R:"
180 #else
181 "idsxm"
182 #endif
183 ;
184 /* end of COMMAND LINE OPTIONS */
185
186 static char *TEST_METRIC = NULL;
187 int threads_num = 0;
188 ZBX_THREAD_HANDLE *threads = NULL;
189
190 unsigned char program_type = ZBX_PROGRAM_TYPE_AGENTD;
191
192 ZBX_THREAD_LOCAL unsigned char process_type = 255; /* ZBX_PROCESS_TYPE_UNKNOWN */
193 ZBX_THREAD_LOCAL int process_num;
194 ZBX_THREAD_LOCAL int server_num = 0;
195
196 ZBX_THREAD_ACTIVECHK_ARGS *CONFIG_ACTIVE_ARGS = NULL;
197
198 int CONFIG_ALERTER_FORKS = 0;
199 int CONFIG_DISCOVERER_FORKS = 0;
200 int CONFIG_HOUSEKEEPER_FORKS = 0;
201 int CONFIG_PINGER_FORKS = 0;
202 int CONFIG_POLLER_FORKS = 0;
203 int CONFIG_UNREACHABLE_POLLER_FORKS = 0;
204 int CONFIG_HTTPPOLLER_FORKS = 0;
205 int CONFIG_IPMIPOLLER_FORKS = 0;
206 int CONFIG_TIMER_FORKS = 0;
207 int CONFIG_TRAPPER_FORKS = 0;
208 int CONFIG_SNMPTRAPPER_FORKS = 0;
209 int CONFIG_JAVAPOLLER_FORKS = 0;
210 int CONFIG_ESCALATOR_FORKS = 0;
211 int CONFIG_SELFMON_FORKS = 0;
212 int CONFIG_WATCHDOG_FORKS = 0;
213 int CONFIG_DATASENDER_FORKS = 0;
214 int CONFIG_HEARTBEAT_FORKS = 0;
215 int CONFIG_PROXYPOLLER_FORKS = 0;
216 int CONFIG_HISTSYNCER_FORKS = 0;
217 int CONFIG_CONFSYNCER_FORKS = 0;
218 int CONFIG_VMWARE_FORKS = 0;
219 int CONFIG_COLLECTOR_FORKS = 1;
220 int CONFIG_PASSIVE_FORKS = 3; /* number of listeners for processing passive checks */
221 int CONFIG_ACTIVE_FORKS = 0;
222
223 char *opt = NULL;
224
225 #ifdef _WINDOWS
226 void zbx_co_uninitialize();
227 #endif
228
229 int get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num);
230
get_process_info_by_thread(int local_server_num,unsigned char * local_process_type,int * local_process_num)231 int get_process_info_by_thread(int local_server_num, unsigned char *local_process_type, int *local_process_num)
232 {
233 int server_count = 0;
234
235 if (0 == local_server_num)
236 {
237 /* fail if the main process is queried */
238 return FAIL;
239 }
240 else if (local_server_num <= (server_count += CONFIG_COLLECTOR_FORKS))
241 {
242 *local_process_type = ZBX_PROCESS_TYPE_COLLECTOR;
243 *local_process_num = local_server_num - server_count + CONFIG_COLLECTOR_FORKS;
244 }
245 else if (local_server_num <= (server_count += CONFIG_PASSIVE_FORKS))
246 {
247 *local_process_type = ZBX_PROCESS_TYPE_LISTENER;
248 *local_process_num = local_server_num - server_count + CONFIG_PASSIVE_FORKS;
249
250 }
251 else if (local_server_num <= (server_count += CONFIG_ACTIVE_FORKS))
252 {
253 *local_process_type = ZBX_PROCESS_TYPE_ACTIVE_CHECKS;
254 *local_process_num = local_server_num - server_count + CONFIG_ACTIVE_FORKS;
255 }
256 else
257 return FAIL;
258
259 return SUCCEED;
260 }
261
parse_commandline(int argc,char ** argv,ZBX_TASK_EX * t)262 static int parse_commandline(int argc, char **argv, ZBX_TASK_EX *t)
263 {
264 int i, ret = SUCCEED;
265 char ch;
266 #ifdef _WINDOWS
267 unsigned int opt_mask = 0;
268 #endif
269 unsigned short opt_count[256] = {0};
270
271 t->task = ZBX_TASK_START;
272
273 /* parse the command-line */
274 while ((char)EOF != (ch = (char)zbx_getopt_long(argc, argv, shortopts, longopts, NULL)))
275 {
276 opt_count[(unsigned char)ch]++;
277
278 switch (ch)
279 {
280 case 'c':
281 if (NULL == CONFIG_FILE)
282 CONFIG_FILE = strdup(zbx_optarg);
283 break;
284 #ifndef _WINDOWS
285 case 'R':
286 if (SUCCEED != parse_rtc_options(zbx_optarg, program_type, &t->data))
287 exit(EXIT_FAILURE);
288
289 t->task = ZBX_TASK_RUNTIME_CONTROL;
290 break;
291 #endif
292 case 'h':
293 t->task = ZBX_TASK_SHOW_HELP;
294 goto out;
295 case 'V':
296 t->task = ZBX_TASK_SHOW_VERSION;
297 goto out;
298 case 'p':
299 if (ZBX_TASK_START == t->task)
300 t->task = ZBX_TASK_PRINT_SUPPORTED;
301 break;
302 case 't':
303 if (ZBX_TASK_START == t->task)
304 {
305 t->task = ZBX_TASK_TEST_METRIC;
306 TEST_METRIC = strdup(zbx_optarg);
307 }
308 break;
309 case 'f':
310 t->flags |= ZBX_TASK_FLAG_FOREGROUND;
311 break;
312 #ifdef _WINDOWS
313 case 'i':
314 t->task = ZBX_TASK_INSTALL_SERVICE;
315 break;
316 case 'd':
317 t->task = ZBX_TASK_UNINSTALL_SERVICE;
318 break;
319 case 's':
320 t->task = ZBX_TASK_START_SERVICE;
321 break;
322 case 'x':
323 t->task = ZBX_TASK_STOP_SERVICE;
324 break;
325 case 'm':
326 t->flags |= ZBX_TASK_FLAG_MULTIPLE_AGENTS;
327 break;
328 #endif
329 default:
330 t->task = ZBX_TASK_SHOW_USAGE;
331 goto out;
332 }
333 }
334
335 #ifdef _WINDOWS
336 switch (t->task)
337 {
338 case ZBX_TASK_START:
339 break;
340 case ZBX_TASK_INSTALL_SERVICE:
341 case ZBX_TASK_UNINSTALL_SERVICE:
342 case ZBX_TASK_START_SERVICE:
343 case ZBX_TASK_STOP_SERVICE:
344 if (0 != (t->flags & ZBX_TASK_FLAG_FOREGROUND))
345 {
346 zbx_error("foreground option cannot be used with Zabbix agent services");
347 ret = FAIL;
348 goto out;
349 }
350 break;
351 default:
352 if (0 != (t->flags & ZBX_TASK_FLAG_MULTIPLE_AGENTS))
353 {
354 zbx_error("multiple agents option can be used only with Zabbix agent services");
355 ret = FAIL;
356 goto out;
357 }
358 }
359 #endif
360
361 /* every option may be specified only once */
362
363 for (i = 0; NULL != longopts[i].name; i++)
364 {
365 ch = longopts[i].val;
366
367 if ('h' == ch || 'V' == ch)
368 continue;
369
370 if (1 < opt_count[(unsigned char)ch])
371 {
372 if (NULL == strchr(shortopts, ch))
373 zbx_error("option \"--%s\" specified multiple times", longopts[i].name);
374 else
375 zbx_error("option \"-%c\" or \"--%s\" specified multiple times", ch, longopts[i].name);
376
377 ret = FAIL;
378 }
379 }
380
381 if (FAIL == ret)
382 goto out;
383
384 #ifdef _WINDOWS
385 /* check for mutually exclusive options */
386 /* Allowed option combinations. */
387 /* Option 'c' is always optional. */
388 /* p t i d s x m opt_mask */
389 /* --------------------- -------- */
390 /* - - - - - - - 0x00 */
391 /* p - - - - - - 0x40 */
392 /* - t - - - - - 0x20 */
393 /* - - i - - - - 0x10 */
394 /* - - - d - - - 0x08 */
395 /* - - - - s - - 0x04 */
396 /* - - - - - x - 0x02 */
397 /* - - i - - - m 0x11 */
398 /* - - - d - - m 0x09 */
399 /* - - - - s - m 0x05 */
400 /* - - - - - x m 0x03 */
401 /* - - - - - - m 0x01 special case required for starting as a service with '-m' option */
402
403 if (0 < opt_count['p'])
404 opt_mask |= 0x40;
405 if (0 < opt_count['t'])
406 opt_mask |= 0x20;
407 if (0 < opt_count['i'])
408 opt_mask |= 0x10;
409 if (0 < opt_count['d'])
410 opt_mask |= 0x08;
411 if (0 < opt_count['s'])
412 opt_mask |= 0x04;
413 if (0 < opt_count['x'])
414 opt_mask |= 0x02;
415 if (0 < opt_count['m'])
416 opt_mask |= 0x01;
417
418 switch (opt_mask)
419 {
420 case 0x00:
421 case 0x01:
422 case 0x02:
423 case 0x03:
424 case 0x04:
425 case 0x05:
426 case 0x08:
427 case 0x09:
428 case 0x10:
429 case 0x11:
430 case 0x20:
431 case 0x40:
432 break;
433 default:
434 zbx_error("mutually exclusive options used");
435 usage();
436 ret = FAIL;
437 goto out;
438 }
439 #else
440 /* check for mutually exclusive options */
441 if (1 < opt_count['p'] + opt_count['t'] + opt_count['R'])
442 {
443 zbx_error("only one of options \"-p\" or \"--print\", \"-t\" or \"--test\","
444 " \"-R\" or \"--runtime-control\" can be used");
445 ret = FAIL;
446 goto out;
447 }
448 #endif
449 /* Parameters which are not option values are invalid. The check relies on zbx_getopt_internal() which */
450 /* always permutes command line arguments regardless of POSIXLY_CORRECT environment variable. */
451 if (argc > zbx_optind)
452 {
453 for (i = zbx_optind; i < argc; i++)
454 zbx_error("invalid parameter \"%s\"", argv[i]);
455
456 ret = FAIL;
457 goto out;
458 }
459
460 if (NULL == CONFIG_FILE)
461 CONFIG_FILE = zbx_strdup(NULL, DEFAULT_CONFIG_FILE);
462 out:
463 if (FAIL == ret)
464 {
465 zbx_free(TEST_METRIC);
466 zbx_free(CONFIG_FILE);
467 }
468
469 return ret;
470 }
471
472 /******************************************************************************
473 * *
474 * Function: set_defaults *
475 * *
476 * Purpose: set configuration defaults *
477 * *
478 * Author: Vladimir Levijev, Rudolfs Kreicbergs *
479 * *
480 ******************************************************************************/
set_defaults(void)481 static void set_defaults(void)
482 {
483 AGENT_RESULT result;
484 char **value = NULL;
485
486 if (NULL == CONFIG_HOSTNAME)
487 {
488 if (NULL == CONFIG_HOSTNAME_ITEM)
489 CONFIG_HOSTNAME_ITEM = zbx_strdup(CONFIG_HOSTNAME_ITEM, "system.hostname");
490
491 init_result(&result);
492
493 if (SUCCEED == process(CONFIG_HOSTNAME_ITEM, PROCESS_LOCAL_COMMAND | PROCESS_WITH_ALIAS, &result) &&
494 NULL != (value = GET_STR_RESULT(&result)))
495 {
496 assert(*value);
497
498 if (MAX_ZBX_HOSTNAME_LEN < strlen(*value))
499 {
500 (*value)[MAX_ZBX_HOSTNAME_LEN] = '\0';
501 zabbix_log(LOG_LEVEL_WARNING, "hostname truncated to [%s])", *value);
502 }
503
504 CONFIG_HOSTNAME = zbx_strdup(CONFIG_HOSTNAME, *value);
505 }
506 else
507 zabbix_log(LOG_LEVEL_WARNING, "failed to get system hostname from [%s])", CONFIG_HOSTNAME_ITEM);
508
509 free_result(&result);
510 }
511 else if (NULL != CONFIG_HOSTNAME_ITEM)
512 zabbix_log(LOG_LEVEL_WARNING, "both Hostname and HostnameItem defined, using [%s]", CONFIG_HOSTNAME);
513
514 if (NULL != CONFIG_HOST_METADATA && NULL != CONFIG_HOST_METADATA_ITEM)
515 {
516 zabbix_log(LOG_LEVEL_WARNING, "both HostMetadata and HostMetadataItem defined, using [%s]",
517 CONFIG_HOST_METADATA);
518 }
519
520 #ifndef _WINDOWS
521 if (NULL == CONFIG_LOAD_MODULE_PATH)
522 CONFIG_LOAD_MODULE_PATH = zbx_strdup(CONFIG_LOAD_MODULE_PATH, LIBDIR "/modules");
523
524 if (NULL == CONFIG_PID_FILE)
525 CONFIG_PID_FILE = "/var/run/zabbix/zabbix_agentd.pid";
526 #endif
527 if (NULL == CONFIG_LOG_TYPE_STR)
528 CONFIG_LOG_TYPE_STR = zbx_strdup(CONFIG_LOG_TYPE_STR, ZBX_OPTION_LOGTYPE_FILE);
529 }
530
531 /******************************************************************************
532 * *
533 * Function: zbx_validate_config *
534 * *
535 * Purpose: validate configuration parameters *
536 * *
537 * Author: Vladimir Levijev *
538 * *
539 ******************************************************************************/
zbx_validate_config(ZBX_TASK_EX * task)540 static void zbx_validate_config(ZBX_TASK_EX *task)
541 {
542 char *ch_error;
543 int err = 0;
544
545 if (NULL == CONFIG_HOSTS_ALLOWED && 0 != CONFIG_PASSIVE_FORKS)
546 {
547 zabbix_log(LOG_LEVEL_CRIT, "StartAgents is not 0, parameter Server must be defined");
548 err = 1;
549 }
550
551 if (NULL == CONFIG_HOSTNAME)
552 {
553 zabbix_log(LOG_LEVEL_CRIT, "\"Hostname\" configuration parameter is not defined");
554 err = 1;
555 }
556 else if (FAIL == zbx_check_hostname(CONFIG_HOSTNAME, &ch_error))
557 {
558 zabbix_log(LOG_LEVEL_CRIT, "invalid \"Hostname\" configuration parameter: '%s': %s", CONFIG_HOSTNAME,
559 ch_error);
560 zbx_free(ch_error);
561 err = 1;
562 }
563
564 if (NULL != CONFIG_HOST_METADATA && HOST_METADATA_LEN < zbx_strlen_utf8(CONFIG_HOST_METADATA))
565 {
566 zabbix_log(LOG_LEVEL_CRIT, "the value of \"HostMetadata\" configuration parameter cannot be longer than"
567 " %d characters", HOST_METADATA_LEN);
568 err = 1;
569 }
570
571 /* make sure active or passive check is enabled */
572 if (0 == CONFIG_ACTIVE_FORKS && 0 == CONFIG_PASSIVE_FORKS)
573 {
574 zabbix_log(LOG_LEVEL_CRIT, "either active or passive checks must be enabled");
575 err = 1;
576 }
577
578 if (NULL != CONFIG_SOURCE_IP && SUCCEED != is_supported_ip(CONFIG_SOURCE_IP))
579 {
580 zabbix_log(LOG_LEVEL_CRIT, "invalid \"SourceIP\" configuration parameter: '%s'", CONFIG_SOURCE_IP);
581 err = 1;
582 }
583
584 if (SUCCEED != zbx_validate_log_parameters(task))
585 err = 1;
586
587 #if !(defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL))
588 err |= (FAIL == check_cfg_feature_str("TLSConnect", CONFIG_TLS_CONNECT, "TLS support"));
589 err |= (FAIL == check_cfg_feature_str("TLSAccept", CONFIG_TLS_ACCEPT, "TLS support"));
590 err |= (FAIL == check_cfg_feature_str("TLSCAFile", CONFIG_TLS_CA_FILE, "TLS support"));
591 err |= (FAIL == check_cfg_feature_str("TLSCRLFile", CONFIG_TLS_CRL_FILE, "TLS support"));
592 err |= (FAIL == check_cfg_feature_str("TLSServerCertIssuer", CONFIG_TLS_SERVER_CERT_ISSUER, "TLS support"));
593 err |= (FAIL == check_cfg_feature_str("TLSServerCertSubject", CONFIG_TLS_SERVER_CERT_SUBJECT, "TLS support"));
594 err |= (FAIL == check_cfg_feature_str("TLSCertFile", CONFIG_TLS_CERT_FILE, "TLS support"));
595 err |= (FAIL == check_cfg_feature_str("TLSKeyFile", CONFIG_TLS_KEY_FILE, "TLS support"));
596 err |= (FAIL == check_cfg_feature_str("TLSPSKIdentity", CONFIG_TLS_PSK_IDENTITY, "TLS support"));
597 err |= (FAIL == check_cfg_feature_str("TLSPSKFile", CONFIG_TLS_PSK_FILE, "TLS support"));
598 #endif
599 if (0 != err)
600 exit(EXIT_FAILURE);
601 }
602
add_activechk_host(const char * host,unsigned short port)603 static int add_activechk_host(const char *host, unsigned short port)
604 {
605 int i;
606
607 for (i = 0; i < CONFIG_ACTIVE_FORKS; i++)
608 {
609 if (0 == strcmp(CONFIG_ACTIVE_ARGS[i].host, host) && CONFIG_ACTIVE_ARGS[i].port == port)
610 return FAIL;
611 }
612
613 CONFIG_ACTIVE_FORKS++;
614 CONFIG_ACTIVE_ARGS = zbx_realloc(CONFIG_ACTIVE_ARGS, sizeof(ZBX_THREAD_ACTIVECHK_ARGS) * CONFIG_ACTIVE_FORKS);
615 CONFIG_ACTIVE_ARGS[CONFIG_ACTIVE_FORKS - 1].host = zbx_strdup(NULL, host);
616 CONFIG_ACTIVE_ARGS[CONFIG_ACTIVE_FORKS - 1].port = port;
617
618 return SUCCEED;
619 }
620
621 /******************************************************************************
622 * *
623 * Function: get_serveractive_hosts *
624 * *
625 * Purpose: parse string like IP<:port>,[IPv6]<:port> *
626 * *
627 ******************************************************************************/
get_serveractive_hosts(char * active_hosts)628 static void get_serveractive_hosts(char *active_hosts)
629 {
630 char *l = active_hosts, *r;
631 int rc = SUCCEED;
632
633 do
634 {
635 char *host = NULL;
636 unsigned short port;
637
638 if (NULL != (r = strchr(l, ',')))
639 *r = '\0';
640
641 if (SUCCEED != parse_serveractive_element(l, &host, &port, (unsigned short)ZBX_DEFAULT_SERVER_PORT))
642 goto fail;
643
644 rc = add_activechk_host(host, port);
645
646 zbx_free(host);
647
648 if (SUCCEED != rc)
649 goto fail;
650
651 if (NULL != r)
652 {
653 *r = ',';
654 l = r + 1;
655 }
656 }
657 while (NULL != r);
658
659 return;
660 fail:
661 if (SUCCEED != rc)
662 zbx_error("error parsing a \"ServerActive\" option: address \"%s\" specified more than once", l);
663 else
664 zbx_error("error parsing a \"ServerActive\" option: address \"%s\" is invalid", l);
665
666 if (NULL != r)
667 *r = ',';
668
669 exit(EXIT_FAILURE);
670 }
671
672 /******************************************************************************
673 * *
674 * Function: zbx_load_config *
675 * *
676 * Purpose: load configuration from config file *
677 * *
678 * Parameters: requirement - produce error if config file missing or not *
679 * *
680 ******************************************************************************/
zbx_load_config(int requirement,ZBX_TASK_EX * task)681 static void zbx_load_config(int requirement, ZBX_TASK_EX *task)
682 {
683 char *active_hosts = NULL;
684
685 struct cfg_line cfg[] =
686 {
687 /* PARAMETER, VAR, TYPE,
688 MANDATORY, MIN, MAX */
689 {"Server", &CONFIG_HOSTS_ALLOWED, TYPE_STRING_LIST,
690 PARM_OPT, 0, 0},
691 {"ServerActive", &active_hosts, TYPE_STRING_LIST,
692 PARM_OPT, 0, 0},
693 {"Hostname", &CONFIG_HOSTNAME, TYPE_STRING,
694 PARM_OPT, 0, 0},
695 {"HostnameItem", &CONFIG_HOSTNAME_ITEM, TYPE_STRING,
696 PARM_OPT, 0, 0},
697 {"HostMetadata", &CONFIG_HOST_METADATA, TYPE_STRING,
698 PARM_OPT, 0, 0},
699 {"HostMetadataItem", &CONFIG_HOST_METADATA_ITEM, TYPE_STRING,
700 PARM_OPT, 0, 0},
701 {"BufferSize", &CONFIG_BUFFER_SIZE, TYPE_INT,
702 PARM_OPT, 2, 65535},
703 {"BufferSend", &CONFIG_BUFFER_SEND, TYPE_INT,
704 PARM_OPT, 1, SEC_PER_HOUR},
705 #ifndef _WINDOWS
706 {"PidFile", &CONFIG_PID_FILE, TYPE_STRING,
707 PARM_OPT, 0, 0},
708 #endif
709 {"LogType", &CONFIG_LOG_TYPE_STR, TYPE_STRING,
710 PARM_OPT, 0, 0},
711 {"LogFile", &CONFIG_LOG_FILE, TYPE_STRING,
712 PARM_OPT, 0, 0},
713 {"LogFileSize", &CONFIG_LOG_FILE_SIZE, TYPE_INT,
714 PARM_OPT, 0, 1024},
715 {"Timeout", &CONFIG_TIMEOUT, TYPE_INT,
716 PARM_OPT, 1, 30},
717 {"ListenPort", &CONFIG_LISTEN_PORT, TYPE_INT,
718 PARM_OPT, 1024, 32767},
719 {"ListenIP", &CONFIG_LISTEN_IP, TYPE_STRING_LIST,
720 PARM_OPT, 0, 0},
721 {"SourceIP", &CONFIG_SOURCE_IP, TYPE_STRING,
722 PARM_OPT, 0, 0},
723 {"DebugLevel", &CONFIG_LOG_LEVEL, TYPE_INT,
724 PARM_OPT, 0, 5},
725 {"StartAgents", &CONFIG_PASSIVE_FORKS, TYPE_INT,
726 PARM_OPT, 0, 100},
727 {"RefreshActiveChecks", &CONFIG_REFRESH_ACTIVE_CHECKS, TYPE_INT,
728 PARM_OPT, SEC_PER_MIN, SEC_PER_HOUR},
729 {"MaxLinesPerSecond", &CONFIG_MAX_LINES_PER_SECOND, TYPE_INT,
730 PARM_OPT, 1, 1000},
731 {"EnableRemoteCommands", &CONFIG_ENABLE_REMOTE_COMMANDS, TYPE_INT,
732 PARM_OPT, 0, 1},
733 {"LogRemoteCommands", &CONFIG_LOG_REMOTE_COMMANDS, TYPE_INT,
734 PARM_OPT, 0, 1},
735 {"UnsafeUserParameters", &CONFIG_UNSAFE_USER_PARAMETERS, TYPE_INT,
736 PARM_OPT, 0, 1},
737 {"Alias", &CONFIG_ALIASES, TYPE_MULTISTRING,
738 PARM_OPT, 0, 0},
739 {"UserParameter", &CONFIG_USER_PARAMETERS, TYPE_MULTISTRING,
740 PARM_OPT, 0, 0},
741 #ifndef _WINDOWS
742 {"LoadModulePath", &CONFIG_LOAD_MODULE_PATH, TYPE_STRING,
743 PARM_OPT, 0, 0},
744 {"LoadModule", &CONFIG_LOAD_MODULE, TYPE_MULTISTRING,
745 PARM_OPT, 0, 0},
746 {"AllowRoot", &CONFIG_ALLOW_ROOT, TYPE_INT,
747 PARM_OPT, 0, 1},
748 {"User", &CONFIG_USER, TYPE_STRING,
749 PARM_OPT, 0, 0},
750 #endif
751 #ifdef _WINDOWS
752 {"PerfCounter", &CONFIG_PERF_COUNTERS, TYPE_MULTISTRING,
753 PARM_OPT, 0, 0},
754 #endif
755 {"TLSConnect", &CONFIG_TLS_CONNECT, TYPE_STRING,
756 PARM_OPT, 0, 0},
757 {"TLSAccept", &CONFIG_TLS_ACCEPT, TYPE_STRING_LIST,
758 PARM_OPT, 0, 0},
759 {"TLSCAFile", &CONFIG_TLS_CA_FILE, TYPE_STRING,
760 PARM_OPT, 0, 0},
761 {"TLSCRLFile", &CONFIG_TLS_CRL_FILE, TYPE_STRING,
762 PARM_OPT, 0, 0},
763 {"TLSServerCertIssuer", &CONFIG_TLS_SERVER_CERT_ISSUER, TYPE_STRING,
764 PARM_OPT, 0, 0},
765 {"TLSServerCertSubject", &CONFIG_TLS_SERVER_CERT_SUBJECT, TYPE_STRING,
766 PARM_OPT, 0, 0},
767 {"TLSCertFile", &CONFIG_TLS_CERT_FILE, TYPE_STRING,
768 PARM_OPT, 0, 0},
769 {"TLSKeyFile", &CONFIG_TLS_KEY_FILE, TYPE_STRING,
770 PARM_OPT, 0, 0},
771 {"TLSPSKIdentity", &CONFIG_TLS_PSK_IDENTITY, TYPE_STRING,
772 PARM_OPT, 0, 0},
773 {"TLSPSKFile", &CONFIG_TLS_PSK_FILE, TYPE_STRING,
774 PARM_OPT, 0, 0},
775 {NULL}
776 };
777
778 /* initialize multistrings */
779 zbx_strarr_init(&CONFIG_ALIASES);
780 zbx_strarr_init(&CONFIG_USER_PARAMETERS);
781 #ifndef _WINDOWS
782 zbx_strarr_init(&CONFIG_LOAD_MODULE);
783 #endif
784 #ifdef _WINDOWS
785 zbx_strarr_init(&CONFIG_PERF_COUNTERS);
786 #endif
787 parse_cfg_file(CONFIG_FILE, cfg, requirement, ZBX_CFG_STRICT);
788
789 set_defaults();
790
791 CONFIG_LOG_TYPE = zbx_get_log_type(CONFIG_LOG_TYPE_STR);
792
793 if (NULL != active_hosts && '\0' != *active_hosts)
794 get_serveractive_hosts(active_hosts);
795
796 zbx_free(active_hosts);
797
798 if (ZBX_CFG_FILE_REQUIRED == requirement)
799 {
800 zbx_validate_config(task);
801 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
802 zbx_tls_validate_config();
803 #endif
804 }
805 }
806
807 /******************************************************************************
808 * *
809 * Function: zbx_free_config *
810 * *
811 * Purpose: free configuration memory *
812 * *
813 * Author: Vladimir Levijev *
814 * *
815 ******************************************************************************/
zbx_free_config(void)816 static void zbx_free_config(void)
817 {
818 zbx_strarr_free(CONFIG_ALIASES);
819 zbx_strarr_free(CONFIG_USER_PARAMETERS);
820 #ifndef _WINDOWS
821 zbx_strarr_free(CONFIG_LOAD_MODULE);
822 #endif
823 #ifdef _WINDOWS
824 zbx_strarr_free(CONFIG_PERF_COUNTERS);
825 #endif
826 }
827
828 #ifdef _WINDOWS
zbx_exec_service_task(const char * name,const ZBX_TASK_EX * t)829 static int zbx_exec_service_task(const char *name, const ZBX_TASK_EX *t)
830 {
831 int ret;
832
833 switch (t->task)
834 {
835 case ZBX_TASK_INSTALL_SERVICE:
836 ret = ZabbixCreateService(name, t->flags & ZBX_TASK_FLAG_MULTIPLE_AGENTS);
837 break;
838 case ZBX_TASK_UNINSTALL_SERVICE:
839 ret = ZabbixRemoveService();
840 break;
841 case ZBX_TASK_START_SERVICE:
842 ret = ZabbixStartService();
843 break;
844 case ZBX_TASK_STOP_SERVICE:
845 ret = ZabbixStopService();
846 break;
847 default:
848 /* there can not be other choice */
849 assert(0);
850 }
851
852 return ret;
853 }
854 #endif /* _WINDOWS */
855
MAIN_ZABBIX_ENTRY(int flags)856 int MAIN_ZABBIX_ENTRY(int flags)
857 {
858 zbx_socket_t listen_sock;
859 int i, j = 0;
860 #ifdef _WINDOWS
861 DWORD res;
862 #endif
863
864 if (0 != (flags & ZBX_TASK_FLAG_FOREGROUND))
865 {
866 printf("Starting Zabbix Agent [%s]. Zabbix %s (revision %s).\nPress Ctrl+C to exit.\n\n",
867 CONFIG_HOSTNAME, ZABBIX_VERSION, ZABBIX_REVISION);
868 }
869
870 zabbix_open_log(CONFIG_LOG_TYPE, CONFIG_LOG_LEVEL, CONFIG_LOG_FILE);
871
872 #ifdef HAVE_IPV6
873 # define IPV6_FEATURE_STATUS "YES"
874 #else
875 # define IPV6_FEATURE_STATUS " NO"
876 #endif
877 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
878 # define TLS_FEATURE_STATUS "YES"
879 #else
880 # define TLS_FEATURE_STATUS " NO"
881 #endif
882
883 zabbix_log(LOG_LEVEL_INFORMATION, "Starting Zabbix Agent [%s]. Zabbix %s (revision %s).",
884 CONFIG_HOSTNAME, ZABBIX_VERSION, ZABBIX_REVISION);
885
886 zabbix_log(LOG_LEVEL_INFORMATION, "**** Enabled features ****");
887 zabbix_log(LOG_LEVEL_INFORMATION, "IPv6 support: " IPV6_FEATURE_STATUS);
888 zabbix_log(LOG_LEVEL_INFORMATION, "TLS support: " TLS_FEATURE_STATUS);
889 zabbix_log(LOG_LEVEL_INFORMATION, "**************************");
890
891 zabbix_log(LOG_LEVEL_INFORMATION, "using configuration file: %s", CONFIG_FILE);
892
893 #ifndef _WINDOWS
894 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
895 if (SUCCEED != zbx_coredump_disable())
896 {
897 zabbix_log(LOG_LEVEL_CRIT, "cannot disable core dump, exiting...");
898 exit(EXIT_FAILURE);
899 }
900 #endif
901 if (FAIL == load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 1))
902 {
903 zabbix_log(LOG_LEVEL_CRIT, "loading modules failed, exiting...");
904 exit(EXIT_FAILURE);
905 }
906 #endif
907 if (0 != CONFIG_PASSIVE_FORKS)
908 {
909 if (FAIL == zbx_tcp_listen(&listen_sock, CONFIG_LISTEN_IP, (unsigned short)CONFIG_LISTEN_PORT))
910 {
911 zabbix_log(LOG_LEVEL_CRIT, "listener failed: %s", zbx_socket_strerror());
912 exit(EXIT_FAILURE);
913 }
914 }
915
916 init_collector_data();
917
918 #ifdef _WINDOWS
919 init_perf_collector(1);
920 load_perf_counters(CONFIG_PERF_COUNTERS);
921 #endif
922 zbx_free_config();
923
924 #if defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL)
925 zbx_tls_init_parent();
926 #endif
927 /* --- START THREADS ---*/
928
929 /* allocate memory for a collector, all listeners and active checks */
930 threads_num = CONFIG_COLLECTOR_FORKS + CONFIG_PASSIVE_FORKS + CONFIG_ACTIVE_FORKS;
931
932 #ifdef _WINDOWS
933 if (MAXIMUM_WAIT_OBJECTS < threads_num)
934 {
935 zabbix_log(LOG_LEVEL_CRIT, "Too many agent threads. Please reduce the StartAgents configuration"
936 " parameter or the number of active servers in ServerActive configuration parameter.");
937 exit(EXIT_FAILURE);
938 }
939 #endif
940 threads = zbx_calloc(threads, threads_num, sizeof(ZBX_THREAD_HANDLE));
941
942 zabbix_log(LOG_LEVEL_INFORMATION, "agent #0 started [main process]");
943
944 for (i = 0; i < threads_num; i++)
945 {
946 zbx_thread_args_t *thread_args;
947
948 thread_args = (zbx_thread_args_t *)zbx_malloc(NULL, sizeof(zbx_thread_args_t));
949
950 if (FAIL == get_process_info_by_thread(i + 1, &thread_args->process_type, &thread_args->process_num))
951 {
952 THIS_SHOULD_NEVER_HAPPEN;
953 exit(EXIT_FAILURE);
954 }
955
956 thread_args->server_num = i + 1;
957 thread_args->args = NULL;
958
959 switch (thread_args->process_type)
960 {
961 case ZBX_PROCESS_TYPE_COLLECTOR:
962 zbx_thread_start(collector_thread, thread_args, &threads[i]);
963 break;
964 case ZBX_PROCESS_TYPE_LISTENER:
965 thread_args->args = &listen_sock;
966 zbx_thread_start(listener_thread, thread_args, &threads[i]);
967 break;
968 case ZBX_PROCESS_TYPE_ACTIVE_CHECKS:
969 thread_args->args = &CONFIG_ACTIVE_ARGS[j++];
970 zbx_thread_start(active_checks_thread, thread_args, &threads[i]);
971 break;
972 }
973 }
974
975 #ifdef _WINDOWS
976 set_parent_signal_handler(); /* must be called after all threads are created */
977
978 /* wait for an exiting thread */
979 res = WaitForMultipleObjectsEx(threads_num, threads, FALSE, INFINITE, FALSE);
980
981 if (ZBX_IS_RUNNING())
982 {
983 /* Zabbix agent service should either be stopped by the user in ServiceCtrlHandler() or */
984 /* crash. If some thread has terminated normally, it means something is terribly wrong. */
985
986 zabbix_log(LOG_LEVEL_CRIT, "One thread has terminated unexpectedly (code:%lu). Exiting ...", res);
987 THIS_SHOULD_NEVER_HAPPEN;
988
989 /* notify other threads and allow them to terminate */
990 ZBX_DO_EXIT();
991 zbx_sleep(1);
992 }
993 else
994 {
995 zbx_tcp_close(&listen_sock);
996
997 /* Wait for the service worker thread to terminate us. Listener threads may not exit up to */
998 /* CONFIG_TIMEOUT seconds if they're waiting for external processes to finish / timeout */
999 zbx_sleep(CONFIG_TIMEOUT);
1000
1001 THIS_SHOULD_NEVER_HAPPEN;
1002 }
1003 #else
1004 while (-1 == wait(&i)) /* wait for any child to exit */
1005 {
1006 if (EINTR != errno)
1007 {
1008 zabbix_log(LOG_LEVEL_ERR, "failed to wait on child processes: %s", zbx_strerror(errno));
1009 break;
1010 }
1011 }
1012
1013 /* all exiting child processes should be caught by signal handlers */
1014 THIS_SHOULD_NEVER_HAPPEN;
1015 #endif
1016 zbx_on_exit();
1017
1018 return SUCCEED;
1019 }
1020
1021 /******************************************************************************
1022 * *
1023 * Function: zbx_free_service_resources *
1024 * *
1025 * Purpose: free service resources allocated by main thread *
1026 * *
1027 ******************************************************************************/
zbx_free_service_resources(void)1028 void zbx_free_service_resources(void)
1029 {
1030 if (NULL != threads)
1031 {
1032 int i;
1033 #if !defined(_WINDOWS)
1034 sigset_t set;
1035
1036 /* ignore SIGCHLD signals in order for zbx_sleep() to work */
1037 sigemptyset(&set);
1038 sigaddset(&set, SIGCHLD);
1039 sigprocmask(SIG_BLOCK, &set, NULL);
1040 #else
1041 /* wait for threads to finish first. although listener threads will never end */
1042 WaitForMultipleObjectsEx(threads_num, threads, TRUE, 1000, FALSE);
1043 #endif
1044 for (i = 0; i < threads_num; i++)
1045 {
1046 if (threads[i])
1047 zbx_thread_kill(threads[i]);
1048 }
1049
1050 for (i = 0; i < threads_num; i++)
1051 {
1052 if (threads[i])
1053 zbx_thread_wait(threads[i]);
1054
1055 threads[i] = ZBX_THREAD_HANDLE_NULL;
1056 }
1057
1058 zbx_free(threads);
1059 }
1060
1061 free_metrics();
1062 alias_list_free();
1063 free_collector_data();
1064 #ifdef _WINDOWS
1065 free_perf_collector();
1066 zbx_co_uninitialize();
1067 #else
1068 unload_modules();
1069 #endif
1070 zabbix_log(LOG_LEVEL_INFORMATION, "Zabbix Agent stopped. Zabbix %s (revision %s).",
1071 ZABBIX_VERSION, ZABBIX_REVISION);
1072
1073 zabbix_close_log();
1074 }
1075
zbx_on_exit(void)1076 void zbx_on_exit(void)
1077 {
1078 zabbix_log(LOG_LEVEL_DEBUG, "zbx_on_exit() called");
1079
1080 zbx_free_service_resources();
1081
1082 #if defined(_WINDOWS) && (defined(HAVE_POLARSSL) || defined(HAVE_GNUTLS) || defined(HAVE_OPENSSL))
1083 zbx_tls_free();
1084 zbx_tls_library_deinit(); /* deinitialize crypto library from parent thread */
1085 #endif
1086 #if defined(PS_OVERWRITE_ARGV)
1087 setproctitle_free_env();
1088 #endif
1089
1090 exit(EXIT_SUCCESS);
1091 }
1092
main(int argc,char ** argv)1093 int main(int argc, char **argv)
1094 {
1095 ZBX_TASK_EX t = {ZBX_TASK_START};
1096 #ifdef _WINDOWS
1097 int ret;
1098
1099 /* Provide, so our process handles errors instead of the system itself. */
1100 /* Attention!!! */
1101 /* The system does not display the critical-error-handler message box. */
1102 /* Instead, the system sends the error to the calling process.*/
1103 SetErrorMode(SEM_FAILCRITICALERRORS);
1104 #endif
1105 #if defined(PS_OVERWRITE_ARGV) || defined(PS_PSTAT_ARGV)
1106 argv = setproctitle_save_env(argc, argv);
1107 #endif
1108 progname = get_program_name(argv[0]);
1109
1110 if (SUCCEED != parse_commandline(argc, argv, &t))
1111 exit(EXIT_FAILURE);
1112
1113 import_symbols();
1114
1115 /* this is needed to set default hostname in zbx_load_config() */
1116 init_metrics();
1117
1118 switch (t.task)
1119 {
1120 case ZBX_TASK_SHOW_USAGE:
1121 usage();
1122 exit(EXIT_FAILURE);
1123 break;
1124 #ifndef _WINDOWS
1125 case ZBX_TASK_RUNTIME_CONTROL:
1126 zbx_load_config(ZBX_CFG_FILE_REQUIRED, &t);
1127 exit(SUCCEED == zbx_sigusr_send(t.data) ? EXIT_SUCCESS : EXIT_FAILURE);
1128 break;
1129 #else
1130 case ZBX_TASK_INSTALL_SERVICE:
1131 case ZBX_TASK_UNINSTALL_SERVICE:
1132 case ZBX_TASK_START_SERVICE:
1133 case ZBX_TASK_STOP_SERVICE:
1134 if (t.flags & ZBX_TASK_FLAG_MULTIPLE_AGENTS)
1135 {
1136 zbx_load_config(ZBX_CFG_FILE_REQUIRED, &t);
1137
1138 zbx_snprintf(ZABBIX_SERVICE_NAME, sizeof(ZABBIX_SERVICE_NAME), "%s [%s]",
1139 APPLICATION_NAME, CONFIG_HOSTNAME);
1140 zbx_snprintf(ZABBIX_EVENT_SOURCE, sizeof(ZABBIX_EVENT_SOURCE), "%s [%s]",
1141 APPLICATION_NAME, CONFIG_HOSTNAME);
1142 }
1143 else
1144 zbx_load_config(ZBX_CFG_FILE_OPTIONAL, &t);
1145
1146 zbx_free_config();
1147
1148 ret = zbx_exec_service_task(argv[0], &t);
1149 free_metrics();
1150 exit(SUCCEED == ret ? EXIT_SUCCESS : EXIT_FAILURE);
1151 break;
1152 #endif
1153 case ZBX_TASK_TEST_METRIC:
1154 case ZBX_TASK_PRINT_SUPPORTED:
1155 zbx_load_config(ZBX_CFG_FILE_OPTIONAL, &t);
1156 #ifdef _WINDOWS
1157 init_perf_collector(0);
1158 load_perf_counters(CONFIG_PERF_COUNTERS);
1159 #else
1160 zbx_set_common_signal_handlers();
1161 #endif
1162 #ifndef _WINDOWS
1163 if (FAIL == load_modules(CONFIG_LOAD_MODULE_PATH, CONFIG_LOAD_MODULE, CONFIG_TIMEOUT, 0))
1164 {
1165 zabbix_log(LOG_LEVEL_CRIT, "loading modules failed, exiting...");
1166 exit(EXIT_FAILURE);
1167 }
1168 #endif
1169 load_user_parameters(CONFIG_USER_PARAMETERS);
1170 load_aliases(CONFIG_ALIASES);
1171 zbx_free_config();
1172 if (ZBX_TASK_TEST_METRIC == t.task)
1173 test_parameter(TEST_METRIC);
1174 else
1175 test_parameters();
1176 #ifdef _WINDOWS
1177 free_perf_collector(); /* cpu_collector must be freed before perf_collector is freed */
1178 #endif
1179 #ifndef _WINDOWS
1180 unload_modules();
1181 #endif
1182 free_metrics();
1183 alias_list_free();
1184 exit(EXIT_SUCCESS);
1185 break;
1186 case ZBX_TASK_SHOW_VERSION:
1187 version();
1188 #ifdef _AIX
1189 printf("\n");
1190 tl_version();
1191 #endif
1192 exit(EXIT_SUCCESS);
1193 break;
1194 case ZBX_TASK_SHOW_HELP:
1195 help();
1196 exit(EXIT_SUCCESS);
1197 break;
1198 default:
1199 zbx_load_config(ZBX_CFG_FILE_REQUIRED, &t);
1200 load_user_parameters(CONFIG_USER_PARAMETERS);
1201 load_aliases(CONFIG_ALIASES);
1202 break;
1203 }
1204
1205 START_MAIN_ZABBIX_ENTRY(CONFIG_ALLOW_ROOT, CONFIG_USER, t.flags);
1206
1207 exit(EXIT_SUCCESS);
1208 }
1209