Imported Upstream version 3.5.1.dfsg

This commit is contained in:
Mario Fetka 2017-05-19 22:22:40 +02:00
commit 25c8be1dce
792 changed files with 209093 additions and 0 deletions

19
.gitignore vendored Normal file
View File

@ -0,0 +1,19 @@
pkg
subst
pkginfo
Prototype
nagios.SPARC.pkg.tar.gz
autom4te.cache
config.log
config.status
daemon-init
Makefile
.deps/
.libs/
*.o
*.la
*.lo
*.gcda
*.gcno
/gmon.out

748
Changelog Normal file
View File

@ -0,0 +1,748 @@
#####################
Nagios 3.x Change Log
#####################
3.5.1 - 08/30/2013
------------------
* Added handler for SIGXFSZ signal (Eric Stanley)
* Fixed bug #444: Nagios 3.5.0 problem with macro $ADMINEMAIL$ : @ is converted to %40 after 2 nagios reload (Duplicate of bug #407)
* Fixed bug #407: Reloading nagios config causes spaces in notifications to become plus signs (Alexey Dvoryanchikov)
* Fixed bug #445: Adding triggered downtime for child hosts causes a SIGSEGV on restart/reload (Eric Stanley)
* Fixed bug #375: Freshness expiration never reached and bug #427: freshness threshold doesn't work if it is set long (Scott Wilkerson, Eric Stanley)
* Fixed bug #432: Downtime scheduled as "Nagios Process" and not the Users name (Sam Lansing, Eric Stanley)
3.5.0 - 03/15/2013
------------------
* Fixed bug #403: The "configuration" page of the webui doesn't use entity encoding when displaying the "command expansion" item (Eric Stanley, Phil Randal)
* Fixed bug #424: Nagios Core 3.4.4 seg fault (core dump) on restart after removing config for running service (Eric Stanley)
* Updated CGI utility functions to support UTF-8 characters (Eric Stanley)
* Fixed bug where selecting Command Expansion from Configuration CGI page would display commands instead (Eric Stanley)
* Fixed bug #369: status.cgi crashes with segfault when there are german ulauts (äöüß) in the hostname or the servicename (Eric Stanley)
* Fixed bug #418: Scheduled Downtime Notifications Resent On Nagios Restart/reload (Eric Stanley)
3.4.4 - 01/12/2013
------------------
* Reenabled check for newer versions of Nagios Core (Mike Guthrie)
* Fixed bug #408: service checks get duplicated on reload (Eric Stanley)
* Fixed bug #401: segmentation fault on Solaris when parsing unknown timeperiod directives. (Eric Stanley)
* Added NULL pointer checks to CGI code. (Eric Stanley)
* Fixed buffer overflow vulnerability in CGI code. Thanks to Neohapsis (http://archives.neohapsis.com/archives/fulldisclosure/2012-12/0108.html) for finding this. (Eric Stanley)
3.4.3 - 11/30/2012
------------------
* Reverted squeue changes intended for Nagios 4
* Reapplied all patches from 3.4.2 release
* Applied fix for pagination and sorting on status.cgi #381 (Phil Randal)
3.4.2 - 11/09/2012
------------------
FIXES
* Fixed issue where deleting a downtime could cause Nagios to crash (Eric Stanley)
* Corrected logic so that end times for flexible downtimes are calculated from the downtime start rather than the current time in the case where Nagios is restarted (Eric Stanley)
* Fixed issue introduced by fix for bug #124 where flexible downtimes are not taken into account on Nagios restart. (Scott Wilkerson, Eric Stanley)
* Fixed bug #247: If a service reports no performance data, the perfdata log file has no line indicating the test. (omnikron@free.fr)
* Fixed link for unhandled unreachable host problems on tactical overview page (Rudolf Cejka)
* Fixed bug #345 with wild card searches not paging properly on status.cgi (Phil Randal)
* Fixed bug #343 on status.cgi where Service Group Summary can potentially show wrong totals (Mark Ziesemer)
* Fixed memory leaks on SIGHUP (Carlos Velasco)
3.4.1 - 05/11/2012
------------------
FIXES
* Double quotes in check_command definition break functionality (#332, reverts #86)
3.4.0 - 05/04/2012
------------------
ENHANCEMENTS
* Added service_check_timeout_state configuration variable (Bill McGonigle)
* Permanently remove sleep on run_event == FALSE in main loop (Max <perldork@webwizarddesign.com>)
* Reduce notification load by moving notification viability check into notification list creation (Opsview Team)
* Added code to apply allow_empty_hostgroup_assignment flag to host and service dependencies (Daniel Wittenberg)
* Users can now see hostgroups and servicegroups that contain at least one host or service they are authorized for, instead of having to be authorized for them all (Ethan Galstad)
* RSS feed boxes fallback if an error occurs (Ethan Galstad)
* RSS feeds no longer block main page load (Mike Guthrie)
FIXES
* Fix $NOTIFICATIONRECIPIENTS$ macro to contain all contacts assigned to host|service, not only notified contacts (Bug #98 Matt Harrington)
* Scheduled Downtime Notifications Resent On Nagios Restart/reload (Bug #124 - ricardo)
* NOTIFICATIONTYPE MACRO never became CUSTOM (Bug #168 - Alexey Dvoryanchikov)
* Plugged minor memory leaks in notification logic
3.3.1 - 07/25/2011
------------------
ENHANCEMENTS
* Added support for same host service dependencies with servicegroups (Mathieu Gagné)
* Empty hostgroups referenced from services now optionally generate a warning instead of an error.
* Documentation links now point to online resources
* Matt Wall's Exfoliation theme is now installed by default. You can reinstall the classic theme with "make install-classicui"
* Downtime delete commands made "distributable" by deleting by host group name, host name or start time/comment (Opsview team)
* Allow status.cgi to order by "host urgency" (Jochen Bern)
* Added news items and quick links to main splash page
* Added ability to authenticate to CGIs using contactgroup name (Stephen Gran)
FIXES
* Fixes status.cgi when called with no parameters, where host should be set to all if none specified (Michael Friedrich)
* Fixes possible validation error with empty hostgroups/servicegroups (Sven-Göran Bergh)
* Performance-data handling and checking is now thread-safe so long as embedded perl is not used.
* Children should no longer hang on mutex locks held in parent for localtime() (and similar) calls.
* Debug logging is now properly serialized, using soft-locking with a timeout of 150 milliseconds to avoid multiple threads competing for the privilege to write debug info.
* Fixed extraneous alerts for services when host is down
* Fixed incorrect parsing of multi-line host check results (Jochen Bern)
* Fixed bug with passive host checks being incorrectly sent to event brokers as active checks
* Fixed bug where passive host check status updates were not being propagated to event brokers
* Reverted 'Fix for retaining host display name and alias, as well as service display name' as configuration information stored incorrectly over a reload
* Fixed compile warnings for size_t (Michael Friedrich)
* Fixed problem where acknowledgements were getting reset when a hard state change occurred
* Removed duplicated unlinks for check result files with multiple results
* Fixed race condition on flexible downtime commands when duration not set or zero (Michael Friedrich)
* Fixed flexible downtime on service hard state change doesn't get triggered/activated (Michael Friedrich)
* Fixed XSS vulnerability in config.cgi and statusmap.cgi (Stefan Schurtz)
* Fixed segfault when sending host notifications (Michael Friedrich)
* Fixed bug where unauthorized contacts could issue hostgroup and servicegroup commands (Sven Nierlein)
WARNINGS
3.2.3 - 10/03/2010
------------------
ENHANCEMENTS
FIXES
* Fixes problem where disabling all active hosts/services was not taking effect
* Fixes for compiler warnings (code cleanup by Stephen Gran)
* Fixes for format errors in event handler logging (Guillaume Rousse)
* Fixed incorrect info in sample nagios.cfg file for state_retention_file (Michael Friedrich)
* Fixed broker_event_handler() to return ERR if data is NULL (Michael Friedrich)
WARNINGS
3.2.2 - 09/01/2010
------------------
ENHANCEMENTS
* Patch to new_mini_epn to allow any command line length without breaking on extra trailing or leading whitespace (Ray Bengen)
* Patch to mini_epn to allow any command line length (Thomas Guyot-Sionnest)
* Patch to speed up loading of state retention data (Matthieu Kermagoret)
* Custom notifications are now suppressed during scheduled downtime (Sven Nierlein)
* Added code to warn user about exit code of 126 meaning plugin is not executable (bug #153)
* Scheduled downtime can now start on SOFT error states (bug #47)
* Main window frame URL can now be specify with a "corewindow=" parameter
* Improved config CGI shows commands, command args in an easier to use manner (Jochen Bern)
* Added ability for NEB modules to override execution of event handlers (Sven Nierlein)
* Custom macros are no longer cleaned/stripped as they are user-defined and should be trusted (Peter Morch)
FIXES
* Fix for choosing next valid time on day of DST change when clocks go one hour backwards
* Fix for nagios now erroring when "Error: Could not find any contactgroup matching..." displayed
* Fix tap tests for Solaris 10 and newer versions of Test::Harness
* Fix for notifications not being sent out when scheduled downtime is cancelled (Daniel Pouzzner)
* Fix for first notification delay being calculated incorrectly, and notifications potentially going out early (Pawel Malachowski)
* Fix for text of scheduling downtime of all services on a host (Holger Weiss)
* Fix for services inheriting notification period from hosts if not defined (Gordon Messmer)
* Fix for incorrect service states on host failures (bug #130 Petya Kohts)
* Fix for incorrect service state attributes being set on host failures (bug #128 Petya Kohts)
* Fix for non-scheduled hosts and services not being updated in NDOUtils
* Fix for typos in TAC, CMD CGIs (bugs #150, #144, #148)
* Fix for types in documentation (bugs #145, #105, #106)
* Fix for incorrect host state counts in status CGI when viewing servicegroups (bug #72)
* Fix for new Splunk integration query parameters (bug #136)
* Fix for extra field header in availability CSV export (bug #113)
* Fix for macro processing code modifying input string (Jochen Bern)
* Fix for update check API
* Fix for CGI speedup when persistent=0 for comments
* Fix for event execution loop re-scheduling host checks instead of executing them if service checks are disabled (bug #152)
* Fix for segfaults on Solaris (Torsten Huebler)
* Fix for incorrect comment expiration times being passed to event broker (Mattieu Kermagot)
* Doc updates related to cleaning of custom macros (Peter Valdemar Morch)
* Fix to sample notify-service-by-email command (bug #62)
* Fix for retaining host display name and alias, as well as service display name (Folkert van Heusden)
3.2.1 - 03/09/2010
------------------
ENHANCEMENTS
* Link to allow scheduling downtime for all services on a host (Hendrik Baecker)
* Speedup to CGIs when lots of comments or downtimes in status.dat file (Jonathan Kamens)
* Patch for new_mini_epn to allow for any command line length without breaking extra trailing or leading whitespace (Ray Bengen)
FIXES
* Fix for incorrect scheduling when time has gone back an hour (partial fix for 24x7)
* Fix for compile on Fedora Core 3 (bug #0000082)
* Fix for compile on Solaris
* Fix for logging test, which was not timezone aware (bug #0000077 - Allan Clark)
* Trivial cleanups for autoconf (Allan Clark)
* Fix for CSS validation of padding: X
* Fix for documentation re: case-insensitive nature of custom variables (Marc Powell)
* Fix for template configurations which use negated wildcards (Tim Wilde)
WARNINGS
* N/A
3.2.0 - 08/12/2009
------------------
* Fix for read-only permissions bug in CGIs that caused problems viewing comments (bug #0000029)
* Fix for incorrect CGI reports (availability, trends, etc.) when reporting period spans Daylight Savings Time (bug #0000046)
* Fix for detection of truecolor support in GD library (Lars Hecking)
* Reverted to use --datadir configure script option instead of the more recently introduced --datarootdir option
* Status and retention files are now flushed/synced to disk to prevent incomplete information being displayed in CGIs
* Fix for incorrect next service check time calculation when Nagios is reloaded with different timeperiod ranges
* Updated Fedora quickstart guide to indicate PHP requirements
* Known issue: Service checks that are defined with timeperiods that contain "exclude" directives are incorrectly re-scheduled. Don't use these for now - we'll get this fixed for 3.4
3.1.2 - 06/23/2009
------------------
* Fix for CPU hogging in service and host check scheduling logic
3.1.1 - 06/22/2009
------------------
* New "important check command" flag for use in service templates, to aid configuration in distributed environments
* Fix for nagios validation error when no services defined
* Fix for stylesheet link
* Fix for extinfo.cgi error message when cgi.cfg doesn't exist
* Fix for notifications.cgi where Update button on right didn't retain host information when no host= was in query parameters
* Fix for potential bug where a contactgroup with no members could cause parsing errors
* Fix for W3 validation for history.cgi
* Fix for W3 validation for extinfo.cgi
* Fix for nagiostats to return non-zero with failures in MRTG mode
* Added t/ directory for tests. Use make test to run. Requires perl on development server
* Fix for duplicate event_id attributes in status and retention data
* Fix for duplicate unlink() during check processing
* Added missing check period column to host config display (CGI)
* Fix for embedded Perl initialization under FreeBSD
* Fix for incorrect re-initialization of mutext after program restart
* Fix for incorrect weighting in host flap detection logic
* Added libtap to distribution. Use ./configure --enable-libtap to compile
* nagios.log permissions are now kept after log rotation
* Fix for "Max concurrent service checks (X) has been reached" messages - will now push services 5 + random(10) seconds ahead for retry
* Fix for removing old HTML files for web frontend that are now replaced with PHP equivalents (index/main/side.html)
* Fix for incorrect service history link text in CGIs
* Fix for useless code loop in netutils.c
* Fix for potential divide by zero in event scheduling code
* Fix for trailing backslash in plugin output causing memory corruption in CGIs
* Fix for bug that could affect host/service scheduling during clock time skew or changes to timeperod definitions between restarts
* Leading whitespace from continuation lines in configuration files is now stripped out
* Fix for bug where pipe (used by IPC) file descriptors get inherited by child processed (e.g. event handlers) (bug #0000026)
* Fix for failure to daemonize - Nagios now bails (bug #0000011)
* Fix for notifications about flapping starting not processed properly by retention data
* Patch to add transparency to statusmap icons for truecolor images
* Patch to add read-only permissions to extinfo CGI
* Security fix for statuswml.cgi where arbitrary shell injection was possible
3.1.0 - 01/25/2009
------------------
* Added automatic update check functionality - runs once a day to check for new Nagios releases
* Splash screen on web UI now indicates whether a new update is available (requires that update checks are enabled)
* Updates to nagiostats utility for faster execution if using external stats file
* Added a bit more verbosity to config verification
* Fixed bug in logging event handlers
* Fix to prevent debug output from being shown when Nagios is compiled with embedded Perl interpreter
* Fix for CPU hogging issues on OpenBSD
* Fix to RPM spec file for sample configuration files
* Fix for bug in time calculation routines that could cause notification, reporting, and check scheduling anomalies
* Fix for scheduling forced service checks from web interface
* Minor mods for frameset base for HTML compliance (more fixes coming soon)
* Fix for bug in handling of hard host and service problem states during restarts that could incorrectly set current check attempt and adversely affect notifications, etc.
* Fix for bug in timeperiod calculation of year/month rollovers and display of fixed calendar dates in web interface
3.0.6 - 12/01/2008
------------------
* Fix for CGI submission of external commands (writing newlines and submitting service comments)
* Fix for Apache group membership in RPM spec file
* Fix for improper notification propagation command processing
* Better out-of-disk-space error handling when writing retention and status files
* Disabled adaptive check and eventhandler commands for security reasons
* Fix for reading output from system commands (event handlers, etc) that have timed out
* Added wildcard host matching in CGIs
* Fixes for playing audio alerts in CGIs
* Fix for incorrect host status links in status CGI when viewing hostgroup summary
* Added support for x509 cert authentication in the CGIs
3.0.5 - 11/04/2008
------------------
* Security fix for Cross Site Request Forgery (CSRF) bug reported by Tim Starling.
* Sample audio files for CGIs removed from distribution
* Fix for mutliline config file continuation bug
* Minor fix to RPM spec file
* Fix for AIX compiler warnings
* Minor sample config file fix
* Added documentation on CGI security issues
3.0.4 - 10/15/2008
------------------
* Fix for properly terminating plugins when parent processes get killed (e.g. using 'killall nagios' with check_timeout plugins running)
* Fix for event broker callback when service notifications are disabled
* Fix for scheduling scheduling servicegroup downtime with 'hosts too' option in CGIs
* Fix for segfault under Solaris with NULL plugin output
* Fixes for bugs in sample event handlers - stop/start active service checks and enable notifications
* Cosmetic fix for logging of notifications
* Fix for high CPU utilization under OS X
* Fix for host/service name encoding in CGIs (trends and availability reports, etc.)
3.0.3 - 06/25/2008
------------------
* Typo fix in object config routines
* Segfault fix in history CGI
* Fix for bug in retention of contact notification options
* Fix for bug in calculation of negative (month) days in timeperiod definitions
* Fix for debug logging of notifications
* Fix for encoding host and servicegroup names in trends and availability CGIs
* Fix for checking for abnormal termination of host checks
* Fix for spurious orphaned host check errors with non-scheduled hosts
* Fix for url encoding null string in CGIs (caused status CGI segfault)
* Fix for encoding URLs in macros
* Fix for bug in handling of contact groups in escalation definitions
* Changes to service check event broker logic (DNX patches)
* Minor doc updates
3.0.2 - 05/19/2008
------------------
* Minor bug fixes in CGIs to ensure extra host/servicegroup url strings are terminated properly
* Minor bug fix in navigation frame link for unhandled service problems
* Better error logging during fork() errors
* Embedded Perl is now disabled by default
* Fixed bug in parsing host dependencies
* Added note to Makefile about 'make install-webconf' option
* Fixed bug in config CGI where active host check attributes were not displayed properly
* Fixed bug in status CGI where sounds were not played for passive service problems
* Fixed sample script for distributed monitoring
* Updated p1.pl to allow for 4KB lines in Perl plugin output under epn
* Fixed bug in command for disabling contact notifications
* Fix for bugs in host and service orphan check logic
* Fix for 'make install' functionality for contrib directory
* Fix for host problem links in CGI status summary view
* Fix for properly escaping macros containing URLs
* Patches for possible XSS vulnerability in CGIs (CVE-2007-5803) - Florian Weimer & SUSE Linux team
3.0.1 - 04/01/2008
-------------------
* Fixed bug in trends CGI with user not being authorized for hosts/services
* Fixed bug in status CGI with page layout messing up when sounds enabled
3.0 - 03/13/2008
-------------------
* Faster program startup times (especially in large installs) with new object lookup code
* Fix for special contact inheritance rules in host and service escalations
* Fix for threading-related bugs that resulted in checks failing under NetBSD
* Configure script fix
* Fix for bug in processing $CONTACTADDRESSx$ macros
* Documentation fixes
3.0rc3 - 02/26/2008
-------------------
* Fix for passive service check stats bugs in nagiostats
* Nagios no longer warns or errors when encountering host/contact/service groups with empty memberships
* Debugging info fix in notification logic
* Fix for multiline support in config files (again)
* Fix for stripping illegal chars in output, perfdata macros
* Patch to allow non-ASCII characters in notifications, etc.
* Fix for bug in on-demand service macros with blank/null host names
* Fix for cleaning up zombie child processes if large installation tweaks disabled and fork twice option disabled
* Fix for incorrect total checks counts in nagiostats
* Fix for segfault if embedded Perl support compiled in, but disabled by config file option
* Smarter host check logic to reduce (uncached) on-demand host checks during "stable" service problems
* Fix for recursive subgroup membership for host/service/contact groups
* Fix for renaming/moving files on network file systems
* New flap detection startup logic speedups when large installations tweaks enabled
* Speed improvements during startup routines when using precached config
* Speed improvements in reading retention data during startup
* Safer loading mechanism for NEB modules to prevent segfaults in Nagios
* Fix for segfault in CGIs when converting object names with extended ASCII characters to URLs
3.0rc2 - 01/29/2008
-------------------
* Changed embedded audio MIME types in CGIs to "application/wav"
* Fixed bug in sample helloworld NEB module
* Modified p1.pl to allow for multiline-line output of Perl plugins under embedded Perl interpreter (epn)
* Fix for incorrect environment variables names for custom host and contact macros
* Fix for external command file thread polling code
* Fix for cfg_dir directive not working on Solaris
* Fixed segfault in extinfo CGI when passed an invalid service description/name
* Fixed bug in summary CGI with reports on specific hosts
* Fix for writing check result files under Cygwin
* Fix for not building sample helloworld.o event broker module if event broker is disabled by configure script
* Fix to sample event handler scripts
* Fix for handling plugin output with escaped newlines and backslashes
* Fix for bug in service and host event scheduling logic
* Fix for reversed object sort order when using fast startup options
* Fix for bug with notification commands not being run if notifications were not logged
3.0rc1 - 12/17/2007
-------------------
* Fixed bug where status log was left after a restart with faulty config
* Fix for compilation bug on systems that don't support setenv() (e.g. Solaris)
* Support for line continuation/breaks in config files - end lines with one backslash (\) to continue on next line
* Fixed bug with not deleting old check result files that contained results for invalid host/service
* Fixed bug with init script option to check Nagios config
* Auto-filled comment/author fields for acknowledging problems through WAP interface
* Fixed bug with processing of CONTACTGROUPNAMES, NOTES, NOTESURL, and ACTIONURL macros
* Doc fix regarding soft state dependencies
* Fix for segfault in event broker module code
3.0b7 - 11/23/2007
------------------
* Memory leak fix in macro code
* Added use_timezone option to allow Nagios instances to run in non-native timezones
* Fix for encoding HTML characters in CGIs
* Fix for unimplemented $LASTHOSTSTATE$, $LASTHOSTSTATEID$, $LASTSERVICESTATE$, and $LASTSERVICESTATEID$ macros
* Fixes for memory leaks with passive check, performance data routines
* Makefile fixes
* Code cleanup, fixes for compiler warnings
* Fix to prevent FLAPPINGSTART notifications from incorrectly being resent after program restarts
* Added free_child_process_memory and child_processes_fork_twice options for performance tweaks
* Fix for bug in processing of on-demand service macros
3.0b6 - 10/31/2007
------------------
* Logging API revamp, cleanup
* Misc internal performance improvements
* Bug fix with attempting to access an uninitalized mutex if external commands are disabled
* Updates to .cvsignore files
* Fix for embedded Perl interpreter to recache scripts when they're modified
* Fix for cancelling inheritance with 'null' in various object directives
* Additional functionality of additive inheritance feature
* Fixed bug where missing host/servicegroups in object definitions didn't always generate errors
* Increased max plugin output length cap from 4kb to 8kb
* Caching of Perl scripts now enabled by default if embedded Perl interpreter is compiled in
* Fix for segfault when contact definitions had no notification timeperiods defined
* Retention of host/service check scheduling options
* Fix for race condition when freshening host and service check results
* Added null -b option to install-sh for Solaris so install scripts don't break
* Added .gitignore files for git users
* Added new external commands to change notification period for host, services, and contact on-the-fly
* Added new external commands to change modified object attributes (affecting data retention logic)
* Added $ISVALIDTIME:$ and $NEXTVALIDTIME:$ on-demand macros
* Added enable_environment_macros option to determine whether or not macros are set as environment vars
* Major overhaul (read: complete rewrite) of macro code, so macros are now only computed when found
* Summary macros are now available as regular (non-environment) macros if requested when large installation tweaks are enabled
* Bug fix for scheduling hostgroup host downtime through web interface
* Better error logging when failing to rename/move files
* Added $LASTHOSTSTATE$, $LASTHOSTSTATEID$, $LASTSERVICESTATE$, and $LASTSERVICESTATEID$ macros
* Addition of object pointers to event broker module data structures (may require event broker module rebuilds)
* Spec file changes to better support RPM builds on 64-bit systems
* Possible fix for Unicode html encoding errors in CGIs
3.0b5 - 10/08/2007
------------------
* Minor bug fix in CSS files
* Bug fix in sample config files
* Fix for recovery notifications not being sent out when first_notification_delay option used in host/service definitions
* Fix for ochp commands not running properly
* Special additive inheritance rule: escalation contact(group)(s) that begin with '+' will now inherit from associated host/service definition if not inheriting from another escalation template
* Status file is no longer deleted during restarts due to a SIGHUP or external command
* Improvement in service flap detection logic
* Added additional_freshness_latency config file directive
* Improvements in freshness check logic
* Temporarily removed $SERVICEGROUPMEMBERS$ macro, as it was causing crashes for some users (this need further investigation)
* Added $EVENTSTARTTIME$ macro to indicate time Nagios started processing events (checks, etc.)
* Added use_pending_states option to CGI config file to determine displayed state of hosts/services that have not been checked
* Workaround to prevent browsers from incorrectly using cached statusmap image on page refresh
* Fix for incorrect latency calculations for passive host/service checks
* Added passive check latency stats to nagiostats
* Added support for relative paths in config_file and config_dir directives
* Fix for compile error under Solaris
3.0b4 - 09/27/2007
------------------
* New macros: $HOSTGROUPMEMBERS$, $HOSTGROUPNOTES$, $HOSTGROUPNOTESURL$, $HOSTGROUPACTIONURL$, $SERVICEGROUPMEMBERS$, $SERVICEGROUPNOTES$, $SERVICEGROUPNOTESURL$, $SERVICEGROUPACTIONURL$, $CONTACTGROUPALIAS$, $CONTACTGROUPMEMBERS$, $NOTIFICATIONRECIPIENTS$, $NOTIFICATIONAUTHOR$, $NOTIFICATIONAUTHORNAME$, $NOTIFICATIONAUTHORALIAS$, $NOTIFICATIONCOMMENT$
* Removed host/service downtime author/comment macros introduced in 3.0b2 in favor of more generic $NOTIFICATION...$ macros
* Fix for segfault when cancelling active scheduled host downtime
* Macro code cleanup
* Added on-demand contact and contactgroup macro support
* More complete (but still partial) support for macros in CGIs ($xNOTES$, $xNOTESURL$, and $xACTIONURL$ macros)
* Fixed bug in config CGI with displaying incorrect notification interval for escalations
* Added new 'check' option to init script to verify configuration
* Added custom host and service notifications, with option to force the notifications and broadcast them to all contacts
* Fix for on-demand/cached host check statistics
* Fixed bug where null host check command would cause high CPU utilization
* Alias, if not specified, now defaults to object name in host, hostgroup, servicegroup, contact, and contactgroup definitions
* Fixed bug with excluding hosts, services, and contacts with bang (!) in object definitions
* Fixed bug in nagiostats with NULL mrtg data arguments printing bogus string
* Added custom delimiter option in nagiostats output (useful for CSV output)
3.0b3 - 08/30/2007
------------------
* Minor bug fix for debug logging of macros
* Version number is now printed in CGI pages
* HTML documentation cleanup (HTML Tidy, link checking, etc.)
* Fixed bug where notifications would not be sent out host/service contact group members
3.0b2 - 08/29/2007
------------------
* Fix for some sample config files getting installed with .sample extension
* Improvements to the host check logic performance (more use of cached and parallel checks)
* Minor bug fix with notification timeout error messages
* Fix bug with logging of passive host and service check results
* Fixed bug with warning about no contactgroups being defined
* Internal data structure cleanups
* New macros: $SERVICEISVOLATILE$, $TOTALHOSTSERVICES$, $TOTALHOSTSERVICESOK$, $TOTALHOSTSERVICESWARNING$, $TOTALHOSTSERVICESUNKNOWN$, $TOTALHOSTSERVICESCRITICAL$, $HOSTDOWNTIMEAUTHOR$, $HOSTDOWNTIMEAUTHORNAME$, $HOSTDOWNTIMEAUTHORALIAS$, $HOSTDOWNTIMECOMMENT$, $SERVICEDOWNTIMEAUTHOR$, $SERVICEDOWNTIMEAUTHORNAME$, $SERVICEDOWNTIMEAUTHORALIAS$, $SERVICEDOWNTIMECOMMENT$
* Added 'lock_author_names' option to CGI config file to prevent alteration of author names
when submitting comments, scheduled downtime, etc.
* Fix for concatentation of multiline plugin perfdata
* Added status CGI host/service property filters for hard and soft states
3.0b1 - 07/31/2007
------------------
* Fixed bug with processing epn directives in Perl plugins
* Fixed bug with check_result_path config option being ignored
* Added $MAXHOSTATTEMPTS$ and $MAXSERVICEATTEMPTS$ macros
* Fixed bug with incorrect output returned from embedded Perl plugins
* Fixed bug where status data file was not read by CGIs using mmap()
* Fix for CGI segfault
* Program status now updated at least every 5 seconds for addons that watch NDOUtils DB
* Added escape_html_tags option to CGI config file to escape HTML tags in plugin output
* Added optional integration with Splunk into the CGIs
* Added new action and notes URL target frame options to CGI config file
* Added new 'exclude' option to timeperiod definitions for easy on-call rotation definitions
3.0a5 - 06/19/2007
------------------
* Fixed problem with multiline long plugin output and Perl plugin output
* Fixed compilation problem with embedded Perl
* More debug/trace log functionality
* Added new 'passive_host_checks_are_soft' config option
* Fixed bug with host notifications occurring during soft host states
* Fixed bug in processing multiple check results contained in a single file
* Expanded timeperiod definitions to allow for day/date exceptions
* Changes to sample config files and installation location
* Changed debug file format to include current pid
* Added 'initial_state' option to host and service definitions to allow for non-UP/OK initial states
* Minor changes to freshness threshold calculation
* Documentation updates
3.0a4 - 05/08/2007
------------------
* Fix for segfault fix when low priority event queue's only item is removed
* Added test for writeability of temp directory during configuration test
* Fix for unescaping backslashes in plugin output in the CGIs
* Removed check_result_buffer_slots option from main configuration file
* New IPC method for passing host/service check results back to main daemon
* Added check_result_path option to set path used to store check results
* Added max_check_result_file_age option to control processing of check results in older files
* Added new --with-temp-dir option to configure script
* Removed legacy 2.x host check logic and use_old_host_check_logic option
* Removed DEBUGx options from configure script
* Added new debug/trace log functionaltiy (only partially complete)
* Fixed compilation error under OSX
* Fix for SIGTERMs being seen as SIGEXITs, non-logging of SIGTERMs/shutdowns
3.0a3 - 04/10/2007
------------------
* Configure script fix for no mail program found/installed on system
* Fix for compilation warnings about implicit declaration of round() - may (strangely enough) also
fix segfaults that were occuring on some systems
* Added detection of Apache conf.d directory and 'make install-webconf' functionality
* Configure script option bug fixes for cygwin and embedded perl
* Added buffer stats and check statistics to performance information in extinfo CGI
* Hostgroup and servicegroup definitions now have notes, notes_url, and action_url directives
* Patch for incorrect time down percentage in availability CGI
* Command definitions and host/service plugin perfdata with HTML should now be escaped in CGIs
* Updated init script to fix a race condition during restarts
* Documentation updates
3.0a2 - 03/27/2007
------------------
* Added warning about aggregate_status_updates directive being deprecated.
* Added new "p" option to host/service_perfdata_file_mode directives for pipes.
* Fix for incorrect performance data file write/append mode options
* Regular expression matching in object config files now also triggered by '+' and '\.'
* Added support for extended regular expression matching in object config files
* Fix for incorrect processing of y_2d coordinates for host objects in statusmap layout
* Fix for current status of hosts with no check command defined
* SIGSEGV signals should now be logged again (broken in 3.0a1)
* Added warning for invalid temp_path directory
* Documentation bug fixes and updates
3.0a1 - 03/06/2007
------------------
Here are all the changes since Nagios 2.x:
* Adaptive monitoring:
- Check timeperiod can now be modified on-the-fly
* Notification changes:
- Added first_notification_delay to host and object definitions to delay first notification
- Notifications are now sent out when flap detection is disabled on a host/service-specific
or program-wide basis ($NOTIFICATIONTYPE$ macro = "FLAPPINGDISABLED")
- Notifications can now be sent out when scheduled downtime starts, ends, and is cancelled. The
$NOTIFICATIONTYPE$ macro will be set to "DOWNTIMESTART", "DOWNTIMEEND", or "DOWNTIMECANCELLED",
respectively. In order to receive downtime notifications, specify 's' or 'downtime' in contact, host,
and/or service notification options.
* Object changes:
- Added ability to use multiple template names (separated by commas) in object definitions
- Added ability to null out optional character directives in object definitions (using 'null' without quotes)
- Added hostg/service/contactgroup_members directives to host/service/contactgroup definitions,
respectively, for allowing including host, service, or contact members from "sub" groups.
- Added support for custom variables in host, service, and contact definitions
- Added host_notifications_enabled, service_notifications_enabled, can_submit_commands to contact definitions
- Added optional display_name directive to host and service definitions
- Removed serviceextinfo definitions and merged variables with service definitions
- Removed hostextinfo definitions and merged variables with host definitions
- Services inherit contactgroups, notification interval, and notification period from associated host if not specified
- Service escalations inherit contactgroups, notification interval, and escalation period from associated service if not specified
- Host escalations inherit contactgroups, notification interval, and escalation period from associated host if not specified
- Host, service, host escalation, and service escalation definitions now support a 'contacts' directive, along with 'contact_groups'
- Service dependencies with blank dependent host/hostgroup names will create "same host" dependencies
* Performance optimizations:
- Added ability to precache object config files
- Added ability to exclude object relationship and circular path
checks from verification process
* Check output:
- Multiline output support for host and service checks
* Macro changes:
- Added $LONGHOSTOUTPUT$ and $LONGSERVICEOUTPUT$ macros
- Added $TEMPPATH$ macro
- Removed $COMMENTDATAFILE$ and $DOWNTIMEDATAFILE$ macros
- Added $HOSTDISPLAYNAME$ and $SERVICEDISPLAYNAME$ macros
- Custom host/service/contact macros accessible via $_HOST<varname>$, $_SERVICE<varname>, or $_CONTACT<varname>$.
On-demand host/service macros for custom vars are working. Custom vars are also set as environment vars.
- On-demand service macros can contain and empty host name field. In this case, the name of the current host will be used.
- $HOSTNOTES$ and $SERVICENOTES$ macros may now contain macros themselves
* Flapping changes:
- Added flap_detection_options directive to host and service definitions to control which
states (i.e. OK, WARNING, UNKNOWN, and/or CRITICAL) are used in flap detection logic
- Percent state change and state history are now retained and recorded even when host/service
flap detection is disabled.
- Hosts and services are immediately check for flapping when flap detection is enabled program-wide.
- Hosts/services that are flapping when flap detection is disabled program-wide are now logged
* External command changes:
- Added PROCESS_FILE external command to allow processing of external commands found in
an external (regular) file. Very useful for passive checks with long output or scripting.
- Custom commands can now be submitted to Nagios. Custom command names are prefixed with an underscore
and are not processed internally by the Nagios daemon. They may, however, be processed by NEB modules.
- External commands are now checked by default. Nagios 2.x and earlier did not check for external commands
by default.
* Status data changes:
- Contact status information is now saved (although it is not processed by the old CGIs)
* Retention data changes:
- Contact status information is now retained across program restarts
- Comment and downtime IDs are now stored across program restarts, should be unique unless reset
- Added retained_host/service_attribute_mask variables to control what host/service attribs are retained globally
- Added retained_process_host/service_attribute_mask variables to control what process attribs are retained
- Added retained_contact_host/service_attribute_mask variables to control what contact attribs are retained globally
* Downtime changes:
- Scheduled downtime entries are now stored in the status and retention files
* Comment changes:
- Comments are now stored in the status and retention files
- Non-persistent acknowledgement comments are now deleted when the acknowledgement is removed (instead of when Nagios restarts)
* Host check logic changes:
- Most host checks are now run asynchronously, in parallel!
- Scheduled host checks now help improve performance, instead of hinder it (if caching is enabled)
- Added cached_host_check_horizon option for enabling use of cached host check results
- Added enable_predictive_host_dependency_checks for enabling predictive checks of dependent hosts
- Added retry_interval to host definitions
- Added check_for_orphaned_hosts option and support for orphaned host checks
- Passive host check states can now be translated from their original DOWN/UNREACHABLE state if the
new translate_passive_host_results option is enabled
* Service check logic changes:
- 'parallelize' option in service definitions deprecated/no longer used
- Added cached_service_check_horizon option for enabling use of cached service check results
- Added enable_predictive_service_dependency_checks for enabling predictive checks of dependent services
* Dependency changes:
- Host and service dependencies can now have a timeperiod during which they're valid (dependency_period directive)
* Event broker changes:
- Updated NEB API version
- Modified adaptive program status callback
- Added adaptive contact status callback
- Added host/service precheck callbacks to allow modules to cancel/override internal host/service checks
* Embedded Perl changes:
- Added 'enable_embedded_perl' option to main config file to control whether epn is enabled/disabled
- Added support for perl plugins to specify whether or not they should be run under the epn... The
second to tenth line of a perl plugin may start with '# nagios: +epn' or '# nagios: -epn' to explicity indicate that it
should be run under the epn.
- Added 'use_embedded_perl_implicitly' option to main config file to determine whether or not perl
plugins will use the epn if they don't explicitly allow/disalow it
* CGI changes:
- Hostgroup and servicegroup summaries now show important/unimportant problem breakdowns like the TAC CGI
- Minor layout changes to host and service detail views in extinfo CGI
* Misc changes:
- More information given when testing scheduling (-s command line option)
- Removed fixed length restrictions for host names and service descriptions
- Plugin output length restriction bumped up to 4K
- Added temp_path directive to main config file for specifying temp directory
- Multiline output support for system commands via my_system()
- Added global event_id and notification_id vars that are at least unique during a single run of Nagios
- Default is now to check for orphaned services, rather than not
- Renamed service_reaper_frequency to check_result_reaper_frequency
- Fractional notification and check intervals are now supported (e.g. "3.5" minutes)
- Backslash chars are now used to escape command arguments that contain \ or ! characters
- Added 'external_command_buffer_slots' and 'check_result_buffer_slots' variables to specify size of internal buffers
- Added check statistics to status file, available via nagiostats for graphing in MRTG
- Added $HOSTGROUPNAMES$, $SERVICEGROUPNAMES$, $HOSTACKAUTHORNAME$, $HOSTACKAUTHORALIAS$, $SERVICEACKAUTHORNAME$,
and $SERVICEACKAUTHORALIAS$ macros

17
INSTALLING Normal file
View File

@ -0,0 +1,17 @@
Nagios Installation Instructions
--------------------------------
A quickstart installation guide can now be found in the HTML
documentation. You can find the quickstart guide (quickstart.html)
in the following subdirectory:
html/docs/
The quickstart covers all the basic steps you need to follow
to install Nagios, the Nagios plugins, and start out monitoring
the machine that Nagios is installed on.
Good luck!

11
LEGAL Normal file
View File

@ -0,0 +1,11 @@
All source code, binaries, documentation, information, and other files
contained in this distribution are provided AS IS with NO WARRANTY OF
ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS
FOR A PARTICULAR PURPOSE.
Nagios and the Nagios logo are trademarks, servicemarks, registered
trademarks or registered servicemarks owned by Nagios Enterprises, LLC.
All other trademarks, servicemarks, registered trademarks, and
registered servicemarks are the property of their respective owner(s).

340
LICENSE Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

379
Makefile.in Normal file
View File

@ -0,0 +1,379 @@
###############################
# Makefile for Nagios
#
# Last Modified: 04-13-2008
###############################
# Source code directories
SRC_BASE=@srcdir@/base
SRC_CGI=@srcdir@/cgi
SRC_HTM=@srcdir@/html
SRC_MODULE=@srcdir@/module
SRC_INCLUDE=@srcdir@/include
SRC_COMMON=@srcdir@/common
SRC_XDATA=@srcdir@/xdata
SRC_CONTRIB=@srcdir@/contrib
SRC_TTAP=@srcdir@/t-tap
CC=@CC@
CFLAGS=@CFLAGS@ @DEFS@
LDFLAGS=@LDFLAGS@ @LIBS@
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CHECKRESULTDIR=@CHECKRESULTDIR@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
CGIDIR=@sbindir@
LIBEXECDIR=@libexecdir@
HTMLDIR=@datadir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
HTTPD_CONF=@HTTPD_CONF@
INIT_DIR=@init_dir@
INIT_OPTS=-o root -g root
CGICFGDIR=$(CGIDIR)
PERLDIR=@PERLDIR@
USE_EVENTBROKER=@USE_EVENTBROKER@
USE_LIBTAP=@USE_LIBTAP@
INSTALLPERLSTUFF=@INSTALLPERLSTUFF@
CGIEXTRAS=@CGIEXTRAS@
SNPRINTF_O=@SNPRINTF_O@
CP=@CP@
@SET_MAKE@
none:
@echo "Please supply a command line argument (i.e. 'make all'). Other targets are:"
@echo " nagios cgis contrib modules"
@echo " clean"
@echo " install install-base install-cgis install-html install-exfoliation install-config install-init install-commandmode fullinstall"
# @echo " uninstall"
# FreeBSD make does not support -C option, so we'll use the Apache style... (patch by Stanley Hopcroft 12/27/1999)
pretty: indent
indent:
@sh indent-all.sh
ctags:
ctags -R
all:
cd $(SRC_BASE) && $(MAKE)
cd $(SRC_CGI) && $(MAKE)
cd $(SRC_HTM) && $(MAKE)
if [ x$(USE_EVENTBROKER) = xyes ]; then \
cd $(SRC_MODULE) && $(MAKE); \
fi
@echo ""
@echo "*** Compile finished ***"
@echo ""
@echo "If the main program and CGIs compiled without any errors, you"
@echo "can continue with installing Nagios as follows (type 'make'"
@echo "without any arguments for a list of all possible options):"
@echo ""
@echo " make install"
@echo " - This installs the main program, CGIs, and HTML files"
@echo ""
@echo " make install-init"
@echo " - This installs the init script in $(DESTDIR)$(INIT_DIR)"
@echo ""
@echo " make install-commandmode"
@echo " - This installs and configures permissions on the"
@echo " directory for holding the external command file"
@echo ""
@echo " make install-config"
@echo " - This installs *SAMPLE* config files in $(DESTDIR)$(CFGDIR)"
@echo " You'll have to modify these sample files before you can"
@echo " use Nagios. Read the HTML documentation for more info"
@echo " on doing this. Pay particular attention to the docs on"
@echo " object configuration files, as they determine what/how"
@echo " things get monitored!"
@echo ""
@echo " make install-webconf"
@echo " - This installs the Apache config file for the Nagios"
@echo " web interface"
@echo ""
@echo " make install-exfoliation"
@echo " - This installs the Exfoliation theme for the Nagios"
@echo " web interface"
@echo ""
@echo " make install-classicui"
@echo " - This installs the classic theme for the Nagios"
@echo " web interface"
@echo ""
@echo ""
@echo "*** Support Notes *******************************************"
@echo ""
@echo "If you have questions about configuring or running Nagios,"
@echo "please make sure that you:"
@echo ""
@echo " - Look at the sample config files"
@echo " - Read the documentation on the Nagios Library at:"
@echo " http://library.nagios.com"
@echo ""
@echo "before you post a question to one of the mailing lists."
@echo "Also make sure to include pertinent information that could"
@echo "help others help you. This might include:"
@echo ""
@echo " - What version of Nagios you are using"
@echo " - What version of the plugins you are using"
@echo " - Relevant snippets from your config files"
@echo " - Relevant error messages from the Nagios log file"
@echo ""
@echo "For more information on obtaining support for Nagios, visit:"
@echo ""
@echo " http://support.nagios.com"
@echo ""
@echo "*************************************************************"
@echo ""
@echo "Enjoy."
@echo ""
nagios:
cd $(SRC_BASE) && $(MAKE)
config:
@echo "Sample config files are automatically generated once you run the"
@echo "configure script. You can install the sample config files on your"
@echo "system by using the 'make install-config' command."
cgis:
cd $(SRC_CGI) && $(MAKE)
html:
cd $(SRC_HTM) && $(MAKE)
contrib:
cd $(SRC_CONTRIB) && $(MAKE)
modules:
cd $(SRC_MODULE) && $(MAKE)
clean:
cd $(SRC_BASE) && $(MAKE) $@
cd $(SRC_CGI) && $(MAKE) $@
cd $(SRC_COMMON) && $(MAKE) $@
cd $(SRC_XDATA) && $(MAKE) $@
cd $(SRC_HTM) && $(MAKE) $@
cd $(SRC_INCLUDE) && $(MAKE) $@
cd $(SRC_CONTRIB) && $(MAKE) $@
cd $(SRC_MODULE) && $(MAKE) $@
cd $(SRC_TTAP) && $(MAKE) $@
rm -f *.cfg core
rm -f *~ *.*~ */*~ */*.*~ */*/*.*~
distclean: clean
cd $(SRC_BASE) && $(MAKE) $@
cd $(SRC_CGI) && $(MAKE) $@
cd $(SRC_COMMON) && $(MAKE) $@
cd $(SRC_XDATA) && $(MAKE) $@
cd $(SRC_HTM) && $(MAKE) $@
cd $(SRC_INCLUDE) && $(MAKE) $@
cd $(SRC_CONTRIB) && $(MAKE) $@
cd $(SRC_MODULE) && $(MAKE) $@
cd $(SRC_TTAP) && $(MAKE) $@
rm -f sample-config/*.cfg sample-config/*.conf sample-config/template-object/*.cfg
rm -f daemon-init pkginfo
rm -f Makefile subst
rm -f config.log config.status config.cache
rm -f tags
devclean: distclean
test:
$(MAKE) test-perl
$(MAKE) test-tap
test-tap: tap/src/tap.o nagios cgis
@if [ x$(USE_LIBTAP) = xyes ]; then \
cd $(SRC_TTAP) && $(MAKE) test; \
else \
echo "NOTE: You must run configure with --enable-libtap to run the C tap tests"; \
fi
tap/src/tap.o:
cd tap && $(MAKE)
test-perl: cgis
cd t && $(MAKE) test
install-html:
cd $(SRC_HTM) && $(MAKE) install
make install-exfoliation
install-base:
cd $(SRC_BASE) && $(MAKE) install
install-cgis:
cd $(SRC_CGI) && $(MAKE) install
install:
cd $(SRC_BASE) && $(MAKE) $@
cd $(SRC_CGI) && $(MAKE) $@
cd $(SRC_HTM) && $(MAKE) $@
$(MAKE) install-exfoliation
$(MAKE) install-basic
install-unstripped:
cd $(SRC_BASE) && $(MAKE) $@
cd $(SRC_CGI) && $(MAKE) $@
cd $(SRC_HTM) && $(MAKE) $@
$(MAKE) install-exfoliation
$(MAKE) install-basic
install-basic:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBEXECDIR)
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(LOGDIR)
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(LOGDIR)/archives
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CHECKRESULTDIR)
if [ $(INSTALLPERLSTUFF) = yes ]; then \
$(INSTALL) -m 664 $(INSTALL_OPTS) p1.pl $(DESTDIR)$(BINDIR); \
fi;
@echo ""
@echo "*** Main program, CGIs and HTML files installed ***"
@echo ""
@echo "You can continue with installing Nagios as follows (type 'make'"
@echo "without any arguments for a list of all possible options):"
@echo ""
@echo " make install-init"
@echo " - This installs the init script in $(DESTDIR)$(INIT_DIR)"
@echo ""
@echo " make install-commandmode"
@echo " - This installs and configures permissions on the"
@echo " directory for holding the external command file"
@echo ""
@echo " make install-config"
@echo " - This installs sample config files in $(DESTDIR)$(CFGDIR)"
@echo ""
install-config:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CFGDIR)
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CFGDIR)/objects
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/nagios.cfg $(DESTDIR)$(CFGDIR)/nagios.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/cgi.cfg $(DESTDIR)$(CFGDIR)/cgi.cfg
$(INSTALL) -b -m 660 $(INSTALL_OPTS) sample-config/resource.cfg $(DESTDIR)$(CFGDIR)/resource.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/templates.cfg $(DESTDIR)$(CFGDIR)/objects/templates.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/commands.cfg $(DESTDIR)$(CFGDIR)/objects/commands.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/contacts.cfg $(DESTDIR)$(CFGDIR)/objects/contacts.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/timeperiods.cfg $(DESTDIR)$(CFGDIR)/objects/timeperiods.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/localhost.cfg $(DESTDIR)$(CFGDIR)/objects/localhost.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/windows.cfg $(DESTDIR)$(CFGDIR)/objects/windows.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/printer.cfg $(DESTDIR)$(CFGDIR)/objects/printer.cfg
$(INSTALL) -b -m 664 $(INSTALL_OPTS) sample-config/template-object/switch.cfg $(DESTDIR)$(CFGDIR)/objects/switch.cfg
@echo ""
@echo "*** Config files installed ***"
@echo ""
@echo "Remember, these are *SAMPLE* config files. You'll need to read"
@echo "the documentation for more information on how to actually define"
@echo "services, hosts, etc. to fit your particular needs."
@echo ""
install-webconf:
$(INSTALL) -m 644 sample-config/httpd.conf $(DESTDIR)$(HTTPD_CONF)/nagios.conf
@echo ""
@echo "*** Nagios/Apache conf file installed ***"
@echo ""
install-exfoliation:
cp -rf contrib/exfoliation/stylesheets/* $(DESTDIR)$(HTMLDIR)/stylesheets
cp -rf contrib/exfoliation/images/* $(DESTDIR)$(HTMLDIR)/images
@echo ""
@echo "*** Exfoliation theme installed ***"
@echo "NOTE: Use 'make install-classicui' to revert to classic Nagios theme";
@echo ""
install-classicui:
cp -rf html/stylesheets/* $(DESTDIR)$(HTMLDIR)/stylesheets
cp -rf html/images/* $(DESTDIR)$(HTMLDIR)/images
@echo ""
@echo "*** Classic theme installed ***"
@echo "NOTE: Use 'make install-exfoliation' to use new Nagios theme";
@echo ""
install-init: install-daemoninit
install-daemoninit:
$(INSTALL) -m 755 -d $(INIT_OPTS) $(DESTDIR)$(INIT_DIR)
$(INSTALL) -m 755 $(INIT_OPTS) daemon-init $(DESTDIR)$(INIT_DIR)/nagios
@echo ""
@echo "*** Init script installed ***"
@echo ""
install-commandmode:
$(INSTALL) -m 775 $(COMMAND_OPTS) -d $(DESTDIR)$(LOGDIR)/rw
chmod g+s $(DESTDIR)$(LOGDIR)/rw
@echo ""
@echo "*** External command directory configured ***"
@echo ""
fullinstall: install install-init install-commandmode install-webconf
# Uninstall is too destructive if base install directory is /usr, etc.
#uninstall:
# rm -rf $(DESTDIR)$(BINDIR)/nagios $(DESTDIR)$(CGIDIR)/*.cgi $(DESTDIR)$(CFGDIR)/*.cfg $(DESTDIR)$(HTMLDIR)
#
# Targets for creating packages on various architectures
#
# Solaris pkgmk
PACKDIR=@PACKDIR@
VERSION=@VERSION@
Prototype:
if [ ! -d $(PACKDIR) ] ; then mkdir $(PACKDIR); fi
if [ ! -d $(PACKDIR)/etc ] ; then mkdir $(PACKDIR)/etc; fi
if [ ! -d $(PACKDIR)/etc/init.d ] ; then mkdir $(PACKDIR)/etc/init.d; fi
if [ ! -d $(PACKDIR)/etc/nagios ] ; then mkdir $(PACKDIR)/etc/nagios; fi
$(MAKE) all
$(MAKE) DESTDIR=$(PACKDIR) INIT_OPTS='' INSTALL_OPTS='' COMMAND_OPTS='' nagios_grp='' nagios_usr='' fullinstall
$(INSTALL) -m 644 sample-config/nagios.cfg $(PACKDIR)$(CFGDIR)/nagios.cfg.$(VERSION)
$(INSTALL) -m 644 sample-config/cgi.cfg $(PACKDIR)$(CFGDIR)/cgi.cfg.$(VERSION)
$(INSTALL) -m 640 sample-config/resource.cfg $(PACKDIR)$(CFGDIR)/resource.cfg.$(VERSION)
$(INSTALL) -m 664 sample-config/template-object/bigger.cfg $(PACKDIR)$(CFGDIR)/bigger.cfg.$(VERSION)
$(INSTALL) -m 664 sample-config/template-object/minimal.cfg $(PACKDIR)$(CFGDIR)/minimal.cfg.$(VERSION)
$(INSTALL) -m 664 sample-config/template-object/checkcommands.cfg $(PACKDIR)$(CFGDIR)/checkcommands.cfg.$(VERSION)
$(INSTALL) -m 664 sample-config/template-object/misccommands.cfg $(PACKDIR)$(CFGDIR)/misccommands.cfg.$(VERSION)
cd contrib; $(MAKE) all; $(MAKE) DESTDIR=$(PACKDIR) INIT_OPTS='' INSTALL_OPTS='' COMMAND_OPTS='' nagios_grp='' nagios_usr='' install
echo i pkginfo> Prototype
if [ -f checkinstall ] ; then echo i checkinstall>> Prototype; fi
if [ -f preinstall ] ; then echo i preinstall>> Prototype; fi
if [ -f postinstall ] ; then echo i postinstall>> Prototype; fi
pkgproto $(PACKDIR)=/ | sed -e "s|$(LOGNAME) $(GROUP)$$|root root|" | egrep -v "(s|d) none (/|/etc|/var|/usr|/usr/local) " >> Prototype
pkg/nagios/pkgmap: Prototype
mkdir $(PACKDIR)/nagios
pkgmk -o -r / -f Prototype -d $(PACKDIR) nagios
nagios.SPARC.pkg.tar.gz: pkg/nagios/pkgmap
cd $(PACKDIR) && tar -cf - nagios | gzip -9 -c > ../nagios.SPARC.pkg.tar.gz
pkgset: nagios.SPARC.pkg.tar.gz
pkgclean:
rm -rf pkg Prototype nagios.SPARC.pkg.tar.gz
# Targets that always get built
.PHONY: indent clean clean distclean

39
OutputTrap.pm Normal file
View File

@ -0,0 +1,39 @@
package OutputTrap;
#
# Methods for use by tied STDOUT in embedded PERL module.
#
# Simply redirects STDOUT to a temporary file associated with the
# current child/grandchild process.
#
use strict;
# Perl before 5.6 does not seem to have warnings.pm ???
#use warnings;
use IO::File;
sub TIEHANDLE {
my ($class, $fn) = @_;
my $handle = new IO::File "> $fn" or die "Cannot open embedded work filei $!\n";
bless { FH => $handle, Value => 0}, $class;
}
sub PRINT {
my $self = shift;
my $handle = $self -> {FH};
print $handle join("",@_);
}
sub PRINTF {
my $self = shift;
my $fmt = shift;
my $handle = $self -> {FH};
printf $handle ($fmt,@_);
}
sub CLOSE {
my $self = shift;
my $handle = $self -> {FH};
close $handle;
}
1;
__END__

29
README Normal file
View File

@ -0,0 +1,29 @@
Nagios 3.x README
-----------------
Nagios is a host/service/network monitoring program written in C and
released under the GNU General Public License. CGI programs are
included to allow you to view the current status, history, etc via
a web interface if you so desire.
Features:
1) Monitoring of network services (via SMTP, POP3, HTTP, PING, etc).
2) A plugin interface to allow for user-developed service monitoring methods.
3) Notifications when problems occur and get resolved (via email, pager,
or user-defined method).
4) Ability to define "event handlers" for proactive problem resolution
5) Web output (current status, notifications, problem history, log file, etc.)
6) Automatic log file rotation/archiving
For installation instructions, use a web browser to read the HTML documentation
in the html/docs subdirectory.
Visit the Nagios homepage at http://www.nagios.org for online
documentation, new releases, bug reports, information on the mailing
lists, etc.
-- Ethan Galstad (egalstad@nagios.org)

303
THANKS Normal file
View File

@ -0,0 +1,303 @@
=======
THANKS!
=======
The success of Nagios has been due to the fantastic community members that
support it and provide bug reports, patches, and great ideas. Here are a
few of the many members that have contributed to Nagios in various ways
since 1999. If I missed your name, let me know.
* Greg Abrams
* Petr Adamec
* Gavin Adams
* David Allan
* Felipe Almeida
* Markus Almroth
* Jon Andrews
* Michael Anthon
* Bernd Arnold
* Erwan Arzur
* Volker Aust
* Hendrik Baecker
* Markus Baertschi
* Michael Bailey
* Luigi Balzano
* Sebastien Barbereau
* Wolfgang Barth
* Devin Bayer
* Simon Beale
* Ben Bell
* Marlo Bell
* Ray Bengen
* Derrick Bennett
* Chris Bensend
* Kevin Benton
* Gary Berger
* Sven-Göran Bergh
* Jochen Bern
* Tom Bertelson
* Joel Berry
* Olivier Beytrison
* Christoph Biedl
* Dennis Biringer
* Mike Bird
* Jason Blakey
* Jeffrey Blank
* Ian Blenke
* Fran Boon
* Jeremy Bouse
* Adam Bowen
* Ludo Bosmans
* Henning Brauer
* Michael Bunk
* Daniel Burke
* Grant Byers
* John Calcote
* Don Carroll
* Ian Cass
* Alexios Chouhoulas
* Allan Clark
* Jonathan Clarke
* Justin Clarke
* Perry Clarke
* Nick Cleaton
* Charlie Cook
* Garry Cook
* Jeff Cours
* Michelle Craft
* Matthias Cramer
* Matthieu Kermagoret
* Jim Crilley
* Joel Crisp
* Jean-Eric Cuendet
* Ahmon Dancy
* Jan David
* Stephen Davies
* Karl DeBisschop
* Tom De Blende
* Mark DeTrano
* Thomas Dohl
* Mike Dorman
* Albrecht Dress
* Alok Dubey
* Jim Dumser
* Thomas Dunkel
* Matthias Eble
* Ari Edelkind
* Matthias Eichler
* Rob Enders
* Andreas Ericsson
* Matt Ezell
* Sylvain Falardeau
* Duncan Ferguson
* Sean Finney
* Andy Finkenstadt
* Mika Fischer
* Matthias Flacke
* Marcus Fleige
* Matthias Flittner
* Bastian Friedrich
* Jean Gabes
* Szabo Gabor
* Mathieu Gagne
* Dan Gailey
* Darren Gamble
* Robert Gash
* Hugo Gayosso
* Subhendu Ghosh
* Mark Goldfinch
* Jeffrey Goldschrafe
* Jan Grant
* Stephen Gran
* Matthew Grant
* Martin Green
* Todd Green
* Nathan Grennan
* Sebastian Guarino
* Thomas Guyot-Sionnest
* Sergio Guzman
* Hugo Hallqvist
* Lars Hansson
* Ben Heavner
* Lars Hecking
* Jason Hedden
* Karl Hegbloom
* Thomas Hepper
* Marcus Hildenbrand
* Arne Hinrichsen
* Ronald Ho
* Stanley Hopcroft
* Sam Howard
* Torsten Huebler
* Stig Jacobsen
* Percy Jahn
* Stewart James
* Olivier Jan
* Jeff Johnson
* Jonathan Kamens
* Andrew Kaplan
* Lars Kellogg-Stedman
* Paul Kent
* Matthieu Kermagoret
* Matthias Kerk
* Bo Kersey
* Andreas Kirchwitz
* Burkhard Klaus
* Tobias Klausmann
* Igno Kley
* Rene Klootwijk
* David Kmoch
* Brandon Knitter
* Uwe Knop
* Ryoji Kobayashi
* Uwe Knop
* Daniel Koffler
* Petya Kohts
* Chris Kolquist
* Jiri Kostern
* Christoph Kron
* Ivan Kuncl
* Dean Lane
* Ingo Lantschner
* Gerhard Lausser
* William Leibzon
* Pedro Leite
* Bernard Li
* Joerg Linge
* Michael Little
* Shad Lords
* Larry Low
* Michael Lubben
* Tyler Lund
* Jacob Lundqvist
* James Maddison
* Joseph Maiorana
* Ricardo Maraschini
* Michael Marineau
* Roberto Marrodan
* Ernst-Deiter Martin
* Christoph Maser
* Christian Masopust
* Emanuel Massano
* Richard Mayhew
* Mike McHenry
* Gordon Messmer
* Lars Michelson
* Martin Mielke
* Christian Mies
* Gary Miller
* Peter Valdemar Morch
* James Moseley
* Tobias Mucke
* Gerd Mueller
* Bob (Netshell)
* Time Niemueller
* Sven Nierlein
* Michael O'Reilly
* Tomer Okavi
* Vadim Okun
* Hiren Patel
* Rob Patrick
* Remi Paulmier
* Alex Peeters
* James "Showkilr" Peterson
* Cary Petterborg
* Bill Pier
* Badri Pillai
* Steven Pokrandt
* Jim Popovitch
* Janet Post
* Paul Pot
* Daniel Pouzzner
* Marc Powell
* William Preston
* Patrick Proy
* Luiz Felipe R E
* Alain Radix
* Kenneth Ray
* Nick Reinking
* Rob Remus
* Alessandro Ren
* Bob Rentschler
* Mindaugas Riauba
* Matthew Richardson
* Dietmar Rieder
* Brian Riggs
* Peter Ringe
* Eirik Robertstad
* Stefan Rompf
* Amir Rosenblatt
* Luke Ross
* Ralph Rossner
* Chris Rothecker
* John Rouillard
* Yves Rubin
* Mattias Ryrlen
* Jonathan Saggau
* Karel Salavec
* Jorge Sanchez
* Bogdan Sandu
* Pavel Satrapa
* Frederic Schaer
* Mark Schenker
* David Schlecht
* Russell Scibetti
* Max Schubert
* Stefan Schurtz
* Thomas Sebastien
* Brian Seklecki
* Denis Seleznyov
* Lonny Selinger
* Nate Shafer
* Moshe Sharon
* Andy Shellam
* Nick Shore
* Ryan Skorstad
* Michael Smedius
* Gordon Smith
* Lou Sneddon
* Mark Spieth
* Tim Starling
* Thomas Stolle
* Kevin Stone
* Herbert Straub
* Sven Strickroth
* SUSE Linux Team
* Horvath Tamas
* Nicholas Tang
* Glenn Thompson
* Robert Thompson
* Josh Thorstad
* David Tilloy
* Gennaro Tortone
* Steve Underwood
* Kai Ung
* Stephane Urbanovski
* Franky Van Liedekerke
* Nikola Vassilev
* Esteban Manchado Velazquez
* Geert Vanderkelen
* Carlos Velasco
* Jan Vejvalka
* Robert August Vincent II
* Dave Viner
* Ton Voon
* Lars Vogdt
* Phil Walther
* Jeremy Weatherford
* Holger Weiss
* Tom Welsh
* Brad Werschler
* Peter Westlake
* Todd Wheeler
* Florian Weimer
* Tim Wilde
* Chris Witterholt
* Evan Winter
* Armin Wolfermann
* Greg Woods
* Cliff Woolley
* Mitch Wright
* Michal Zimen
* Pawel Zuzelski
* Anders K. Lindgren

19
UPGRADING Normal file
View File

@ -0,0 +1,19 @@
Upgrading to Nagios 3.x
-----------------------
The HTML documentation covers what you need to know in order
to upgrade from Nagios 2.x You can find the documentation in
the following subdirectory:
html/docs
Make sure to read the following sections:
- "What's New" (whatsnew.html)
- "Upgrading Nagios" (upgrading.html)

3
base/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
nagios
nagiostats

213
base/Makefile.in Normal file
View File

@ -0,0 +1,213 @@
############################
# Makefile for Nagios
#
# Last Modified: 12-05-2008
############################
# Source code directories
SRC_COMMON=../common
SRC_INCLUDE=../include
SRC_XDATA=../xdata
CC=@CC@
CFLAGS=-Wall @CFLAGS@ @DEFS@ -DNSCORE
# Compiler flags for use with gprof
#CFLAGS=-pg -DHAVE_CONFIG_H -DNSCORE
# Compiler flags for use with Valgrind
#CFLAGS=-O0 -g -DHAVE_CONFIG_H -DNSCORE
# Compiler flags for optimization (overrides default)
#CFLAGS=-O3 -Wall -fno-strict-aliasing -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -DHAVE_CONFIG_H -DNSCORE
# Compiler flags for optimization (complements default)
#CFLAGS_WARN=-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs
#CFLAGS_DEBUG=-ggdb3 -g3
#CFLAGS_GPROF=-pg
#CFLAGS+=$(CFLAGS_WARN) $(CFLAGS_DEBUG) $(CFLAGS_GPROF)
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
CGIDIR=@sbindir@
HTMLDIR=@datarootdir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
STRIP=@STRIP@
CGIURL=@cgiurl@
HTMURL=@htmurl@
MATHLIBS=-lm
PERLLIBS=@PERLLIBS@
PERLXSI_O=@PERLXSI_O@
SOCKETLIBS=@SOCKETLIBS@
THREADLIBS=@THREADLIBS@
BROKERLIBS=@BROKERLIBS@
BROKER_LDFLAGS=@BROKER_LDFLAGS@
CP=@CP@
# External data I/O code and headers
XSDC=@XSDC@
XSDH=@XSDH@
XCDC=@XCDC@
XCDH=@XCDH@
XRDC=@XRDC@
XRDH=@XRDH@
XODC=@XODC@
XODH=@XODH@
XPDC=@XPDC@
XPDH=@XPDH@
XDDC=@XDDC@
XDDH=@XDDH@
# Extra base code
BASEEXTRALIBS=@BASEEXTRALIBS@
# Generated automatically from configure script
SNPRINTF_O=@SNPRINTF_O@
BROKER_O=@BROKER_O@
BROKER_H=@BROKER_H@
# Object data
#ODATALIBS=$(SRC_COMMON)/objects.c $(SRC_XDATA)/$(XODC)
#ODATAHDRS=$(SRC_INCLUDE)/objects.h $(SRC_XDATA)/$(XODH)
ODATALIBS=objects-base.o xobjects-base.o
ODATAHDRS=
ODATADEPS=$(ODATALIBS)
# Retention data
#RDATALIBS=sretention.o $(SRC_XDATA)/$(XRDC)
#RDATAHDRS=$(SRC_INCLUDE)/sretention.h $(SRC_XDATA)/$(XRDH)
RDATALIBS=retention-base.o xretention-base.o
RDATAHDRS=
RDATADEPS=$(RDATALIBS)
# Comment data
#CDATALIBS=$(SRC_COMMON)/comments.c $(SRC_XDATA)/$(XCDC)
#CDATAHDRS=$(SRC_INCLUDE)/comments.h $(SRC_XDATA)/$(XCDH)
CDATALIBS=comments-base.o xcomments-base.o
CDATAHDRS=
CDATADEPS=$(CDATALIBS)
# Status data
#SDATALIBS=$(SRC_COMMON)/statusdata.c $(SRC_XDATA)/$(XSDC)
#SDATAHDRS=$(SRC_INCLUDE)/statusdata.h $(SRC_XDATA)/$(XSDH)
SDATALIBS=statusdata-base.o xstatusdata-base.o
SDATAHDRS=
SDATADEPS=$(SDATALIBS)
# Performance data
#PDATALIBS=perfdata.o $(SRC_XDATA)/$(XPDC)
#PDATAHDRS=$(SRC_INCLUDE)/perfdata.h $(SRC_XDATA)/$(XPDH)
PDATALIBS=perfdata-base.o xperfdata-base.o
PDATAHDRS=
PDATADEPS=$(PDATALIBS)
# Downtime data
#DDATALIBS=$(SRC_COMMON)/downtime.c $(SRC_XDATA)/$(XDDC)
#DDATAHDRS=$(SRC_INCLUDE)/downtime.h $(SRC_XDATA)/$(XDDH)
DDATALIBS=downtime-base.o xdowntime-base.o
DDATAHDRS=
DDATADEPS=$(DDATALIBS)
OBJS=$(BROKER_O) $(SRC_COMMON)/shared.o checks.o config.o commands.o events.o flapping.o logging.o macros-base.o netutils.o notifications.o sehandlers.o skiplist.o utils.o $(RDATALIBS) $(CDATALIBS) $(ODATALIBS) $(SDATALIBS) $(PDATALIBS) $(DDATALIBS) $(BASEEXTRALIBS) $(SNPRINTF_O) $(PERLXSI_O)
OBJDEPS=$(ODATADEPS) $(ODATADEPS) $(RDATADEPS) $(CDATADEPS) $(SDATADEPS) $(PDATADEPS) $(DDATADEPS) $(BROKER_H)
all: nagios nagiostats
######## REQUIRED FILES ##########
macros-base.o: $(SRC_COMMON)/macros.c $(SRC_INCLUDE)/macros.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/macros.c
skiplist.o: $(SRC_COMMON)/skiplist.c $(SRC_INCLUDE)/skiplist.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/skiplist.c
objects-base.o: $(SRC_COMMON)/objects.c $(SRC_INCLUDE)/objects.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/objects.c
xobjects-base.o: $(SRC_XDATA)/$(XODC) $(SRC_XDATA)/$(XODH)
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XODC)
statusdata-base.o: $(SRC_COMMON)/statusdata.c $(SRC_INCLUDE)/statusdata.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/statusdata.c
xstatusdata-base.o: $(SRC_XDATA)/$(XSDC) $(SRC_XDATA)/$(XSDH)
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XSDC)
comments-base.o: $(SRC_COMMON)/comments.c $(SRC_INCLUDE)/comments.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/comments.c
xcomments-base.o: $(SRC_XDATA)/$(XCDC) $(SRC_XDATA)/$(XCDH)
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XCDC)
downtime-base.o: $(SRC_COMMON)/downtime.c $(SRC_INCLUDE)/downtime.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/downtime.c
xdowntime-base.o: $(SRC_XDATA)/$(XDDC) $(SRC_XDATA)/$(XDDH)
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XDDC)
perfdata-base.o: perfdata.c $(SRC_INCLUDE)/perfdata.h
$(CC) $(CFLAGS) -c -o $@ perfdata.c
xperfdata-base.o: $(SRC_XDATA)/$(XPDC) $(SRC_XDATA)/$(XPDH)
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XPDC)
retention-base.o: sretention.c $(SRC_INCLUDE)/sretention.h
$(CC) $(CFLAGS) -c -o $@ sretention.c
xretention-base.o: $(SRC_XDATA)/$(XRDC) $(SRC_XDATA)/$(XRDH)
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XRDC)
$(SRC_COMMON)/shared.o: $(SRC_COMMON)/shared.c
$(CC) $(CFLAGS) -c -o $@ $<
########## NAGIOS ##########
nagios: nagios.c $(OBJS) $(OBJDEPS) $(SRC_INCLUDE)/nagios.h $(SRC_INCLUDE)/locations.h
$(CC) $(CFLAGS) -o $@ nagios.c $(OBJS) $(BROKER_LDFLAGS) $(LDFLAGS) $(PERLLIBS) $(MATHLIBS) $(SOCKETLIBS) $(THREADLIBS) $(BROKERLIBS) $(LIBS)
nagiostats: nagiostats.c $(SRC_INCLUDE)/locations.h
$(CC) $(CFLAGS) -o $@ nagiostats.c $(LDFLAGS) $(MATHLIBS) $(LIBS)
$(OBJS): $(SRC_INCLUDE)/locations.h
clean:
rm -f nagios nagiostats core *.o gmon.out
rm -f *~ *.*~
distclean: clean
rm -f perlxsi.c
rm -f Makefile
devclean: distclean
install:
$(MAKE) install-basic
$(MAKE) strip-post-install
install-unstripped:
$(MAKE) install-basic
install-basic:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(BINDIR)
$(INSTALL) -m 774 $(INSTALL_OPTS) @nagios_name@ $(DESTDIR)$(BINDIR)
$(INSTALL) -m 774 $(INSTALL_OPTS) @nagiostats_name@ $(DESTDIR)$(BINDIR)
strip-post-install:
$(STRIP) $(DESTDIR)$(BINDIR)/@nagios_name@
$(STRIP) $(DESTDIR)$(BINDIR)/@nagiostats_name@

1017
base/broker.c Normal file

File diff suppressed because it is too large Load Diff

4405
base/checks.c Normal file

File diff suppressed because it is too large Load Diff

5223
base/commands.c Normal file

File diff suppressed because it is too large Load Diff

2818
base/config.c Normal file

File diff suppressed because it is too large Load Diff

1847
base/events.c Normal file

File diff suppressed because it is too large Load Diff

795
base/flapping.c Normal file
View File

@ -0,0 +1,795 @@
/*****************************************************************************
*
* FLAPPING.C - State flap detection and handling routines for Nagios
*
* Copyright (c) 2001-2009 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 05-15-2009
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
/*********** COMMON HEADER FILES ***********/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/comments.h"
#include "../include/statusdata.h"
#include "../include/nagios.h"
#include "../include/broker.h"
extern int interval_length;
extern int enable_flap_detection;
extern double low_service_flap_threshold;
extern double high_service_flap_threshold;
extern double low_host_flap_threshold;
extern double high_host_flap_threshold;
extern host *host_list;
extern service *service_list;
extern unsigned long modified_host_process_attributes;
extern unsigned long modified_service_process_attributes;
/******************************************************************/
/******************** FLAP DETECTION FUNCTIONS ********************/
/******************************************************************/
/* detects service flapping */
void check_for_service_flapping(service *svc, int update, int allow_flapstart_notification) {
int update_history = TRUE;
int is_flapping = FALSE;
register int x = 0;
register int y = 0;
int last_state_history_value = STATE_OK;
double curved_changes = 0.0;
double curved_percent_change = 0.0;
double low_threshold = 0.0;
double high_threshold = 0.0;
double low_curve_value = 0.75;
double high_curve_value = 1.25;
/* large install tweaks skips all flap detection logic - including state change calculation */
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_service_flapping()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Checking service '%s' on host '%s' for flapping...\n", svc->description, svc->host_name);
/* if this is a soft service state and not a soft recovery, don't record this in the history */
/* only hard states and soft recoveries get recorded for flap detection */
if(svc->state_type == SOFT_STATE && svc->current_state != STATE_OK)
return;
/* what threshold values should we use (global or service-specific)? */
low_threshold = (svc->low_flap_threshold <= 0.0) ? low_service_flap_threshold : svc->low_flap_threshold;
high_threshold = (svc->high_flap_threshold <= 0.0) ? high_service_flap_threshold : svc->high_flap_threshold;
update_history = update;
/* should we update state history for this state? */
if(update_history == TRUE) {
if(svc->current_state == STATE_OK && svc->flap_detection_on_ok == FALSE)
update_history = FALSE;
if(svc->current_state == STATE_WARNING && svc->flap_detection_on_warning == FALSE)
update_history = FALSE;
if(svc->current_state == STATE_UNKNOWN && svc->flap_detection_on_unknown == FALSE)
update_history = FALSE;
if(svc->current_state == STATE_CRITICAL && svc->flap_detection_on_critical == FALSE)
update_history = FALSE;
}
/* record current service state */
if(update_history == TRUE) {
/* record the current state in the state history */
svc->state_history[svc->state_history_index] = svc->current_state;
/* increment state history index to next available slot */
svc->state_history_index++;
if(svc->state_history_index >= MAX_STATE_HISTORY_ENTRIES)
svc->state_history_index = 0;
}
/* calculate overall and curved percent state changes */
for(x = 0, y = svc->state_history_index; x < MAX_STATE_HISTORY_ENTRIES; x++) {
if(x == 0) {
last_state_history_value = svc->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
continue;
}
if(last_state_history_value != svc->state_history[y])
curved_changes += (((double)(x - 1) * (high_curve_value - low_curve_value)) / ((double)(MAX_STATE_HISTORY_ENTRIES - 2))) + low_curve_value;
last_state_history_value = svc->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
}
/* calculate overall percent change in state */
curved_percent_change = (double)(((double)curved_changes * 100.0) / (double)(MAX_STATE_HISTORY_ENTRIES - 1));
svc->percent_state_change = curved_percent_change;
log_debug_info(DEBUGL_FLAPPING, 2, "LFT=%.2f, HFT=%.2f, CPC=%.2f, PSC=%.2f%%\n", low_threshold, high_threshold, curved_percent_change, curved_percent_change);
/* don't do anything if we don't have flap detection enabled on a program-wide basis */
if(enable_flap_detection == FALSE)
return;
/* don't do anything if we don't have flap detection enabled for this service */
if(svc->flap_detection_enabled == FALSE)
return;
/* are we flapping, undecided, or what?... */
/* we're undecided, so don't change the current flap state */
if(curved_percent_change > low_threshold && curved_percent_change < high_threshold)
return;
/* we're below the lower bound, so we're not flapping */
else if(curved_percent_change <= low_threshold)
is_flapping = FALSE;
/* else we're above the upper bound, so we are flapping */
else if(curved_percent_change >= high_threshold)
is_flapping = TRUE;
log_debug_info(DEBUGL_FLAPPING, 1, "Service %s flapping (%.2f%% state change).\n", (is_flapping == TRUE) ? "is" : "is not", curved_percent_change);
/* did the service just start flapping? */
if(is_flapping == TRUE && svc->is_flapping == FALSE)
set_service_flap(svc, curved_percent_change, high_threshold, low_threshold, allow_flapstart_notification);
/* did the service just stop flapping? */
else if(is_flapping == FALSE && svc->is_flapping == TRUE)
clear_service_flap(svc, curved_percent_change, high_threshold, low_threshold);
return;
}
/* detects host flapping */
void check_for_host_flapping(host *hst, int update, int actual_check, int allow_flapstart_notification) {
int update_history = TRUE;
int is_flapping = FALSE;
register int x = 0;
register int y = 0;
int last_state_history_value = HOST_UP;
unsigned long wait_threshold = 0L;
double curved_changes = 0.0;
double curved_percent_change = 0.0;
time_t current_time = 0L;
double low_threshold = 0.0;
double high_threshold = 0.0;
double low_curve_value = 0.75;
double high_curve_value = 1.25;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_host_flapping()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Checking host '%s' for flapping...\n", hst->name);
time(&current_time);
/* period to wait for updating archived state info if we have no state change */
if(hst->total_services == 0)
wait_threshold = hst->notification_interval * interval_length;
else
wait_threshold = (hst->total_service_check_interval * interval_length) / hst->total_services;
update_history = update;
/* should we update state history for this state? */
if(update_history == TRUE) {
if(hst->current_state == HOST_UP && hst->flap_detection_on_up == FALSE)
update_history = FALSE;
if(hst->current_state == HOST_DOWN && hst->flap_detection_on_down == FALSE)
update_history = FALSE;
if(hst->current_state == HOST_UNREACHABLE && hst->flap_detection_on_unreachable == FALSE)
update_history = FALSE;
}
/* if we didn't have an actual check, only update if we've waited long enough */
if(update_history == TRUE && actual_check == FALSE && (current_time - hst->last_state_history_update) < wait_threshold) {
update_history = FALSE;
}
/* what thresholds should we use (global or host-specific)? */
low_threshold = (hst->low_flap_threshold <= 0.0) ? low_host_flap_threshold : hst->low_flap_threshold;
high_threshold = (hst->high_flap_threshold <= 0.0) ? high_host_flap_threshold : hst->high_flap_threshold;
/* record current host state */
if(update_history == TRUE) {
/* update the last record time */
hst->last_state_history_update = current_time;
/* record the current state in the state history */
hst->state_history[hst->state_history_index] = hst->current_state;
/* increment state history index to next available slot */
hst->state_history_index++;
if(hst->state_history_index >= MAX_STATE_HISTORY_ENTRIES)
hst->state_history_index = 0;
}
/* calculate overall changes in state */
for(x = 0, y = hst->state_history_index; x < MAX_STATE_HISTORY_ENTRIES; x++) {
if(x == 0) {
last_state_history_value = hst->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
continue;
}
if(last_state_history_value != hst->state_history[y])
curved_changes += (((double)(x - 1) * (high_curve_value - low_curve_value)) / ((double)(MAX_STATE_HISTORY_ENTRIES - 2))) + low_curve_value;
last_state_history_value = hst->state_history[y];
y++;
if(y >= MAX_STATE_HISTORY_ENTRIES)
y = 0;
}
/* calculate overall percent change in state */
curved_percent_change = (double)(((double)curved_changes * 100.0) / (double)(MAX_STATE_HISTORY_ENTRIES - 1));
hst->percent_state_change = curved_percent_change;
log_debug_info(DEBUGL_FLAPPING, 2, "LFT=%.2f, HFT=%.2f, CPC=%.2f, PSC=%.2f%%\n", low_threshold, high_threshold, curved_percent_change, curved_percent_change);
/* don't do anything if we don't have flap detection enabled on a program-wide basis */
if(enable_flap_detection == FALSE)
return;
/* don't do anything if we don't have flap detection enabled for this host */
if(hst->flap_detection_enabled == FALSE)
return;
/* are we flapping, undecided, or what?... */
/* we're undecided, so don't change the current flap state */
if(curved_percent_change > low_threshold && curved_percent_change < high_threshold)
return;
/* we're below the lower bound, so we're not flapping */
else if(curved_percent_change <= low_threshold)
is_flapping = FALSE;
/* else we're above the upper bound, so we are flapping */
else if(curved_percent_change >= high_threshold)
is_flapping = TRUE;
log_debug_info(DEBUGL_FLAPPING, 1, "Host %s flapping (%.2f%% state change).\n", (is_flapping == TRUE) ? "is" : "is not", curved_percent_change);
/* did the host just start flapping? */
if(is_flapping == TRUE && hst->is_flapping == FALSE)
set_host_flap(hst, curved_percent_change, high_threshold, low_threshold, allow_flapstart_notification);
/* did the host just stop flapping? */
else if(is_flapping == FALSE && hst->is_flapping == TRUE)
clear_host_flap(hst, curved_percent_change, high_threshold, low_threshold);
return;
}
/******************************************************************/
/********************* FLAP HANDLING FUNCTIONS ********************/
/******************************************************************/
/* handles a service that is flapping */
void set_service_flap(service *svc, double percent_change, double high_threshold, double low_threshold, int allow_flapstart_notification) {
char *temp_buffer = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "set_service_flap()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Service '%s' on host '%s' started flapping!\n", svc->description, svc->host_name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_RUNTIME_WARNING, FALSE, "SERVICE FLAPPING ALERT: %s;%s;STARTED; Service appears to have started flapping (%2.1f%% change >= %2.1f%% threshold)\n", svc->host_name, svc->description, percent_change, high_threshold);
/* add a non-persistent comment to the service */
asprintf(&temp_buffer, "Notifications for this service are being suppressed because it was detected as having been flapping between different states (%2.1f%% change >= %2.1f%% threshold). When the service state stabilizes and the flapping stops, notifications will be re-enabled.", percent_change, high_threshold);
add_new_service_comment(FLAPPING_COMMENT, svc->host_name, svc->description, time(NULL), "(Nagios Process)", temp_buffer, 0, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, &(svc->flapping_comment_id));
my_free(temp_buffer);
/* set the flapping indicator */
svc->is_flapping = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_FLAPPING, svc, percent_change, high_threshold, low_threshold, NULL);
#endif
/* see if we should check to send a recovery notification out when flapping stops */
if(svc->current_state != STATE_OK && svc->current_notification_number > 0)
svc->check_flapping_recovery_notification = TRUE;
else
svc->check_flapping_recovery_notification = FALSE;
/* send a notification */
if(allow_flapstart_notification == TRUE)
service_notification(svc, NOTIFICATION_FLAPPINGSTART, NULL, NULL, NOTIFICATION_OPTION_NONE);
return;
}
/* handles a service that has stopped flapping */
void clear_service_flap(service *svc, double percent_change, double high_threshold, double low_threshold) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "clear_service_flap()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Service '%s' on host '%s' stopped flapping.\n", svc->description, svc->host_name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE FLAPPING ALERT: %s;%s;STOPPED; Service appears to have stopped flapping (%2.1f%% change < %2.1f%% threshold)\n", svc->host_name, svc->description, percent_change, low_threshold);
/* delete the comment we added earlier */
if(svc->flapping_comment_id != 0)
delete_service_comment(svc->flapping_comment_id);
svc->flapping_comment_id = 0;
/* clear the flapping indicator */
svc->is_flapping = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_NORMAL, SERVICE_FLAPPING, svc, percent_change, high_threshold, low_threshold, NULL);
#endif
/* send a notification */
service_notification(svc, NOTIFICATION_FLAPPINGSTOP, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* should we send a recovery notification? */
if(svc->check_flapping_recovery_notification == TRUE && svc->current_state == STATE_OK)
service_notification(svc, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* clear the recovery notification flag */
svc->check_flapping_recovery_notification = FALSE;
return;
}
/* handles a host that is flapping */
void set_host_flap(host *hst, double percent_change, double high_threshold, double low_threshold, int allow_flapstart_notification) {
char *temp_buffer = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "set_host_flap()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Host '%s' started flapping!\n", hst->name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_RUNTIME_WARNING, FALSE, "HOST FLAPPING ALERT: %s;STARTED; Host appears to have started flapping (%2.1f%% change > %2.1f%% threshold)\n", hst->name, percent_change, high_threshold);
/* add a non-persistent comment to the host */
asprintf(&temp_buffer, "Notifications for this host are being suppressed because it was detected as having been flapping between different states (%2.1f%% change > %2.1f%% threshold). When the host state stabilizes and the flapping stops, notifications will be re-enabled.", percent_change, high_threshold);
add_new_host_comment(FLAPPING_COMMENT, hst->name, time(NULL), "(Nagios Process)", temp_buffer, 0, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, &(hst->flapping_comment_id));
my_free(temp_buffer);
/* set the flapping indicator */
hst->is_flapping = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_FLAPPING, hst, percent_change, high_threshold, low_threshold, NULL);
#endif
/* see if we should check to send a recovery notification out when flapping stops */
if(hst->current_state != HOST_UP && hst->current_notification_number > 0)
hst->check_flapping_recovery_notification = TRUE;
else
hst->check_flapping_recovery_notification = FALSE;
/* send a notification */
if(allow_flapstart_notification == TRUE)
host_notification(hst, NOTIFICATION_FLAPPINGSTART, NULL, NULL, NOTIFICATION_OPTION_NONE);
return;
}
/* handles a host that has stopped flapping */
void clear_host_flap(host *hst, double percent_change, double high_threshold, double low_threshold) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "clear_host_flap()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Host '%s' stopped flapping.\n", hst->name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "HOST FLAPPING ALERT: %s;STOPPED; Host appears to have stopped flapping (%2.1f%% change < %2.1f%% threshold)\n", hst->name, percent_change, low_threshold);
/* delete the comment we added earlier */
if(hst->flapping_comment_id != 0)
delete_host_comment(hst->flapping_comment_id);
hst->flapping_comment_id = 0;
/* clear the flapping indicator */
hst->is_flapping = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_NORMAL, HOST_FLAPPING, hst, percent_change, high_threshold, low_threshold, NULL);
#endif
/* send a notification */
host_notification(hst, NOTIFICATION_FLAPPINGSTOP, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* should we send a recovery notification? */
if(hst->check_flapping_recovery_notification == TRUE && hst->current_state == HOST_UP)
host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* clear the recovery notification flag */
hst->check_flapping_recovery_notification = FALSE;
return;
}
/******************************************************************/
/***************** FLAP DETECTION STATUS FUNCTIONS ****************/
/******************************************************************/
/* enables flap detection on a program wide basis */
void enable_flap_detection_routines(void) {
host *temp_host = NULL;
service *temp_service = NULL;
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "enable_flap_detection_routines()\n");
/* bail out if we're already set */
if(enable_flap_detection == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* set flap detection flag */
enable_flap_detection = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, attr, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update program status */
update_program_status(FALSE);
/* check for flapping */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next)
check_for_host_flapping(temp_host, FALSE, FALSE, TRUE);
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next)
check_for_service_flapping(temp_service, FALSE, TRUE);
return;
}
/* disables flap detection on a program wide basis */
void disable_flap_detection_routines(void) {
host *temp_host = NULL;
service *temp_service = NULL;
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "disable_flap_detection_routines()\n");
/* bail out if we're already set */
if(enable_flap_detection == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* set flap detection flag */
enable_flap_detection = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, attr, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update program status */
update_program_status(FALSE);
/* handle the details... */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next)
handle_host_flap_detection_disabled(temp_host);
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next)
handle_service_flap_detection_disabled(temp_service);
return;
}
/* enables flap detection for a specific host */
void enable_host_flap_detection(host *hst) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "enable_host_flap_detection()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Enabling flap detection for host '%s'.\n", hst->name);
/* nothing to do... */
if(hst->flap_detection_enabled == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the flap detection enabled flag */
hst->flap_detection_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* check for flapping */
check_for_host_flapping(hst, FALSE, FALSE, TRUE);
/* update host status */
update_host_status(hst, FALSE);
return;
}
/* disables flap detection for a specific host */
void disable_host_flap_detection(host *hst) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "disable_host_flap_detection()\n");
if(hst == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Disabling flap detection for host '%s'.\n", hst->name);
/* nothing to do... */
if(hst->flap_detection_enabled == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the flap detection enabled flag */
hst->flap_detection_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CMD_NONE, attr, hst->modified_attributes, NULL);
#endif
/* handle the details... */
handle_host_flap_detection_disabled(hst);
return;
}
/* handles the details for a host when flap detection is disabled (globally or per-host) */
void handle_host_flap_detection_disabled(host *hst) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_host_flap_detection_disabled()\n");
if(hst == NULL)
return;
/* if the host was flapping, remove the flapping indicator */
if(hst->is_flapping == TRUE) {
hst->is_flapping = FALSE;
/* delete the original comment we added earlier */
if(hst->flapping_comment_id != 0)
delete_host_comment(hst->flapping_comment_id);
hst->flapping_comment_id = 0;
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "HOST FLAPPING ALERT: %s;DISABLED; Flap detection has been disabled\n", hst->name);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_DISABLED, HOST_FLAPPING, hst, hst->percent_state_change, 0.0, 0.0, NULL);
#endif
/* send a notification */
host_notification(hst, NOTIFICATION_FLAPPINGDISABLED, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* should we send a recovery notification? */
if(hst->check_flapping_recovery_notification == TRUE && hst->current_state == HOST_UP)
host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* clear the recovery notification flag */
hst->check_flapping_recovery_notification = FALSE;
}
/* update host status */
update_host_status(hst, FALSE);
return;
}
/* enables flap detection for a specific service */
void enable_service_flap_detection(service *svc) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "enable_service_flap_detection()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Enabling flap detection for service '%s' on host '%s'.\n", svc->description, svc->host_name);
/* nothing to do... */
if(svc->flap_detection_enabled == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the flap detection enabled flag */
svc->flap_detection_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* check for flapping */
check_for_service_flapping(svc, FALSE, TRUE);
/* update service status */
update_service_status(svc, FALSE);
return;
}
/* disables flap detection for a specific service */
void disable_service_flap_detection(service *svc) {
unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED;
log_debug_info(DEBUGL_FUNCTIONS, 0, "disable_service_flap_detection()\n");
if(svc == NULL)
return;
log_debug_info(DEBUGL_FLAPPING, 1, "Disabling flap detection for service '%s' on host '%s'.\n", svc->description, svc->host_name);
/* nothing to do... */
if(svc->flap_detection_enabled == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the flap detection enabled flag */
svc->flap_detection_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CMD_NONE, attr, svc->modified_attributes, NULL);
#endif
/* handle the details... */
handle_service_flap_detection_disabled(svc);
return;
}
/* handles the details for a service when flap detection is disabled (globally or per-service) */
void handle_service_flap_detection_disabled(service *svc) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_service_flap_detection_disabled()\n");
if(svc == NULL)
return;
/* if the service was flapping, remove the flapping indicator */
if(svc->is_flapping == TRUE) {
svc->is_flapping = FALSE;
/* delete the original comment we added earlier */
if(svc->flapping_comment_id != 0)
delete_service_comment(svc->flapping_comment_id);
svc->flapping_comment_id = 0;
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE FLAPPING ALERT: %s;%s;DISABLED; Flap detection has been disabled\n", svc->host_name, svc->description);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_DISABLED, SERVICE_FLAPPING, svc, svc->percent_state_change, 0.0, 0.0, NULL);
#endif
/* send a notification */
service_notification(svc, NOTIFICATION_FLAPPINGDISABLED, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* should we send a recovery notification? */
if(svc->check_flapping_recovery_notification == TRUE && svc->current_state == STATE_OK)
service_notification(svc, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
/* clear the recovery notification flag */
svc->check_flapping_recovery_notification = FALSE;
}
/* update service status */
update_service_status(svc, FALSE);
return;
}

595
base/logging.c Normal file
View File

@ -0,0 +1,595 @@
/*****************************************************************************
*
* LOGGING.C - Log file functions for use with Nagios
*
* Copyright (c) 1999-2007 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 10-28-2007
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/statusdata.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/broker.h"
extern char *log_file;
extern char *temp_file;
extern char *log_archive_path;
extern host *host_list;
extern service *service_list;
extern int use_syslog;
extern int log_service_retries;
extern int log_initial_states;
extern unsigned long logging_options;
extern unsigned long syslog_options;
extern int verify_config;
extern int test_scheduling;
extern time_t last_log_rotation;
extern int log_rotation_method;
extern int daemon_mode;
extern char *debug_file;
extern int debug_level;
extern int debug_verbosity;
extern unsigned long max_debug_file_size;
FILE *debug_file_fp = NULL;
static pthread_mutex_t debug_fp_lock;
/* These simple helpers should most likely be elsewhere */
static const char *service_state_name(int state) {
switch(state) {
case STATE_OK:
return "OK";
case STATE_WARNING:
return "WARNING";
case STATE_CRITICAL:
return "CRITICAL";
}
return "UNKNOWN";
}
static const char *host_state_name(int state) {
switch(state) {
case HOST_UP:
return "UP";
case HOST_DOWN:
return "DOWN";
case HOST_UNREACHABLE:
return "UNREACHABLE";
}
return "(unknown)";
}
static const char *state_type_name(int state_type) {
return state_type == HARD_STATE ? "HARD" : "SOFT";
}
/*
* since we don't want child processes to hang indefinitely
* in case they inherit a locked lock, we use soft-locking
* here, which basically tries to acquire the lock for a
* short while and then gives up, returning -1 to signal
* the error
*/
static inline int soft_lock(pthread_mutex_t *lock) {
int i;
for(i = 0; i < 5; i++) {
if(!pthread_mutex_trylock(lock)) {
/* success */
return 0;
}
if(errno == EDEADLK) {
/* we already have the lock */
return 0;
}
/* sleep briefly */
usleep(30);
}
return -1; /* we failed to get the lock. Nothing to do */
}
/******************************************************************/
/************************ LOGGING FUNCTIONS ***********************/
/******************************************************************/
/* write something to the console */
static void write_to_console(char *buffer) {
/* should we print to the console? */
if(daemon_mode == FALSE)
printf("%s\n", buffer);
}
/* write something to the log file, syslog, and possibly the console */
static void write_to_logs_and_console(char *buffer, unsigned long data_type, int display) {
register int len = 0;
register int x = 0;
/* strip unnecessary newlines */
len = strlen(buffer);
for(x = len - 1; x >= 0; x--) {
if(buffer[x] == '\n')
buffer[x] = '\x0';
else
break;
}
/* write messages to the logs */
write_to_all_logs(buffer, data_type);
/* write message to the console */
if(display == TRUE) {
/* don't display warnings if we're just testing scheduling */
if(test_scheduling == TRUE && data_type == NSLOG_VERIFICATION_WARNING)
return;
write_to_console(buffer);
}
}
/* The main logging function */
void logit(int data_type, int display, const char *fmt, ...) {
va_list ap;
char *buffer = NULL;
va_start(ap, fmt);
if(vasprintf(&buffer, fmt, ap) > 0) {
write_to_logs_and_console(buffer, data_type, display);
free(buffer);
}
va_end(ap);
}
/* write something to the log file and syslog facility */
int write_to_all_logs(char *buffer, unsigned long data_type) {
/* write to syslog */
write_to_syslog(buffer, data_type);
/* write to main log */
write_to_log(buffer, data_type, NULL);
return OK;
}
/* write something to the log file and syslog facility */
static void write_to_all_logs_with_timestamp(char *buffer, unsigned long data_type, time_t *timestamp) {
/* write to syslog */
write_to_syslog(buffer, data_type);
/* write to main log */
write_to_log(buffer, data_type, timestamp);
}
/* write something to the nagios log file */
int write_to_log(char *buffer, unsigned long data_type, time_t *timestamp) {
FILE *fp = NULL;
time_t log_time = 0L;
if(buffer == NULL)
return ERROR;
/* don't log anything if we're not actually running... */
if(verify_config == TRUE || test_scheduling == TRUE)
return OK;
/* make sure we can log this type of entry */
if(!(data_type & logging_options))
return OK;
fp = fopen(log_file, "a+");
if(fp == NULL) {
if(daemon_mode == FALSE)
printf("Warning: Cannot open log file '%s' for writing\n", log_file);
return ERROR;
}
/* what timestamp should we use? */
if(timestamp == NULL)
time(&log_time);
else
log_time = *timestamp;
/* strip any newlines from the end of the buffer */
strip(buffer);
/* write the buffer to the log file */
fprintf(fp, "[%lu] %s\n", log_time, buffer);
fclose(fp);
#ifdef USE_EVENT_BROKER
/* send data to the event broker */
broker_log_data(NEBTYPE_LOG_DATA, NEBFLAG_NONE, NEBATTR_NONE, buffer, data_type, log_time, NULL);
#endif
return OK;
}
/* write something to the syslog facility */
int write_to_syslog(char *buffer, unsigned long data_type) {
if(buffer == NULL)
return ERROR;
/* don't log anything if we're not actually running... */
if(verify_config == TRUE || test_scheduling == TRUE)
return OK;
/* bail out if we shouldn't write to syslog */
if(use_syslog == FALSE)
return OK;
/* make sure we should log this type of entry */
if(!(data_type & syslog_options))
return OK;
/* write the buffer to the syslog facility */
syslog(LOG_USER | LOG_INFO, "%s", buffer);
return OK;
}
/* write a service problem/recovery to the nagios log file */
int log_service_event(service *svc) {
char *temp_buffer = NULL;
unsigned long log_options = 0L;
host *temp_host = NULL;
/* don't log soft errors if the user doesn't want to */
if(svc->state_type == SOFT_STATE && !log_service_retries)
return OK;
/* get the log options */
if(svc->current_state == STATE_UNKNOWN)
log_options = NSLOG_SERVICE_UNKNOWN;
else if(svc->current_state == STATE_WARNING)
log_options = NSLOG_SERVICE_WARNING;
else if(svc->current_state == STATE_CRITICAL)
log_options = NSLOG_SERVICE_CRITICAL;
else
log_options = NSLOG_SERVICE_OK;
/* find the associated host */
if((temp_host = svc->host_ptr) == NULL)
return ERROR;
asprintf(&temp_buffer, "SERVICE ALERT: %s;%s;%s;%s;%d;%s\n",
svc->host_name, svc->description,
service_state_name(svc->current_state),
state_type_name(svc->state_type),
svc->current_attempt,
(svc->plugin_output == NULL) ? "" : svc->plugin_output);
write_to_all_logs(temp_buffer, log_options);
return OK;
}
/* write a host problem/recovery to the log file */
int log_host_event(host *hst) {
char *temp_buffer = NULL;
unsigned long log_options = 0L;
/* get the log options */
if(hst->current_state == HOST_DOWN)
log_options = NSLOG_HOST_DOWN;
else if(hst->current_state == HOST_UNREACHABLE)
log_options = NSLOG_HOST_UNREACHABLE;
else
log_options = NSLOG_HOST_UP;
asprintf(&temp_buffer, "HOST ALERT: %s;%s;%s;%d;%s\n",
hst->name,
host_state_name(hst->current_state),
state_type_name(hst->state_type),
hst->current_attempt,
(hst->plugin_output == NULL) ? "" : hst->plugin_output);
write_to_all_logs(temp_buffer, log_options);
my_free(temp_buffer);
return OK;
}
/* logs host states */
int log_host_states(int type, time_t *timestamp) {
char *temp_buffer = NULL;
host *temp_host = NULL;;
/* bail if we shouldn't be logging initial states */
if(type == INITIAL_STATES && log_initial_states == FALSE)
return OK;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
asprintf(&temp_buffer, "%s HOST STATE: %s;%s;%s;%d;%s\n", (type == INITIAL_STATES) ? "INITIAL" : "CURRENT",
temp_host->name,
host_state_name(temp_host->current_state),
state_type_name(temp_host->state_type),
temp_host->current_attempt,
(temp_host->plugin_output == NULL) ? "" : temp_host->plugin_output);
write_to_all_logs_with_timestamp(temp_buffer, NSLOG_INFO_MESSAGE, timestamp);
my_free(temp_buffer);
}
return OK;
}
/* logs service states */
int log_service_states(int type, time_t *timestamp) {
char *temp_buffer = NULL;
service *temp_service = NULL;
host *temp_host = NULL;;
/* bail if we shouldn't be logging initial states */
if(type == INITIAL_STATES && log_initial_states == FALSE)
return OK;
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
/* find the associated host */
if((temp_host = temp_service->host_ptr) == NULL)
continue;
asprintf(&temp_buffer, "%s SERVICE STATE: %s;%s;%s;%s;%d;%s\n",
(type == INITIAL_STATES) ? "INITIAL" : "CURRENT",
temp_service->host_name, temp_service->description,
service_state_name(temp_service->current_state),
state_type_name(temp_service->state_type),
temp_service->current_attempt,
temp_service->plugin_output);
write_to_all_logs_with_timestamp(temp_buffer, NSLOG_INFO_MESSAGE, timestamp);
my_free(temp_buffer);
}
return OK;
}
/* rotates the main log file */
int rotate_log_file(time_t rotation_time) {
char *temp_buffer = NULL;
char method_string[16] = "";
char *log_archive = NULL;
struct tm *t, tm_s;
int rename_result = 0;
int stat_result = -1;
struct stat log_file_stat;
if(log_rotation_method == LOG_ROTATION_NONE) {
return OK;
}
else if(log_rotation_method == LOG_ROTATION_HOURLY)
strcpy(method_string, "HOURLY");
else if(log_rotation_method == LOG_ROTATION_DAILY)
strcpy(method_string, "DAILY");
else if(log_rotation_method == LOG_ROTATION_WEEKLY)
strcpy(method_string, "WEEKLY");
else if(log_rotation_method == LOG_ROTATION_MONTHLY)
strcpy(method_string, "MONTHLY");
else
return ERROR;
/* update the last log rotation time and status log */
last_log_rotation = time(NULL);
update_program_status(FALSE);
t = localtime_r(&rotation_time, &tm_s);
stat_result = stat(log_file, &log_file_stat);
/* get the archived filename to use */
asprintf(&log_archive, "%s%snagios-%02d-%02d-%d-%02d.log", log_archive_path, (log_archive_path[strlen(log_archive_path) - 1] == '/') ? "" : "/", t->tm_mon + 1, t->tm_mday, t->tm_year + 1900, t->tm_hour);
/* rotate the log file */
rename_result = my_rename(log_file, log_archive);
if(rename_result) {
my_free(log_archive);
return ERROR;
}
/* record the log rotation after it has been done... */
asprintf(&temp_buffer, "LOG ROTATION: %s\n", method_string);
write_to_all_logs_with_timestamp(temp_buffer, NSLOG_PROCESS_INFO, &rotation_time);
my_free(temp_buffer);
/* record log file version format */
write_log_file_info(&rotation_time);
if(stat_result == 0) {
chmod(log_file, log_file_stat.st_mode);
chown(log_file, log_file_stat.st_uid, log_file_stat.st_gid);
}
/* log current host and service state */
log_host_states(CURRENT_STATES, &rotation_time);
log_service_states(CURRENT_STATES, &rotation_time);
/* free memory */
my_free(log_archive);
return OK;
}
/* record log file version/info */
int write_log_file_info(time_t *timestamp) {
char *temp_buffer = NULL;
/* write log version */
asprintf(&temp_buffer, "LOG VERSION: %s\n", LOG_VERSION_2);
write_to_all_logs_with_timestamp(temp_buffer, NSLOG_PROCESS_INFO, timestamp);
my_free(temp_buffer);
return OK;
}
/* opens the debug log for writing */
int open_debug_log(void) {
/* don't do anything if we're not actually running... */
if(verify_config == TRUE || test_scheduling == TRUE)
return OK;
/* don't do anything if we're not debugging */
if(debug_level == DEBUGL_NONE)
return OK;
if((debug_file_fp = fopen(debug_file, "a+")) == NULL)
return ERROR;
return OK;
}
/* change the ownership of the debug log. This is done so that if Nagios
receives a HUP signal, it will be owned by a user that can reopen the file */
int chown_debug_log(uid_t uid, gid_t gid) {
/* don't do anything if we're not actually running... */
if(verify_config == TRUE || test_scheduling == TRUE)
return OK;
/* don't do anything if we're not debugging */
if(debug_level == DEBUGL_NONE)
return OK;
if(chown(debug_file, uid, gid) < 0) {
logit(NSLOG_RUNTIME_WARNING, TRUE,
"Failed to change ownership on debug log: %s.",
strerror(errno));
return ERROR;
}
return OK;
}
/* closes the debug log */
int close_debug_log(void) {
if(debug_file_fp != NULL)
fclose(debug_file_fp);
debug_file_fp = NULL;
return OK;
}
/* write to the debug log */
int log_debug_info(int level, int verbosity, const char *fmt, ...) {
va_list ap;
char *temp_path = NULL;
struct timeval current_time;
if(!(debug_level == DEBUGL_ALL || (level & debug_level)))
return OK;
if(verbosity > debug_verbosity)
return OK;
if(debug_file_fp == NULL)
return ERROR;
/*
* lock it so concurrent threads don't stomp on each other's
* writings. We maintain the lock until we've (optionally)
* renamed the file.
* If soft_lock() fails we return early.
*/
if(soft_lock(&debug_fp_lock) < 0)
return ERROR;
/* write the timestamp */
gettimeofday(&current_time, NULL);
fprintf(debug_file_fp, "[%lu.%06lu] [%03d.%d] [pid=%lu] ", current_time.tv_sec, current_time.tv_usec, level, verbosity, (unsigned long)getpid());
/* write the data */
va_start(ap, fmt);
vfprintf(debug_file_fp, fmt, ap);
va_end(ap);
/* flush, so we don't have problems tailing or when fork()ing */
fflush(debug_file_fp);
/* if file has grown beyond max, rotate it */
if((unsigned long)ftell(debug_file_fp) > max_debug_file_size && max_debug_file_size > 0L) {
/* close the file */
close_debug_log();
/* rotate the log file */
asprintf(&temp_path, "%s.old", debug_file);
if(temp_path) {
/* unlink the old debug file */
unlink(temp_path);
/* rotate the debug file */
my_rename(debug_file, temp_path);
/* free memory */
my_free(temp_path);
}
/* open a new file */
open_debug_log();
}
pthread_mutex_unlock(&debug_fp_lock);
return OK;
}

937
base/nagios.c Normal file
View File

@ -0,0 +1,937 @@
/*****************************************************************************
*
* NAGIOS.C - Core Program Code For Nagios
*
* Program: Nagios Core
* Version: 3.5.1
* License: GPL
* Copyright (c) 2009-2010 Nagios Core Development Team and Community Contributors
* Copyright (c) 1999-2009 Ethan Galstad
*
* First Written: 01-28-1999 (start of development)
* Last Modified:
*
* Description:
*
* Nagios is a network monitoring tool that will check hosts and services
* that you specify. It has the ability to notify contacts via email, pager,
* or other user-defined methods when a service or host goes down and
* recovers. Service and host monitoring is done through the use of external
* plugins which can be developed independently of Nagios.
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/comments.h"
#include "../include/downtime.h"
#include "../include/statusdata.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/sretention.h"
#include "../include/perfdata.h"
#include "../include/broker.h"
#include "../include/nebmods.h"
#include "../include/nebmodules.h"
/*#define DEBUG_MEMORY 1*/
#ifdef DEBUG_MEMORY
#include <mcheck.h>
#endif
char *config_file = NULL;
char *log_file = NULL;
char *command_file = NULL;
char *temp_file = NULL;
char *temp_path = NULL;
char *check_result_path = NULL;
char *lock_file = NULL;
char *log_archive_path = NULL;
char *p1_file = NULL; /**** EMBEDDED PERL ****/
char *auth_file = NULL; /**** EMBEDDED PERL INTERPRETER AUTH FILE ****/
char *nagios_user = NULL;
char *nagios_group = NULL;
char *global_host_event_handler = NULL;
char *global_service_event_handler = NULL;
command *global_host_event_handler_ptr = NULL;
command *global_service_event_handler_ptr = NULL;
char *ocsp_command = NULL;
char *ochp_command = NULL;
command *ocsp_command_ptr = NULL;
command *ochp_command_ptr = NULL;
char *illegal_object_chars = NULL;
char *illegal_output_chars = NULL;
int use_regexp_matches = FALSE;
int use_true_regexp_matching = FALSE;
int use_syslog = DEFAULT_USE_SYSLOG;
int log_notifications = DEFAULT_NOTIFICATION_LOGGING;
int log_service_retries = DEFAULT_LOG_SERVICE_RETRIES;
int log_host_retries = DEFAULT_LOG_HOST_RETRIES;
int log_event_handlers = DEFAULT_LOG_EVENT_HANDLERS;
int log_initial_states = DEFAULT_LOG_INITIAL_STATES;
int log_external_commands = DEFAULT_LOG_EXTERNAL_COMMANDS;
int log_passive_checks = DEFAULT_LOG_PASSIVE_CHECKS;
unsigned long logging_options = 0;
unsigned long syslog_options = 0;
int service_check_timeout = DEFAULT_SERVICE_CHECK_TIMEOUT;
int service_check_timeout_state = STATE_CRITICAL;
int host_check_timeout = DEFAULT_HOST_CHECK_TIMEOUT;
int event_handler_timeout = DEFAULT_EVENT_HANDLER_TIMEOUT;
int notification_timeout = DEFAULT_NOTIFICATION_TIMEOUT;
int ocsp_timeout = DEFAULT_OCSP_TIMEOUT;
int ochp_timeout = DEFAULT_OCHP_TIMEOUT;
double sleep_time = DEFAULT_SLEEP_TIME;
int interval_length = DEFAULT_INTERVAL_LENGTH;
int service_inter_check_delay_method = ICD_SMART;
int host_inter_check_delay_method = ICD_SMART;
int service_interleave_factor_method = ILF_SMART;
int max_host_check_spread = DEFAULT_HOST_CHECK_SPREAD;
int max_service_check_spread = DEFAULT_SERVICE_CHECK_SPREAD;
int command_check_interval = DEFAULT_COMMAND_CHECK_INTERVAL;
int check_reaper_interval = DEFAULT_CHECK_REAPER_INTERVAL;
int max_check_reaper_time = DEFAULT_MAX_REAPER_TIME;
int service_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL;
int host_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL;
int auto_rescheduling_interval = DEFAULT_AUTO_RESCHEDULING_INTERVAL;
int check_external_commands = DEFAULT_CHECK_EXTERNAL_COMMANDS;
int check_orphaned_services = DEFAULT_CHECK_ORPHANED_SERVICES;
int check_orphaned_hosts = DEFAULT_CHECK_ORPHANED_HOSTS;
int check_service_freshness = DEFAULT_CHECK_SERVICE_FRESHNESS;
int check_host_freshness = DEFAULT_CHECK_HOST_FRESHNESS;
int auto_reschedule_checks = DEFAULT_AUTO_RESCHEDULE_CHECKS;
int auto_rescheduling_window = DEFAULT_AUTO_RESCHEDULING_WINDOW;
int additional_freshness_latency = DEFAULT_ADDITIONAL_FRESHNESS_LATENCY;
int check_for_updates = DEFAULT_CHECK_FOR_UPDATES;
int bare_update_check = DEFAULT_BARE_UPDATE_CHECK;
time_t last_update_check = 0L;
unsigned long update_uid = 0L;
int update_available = FALSE;
char *last_program_version = NULL;
char *new_program_version = NULL;
time_t last_command_check = 0L;
time_t last_command_status_update = 0L;
time_t last_log_rotation = 0L;
time_t last_program_stop = 0L;
int use_aggressive_host_checking = DEFAULT_AGGRESSIVE_HOST_CHECKING;
unsigned long cached_host_check_horizon = DEFAULT_CACHED_HOST_CHECK_HORIZON;
unsigned long cached_service_check_horizon = DEFAULT_CACHED_SERVICE_CHECK_HORIZON;
int enable_predictive_host_dependency_checks = DEFAULT_ENABLE_PREDICTIVE_HOST_DEPENDENCY_CHECKS;
int enable_predictive_service_dependency_checks = DEFAULT_ENABLE_PREDICTIVE_SERVICE_DEPENDENCY_CHECKS;
int soft_state_dependencies = FALSE;
int retain_state_information = FALSE;
int retention_update_interval = DEFAULT_RETENTION_UPDATE_INTERVAL;
int use_retained_program_state = TRUE;
int use_retained_scheduling_info = FALSE;
int retention_scheduling_horizon = DEFAULT_RETENTION_SCHEDULING_HORIZON;
unsigned long modified_host_process_attributes = MODATTR_NONE;
unsigned long modified_service_process_attributes = MODATTR_NONE;
unsigned long retained_host_attribute_mask = 0L;
unsigned long retained_service_attribute_mask = 0L;
unsigned long retained_contact_host_attribute_mask = 0L;
unsigned long retained_contact_service_attribute_mask = 0L;
unsigned long retained_process_host_attribute_mask = 0L;
unsigned long retained_process_service_attribute_mask = 0L;
unsigned long next_comment_id = 0L;
unsigned long next_downtime_id = 0L;
unsigned long next_event_id = 0L;
unsigned long next_problem_id = 0L;
unsigned long next_notification_id = 0L;
int log_rotation_method = LOG_ROTATION_NONE;
int sigshutdown = FALSE;
int sigrestart = FALSE;
char *sigs[35] = {"EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO", "PWR", "UNUSED", "ZERR", "DEBUG", (char *)NULL};
int caught_signal = FALSE;
int sig_id = 0;
int restarting = FALSE;
int verify_config = FALSE;
int verify_object_relationships = TRUE;
int verify_circular_paths = TRUE;
int test_scheduling = FALSE;
int precache_objects = FALSE;
int use_precached_objects = FALSE;
int daemon_mode = FALSE;
int daemon_dumps_core = TRUE;
int max_parallel_service_checks = DEFAULT_MAX_PARALLEL_SERVICE_CHECKS;
int currently_running_service_checks = 0;
int currently_running_host_checks = 0;
time_t program_start = 0L;
time_t event_start = 0L;
int nagios_pid = 0;
int enable_notifications = TRUE;
int execute_service_checks = TRUE;
int accept_passive_service_checks = TRUE;
int execute_host_checks = TRUE;
int accept_passive_host_checks = TRUE;
int enable_event_handlers = TRUE;
int obsess_over_services = FALSE;
int obsess_over_hosts = FALSE;
int enable_failure_prediction = TRUE;
int translate_passive_host_checks = DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS;
int passive_host_checks_are_soft = DEFAULT_PASSIVE_HOST_CHECKS_SOFT;
int aggregate_status_updates = TRUE;
int status_update_interval = DEFAULT_STATUS_UPDATE_INTERVAL;
int time_change_threshold = DEFAULT_TIME_CHANGE_THRESHOLD;
unsigned long event_broker_options = BROKER_NOTHING;
int process_performance_data = DEFAULT_PROCESS_PERFORMANCE_DATA;
int enable_flap_detection = DEFAULT_ENABLE_FLAP_DETECTION;
double low_service_flap_threshold = DEFAULT_LOW_SERVICE_FLAP_THRESHOLD;
double high_service_flap_threshold = DEFAULT_HIGH_SERVICE_FLAP_THRESHOLD;
double low_host_flap_threshold = DEFAULT_LOW_HOST_FLAP_THRESHOLD;
double high_host_flap_threshold = DEFAULT_HIGH_HOST_FLAP_THRESHOLD;
int use_large_installation_tweaks = DEFAULT_USE_LARGE_INSTALLATION_TWEAKS;
int enable_environment_macros = TRUE;
int free_child_process_memory = -1;
int child_processes_fork_twice = -1;
int enable_embedded_perl = DEFAULT_ENABLE_EMBEDDED_PERL;
int use_embedded_perl_implicitly = DEFAULT_USE_EMBEDDED_PERL_IMPLICITLY;
int embedded_perl_initialized = FALSE;
int date_format = DATE_FORMAT_US;
char *use_timezone = NULL;
int allow_empty_hostgroup_assignment = DEFAULT_ALLOW_EMPTY_HOSTGROUP_ASSIGNMENT;
int command_file_fd;
FILE *command_file_fp;
int command_file_created = FALSE;
extern contact *contact_list;
extern contactgroup *contactgroup_list;
extern hostgroup *hostgroup_list;
extern command *command_list;
extern timeperiod *timeperiod_list;
extern serviceescalation *serviceescalation_list;
notification *notification_list;
check_result check_result_info;
check_result *check_result_list = NULL;
unsigned long max_check_result_file_age = DEFAULT_MAX_CHECK_RESULT_AGE;
dbuf check_result_dbuf;
circular_buffer external_command_buffer;
circular_buffer check_result_buffer;
pthread_t worker_threads[TOTAL_WORKER_THREADS];
int external_command_buffer_slots = DEFAULT_EXTERNAL_COMMAND_BUFFER_SLOTS;
check_stats check_statistics[MAX_CHECK_STATS_TYPES];
char *debug_file;
int debug_level = DEFAULT_DEBUG_LEVEL;
int debug_verbosity = DEFAULT_DEBUG_VERBOSITY;
unsigned long max_debug_file_size = DEFAULT_MAX_DEBUG_FILE_SIZE;
/* Following main() declaration required by older versions of Perl ut 5.00503 */
int main(int argc, char **argv, char **env) {
int result;
int error = FALSE;
char *buffer = NULL;
int display_license = FALSE;
int display_help = FALSE;
int c = 0;
struct tm *tm, tm_s;
time_t now;
char datestring[256];
nagios_macros *mac;
mac = get_global_macros();
#ifdef HAVE_GETOPT_H
int option_index = 0;
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"license", no_argument, 0, 'V'},
{"verify-config", no_argument, 0, 'v'},
{"daemon", no_argument, 0, 'd'},
{"test-scheduling", no_argument, 0, 's'},
{"dont-verify-objects", no_argument, 0, 'o'},
{"dont-verify-paths", no_argument, 0, 'x'},
{"precache-objects", no_argument, 0, 'p'},
{"use-precached-objects", no_argument, 0, 'u'},
{0, 0, 0, 0}
};
#endif
/* make sure we have the correct number of command line arguments */
if(argc < 2)
error = TRUE;
/* get all command line arguments */
while(1) {
#ifdef HAVE_GETOPT_H
c = getopt_long(argc, argv, "+hVvdsoxpu", long_options, &option_index);
#else
c = getopt(argc, argv, "+hVvdsoxpu");
#endif
if(c == -1 || c == EOF)
break;
switch(c) {
case '?': /* usage */
case 'h':
display_help = TRUE;
break;
case 'V': /* version */
display_license = TRUE;
break;
case 'v': /* verify */
verify_config = TRUE;
break;
case 's': /* scheduling check */
test_scheduling = TRUE;
break;
case 'd': /* daemon mode */
daemon_mode = TRUE;
break;
case 'o': /* don't verify objects */
/*
verify_object_relationships=FALSE;
*/
break;
case 'x': /* don't verify circular paths */
verify_circular_paths = FALSE;
break;
case 'p': /* precache object config */
precache_objects = TRUE;
break;
case 'u': /* use precached object config */
use_precached_objects = TRUE;
break;
default:
break;
}
}
/* make sure we have the right combination of arguments */
if(precache_objects == TRUE && (test_scheduling == FALSE && verify_config == FALSE)) {
error = TRUE;
display_help = TRUE;
}
#ifdef DEBUG_MEMORY
mtrace();
#endif
if(daemon_mode == FALSE) {
printf("\nNagios Core %s\n", PROGRAM_VERSION);
printf("Copyright (c) 2009-2011 Nagios Core Development Team and Community Contributors\n");
printf("Copyright (c) 1999-2009 Ethan Galstad\n");
printf("Last Modified: %s\n", PROGRAM_MODIFICATION_DATE);
printf("License: GPL\n\n");
printf("Website: http://www.nagios.org\n");
}
/* just display the license */
if(display_license == TRUE) {
printf("This program is free software; you can redistribute it and/or modify\n");
printf("it under the terms of the GNU General Public License version 2 as\n");
printf("published by the Free Software Foundation.\n\n");
printf("This program is distributed in the hope that it will be useful,\n");
printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
printf("GNU General Public License for more details.\n\n");
printf("You should have received a copy of the GNU General Public License\n");
printf("along with this program; if not, write to the Free Software\n");
printf("Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
exit(OK);
}
/* make sure we got the main config file on the command line... */
if(optind >= argc)
error = TRUE;
/* if there are no command line options (or if we encountered an error), print usage */
if(error == TRUE || display_help == TRUE) {
printf("Usage: %s [options] <main_config_file>\n", argv[0]);
printf("\n");
printf("Options:\n");
printf("\n");
printf(" -v, --verify-config Verify all configuration data\n");
printf(" -s, --test-scheduling Shows projected/recommended check scheduling and other\n");
printf(" diagnostic info based on the current configuration files.\n");
/*printf(" -o, --dont-verify-objects Don't verify object relationships - USE WITH CAUTION!\n");*/
printf(" -x, --dont-verify-paths Don't check for circular object paths - USE WITH CAUTION!\n");
printf(" -p, --precache-objects Precache object configuration - use with -v or -s options\n");
printf(" -u, --use-precached-objects Use precached object config file\n");
printf(" -d, --daemon Starts Nagios in daemon mode, instead of as a foreground process\n");
printf("\n");
printf("Visit the Nagios website at http://www.nagios.org/ for bug fixes, new\n");
printf("releases, online documentation, FAQs, information on subscribing to\n");
printf("the mailing lists, and commercial support options for Nagios.\n");
printf("\n");
exit(ERROR);
}
/*
* Set the signal handler for the SIGXFSZ signal here because
* we may encounter this signal before the other signal handlers
* are set.
*/
signal(SIGXFSZ, handle_sigxfsz);
/* config file is last argument specified */
config_file = (char *)strdup(argv[optind]);
if(config_file == NULL) {
printf("Error allocating memory.\n");
exit(ERROR);
}
/* make sure the config file uses an absolute path */
if(config_file[0] != '/') {
/* save the name of the config file */
buffer = (char *)strdup(config_file);
/* reallocate a larger chunk of memory */
config_file = (char *)realloc(config_file, MAX_FILENAME_LENGTH);
if(config_file == NULL) {
printf("Error allocating memory.\n");
exit(ERROR);
}
/* get absolute path of current working directory */
getcwd(config_file, MAX_FILENAME_LENGTH);
/* append a forward slash */
strncat(config_file, "/", 1);
config_file[MAX_FILENAME_LENGTH - 1] = '\x0';
/* append the config file to the path */
strncat(config_file, buffer, MAX_FILENAME_LENGTH - strlen(config_file) - 1);
config_file[MAX_FILENAME_LENGTH - 1] = '\x0';
my_free(buffer);
}
/* we're just verifying the configuration... */
if(verify_config == TRUE) {
/* reset program variables */
reset_variables();
printf("Reading configuration data...\n");
/* read in the configuration files (main config file, resource and object config files) */
if((result = read_main_config_file(config_file)) == OK) {
printf(" Read main config file okay...\n");
/* drop privileges */
if((result = drop_privileges(nagios_user, nagios_group)) == ERROR)
printf(" Failed to drop privileges. Aborting.");
else {
/* read object config files */
if((result = read_all_object_data(config_file)) == OK)
printf(" Read object config files okay...\n");
else
printf(" Error processing object config files!\n");
}
}
else
printf(" Error processing main config file!\n\n");
printf("\n");
/* there was a problem reading the config files */
if(result != OK) {
/* if the config filename looks fishy, warn the user */
if(!strstr(config_file, "nagios.cfg")) {
printf("\n***> The name of the main configuration file looks suspicious...\n");
printf("\n");
printf(" Make sure you are specifying the name of the MAIN configuration file on\n");
printf(" the command line and not the name of another configuration file. The\n");
printf(" main configuration file is typically '/usr/local/nagios/etc/nagios.cfg'\n");
}
printf("\n***> One or more problems was encountered while processing the config files...\n");
printf("\n");
printf(" Check your configuration file(s) to ensure that they contain valid\n");
printf(" directives and data defintions. If you are upgrading from a previous\n");
printf(" version of Nagios, you should be aware that some variables/definitions\n");
printf(" may have been removed or modified in this version. Make sure to read\n");
printf(" the HTML documentation regarding the config files, as well as the\n");
printf(" 'Whats New' section to find out what has changed.\n\n");
}
/* the config files were okay, so run the pre-flight check */
else {
printf("Running pre-flight check on configuration data...\n\n");
/* run the pre-flight check to make sure things look okay... */
result = pre_flight_check();
if(result == OK)
printf("\nThings look okay - No serious problems were detected during the pre-flight check\n");
else {
printf("\n***> One or more problems was encountered while running the pre-flight check...\n");
printf("\n");
printf(" Check your configuration file(s) to ensure that they contain valid\n");
printf(" directives and data defintions. If you are upgrading from a previous\n");
printf(" version of Nagios, you should be aware that some variables/definitions\n");
printf(" may have been removed or modified in this version. Make sure to read\n");
printf(" the HTML documentation regarding the config files, as well as the\n");
printf(" 'Whats New' section to find out what has changed.\n\n");
}
}
/* clean up after ourselves */
cleanup();
/* free config_file */
my_free(config_file);
/* exit */
exit(result);
}
/* we're just testing scheduling... */
else if(test_scheduling == TRUE) {
/* reset program variables */
reset_variables();
/* read in the configuration files (main config file and all host config files) */
result = read_main_config_file(config_file);
/* drop privileges */
if(result == OK)
if((result = drop_privileges(nagios_user, nagios_group)) == ERROR)
printf("Failed to drop privileges. Aborting.");
/* read object config files */
if(result == OK)
result = read_all_object_data(config_file);
/* read initial service and host state information */
if(result == OK) {
initialize_retention_data(config_file);
read_initial_state_information();
}
if(result != OK)
printf("***> One or more problems was encountered while reading configuration data...\n");
/* run the pre-flight check to make sure everything looks okay */
if(result == OK) {
if((result = pre_flight_check()) != OK)
printf("***> One or more problems was encountered while running the pre-flight check...\n");
}
if(result == OK) {
/* initialize the event timing loop */
init_timing_loop();
/* display scheduling information */
display_scheduling_info();
if(precache_objects == TRUE) {
printf("\n");
printf("OBJECT PRECACHING\n");
printf("-----------------\n");
printf("Object config files were precached.\n");
}
}
#undef TEST_TIMEPERIODS
#ifdef TEST_TIMEPERIODS
/* DO SOME TIMEPERIOD TESTING - ADDED 08/11/2009 */
time_t now, pref_time, valid_time;
timeperiod *tp;
tp = find_timeperiod("247_exclusion");
time(&now);
pref_time = now;
get_next_valid_time(pref_time, &valid_time, tp);
printf("=====\n");
printf("CURRENT: %lu = %s", (unsigned long)now, ctime(&now));
printf("PREFERRED: %lu = %s", (unsigned long)pref_time, ctime(&pref_time));
printf("NEXT: %lu = %s", (unsigned long)valid_time, ctime(&valid_time));
printf("=====\n");
#endif
/* clean up after ourselves */
cleanup();
/* exit */
exit(result);
}
/* else start to monitor things... */
else {
/* keep monitoring things until we get a shutdown command */
do {
/* reset program variables */
reset_variables();
/* get PID */
nagios_pid = (int)getpid();
/* read in the configuration files (main and resource config files) */
result = read_main_config_file(config_file);
/* NOTE 11/06/07 EG moved to after we read config files, as user may have overridden timezone offset */
/* get program (re)start time and save as macro */
program_start = time(NULL);
my_free(mac->x[MACRO_PROCESSSTARTTIME]);
asprintf(&mac->x[MACRO_PROCESSSTARTTIME], "%lu", (unsigned long)program_start);
/* open debug log */
open_debug_log();
/* drop privileges */
if(drop_privileges(nagios_user, nagios_group) == ERROR) {
logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_CONFIG_ERROR, TRUE, "Failed to drop privileges. Aborting.");
cleanup();
exit(ERROR);
}
#ifdef USE_EVENT_BROKER
/* initialize modules */
neb_init_modules();
neb_init_callback_list();
#endif
/* this must be logged after we read config data, as user may have changed location of main log file */
logit(NSLOG_PROCESS_INFO, TRUE, "Nagios %s starting... (PID=%d)\n", PROGRAM_VERSION, (int)getpid());
/* log the local time - may be different than clock time due to timezone offset */
now = time(NULL);
tm = localtime_r(&now, &tm_s);
strftime(datestring, sizeof(datestring), "%a %b %d %H:%M:%S %Z %Y", tm);
logit(NSLOG_PROCESS_INFO, TRUE, "Local time is %s", datestring);
/* write log version/info */
write_log_file_info(NULL);
#ifdef USE_EVENT_BROKER
/* load modules */
neb_load_all_modules();
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_PRELAUNCH, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
/* read in all object config data */
if(result == OK)
result = read_all_object_data(config_file);
/* there was a problem reading the config files */
if(result != OK)
logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_CONFIG_ERROR, TRUE, "Bailing out due to one or more errors encountered in the configuration files. Run Nagios from the command line with the -v option to verify your config before restarting. (PID=%d)", (int)getpid());
else {
/* run the pre-flight check to make sure everything looks okay*/
if((result = pre_flight_check()) != OK)
logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR | NSLOG_VERIFICATION_ERROR, TRUE, "Bailing out due to errors encountered while running the pre-flight check. Run Nagios from the command line with the -v option to verify your config before restarting. (PID=%d)\n", (int)getpid());
}
/* an error occurred that prevented us from (re)starting */
if(result != OK) {
/* if we were restarting, we need to cleanup from the previous run */
if(sigrestart == TRUE) {
/* clean up the status data */
cleanup_status_data(config_file, TRUE);
/* shutdown the external command worker thread */
shutdown_command_file_worker_thread();
/* close and delete the external command file FIFO */
close_command_file();
/* cleanup embedded perl interpreter */
if(embedded_perl_initialized == TRUE)
deinit_embedded_perl();
}
#ifdef USE_EVENT_BROKER
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_PROCESS_INITIATED, NEBATTR_SHUTDOWN_ABNORMAL, NULL);
#endif
cleanup();
exit(ERROR);
}
/* initialize embedded Perl interpreter */
/* NOTE 02/15/08 embedded Perl must be initialized if compiled in, regardless of whether or not its enabled in the config file */
/* It compiled it, but not initialized, Nagios will segfault in readdir() calls, as libperl takes this function over */
if(embedded_perl_initialized == FALSE) {
/* if(enable_embedded_perl==TRUE){*/
#ifdef EMBEDDEDPERL
init_embedded_perl(env);
#else
init_embedded_perl(NULL);
#endif
embedded_perl_initialized = TRUE;
/* }*/
}
/* handle signals (interrupts) */
setup_sighandler();
#ifdef USE_EVENT_BROKER
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_START, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
/* enter daemon mode (unless we're restarting...) */
if(daemon_mode == TRUE && sigrestart == FALSE) {
result = daemon_init();
/* we had an error daemonizing, so bail... */
if(result == ERROR) {
logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, TRUE, "Bailing out due to failure to daemonize. (PID=%d)", (int)getpid());
#ifdef USE_EVENT_BROKER
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_PROCESS_INITIATED, NEBATTR_SHUTDOWN_ABNORMAL, NULL);
#endif
cleanup();
exit(ERROR);
}
asprintf(&buffer, "Finished daemonizing... (New PID=%d)\n", (int)getpid());
write_to_all_logs(buffer, NSLOG_PROCESS_INFO);
my_free(buffer);
/* get new PID */
nagios_pid = (int)getpid();
}
/* open the command file (named pipe) for reading */
result = open_command_file();
if(result != OK) {
logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, TRUE, "Bailing out due to errors encountered while trying to initialize the external command file... (PID=%d)\n", (int)getpid());
#ifdef USE_EVENT_BROKER
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_PROCESS_INITIATED, NEBATTR_SHUTDOWN_ABNORMAL, NULL);
#endif
cleanup();
exit(ERROR);
}
/* initialize status data unless we're starting */
if(sigrestart == FALSE)
initialize_status_data(config_file);
/* read initial service and host state information */
initialize_retention_data(config_file);
read_initial_state_information();
/* initialize comment data */
initialize_comment_data(config_file);
/* initialize scheduled downtime data */
initialize_downtime_data(config_file);
/* initialize performance data */
initialize_performance_data(config_file);
/* Determine which checks are still executing so they are not
scheduled when the timing loop is initialized */
find_executing_checks(check_result_path);
/* initialize the event timing loop */
init_timing_loop();
/* initialize check statistics */
init_check_stats();
/* check for updates */
check_for_nagios_updates(FALSE, TRUE);
/* update all status data (with retained information) */
update_all_status_data();
/* log initial host and service state */
log_host_states(INITIAL_STATES, NULL);
log_service_states(INITIAL_STATES, NULL);
/* reset the restart flag */
sigrestart = FALSE;
#ifdef USE_EVENT_BROKER
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_EVENTLOOPSTART, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
/* get event start time and save as macro */
event_start = time(NULL);
my_free(mac->x[MACRO_EVENTSTARTTIME]);
asprintf(&mac->x[MACRO_EVENTSTARTTIME], "%lu", (unsigned long)event_start);
/***** start monitoring all services *****/
/* (doesn't return until a restart or shutdown signal is encountered) */
event_execution_loop();
/* 03/01/2007 EG Moved from sighandler() to prevent FUTEX locking problems under NPTL */
/* 03/21/2007 EG SIGSEGV signals are still logged in sighandler() so we don't loose them */
/* did we catch a signal? */
if(caught_signal == TRUE) {
if(sig_id == SIGHUP)
asprintf(&buffer, "Caught SIGHUP, restarting...\n");
else if(sig_id != SIGSEGV)
asprintf(&buffer, "Caught SIG%s, shutting down...\n", sigs[sig_id]);
write_to_all_logs(buffer, NSLOG_PROCESS_INFO);
my_free(buffer);
}
#ifdef USE_EVENT_BROKER
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_EVENTLOOPEND, NEBFLAG_NONE, NEBATTR_NONE, NULL);
if(sigshutdown == TRUE)
broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_USER_INITIATED, NEBATTR_SHUTDOWN_NORMAL, NULL);
else if(sigrestart == TRUE)
broker_program_state(NEBTYPE_PROCESS_RESTART, NEBFLAG_USER_INITIATED, NEBATTR_RESTART_NORMAL, NULL);
#endif
/* save service and host state information */
save_state_information(FALSE);
cleanup_retention_data(config_file);
/* clean up performance data */
cleanup_performance_data(config_file);
/* clean up the scheduled downtime data */
cleanup_downtime_data(config_file);
/* clean up the comment data */
cleanup_comment_data(config_file);
/* clean up the status data unless we're restarting */
if(sigrestart == FALSE)
cleanup_status_data(config_file, TRUE);
/* close and delete the external command file FIFO unless we're restarting */
if(sigrestart == FALSE) {
shutdown_command_file_worker_thread();
close_command_file();
}
/* cleanup embedded perl interpreter */
if(sigrestart == FALSE)
deinit_embedded_perl();
/* shutdown stuff... */
if(sigshutdown == TRUE) {
/* make sure lock file has been removed - it may not have been if we received a shutdown command */
if(daemon_mode == TRUE)
unlink(lock_file);
/* log a shutdown message */
logit(NSLOG_PROCESS_INFO, TRUE, "Successfully shutdown... (PID=%d)\n", (int)getpid());
}
/* clean up after ourselves */
cleanup();
/* close debug log */
close_debug_log();
}
while(sigrestart == TRUE && sigshutdown == FALSE);
/* free misc memory */
my_free(config_file);
}
return OK;
}

1778
base/nagiostats.c Normal file

File diff suppressed because it is too large Load Diff

640
base/nebmods.c Normal file
View File

@ -0,0 +1,640 @@
/*****************************************************************************
*
* NEBMODS.C - Event Broker Module Functions
*
* Copyright (c) 2002-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 11-02-2008
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/nebmods.h"
#include "../include/neberrors.h"
#include "../include/nagios.h"
#ifdef USE_EVENT_BROKER
nebmodule *neb_module_list = NULL;
nebcallback **neb_callback_list = NULL;
extern char *temp_path;
/*#define DEBUG*/
/****************************************************************************/
/****************************************************************************/
/* INITIALIZATION/CLEANUP FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* initialize module routines */
int neb_init_modules(void) {
#ifdef USE_LTDL
int result = OK;
#endif
/* initialize library */
#ifdef USE_LTDL
result = lt_dlinit();
if(result)
return ERROR;
#endif
return OK;
}
/* deinitialize module routines */
int neb_deinit_modules(void) {
#ifdef USE_LTDL
int result = OK;
#endif
/* deinitialize library */
#ifdef USE_LTDL
result = lt_dlexit();
if(result)
return ERROR;
#endif
return OK;
}
/* add a new module to module list */
int neb_add_module(char *filename, char *args, int should_be_loaded) {
nebmodule *new_module = NULL;
int x = OK;
if(filename == NULL)
return ERROR;
/* allocate memory */
new_module = (nebmodule *)malloc(sizeof(nebmodule));
if(new_module == NULL)
return ERROR;
/* initialize vars */
new_module->filename = (char *)strdup(filename);
new_module->args = (args == NULL) ? NULL : (char *)strdup(args);
new_module->should_be_loaded = should_be_loaded;
new_module->is_currently_loaded = FALSE;
for(x = 0; x < NEBMODULE_MODINFO_NUMITEMS; x++)
new_module->info[x] = NULL;
new_module->module_handle = NULL;
new_module->init_func = NULL;
new_module->deinit_func = NULL;
#ifdef HAVE_PTHREAD_H
new_module->thread_id = (pthread_t)NULL;
#endif
/* add module to head of list */
new_module->next = neb_module_list;
neb_module_list = new_module;
log_debug_info(DEBUGL_EVENTBROKER, 0, "Added module: name='%s', args='%s', should_be_loaded='%d'\n", filename, args, should_be_loaded);
return OK;
}
/* free memory allocated to module list */
int neb_free_module_list(void) {
nebmodule *temp_module = NULL;
nebmodule *next_module = NULL;
int x = OK;
for(temp_module = neb_module_list; temp_module;) {
next_module = temp_module->next;
my_free(temp_module->filename);
my_free(temp_module->args);
for(x = 0; x < NEBMODULE_MODINFO_NUMITEMS; x++)
my_free(temp_module->info[x]);
my_free(temp_module);
temp_module = next_module;
}
neb_module_list = NULL;
return OK;
}
/****************************************************************************/
/****************************************************************************/
/* LOAD/UNLOAD FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* load all modules */
int neb_load_all_modules(void) {
nebmodule *temp_module = NULL;
int result = OK;
for(temp_module = neb_module_list; temp_module; temp_module = temp_module->next) {
result = neb_load_module(temp_module);
}
return OK;
}
#ifndef PATH_MAX
# define PATH_MAX 4096
#endif
/* load a particular module */
int neb_load_module(nebmodule *mod) {
int (*initfunc)(int, char *, void *);
int *module_version_ptr = NULL;
char output_file[PATH_MAX];
int dest_fd, result = OK;
if(mod == NULL || mod->filename == NULL)
return ERROR;
/* don't reopen the module */
if(mod->is_currently_loaded == TRUE)
return OK;
/* don't load modules unless they should be loaded */
if(mod->should_be_loaded == FALSE)
return ERROR;
/**********
Using dlopen() is great, but a real danger as-is. The problem with loaded modules is that if you overwrite the original file (e.g. using 'mv'),
you do not alter the inode of the original file. Since the original file/module is memory-mapped in some fashion, Nagios will segfault the next
time an event broker call is directed to one of the module's callback functions. This is extremely problematic when it comes to upgrading NEB
modules while Nagios is running. A workaround is to (1) 'mv' the original/loaded module file to another name (on the same filesystem)
and (2) copy the new module file to the location of the original one (using the original filename). In this scenario, dlopen() will keep referencing
the original file/inode for callbacks. This is not an ideal solution. A better one is to delete the module file once it is loaded by dlopen().
This prevents other processed from unintentially overwriting the original file, which would cause Nagios to crash. However, if we delete the file
before anyone else can muck with it, things should be good. 'lsof' shows that a deleted file is still referenced by the kernel and callback
functions continue to work once the module has been loaded. Long story, but this took quite a while to figure out, as there isn't much
of anything I could find on the subject other than some sketchy info on similar problems on HP-UX. Hopefully this will save future coders some time.
So... the trick is to (1) copy the module to a temp file, (2) dlopen() the temp file, and (3) immediately delete the temp file.
************/
/*
* open a temp file for copying the module. We use my_fdcopy() so
* we re-use the destination file descriptor returned by mkstemp(3),
* which we have to close ourselves.
*/
snprintf(output_file, sizeof(output_file) - 1, "%s/nebmodXXXXXX", temp_path);
dest_fd = mkstemp(output_file);
result = my_fdcopy(mod->filename, output_file, dest_fd);
close(dest_fd);
if(result == ERROR) {
logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Failed to safely copy module '%s'. The module will not be loaded\n", mod->filename);
return ERROR;
}
/* load the module (use the temp copy we just made) */
#ifdef USE_LTDL
mod->module_handle = lt_dlopen(output_file);
#else
mod->module_handle = (void *)dlopen(output_file, RTLD_NOW | RTLD_GLOBAL);
#endif
if(mod->module_handle == NULL) {
#ifdef USE_LTDL
logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Could not load module '%s' -> %s\n", mod->filename, lt_dlerror());
#else
logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Could not load module '%s' -> %s\n", mod->filename, dlerror());
#endif
return ERROR;
}
/* mark the module as being loaded */
mod->is_currently_loaded = TRUE;
/* delete the temp copy of the module we just created and loaded */
/* this will prevent other processes from overwriting the file (using the same inode), which would cause Nagios to crash */
/* the kernel will keep the deleted file in memory until we unload it */
/* NOTE: This *should* be portable to most Unices, but I've only tested it on Linux */
if(unlink(output_file) == -1) {
logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Could not delete temporary file '%s' used for module '%s'. The module will be unloaded: %s\n", output_file, mod->filename, strerror(errno));
neb_unload_module(mod, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_API_VERSION);
return ERROR;
}
/* find module API version */
#ifdef USE_LTDL
module_version_ptr = (int *)lt_dlsym(mod->module_handle, "__neb_api_version");
#else
module_version_ptr = (int *)dlsym(mod->module_handle, "__neb_api_version");
#endif
/* check the module API version */
if(module_version_ptr == NULL || ((*module_version_ptr) != CURRENT_NEB_API_VERSION)) {
logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Module '%s' is using an old or unspecified version of the event broker API. Module will be unloaded.\n", mod->filename);
neb_unload_module(mod, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_API_VERSION);
return ERROR;
}
/* locate the initialization function */
#ifdef USE_LTDL
mod->init_func = lt_dlsym(mod->module_handle, "nebmodule_init");
#else
mod->init_func = (void *)dlsym(mod->module_handle, "nebmodule_init");
#endif
/* if the init function could not be located, unload the module */
if(mod->init_func == NULL) {
logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Could not locate nebmodule_init() in module '%s'. Module will be unloaded.\n", mod->filename);
neb_unload_module(mod, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_NO_INIT);
return ERROR;
}
/* run the module's init function */
initfunc = mod->init_func;
result = (*initfunc)(NEBMODULE_NORMAL_LOAD, mod->args, mod->module_handle);
/* if the init function returned an error, unload the module */
if(result != OK) {
logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Function nebmodule_init() in module '%s' returned an error. Module will be unloaded.\n", mod->filename);
neb_unload_module(mod, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_BAD_INIT);
return ERROR;
}
logit(NSLOG_INFO_MESSAGE, FALSE, "Event broker module '%s' initialized successfully.\n", mod->filename);
/* locate the de-initialization function (may or may not be present) */
#ifdef USE_LTDL
mod->deinit_func = lt_dlsym(mod->module_handle, "nebmodule_deinit");
#else
mod->deinit_func = (void *)dlsym(mod->module_handle, "nebmodule_deinit");
#endif
log_debug_info(DEBUGL_EVENTBROKER, 0, "Module '%s' loaded with return code of '%d'\n", mod->filename, result);
if(mod->deinit_func != NULL)
log_debug_info(DEBUGL_EVENTBROKER, 0, "nebmodule_deinit() found\n");
return OK;
}
/* close (unload) all modules that are currently loaded */
int neb_unload_all_modules(int flags, int reason) {
nebmodule *temp_module;
for(temp_module = neb_module_list; temp_module; temp_module = temp_module->next) {
/* skip modules that are not loaded */
if(temp_module->is_currently_loaded == FALSE)
continue;
/* skip modules that do not have a valid handle */
if(temp_module->module_handle == NULL)
continue;
/* close/unload the module */
neb_unload_module(temp_module, flags, reason);
}
return OK;
}
/* close (unload) a particular module */
int neb_unload_module(nebmodule *mod, int flags, int reason) {
int (*deinitfunc)(int, int);
int result = OK;
if(mod == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTBROKER, 0, "Attempting to unload module '%s': flags=%d, reason=%d\n", mod->filename, flags, reason);
/* call the de-initialization function if available (and the module was initialized) */
if(mod->deinit_func && reason != NEBMODULE_ERROR_BAD_INIT) {
deinitfunc = mod->deinit_func;
/* module can opt to not be unloaded */
result = (*deinitfunc)(flags, reason);
/* if module doesn't want to be unloaded, exit with error (unless its being forced) */
if(result != OK && !(flags & NEBMODULE_FORCE_UNLOAD))
return ERROR;
}
/* deregister all of the module's callbacks */
neb_deregister_module_callbacks(mod);
/* unload the module */
#ifdef USE_LTDL
result = lt_dlclose(mod->module_handle);
#else
result = dlclose(mod->module_handle);
#endif
/* mark the module as being unloaded */
mod->is_currently_loaded = FALSE;
log_debug_info(DEBUGL_EVENTBROKER, 0, "Module '%s' unloaded successfully.\n", mod->filename);
logit(NSLOG_INFO_MESSAGE, FALSE, "Event broker module '%s' deinitialized successfully.\n", mod->filename);
return OK;
}
/****************************************************************************/
/****************************************************************************/
/* INFO FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* sets module information */
int neb_set_module_info(void *handle, int type, char *data) {
nebmodule *temp_module = NULL;
if(handle == NULL)
return NEBERROR_NOMODULE;
/* check type */
if(type < 0 || type >= NEBMODULE_MODINFO_NUMITEMS)
return NEBERROR_MODINFOBOUNDS;
/* find the module */
for(temp_module = neb_module_list; temp_module != NULL; temp_module = temp_module->next) {
if((void *)temp_module->module_handle == (void *)handle)
break;
}
if(temp_module == NULL)
return NEBERROR_BADMODULEHANDLE;
/* free any previously allocated memory */
my_free(temp_module->info[type]);
/* allocate memory for the new data */
if((temp_module->info[type] = (char *)strdup(data)) == NULL)
return NEBERROR_NOMEM;
return OK;
}
/****************************************************************************/
/****************************************************************************/
/* CALLBACK FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* allows a module to register a callback function */
int neb_register_callback(int callback_type, void *mod_handle, int priority, int (*callback_func)(int, void *)) {
nebmodule *temp_module = NULL;
nebcallback *new_callback = NULL;
nebcallback *temp_callback = NULL;
nebcallback *last_callback = NULL;
if(callback_func == NULL)
return NEBERROR_NOCALLBACKFUNC;
if(neb_callback_list == NULL)
return NEBERROR_NOCALLBACKLIST;
if(mod_handle == NULL)
return NEBERROR_NOMODULEHANDLE;
/* make sure the callback type is within bounds */
if(callback_type < 0 || callback_type >= NEBCALLBACK_NUMITEMS)
return NEBERROR_CALLBACKBOUNDS;
/* make sure module handle is valid */
for(temp_module = neb_module_list; temp_module; temp_module = temp_module->next) {
if((void *)temp_module->module_handle == (void *)mod_handle)
break;
}
if(temp_module == NULL)
return NEBERROR_BADMODULEHANDLE;
/* allocate memory */
new_callback = (nebcallback *)malloc(sizeof(nebcallback));
if(new_callback == NULL)
return NEBERROR_NOMEM;
new_callback->priority = priority;
new_callback->module_handle = (void *)mod_handle;
new_callback->callback_func = (void *)callback_func;
/* add new function to callback list, sorted by priority (first come, first served for same priority) */
new_callback->next = NULL;
if(neb_callback_list[callback_type] == NULL)
neb_callback_list[callback_type] = new_callback;
else {
last_callback = NULL;
for(temp_callback = neb_callback_list[callback_type]; temp_callback != NULL; temp_callback = temp_callback->next) {
if(temp_callback->priority > new_callback->priority)
break;
last_callback = temp_callback;
}
if(last_callback == NULL)
neb_callback_list[callback_type] = new_callback;
else {
if(temp_callback == NULL)
last_callback->next = new_callback;
else {
new_callback->next = temp_callback;
last_callback->next = new_callback;
}
}
}
return OK;
}
/* dregisters all callback functions for a given module */
int neb_deregister_module_callbacks(nebmodule *mod) {
nebcallback *temp_callback = NULL;
nebcallback *next_callback = NULL;
int callback_type = 0;
if(mod == NULL)
return NEBERROR_NOMODULE;
if(neb_callback_list == NULL)
return OK;
for(callback_type = 0; callback_type < NEBCALLBACK_NUMITEMS; callback_type++) {
for(temp_callback = neb_callback_list[callback_type]; temp_callback != NULL; temp_callback = next_callback) {
next_callback = temp_callback->next;
if((void *)temp_callback->module_handle == (void *)mod->module_handle)
neb_deregister_callback(callback_type, (int(*)(int, void*))temp_callback->callback_func);
}
}
return OK;
}
/* allows a module to deregister a callback function */
int neb_deregister_callback(int callback_type, int (*callback_func)(int, void *)) {
nebcallback *temp_callback = NULL;
nebcallback *last_callback = NULL;
nebcallback *next_callback = NULL;
if(callback_func == NULL)
return NEBERROR_NOCALLBACKFUNC;
if(neb_callback_list == NULL)
return NEBERROR_NOCALLBACKLIST;
/* make sure the callback type is within bounds */
if(callback_type < 0 || callback_type >= NEBCALLBACK_NUMITEMS)
return NEBERROR_CALLBACKBOUNDS;
/* find the callback to remove */
for(temp_callback = last_callback = neb_callback_list[callback_type]; temp_callback != NULL; temp_callback = next_callback) {
next_callback = temp_callback->next;
/* we found it */
if(temp_callback->callback_func == (void *)callback_func)
break;
last_callback = temp_callback;
}
/* we couldn't find the callback */
if(temp_callback == NULL)
return NEBERROR_CALLBACKNOTFOUND;
else {
/* only one item in the list */
if(temp_callback != last_callback->next)
neb_callback_list[callback_type] = NULL;
else
last_callback->next = next_callback;
my_free(temp_callback);
}
return OK;
}
/* make callbacks to modules */
int neb_make_callbacks(int callback_type, void *data) {
nebcallback *temp_callback, *next_callback;
int (*callbackfunc)(int, void *);
register int cbresult = 0;
int total_callbacks = 0;
/* make sure callback list is initialized */
if(neb_callback_list == NULL)
return ERROR;
/* make sure the callback type is within bounds */
if(callback_type < 0 || callback_type >= NEBCALLBACK_NUMITEMS)
return ERROR;
log_debug_info(DEBUGL_EVENTBROKER, 1, "Making callbacks (type %d)...\n", callback_type);
/* make the callbacks... */
for(temp_callback = neb_callback_list[callback_type]; temp_callback; temp_callback = next_callback) {
next_callback = temp_callback->next;
callbackfunc = temp_callback->callback_func;
cbresult = callbackfunc(callback_type, data);
temp_callback = next_callback;
total_callbacks++;
log_debug_info(DEBUGL_EVENTBROKER, 2, "Callback #%d (type %d) return code = %d\n", total_callbacks, callback_type, cbresult);
/* module wants to cancel callbacks to other modules (and potentially cancel the default Nagios handling of an event) */
if(cbresult == NEBERROR_CALLBACKCANCEL)
break;
/* module wants to override default Nagios handling of an event */
/* not sure if we should bail out here just because one module wants to override things - what about other modules? EG 12/11/2006 */
else if(cbresult == NEBERROR_CALLBACKOVERRIDE)
break;
}
return cbresult;
}
/* initialize callback list */
int neb_init_callback_list(void) {
register int x = 0;
/* allocate memory for the callback list */
neb_callback_list = (nebcallback **)malloc(NEBCALLBACK_NUMITEMS * sizeof(nebcallback *));
if(neb_callback_list == NULL)
return ERROR;
/* initialize list pointers */
for(x = 0; x < NEBCALLBACK_NUMITEMS; x++)
neb_callback_list[x] = NULL;
return OK;
}
/* free memory allocated to callback list */
int neb_free_callback_list(void) {
nebcallback *temp_callback = NULL;
nebcallback *next_callback = NULL;
register int x = 0;
if(neb_callback_list == NULL)
return OK;
for(x = 0; x < NEBCALLBACK_NUMITEMS; x++) {
for(temp_callback = neb_callback_list[x]; temp_callback != NULL; temp_callback = next_callback) {
next_callback = temp_callback->next;
my_free(temp_callback);
}
neb_callback_list[x] = NULL;
}
my_free(neb_callback_list);
return OK;
}
#endif

292
base/netutils.c Normal file
View File

@ -0,0 +1,292 @@
/*****************************************************************************
*
* NETUTILS.C - Network connection utility functions for Nagios
*
* Copyright (c) 1999,2008 Ethan Galstad (egalstad@nagios.org)
* Portions Copyright (c) 1999-2008 Nagios Plugin development team
* Last Modified: 12-04-2008
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/netutils.h"
/* connect to a TCP socket in nonblocking fashion */
int my_tcp_connect(char *host_name, int port, int *sd, int timeout) {
struct addrinfo hints;
struct addrinfo *res;
int result;
char port_str[6];
int flags = 0;
fd_set rfds;
fd_set wfds;
struct timeval tv;
int optval;
socklen_t optlen;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
/* make sure our static port_str is long enough */
if(port > 65535)
return ERROR;
snprintf(port_str, sizeof(port_str), "%d", port);
result = getaddrinfo(host_name, port_str, &hints, &res);
if(result != 0) {
/*printf("GETADDRINFO: %s (%s) = %s\n",host_name,port_str,gai_strerror(result));*/
return ERROR;
}
/* create a socket */
*sd = socket(res->ai_family, SOCK_STREAM, res->ai_protocol);
if(*sd < 0) {
freeaddrinfo(res);
return ERROR;
}
/* make socket non-blocking */
flags = fcntl(*sd, F_GETFL, 0);
fcntl(*sd, F_SETFL, flags | O_NONBLOCK);
/* attempt to connect */
result = connect(*sd, res->ai_addr, res->ai_addrlen);
/* immediately successful connect */
if(result == 0) {
result = OK;
/*printf("IMMEDIATE SUCCESS\n");*/
}
/* connection error */
else if(result < 0 && errno != EINPROGRESS) {
result = ERROR;
}
/* connection in progress - wait for it... */
else {
do {
/* set connection timeout */
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&wfds);
FD_SET(*sd, &wfds);
rfds = wfds;
/* wait for readiness */
result = select((*sd) + 1, &rfds, &wfds, NULL, &tv);
/*printf("SELECT RESULT: %d\n",result);*/
/* timeout */
if(result == 0) {
/*printf("TIMEOUT\n");*/
result = ERROR;
break;
}
/* an error occurred */
if(result < 0 && errno != EINTR) {
result = ERROR;
break;
}
/* got something - check it */
else if(result > 0) {
/* get socket options to check for errors */
optlen = sizeof(int);
if(getsockopt(*sd, SOL_SOCKET, SO_ERROR, (void *)(&optval), &optlen) < 0) {
result = ERROR;
break;
}
/* an error occurred in the connection */
if(optval != 0) {
result = ERROR;
break;
}
/* the connection was good! */
/*
printf("CONNECT SELECT: ERRNO=%s\n",strerror(errno));
printf("CONNECT SELECT: OPTVAL=%s\n",strerror(optval));
*/
result = OK;
break;
}
/* some other error occurred */
else {
result = ERROR;
break;
}
}
while(1);
}
freeaddrinfo(res);
return result;
}
/* based on Beej's sendall - thanks Beej! */
int my_sendall(int s, char *buf, int *len, int timeout) {
int total_sent = 0;
int bytes_left = 0;
int n;
fd_set wfds;
struct timeval tv;
int result = OK;
time_t start_time;
time_t current_time;
time(&start_time);
bytes_left = *len;
while(total_sent < *len) {
/* set send timeout */
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&wfds);
FD_SET(s, &wfds);
/* wait for readiness */
result = select(s + 1, NULL, &wfds, NULL, &tv);
/* timeout */
if(result == 0) {
/*printf("RECV SELECT TIMEOUT\n");*/
result = ERROR;
break;
}
/* error */
else if(result < 0) {
/*printf("RECV SELECT ERROR: %s\n",strerror(errno));*/
result = ERROR;
break;
}
/* we're ready to write some data */
result = OK;
/* send the data */
n = send(s, buf + total_sent, bytes_left, 0);
if(n == -1) {
/*printf("SEND ERROR: (%d) %s\n",s,strerror(errno));*/
break;
}
total_sent += n;
bytes_left -= n;
/* make sure we haven't overrun the timeout */
time(&current_time);
if(current_time - start_time > timeout) {
result = ERROR;
break;
}
}
*len = total_sent;
return result;
}
/* receives all data in non-blocking mode with a timeout - modelled after sendall() */
int my_recvall(int s, char *buf, int *len, int timeout) {
int total_received = 0;
int bytes_left = *len;
int n = 0;
time_t start_time;
time_t current_time;
fd_set rfds;
struct timeval tv;
int result = OK;
/* clear the receive buffer */
bzero(buf, *len);
time(&start_time);
/* receive all data */
while(total_received < *len) {
/* set receive timeout */
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(s, &rfds);
/* wait for readiness */
result = select(s + 1, &rfds, NULL, NULL, &tv);
/* timeout */
if(result == 0) {
/*printf("RECV SELECT TIMEOUT\n");*/
result = ERROR;
break;
}
/* error */
else if(result < 0) {
/*printf("RECV SELECT ERROR: %s\n",strerror(errno));*/
result = ERROR;
break;
}
/* we're ready to read some data */
result = OK;
/* receive some data */
n = recv(s, buf + total_received, bytes_left, 0);
/* server disconnected */
if(n == 0) {
/*printf("SERVER DISCONNECT\n");*/
break;
}
/* apply bytes we received */
total_received += n;
bytes_left -= n;
/* make sure we haven't overrun the timeout */
time(&current_time);
if(current_time - start_time > timeout) {
result = ERROR;
break;
}
}
/* return number of bytes actually received here */
*len = total_received;
return result;
}

2170
base/notifications.c Normal file

File diff suppressed because it is too large Load Diff

116
base/perfdata.c Normal file
View File

@ -0,0 +1,116 @@
/*****************************************************************************
*
* PERFDATA.C - Performance data routines for Nagios
*
* Copyright (c) 2000-2004 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 11-29-2004
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
/*********** COMMON HEADER FILES ***********/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/perfdata.h"
#include "../include/macros.h"
/***** IMPLEMENTATION-SPECIFIC HEADER FILES *****/
#ifdef USE_XPDDEFAULT
#include "../xdata/xpddefault.h"
#endif
extern int process_performance_data;
/******************************************************************/
/************** INITIALIZATION & CLEANUP FUNCTIONS ****************/
/******************************************************************/
/* initializes performance data */
int initialize_performance_data(char *config_file) {
#ifdef USE_XPDDEFAULT
xpddefault_initialize_performance_data(config_file);
#endif
return OK;
}
/* cleans up performance data */
int cleanup_performance_data(char *config_file) {
#ifdef USE_XPDDEFAULT
xpddefault_cleanup_performance_data(config_file);
#endif
return OK;
}
/******************************************************************/
/****************** PERFORMANCE DATA FUNCTIONS ********************/
/******************************************************************/
/* updates service performance data */
int update_service_performance_data(service *svc) {
/* should we be processing performance data for anything? */
if(process_performance_data == FALSE)
return OK;
/* should we process performance data for this service? */
if(svc->process_performance_data == FALSE)
return OK;
/* process the performance data! */
#ifdef USE_XPDDEFAULT
xpddefault_update_service_performance_data(svc);
#endif
return OK;
}
/* updates host performance data */
int update_host_performance_data(host *hst) {
/* should we be processing performance data for anything? */
if(process_performance_data == FALSE)
return OK;
/* should we process performance data for this host? */
if(hst->process_performance_data == FALSE)
return OK;
/* process the performance data! */
#ifdef USE_XPDDEFAULT
xpddefault_update_host_performance_data(hst);
#endif
return OK;
}

700
base/sehandlers.c Normal file
View File

@ -0,0 +1,700 @@
/*****************************************************************************
*
* SEHANDLERS.C - Service and host event and state handlers for Nagios
*
* Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 08-05-2010
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/comments.h"
#include "../include/common.h"
#include "../include/statusdata.h"
#include "../include/downtime.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/perfdata.h"
#include "../include/broker.h"
#ifdef USE_EVENT_BROKER
#include "../include/neberrors.h"
#endif
extern int enable_event_handlers;
extern int obsess_over_services;
extern int obsess_over_hosts;
extern int log_event_handlers;
extern unsigned long next_event_id;
extern unsigned long next_problem_id;
extern int event_handler_timeout;
extern int ocsp_timeout;
extern int ochp_timeout;
extern char *global_host_event_handler;
extern char *global_service_event_handler;
extern command *global_host_event_handler_ptr;
extern command *global_service_event_handler_ptr;
extern char *ocsp_command;
extern char *ochp_command;
extern command *ocsp_command_ptr;
extern command *ochp_command_ptr;
extern time_t program_start;
/******************************************************************/
/************* OBSESSIVE COMPULSIVE HANDLER FUNCTIONS *************/
/******************************************************************/
/* handles service check results in an obsessive compulsive manner... */
int obsessive_compulsive_service_check_processor(service *svc) {
char *raw_command = NULL;
char *processed_command = NULL;
host *temp_host = NULL;
int early_timeout = FALSE;
double exectime = 0.0;
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
nagios_macros mac;
log_debug_info(DEBUGL_FUNCTIONS, 0, "obsessive_compulsive_service_check_processor()\n");
if(svc == NULL)
return ERROR;
/* bail out if we shouldn't be obsessing */
if(obsess_over_services == FALSE)
return OK;
if(svc->obsess_over_service == FALSE)
return OK;
/* if there is no valid command, exit */
if(ocsp_command == NULL)
return ERROR;
/* find the associated host */
if((temp_host = (host *)svc->host_ptr) == NULL)
return ERROR;
/* update service macros */
memset(&mac, 0, sizeof(mac));
grab_host_macros_r(&mac, temp_host);
grab_service_macros_r(&mac, svc);
/* get the raw command line */
get_raw_command_line_r(&mac, ocsp_command_ptr, ocsp_command, &raw_command, macro_options);
if(raw_command == NULL) {
clear_volatile_macros_r(&mac);
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 2, "Raw obsessive compulsive service processor command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(&mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL) {
clear_volatile_macros_r(&mac);
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 2, "Processed obsessive compulsive service processor command line: %s\n", processed_command);
/* run the command */
my_system_r(&mac, processed_command, ocsp_timeout, &early_timeout, &exectime, NULL, 0);
clear_volatile_macros_r(&mac);
/* check to see if the command timed out */
if(early_timeout == TRUE)
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: OCSP command '%s' for service '%s' on host '%s' timed out after %d seconds\n", processed_command, svc->description, svc->host_name, ocsp_timeout);
/* free memory */
my_free(processed_command);
return OK;
}
/* handles host check results in an obsessive compulsive manner... */
int obsessive_compulsive_host_check_processor(host *hst) {
char *raw_command = NULL;
char *processed_command = NULL;
int early_timeout = FALSE;
double exectime = 0.0;
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
nagios_macros mac;
log_debug_info(DEBUGL_FUNCTIONS, 0, "obsessive_compulsive_host_check_processor()\n");
if(hst == NULL)
return ERROR;
/* bail out if we shouldn't be obsessing */
if(obsess_over_hosts == FALSE)
return OK;
if(hst->obsess_over_host == FALSE)
return OK;
/* if there is no valid command, exit */
if(ochp_command == NULL)
return ERROR;
/* update macros */
memset(&mac, 0, sizeof(mac));
grab_host_macros_r(&mac, hst);
/* get the raw command line */
get_raw_command_line_r(&mac, ochp_command_ptr, ochp_command, &raw_command, macro_options);
if(raw_command == NULL) {
clear_volatile_macros_r(&mac);
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 2, "Raw obsessive compulsive host processor command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(&mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL) {
clear_volatile_macros_r(&mac);
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 2, "Processed obsessive compulsive host processor command line: %s\n", processed_command);
/* run the command */
my_system_r(&mac, processed_command, ochp_timeout, &early_timeout, &exectime, NULL, 0);
clear_volatile_macros_r(&mac);
/* check to see if the command timed out */
if(early_timeout == TRUE)
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: OCHP command '%s' for host '%s' timed out after %d seconds\n", processed_command, hst->name, ochp_timeout);
/* free memory */
my_free(processed_command);
return OK;
}
/******************************************************************/
/**************** SERVICE EVENT HANDLER FUNCTIONS *****************/
/******************************************************************/
/* handles changes in the state of a service */
int handle_service_event(service *svc) {
host *temp_host = NULL;
nagios_macros mac;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_service_event()\n");
if(svc == NULL)
return ERROR;
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_statechange_data(NEBTYPE_STATECHANGE_END, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_STATECHANGE, (void *)svc, svc->current_state, svc->state_type, svc->current_attempt, svc->max_attempts, NULL);
#endif
/* bail out if we shouldn't be running event handlers */
if(enable_event_handlers == FALSE)
return OK;
if(svc->event_handler_enabled == FALSE)
return OK;
/* find the host */
if((temp_host = (host *)svc->host_ptr) == NULL)
return ERROR;
/* update service macros */
memset(&mac, 0, sizeof(mac));
grab_host_macros_r(&mac, temp_host);
grab_service_macros_r(&mac, svc);
/* run the global service event handler */
run_global_service_event_handler(&mac, svc);
/* run the event handler command if there is one */
if(svc->event_handler != NULL)
run_service_event_handler(&mac, svc);
clear_volatile_macros_r(&mac);
/* check for external commands - the event handler may have given us some directives... */
check_for_external_commands();
return OK;
}
/* runs the global service event handler */
int run_global_service_event_handler(nagios_macros *mac, service *svc) {
char *raw_command = NULL;
char *processed_command = NULL;
char *raw_logentry = NULL;
char *processed_logentry = NULL;
char *command_output = NULL;
int early_timeout = FALSE;
double exectime = 0.0;
int result = 0;
#ifdef USE_EVENT_BROKER
struct timeval start_time;
struct timeval end_time;
int neb_result = OK;
#endif
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_global_service_event_handler()\n");
if(svc == NULL)
return ERROR;
/* bail out if we shouldn't be running event handlers */
if(enable_event_handlers == FALSE)
return OK;
/* a global service event handler command has not been defined */
if(global_service_event_handler == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 1, "Running global event handler for service '%s' on host '%s'...\n", svc->description, svc->host_name);
#ifdef USE_EVENT_BROKER
/* get start time */
gettimeofday(&start_time, NULL);
#endif
/* get the raw command line */
get_raw_command_line_r(mac, global_service_event_handler_ptr, global_service_event_handler, &raw_command, macro_options);
if(raw_command == NULL) {
return ERROR;
}
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Raw global service event handler command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Processed global service event handler command line: %s\n", processed_command);
if(log_event_handlers == TRUE) {
asprintf(&raw_logentry, "GLOBAL SERVICE EVENT HANDLER: %s;%s;$SERVICESTATE$;$SERVICESTATETYPE$;$SERVICEATTEMPT$;%s\n", svc->host_name, svc->description, global_service_event_handler);
process_macros_r(mac, raw_logentry, &processed_logentry, macro_options);
logit(NSLOG_EVENT_HANDLER, FALSE, "%s", processed_logentry);
}
#ifdef USE_EVENT_BROKER
/* send event data to broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_event_handler(NEBTYPE_EVENTHANDLER_START, NEBFLAG_NONE, NEBATTR_NONE, GLOBAL_SERVICE_EVENTHANDLER, (void *)svc, svc->current_state, svc->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, global_service_event_handler, processed_command, NULL, NULL);
/* neb module wants to override (or cancel) the event handler - perhaps it will run the eventhandler itself */
if(neb_result == NEBERROR_CALLBACKOVERRIDE) {
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
#endif
/* run the command */
result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0);
/* check to see if the event handler timed out */
if(early_timeout == TRUE)
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Global service event handler command '%s' timed out after %d seconds\n", processed_command, event_handler_timeout);
#ifdef USE_EVENT_BROKER
/* get end time */
gettimeofday(&end_time, NULL);
#endif
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_event_handler(NEBTYPE_EVENTHANDLER_END, NEBFLAG_NONE, NEBATTR_NONE, GLOBAL_SERVICE_EVENTHANDLER, (void *)svc, svc->current_state, svc->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, global_service_event_handler, processed_command, command_output, NULL);
#endif
/* free memory */
my_free(command_output);
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
/* runs a service event handler command */
int run_service_event_handler(nagios_macros *mac, service *svc) {
char *raw_command = NULL;
char *processed_command = NULL;
char *raw_logentry = NULL;
char *processed_logentry = NULL;
char *command_output = NULL;
int early_timeout = FALSE;
double exectime = 0.0;
int result = 0;
#ifdef USE_EVENT_BROKER
struct timeval start_time;
struct timeval end_time;
int neb_result = OK;
#endif
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_service_event_handler()\n");
if(svc == NULL)
return ERROR;
/* bail if there's no command */
if(svc->event_handler == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 1, "Running event handler for service '%s' on host '%s'...\n", svc->description, svc->host_name);
#ifdef USE_EVENT_BROKER
/* get start time */
gettimeofday(&start_time, NULL);
#endif
/* get the raw command line */
get_raw_command_line_r(mac, svc->event_handler_ptr, svc->event_handler, &raw_command, macro_options);
if(raw_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Raw service event handler command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Processed service event handler command line: %s\n", processed_command);
if(log_event_handlers == TRUE) {
asprintf(&raw_logentry, "SERVICE EVENT HANDLER: %s;%s;$SERVICESTATE$;$SERVICESTATETYPE$;$SERVICEATTEMPT$;%s\n", svc->host_name, svc->description, svc->event_handler);
process_macros_r(mac, raw_logentry, &processed_logentry, macro_options);
logit(NSLOG_EVENT_HANDLER, FALSE, "%s", processed_logentry);
}
#ifdef USE_EVENT_BROKER
/* send event data to broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_event_handler(NEBTYPE_EVENTHANDLER_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_EVENTHANDLER, (void *)svc, svc->current_state, svc->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, svc->event_handler, processed_command, NULL, NULL);
/* neb module wants to override (or cancel) the event handler - perhaps it will run the eventhandler itself */
if(neb_result == NEBERROR_CALLBACKOVERRIDE) {
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
#endif
/* run the command */
result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0);
/* check to see if the event handler timed out */
if(early_timeout == TRUE)
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Service event handler command '%s' timed out after %d seconds\n", processed_command, event_handler_timeout);
#ifdef USE_EVENT_BROKER
/* get end time */
gettimeofday(&end_time, NULL);
#endif
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_event_handler(NEBTYPE_EVENTHANDLER_END, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_EVENTHANDLER, (void *)svc, svc->current_state, svc->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, svc->event_handler, processed_command, command_output, NULL);
#endif
/* free memory */
my_free(command_output);
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
/******************************************************************/
/****************** HOST EVENT HANDLER FUNCTIONS ******************/
/******************************************************************/
/* handles a change in the status of a host */
int handle_host_event(host *hst) {
nagios_macros mac;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_host_event()\n");
if(hst == NULL)
return ERROR;
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_statechange_data(NEBTYPE_STATECHANGE_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_STATECHANGE, (void *)hst, hst->current_state, hst->state_type, hst->current_attempt, hst->max_attempts, NULL);
#endif
/* bail out if we shouldn't be running event handlers */
if(enable_event_handlers == FALSE)
return OK;
if(hst->event_handler_enabled == FALSE)
return OK;
/* update host macros */
memset(&mac, 0, sizeof(mac));
grab_host_macros_r(&mac, hst);
/* run the global host event handler */
run_global_host_event_handler(&mac, hst);
/* run the event handler command if there is one */
if(hst->event_handler != NULL)
run_host_event_handler(&mac, hst);
/* check for external commands - the event handler may have given us some directives... */
check_for_external_commands();
return OK;
}
/* runs the global host event handler */
int run_global_host_event_handler(nagios_macros *mac, host *hst) {
char *raw_command = NULL;
char *processed_command = NULL;
char *raw_logentry = NULL;
char *processed_logentry = NULL;
char *command_output = NULL;
int early_timeout = FALSE;
double exectime = 0.0;
int result = 0;
#ifdef USE_EVENT_BROKER
struct timeval start_time;
struct timeval end_time;
int neb_result = OK;
#endif
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_global_host_event_handler()\n");
if(hst == NULL)
return ERROR;
/* bail out if we shouldn't be running event handlers */
if(enable_event_handlers == FALSE)
return OK;
/* no global host event handler command is defined */
if(global_host_event_handler == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 1, "Running global event handler for host '%s'..\n", hst->name);
#ifdef USE_EVENT_BROKER
/* get start time */
gettimeofday(&start_time, NULL);
#endif
/* get the raw command line */
get_raw_command_line_r(mac, global_host_event_handler_ptr, global_host_event_handler, &raw_command, macro_options);
if(raw_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Raw global host event handler command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Processed global host event handler command line: %s\n", processed_command);
if(log_event_handlers == TRUE) {
asprintf(&raw_logentry, "GLOBAL HOST EVENT HANDLER: %s;$HOSTSTATE$;$HOSTSTATETYPE$;$HOSTATTEMPT$;%s\n", hst->name, global_host_event_handler);
process_macros_r(mac, raw_logentry, &processed_logentry, macro_options);
logit(NSLOG_EVENT_HANDLER, FALSE, "%s", processed_logentry);
}
#ifdef USE_EVENT_BROKER
/* send event data to broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_event_handler(NEBTYPE_EVENTHANDLER_START, NEBFLAG_NONE, NEBATTR_NONE, GLOBAL_HOST_EVENTHANDLER, (void *)hst, hst->current_state, hst->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, global_host_event_handler, processed_command, NULL, NULL);
/* neb module wants to override (or cancel) the event handler - perhaps it will run the eventhandler itself */
if(neb_result == NEBERROR_CALLBACKOVERRIDE) {
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
#endif
/* run the command */
result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0);
/* check for a timeout in the execution of the event handler command */
if(early_timeout == TRUE)
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Global host event handler command '%s' timed out after %d seconds\n", processed_command, event_handler_timeout);
#ifdef USE_EVENT_BROKER
/* get end time */
gettimeofday(&end_time, NULL);
#endif
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_event_handler(NEBTYPE_EVENTHANDLER_END, NEBFLAG_NONE, NEBATTR_NONE, GLOBAL_HOST_EVENTHANDLER, (void *)hst, hst->current_state, hst->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, global_host_event_handler, processed_command, command_output, NULL);
#endif
/* free memory */
my_free(command_output);
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
/* runs a host event handler command */
int run_host_event_handler(nagios_macros *mac, host *hst) {
char *raw_command = NULL;
char *processed_command = NULL;
char *raw_logentry = NULL;
char *processed_logentry = NULL;
char *command_output = NULL;
int early_timeout = FALSE;
double exectime = 0.0;
int result = 0;
#ifdef USE_EVENT_BROKER
struct timeval start_time;
struct timeval end_time;
int neb_result = OK;
#endif
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_host_event_handler()\n");
if(hst == NULL)
return ERROR;
/* bail if there's no command */
if(hst->event_handler == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 1, "Running event handler for host '%s'..\n", hst->name);
#ifdef USE_EVENT_BROKER
/* get start time */
gettimeofday(&start_time, NULL);
#endif
/* get the raw command line */
get_raw_command_line_r(mac, hst->event_handler_ptr, hst->event_handler, &raw_command, macro_options);
if(raw_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Raw host event handler command line: %s\n", raw_command);
/* process any macros in the raw command line */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
return ERROR;
log_debug_info(DEBUGL_EVENTHANDLERS, 2, "Processed host event handler command line: %s\n", processed_command);
if(log_event_handlers == TRUE) {
asprintf(&raw_logentry, "HOST EVENT HANDLER: %s;$HOSTSTATE$;$HOSTSTATETYPE$;$HOSTATTEMPT$;%s\n", hst->name, hst->event_handler);
process_macros_r(mac, raw_logentry, &processed_logentry, macro_options);
logit(NSLOG_EVENT_HANDLER, FALSE, "%s", processed_logentry);
}
#ifdef USE_EVENT_BROKER
/* send event data to broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_event_handler(NEBTYPE_EVENTHANDLER_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_EVENTHANDLER, (void *)hst, hst->current_state, hst->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, hst->event_handler, processed_command, NULL, NULL);
/* neb module wants to override (or cancel) the event handler - perhaps it will run the eventhandler itself */
if(neb_result == NEBERROR_CALLBACKOVERRIDE) {
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}
#endif
/* run the command */
result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0);
/* check to see if the event handler timed out */
if(early_timeout == TRUE)
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Host event handler command '%s' timed out after %d seconds\n", processed_command, event_handler_timeout);
#ifdef USE_EVENT_BROKER
/* get end time */
gettimeofday(&end_time, NULL);
#endif
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_event_handler(NEBTYPE_EVENTHANDLER_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_EVENTHANDLER, (void *)hst, hst->current_state, hst->state_type, start_time, end_time, exectime, event_handler_timeout, early_timeout, result, hst->event_handler, processed_command, command_output, NULL);
#endif
/* free memory */
my_free(command_output);
my_free(processed_command);
my_free(raw_logentry);
my_free(processed_logentry);
return OK;
}

145
base/sretention.c Normal file
View File

@ -0,0 +1,145 @@
/*****************************************************************************
*
* SRETENTION.C - State retention routines for Nagios
*
* Copyright (c) 1999-2006 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 10-18-2006
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
/*********** COMMON HEADER FILES ***********/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/statusdata.h"
#include "../include/nagios.h"
#include "../include/sretention.h"
#include "../include/broker.h"
extern int retain_state_information;
/**** IMPLEMENTATION SPECIFIC HEADER FILES ****/
#ifdef USE_XRDDEFAULT
#include "../xdata/xrddefault.h" /* default routines */
#endif
/******************************************************************/
/************* TOP-LEVEL STATE INFORMATION FUNCTIONS **************/
/******************************************************************/
/* initializes retention data at program start */
int initialize_retention_data(char *config_file) {
int result = OK;
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XRDDEFAULT
result = xrddefault_initialize_retention_data(config_file);
#endif
return result;
}
/* cleans up retention data before program termination */
int cleanup_retention_data(char *config_file) {
int result = OK;
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XRDDEFAULT
result = xrddefault_cleanup_retention_data(config_file);
#endif
return result;
}
/* save all host and service state information */
int save_state_information(int autosave) {
int result = OK;
if(retain_state_information == FALSE)
return OK;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_retention_data(NEBTYPE_RETENTIONDATA_STARTSAVE, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
/********* IMPLEMENTATION-SPECIFIC OUTPUT FUNCTION ********/
#ifdef USE_XRDDEFAULT
result = xrddefault_save_state_information();
#endif
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_retention_data(NEBTYPE_RETENTIONDATA_ENDSAVE, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
if(result == ERROR)
return ERROR;
if(autosave == TRUE)
logit(NSLOG_PROCESS_INFO, FALSE, "Auto-save of retention data completed successfully.\n");
return OK;
}
/* reads in initial host and state information */
int read_initial_state_information(void) {
int result = OK;
if(retain_state_information == FALSE)
return OK;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_retention_data(NEBTYPE_RETENTIONDATA_STARTLOAD, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
/********* IMPLEMENTATION-SPECIFIC INPUT FUNCTION ********/
#ifdef USE_XRDDEFAULT
result = xrddefault_read_state_information();
#endif
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_retention_data(NEBTYPE_RETENTIONDATA_ENDLOAD, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
if(result == ERROR)
return ERROR;
return OK;
}

4526
base/utils.c Normal file

File diff suppressed because it is too large Load Diff

3
cgi/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
*.cgi
Makefile

214
cgi/Makefile.in Normal file
View File

@ -0,0 +1,214 @@
###############################
# Makefile for Nagios CGIs
#
# Last Modified: 10-30-2008
###############################
# Source code directories
SRC_COMMON=../common
SRC_INCLUDE=../include
SRC_XDATA=../xdata
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
CGIDIR=@sbindir@
HTMLDIR=@datarootdir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
STRIP=@STRIP@
CGIEXTRAS=@CGIEXTRAS@
CP=@CP@
CC=@CC@
CFLAGS=-Wall @CFLAGS@ @DEFS@ -DNSCGI
# Compiler flags for optimization (overrides default)
#CFLAGS=-O3 -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -DHAVE_CONFIG_H -DNSCGI
# Compiler flags for optimization (complements default)
#CFLAGS_WARN=-Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs
#CFLAGS_DEBUG=-ggdb3 -g3
#CFLAGS+=$(CFLAGS_WARN) $(CFLAGS_DEBUG)
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
CGIS=avail.cgi cmd.cgi config.cgi extinfo.cgi history.cgi notifications.cgi outages.cgi showlog.cgi status.cgi statuswml.cgi summary.cgi tac.cgi $(CGIEXTRAS)
# External data I/O code and headers
XSDC=@XSDC@
XSDH=@XSDH@
XCDC=@XCDC@
XCDH=@XCDH@
XODC=@XODC@
XODH=@XODH@
XDDC=@XDDC@
XDDH=@XDDH@
# Generated automatically from configure script
SNPRINTF_O=@SNPRINTF_O@
# Object functions
ODATALIBS=objects-cgi.o xobjects-cgi.o
ODATAHDRS=
ODATADEPS=$(ODATALIBS)
# Host, service, and program status functions
SDATALIBS=statusdata-cgi.o xstatusdata-cgi.o comments-cgi.o downtime-cgi.o
SDATAHDRS=
SDATADEPS=$(SDATALIBS)
# Host and service comment functions
CDATALIBS=
CDATAHDRS=
CDATADEPS=$(CDATALIBS)
# Host and service downtime functions
DDATALIBS=
DDATAHDRS=
DDATADEPS=$(DDATALIBS)
# Common CGI functions (includes object and status functions)
CGILIBS=$(SRC_COMMON)/shared.o getcgi.o cgiutils.o cgiauth.o macros-cgi.o skiplist.o $(SNPRINTF_O) $(ODATALIBS) $(SDATALIBS)
CGIHDRS=$(SRC_INCLUDE)/config.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/locations.h
CGIDEPS=$(CGILIBS) $(ODATADEPS) $(SDATADEPS)
MATHLIBS=-lm
GDLIBS=@GDLIBS@
all cgis: $(CGIS)
$(CGILIBS): $(CGIHDRS)
######## REQUIRED LIBRARIES ##########
skiplist.o: $(SRC_COMMON)/skiplist.c $(SRC_INCLUDE)/skiplist.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/skiplist.c
macros-cgi.o: $(SRC_COMMON)/macros.c $(SRC_INCLUDE)/macros.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/macros.c
objects-cgi.o: $(SRC_COMMON)/objects.c $(SRC_INCLUDE)/objects.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/objects.c
xobjects-cgi.o: $(SRC_XDATA)/$(XODC) $(SRC_XDATA)/$(XODH)
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XODC)
statusdata-cgi.o: $(SRC_COMMON)/statusdata.c $(SRC_INCLUDE)/statusdata.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/statusdata.c
xstatusdata-cgi.o: $(SRC_XDATA)/$(XSDC) $(SRC_XDATA)/$(XSDH)
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XSDC)
comments-cgi.o: $(SRC_COMMON)/comments.c $(SRC_INCLUDE)/comments.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/comments.c
xcomments-cgi.o: $(SRC_XDATA)/$(XCDC) $(SRC_XDATA)/$(XCDH)
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XCDC)
downtime-cgi.o: $(SRC_COMMON)/downtime.c $(SRC_INCLUDE)/downtime.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/downtime.c
xdowntime-cgi.o: $(SRC_XDATA)/$(XDDC) $(SRC_XDATA)/$(XDDH)
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XDDC)
$(SRC_COMMON)/shared.o: $(SRC_COMMON)/shared.c
$(CC) $(CFLAGS) -c -o $@ $<
########## CGIS ##########
avail.cgi: avail.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ avail.c $(CGILIBS) $(LIBS)
checksanity.cgi: checksanity.c $(CGIDEPS) $(CDATADEPS) $(DDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ checksanity.c $(CGILIBS) $(CDATALIBS) $(DDATALIBS) $(LIBS)
cmd.cgi: cmd.c $(CGIDEPS) $(CDATADEPS) $(DDATADEPS) extcmd_list.o
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ cmd.c extcmd_list.o $(CGILIBS) $(CDATALIBS) $(DDATALIBS) $(LIBS)
config.cgi: config.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ config.c $(CGILIBS) $(LIBS)
extinfo.cgi: extinfo.c $(CGIDEPS) $(CDATADEPS) $(DDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ extinfo.c $(CGILIBS) $(CDATALIBS) $(DDATALIBS) $(LIBS)
history.cgi: history.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ history.c $(CGILIBS) $(LIBS)
ministatus.cgi: ministatus.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ ministatus.c $(CGILIBS) $(LIBS)
notifications.cgi: notifications.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ notifications.c $(CGILIBS) $(LIBS)
outages.cgi: outages.c $(CGIDEPS) $(CDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ outages.c $(CGILIBS) $(CDATALIBS) $(LIBS)
showlog.cgi: showlog.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ showlog.c $(CGILIBS) $(LIBS)
status.cgi: status.c $(CGIDEPS) $(CDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ status.c $(CGILIBS) $(CDATALIBS) $(LIBS)
statuswml.cgi: statuswml.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ statuswml.c $(CGILIBS) $(LIBS)
statusmap.cgi: statusmap.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ statusmap.c $(CGILIBS) $(GDLIBS) $(LIBS)
statuswrl.cgi: statuswrl.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ statuswrl.c $(CGILIBS) $(MATHLIBS) $(LIBS)
summary.cgi: summary.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ summary.c $(CGILIBS) $(LIBS)
tac.cgi: tac.c $(CGIDEPS) $(CDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ tac.c $(CGILIBS) $(CDATALIBS) $(LIBS)
tac-xml.cgi: tac-xml.c $(CGIDEPS) $(CDATADEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ tac-xml.c $(CGILIBS) $(CDATALIBS) $(LIBS)
trends.cgi: trends.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ trends.c $(CGILIBS) $(GDLIBS) $(LIBS)
histogram.cgi: histogram.c $(CGIDEPS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ histogram.c $(CGILIBS) $(GDLIBS) $(LIBS)
clean:
rm -f $(CGIS)
rm -f *.o core gmon.out
rm -f *~ *.*~
distclean: clean
rm -f Makefile cgiutils.h
devclean: distclean
install:
$(MAKE) install-basic
$(MAKE) strip-post-install
install-unstripped:
$(MAKE) install-basic
install-basic:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CGIDIR)
for file in *.cgi; do \
$(INSTALL) -m 775 $(INSTALL_OPTS) $$file $(DESTDIR)$(CGIDIR); \
done
strip-post-install:
for file in *.cgi; do \
$(STRIP) $(DESTDIR)$(CGIDIR)/$$file; \
done

4871
cgi/avail.c Normal file

File diff suppressed because it is too large Load Diff

610
cgi/cgiauth.c Normal file
View File

@ -0,0 +1,610 @@
/*****************************************************************************
*
* CGIAUTH.C - Authorization utilities for Nagios CGIs
*
* Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 11-30-2008
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
extern char main_config_file[MAX_FILENAME_LENGTH];
extern hostgroup *hostgroup_list;
extern servicegroup *servicegroup_list;
extern int use_authentication;
extern int use_ssl_authentication;
/* get current authentication information */
int get_authentication_information(authdata *authinfo) {
mmapfile *thefile;
char *input = NULL;
char *temp_ptr = NULL;
contact *temp_contact = NULL;
contactgroup *temp_contactgroup = NULL;
if(authinfo == NULL)
return ERROR;
/* initial values... */
authinfo->authorized_for_all_hosts = FALSE;
authinfo->authorized_for_all_host_commands = FALSE;
authinfo->authorized_for_all_services = FALSE;
authinfo->authorized_for_all_service_commands = FALSE;
authinfo->authorized_for_system_information = FALSE;
authinfo->authorized_for_system_commands = FALSE;
authinfo->authorized_for_configuration_information = FALSE;
authinfo->authorized_for_read_only = FALSE;
/* grab username from the environment... */
if(use_ssl_authentication) {
/* patch by Pawl Zuzelski - 7/22/08 */
temp_ptr = getenv("SSL_CLIENT_S_DN_CN");
}
else {
temp_ptr = getenv("REMOTE_USER");
}
if(temp_ptr == NULL) {
authinfo->username = "";
authinfo->authenticated = FALSE;
}
else {
authinfo->username = (char *)malloc(strlen(temp_ptr) + 1);
if(authinfo->username == NULL)
authinfo->username = "";
else
strcpy(authinfo->username, temp_ptr);
if(!strcmp(authinfo->username, ""))
authinfo->authenticated = FALSE;
else
authinfo->authenticated = TRUE;
}
/* read in authorization override vars from config file... */
if((thefile = mmap_fopen(get_cgi_config_location())) != NULL) {
while(1) {
/* free memory */
free(input);
/* read the next line */
if((input = mmap_fgets_multiline(thefile)) == NULL)
break;
strip(input);
/* we don't have a username yet, so fake the authentication if we find a default username defined */
if(!strcmp(authinfo->username, "") && strstr(input, "default_user_name=") == input) {
temp_ptr = strtok(input, "=");
temp_ptr = strtok(NULL, ",");
authinfo->username = (char *)malloc(strlen(temp_ptr) + 1);
if(authinfo->username == NULL)
authinfo->username = "";
else
strcpy(authinfo->username, temp_ptr);
if(!strcmp(authinfo->username, ""))
authinfo->authenticated = FALSE;
else
authinfo->authenticated = TRUE;
}
else if(strstr(input, "authorized_for_all_hosts=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
if(!strcmp(temp_ptr, authinfo->username) || !strcmp(temp_ptr, "*"))
authinfo->authorized_for_all_hosts = TRUE;
}
}
else if(strstr(input, "authorized_for_all_services=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
if(!strcmp(temp_ptr, authinfo->username) || !strcmp(temp_ptr, "*"))
authinfo->authorized_for_all_services = TRUE;
}
}
else if(strstr(input, "authorized_for_system_information=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
if(!strcmp(temp_ptr, authinfo->username) || !strcmp(temp_ptr, "*"))
authinfo->authorized_for_system_information = TRUE;
}
}
else if(strstr(input, "authorized_for_configuration_information=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
if(!strcmp(temp_ptr, authinfo->username) || !strcmp(temp_ptr, "*"))
authinfo->authorized_for_configuration_information = TRUE;
}
}
else if(strstr(input, "authorized_for_all_host_commands=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
if(!strcmp(temp_ptr, authinfo->username) || !strcmp(temp_ptr, "*"))
authinfo->authorized_for_all_host_commands = TRUE;
}
}
else if(strstr(input, "authorized_for_all_service_commands=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
if(!strcmp(temp_ptr, authinfo->username) || !strcmp(temp_ptr, "*"))
authinfo->authorized_for_all_service_commands = TRUE;
}
}
else if(strstr(input, "authorized_for_system_commands=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
if(!strcmp(temp_ptr, authinfo->username) || !strcmp(temp_ptr, "*"))
authinfo->authorized_for_system_commands = TRUE;
}
}
else if(strstr(input, "authorized_for_read_only=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
if(!strcmp(temp_ptr, authinfo->username) || !strcmp(temp_ptr, "*"))
authinfo->authorized_for_read_only = TRUE;
}
}
else if((temp_contact = find_contact(authinfo->username)) != NULL) {
if(strstr(input, "authorized_contactgroup_for_all_hosts=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
temp_contactgroup = find_contactgroup(temp_ptr);
if(is_contact_member_of_contactgroup(temp_contactgroup, temp_contact))
authinfo->authorized_for_all_hosts = TRUE;
}
}
else if(strstr(input, "authorized_contactgroup_for_all_services=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
temp_contactgroup = find_contactgroup(temp_ptr);
if(is_contact_member_of_contactgroup(temp_contactgroup, temp_contact))
authinfo->authorized_for_all_services = TRUE;
}
}
else if(strstr(input, "authorized_contactgroup_for_system_information=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
temp_contactgroup = find_contactgroup(temp_ptr);
if(is_contact_member_of_contactgroup(temp_contactgroup, temp_contact))
authinfo->authorized_for_system_information = TRUE;
}
}
else if(strstr(input, "authorized_contactgroup_for_configuration_information=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
temp_contactgroup = find_contactgroup(temp_ptr);
if(is_contact_member_of_contactgroup(temp_contactgroup, temp_contact))
authinfo->authorized_for_configuration_information = TRUE;
}
}
else if(strstr(input, "authorized_contactgroup_for_all_host_commands=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
temp_contactgroup = find_contactgroup(temp_ptr);
if(is_contact_member_of_contactgroup(temp_contactgroup, temp_contact))
authinfo->authorized_for_all_host_commands = TRUE;
}
}
else if(strstr(input, "authorized_contactgroup_for_all_service_commands=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
temp_contactgroup = find_contactgroup(temp_ptr);
if(is_contact_member_of_contactgroup(temp_contactgroup, temp_contact))
authinfo->authorized_for_all_service_commands = TRUE;
}
}
else if(strstr(input, "authorized_contactgroup_for_system_commands=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
temp_contactgroup = find_contactgroup(temp_ptr);
if(is_contact_member_of_contactgroup(temp_contactgroup, temp_contact))
authinfo->authorized_for_system_commands = TRUE;
}
}
else if(strstr(input, "authorized_contactgroup_for_read_only=") == input) {
temp_ptr = strtok(input, "=");
while((temp_ptr = strtok(NULL, ","))) {
temp_contactgroup = find_contactgroup(temp_ptr);
if(is_contact_member_of_contactgroup(temp_contactgroup, temp_contact))
authinfo->authorized_for_read_only = TRUE;
}
}
}
}
/* free memory and close the file */
free(input);
mmap_fclose(thefile);
}
if(authinfo->authenticated == TRUE)
return OK;
else
return ERROR;
}
/* check if user is authorized to view information about a particular host */
int is_authorized_for_host(host *hst, authdata *authinfo) {
contact *temp_contact;
if(hst == NULL)
return FALSE;
/* if we're not using authentication, fake it */
if(use_authentication == FALSE)
return TRUE;
/* if this user has not authenticated return error */
if(authinfo->authenticated == FALSE)
return FALSE;
/* if this user is authorized for all hosts, they are for this one... */
if(is_authorized_for_all_hosts(authinfo) == TRUE)
return TRUE;
/* find the contact */
temp_contact = find_contact(authinfo->username);
/* see if this user is a contact for the host */
if(is_contact_for_host(hst, temp_contact) == TRUE)
return TRUE;
/* see if this user is an escalated contact for the host */
if(is_escalated_contact_for_host(hst, temp_contact) == TRUE)
return TRUE;
return FALSE;
}
/* check if user is authorized to view information about all hosts in a particular hostgroup */
int is_authorized_for_hostgroup(hostgroup *hg, authdata *authinfo) {
hostsmember *temp_hostsmember;
host *temp_host;
if(hg == NULL)
return FALSE;
/* CHANGED in 2.0 - user must be authorized for ALL hosts in a hostgroup, not just one */
/* see if user is authorized for all hosts in the hostgroup */
/*
for(temp_hostsmember = hg->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
temp_host = find_host(temp_hostsmember->host_name);
if(is_authorized_for_host(temp_host, authinfo) == FALSE)
return FALSE;
}
*/
/* Reverted for 3.3.2 - must only be a member of one hostgroup */
for(temp_hostsmember = hg->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
temp_host = find_host(temp_hostsmember->host_name);
if(is_authorized_for_host(temp_host, authinfo) == TRUE)
return TRUE;
}
/*return TRUE;*/
return FALSE;
}
/* check if user is authorized to view information about all services in a particular servicegroup */
int is_authorized_for_servicegroup(servicegroup *sg, authdata *authinfo) {
servicesmember *temp_servicesmember;
service *temp_service;
if(sg == NULL)
return FALSE;
/* see if user is authorized for all services in the servicegroup */
/*
for(temp_servicesmember = sg->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
temp_service = find_service(temp_servicesmember->host_name, temp_servicesmember->service_description);
if(is_authorized_for_service(temp_service, authinfo) == FALSE)
return FALSE;
}
*/
/* Reverted for 3.3.2 - must only be a member of one hostgroup */
for(temp_servicesmember = sg->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
temp_service = find_service(temp_servicesmember->host_name, temp_servicesmember->service_description);
if(is_authorized_for_service(temp_service, authinfo) == TRUE)
return TRUE;
}
/*return TRUE*/;
return FALSE;
}
/* check if current user is restricted to read only */
int is_authorized_for_read_only(authdata *authinfo) {
/* if we're not using authentication, fake it */
if(use_authentication == FALSE)
return FALSE;
/* if this user has not authenticated return error */
if(authinfo->authenticated == FALSE)
return FALSE;
return authinfo->authorized_for_read_only;
}
/* check if user is authorized to view information about a particular service */
int is_authorized_for_service(service *svc, authdata *authinfo) {
host *temp_host;
contact *temp_contact;
if(svc == NULL)
return FALSE;
/* if we're not using authentication, fake it */
if(use_authentication == FALSE)
return TRUE;
/* if this user has not authenticated return error */
if(authinfo->authenticated == FALSE)
return FALSE;
/* if this user is authorized for all services, they are for this one... */
if(is_authorized_for_all_services(authinfo) == TRUE)
return TRUE;
/* find the host */
temp_host = find_host(svc->host_name);
if(temp_host == NULL)
return FALSE;
/* if this user is authorized for this host, they are for all services on it as well... */
if(is_authorized_for_host(temp_host, authinfo) == TRUE)
return TRUE;
/* find the contact */
temp_contact = find_contact(authinfo->username);
/* see if this user is a contact for the service */
if(is_contact_for_service(svc, temp_contact) == TRUE)
return TRUE;
/* see if this user is an escalated contact for the service */
if(is_escalated_contact_for_service(svc, temp_contact) == TRUE)
return TRUE;
return FALSE;
}
/* check if current user is authorized to view information on all hosts */
int is_authorized_for_all_hosts(authdata *authinfo) {
/* if we're not using authentication, fake it */
if(use_authentication == FALSE)
return TRUE;
/* if this user has not authenticated return error */
if(authinfo->authenticated == FALSE)
return FALSE;
return authinfo->authorized_for_all_hosts;
}
/* check if current user is authorized to view information on all service */
int is_authorized_for_all_services(authdata *authinfo) {
/* if we're not using authentication, fake it */
if(use_authentication == FALSE)
return TRUE;
/* if this user has not authenticated return error */
if(authinfo->authenticated == FALSE)
return FALSE;
return authinfo->authorized_for_all_services;
}
/* check if current user is authorized to view system information */
int is_authorized_for_system_information(authdata *authinfo) {
/* if we're not using authentication, fake it */
if(use_authentication == FALSE)
return TRUE;
/* if this user has not authenticated return error */
if(authinfo->authenticated == FALSE)
return FALSE;
return authinfo->authorized_for_system_information;
}
/* check if current user is authorized to view configuration information */
int is_authorized_for_configuration_information(authdata *authinfo) {
/* if we're not using authentication, fake it */
if(use_authentication == FALSE)
return TRUE;
/* if this user has not authenticated return error */
if(authinfo->authenticated == FALSE)
return FALSE;
return authinfo->authorized_for_configuration_information;
}
/* check if current user is authorized to issue system commands */
int is_authorized_for_system_commands(authdata *authinfo) {
/* if we're not using authentication, fake it */
if(use_authentication == FALSE)
return TRUE;
/* if this user has not authenticated return error */
if(authinfo->authenticated == FALSE)
return FALSE;
return authinfo->authorized_for_system_commands;
}
/* check is the current user is authorized to issue commands relating to a particular service */
int is_authorized_for_service_commands(service *svc, authdata *authinfo) {
host *temp_host;
contact *temp_contact;
if(svc == NULL)
return FALSE;
/* if we're not using authentication, fake it */
if(use_authentication == FALSE)
return TRUE;
/* if this user has not authenticated return error */
if(authinfo->authenticated == FALSE)
return FALSE;
/* the user is authorized if they have rights to the service */
if(is_authorized_for_service(svc, authinfo) == TRUE) {
/* find the host */
temp_host = find_host(svc->host_name);
if(temp_host == NULL)
return FALSE;
/* find the contact */
temp_contact = find_contact(authinfo->username);
/* reject if contact is not allowed to issue commands */
if(temp_contact && temp_contact->can_submit_commands == FALSE)
return FALSE;
/* see if this user is a contact for the host */
if(is_contact_for_host(temp_host, temp_contact) == TRUE)
return TRUE;
/* see if this user is an escalated contact for the host */
if(is_escalated_contact_for_host(temp_host, temp_contact) == TRUE)
return TRUE;
/* this user is a contact for the service, so they have permission... */
if(is_contact_for_service(svc, temp_contact) == TRUE)
return TRUE;
/* this user is an escalated contact for the service, so they have permission... */
if(is_escalated_contact_for_service(svc, temp_contact) == TRUE)
return TRUE;
/* this user is not a contact for the host, so they must have been given explicit permissions to all service commands */
if(authinfo->authorized_for_all_service_commands == TRUE)
return TRUE;
}
return FALSE;
}
/* check is the current user is authorized to issue commands relating to a particular host */
int is_authorized_for_host_commands(host *hst, authdata *authinfo) {
contact *temp_contact;
if(hst == NULL)
return FALSE;
/* if we're not using authentication, fake it */
if(use_authentication == FALSE)
return TRUE;
/* if this user has not authenticated return error */
if(authinfo->authenticated == FALSE)
return FALSE;
/* the user is authorized if they have rights to the host */
if(is_authorized_for_host(hst, authinfo) == TRUE) {
/* find the contact */
temp_contact = find_contact(authinfo->username);
/* reject if contact is not allowed to issue commands */
if(temp_contact && temp_contact->can_submit_commands == FALSE)
return FALSE;
/* this user is a contact for the host, so they have permission... */
if(is_contact_for_host(hst, temp_contact) == TRUE)
return TRUE;
/* this user is an escalated contact for the host, so they have permission... */
if(is_escalated_contact_for_host(hst, temp_contact) == TRUE)
return TRUE;
/* this user is not a contact for the host, so they must have been given explicit permissions to all host commands */
if(authinfo->authorized_for_all_host_commands == TRUE)
return TRUE;
}
return FALSE;
}
/* check is the current user is authorized to issue commands relating to a particular servicegroup */
int is_authorized_for_servicegroup_commands(servicegroup *sg, authdata *authinfo) {
servicesmember *temp_servicesmember;
service *temp_service;
if(sg == NULL)
return FALSE;
/* see if user is authorized for all services commands in the servicegroup */
for(temp_servicesmember = sg->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
temp_service = find_service(temp_servicesmember->host_name, temp_servicesmember->service_description);
if(is_authorized_for_service_commands(temp_service, authinfo) == FALSE)
return FALSE;
}
return TRUE;
}
/* check is the current user is authorized to issue commands relating to a particular hostgroup */
int is_authorized_for_hostgroup_commands(hostgroup *hg, authdata *authinfo) {
hostsmember *temp_hostsmember;
host *temp_host;
if(hg == NULL)
return FALSE;
/* see if user is authorized for all hosts in the hostgroup */
for(temp_hostsmember = hg->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
temp_host = find_host(temp_hostsmember->host_name);
if(is_authorized_for_host_commands(temp_host, authinfo) == FALSE)
return FALSE;
}
return TRUE;
}

1874
cgi/cgiutils.c Normal file

File diff suppressed because it is too large Load Diff

2822
cgi/cmd.c Normal file

File diff suppressed because it is too large Load Diff

2483
cgi/config.c Normal file

File diff suppressed because it is too large Load Diff

223
cgi/extcmd_list.c Normal file
View File

@ -0,0 +1,223 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "../include/common.h"
struct nagios_extcmd {
const char *name;
int id;
/* size_t namelen;
int min_args;
int (*handler)(struct nagios_extcmd *, int, char **);
struct nagios_extcmd *next_handler;
*/
};
#define CMD_DEF(name, min_args, handler) \
{ #name, CMD_ ## name }
/* { #name, sizeof(#name) - 1, CMD_ ## name, min_args, handler, NULL } */
struct nagios_extcmd in_core_commands[] = {
CMD_DEF(NONE, 0, NULL),
CMD_DEF(ADD_HOST_COMMENT, 0, NULL),
CMD_DEF(DEL_HOST_COMMENT, 0, NULL),
CMD_DEF(ADD_SVC_COMMENT, 0, NULL),
CMD_DEF(DEL_SVC_COMMENT, 0, NULL),
CMD_DEF(ENABLE_SVC_CHECK, 0, NULL),
CMD_DEF(DISABLE_SVC_CHECK, 0, NULL),
CMD_DEF(SCHEDULE_SVC_CHECK, 0, NULL),
CMD_DEF(DELAY_SVC_NOTIFICATION, 0, NULL),
CMD_DEF(DELAY_HOST_NOTIFICATION, 0, NULL),
CMD_DEF(DISABLE_NOTIFICATIONS, 0, NULL),
CMD_DEF(ENABLE_NOTIFICATIONS, 0, NULL),
CMD_DEF(RESTART_PROCESS, 0, NULL),
CMD_DEF(SHUTDOWN_PROCESS, 0, NULL),
CMD_DEF(ENABLE_HOST_SVC_CHECKS, 0, NULL),
CMD_DEF(DISABLE_HOST_SVC_CHECKS, 0, NULL),
CMD_DEF(SCHEDULE_HOST_SVC_CHECKS, 0, NULL),
CMD_DEF(DELAY_HOST_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(DEL_ALL_HOST_COMMENTS, 0, NULL),
CMD_DEF(DEL_ALL_SVC_COMMENTS, 0, NULL),
CMD_DEF(ENABLE_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(ENABLE_HOST_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_HOST_NOTIFICATIONS, 0, NULL),
CMD_DEF(ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST, 0, NULL),
CMD_DEF(DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST, 0, NULL),
CMD_DEF(ENABLE_HOST_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_HOST_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(PROCESS_SERVICE_CHECK_RESULT, 0, NULL),
CMD_DEF(SAVE_STATE_INFORMATION, 0, NULL),
CMD_DEF(READ_STATE_INFORMATION, 0, NULL),
CMD_DEF(ACKNOWLEDGE_HOST_PROBLEM, 0, NULL),
CMD_DEF(ACKNOWLEDGE_SVC_PROBLEM, 0, NULL),
CMD_DEF(START_EXECUTING_SVC_CHECKS, 0, NULL),
CMD_DEF(STOP_EXECUTING_SVC_CHECKS, 0, NULL),
CMD_DEF(START_ACCEPTING_PASSIVE_SVC_CHECKS, 0, NULL),
CMD_DEF(STOP_ACCEPTING_PASSIVE_SVC_CHECKS, 0, NULL),
CMD_DEF(ENABLE_PASSIVE_SVC_CHECKS, 0, NULL),
CMD_DEF(DISABLE_PASSIVE_SVC_CHECKS, 0, NULL),
CMD_DEF(ENABLE_EVENT_HANDLERS, 0, NULL),
CMD_DEF(DISABLE_EVENT_HANDLERS, 0, NULL),
CMD_DEF(ENABLE_HOST_EVENT_HANDLER, 0, NULL),
CMD_DEF(DISABLE_HOST_EVENT_HANDLER, 0, NULL),
CMD_DEF(ENABLE_SVC_EVENT_HANDLER, 0, NULL),
CMD_DEF(DISABLE_SVC_EVENT_HANDLER, 0, NULL),
CMD_DEF(ENABLE_HOST_CHECK, 0, NULL),
CMD_DEF(DISABLE_HOST_CHECK, 0, NULL),
CMD_DEF(START_OBSESSING_OVER_SVC_CHECKS, 0, NULL),
CMD_DEF(STOP_OBSESSING_OVER_SVC_CHECKS, 0, NULL),
CMD_DEF(REMOVE_HOST_ACKNOWLEDGEMENT, 0, NULL),
CMD_DEF(REMOVE_SVC_ACKNOWLEDGEMENT, 0, NULL),
CMD_DEF(SCHEDULE_FORCED_HOST_SVC_CHECKS, 0, NULL),
CMD_DEF(SCHEDULE_FORCED_SVC_CHECK, 0, NULL),
CMD_DEF(SCHEDULE_HOST_DOWNTIME, 0, NULL),
CMD_DEF(SCHEDULE_SVC_DOWNTIME, 0, NULL),
CMD_DEF(ENABLE_HOST_FLAP_DETECTION, 0, NULL),
CMD_DEF(DISABLE_HOST_FLAP_DETECTION, 0, NULL),
CMD_DEF(ENABLE_SVC_FLAP_DETECTION, 0, NULL),
CMD_DEF(DISABLE_SVC_FLAP_DETECTION, 0, NULL),
CMD_DEF(ENABLE_FLAP_DETECTION, 0, NULL),
CMD_DEF(DISABLE_FLAP_DETECTION, 0, NULL),
CMD_DEF(ENABLE_HOSTGROUP_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_HOSTGROUP_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(ENABLE_HOSTGROUP_HOST_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_HOSTGROUP_HOST_NOTIFICATIONS, 0, NULL),
CMD_DEF(ENABLE_HOSTGROUP_SVC_CHECKS, 0, NULL),
CMD_DEF(DISABLE_HOSTGROUP_SVC_CHECKS, 0, NULL),
CMD_DEF(CANCEL_HOST_DOWNTIME, 0, NULL),
CMD_DEF(CANCEL_SVC_DOWNTIME, 0, NULL),
CMD_DEF(CANCEL_ACTIVE_HOST_DOWNTIME, 0, NULL),
CMD_DEF(CANCEL_PENDING_HOST_DOWNTIME, 0, NULL),
CMD_DEF(CANCEL_ACTIVE_SVC_DOWNTIME, 0, NULL),
CMD_DEF(CANCEL_PENDING_SVC_DOWNTIME, 0, NULL),
CMD_DEF(CANCEL_ACTIVE_HOST_SVC_DOWNTIME, 0, NULL),
CMD_DEF(CANCEL_PENDING_HOST_SVC_DOWNTIME, 0, NULL),
CMD_DEF(FLUSH_PENDING_COMMANDS, 0, NULL),
CMD_DEF(DEL_HOST_DOWNTIME, 0, NULL),
CMD_DEF(DEL_SVC_DOWNTIME, 0, NULL),
CMD_DEF(ENABLE_FAILURE_PREDICTION, 0, NULL),
CMD_DEF(DISABLE_FAILURE_PREDICTION, 0, NULL),
CMD_DEF(ENABLE_PERFORMANCE_DATA, 0, NULL),
CMD_DEF(DISABLE_PERFORMANCE_DATA, 0, NULL),
CMD_DEF(SCHEDULE_HOSTGROUP_HOST_DOWNTIME, 0, NULL),
CMD_DEF(SCHEDULE_HOSTGROUP_SVC_DOWNTIME, 0, NULL),
CMD_DEF(SCHEDULE_HOST_SVC_DOWNTIME, 0, NULL),
CMD_DEF(PROCESS_HOST_CHECK_RESULT, 0, NULL),
CMD_DEF(START_EXECUTING_HOST_CHECKS, 0, NULL),
CMD_DEF(STOP_EXECUTING_HOST_CHECKS, 0, NULL),
CMD_DEF(START_ACCEPTING_PASSIVE_HOST_CHECKS, 0, NULL),
CMD_DEF(STOP_ACCEPTING_PASSIVE_HOST_CHECKS, 0, NULL),
CMD_DEF(ENABLE_PASSIVE_HOST_CHECKS, 0, NULL),
CMD_DEF(DISABLE_PASSIVE_HOST_CHECKS, 0, NULL),
CMD_DEF(START_OBSESSING_OVER_HOST_CHECKS, 0, NULL),
CMD_DEF(STOP_OBSESSING_OVER_HOST_CHECKS, 0, NULL),
CMD_DEF(SCHEDULE_HOST_CHECK, 0, NULL),
CMD_DEF(SCHEDULE_FORCED_HOST_CHECK, 0, NULL),
CMD_DEF(START_OBSESSING_OVER_SVC, 0, NULL),
CMD_DEF(STOP_OBSESSING_OVER_SVC, 0, NULL),
CMD_DEF(START_OBSESSING_OVER_HOST, 0, NULL),
CMD_DEF(STOP_OBSESSING_OVER_HOST, 0, NULL),
CMD_DEF(ENABLE_HOSTGROUP_HOST_CHECKS, 0, NULL),
CMD_DEF(DISABLE_HOSTGROUP_HOST_CHECKS, 0, NULL),
CMD_DEF(ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS, 0, NULL),
CMD_DEF(DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS, 0, NULL),
CMD_DEF(ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS, 0, NULL),
CMD_DEF(DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS, 0, NULL),
CMD_DEF(ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS, 0, NULL),
CMD_DEF(ENABLE_SERVICEGROUP_SVC_CHECKS, 0, NULL),
CMD_DEF(DISABLE_SERVICEGROUP_SVC_CHECKS, 0, NULL),
CMD_DEF(ENABLE_SERVICEGROUP_HOST_CHECKS, 0, NULL),
CMD_DEF(DISABLE_SERVICEGROUP_HOST_CHECKS, 0, NULL),
CMD_DEF(ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS, 0, NULL),
CMD_DEF(DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS, 0, NULL),
CMD_DEF(ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS, 0, NULL),
CMD_DEF(DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS, 0, NULL),
CMD_DEF(SCHEDULE_SERVICEGROUP_HOST_DOWNTIME, 0, NULL),
CMD_DEF(SCHEDULE_SERVICEGROUP_SVC_DOWNTIME, 0, NULL),
CMD_DEF(CHANGE_GLOBAL_HOST_EVENT_HANDLER, 0, NULL),
CMD_DEF(CHANGE_GLOBAL_SVC_EVENT_HANDLER, 0, NULL),
CMD_DEF(CHANGE_HOST_EVENT_HANDLER, 0, NULL),
CMD_DEF(CHANGE_SVC_EVENT_HANDLER, 0, NULL),
CMD_DEF(CHANGE_HOST_CHECK_COMMAND, 0, NULL),
CMD_DEF(CHANGE_SVC_CHECK_COMMAND, 0, NULL),
CMD_DEF(CHANGE_NORMAL_HOST_CHECK_INTERVAL, 0, NULL),
CMD_DEF(CHANGE_NORMAL_SVC_CHECK_INTERVAL, 0, NULL),
CMD_DEF(CHANGE_RETRY_SVC_CHECK_INTERVAL, 0, NULL),
CMD_DEF(CHANGE_MAX_HOST_CHECK_ATTEMPTS, 0, NULL),
CMD_DEF(CHANGE_MAX_SVC_CHECK_ATTEMPTS, 0, NULL),
CMD_DEF(SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME, 0, NULL),
CMD_DEF(ENABLE_HOST_AND_CHILD_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_HOST_AND_CHILD_NOTIFICATIONS, 0, NULL),
CMD_DEF(SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME, 0, NULL),
CMD_DEF(ENABLE_SERVICE_FRESHNESS_CHECKS, 0, NULL),
CMD_DEF(DISABLE_SERVICE_FRESHNESS_CHECKS, 0, NULL),
CMD_DEF(ENABLE_HOST_FRESHNESS_CHECKS, 0, NULL),
CMD_DEF(DISABLE_HOST_FRESHNESS_CHECKS, 0, NULL),
CMD_DEF(SET_HOST_NOTIFICATION_NUMBER, 0, NULL),
CMD_DEF(SET_SVC_NOTIFICATION_NUMBER, 0, NULL),
CMD_DEF(CHANGE_HOST_CHECK_TIMEPERIOD, 0, NULL),
CMD_DEF(CHANGE_SVC_CHECK_TIMEPERIOD, 0, NULL),
CMD_DEF(PROCESS_FILE, 0, NULL),
CMD_DEF(CHANGE_CUSTOM_HOST_VAR, 0, NULL),
CMD_DEF(CHANGE_CUSTOM_SVC_VAR, 0, NULL),
CMD_DEF(CHANGE_CUSTOM_CONTACT_VAR, 0, NULL),
CMD_DEF(ENABLE_CONTACT_HOST_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_CONTACT_HOST_NOTIFICATIONS, 0, NULL),
CMD_DEF(ENABLE_CONTACT_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_CONTACT_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS, 0, NULL),
CMD_DEF(ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS, 0, NULL),
CMD_DEF(CHANGE_RETRY_HOST_CHECK_INTERVAL, 0, NULL),
CMD_DEF(SEND_CUSTOM_HOST_NOTIFICATION, 0, NULL),
CMD_DEF(SEND_CUSTOM_SVC_NOTIFICATION, 0, NULL),
CMD_DEF(CHANGE_HOST_NOTIFICATION_TIMEPERIOD, 0, NULL),
CMD_DEF(CHANGE_SVC_NOTIFICATION_TIMEPERIOD, 0, NULL),
CMD_DEF(CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD, 0, NULL),
CMD_DEF(CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD, 0, NULL),
CMD_DEF(CHANGE_HOST_MODATTR, 0, NULL),
CMD_DEF(CHANGE_SVC_MODATTR, 0, NULL),
CMD_DEF(CHANGE_CONTACT_MODATTR, 0, NULL),
CMD_DEF(CHANGE_CONTACT_MODHATTR, 0, NULL),
CMD_DEF(CHANGE_CONTACT_MODSATTR, 0, NULL),
};
#undef CMD_DEF
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
#endif
const char *extcmd_get_name(int id) {
int i;
for(i = 0; i < ARRAY_SIZE(in_core_commands); i++) {
struct nagios_extcmd *ecmd;
ecmd = &in_core_commands[i];
if(ecmd->id == id)
return ecmd->name;
}
return NULL;
}
#ifdef ECMD_LIST_TESTING
int main(int argc, char **argv) {
int i, no_handler = 0;
for(i = 0; i < ARRAY_SIZE(in_core_commands); i++) {
struct nagios_extcmd *cmd = &in_core_commands[i];
if(!cmd->handler) {
no_handler++;
printf("%s has no handler\n", extcmd_get_name(i));
}
}
printf("%d of %d commands have no handler\n",
no_handler, ARRAY_SIZE(in_core_commands));
return 0;
}
#endif

3200
cgi/extinfo.c Normal file

File diff suppressed because it is too large Load Diff

517
cgi/getcgi.c Normal file
View File

@ -0,0 +1,517 @@
/******************************************
*
* GETCGI.C - Nagios CGI Input Routines
*
* Last Modified: 05-15-2006
*
*****************************************/
#include "../include/config.h"
#include "../include/getcgi.h"
#include <stdio.h>
#include <stdlib.h>
#undef PARANOID_CGI_INPUT
/* Remove potentially harmful characters from CGI input that we don't need or want */
void sanitize_cgi_input(char **cgivars) {
char *strptr;
int x, y, i;
int keep;
/* don't strip for now... */
return;
for(strptr = cgivars[i = 0]; strptr != NULL; strptr = cgivars[++i]) {
for(x = 0, y = 0; strptr[x] != '\x0'; x++) {
keep = 1;
/* remove potentially nasty characters */
if(strptr[x] == ';' || strptr[x] == '|' || strptr[x] == '&' || strptr[x] == '<' || strptr[x] == '>')
keep = 0;
#ifdef PARANOID_CGI_INPUT
else if(strptr[x] == '/' || strptr[x] == '\\')
keep = 0;
#endif
if(keep == 1)
strptr[y++] = strptr[x];
}
strptr[y] = '\x0';
}
return;
}
/* convert encoded hex string (2 characters representing an 8-bit number) to its ASCII char equivalent */
unsigned char hex_to_char(char *input) {
unsigned char outchar = '\x0';
unsigned int outint;
char tempbuf[3];
/* NULL or empty string */
if(input == NULL)
return '\x0';
if(input[0] == '\x0')
return '\x0';
tempbuf[0] = input[0];
tempbuf[1] = input[1];
tempbuf[2] = '\x0';
sscanf(tempbuf, "%X", &outint);
/* only convert "normal" ASCII characters - we don't want the rest. Normally you would
convert all characters (i.e. for allowing users to post binary files), but since we
aren't doing this, stay on the cautious side of things and reject outsiders... */
#ifdef PARANOID_CGI_INPUT
if(outint < 32 || outint > 126)
outint = 0;
#endif
outchar = (unsigned char)outint;
return outchar;
}
/* unescape hex characters in CGI input */
void unescape_cgi_input(char *input) {
int x, y;
int len;
if(input == NULL)
return;
len = strlen(input);
for(x = 0, y = 0; x < len; x++, y++) {
if(input[x] == '\x0')
break;
else if(input[x] == '%') {
input[y] = hex_to_char(&input[x + 1]);
x += 2;
}
else
input[y] = input[x];
}
input[y] = '\x0';
return;
}
/* read the CGI input and place all name/val pairs into list. returns list containing name1, value1, name2, value2, ... , NULL */
/* this is a hacked version of a routine I found a long time ago somewhere - can't remember where anymore */
char **getcgivars(void) {
register int i;
char *accept_language;
char *request_method;
char *content_type;
char *content_length_string;
int content_length;
char *cgiinput;
char **cgivars;
char **pairlist;
int paircount;
char *nvpair;
char *eqpos;
/* initialize char variable(s) */
cgiinput = "";
/* Attempt to set the locale */
accept_language = getenv("HTTP_ACCEPT_LANGUAGE");
process_language(accept_language);
/* depending on the request method, read all CGI input into cgiinput */
request_method = getenv("REQUEST_METHOD");
if(request_method == NULL)
request_method = "";
if(!strcmp(request_method, "GET") || !strcmp(request_method, "HEAD")) {
/* check for NULL query string environment variable - 04/28/00 (Ludo Bosmans) */
if(getenv("QUERY_STRING") == NULL) {
cgiinput = (char *)malloc(1);
if(cgiinput != NULL)
cgiinput[0] = '\x0';
}
else
cgiinput = strdup(getenv("QUERY_STRING"));
if(cgiinput == NULL) {
printf("getcgivars(): Could not allocate memory for CGI input.\n");
exit(1);
}
}
else if(!strcmp(request_method, "POST") || !strcmp(request_method, "PUT")) {
/* if CONTENT_TYPE variable is not specified, RFC-2068 says we should assume it is "application/octet-string" */
/* mobile (WAP) stations generate CONTENT_TYPE with charset, we we should only check first 33 chars */
content_type = getenv("CONTENT_TYPE");
if(content_type == NULL)
content_type = "";
if(strlen(content_type) && strncasecmp(content_type, "application/x-www-form-urlencoded", 33)) {
printf("getcgivars(): Unsupported Content-Type.\n");
exit(1);
}
content_length_string = getenv("CONTENT_LENGTH");
if(content_length_string == NULL)
content_length_string = "0";
if(!(content_length = atoi(content_length_string))) {
printf("getcgivars(): No Content-Length was sent with the POST request.\n") ;
exit(1);
}
/* suspicious content length */
if((content_length < 0) || (content_length >= INT_MAX - 1)) {
printf("getcgivars(): Suspicious Content-Length was sent with the POST request.\n");
exit(1);
}
if(!(cgiinput = (char *)malloc(content_length + 1))) {
printf("getcgivars(): Could not allocate memory for CGI input.\n");
exit(1);
}
if(!fread(cgiinput, content_length, 1, stdin)) {
printf("getcgivars(): Could not read input from STDIN.\n");
exit(1);
}
cgiinput[content_length] = '\0';
}
else {
printf("getcgivars(): Unsupported REQUEST_METHOD -> '%s'\n", request_method);
printf("\n");
printf("I'm guessing you're trying to execute the CGI from a command line.\n");
printf("In order to do that, you need to set the REQUEST_METHOD environment\n");
printf("variable to either \"GET\", \"HEAD\", or \"POST\". When using the\n");
printf("GET and HEAD methods, arguments can be passed to the CGI\n");
printf("by setting the \"QUERY_STRING\" environment variable. If you're\n");
printf("using the POST method, data is read from standard input. Also of\n");
printf("note: if you've enabled authentication in the CGIs, you must set the\n");
printf("\"REMOTE_USER\" environment variable to be the name of the user you're\n");
printf("\"authenticated\" as.\n");
printf("\n");
exit(1);
}
/* change all plus signs back to spaces */
for(i = 0; cgiinput[i]; i++) {
if(cgiinput[i] == '+')
cgiinput[i] = ' ';
}
/* first, split on ampersands (&) to extract the name-value pairs into pairlist */
/* allocate memory for 256 name-value pairs at a time, increasing by same
amount as necessary... */
pairlist = (char **)malloc(256 * sizeof(char **));
if(pairlist == NULL) {
printf("getcgivars(): Could not allocate memory for name-value pairlist.\n");
exit(1);
}
paircount = 0;
nvpair = strtok(cgiinput, "&");
while(nvpair) {
pairlist[paircount] = strdup(nvpair);
if(NULL == pairlist[paircount]) {
printf("getcgivars(): Could not allocate memory for name-value pair #%d.\n", paircount);
exit(1);
}
paircount++;
if(!(paircount % 256)) {
pairlist = (char **)realloc(pairlist, (paircount + 256) * sizeof(char **));
if(pairlist == NULL) {
printf("getcgivars(): Could not re-allocate memory for name-value pairlist.\n");
exit(1);
}
}
nvpair = strtok(NULL, "&");
}
/* terminate the list */
pairlist[paircount] = '\x0';
/* extract the names and values from the pairlist */
cgivars = (char **)malloc((paircount * 2 + 1) * sizeof(char **));
if(cgivars == NULL) {
printf("getcgivars(): Could not allocate memory for name-value list.\n");
exit(1);
}
for(i = 0; i < paircount; i++) {
/* get the variable name preceding the equal (=) sign */
if((eqpos = strchr(pairlist[i], '=')) != NULL) {
*eqpos = '\0';
cgivars[i * 2 + 1] = strdup(eqpos + 1);
if(NULL == cgivars[ i * 2 + 1]) {
printf("getcgivars(): Could not allocate memory for cgi value #%d.\n", i);
exit(1);
}
unescape_cgi_input(cgivars[i * 2 + 1]);
}
else {
cgivars[i * 2 + 1] = strdup("");
if(NULL == cgivars[ i * 2 + 1]) {
printf("getcgivars(): Could not allocate memory for empty stringfor variable value #%d.\n", i);
exit(1);
}
unescape_cgi_input(cgivars[i * 2 + 1]);
}
/* get the variable value (or name/value of there was no real "pair" in the first place) */
cgivars[i * 2] = strdup(pairlist[i]);
if(NULL == cgivars[ i * 2]) {
printf("getcgivars(): Could not allocate memory for cgi name #%d.\n", i);
exit(1);
}
unescape_cgi_input(cgivars[i * 2]);
}
/* terminate the name-value list */
cgivars[paircount * 2] = '\x0';
/* free allocated memory */
free(cgiinput);
for(i = 0; pairlist[i] != NULL; i++)
free(pairlist[i]);
free(pairlist);
/* sanitize the name-value strings */
sanitize_cgi_input(cgivars);
/* return the list of name-value strings */
return cgivars;
}
/* Set the locale based on the HTTP_ACCEPT_LANGUAGE variable value sent by
the browser */
void process_language(char * accept_language) {
accept_languages *accept_langs = NULL;
int x;
char locale_string[ 64];
char * locale = NULL;
char * locale_failsafe[] = { "en_US.utf8", "POSIX", "C" };
if(accept_language != NULL) {
accept_langs = parse_accept_languages(accept_language);
}
if(NULL != accept_langs) {
/* Sort the results */
qsort(accept_langs->languages, accept_langs->count,
sizeof(accept_langs->languages[ 0]), compare_accept_languages);
/* Try each language in order of priority */
for(x = 0; ((x < accept_langs->count) && (NULL == locale)); x++) {
snprintf(locale_string, sizeof(locale_string), "%s_%s.%s",
accept_langs->languages[ x]->language,
accept_langs->languages[ x]->locality, "utf8");
locale = setlocale(LC_CTYPE, locale_string);
if(NULL != locale) break;
}
free_accept_languages(accept_langs);
}
if(NULL == locale) { /* Still isn't set */
/* Try the fail safe locales */
for(x = 0; ((x < (sizeof(locale_failsafe) / sizeof(char *))) &&
(NULL == locale)); x++) {
locale = setlocale(LC_CTYPE, locale_failsafe[ x]);
}
}
}
accept_languages * parse_accept_languages(char * acceptlang) {
char * langdup; /* Duplicate of accept language for parsing */
accept_languages *langs = NULL;
char * langtok; /* Language token (language + locality + q value) */
char * saveptr; /* Save state of tokenization */
char * qdelim; /* location of the delimiter ';q=' */
char * localitydelim; /* Delimiter for locality specifier */
int x;
char * stp;
/* If the browser did not pass an HTTP_ACCEPT_LANGUAGE variable, there
is not much we can do */
if(NULL == acceptlang) {
return NULL;
}
/* Duplicate the browser supplied HTTP_ACCEPT_LANGUAGE variable */
if(NULL == (langdup = strdup(acceptlang))) {
printf("Unable to allocate memory for langdup\n");
return NULL;
}
/* Initialize the structure to contain the parsed HTTP_ACCEPT_LANGUAGE
information */
if(NULL == (langs = malloc(sizeof(accept_languages)))) {
printf("Unable to allocate memory for langs\n");
free(langdup);
return NULL;
}
langs->count = 0;
langs->languages = (accept_language **)NULL;
/* Tokenize the HTTP_ACCEPT_LANGUAGE string */
langtok = strtok_r(langdup, ",", &saveptr);
while(langtok != NULL) {
/* Bump the count and allocate memory for structures */
langs->count++;
if(NULL == langs->languages) {
/* Adding first language */
if(NULL == (langs->languages =
malloc(langs->count * sizeof(accept_language *)))) {
printf("Unable to allocate memory for first language\n");
langs->count--;
free_accept_languages(langs);
free(langdup);
return NULL;
}
}
else {
/* Adding additional language */
if(NULL == (langs->languages = realloc(langs->languages,
langs->count * sizeof(accept_language *)))) {
printf("Unable to allocate memory for additional language\n");
langs->count--;
free_accept_languages(langs);
free(langdup);
return NULL;
}
}
if(NULL == (langs->languages[ langs->count - 1] =
malloc(sizeof(accept_language)))) {
printf("Unable to allocate memory for language\n");
langs->count--;
free_accept_languages(langs);
free(langdup);
return NULL;
}
langs->languages[ langs->count - 1]->language = (char *)NULL;
langs->languages[ langs->count - 1]->locality = (char *)NULL;
langs->languages[ langs->count - 1]->q = 1.0;
/* Check to see if there is a q value */
qdelim = strstr(langtok, ACCEPT_LANGUAGE_Q_DELIMITER);
if(NULL != qdelim) { /* found a q value */
langs->languages[ langs->count - 1]->q =
strtod(qdelim + strlen(ACCEPT_LANGUAGE_Q_DELIMITER), NULL);
langtok[ qdelim - langtok] = '\0';
}
/* Check to see if there is a locality specifier */
if(NULL == (localitydelim = strchr(langtok, '-'))) {
localitydelim = strchr(langtok, '_');
}
if(NULL != localitydelim) {
/* We have a locality delimiter, so copy it */
if(NULL == (langs->languages[ langs->count - 1]->locality =
strdup(localitydelim + 1))) {
printf("Unable to allocate memory for locality '%s'\n",
langtok);
free_accept_languages(langs);
free(langdup);
return NULL;
}
/* Ensure it is upper case */
for(x = 0, stp = langs->languages[ langs->count - 1]->locality;
x < strlen(langs->languages[ langs->count - 1]->locality);
x++, stp++) {
*stp = toupper(*stp);
}
/* Then null out the delimiter so the language copy works */
*localitydelim = '\0';
}
if(NULL == (langs->languages[ langs->count - 1]->language =
strdup(langtok))) {
printf("Unable to allocate memory for language '%s'\n",
langtok);
free_accept_languages(langs);
free(langdup);
return NULL;
}
/* Get the next language token */
langtok = strtok_r(NULL, ",", &saveptr);
}
free(langdup);
return langs;
}
int compare_accept_languages(const void *p1, const void *p2) {
accept_language * lang1 = *(accept_language **)p1;
accept_language * lang2 = *(accept_language **)p2;
if(lang1->q == lang2->q) {
if(((NULL == lang1->locality) && (NULL == lang2->locality)) ||
((NULL != lang1->locality) && (NULL != lang2->locality))) {
return 0;
}
else if(NULL != lang1->locality) {
return -1;
}
else { /* NULL != lang2->locality */
return 1;
}
}
else {
return(lang2->q > lang1->q);
}
}
void free_accept_languages(accept_languages * langs) {
int x;
if(NULL == langs) {
return;
}
for(x = 0; x < langs->count; x++) {
if(NULL != langs->languages[ x]) {
if(langs->languages[ x]->language != NULL) {
free(langs->languages[ x]->language);
}
if(langs->languages[ x]->locality != NULL) {
free(langs->languages[ x]->locality);
}
free(langs->languages[ x]);
}
}
if(langs->languages != NULL) {
free(langs->languages);
}
free(langs);
return;
}
/* free() memory allocated to storing the CGI variables */
void free_cgivars(char **cgivars) {
register int x;
for(x = 0; cgivars[x] != '\x0'; x++)
free(cgivars[x]);
return;
}

2481
cgi/histogram.c Normal file

File diff suppressed because it is too large Load Diff

971
cgi/history.c Normal file
View File

@ -0,0 +1,971 @@
/***********************************************************************
*
* HISTORY.C - Nagios History CGI
*
* Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 06-23-2008
*
* This CGI program will display the history for the specified host.
* If no host is specified, the history for all hosts will be displayed.
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
***********************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/getcgi.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
#define DISPLAY_HOSTS 0
#define DISPLAY_SERVICES 1
#define SERVICE_HISTORY 0
#define HOST_HISTORY 1
#define SERVICE_FLAPPING_HISTORY 2
#define HOST_FLAPPING_HISTORY 3
#define SERVICE_DOWNTIME_HISTORY 4
#define HOST_DOWNTIME_HISTORY 5
#define STATE_ALL 0
#define STATE_SOFT 1
#define STATE_HARD 2
void get_history(void);
void document_header(int);
void document_footer(void);
int process_cgivars(void);
extern char main_config_file[MAX_FILENAME_LENGTH];
extern char url_html_path[MAX_FILENAME_LENGTH];
extern char url_images_path[MAX_FILENAME_LENGTH];
extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
extern int log_rotation_method;
extern int enable_splunk_integration;
authdata current_authdata;
char log_file_to_use[MAX_FILENAME_LENGTH];
int log_archive = 0;
int show_all_hosts = TRUE;
char *host_name = "all";
char *svc_description = "";
int display_type = DISPLAY_HOSTS;
int use_lifo = TRUE;
int history_options = HISTORY_ALL;
int state_options = STATE_ALL;
int embedded = FALSE;
int display_header = TRUE;
int display_frills = TRUE;
int display_timebreaks = TRUE;
int display_system_messages = TRUE;
int display_flapping_alerts = TRUE;
int display_downtime_alerts = TRUE;
int main(void) {
int result = OK;
char temp_buffer[MAX_INPUT_BUFFER];
char temp_buffer2[MAX_INPUT_BUFFER];
/* get the variables passed to us */
process_cgivars();
/* reset internal CGI variables */
reset_cgi_vars();
/* read the CGI configuration file */
result = read_cgi_config_file(get_cgi_config_location());
if(result == ERROR) {
document_header(FALSE);
cgi_config_file_error(get_cgi_config_location());
document_footer();
return ERROR;
}
/* read the main configuration file */
result = read_main_config_file(main_config_file);
if(result == ERROR) {
document_header(FALSE);
main_config_file_error(main_config_file);
document_footer();
return ERROR;
}
/* read all object configuration data */
result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
if(result == ERROR) {
document_header(FALSE);
object_data_error();
document_footer();
return ERROR;
}
document_header(TRUE);
/* get authentication information */
get_authentication_information(&current_authdata);
/* determine what log file we should be using */
get_log_archive_to_use(log_archive, log_file_to_use, (int)sizeof(log_file_to_use));
if(display_header == TRUE) {
/* begin top table */
printf("<table border=0 width=100%%>\n");
printf("<tr>\n");
/* left column of the first row */
printf("<td align=left valign=top width=33%%>\n");
if(display_type == DISPLAY_SERVICES)
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Service Alert History");
else if(show_all_hosts == TRUE)
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Alert History");
else
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host Alert History");
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
display_info_table(temp_buffer, FALSE, &current_authdata);
printf("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 CLASS='linkBox'>\n");
printf("<TR><TD CLASS='linkBox'>\n");
if(display_type == DISPLAY_HOSTS) {
printf("<A HREF='%s?host=%s'>View Status Detail For %s</A><BR />\n", STATUS_CGI, (show_all_hosts == TRUE) ? "all" : url_encode(host_name), (show_all_hosts == TRUE) ? "All Hosts" : "This Host");
printf("<A HREF='%s?host=%s'>View Notifications For %s</A><BR />\n", NOTIFICATIONS_CGI, (show_all_hosts == TRUE) ? "all" : url_encode(host_name), (show_all_hosts == TRUE) ? "All Hosts" : "This Host");
#ifdef USE_TRENDS
if(show_all_hosts == FALSE)
printf("<A HREF='%s?host=%s'>View Trends For This Host</A>\n", TRENDS_CGI, url_encode(host_name));
#endif
}
else {
printf("<A HREF='%s?host=%s&", NOTIFICATIONS_CGI, url_encode(host_name));
printf("service=%s'>View Notifications For This Service</A><BR />\n", url_encode(svc_description));
#ifdef USE_TRENDS
printf("<A HREF='%s?host=%s&", TRENDS_CGI, url_encode(host_name));
printf("service=%s'>View Trends For This Service</A><BR />\n", url_encode(svc_description));
#endif
printf("<A HREF='%s?host=%s'>View History For This Host</A>\n", HISTORY_CGI, url_encode(host_name));
}
printf("</TD></TR>\n");
printf("</TABLE>\n");
printf("</td>\n");
/* middle column of top row */
printf("<td align=center valign=top width=33%%>\n");
printf("<DIV ALIGN=CENTER CLASS='dataTitle'>\n");
if(display_type == DISPLAY_SERVICES)
printf("Service '%s' On Host '%s'", svc_description, host_name);
else if(show_all_hosts == TRUE)
printf("All Hosts and Services");
else
printf("Host '%s'", host_name);
printf("</DIV>\n");
printf("<BR />\n");
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s?%shost=%s&type=%d&statetype=%d&", HISTORY_CGI, (use_lifo == FALSE) ? "oldestfirst&" : "", url_encode(host_name), history_options, state_options);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
if(display_type == DISPLAY_SERVICES) {
snprintf(temp_buffer2, sizeof(temp_buffer2) - 1, "service=%s&", url_encode(svc_description));
temp_buffer2[sizeof(temp_buffer2) - 1] = '\x0';
strncat(temp_buffer, temp_buffer2, sizeof(temp_buffer) - strlen(temp_buffer) - 1);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
}
display_nav_table(temp_buffer, log_archive);
printf("</td>\n");
/* right hand column of top row */
printf("<td align=right valign=top width=33%%>\n");
printf("<form method=\"GET\" action=\"%s\">\n", HISTORY_CGI);
printf("<table border=0 CLASS='optBox'>\n");
printf("<input type='hidden' name='host' value='%s'>\n", (show_all_hosts == TRUE) ? "all" : escape_string(host_name));
if(display_type == DISPLAY_SERVICES)
printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
printf("<input type='hidden' name='archive' value='%d'>\n", log_archive);
printf("<tr>\n");
printf("<td align=left CLASS='optBoxItem'>State type options:</td>\n");
printf("</tr>\n");
printf("<tr>\n");
printf("<td align=left CLASS='optBoxItem'><select name='statetype'>\n");
printf("<option value=%d %s>All state types</option>\n", STATE_ALL, (state_options == STATE_ALL) ? "selected" : "");
printf("<option value=%d %s>Soft states</option>\n", STATE_SOFT, (state_options == STATE_SOFT) ? "selected" : "");
printf("<option value=%d %s>Hard states</option>\n", STATE_HARD, (state_options == STATE_HARD) ? "selected" : "");
printf("</select></td>\n");
printf("</tr>\n");
printf("<tr>\n");
printf("<td align=left CLASS='optBoxItem'>History detail level for ");
if(display_type == DISPLAY_HOSTS)
printf("%s host%s", (show_all_hosts == TRUE) ? "all" : "this", (show_all_hosts == TRUE) ? "s" : "");
else
printf("service");
printf(":</td>\n");
printf("</tr>\n")
;
printf("<tr>\n");
printf("<td align=left CLASS='optBoxItem'><select name='type'>\n");
if(display_type == DISPLAY_HOSTS)
printf("<option value=%d %s>All alerts</option>\n", HISTORY_ALL, (history_options == HISTORY_ALL) ? "selected" : "");
printf("<option value=%d %s>All service alerts</option>\n", HISTORY_SERVICE_ALL, (history_options == HISTORY_SERVICE_ALL) ? "selected" : "");
if(display_type == DISPLAY_HOSTS)
printf("<option value=%d %s>All host alerts</option>\n", HISTORY_HOST_ALL, (history_options == HISTORY_HOST_ALL) ? "selected" : "");
printf("<option value=%d %s>Service warning</option>\n", HISTORY_SERVICE_WARNING, (history_options == HISTORY_SERVICE_WARNING) ? "selected" : "");
printf("<option value=%d %s>Service unknown</option>\n", HISTORY_SERVICE_UNKNOWN, (history_options == HISTORY_SERVICE_UNKNOWN) ? "selected" : "");
printf("<option value=%d %s>Service critical</option>\n", HISTORY_SERVICE_CRITICAL, (history_options == HISTORY_SERVICE_CRITICAL) ? "selected" : "");
printf("<option value=%d %s>Service recovery</option>\n", HISTORY_SERVICE_RECOVERY, (history_options == HISTORY_SERVICE_RECOVERY) ? "selected" : "");
if(display_type == DISPLAY_HOSTS) {
printf("<option value=%d %s>Host down</option>\n", HISTORY_HOST_DOWN, (history_options == HISTORY_HOST_DOWN) ? "selected" : "");
printf("<option value=%d %s>Host unreachable</option>\n", HISTORY_HOST_UNREACHABLE, (history_options == HISTORY_HOST_UNREACHABLE) ? "selected" : "");
printf("<option value=%d %s>Host recovery</option>\n", HISTORY_HOST_RECOVERY, (history_options == HISTORY_HOST_RECOVERY) ? "selected" : "");
}
printf("</select></td>\n");
printf("</tr>\n");
printf("<tr>\n");
printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='noflapping' %s> Hide Flapping Alerts</td>", (display_flapping_alerts == FALSE) ? "checked" : "");
printf("</tr>\n");
printf("<tr>\n");
printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='nodowntime' %s> Hide Downtime Alerts</td>", (display_downtime_alerts == FALSE) ? "checked" : "");
printf("</tr>\n");
printf("<tr>\n");
printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='nosystem' %s> Hide Process Messages</td>", (display_system_messages == FALSE) ? "checked" : "");
printf("</tr>\n");
printf("<tr>\n");
printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='oldestfirst' %s> Older Entries First</td>", (use_lifo == FALSE) ? "checked" : "");
printf("</tr>\n");
printf("<tr>\n");
printf("<td align=left CLASS='optBoxItem'><input type='submit' value='Update'></td>\n");
printf("</tr>\n");
/* display context-sensitive help */
printf("<tr>\n");
printf("<td align=right>\n");
display_context_help(CONTEXTHELP_HISTORY);
printf("</td>\n");
printf("</tr>\n");
printf("</table>\n");
printf("</form>\n");
printf("</td>\n");
/* end of top table */
printf("</tr>\n");
printf("</table>\n");
}
/* display history */
get_history();
document_footer();
/* free allocated memory */
free_memory();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
time_t expire_time;
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
time(&current_time);
get_time_string(&current_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
printf("Last-Modified: %s\r\n", date_time);
expire_time = (time_t)0L;
get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
printf("Expires: %s\r\n", date_time);
printf("Content-type: text/html\r\n\r\n");
if(embedded == TRUE)
return;
printf("<html>\n");
printf("<head>\n");
printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
printf("<title>\n");
printf("Nagios History\n");
printf("</title>\n");
if(use_stylesheet == TRUE) {
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, HISTORY_CSS);
}
printf("</head>\n");
printf("<BODY CLASS='history'>\n");
/* include user SSI header */
include_ssi_files(HISTORY_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(HISTORY_CGI, SSI_FOOTER);
printf("</body>\n");
printf("</html>\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
for(x = 0; variables[x] != NULL; x++) {
/* do some basic length checking on the variable identifier to prevent buffer overflows */
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1)
continue;
/* we found the host argument */
else if(!strcmp(variables[x], "host")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((host_name = (char *)strdup(variables[x])) == NULL)
host_name = "";
strip_html_brackets(host_name);
display_type = DISPLAY_HOSTS;
if(!strcmp(host_name, "all"))
show_all_hosts = TRUE;
else
show_all_hosts = FALSE;
}
/* we found the service argument */
else if(!strcmp(variables[x], "service")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((svc_description = (char *)strdup(variables[x])) == NULL)
svc_description = "";
strip_html_brackets(svc_description);
display_type = DISPLAY_SERVICES;
}
/* we found the history type argument */
else if(!strcmp(variables[x], "type")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
history_options = atoi(variables[x]);
}
/* we found the history state type argument */
else if(!strcmp(variables[x], "statetype")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
state_options = atoi(variables[x]);
}
/* we found the log archive argument */
else if(!strcmp(variables[x], "archive")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
log_archive = atoi(variables[x]);
if(log_archive < 0)
log_archive = 0;
}
/* we found the order argument */
else if(!strcmp(variables[x], "oldestfirst")) {
use_lifo = FALSE;
}
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
/* we found the noheader option */
else if(!strcmp(variables[x], "noheader"))
display_header = FALSE;
/* we found the nofrills option */
else if(!strcmp(variables[x], "nofrills"))
display_frills = FALSE;
/* we found the notimebreaks option */
else if(!strcmp(variables[x], "notimebreaks"))
display_timebreaks = FALSE;
/* we found the no system messages option */
else if(!strcmp(variables[x], "nosystem"))
display_system_messages = FALSE;
/* we found the no flapping alerts option */
else if(!strcmp(variables[x], "noflapping"))
display_flapping_alerts = FALSE;
/* we found the no downtime alerts option */
else if(!strcmp(variables[x], "nodowntime"))
display_downtime_alerts = FALSE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
void get_history(void) {
mmapfile *thefile = NULL;
char image[MAX_INPUT_BUFFER];
char image_alt[MAX_INPUT_BUFFER];
char *input = NULL;
char *input2 = NULL;
char match1[MAX_INPUT_BUFFER];
char match2[MAX_INPUT_BUFFER];
int found_line = FALSE;
int system_message = FALSE;
int display_line = FALSE;
time_t t;
char date_time[MAX_DATETIME_LENGTH];
char *temp_buffer = NULL;
int history_type = SERVICE_HISTORY;
int history_detail_type = HISTORY_SERVICE_CRITICAL;
char *entry_host_name = NULL;
char *entry_service_desc = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
int result = 0;
char last_message_date[MAX_INPUT_BUFFER] = "";
char current_message_date[MAX_INPUT_BUFFER] = "";
struct tm *time_ptr = NULL;
if(use_lifo == TRUE) {
result = read_file_into_lifo(log_file_to_use);
if(result != LIFO_OK) {
if(result == LIFO_ERROR_MEMORY) {
printf("<P><DIV CLASS='warningMessage'>Not enough memory to reverse log file - displaying history in natural order...</DIV></P>\n");
}
else if(result == LIFO_ERROR_FILE) {
printf("<HR><P><DIV CLASS='errorMessage'>Error: Cannot open log file '%s' for reading!</DIV></P><HR>", log_file_to_use);
return;
}
use_lifo = FALSE;
}
}
if(use_lifo == FALSE) {
if((thefile = mmap_fopen(log_file_to_use)) == NULL) {
printf("<HR><P><DIV CLASS='errorMessage'>Error: Cannot open log file '%s' for reading!</DIV></P><HR>", log_file_to_use);
return;
}
}
printf("<P><DIV CLASS='logEntries'>\n");
while(1) {
my_free(input);
my_free(input2);
if(use_lifo == TRUE) {
if((input = pop_lifo()) == NULL)
break;
}
else {
if((input = mmap_fgets(thefile)) == NULL)
break;
}
strip(input);
strcpy(image, "");
strcpy(image_alt, "");
system_message = FALSE;
if((input2 = (char *)strdup(input)) == NULL)
continue;
/* service state alerts */
if(strstr(input, "SERVICE ALERT:")) {
history_type = SERVICE_HISTORY;
/* get host and service names */
temp_buffer = my_strtok(input2, "]");
temp_buffer = my_strtok(NULL, ":");
temp_buffer = my_strtok(NULL, ";");
if(temp_buffer)
entry_host_name = strdup(temp_buffer + 1);
else
entry_host_name = NULL;
temp_buffer = my_strtok(NULL, ";");
if(temp_buffer)
entry_service_desc = strdup(temp_buffer);
else
entry_service_desc = NULL;
if(strstr(input, ";CRITICAL;")) {
strncpy(image, CRITICAL_ICON, sizeof(image));
strncpy(image_alt, CRITICAL_ICON_ALT, sizeof(image_alt));
history_detail_type = HISTORY_SERVICE_CRITICAL;
}
else if(strstr(input, ";WARNING;")) {
strncpy(image, WARNING_ICON, sizeof(image));
strncpy(image_alt, WARNING_ICON_ALT, sizeof(image_alt));
history_detail_type = HISTORY_SERVICE_WARNING;
}
else if(strstr(input, ";UNKNOWN;")) {
strncpy(image, UNKNOWN_ICON, sizeof(image));
strncpy(image_alt, UNKNOWN_ICON_ALT, sizeof(image_alt));
history_detail_type = HISTORY_SERVICE_UNKNOWN;
}
else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;")) {
strncpy(image, OK_ICON, sizeof(image));
strncpy(image_alt, OK_ICON_ALT, sizeof(image_alt));
history_detail_type = HISTORY_SERVICE_RECOVERY;
}
}
/* service flapping alerts */
else if(strstr(input, "SERVICE FLAPPING ALERT:")) {
if(display_flapping_alerts == FALSE)
continue;
history_type = SERVICE_FLAPPING_HISTORY;
/* get host and service names */
temp_buffer = my_strtok(input2, "]");
temp_buffer = my_strtok(NULL, ":");
temp_buffer = my_strtok(NULL, ";");
if(temp_buffer)
entry_host_name = strdup(temp_buffer + 1);
else
entry_host_name = NULL;
temp_buffer = my_strtok(NULL, ";");
if(temp_buffer)
entry_service_desc = strdup(temp_buffer);
else
entry_service_desc = NULL;
strncpy(image, FLAPPING_ICON, sizeof(image));
if(strstr(input, ";STARTED;"))
strncpy(image_alt, "Service started flapping", sizeof(image_alt));
else if(strstr(input, ";STOPPED;"))
strncpy(image_alt, "Service stopped flapping", sizeof(image_alt));
else if(strstr(input, ";DISABLED;"))
strncpy(image_alt, "Service flap detection disabled", sizeof(image_alt));
}
/* service downtime alerts */
else if(strstr(input, "SERVICE DOWNTIME ALERT:")) {
if(display_downtime_alerts == FALSE)
continue;
history_type = SERVICE_DOWNTIME_HISTORY;
/* get host and service names */
temp_buffer = my_strtok(input2, "]");
temp_buffer = my_strtok(NULL, ":");
temp_buffer = my_strtok(NULL, ";");
if(temp_buffer)
entry_host_name = strdup(temp_buffer + 1);
else
entry_host_name = NULL;
temp_buffer = my_strtok(NULL, ";");
if(temp_buffer)
entry_service_desc = strdup(temp_buffer);
else
entry_service_desc = NULL;
strncpy(image, SCHEDULED_DOWNTIME_ICON, sizeof(image));
if(strstr(input, ";STARTED;"))
strncpy(image_alt, "Service entered a period of scheduled downtime", sizeof(image_alt));
else if(strstr(input, ";STOPPED;"))
strncpy(image_alt, "Service exited from a period of scheduled downtime", sizeof(image_alt));
else if(strstr(input, ";CANCELLED;"))
strncpy(image_alt, "Service scheduled downtime has been cancelled", sizeof(image_alt));
}
/* host state alerts */
else if(strstr(input, "HOST ALERT:")) {
history_type = HOST_HISTORY;
/* get host name */
temp_buffer = my_strtok(input2, "]");
temp_buffer = my_strtok(NULL, ":");
temp_buffer = my_strtok(NULL, ";");
if(temp_buffer)
entry_host_name = strdup(temp_buffer + 1);
else
entry_host_name = NULL;
if(strstr(input, ";DOWN;")) {
strncpy(image, HOST_DOWN_ICON, sizeof(image));
strncpy(image_alt, HOST_DOWN_ICON_ALT, sizeof(image_alt));
history_detail_type = HISTORY_HOST_DOWN;
}
else if(strstr(input, ";UNREACHABLE;")) {
strncpy(image, HOST_UNREACHABLE_ICON, sizeof(image));
strncpy(image_alt, HOST_UNREACHABLE_ICON_ALT, sizeof(image_alt));
history_detail_type = HISTORY_HOST_UNREACHABLE;
}
else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;")) {
strncpy(image, HOST_UP_ICON, sizeof(image));
strncpy(image_alt, HOST_UP_ICON_ALT, sizeof(image_alt));
history_detail_type = HISTORY_HOST_RECOVERY;
}
}
/* host flapping alerts */
else if(strstr(input, "HOST FLAPPING ALERT:")) {
if(display_flapping_alerts == FALSE)
continue;
history_type = HOST_FLAPPING_HISTORY;
/* get host name */
temp_buffer = my_strtok(input2, "]");
temp_buffer = my_strtok(NULL, ":");
temp_buffer = my_strtok(NULL, ";");
if(temp_buffer)
entry_host_name = strdup(temp_buffer + 1);
else
entry_host_name = NULL;
strncpy(image, FLAPPING_ICON, sizeof(image));
if(strstr(input, ";STARTED;"))
strncpy(image_alt, "Host started flapping", sizeof(image_alt));
else if(strstr(input, ";STOPPED;"))
strncpy(image_alt, "Host stopped flapping", sizeof(image_alt));
else if(strstr(input, ";DISABLED;"))
strncpy(image_alt, "Host flap detection disabled", sizeof(image_alt));
}
/* host downtime alerts */
else if(strstr(input, "HOST DOWNTIME ALERT:")) {
if(display_downtime_alerts == FALSE)
continue;
history_type = HOST_DOWNTIME_HISTORY;
/* get host name */
temp_buffer = my_strtok(input2, "]");
temp_buffer = my_strtok(NULL, ":");
temp_buffer = my_strtok(NULL, ";");
if(temp_buffer)
entry_host_name = strdup(temp_buffer + 1);
else
entry_host_name = NULL;
strncpy(image, SCHEDULED_DOWNTIME_ICON, sizeof(image));
if(strstr(input, ";STARTED;"))
strncpy(image_alt, "Host entered a period of scheduled downtime", sizeof(image_alt));
else if(strstr(input, ";STOPPED;"))
strncpy(image_alt, "Host exited from a period of scheduled downtime", sizeof(image_alt));
else if(strstr(input, ";CANCELLED;"))
strncpy(image_alt, "Host scheduled downtime has been cancelled", sizeof(image_alt));
}
else if(display_system_messages == FALSE)
continue;
/* program start */
else if(strstr(input, " starting...")) {
strncpy(image, START_ICON, sizeof(image));
strncpy(image_alt, START_ICON_ALT, sizeof(image_alt));
system_message = TRUE;
}
/* normal program termination */
else if(strstr(input, " shutting down...")) {
strncpy(image, STOP_ICON, sizeof(image));
strncpy(image_alt, STOP_ICON_ALT, sizeof(image_alt));
system_message = TRUE;
}
/* abnormal program termination */
else if(strstr(input, "Bailing out")) {
strncpy(image, STOP_ICON, sizeof(image));
strncpy(image_alt, STOP_ICON_ALT, sizeof(image_alt));
system_message = TRUE;
}
/* program restart */
else if(strstr(input, " restarting...")) {
strncpy(image, RESTART_ICON, sizeof(image));
strncpy(image_alt, RESTART_ICON_ALT, sizeof(image_alt));
system_message = TRUE;
}
image[sizeof(image) - 1] = '\x0';
image_alt[sizeof(image_alt) - 1] = '\x0';
/* get the timestamp */
temp_buffer = strtok(input, "]");
t = (temp_buffer == NULL) ? 0L : strtoul(temp_buffer + 1, NULL, 10);
time_ptr = localtime(&t);
strftime(current_message_date, sizeof(current_message_date), "%B %d, %Y %H:00\n", time_ptr);
current_message_date[sizeof(current_message_date) - 1] = '\x0';
get_time_string(&t, date_time, sizeof(date_time), SHORT_DATE_TIME);
strip(date_time);
temp_buffer = strtok(NULL, "\n");
if(strcmp(image, "")) {
display_line = FALSE;
if(system_message == TRUE)
display_line = TRUE;
else if(display_type == DISPLAY_HOSTS) {
if(history_type == HOST_HISTORY || history_type == SERVICE_HISTORY) {
snprintf(match1, sizeof(match1),
" HOST ALERT: %s;", host_name);
snprintf(match2, sizeof(match2),
" SERVICE ALERT: %s;", host_name);
}
else if(history_type == HOST_FLAPPING_HISTORY || history_type == SERVICE_FLAPPING_HISTORY) {
snprintf(match1, sizeof(match1),
" HOST FLAPPING ALERT: %s;", host_name);
snprintf(match2, sizeof(match2),
" SERVICE FLAPPING ALERT: %s;", host_name);
}
else if(history_type == HOST_DOWNTIME_HISTORY || history_type == SERVICE_DOWNTIME_HISTORY) {
snprintf(match1, sizeof(match1),
" HOST DOWNTIME ALERT: %s;", host_name);
snprintf(match2, sizeof(match2),
" SERVICE DOWNTIME ALERT: %s;", host_name);
}
if(show_all_hosts == TRUE)
display_line = TRUE;
else if(strstr(temp_buffer, match1))
display_line = TRUE;
else if(strstr(temp_buffer, match2))
display_line = TRUE;
if(display_line == TRUE) {
if(history_options == HISTORY_ALL)
display_line = TRUE;
else if(history_options == HISTORY_HOST_ALL && (history_type == HOST_HISTORY || history_type == HOST_FLAPPING_HISTORY || history_type == HOST_DOWNTIME_HISTORY))
display_line = TRUE;
else if(history_options == HISTORY_SERVICE_ALL && (history_type == SERVICE_HISTORY || history_type == SERVICE_FLAPPING_HISTORY || history_type == SERVICE_DOWNTIME_HISTORY))
display_line = TRUE;
else if((history_type == HOST_HISTORY || history_type == SERVICE_HISTORY) && (history_detail_type & history_options))
display_line = TRUE;
else
display_line = FALSE;
}
/* check alert state types */
if(display_line == TRUE && (history_type == HOST_HISTORY || history_type == SERVICE_HISTORY)) {
if(state_options == STATE_ALL)
display_line = TRUE;
else if((state_options & STATE_SOFT) && strstr(temp_buffer, ";SOFT;"))
display_line = TRUE;
else if((state_options & STATE_HARD) && strstr(temp_buffer, ";HARD;"))
display_line = TRUE;
else
display_line = FALSE;
}
}
else if(display_type == DISPLAY_SERVICES) {
if(history_type == SERVICE_HISTORY)
snprintf(match1, sizeof(match1), " SERVICE ALERT: %s;%s;", host_name, svc_description);
else if(history_type == SERVICE_FLAPPING_HISTORY)
snprintf(match1, sizeof(match1), " SERVICE FLAPPING ALERT: %s;%s;", host_name, svc_description);
else if(history_type == SERVICE_DOWNTIME_HISTORY)
snprintf(match1, sizeof(match1), " SERVICE DOWNTIME ALERT: %s;%s;", host_name, svc_description);
if(strstr(temp_buffer, match1) && (history_type == SERVICE_HISTORY || history_type == SERVICE_FLAPPING_HISTORY || history_type == SERVICE_DOWNTIME_HISTORY))
display_line = TRUE;
if(display_line == TRUE) {
if(history_options == HISTORY_ALL || history_options == HISTORY_SERVICE_ALL)
display_line = TRUE;
else if(history_options & history_detail_type)
display_line = TRUE;
else
display_line = FALSE;
}
/* check alert state type */
if(display_line == TRUE && history_type == SERVICE_HISTORY) {
if(state_options == STATE_ALL)
display_line = TRUE;
else if((state_options & STATE_SOFT) && strstr(temp_buffer, ";SOFT;"))
display_line = TRUE;
else if((state_options & STATE_HARD) && strstr(temp_buffer, ";HARD;"))
display_line = TRUE;
else
display_line = FALSE;
}
}
/* make sure user is authorized to view this host or service information */
if(system_message == FALSE) {
if(history_type == HOST_HISTORY || history_type == HOST_FLAPPING_HISTORY || history_type == HOST_DOWNTIME_HISTORY) {
temp_host = find_host(entry_host_name);
if(is_authorized_for_host(temp_host, &current_authdata) == FALSE)
display_line = FALSE;
}
else {
temp_service = find_service(entry_host_name, entry_service_desc);
if(is_authorized_for_service(temp_service, &current_authdata) == FALSE)
display_line = FALSE;
}
}
/* display the entry if we should... */
if(display_line == TRUE) {
if(strcmp(last_message_date, current_message_date) != 0 && display_timebreaks == TRUE) {
printf("</DIV><BR CLEAR='all' />\n");
printf("<DIV CLASS='dateTimeBreak'>\n");
printf("<table border=0 width=95%%><tr>");
printf("<td width=40%%><hr width=100%%></td>");
printf("<td align=center CLASS='dateTimeBreak'>%s</td>", current_message_date);
printf("<td width=40%%><hr width=100%%></td>");
printf("</tr></table>\n");
printf("</DIV>\n");
printf("<BR CLEAR='all' /><DIV CLASS='logEntries'>\n");
strncpy(last_message_date, current_message_date, sizeof(last_message_date));
last_message_date[sizeof(last_message_date) - 1] = '\x0';
}
if(display_frills == TRUE)
printf("<img align='left' src='%s%s' alt='%s' title='%s' />", url_images_path, image, image_alt, image_alt);
printf("[%s] %s", date_time, html_encode(temp_buffer, FALSE));
if(enable_splunk_integration == TRUE) {
printf("&nbsp;&nbsp;&nbsp;");
display_splunk_generic_url(temp_buffer, 2);
}
printf("<br clear='all' />\n");
found_line = TRUE;
}
}
/* free memory */
free(entry_host_name);
entry_host_name = NULL;
free(entry_service_desc);
entry_service_desc = NULL;
}
printf("</DIV></P>\n");
if(found_line == FALSE) {
printf("<HR>\n");
printf("<P><DIV CLASS='warningMessage'>No history information was found ");
if(display_type == DISPLAY_HOSTS)
printf("%s", (show_all_hosts == TRUE) ? "" : "for this host ");
else
printf("for this service ");
printf("in %s log file</DIV></P>", (log_archive == 0) ? "the current" : "this archived");
}
printf("<HR>\n");
my_free(input);
my_free(input2);
if(use_lifo == TRUE)
free_lifo_memory();
else
mmap_fclose(thefile);
return;
}

777
cgi/notifications.c Normal file
View File

@ -0,0 +1,777 @@
/************************************************************************
*
* NOTIFICATIONS.C - Nagios Notifications CGI
*
* Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 01-08-2008
*
* This CGI program will display the notification events for
* a given host or contact or for all contacts/hosts.
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
***********************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/getcgi.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
extern char main_config_file[MAX_FILENAME_LENGTH];
extern char url_html_path[MAX_FILENAME_LENGTH];
extern char url_images_path[MAX_FILENAME_LENGTH];
extern char url_docs_path[MAX_FILENAME_LENGTH];
extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
extern int log_rotation_method;
#define FIND_HOST 1
#define FIND_CONTACT 2
#define FIND_SERVICE 3
#define MAX_QUERYNAME_LENGTH 256
#define SERVICE_NOTIFICATION 0
#define HOST_NOTIFICATION 1
#define SERVICE_NOTIFICATION_STRING "] SERVICE NOTIFICATION:"
#define HOST_NOTIFICATION_STRING "] HOST NOTIFICATION:"
void display_notifications(void);
void document_header(int);
void document_footer(void);
int process_cgivars(void);
authdata current_authdata;
char log_file_to_use[MAX_FILENAME_LENGTH];
int log_archive = 0;
int query_type = FIND_HOST;
int find_all = TRUE;
char *query_contact_name = "";
char *query_host_name = "";
char *query_svc_description = "";
int notification_options = NOTIFICATION_ALL;
int use_lifo = TRUE;
int embedded = FALSE;
int display_header = TRUE;
int main(void) {
int result = OK;
char temp_buffer[MAX_INPUT_BUFFER];
char temp_buffer2[MAX_INPUT_BUFFER];
/* get the arguments passed in the URL */
process_cgivars();
/* reset internal variables */
reset_cgi_vars();
/* read the CGI configuration file */
result = read_cgi_config_file(get_cgi_config_location());
if(result == ERROR) {
document_header(FALSE);
cgi_config_file_error(get_cgi_config_location());
document_footer();
return ERROR;
}
/* read the main configuration file */
result = read_main_config_file(main_config_file);
if(result == ERROR) {
document_header(FALSE);
main_config_file_error(main_config_file);
document_footer();
return ERROR;
}
/* read all object configuration data */
result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
if(result == ERROR) {
document_header(FALSE);
object_data_error();
document_footer();
return ERROR;
}
document_header(TRUE);
/* get authentication information */
get_authentication_information(&current_authdata);
/* determine what log file we should use */
get_log_archive_to_use(log_archive, log_file_to_use, (int)sizeof(log_file_to_use));
if(display_header == TRUE) {
/* begin top table */
printf("<table border=0 width=100%%>\n");
printf("<tr>\n");
/* left column of top row */
printf("<td align=left valign=top width=33%%>\n");
if(query_type == FIND_SERVICE)
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Service Notifications");
else if(query_type == FIND_HOST) {
if(find_all == TRUE)
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Notifications");
else
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host Notifications");
}
else
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Contact Notifications");
display_info_table(temp_buffer, FALSE, &current_authdata);
if(query_type == FIND_HOST || query_type == FIND_SERVICE) {
printf("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 CLASS='linkBox'>\n");
printf("<TR><TD CLASS='linkBox'>\n");
if(query_type == FIND_HOST) {
printf("<A HREF='%s?host=%s'>View Status Detail For %s</A><BR>\n", STATUS_CGI, (find_all == TRUE) ? "all" : url_encode(query_host_name), (find_all == TRUE) ? "All Hosts" : "This Host");
printf("<A HREF='%s?host=%s'>View History For %s</A><BR>\n", HISTORY_CGI, (find_all == TRUE) ? "all" : url_encode(query_host_name), (find_all == TRUE) ? "All Hosts" : "This Host");
#ifdef USE_TRENDS
if(find_all == FALSE)
printf("<A HREF='%s?host=%s'>View Trends For This Host</A><BR>\n", TRENDS_CGI, url_encode(query_host_name));
#endif
}
else if(query_type == FIND_SERVICE) {
printf("<A HREF='%s?host=%s&", HISTORY_CGI, (find_all == TRUE) ? "all" : url_encode(query_host_name));
printf("service=%s'>View History For This Service</A><BR>\n", url_encode(query_svc_description));
#ifdef USE_TRENDS
printf("<A HREF='%s?host=%s&", TRENDS_CGI, (find_all == TRUE) ? "all" : url_encode(query_host_name));
printf("service=%s'>View Trends For This Service</A><BR>\n", url_encode(query_svc_description));
#endif
}
printf("</TD></TR>\n");
printf("</TABLE>\n");
}
printf("</td>\n");
/* middle column of top row */
printf("<td align=center valign=top width=33%%>\n");
printf("<DIV ALIGN=CENTER CLASS='dataTitle'>\n");
if(query_type == FIND_SERVICE)
printf("Service '%s' On Host '%s'", query_svc_description, query_host_name);
else if(query_type == FIND_HOST) {
if(find_all == TRUE)
printf("All Hosts and Services");
else
printf("Host '%s'", query_host_name);
}
else {
if(find_all == TRUE)
printf("All Contacts");
else
printf("Contact '%s'", query_contact_name);
}
printf("</DIV>\n");
printf("<BR>\n");
if(query_type == FIND_SERVICE) {
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s?%shost=%s&", NOTIFICATIONS_CGI, (use_lifo == FALSE) ? "oldestfirst&" : "", url_encode(query_host_name));
snprintf(temp_buffer2, sizeof(temp_buffer2) - 1, "service=%s&type=%d&", url_encode(query_svc_description), notification_options);
strncat(temp_buffer, temp_buffer2, sizeof(temp_buffer) - strlen(temp_buffer) - 1);
}
else
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s?%s%s=%s&type=%d&", NOTIFICATIONS_CGI, (use_lifo == FALSE) ? "oldestfirst&" : "", (query_type == FIND_HOST) ? "host" : "contact", (query_type == FIND_HOST) ? url_encode(query_host_name) : url_encode(query_contact_name), notification_options);
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
display_nav_table(temp_buffer, log_archive);
printf("</td>\n");
/* right hand column of top row */
printf("<td align=right valign=top width=33%%>\n");
printf("<form method='GET' action='%s'>\n", NOTIFICATIONS_CGI);
if(query_type == FIND_SERVICE) {
printf("<input type='hidden' name='host' value='%s'>\n", escape_string(query_host_name));
printf("<input type='hidden' name='service' value='%s'>\n", escape_string(query_svc_description));
}
else
printf("<input type='hidden' name='%s' value='%s'>\n", (query_type == FIND_HOST) ? "host" : "contact", (query_type == FIND_HOST) ? escape_string(query_host_name) : escape_string(query_contact_name));
printf("<input type='hidden' name='archive' value='%d'>\n", log_archive);
printf("<table border=0 CLASS='optBox'>\n");
printf("<tr>\n");
if(query_type == FIND_SERVICE)
printf("<td align=left colspan=2 CLASS='optBoxItem'>Notification detail level for this service:</td>");
else
printf("<td align=left colspan=2 CLASS='optBoxItem'>Notification detail level for %s %s%s:</td>", (find_all == TRUE) ? "all" : "this", (query_type == FIND_HOST) ? "host" : "contact", (find_all == TRUE) ? "s" : "");
printf("</tr>\n");
printf("<tr>\n");
printf("<td align=left colspan=2 CLASS='optBoxItem'><select name='type'>\n");
printf("<option value=%d %s>All notifications\n", NOTIFICATION_ALL, (notification_options == NOTIFICATION_ALL) ? "selected" : "");
if(query_type != FIND_SERVICE) {
printf("<option value=%d %s>All service notifications\n", NOTIFICATION_SERVICE_ALL, (notification_options == NOTIFICATION_SERVICE_ALL) ? "selected" : "");
printf("<option value=%d %s>All host notifications\n", NOTIFICATION_HOST_ALL, (notification_options == NOTIFICATION_HOST_ALL) ? "selected" : "");
}
printf("<option value=%d %s>Service custom\n", NOTIFICATION_SERVICE_CUSTOM, (notification_options == NOTIFICATION_SERVICE_CUSTOM) ? "selected" : "");
printf("<option value=%d %s>Service acknowledgements\n", NOTIFICATION_SERVICE_ACK, (notification_options == NOTIFICATION_SERVICE_ACK) ? "selected" : "");
printf("<option value=%d %s>Service warning\n", NOTIFICATION_SERVICE_WARNING, (notification_options == NOTIFICATION_SERVICE_WARNING) ? "selected" : "");
printf("<option value=%d %s>Service unknown\n", NOTIFICATION_SERVICE_UNKNOWN, (notification_options == NOTIFICATION_SERVICE_UNKNOWN) ? "selected" : "");
printf("<option value=%d %s>Service critical\n", NOTIFICATION_SERVICE_CRITICAL, (notification_options == NOTIFICATION_SERVICE_CRITICAL) ? "selected" : "");
printf("<option value=%d %s>Service recovery\n", NOTIFICATION_SERVICE_RECOVERY, (notification_options == NOTIFICATION_SERVICE_RECOVERY) ? "selected" : "");
printf("<option value=%d %s>Service flapping\n", NOTIFICATION_SERVICE_FLAP, (notification_options == NOTIFICATION_SERVICE_FLAP) ? "selected" : "");
if(query_type != FIND_SERVICE) {
printf("<option value=%d %s>Host custom\n", NOTIFICATION_HOST_CUSTOM, (notification_options == NOTIFICATION_HOST_CUSTOM) ? "selected" : "");
printf("<option value=%d %s>Host acknowledgements\n", NOTIFICATION_HOST_ACK, (notification_options == NOTIFICATION_HOST_ACK) ? "selected" : "");
printf("<option value=%d %s>Host down\n", NOTIFICATION_HOST_DOWN, (notification_options == NOTIFICATION_HOST_DOWN) ? "selected" : "");
printf("<option value=%d %s>Host unreachable\n", NOTIFICATION_HOST_UNREACHABLE, (notification_options == NOTIFICATION_HOST_UNREACHABLE) ? "selected" : "");
printf("<option value=%d %s>Host recovery\n", NOTIFICATION_HOST_RECOVERY, (notification_options == NOTIFICATION_HOST_RECOVERY) ? "selected" : "");
printf("<option value=%d %s>Host flapping\n", NOTIFICATION_HOST_FLAP, (notification_options == NOTIFICATION_HOST_FLAP) ? "selected" : "");
}
printf("</select></td>\n");
printf("</tr>\n");
printf("<tr>\n");
printf("<td align=left CLASS='optBoxItem'>Older Entries First:</td>\n");
printf("<td></td>\n");
printf("</tr>\n");
printf("<tr>\n");
printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='oldestfirst' %s></td>", (use_lifo == FALSE) ? "checked" : "");
printf("<td align=right CLASS='optBoxItem'><input type='submit' value='Update'></td>\n");
printf("</tr>\n");
/* display context-sensitive help */
printf("<tr><td></td><td align=right valign=bottom>\n");
display_context_help(CONTEXTHELP_NOTIFICATIONS);
printf("</td></tr>\n");
printf("</table>\n");
printf("</form>\n");
printf("</td>\n");
/* end of top table */
printf("</tr>\n");
printf("</table>\n");
}
/* display notifications */
display_notifications();
document_footer();
/* free allocated memory */
free_memory();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
time_t expire_time;
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
time(&current_time);
get_time_string(&current_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME);
printf("Last-Modified: %s\r\n", date_time);
expire_time = (time_t)0L;
get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME);
printf("Expires: %s\r\n", date_time);
printf("Content-type: text/html\r\n\r\n");
if(embedded == TRUE)
return;
printf("<html>\n");
printf("<head>\n");
printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
printf("<title>\n");
printf("Alert Notifications\n");
printf("</title>\n");
if(use_stylesheet == TRUE) {
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, NOTIFICATIONS_CSS);
}
printf("</head>\n");
printf("<body CLASS='notifications'>\n");
/* include user SSI header */
include_ssi_files(NOTIFICATIONS_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(NOTIFICATIONS_CGI, SSI_FOOTER);
printf("</body>\n");
printf("</html>\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
for(x = 0; variables[x] != NULL; x++) {
/* do some basic length checking on the variable identifier to prevent buffer overflows */
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
x++;
continue;
}
/* we found the host argument */
else if(!strcmp(variables[x], "host")) {
query_type = FIND_HOST;
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((query_host_name = strdup(variables[x])) == NULL)
query_host_name = "";
strip_html_brackets(query_host_name);
if(!strcmp(query_host_name, "all"))
find_all = TRUE;
else
find_all = FALSE;
}
/* we found the contact argument */
else if(!strcmp(variables[x], "contact")) {
query_type = FIND_CONTACT;
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((query_contact_name = strdup(variables[x])) == NULL)
query_contact_name = "";
strip_html_brackets(query_contact_name);
if(!strcmp(query_contact_name, "all"))
find_all = TRUE;
else
find_all = FALSE;
}
/* we found the service argument */
else if(!strcmp(variables[x], "service")) {
query_type = FIND_SERVICE;
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((query_svc_description = strdup(variables[x])) == NULL)
query_svc_description = "";
strip_html_brackets(query_svc_description);
}
/* we found the notification type argument */
else if(!strcmp(variables[x], "type")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
notification_options = atoi(variables[x]);
}
/* we found the log archive argument */
else if(!strcmp(variables[x], "archive")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
log_archive = atoi(variables[x]);
if(log_archive < 0)
log_archive = 0;
}
/* we found the order argument */
else if(!strcmp(variables[x], "oldestfirst")) {
use_lifo = FALSE;
}
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
/* we found the noheader option */
else if(!strcmp(variables[x], "noheader"))
display_header = FALSE;
}
/*
* Set some default values if not already set.
* Done here as they won't be set if variable
* not provided via cgi parameters
* Only required for hosts & contacts, not services
* as there is no service_name=all option
*/
if(query_type == FIND_HOST && strlen(query_host_name) == 0) {
query_host_name = "all";
find_all = TRUE;
}
if(query_type == FIND_CONTACT && strlen(query_contact_name) == 0) {
query_contact_name = "all";
find_all = TRUE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
void display_notifications(void) {
mmapfile *thefile = NULL;
char *input = NULL;
char *temp_buffer;
char date_time[MAX_DATETIME_LENGTH];
char alert_level[MAX_INPUT_BUFFER];
char alert_level_class[MAX_INPUT_BUFFER];
char contact_name[MAX_INPUT_BUFFER];
char service_name[MAX_INPUT_BUFFER];
char host_name[MAX_INPUT_BUFFER];
char method_name[MAX_INPUT_BUFFER];
int show_entry;
int total_notifications;
int notification_type = SERVICE_NOTIFICATION;
int notification_detail_type = NOTIFICATION_SERVICE_CRITICAL;
int odd = 0;
time_t t;
host *temp_host;
service *temp_service;
int result;
if(use_lifo == TRUE) {
result = read_file_into_lifo(log_file_to_use);
if(result != LIFO_OK) {
if(result == LIFO_ERROR_MEMORY) {
printf("<P><DIV CLASS='warningMessage'>Not enough memory to reverse log file - displaying notifications in natural order...</DIV></P>");
}
else if(result == LIFO_ERROR_FILE) {
printf("<P><DIV CLASS='errorMessage'>Error: Cannot open log file '%s' for reading!</DIV></P>", log_file_to_use);
return;
}
use_lifo = FALSE;
}
}
if(use_lifo == FALSE) {
if((thefile = mmap_fopen(log_file_to_use)) == NULL) {
printf("<P><DIV CLASS='errorMessage'>Error: Cannot open log file '%s' for reading!</DIV></P>", log_file_to_use);
return;
}
}
printf("<p>\n");
printf("<div align='center'>\n");
printf("<table border=0 CLASS='notifications'>\n");
printf("<tr>\n");
printf("<th CLASS='notifications'>Host</th>\n");
printf("<th CLASS='notifications'>Service</th>\n");
printf("<th CLASS='notifications'>Type</th>\n");
printf("<th CLASS='notifications'>Time</th>\n");
printf("<th CLASS='notifications'>Contact</th>\n");
printf("<th CLASS='notifications'>Notification Command</th>\n");
printf("<th CLASS='notifications'>Information</th>\n");
printf("</tr>\n");
total_notifications = 0;
while(1) {
free(input);
if(use_lifo == TRUE) {
if((input = pop_lifo()) == NULL)
break;
}
else {
if((input = mmap_fgets(thefile)) == NULL)
break;
}
strip(input);
/* see if this line contains the notification event string */
if(strstr(input, HOST_NOTIFICATION_STRING) || strstr(input, SERVICE_NOTIFICATION_STRING)) {
if(strstr(input, HOST_NOTIFICATION_STRING))
notification_type = HOST_NOTIFICATION;
else
notification_type = SERVICE_NOTIFICATION;
/* get the date/time */
temp_buffer = (char *)strtok(input, "]");
t = (time_t)(temp_buffer == NULL) ? 0L : strtoul(temp_buffer + 1, NULL, 10);
get_time_string(&t, date_time, (int)sizeof(date_time), SHORT_DATE_TIME);
strip(date_time);
/* get the contact name */
temp_buffer = (char *)strtok(NULL, ":");
temp_buffer = (char *)strtok(NULL, ";");
snprintf(contact_name, sizeof(contact_name), "%s", (temp_buffer == NULL) ? "" : temp_buffer + 1);
contact_name[sizeof(contact_name) - 1] = '\x0';
/* get the host name */
temp_buffer = (char *)strtok(NULL, ";");
snprintf(host_name, sizeof(host_name), "%s", (temp_buffer == NULL) ? "" : temp_buffer);
host_name[sizeof(host_name) - 1] = '\x0';
/* get the service name */
if(notification_type == SERVICE_NOTIFICATION) {
temp_buffer = (char *)strtok(NULL, ";");
snprintf(service_name, sizeof(service_name), "%s", (temp_buffer == NULL) ? "" : temp_buffer);
service_name[sizeof(service_name) - 1] = '\x0';
}
/* get the alert level */
temp_buffer = (char *)strtok(NULL, ";");
snprintf(alert_level, sizeof(alert_level), "%s", (temp_buffer == NULL) ? "" : temp_buffer);
alert_level[sizeof(alert_level) - 1] = '\x0';
if(notification_type == SERVICE_NOTIFICATION) {
if(!strcmp(alert_level, "CRITICAL")) {
notification_detail_type = NOTIFICATION_SERVICE_CRITICAL;
strcpy(alert_level_class, "CRITICAL");
}
else if(!strcmp(alert_level, "WARNING")) {
notification_detail_type = NOTIFICATION_SERVICE_WARNING;
strcpy(alert_level_class, "WARNING");
}
else if(!strcmp(alert_level, "RECOVERY") || !strcmp(alert_level, "OK")) {
strcpy(alert_level, "OK");
notification_detail_type = NOTIFICATION_SERVICE_RECOVERY;
strcpy(alert_level_class, "OK");
}
else if(strstr(alert_level, "CUSTOM (")) {
notification_detail_type = NOTIFICATION_SERVICE_CUSTOM;
strcpy(alert_level_class, "CUSTOM");
}
else if(strstr(alert_level, "ACKNOWLEDGEMENT (")) {
notification_detail_type = NOTIFICATION_SERVICE_ACK;
strcpy(alert_level_class, "ACKNOWLEDGEMENT");
}
else if(strstr(alert_level, "FLAPPINGSTART (")) {
strcpy(alert_level, "FLAPPING START");
notification_detail_type = NOTIFICATION_SERVICE_FLAP;
strcpy(alert_level_class, "UNKNOWN");
}
else if(strstr(alert_level, "FLAPPINGSTOP (")) {
strcpy(alert_level, "FLAPPING STOP");
notification_detail_type = NOTIFICATION_SERVICE_FLAP;
strcpy(alert_level_class, "UNKNOWN");
}
else {
strcpy(alert_level, "UNKNOWN");
notification_detail_type = NOTIFICATION_SERVICE_UNKNOWN;
strcpy(alert_level_class, "UNKNOWN");
}
}
else {
if(!strcmp(alert_level, "DOWN")) {
strncpy(alert_level, "HOST DOWN", sizeof(alert_level));
strcpy(alert_level_class, "HOSTDOWN");
notification_detail_type = NOTIFICATION_HOST_DOWN;
}
else if(!strcmp(alert_level, "UNREACHABLE")) {
strncpy(alert_level, "HOST UNREACHABLE", sizeof(alert_level));
strcpy(alert_level_class, "HOSTUNREACHABLE");
notification_detail_type = NOTIFICATION_HOST_UNREACHABLE;
}
else if(!strcmp(alert_level, "RECOVERY") || !strcmp(alert_level, "UP")) {
strncpy(alert_level, "HOST UP", sizeof(alert_level));
strcpy(alert_level_class, "HOSTUP");
notification_detail_type = NOTIFICATION_HOST_RECOVERY;
}
else if(strstr(alert_level, "CUSTOM (")) {
strcpy(alert_level_class, "HOSTCUSTOM");
notification_detail_type = NOTIFICATION_HOST_CUSTOM;
}
else if(strstr(alert_level, "ACKNOWLEDGEMENT (")) {
strcpy(alert_level_class, "HOSTACKNOWLEDGEMENT");
notification_detail_type = NOTIFICATION_HOST_ACK;
}
else if(strstr(alert_level, "FLAPPINGSTART (")) {
strcpy(alert_level, "FLAPPING START");
strcpy(alert_level_class, "UNKNOWN");
notification_detail_type = NOTIFICATION_HOST_FLAP;
}
else if(strstr(alert_level, "FLAPPINGSTOP (")) {
strcpy(alert_level, "FLAPPING STOP");
strcpy(alert_level_class, "UNKNOWN");
notification_detail_type = NOTIFICATION_HOST_FLAP;
}
}
/* get the method name */
temp_buffer = (char *)strtok(NULL, ";");
snprintf(method_name, sizeof(method_name), "%s", (temp_buffer == NULL) ? "" : temp_buffer);
method_name[sizeof(method_name) - 1] = '\x0';
/* move to the informational message */
temp_buffer = strtok(NULL, ";");
show_entry = FALSE;
/* if we're searching by contact, filter out unwanted contact */
if(query_type == FIND_CONTACT) {
if(find_all == TRUE)
show_entry = TRUE;
else if(!strcmp(query_contact_name, contact_name))
show_entry = TRUE;
}
else if(query_type == FIND_HOST) {
if(find_all == TRUE)
show_entry = TRUE;
else if(!strcmp(query_host_name, host_name))
show_entry = TRUE;
}
else if(query_type == FIND_SERVICE) {
if(!strcmp(query_host_name, host_name) && !strcmp(query_svc_description, service_name))
show_entry = TRUE;
}
if(show_entry == TRUE) {
if(notification_options == NOTIFICATION_ALL)
show_entry = TRUE;
else if(notification_options == NOTIFICATION_HOST_ALL && notification_type == HOST_NOTIFICATION)
show_entry = TRUE;
else if(notification_options == NOTIFICATION_SERVICE_ALL && notification_type == SERVICE_NOTIFICATION)
show_entry = TRUE;
else if(notification_detail_type & notification_options)
show_entry = TRUE;
else
show_entry = FALSE;
}
/* make sure user has authorization to view this notification */
if(notification_type == HOST_NOTIFICATION) {
temp_host = find_host(host_name);
if(is_authorized_for_host(temp_host, &current_authdata) == FALSE)
show_entry = FALSE;
}
else {
temp_service = find_service(host_name, service_name);
if(is_authorized_for_service(temp_service, &current_authdata) == FALSE)
show_entry = FALSE;
}
if(show_entry == TRUE) {
total_notifications++;
if(odd) {
odd = 0;
printf("<tr CLASS='notificationsOdd'>\n");
}
else {
odd = 1;
printf("<tr CLASS='notificationsEven'>\n");
}
printf("<td CLASS='notifications%s'><a href='%s?type=%d&host=%s'>%s</a></td>\n", (odd) ? "Even" : "Odd", EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(host_name), host_name);
if(notification_type == SERVICE_NOTIFICATION) {
printf("<td CLASS='notifications%s'><a href='%s?type=%d&host=%s", (odd) ? "Even" : "Odd", EXTINFO_CGI, DISPLAY_SERVICE_INFO, url_encode(host_name));
printf("&service=%s'>%s</a></td>\n", url_encode(service_name), service_name);
}
else
printf("<td CLASS='notifications%s'>N/A</td>\n", (odd) ? "Even" : "Odd");
printf("<td CLASS='notifications%s'>%s</td>\n", alert_level_class, alert_level);
printf("<td CLASS='notifications%s'>%s</td>\n", (odd) ? "Even" : "Odd", date_time);
printf("<td CLASS='notifications%s'><a href='%s?type=contacts#%s'>%s</a></td>\n", (odd) ? "Even" : "Odd", CONFIG_CGI, url_encode(contact_name), contact_name);
printf("<td CLASS='notifications%s'><a href='%s?type=commands#%s'>%s</a></td>\n", (odd) ? "Even" : "Odd", CONFIG_CGI, url_encode(method_name), method_name);
printf("<td CLASS='notifications%s'>%s</td>\n", (odd) ? "Even" : "Odd", html_encode(temp_buffer, FALSE));
printf("</tr>\n");
}
}
}
printf("</table>\n");
printf("</div>\n");
printf("</p>\n");
if(total_notifications == 0) {
printf("<P><DIV CLASS='errorMessage'>No notifications have been recorded");
if(find_all == FALSE) {
if(query_type == FIND_SERVICE)
printf(" for this service");
else if(query_type == FIND_CONTACT)
printf(" for this contact");
else
printf(" for this host");
}
printf(" in %s log file</DIV></P>", (log_archive == 0) ? "the current" : "this archived");
}
free(input);
if(use_lifo == TRUE)
free_lifo_memory();
else
mmap_fclose(thefile);
return;
}

697
cgi/outages.c Normal file
View File

@ -0,0 +1,697 @@
/**************************************************************************
*
* OUTAGES.C - Nagios Network Outages CGI
*
* Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 01-08-2008
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/comments.h"
#include "../include/statusdata.h"
#include "../include/cgiutils.h"
#include "../include/getcgi.h"
#include "../include/cgiauth.h"
extern int refresh_rate;
extern time_t program_start;
extern host *host_list;
extern service *service_list;
extern hoststatus *hoststatus_list;
extern servicestatus *servicestatus_list;
extern char main_config_file[MAX_FILENAME_LENGTH];
extern char url_html_path[MAX_FILENAME_LENGTH];
extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
extern char url_images_path[MAX_FILENAME_LENGTH];
extern char url_logo_images_path[MAX_FILENAME_LENGTH];
extern char log_file[MAX_FILENAME_LENGTH];
/* HOSTOUTAGE structure */
typedef struct hostoutage_struct {
host *hst;
int severity;
int affected_child_hosts;
int affected_child_services;
unsigned long monitored_time;
unsigned long time_up;
float percent_time_up;
unsigned long time_down;
float percent_time_down;
unsigned long time_unreachable;
float percent_time_unreachable;
struct hostoutage_struct *next;
} hostoutage;
/* HOSTOUTAGESORT structure */
typedef struct hostoutagesort_struct {
hostoutage *outage;
struct hostoutagesort_struct *next;
} hostoutagesort;
void document_header(int);
void document_footer(void);
int process_cgivars(void);
void display_network_outages(void);
void find_hosts_causing_outages(void);
void calculate_outage_effects(void);
void calculate_outage_effect_of_host(host *, int *, int *);
int is_route_to_host_blocked(host *);
int number_of_host_services(host *);
void add_hostoutage(host *);
void sort_hostoutages(void);
void free_hostoutage_list(void);
void free_hostoutagesort_list(void);
authdata current_authdata;
hostoutage *hostoutage_list = NULL;
hostoutagesort *hostoutagesort_list = NULL;
int service_severity_divisor = 4; /* default = services are 1/4 as important as hosts */
int embedded = FALSE;
int display_header = TRUE;
int main(void) {
int result = OK;
/* get the arguments passed in the URL */
process_cgivars();
/* reset internal variables */
reset_cgi_vars();
/* read the CGI configuration file */
result = read_cgi_config_file(get_cgi_config_location());
if(result == ERROR) {
document_header(FALSE);
cgi_config_file_error(get_cgi_config_location());
document_footer();
return ERROR;
}
/* read the main configuration file */
result = read_main_config_file(main_config_file);
if(result == ERROR) {
document_header(FALSE);
main_config_file_error(main_config_file);
document_footer();
return ERROR;
}
/* read all object configuration data */
result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
if(result == ERROR) {
document_header(FALSE);
object_data_error();
document_footer();
return ERROR;
}
/* read all status data */
result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA);
if(result == ERROR) {
document_header(FALSE);
status_data_error();
document_footer();
free_memory();
return ERROR;
}
document_header(TRUE);
/* get authentication information */
get_authentication_information(&current_authdata);
if(display_header == TRUE) {
/* begin top table */
printf("<table border=0 width=100%%>\n");
printf("<tr>\n");
/* left column of the first row */
printf("<td align=left valign=top width=33%%>\n");
display_info_table("Network Outages", TRUE, &current_authdata);
printf("</td>\n");
/* middle column of top row */
printf("<td align=center valign=top width=33%%>\n");
printf("</td>\n");
/* right column of top row */
printf("<td align=right valign=bottom width=33%%>\n");
/* display context-sensitive help */
display_context_help(CONTEXTHELP_OUTAGES);
printf("</td>\n");
/* end of top table */
printf("</tr>\n");
printf("</table>\n");
}
/* display network outage info */
display_network_outages();
document_footer();
/* free memory allocated to comment data */
free_comment_data();
/* free all allocated memory */
free_memory();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
time_t expire_time;
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
printf("Refresh: %d\r\n", refresh_rate);
time(&current_time);
get_time_string(&current_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME);
printf("Last-Modified: %s\r\n", date_time);
expire_time = (time_t)0L;
get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME);
printf("Expires: %s\r\n", date_time);
printf("Content-type: text/html\r\n\r\n");
if(embedded == TRUE)
return;
printf("<html>\n");
printf("<head>\n");
printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
printf("<title>\n");
printf("Network Outages\n");
printf("</title>\n");
if(use_stylesheet == TRUE) {
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>", url_stylesheets_path, COMMON_CSS);
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>", url_stylesheets_path, OUTAGES_CSS);
}
printf("</head>\n");
printf("<body CLASS='outages'>\n");
/* include user SSI header */
include_ssi_files(OUTAGES_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(OUTAGES_CGI, SSI_FOOTER);
printf("</body>\n");
printf("</html>\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
for(x = 0; variables[x] != NULL; x++) {
/* do some basic length checking on the variable identifier to prevent buffer overflows */
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
x++;
continue;
}
/* we found the service severity divisor option */
if(!strcmp(variables[x], "service_divisor")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
service_severity_divisor = atoi(variables[x]);
if(service_severity_divisor < 1)
service_severity_divisor = 1;
}
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
/* we found the noheader option */
else if(!strcmp(variables[x], "noheader"))
display_header = FALSE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
/* shows all hosts that are causing network outages */
void display_network_outages(void) {
char temp_buffer[MAX_INPUT_BUFFER];
int number_of_problem_hosts = 0;
int number_of_blocking_problem_hosts = 0;
hostoutagesort *temp_hostoutagesort;
hostoutage *temp_hostoutage;
hoststatus *temp_hoststatus;
int odd = 0;
char *bg_class = "";
char *status = "";
int days;
int hours;
int minutes;
int seconds;
int total_comments;
time_t t;
time_t current_time;
char state_duration[48];
int total_entries = 0;
/* user must be authorized for all hosts.. */
if(is_authorized_for_all_hosts(&current_authdata) == FALSE) {
printf("<P><DIV CLASS='errorMessage'>It appears as though you do not have permission to view information you requested...</DIV></P>\n");
printf("<P><DIV CLASS='errorDescription'>If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI<br>");
printf("and check the authorization options in your CGI configuration file.</DIV></P>\n");
return;
}
/* find all hosts that are causing network outages */
find_hosts_causing_outages();
/* calculate outage effects */
calculate_outage_effects();
/* sort the outage list by severity */
sort_hostoutages();
/* count the number of top-level hosts that are down and the ones that are actually blocking children hosts */
for(temp_hostoutage = hostoutage_list; temp_hostoutage != NULL; temp_hostoutage = temp_hostoutage->next) {
number_of_problem_hosts++;
if(temp_hostoutage->affected_child_hosts > 1)
number_of_blocking_problem_hosts++;
}
/* display the problem hosts... */
printf("<P><DIV ALIGN=CENTER>\n");
printf("<DIV CLASS='dataTitle'>Blocking Outages</DIV>\n");
printf("<TABLE BORDER=0 CLASS='data'>\n");
printf("<TR>\n");
printf("<TH CLASS='data'>Severity</TH><TH CLASS='data'>Host</TH><TH CLASS='data'>State</TH><TH CLASS='data'>Notes</TH><TH CLASS='data'>State Duration</TH><TH CLASS='data'># Hosts Affected</TH><TH CLASS='data'># Services Affected</TH><TH CLASS='data'>Actions</TH>\n");
printf("</TR>\n");
for(temp_hostoutagesort = hostoutagesort_list; temp_hostoutagesort != NULL; temp_hostoutagesort = temp_hostoutagesort->next) {
temp_hostoutage = temp_hostoutagesort->outage;
if(temp_hostoutage == NULL)
continue;
/* skip hosts that are not blocking anyone */
if(temp_hostoutage->affected_child_hosts <= 1)
continue;
temp_hoststatus = find_hoststatus(temp_hostoutage->hst->name);
if(temp_hoststatus == NULL)
continue;
/* make sure we only caught valid state types */
if(temp_hoststatus->status != HOST_DOWN && temp_hoststatus->status != HOST_UNREACHABLE)
continue;
total_entries++;
if(odd == 0) {
odd = 1;
bg_class = "dataOdd";
}
else {
odd = 0;
bg_class = "dataEven";
}
if(temp_hoststatus->status == HOST_UNREACHABLE)
status = "UNREACHABLE";
else if(temp_hoststatus->status == HOST_DOWN)
status = "DOWN";
printf("<TR CLASS='%s'>\n", bg_class);
printf("<TD CLASS='%s'>%d</TD>\n", bg_class, temp_hostoutage->severity);
printf("<TD CLASS='%s'><A HREF='%s?type=%d&host=%s'>%s</A></TD>\n", bg_class, EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(temp_hostoutage->hst->name), temp_hostoutage->hst->name);
printf("<TD CLASS='host%s'>%s</TD>\n", status, status);
total_comments = number_of_host_comments(temp_hostoutage->hst->name);
if(total_comments > 0) {
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "This host has %d comment%s associated with it", total_comments, (total_comments == 1) ? "" : "s");
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
printf("<TD CLASS='%s'><A HREF='%s?type=%d&host=%s#comments'><IMG SRC='%s%s' BORDER=0 ALT='%s' TITLE='%s'></A></TD>\n", bg_class, EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(temp_hostoutage->hst->name), url_images_path, COMMENT_ICON, temp_buffer, temp_buffer);
}
else
printf("<TD CLASS='%s'>N/A</TD>\n", bg_class);
current_time = time(NULL);
if(temp_hoststatus->last_state_change == (time_t)0)
t = current_time - program_start;
else
t = current_time - temp_hoststatus->last_state_change;
get_time_breakdown((unsigned long)t, &days, &hours, &minutes, &seconds);
snprintf(state_duration, sizeof(state_duration) - 1, "%2dd %2dh %2dm %2ds%s", days, hours, minutes, seconds, (temp_hoststatus->last_state_change == (time_t)0) ? "+" : "");
state_duration[sizeof(state_duration) - 1] = '\x0';
printf("<TD CLASS='%s'>%s</TD>\n", bg_class, state_duration);
printf("<TD CLASS='%s'>%d</TD>\n", bg_class, temp_hostoutage->affected_child_hosts);
printf("<TD CLASS='%s'>%d</TD>\n", bg_class, temp_hostoutage->affected_child_services);
printf("<TD CLASS='%s'>", bg_class);
printf("<A HREF='%s?host=%s'><IMG SRC='%s%s' BORDER=0 ALT='View status detail for this host' TITLE='View status detail for this host'></A>\n", STATUS_CGI, url_encode(temp_hostoutage->hst->name), url_images_path, STATUS_DETAIL_ICON);
#ifdef USE_STATUSMAP
printf("<A HREF='%s?host=%s'><IMG SRC='%s%s' BORDER=0 ALT='View status map for this host and its children' TITLE='View status map for this host and its children'></A>\n", STATUSMAP_CGI, url_encode(temp_hostoutage->hst->name), url_images_path, STATUSMAP_ICON);
#endif
#ifdef USE_STATUSWRL
printf("<A HREF='%s?host=%s'><IMG SRC='%s%s' BORDER=0 ALT='View 3-D status map for this host and its children' TITLE='View 3-D status map for this host and its children'></A>\n", STATUSWORLD_CGI, url_encode(temp_hostoutage->hst->name), url_images_path, STATUSWORLD_ICON);
#endif
#ifdef USE_TRENDS
printf("<A HREF='%s?host=%s'><IMG SRC='%s%s' BORDER=0 ALT='View trends for this host' TITLE='View trends for this host'></A>\n", TRENDS_CGI, url_encode(temp_hostoutage->hst->name), url_images_path, TRENDS_ICON);
#endif
printf("<A HREF='%s?host=%s'><IMG SRC='%s%s' BORDER=0 ALT='View alert history for this host' TITLE='View alert history for this host'></A>\n", HISTORY_CGI, url_encode(temp_hostoutage->hst->name), url_images_path, HISTORY_ICON);
printf("<A HREF='%s?host=%s'><IMG SRC='%s%s' BORDER=0 ALT='View notifications for this host' TITLE='View notifications for this host'></A>\n", NOTIFICATIONS_CGI, url_encode(temp_hostoutage->hst->name), url_images_path, NOTIFICATION_ICON);
printf("</TD>\n");
printf("</TR>\n");
}
printf("</TABLE>\n");
printf("</DIV></P>\n");
if(total_entries == 0)
printf("<DIV CLASS='itemTotalsTitle'>%d Blocking Outages Displayed</DIV>\n", total_entries);
/* free memory allocated to the host outage list */
free_hostoutage_list();
free_hostoutagesort_list();
return;
}
/* determine what hosts are causing network outages */
void find_hosts_causing_outages(void) {
hoststatus *temp_hoststatus;
host *temp_host;
/* check all hosts */
for(temp_hoststatus = hoststatus_list; temp_hoststatus != NULL; temp_hoststatus = temp_hoststatus->next) {
/* check only hosts that are not up and not pending */
if(temp_hoststatus->status != HOST_UP && temp_hoststatus->status != HOST_PENDING) {
/* find the host entry */
temp_host = find_host(temp_hoststatus->host_name);
if(temp_host == NULL)
continue;
/* if the route to this host is not blocked, it is a causing an outage */
if(is_route_to_host_blocked(temp_host) == FALSE)
add_hostoutage(temp_host);
}
}
return;
}
/* adds a host outage entry */
void add_hostoutage(host *hst) {
hostoutage *new_hostoutage;
/* allocate memory for a new structure */
new_hostoutage = (hostoutage *)malloc(sizeof(hostoutage));
if(new_hostoutage == NULL)
return;
new_hostoutage->hst = hst;
new_hostoutage->severity = 0;
new_hostoutage->affected_child_hosts = 0;
new_hostoutage->affected_child_services = 0;
/* add the structure to the head of the list in memory */
new_hostoutage->next = hostoutage_list;
hostoutage_list = new_hostoutage;
return;
}
/* frees all memory allocated to the host outage list */
void free_hostoutage_list(void) {
hostoutage *this_hostoutage;
hostoutage *next_hostoutage;
/* free all list members */
for(this_hostoutage = hostoutage_list; this_hostoutage != NULL; this_hostoutage = next_hostoutage) {
next_hostoutage = this_hostoutage->next;
free(this_hostoutage);
}
/* reset list pointer */
hostoutage_list = NULL;
return;
}
/* frees all memory allocated to the host outage sort list */
void free_hostoutagesort_list(void) {
hostoutagesort *this_hostoutagesort;
hostoutagesort *next_hostoutagesort;
/* free all list members */
for(this_hostoutagesort = hostoutagesort_list; this_hostoutagesort != NULL; this_hostoutagesort = next_hostoutagesort) {
next_hostoutagesort = this_hostoutagesort->next;
free(this_hostoutagesort);
}
/* reset list pointer */
hostoutagesort_list = NULL;
return;
}
/* calculates network outage effect of all hosts that are causing blockages */
void calculate_outage_effects(void) {
hostoutage *temp_hostoutage;
/* check all hosts causing problems */
for(temp_hostoutage = hostoutage_list; temp_hostoutage != NULL; temp_hostoutage = temp_hostoutage->next) {
/* calculate the outage effect of this particular hosts */
calculate_outage_effect_of_host(temp_hostoutage->hst, &temp_hostoutage->affected_child_hosts, &temp_hostoutage->affected_child_services);
temp_hostoutage->severity = (temp_hostoutage->affected_child_hosts + (temp_hostoutage->affected_child_services / service_severity_divisor));
}
return;
}
/* calculates network outage effect of a particular host being down or unreachable */
void calculate_outage_effect_of_host(host *hst, int *affected_hosts, int *affected_services) {
int total_child_hosts_affected = 0;
int total_child_services_affected = 0;
int temp_child_hosts_affected = 0;
int temp_child_services_affected = 0;
host *temp_host;
/* find all child hosts of this host */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
/* skip this host if it is not a child */
if(is_host_immediate_child_of_host(hst, temp_host) == FALSE)
continue;
/* calculate the outage effect of the child */
calculate_outage_effect_of_host(temp_host, &temp_child_hosts_affected, &temp_child_services_affected);
/* keep a running total of outage effects */
total_child_hosts_affected += temp_child_hosts_affected;
total_child_services_affected += temp_child_services_affected;
}
*affected_hosts = total_child_hosts_affected + 1;
*affected_services = total_child_services_affected + number_of_host_services(hst);
return;
}
/* tests whether or not a host is "blocked" by upstream parents (host is already assumed to be down or unreachable) */
int is_route_to_host_blocked(host *hst) {
hostsmember *temp_hostsmember;
hoststatus *temp_hoststatus;
/* if the host has no parents, it is not being blocked by anyone */
if(hst->parent_hosts == NULL)
return FALSE;
/* check all parent hosts */
for(temp_hostsmember = hst->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
/* find the parent host's status */
temp_hoststatus = find_hoststatus(temp_hostsmember->host_name);
if(temp_hoststatus == NULL)
continue;
/* at least one parent it up (or pending), so this host is not blocked */
if(temp_hoststatus->status == HOST_UP || temp_hoststatus->status == HOST_PENDING)
return FALSE;
}
return TRUE;
}
/* calculates the number of services associated a particular host */
int number_of_host_services(host *hst) {
int total_services = 0;
service *temp_service;
/* check all services */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
if(!strcmp(temp_service->host_name, hst->name))
total_services++;
}
return total_services;
}
/* sort the host outages by severity */
void sort_hostoutages(void) {
hostoutagesort *last_hostoutagesort;
hostoutagesort *new_hostoutagesort;
hostoutagesort *temp_hostoutagesort;
hostoutage *temp_hostoutage;
if(hostoutage_list == NULL)
return;
/* sort all host outage entries */
for(temp_hostoutage = hostoutage_list; temp_hostoutage != NULL; temp_hostoutage = temp_hostoutage->next) {
/* allocate memory for a new sort structure */
new_hostoutagesort = (hostoutagesort *)malloc(sizeof(hostoutagesort));
if(new_hostoutagesort == NULL)
return;
new_hostoutagesort->outage = temp_hostoutage;
last_hostoutagesort = hostoutagesort_list;
for(temp_hostoutagesort = hostoutagesort_list; temp_hostoutagesort != NULL; temp_hostoutagesort = temp_hostoutagesort->next) {
if(new_hostoutagesort->outage->severity >= temp_hostoutagesort->outage->severity) {
new_hostoutagesort->next = temp_hostoutagesort;
if(temp_hostoutagesort == hostoutagesort_list)
hostoutagesort_list = new_hostoutagesort;
else
last_hostoutagesort->next = new_hostoutagesort;
break;
}
else
last_hostoutagesort = temp_hostoutagesort;
}
if(hostoutagesort_list == NULL) {
new_hostoutagesort->next = NULL;
hostoutagesort_list = new_hostoutagesort;
}
else if(temp_hostoutagesort == NULL) {
new_hostoutagesort->next = NULL;
last_hostoutagesort->next = new_hostoutagesort;
}
}
return;
}

550
cgi/showlog.c Normal file
View File

@ -0,0 +1,550 @@
/***********************************************************************
*
* SHOWLOG.C - Nagios Log File CGI
*
* Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 01-08-2008
*
* This CGI program will display the contents of the Nagios
* log file.
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
***********************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/getcgi.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
extern char main_config_file[MAX_FILENAME_LENGTH];
extern char url_html_path[MAX_FILENAME_LENGTH];
extern char url_images_path[MAX_FILENAME_LENGTH];
extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
extern int log_rotation_method;
extern int enable_splunk_integration;
void document_header(int);
void document_footer(void);
int process_cgivars(void);
authdata current_authdata;
int display_log(void);
char log_file_to_use[MAX_FILENAME_LENGTH] = "";
int log_archive = 0;
int use_lifo = TRUE;
int embedded = FALSE;
int display_header = TRUE;
int display_frills = TRUE;
int display_timebreaks = TRUE;
int main(void) {
int result = OK;
char temp_buffer[MAX_INPUT_BUFFER];
/* get the CGI variables passed in the URL */
process_cgivars();
/* reset internal variables */
reset_cgi_vars();
/* read the CGI configuration file */
result = read_cgi_config_file(get_cgi_config_location());
if(result == ERROR) {
document_header(FALSE);
cgi_config_file_error(get_cgi_config_location());
document_footer();
return ERROR;
}
/* read the main configuration file */
result = read_main_config_file(main_config_file);
if(result == ERROR) {
document_header(FALSE);
main_config_file_error(main_config_file);
document_footer();
return ERROR;
}
/* read all object configuration data */
result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
if(result == ERROR) {
document_header(FALSE);
object_data_error();
document_footer();
return ERROR;
}
document_header(TRUE);
/* get authentication information */
get_authentication_information(&current_authdata);
/* determine what log file we should be using */
get_log_archive_to_use(log_archive, log_file_to_use, (int)sizeof(log_file_to_use));
if(display_header == TRUE) {
/* begin top table */
printf("<table border=0 width=100%% cellpadding=0 cellspacing=0>\n");
printf("<tr>\n");
/* left column of top table - info box */
printf("<td align=left valign=top width=33%%>\n");
display_info_table((log_rotation_method == LOG_ROTATION_NONE || log_archive == 0) ? "Current Event Log" : "Archived Event Log", FALSE, &current_authdata);
printf("</td>\n");
/* middle column of top table - log file navigation options */
printf("<td align=center valign=top width=33%%>\n");
snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s?%s", SHOWLOG_CGI, (use_lifo == FALSE) ? "oldestfirst&" : "");
temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
display_nav_table(temp_buffer, log_archive);
printf("</td>\n");
/* right hand column of top row */
printf("<td align=right valign=top width=33%%>\n");
printf("<form method='GET' action='%s'>\n", SHOWLOG_CGI);
printf("<input type='hidden' name='archive' value='%d'>\n", log_archive);
printf("<table border=0 cellspacing=0 cellpadding=0 CLASS='optBox'>\n");
printf("<tr>");
printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='checkbox' name='oldestfirst' %s> Older Entries First:</td>", (use_lifo == FALSE) ? "checked" : "");
printf("</tr>\n");
printf("<tr>");
printf("<td align=left valign=bottom CLASS='optBoxItem'><input type='submit' value='Update'></td>\n");
printf("</tr>\n");
/* display context-sensitive help */
printf("<tr>\n");
printf("<td align=right>\n");
display_context_help(CONTEXTHELP_LOG);
printf("</td>\n");
printf("</tr>\n");
printf("</table>\n");
printf("</form>\n");
printf("</td>\n");
/* end of top table */
printf("</tr>\n");
printf("</table>\n");
printf("</p>\n");
}
/* display the contents of the log file */
display_log();
document_footer();
/* free allocated memory */
free_memory();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
time_t expire_time;
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
time(&current_time);
get_time_string(&current_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME);
printf("Last-Modified: %s\r\n", date_time);
expire_time = (time_t)0L;
get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME);
printf("Expires: %s\r\n", date_time);
printf("Content-type: text/html\r\n\r\n");
if(embedded == TRUE)
return;
printf("<HTML>\n");
printf("<HEAD>\n");
printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
printf("<TITLE>\n");
printf("Nagios Log File\n");
printf("</TITLE>\n");
if(use_stylesheet == TRUE) {
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, SHOWLOG_CSS);
}
printf("</HEAD>\n");
printf("<BODY CLASS='showlog'>\n");
/* include user SSI header */
include_ssi_files(SHOWLOG_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(SHOWLOG_CGI, SSI_FOOTER);
printf("</BODY>\n");
printf("</HTML>\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
for(x = 0; variables[x] != NULL; x++) {
/* do some basic length checking on the variable identifier to prevent buffer overflows */
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
continue;
}
/* we found the archive argument */
else if(!strcmp(variables[x], "archive")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
log_archive = atoi(variables[x]);
if(log_archive < 0)
log_archive = 0;
}
/* we found the order argument */
else if(!strcmp(variables[x], "oldestfirst")) {
use_lifo = FALSE;
}
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
/* we found the noheader option */
else if(!strcmp(variables[x], "noheader"))
display_header = FALSE;
/* we found the nofrills option */
else if(!strcmp(variables[x], "nofrills"))
display_frills = FALSE;
/* we found the notimebreaks option */
else if(!strcmp(variables[x], "notimebreaks"))
display_timebreaks = FALSE;
/* we received an invalid argument */
else
error = TRUE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
/* display the contents of the log file */
int display_log(void) {
char *input = NULL;
char image[MAX_INPUT_BUFFER];
char image_alt[MAX_INPUT_BUFFER];
time_t t;
char *temp_buffer = NULL;
char date_time[MAX_DATETIME_LENGTH];
int error = FALSE;
mmapfile *thefile = NULL;
char last_message_date[MAX_INPUT_BUFFER] = "";
char current_message_date[MAX_INPUT_BUFFER] = "";
struct tm *time_ptr = NULL;
/* check to see if the user is authorized to view the log file */
if(is_authorized_for_system_information(&current_authdata) == FALSE) {
printf("<HR>\n");
printf("<DIV CLASS='errorMessage'>It appears as though you do not have permission to view the log file...</DIV><br><br>\n");
printf("<DIV CLASS='errorDescription'>If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI<br>and check the authorization options in your CGI configuration file.</DIV>\n");
printf("<HR>\n");
return ERROR;
}
error = FALSE;
if(use_lifo == TRUE) {
error = read_file_into_lifo(log_file_to_use);
if(error != LIFO_OK) {
if(error == LIFO_ERROR_MEMORY) {
printf("<P><DIV CLASS='warningMessage'>Not enough memory to reverse log file - displaying log in natural order...</DIV></P>");
error = FALSE;
}
else
error = TRUE;
use_lifo = FALSE;
}
else
error = FALSE;
}
if(use_lifo == FALSE) {
if((thefile = mmap_fopen(log_file_to_use)) == NULL) {
printf("<HR>\n");
printf("<P><DIV CLASS='errorMessage'>Error: Could not open log file '%s' for reading!</DIV></P>", log_file_to_use);
printf("<HR>\n");
error = TRUE;
}
}
if(error == FALSE) {
printf("<P><DIV CLASS='logEntries'>\n");
while(1) {
free(input);
if(use_lifo == TRUE) {
if((input = pop_lifo()) == NULL)
break;
}
else if((input = mmap_fgets(thefile)) == NULL)
break;
strip(input);
if(strstr(input, " starting...")) {
strcpy(image, START_ICON);
strcpy(image_alt, START_ICON_ALT);
}
else if(strstr(input, " shutting down...")) {
strcpy(image, STOP_ICON);
strcpy(image_alt, STOP_ICON_ALT);
}
else if(strstr(input, "Bailing out")) {
strcpy(image, STOP_ICON);
strcpy(image_alt, STOP_ICON_ALT);
}
else if(strstr(input, " restarting...")) {
strcpy(image, RESTART_ICON);
strcpy(image_alt, RESTART_ICON_ALT);
}
else if(strstr(input, "HOST ALERT:") && strstr(input, ";DOWN;")) {
strcpy(image, HOST_DOWN_ICON);
strcpy(image_alt, HOST_DOWN_ICON_ALT);
}
else if(strstr(input, "HOST ALERT:") && strstr(input, ";UNREACHABLE;")) {
strcpy(image, HOST_UNREACHABLE_ICON);
strcpy(image_alt, HOST_UNREACHABLE_ICON_ALT);
}
else if(strstr(input, "HOST ALERT:") && (strstr(input, ";RECOVERY;") || strstr(input, ";UP;"))) {
strcpy(image, HOST_UP_ICON);
strcpy(image_alt, HOST_UP_ICON_ALT);
}
else if(strstr(input, "HOST NOTIFICATION:")) {
strcpy(image, HOST_NOTIFICATION_ICON);
strcpy(image_alt, HOST_NOTIFICATION_ICON_ALT);
}
else if(strstr(input, "SERVICE ALERT:") && strstr(input, ";CRITICAL;")) {
strcpy(image, CRITICAL_ICON);
strcpy(image_alt, CRITICAL_ICON_ALT);
}
else if(strstr(input, "SERVICE ALERT:") && strstr(input, ";WARNING;")) {
strcpy(image, WARNING_ICON);
strcpy(image_alt, WARNING_ICON_ALT);
}
else if(strstr(input, "SERVICE ALERT:") && strstr(input, ";UNKNOWN;")) {
strcpy(image, UNKNOWN_ICON);
strcpy(image_alt, UNKNOWN_ICON_ALT);
}
else if(strstr(input, "SERVICE ALERT:") && (strstr(input, ";RECOVERY;") || strstr(input, ";OK;"))) {
strcpy(image, OK_ICON);
strcpy(image_alt, OK_ICON_ALT);
}
else if(strstr(input, "SERVICE NOTIFICATION:")) {
strcpy(image, NOTIFICATION_ICON);
strcpy(image_alt, NOTIFICATION_ICON_ALT);
}
else if(strstr(input, "SERVICE EVENT HANDLER:")) {
strcpy(image, SERVICE_EVENT_ICON);
strcpy(image_alt, SERVICE_EVENT_ICON_ALT);
}
else if(strstr(input, "HOST EVENT HANDLER:")) {
strcpy(image, HOST_EVENT_ICON);
strcpy(image_alt, HOST_EVENT_ICON_ALT);
}
else if(strstr(input, "EXTERNAL COMMAND:")) {
strcpy(image, EXTERNAL_COMMAND_ICON);
strcpy(image_alt, EXTERNAL_COMMAND_ICON_ALT);
}
else if(strstr(input, "PASSIVE SERVICE CHECK:")) {
strcpy(image, PASSIVE_ICON);
strcpy(image_alt, "Passive Service Check");
}
else if(strstr(input, "PASSIVE HOST CHECK:")) {
strcpy(image, PASSIVE_ICON);
strcpy(image_alt, "Passive Host Check");
}
else if(strstr(input, "LOG ROTATION:")) {
strcpy(image, LOG_ROTATION_ICON);
strcpy(image_alt, LOG_ROTATION_ICON_ALT);
}
else if(strstr(input, "active mode...")) {
strcpy(image, ACTIVE_ICON);
strcpy(image_alt, ACTIVE_ICON_ALT);
}
else if(strstr(input, "standby mode...")) {
strcpy(image, STANDBY_ICON);
strcpy(image_alt, STANDBY_ICON_ALT);
}
else if(strstr(input, "SERVICE FLAPPING ALERT:") && strstr(input, ";STARTED;")) {
strcpy(image, FLAPPING_ICON);
strcpy(image_alt, "Service started flapping");
}
else if(strstr(input, "SERVICE FLAPPING ALERT:") && strstr(input, ";STOPPED;")) {
strcpy(image, FLAPPING_ICON);
strcpy(image_alt, "Service stopped flapping");
}
else if(strstr(input, "SERVICE FLAPPING ALERT:") && strstr(input, ";DISABLED;")) {
strcpy(image, FLAPPING_ICON);
strcpy(image_alt, "Service flap detection disabled");
}
else if(strstr(input, "HOST FLAPPING ALERT:") && strstr(input, ";STARTED;")) {
strcpy(image, FLAPPING_ICON);
strcpy(image_alt, "Host started flapping");
}
else if(strstr(input, "HOST FLAPPING ALERT:") && strstr(input, ";STOPPED;")) {
strcpy(image, FLAPPING_ICON);
strcpy(image_alt, "Host stopped flapping");
}
else if(strstr(input, "HOST FLAPPING ALERT:") && strstr(input, ";DISABLED;")) {
strcpy(image, FLAPPING_ICON);
strcpy(image_alt, "Host flap detection disabled");
}
else if(strstr(input, "SERVICE DOWNTIME ALERT:") && strstr(input, ";STARTED;")) {
strcpy(image, SCHEDULED_DOWNTIME_ICON);
strcpy(image_alt, "Service entered a period of scheduled downtime");
}
else if(strstr(input, "SERVICE DOWNTIME ALERT:") && strstr(input, ";STOPPED;")) {
strcpy(image, SCHEDULED_DOWNTIME_ICON);
strcpy(image_alt, "Service exited a period of scheduled downtime");
}
else if(strstr(input, "SERVICE DOWNTIME ALERT:") && strstr(input, ";CANCELLED;")) {
strcpy(image, SCHEDULED_DOWNTIME_ICON);
strcpy(image_alt, "Service scheduled downtime has been cancelled");
}
else if(strstr(input, "HOST DOWNTIME ALERT:") && strstr(input, ";STARTED;")) {
strcpy(image, SCHEDULED_DOWNTIME_ICON);
strcpy(image_alt, "Host entered a period of scheduled downtime");
}
else if(strstr(input, "HOST DOWNTIME ALERT:") && strstr(input, ";STOPPED;")) {
strcpy(image, SCHEDULED_DOWNTIME_ICON);
strcpy(image_alt, "Host exited a period of scheduled downtime");
}
else if(strstr(input, "HOST DOWNTIME ALERT:") && strstr(input, ";CANCELLED;")) {
strcpy(image, SCHEDULED_DOWNTIME_ICON);
strcpy(image_alt, "Host scheduled downtime has been cancelled");
}
else {
strcpy(image, INFO_ICON);
strcpy(image_alt, INFO_ICON_ALT);
}
temp_buffer = strtok(input, "]");
t = (temp_buffer == NULL) ? 0L : strtoul(temp_buffer + 1, NULL, 10);
time_ptr = localtime(&t);
strftime(current_message_date, sizeof(current_message_date), "%B %d, %Y %H:00\n", time_ptr);
current_message_date[sizeof(current_message_date) - 1] = '\x0';
if(strcmp(last_message_date, current_message_date) != 0 && display_timebreaks == TRUE) {
printf("<BR CLEAR='all'>\n");
printf("<DIV CLASS='dateTimeBreak'>\n");
printf("<table border=0 width=95%%><tr>");
printf("<td width=40%%><hr width=100%%></td>");
printf("<td align=center CLASS='dateTimeBreak'>%s</td>", current_message_date);
printf("<td width=40%%><hr width=100%%></td>");
printf("</tr></table>\n");
printf("</DIV>\n");
printf("<BR CLEAR='all'><DIV CLASS='logEntries'>\n");
strncpy(last_message_date, current_message_date, sizeof(last_message_date));
last_message_date[sizeof(last_message_date) - 1] = '\x0';
}
get_time_string(&t, date_time, (int)sizeof(date_time), SHORT_DATE_TIME);
strip(date_time);
temp_buffer = strtok(NULL, "\n");
if(display_frills == TRUE)
printf("<img align='left' src='%s%s' alt='%s' title='%s'>", url_images_path, image, image_alt, image_alt);
printf("[%s] %s", date_time, (temp_buffer == NULL) ? "" : html_encode(temp_buffer, FALSE));
if(enable_splunk_integration == TRUE) {
printf("&nbsp;&nbsp;&nbsp;");
display_splunk_generic_url(temp_buffer, 2);
}
printf("<br clear='all'>\n");
}
printf("</DIV></P>\n");
printf("<HR>\n");
free(input);
if(use_lifo == FALSE)
mmap_fclose(thefile);
}
if(use_lifo == TRUE)
free_lifo_memory();
return OK;
}

5469
cgi/status.c Normal file

File diff suppressed because it is too large Load Diff

2859
cgi/statusmap.c Normal file

File diff suppressed because it is too large Load Diff

1515
cgi/statuswml.c Normal file

File diff suppressed because it is too large Load Diff

1301
cgi/statuswrl.c Normal file

File diff suppressed because it is too large Load Diff

2808
cgi/summary.c Normal file

File diff suppressed because it is too large Load Diff

1666
cgi/tac.c Normal file

File diff suppressed because it is too large Load Diff

3052
cgi/trends.c Normal file

File diff suppressed because it is too large Load Diff

1
common/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
Makefile

39
common/Makefile.in Normal file
View File

@ -0,0 +1,39 @@
############################
# Makefile for Nagios
#
# Last Modified: 04-08-2003
############################
# Source code directories
SRC_BASE=../common
SRC_CGI=../cgi
CC=@CC@
CFLAGS=@CFLAGS@ @DEFS@
LDFLAGS=@LDFLAGS@ @LIBS@
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
CGIDIR=@sbindir@
HTMLDIR=@datarootdir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
CP=@CP@
clean:
rm -f core *.o
rm -f *~
distclean: clean
rm -f Makefile
devclean: distclean
install:

742
common/comments.c Normal file
View File

@ -0,0 +1,742 @@
/*****************************************************************************
*
* COMMENTS.C - Comment functions for Nagios
*
* Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 08-28-2010
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/comments.h"
#include "../include/objects.h"
/***** IMPLEMENTATION-SPECIFIC INCLUDES *****/
#ifdef USE_XCDDEFAULT
#include "../xdata/xcddefault.h"
#endif
#ifdef NSCORE
#include "../include/nagios.h"
#include "../include/broker.h"
#endif
#ifdef NSCGI
#include "../include/cgiutils.h"
#endif
comment *comment_list = NULL;
int defer_comment_sorting = 0;
comment **comment_hashlist = NULL;
#ifdef NSCORE
pthread_mutex_t nagios_comment_lock = PTHREAD_MUTEX_INITIALIZER;
/******************************************************************/
/**************** INITIALIZATION/CLEANUP FUNCTIONS ****************/
/******************************************************************/
/* initializes comment data */
int initialize_comment_data(char *config_file) {
int result = OK;
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XCDDEFAULT
result = xcddefault_initialize_comment_data(config_file);
#endif
return result;
}
/* removes old/invalid comments */
int cleanup_comment_data(char *config_file) {
int result = OK;
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XCDDEFAULT
result = xcddefault_cleanup_comment_data(config_file);
#endif
return result;
}
/******************************************************************/
/****************** COMMENT OUTPUT FUNCTIONS **********************/
/******************************************************************/
/* adds a new host or service comment */
int add_new_comment(int type, int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long *comment_id) {
int result = OK;
unsigned long new_comment_id = 0L;
if(type == HOST_COMMENT)
result = add_new_host_comment(entry_type, host_name, entry_time, author_name, comment_data, persistent, source, expires, expire_time, &new_comment_id);
else
result = add_new_service_comment(entry_type, host_name, svc_description, entry_time, author_name, comment_data, persistent, source, expires, expire_time, &new_comment_id);
/* add an event to expire comment data if necessary... */
if(expires == TRUE)
schedule_new_event(EVENT_EXPIRE_COMMENT, FALSE, expire_time, FALSE, 0, NULL, TRUE, (void *)new_comment_id, NULL, 0);
/* save comment id */
if(comment_id != NULL)
*comment_id = new_comment_id;
return result;
}
/* adds a new host comment */
int add_new_host_comment(int entry_type, char *host_name, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long *comment_id) {
int result = OK;
unsigned long new_comment_id = 0L;
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XCDDEFAULT
result = xcddefault_add_new_host_comment(entry_type, host_name, entry_time, author_name, comment_data, persistent, source, expires, expire_time, &new_comment_id);
#endif
/* save comment id */
if(comment_id != NULL)
*comment_id = new_comment_id;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_comment_data(NEBTYPE_COMMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, HOST_COMMENT, entry_type, host_name, NULL, entry_time, author_name, comment_data, persistent, source, expires, expire_time, new_comment_id, NULL);
#endif
return result;
}
/* adds a new service comment */
int add_new_service_comment(int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long *comment_id) {
int result = OK;
unsigned long new_comment_id = 0L;
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XCDDEFAULT
result = xcddefault_add_new_service_comment(entry_type, host_name, svc_description, entry_time, author_name, comment_data, persistent, source, expires, expire_time, &new_comment_id);
#endif
/* save comment id */
if(comment_id != NULL)
*comment_id = new_comment_id;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_comment_data(NEBTYPE_COMMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_COMMENT, entry_type, host_name, svc_description, entry_time, author_name, comment_data, persistent, source, expires, expire_time, new_comment_id, NULL);
#endif
return result;
}
/******************************************************************/
/***************** COMMENT DELETION FUNCTIONS *********************/
/******************************************************************/
/* deletes a host or service comment */
int delete_comment(int type, unsigned long comment_id) {
int result = OK;
comment *this_comment = NULL;
comment *last_comment = NULL;
comment *next_comment = NULL;
int hashslot = 0;
comment *this_hash = NULL;
comment *last_hash = NULL;
/* lock the comments so we can modify them safely */
#ifdef NSCORE
pthread_mutex_lock(&nagios_comment_lock);
#endif
/* find the comment we should remove */
for(this_comment = comment_list, last_comment = comment_list; this_comment != NULL; this_comment = next_comment) {
next_comment = this_comment->next;
/* we found the comment we should delete */
if(this_comment->comment_id == comment_id && this_comment->comment_type == type)
break;
last_comment = this_comment;
}
/* remove the comment from the list in memory */
if(this_comment != NULL) {
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_comment_data(NEBTYPE_COMMENT_DELETE, NEBFLAG_NONE, NEBATTR_NONE, type, this_comment->entry_type, this_comment->host_name, this_comment->service_description, this_comment->entry_time, this_comment->author, this_comment->comment_data, this_comment->persistent, this_comment->source, this_comment->expires, this_comment->expire_time, comment_id, NULL);
#endif
/* first remove from chained hash list */
hashslot = hashfunc(this_comment->host_name, NULL, COMMENT_HASHSLOTS);
last_hash = NULL;
for(this_hash = comment_hashlist[hashslot]; this_hash; this_hash = this_hash->nexthash) {
if(this_hash == this_comment) {
if(last_hash)
last_hash->nexthash = this_hash->nexthash;
else {
if(this_hash->nexthash)
comment_hashlist[hashslot] = this_hash->nexthash;
else
comment_hashlist[hashslot] = NULL;
}
break;
}
last_hash = this_hash;
}
/* then removed from linked list */
if(comment_list == this_comment)
comment_list = this_comment->next;
else
last_comment->next = next_comment;
/* free memory */
my_free(this_comment->host_name);
my_free(this_comment->service_description);
my_free(this_comment->author);
my_free(this_comment->comment_data);
my_free(this_comment);
result = OK;
}
else
result = ERROR;
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XCDDEFAULT
if(type == HOST_COMMENT)
result = xcddefault_delete_host_comment(comment_id);
else
result = xcddefault_delete_service_comment(comment_id);
#endif
#ifdef NSCORE
pthread_mutex_unlock(&nagios_comment_lock);
#endif
return result;
}
/* deletes a host comment */
int delete_host_comment(unsigned long comment_id) {
int result = OK;
/* delete the comment from memory */
result = delete_comment(HOST_COMMENT, comment_id);
return result;
}
/* deletes a service comment */
int delete_service_comment(unsigned long comment_id) {
int result = OK;
/* delete the comment from memory */
result = delete_comment(SERVICE_COMMENT, comment_id);
return result;
}
/* deletes all comments for a particular host or service */
int delete_all_comments(int type, char *host_name, char *svc_description) {
int result = OK;
if(type == HOST_COMMENT)
result = delete_all_host_comments(host_name);
else
result = delete_all_service_comments(host_name, svc_description);
return result;
}
/* deletes all comments for a particular host */
int delete_all_host_comments(char *host_name) {
int result = OK;
comment *temp_comment = NULL;
comment *next_comment = NULL;
if(host_name == NULL)
return ERROR;
/* delete host comments from memory */
for(temp_comment = get_first_comment_by_host(host_name); temp_comment != NULL; temp_comment = next_comment) {
next_comment = get_next_comment_by_host(host_name, temp_comment);
if(temp_comment->comment_type == HOST_COMMENT)
delete_comment(HOST_COMMENT, temp_comment->comment_id);
}
return result;
}
/* deletes all non-persistent acknowledgement comments for a particular host */
int delete_host_acknowledgement_comments(host *hst) {
int result = OK;
comment *temp_comment = NULL;
comment *next_comment = NULL;
if(hst == NULL)
return ERROR;
/* delete comments from memory */
temp_comment = get_first_comment_by_host(hst->name);
while(temp_comment) {
next_comment = get_next_comment_by_host(hst->name, temp_comment);
if(temp_comment->comment_type == HOST_COMMENT && temp_comment->entry_type == ACKNOWLEDGEMENT_COMMENT && temp_comment->persistent == FALSE) {
delete_comment(HOST_COMMENT, temp_comment->comment_id);
}
temp_comment = next_comment;
}
return result;
}
/* deletes all comments for a particular service */
int delete_all_service_comments(char *host_name, char *svc_description) {
int result = OK;
comment *temp_comment = NULL;
comment *next_comment = NULL;
if(host_name == NULL || svc_description == NULL)
return ERROR;
/* delete service comments from memory */
for(temp_comment = comment_list; temp_comment != NULL; temp_comment = next_comment) {
next_comment = temp_comment->next;
if(temp_comment->comment_type == SERVICE_COMMENT && !strcmp(temp_comment->host_name, host_name) && !strcmp(temp_comment->service_description, svc_description))
delete_comment(SERVICE_COMMENT, temp_comment->comment_id);
}
return result;
}
/* deletes all non-persistent acknowledgement comments for a particular service */
int delete_service_acknowledgement_comments(service *svc) {
int result = OK;
comment *temp_comment = NULL;
comment *next_comment = NULL;
if(svc == NULL)
return ERROR;
/* delete comments from memory */
for(temp_comment = comment_list; temp_comment != NULL; temp_comment = next_comment) {
next_comment = temp_comment->next;
if(temp_comment->comment_type == SERVICE_COMMENT && !strcmp(temp_comment->host_name, svc->host_name) && !strcmp(temp_comment->service_description, svc->description) && temp_comment->entry_type == ACKNOWLEDGEMENT_COMMENT && temp_comment->persistent == FALSE)
delete_comment(SERVICE_COMMENT, temp_comment->comment_id);
}
return result;
}
/* checks for an expired comment (and removes it) */
int check_for_expired_comment(unsigned long comment_id) {
comment *temp_comment = NULL;
/* check all comments */
for(temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) {
/* delete the now expired comment */
if(temp_comment->comment_id == comment_id && temp_comment->expires == TRUE && temp_comment->expire_time < time(NULL)) {
delete_comment(temp_comment->comment_type, comment_id);
break;
}
}
return OK;
}
#endif
/******************************************************************/
/****************** CHAINED HASH FUNCTIONS ************************/
/******************************************************************/
/* adds comment to hash list in memory */
int add_comment_to_hashlist(comment *new_comment) {
comment *temp_comment = NULL;
comment *lastpointer = NULL;
int hashslot = 0;
/* initialize hash list */
if(comment_hashlist == NULL) {
int i;
comment_hashlist = (comment **)malloc(sizeof(comment *) * COMMENT_HASHSLOTS);
if(comment_hashlist == NULL)
return 0;
for(i = 0; i < COMMENT_HASHSLOTS; i++)
comment_hashlist[i] = NULL;
}
if(!new_comment)
return 0;
hashslot = hashfunc(new_comment->host_name, NULL, COMMENT_HASHSLOTS);
lastpointer = NULL;
for(temp_comment = comment_hashlist[hashslot]; temp_comment && compare_hashdata(temp_comment->host_name, NULL, new_comment->host_name, NULL) < 0; temp_comment = temp_comment->nexthash) {
if(compare_hashdata(temp_comment->host_name, NULL, new_comment->host_name, NULL) >= 0)
break;
lastpointer = temp_comment;
}
/* multiples are allowed */
if(lastpointer)
lastpointer->nexthash = new_comment;
else
comment_hashlist[hashslot] = new_comment;
new_comment->nexthash = temp_comment;
return 1;
}
/******************************************************************/
/******************** ADDITION FUNCTIONS **************************/
/******************************************************************/
/* adds a host comment to the list in memory */
int add_host_comment(int entry_type, char *host_name, time_t entry_time, char *author, char *comment_data, unsigned long comment_id, int persistent, int expires, time_t expire_time, int source) {
int result = OK;
result = add_comment(HOST_COMMENT, entry_type, host_name, NULL, entry_time, author, comment_data, comment_id, persistent, expires, expire_time, source);
return result;
}
/* adds a service comment to the list in memory */
int add_service_comment(int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author, char *comment_data, unsigned long comment_id, int persistent, int expires, time_t expire_time, int source) {
int result = OK;
result = add_comment(SERVICE_COMMENT, entry_type, host_name, svc_description, entry_time, author, comment_data, comment_id, persistent, expires, expire_time, source);
return result;
}
/* adds a comment to the list in memory */
int add_comment(int comment_type, int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author, char *comment_data, unsigned long comment_id, int persistent, int expires, time_t expire_time, int source) {
comment *new_comment = NULL;
comment *last_comment = NULL;
comment *temp_comment = NULL;
int result = OK;
/* make sure we have the data we need */
if(host_name == NULL || author == NULL || comment_data == NULL || (comment_type == SERVICE_COMMENT && svc_description == NULL))
return ERROR;
/* allocate memory for the comment */
if((new_comment = (comment *)calloc(1, sizeof(comment))) == NULL)
return ERROR;
/* duplicate vars */
if((new_comment->host_name = (char *)strdup(host_name)) == NULL)
result = ERROR;
if(comment_type == SERVICE_COMMENT) {
if((new_comment->service_description = (char *)strdup(svc_description)) == NULL)
result = ERROR;
}
if((new_comment->author = (char *)strdup(author)) == NULL)
result = ERROR;
if((new_comment->comment_data = (char *)strdup(comment_data)) == NULL)
result = ERROR;
new_comment->comment_type = comment_type;
new_comment->entry_type = entry_type;
new_comment->source = source;
new_comment->entry_time = entry_time;
new_comment->comment_id = comment_id;
new_comment->persistent = (persistent == TRUE) ? TRUE : FALSE;
new_comment->expires = (expires == TRUE) ? TRUE : FALSE;
new_comment->expire_time = expire_time;
/* add comment to hash list */
if(result == OK) {
if(!add_comment_to_hashlist(new_comment))
result = ERROR;
}
/* handle errors */
if(result == ERROR) {
my_free(new_comment->comment_data);
my_free(new_comment->author);
my_free(new_comment->service_description);
my_free(new_comment->host_name);
my_free(new_comment);
return ERROR;
}
if(defer_comment_sorting) {
new_comment->next = comment_list;
comment_list = new_comment;
}
else {
/* add new comment to comment list, sorted by comment id,
* but lock the list first so broker threads doesn't crash
* out in case they're modifying this list too
*/
#ifdef NSCORE
pthread_mutex_lock(&nagios_comment_lock);
#endif
last_comment = comment_list;
for(temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) {
if(new_comment->comment_id < temp_comment->comment_id) {
new_comment->next = temp_comment;
if(temp_comment == comment_list)
comment_list = new_comment;
else
last_comment->next = new_comment;
break;
}
else
last_comment = temp_comment;
}
if(comment_list == NULL) {
new_comment->next = NULL;
comment_list = new_comment;
}
else if(temp_comment == NULL) {
new_comment->next = NULL;
last_comment->next = new_comment;
}
#ifdef NSCORE
pthread_mutex_unlock(&nagios_comment_lock);
#endif
}
#ifdef NSCORE
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_comment_data(NEBTYPE_COMMENT_LOAD, NEBFLAG_NONE, NEBATTR_NONE, comment_type, entry_type, host_name, svc_description, entry_time, author, comment_data, persistent, source, expires, expire_time, comment_id, NULL);
#endif
#endif
return OK;
}
static int comment_compar(const void *p1, const void *p2) {
comment *c1 = *(comment **)p1;
comment *c2 = *(comment **)p2;
return (c1->comment_id < c2->comment_id) ? -1 : (c1->comment_id - c2->comment_id);
}
int sort_comments(void) {
comment **array, *temp_comment;
unsigned long i = 0, unsorted_comments = 0;
if(!defer_comment_sorting)
return OK;
defer_comment_sorting = 0;
temp_comment = comment_list;
while(temp_comment != NULL) {
temp_comment = temp_comment->next;
unsorted_comments++;
}
if(!unsorted_comments)
return OK;
if(!(array = malloc(sizeof(*array) * unsorted_comments)))
return ERROR;
while(comment_list) {
array[i++] = comment_list;
comment_list = comment_list->next;
}
qsort((void *)array, i, sizeof(*array), comment_compar);
comment_list = temp_comment = array[0];
for(i = 1; i < unsorted_comments; i++) {
temp_comment->next = array[i];
temp_comment = temp_comment->next;
}
temp_comment->next = NULL;
my_free(array);
return OK;
}
/******************************************************************/
/********************* CLEANUP FUNCTIONS **************************/
/******************************************************************/
/* frees memory allocated for the comment data */
void free_comment_data(void) {
comment *this_comment = NULL;
comment *next_comment = NULL;
/* free memory for the comment list */
for(this_comment = comment_list; this_comment != NULL; this_comment = next_comment) {
next_comment = this_comment->next;
my_free(this_comment->host_name);
my_free(this_comment->service_description);
my_free(this_comment->author);
my_free(this_comment->comment_data);
my_free(this_comment);
}
/* free hash list and reset list pointer */
my_free(comment_hashlist);
comment_hashlist = NULL;
comment_list = NULL;
return;
}
/******************************************************************/
/********************* UTILITY FUNCTIONS **************************/
/******************************************************************/
/* get the number of comments associated with a particular host */
int number_of_host_comments(char *host_name) {
comment *temp_comment = NULL;
int total_comments = 0;
if(host_name == NULL)
return 0;
for(temp_comment = get_first_comment_by_host(host_name); temp_comment != NULL; temp_comment = get_next_comment_by_host(host_name, temp_comment)) {
if(temp_comment->comment_type == HOST_COMMENT)
total_comments++;
}
return total_comments;
}
/* get the number of comments associated with a particular service */
int number_of_service_comments(char *host_name, char *svc_description) {
comment *temp_comment = NULL;
int total_comments = 0;
if(host_name == NULL || svc_description == NULL)
return 0;
for(temp_comment = get_first_comment_by_host(host_name); temp_comment != NULL; temp_comment = get_next_comment_by_host(host_name, temp_comment)) {
if(temp_comment->comment_type == SERVICE_COMMENT && !strcmp(temp_comment->service_description, svc_description))
total_comments++;
}
return total_comments;
}
/******************************************************************/
/********************* TRAVERSAL FUNCTIONS ************************/
/******************************************************************/
comment *get_first_comment_by_host(char *host_name) {
return get_next_comment_by_host(host_name, NULL);
}
comment *get_next_comment_by_host(char *host_name, comment *start) {
comment *temp_comment = NULL;
if(host_name == NULL || comment_hashlist == NULL)
return NULL;
if(start == NULL)
temp_comment = comment_hashlist[hashfunc(host_name, NULL, COMMENT_HASHSLOTS)];
else
temp_comment = start->nexthash;
for(; temp_comment && compare_hashdata(temp_comment->host_name, NULL, host_name, NULL) < 0; temp_comment = temp_comment->nexthash);
if(temp_comment && compare_hashdata(temp_comment->host_name, NULL, host_name, NULL) == 0)
return temp_comment;
return NULL;
}
/******************************************************************/
/********************** SEARCH FUNCTIONS **************************/
/******************************************************************/
/* find a service comment by id */
comment *find_service_comment(unsigned long comment_id) {
return find_comment(comment_id, SERVICE_COMMENT);
}
/* find a host comment by id */
comment *find_host_comment(unsigned long comment_id) {
return find_comment(comment_id, HOST_COMMENT);
}
/* find a comment by id */
comment *find_comment(unsigned long comment_id, int comment_type) {
comment *temp_comment = NULL;
for(temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) {
if(temp_comment->comment_id == comment_id && temp_comment->comment_type == comment_type)
return temp_comment;
}
return NULL;
}

1260
common/downtime.c Normal file

File diff suppressed because it is too large Load Diff

3356
common/macros.c Normal file

File diff suppressed because it is too large Load Diff

3613
common/objects.c Normal file

File diff suppressed because it is too large Load Diff

511
common/shared.c Normal file
View File

@ -0,0 +1,511 @@
#include "../include/config.h"
#include "../include/common.h"
/*
* This file holds random utility functions shared by cgi's and
* core.
*/
extern int date_format;
/* fix the problem with strtok() skipping empty options between tokens */
char *my_strtok(char *buffer, char *tokens) {
char *token_position = NULL;
char *sequence_head = NULL;
static char *my_strtok_buffer = NULL;
static char *original_my_strtok_buffer = NULL;
if(buffer != NULL) {
my_free(original_my_strtok_buffer);
if((my_strtok_buffer = (char *)strdup(buffer)) == NULL)
return NULL;
original_my_strtok_buffer = my_strtok_buffer;
}
sequence_head = my_strtok_buffer;
if(sequence_head[0] == '\x0')
return NULL;
token_position = strchr(my_strtok_buffer, tokens[0]);
if(token_position == NULL) {
my_strtok_buffer = strchr(my_strtok_buffer, '\x0');
return sequence_head;
}
token_position[0] = '\x0';
my_strtok_buffer = token_position + 1;
return sequence_head;
}
/* fixes compiler problems under Solaris, since strsep() isn't included */
/* this code is taken from the glibc source */
char *my_strsep(char **stringp, const char *delim) {
char *begin, *end;
begin = *stringp;
if(begin == NULL)
return NULL;
/* A frequent case is when the delimiter string contains only one
* character. Here we don't need to call the expensive `strpbrk'
* function and instead work using `strchr'. */
if(delim[0] == '\0' || delim[1] == '\0') {
char ch = delim[0];
if(ch == '\0' || begin[0] == '\0')
end = NULL;
else {
if(*begin == ch)
end = begin;
else
end = strchr(begin + 1, ch);
}
}
else {
/* find the end of the token. */
end = strpbrk(begin, delim);
}
if(end) {
/* terminate the token and set *STRINGP past NUL character. */
*end++ = '\0';
*stringp = end;
}
else
/* no more delimiters; this is the last token. */
*stringp = NULL;
return begin;
}
/* open a file read-only via mmap() */
mmapfile *mmap_fopen(char *filename) {
mmapfile *new_mmapfile = NULL;
int fd = 0;
void *mmap_buf = NULL;
struct stat statbuf;
int mode = O_RDONLY;
unsigned long file_size = 0L;
if(filename == NULL)
return NULL;
/* allocate memory */
if((new_mmapfile = (mmapfile *) malloc(sizeof(mmapfile))) == NULL)
return NULL;
/* open the file */
if((fd = open(filename, mode)) == -1) {
my_free(new_mmapfile);
return NULL;
}
/* get file info */
if((fstat(fd, &statbuf)) == -1) {
close(fd);
my_free(new_mmapfile);
return NULL;
}
/* get file size */
file_size = (unsigned long)statbuf.st_size;
/* only mmap() if we have a file greater than 0 bytes */
if(file_size > 0) {
/* mmap() the file - allocate one extra byte for processing zero-byte files */
if((mmap_buf =
(void *)mmap(0, file_size, PROT_READ, MAP_PRIVATE, fd,
0)) == MAP_FAILED) {
close(fd);
my_free(new_mmapfile);
return NULL;
}
}
else
mmap_buf = NULL;
/* populate struct info for later use */
new_mmapfile->path = (char *)strdup(filename);
new_mmapfile->fd = fd;
new_mmapfile->file_size = (unsigned long)file_size;
new_mmapfile->current_position = 0L;
new_mmapfile->current_line = 0L;
new_mmapfile->mmap_buf = mmap_buf;
return new_mmapfile;
}
/* close a file originally opened via mmap() */
int mmap_fclose(mmapfile * temp_mmapfile) {
if(temp_mmapfile == NULL)
return ERROR;
/* un-mmap() the file */
if(temp_mmapfile->file_size > 0L)
munmap(temp_mmapfile->mmap_buf, temp_mmapfile->file_size);
/* close the file */
close(temp_mmapfile->fd);
/* free memory */
my_free(temp_mmapfile->path);
my_free(temp_mmapfile);
return OK;
}
/* gets one line of input from an mmap()'ed file */
char *mmap_fgets(mmapfile * temp_mmapfile) {
char *buf = NULL;
unsigned long x = 0L;
int len = 0;
if(temp_mmapfile == NULL)
return NULL;
/* size of file is 0 bytes */
if(temp_mmapfile->file_size == 0L)
return NULL;
/* we've reached the end of the file */
if(temp_mmapfile->current_position >= temp_mmapfile->file_size)
return NULL;
/* find the end of the string (or buffer) */
for(x = temp_mmapfile->current_position; x < temp_mmapfile->file_size;
x++) {
if(*((char *)(temp_mmapfile->mmap_buf) + x) == '\n') {
x++;
break;
}
}
/* calculate length of line we just read */
len = (int)(x - temp_mmapfile->current_position);
/* allocate memory for the new line */
if((buf = (char *)malloc(len + 1)) == NULL)
return NULL;
/* copy string to newly allocated memory and terminate the string */
memcpy(buf,
((char *)(temp_mmapfile->mmap_buf) +
temp_mmapfile->current_position), len);
buf[len] = '\x0';
/* update the current position */
temp_mmapfile->current_position = x;
/* increment the current line */
temp_mmapfile->current_line++;
return buf;
}
/* gets one line of input from an mmap()'ed file (may be contained on more than one line in the source file) */
char *mmap_fgets_multiline(mmapfile * temp_mmapfile) {
char *buf = NULL;
char *tempbuf = NULL;
char *stripped = NULL;
int len = 0;
int len2 = 0;
int end = 0;
if(temp_mmapfile == NULL)
return NULL;
while(1) {
my_free(tempbuf);
if((tempbuf = mmap_fgets(temp_mmapfile)) == NULL)
break;
if(buf == NULL) {
len = strlen(tempbuf);
if((buf = (char *)malloc(len + 1)) == NULL)
break;
memcpy(buf, tempbuf, len);
buf[len] = '\x0';
}
else {
/* strip leading white space from continuation lines */
stripped = tempbuf;
while(*stripped == ' ' || *stripped == '\t')
stripped++;
len = strlen(stripped);
len2 = strlen(buf);
if((buf =
(char *)realloc(buf, len + len2 + 1)) == NULL)
break;
strcat(buf, stripped);
len += len2;
buf[len] = '\x0';
}
if(len == 0)
break;
/* handle Windows/DOS CR/LF */
if(len >= 2 && buf[len - 2] == '\r')
end = len - 3;
/* normal Unix LF */
else if(len >= 1 && buf[len - 1] == '\n')
end = len - 2;
else
end = len - 1;
/* two backslashes found. unescape first backslash first and break */
if(end >= 1 && buf[end - 1] == '\\' && buf[end] == '\\') {
buf[end] = '\n';
buf[end + 1] = '\x0';
break;
}
/* one backslash found. continue reading the next line */
else if(end > 0 && buf[end] == '\\')
buf[end] = '\x0';
/* no continuation marker was found, so break */
else
break;
}
my_free(tempbuf);
return buf;
}
/* strip newline, carriage return, and tab characters from beginning and end of a string */
void strip(char *buffer) {
register int x, z;
int len;
if(buffer == NULL || buffer[0] == '\x0')
return;
/* strip end of string */
len = (int)strlen(buffer);
for(x = len - 1; x >= 0; x--) {
switch(buffer[x]) {
case ' ':
case '\n':
case '\r':
case '\t':
buffer[x] = '\x0';
continue;
}
break;
}
/* if we stripped all of it, just return */
if(!x)
return;
/* save last position for later... */
z = x;
/* strip beginning of string (by shifting) */
/* NOTE: this is very expensive to do, so avoid it whenever possible */
for(x = 0;; x++) {
switch(buffer[x]) {
case ' ':
case '\n':
case '\r':
case '\t':
continue;
}
break;
}
if(x > 0 && z > 0) {
/* new length of the string after we stripped the end */
len = z + 1;
/* shift chars towards beginning of string to remove leading whitespace */
for(z = x; z < len; z++)
buffer[z - x] = buffer[z];
buffer[len - x] = '\x0';
}
}
/**************************************************
*************** HASH FUNCTIONS *******************
**************************************************/
/* dual hash function */
int hashfunc(const char *name1, const char *name2, int hashslots) {
unsigned int i, result;
result = 0;
if(name1)
for(i = 0; i < strlen(name1); i++)
result += name1[i];
if(name2)
for(i = 0; i < strlen(name2); i++)
result += name2[i];
result = result % hashslots;
return result;
}
/* dual hash data comparison */
int compare_hashdata(const char *val1a, const char *val1b, const char *val2a,
const char *val2b) {
int result = 0;
/* NOTE: If hash calculation changes, update the compare_strings() function! */
/* check first name */
if(val1a == NULL && val2a == NULL)
result = 0;
else if(val1a == NULL)
result = 1;
else if(val2a == NULL)
result = -1;
else
result = strcmp(val1a, val2a);
/* check second name if necessary */
if(result == 0) {
if(val1b == NULL && val2b == NULL)
result = 0;
else if(val1b == NULL)
result = 1;
else if(val2b == NULL)
result = -1;
else
result = strcmp(val1b, val2b);
}
return result;
}
/*
* given a date/time in time_t format, produce a corresponding
* date/time string, including timezone
*/
void get_datetime_string(time_t * raw_time, char *buffer, int buffer_length,
int type) {
time_t t;
struct tm *tm_ptr, tm_s;
int hour;
int minute;
int second;
int month;
int day;
int year;
char *weekdays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
char *months[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept",
"Oct", "Nov", "Dec"
};
char *tzone = "";
if(raw_time == NULL)
time(&t);
else
t = *raw_time;
if(type == HTTP_DATE_TIME)
tm_ptr = gmtime_r(&t, &tm_s);
else
tm_ptr = localtime_r(&t, &tm_s);
hour = tm_ptr->tm_hour;
minute = tm_ptr->tm_min;
second = tm_ptr->tm_sec;
month = tm_ptr->tm_mon + 1;
day = tm_ptr->tm_mday;
year = tm_ptr->tm_year + 1900;
#ifdef HAVE_TM_ZONE
tzone = (char *)(tm_ptr->tm_zone);
#else
tzone = (tm_ptr->tm_isdst) ? tzname[1] : tzname[0];
#endif
/* ctime() style date/time */
if(type == LONG_DATE_TIME)
snprintf(buffer, buffer_length, "%s %s %d %02d:%02d:%02d %s %d",
weekdays[tm_ptr->tm_wday], months[tm_ptr->tm_mon], day,
hour, minute, second, tzone, year);
/* short date/time */
else if(type == SHORT_DATE_TIME) {
if(date_format == DATE_FORMAT_EURO)
snprintf(buffer, buffer_length,
"%02d-%02d-%04d %02d:%02d:%02d", day, month,
year, hour, minute, second);
else if(date_format == DATE_FORMAT_ISO8601
|| date_format == DATE_FORMAT_STRICT_ISO8601)
snprintf(buffer, buffer_length,
"%04d-%02d-%02d%c%02d:%02d:%02d", year, month,
day,
(date_format ==
DATE_FORMAT_STRICT_ISO8601) ? 'T' : ' ', hour,
minute, second);
else
snprintf(buffer, buffer_length,
"%02d-%02d-%04d %02d:%02d:%02d", month, day,
year, hour, minute, second);
}
/* short date */
else if(type == SHORT_DATE) {
if(date_format == DATE_FORMAT_EURO)
snprintf(buffer, buffer_length, "%02d-%02d-%04d", day,
month, year);
else if(date_format == DATE_FORMAT_ISO8601
|| date_format == DATE_FORMAT_STRICT_ISO8601)
snprintf(buffer, buffer_length, "%04d-%02d-%02d", year,
month, day);
else
snprintf(buffer, buffer_length, "%02d-%02d-%04d", month,
day, year);
}
/* expiration date/time for HTTP headers */
else if(type == HTTP_DATE_TIME)
snprintf(buffer, buffer_length,
"%s, %02d %s %d %02d:%02d:%02d GMT",
weekdays[tm_ptr->tm_wday], day, months[tm_ptr->tm_mon],
year, hour, minute, second);
/* short time */
else
snprintf(buffer, buffer_length, "%02d:%02d:%02d", hour, minute,
second);
buffer[buffer_length - 1] = '\x0';
}
/* get days, hours, minutes, and seconds from a raw time_t format or total seconds */
void get_time_breakdown(unsigned long raw_time, int *days, int *hours,
int *minutes, int *seconds) {
unsigned long temp_time;
int temp_days;
int temp_hours;
int temp_minutes;
int temp_seconds;
temp_time = raw_time;
temp_days = temp_time / 86400;
temp_time -= (temp_days * 86400);
temp_hours = temp_time / 3600;
temp_time -= (temp_hours * 3600);
temp_minutes = temp_time / 60;
temp_time -= (temp_minutes * 60);
temp_seconds = (int)temp_time;
*days = temp_days;
*hours = temp_hours;
*minutes = temp_minutes;
*seconds = temp_seconds;
}

558
common/skiplist.c Normal file
View File

@ -0,0 +1,558 @@
/************************************************************************
*
* SKIPLIST.C - Skiplist functions for use in Nagios event/object lists
*
* Copyright (c) 2008 Ethan Galstad
* Last Modified: 02-28-2008
*
* Notes:
*
* These function implement a slightly modified skiplist from that
* described by William Pugh (ftp://ftp.cs.umd.edu/pub/skipLists/skiplists.pdf).
* The structures and function were modified to allow the list to act
* like a priority queue for the Nagios event list/queue(s). Multiple nodes with
* the same key value are allowed on the list to accomodate multiple events
* occurring at the same (second) point in time. Implemented peek() and pop()
* functions to allow for quick event queue processing, and a method to delete
* a specific list item, based on its pointer, rather than its data value. Again,
* this is useful for the Nagios event queue.
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
************************************************************************/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/skiplist.h"
skiplist *skiplist_new(int max_levels, float level_probability, int allow_duplicates, int append_duplicates, int (*compare_function)(void *, void *)) {
skiplist *newlist = NULL;
/* alloc memory for new list structure */
if((newlist = (skiplist *)malloc(sizeof(skiplist)))) {
/* initialize levels, etc. */
newlist->current_level = 0;
newlist->max_levels = max_levels;
newlist->level_probability = level_probability;
newlist->allow_duplicates = allow_duplicates;
newlist->append_duplicates = append_duplicates;
newlist->items = 0;
newlist->compare_function = compare_function;
/* initialize head node */
newlist->head = skiplist_new_node(newlist, max_levels);
}
return newlist;
}
int skiplist_insert(skiplist *list, void *data) {
skiplistnode **update = NULL;
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
skiplistnode *newnode = NULL;
int level = 0;
int x = 0;
if(list == NULL || data == NULL) {
return SKIPLIST_ERROR_ARGS;
}
/* initialize update vector */
if((update = (skiplistnode **)malloc(sizeof(skiplistnode *) * list->max_levels)) == NULL) {
return SKIPLIST_ERROR_MEMORY;
}
for(x = 0; x < list->max_levels; x++)
update[x] = NULL;
/* check to make sure we don't have duplicates */
/* NOTE: this could made be more efficient */
if(list->allow_duplicates == FALSE) {
if(skiplist_find_first(list, data, NULL))
return SKIPLIST_ERROR_DUPLICATE;
}
/* find proper position for insert, remember pointers with an update vector */
thisnode = list->head;
for(level = list->current_level; level >= 0; level--) {
while((nextnode = thisnode->forward[level])) {
if(list->append_duplicates == TRUE) {
if(list->compare_function(nextnode->data, data) > 0)
break;
}
else {
if(list->compare_function(nextnode->data, data) >= 0)
break;
}
thisnode = nextnode;
}
update[level] = thisnode;
}
/* get a random level the new node should be inserted at */
level = skiplist_random_level(list);
/*printf("INSERTION LEVEL: %d\n",level);*/
/* we're adding a new level... */
if(level > list->current_level) {
/*printf("NEW LEVEL!\n");*/
list->current_level++;
level = list->current_level;
update[level] = list->head;
}
/* create a new node */
if((newnode = skiplist_new_node(list, level)) == NULL) {
/*printf("NODE ERROR\n");*/
free(update);
return SKIPLIST_ERROR_MEMORY;
}
newnode->data = data;
/* update pointers to insert node at proper location */
do {
thisnode = update[level];
newnode->forward[level] = thisnode->forward[level];
thisnode->forward[level] = newnode;
}
while(--level >= 0);
/* update counters */
list->items++;
/* free memory */
free(update);
return SKIPLIST_OK;
}
skiplistnode *skiplist_new_node(skiplist *list, int node_levels) {
skiplistnode *newnode = NULL;
register int x = 0;
if(list == NULL)
return NULL;
if(node_levels < 0 || node_levels > list->max_levels)
return NULL;
/* allocate memory for node + variable number of level pointers */
if((newnode = (skiplistnode *)malloc(sizeof(skiplistnode) + (node_levels * sizeof(skiplistnode *))))) {
/* initialize forward pointers */
for(x = 0; x < node_levels; x++)
newnode->forward[x] = NULL;
/* initialize data pointer */
newnode->data = NULL;
}
return newnode;
}
int skiplist_random_level(skiplist *list) {
int level = 0;
float r = 0.0;
if(list == NULL)
return -1;
for(level = 0; level < list->max_levels; level++) {
r = ((float)rand() / (float)RAND_MAX);
if(r > list->level_probability)
break;
}
return (level >= list->max_levels) ? list->max_levels - 1 : level;
}
int skiplist_empty(skiplist *list) {
skiplistnode *this = NULL;
skiplistnode *next = NULL;
int level = 0;
if(list == NULL)
return ERROR;
/* free all list nodes (but not header) */
for(this = list->head->forward[0]; this != NULL; this = next) {
next = this->forward[0];
free(this);
}
/* reset level pointers */
for(level = list->current_level; level >= 0; level--)
list->head->forward[level] = NULL;
/* reset list level */
list->current_level = 0;
/* reset items */
list->items = 0;
return OK;
}
int skiplist_free(skiplist **list) {
skiplistnode *this = NULL;
skiplistnode *next = NULL;
if(list == NULL)
return ERROR;
if(*list == NULL)
return OK;
/* free header and all list nodes */
for(this = (*list)->head; this != NULL; this = next) {
next = this->forward[0];
free(this);
}
/* free list structure */
free(*list);
*list = NULL;
return OK;
}
/* get first item in list */
void *skiplist_peek(skiplist *list) {
if(list == NULL)
return NULL;
/* return first item */
return list->head->forward[0]->data;
}
/* get/remove first item in list */
void *skiplist_pop(skiplist *list) {
skiplistnode *thisnode = NULL;
void *data = NULL;
int level = 0;
if(list == NULL)
return NULL;
/* get first item */
thisnode = list->head->forward[0];
if(thisnode == NULL)
return NULL;
/* get data for first item */
data = thisnode->data;
/* remove first item from queue - update forward links from head to first node */
for(level = 0; level <= list->current_level; level++) {
if(list->head->forward[level] == thisnode)
list->head->forward[level] = thisnode->forward[level];
}
/* free deleted node */
free(thisnode);
/* adjust items */
list->items--;
return data;
}
/* get first item in list */
void *skiplist_get_first(skiplist *list, void **node_ptr) {
skiplistnode *thisnode = NULL;
if(list == NULL)
return NULL;
/* get first node */
thisnode = list->head->forward[0];
/* return pointer to node */
if(node_ptr)
*node_ptr = (void *)thisnode;
if(thisnode)
return thisnode->data;
else
return NULL;
}
/* get next item in list */
void *skiplist_get_next(void **node_ptr) {
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
if(node_ptr == NULL || *node_ptr == NULL)
return NULL;
thisnode = (skiplistnode *)(*node_ptr);
nextnode = thisnode->forward[0];
*node_ptr = (void *)nextnode;
if(nextnode)
return nextnode->data;
else
return NULL;
}
/* first first item in list */
void *skiplist_find_first(skiplist *list, void *data, void **node_ptr) {
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
int level = 0;
if(list == NULL || data == NULL)
return NULL;
thisnode = list->head;
for(level = list->current_level; level >= 0; level--) {
while((nextnode = thisnode->forward[level])) {
if(list->compare_function(nextnode->data, data) >= 0)
break;
thisnode = nextnode;
}
}
/* we found it! */
if(nextnode && list->compare_function(nextnode->data, data) == 0) {
if(node_ptr)
*node_ptr = (void *)nextnode;
return nextnode->data;
}
else {
if(node_ptr)
*node_ptr = NULL;
}
return NULL;
}
/* find next match */
void *skiplist_find_next(skiplist *list, void *data, void **node_ptr) {
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
if(list == NULL || data == NULL || node_ptr == NULL)
return NULL;
if(*node_ptr == NULL)
return NULL;
thisnode = (skiplistnode *)(*node_ptr);
nextnode = thisnode->forward[0];
if(nextnode) {
if(list->compare_function(nextnode->data, data) == 0) {
*node_ptr = (void *)nextnode;
return nextnode->data;
}
}
*node_ptr = NULL;
return NULL;
}
/* delete (all) matching item(s) from list */
int skiplist_delete(skiplist *list, void *data) {
return skiplist_delete_all(list, data);
}
/* delete first matching item from list */
int skiplist_delete_first(skiplist *list, void *data) {
skiplistnode **update = NULL;
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
int level = 0;
int top_level = 0;
int deleted = FALSE;
int x = 0;
if(list == NULL || data == NULL)
return ERROR;
/* initialize update vector */
if((update = (skiplistnode **)malloc(sizeof(skiplistnode *) * list->max_levels)) == NULL)
return ERROR;
for(x = 0; x < list->max_levels; x++)
update[x] = NULL;
/* find location in list */
thisnode = list->head;
for(top_level = level = list->current_level; level >= 0; level--) {
while((nextnode = thisnode->forward[level])) {
if(list->compare_function(nextnode->data, data) >= 0)
break;
thisnode = nextnode;
}
update[level] = thisnode;
}
/* we found a match! */
if(list->compare_function(nextnode->data, data) == 0) {
/* adjust level pointers to bypass (soon to be) removed node */
for(level = 0; level <= top_level; level++) {
thisnode = update[level];
if(thisnode->forward[level] != nextnode)
break;
thisnode->forward[level] = nextnode->forward[level];
}
/* free node memory */
free(nextnode);
/* adjust top/current level of list is necessary */
while(list->head->forward[top_level] == NULL && top_level > 0)
top_level--;
list->current_level = top_level;
/* adjust items */
list->items--;
deleted = TRUE;
}
/* free memory */
free(update);
return deleted;
}
/* delete all matching items from list */
int skiplist_delete_all(skiplist *list, void *data) {
int deleted = 0;
int total_deleted = 0;
/* NOTE: there is a more efficient way to do this... */
while((deleted = skiplist_delete_first(list, data)) == 1)
total_deleted++;
return total_deleted;
}
/* delete specific node from list */
int skiplist_delete_node(skiplist *list, void *node_ptr) {
void *data = NULL;
skiplistnode **update = NULL;
skiplistnode *thenode = NULL;
skiplistnode *thisnode = NULL;
skiplistnode *nextnode = NULL;
int level = 0;
int top_level = 0;
int deleted = FALSE;
int x = 0;
if(list == NULL || node_ptr == NULL)
return ERROR;
/* we'll need the data from the node to first find the node */
thenode = (skiplistnode *)node_ptr;
data = thenode->data;
/* initialize update vector */
if((update = (skiplistnode **)malloc(sizeof(skiplistnode *) * list->max_levels)) == NULL)
return ERROR;
for(x = 0; x < list->max_levels; x++)
update[x] = NULL;
/* find location in list */
thisnode = list->head;
for(top_level = level = list->current_level; level >= 0; level--) {
while((nextnode = thisnode->forward[level])) {
/* next node would be too far */
if(list->compare_function(nextnode->data, data) > 0)
break;
/* this is the exact node we want */
if(list->compare_function(nextnode->data, data) == 0 && nextnode == thenode)
break;
thisnode = nextnode;
}
update[level] = thisnode;
}
/* we found a match! (value + pointers match) */
if(nextnode && list->compare_function(nextnode->data, data) == 0 && nextnode == thenode) {
/* adjust level pointers to bypass (soon to be) removed node */
for(level = 0; level <= top_level; level++) {
thisnode = update[level];
if(thisnode->forward[level] != nextnode)
break;
thisnode->forward[level] = nextnode->forward[level];
}
/* free node memory */
free(nextnode);
/* adjust top/current level of list is necessary */
while(list->head->forward[top_level] == NULL && top_level > 0)
top_level--;
list->current_level = top_level;
/* adjust items */
list->items--;
deleted = TRUE;
}
/* free memory */
free(update);
return deleted;
}

1459
common/snprintf.c Normal file

File diff suppressed because it is too large Load Diff

575
common/statusdata.c Normal file
View File

@ -0,0 +1,575 @@
/*****************************************************************************
*
* STATUSDATA.C - External status data for Nagios CGIs
*
* Copyright (c) 2000-2006 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 10-19-2006
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
/*********** COMMON HEADER FILES ***********/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/statusdata.h"
#ifdef NSCORE
#include "../include/nagios.h"
#include "../include/broker.h"
#endif
#ifdef NSCGI
#include "../include/cgiutils.h"
#endif
/**** IMPLEMENTATION SPECIFIC HEADER FILES ****/
#ifdef USE_XSDDEFAULT
#include "../xdata/xsddefault.h" /* default routines */
#endif
#ifdef NSCORE
extern int aggregate_status_updates;
#endif
#ifdef NSCGI
hoststatus *hoststatus_list = NULL;
hoststatus *hoststatus_list_tail = NULL;
servicestatus *servicestatus_list = NULL;
servicestatus *servicestatus_list_tail = NULL;
hoststatus **hoststatus_hashlist = NULL;
servicestatus **servicestatus_hashlist = NULL;
extern int use_pending_states;
#endif
#ifdef NSCORE
/******************************************************************/
/****************** TOP-LEVEL OUTPUT FUNCTIONS ********************/
/******************************************************************/
/* initializes status data at program start */
int initialize_status_data(char *config_file) {
int result = OK;
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XSDDEFAULT
result = xsddefault_initialize_status_data(config_file);
#endif
return result;
}
/* update all status data (aggregated dump) */
int update_all_status_data(void) {
int result = OK;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_aggregated_status_data(NEBTYPE_AGGREGATEDSTATUS_STARTDUMP, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XSDDEFAULT
result = xsddefault_save_status_data();
#endif
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_aggregated_status_data(NEBTYPE_AGGREGATEDSTATUS_ENDDUMP, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
if(result != OK)
return ERROR;
return OK;
}
/* cleans up status data before program termination */
int cleanup_status_data(char *config_file, int delete_status_data) {
int result = OK;
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XSDDEFAULT
result = xsddefault_cleanup_status_data(config_file, delete_status_data);
#endif
return result;
}
/* updates program status info */
int update_program_status(int aggregated_dump) {
#ifdef USE_EVENT_BROKER
/* send data to event broker (non-aggregated dumps only) */
if(aggregated_dump == FALSE)
broker_program_status(NEBTYPE_PROGRAMSTATUS_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
/* currently a noop if aggregated updates is TRUE */
/* update all status data if we're not aggregating updates */
if(aggregate_status_updates == FALSE)
update_all_status_data();
return OK;
}
/* updates host status info */
int update_host_status(host *hst, int aggregated_dump) {
#ifdef USE_EVENT_BROKER
/* send data to event broker (non-aggregated dumps only) */
if(aggregated_dump == FALSE)
broker_host_status(NEBTYPE_HOSTSTATUS_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, NULL);
#endif
/* currently a noop if aggregated updates is TRUE */
/* update all status data if we're not aggregating updates */
if(aggregate_status_updates == FALSE)
update_all_status_data();
return OK;
}
/* updates service status info */
int update_service_status(service *svc, int aggregated_dump) {
#ifdef USE_EVENT_BROKER
/* send data to event broker (non-aggregated dumps only) */
if(aggregated_dump == FALSE)
broker_service_status(NEBTYPE_SERVICESTATUS_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, NULL);
#endif
/* currently a noop if aggregated updates is TRUE */
/* update all status data if we're not aggregating updates */
if(aggregate_status_updates == FALSE)
update_all_status_data();
return OK;
}
/* updates contact status info */
int update_contact_status(contact *cntct, int aggregated_dump) {
#ifdef USE_EVENT_BROKER
/* send data to event broker (non-aggregated dumps only) */
if(aggregated_dump == FALSE)
broker_contact_status(NEBTYPE_CONTACTSTATUS_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cntct, NULL);
#endif
/* currently a noop if aggregated updates is TRUE */
/* update all status data if we're not aggregating updates */
if(aggregate_status_updates == FALSE)
update_all_status_data();
return OK;
}
#endif
#ifdef NSCGI
/******************************************************************/
/******************* TOP-LEVEL INPUT FUNCTIONS ********************/
/******************************************************************/
/* reads in all status data */
int read_status_data(char *config_file, int options) {
int result = OK;
/**** IMPLEMENTATION-SPECIFIC CALLS ****/
#ifdef USE_XSDDEFAULT
result = xsddefault_read_status_data(config_file, options);
#endif
#ifdef USE_XSDDB
result = xsddb_read_status_data(config_file, options);
#endif
return result;
}
/******************************************************************/
/****************** CHAINED HASH FUNCTIONS ************************/
/******************************************************************/
/* adds hoststatus to hash list in memory */
int add_hoststatus_to_hashlist(hoststatus *new_hoststatus) {
hoststatus *temp_hoststatus = NULL;
hoststatus *lastpointer = NULL;
int hashslot = 0;
int i = 0;
/* initialize hash list */
if(hoststatus_hashlist == NULL) {
hoststatus_hashlist = (hoststatus **)malloc(sizeof(hoststatus *) * HOSTSTATUS_HASHSLOTS);
if(hoststatus_hashlist == NULL)
return 0;
for(i = 0; i < HOSTSTATUS_HASHSLOTS; i++)
hoststatus_hashlist[i] = NULL;
}
if(!new_hoststatus)
return 0;
hashslot = hashfunc(new_hoststatus->host_name, NULL, HOSTSTATUS_HASHSLOTS);
lastpointer = NULL;
for(temp_hoststatus = hoststatus_hashlist[hashslot]; temp_hoststatus && compare_hashdata(temp_hoststatus->host_name, NULL, new_hoststatus->host_name, NULL) < 0; temp_hoststatus = temp_hoststatus->nexthash)
lastpointer = temp_hoststatus;
if(!temp_hoststatus || (compare_hashdata(temp_hoststatus->host_name, NULL, new_hoststatus->host_name, NULL) != 0)) {
if(lastpointer)
lastpointer->nexthash = new_hoststatus;
else
hoststatus_hashlist[hashslot] = new_hoststatus;
new_hoststatus->nexthash = temp_hoststatus;
return 1;
}
/* else already exists */
return 0;
}
int add_servicestatus_to_hashlist(servicestatus *new_servicestatus) {
servicestatus *temp_servicestatus = NULL, *lastpointer = NULL;
int hashslot = 0;
int i = 0;
/* initialize hash list */
if(servicestatus_hashlist == NULL) {
servicestatus_hashlist = (servicestatus **)malloc(sizeof(servicestatus *) * SERVICESTATUS_HASHSLOTS);
if(servicestatus_hashlist == NULL)
return 0;
for(i = 0; i < SERVICESTATUS_HASHSLOTS; i++)
servicestatus_hashlist[i] = NULL;
}
if(!new_servicestatus)
return 0;
hashslot = hashfunc(new_servicestatus->host_name, new_servicestatus->description, SERVICESTATUS_HASHSLOTS);
lastpointer = NULL;
for(temp_servicestatus = servicestatus_hashlist[hashslot]; temp_servicestatus && compare_hashdata(temp_servicestatus->host_name, temp_servicestatus->description, new_servicestatus->host_name, new_servicestatus->description) < 0; temp_servicestatus = temp_servicestatus->nexthash)
lastpointer = temp_servicestatus;
if(!temp_servicestatus || (compare_hashdata(temp_servicestatus->host_name, temp_servicestatus->description, new_servicestatus->host_name, new_servicestatus->description) != 0)) {
if(lastpointer)
lastpointer->nexthash = new_servicestatus;
else
servicestatus_hashlist[hashslot] = new_servicestatus;
new_servicestatus->nexthash = temp_servicestatus;
return 1;
}
/* else already exists */
return 0;
}
/******************************************************************/
/********************** ADDITION FUNCTIONS ************************/
/******************************************************************/
/* adds a host status entry to the list in memory */
int add_host_status(hoststatus *new_hoststatus) {
char date_string[MAX_DATETIME_LENGTH];
/* make sure we have what we need */
if(new_hoststatus == NULL)
return ERROR;
if(new_hoststatus->host_name == NULL)
return ERROR;
/* massage host status a bit */
if(new_hoststatus != NULL) {
switch(new_hoststatus->status) {
case 0:
new_hoststatus->status = HOST_UP;
break;
case 1:
new_hoststatus->status = HOST_DOWN;
break;
case 2:
new_hoststatus->status = HOST_UNREACHABLE;
break;
default:
new_hoststatus->status = HOST_UP;
break;
}
if(new_hoststatus->has_been_checked == FALSE) {
if(use_pending_states == TRUE)
new_hoststatus->status = HOST_PENDING;
my_free(new_hoststatus->plugin_output);
if(new_hoststatus->should_be_scheduled == TRUE) {
get_time_string(&new_hoststatus->next_check, date_string, sizeof(date_string), LONG_DATE_TIME);
asprintf(&new_hoststatus->plugin_output, "Host check scheduled for %s", date_string);
}
else {
/* passive-only hosts that have just been scheduled for a forced check */
if(new_hoststatus->checks_enabled == FALSE && new_hoststatus->next_check != (time_t)0L && (new_hoststatus->check_options & CHECK_OPTION_FORCE_EXECUTION)) {
get_time_string(&new_hoststatus->next_check, date_string, sizeof(date_string), LONG_DATE_TIME);
asprintf(&new_hoststatus->plugin_output, "Forced host check scheduled for %s", date_string);
}
/* passive-only hosts not scheduled to be checked */
else
new_hoststatus->plugin_output = (char *)strdup("Host is not scheduled to be checked...");
}
}
}
new_hoststatus->next = NULL;
new_hoststatus->nexthash = NULL;
/* add new hoststatus to hoststatus chained hash list */
if(!add_hoststatus_to_hashlist(new_hoststatus))
return ERROR;
/* object cache file is already sorted, so just add new items to end of list */
if(hoststatus_list == NULL) {
hoststatus_list = new_hoststatus;
hoststatus_list_tail = new_hoststatus;
}
else {
hoststatus_list_tail->next = new_hoststatus;
hoststatus_list_tail = new_hoststatus;
}
return OK;
}
/* adds a service status entry to the list in memory */
int add_service_status(servicestatus *new_svcstatus) {
char date_string[MAX_DATETIME_LENGTH];
/* make sure we have what we need */
if(new_svcstatus == NULL)
return ERROR;
if(new_svcstatus->host_name == NULL || new_svcstatus->description == NULL)
return ERROR;
/* massage service status a bit */
if(new_svcstatus != NULL) {
switch(new_svcstatus->status) {
case 0:
new_svcstatus->status = SERVICE_OK;
break;
case 1:
new_svcstatus->status = SERVICE_WARNING;
break;
case 2:
new_svcstatus->status = SERVICE_CRITICAL;
break;
case 3:
new_svcstatus->status = SERVICE_UNKNOWN;
break;
default:
new_svcstatus->status = SERVICE_OK;
break;
}
if(new_svcstatus->has_been_checked == FALSE) {
if(use_pending_states == TRUE)
new_svcstatus->status = SERVICE_PENDING;
my_free(new_svcstatus->plugin_output);
if(new_svcstatus->should_be_scheduled == TRUE) {
get_time_string(&new_svcstatus->next_check, date_string, sizeof(date_string), LONG_DATE_TIME);
asprintf(&new_svcstatus->plugin_output, "Service check scheduled for %s", date_string);
}
else {
/* passive-only services that have just been scheduled for a forced check */
if(new_svcstatus->checks_enabled == FALSE && new_svcstatus->next_check != (time_t)0L && (new_svcstatus->check_options & CHECK_OPTION_FORCE_EXECUTION)) {
get_time_string(&new_svcstatus->next_check, date_string, sizeof(date_string), LONG_DATE_TIME);
asprintf(&new_svcstatus->plugin_output, "Forced service check scheduled for %s", date_string);
}
/* passive-only services not scheduled to be checked */
else
new_svcstatus->plugin_output = (char *)strdup("Service is not scheduled to be checked...");
}
}
}
new_svcstatus->next = NULL;
new_svcstatus->nexthash = NULL;
/* add new servicestatus to servicestatus chained hash list */
if(!add_servicestatus_to_hashlist(new_svcstatus))
return ERROR;
/* object cache file is already sorted, so just add new items to end of list */
if(servicestatus_list == NULL) {
servicestatus_list = new_svcstatus;
servicestatus_list_tail = new_svcstatus;
}
else {
servicestatus_list_tail->next = new_svcstatus;
servicestatus_list_tail = new_svcstatus;
}
return OK;
}
/******************************************************************/
/*********************** CLEANUP FUNCTIONS ************************/
/******************************************************************/
/* free all memory for status data */
void free_status_data(void) {
hoststatus *this_hoststatus = NULL;
hoststatus *next_hoststatus = NULL;
servicestatus *this_svcstatus = NULL;
servicestatus *next_svcstatus = NULL;
/* free memory for the host status list */
for(this_hoststatus = hoststatus_list; this_hoststatus != NULL; this_hoststatus = next_hoststatus) {
next_hoststatus = this_hoststatus->next;
my_free(this_hoststatus->host_name);
my_free(this_hoststatus->plugin_output);
my_free(this_hoststatus->long_plugin_output);
my_free(this_hoststatus->perf_data);
my_free(this_hoststatus);
}
/* free memory for the service status list */
for(this_svcstatus = servicestatus_list; this_svcstatus != NULL; this_svcstatus = next_svcstatus) {
next_svcstatus = this_svcstatus->next;
my_free(this_svcstatus->host_name);
my_free(this_svcstatus->description);
my_free(this_svcstatus->plugin_output);
my_free(this_svcstatus->long_plugin_output);
my_free(this_svcstatus->perf_data);
my_free(this_svcstatus);
}
/* free hash lists reset list pointers */
my_free(hoststatus_hashlist);
my_free(servicestatus_hashlist);
hoststatus_list = NULL;
servicestatus_list = NULL;
return;
}
/******************************************************************/
/************************ SEARCH FUNCTIONS ************************/
/******************************************************************/
/* find a host status entry */
hoststatus *find_hoststatus(char *host_name) {
hoststatus *temp_hoststatus = NULL;
if(host_name == NULL || hoststatus_hashlist == NULL)
return NULL;
for(temp_hoststatus = hoststatus_hashlist[hashfunc(host_name, NULL, HOSTSTATUS_HASHSLOTS)]; temp_hoststatus && compare_hashdata(temp_hoststatus->host_name, NULL, host_name, NULL) < 0; temp_hoststatus = temp_hoststatus->nexthash);
if(temp_hoststatus && (compare_hashdata(temp_hoststatus->host_name, NULL, host_name, NULL) == 0))
return temp_hoststatus;
return NULL;
}
/* find a service status entry */
servicestatus *find_servicestatus(char *host_name, char *svc_desc) {
servicestatus *temp_servicestatus = NULL;
if(host_name == NULL || svc_desc == NULL || servicestatus_hashlist == NULL)
return NULL;
for(temp_servicestatus = servicestatus_hashlist[hashfunc(host_name, svc_desc, SERVICESTATUS_HASHSLOTS)]; temp_servicestatus && compare_hashdata(temp_servicestatus->host_name, temp_servicestatus->description, host_name, svc_desc) < 0; temp_servicestatus = temp_servicestatus->nexthash);
if(temp_servicestatus && (compare_hashdata(temp_servicestatus->host_name, temp_servicestatus->description, host_name, svc_desc) == 0))
return temp_servicestatus;
return NULL;
}
/******************************************************************/
/*********************** UTILITY FUNCTIONS ************************/
/******************************************************************/
/* gets the total number of services of a certain state for a specific host */
int get_servicestatus_count(char *host_name, int type) {
servicestatus *temp_status = NULL;
int count = 0;
if(host_name == NULL)
return 0;
for(temp_status = servicestatus_list; temp_status != NULL; temp_status = temp_status->next) {
if(temp_status->status & type) {
if(!strcmp(host_name, temp_status->host_name))
count++;
}
}
return count;
}
#endif

1510
config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

1619
config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

8860
configure vendored Executable file

File diff suppressed because it is too large Load Diff

880
configure.in Normal file
View File

@ -0,0 +1,880 @@
dnl Process this -*-m4-*- file with autoconf to produce a configure script.
dnl Disable caching
define([AC_CACHE_LOAD],)
define([AC_CACHE_SAVE],)
AC_INIT(base/nagios.c)
AC_CONFIG_HEADER(include/config.h include/snprintf.h)
AC_PREFIX_DEFAULT(/usr/local/nagios)
PKG_NAME=nagios
PKG_VERSION="3.5.1"
PKG_HOME_URL="http://www.nagios.org/"
PKG_REL_DATE="08-30-2013"
dnl Figure out how to invoke "install" and what install options to use.
AC_PROG_INSTALL
AC_SUBST(INSTALL)
dnl What OS are we running?
AC_CANONICAL_HOST
dnl Checks for programs.
AC_PROG_CC
AC_PROG_MAKE_SET
AC_PATH_PROG([STRIP],[strip],[true])
dnl Checks for header files.
AC_HEADER_STDC
AC_HEADER_TIME
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(arpa/inet.h ctype.h dirent.h errno.h fcntl.h getopt.h grp.h libgen.h limits.h math.h netdb.h netinet/in.h pthread.h pthreads.h pwd.h regex.h signal.h socket.h stdarg.h string.h strings.h sys/mman.h sys/types.h sys/time.h sys/resource.h sys/wait.h sys/socket.h sys/stat.h sys/timeb.h sys/un.h sys/ipc.h sys/msg.h sys/poll.h syslog.h uio.h unistd.h locale.h wchar.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_STRUCT_TM
AC_STRUCT_TIMEZONE
AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_SIGNAL
AC_TYPE_GETGROUPS
dnl Check for asprintf() and friends...
AC_CACHE_CHECK([for va_copy],ac_cv_HAVE_VA_COPY,[
AC_TRY_LINK([#include <stdarg.h>
va_list ap1,ap2;], [va_copy(ap1,ap2);],
ac_cv_HAVE_VA_COPY=yes,
ac_cv_HAVE_VA_COPY=no)])
if test x"$ac_cv_HAVE_VA_COPY" = x"yes"; then
AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available])
else
AC_CACHE_CHECK([for __va_copy],ac_cv_HAVE___VA_COPY,[
AC_TRY_LINK([#include <stdarg.h>
va_list ap1,ap2;], [__va_copy(ap1,ap2);],
ac_cv_HAVE___VA_COPY=yes,
ac_cv_HAVE___VA_COPY=no)])
if test x"$ac_cv_HAVE___VA_COPY" = x"yes"; then
AC_DEFINE(HAVE___VA_COPY,1,[Whether __va_copy() is available])
fi
fi
AC_CHECK_FUNC(vsnprintf,,SNPRINTF_O=../common/snprintf.o)
AC_CHECK_FUNC(snprintf,,SNPRINTF_O=../common/snprintf.o)
AC_CHECK_FUNC(asprintf,,SNPRINTF_O=../common/snprintf.o)
AC_CHECK_FUNC(vasprintf,,SNPRINTF_O=../common/snprintf.o)
AC_CACHE_CHECK([for C99 vsnprintf],ac_cv_HAVE_C99_VSNPRINTF,[
AC_TRY_RUN([
#include <sys/types.h>
#include <stdarg.h>
void foo(const char *format, ...) {
va_list ap;
int len;
char buf[5];
va_start(ap, format);
len = vsnprintf(buf, 0, format, ap);
va_end(ap);
if (len != 5) exit(1);
va_start(ap, format);
len = vsnprintf(0, 0, format, ap);
va_end(ap);
if (len != 5) exit(1);
if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(1);
exit(0);
}
main() { foo("hello"); }
],
ac_cv_HAVE_C99_VSNPRINTF=yes,ac_cv_HAVE_C99_VSNPRINTF=no,ac_cv_HAVE_C99_VSNPRINTF=cross)])
if test x"$ac_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
AC_DEFINE(HAVE_C99_VSNPRINTF,1,[Define if system has C99 compatible vsnprintf])
fi
dnl AC_CHECK_FUNC(snprintf,AC_DEFINE(HAVE_SNPRINTF),SNPRINTF_O=../common/snprintf.o)
AC_SUBST(SNPRINTF_O)
dnl Checks for library functions.
AC_SEARCH_LIBS([getservbyname],[nsl],
[if test "$ac_cv_search_getservbyname" != "none required"; then
SOCKETLIBS="$SOCKETLIBS -lnsl"
fi])
AC_SEARCH_LIBS([connect],[socket],
[if test "$ac_cv_search_connect" != "none required"; then
SOCKETLIBS="$SOCKETLIBS -lsocket"
fi])
AC_SUBST(SOCKETLIBS)
AC_CHECK_FUNCS(initgroups setenv strdup strstr strtoul unsetenv)
AC_MSG_CHECKING(for type of socket size)
AC_TRY_COMPILE([#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
],
[int a = send(1, (const void *) 0, (size_t) 0, (int) 0);],
[AC_DEFINE(SOCKET_SIZE_TYPE, size_t, [typedef for socket size]) AC_MSG_RESULT(size_t)],
[AC_DEFINE(SOCKET_SIZE_TYPE, int, [typedef for socket size]) AC_MSG_RESULT(int)])
dnl Test for pthreads support - taken from ICU FreeBSD Port configure script
THREADLIBS=""
have_pthreads="no"
dnl FreeBSD: Try ports/linuxthreads first - Mammad Zadeh <mammad@yahoo-inc.com>
dnl FreeBSD -pthread check - Jonathan McDowell <noodles@earth.li>
AC_DEFUN([AC_PTHREAD_FREEBSD],[
AC_CHECK_LIB(lthread,pthread_create,[
CFLAGS="-D_THREAD_SAFE -I/usr/local/include/pthread/linuxthreads -I/usr/include $CFLAGS"
THREADLIBS="-L/usr/local/lib -llthread -llgcc_r"
],[
AC_MSG_CHECKING([if we need -pthread for threads])
AC_CACHE_VAL(ac_ldflag_pthread,[
ac_save_LDFLAGS="$LDFLAGS"
LDFLAGS="-pthread $LDFLAGS"
AC_TRY_LINK([
char pthread_create();
],
pthread_create();,
eval "ac_ldflag_pthread=yes",
eval "ac_ldflag_pthread=no"
),
THREADLIBS="$ac_save_LDFLAGS"
])
if eval "test \"`echo $ac_ldflag_pthread`\" = yes"; then
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
],-L/usr/local/lib)
])
dnl Test for HPUX cma threads first..
AC_CHECK_LIB(cma,pthread_create,THREADLIBS="$THREADLIBS -lpthread")
if test $ac_cv_lib_cma_pthread_create = yes; then
have_pthreads="yes"
fi
dnl special pthread handling
dnl AIX uses pthreads instead of pthread, and HP/UX uses cma
dnl FreeBSD users -pthread
AC_CHECK_LIB(pthread,pthread_create,THREADLIBS="$THREADLIBS -lpthread")
if test $ac_cv_lib_pthread_pthread_create = yes; then
have_pthreads="yes"
else
dnl For HP 11
AC_CHECK_LIB(pthread,pthread_mutex_init,THREADLIBS="$THREADLIBS -lpthread")
if test $ac_cv_lib_pthread_pthread_mutex_init = yes; then
have_pthreads="yes"
fi
fi
dnl AIX uses pthreads instead of pthread
if test $have_pthreads = "no"; then
AC_CHECK_LIB(pthreads,pthread_create,THREADLIBS="$THREADLIBS -lpthreads")
if test $ac_cv_lib_pthreads_pthread_create = yes; then
have_pthreads="yes"
fi
fi
dnl all other thread tests fail, try BSD's -pthread
if test $have_pthreads = "no"; then
AC_PTHREAD_FREEBSD
fi
AC_SUBST(THREADLIBS)
dnl Solaris needs rt or posix4 libraries for nanosleep()
AC_SEARCH_LIBS(nanosleep,[rt posix4],,[
echo "Error: nanosleep() needed for timing operations."
exit 1
])
AC_ARG_WITH(nagios_user,AC_HELP_STRING([--with-nagios-user=<user>],[sets user name to run nagios]),nagios_user=$withval,nagios_user=nagios)
AC_ARG_WITH(nagios_group,AC_HELP_STRING([--with-nagios-group=<grp>],[sets group name to run nagios]),nagios_grp=$withval,nagios_grp=nagios)
AC_SUBST(nagios_user)
AC_SUBST(nagios_grp)
AC_DEFINE_UNQUOTED(DEFAULT_NAGIOS_USER,"$nagios_user",[user name to run nagios])
AC_DEFINE_UNQUOTED(DEFAULT_NAGIOS_GROUP,"$nagios_grp",[group name to run nagios])
INSTALL_OPTS="-o $nagios_user -g $nagios_grp"
AC_SUBST(INSTALL_OPTS)
AC_ARG_WITH(command_user,AC_HELP_STRING([--with-command-user=<user>],[sets user name for command access]),command_user=$withval,command_user=$nagios_user)
AC_ARG_WITH(command_group,AC_HELP_STRING([--with-command-group=<grp>],[sets group name for command access]),command_grp=$withval,command_grp=$nagios_grp)
AC_SUBST(command_user)
AC_SUBST(command_grp)
COMMAND_OPTS="-o $command_user -g $command_grp"
AC_SUBST(COMMAND_OPTS)
dnl Check for location of mail program
MAIL_PROG=no
AC_ARG_WITH(mail,--with-mail=<path_to_mail> sets path to equivalent program to mail,MAIL_PROG=$withval,MAIL_PROG=no)
if test x$MAIL_PROG = xno; then
AC_PATH_PROG(MAIL_PROG,mail)
fi
dnl Fix for systems that don't (yet) have mail/mailx installed...
if test x$MAIL_PROG = x; then
MAIL_PROG="/bin/mail"
fi
AC_SUBST(MAIL_PROG)
dnl Check for location of Apache conf.d directory
HTTP_CONF=no
AC_ARG_WITH(httpd_conf,--with-httpd-conf=<path_to_conf> sets path to Apache conf.d directory,HTTPD_CONF=$withval,HTTPD_CONF=no)
if test x$HTTPD_CONF = xno; then
if test -d /etc/httpd/conf.d; then
HTTPD_CONF="/etc/httpd/conf.d"
elif test -d /etc/apache2/conf.d; then
HTTPD_CONF="/etc/apache2/conf.d"
elif test -d /etc/apache/conf.d; then
HTTPD_CONF="/etc/apache/conf.d"
else
HTTPD_CONF="/etc/httpd/conf.d"
fi
fi
AC_SUBST(HTTPD_CONF)
dnl Location of check result path
CHECKRESULTDIR=no
AC_ARG_WITH(checkresult-dir,--with-checkresult-dir=<path> sets path to check results spool directory,CHECKRESULTDIR=$withval,CHECKRESULTDIR=no)
if test x$CHECKRESULTDIR = xno; then
CHECKRESULTDIR="$localstatedir/spool/checkresults"
fi
AC_SUBST(CHECKRESULTDIR)
dnl Location of check result path
TMPDIR=no
AC_ARG_WITH(temp-dir,--with-temp-dir=<path> sets path to temp directory,TMPDIR=$withval,TMPDIR=no)
if test x$TMPDIR = xno; then
TMPDIR="/tmp"
fi
AC_SUBST(TMPDIR)
dnl Check for location of init scripts
init_dir=/etc/rc.d/init.d
if test -d /etc/rc.d/init.d; then
init_dir="/etc/rc.d/init.d"
elif test -d /usr/local/etc/rc.d; then
init_dir="/usr/local/etc/rc.d"
elif test -d /etc/rc.d; then
init_dir="/etc/rc.d"
elif test -d /etc/init.d; then
init_dir="/etc/init.d"
elif test -d /sbin/init.d; then
init_dir="/sbin/init.d"
fi
dnl User can override init script location
AC_ARG_WITH(init_dir,--with-init-dir=<path> sets directory to place init script into,init_dir=$withval)
AC_SUBST(init_dir)
dnl User can override lock file location
AC_ARG_WITH(lockfile,--with-lockfile=<path> sets path and file name for lock file,lockfile=$withval,lockfile=$localstatedir/nagios.lock)
AC_SUBST(lockfile)
dnl Default xdata routines...
XSDTYPE=default
XCDTYPE=default
XRDTYPE=default
XODTYPE=template
XPDTYPE=default
XDDTYPE=default
XSDCOMMENT=
XCDCOMMENT=
XRDCOMMENT=
XODCOMMENT=
XPDCOMMENT=
XDDCOMMENT=
USE_MYSQL=no
USE_PGSQL=no
dnl Status data
AC_DEFINE_UNQUOTED(USE_XSDDEFAULT,,[use default routines (in xdata/xsddefault.*) for status data I/O...])
XSDC="xsddefault.c"
XSDH="xsddefault.h"
XSDCOMMENT="Default (text file)"
echo "We'll use default routines (in xdata/xsddefault.*) for status data I/O..."
AC_SUBST(XSDC)
AC_SUBST(XSDH)
dnl Comment data
AC_DEFINE_UNQUOTED(USE_XCDDEFAULT,,[use default routines (in xdata/xcddefault.*) for comment data I/O...])
XCDC="xcddefault.c"
XCDH="xcddefault.h"
XCDCOMMENT="Default (text file)"
echo "We'll use default routines (in xdata/xcddefault.*) for comment data I/O..."
AC_SUBST(XCDC)
AC_SUBST(XCDH)
dnl Retention data
AC_DEFINE_UNQUOTED(USE_XRDDEFAULT,,[use default routines (in xdata/xrddefault.*) for retention data I/O...])
XRDC="xrddefault.c"
XRDH="xrddefault.h"
XRDCOMMENT="Default (text file)"
echo "We'll use default routines (in xdata/xrddefault.*) for retention data I/O..."
AC_SUBST(XRDC)
AC_SUBST(XRDH)
dnl Object data
AC_DEFINE_UNQUOTED(USE_XODTEMPLATE,,[use template-based routines (in xdata/xodtemplate.*) for object data I/O...])
XODC="xodtemplate.c"
XODH="xodtemplate.h"
XODCOMMENT="Template-based (text file)"
echo "We'll use template-based routines (in xdata/xodtemplate.*) for object data I/O..."
AC_SUBST(XODC)
AC_SUBST(XODH)
dnl Performance data
AC_DEFINE_UNQUOTED(USE_XPDDEFAULT,,[use default routines (in xdata/xpddefault.*) for performance data I/O...])
XPDC="xpddefault.c"
XPDH="xpddefault.h"
XPDCOMMENT="Default (external commands)"
echo "We'll use default routines (in xdata/xpddefault.*) for performance data I/O..."
AC_SUBST(XPDC)
AC_SUBST(XPDH)
dnl Downtime data
AC_DEFINE_UNQUOTED(USE_XDDDEFAULT,,[use default routines (in xdata/xdddefault.*) for scheduled downtime data I/O...])
XDDC="xdddefault.c"
XDDH="xdddefault.h"
XDDCOMMENT="Default (text file)"
echo "We'll use default routines (in xdata/xdddefault.*) for scheduled downtime data I/O..."
AC_SUBST(XDDC)
AC_SUBST(XDDH)
dnl Optional GD library and include paths
AC_ARG_WITH(gd-lib,--with-gd-lib=DIR sets location of the gd library,[
LDFLAGS="${LDFLAGS} -L${withval}"
LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}"
])
AC_ARG_WITH(gd-inc,--with-gd-inc=DIR sets location of the gd include files,[
CFLAGS="${CFLAGS} -I${withval}"
])
TRYGD=yep
dnl statusmap CGI enabled by default, unless users chooses not to use it
TRYSTATUSMAP=yep
AC_ARG_ENABLE(statusmap,--disable-statusmap=disables compilation of statusmap CGI,TRYSTATUSMAP=nope)
dnl statuswrl CGI enabled by default, unless users chooses not to use it
TRYSTATUSWRL=yep
AC_ARG_ENABLE(statuswrl,--disable-statuswrl=disables compilation of statuswrl (VRML) CGI,TRYSTATUSWRL=nope)
if test x$TRYSTATUSWRL = xyep; then
AC_DEFINE_UNQUOTED(USE_STATUSWRL,,[statuswrl CGI enabled by default, unless users chooses not to use it])
CGIEXTRAS="$CGIEXTRAS statuswrl.cgi"
fi
dnl JMD_CHECK_LIB_ORDER(LIBRARY, FUNCTION, ORDER [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND
dnl [, OTHER-LIBRARIES]]])
AC_DEFUN([JMD_CHECK_LIB_ORDER],
[AC_MSG_CHECKING([for $2 in -l$1 (order $3)])
dnl Use a cache variable name containing both the library and function name,
dnl because the test really is for library $1 defining function $2, not
dnl just for library $1. Separate tests with the same $1 and different $2s
dnl may have different results.
ac_lib_var=`echo $1['_']$2['_']$3 | sed 'y%./+-%__p_%'`
AC_CACHE_VAL(ac_cv_lib_$ac_lib_var,
[ac_save_LIBS="$LIBS"
LIBS="-l$1 $6 $LIBS"
AC_TRY_LINK(dnl
ifelse([AC_LANG], [FORTRAN77], ,
ifelse([$2], [main], , dnl Avoid conflicting decl of main.
[/* Override any gcc2 internal prototype to avoid an error. */
]ifelse([AC_LANG], CPLUSPLUS, [#ifdef __cplusplus
extern "C"
#endif
])dnl
[/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char $2();
])),
[$2()],
eval "ac_cv_lib_$ac_lib_var=yes",
eval "ac_cv_lib_$ac_lib_var=no")
LIBS="$ac_save_LIBS"
])dnl
if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
AC_MSG_RESULT(yes)
ifelse([$4], ,
[changequote(, )dnl
ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
-e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
changequote([, ])dnl
AC_DEFINE_UNQUOTED($ac_tr_lib)
LIBS="-l$1 $LIBS"
], [$4])
else
AC_MSG_RESULT(no)
ifelse([$5], , , [$5
])dnl
fi
])
dnl Should we try and detect the GD libs?
if test x$TRYGD = xyep; then
dnl libiconv is required on some systems - tack it on if found
AC_CHECK_LIB(iconv,main,ICONV=-liconv,)
dnl See if the GD lib is available and supports PNG images...
dnl GD > 1.8.3 requires the TrueType library to be present as well, so test for that first...
JMD_CHECK_LIB_ORDER(gd,gdImagePng,1,[
GDLIBFOUND=yep
GDLIBS="-lgd -lttf -lpng -ljpeg -lz -lm"
],:,[-lttf -lpng -ljpeg -lz -lm])
dnl GD > 1.8.1 requires the jpeg library to be present as well, so test for that...
if test x$GDLIBFOUND = x; then
JMD_CHECK_LIB_ORDER(gd,gdImagePng,2,[
GDLIBFOUND=yep
GDLIBS="-lgd $ICONV -lpng -ljpeg -lz -lm"
],:,[$ICONV -lpng -ljpeg -lz -lm])
fi
dnl If we failed the first test, try without jpeg library
if test x$GDLIBFOUND = x; then
JMD_CHECK_LIB_ORDER(gd,gdImagePng,3,[
GDLIBFOUND=yep
GDLIBS="-lgd $ICONV -lz -lm -lpng"
],:,[$ICONV -lz -lm -lpng])
fi
dnl We failed again, so try a different library ordering (without jpeg libs)
if test x$GDLIBFOUND = x; then
JMD_CHECK_LIB_ORDER(gd,gdImagePng,4,[
GDLIBFOUND=yep
GDLIBS="-lgd $ICONV -lpng -lz -lm"
],:,[$ICONV -lpng -lz -lm])
fi
dnl Did we find the necessary GD libraries?
if test x$GDLIBFOUND = x; then
echo ""
echo ""
echo "*** GD, PNG, and/or JPEG libraries could not be located... *********"
echo ""
echo "Boutell's GD library is required to compile the statusmap, trends"
echo "and histogram CGIs. Get it from http://www.boutell.com/gd/, compile"
echo "it, and use the --with-gd-lib and --with-gd-inc arguments to specify"
echo "the locations of the GD library and include files."
echo ""
echo "NOTE: In addition to the gd-devel library, you'll also need to make"
echo " sure you have the png-devel and jpeg-devel libraries installed"
echo " on your system."
echo ""
echo "NOTE: After you install the necessary libraries on your system:"
echo " 1. Make sure /etc/ld.so.conf has an entry for the directory in"
echo " which the GD, PNG, and JPEG libraries are installed."
echo " 2. Run 'ldconfig' to update the run-time linker options."
echo " 3. Run 'make clean' in the Nagios distribution to clean out"
echo " any old references to your previous compile."
echo " 4. Rerun the configure script."
echo ""
echo "NOTE: If you can't get the configure script to recognize the GD libs"
echo " on your system, get over it and move on to other things. The"
echo " CGIs that use the GD libs are just a small part of the entire"
echo " Nagios package. Get everything else working first and then"
echo " revisit the problem. Make sure to check the nagios-users"
echo " mailing list archives for possible solutions to GD library"
echo " problems when you resume your troubleshooting."
echo ""
echo "********************************************************************"
echo ""
echo ""
dnl We found the GD lib!
else
echo "GD library was found!"
if test x$TRYSTATUSMAP = xyep; then
AC_DEFINE_UNQUOTED(USE_STATUSMAP,,[defined if the user chose to include status map])
CGIEXTRAS="$CGIEXTRAS statusmap.cgi"
AC_CHECK_LIB(gd,gdImageCreateTrueColor,
AC_DEFINE(HAVE_GDIMAGECREATETRUECOLOR,1,
[Define if your gd library has gdImageCreateTrueColor]))
fi
dnl compile trends CGI
AC_DEFINE_UNQUOTED(USE_TRENDS,,[compile trends CGI])
CGIEXTRAS="$CGIEXTRAS trends.cgi"
dnl compile histogram CGI
AC_DEFINE_UNQUOTED(USE_HISTOGRAM,,[compile histogram CGI])
CGIEXTRAS="$CGIEXTRAS histogram.cgi"
fi
fi
AC_ARG_WITH(cgiurl,--with-cgiurl=<local-url> sets URL for cgi programs (do not use a trailing slash),cgiurl=$withval,cgiurl=/nagios/cgi-bin)
AC_ARG_WITH(htmurl,--with-htmurl=<local-url> sets URL for public html,htmurl=$withval,htmurl=/nagios)
AC_SUBST(htmurl)
AC_SUBST(cgiurl)
USE_NANOSLEEP=yes
AC_ARG_ENABLE(nanosleep,--enable-nanosleep enables use of nanosleep (instead of sleep) in event timing,USE_NANOSLEEP=$enableval,USE_NANOSLEEP=yes)
if test x$USE_NANOSLEEP = xyes; then
AC_DEFINE_UNQUOTED(USE_NANOSLEEP,,[enables use of nanosleep (instead of sleep)])
fi
USE_EVENTBROKER=yes
AC_ARG_ENABLE(event-broker,--enable-event-broker enables integration of event broker routines,USE_EVENTBROKER=$enableval,USE_EVENTBROKER=yes)
BROKER_LDFLAGS=""
BROKERLIBS="";
some_dl_found="no";
if test x$USE_EVENTBROKER = xyes; then
dnl Which loader library should we use? libtdl or dl?
dnl Hopefully this will be portable and not give us headaches...
AC_CHECK_HEADER(ltdl.h,[
AC_CHECK_LIB(ltdl,lt_dlinit,[
AC_DEFINE(HAVE_LTDL_H,,[Which loader library should we use? libtdl or dl?])
some_dl_found="yes"
BROKERLIBS="$BROKERLIBS -lltdl"
])
])
if test "x$some_dl_found" != xyes; then
AC_CHECK_HEADER(dlfcn.h,[
AC_CHECK_LIB(dl,dlopen,[
AC_DEFINE(HAVE_DLFCN_H,,[Which loader library should we use? libtdl or dl?])
some_dl_found="yes"
BROKERLIBS="$BROKERLIBS -ldl"
])
])
fi
dnl - Modified from www.erlang.org
# Check how to export functions from the broker executable, needed
# when dynamically loaded drivers are loaded (so that they can find
# broker functions).
# OS'es with ELF executables using the GNU linker (Linux and recent *BSD,
# in rare cases Solaris) typically need '-Wl,-export-dynamic' (i.e. pass
# -export-dynamic to the linker - also known as -rdynamic and some other
# variants); some sysVr4 system(s) instead need(s) '-Wl,-Bexport'.
# AIX 4.x (perhaps only for x>=2) wants -Wl,-bexpall,-brtl and doesn't
# reliably return an error for others, thus we separate it out.
# Otherwise we assume that if the linker accepts the flag, it is needed.
AC_MSG_CHECKING(for extra flags needed to export symbols)
case $host_os in
aix4*|aix5*)
BROKER_LDFLAGS="$BROKER_LDFLAGS -Wl,-bexpall,-brtl"
;;
bsdi*)
BROKER_LDFLAGS="$BROKER_LDFLAGS -rdynamic"
;;
*)
save_ldflags="$LDFLAGS"
LDFLAGS=-Wl,-export-dynamic
AC_TRY_LINK(,,[BROKER_LDFLAGS="$BROKER_LDFLAGS -Wl,-export-dynamic"], [
LDFLAGS=-Wl,-Bexport
AC_TRY_LINK(,,[BROKER_LDFLAGS="$BROKER_LDFLAGS -Wl,-Bexport"],
AC_MSG_RESULT(none))])
LDFLAGS="$save_ldflags"
;;
esac
AC_SUBST(BROKER_LDFLAGS)
AC_SUBST(BROKERLIBS)
test "x$BROKER_LDFLAGS" != x && AC_MSG_RESULT([$BROKER_LDFLAGS])
dnl - Modified version from www.erlang.org
dnl - Some 12/15/05 mods made after reading http://xaxxon.slackworks.com/phuku/dl.html
AC_MSG_CHECKING(for linker flags for loadable modules)
case $host_os in
solaris2*|sysv4*)
MOD_LDFLAGS="-G"
;;
aix4*|aix5*)
#MOD_LDFLAGS="-G -bnoentry -bexpall"
MOD_LDFLAGS="-G -bM:SRE -bnoentry -bexpall"
;;
freebsd2*)
# Non-ELF GNU linker
MOD_LDFLAGS="-Bshareable"
;;
darwin*)
# Mach-O linker, a shared lib and a loadable
# object file is not the same thing.
MOD_LDFLAGS="-bundle -flat_namespace -undefined suppress"
MOD_CFLAGS="$MOD_CFLAGS -fno-common"
;;
linux* | k*bsd*-gnu*)
# assume GNU linker and ELF
MOD_LDFLAGS="-shared"
MOD_CFLAGS="-fPIC"
;;
freebsd*)
MOD_LDFLAGS="-shared"
MOD_CFLAGS="-fPIC"
;;
*)
# assume GNU linker and ELF
MOD_LDFLAGS="-shared"
;;
esac
AC_MSG_RESULT([$MOD_LDFLAGS])
AC_SUBST(MOD_CFLAGS)
AC_SUBST(MOD_LDFLAGS)
AC_DEFINE_UNQUOTED(USE_EVENT_BROKER,,[defined to bring in the event broker objects])
BROKER_O="broker.o nebmods.o"
AC_SUBST(BROKER_O)
BROKER_H="../include/broker.h ../include/nebmods.h ../include/nebmodules.h ../include/nebcallbacks.h ../include/neberrors.h"
AC_SUBST(BROKER_H)
fi
USEPERL=no;
INSTALLPERLSTUFF=no;
AC_ARG_ENABLE(embedded-perl,--enable-embedded-perl will enable embedded Perl interpreter,[
USEPERL=$enableval
]
,USEPERL=no)
PERLCACHE=yes;
AC_ARG_WITH(perlcache,--with-perlcache turns on cacheing of internally compiled Perl scripts,[
PERLCACHE=$withval
]
,[
AC_DEFINE(DO_CLEAN,"1",[whether to clean cached compiled perl])
PERLCACHE=yes;
])
dnl Is embedded Perl being compiled in?
if test x$USEPERL = xyes; then
AC_DEFINE_UNQUOTED(EMBEDDEDPERL,,[Is embedded Perl being compiled in?])
PERLLIBS="`perl -MExtUtils::Embed -e ldopts`"
PERLDIR="`perl -MConfig -e 'print $Config{installsitearch}'`"
CFLAGS="${CFLAGS} `perl -MExtUtils::Embed -e ccopts`"
USEPERL=yes
INSTALLPERLSTUFF=yes;
PERLXSI_O=perlxsi.o
OBJS="${OBJS} ${PERLXSI_O}"
echo "creating base/perlxsi.c"
perl -MExtUtils::Embed -e xsinit -- -o base/perlxsi.c
echo "Embedded Perl interpreter will be compiled in..."
dnl Is caching enabled?
if test x$PERLCACHE = xyes; then
AC_DEFINE(DO_CLEAN,"0",[whether to clean cached compiled perl])
PERLCACHE=yes;
echo "Internally compiled Perl scripts will be cached..."
else
AC_DEFINE(DO_CLEAN,"1",[whether to clean cached compiled perl])
echo "Internally compiled Perl scripts will NOT be cached..."
fi
fi
dnl Test if we're using threaded Perl (patch by Chip Ach)
if test x$USEPERL = xyes; then
if (perl -e 'use Config;exit -1 unless ($Config{'usethreads'});'); then
echo "Using threaded perl"
AC_DEFINE_UNQUOTED(THREADEDPERL,,[defined if we're using threaded Perl])
fi
fi
dnl Option for compiling under CYGWIN
nagios_name=nagios
nagiostats_name=nagiostats
cygwin=no
AC_ARG_ENABLE(cygwin,--enable-cygwin enables building under the CYGWIN environment,[
cygwin=$enableval
])
if test x$cygwin = xyes; then
CFLAGS="${CFLAGS} -DCYGWIN"
nagios_name=nagios.exe;
nagiostats_name=nagiostats.exe;
fi
AC_SUBST(nagios_name)
AC_SUBST(nagiostats_name)
dnl Should predictive failure routines be compiled in?
dnl AC_ARG_ENABLE(failure-prediction,--enable-failure-prediction will enable integration with failure prediction module (NOT HERE YET!),[
dnl AC_DEFINE_UNQUOTED(PREDICT_FAILURES)
dnl BASEEXTRALIBS="$BASEEXTRALIBS \$(FDATALIBS)"
dnl echo "Failure prediction routines (incomplete!) will be compiled in..."
dnl ])
dnl Find traceroute
AC_PATH_PROG(PATH_TO_TRACEROUTE,traceroute)
AC_DEFINE_UNQUOTED(TRACEROUTE_COMMAND,"$PATH_TO_TRACEROUTE",[traceroute command to use])
dnl Package directory for Solaris pkgmk (and other OSs, eventually)
dnl VERSION=`grep 1.0 include/common.h | cut -d ' ' -f 3 | sed 's/"//g'`
VERSION=$PKG_VERSION
PACKDIR=`pwd`/pkg
AC_SUBST(PACKDIR)
AC_SUBST(VERSION)
AC_MSG_CHECKING(for type va_list)
AC_TRY_COMPILE([#ifdef __STDC__
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#else
#include <sys/types.h>
#include <stdio.h>
#include <varargs.h>
#endif],
[va_list args;],
[AC_MSG_RESULT(yes)],
[AC_DEFINE(NEED_VA_LIST,,[defined if va_list fails to compile]) AC_MSG_RESULT(no)])
dnl Check if we should build local libtap
dnl From Nagios Plugins
dnl Have disabled autodetection of system library until later
AC_ARG_ENABLE(libtap,
AC_HELP_STRING([--enable-libtap],
[Enable built-in libtap for unit-testing (default: no).]),
[enable_libtap=$enableval],
[enable_libtap=no])
#Disabled for moment
#AM_CONDITIONAL([USE_LIBTAP_LOCAL],[test "$enable_libtap" = "yes"])
# Disabled for moment
# If not local, check if we can use the system one
#if test "$enable_libtap" != "yes" ; then
# dnl Check for libtap, to run perl-like tests
# AC_CHECK_LIB(tap, plan_tests,
# enable_libtap="yes"
# )
#fi
# Finally, define tests if we use libtap
if test "$enable_libtap" = "yes" ; then
AC_CONFIG_SUBDIRS([tap])
USE_LIBTAP=yes
else
USE_LIBTAP=no
fi
AC_SUBST(USE_LIBTAP)
AC_SUBST(CGIEXTRAS)
AC_SUBST(GDLIBS)
AC_SUBST(PERLLIBS)
AC_SUBST(PERLDIR)
AC_SUBST(PERLXSI_O)
AC_SUBST(BASEEXTRALIBS)
AC_SUBST(INITDIR)
AC_SUBST(INSTALLPERLSTUFF)
AC_SUBST(USE_EVENTBROKER)
AC_PATH_PROG(PERL,perl)
AC_OUTPUT(Makefile subst pkginfo base/Makefile common/Makefile contrib/Makefile cgi/Makefile html/Makefile module/Makefile xdata/Makefile daemon-init t/Makefile t-tap/Makefile)
perl subst include/locations.h
perl subst html/config.inc.php
echo ""
echo "Creating sample config files in sample-config/ ..."
perl subst sample-config/nagios.cfg
perl subst sample-config/cgi.cfg
perl subst sample-config/resource.cfg
perl subst sample-config/httpd.conf
perl subst sample-config/mrtg.cfg
perl subst sample-config/template-object/templates.cfg
perl subst sample-config/template-object/commands.cfg
perl subst sample-config/template-object/timeperiods.cfg
perl subst sample-config/template-object/contacts.cfg
perl subst sample-config/template-object/localhost.cfg
perl subst sample-config/template-object/windows.cfg
perl subst sample-config/template-object/printer.cfg
perl subst sample-config/template-object/switch.cfg
dnl Review options
echo ""
echo ""
AC_MSG_RESULT([*** Configuration summary for $PKG_NAME $PKG_VERSION $PKG_REL_DATE ***:])
echo ""
echo " General Options:"
echo " -------------------------"
AC_MSG_RESULT([ Nagios executable: $nagios_name])
AC_MSG_RESULT([ Nagios user/group: $nagios_user,$nagios_grp])
AC_MSG_RESULT([ Command user/group: $command_user,$command_grp])
if test x$USEPERL = xyes; then
if test x$PERLCACHE = xyes; then
AC_MSG_RESULT([ Embedded Perl: yes, with caching])
else
AC_MSG_RESULT([ Embedded Perl: yes, without caching])
fi
else
AC_MSG_RESULT([ Embedded Perl: no])
fi
if test x$USE_EVENTBROKER = xyes; then
AC_MSG_RESULT([ Event Broker: yes])
else
AC_MSG_RESULT([ Event Broker: no])
fi
AC_MSG_RESULT([ Install \${prefix}: $prefix])
AC_MSG_RESULT([ Lock file: $lockfile])
AC_MSG_RESULT([ Check result directory: $CHECKRESULTDIR])
AC_MSG_RESULT([ Init directory: $init_dir])
AC_MSG_RESULT([ Apache conf.d directory: $HTTPD_CONF])
AC_MSG_RESULT([ Mail program: $MAIL_PROG])
AC_MSG_RESULT([ Host OS: $host_os])
echo ""
echo " Web Interface Options:"
echo " ------------------------"
AC_MSG_RESULT([ HTML URL: http://localhost$htmurl/])
AC_MSG_RESULT([ CGI URL: http://localhost$cgiurl/])
AC_MSG_RESULT([ Traceroute (used by WAP): $PATH_TO_TRACEROUTE])
dnl echo ""
dnl echo " External Data Routines:"
dnl echo " ------------------------"
dnl AC_MSG_RESULT([ Status data: $XSDCOMMENT])
dnl AC_MSG_RESULT([ Comment data: $XCDCOMMENT])
dnl AC_MSG_RESULT([ Downtime data: $XDDCOMMENT])
dnl AC_MSG_RESULT([ Peformance data: $XPDCOMMENT])
echo ""
echo ""
echo "Review the options above for accuracy. If they look okay,"
echo "type 'make all' to compile the main program and CGIs."
echo ""

2
contrib/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
perlxsi.c
Makefile

90
contrib/Makefile.in Normal file
View File

@ -0,0 +1,90 @@
###############################
# Makefile for contrib software
#
# Last Modified: 05-19-2008
###############################
CC=@CC@
CFLAGS=@CFLAGS@ @DEFS@
LDFLAGS=@LDFLAGS@ @LIBS@
# Source code directories
SRC_INCLUDE=../include
SRC_COMMON=../common
SRC_CGI=../cgi
# Generated automatically from configure script
SNPRINTF_O=@SNPRINTF_O@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
prefix=@prefix@
exec_prefix=@exec_prefix@
CGIDIR=@sbindir@
BINDIR=@bindir@
CGIS=traceroute.cgi daemonchk.cgi
UTILS=mini_epn new_mini_epn convertcfg
ALL=$(CGIS) $(UTILS)
CGI_C=$(SRC_CGI)/getcgi.c
CGI_O=$(SRC_CGI)/getcgi.o $(SNPRINTF_O)
CGI_H=$(SRC_INCLUDE)/getcgi.h
COMMON_H=$(SRC_INCLUDE)/config.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/locations.h
##############################################################################
# standard targets (all, clean, distclean, devclean, install)
all: $(ALL)
clean:
rm -f convertcfg daemonchk.cgi mini_epn new_mini_epn core *.o
rm -f */*/*~
rm -f */*~
rm -f *~
distclean: clean
rm -f Makefile
devclean: distclean
install:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CGIDIR)
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(BINDIR)
for f in $(CGIS); do $(INSTALL) -m 775 $(INSTALL_OPTS) $$f $(DESTDIR)$(CGIDIR); done
for f in $(UTILS); do $(INSTALL) -m 775 $(INSTALL_OPTS) $$f $(DESTDIR)$(BINDIR); done
##############################################################################
# rules and dependencies for actual target programs
daemonchk.cgi: daemonchk.o $(CGI_O) $(CGI_H) $(COMMON_H)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(CGI_O)
daemonchk.o: daemonchk.c
$(CC) $(CLFAGS) -c -o $@ $< -I$(SRC_INCLUDE)
mini_epn: mini_epn.c
perl -MExtUtils::Embed -e xsinit
$(CC) $(CFLAGS) -c perlxsi.c `perl -MExtUtils::Embed -e ccopts`
$(CC) $(CFLAGS) -c mini_epn.c `perl -MExtUtils::Embed -e ccopts`
$(CC) $(CFLAGS) $(LDFLAGS) perlxsi.o mini_epn.o `perl -MExtUtils::Embed -e ccopts -e ldopts` -o $@
new_mini_epn: new_mini_epn.c
perl -MExtUtils::Embed -e xsinit
$(CC) $(CFLAGS) -c perlxsi.c `perl -MExtUtils::Embed -e ccopts`
$(CC) $(CFLAGS) -c new_mini_epn.c `perl -MExtUtils::Embed -e ccopts`
$(CC) $(CFLAGS) $(LDFLAGS) perlxsi.o new_mini_epn.o `perl -MExtUtils::Embed -e ccopts -e ldopts` -o $@
##############################################################################
# dependencies
$(CGI_O): $(CGI_C)
cd $(SRC_CGI) && make $(CGI_O)
##############################################################################
# implicit rules
%.cgi : %.c
$(CC) $(CFLAGS) $(LDFLAGS) $< $(CGI_O) -o $@

48
contrib/README Normal file
View File

@ -0,0 +1,48 @@
#####################
Nagios Contrib README
#####################
This directory contains various programs, scripts, etc. that
have been contribed by various people. Read the source code
if you want to find who did what.
Here is a description of what you'll find...
Conversion Programs:
--------------------
- convertcfg.c is a program to quickly convert old "host" config
files to the new template-based object config files. It can also
convert extended host information definitions. Type 'make convertcfg'
to compile the utility.
Additional CGIs:
----------------
- traceroute.cgi is (surprise) a CGI that allows you to do a traceroute
to a specific IP address. Simply do a 'chmod +x' to make it executeable
and place it in the CGI directory (i.e. /usr/local/nagios/sbin).
Requires Perl.
- daemonchk.c is a CGI contributed by Karl DeBisschop that can test to
see whether or not the Nagios process is running.
Miscellaneous Goodies:
----------------------
- htaccess.sample is a *sample* .htaccess file that can be used with
Apache to require password authentication for access to the web
interface.
- mini_epn.c is a mini embedded Perl interpreter that can be used to
test the feasibility of running various Perl plugins with the
embedded Perl interpreter compiled in.

747
contrib/convertcfg.c Normal file
View File

@ -0,0 +1,747 @@
/************************************************************************
*
* CONVERTCFG.C - Config File Convertor
*
* Copyright (c) 2001-2005 Ethan Galstad (egalstad@nagios.org)
* Last Modified: 08-12-2005
*
* License:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *my_strsep(char **, const char *);
int main(int argc, char **argv) {
FILE *fp;
char *temp_ptr;
char *temp_ptr2;
char input[8096];
int notify_recovery;
int notify_warning;
int notify_critical;
int notify_down;
int notify_unreachable;
int option;
int have_template = 0;
int x = 0, y = 0;
char *host_name;
char *service_description;
char *host_name2;
char *service_description2;
if(argc != 3) {
printf("Nagios Config File Converter\n");
printf("Written by Ethan Galstad (egalstad@nagios.org)\n");
printf("Last Modified: 08-12-2005\n");
printf("\n");
printf("Usage: %s <config file> <object type>\n", argv[0]);
printf("\n");
printf("Valid object types include:\n");
printf("\n");
printf("\ttimeperiods\n");
printf("\tcommands\n");
printf("\tcontacts\n");
printf("\tcontactgroups\n");
printf("\thosts\n");
printf("\thostgroups\n");
printf("\thostgroupescalationss\n");
printf("\tservices\n");
printf("\tservicedependencies\n");
printf("\tserviceescalations\n");
printf("\n");
printf("\thostextinfo\n");
printf("\tserviceextinfo\n");
printf("\n");
printf("Notes:\n");
printf("\n");
printf("This utility is designed to aide you in converting your old 'host'\n");
printf("config file(s) to the new template-based config file style. It is\n");
printf("also capable of converting extended host and service information\n");
printf("definitions in your old CGI config file.\n");
printf("\n");
printf("Supply the name of your old 'host' config file (or your old CGI config\n");
printf("file if you're converting extended host/service definitions) on the\n");
printf("command line, along with the type of object you would like to produce\n");
printf("a new config file for. Your old config file is not overwritten - new\n");
printf("configuration data is printed to standard output, so you can redirect it\n");
printf("wherever you like.\n");
printf("\n");
printf("Please note that you can only specify one type of object at a time\n");
printf("on the command line.\n");
printf("\n");
printf("IMPORTANT: This utility will generate Nagios 1.x compliant config files.\n");
printf("However, the config files are not totally compatible with Nagios 2.x, so\n");
printf("you will have to do some manual tweaking.\n");
printf("\n");
return -1;
}
fp = fopen(argv[1], "r");
if(fp == NULL) {
printf("Error: Could not open file '%s' for reading.\n", argv[1]);
return -1;
}
for(fgets(input, sizeof(input) - 1, fp); !feof(fp); fgets(input, sizeof(input) - 1, fp)) {
/* skip blank lines and comments */
if(input[0] == '#' || input[0] == '\x0' || input[0] == '\n' || input[0] == '\r')
continue;
/* timeperiods */
if(strstr(input, "timeperiod[") && !strcmp(argv[2], "timeperiods")) {
temp_ptr2 = &input[0];
temp_ptr = my_strsep(&temp_ptr2, "[");
temp_ptr = my_strsep(&temp_ptr2, "]");
printf("# '%s' timeperiod definition\n", temp_ptr);
printf("define timeperiod{\n");
/*printf("\tname\t\t%s\n",temp_ptr);*/
printf("\ttimeperiod_name\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\talias\t\t%s\n", temp_ptr + 1);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tsunday\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tmonday\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\ttuesday\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\twednesday\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tthursday\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tfriday\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";\r\n");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tsaturday\t%s\n", temp_ptr);
printf("\t}\n\n\n");
}
/* commands */
if(strstr(input, "command[") && !strcmp(argv[2], "commands")) {
temp_ptr = strtok(input, "[");
temp_ptr = strtok(NULL, "]");
printf("# '%s' command definition\n", temp_ptr);
printf("define command{\n");
/*printf("\tname\t\t%s\n",temp_ptr);*/
printf("\tcommand_name\t%s\n", temp_ptr);
temp_ptr = strtok(NULL, "\n");
printf("\tcommand_line\t%s\n", temp_ptr + 1);
printf("\t}\n\n\n");
}
/* contacts */
if(strstr(input, "contact[") && !strcmp(argv[2], "contacts")) {
temp_ptr2 = &input[0];
temp_ptr = my_strsep(&temp_ptr2, "[");
temp_ptr = my_strsep(&temp_ptr2, "]");
printf("# '%s' contact definition\n", temp_ptr);
printf("define contact{\n");
/*printf("\tname\t\t\t\t%s\n",temp_ptr);*/
printf("\tcontact_name\t\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\talias\t\t\t\t%s\n", temp_ptr + 1);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tservice_notification_period\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\thost_notification_period\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_recovery = atoi(temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_critical = atoi(temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_warning = atoi(temp_ptr);
option = 0;
printf("\tservice_notification_options\t");
if(notify_recovery == 1 || notify_critical == 1 || notify_warning == 1) {
if(notify_warning == 1) {
printf("w,u");
option = 1;
}
if(notify_critical == 1) {
if(option == 1)
printf(",");
printf("c");
option = 1;
}
if(notify_recovery == 1) {
if(option == 1)
printf(",");
printf("r");
}
}
else
printf("n");
printf("\n");
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_recovery = atoi(temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_down = atoi(temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_unreachable = atoi(temp_ptr);
option = 0;
printf("\thost_notification_options\t");
if(notify_recovery == 1 || notify_down == 1 || notify_unreachable == 1) {
if(notify_down == 1) {
printf("d");
option = 1;
}
if(notify_unreachable == 1) {
if(option == 1)
printf(",");
printf("u");
option = 1;
}
if(notify_recovery == 1) {
if(option == 1)
printf(",");
printf("r");
}
}
else
printf("n");
printf("\n");
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tservice_notification_commands\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\thost_notification_commands\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\temail\t\t\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";\r\n");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tpager\t\t\t\t%s\n", temp_ptr);
printf("\t}\n\n\n");
}
/* contactgroups */
if(strstr(input, "contactgroup[") && !strcmp(argv[2], "contactgroups")) {
temp_ptr = strtok(input, "[");
temp_ptr = strtok(NULL, "]");
printf("# '%s' contact group definition\n", temp_ptr);
printf("define contactgroup{\n");
/*printf("\tname\t\t\t%s\n",temp_ptr);*/
printf("\tcontactgroup_name\t%s\n", temp_ptr);
temp_ptr = strtok(NULL, ";");
printf("\talias\t\t\t%s\n", temp_ptr + 1);
temp_ptr = strtok(NULL, "\n");
printf("\tmembers\t\t\t%s\n", temp_ptr);
printf("\t}\n\n\n");
}
/* hosts */
if(strstr(input, "host[") && !strcmp(argv[2], "hosts")) {
if(have_template == 0) {
printf("# Generic host definition template\n");
printf("define host{\n");
printf("\tname\t\t\t\tgeneric-host\t; The name of this host template - referenced in other host definitions, used for template recursion/resolution\n");
printf("\tactive_checks_enabled\t\t1\t; Active host checks are enabled\n");
printf("\tpassive_checks_enabled\t\t1\t; Passive host checks are enabled/accepted\n");
printf("\tnotifications_enabled\t\t1\t; Host notifications are enabled\n");
printf("\tevent_handler_enabled\t\t1\t; Host event handler is enabled\n");
printf("\tflap_detection_enabled\t\t1\t; Flap detection is enabled\n");
/*printf("\tfailure_prediction_enabled\t1\t; Failure prediction is enabled\n");*/
printf("\tprocess_perf_data\t\t1\t; Process performance data\n");
printf("\tretain_status_information\t1\t; Retain status information across program restarts\n");
printf("\tretain_nonstatus_information\t1\t; Retain non-status information across program restarts\n");
printf("\n");
printf("\tregister\t\t\t0\t; DONT REGISTER THIS DEFINITION - ITS NOT A REAL HOST, JUST A TEMPLATE!\n");
printf("\t}\n\n");
have_template = 1;
}
temp_ptr2 = &input[0];
temp_ptr = my_strsep(&temp_ptr2, "[");
temp_ptr = my_strsep(&temp_ptr2, "]");
printf("# '%s' host definition\n", temp_ptr);
printf("define host{\n");
printf("\tuse\t\t\tgeneric-host\t\t; Name of host template to use\n\n");
printf("\thost_name\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\talias\t\t\t%s\n", temp_ptr + 1);
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\taddress\t\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tparents\t\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tcheck_command\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tmax_check_attempts\t%d\n", atoi(temp_ptr));
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tnotification_interval\t%d\n", atoi(temp_ptr));
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tnotification_period\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_recovery = atoi(temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_down = atoi(temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_unreachable = atoi(temp_ptr);
option = 0;
printf("\tnotification_options\t");
if(notify_recovery == 1 || notify_down == 1 || notify_unreachable == 1) {
if(notify_down == 1) {
printf("d");
option = 1;
}
if(notify_unreachable == 1) {
if(option == 1)
printf(",");
printf("u");
option = 1;
}
if(notify_recovery == 1) {
if(option == 1)
printf(",");
printf("r");
}
}
else
printf("n");
printf("\n");
temp_ptr = my_strsep(&temp_ptr2, ";\r\n");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tevent_handler\t\t%s\n", temp_ptr);
printf("\t}\n\n\n");
}
/* hostgroups */
if(strstr(input, "hostgroup[") && !strcmp(argv[2], "hostgroups")) {
temp_ptr = strtok(input, "[");
temp_ptr = strtok(NULL, "]");
printf("# '%s' host group definition\n", temp_ptr);
printf("define hostgroup{\n");
/*printf("\tname\t\t%s\n",temp_ptr);*/
printf("\thostgroup_name\t%s\n", temp_ptr);
temp_ptr = strtok(NULL, ";");
printf("\talias\t\t%s\n", temp_ptr + 1);
temp_ptr = strtok(NULL, ";");
/*printf("\tcontact_groups\t%s\n",temp_ptr);*/
temp_ptr = strtok(NULL, "\n");
printf("\tmembers\t\t%s\n", temp_ptr);
printf("\t}\n\n\n");
}
/* services */
if(strstr(input, "service[") && !strcmp(argv[2], "services")) {
if(have_template == 0) {
printf("# Generic service definition template\n");
printf("define service{\n");
printf("\tname\t\t\t\tgeneric-service\t; The 'name' of this service template, referenced in other service definitions\n");
printf("\tactive_checks_enabled\t\t1\t; Active service checks are enabled\n");
printf("\tpassive_checks_enabled\t\t1\t; Passive service checks are enabled/accepted\n");
printf("\tparallelize_check\t\t1\t; Active service checks should be parallelized (disabling this can lead to major performance problems)\n");
printf("\tobsess_over_service\t\t1\t; We should obsess over this service (if necessary)\n");
printf("\tcheck_freshness\t\t\t0\t; Default is to NOT check service 'freshness'\n");
printf("\tnotifications_enabled\t\t1\t; Service notifications are enabled\n");
printf("\tevent_handler_enabled\t\t1\t; Service event handler is enabled\n");
printf("\tflap_detection_enabled\t\t1\t; Flap detection is enabled\n");
/*printf("\tfailure_prediction_enabled\t1\t; Failure prediction is enabled\n");*/
printf("\tprocess_perf_data\t\t1\t; Process performance data\n");
printf("\tretain_status_information\t1\t; Retain status information across program restarts\n");
printf("\tretain_nonstatus_information\t1\t; Retain non-status information across program restarts\n");
printf("\n");
printf("\tregister\t\t\t0\t; DONT REGISTER THIS DEFINITION - ITS NOT A REAL SERVICE, JUST A TEMPLATE!\n");
printf("\t}\n\n");
have_template = 1;
}
temp_ptr2 = &input[0];
temp_ptr = my_strsep(&temp_ptr2, "[");
temp_ptr = my_strsep(&temp_ptr2, "]");
printf("# Service definition\n");
printf("define service{\n");
printf("\tuse\t\t\t\tgeneric-service\t\t; Name of service template to use\n\n");
printf("\thost_name\t\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tservice_description\t\t%s\n", temp_ptr + 1);
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tis_volatile\t\t\t%d\n", atoi(temp_ptr));
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tcheck_period\t\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tmax_check_attempts\t\t%d\n", atoi(temp_ptr));
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tnormal_check_interval\t\t%d\n", atoi(temp_ptr));
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tretry_check_interval\t\t%d\n", atoi(temp_ptr));
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tcontact_groups\t\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tnotification_interval\t\t%d\n", atoi(temp_ptr));
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tnotification_period\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_recovery = atoi(temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_critical = atoi(temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
notify_warning = atoi(temp_ptr);
option = 0;
printf("\tnotification_options\t\t");
if(notify_recovery == 1 || notify_critical == 1 || notify_warning == 1) {
if(notify_warning == 1) {
printf("w,u");
option = 1;
}
if(notify_critical == 1) {
if(option == 1)
printf(",");
printf("c");
option = 1;
}
if(notify_recovery == 1) {
if(option == 1)
printf(",");
printf("r");
}
}
else
printf("n");
printf("\n");
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tevent_handler\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";\r\n");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tcheck_command\t\t\t%s\n", temp_ptr);
printf("\t}\n\n\n");
}
/* hostgroup escalations */
if(strstr(input, "hostgroupescalation[") && !strcmp(argv[2], "hostgroupescalations")) {
x++;
temp_ptr2 = &input[0];
temp_ptr = my_strsep(&temp_ptr2, "[");
temp_ptr = my_strsep(&temp_ptr2, "]");
printf("# Hostgroup '%s' escalation definition\n", temp_ptr);
printf("define hostgroupescalation{\n");
printf("\thostgroup_name\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, "-");
printf("\tfirst_notification\t\t%d\n", atoi(temp_ptr + 1));
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tlast_notification\t\t%d\n", atoi(temp_ptr));
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tcontact_groups\t\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";\r\n");
printf("\tnotification_interval\t\t%d\n", atoi(temp_ptr));
printf("\t}\n\n\n");
}
/* service escalations */
if(strstr(input, "serviceescalation[") && !strcmp(argv[2], "serviceescalations")) {
x++;
printf("# Serviceescalation definition\n");
printf("define serviceescalation{\n");
temp_ptr2 = &input[0];
temp_ptr = my_strsep(&temp_ptr2, "[");
host_name = my_strsep(&temp_ptr2, ";");
service_description = my_strsep(&temp_ptr2, "]");
printf("\thost_name\t\t%s\n", host_name);
printf("\tservice_description\t\t%s\n", service_description);
temp_ptr = my_strsep(&temp_ptr2, "-");
printf("\tfirst_notification\t\t%d\n", atoi(temp_ptr + 1));
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tlast_notification\t\t%d\n", atoi(temp_ptr));
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("\tcontact_groups\t\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";\r\n");
printf("\tnotification_interval\t\t%d\n", atoi(temp_ptr));
printf("\t}\n\n\n");
}
/* service dependencies */
if(strstr(input, "servicedependency[") && !strcmp(argv[2], "servicedependencies")) {
temp_ptr2 = &input[0];
temp_ptr = my_strsep(&temp_ptr2, "[");
host_name = my_strsep(&temp_ptr2, ";");
service_description = my_strsep(&temp_ptr2, "]");
host_name2 = my_strsep(&temp_ptr2, ";") + 1;
service_description2 = my_strsep(&temp_ptr2, ";");
temp_ptr = my_strsep(&temp_ptr2, ";");
x++;
printf("# Servicedependency definition\n");
printf("define servicedependency{\n");
printf("\thost_name\t\t\t%s\n", host_name2);
printf("\tservice_description\t\t%s\n", service_description2);
printf("\tdependent_host_name\t\t%s\n", host_name);
printf("\tdependent_service_description\t%s\n", service_description);
printf("\texecution_failure_criteria\t");
for(y = 0; temp_ptr[y] != '\x0'; y++)
printf("%s%c", (y > 0) ? "," : "", temp_ptr[y]);
if(y == 0)
printf("n");
printf("\t; These are the criteria for which check execution will be suppressed\n");
temp_ptr = my_strsep(&temp_ptr2, ";\r\n");
printf("\tnotification_failure_criteria\t");
for(y = 0; temp_ptr[y] != '\x0'; y++)
printf("%s%c", (y > 0) ? "," : "", temp_ptr[y]);
if(y == 0)
printf("n");
printf("\t; These are the criteria for which notifications will be suppressed\n");
printf("\t}\n\n\n");
}
/* extended host info */
if(strstr(input, "hostextinfo[") && !strcmp(argv[2], "hostextinfo")) {
temp_ptr2 = &input[0];
temp_ptr = my_strsep(&temp_ptr2, "[");
temp_ptr = my_strsep(&temp_ptr2, "]");
printf("# '%s' hostextinfo definition\n", temp_ptr);
printf("define hostextinfo{\n");
printf("\thost_name\t\t%s\t\t; The name of the host this data is associated with\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr + 1 != NULL && strcmp(temp_ptr + 1, ""))
printf("\tnotes_url\t\t\t%s\n", temp_ptr + 1);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\ticon_image\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tvrml_image\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\tstatusmap_image\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\ticon_image_alt\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\t2d_coords\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";\r\n");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\t3d_coords\t\t%s\n", temp_ptr);
printf("\t}\n\n\n");
}
/* extended service info */
if(strstr(input, "serviceextinfo[") && !strcmp(argv[2], "serviceextinfo")) {
temp_ptr2 = &input[0];
temp_ptr = my_strsep(&temp_ptr2, "[");
temp_ptr = my_strsep(&temp_ptr2, ";");
printf("# serviceextinfo definition\n", temp_ptr);
printf("define serviceextinfo{\n");
printf("\thost_name\t\t%s\t\t; The name of the service this data is associated with\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, "]");
printf("\tservice_description\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr + 1 != NULL && strcmp(temp_ptr + 1, ""))
printf("\tnotes_url\t\t%s\n", temp_ptr + 1);
temp_ptr = my_strsep(&temp_ptr2, ";");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\ticon_image\t\t%s\n", temp_ptr);
temp_ptr = my_strsep(&temp_ptr2, ";\r\n");
if(temp_ptr != NULL && strcmp(temp_ptr, ""))
printf("\ticon_image_alt\t\t%s\n", temp_ptr);
printf("\t}\n\n\n");
}
}
fclose(fp);
return 0;
}
/* fixes compiler problems under Solaris, since strsep() isn't included */
/* this code is taken from the glibc source */
char *my_strsep(char **stringp, const char *delim) {
char *begin, *end;
begin = *stringp;
if(begin == NULL)
return NULL;
/* A frequent case is when the delimiter string contains only one
character. Here we don't need to call the expensive `strpbrk'
function and instead work using `strchr'. */
if(delim[0] == '\0' || delim[1] == '\0') {
char ch = delim[0];
if(ch == '\0')
end = NULL;
else {
if(*begin == ch)
end = begin;
else
end = strchr(begin + 1, ch);
}
}
else
/* Find the end of the token. */
end = strpbrk(begin, delim);
if(end) {
/* Terminate the token and set *STRINGP past NUL character. */
*end++ = '\0';
*stringp = end;
}
else
/* No more delimiters; this is the last token. */
*stringp = NULL;
return begin;
}

277
contrib/daemonchk.c Normal file
View File

@ -0,0 +1,277 @@
#include "config.h"
#include "common.h"
#include "locations.h"
#include "cgiutils.h"
#include "getcgi.h"
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
#include <stdarg.h>
#define CHARLEN 256
#define max(a,b) ((a)>(b))?(a):(b)
static void document_header(void);
//static void document_footer(void);
static int process_cgivars(void);
static char *strscpy(char *dest, const char *src);
static char *ssprintf(char *str, const char *fmt, ...);
static void terminate(int result, const char *fmt, ...);
static void get_expire_time_string(time_t *raw_time, char *buffer, int buffer_length);
int main(int argc, char **argv) {
FILE *fp;
char *status_file = NULL;
char *lock_file = NULL;
char *proc_file = NULL;
char input_buffer[CHARLEN];
int c, age, pid, testpid, found;
int wt = -1;
int ct = -1;
struct stat statbuf;
time_t current_time;
#ifdef DEFAULT_STATUS_FILE
status_file = strscpy(status_file, DEFAULT_STATUS_FILE);
#else
status_file = strscpy(status_file, "/var/log/nagios/status.log");
#endif
#ifdef DEFAULT_LOCK_FILE
lock_file = strscpy(lock_file, DEFAULT_LOCK_FILE);
#else
lock_file = strscpy(lock_file, "/tmp/nagios.lock");
#endif
if(getenv("REQUEST_METHOD")) {
process_cgivars();
document_header();
}
else { /* get arguments */
while((c = getopt(argc, argv, "+c:w:s:l:")) != EOF) {
switch(c) {
case 'c':
ct = atoi(optarg);
break;
case 'w':
wt = atoi(optarg);
break;
case 's':
status_file = optarg;
break;
case 'l':
lock_file = optarg;
break;
}
}
}
/* find status file, get lastmod time */
if(stat(status_file, &statbuf) == -1) {
printf("NAGIOS CRITICAL - could not find status log: %s\n", status_file);
exit(STATE_CRITICAL);
}
time(&current_time);
age = (int)(current_time - statbuf.st_mtime);
/* find lock file. get pid if it exists */
if(stat(lock_file, &statbuf) == -1) {
printf("NAGIOS CRITICAL - could not find lock file: %s\n", lock_file);
exit(STATE_CRITICAL);
}
fp = fopen(lock_file, "r");
fscanf(fp, "%d", &pid);
fclose(fp);
proc_file = ssprintf(proc_file, "/proc/%d", pid);
if(stat("/proc", &statbuf) == 0) {
if(stat(proc_file, &statbuf) == -1) {
printf("NAGIOS CRITICAL - could not find proc file: %s\n", proc_file);
exit(STATE_CRITICAL);
}
}
else if(snprintf(proc_file, CHARLEN - 1, "/bin/ps -o pid -p %d", pid) &&
(fp = popen(proc_file, "r")) != NULL) {
fgets(input_buffer, CHARLEN - 1, fp);
fgets(input_buffer, CHARLEN - 1, fp);
if(sscanf(input_buffer, "%d", &testpid) == 1) {
if(testpid != pid) {
printf("NAGIOS CRITICAL - could not find process(1): %d\n", pid);
exit(STATE_CRITICAL);
}
}
}
else if(snprintf(proc_file, CHARLEN - 1, "/bin/ps -eo pid") &&
(fp = popen(proc_file, "r")) != NULL) {
found = FALSE;
fgets(input_buffer, CHARLEN - 1, fp);
while(fgets(input_buffer, CHARLEN - 1, fp)) {
if(sscanf(input_buffer, "%d", &testpid) == 1)
if(testpid == pid) found = TRUE;
}
if(!found) {
printf("NAGIOS CRITICAL - could not find process(2): %d\n", pid);
exit(STATE_CRITICAL);
}
}
else if(snprintf(proc_file, CHARLEN - 1, "/bin/ps -Ao pid") &&
(fp = popen(proc_file, "r")) != NULL) {
found = FALSE;
fgets(input_buffer, CHARLEN - 1, fp);
while(fgets(input_buffer, CHARLEN - 1, fp)) {
if(sscanf(input_buffer, "%d", &testpid) == 1)
if(testpid == pid) found = TRUE;
}
if(!found) {
printf("NAGIOS CRITICAL - could not find process(2): %d\n", pid);
exit(STATE_CRITICAL);
}
}
if(ct > 0 && ct < age) {
printf("NAGIOS CRITICAL - status written %d seconds ago\n", age);
exit(STATE_CRITICAL);
}
else if(wt > 0 && wt < age) {
printf("NAGIOS WARNING - status written %d seconds ago\n", age);
exit(STATE_WARNING);
}
else {
printf("NAGIOS ok - status written %d seconds ago\n", age);
exit(STATE_OK);
}
}
static void document_header(void) {
char date_time[48];
time_t current_time;
printf("Cache-Control: no-store\nPragma: no-cache\n");
time(&current_time);
get_expire_time_string(&current_time, date_time, (int)sizeof(date_time));
printf("Last-Modified: %s\n", date_time);
printf("Expires: %s\n", date_time);
printf("Content-type: text/html\n\n");
printf("<html>\n<head>\n<title>Nagios Daemon Status</title>\n</head>\n");
printf("<body onunload=\"if (window.wnd && wnd.close) wnd.close(); return true;\">\n");
return;
}
static int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
for(x = 0; variables[x] != NULL; x++) {
/* do some basic length checking on the variable identifier to prevent buffer overflows */
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
x++;
continue;
}
}
return error;
}
/* get date/time string used in META tags for page expiration */
static void get_expire_time_string(time_t *raw_time, char *buffer, int buffer_length) {
time_t t;
struct tm *tm_ptr;
int day;
int hour;
int minute;
int second;
int year;
char *weekdays[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"};
if(raw_time == NULL)
time(&t);
else
t = *raw_time;
tm_ptr = gmtime(&t);
hour = tm_ptr->tm_hour;
minute = tm_ptr->tm_min;
second = tm_ptr->tm_sec;
day = tm_ptr->tm_mday;
year = tm_ptr->tm_year + 1900;
snprintf(buffer, buffer_length, "%s, %d %s %d %02d:%02d:%02d GMT", weekdays[tm_ptr->tm_wday], day, months[tm_ptr->tm_mon], year, hour, minute, second);
buffer[buffer_length - 1] = '\x0';
return;
}
static char *strscpy(char *dest, const char *src) {
int len;
if(src != NULL)
len = strlen(src) + 1;
else
return dest;
if(dest == NULL || strlen(dest) < len)
dest = realloc(dest, len);
if(dest == NULL)
terminate(STATE_UNKNOWN, "failed realloc in strscpy\n");
strncpy(dest, src, len);
return dest;
}
static char *ssprintf(char *str, const char *fmt, ...) {
va_list ap;
int nchars;
int size;
if(str == NULL)
str = malloc(CHARLEN);
if(str == NULL)
terminate(STATE_UNKNOWN, "malloc failed in ssprintf");
size = max(strlen(str), CHARLEN);
va_start(ap, fmt);
while(1) {
nchars = vsnprintf(str, size, fmt, ap);
if(nchars > -1)
if(nchars < size) {
va_end(ap);
return str;
}
else {
size = nchars + 1;
}
else
size *= 2;
str = realloc(str, nchars + 1);
if(str == NULL)
terminate(STATE_UNKNOWN, "realloc failed in ssprintf");
}
}
static void terminate(int result, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
exit(result);
}

26
contrib/epn_nagios.h Normal file
View File

@ -0,0 +1,26 @@
/******** BEGIN EMBEDDED PERL INTERPRETER DECLARATIONS ********/
#include <EXTERN.h>
#include <perl.h>
#include <fcntl.h>
#undef ctime /* don't need perl's threaded version */
#undef printf /* can't use perl's printf until initialized */
/* In perl.h (or friends) there is a macro that defines sighandler as Perl_sighandler, so we must #undef it so we can use our sighandler() function */
#undef sighandler
/* and we don't need perl's reentrant versions */
#undef localtime
#undef getpwnam
#undef getgrnam
#undef strerror
#ifdef aTHX
EXTERN_C void xs_init(pTHX);
#else
EXTERN_C void xs_init(void);
#endif
/******** END EMBEDDED PERL INTERPRETER DECLARATIONS ********/

View File

@ -0,0 +1,26 @@
#!/bin/sh
# Write a command to the Nagios command file to cause
# it to disable active service checks. This can be
# referred to as 'standby' mode in a redundant monitoring
# environment.
# Notes:
# 1) This script is not intended to be used as an
# event handler by itself. Instead, it is used by other
# event handler scripts (like the redundancy examples).
# 2) In order for Nagios to process any commands that
# are written to the command file, you must enable
# the check_external_commands option in the main
# configuration file.
printfcmd="/usr/bin/printf"
CommandFile="/usr/local/nagios/var/rw/nagios.cmd"
# get the current date/time in seconds since UNIX epoch
datetime=`date +%s`
# pipe the command to the command file
`$printfcmd "[%i] STOP_EXECUTING_SVC_CHECKS\n" $datetime >> $CommandFile`

View File

@ -0,0 +1,24 @@
#!/bin/sh
# Write a command to the Nagios command file to cause
# it to disable host and service notifications
# Notes:
# 1) This script is not intended to be used as an
# event handler by itself. Instead, it is used by other
# event handler scripts (like the redundancy examples).
# 2) In order for Nagios to process any commands that
# are written to the command file, you must enable
# the check_external_commands option in the main
# configuration file.
printfcmd="/usr/bin/printf"
CommandFile="/usr/local/nagios/var/rw/nagios.cmd"
# get the current date/time in seconds since UNIX epoch
datetime=`date +%s`
# pipe the command to the command file
`$printfcmd "[%i] DISABLE_NOTIFICATIONS;%i\n" $datetime $datetime >> $CommandFile`

View File

@ -0,0 +1,46 @@
#!/bin/sh
# OBSESSIVE_SVC_HANDLER
# Written by Ethan Galstad (nagios@nagils.org)
# Last Modified: 07-19-2001
#
# This script is intended to run as the OCSP command
# on a distributed monitoring server. The script calls
# submit_check_result_via_nsca to send the service check
# results to the central monitoring server.
#
# Arguments:
# $1 = host_name (Short name of host that the service is
# associated with)
# $2 = svc_description (Description of the service)
# $3 = state_string (A string representing the status of
# the given service - "OK", "WARNING", "CRITICAL"
# or "UNKNOWN")
# $4 = plugin_output (A text string that should be used
# as the plugin output for the service checks)
#
# Location of the submit_check_result_via_nsca script
SubmitCmd="/usr/local/nagios/libexec/eventhandlers/submit_check_result_via_nsca"
# Convert the state string to the corresponding return code
return_code=-1
case "$3" in
OK)
return_code=0
;;
WARNING)
return_code=1
;;
CRITICAL)
return_code=2
;;
UNKNOWN)
return_code=3
;;
esac
# Send the service check results to the central monitoring server
$SubmitCmd "$1" "$2" $return_code "$4"

View File

@ -0,0 +1,39 @@
#!/bin/sh
# SUBMIT_CHECK_RESULT_VIA_NSCA
# Written by Ethan Galstad (egalstad@nagios.org)
# Last Modified: 10-15-2008
#
# This script will send passive check results to the
# nsca daemon that runs on the central Nagios server.
# If you simply want to submit passive checks from the
# same machine that Nagios is running on, look at the
# submit_check_result script.
#
# Arguments:
# $1 = host_name (Short name of host that the service is
# associated with)
# $2 = svc_description (Description of the service)
# $3 = return_code (An integer that determines the state
# of the service check, 0=OK, 1=WARNING, 2=CRITICAL,
# 3=UNKNOWN).
# $4 = plugin_output (A text string that should be used
# as the plugin output for the service check)s
#
#
# Note:
# Modify the NagiosHost parameter to match the name or
# IP address of the central server that has the nsca
# daemon running.
printfcmd="/usr/bin/printf"
NscaBin="/usr/local/nagios/libexec/send_nsca"
NscaCfg="/usr/local/nagios/etc/send_nsca.cfg"
NagiosHost="nagioshost"
# Fire the data off to the NSCA daemon using the send_nsca script
$printfcmd "%s\t%s\t%s\t%s\n" "$1" "$2" "$3" "$4" | $NscaBin -H $NagiosHost -c $NscaCfg
# EOF

View File

@ -0,0 +1,26 @@
#!/bin/sh
# Write a command to the Nagios command file to cause
# it to enable active service checks. This can be
# referred to as 'active' mode in a redundant monitoring
# environment.
# Notes:
# 1) This script is not intended to be used as an
# event handler by itself. Instead, it is used by other
# event handler scripts (like the redundancy examples).
# 2) In order for Nagios to process any commands that
# are written to the command file, you must enable
# the check_external_commands option in the main
# configuration file.
printfcmd="/usr/bin/printf"
CommandFile="/usr/local/nagios/var/rw/nagios.cmd"
# get the current date/time in seconds since UNIX epoch
datetime=`date +%s`
# pipe the command to the command file
`$printfcmd "[%i] START_EXECUTING_SVC_CHECKS\n" $datetime >> $CommandFile`

View File

@ -0,0 +1,27 @@
#!/bin/sh
# Write a command to the Nagios command file to cause
# it to enable host and service notifications
# Notes:
# 1) This script is not intended to be used as an
# event handler by itself. Instead, it is used by other
# event handler scripts (like the redundancy examples).
# 2) In order for Nagios to process any commands that
# are written to the command file, you must enable
# the check_external_commands option in the main
# configuration file.
printfcmd="/usr/bin/printf"
CommandFile="/usr/local/nagios/var/rw/nagios.cmd"
# get the current date/time in seconds since UNIX epoch
datetime=`date +%s`
# pipe the command to the command file
`$printfcmd "[%i] ENABLE_NOTIFICATIONS;%i\n" $datetime $datetime >> $CommandFile`

View File

@ -0,0 +1,68 @@
#!/bin/sh
# REDUNDANCY EVENT HANDLER SCRIPT
# Written By: Ethan Galstad (egalstad@nagios.org)
# Last Modified: 02-19-2004
#
# This is an example script for implementing redundancy.
# Read the HTML documentation on redundant monitoring for more
# information on what this does.
# Location of the echo and mail commands
echocmd="/bin/echo"
mailcmd="/bin/mail"
# Location of the event handlers
eventhandlerdir="/usr/local/nagios/libexec/eventhandlers"
# Only take action on hard host states...
case "$2" in
HARD)
case "$1" in
DOWN)
# The master host has gone down!
# We should now become the master host and take
# over the responsibilities of monitoring the
# network, so enable notifications...
`$eventhandlerdir/enable_notifications`
# Notify someone of what has happened with the original
# master server and our taking over the monitoring
# responsibilities. No one was notified of the master
# host going down, since the notification would have
# occurred while we were in standby mode, so this is a good idea...
#`$echocmd "Master Nagios host is down!" | /bin/mail -s "Master Nagios Host Is Down" root@localhost`
#`$echocmd "Slave Nagios host has entered ACTIVE mode and taken over network monitoring responsibilities!" | $mailcmd -s "Slave Nagios Host Has Entered ACTIVE Mode" root@localhost`
;;
UP)
# The master host has recovered!
# We should go back to being the slave host and
# let the master host do the monitoring, so
# disable notifications...
`$eventhandlerdir/disable_notifications`
# Notify someone of what has happened. Users were
# already notified of the master host recovery because we
# were in active mode at the time the recovery happened.
# However, we should let someone know that we're switching
# back to standby mode...
#`$echocmd "The master Nagios host has recovered, so the slave Nagios host has returned to standby mode..." | $mailcmd -s "Slave Nagios Host Has Returned To STANDBY Mode" root@localhost`
;;
esac
;;
esac
exit 0

View File

@ -0,0 +1,58 @@
#!/bin/sh
# REDUNDANCY EVENT HANDLER SCRIPT
# Written By: Ethan Galstad (egalstad@nagios.org)
# Last Modified: 05-30-2006
#
# This is an example script for implementing redundancy.
# Read the HTML documentation on redundant monitoring for more
# information on what this does.
# Location of the echo and mail commands
echocmd="/bin/echo"
mailcmd="/bin/mail"
# Location of the event handlers
eventhandlerdir="/usr/local/nagios/libexec/eventhandlers"
# Only take action on hard service states...
case "$2" in
HARD)
case "$1" in
CRITICAL)
# The master Nagios process is not running!
# We should now become the master host and
# take over the responsibility of monitoring
# the network, so enable active checks...
`$eventhandlerdir/enable_active_service_checks`
;;
WARNING|UNKNOWN)
# The master Nagios process may or may not
# be running.. We won't do anything here, but
# to be on the safe side you may decide you
# want the slave host to become the master in
# these situations...
;;
OK)
# The master Nagios process running again!
# We should go back to being the slave host,
# so disable active checks
`eventhandlerdir/disable_active_service_checks`
;;
esac
;;
esac
exit 0

View File

@ -0,0 +1,36 @@
#!/bin/sh
# SUBMIT_CHECK_RESULT
# Written by Ethan Galstad (egalstad@nagios.org)
# Last Modified: 02-18-2002
#
# This script will write a command to the Nagios command
# file to cause Nagios to process a passive service check
# result. Note: This script is intended to be run on the
# same host that is running Nagios. If you want to
# submit passive check results from a remote machine, look
# at using the nsca addon.
#
# Arguments:
# $1 = host_name (Short name of host that the service is
# associated with)
# $2 = svc_description (Description of the service)
# $3 = return_code (An integer that determines the state
# of the service check, 0=OK, 1=WARNING, 2=CRITICAL,
# 3=UNKNOWN).
# $4 = plugin_output (A text string that should be used
# as the plugin output for the service check)
#
echocmd="/bin/echo"
CommandFile="/usr/local/nagios/var/rw/nagios.cmd"
# get the current date/time in seconds since UNIX epoch
datetime=`date +%s`
# create the command line to add to the command file
cmdline="[$datetime] PROCESS_SERVICE_CHECK_RESULT;$1;$2;$3;$4"
# append the command to the end of the command file
`$echocmd $cmdline >> $CommandFile`

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 909 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 961 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

Some files were not shown because too many files have changed in this diff Show More