1 /*****************************************************************************
2  *
3  * CONFIG.C - Configuration input and verification routines for Nagios
4  *
5  * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
6  * Last Modified: 12-14-2008
7  *
8  * License:
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  *****************************************************************************/
24 
25 #include "../include/config.h"
26 #include "../include/common.h"
27 #include "../include/objects.h"
28 #include "../include/macros.h"
29 #include "../include/nagios.h"
30 #include "../include/broker.h"
31 #include "../include/nebmods.h"
32 #include "../include/nebmodules.h"
33 
34 
35 extern char	*log_file;
36 extern char     *command_file;
37 extern char     *temp_file;
38 extern char     *temp_path;
39 extern char     *check_result_path;
40 extern char     *lock_file;
41 extern char	*log_archive_path;
42 extern char     *auth_file;
43 extern char	*p1_file;
44 
45 extern char     *nagios_user;
46 extern char     *nagios_group;
47 
48 extern char     *macro_user[MAX_USER_MACROS];
49 
50 extern char     *global_host_event_handler;
51 extern char     *global_service_event_handler;
52 extern command  *global_host_event_handler_ptr;
53 extern command  *global_service_event_handler_ptr;
54 
55 extern char     *ocsp_command;
56 extern char     *ochp_command;
57 extern command  *ocsp_command_ptr;
58 extern command  *ochp_command_ptr;
59 
60 extern char     *illegal_object_chars;
61 extern char     *illegal_output_chars;
62 
63 extern int      use_regexp_matches;
64 extern int      use_true_regexp_matching;
65 
66 extern int	use_syslog;
67 extern int      log_notifications;
68 extern int      log_service_retries;
69 extern int      log_host_retries;
70 extern int      log_event_handlers;
71 extern int      log_external_commands;
72 extern int      log_passive_checks;
73 
74 extern int      service_check_timeout;
75 extern int      service_check_timeout_state;
76 extern int      host_check_timeout;
77 extern int      event_handler_timeout;
78 extern int      notification_timeout;
79 extern int      ocsp_timeout;
80 extern int      ochp_timeout;
81 
82 extern int      log_initial_states;
83 
84 extern int      daemon_mode;
85 extern int      daemon_dumps_core;
86 
87 extern int      verify_config;
88 extern int      verify_object_relationships;
89 extern int      verify_circular_paths;
90 extern int      test_scheduling;
91 extern int      precache_objects;
92 extern int      use_precached_objects;
93 
94 extern double   sleep_time;
95 extern int      interval_length;
96 extern int      service_inter_check_delay_method;
97 extern int      host_inter_check_delay_method;
98 extern int      service_interleave_factor_method;
99 extern int      max_host_check_spread;
100 extern int      max_service_check_spread;
101 
102 extern sched_info scheduling_info;
103 
104 extern int      max_child_process_time;
105 
106 extern int      max_parallel_service_checks;
107 
108 extern int      command_check_interval;
109 extern int      check_reaper_interval;
110 extern int      max_check_reaper_time;
111 extern int      service_freshness_check_interval;
112 extern int      host_freshness_check_interval;
113 extern int      auto_rescheduling_interval;
114 extern int      auto_rescheduling_window;
115 
116 extern int      check_external_commands;
117 extern int      check_orphaned_services;
118 extern int      check_orphaned_hosts;
119 extern int      check_service_freshness;
120 extern int      check_host_freshness;
121 extern int      auto_reschedule_checks;
122 
123 extern int      additional_freshness_latency;
124 
125 extern int      check_for_updates;
126 extern int      bare_update_check;
127 
128 extern int      use_aggressive_host_checking;
129 extern unsigned long cached_host_check_horizon;
130 extern unsigned long cached_service_check_horizon;
131 extern int      enable_predictive_host_dependency_checks;
132 extern int      enable_predictive_service_dependency_checks;
133 
134 extern int      soft_state_dependencies;
135 
136 extern int      retain_state_information;
137 extern int      retention_update_interval;
138 extern int      use_retained_program_state;
139 extern int      use_retained_scheduling_info;
140 extern int      retention_scheduling_horizon;
141 extern unsigned long retained_host_attribute_mask;
142 extern unsigned long retained_service_attribute_mask;
143 extern unsigned long retained_contact_host_attribute_mask;
144 extern unsigned long retained_contact_service_attribute_mask;
145 extern unsigned long retained_process_host_attribute_mask;
146 extern unsigned long retained_process_service_attribute_mask;
147 
148 extern int      log_rotation_method;
149 
150 extern int      enable_notifications;
151 extern int      execute_service_checks;
152 extern int      accept_passive_service_checks;
153 extern int      execute_host_checks;
154 extern int      accept_passive_host_checks;
155 extern int      enable_event_handlers;
156 extern int      obsess_over_services;
157 extern int      obsess_over_hosts;
158 extern int      enable_failure_prediction;
159 
160 extern int      translate_passive_host_checks;
161 extern int      passive_host_checks_are_soft;
162 
163 extern int      aggregate_status_updates;
164 extern int      status_update_interval;
165 
166 extern int      time_change_threshold;
167 
168 extern unsigned long event_broker_options;
169 
170 extern int      process_performance_data;
171 
172 extern int      enable_flap_detection;
173 
174 extern double   low_service_flap_threshold;
175 extern double   high_service_flap_threshold;
176 extern double   low_host_flap_threshold;
177 extern double   high_host_flap_threshold;
178 
179 extern int      use_large_installation_tweaks;
180 extern int      enable_environment_macros;
181 extern int      free_child_process_memory;
182 extern int      child_processes_fork_twice;
183 
184 extern int      enable_embedded_perl;
185 extern int      use_embedded_perl_implicitly;
186 
187 extern int      date_format;
188 extern char     *use_timezone;
189 
190 extern contact		*contact_list;
191 extern contactgroup	*contactgroup_list;
192 extern host             *host_list;
193 extern hostgroup	*hostgroup_list;
194 extern service          *service_list;
195 extern servicegroup     *servicegroup_list;
196 extern notification     *notification_list;
197 extern command          *command_list;
198 extern timeperiod       *timeperiod_list;
199 extern serviceescalation *serviceescalation_list;
200 extern servicedependency *servicedependency_list;
201 extern hostdependency   *hostdependency_list;
202 extern hostescalation   *hostescalation_list;
203 
204 extern host		**host_hashlist;
205 extern service		**service_hashlist;
206 
207 extern int              external_command_buffer_slots;
208 
209 extern unsigned long    max_check_result_file_age;
210 
211 extern char             *debug_file;
212 extern int              debug_level;
213 extern int              debug_verbosity;
214 extern unsigned long    max_debug_file_size;
215 
216 extern int              allow_empty_hostgroup_assignment;
217 
218 
219 
220 /******************************************************************/
221 /************** CONFIGURATION INPUT FUNCTIONS *********************/
222 /******************************************************************/
223 
224 /* read all configuration data */
read_all_object_data(char * main_config_file)225 int read_all_object_data(char *main_config_file) {
226 	int result = OK;
227 	int options = 0;
228 	int cache = FALSE;
229 	int precache = FALSE;
230 
231 	options = READ_ALL_OBJECT_DATA;
232 
233 	/* cache object definitions if we're up and running */
234 	if(verify_config == FALSE && test_scheduling == FALSE)
235 		cache = TRUE;
236 
237 	/* precache object definitions */
238 	if(precache_objects == TRUE && (verify_config == TRUE || test_scheduling == TRUE))
239 		precache = TRUE;
240 
241 	/* read in all host configuration data from external sources */
242 	result = read_object_config_data(main_config_file, options, cache, precache);
243 	if(result != OK)
244 		return ERROR;
245 
246 	return OK;
247 	}
248 
249 
250 /* process the main configuration file */
read_main_config_file(char * main_config_file)251 int read_main_config_file(char *main_config_file) {
252 	char *input = NULL;
253 	char *variable = NULL;
254 	char *value = NULL;
255 	char *error_message = NULL;
256 	char *temp_ptr = NULL;
257 	mmapfile *thefile = NULL;
258 	int current_line = 0;
259 	int error = FALSE;
260 	int command_check_interval_is_seconds = FALSE;
261 	char *modptr = NULL;
262 	char *argptr = NULL;
263 	DIR *tmpdir = NULL;
264 	nagios_macros *mac;
265 
266 	mac = get_global_macros();
267 
268 
269 	/* open the config file for reading */
270 	if((thefile = mmap_fopen(main_config_file)) == NULL) {
271 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Cannot open main configuration file '%s' for reading!", main_config_file);
272 		return ERROR;
273 		}
274 
275 	/* save the main config file macro */
276 	my_free(mac->x[MACRO_MAINCONFIGFILE]);
277 	if((mac->x[MACRO_MAINCONFIGFILE] = (char *)strdup(main_config_file)))
278 		strip(mac->x[MACRO_MAINCONFIGFILE]);
279 
280 	/* process all lines in the config file */
281 	while(1) {
282 
283 		/* free memory */
284 		my_free(input);
285 		my_free(variable);
286 		my_free(value);
287 
288 		/* read the next line */
289 		if((input = mmap_fgets_multiline(thefile)) == NULL)
290 			break;
291 
292 		current_line = thefile->current_line;
293 
294 		strip(input);
295 
296 		/* skip blank lines and comments */
297 		if(input[0] == '\x0' || input[0] == '#')
298 			continue;
299 
300 		/* get the variable name */
301 		if((temp_ptr = my_strtok(input, "=")) == NULL) {
302 			asprintf(&error_message, "NULL variable");
303 			error = TRUE;
304 			break;
305 			}
306 		if((variable = (char *)strdup(temp_ptr)) == NULL) {
307 			asprintf(&error_message, "malloc() error");
308 			error = TRUE;
309 			break;
310 			}
311 
312 		/* get the value */
313 		if((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
314 			asprintf(&error_message, "NULL value");
315 			error = TRUE;
316 			break;
317 			}
318 		if((value = (char *)strdup(temp_ptr)) == NULL) {
319 			asprintf(&error_message, "malloc() error");
320 			error = TRUE;
321 			break;
322 			}
323 		strip(variable);
324 		strip(value);
325 
326 		/* process the variable/value */
327 
328 		if(!strcmp(variable, "resource_file")) {
329 
330 			/* save the macro */
331 			my_free(mac->x[MACRO_RESOURCEFILE]);
332 			mac->x[MACRO_RESOURCEFILE] = (char *)strdup(value);
333 
334 			/* process the resource file */
335 			read_resource_file(value);
336 			}
337 
338 		else if(!strcmp(variable, "log_file")) {
339 
340 			if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
341 				asprintf(&error_message, "Log file is too long");
342 				error = TRUE;
343 				break;
344 				}
345 
346 			my_free(log_file);
347 			log_file = (char *)strdup(value);
348 
349 			/* save the macro */
350 			my_free(mac->x[MACRO_LOGFILE]);
351 			mac->x[MACRO_LOGFILE] = (char *)strdup(log_file);
352 			}
353 
354 		else if(!strcmp(variable, "debug_level"))
355 			debug_level = atoi(value);
356 
357 		else if(!strcmp(variable, "debug_verbosity"))
358 			debug_verbosity = atoi(value);
359 
360 		else if(!strcmp(variable, "debug_file")) {
361 
362 			if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
363 				asprintf(&error_message, "Debug log file is too long");
364 				error = TRUE;
365 				break;
366 				}
367 
368 			my_free(debug_file);
369 			debug_file = (char *)strdup(value);
370 			}
371 
372 		else if(!strcmp(variable, "max_debug_file_size"))
373 			max_debug_file_size = strtoul(value, NULL, 0);
374 
375 		else if(!strcmp(variable, "command_file")) {
376 
377 			if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
378 				asprintf(&error_message, "Command file is too long");
379 				error = TRUE;
380 				break;
381 				}
382 
383 			my_free(command_file);
384 			command_file = (char *)strdup(value);
385 
386 			/* save the macro */
387 			my_free(mac->x[MACRO_COMMANDFILE]);
388 			mac->x[MACRO_COMMANDFILE] = (char *)strdup(value);
389 			}
390 
391 		else if(!strcmp(variable, "temp_file")) {
392 
393 			if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
394 				asprintf(&error_message, "Temp file is too long");
395 				error = TRUE;
396 				break;
397 				}
398 
399 			my_free(temp_file);
400 			temp_file = (char *)strdup(value);
401 
402 			/* save the macro */
403 			my_free(mac->x[MACRO_TEMPFILE]);
404 			mac->x[MACRO_TEMPFILE] = (char *)strdup(temp_file);
405 			}
406 
407 		else if(!strcmp(variable, "temp_path")) {
408 
409 			if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
410 				asprintf(&error_message, "Temp path is too long");
411 				error = TRUE;
412 				break;
413 				}
414 
415 			if((tmpdir = opendir((char *)value)) == NULL) {
416 				asprintf(&error_message, "Temp path is not a valid directory");
417 				error = TRUE;
418 				break;
419 				}
420 			closedir(tmpdir);
421 
422 			my_free(temp_path);
423 			if((temp_path = (char *)strdup(value))) {
424 				strip(temp_path);
425 				/* make sure we don't have a trailing slash */
426 				if(temp_path[strlen(temp_path) - 1] == '/')
427 					temp_path[strlen(temp_path) - 1] = '\x0';
428 				}
429 
430 			/* save the macro */
431 			my_free(mac->x[MACRO_TEMPPATH]);
432 			mac->x[MACRO_TEMPPATH] = (char *)strdup(temp_path);
433 			}
434 
435 		else if(!strcmp(variable, "check_result_path")) {
436 
437 			if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
438 				asprintf(&error_message, "Check result path is too long");
439 				error = TRUE;
440 				break;
441 				}
442 
443 			if((tmpdir = opendir((char *)value)) == NULL) {
444 				asprintf(&error_message, "Check result path is not a valid directory");
445 				error = TRUE;
446 				break;
447 				}
448 			closedir(tmpdir);
449 
450 			my_free(temp_path);
451 			if((temp_path = (char *)strdup(value))) {
452 				strip(temp_path);
453 				/* make sure we don't have a trailing slash */
454 				if(temp_path[strlen(temp_path) - 1] == '/')
455 					temp_path[strlen(temp_path) - 1] = '\x0';
456 				}
457 
458 			my_free(check_result_path);
459 			check_result_path = (char *)strdup(temp_path);
460 			}
461 
462 		else if(!strcmp(variable, "max_check_result_file_age"))
463 			max_check_result_file_age = strtoul(value, NULL, 0);
464 
465 		else if(!strcmp(variable, "lock_file")) {
466 
467 			if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
468 				asprintf(&error_message, "Lock file is too long");
469 				error = TRUE;
470 				break;
471 				}
472 
473 			my_free(lock_file);
474 			lock_file = (char *)strdup(value);
475 			}
476 
477 		else if(!strcmp(variable, "global_host_event_handler")) {
478 			my_free(global_host_event_handler);
479 			global_host_event_handler = (char *)strdup(value);
480 			}
481 
482 		else if(!strcmp(variable, "global_service_event_handler")) {
483 			my_free(global_service_event_handler);
484 			global_service_event_handler = (char *)strdup(value);
485 			}
486 
487 		else if(!strcmp(variable, "ocsp_command")) {
488 			my_free(ocsp_command);
489 			ocsp_command = (char *)strdup(value);
490 			}
491 
492 		else if(!strcmp(variable, "ochp_command")) {
493 			my_free(ochp_command);
494 			ochp_command = (char *)strdup(value);
495 			}
496 
497 		else if(!strcmp(variable, "nagios_user")) {
498 			my_free(nagios_user);
499 			nagios_user = (char *)strdup(value);
500 			}
501 
502 		else if(!strcmp(variable, "nagios_group")) {
503 			my_free(nagios_group);
504 			nagios_group = (char *)strdup(value);
505 			}
506 
507 		else if(!strcmp(variable, "admin_email")) {
508 
509 			/* save the macro */
510 			my_free(mac->x[MACRO_ADMINEMAIL]);
511 			mac->x[MACRO_ADMINEMAIL] = (char *)strdup(value);
512 			}
513 
514 		else if(!strcmp(variable, "admin_pager")) {
515 
516 			/* save the macro */
517 			my_free(mac->x[MACRO_ADMINPAGER]);
518 			mac->x[MACRO_ADMINPAGER] = (char *)strdup(value);
519 			}
520 
521 		else if(!strcmp(variable, "use_syslog")) {
522 
523 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
524 				asprintf(&error_message, "Illegal value for use_syslog");
525 				error = TRUE;
526 				break;
527 				}
528 
529 			use_syslog = (atoi(value) > 0) ? TRUE : FALSE;
530 			}
531 
532 		else if(!strcmp(variable, "log_notifications")) {
533 
534 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
535 				asprintf(&error_message, "Illegal value for log_notifications");
536 				error = TRUE;
537 				break;
538 				}
539 
540 			log_notifications = (atoi(value) > 0) ? TRUE : FALSE;
541 			}
542 
543 		else if(!strcmp(variable, "log_service_retries")) {
544 
545 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
546 				asprintf(&error_message, "Illegal value for log_service_retries");
547 				error = TRUE;
548 				break;
549 				}
550 
551 			log_service_retries = (atoi(value) > 0) ? TRUE : FALSE;
552 			}
553 
554 		else if(!strcmp(variable, "log_host_retries")) {
555 
556 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
557 				asprintf(&error_message, "Illegal value for log_host_retries");
558 				error = TRUE;
559 				break;
560 				}
561 
562 			log_host_retries = (atoi(value) > 0) ? TRUE : FALSE;
563 			}
564 
565 		else if(!strcmp(variable, "log_event_handlers")) {
566 
567 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
568 				asprintf(&error_message, "Illegal value for log_event_handlers");
569 				error = TRUE;
570 				break;
571 				}
572 
573 			log_event_handlers = (atoi(value) > 0) ? TRUE : FALSE;
574 			}
575 
576 		else if(!strcmp(variable, "log_external_commands")) {
577 
578 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
579 				asprintf(&error_message, "Illegal value for log_external_commands");
580 				error = TRUE;
581 				break;
582 				}
583 
584 			log_external_commands = (atoi(value) > 0) ? TRUE : FALSE;
585 			}
586 
587 		else if(!strcmp(variable, "log_passive_checks")) {
588 
589 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
590 				asprintf(&error_message, "Illegal value for log_passive_checks");
591 				error = TRUE;
592 				break;
593 				}
594 
595 			log_passive_checks = (atoi(value) > 0) ? TRUE : FALSE;
596 			}
597 
598 		else if(!strcmp(variable, "log_initial_states")) {
599 
600 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
601 				asprintf(&error_message, "Illegal value for log_initial_states");
602 				error = TRUE;
603 				break;
604 				}
605 
606 			log_initial_states = (atoi(value) > 0) ? TRUE : FALSE;
607 			}
608 
609 		else if(!strcmp(variable, "retain_state_information")) {
610 
611 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
612 				asprintf(&error_message, "Illegal value for retain_state_information");
613 				error = TRUE;
614 				break;
615 				}
616 
617 			retain_state_information = (atoi(value) > 0) ? TRUE : FALSE;
618 			}
619 
620 		else if(!strcmp(variable, "retention_update_interval")) {
621 
622 			retention_update_interval = atoi(value);
623 			if(retention_update_interval < 0) {
624 				asprintf(&error_message, "Illegal value for retention_update_interval");
625 				error = TRUE;
626 				break;
627 				}
628 			}
629 
630 		else if(!strcmp(variable, "use_retained_program_state")) {
631 
632 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
633 				asprintf(&error_message, "Illegal value for use_retained_program_state");
634 				error = TRUE;
635 				break;
636 				}
637 
638 			use_retained_program_state = (atoi(value) > 0) ? TRUE : FALSE;
639 			}
640 
641 		else if(!strcmp(variable, "use_retained_scheduling_info")) {
642 
643 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
644 				asprintf(&error_message, "Illegal value for use_retained_scheduling_info");
645 				error = TRUE;
646 				break;
647 				}
648 
649 			use_retained_scheduling_info = (atoi(value) > 0) ? TRUE : FALSE;
650 			}
651 
652 		else if(!strcmp(variable, "retention_scheduling_horizon")) {
653 
654 			retention_scheduling_horizon = atoi(value);
655 
656 			if(retention_scheduling_horizon <= 0) {
657 				asprintf(&error_message, "Illegal value for retention_scheduling_horizon");
658 				error = TRUE;
659 				break;
660 				}
661 			}
662 
663 		else if(!strcmp(variable, "additional_freshness_latency"))
664 			additional_freshness_latency = atoi(value);
665 
666 		else if(!strcmp(variable, "retained_host_attribute_mask"))
667 			retained_host_attribute_mask = strtoul(value, NULL, 0);
668 
669 		else if(!strcmp(variable, "retained_service_attribute_mask"))
670 			retained_service_attribute_mask = strtoul(value, NULL, 0);
671 
672 		else if(!strcmp(variable, "retained_process_host_attribute_mask"))
673 			retained_process_host_attribute_mask = strtoul(value, NULL, 0);
674 
675 		else if(!strcmp(variable, "retained_process_service_attribute_mask"))
676 			retained_process_service_attribute_mask = strtoul(value, NULL, 0);
677 
678 		else if(!strcmp(variable, "retained_contact_host_attribute_mask"))
679 			retained_contact_host_attribute_mask = strtoul(value, NULL, 0);
680 
681 		else if(!strcmp(variable, "retained_contact_service_attribute_mask"))
682 			retained_contact_service_attribute_mask = strtoul(value, NULL, 0);
683 
684 		else if(!strcmp(variable, "obsess_over_services")) {
685 
686 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
687 				asprintf(&error_message, "Illegal value for obsess_over_services");
688 				error = TRUE;
689 				break;
690 				}
691 
692 			obsess_over_services = (atoi(value) > 0) ? TRUE : FALSE;
693 			}
694 
695 		else if(!strcmp(variable, "obsess_over_hosts")) {
696 
697 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
698 				asprintf(&error_message, "Illegal value for obsess_over_hosts");
699 				error = TRUE;
700 				break;
701 				}
702 
703 			obsess_over_hosts = (atoi(value) > 0) ? TRUE : FALSE;
704 			}
705 
706 		else if(!strcmp(variable, "translate_passive_host_checks")) {
707 
708 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
709 				asprintf(&error_message, "Illegal value for translate_passive_host_checks");
710 				error = TRUE;
711 				break;
712 				}
713 
714 			translate_passive_host_checks = (atoi(value) > 0) ? TRUE : FALSE;
715 			}
716 
717 		else if(!strcmp(variable, "passive_host_checks_are_soft"))
718 			passive_host_checks_are_soft = (atoi(value) > 0) ? TRUE : FALSE;
719 
720 		else if(!strcmp(variable, "service_check_timeout")) {
721 
722 			service_check_timeout = atoi(value);
723 
724 			if(service_check_timeout <= 0) {
725 				asprintf(&error_message, "Illegal value for service_check_timeout");
726 				error = TRUE;
727 				break;
728 				}
729 			}
730 
731 
732 		else if(!strcmp(variable, "service_check_timeout_state")) {
733 
734 			if(!strcmp(value, "o"))
735 				service_check_timeout_state = STATE_OK;
736 			else if(!strcmp(value, "w"))
737 				service_check_timeout_state = STATE_WARNING;
738 			else if(!strcmp(value, "c"))
739 				service_check_timeout_state = STATE_CRITICAL;
740 			else if(!strcmp(value, "u"))
741 				service_check_timeout_state = STATE_UNKNOWN;
742 			else {
743 				asprintf(&error_message, "Illegal value for service_check_timeout_state");
744 				error = TRUE;
745 				break;
746 				}
747 			}
748 
749 		else if(!strcmp(variable, "host_check_timeout")) {
750 
751 			host_check_timeout = atoi(value);
752 
753 			if(host_check_timeout <= 0) {
754 				asprintf(&error_message, "Illegal value for host_check_timeout");
755 				error = TRUE;
756 				break;
757 				}
758 			}
759 
760 		else if(!strcmp(variable, "event_handler_timeout")) {
761 
762 			event_handler_timeout = atoi(value);
763 
764 			if(event_handler_timeout <= 0) {
765 				asprintf(&error_message, "Illegal value for event_handler_timeout");
766 				error = TRUE;
767 				break;
768 				}
769 			}
770 
771 		else if(!strcmp(variable, "notification_timeout")) {
772 
773 			notification_timeout = atoi(value);
774 
775 			if(notification_timeout <= 0) {
776 				asprintf(&error_message, "Illegal value for notification_timeout");
777 				error = TRUE;
778 				break;
779 				}
780 			}
781 
782 		else if(!strcmp(variable, "ocsp_timeout")) {
783 
784 			ocsp_timeout = atoi(value);
785 
786 			if(ocsp_timeout <= 0) {
787 				asprintf(&error_message, "Illegal value for ocsp_timeout");
788 				error = TRUE;
789 				break;
790 				}
791 			}
792 
793 		else if(!strcmp(variable, "ochp_timeout")) {
794 
795 			ochp_timeout = atoi(value);
796 
797 			if(ochp_timeout <= 0) {
798 				asprintf(&error_message, "Illegal value for ochp_timeout");
799 				error = TRUE;
800 				break;
801 				}
802 			}
803 
804 		else if(!strcmp(variable, "use_agressive_host_checking") || !strcmp(variable, "use_aggressive_host_checking")) {
805 
806 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
807 				asprintf(&error_message, "Illegal value for use_aggressive_host_checking");
808 				error = TRUE;
809 				break;
810 				}
811 
812 			use_aggressive_host_checking = (atoi(value) > 0) ? TRUE : FALSE;
813 			}
814 
815 		else if(!strcmp(variable, "cached_host_check_horizon"))
816 			cached_host_check_horizon = strtoul(value, NULL, 0);
817 
818 		else if(!strcmp(variable, "enable_predictive_host_dependency_checks"))
819 			enable_predictive_host_dependency_checks = (atoi(value) > 0) ? TRUE : FALSE;
820 
821 		else if(!strcmp(variable, "cached_service_check_horizon"))
822 			cached_service_check_horizon = strtoul(value, NULL, 0);
823 
824 		else if(!strcmp(variable, "enable_predictive_service_dependency_checks"))
825 			enable_predictive_service_dependency_checks = (atoi(value) > 0) ? TRUE : FALSE;
826 
827 		else if(!strcmp(variable, "soft_state_dependencies")) {
828 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
829 				asprintf(&error_message, "Illegal value for soft_state_dependencies");
830 				error = TRUE;
831 				break;
832 				}
833 
834 			soft_state_dependencies = (atoi(value) > 0) ? TRUE : FALSE;
835 			}
836 
837 		else if(!strcmp(variable, "log_rotation_method")) {
838 			if(!strcmp(value, "n"))
839 				log_rotation_method = LOG_ROTATION_NONE;
840 			else if(!strcmp(value, "h"))
841 				log_rotation_method = LOG_ROTATION_HOURLY;
842 			else if(!strcmp(value, "d"))
843 				log_rotation_method = LOG_ROTATION_DAILY;
844 			else if(!strcmp(value, "w"))
845 				log_rotation_method = LOG_ROTATION_WEEKLY;
846 			else if(!strcmp(value, "m"))
847 				log_rotation_method = LOG_ROTATION_MONTHLY;
848 			else {
849 				asprintf(&error_message, "Illegal value for log_rotation_method");
850 				error = TRUE;
851 				break;
852 				}
853 			}
854 
855 		else if(!strcmp(variable, "log_archive_path")) {
856 
857 			if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
858 				asprintf(&error_message, "Log archive path too long");
859 				error = TRUE;
860 				break;
861 				}
862 
863 			my_free(log_archive_path);
864 			log_archive_path = (char *)strdup(value);
865 			}
866 
867 		else if(!strcmp(variable, "enable_event_handlers"))
868 			enable_event_handlers = (atoi(value) > 0) ? TRUE : FALSE;
869 
870 		else if(!strcmp(variable, "enable_notifications"))
871 			enable_notifications = (atoi(value) > 0) ? TRUE : FALSE;
872 
873 		else if(!strcmp(variable, "execute_service_checks"))
874 			execute_service_checks = (atoi(value) > 0) ? TRUE : FALSE;
875 
876 		else if(!strcmp(variable, "accept_passive_service_checks"))
877 			accept_passive_service_checks = (atoi(value) > 0) ? TRUE : FALSE;
878 
879 		else if(!strcmp(variable, "execute_host_checks"))
880 			execute_host_checks = (atoi(value) > 0) ? TRUE : FALSE;
881 
882 		else if(!strcmp(variable, "accept_passive_host_checks"))
883 			accept_passive_host_checks = (atoi(value) > 0) ? TRUE : FALSE;
884 
885 		else if(!strcmp(variable, "service_inter_check_delay_method")) {
886 			if(!strcmp(value, "n"))
887 				service_inter_check_delay_method = ICD_NONE;
888 			else if(!strcmp(value, "d"))
889 				service_inter_check_delay_method = ICD_DUMB;
890 			else if(!strcmp(value, "s"))
891 				service_inter_check_delay_method = ICD_SMART;
892 			else {
893 				service_inter_check_delay_method = ICD_USER;
894 				scheduling_info.service_inter_check_delay = strtod(value, NULL);
895 				if(scheduling_info.service_inter_check_delay <= 0.0) {
896 					asprintf(&error_message, "Illegal value for service_inter_check_delay_method");
897 					error = TRUE;
898 					break;
899 					}
900 				}
901 			}
902 
903 		else if(!strcmp(variable, "max_service_check_spread")) {
904 			strip(value);
905 			max_service_check_spread = atoi(value);
906 			if(max_service_check_spread < 1) {
907 				asprintf(&error_message, "Illegal value for max_service_check_spread");
908 				error = TRUE;
909 				break;
910 				}
911 			}
912 
913 		else if(!strcmp(variable, "host_inter_check_delay_method")) {
914 
915 			if(!strcmp(value, "n"))
916 				host_inter_check_delay_method = ICD_NONE;
917 			else if(!strcmp(value, "d"))
918 				host_inter_check_delay_method = ICD_DUMB;
919 			else if(!strcmp(value, "s"))
920 				host_inter_check_delay_method = ICD_SMART;
921 			else {
922 				host_inter_check_delay_method = ICD_USER;
923 				scheduling_info.host_inter_check_delay = strtod(value, NULL);
924 				if(scheduling_info.host_inter_check_delay <= 0.0) {
925 					asprintf(&error_message, "Illegal value for host_inter_check_delay_method");
926 					error = TRUE;
927 					break;
928 					}
929 				}
930 			}
931 
932 		else if(!strcmp(variable, "max_host_check_spread")) {
933 
934 			max_host_check_spread = atoi(value);
935 			if(max_host_check_spread < 1) {
936 				asprintf(&error_message, "Illegal value for max_host_check_spread");
937 				error = TRUE;
938 				break;
939 				}
940 			}
941 
942 		else if(!strcmp(variable, "service_interleave_factor")) {
943 			if(!strcmp(value, "s"))
944 				service_interleave_factor_method = ILF_SMART;
945 			else {
946 				service_interleave_factor_method = ILF_USER;
947 				scheduling_info.service_interleave_factor = atoi(value);
948 				if(scheduling_info.service_interleave_factor < 1)
949 					scheduling_info.service_interleave_factor = 1;
950 				}
951 			}
952 
953 		else if(!strcmp(variable, "max_concurrent_checks")) {
954 
955 			max_parallel_service_checks = atoi(value);
956 			if(max_parallel_service_checks < 0) {
957 				asprintf(&error_message, "Illegal value for max_concurrent_checks");
958 				error = TRUE;
959 				break;
960 				}
961 			}
962 
963 		else if(!strcmp(variable, "check_result_reaper_frequency") || !strcmp(variable, "service_reaper_frequency")) {
964 
965 			check_reaper_interval = atoi(value);
966 			if(check_reaper_interval < 1) {
967 				asprintf(&error_message, "Illegal value for check_result_reaper_frequency");
968 				error = TRUE;
969 				break;
970 				}
971 			}
972 
973 		else if(!strcmp(variable, "max_check_result_reaper_time")) {
974 
975 			max_check_reaper_time = atoi(value);
976 			if(max_check_reaper_time < 1) {
977 				asprintf(&error_message, "Illegal value for max_check_result_reaper_time");
978 				error = TRUE;
979 				break;
980 				}
981 			}
982 
983 		else if(!strcmp(variable, "sleep_time")) {
984 
985 			sleep_time = atof(value);
986 			if(sleep_time <= 0.0) {
987 				asprintf(&error_message, "Illegal value for sleep_time");
988 				error = TRUE;
989 				break;
990 				}
991 			}
992 
993 		else if(!strcmp(variable, "interval_length")) {
994 
995 			interval_length = atoi(value);
996 			if(interval_length < 1) {
997 				asprintf(&error_message, "Illegal value for interval_length");
998 				error = TRUE;
999 				break;
1000 				}
1001 			}
1002 
1003 		else if(!strcmp(variable, "check_external_commands")) {
1004 
1005 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
1006 				asprintf(&error_message, "Illegal value for check_external_commands");
1007 				error = TRUE;
1008 				break;
1009 				}
1010 
1011 			check_external_commands = (atoi(value) > 0) ? TRUE : FALSE;
1012 			}
1013 
1014 		else if(!strcmp(variable, "command_check_interval")) {
1015 
1016 			command_check_interval_is_seconds = (strstr(value, "s")) ? TRUE : FALSE;
1017 			command_check_interval = atoi(value);
1018 			if(command_check_interval < -1 || command_check_interval == 0) {
1019 				asprintf(&error_message, "Illegal value for command_check_interval");
1020 				error = TRUE;
1021 				break;
1022 				}
1023 			}
1024 
1025 		else if(!strcmp(variable, "check_for_orphaned_services")) {
1026 
1027 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
1028 				asprintf(&error_message, "Illegal value for check_for_orphaned_services");
1029 				error = TRUE;
1030 				break;
1031 				}
1032 
1033 			check_orphaned_services = (atoi(value) > 0) ? TRUE : FALSE;
1034 			}
1035 
1036 		else if(!strcmp(variable, "check_for_orphaned_hosts")) {
1037 
1038 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
1039 				asprintf(&error_message, "Illegal value for check_for_orphaned_hosts");
1040 				error = TRUE;
1041 				break;
1042 				}
1043 
1044 			check_orphaned_hosts = (atoi(value) > 0) ? TRUE : FALSE;
1045 			}
1046 
1047 		else if(!strcmp(variable, "check_service_freshness")) {
1048 
1049 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
1050 				asprintf(&error_message, "Illegal value for check_service_freshness");
1051 				error = TRUE;
1052 				break;
1053 				}
1054 
1055 			check_service_freshness = (atoi(value) > 0) ? TRUE : FALSE;
1056 			}
1057 
1058 		else if(!strcmp(variable, "check_host_freshness")) {
1059 
1060 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
1061 				asprintf(&error_message, "Illegal value for check_host_freshness");
1062 				error = TRUE;
1063 				break;
1064 				}
1065 
1066 			check_host_freshness = (atoi(value) > 0) ? TRUE : FALSE;
1067 			}
1068 
1069 		else if(!strcmp(variable, "service_freshness_check_interval") || !strcmp(variable, "freshness_check_interval")) {
1070 
1071 			service_freshness_check_interval = atoi(value);
1072 			if(service_freshness_check_interval <= 0) {
1073 				asprintf(&error_message, "Illegal value for service_freshness_check_interval");
1074 				error = TRUE;
1075 				break;
1076 				}
1077 			}
1078 
1079 		else if(!strcmp(variable, "host_freshness_check_interval")) {
1080 
1081 			host_freshness_check_interval = atoi(value);
1082 			if(host_freshness_check_interval <= 0) {
1083 				asprintf(&error_message, "Illegal value for host_freshness_check_interval");
1084 				error = TRUE;
1085 				break;
1086 				}
1087 			}
1088 		else if(!strcmp(variable, "auto_reschedule_checks")) {
1089 
1090 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
1091 				asprintf(&error_message, "Illegal value for auto_reschedule_checks");
1092 				error = TRUE;
1093 				break;
1094 				}
1095 
1096 			auto_reschedule_checks = (atoi(value) > 0) ? TRUE : FALSE;
1097 			}
1098 
1099 		else if(!strcmp(variable, "auto_rescheduling_interval")) {
1100 
1101 			auto_rescheduling_interval = atoi(value);
1102 			if(auto_rescheduling_interval <= 0) {
1103 				asprintf(&error_message, "Illegal value for auto_rescheduling_interval");
1104 				error = TRUE;
1105 				break;
1106 				}
1107 			}
1108 
1109 		else if(!strcmp(variable, "auto_rescheduling_window")) {
1110 
1111 			auto_rescheduling_window = atoi(value);
1112 			if(auto_rescheduling_window <= 0) {
1113 				asprintf(&error_message, "Illegal value for auto_rescheduling_window");
1114 				error = TRUE;
1115 				break;
1116 				}
1117 			}
1118 
1119 		else if(!strcmp(variable, "aggregate_status_updates")) {
1120 
1121 			/* DEPRECATED - ALL UPDATED ARE AGGREGATED AS OF NAGIOS 3.X */
1122 			/*aggregate_status_updates=(atoi(value)>0)?TRUE:FALSE;*/
1123 
1124 			logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: aggregate_status_updates directive ignored.  All status file updates are now aggregated.");
1125 			}
1126 
1127 		else if(!strcmp(variable, "status_update_interval")) {
1128 
1129 			status_update_interval = atoi(value);
1130 			if(status_update_interval <= 1) {
1131 				asprintf(&error_message, "Illegal value for status_update_interval");
1132 				error = TRUE;
1133 				break;
1134 				}
1135 			}
1136 
1137 		else if(!strcmp(variable, "time_change_threshold")) {
1138 
1139 			time_change_threshold = atoi(value);
1140 
1141 			if(time_change_threshold <= 5) {
1142 				asprintf(&error_message, "Illegal value for time_change_threshold");
1143 				error = TRUE;
1144 				break;
1145 				}
1146 			}
1147 
1148 		else if(!strcmp(variable, "process_performance_data"))
1149 			process_performance_data = (atoi(value) > 0) ? TRUE : FALSE;
1150 
1151 		else if(!strcmp(variable, "enable_flap_detection"))
1152 			enable_flap_detection = (atoi(value) > 0) ? TRUE : FALSE;
1153 
1154 		else if(!strcmp(variable, "enable_failure_prediction"))
1155 			enable_failure_prediction = (atoi(value) > 0) ? TRUE : FALSE;
1156 
1157 		else if(!strcmp(variable, "low_service_flap_threshold")) {
1158 
1159 			low_service_flap_threshold = strtod(value, NULL);
1160 			if(low_service_flap_threshold <= 0.0 || low_service_flap_threshold >= 100.0) {
1161 				asprintf(&error_message, "Illegal value for low_service_flap_threshold");
1162 				error = TRUE;
1163 				break;
1164 				}
1165 			}
1166 
1167 		else if(!strcmp(variable, "high_service_flap_threshold")) {
1168 
1169 			high_service_flap_threshold = strtod(value, NULL);
1170 			if(high_service_flap_threshold <= 0.0 ||  high_service_flap_threshold > 100.0) {
1171 				asprintf(&error_message, "Illegal value for high_service_flap_threshold");
1172 				error = TRUE;
1173 				break;
1174 				}
1175 			}
1176 
1177 		else if(!strcmp(variable, "low_host_flap_threshold")) {
1178 
1179 			low_host_flap_threshold = strtod(value, NULL);
1180 			if(low_host_flap_threshold <= 0.0 || low_host_flap_threshold >= 100.0) {
1181 				asprintf(&error_message, "Illegal value for low_host_flap_threshold");
1182 				error = TRUE;
1183 				break;
1184 				}
1185 			}
1186 
1187 		else if(!strcmp(variable, "high_host_flap_threshold")) {
1188 
1189 			high_host_flap_threshold = strtod(value, NULL);
1190 			if(high_host_flap_threshold <= 0.0 || high_host_flap_threshold > 100.0) {
1191 				asprintf(&error_message, "Illegal value for high_host_flap_threshold");
1192 				error = TRUE;
1193 				break;
1194 				}
1195 			}
1196 
1197 		else if(!strcmp(variable, "date_format")) {
1198 
1199 			if(!strcmp(value, "euro"))
1200 				date_format = DATE_FORMAT_EURO;
1201 			else if(!strcmp(value, "iso8601"))
1202 				date_format = DATE_FORMAT_ISO8601;
1203 			else if(!strcmp(value, "strict-iso8601"))
1204 				date_format = DATE_FORMAT_STRICT_ISO8601;
1205 			else
1206 				date_format = DATE_FORMAT_US;
1207 			}
1208 
1209 		else if(!strcmp(variable, "use_timezone")) {
1210 			my_free(use_timezone);
1211 			use_timezone = (char *)strdup(value);
1212 			}
1213 
1214 		else if(!strcmp(variable, "p1_file")) {
1215 
1216 			if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
1217 				asprintf(&error_message, "P1 file is too long");
1218 				error = TRUE;
1219 				break;
1220 				}
1221 
1222 			my_free(p1_file);
1223 			p1_file = (char *)strdup(value);
1224 			}
1225 
1226 		else if(!strcmp(variable, "event_broker_options")) {
1227 
1228 			if(!strcmp(value, "-1"))
1229 				event_broker_options = BROKER_EVERYTHING;
1230 			else
1231 				event_broker_options = strtoul(value, NULL, 0);
1232 			}
1233 
1234 		else if(!strcmp(variable, "illegal_object_name_chars"))
1235 			illegal_object_chars = (char *)strdup(value);
1236 
1237 		else if(!strcmp(variable, "illegal_macro_output_chars"))
1238 			illegal_output_chars = (char *)strdup(value);
1239 
1240 
1241 		else if(!strcmp(variable, "broker_module")) {
1242 			modptr = strtok(value, " \n");
1243 			argptr = strtok(NULL, "\n");
1244 #ifdef USE_EVENT_BROKER
1245 			neb_add_module(modptr, argptr, TRUE);
1246 #endif
1247 			}
1248 
1249 		else if(!strcmp(variable, "use_regexp_matching"))
1250 			use_regexp_matches = (atoi(value) > 0) ? TRUE : FALSE;
1251 
1252 		else if(!strcmp(variable, "use_true_regexp_matching"))
1253 			use_true_regexp_matching = (atoi(value) > 0) ? TRUE : FALSE;
1254 
1255 		else if(!strcmp(variable, "daemon_dumps_core")) {
1256 
1257 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
1258 				asprintf(&error_message, "Illegal value for daemon_dumps_core");
1259 				error = TRUE;
1260 				break;
1261 				}
1262 
1263 			daemon_dumps_core = (atoi(value) > 0) ? TRUE : FALSE;
1264 			}
1265 
1266 		else if(!strcmp(variable, "use_large_installation_tweaks")) {
1267 
1268 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
1269 				asprintf(&error_message, "Illegal value for use_large_installation_tweaks ");
1270 				error = TRUE;
1271 				break;
1272 				}
1273 
1274 			use_large_installation_tweaks = (atoi(value) > 0) ? TRUE : FALSE;
1275 			}
1276 
1277 		else if(!strcmp(variable, "enable_environment_macros"))
1278 			enable_environment_macros = (atoi(value) > 0) ? TRUE : FALSE;
1279 
1280 		else if(!strcmp(variable, "free_child_process_memory"))
1281 			free_child_process_memory = (atoi(value) > 0) ? TRUE : FALSE;
1282 
1283 		else if(!strcmp(variable, "child_processes_fork_twice"))
1284 			child_processes_fork_twice = (atoi(value) > 0) ? TRUE : FALSE;
1285 
1286 		else if(!strcmp(variable, "enable_embedded_perl")) {
1287 
1288 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
1289 				asprintf(&error_message, "Illegal value for enable_embedded_perl");
1290 				error = TRUE;
1291 				break;
1292 				}
1293 
1294 			enable_embedded_perl = (atoi(value) > 0) ? TRUE : FALSE;
1295 			}
1296 
1297 		else if(!strcmp(variable, "use_embedded_perl_implicitly")) {
1298 
1299 			if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
1300 				asprintf(&error_message, "Illegal value for use_embedded_perl_implicitly");
1301 				error = TRUE;
1302 				break;
1303 				}
1304 
1305 			use_embedded_perl_implicitly = (atoi(value) > 0) ? TRUE : FALSE;
1306 			}
1307 
1308 		else if(!strcmp(variable, "external_command_buffer_slots"))
1309 			external_command_buffer_slots = atoi(value);
1310 
1311 		else if(!strcmp(variable, "check_for_updates"))
1312 			check_for_updates = (atoi(value) > 0) ? TRUE : FALSE;
1313 
1314 		else if(!strcmp(variable, "bare_update_check"))
1315 			bare_update_check = (atoi(value) > 0) ? TRUE : FALSE;
1316 
1317 		/*** AUTH_FILE VARIABLE USED BY EMBEDDED PERL INTERPRETER ***/
1318 		else if(!strcmp(variable, "auth_file")) {
1319 
1320 			if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
1321 				asprintf(&error_message, "Auth file is too long");
1322 				error = TRUE;
1323 				break;
1324 				}
1325 
1326 			my_free(auth_file);
1327 			auth_file = (char *)strdup(value);
1328 			}
1329 
1330 		/* warn about old variables */
1331 		else if(!strcmp(variable, "comment_file") || !strcmp(variable, "xcddefault_comment_file")) {
1332 			logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: comment_file variable ignored.  Comments are now stored in the status and retention files.");
1333 			}
1334 		else if(!strcmp(variable, "downtime_file") || !strcmp(variable, "xdddefault_downtime_file")) {
1335 			logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: downtime_file variable ignored.  Downtime entries are now stored in the status and retention files.");
1336 			}
1337 
1338 		/* skip external data directives */
1339 		else if(strstr(input, "x") == input)
1340 			continue;
1341 
1342 		/* ignore external variables */
1343 		else if(!strcmp(variable, "status_file"))
1344 			continue;
1345 		else if(!strcmp(variable, "perfdata_timeout"))
1346 			continue;
1347 		else if(strstr(variable, "host_perfdata") == variable)
1348 			continue;
1349 		else if(strstr(variable, "service_perfdata") == variable)
1350 			continue;
1351 		else if(strstr(input, "cfg_file=") == input || strstr(input, "cfg_dir=") == input)
1352 			continue;
1353 		else if(strstr(input, "state_retention_file=") == input)
1354 			continue;
1355 		else if(strstr(input, "object_cache_file=") == input)
1356 			continue;
1357 		else if(strstr(input, "precached_object_file=") == input)
1358 			continue;
1359 		else if(!strcmp(variable, "allow_empty_hostgroup_assignment")) {
1360 			allow_empty_hostgroup_assignment = (atoi(value) > 0) ? TRUE : FALSE;
1361 			}
1362 
1363 		/* we don't know what this variable is... */
1364 		else {
1365 			asprintf(&error_message, "UNKNOWN VARIABLE");
1366 			error = TRUE;
1367 			break;
1368 			}
1369 
1370 		}
1371 
1372 	/* adjust timezone values */
1373 	if(use_timezone != NULL)
1374 		set_environment_var("TZ", use_timezone, 1);
1375 	tzset();
1376 
1377 	/* adjust command check interval */
1378 	if(command_check_interval_is_seconds == FALSE && command_check_interval != -1)
1379 		command_check_interval *= interval_length;
1380 
1381 	/* adjust tweaks */
1382 	if(free_child_process_memory == -1)
1383 		free_child_process_memory = (use_large_installation_tweaks == TRUE) ? FALSE : TRUE;
1384 	if(child_processes_fork_twice == -1)
1385 		child_processes_fork_twice = (use_large_installation_tweaks == TRUE) ? FALSE : TRUE;
1386 
1387 
1388 	/* handle errors */
1389 	if(error == TRUE) {
1390 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error in configuration file '%s' - Line %d (%s)", main_config_file, current_line, (error_message == NULL) ? "NULL" : error_message);
1391 		return ERROR;
1392 		}
1393 
1394 	/* free leftover memory and close the file */
1395 	my_free(input);
1396 	mmap_fclose(thefile);
1397 
1398 	/* free memory */
1399 	my_free(error_message);
1400 	my_free(input);
1401 	my_free(variable);
1402 	my_free(value);
1403 
1404 	/* make sure a log file has been specified */
1405 	strip(log_file);
1406 	if(!strcmp(log_file, "")) {
1407 		if(daemon_mode == FALSE)
1408 			printf("Error: Log file is not specified anywhere in main config file '%s'!\n", main_config_file);
1409 		return ERROR;
1410 		}
1411 
1412 	return OK;
1413 	}
1414 
1415 
1416 
1417 /* processes macros in resource file */
read_resource_file(char * resource_file)1418 int read_resource_file(char *resource_file) {
1419 	char *input = NULL;
1420 	char *variable = NULL;
1421 	char *value = NULL;
1422 	char *temp_ptr = NULL;
1423 	mmapfile *thefile = NULL;
1424 	int current_line = 1;
1425 	int error = FALSE;
1426 	int user_index = 0;
1427 
1428 	if((thefile = mmap_fopen(resource_file)) == NULL) {
1429 		logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Cannot open resource file '%s' for reading!", resource_file);
1430 		return ERROR;
1431 		}
1432 
1433 	/* process all lines in the resource file */
1434 	while(1) {
1435 
1436 		/* free memory */
1437 		my_free(input);
1438 		my_free(variable);
1439 		my_free(value);
1440 
1441 		/* read the next line */
1442 		if((input = mmap_fgets_multiline(thefile)) == NULL)
1443 			break;
1444 
1445 		current_line = thefile->current_line;
1446 
1447 		/* skip blank lines and comments */
1448 		if(input[0] == '#' || input[0] == '\x0' || input[0] == '\n' || input[0] == '\r')
1449 			continue;
1450 
1451 		strip(input);
1452 
1453 		/* get the variable name */
1454 		if((temp_ptr = my_strtok(input, "=")) == NULL) {
1455 			logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable - Line %d of resource file '%s'", current_line, resource_file);
1456 			error = TRUE;
1457 			break;
1458 			}
1459 		if((variable = (char *)strdup(temp_ptr)) == NULL) {
1460 			error = TRUE;
1461 			break;
1462 			}
1463 
1464 		/* get the value */
1465 		if((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
1466 			logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable value - Line %d of resource file '%s'", current_line, resource_file);
1467 			error = TRUE;
1468 			break;
1469 			}
1470 		if((value = (char *)strdup(temp_ptr)) == NULL) {
1471 			error = TRUE;
1472 			break;
1473 			}
1474 
1475 		/* what should we do with the variable/value pair? */
1476 
1477 		/* check for macro declarations */
1478 		if(variable[0] == '$' && variable[strlen(variable) - 1] == '$') {
1479 
1480 			/* $USERx$ macro declarations */
1481 			if(strstr(variable, "$USER") == variable  && strlen(variable) > 5) {
1482 				user_index = atoi(variable + 5) - 1;
1483 				if(user_index >= 0 && user_index < MAX_USER_MACROS) {
1484 					my_free(macro_user[user_index]);
1485 					macro_user[user_index] = (char *)strdup(value);
1486 					}
1487 				}
1488 			}
1489 		}
1490 
1491 	/* free leftover memory and close the file */
1492 	my_free(input);
1493 	mmap_fclose(thefile);
1494 
1495 	/* free memory */
1496 	my_free(variable);
1497 	my_free(value);
1498 
1499 	if(error == TRUE)
1500 		return ERROR;
1501 
1502 	return OK;
1503 	}
1504 
1505 
1506 
1507 
1508 
1509 
1510 /****************************************************************/
1511 /**************** CONFIG VERIFICATION FUNCTIONS *****************/
1512 /****************************************************************/
1513 
1514 /* do a pre-flight check to make sure object relationships, etc. make sense */
pre_flight_check(void)1515 int pre_flight_check(void) {
1516 	host *temp_host = NULL;
1517 	char *buf = NULL;
1518 	service *temp_service = NULL;
1519 	command *temp_command = NULL;
1520 	char *temp_command_name = "";
1521 	int warnings = 0;
1522 	int errors = 0;
1523 	struct timeval tv[4];
1524 	double runtime[4];
1525 	int temp_path_fd = -1;
1526 
1527 
1528 	if(test_scheduling == TRUE)
1529 		gettimeofday(&tv[0], NULL);
1530 
1531 	/********************************************/
1532 	/* check object relationships               */
1533 	/********************************************/
1534 	pre_flight_object_check(&warnings, &errors);
1535 	if(test_scheduling == TRUE)
1536 		gettimeofday(&tv[1], NULL);
1537 
1538 
1539 	/********************************************/
1540 	/* check for circular paths between hosts   */
1541 	/********************************************/
1542 	pre_flight_circular_check(&warnings, &errors);
1543 	if(test_scheduling == TRUE)
1544 		gettimeofday(&tv[2], NULL);
1545 
1546 
1547 	/********************************************/
1548 	/* check global event handler commands...   */
1549 	/********************************************/
1550 	if(verify_config == TRUE)
1551 		printf("Checking global event handlers...\n");
1552 	if(global_host_event_handler != NULL) {
1553 
1554 		/* check the event handler command */
1555 		buf = (char *)strdup(global_host_event_handler);
1556 
1557 		/* get the command name, leave any arguments behind */
1558 		temp_command_name = my_strtok(buf, "!");
1559 
1560 		temp_command = find_command(temp_command_name);
1561 		if(temp_command == NULL) {
1562 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Global host event handler command '%s' is not defined anywhere!", temp_command_name);
1563 			errors++;
1564 			}
1565 
1566 		/* save the pointer to the command for later */
1567 		global_host_event_handler_ptr = temp_command;
1568 
1569 		my_free(buf);
1570 		}
1571 	if(global_service_event_handler != NULL) {
1572 
1573 		/* check the event handler command */
1574 		buf = (char *)strdup(global_service_event_handler);
1575 
1576 		/* get the command name, leave any arguments behind */
1577 		temp_command_name = my_strtok(buf, "!");
1578 
1579 		temp_command = find_command(temp_command_name);
1580 		if(temp_command == NULL) {
1581 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Global service event handler command '%s' is not defined anywhere!", temp_command_name);
1582 			errors++;
1583 			}
1584 
1585 		/* save the pointer to the command for later */
1586 		global_service_event_handler_ptr = temp_command;
1587 
1588 		my_free(buf);
1589 		}
1590 
1591 
1592 	/**************************************************/
1593 	/* check obsessive processor commands...          */
1594 	/**************************************************/
1595 	if(verify_config == TRUE)
1596 		printf("Checking obsessive compulsive processor commands...\n");
1597 	if(ocsp_command != NULL) {
1598 
1599 		buf = (char *)strdup(ocsp_command);
1600 
1601 		/* get the command name, leave any arguments behind */
1602 		temp_command_name = my_strtok(buf, "!");
1603 
1604 		temp_command = find_command(temp_command_name);
1605 		if(temp_command == NULL) {
1606 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Obsessive compulsive service processor command '%s' is not defined anywhere!", temp_command_name);
1607 			errors++;
1608 			}
1609 
1610 		/* save the pointer to the command for later */
1611 		ocsp_command_ptr = temp_command;
1612 
1613 		my_free(buf);
1614 		}
1615 	if(ochp_command != NULL) {
1616 
1617 		buf = (char *)strdup(ochp_command);
1618 
1619 		/* get the command name, leave any arguments behind */
1620 		temp_command_name = my_strtok(buf, "!");
1621 
1622 		temp_command = find_command(temp_command_name);
1623 		if(temp_command == NULL) {
1624 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Obsessive compulsive host processor command '%s' is not defined anywhere!", temp_command_name);
1625 			errors++;
1626 			}
1627 
1628 		/* save the pointer to the command for later */
1629 		ochp_command_ptr = temp_command;
1630 
1631 		my_free(buf);
1632 		}
1633 
1634 
1635 	/**************************************************/
1636 	/* check various settings...                      */
1637 	/**************************************************/
1638 	if(verify_config == TRUE)
1639 		printf("Checking misc settings...\n");
1640 
1641 	/* check if we can write to temp_path */
1642 	asprintf(&buf, "%s/nagiosXXXXXX", temp_path);
1643 	if((temp_path_fd = mkstemp(buf)) == -1) {
1644 		logit(NSLOG_VERIFICATION_ERROR, TRUE, "\tError: Unable to write to temp_path ('%s') - %s\n", temp_path, strerror(errno));
1645 		errors++;
1646 		}
1647 	else {
1648 		close(temp_path_fd);
1649 		remove(buf);
1650 		}
1651 	my_free(buf);
1652 
1653 	/* check if we can write to check_result_path */
1654 	asprintf(&buf, "%s/nagiosXXXXXX", check_result_path);
1655 	if((temp_path_fd = mkstemp(buf)) == -1) {
1656 		logit(NSLOG_VERIFICATION_WARNING, TRUE, "\tError: Unable to write to check_result_path ('%s') - %s\n", check_result_path, strerror(errno));
1657 		errors++;
1658 		}
1659 	else {
1660 		close(temp_path_fd);
1661 		remove(buf);
1662 		}
1663 	my_free(buf);
1664 
1665 	/* warn if user didn't specify any illegal macro output chars */
1666 	if(illegal_output_chars == NULL) {
1667 		logit(NSLOG_VERIFICATION_WARNING, TRUE, "%s", "Warning: Nothing specified for illegal_macro_output_chars variable!\n");
1668 		warnings++;
1669 		}
1670 
1671 	/* count number of services associated with each host (we need this for flap detection)... */
1672 	for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
1673 		if((temp_host = find_host(temp_service->host_name))) {
1674 			temp_host->total_services++;
1675 			temp_host->total_service_check_interval += temp_service->check_interval;
1676 			}
1677 		}
1678 
1679 	if(verify_config == TRUE) {
1680 		printf("\n");
1681 		printf("Total Warnings: %d\n", warnings);
1682 		printf("Total Errors:   %d\n", errors);
1683 		}
1684 
1685 	if(test_scheduling == TRUE)
1686 		gettimeofday(&tv[3], NULL);
1687 
1688 	if(test_scheduling == TRUE) {
1689 
1690 		if(verify_object_relationships == TRUE)
1691 			runtime[0] = (double)((double)(tv[1].tv_sec - tv[0].tv_sec) + (double)((tv[1].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0);
1692 		else
1693 			runtime[0] = 0.0;
1694 		if(verify_circular_paths == TRUE)
1695 			runtime[1] = (double)((double)(tv[2].tv_sec - tv[1].tv_sec) + (double)((tv[2].tv_usec - tv[1].tv_usec) / 1000.0) / 1000.0);
1696 		else
1697 			runtime[1] = 0.0;
1698 		runtime[2] = (double)((double)(tv[3].tv_sec - tv[2].tv_sec) + (double)((tv[3].tv_usec - tv[2].tv_usec) / 1000.0) / 1000.0);
1699 		runtime[3] = runtime[0] + runtime[1] + runtime[2];
1700 
1701 		printf("Timing information on configuration verification is listed below.\n\n");
1702 
1703 		printf("CONFIG VERIFICATION TIMES          (* = Potential for speedup with -x option)\n");
1704 		printf("----------------------------------\n");
1705 		printf("Object Relationships: %.6lf sec\n", runtime[0]);
1706 		printf("Circular Paths:       %.6lf sec  *\n", runtime[1]);
1707 		printf("Misc:                 %.6lf sec\n", runtime[2]);
1708 		printf("                      ============\n");
1709 		printf("TOTAL:                %.6lf sec  * = %.6lf sec (%.1f%%) estimated savings\n", runtime[3], runtime[1], (runtime[1] / runtime[3]) * 100.0);
1710 		printf("\n\n");
1711 		}
1712 
1713 	return (errors > 0) ? ERROR : OK;
1714 	}
1715 
1716 
1717 
1718 /* do a pre-flight check to make sure object relationships make sense */
pre_flight_object_check(int * w,int * e)1719 int pre_flight_object_check(int *w, int *e) {
1720 	contact *temp_contact = NULL;
1721 	commandsmember *temp_commandsmember = NULL;
1722 	contactgroup *temp_contactgroup = NULL;
1723 	contactsmember *temp_contactsmember = NULL;
1724 	contactgroupsmember *temp_contactgroupsmember = NULL;
1725 	host *temp_host = NULL;
1726 	host *temp_host2 = NULL;
1727 	hostsmember *temp_hostsmember = NULL;
1728 	hostgroup *temp_hostgroup = NULL;
1729 	servicegroup *temp_servicegroup = NULL;
1730 	servicesmember *temp_servicesmember = NULL;
1731 	service *temp_service = NULL;
1732 	service *temp_service2 = NULL;
1733 	command *temp_command = NULL;
1734 	timeperiod *temp_timeperiod = NULL;
1735 	timeperiod *temp_timeperiod2 = NULL;
1736 	timeperiodexclusion *temp_timeperiodexclusion = NULL;
1737 	serviceescalation *temp_se = NULL;
1738 	hostescalation *temp_he = NULL;
1739 	servicedependency *temp_sd = NULL;
1740 	hostdependency *temp_hd = NULL;
1741 	char *buf = NULL;
1742 	char *temp_command_name = "";
1743 	int found = FALSE;
1744 	int total_objects = 0;
1745 	int warnings = 0;
1746 	int errors = 0;
1747 
1748 
1749 #ifdef TEST
1750 	void *ptr = NULL;
1751 	char *buf1 = "";
1752 	char *buf2 = "";
1753 	buf1 = "temptraxe1";
1754 	buf2 = "Probe 2";
1755 	for(temp_se = get_first_serviceescalation_by_service(buf1, buf2, &ptr); temp_se != NULL; temp_se = get_next_serviceescalation_by_service(buf1, buf2, &ptr)) {
1756 		printf("FOUND ESCALATION FOR SVC '%s'/'%s': %d-%d/%.3f, PTR=%p\n", buf1, buf2, temp_se->first_notification, temp_se->last_notification, temp_se->notification_interval, ptr);
1757 		}
1758 	for(temp_he = get_first_hostescalation_by_host(buf1, &ptr); temp_he != NULL; temp_he = get_next_hostescalation_by_host(buf1, &ptr)) {
1759 		printf("FOUND ESCALATION FOR HOST '%s': %d-%d/%d, PTR=%p\n", buf1, temp_he->first_notification, temp_he->last_notification, temp_he->notification_interval, ptr);
1760 		}
1761 #endif
1762 
1763 	/* bail out if we aren't supposed to verify object relationships */
1764 	if(verify_object_relationships == FALSE)
1765 		return OK;
1766 
1767 
1768 	/*****************************************/
1769 	/* check each service...                 */
1770 	/*****************************************/
1771 	if(verify_config == TRUE)
1772 		printf("Checking services...\n");
1773 	if(get_service_count() == 0) {
1774 		logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: There are no services defined!");
1775 		errors++;
1776 		}
1777 	total_objects = 0;
1778 	for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
1779 
1780 		total_objects++;
1781 		found = FALSE;
1782 
1783 		/* check for a valid host */
1784 		temp_host = find_host(temp_service->host_name);
1785 
1786 		/* we couldn't find an associated host! */
1787 		if(!temp_host) {
1788 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in service '%s' not defined anywhere!", temp_service->host_name, temp_service->description);
1789 			errors++;
1790 			}
1791 
1792 		/* save the host pointer for later */
1793 		temp_service->host_ptr = temp_host;
1794 
1795 		/* add a reverse link from the host to the service for faster lookups later */
1796 		add_service_link_to_host(temp_host, temp_service);
1797 
1798 		/* check the event handler command */
1799 		if(temp_service->event_handler != NULL) {
1800 
1801 			/* check the event handler command */
1802 			buf = (char *)strdup(temp_service->event_handler);
1803 
1804 			/* get the command name, leave any arguments behind */
1805 			temp_command_name = my_strtok(buf, "!");
1806 
1807 			temp_command = find_command(temp_command_name);
1808 			if(temp_command == NULL) {
1809 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Event handler command '%s' specified in service '%s' for host '%s' not defined anywhere", temp_command_name, temp_service->description, temp_service->host_name);
1810 				errors++;
1811 				}
1812 
1813 			my_free(buf);
1814 
1815 			/* save the pointer to the event handler for later */
1816 			temp_service->event_handler_ptr = temp_command;
1817 			}
1818 
1819 		/* check the service check_command */
1820 		buf = (char *)strdup(temp_service->service_check_command);
1821 
1822 		/* get the command name, leave any arguments behind */
1823 		temp_command_name = my_strtok(buf, "!");
1824 
1825 		temp_command = find_command(temp_command_name);
1826 		if(temp_command == NULL) {
1827 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service check command '%s' specified in service '%s' for host '%s' not defined anywhere!", temp_command_name, temp_service->description, temp_service->host_name);
1828 			errors++;
1829 			}
1830 
1831 		my_free(buf);
1832 
1833 		/* save the pointer to the check command for later */
1834 		temp_service->check_command_ptr = temp_command;
1835 
1836 		/* check for sane recovery options */
1837 		if(temp_service->notify_on_recovery == TRUE && temp_service->notify_on_warning == FALSE && temp_service->notify_on_critical == FALSE) {
1838 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Recovery notification option in service '%s' for host '%s' doesn't make any sense - specify warning and/or critical options as well", temp_service->description, temp_service->host_name);
1839 			warnings++;
1840 			}
1841 
1842 		/* reset the found flag */
1843 		found = FALSE;
1844 
1845 		/* check for valid contacts */
1846 		for(temp_contactsmember = temp_service->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
1847 
1848 			temp_contact = find_contact(temp_contactsmember->contact_name);
1849 
1850 			if(temp_contact == NULL) {
1851 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in service '%s' for host '%s' is not defined anywhere!", temp_contactsmember->contact_name, temp_service->description, temp_service->host_name);
1852 				errors++;
1853 				}
1854 
1855 			/* save the contact pointer for later */
1856 			temp_contactsmember->contact_ptr = temp_contact;
1857 			}
1858 
1859 		/* check all contact groupss */
1860 		for(temp_contactgroupsmember = temp_service->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
1861 
1862 			temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name);
1863 
1864 			if(temp_contactgroup == NULL) {
1865 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in service '%s' for host '%s' is not defined anywhere!", temp_contactgroupsmember->group_name, temp_service->description, temp_service->host_name);
1866 				errors++;
1867 				}
1868 
1869 			/* save the contact group pointer for later */
1870 			temp_contactgroupsmember->group_ptr = temp_contactgroup;
1871 			}
1872 
1873 		/* check to see if there is at least one contact/group */
1874 		if(temp_service->contacts == NULL && temp_service->contact_groups == NULL) {
1875 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has no default contacts or contactgroups defined!", temp_service->description, temp_service->host_name);
1876 			warnings++;
1877 			}
1878 
1879 		/* verify service check timeperiod */
1880 		if(temp_service->check_period == NULL) {
1881 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has no check time period defined!", temp_service->description, temp_service->host_name);
1882 			warnings++;
1883 			}
1884 		else {
1885 			temp_timeperiod = find_timeperiod(temp_service->check_period);
1886 			if(temp_timeperiod == NULL) {
1887 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Check period '%s' specified for service '%s' on host '%s' is not defined anywhere!", temp_service->check_period, temp_service->description, temp_service->host_name);
1888 				errors++;
1889 				}
1890 
1891 			/* save the pointer to the check timeperiod for later */
1892 			temp_service->check_period_ptr = temp_timeperiod;
1893 			}
1894 
1895 		/* check service notification timeperiod */
1896 		if(temp_service->notification_period == NULL) {
1897 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has no notification time period defined!", temp_service->description, temp_service->host_name);
1898 			warnings++;
1899 			}
1900 
1901 		else {
1902 			temp_timeperiod = find_timeperiod(temp_service->notification_period);
1903 			if(temp_timeperiod == NULL) {
1904 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Notification period '%s' specified for service '%s' on host '%s' is not defined anywhere!", temp_service->notification_period, temp_service->description, temp_service->host_name);
1905 				errors++;
1906 				}
1907 
1908 			/* save the pointer to the notification timeperiod for later */
1909 			temp_service->notification_period_ptr = temp_timeperiod;
1910 			}
1911 
1912 		/* see if the notification interval is less than the check interval */
1913 		if(temp_service->notification_interval < temp_service->check_interval && temp_service->notification_interval != 0) {
1914 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s'  has a notification interval less than its check interval!  Notifications are only re-sent after checks are made, so the effective notification interval will be that of the check interval.", temp_service->description, temp_service->host_name);
1915 			warnings++;
1916 			}
1917 
1918 		/* check for illegal characters in service description */
1919 		if(use_precached_objects == FALSE) {
1920 			if(contains_illegal_object_chars(temp_service->description) == TRUE) {
1921 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The description string for service '%s' on host '%s' contains one or more illegal characters.", temp_service->description, temp_service->host_name);
1922 				errors++;
1923 				}
1924 			}
1925 		}
1926 
1927 	if(verify_config == TRUE)
1928 		printf("\tChecked %d services.\n", total_objects);
1929 
1930 
1931 
1932 	/*****************************************/
1933 	/* check all hosts...                    */
1934 	/*****************************************/
1935 	if(verify_config == TRUE)
1936 		printf("Checking hosts...\n");
1937 
1938 	if(get_host_count() == 0) {
1939 		logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: There are no hosts defined!");
1940 		errors++;
1941 		}
1942 
1943 	total_objects = 0;
1944 	for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
1945 
1946 		total_objects++;
1947 		found = FALSE;
1948 
1949 		/* make sure each host has at least one service associated with it */
1950 		/* 02/21/08 NOTE: this is extremely inefficient */
1951 		if(use_precached_objects == FALSE && use_large_installation_tweaks == FALSE) {
1952 
1953 			for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
1954 				if(!strcmp(temp_service->host_name, temp_host->name)) {
1955 					found = TRUE;
1956 					break;
1957 					}
1958 				}
1959 
1960 			/* we couldn't find a service associated with this host! */
1961 			if(found == FALSE) {
1962 				logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host '%s' has no services associated with it!", temp_host->name);
1963 				warnings++;
1964 				}
1965 
1966 			found = FALSE;
1967 			}
1968 
1969 		/* check the event handler command */
1970 		if(temp_host->event_handler != NULL) {
1971 
1972 			/* check the event handler command */
1973 			buf = (char *)strdup(temp_host->event_handler);
1974 
1975 			/* get the command name, leave any arguments behind */
1976 			temp_command_name = my_strtok(buf, "!");
1977 
1978 			temp_command = find_command(temp_command_name);
1979 			if(temp_command == NULL) {
1980 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Event handler command '%s' specified for host '%s' not defined anywhere", temp_command_name, temp_host->name);
1981 				errors++;
1982 				}
1983 
1984 			my_free(buf);
1985 
1986 			/* save the pointer to the event handler command for later */
1987 			temp_host->event_handler_ptr = temp_command;
1988 			}
1989 
1990 		/* hosts that don't have check commands defined shouldn't ever be checked... */
1991 		if(temp_host->host_check_command != NULL) {
1992 
1993 			/* check the host check_command */
1994 			buf = (char *)strdup(temp_host->host_check_command);
1995 
1996 			/* get the command name, leave any arguments behind */
1997 			temp_command_name = my_strtok(buf, "!");
1998 
1999 			temp_command = find_command(temp_command_name);
2000 			if(temp_command == NULL) {
2001 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host check command '%s' specified for host '%s' is not defined anywhere!", temp_command_name, temp_host->name);
2002 				errors++;
2003 				}
2004 
2005 			/* save the pointer to the check command for later */
2006 			temp_host->check_command_ptr = temp_command;
2007 
2008 			my_free(buf);
2009 			}
2010 
2011 		/* check host check timeperiod */
2012 		if(temp_host->check_period != NULL) {
2013 			temp_timeperiod = find_timeperiod(temp_host->check_period);
2014 			if(temp_timeperiod == NULL) {
2015 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Check period '%s' specified for host '%s' is not defined anywhere!", temp_host->check_period, temp_host->name);
2016 				errors++;
2017 				}
2018 
2019 			/* save the pointer to the check timeperiod for later */
2020 			temp_host->check_period_ptr = temp_timeperiod;
2021 			}
2022 
2023 		/* check all contacts */
2024 		for(temp_contactsmember = temp_host->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
2025 
2026 			temp_contact = find_contact(temp_contactsmember->contact_name);
2027 
2028 			if(temp_contact == NULL) {
2029 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in host '%s' is not defined anywhere!", temp_contactsmember->contact_name, temp_host->name);
2030 				errors++;
2031 				}
2032 
2033 			/* save the contact pointer for later */
2034 			temp_contactsmember->contact_ptr = temp_contact;
2035 			}
2036 
2037 		/* check all contact groups */
2038 		for(temp_contactgroupsmember = temp_host->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
2039 
2040 			temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name);
2041 
2042 			if(temp_contactgroup == NULL) {
2043 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in host '%s' is not defined anywhere!", temp_contactgroupsmember->group_name, temp_host->name);
2044 				errors++;
2045 				}
2046 
2047 			/* save the contact group pointer for later */
2048 			temp_contactgroupsmember->group_ptr = temp_contactgroup;
2049 			}
2050 
2051 		/* check to see if there is at least one contact/group */
2052 		if(temp_host->contacts == NULL && temp_host->contact_groups == NULL) {
2053 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host '%s' has no default contacts or contactgroups defined!", temp_host->name);
2054 			warnings++;
2055 			}
2056 
2057 		/* check notification timeperiod */
2058 		if(temp_host->notification_period != NULL) {
2059 			temp_timeperiod = find_timeperiod(temp_host->notification_period);
2060 			if(temp_timeperiod == NULL) {
2061 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Notification period '%s' specified for host '%s' is not defined anywhere!", temp_host->notification_period, temp_host->name);
2062 				errors++;
2063 				}
2064 
2065 			/* save the pointer to the notification timeperiod for later */
2066 			temp_host->notification_period_ptr = temp_timeperiod;
2067 			}
2068 
2069 		/* check all parent parent host */
2070 		for(temp_hostsmember = temp_host->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
2071 
2072 			if((temp_host2 = find_host(temp_hostsmember->host_name)) == NULL) {
2073 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: '%s' is not a valid parent for host '%s'!", temp_hostsmember->host_name, temp_host->name);
2074 				errors++;
2075 				}
2076 
2077 			/* save the parent host pointer for later */
2078 			temp_hostsmember->host_ptr = temp_host2;
2079 
2080 			/* add a reverse (child) link to make searches faster later on */
2081 			add_child_link_to_host(temp_host2, temp_host);
2082 			}
2083 
2084 		/* check for sane recovery options */
2085 		if(temp_host->notify_on_recovery == TRUE && temp_host->notify_on_down == FALSE && temp_host->notify_on_unreachable == FALSE) {
2086 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Recovery notification option in host '%s' definition doesn't make any sense - specify down and/or unreachable options as well", temp_host->name);
2087 			warnings++;
2088 			}
2089 
2090 		/* check for illegal characters in host name */
2091 		if(use_precached_objects == FALSE) {
2092 			if(contains_illegal_object_chars(temp_host->name) == TRUE) {
2093 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of host '%s' contains one or more illegal characters.", temp_host->name);
2094 				errors++;
2095 				}
2096 			}
2097 		}
2098 
2099 
2100 	if(verify_config == TRUE)
2101 		printf("\tChecked %d hosts.\n", total_objects);
2102 
2103 
2104 	/*****************************************/
2105 	/* check each host group...              */
2106 	/*****************************************/
2107 	if(verify_config == TRUE)
2108 		printf("Checking host groups...\n");
2109 	for(temp_hostgroup = hostgroup_list, total_objects = 0; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next, total_objects++) {
2110 
2111 		/* check all group members */
2112 		for(temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
2113 
2114 			temp_host = find_host(temp_hostsmember->host_name);
2115 			if(temp_host == NULL) {
2116 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in host group '%s' is not defined anywhere!", temp_hostsmember->host_name, temp_hostgroup->group_name);
2117 				errors++;
2118 				}
2119 
2120 			/* save a pointer to this hostgroup for faster host/group membership lookups later */
2121 			else
2122 				add_object_to_objectlist(&temp_host->hostgroups_ptr, (void *)temp_hostgroup);
2123 
2124 			/* save host pointer for later */
2125 			temp_hostsmember->host_ptr = temp_host;
2126 			}
2127 
2128 		/* check for illegal characters in hostgroup name */
2129 		if(use_precached_objects == FALSE) {
2130 			if(contains_illegal_object_chars(temp_hostgroup->group_name) == TRUE) {
2131 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of hostgroup '%s' contains one or more illegal characters.", temp_hostgroup->group_name);
2132 				errors++;
2133 				}
2134 			}
2135 		}
2136 
2137 	if(verify_config == TRUE)
2138 		printf("\tChecked %d host groups.\n", total_objects);
2139 
2140 
2141 	/*****************************************/
2142 	/* check each service group...           */
2143 	/*****************************************/
2144 	if(verify_config == TRUE)
2145 		printf("Checking service groups...\n");
2146 	for(temp_servicegroup = servicegroup_list, total_objects = 0; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next, total_objects++) {
2147 
2148 		/* check all group members */
2149 		for(temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
2150 
2151 			temp_service = find_service(temp_servicesmember->host_name, temp_servicesmember->service_description);
2152 			if(temp_service == NULL) {
2153 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service group '%s' is not defined anywhere!", temp_servicesmember->service_description, temp_servicesmember->host_name, temp_servicegroup->group_name);
2154 				errors++;
2155 				}
2156 
2157 			/* save a pointer to this servicegroup for faster service/group membership lookups later */
2158 			else
2159 				add_object_to_objectlist(&temp_service->servicegroups_ptr, (void *)temp_servicegroup);
2160 
2161 			/* save service pointer for later */
2162 			temp_servicesmember->service_ptr = temp_service;
2163 			}
2164 
2165 		/* check for illegal characters in servicegroup name */
2166 		if(use_precached_objects == FALSE) {
2167 			if(contains_illegal_object_chars(temp_servicegroup->group_name) == TRUE) {
2168 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of servicegroup '%s' contains one or more illegal characters.", temp_servicegroup->group_name);
2169 				errors++;
2170 				}
2171 			}
2172 		}
2173 
2174 	if(verify_config == TRUE)
2175 		printf("\tChecked %d service groups.\n", total_objects);
2176 
2177 
2178 
2179 	/*****************************************/
2180 	/* check all contacts...                 */
2181 	/*****************************************/
2182 	if(verify_config == TRUE)
2183 		printf("Checking contacts...\n");
2184 	if(contact_list == NULL) {
2185 		logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: There are no contacts defined!");
2186 		errors++;
2187 		}
2188 	for(temp_contact = contact_list, total_objects = 0; temp_contact != NULL; temp_contact = temp_contact->next, total_objects++) {
2189 
2190 		/* check service notification commands */
2191 		if(temp_contact->service_notification_commands == NULL) {
2192 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' has no service notification commands defined!", temp_contact->name);
2193 			errors++;
2194 			}
2195 		else for(temp_commandsmember = temp_contact->service_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) {
2196 
2197 				/* check the host notification command */
2198 				buf = (char *)strdup(temp_commandsmember->command);
2199 
2200 				/* get the command name, leave any arguments behind */
2201 				temp_command_name = my_strtok(buf, "!");
2202 
2203 				temp_command = find_command(temp_command_name);
2204 				if(temp_command == NULL) {
2205 					logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification command '%s' specified for contact '%s' is not defined anywhere!", temp_command_name, temp_contact->name);
2206 					errors++;
2207 					}
2208 
2209 				/* save pointer to the command for later */
2210 				temp_commandsmember->command_ptr = temp_command;
2211 
2212 				my_free(buf);
2213 				}
2214 
2215 		/* check host notification commands */
2216 		if(temp_contact->host_notification_commands == NULL) {
2217 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' has no host notification commands defined!", temp_contact->name);
2218 			errors++;
2219 			}
2220 		else for(temp_commandsmember = temp_contact->host_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) {
2221 
2222 				/* check the host notification command */
2223 				buf = (char *)strdup(temp_commandsmember->command);
2224 
2225 				/* get the command name, leave any arguments behind */
2226 				temp_command_name = my_strtok(buf, "!");
2227 
2228 				temp_command = find_command(temp_command_name);
2229 				if(temp_command == NULL) {
2230 					logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification command '%s' specified for contact '%s' is not defined anywhere!", temp_command_name, temp_contact->name);
2231 					errors++;
2232 					}
2233 
2234 				/* save pointer to the command for later */
2235 				temp_commandsmember->command_ptr = temp_command;
2236 
2237 				my_free(buf);
2238 				}
2239 
2240 		/* check service notification timeperiod */
2241 		if(temp_contact->service_notification_period == NULL) {
2242 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Contact '%s' has no service notification time period defined!", temp_contact->name);
2243 			warnings++;
2244 			}
2245 
2246 		else {
2247 			temp_timeperiod = find_timeperiod(temp_contact->service_notification_period);
2248 			if(temp_timeperiod == NULL) {
2249 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification period '%s' specified for contact '%s' is not defined anywhere!", temp_contact->service_notification_period, temp_contact->name);
2250 				errors++;
2251 				}
2252 
2253 			/* save the pointer to the service notification timeperiod for later */
2254 			temp_contact->service_notification_period_ptr = temp_timeperiod;
2255 			}
2256 
2257 		/* check host notification timeperiod */
2258 		if(temp_contact->host_notification_period == NULL) {
2259 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Contact '%s' has no host notification time period defined!", temp_contact->name);
2260 			warnings++;
2261 			}
2262 
2263 		else {
2264 			temp_timeperiod = find_timeperiod(temp_contact->host_notification_period);
2265 			if(temp_timeperiod == NULL) {
2266 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification period '%s' specified for contact '%s' is not defined anywhere!", temp_contact->host_notification_period, temp_contact->name);
2267 				errors++;
2268 				}
2269 
2270 			/* save the pointer to the host notification timeperiod for later */
2271 			temp_contact->host_notification_period_ptr = temp_timeperiod;
2272 			}
2273 
2274 		/* check for sane host recovery options */
2275 		if(temp_contact->notify_on_host_recovery == TRUE && temp_contact->notify_on_host_down == FALSE && temp_contact->notify_on_host_unreachable == FALSE) {
2276 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host recovery notification option for contact '%s' doesn't make any sense - specify down and/or unreachable options as well", temp_contact->name);
2277 			warnings++;
2278 			}
2279 
2280 		/* check for sane service recovery options */
2281 		if(temp_contact->notify_on_service_recovery == TRUE && temp_contact->notify_on_service_critical == FALSE && temp_contact->notify_on_service_warning == FALSE) {
2282 			logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service recovery notification option for contact '%s' doesn't make any sense - specify critical and/or warning options as well", temp_contact->name);
2283 			warnings++;
2284 			}
2285 
2286 		/* check for illegal characters in contact name */
2287 		if(use_precached_objects == FALSE) {
2288 			if(contains_illegal_object_chars(temp_contact->name) == TRUE) {
2289 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of contact '%s' contains one or more illegal characters.", temp_contact->name);
2290 				errors++;
2291 				}
2292 			}
2293 		}
2294 
2295 	if(verify_config == TRUE)
2296 		printf("\tChecked %d contacts.\n", total_objects);
2297 
2298 
2299 
2300 	/*****************************************/
2301 	/* check each contact group...           */
2302 	/*****************************************/
2303 	if(verify_config == TRUE)
2304 		printf("Checking contact groups...\n");
2305 	for(temp_contactgroup = contactgroup_list, total_objects = 0; temp_contactgroup != NULL; temp_contactgroup = temp_contactgroup->next, total_objects++) {
2306 
2307 		found = FALSE;
2308 
2309 		/* check all the group members */
2310 		for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
2311 
2312 			temp_contact = find_contact(temp_contactsmember->contact_name);
2313 			if(temp_contact == NULL) {
2314 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in contact group '%s' is not defined anywhere!", temp_contactsmember->contact_name, temp_contactgroup->group_name);
2315 				errors++;
2316 				}
2317 
2318 			/* save a pointer to this contactgroup for faster contact/group membership lookups later */
2319 			else
2320 				add_object_to_objectlist(&temp_contact->contactgroups_ptr, (void *)temp_contactgroup);
2321 
2322 			/* save the contact pointer for later */
2323 			temp_contactsmember->contact_ptr = temp_contact;
2324 			}
2325 
2326 		/* check for illegal characters in contactgroup name */
2327 		if(use_precached_objects == FALSE) {
2328 			if(contains_illegal_object_chars(temp_contactgroup->group_name) == TRUE) {
2329 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of contact group '%s' contains one or more illegal characters.", temp_contactgroup->group_name);
2330 				errors++;
2331 				}
2332 			}
2333 		}
2334 
2335 	if(verify_config == TRUE)
2336 		printf("\tChecked %d contact groups.\n", total_objects);
2337 
2338 
2339 
2340 	/*****************************************/
2341 	/* check all service escalations...     */
2342 	/*****************************************/
2343 	if(verify_config == TRUE)
2344 		printf("Checking service escalations...\n");
2345 
2346 	for(temp_se = serviceescalation_list, total_objects = 0; temp_se != NULL; temp_se = temp_se->next, total_objects++) {
2347 
2348 		/* find the service */
2349 		temp_service = find_service(temp_se->host_name, temp_se->description);
2350 		if(temp_service == NULL) {
2351 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service escalation is not defined anywhere!", temp_se->description, temp_se->host_name);
2352 			errors++;
2353 			}
2354 
2355 		/* save the service pointer for later */
2356 		temp_se->service_ptr = temp_service;
2357 
2358 		/* find the timeperiod */
2359 		if(temp_se->escalation_period != NULL) {
2360 			temp_timeperiod = find_timeperiod(temp_se->escalation_period);
2361 			if(temp_timeperiod == NULL) {
2362 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Escalation period '%s' specified in service escalation for service '%s' on host '%s' is not defined anywhere!", temp_se->escalation_period, temp_se->description, temp_se->host_name);
2363 				errors++;
2364 				}
2365 
2366 			/* save the timeperiod pointer for later */
2367 			temp_se->escalation_period_ptr = temp_timeperiod;
2368 			}
2369 
2370 		/* find the contacts */
2371 		for(temp_contactsmember = temp_se->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
2372 
2373 			/* find the contact */
2374 			temp_contact = find_contact(temp_contactsmember->contact_name);
2375 			if(temp_contact == NULL) {
2376 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in service escalation for service '%s' on host '%s' is not defined anywhere!", temp_contactsmember->contact_name, temp_se->description, temp_se->host_name);
2377 				errors++;
2378 				}
2379 
2380 			/* save the contact pointer for later */
2381 			temp_contactsmember->contact_ptr = temp_contact;
2382 			}
2383 
2384 		/* check all contact groups */
2385 		for(temp_contactgroupsmember = temp_se->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
2386 
2387 			temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name);
2388 
2389 			if(temp_contactgroup == NULL) {
2390 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in service escalation for service '%s' on host '%s' is not defined anywhere!", temp_contactgroupsmember->group_name, temp_se->description, temp_se->host_name);
2391 				errors++;
2392 				}
2393 
2394 			/* save the contact group pointer for later */
2395 			temp_contactgroupsmember->group_ptr = temp_contactgroup;
2396 			}
2397 		}
2398 
2399 	if(verify_config == TRUE)
2400 		printf("\tChecked %d service escalations.\n", total_objects);
2401 
2402 
2403 
2404 	/*****************************************/
2405 	/* check all service dependencies...     */
2406 	/*****************************************/
2407 	if(verify_config == TRUE)
2408 		printf("Checking service dependencies...\n");
2409 
2410 	for(temp_sd = servicedependency_list, total_objects = 0; temp_sd != NULL; temp_sd = temp_sd->next, total_objects++) {
2411 
2412 		/* find the dependent service */
2413 		temp_service = find_service(temp_sd->dependent_host_name, temp_sd->dependent_service_description);
2414 		if(temp_service == NULL) {
2415 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependent service '%s' on host '%s' specified in service dependency for service '%s' on host '%s' is not defined anywhere!", temp_sd->dependent_service_description, temp_sd->dependent_host_name, temp_sd->service_description, temp_sd->host_name);
2416 			errors++;
2417 			}
2418 
2419 		/* save pointer for later */
2420 		temp_sd->dependent_service_ptr = temp_service;
2421 
2422 		/* find the service we're depending on */
2423 		temp_service2 = find_service(temp_sd->host_name, temp_sd->service_description);
2424 		if(temp_service2 == NULL) {
2425 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service dependency for service '%s' on host '%s' is not defined anywhere!", temp_sd->service_description, temp_sd->host_name, temp_sd->dependent_service_description, temp_sd->dependent_host_name);
2426 			errors++;
2427 			}
2428 
2429 		/* save pointer for later */
2430 		temp_sd->master_service_ptr = temp_service2;
2431 
2432 		/* make sure they're not the same service */
2433 		if(temp_service == temp_service2) {
2434 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service dependency definition for service '%s' on host '%s' is circular (it depends on itself)!", temp_sd->dependent_service_description, temp_sd->dependent_host_name);
2435 			errors++;
2436 			}
2437 
2438 		/* find the timeperiod */
2439 		if(temp_sd->dependency_period != NULL) {
2440 			temp_timeperiod = find_timeperiod(temp_sd->dependency_period);
2441 			if(temp_timeperiod == NULL) {
2442 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependency period '%s' specified in service dependency for service '%s' on host '%s' is not defined anywhere!", temp_sd->dependency_period, temp_sd->dependent_service_description, temp_sd->dependent_host_name);
2443 				errors++;
2444 				}
2445 
2446 			/* save the timeperiod pointer for later */
2447 			temp_sd->dependency_period_ptr = temp_timeperiod;
2448 			}
2449 		}
2450 
2451 	if(verify_config == TRUE)
2452 		printf("\tChecked %d service dependencies.\n", total_objects);
2453 
2454 
2455 
2456 	/*****************************************/
2457 	/* check all host escalations...     */
2458 	/*****************************************/
2459 	if(verify_config == TRUE)
2460 		printf("Checking host escalations...\n");
2461 
2462 	for(temp_he = hostescalation_list, total_objects = 0; temp_he != NULL; temp_he = temp_he->next, total_objects++) {
2463 
2464 		/* find the host */
2465 		temp_host = find_host(temp_he->host_name);
2466 		if(temp_host == NULL) {
2467 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in host escalation is not defined anywhere!", temp_he->host_name);
2468 			errors++;
2469 			}
2470 
2471 		/* save the host pointer for later */
2472 		temp_he->host_ptr = temp_host;
2473 
2474 		/* find the timeperiod */
2475 		if(temp_he->escalation_period != NULL) {
2476 			temp_timeperiod = find_timeperiod(temp_he->escalation_period);
2477 			if(temp_timeperiod == NULL) {
2478 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Escalation period '%s' specified in host escalation for host '%s' is not defined anywhere!", temp_he->escalation_period, temp_he->host_name);
2479 				errors++;
2480 				}
2481 
2482 			/* save the timeperiod pointer for later */
2483 			temp_he->escalation_period_ptr = temp_timeperiod;
2484 			}
2485 
2486 		/* find the contacts */
2487 		for(temp_contactsmember = temp_he->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
2488 
2489 			/* find the contact*/
2490 			temp_contact = find_contact(temp_contactsmember->contact_name);
2491 			if(temp_contact == NULL) {
2492 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in host escalation for host '%s' is not defined anywhere!", temp_contactsmember->contact_name, temp_he->host_name);
2493 				errors++;
2494 				}
2495 
2496 			/* save the contact pointer for later */
2497 			temp_contactsmember->contact_ptr = temp_contact;
2498 			}
2499 
2500 		/* check all contact groups */
2501 		for(temp_contactgroupsmember = temp_he->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
2502 
2503 			temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name);
2504 
2505 			if(temp_contactgroup == NULL) {
2506 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in host escalation for host '%s' is not defined anywhere!", temp_contactgroupsmember->group_name, temp_he->host_name);
2507 				errors++;
2508 				}
2509 
2510 			/* save the contact group pointer for later */
2511 			temp_contactgroupsmember->group_ptr = temp_contactgroup;
2512 			}
2513 		}
2514 
2515 	if(verify_config == TRUE)
2516 		printf("\tChecked %d host escalations.\n", total_objects);
2517 
2518 
2519 
2520 	/*****************************************/
2521 	/* check all host dependencies...     */
2522 	/*****************************************/
2523 	if(verify_config == TRUE)
2524 		printf("Checking host dependencies...\n");
2525 
2526 	for(temp_hd = hostdependency_list, total_objects = 0; temp_hd != NULL; temp_hd = temp_hd->next, total_objects++) {
2527 
2528 		/* find the dependent host */
2529 		temp_host = find_host(temp_hd->dependent_host_name);
2530 		if(temp_host == NULL) {
2531 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependent host specified in host dependency for host '%s' is not defined anywhere!", temp_hd->dependent_host_name);
2532 			errors++;
2533 			}
2534 
2535 		/* save pointer for later */
2536 		temp_hd->dependent_host_ptr = temp_host;
2537 
2538 		/* find the host we're depending on */
2539 		temp_host2 = find_host(temp_hd->host_name);
2540 		if(temp_host2 == NULL) {
2541 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host specified in host dependency for host '%s' is not defined anywhere!", temp_hd->dependent_host_name);
2542 			errors++;
2543 			}
2544 
2545 		/* save pointer for later */
2546 		temp_hd->master_host_ptr = temp_host2;
2547 
2548 		/* make sure they're not the same host */
2549 		if(temp_host == temp_host2) {
2550 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host dependency definition for host '%s' is circular (it depends on itself)!", temp_hd->dependent_host_name);
2551 			errors++;
2552 			}
2553 
2554 		/* find the timeperiod */
2555 		if(temp_hd->dependency_period != NULL) {
2556 			temp_timeperiod = find_timeperiod(temp_hd->dependency_period);
2557 			if(temp_timeperiod == NULL) {
2558 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependency period '%s' specified in host dependency for host '%s' is not defined anywhere!", temp_hd->dependency_period, temp_hd->dependent_host_name);
2559 				errors++;
2560 				}
2561 
2562 			/* save the timeperiod pointer for later */
2563 			temp_hd->dependency_period_ptr = temp_timeperiod;
2564 			}
2565 		}
2566 
2567 	if(verify_config == TRUE)
2568 		printf("\tChecked %d host dependencies.\n", total_objects);
2569 
2570 
2571 
2572 	/*****************************************/
2573 	/* check all commands...                 */
2574 	/*****************************************/
2575 	if(verify_config == TRUE)
2576 		printf("Checking commands...\n");
2577 
2578 	for(temp_command = command_list, total_objects = 0; temp_command != NULL; temp_command = temp_command->next, total_objects++) {
2579 
2580 		/* check for illegal characters in command name */
2581 		if(use_precached_objects == FALSE) {
2582 			if(contains_illegal_object_chars(temp_command->name) == TRUE) {
2583 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of command '%s' contains one or more illegal characters.", temp_command->name);
2584 				errors++;
2585 				}
2586 			}
2587 		}
2588 
2589 	if(verify_config == TRUE)
2590 		printf("\tChecked %d commands.\n", total_objects);
2591 
2592 
2593 
2594 	/*****************************************/
2595 	/* check all timeperiods...              */
2596 	/*****************************************/
2597 	if(verify_config == TRUE)
2598 		printf("Checking time periods...\n");
2599 
2600 	for(temp_timeperiod = timeperiod_list, total_objects = 0; temp_timeperiod != NULL; temp_timeperiod = temp_timeperiod->next, total_objects++) {
2601 
2602 		/* check for illegal characters in timeperiod name */
2603 		if(use_precached_objects == FALSE) {
2604 			if(contains_illegal_object_chars(temp_timeperiod->name) == TRUE) {
2605 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of time period '%s' contains one or more illegal characters.", temp_timeperiod->name);
2606 				errors++;
2607 				}
2608 			}
2609 
2610 		/* check for valid timeperiod names in exclusion list */
2611 		for(temp_timeperiodexclusion = temp_timeperiod->exclusions; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) {
2612 
2613 			temp_timeperiod2 = find_timeperiod(temp_timeperiodexclusion->timeperiod_name);
2614 			if(temp_timeperiod2 == NULL) {
2615 				logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Excluded time period '%s' specified in timeperiod '%s' is not defined anywhere!", temp_timeperiodexclusion->timeperiod_name, temp_timeperiod->name);
2616 				errors++;
2617 				}
2618 
2619 			/* save the timeperiod pointer for later */
2620 			temp_timeperiodexclusion->timeperiod_ptr = temp_timeperiod2;
2621 			}
2622 		}
2623 
2624 	if(verify_config == TRUE)
2625 		printf("\tChecked %d time periods.\n", total_objects);
2626 
2627 
2628 
2629 	/* update warning and error count */
2630 	*w += warnings;
2631 	*e += errors;
2632 
2633 	return (errors > 0) ? ERROR : OK;
2634 	}
2635 
2636 
2637 /* dfs status values */
2638 #define DFS_UNCHECKED                    0  /* default value */
2639 #define DFS_TEMP_CHECKED                 1  /* check just one time */
2640 #define DFS_OK                           2  /* no problem */
2641 #define DFS_NEAR_LOOP                    3  /* has trouble sons */
2642 #define DFS_LOOPY                        4  /* is a part of a loop */
2643 
2644 #define dfs_get_status(h) h->circular_path_checked
2645 #define dfs_unset_status(h) h->circular_path_checked = 0
2646 #define dfs_set_status(h, flag) h->circular_path_checked = (flag)
2647 #define dfs_host_status(h) (h ? dfs_get_status(h) : DFS_OK)
2648 
2649 /**
2650  * Modified version of Depth-first Search
2651  * http://en.wikipedia.org/wiki/Depth-first_search
2652  */
dfs_host_path(host * root)2653 static int dfs_host_path(host *root) {
2654 	hostsmember *child = NULL;
2655 
2656 	if(!root)
2657 		return DFS_NEAR_LOOP;
2658 
2659 	if(dfs_get_status(root) != DFS_UNCHECKED)
2660 		return dfs_get_status(root);
2661 
2662 	/* Mark the root temporary checked */
2663 	dfs_set_status(root, DFS_TEMP_CHECKED);
2664 
2665 	/* We are scanning the children */
2666 	for(child = root->child_hosts; child != NULL; child = child->next) {
2667 		int child_status = dfs_get_status(child->host_ptr);
2668 
2669 		/* If a child is not checked, check it */
2670 		if(child_status == DFS_UNCHECKED)
2671 			child_status = dfs_host_path(child->host_ptr);
2672 
2673 		/* If a child already temporary checked, its a problem,
2674 		 * loop inside, and its a acked status */
2675 		if(child_status == DFS_TEMP_CHECKED) {
2676 			dfs_set_status(child->host_ptr, DFS_LOOPY);
2677 			dfs_set_status(root, DFS_LOOPY);
2678 			}
2679 
2680 		/* If a child already temporary checked, its a problem, loop inside */
2681 		if(child_status == DFS_NEAR_LOOP || child_status == DFS_LOOPY) {
2682 			/* if a node is know to be part of a loop, do not let it be less */
2683 			if(dfs_get_status(root) != DFS_LOOPY)
2684 				dfs_set_status(root, DFS_NEAR_LOOP);
2685 
2686 			/* we already saw this child, it's a problem */
2687 			dfs_set_status(child->host_ptr, DFS_LOOPY);
2688 			}
2689 		}
2690 
2691 	/*
2692 	 * If root have been modified, do not set it OK
2693 	 * A node is OK if and only if all of his children are OK
2694 	 * If it does not have child, goes ok
2695 	 */
2696 	if(dfs_get_status(root) == DFS_TEMP_CHECKED)
2697 		dfs_set_status(root, DFS_OK);
2698 	return dfs_get_status(root);
2699 	}
2700 
2701 
2702 /* check for circular paths and dependencies */
pre_flight_circular_check(int * w,int * e)2703 int pre_flight_circular_check(int *w, int *e) {
2704 	host *temp_host = NULL;
2705 	servicedependency *temp_sd = NULL;
2706 	servicedependency *temp_sd2 = NULL;
2707 	hostdependency *temp_hd = NULL;
2708 	hostdependency *temp_hd2 = NULL;
2709 	int found = FALSE;
2710 	int result = OK;
2711 	int warnings = 0;
2712 	int errors = 0;
2713 
2714 
2715 	/* bail out if we aren't supposed to verify circular paths */
2716 	if(verify_circular_paths == FALSE)
2717 		return OK;
2718 
2719 
2720 	/********************************************/
2721 	/* check for circular paths between hosts   */
2722 	/********************************************/
2723 	if(verify_config == TRUE)
2724 		printf("Checking for circular paths between hosts...\n");
2725 
2726 	/* check routes between all hosts */
2727 	found = FALSE;
2728 	result = OK;
2729 
2730 
2731 	/* We clean the dsf status from previous check */
2732 	for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
2733 		dfs_set_status(temp_host, DFS_UNCHECKED);
2734 		}
2735 
2736 	for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
2737 		if(dfs_host_path(temp_host) == DFS_LOOPY)
2738 			errors = 1;
2739 		}
2740 
2741 	for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
2742 		if(dfs_get_status(temp_host) == DFS_LOOPY)
2743 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The host '%s' is part of a circular parent/child chain!", temp_host->name);
2744 		/* clean DFS status */
2745 		dfs_set_status(temp_host, DFS_UNCHECKED);
2746 		}
2747 
2748 
2749 	/********************************************/
2750 	/* check for circular dependencies         */
2751 	/********************************************/
2752 	if(verify_config == TRUE)
2753 		printf("Checking for circular host and service dependencies...\n");
2754 
2755 	/* check execution dependencies between all services */
2756 	for(temp_sd = servicedependency_list; temp_sd != NULL; temp_sd = temp_sd->next) {
2757 
2758 		/* clear checked flag for all dependencies */
2759 		for(temp_sd2 = servicedependency_list; temp_sd2 != NULL; temp_sd2 = temp_sd2->next)
2760 			temp_sd2->circular_path_checked = FALSE;
2761 
2762 		found = check_for_circular_servicedependency_path(temp_sd, temp_sd, EXECUTION_DEPENDENCY);
2763 		if(found == TRUE) {
2764 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular execution dependency (which could result in a deadlock) exists for service '%s' on host '%s'!", temp_sd->service_description, temp_sd->host_name);
2765 			errors++;
2766 			}
2767 		}
2768 
2769 	/* check notification dependencies between all services */
2770 	for(temp_sd = servicedependency_list; temp_sd != NULL; temp_sd = temp_sd->next) {
2771 
2772 		/* clear checked flag for all dependencies */
2773 		for(temp_sd2 = servicedependency_list; temp_sd2 != NULL; temp_sd2 = temp_sd2->next)
2774 			temp_sd2->circular_path_checked = FALSE;
2775 
2776 		found = check_for_circular_servicedependency_path(temp_sd, temp_sd, NOTIFICATION_DEPENDENCY);
2777 		if(found == TRUE) {
2778 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular notification dependency (which could result in a deadlock) exists for service '%s' on host '%s'!", temp_sd->service_description, temp_sd->host_name);
2779 			errors++;
2780 			}
2781 		}
2782 
2783 	/* check execution dependencies between all hosts */
2784 	for(temp_hd = hostdependency_list; temp_hd != NULL; temp_hd = temp_hd->next) {
2785 
2786 		/* clear checked flag for all dependencies */
2787 		for(temp_hd2 = hostdependency_list; temp_hd2 != NULL; temp_hd2 = temp_hd2->next)
2788 			temp_hd2->circular_path_checked = FALSE;
2789 
2790 		found = check_for_circular_hostdependency_path(temp_hd, temp_hd, EXECUTION_DEPENDENCY);
2791 		if(found == TRUE) {
2792 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular execution dependency (which could result in a deadlock) exists for host '%s'!", temp_hd->host_name);
2793 			errors++;
2794 			}
2795 		}
2796 
2797 	/* check notification dependencies between all hosts */
2798 	for(temp_hd = hostdependency_list; temp_hd != NULL; temp_hd = temp_hd->next) {
2799 
2800 		/* clear checked flag for all dependencies */
2801 		for(temp_hd2 = hostdependency_list; temp_hd2 != NULL; temp_hd2 = temp_hd2->next)
2802 			temp_hd2->circular_path_checked = FALSE;
2803 
2804 		found = check_for_circular_hostdependency_path(temp_hd, temp_hd, NOTIFICATION_DEPENDENCY);
2805 		if(found == TRUE) {
2806 			logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular notification dependency (which could result in a deadlock) exists for host '%s'!", temp_hd->host_name);
2807 			errors++;
2808 			}
2809 		}
2810 
2811 
2812 	/* update warning and error count */
2813 	*w += warnings;
2814 	*e += errors;
2815 
2816 	return (errors > 0) ? ERROR : OK;
2817 	}
2818 
2819