pax_global_header 0000666 0000000 0000000 00000000064 13652113235 0014513 g ustar 00root root 0000000 0000000 52 comment=dbe701f230365aac8f16427672dc1206a0ec4a77
nagios-4.4.6/ 0000775 0000000 0000000 00000000000 13652113235 0013006 5 ustar 00root root 0000000 0000000 nagios-4.4.6/.gitignore 0000664 0000000 0000000 00000000775 13652113235 0015007 0 ustar 00root root 0000000 0000000 pkg
subst
pkginfo
Prototype
nagios.SPARC.pkg.tar.gz
autom4te.cache
config.log
config.status
daemon-init
openrc-init
Makefile
tags
.deps/
.libs/
nbproject/
.kdev4/
.settings/
.cproject
.project
*.kdev4
*.o
*.la
*.lo
*.a
*.so
cgi/run*
gmon.out
core.[1-9]*
/Documentation
*.pre-indent
*.swp
*.gcda
*.gcno
*.gcov
coverage-report/
nagioscore.info-file
html/angularjs/angular-1.3.9
html/angularjs/ui-utils-0.2.3
html/bootstrap-3.3.7
html/d3
html/index.php
html/js/histogram.js
html/js/map.js
html/js/trends.js
nagios-4.4.6/.travis.yml 0000664 0000000 0000000 00000006224 13652113235 0015123 0 ustar 00root root 0000000 0000000 language: c
sudo: true
matrix:
include:
- os: linux
dist: trusty
addons:
apt:
packages:
- apache2
- build-essential
- gcovr
- gperf
- lcov
- libgd-dev
- php5
- php5-gd
- unzip
- valgrind
env:
- MATRIX_EVAL="CC=gcc && CXX=g++"
- os: linux
dist: trusty
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- apache2
- build-essential
- gcovr
- gperf
- g++-5
- lcov
- libgd-dev
- php5
- php5-gd
- unzip
- valgrind
env:
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
- os: linux
dist: trusty
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- apache2
- build-essential
- gcovr
- gperf
- g++-6
- lcov
- libgd-dev
- php5
- php5-gd
- unzip
- valgrind
env:
- MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"
- os: linux
dist: trusty
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- apache2
- build-essential
- gcovr
- gperf
- g++-7
- lcov
- libgd-dev
- php5
- php5-gd
- unzip
- valgrind
env:
- MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
- os: linux
dist: trusty
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- apache2
- build-essential
- gcovr
- gperf
- g++-8
- lcov
- libgd-dev
- php5
- php5-gd
- unzip
- valgrind
env:
- MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
- os: linux
dist: trusty
addons:
apt:
sources:
- llvm-toolchain-trusty-5.0
packages:
- apache2
- build-essential
- clang-5.0
- gcovr
- gperf
- lcov
- libgd-dev
- php5
- php5-gd
- unzip
- valgrind
env:
- MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"
- os: linux
dist: trusty
addons:
apt:
sources:
- llvm-toolchain-trusty-6.0
- ubuntu-toolchain-r-test
packages:
- apache2
- build-essential
- clang-6.0
- gcovr
- gperf
- g++-4.9
- lcov
- libgd-dev
- php5
- php5-gd
- unzip
- valgrind
env:
- MATRIX_EVAL="CC=clang-6.0 && CXX=clang++-6.0"
before_install:
- eval "${MATRIX_EVAL}"
script:
- ./configure --enable-testing
- make test
- gcovr -r .
nagios-4.4.6/CONTRIBUTING.md 0000664 0000000 0000000 00000014223 13652113235 0015241 0 ustar 00root root 0000000 0000000 # Contributing
Thank you for considering contributing your time and effort to this Nagios project.
This document serves as our guidelines for contribution. Keep in mind that these
are simply *guidelines* - nothing here is set in stone.
## Questions
If you have a question, you don't need to file an Issue. You can simply connect
with the Nagios Support Team via the
[Nagios Support Forum](https://support.nagios.com/forum/).
Not to say that you **can't** open an Issue - but you'll likely get a much faster
response by posting it on the forum.
## Ideas
If you have an idea your best bet is to open an Issue. This gets it on the radar much
quicker than any other method.
First, let's define what an "Idea" really is. An Idea is simply an
[Enhancement](#enhancements) request in its infancy.
There's really nothing to it!
Something as simple as "I think that this project should somehow connect with a
widget" is a valid Idea.
These are unrefined and raw. That's why you open an issue - so everyone gets a chance
to chime in and come up with a plan!
## Feedback
Feedback can be given via several methods. The *easiest* method is by opening an Issue.
You're more than welcome to leave feedback on the
[Nagios Support Forum](https://support.nagios.com/forum/) as well.
By opening an Issue, however, you're insuring that the maintainers and reviewers are
the first ones to see the feedback. In most cases, this is likely ideal.
## Bugs
Here's where it starts to get serious.
Following the guidelines outlined in this section allows the maintainers, developers, and
community to understand and reproduce your bug report.
Make sure to search existing open and closed [Issues](https://guides.github.com/features/issues/)
before opening a bug report. If you find a closed Issue that seems like it's the same
thing that you're experiencing, open a new Issue and include a link to the original Issue
in the body of the new one.
**If you have a bug, you *NEED* to open an Issue.**
Not only that, but when you open the Issue, this is what we ***absolutely require***:
* Use a clear and concise title for the Issue to identify the problem accurately
* Describe the bug with as much detail as you can
* Include the version of the project containing the bug you're reporting
* Include your operating system information (`uname -a`)
* Include a list of third party modules that are installed and/or loaded
* Explain the behavior you expected to see (and why) vs. what actually happened
Once you've got that covered - there's still more to include if you want to
make a ***killer*** report:
* Describe the ***exact steps*** that reproduce the problem
* Provide **specific** examples to demonstrate those steps
* If your bug is from an older version, make sure test against the latest (and/or the `maint` branch)
* Include any screenshots that can help explain the issue
* Include a file containing `strace` and/or `valgrind` output
* Explain when the problem started happening: was it after an upgrade? or was it always present?
* Define how reliably you can reproduce the bug
* Any other information that you decide is relevant is also welcome
## Enhancements
An enhancement is either a completely new feature or an improvement to existing
functionality. We consider it to be a bit different than idea - based solely
on the fact that it's more detailed than an idea would be.
So you've got an idea for an ehancement? Great!
Following the guidelines outlined in this section allows maintainers, developers, and
the community to understand your enhancement and determine whether or not it's worth
doing and/or what's involved in carrying it out.
Make sure to search open and closed Issues and Pull Requests to determine if
someone has either submitted the enhancement. If you feel like your enhancement
is similar to one found, make sure to link the original in your request.
Enhancements are submitted by opening an Issue.
Unlike an [Idea](#idea), when you decide to submit your enhancement and open
the Issue, we require at least the following information:
* Use a clear and descriptive title to illustrate the enhancement you're requesting
* Describe the current behavior (if it exists) and what changes you think should be made
* Explain the enhancement in detail - make sure it makes sense and is easily understandable
* Specify why the enhancement would be useful and who it would be useful to
* If there is some other project or program where this enhancement already exists, make sure
to link to it
Beyond that, there are a few more things you can do to make sure you **really** get your
point across:
* Create a mockup of the enhancement (if applicable) and attach whatever files you can
* Provide a step-by-step description of the suggested enhancement
* Generate a fully dressed use-case for the enhancement request
* Create a specification for the preferred implementation of the enhancement
* Include a timeline regarding development expectations towards the request
## Submitting Code
Everything else in this document has lead up to this moment - how can ***you*** submit
code to the **project**.
We allow code submissions via [Pull Requests](https://help.github.com/articles/about-pull-requests/).
These let you (and us) discuss and review any changes to code in any repository you've made.
How to create and manage Pull Requests is outside of the scope of this document, but make
sure to check out GitHub's official documentation ([link here](https://help.github.com/))
to get a handle on it.
While you're forking the repository to create a patch or an enhancement, create a *new
branch* to make the change - it will be easier to submit a pull request using a new
branch in your forked repository!
When you submit a Pull Request, make sure you follow the guidelines:
* Make sure you're submitting to the proper branch. Branch `maint` is used for the
**next** bugfix release. The next enhancement release branch will vary.
* ***NEVER*** submit a Pull Request to `master` branch.
* Keep commit messages as concise as possible.
* Update the appropriate files in regards to your changes:
* `Changelog`
* `THANKS`
* End all committed files with a newline.
* Test your changes and include the results as a comment.
nagios-4.4.6/Changelog 0000664 0000000 0000000 00000077516 13652113235 0014640 0 ustar 00root root 0000000 0000000 ########################
Nagios Core 4 Change Log
########################
4.4.6 - 2020-04-28
------------------
FIXES
* Fixed Map display in Internet Explorer 11 (#714) (Scott Wilkerson)
* Fixed duplicate properties appearing in statusjson.cgi (#718) (Sebastian Wolf)
* Fixed NERD not building when enabled in ./configure (#723) (Sebastian Wolf)
* Fixed build process when using GCC 10 (#721) (Michael Orlitzky)
* Fixed postauth vulnerabilities in histogram.js, map.js, trends.js (CVE-2020-1408) (Thanks UraSec Team) (Sebastian Wolf)
* When using systemd, configuration will be verified before reloading (#715) (tatref)
* Fixed HARD OK states triggering on the maximum check attempt (#757) (Sebastian Wolf)
4.4.5 - 2019-08-20
------------------
FIXES
* Reverted changes related to #625 due to CPU load issues
* Partially reverted changes for #647 due to CPU load issues
* Fixed "Quick Search" so that leading/trailing whitespace doesn't affect output (#681) (Sebastian Wolf)
* Fixed build issues on non-RPM-based platforms (#617) (T.J. Yang)
4.4.4 - 2019-07-29
------------------
FIXES
* Fixed log rotation logic to not repeatedly schedule rotation on a DST change (#610, #626) (Jaroslav Jindrak & Sebastian Wolf)
* Fixed $SERVICEPROBLEMID$ to be reset after service recovery (#621) (Sebastian Wolf)
* Fixed defunct worker processes appearing after nagios was reloaded (#441, #620) (Sebastian Wolf)
* Fixed main nagios thread to release nagios.qh on a closed connection (#635) (Sebastian Wolf)
* Fixed semicolon escaping to remove prepended backslash (\) (#643) (Sebastian Wolf)
* Fixed 'Checks of this host have been disabled' message showing on passive-only hosts (#632) (Vojtěch Širůček & Sebastian Wolf)
* Fixed last_hard_state showing the current hard state when service status is brokered (#633) (Sebastian Wolf)
* Fixed long plugin output (>8KB) occasionally getting truncated (#625) (Sebastian Wolf)
* Fixed check scheduling for objects with large check_intervals and small timeperiods (#647) (Sebastian Wolf)
* Fixed SOFT recoveries sending when services had HARD recovery some time after host recovery (#651) (Sebastian Wolf)
* Fixed incorrect permissions on debugging builds of FreeBSD (#420) (Sebastian Wolf)
* Fixed NEB callback lists being partially orphaned when multiple modules subscribe to one callback (#590) (Sebastian Wolf)
* Fixed memory leaks in run_async_service_check(), run_async_host_check() when checks are brokered (#664) (Sebastian Wolf)
* Fixed potential XSS in main.php, map.php (#671, #672) (Jak Gibb)
* Removed NEB brokering for nagios daemonization, since daemonization occurs before NEB initialization (#591) (Sebastian Wolf)
4.4.3 - 2019-01-15
------------------
FIXES
* Fixed services sending recovery emails when they recover if host in down state (#572) (Scott Wilkerson)
* Fixed a make error when building on the aarch64 architecture (#598) (Gareth Randall)
* Fixed --with-cgibindir and --with-webdir to actually set values given (#585) (lawsontyler)
* Fixed soft recovery states for services (#575) (Jake Omann)
* Fixed XSS vulnerability in Alert Summary report (CVE-2018-18245) (Jake Omann)
* Fixed services in soft states sometimes not switching into hard states (#576) (Jake Omann)
* Fixed last_state_change to update when a state goes from soft -> hard state (#592) (Jake Omann)
* Fixed Map link always being set to undefined host and don't show link for Nagios Process root note (#539) (Jake Omann)
* Fixed notifications sending when services went into hard state on a down or unreachable host (#584) (Jake Omann)
* Fixed log_host_retries not logging the host soft state checks (#599) (Jake Omann)
* Fixed stalking_options N option to properly log only when a notification is actually sent (#604) (Jake Omann)
* Fixed issue with service status totals being zero when servicegroup=all on servicegroup status page (#579) (Jake Omann)
* Fixed escalation notifications logic and recovery notifications not going out (#582) (Jake Omann)
* Fixed not finding child index causing duplicate hosts showing in the Map (#471) (Jake Omann)
* Fixed Map configuration popup checkboxes not working and Root Node not populating (#543) (Jake Omann)
* Fixed cleanup and deinit of neb modules on reload (#573) (Jake Omann)
4.4.2 - 2018-08-16
------------------
FIXES
* Fix comment data being duplicated after a `service nagios reload` or similar (#549) (Bryan Heden)
* Fix check_interval and retry_interval not changing at the appropriate times (#551) (Scott Wilkerson)
* Fixed passive checks sending recovery email when host was previously UP (#552) (Scott Wilkerson)
* Fixed flapping comments duplication on nagios reload (#554) (Christian Jung)
* Fix for CVE-2018-13441, CVE-2018-13458, CVE-2018-13457 null pointer dereference (Trevor McDonald)
* Fixed syntax error in file: default-init.in (#558) (Christian Zettel)
* Reset current notification number and state flags when the host recovers, reset all service variables when they recover fixes (#557) (Scott Wilkerson)
* Fixed wrong counting of service status totals when showing servicegroup details (#548) (Christian Zettel, Bryan Heden)
* Fixed avail.cgi not printing CSV output when checkbox is checked (for any type: host/service/hostgroup/servicegroup) (#570) (Bryan Heden)
* Fixed nagios not logging SOFT state changes after 1 (Scott Wilkerson)
4.4.1 - 2018-06-25
------------------
FIXES
* Revert some macro->kvvec changes causing problems when `enable_environment_macros` was enabled (Bryan Heden)
* Adjust `process_macro_r` function logic so that it handles macros properly (Bryan Heden)
* Fix spec file for systemd (Karsten Weiss, Fr3dY, Bryan Heden)
* Fix bug where `ssize_t` typedef to int on some systems (Bryan Heden)
4.4.0 - 2018-06-19
------------------
ENHANCEMENTS
* new status for check dependencies (John Frickson)
* Allow more flexible requirements for comments (John Frickson)
* Add a `statusCRITICALACK` class for the status column (John Frickson)
* CSV output based on groups (all options) (John Frickson)
* New Macro(s) to generate URL for host / service object to be used in notifications (John Frickson)
* New Macro(s) to determine if host/service notifications are enabled (#419) (Bryan Heden)
* New Macro(s) for obtaining the host/service notification periods (#350) (Bryan Heden)
* enable_page_tour interface option (Bryan Heden)
* Code cleanups in important sections (Workers, Handling Results) (Bryan Heden)
* Automatic mail program detection (with same /bin/mail failback) (Bryan Heden)
* Incorporated [autoconf-macros](https://github.com/NagiosEnterprises/autoconf-macros) into Core (Bryan Heden)
* Lots of enhancements/additions to configure/make process. (Bryan Heden)
* Moved all files to startup/
* Added upstart job
* Added system limit detection (RLIMIT_NPROC) to check for anticipated fork() failures (#434) (Bryan Heden)
* Added stalking on notifications (`N` or `notifications` option when specifying `stalking_options`) (#342) (Bryan Heden)
* Added automatic `systemctl daemon-reload` and `initctl reload-configuration` where applicable on `make install-init` (Bryan Heden)
* Added case-insentive command submission. (#373) (Bryan Heden)
* Enabled `check_external_commands` by default (Bryan Heden)
FIXES
* Command line macro detection skips potential macros with no ending dollar sign (Bryan Heden, Jake Omann)
* Fixed a lockup condition sometimes encountered on shutdown or restart (Aaron Beck)
* Fixed negative time offset calculations computing incorrectly sometimes (bbeutel)
* Fixed reloads causing defunct (zombie) processes (#441) (Bryan Heden)
* Fixed wait3(), wait4() implementations (replaced with waitpid()) (#326) (Bryan Heden)
* Fixed additive inheritance not testing for duplicates in hosts/services/(+escalations) (#392) (Bryan Heden)
* Fixed very very (around 600k chars or greater) large plugin output crashing Nagios (#432) (Bryan Heden)
* Fixed first_notification_delay not beeing calculated from last_hard_state_change (#425) (Christian Zettel)
* Fixed duplicate downtime ID occuring from downtimes in retention file (#506) (Franz [feisenko])
* Fixed segfault when navbarsearch was used in status.cgi for something other than a host (#489) (Bryan Heden)
* Fixed some miscellaneous ./configure issues on Solaris (Bryan Heden, Troy Lea)
* Fixed "Locate host on map" link (#496) (Troy Lea)
* Fixed service groups defined with unknown service members (that aren't first in the list) not erroring out (#500) (Bryan Heden)
* Fixed tac.cgi to have consistent behavior with the other cgis (#481) (Bryan Heden, Matt Capra)
* Fixed clear_host/service_flapping command logic to broker/notify properly (#525) (Bryan Heden, Karsten Weiss)
4.3.4 - 2017-08-24
------------------
* Improved config file parsing (Mark Felder)
* Fixed configure script to check for existence of /run for lock file (in regards to CVE-2017-12847, Bryan Heden)
* Use absolute paths when deleting check results files (Emmanuel Dreyfus)
* Add sanity checking in reassign_worker (sq5bpf)
4.3.3 - 2017-08-12
------------------
* xodtemplate.c wrong option-deprecation code warning (alex2grad / John Frickson)
* On-demand host check always use cached host state (John Frickson)
* 'á' causes Service Status Information to not be displayed (John Frickson)
* New Macro(s) to generate URL for host / service object (John Frickson)
* Fix minor map issues (Troy Lea)
* Fix lockfile issues (Bryan Heden)
* Switch order of daemon_init and drop_priveleges (CVE-2017-12847, Bryan Heden)
* Add an OpenRC init script (Michael Orlitzky)
4.3.2 - 2017-05-09
------------------
FIXES
* Every 15sec /var/log/messages is flooded with "nagios: set_environment_var" (John Frickson)
* Changed release date to ISO format (yyyy-mm-dd) (John Frickson)
* `make all` fails if unzip is not installed (John Frickson)
* Quick Search no longer allows search by Alias (John Frickson)
* flexible downtime on a service immediately turns off notifications (John Frickson)
* Fix to allow url_encode to be called twice (Z. Liu)
* Update timeperiods.cfg.in (spelling) (Parth Laxmikant Kolekar)
* Spelling fixes (Josh Soref)
* Vent command pipe before remove to avoid deadlocks on writing end (Kai Kunstmann)
* CGI utility cgiutil.c does not process relative config file path names properly (John Frickson)
* xdata/xodtemplate.c bug in option-deprecation code (John Frickson)
* Wildcard searching causes service status links to not work properly (John Frickson)
* Quick search with no hits shows a permission denied error (John Frickson)
* Setting a service as its own parent is not caught by the sanity checker (-v) and causes a segfault (John Frickson)
4.3.1 - 2017-02-23
------------------
FIXES
* Service hard state generation and host hard or soft down status (John Frickson)
* Comments are duplicated through Nagios reload (John Frickson)
* host hourly value is incorrectly dumped as json boolean (John Frickson)
* Bug - Quick Search no longer allows search by IP (John Frickson)
* Config: status_update_interval can not be set to 1 (John Frickson)
* Check attempts not increasing if nagios is reloaded (John Frickson)
* nagios hangs on reload while sending external command to cmd file (John Frickson)
* Feature Request: return code xxx out of bounds - include message as well (John Frickson)
4.3.0 - 2017-02-21
------------------
SECURITY FIXES
* Fix for CVE-2016-6209 - The "corewindow" parameter (as in
http://localhost/nagios?corewindow=www.somewhere.com) has been disabled by
default. See the UPGRADING document for how to enable it. (John Frickson)
FIXES
* Fix early event scheduling (pmalek / John Frickson)
* on-demand host checks triggered by service checks cause attempt number increments (fredericve)
* Service notification not being send when host is in soft down state (John Frickson)
* configure does not error if no perl installed on CentOS 7 (John Frickson)
* failed passive requests leave .ok files in checkresults dir (caronc)
* Services don't show in status.cgi if "noheader" specified (John Frickson)
* Standardized check interval config file names (John Frickson)
* "Event Log" (showlog.cgi) could not open log file (John Frickson)
* "nagios_check_command" has been deprecated since v3.0. Last vestiges removed (John Frickson)
ENHANCEMENTS
* Added new flag to cgi.cfg: tac_cgi_hard_only to show only HARD states (John Frickson)
* Add broker-event for the end of a timed event (NEBTYPE_TIMEDEVENT_END) (John Frickson)
* There is no Macro to retrieve addresses of hostgroup members (now $HOSTGROUPMEMBERADDRESSES$) (John Frickson)
* Add "Page Tour" videos to several of the core web pages (John Frickson)
* Added a login page, and a `Logoff` links (John Frickson)
* On the status map, the host name will be colored if services are not all OK. (John Frickson)
* Added "Clear flapping state" command on host and services detail pages. (John Frickson)
* User-entered comment now displays below generated comment for downtime (John Frickson)
4.2.4 - 2016-12-07
------------------
SECURITY FIXES
* Fixed another root privilege escalation (CVE-2016-9566) Thanks for bringing this
to our attention go to Dawid Golunski (http://legalhackers.com).
4.2.3 - 2016-11-21
-------------------
SECURITY FIXES
* Fixed a root privilege escalation (CVE-2016-8641) (John Frickson)
FIXES
* external command during reload doesn't work (John Frickson)
* Nagios provides no error condition as to why it fails on the verify for serviceescalation (John Frickson)
* No root group in FreeBSD and Apple OS X (John Frickson)
* jsonquery.html doesn't display scheduled_time_ok correctly (John Frickson)
* daemon_dumps_core=1 has no effect on Linux when Nagios started as root (John Frickson)
* Configuration check in hostgroup - misspelled hostname does not error (John Frickson)
* contacts or contact_groups directive with no value should not be allowed (John Frickson)
* Compile 64-bit on SPARC produces LD error (John Frickson)
* HOSTSTATEID returns 0 even if host does not exist (John Frickson)
* Submitting UNREACHABLE passive result for host sets it as DOWN if the host has no parents (John Frickson)
* nagios: job XX (pid=YY): read() returned error 11 (changed from LOG_ERR to LOG_NOTICE) (John Frickson)
* Fix for quick search not showing services if wildcard used (John Frickson)
4.2.2 - 2016-10-24
------------------
SECURITY FIXES
* There was a fix to vulnerability CVE-2008-4796 in the 4.2.0 release on
August 1, 2016. The fix was apparently incomplete, as there was still a
problem. However, we are now getting all RSS feeds using AJAX calls
instead of the (outdated) MagpieRSS package. Thanks for bringing this to
our attention go to Dawid Golunski (http://legalhackers.com).
ENHANCEMENTS
* Update status.c to display passive check icon for hosts when passive checks
are enabled and actives disabled (John Frickson)
FIXES
* Fix permissions for Host Groups reports (status.cgi) (Patrik Halfar)
* Service Parents does not appear to be functioning as intended (lev)
* Availability report mixes up scheduled and unscheduled warning percentages (Helmut Mikulcik)
* Invalid values for saved_stamp in compute_subject_downtime_times() (John Frickson)
* Remove deprecated "framespacing" (John Frickson)
* The nagios tarball contains two identical jquery copies (John Frickson)
* extinfo.cgi does not set content-type (most cgi's don't) (John Frickson)
* Timeperiods are corrupted by external command CHANGE_SVC_CHECK_TIMEPERIOD (xoubih)
* Quick search doesn't show hosts without services (service status detail page) (John Frickson)
* In host/services details view, if exactly 100 entries would not show last one (John Frickson)
* nagios host URL parameter for NEW map doesn`t work - Network Map for All Hosts (John Frickson)
* next_problem_id is improperly initialized (gherteg)
* Passive problems not showing as "unhandled" (John Frickson)
* September reported as Sept instead of Sep (Rostislav Opočenský)
* Notifications are not sent for active alerts after scheduled downtime ends (John Frickson)
* Nagios 4.2.0 not working on Solaris (John Frickson)
* install-exfoliation and install-classicui don't work FreeBSD and Mac OS X (John Frickson)
* Updated makefile to delete some no-longer-needed files (John Frickson)
4.2.1 - 2016-09-06
------------------
FIXES
* Fix undefined variable php error (John Frickson)
* Links on the sidebar menu under 'Problems' are indented too far (John Frickson)
* Using $ARGn$ Macros in perfdata (John Frickson)
* using a wildcard in search returns service status total all zero's (John Frickson)
* read_only does not take priority (deppy)
* Running nagios -v on 4.2.0 takes 90+ seconds (John Frickson)
* Bare "make" invoked in subtarget (mjo)
* Theme images/stylesheets installed with inconsistent permissions (mjo / John Frickson)
* Missing Image for Host and Service State Trends in Availability Report (nichokap / John Frickson)
* Maintain non-persistent comments through reload (John Frickson)
* Servicegroup availability report ignores includesoftstates in service report links (PriceChild)
* error: format not a string literal and no format arguments (Karsten Weiss)
* Synced config.guess and config.sub with GNU (Zakhar Kleyman)
4.2.0 - 2016-08-01
------------------
SECURITY FIXES
* Fixed vulnerability CVE-2008-4796 (John Frickson)
* Fixed vulnerability CVE-2013-4214 (John Frickson)
* web interface vulnerable to Cross-Site Request Forgery attacks (John Frickson)
ENHANCEMENTS
* Increase socket queue length for listen()
* Added host name to the website page title (leres / John Frickson)
* Added additional icons for NetBSD and SuSE (John Frickson)
* The new Status Map will now use cgi.cfg options (John Frickson)
default_statusmap_layout will default to "6" for the new map
* The new Status Map will now show some valid values in the popup for "Nagios Process" (John Frickson)
FIXES
* Network outage view without access to all hosts (John Frickson)
* Core workers looping (John Frickson)
* service query returns duplicate host_name and description fields in the returned data (John Frickson)
* HTML output of plug-ins is parsed in wrong way => webgui unusable (John Frickson)
* Command worker fails to handle SIGPIPE
* "View Status" links under "Map" broken in Nagios Core Version 4.1.1 (John Frickson)
* Can't send big buffer - wproc: Core Worker seems to be choked (velripn / John Frickson)
* Too big CPU load on FreeBSD and other systems using poll() interface (cejkar)
* Flexible downtime recorded as unscheduled downtime (John Frickson)
* Service Flexible downtimes produce 1 notification before entering (John Frickson)
* Once you "set flap_detection_enabled 0" it should remove flapping state from the host/services page (John Frickson)
* New map doesn't finish loading if a logo image is not found (John Frickson)
* Extraneous Div end tag in map.html (Scott Wilkerson)
* Issue with "Problems" section (John Frickson)
* Status Map icons and online/offline status dots disappear in IE11 (John Frickson)
* New network map overlays the nagios process with objects (John Frickson)
* Added Default-Start and Default-Stop to the init script (John Frickson)
* Compile / logging issues with BSD 6
* Related to above, Fixed a lot of incorrectly handled time_t's in *printf's (John Frickson)
* New map not working for RU locale (actually, most locales) (John Frickson)
* Replaced all instances of signal() with sigaction() + blocking (John Frickson)
* UTF-8 characters like german ä are not processed properly by function url_encode (John Frickson)
* nagios worker processes can hog CPU (huxley / John Frickson)
* custom time periods that include special characters were not being handled in reports (John Frickson)
* Fixed init script to wait up to 90 seconds then kill the nagios process (John Frickson)
* No Host Groups results in wrong error message (John Frickson)
* Setup Nagios users to view specific host is not working in the new network map (John Frickson)
* statusjson.cgi fails glibc realloc truncate response output (John Frickson)
* Report Time Period does not work if an @ character is in the timeperiod name (John Frickson)
* State History does not use actual plugin long_output (John Frickson)
* Time period corruption (xoubih)
* Tactical Overview - Disabled Flap Detection Link (John Frickson)
4.1.1 - 08/19/2015
------------------
FIXES
* CGI Could not read object configuration data (broken by error in 4.1.0)
* exclude (!) not working (broken by mis-applied fix for 4.1.0)
4.1.0 - 08/18/2015
------------------
ENHANCEMENTS
* Promoted JSON CGIs to released status (Eric Stanley)
* New graphical CGI displays: statusmap, trends, histogram (Eric Stanley)
* Make sticky status for acks and comments configurable enhancement #20 (Trevor McDonald / Scott Wilkerson)
* Add host_down_disable_service_checks directive to nagios.cfg #44 (Trevor McDonald / Scott Wilkerson)
* httpd.conf doesn't support Apache versions > 2.3 (DanielB / John Frickson)
FIXES
* Fix for not all service dependencies created (John Frickson)
* Fix SIGSEGV with empty custom variable (orbis / John Frickson)
* Fix contact macros in environment variables (dvoryanchikov)
* Fixed host's current attempt goes to 1 after going to hard state (John Frickson)
* Fixed two bugs/problems: Replace use of %zd in base/utils.c & incorrect va_start() in cgi/jsonutils.c (Peter Eriksson)
* Fixed: Let remove_specialized actually remove all workers (Phil Mayers)
* Fixed log file spam caused when using perfdata command directives in nagios.cfg (shashikanthbussa)
* Fixed off-by-one error in bounds check leads to segfault (Phil Mayers)
* Added links for legacy graphical displays (Eric Stanley)
* Update embedded URL's to https versions of Nagios websites (scottwilkerson)
* Fixed doxygen comments to work with latest doxygen 1.8.9.1 #30 (Trevor McDonald)
* Fixed makefile target "html" to PHONY to fix GitHub issue #28 (Trevor McDonald)
* Fixed typo as per GitHub issue #27 (Trevor McDonald)
* Fixed jsonquery.php 404 not found error, and disabled Send Query button until form populates #43 (Scott Wilkerson)
* Fixed linking in Tactical Overview for several of the Host entries in Featured section #48 (Scott Wilkerson)
* Fixed passing limit and sort options to pagination and sort links #42 (Scott Wilkerson)
* Added form field for icon URL and clean-up when it changes in CGI Status Map. (Eric Stanley)
* Added options to cgi.cfg to uncheck sticky and send when acknowledging a problem (Trevor McDonald)
* Low impact changes to automate the generation of RPMs from nagios.spec file. (T.J. Yang)
* Update index.php (Trevor McDonald)
* Fixed escaping of corewindow parameter to account for possible XSS injection (Scott Wilkerson)
* Typo correction (T.J. Yang)
* Make getCoreStatus respect cgi_base_url (Moritz Schlarb)
* Adjusted map layout to work within frames (Eric Stanley)
* Fixed map displays are now the full size of browser window (Eric Stanley)
* Fixed labels and icons on circular markup no longer scale on zoom (Eric Stanley)
* Got all maps except circular markup working with icons (Eric Stanley)
* Fixes to make legacy CGIs work again. (Eric Stanley)
* Fixes to make all/html target tolerant of being run multiple times (Eric Stanley)
* For user-supplied maps, converted node group to have transform (Eric Stanley)
* Fixed issue transitioning from circular markup map to other maps (Eric Stanley)
* Fix displayForm to trigger on the button press (Scott Wilkerson)
* Fix fo getBBox crash on Firefox (Eric Stanley)
* Fixed map now resets zoom when form apply()'d (Eric Stanley)
* Fixed so close box on dialogs actually closes dialog (Eric Stanley)
* Corrected directive in trends display (Eric Stanley)
* Fixed minor issue with link in trends links (Eric Stanley)
* Fixed issue with map displaying on Firefox (Eric Stanley)
* Added exclusions for ctags generation (Eric Stanley)
* Update map-popup.html (Scott Wilkerson)
* Initial commit of new graphical CGIs (Eric Stanley)
* Fixed Github bug #18 - archivejson.cgi returns wrong host for state change query (Eric Stanley)
* Status JSON: Added next_check to service details (Eric Stanley)
* Fixed escaping of keys for scalar values in JSON CGIs (Eric Stanley)
* build: Include if it exists. (Eric J. Mislivec)
* lib-tests: test-io{cache|broker} need -lsocket to link. (Eric J. Mislivec)
* lib-tests: test-runcmd assumes GNU echo. (Eric J. Mislivec)
* lib-tests: Signal handlers don't return int on most platforms, and using a cast was the wrong way to resolve this. (Eric J. Mislivec)
* Fix some type/format mismatch warnings for pid_t. (Eric J. Mislivec)
* Fix build on Solaris. (Eric J. Mislivec)
* runcmd: Fix build when we don't HAVE_SETENV. (Eric J. Mislivec)
* Fixed checkresult output processing (Eric Mislivec)
* Corrected escaping of long output macros (Eric Mislivec)
* Fixed null pointer dereferences in archive JSON (Eric Stanley)
* Fixed memory overwrite issue in JSON string escaping (Eric Stanley)
* JSON CGI: Now escaping object and array keys (Eric Stanley)
KNOWN ISSUES
* New map does not account for multiple parents, leaving "legacy" map as an option in the menu
4.0.8 - 08/12/2014
------------------
ENHANCEMENTS
* Removed 8 kB string size limitation in JSON CGIs (Eric Stanley)
* Re-implemented auto-rescheduling of checks (Eric Mislivec)
* Avoid bunching of checks delayed due to timeperiod constraints (Eric Stanley)
* Limit the number of autocalculated core workers to not spawn too many on large systems (Eric Mislivec, Janice Singh)
FIXES
* Removed quotes from numeric duration values in JSON CGIs (Eric Stanley)
* Fixed escaping in JSON CGIs so all required characters are escaped, and in the correct order (Eric Stanley)
* Fixed segfault in archive JSON CGI when plugin output was empty (Eric Stanley)
* Fixed several possibilities for buffer overflow (Eric Mislivec, Dirkjan Bussink)
* Fixed Tracker #582, #626: Handle VAR=VAL assignments at the start of simple commands (Eric Mislivec, Phil Randal)
* Fixed Tracker #630: Recognize '<' and '>' as redirection operators (Eric Mislivec)
* Corrected worker communication protocol documentation (Phil Mayers)
* Fixed init script to leave config test log in a better location, let sysconfig override init script variables, and not remove nagios.cmd when attempting to start with another instance running (Eric Mislivec, Robin Kearney)
* Fixed Tracker #361: Downtime notifications not displayed properly (Andrew Widdersheim)
4.0.7 - 06/03/2014
------------------
ENHANCEMENTS
* Added value of custom variables to Object JSON output for hosts, services and contacts (Eric Stanley)
FIXES
* Fixed bug #616: Unescape plugin output read from checkresult files, fix multiline perf data concatenation, and avoid extra memory allocation and copies. (Eric Mislivec)
* Fixed bug #609: Image on home page doesn't have correct image path prefix. (Derek Brewer)
* Fixed bug #608: Extra newline in service check timeout output string. (Mauno Pihelgas)
* Fixed bug #596: Crashes checking contact authorization for host escalations. (Alexey Dvoryanchikov - duplicates #590, #586)
* Fixed bug #496: Syntax error in exfoliation's common.css. (Karsten Weiss)
4.0.6 - 04/29/2014
------------------
ENHANCEMENTS
* Added name of authenticated user to JSON CGI results object (Eric Stanley)
* Added Nagios Core version to the Status JSON CGI programstatus query (Eric Stanley)
* Added daemon status to main page (Eric Mislivec)
FIXES
* Fixed bug #600: Service Check Timeout State always returns OK (0) status (Mauno Pihelgas, Eric Stanley)
* Fixed bug #583: Status Check Output of (No output on stdout) stderr: (Eric
Stanley - duplicate of bug #573)
* Fixed bug #573: Service checks returns (No output on stdout) stderr (Eric Stanley)
* Fixed bug #438: Reloads during downtime causes wrong availability calculations (Eric Stanley)
* Fixed feed updates when daemon can not access external networks (Eric Mislivec)
* Archive JSON: Fixed bugs calculating availability (Eric Stanley)
* Archive JSON: Allow missing logs to be skipped (Eric Stanley)
4.0.5 - 04/11/2014
------------------
* Fixed bug #595: Nagios 4 security fix (Alexey Dvoryanchikov, Eric Stanley)
* Fixed bug #594: Nagios 4 fix contactgroups parsing (Alexey Dvoryanchikov, Eric Stanley)
* Fixed bug #577: Nagios 4 checks stalled when write to socket failed (Alexey Dvoryanchikov)
* Fixed bug #580: Nagios 4 memory leak (Eric Stanley)
* Fixed init script to remove the switching of users when performing configuration verification which was causing failures if nagios user was set to nologin (Scott Wilkerson)
* Fixed auto creation of RAMDISK via environment variables in init script to properly check existence using $RAMDISK_DIR environment variable. (Scott Wilkerson)
* Fixed unreferenced variable NagiosVarDir in daemon-init (Eric Mislivec)
* Fixed bug where audio alerts wouldn't work with a 0 height and width - https://support.nagios.com/forum/viewtopic.php?t=26387 (Scott Wilkerson)
4.0.4 - 03/14/2014
------------------
ENHANCEMENTS
* JSON CGIs moved to beta status (Eric Stanley)
FIXES
* Fixed bug #491,#553: Rebuilt the daemon-init scripts back to something that should work on all systems (Scott Wilkerson)
4.0.3 - 02/28/2014
------------------
ENHANCEMENTS
* Aliased hourly_value to importance and minimum_value to minimum_importance and deprecated the former (Eric Stanley)
* Added host and service importance macros (Eric Stanley)
* Added notifications on flexible downtime expiration (Dan Wittenberg)
FIXES
* Bug #548: Temporary fix that rejects all external command during restart to prevent Core from crashing (Eric Stanley)
* Corrected calculation of host importance and importance defaults (Eric Stanley)
* Fixed bug #498: Nagios 4 enable_environment_macros=1 not working (Eric Stanley, Alexey Dvoryanchikov)
* No longer checks whether logs can be written when verifying configuration (Eric Stanley)
* Fixed CGI bug where the CGI could read past the end of the list of CGI variables, potentially crashing the CGI (Scott Wilkerson)
* Fixed inheritance of hourly_value from host and service templates (Scott Wilkerson)
* Fixed bug #502: 4.0.0: Configuration -> Service Escalations = incomplete list (Eric Stanley)
* Fixed bug #523: quotes and double quotes in plugin message are converted to HTML escapes in Nagios 4.0 (duplicate of bug #524)
* Fixed bug #524: URLs returned in plugin check results are not correctly displayed (Eric Stanley)
* Fixed bug where passive service checks would return "Service check timed out after 0.00 seconds" (Scott Wilkerson)
4.0.2 - 11/25/2013
------------------
FIXES
* Fixed bug 528: Nagios 4.0.1: Logrotation: Only current host- and servicestates saved in rotated logfiles (duplicate of 507)
* Fixed bug 507: Nagios 4.0.0 - Problem during log rotate (Stefano Ghelfi)
* Fixed bug 530: RPM spec file sets wrong permissions on plugins directory (duplicate of bug 494)
* Fixed bug 494: nagios.spec fixes (with patch) (Karsten Weiss)
* Fixed bug 515: Segsegv after starting up nagios (duplicate of bug 526)
* Fixed bug 513: Crash while entering downtime for service (duplicate of bug 526)
* Fixed bug 529: Core Worker failed to reap child in 4.0.1 Description
* Fixed bug 514: scheduled downtime not showing in web interface (Eric Stanley)
* Fixed bug 526: sort_downtime() corrupts scheduled_downtime_list causing segfault (Adam James)
* Fixed bug 492: Nagios 4 fails to remove/add checks upon reload (Eric Stanley)
* Fixed Bug 484: Beta4.0.0b4 service checks returning (No output on stdout) (Eric Stanley)
* Fixed Bug 470: statusmap doesn't display info (Cameron Moore)
* Fixed Bug 499: Security issue in daemon-init.in, function check_config (Tómas Edwardsson)
4.0.1 - 10/15/2013
------------------
ENHANCEMENTS
* Added compiler flags in RPM spec file to reduce compiler noise (Dan Wittenberg)
* Added logging of failure in dlclose() call (Anton Lofgren)
* Added a simple query handler interface, nagios-qh.rb (Dan Wittenberg)
* Multiple code simplifications, additional error handling in downtime code (Andreas Ericsson)
FIXES
* Reverted commit f99a9a7b which set check_interval to 1 if it was configured as zero.
* Corrected order of arguments when logging unknown hosts/services (Scott Wilkerson)
* Downtime initialized before retention data read (Eric Stanley)
* Patches to make RPM build again (Dan Wittenberg)
* Ensure that scheduled_downtime_depth never drops below zero (Andreas Ericsson)
4.0.0 - 09/20/2013
------------------
See https://assets.nagios.com/downloads/nagioscore/docs/nagioscore/4/en/whatsnew.html for a
list of the changes in Nagios Core 4
nagios-4.4.6/INSTALLING 0000664 0000000 0000000 00000000646 13652113235 0014403 0 ustar 00root root 0000000 0000000 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!
nagios-4.4.6/LEGAL 0000664 0000000 0000000 00000001511 13652113235 0013553 0 ustar 00root root 0000000 0000000 Copyright(c) 1999-2009:
Ethan Galstad
Copyright(c) 2009 until further notice:
Nagios Core Development Team and Nagios Community Contributors
For detailed authorship information, refer to the source control
management history and pay particular attention to commit messages
and the THANKS file.
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).
nagios-4.4.6/LICENSE 0000664 0000000 0000000 00000043122 13652113235 0014015 0 ustar 00root root 0000000 0000000 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.
Copyright (C) 19yy
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.
, 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.
nagios-4.4.6/Makefile.in 0000664 0000000 0000000 00000040172 13652113235 0015057 0 ustar 00root root 0000000 0000000 ###############################
# Makefile for Nagios
#
###############################
# Source code directories
SRC_BASE=@srcdir@/base
SRC_LIB=@srcdir@/lib
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
SRC_WORKERS=@srcdir@/worker
CC=@CC@
CFLAGS=@CFLAGS@ @DEFS@
LDFLAGS=@LDFLAGS@ @LIBS@
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CHECKRESULTDIR=@CHECKRESULTDIR@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
CGIDIR=@cgibindir@
LIBEXECDIR=@libexecdir@
LIBDIR=@libdir@
INCLUDEDIR=@includedir@/nagios
HTMLDIR=@webdir@
datarootdir=@datarootdir@
LN_S=@LN_S@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
HTTPD_CONF=@HTTPD_CONF@
LN_HTTPD_SITES_ENABLED=@LN_HTTPD_SITES_ENABLED@
INIT_DIR=@initdir@
INIT_OPTS=@INIT_OPTS@
CGICFGDIR=$(CGIDIR)
NAGIOS_USER=@nagios_user@
NAGIOS_GRP=@nagios_grp@
DIST=@dist_type@
SRC_INIT=@src_init@
INIT_FILE=@initname@
INIT_TYPE=@init_type@
USE_EVENTBROKER=@USE_EVENTBROKER@
USE_LIBTAP=@USE_LIBTAP@
CGIEXTRAS=@CGIEXTRAS@
CP=@CP@
@SET_MAKE@
none:
@echo "Please supply a command line argument (i.e. 'make all'). Other targets are:"
@echo " nagios cgis contrib modules workers"
@echo " test"
@echo " install install-base"
@echo " install-cgis install-html"
@echo " install-webconf install-config"
@echo " install-init install-daemoninit"
@echo " install-commandmode install-groups-users"
@echo " install-exfoliation install-classicui"
@echo " install-basic install-unstripped"
@echo " fullinstall"
# @echo " uninstall"
@echo " clean"
# 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 --exclude=html/angularjs --exclude=html/d3 --exclude=t-tap
all:
cd $(SRC_BASE) && $(MAKE)
cd $(SRC_CGI) && $(MAKE)
cd $(SRC_HTM) && $(MAKE)
if [ x$(USE_EVENTBROKER) = xyes ]; then \
cd $(SRC_MODULE) && $(MAKE); \
fi
cd $(SRC_WORKERS) && $(MAKE) $@
@echo ""
@echo "*** Compile finished ***"
@echo ""
@echo "If the main program and CGIs compiled without any errors, you"
@echo "can continue with testing or installing Nagios as follows (type"
@echo "'make' without any arguments for a list of all possible options):"
@echo ""
@echo " make test"
@echo " - This runs the test suite"
@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-daemoninit"
@echo " - This will initialize the init script"
@echo " in $(DESTDIR)$(INIT_DIR)"
@echo ""
@echo " make install-groups-users"
@echo " - This adds the users and groups if they do not exist"
@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 " https://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 " https://support.nagios.com"
@echo ""
@echo "*************************************************************"
@echo ""
@echo "Enjoy."
@echo ""
$(SRC_LIB)/libnagios.a:
cd $(SRC_LIB) && $(MAKE)
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)
workers:
cd $(SRC_WORKERS) && $(MAKE) all
clean:
cd $(SRC_LIB) && $(MAKE) $@
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) $@
cd $(SRC_WORKERS) && $(MAKE) $@
rm -f *.cfg core
rm -f *~ *.*~ */*~ */*.*~ */*/*.*~
rm -f nagioscore.info-file
rm -f *.gcno */*.gcno */*/*.gcno
rm -f *.gcda */*.gcda */*/*.gcda
rm -f *.gcov */*.gcov */*/*.gcov
rm -rf coverage-report
distclean: clean
cd $(SRC_LIB) && $(MAKE) $@
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) $@
cd $(SRC_WORKERS) && $(MAKE) $@
rm -f sample-config/*.cfg sample-config/*.conf sample-config/template-object/*.cfg
rm -f daemon-init daemon-service daemon-openrc pkginfo
rm -f Makefile subst
rm -f config.log config.status config.cache
rm -f tags
devclean: distclean
test: nagios cgis
cd $(SRC_LIB) && $(MAKE) 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
coverage: test
@if ! which lcov >/dev/null 2>&1; then \
echo "ERROR: You must install lcov and genhtml first"; \
else \
lcov -c -d . -o nagioscore.info-file; \
genhtml nagioscore.info-file -o coverage-report; \
echo "Your coverage report is in coverage-report/index.html"; \
fi
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 $(COMMAND_OPTS) -d $(DESTDIR)$(CHECKRESULTDIR)
chmod g+s $(DESTDIR)$(CHECKRESULTDIR)
@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-groups-users:
@autoconf-macros/add_group_user $(DIST) $(NAGIOS_USER) $(NAGIOS_GRP) 1
install-webconf:
$(INSTALL) -m 644 sample-config/httpd.conf $(DESTDIR)$(HTTPD_CONF)/nagios.conf
if [ $(LN_HTTPD_SITES_ENABLED) -eq 1 ]; then \
$(LN_S) $(DESTDIR)$(HTTPD_CONF)/nagios.conf $(DESTDIR)/etc/apache2/sites-enabled/nagios.conf; \
fi
@echo ""
@echo "*** Nagios/Apache conf file installed ***"
@echo ""
install-exfoliation:
@cd contrib/exfoliation; \
$(INSTALL) $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/stylesheets; \
for file in $$(find ./stylesheets/ -type f); do \
$(INSTALL) -m 644 $(INSTALL_OPTS) $${file} $(DESTDIR)$(HTMLDIR)/$${file}; \
done; \
$(INSTALL) $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/images; \
for file in $$(find ./images -type f); do \
$(INSTALL) -m 644 $(INSTALL_OPTS) $${file} $(DESTDIR)$(HTMLDIR)/$${file}; \
done; \
cd ../..
@echo ""
@echo "*** Exfoliation theme installed ***"
@echo "NOTE: Use 'make install-classicui' to revert to classic Nagios theme";
@echo ""
install-classicui:
@cd html; \
$(INSTALL) $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/stylesheets; \
for file in $$(find ./stylesheets/ -type f); do \
$(INSTALL) -m 644 $(INSTALL_OPTS) $${file} $(DESTDIR)$(HTMLDIR)/$${file}; \
done; \
$(INSTALL) $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/images; \
for file in $$(find ./images -type f); do \
$(INSTALL) -m 644 $(INSTALL_OPTS) $${file} $(DESTDIR)$(HTMLDIR)/$${file}; \
done; \
cd ..
@echo ""
@echo "*** Classic theme installed ***"
@echo "NOTE: Use 'make install-exfoliation' to use new Nagios theme";
@echo ""
install-init:
$(INSTALL) -m 755 -d $(INIT_OPTS) $(DESTDIR)$(INIT_DIR)
$(INSTALL) -m 755 $(INIT_OPTS) startup/$(SRC_INIT) $(DESTDIR)$(INIT_DIR)/$(INIT_FILE)
install-daemoninit: install-init
@if [ x$(INIT_TYPE) = xsysv ]; then \
if which chkconfig >/dev/null 2>&1; then \
chkconfig --add nagios; \
elif which update-rc.d >/dev/null 2>&1; then \
update-rc.d nagios defaults; \
fi \
elif [ x$(INIT_TYPE) = xsystemd ]; then \
if which systemctl >/dev/null 2>&1; then \
systemctl daemon-reload; \
systemctl enable nagios.service; \
fi; \
chmod 0644 $(INIT_DIR)/$(INIT_FILE); \
elif [ x$(INIT_TYPE) = xupstart ]; then \
if which initctl >/dev/null 2>&1; then \
initctl reload-configuration; \
fi \
elif [ x$(INIT_TYPE) = xopenrc ]; then \
if which rc-update >/dev/null 2>&1; then \
rc-update add nagios default; \
fi \
fi
@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 ""
install-devel: install-headers install-lib
install-headers:
$(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)
$(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/lib
$(INSTALL) -m 644 include/*.h $(DESTDIR)$(INCLUDEDIR)
$(INSTALL) -m 644 lib/*.h $(DESTDIR)$(INCLUDEDIR)/lib
rm -f $(DESTDIR)$(INCLUDEDIR)/config*.h
install-lib: $(SRC_LIB)/libnagios.a
$(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR)
$(INSTALL) -m 644 $(SRC_LIB)/libnagios.a $(DESTDIR)$(LIBDIR)
dox:
@rm -rf Documentation
doxygen doxy.conf
fullinstall: install install-init install-commandmode install-webconf install-devel
# 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
dist: distclean
rm -f nagios-$(VERSION)
ln -s . nagios-$(VERSION)
tar zhcf nagios-$(VERSION).tar.gz --exclude nagios-$(VERSION)/nagios-$(VERSION).tar.gz --exclude nagios-$(VERSION)/nagios-$(VERSION) --exclude RCS --exclude CVS --exclude build-* --exclude *~ --exclude .git* nagios-$(VERSION)/
rm -f nagios-$(VERSION)
# Targets that always get built
.PHONY: indent clean clean distclean dox test html
nagios-4.4.6/README.md 0000664 0000000 0000000 00000006503 13652113235 0014271 0 ustar 00root root 0000000 0000000 Nagios 4.x
==========

[](https://travis-ci.org/NagiosEnterprises/nagioscore)
Nagios is a host/service/network monitoring program written in C and
released under the GNU General Public License, version 2. CGI programs
are included to allow you to view the current status, history, etc via
a web interface if you so desire.
Visit the Nagios homepage at https://www.nagios.org for documentation,
new releases, bug reports, information on discussion forums, and more.
[Features](https://www.nagios.org/about/features/)
-----------------------------------------------
* Monitoring of network services (via SMTP, POP3, HTTP, PING, etc).
* Monitoring of host resources (processor load, disk usage, etc.).
* A plugin interface to allow for user-developed service monitoring
methods.
* Ability to define network host hierarchy using "parent" hosts,
allowing detection of and distinction between hosts that are down
and those that are unreachable.
* Notifications when problems occur and get resolved (via email,
pager, or user-defined method).
* Ability to define event handlers for proactive problem resolution.
* Automatic log file rotation/archiving.
* Optional web interface for viewing current network status,
notification and problem history, log file, etc.
Changes
-------
See the
[Changelog](https://raw.githubusercontent.com/NagiosEnterprises/nagioscore/master/Changelog)
for a summary of important changes and fixes, or the
[commit history](https://github.com/NagiosEnterprises/nagioscore/commits/master)
for more detail.
Download
--------
Latest releases can be downloaded from https://www.nagios.org/download/
Installation
------------
[Quickstart installation guides](http://nagios.sourceforge.net/docs/nagioscore/4/en/quickstart.html)
are available to help you get Nagios up and monitoring.
Documentation & Support
-----------------------
* [User Guide](http://nagios.sourceforge.net/docs/nagioscore/4/en/)
* [Nagios Core Documentation Library](https://library.nagios.com/library/products/nagioscore/)
* [Support Forums](https://support.nagios.com/forum/viewforum.php?f=7)
* [Additional Support Resources](https://www.nagios.org/support/)
Contributing
------------
The Nagios source code is hosted on GitHub:
https://github.com/NagiosEnterprises/nagioscore
Do you have an idea or feature request to make Nagios better? Join or start a
discussion on the [Nagios Core Development forum](https://support.nagios.com/forum/viewforum.php?f=34).
Bugs can be reported by [opening an issue on GitHub](https://github.com/NagiosEnterprises/nagioscore/issues/new).
If you have identified a security related issue in Nagios, please contact
security@nagios.com.
Patches and GitHub pull requests are welcome. Pull requests on GitHub
link commits in version control to review and discussion of the
changes, helping to show how and why changes were made, in addition to
who was involved.
Created by Ethan Galstad, the success of Nagios has been due to the
fantastic community members that support it and provide bug reports,
patches, and great ideas. See the
[THANKS file](https://raw.githubusercontent.com/NagiosEnterprises/nagioscore/master/THANKS)
for some of the many who have contributed since 1999.
nagios-4.4.6/THANKS 0000664 0000000 0000000 00000013310 13652113235 0013717 0 ustar 00root root 0000000 0000000 =======
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, misspelled it or otherwise got it
wrong, please let me know.
* Aaron Beck
* Adam Bowen
* Ahmon Dancy
* Alain Radix
* Albrecht Dress
* Alessandro Ren
* Alex Peeters
* Alexios Chouhoulas
* Allan Clark
* Alok Dubey
* Aman Gupta
* Amir Rosenblatt
* Anders K. Lindgren
* Andreas Ericsson
* Andreas Kirchwitz
* Andrew Kaplan
* Andrew Widdersheim
* Andy Finkenstadt
* Andy Shellam
* Anton Lofgren
* Ari Edelkind
* Armin Wolfermann
* Arne Hinrichsen
* Badri Pillai
* Bastian Friedrich
* Ben Bell
* Ben Heavner
* Bernard Li
* Bernd Arnold
* Bill Pier
* Bo Kersey
* Bob (Netshell)
* Bob Rentschler
* Bogdan Sandu
* Brad Werschler
* Brandon Knitter
* Brian Riggs
* Brian Seklecki
* Burkhard Klaus
* Carlos Velasco
* Cary Petterborg
* Charlie Cook
* Chris Bensend
* Chris Kolquist
* Chris Rothecker
* Chris Witterholt
* Christian Jung
* Christian Masopust
* Christian Mies
* Christian Zettel
* Christoph Biedl
* Christoph Kron
* Christoph Maser
* Cliff Woolley
* Dan Gailey
* Daniel Burke
* Daniel Koffler
* Daniel Pouzzner
* Daniel Wittenberg
* Darren Gamble
* Dave Viner
* David Allan
* David Kmoch
* David Schlecht
* David Tilloy
* David Walser
* Dawid Golunski
* Dean Lane
* Denis Seleznyov
* Dennis Biringer
* Derrick Bennett
* Devin Bayer
* Dietmar Rieder
* Dirkjan Bussink
* Don Carroll
* Duncan Ferguson
* Eirik Robertstad
* Emanuel Massano
* Ernst-Deiter Martin
* Erwan Arzur
* Esteban Manchado Velazquez
* Evan Winter
* Felipe Almeida
* Florian Weimer
* Fr3dY
* Fran Boon
* Franky Van Liedekerke
* Frederic Schaer
* Frederic Van Espen
* Gareth Randall
* Garry Cook
* Gary Berger
* Gary Miller
* Gavin Adams
* Geert Vanderkelen
* Gennaro Tortone
* Geoff Montee
* Gerd Mueller
* Gerhard Lausser
* gherteg
* Glenn Thompson
* Gordon Messmer
* Gordon Smith
* Grant Byers
* Greg Abrams
* Greg Woods
* Hayakawa Shinya
* Helmut Mikulcik
* Hendrik Baecker
* Henning Brauer
* Herbert Straub
* Hiren Patel
* Holger Weiss
* Horvath Tamas
* Hugo Gayosso
* Hugo Hallqvist
* Ian Blenke
* Ian Cass
* Igno Kley
* Ingo Lantschner
* Ivan Kuncl
* Jacob Lundqvist
* Jak Gibb
* James "Showkilr" Peterson
* James Maddison
* James Moseley
* Jan David
* Jan Grant
* Jan Vejvalka
* Janet Post
* Janice Singh
* Jason Blakey
* Jason Hedden
* Jean Gabes
* Jean-Eric Cuendet
* Jeff Cours
* Jeff Johnson
* Jeffrey Blank
* Jeffrey Goldschrafe
* Jeremy Bouse
* Jeremy Weatherford
* Jim Crilley
* Jim Dumser
* Jim Popovitch
* Jiri Kostern
* Jochen Bern
* Joel Berry
* Joel Crisp
* Joerg Linge
* John Calcote
* John Rouillard
* Jon Andrews
* Jonathan Clarke
* Jonathan Kamens
* Jonathan Saggau
* Jorge Sanchez
* Joseph Maiorana
* Josh Soref
* Josh Thorstad
* Justin Clarke
* Kai Kunstmann
* Kai Ung
* Karel Salavec
* Karl DeBisschop
* Karl Hegbloom
* Karsten Weiss
* Kenneth Ray
* Kevin Benton
* Kevin Stone
* Larry Low
* Lars Hansson
* Lars Hecking
* Lars Kellogg-Stedman
* Lars Michelson
* Lars Vogdt
* lev
* Lonny Selinger
* Lou Sneddon
* Ludo Bosmans
* Luigi Balzano
* Luiz Felipe R E
* Luke Ross
* Emmanuel Dreyfus
* Manuel Lanctot
* Marc Powell
* Marcus Fleige
* Marcus Hildenbrand
* Mario Trangoni
* Mark DeTrano
* Mark Felder
* Mark Frost
* Mark Goldfinch
* Mark Schenker
* Mark Spieth
* Markus Almroth
* Markus Baertschi
* Marlo Bell
* Martin Green
* Martin Mielke
* Mathieu Gagne
* Matt Ezell
* Matthew Grant
* Matthew Richardson
* Matthias Cramer
* Matthias Eble
* Matthias Eichler
* Matthias Flacke
* Matthias Flittner
* Matthias Kerk
* Matthieu Kermagoret
* Matthieu Kermagoret
* Mattias Ryrlen
* Max Schubert
* Max Sikstrom
* Michael Anthon
* Michael Bailey
* Michael Bunk
* Michael Little
* Michael Lubben
* Michael Marineau
* Michael O'Reilly
* Michael Orlitzky
* Michael Smedius
* Michal Zimen
* Michelle Craft
* Mika Fischer
* Mike Bird
* Mike Dorman
* Mike McHenry
* Mindaugas Riauba
* Mitch Wright
* Moshe Sharon
* Nate Shafer
* Nathan Grennan
* Nicholas Tang
* Nick Cleaton
* Nick Reinking
* Nick Shore
* Nikola Vassilev
* Olivier Beytrison
* Olivier Jan
* Parth Laxmikant Kolekar
* Patrick Proy
* Patrik Halfar
* Paul Kent
* Paul Pot
* Pavel Satrapa
* Pawel Zuzelski
* Pedro Leite
* Percy Jahn
* Perry Clarke
* Peter Ringe
* Peter Valdemar Morch
* Peter Westlake
* Petr Adamec
* Petya Kohts
* Phil Mayers
* Phil Randal
* Phil Walther
* Ralph Rossner
* Ray Bengen
* Remi Paulmier
* Rémi Verschelde
* Rene Klootwijk
* Ricardo Maraschini
* Richard Mayhew
* Rob Enders
* Rob Patrick
* Rob Remus
* Robert August Vincent II
* Robert Gash
* Robert Thompson
* Roberto Marrodan
* Robin Kearney
* Robin Sonefors
* Ronald Ho
* Rostislav Opočenský
* Russell Scibetti
* Ryan Skorstad
* Ryoji Kobayashi
* Sam Howard
* Sean Finney
* Sebastian Guarino
* Sebastian Wolf
* Sebastien Barbereau
* Sergio Guzman
* Shad Lords
* Simon Beale
* sq5bpf
* Stanley Hopcroft
* Stefan Rompf
* Stefan Schurtz
* Stephane Urbanovski
* Stephen Davies
* Stephen Gran
* Steve Underwood
* Steven Pokrandt
* Stewart James
* Stig Jacobsen
* Subhendu Ghosh
* SUSE Linux Team
* Sven Nierlein
* Sven Strickroth
* Sven-Göran Bergh
* Sylvain Falardeau
* Szabo Gabor
* Thomas Dohl
* Thomas Dunkel
* Thomas Guyot-Sionnest
* Thomas Hepper
* Thomas Sebastien
* Thomas Stolle
* Tim Starling
* Tim Wilde
* Time Niemueller
* T.J. Yang
* Tobias Klausmann
* Tobias Mucke
* Todd Green
* Todd Wheeler
* Tom Bertelson
* Tom De Blende
* Tom Ryder
* Tom Welsh
* Tomer Okavi
* Ton Voon
* Torsten Huebler
* Troy Lea
* Tyler Lund
* Uwe Knop
* Uwe Knop
* Vadim Okun
* Vojtěch Širůček
* Volkan Yazici
* Volker Aust
* William Leibzon
* William Preston
* Wolfgang Barth
* xoubih
* Yves Rubin
* Zakhar Kleyman
* Z. Liu
nagios-4.4.6/UPGRADING 0000664 0000000 0000000 00000001203 13652113235 0014245 0 ustar 00root root 0000000 0000000 Upgrading Nagios Core
=====================
nagios-4.3.0 - 2017-02-21
-------------------------
If you use "corewindow", as in
http://localhost/nagios?corewindow=www.somewhere.com
note that this functionality has been disabled by default in this
release. If you still want to use it, run ./configure with the
parameter --enable-corewindow
nagios-3.0
----------
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)
nagios-4.4.6/aclocal.m4 0000775 0000000 0000000 00000000532 13652113235 0014651 0 ustar 00root root 0000000 0000000 m4_include([autoconf-macros/ax_nagios_get_os])
m4_include([autoconf-macros/ax_nagios_get_distrib])
m4_include([autoconf-macros/ax_nagios_get_init])
m4_include([autoconf-macros/ax_nagios_get_inetd])
m4_include([autoconf-macros/ax_nagios_get_paths])
m4_include([autoconf-macros/ax_nagios_get_files])
m4_include([autoconf-macros/ax_nagios_get_ssl])
nagios-4.4.6/autoconf-macros/ 0000775 0000000 0000000 00000000000 13652113235 0016106 5 ustar 00root root 0000000 0000000 nagios-4.4.6/autoconf-macros/.gitignore 0000664 0000000 0000000 00000000013 13652113235 0020070 0 ustar 00root root 0000000 0000000 nbproject/
nagios-4.4.6/autoconf-macros/CHANGELOG.md 0000664 0000000 0000000 00000000204 13652113235 0017713 0 ustar 00root root 0000000 0000000 1.0.1
-----
* Fix bug determining inetd,xinetd if neither are running (Bryan Heden)
1.0.0
-----
* Initial Release (John Frickson) nagios-4.4.6/autoconf-macros/LICENSE 0000664 0000000 0000000 00000035505 13652113235 0017123 0 ustar 00root root 0000000 0000000 The GNU General Public License, Version 2, June 1991 (GPLv2)
============================================================
> Copyright (C) 1989, 1991 Free Software Foundation, Inc.
> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 Lesser 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.
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. nagios-4.4.6/autoconf-macros/LICENSE.md 0000777 0000000 0000000 00000000000 13652113235 0020512 2LICENSE ustar 00root root 0000000 0000000 nagios-4.4.6/autoconf-macros/README.md 0000664 0000000 0000000 00000016313 13652113235 0017371 0 ustar 00root root 0000000 0000000 autoconf-macros
===============
The purpose of Nagios autoconf-macros is to have a central place for
autoconf macros that can be maintained in one place, but be used by any
of the Nagios software. It is intended to be used as a git subtree.
See the [Usage](#usage) and [References](#references) sections below.
Since this project will be included in several parent projects, any
changes must be as project-neutral as possible.
Make sure to check out the [CHANGELOG](CHANGELOG.md) for relevant
information, as well.
Contents
--------
The collection consists of the following macros:
### AX_NAGIOS_GET_OS alias AC_NAGIOS_GET_OS
> Output Variable : `opsys`
This macro detects the operating system, and transforms it into a generic
label. The most common OS's that use Nagios software are recognized and
used in subsequent macros.
### AX_NAGIOS_GET_DISTRIB_TYPE alias AC_NAGIOS_GET_DISTRIB_TYPE
> Output Variables : `dist_type`, `dist_ver`
This macro detects the distribution type. For Linux, this would be rh
(for Red Hat and derivatives), suse (OpenSUSE, SLES, derivatives), gentoo
(Gentoo and derivatives), debian (Debian and derivatives), and so on.
For BSD, this would be openbsd, netbsd, freebsd, dragonfly, etc. It can
also be aix, solaris, osx, and so on for Unix operating systems.
### AX_NAGIOS_GET_INIT alias AC_NAGIOS_GET_INIT
> Output Variable : `init_type`
This macro detects what software is used to start daemons on bootup
or on request, generally knows as the "init system". The init_type
will generally be one of sysv (many), bsd (Slackware), newbsd (*BSD),
launchd (OS X), smf10 or smf11 (Solaris), systemd (newer Linux),
gentoo (older Gentoo), upstart (several), or unknown.
### AX_NAGIOS_GET_INETD alias AC_NAGIOS_GET_INETD
> Output Variable : `inetd_type`
This macro detects what software is used to start daemons or services
on demand, which historically has been "inetd". The inetd_type
will generally be one of inetd, xinetd, launchd (OS X), smf10 or smf11
(Solaris), systemd (newer Linux), upstart (several), or unknown.
### AX_NAGIOS_GET_PATHS alias AC_NAGIOS_GET_PATHS
> Output Variables : **many!**
This macro determines the installation paths for binaries, config files,
PID files, and so on. For a "standard" install of Nagios, NRPE, NDO Utils,
etc., most will be in the /usr/local/nagios hierarchy with startup files
located in /etc. For distributions or software repositories, the
"--enable-install-method=os" option can be used. This will determine the
O/S dependent directories, such as /usr/bin, /usr/sbin, /var/lib/nagios,
/usr/lib/nagios, etc. or for OS X, /Library/LaunchDaemons.
### AX_NAGIOS_GET_FILES alias AC_NAGIOS_GET_FILES
> Output Variables : `src_init`, `src_inetd`, `src_tmpfile`
Each Nagios project will have a top-level directory named "/startup/".
In that directory will be "*.in" files for the various "init_type" and
"inetd_type" systems. This macro will determine which file(s) from
that directory will be needed.
### AX_NAGIOS_GET_SSL alias AC_NAGIOS_GET_SSL
> Output Variables : `HAVE_KRB5_H`, `HAVE_SSL`, `SSL_INC_DIR`, `SSL_LIB_DIR`, `CFLAGS`, `LDFLAGS`, `LIBS`
This macro checks various directories for SSL libraries and header files.
The searches are based on known install locations on various operating
systems and distributions, for openssl, gnutls-openssl, and nss_compat_ossl.
If it finds the headers and libraries, it will then do an `AC_LINK_IFELSE`
on a simple program to make sure a compile and link will work correctly.
Usage
-----
This repo is intended to be used as a git subtree, so changes will
automatically propagate, and still be reasonably easy to use.
* First, Create, checkout, clone, or branch your project. If you do an
`ls -AF` it might look something like this:
.git/ .gitignore ChangeLog LICENSE Makefile.in
README configure.ac include/ src/
* Then make a reference to _this_ project inside your project.
git remote add autoconf-macros git@github.com:NagiosEnterprises/autoconf-macros
git subtree add --prefix=macros/ autoconf-macros master
* After executing the above two commands, if you do an `ls -AF` now,
it should look like this:
.git/ .gitignore ChangeLog LICENSE Makefile.in
README configure.ac include/ macros/ src/
* The `macros/` directory has been added.
* Now do a `git push` to save everything.
* If you make any changes to autoconf-macros, commit them separately
from any parent-project changes to keep from polluting the commit
history with unrelated comments.
* To submit your changes to autoconf-macros:
git subtree push --prefix=macros autoconf-macros peters-updates
This will create a new branch called `peters-updates`. You then need to
create a _pull request_ to get your changes merged into autoconf-macros
master.
* To get the latest version of `autoconf-macros` into your parent project:
git subtgree pull --squash --prefix=macros autoconf-macros master
References
----------
Now that autoconf-macros is available to your project, you will need to
reference it.
* Create (or add these lines to) file `YourProject/aclocal.m4`
m4_include([macros/ax_nagios_get_os])
m4_include([macros/ax_nagios_get_distrib])
m4_include([macros/ax_nagios_get_init])
m4_include([macros/ax_nagios_get_inetd])
m4_include([macros/ax_nagios_get_paths])
m4_include([macros/ax_nagios_get_files])
m4_include([macros/ax_nagios_get_ssl])
* In your `YourProject/configure.ac` add the following lines. A good place
to put them would be right after any `AC_PROG_*` entries:
AC_NAGIOS_GET_OS
AC_NAGIOS_GET_DISTRIB_TYPE
AC_NAGIOS_GET_INIT
AC_NAGIOS_GET_INETD
AC_NAGIOS_GET_PATHS
AC_NAGIOS_GET_FILES
* If you need SSL functionality, add the following to `YourProject/configure.ac`
where you want to check for SSL:
AC_NAGIOS_GET_SSL
* You will now be able to reference any of the variables in `config.h.in`
and any files listed in the `AC_CONFIG_FILES` macro in `configure.ac`.
License Notice
--------------
Copyright (c) 2016-2017 Nagios Enterprises, LLC
This work is made available to you under the terms of Version 2 of
the GNU General Public License. A copy of that license should have
been provided with this software, but in any event can be obtained
from http://www.fsf.org.
This work 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 or visit their web page on the internet at
http://www.fsf.org.
Questions?
----------
If you have questions about this addon, or problems getting things
working, first try searching the nagios-users mailing list archives.
Details on searching the list archives can be found at
http://www.nagios.org
If you don't find an answer there, post a message in the Nagios
Plugin Development forum at https://support.nagios.com/forum/viewforum.php?f=35
nagios-4.4.6/autoconf-macros/add_group_user 0000775 0000000 0000000 00000007355 13652113235 0021050 0 ustar 00root root 0000000 0000000 #!/bin/sh
#----------------------
# Initialize variables
#----------------------
dist="$1"
uid="$2"
gid="$3"
rc=0
#------------------------------------------------------------------
# Determine if the user should be created with a shell environment
# 0 = no shell (more secure)
# 1 = shell (less secure but sometimes required)
#------------------------------------------------------------------
shell=0
if [ $# -eq 4 ]; then
if [ x$4 = x1 ]; then
shell=1
fi
fi
#-------------------------------------
# Check if the specified group exists
#-------------------------------------
group_exists(){
case $dist in
osx) rc=`dscl . -read /Groups/$gid >/dev/null 2>&1; echo $?` ;;
hpux) rc=`grget -n $gid >/dev/null 2>&1; echo $?` ;;
aix) rc=`lsgroup -a $gid >/dev/null 2>&1; echo $?` ;;
*) rc=`getent group $gid > /dev/null 2>&1; echo $?` ;;
esac
echo $rc
}
#------------------------
# Add the specified user
#------------------------
add_user(){
rc=`id "$uid" > /dev/null 2>&1; echo $?`
if test $rc -eq 0; then
echo "User $uid already exists" > /dev/stderr
echo 0
return
fi
case $dist in
aix)
echo useradd -g $gid $uid > /dev/stderr
rc=`useradd -g $gid $uid; echo $?`
;;
hpux)
echo useradd -m -g $gid $uid > /dev/stderr
rc=`useradd -m -g $gid $uid; echo $?`
;;
solaris)
echo useradd -m -d /export/home/$uid -g $gid $uid > /dev/stderr
rc=`useradd -m -d /export/home/$uid -g $gid $uid; echo $?`
;;
osx)
newid=`dscl . -list /Users UniqueID | tr -s ' ' | cut -d' ' -f2 | sort -n | tail -1`
newid=`expr 1 + $newid`
echo dscl . -create /Users/$uid > /dev/stderr
dscl . -create /Users/$uid
echo dscl . -create /Users/$uid UniqueID $newid > /dev/stderr
dscl . -create /Users/$uid UniqueID $newid
if [ $shell = 0 ]; then
echo dscl . -create /Users/$uid UserShell /usr/bin/false > /dev/stderr
dscl . -create /Users/$uid UserShell /usr/bin/false
fi
echo dscl . -create /Users/$uid PrimaryGroupID 20 > /dev/stderr
dscl . -create /Users/$uid PrimaryGroupID 20
echo dscl . -append /Groups/$gid GroupMembership $uid > /dev/stderr
rc=`dscl . -append /Groups/$gid GroupMembership $uid; echo $?`
;;
freebsd)
if [ $shell = 0 ]; then
echo pw add user $uid -g $gid -s /usr/bin/false > /dev/stderr
rc=`pw add user $uid -g $gid -s /usr/bin/false; echo $?`
else
echo pw add user $uid -g $gid > /dev/stderr
rc=`pw add user $uid -g $gid; echo $?`
fi
;;
netbsd|openbsd)
echo useradd -g $gid $uid > /dev/stderr
rc=`useradd -g $gid $uid; echo $?`
;;
*)
if [ $shell = 0 ]; then
echo useradd -r -g $gid $uid > /dev/stderr
rc=`useradd -r -g $gid $uid; echo $?`
else
echo useradd -g $gid $uid > /dev/stderr
rc=`useradd -g $gid $uid; echo $?`
fi
;;
esac
echo $rc
}
#-------------------------
# Add the specified group
#-------------------------
add_group(){
rc=`group_exists`
if test $rc -eq 0; then
echo "Group $gid already exists" > /dev/stderr
echo 0
return
fi
case $dist in
aix)
echo mkgroup $gid > /dev/stderr
rc=`mkgroup "$gid"; echo $?`
;;
hpux|solaris)
echo groupadd $gid > /dev/stderr
rc=`groupadd "$gid"; echo $?`
;;
osx)
newid=`dscl . -list /Groups gid | tr -s ' ' | cut -d' ' -f2 | sort -n | tail -1`
newid=`expr 1 + $newid`
echo dscl . -create /Groups/$gid gid $newid > /dev/stderr
rc=`dscl . -create /Groups/$gid gid $newid; echo $?`
;;
freebsd)
echo pw add group $gid > /dev/stderr
rc=`pw add group $gid; echo $?`
;;
netbsd|openbsd)
echo groupadd $gid > /dev/stderr
rc=`groupadd $gid; echo $?`
;;
*)
echo groupadd -r $gid > /dev/stderr
rc=`groupadd -r $gid; echo $?`
;;
esac
echo $rc
}
rc=`add_group`
if test $rc -ne 0; then
exit 1;
fi
rc=`add_user`
exit $rc
nagios-4.4.6/autoconf-macros/ax_nagios_get_distrib 0000664 0000000 0000000 00000011431 13652113235 0022360 0 ustar 00root root 0000000 0000000 # ===========================================================================
# SYNOPSIS
#
# AX_NAGIOS_GET_DISTRIB_TYPE
#
# DESCRIPTION
#
# This macro determines the O/S distribution of the computer it is run on.
# $dist_type will be set and will be one of:
# unknown (could not be determined)
# freebsd, netbsd, openbsd, dragonfly, etc (The BSDs)
# suse, rh, debian, gentoo (and possibly their descendants)
# Other major Linux distributions (and possibly their descendants)
# The O/S name for the rest
#
# LICENSE
#
# Copyright (c) 2016 Nagios Core Development Team
#
# 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, see .
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
# ===========================================================================
AU_ALIAS([AC_NAGIOS_GET_DISTRIB_TYPE], [AX_NAGIOS_GET_DISTRIB_TYPE])
AC_DEFUN([AX_NAGIOS_GET_DISTRIB_TYPE],
[
AC_SUBST(dist_type)
AC_SUBST(dist_ver)
#
# Get user hints for possible cross-compile
#
AC_MSG_CHECKING(what the distribution type is )
AC_ARG_WITH(dist-type, AC_HELP_STRING([--with-dist-type=type],
[specify distribution type (suse, rh, debian, etc.)]),
[
#
# Run this if --with was specified
#
if test "x$withval" = x -o x$withval = xno; then
dist_type_wanted=yes
else
dist_type_wanted=no
dist_type="$withval"
dist_ver="unknown"
AC_MSG_RESULT($dist_type)
fi
], [
#
# Run this if --with was not specified
#
dist_type_wanted=yes
])
if test x$dist_type = xno; then
dist_type_wanted=yes
elif test x$dist_type = xyes; then
AC_MSG_ERROR([you must enter a distribution type if '--with-dist-type' is specified])
fi
#
# Determine distribution type if it wasn't supplied
#
dist_ver="unknown"
if test $dist_type_wanted=yes; then
dist_type="unknown"
if test "$opsys" != "linux"; then
dist_type="$opsys"
AS_CASE([$opsys],
[bsd],
dist_type=`uname -s | tr ["[A-Z]" "[a-z]"]`
dist_ver=`uname -r`,
[aix],
dist_ver="`uname -v`.`uname -r`",
[hp-ux],
dist_ver=`uname -r | cut -d'.' -f1-3`,
[solaris],
dist_ver=`uname -r | cut -d'.' -f2`,
[*],
dist_ver=$OSTYPE
)
else
if test -r "/etc/gentoo-release"; then
dist_type="gentoo"
dist_ver=`cat /etc/gentoo-release`
elif test -r "/etc/os-release"; then
. /etc/os-release
if test x"$ID_LIKE" != x; then
dist_type=`echo $ID_LIKE | cut -d' ' -f1 | tr ["[A-Z]" "[a-z]"]`
elif test x"$ID" = xol; then
dist_type=rh
else
dist_type=`echo $ID | tr ["[A-Z]" "[a-z]"]`
fi
if test x"$dist_type" = sles; then
dist_type=suse
fi
if test x"$VERSION_ID" != x; then
dist_ver=$VERSION_ID
elif test x"$VERSION" != x; then
dist_ver=`echo $VERSION | cut -d'.' -f1 | tr -d [:alpha:][:blank:][:punct:]`
fi
elif test -r "/etc/redhat-release"; then
dist_type=rh
dist_ver=`cat /etc/redhat-release`
elif test -r "/etc/debian_version"; then
dist_type="debian"
if test -r "/etc/lsb-release"; then
. /etc/lsb-release
dist_ver=`echo "$DISTRIB_RELEASE"`
else
dist_ver=`cat /etc/debian_version`
fi
elif test -r "/etc/SuSE-release"; then
dist_type=suse
dist_ver=`grep VERSION /etc/SuSE-release`
fi
fi
if test "$dist_ver" != "unknown"; then
dist_ver=`echo "$dist_ver" | cut -d'.' -f1 | tr -d [:alpha:][:blank:][:punct:]`
fi
fi
AC_MSG_RESULT($dist_type)
])
nagios-4.4.6/autoconf-macros/ax_nagios_get_files 0000664 0000000 0000000 00000006504 13652113235 0022027 0 ustar 00root root 0000000 0000000 # ===========================================================================
# SYNOPSIS
#
# AX_NAGIOS_GET_FILES
#
# DESCRIPTION
#
# This macro figures out which init and/or inetd files to use based
# on the results of the AX_NAGIOS_GET_OS, AX_NAGIOS_GET_DISTRIB_TYPE,
# AX_NAGIOS_GET_INIT and AX_NAGIOS_GET_INETD macros. It will select
# the appropriate files(s) from the 'startup' directory and copy it.
#
# LICENSE
#
# Copyright (c) 2016 Nagios Core Development Team
#
# 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, see .
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
# ===========================================================================
AU_ALIAS([AC_NAGIOS_GET_FILES], [AX_NAGIOS_GET_FILES])
AC_DEFUN([AX_NAGIOS_GET_FILES],
[
AC_SUBST(src_init)
AC_SUBST(src_inetd)
AC_SUBST(src_tmpfile)
AC_SUBST(bsd_enable)
src_inetd=""
src_init=""
bsd_enable=""
AC_MSG_CHECKING(for which init file to use )
AS_CASE([$init_type],
[sysv],
src_init=default-init,
[systemd],
src_tmpfile=tmpfile.conf
src_init=default-service,
[bsd],
src_init=bsd-init,
[newbsd],
if test $dist_type = freebsd ; then
bsd_enable="_enable"
src_init=default-init
elif test $dist_type = openbsd ; then
bsd_enable="_flags"
src_init=openbsd-init
elif test $dist_type = netbsd ; then
bsd_enable=""
src_init=newbsd-init
fi,
# [gentoo],
[openrc],
src_init=openrc-init,
[smf*],
src_init="solaris-init.xml"
src_inetd="solaris-inetd.xml",
[upstart],
if test $dist_type = rh ; then
src_init=rh-upstart-init
else
src_init=upstart-init
fi,
[launchd],
src_init="mac-init.plist",
[*],
src_init="unknown"
)
AC_MSG_RESULT($src_init)
AC_MSG_CHECKING(for which inetd files to use )
if test x$src_inetd = x; then
AS_CASE([$inetd_type],
[inetd*],
src_inetd=default-inetd,
[xinetd],
src_inetd=default-xinetd,
[systemd],
src_inetd=default-socket,
[launchd],
src_inetd="mac-inetd.plist",
[*],
src_inetd="unknown"
)
fi
AC_MSG_RESULT($src_inetd)
])
nagios-4.4.6/autoconf-macros/ax_nagios_get_inetd 0000664 0000000 0000000 00000010367 13652113235 0022032 0 ustar 00root root 0000000 0000000 # ===========================================================================
# SYNOPSIS
#
# AX_NAGIOS_GET_INETD
#
# DESCRIPTION
#
# This macro determines whether inetd or xinetd is being used
# The argument are:
# the init type as determined by AX_NAGIOS_GET_INIT
# $inetd_type will be set and will be one of:
# unknown (could not be determined)
# launchd (Mac OS X)
# smf10 (Solaris)
# smf11 (Solaris)
# upstart (Older Debian)
# xinetd (Most Linux, BSD)
# inetd (The rest)
#
# LICENSE
#
# Copyright (c) 2016 Nagios Core Development Team
#
# 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, see .
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
# ===========================================================================
AU_ALIAS([AC_NAGIOS_GET_INETD], [AX_NAGIOS_GET_INETD])
AC_DEFUN([AX_NAGIOS_GET_INETD],
[
AC_SUBST(inetd_type)
#
# Get user hints for possible cross-compile
#
AC_MSG_CHECKING(what inetd is being used )
AC_ARG_WITH(inetd_type, AC_HELP_STRING([--with-inetd-type=type],
[which super-server the system runs (inetd, xinetd, systemd, launchd,
smf10, smf11, etc.)]),
[
inetd_type_wanted=yes
#
# Run this if --with was specified
#
if test "x$withval" = x -o x$withval = xno; then
inetd_type_wanted=yes
else
inetd_type_wanted=no
inetd_type="$withval"
AC_MSG_RESULT($inetd_type)
fi
], [
#
# Run this if --with was not specified
#
inetd_type_wanted=yes
])
if test x$inetd_type = xno; then
inetd_type_wanted=yes
elif test x$inetd_type = xyes; then
AC_MSG_ERROR([you must enter an inetd type if '--with-inetd-type' is specified])
fi
#
# Determine inetd type if it wasn't supplied
#
if test $inetd_type_wanted = yes; then
inetd_disabled=""
AS_CASE([$dist_type],
[solaris],
if test x"$init_type" = "xsmf10" -o x"$init_type" = "xsmf11"; then
inetd_type="$init_type"
else
inetd_type="inetd"
fi,
[*bsd*],
inetd_type=`ps -A -o comm -c | grep inetd`,
[osx],
inetd_type=`launchd`,
[aix|hp-ux],
inetd_type=`UNIX95= ps -A -o comm | grep inetd | head -1`,
[*],
inetd_type=[`ps -C "inetd,xinetd" -o fname | grep -vi COMMAND | head -1`])
if test x"$inetd_type" = x; then
if test -f /etc/xinetd.conf -a -d /etc/xinetd.d; then
inetd_disabled="(Not running)"
inetd_type=xinetd
elif test -f /etc/inetd.conf -o -f /usr/sbin/inetd; then
inetd_type=inetd
inetd_disabled="(Not running)"
fi
fi
if test x"$inetd_type" = x; then
if test x"$init_type" = "xupstart"; then
inetd_type="upstart"
fi
fi
if test x"$inetd_type" = x; then
if test x"$init_type" = "xsystemd"; then
inetd_type="systemd"
else
inetd_type="unknown"
fi
fi
if test -n "$inetd_disabled"; then
AC_MSG_RESULT($inetd_type $inetd_disabled)
else
AC_MSG_RESULT($inetd_type)
fi
fi
])
nagios-4.4.6/autoconf-macros/ax_nagios_get_init 0000664 0000000 0000000 00000013304 13652113235 0021664 0 ustar 00root root 0000000 0000000 # ===========================================================================
# SYNOPSIS
#
# AX_NAGIOS_GET_INIT
#
# DESCRIPTION
#
# This macro determines the O/S distribution of the computer it is run on.
# $init_type will be set and will be one of:
# unknown (could not be determined)
# launchd (Mac OS X)
# bsd (Slackware Linux)
# newbsd (FreeBSD, OpenBSD, NetBSD, Dragonfly, etc)
# smf10 (Solaris)
# smf11 (Solaris)
# systemd (Linux SystemD)
# gentoo (Older Gentoo)
# openrc (Recent Gentoo and some others)
# upstart (Older Debian)
# sysv (The rest)
#
# LICENSE
#
# Copyright (c) 2016 Nagios Core Development Team
#
# 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, see .
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
# ===========================================================================
AU_ALIAS([AC_NAGIOS_GET_INIT], [AX_NAGIOS_GET_INIT])
AC_DEFUN([AX_NAGIOS_GET_INIT],
[
AC_SUBST(init_type)
#
# Get user hints for possible cross-compile
#
AC_MSG_CHECKING(what init system is being used )
AC_ARG_WITH(init_type,AC_HELP_STRING([--with-init-type=type],
[specify init type (bsd, sysv, systemd, launchd, smf10, smf11, upstart,
openrc, etc.)]),
[
#
# Run this if --with was specified
#
if test "x$withval" = x -o x$withval = xno; then
init_type_wanted=yes
else
init_type_wanted=no
init_type="$withval"
AC_MSG_RESULT($init_type)
fi
], [
#
# Run this if --with was not specified
#
init_type_wanted=yes
])
if test x$init_type = xno; then
init_type_wanted=yes
elif test x$init_type = xyes; then
AC_MSG_ERROR([you must enter an init type if '--with-init-type' is specified])
fi
#
# Determine init type if it wasn't supplied
#
if test $init_type_wanted = yes; then
init_type=""
if test x"$opsys" = x; then
init_type="unknown"
init_type_wanted=no
elif test x"$dist_type" = x; then
init_type="unknown"
init_type_wanted=no
elif test "$opsys" = "osx"; then
init_type="launchd"
init_type_wanted=no
elif test "$opsys" = "bsd"; then
init_type="newbsd"
init_type_wanted=no
elif test "$dist_type" = "solaris"; then
if test -d "/lib/svc/manifest"; then
init_type="smf11"
init_type_wanted=no
elif test -d "/lib/svc/monitor"; then
init_type="smf10"
init_type_wanted=no
else
init_type="sysv"
init_type_wanted=no
fi
elif test "$dist_type" = "slackware"; then
init_type="bsd"
init_type_wanted=no
elif test "$dist_type" = "aix"; then
init_type="bsd"
init_type_wanted=no
elif test "$dist_type" = "hp-ux"; then
init_type="unknown"
init_type_wanted=no
fi
fi
PSCMD="ps -p1 -o args"
if test $dist_type = solaris; then
PSCMD="env UNIX95=1; ps -p1 -o args"
fi
if test "$init_type_wanted" = yes; then
pid1=`$PSCMD | grep -vi COMMAND | cut -d' ' -f1`
if test x"$pid1" = "x"; then
init_type="unknown"
init_type_wanted=no
fi
if `echo $pid1 | grep "systemd" > /dev/null`; then
init_type="systemd"
init_type_wanted=no
fi
if test "$init_type_wanted" = yes; then
if test "$pid1" = "init"; then
if test -e "/sbin/init"; then
pid1="/sbin/init";
elif test -e "/usr/sbin/init"; then
pid1="/usr/sbin/init"
else
init_type="unknown"
init_type_wanted=no
fi
fi
if test -L "$pid1"; then
pid1=`readlink "$pid1"`
fi
fi
if test "$init_type_wanted" = yes; then
if `echo $pid1 | grep "systemd" > /dev/null`; then
init_type="systemd"
init_type_wanted=no
elif test -f "/sbin/rc"; then
if test -f /sbin/runscript; then
init_type_wanted=no
if `/sbin/start-stop-daemon -V | grep "OpenRC" > /dev/null`; then
init_type="openrc"
else
init_type="gentoo"
fi
fi
fi
fi
if test "$init_type_wanted" = yes; then
if test "$pid1" = "/sbin/init" -o "$pid1" = "/usr/sbin/init"; then
if `$pid1 --version 2>/dev/null | grep "upstart" >/dev/null`; then
init_type="upstart"
init_type_wanted=no
elif test -f "/etc/rc" -a ! -L "/etc/rc"; then
init_type="newbsd"
init_type_wanted=no
else
init_type="sysv"
init_type_wanted=no
fi
fi
fi
if test "$init_type_wanted" = yes; then
init_type="unknown"
fi
fi
AC_MSG_RESULT($init_type)
])
nagios-4.4.6/autoconf-macros/ax_nagios_get_os 0000664 0000000 0000000 00000006145 13652113235 0021347 0 ustar 00root root 0000000 0000000 # ===========================================================================
# SYNOPSIS
#
# AX_NAGIOS_GET_OS
#
# DESCRIPTION
#
# This macro determines the operating system of the computer it is run on.
#
# LICENSE
#
# Copyright (c) 2016 Nagios Core Development Team
#
# 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, see .
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
# ===========================================================================
AU_ALIAS([AC_NAGIOS_GET_OS], [AX_NAGIOS_GET_OS])
AC_DEFUN([AX_NAGIOS_GET_OS],
[
AC_SUBST(opsys)
AC_SUBST(arch)
#
# Get user hints
#
AC_MSG_CHECKING(what the operating system is )
AC_ARG_WITH(opsys, AC_HELP_STRING([--with-opsys=OS],
[specify operating system (linux, osx, bsd, solaris, irix, cygwin,
aix, hp-ux, etc.)]),
[
#
# Run this if --with was specified
#
if test "x$withval" = x -o x$withval = xno; then
opsys_wanted=yes
else
opsys_wanted=no
opsys="$withval"
AC_MSG_RESULT($opsys)
fi
], [
#
# Run this if --with was not specified
#
opsys_wanted=yes
])
if test x$opsys = xno; then
opsys=""
opsys_wanted=yes
elif test x$opsys = xyes; then
AC_MSG_ERROR([you must enter an O/S type if '--with-opsys' is specified])
fi
#
# Determine operating system if it wasn't supplied
#
if test $opsys_wanted=yes; then
opsys=`uname -s | tr ["[A-Z]" "[a-z]"]`
if test x"$opsys" = "x"; then opsys="unknown"; fi
AS_CASE([$opsys],
[darwin*], opsys="osx",
[*bsd*], opsys="bsd",
[dragonfly], opsys="bsd",
[sunos], opsys="solaris",
[gnu/hurd], opsys="linux",
[irix*], opsys="irix",
[cygwin*], opsys="cygwin",
[mingw*], opsys="mingw",
[msys*], opsys="msys")
fi
arch=`uname -m | tr ["[A-Z]" "[a-z]"]`
AC_MSG_RESULT($opsys)
])
nagios-4.4.6/autoconf-macros/ax_nagios_get_paths 0000664 0000000 0000000 00000053103 13652113235 0022041 0 ustar 00root root 0000000 0000000 # ===========================================================================
# SYNOPSIS
#
# AX_NAGIOS_GET_PATHS
#
# DESCRIPTION
#
# This macro figures out the installation & run paths for various systems
# The argument are:
# the O/S determined by the AX_NAGIOS_GET_OS macro.
# the distribution type as determined by AX_NAGIOS_GET_DISTRIB_TYPE
# the init type as determined by AX_NAGIOS_GET_INIT
# the inetd type as determined by AX_NAGIOS_GET_INETD
#
# LICENSE
#
# Copyright (c) 2016 Nagios Core Development Team
#
# 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, see .
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
# ===========================================================================
AU_ALIAS([AC_NAGIOS_GET_PATHS], [AX_NAGIOS_GET_PATHS])
AC_DEFUN([AX_NAGIOS_GET_PATHS],
[
AC_SUBST(pkgsysconfdir)
AC_SUBST(objsysconfdir)
AC_SUBST(initname)
AC_SUBST(inetdname)
AC_SUBST(pluginsdir)
AC_SUBST(brokersdir)
AC_SUBST(cgibindir)
AC_SUBST(webdir)
AC_SUBST(privatesysconfdir)
AC_SUBST(pkglocalstatedir)
AC_SUBST(logdir)
AC_SUBST(piddir)
AC_SUBST(pipedir)
AC_SUBST(spooldir)
AC_SUBST(initdir)
AC_SUBST(initdiroverridden)
AC_SUBST(inetddir)
AC_SUBST(tmpfilesd)
AC_SUBST(subsyslockdir)
AC_SUBST(subsyslockfile)
if test x$DBG_PATHS != x; then
echo
echo Incoming paths:
echo " prefix $prefix"
echo " exec_prefix $exec_prefix"
echo " bindir $bindir"
echo " libexecdir $libexecdir"
echo " sysconfdir $sysconfdir"
echo " localstatedir $localstatedir"
echo " datarootdir $datarootdir"
echo " datadir $datadir"
echo " localedir $localedir"
echo
fi
AC_MSG_CHECKING(for which paths to use )
AC_ARG_ENABLE(install_method,
AC_HELP_STRING([--enable-install-method=],
[sets the install method to use: 'default' (the default) will install to
/usr/local/nagios, 'os' will try to determine which method to use based
on OS type and distribution. Fine tuning using the '--bindir', etc.
overrides above will still work]),
install_method=$enableval,
install_method=default
)
AC_ARG_ENABLE(showdirs_only,
AC_HELP_STRING([--enable-showdirs-only=yes],
[This option will cause 'configure' to stop after determining the install
locations based on '--enable-install-method', so you can see the
destinations before a full './configure', 'make', 'make install'
process.]),
showdirs_only=$enableval,
showdirs_only=no
)
AS_CASE([$install_method],
[yes], install_method="os",
[no], install_method="default",
[default|os], :,
[*], echo >&6; AC_MSG_ERROR(['--enable-install-method=$install_method' is invalid])
)
if test $showdirs_only != "no"; then showdirs_only="yes"; fi
AS_CASE([$dist_type],
[*solaris*|*hp-ux*|*aix*|*osx*], opsys=unix)
# Does this package need to know:
need_cgi=no # where the cgi-bin directory is
need_web=no # where the website directory is
need_brk=no # where the event broker modules directory is
need_plg=no # where the plugins directory is
need_pipe=no # where the pipe directory is
need_spl=no # where the spool directory is
need_loc=no # where the locale directory is
need_log_subdir=no # where the loc sub-directory is
need_etc_subdir=no # where the etc sub-directory is
need_pls_dir=no # where the package locate state directory is
if test x"$INIT_PROG" = x; then
INIT_PROG="$PKG_NAME"
fi
AS_CASE([$PKG_NAME],
[nagios],
need_log_subdir=yes
need_etc_subdir=yes
need_pls_dir=yes
need_brk=yes
need_pipe=yes
need_spl=yes
need_loc=yes
need_cgi=yes
need_web=yes,
[ndoutils],
need_brk=yes
need_spl=yes,
[nrpe],
need_plg=yes,
[nsca],
need_cgi=no,
[plugins],
need_loc=yes
need_plg=yes
)
AC_ARG_WITH(pkgsysconfdir, AC_HELP_STRING([--with-pkgsysconfdir=DIR],
[where configuration files should be placed]),
if test x$withval != x -a x$withval != xno -a x$withval != xyes; then
pkgsysconfdir="$withval"
fi)
AC_ARG_WITH(objsysconfdir, AC_HELP_STRING([--with-objsysconfdir=DIR],
[where object configuration files should be placed]),
if test x$withval != x -a x$withval != xno -a x$withval != xyes; then
objsysconfdir="$withval"
fi)
AC_ARG_WITH(privatesysconfdir, AC_HELP_STRING([--with-privatesysconfdir=DIR],
[where private configuration files should be placed]),
if test x$withval != x -a x$withval != xno -a x$withval != xyes; then
privatesysconfdir="$withval"
fi)
AC_ARG_WITH(webdir, AC_HELP_STRING([--with-webdir=DIR],
[where the website files should be placed]),
if test x$withval != x -a x$withval != xno -a x$withval != xyes; then
webdir="$withval"
fi)
AC_ARG_WITH(pluginsdir, AC_HELP_STRING([--with-pluginsdir=DIR],
[where the plugins should be placed]),
if test x$withval != x -a x$withval != xno -a x$withval != xyes; then
pluginsdir="$withval"
fi)
AC_ARG_WITH(brokersdir, AC_HELP_STRING([--with-brokersdir=DIR],
[where the broker modules should be placed]),
if test x$withval != x -a x$withval != xno -a x$withval != xyes; then
brokersdir="$withval"
fi)
AC_ARG_WITH(cgibindir, AC_HELP_STRING([--with-cgibindir=DIR],
[where the CGI programs should be placed]),
if test x$withval != x -a x$withval != xno -a x$withval != xyes; then
cgibindir="$withval"
fi)
AC_ARG_WITH(logdir, AC_HELP_STRING([--with-logdir=DIR],
[where log files should be placed]),
if test x$withval != x -a x$withval != xno -a x$withval != xyes; then
logdir="$withval"
fi)
AC_ARG_WITH(piddir, AC_HELP_STRING([--with-piddir=DIR],
[where the PID file should be placed]),
if test x$withval != x -a x$withval != xno -a x$withval != xyes; then
piddir="$withval"
fi)
AC_ARG_WITH(pipedir, AC_HELP_STRING([--with-pipedir=DIR],
[where socket and pipe files should be placed]),
if test x$withval != x -a x$withval != xno -a x$withval != xyes; then
pipedir="$withval"
fi)
#
# Setup the base directory
#
if test $install_method = "default"; then
if test $opsys = "unix"; then
if test x"$prefix" = "xNONE"; then prefix="/usr/local/nagios"; fi
else
if test x"$prefix" = "xNONE"; then prefix=${ac_default_prefix}; fi
fi
datarootdir=${datarootdir="$prefix"}
else
if test x"$datadir" = x'${datarootdir}'; then AS_UNSET(datadir); fi
if test x"$sysconfdir" = x'${prefix}/etc'; then AS_UNSET(sysconfdir); fi
if test x"$prefix" = "xNONE"; then
if test $dist_type = freebsd -o $dist_type = openbsd -o $dist_type = osx; then
prefix="/usr/local"
elif test $dist_type = netbsd; then
prefix="/usr/pkg"
else
prefix="/usr"
fi
fi
if test x"$exec_prefix" = "xNONE"; then exec_prefix=$prefix; fi
if test x"$localstatedir" = x'${prefix}/var'; then
if test $dist_type = "osx"; then
localstatedir="/private/var"
else
localstatedir="/var"
fi
fi
if test $opsys = "unix"; then
if test x"$datarootdir" = x'${prefix}/share'; then
if test $dist_type = "hp-ux"; then
datarootdir="/usr/local/share"
if test x"$libexecdir" = x'${exec_prefix}/libexec'; then
libexecdir="/usr/nagios"
fi
elif test $dist_type = "osx"; then
datarootdir="/usr/local/share"
if test x"$libexecdir" = x'${exec_prefix}/libexec'; then
libexecdir="/usr/local/nagios"
fi
elif test x"$libexecdir" = x'${exec_prefix}/libexec'; then
libexecdir="/usr/lib/nagios"
fi
fi
if test $dist_type = "osx"; then
if test x"$libexecdir" = x'${exec_prefix}/libexec'; then
libexecdir="/usr/local/libexec/nagios"
fi
fi
elif test $opsys = "bsd"; then
if test x"$libexecdir" = x'${exec_prefix}/libexec'; then
libexecdir=${exec_prefix}/libexec/nagios;
fi
elif test x"$libexecdir" = x'${exec_prefix}/lib'; then
libexecdir=${libexecdir}/nagios;
elif test x"$libexecdir" = x'${exec_prefix}/libexec'; then
libexecdir=${exec_prefix}/lib/nagios;
fi
fi
if test x"$exec_prefix" = "xNONE"; then exec_prefix=${prefix}; fi
tmpfilesd=${tmpfilesd="/usr/lib/tmpfiles.d"}
if test ! -d "$tmpfilesd"; then
tmpfilesd="N/A"
else
tmpfilesd="$tmpfilesd/$INIT_PROG.conf"
fi
subsyslockdir=${subsyslockdir="/run"}
if test ! -d "$subsyslockdir"; then
subsyslockdir="N/A"
subsyslockfile="N/A"
else
subsyslockfile="$subsyslockdir/$INIT_PROG.lock"
fi
if test "$need_loc" = no; then
localedir="N/A"
fi
if test $install_method = "default" ; then
#
# Do the default setup
#
datadir=${datadir="$datarootdir"}
if test $need_web = yes; then
webdir=${webdir="$datadir"}
else
webdir="N/A"
fi
if test $opsys = "unix"; then
sysconfdir=${sysconfdir="/etc/opt"}
fi
pkgsysconfdir=${pkgsysconfdir="$sysconfdir"}
if test $need_etc_subdir = yes; then
objsysconfdir=${objsysconfdir="$pkgsysconfdir/objects"}
else
objsysconfdir="N/A"
fi
privatesysconfdir=${privatesysconfdir="$pkgsysconfdir"}
logdir=${logdir="$localstatedir"}
piddir=${piddir="$localstatedir"}
if test "$need_pipe" = yes; then
pipedir=${pipedir="$localstatedir/rw"}
else
pipedir="N/A"
fi
if test "$need_pls_dir" = yes; then
pkglocalstatedir=${pkglocalstatedir="$localstatedir"}
else
pkglocalstatedir="N/A"
fi
if test "$need_spl" = yes; then
spooldir=${spooldir="$localstatedir/var"}
else
spooldir="N/A"
fi
if test $need_brk = yes; then
brokersdir=${brokersdir="$bindir"}
else
brokersdir="N/A"
fi
if test $need_plg = yes; then
pluginsdir=${pluginsdir="$libexecdir"}
else
pluginsdir="N/A"
fi
if test $need_cgi = yes; then
cgibindir=${cgibindir="$prefix/sbin"}
else
cgibindir="N/A"
fi
elif test $opsys = "linux"; then
#
# Linux "Standard" install
#
install_method="$install_method : FHS"
datadir=${datadir="$datarootdir/nagios"}
if test $need_web = yes; then
webdir=${webdir="$datadir/html"}
else
webdir="N/A"
fi
sysconfdir=${sysconfdir="/etc"}
pkgsysconfdir=${pkgsysconfdir="$sysconfdir/nagios"}
if test $need_etc_subdir = yes; then
objsysconfdir=${objsysconfdir="$pkgsysconfdir/objects"}
else
objsysconfdir="N/A"
fi
privatesysconfdir=${privatesysconfdir="$pkgsysconfdir/private"}
if test $need_log_subdir = yes; then
logdir=${logdir="$localstatedir/log/$INIT_PROG"}
else
logdir=${logdir="$localstatedir/log"}
fi
piddir=${piddir="$localstatedir/run/${INIT_PROG}"}
if test "$need_pipe" = yes; then
pipedir=${pipedir="$localstatedir/run/${INIT_PROG}"}
else
pipedir="N/A"
fi
if test "$need_pls_dir" = yes; then
pkglocalstatedir=${pkglocalstatedir="$localstatedir/lib/$INIT_PROG"}
else
pkglocalstatedir="N/A"
fi
if test "$need_spl" = yes; then
spooldir=${spooldir="$localstatedir/spool/$INIT_PROG"}
else
spooldir="N/A"
fi
if test $need_brk = yes; then
brokersdir=${brokersdir="$libexecdir/brokers"}
else
brokersdir="N/A"
fi
if test $need_plg = yes; then
pluginsdir=${pluginsdir="$libexecdir/plugins"}
else
pluginsdir="N/A"
fi
if test $need_cgi = yes; then
cgibindir=${cgibindir="$libexecdir/cgi-bin"}
else
cgibindir="N/A"
fi
elif test $opsys = "unix"; then
#
# "Standard" Unix install
#
install_method="$install_method : Unix Standard"
if test $dist_type = osx; then
install_method="$install_method : OS X Standard"
fi
datadir=${datadir="$datarootdir/nagios"}
if test $need_web = yes; then
webdir=${webdir="$datadir/html"}
else
webdir="N/A"
fi
if test $dist_type = osx; then
sysconfdir=${sysconfdir="/private/etc"}
else
sysconfdir=${sysconfdir="/etc"}
fi
pkgsysconfdir=${pkgsysconfdir="$sysconfdir/nagios"}
if test $need_etc_subdir = yes; then
objsysconfdir=${objsysconfdir="$pkgsysconfdir/objects"}
else
objsysconfdir="N/A"
fi
privatesysconfdir=${privatesysconfdir="$pkgsysconfdir/private"}
if test "$need_pls_dir" = yes; then
pkglocalstatedir=${pkglocalstatedir="$localstatedir/lib/$INIT_PROG"}
else
pkglocalstatedir="N/A"
fi
if test "$need_loc" = yes; then
localedir=${localedir="/usr/local/share/locale//LC_MESSAGES/nagios-plugins.mo"}
fi
if test "$need_spl" = yes; then
spooldir=${spooldir="$localstatedir/spool/$INIT_PROG"}
else
spooldir="N/A"
fi
if test $need_brk = yes; then
brokersdir=${brokersdir="$libexecdir/brokers"}
else
brokersdir="N/A"
fi
if test $need_plg = yes; then
pluginsdir=${pluginsdir="$libexecdir/plugins"}
else
pluginsdir="N/A"
fi
if test $need_cgi = yes; then
cgibindir=${cgibindir="$libexecdir/cgi-bin"}
else
cgibindir="N/A"
fi
AS_CASE([$dist_type],
[*hp-ux*],
piddir=${piddir="$pkgsysconfdir"}
pipedir=${pipedir="$pkglocalstatedir"}
logdir=${logdir="$pkglocalstatedir/log"},
[*],
piddir=${piddir="$localstatedir/run/${INIT_PROG}"}
if test "$need_pipe" = yes; then
pipedir=${pipedir="$localstatedir/run/${INIT_PROG}"}
else
pipedir="N/A"
fi
if test $need_log_subdir = yes; then
logdir=${logdir="$localstatedir/log/$INIT_PROG"}
else
logdir=${logdir="$localstatedir/log"}
fi
)
elif test $opsys = "bsd"; then
#
# "Standard" BSD install
#
install_method="$install_method : BSD"
if test $dist_type = freebsd -o $dist_type = openbsd; then
prefix=${prefix="/usr/local"}
exec_prefix=${exec_prefix="/usr/local"}
if test $dist_type = freebsd; then
install_method="$install_method : FreeBSD"
else
install_method="$install_method : OpenBSD"
fi
elif test $dist_type = netbsd; then
prefix=${prefix="/usr/pkg"}
exec_prefix=${exec_prefix="/usr/pkg"}
install_method="$install_method : NetBSD"
fi
datadir=${datadir="$datarootdir/nagios"}
if test $need_web = yes -o $need_cgi = yes; then
if test $dist_type = freebsd; then
webdir=${webdir="$prefix/www/nagios"}
elif test $dist_type = netbsd; then
webdir=${webdir="$prefix/share/nagios"}
elif test $dist_type = openbsd; then
webdir=${webdir="/var/www/nagios"}
fi
else
webdir="N/A"
fi
if test $dist_type = freebsd; then
sysconfdir=${sysconfdir="/usr/local/etc"}
else
sysconfdir=${sysconfdir="/etc"}
fi
pkgsysconfdir=${pkgsysconfdir="$sysconfdir/nagios"}
if test $need_etc_subdir = yes; then
objsysconfdir=${objsysconfdir="$pkgsysconfdir/objects"}
else
objsysconfdir="N/A"
fi
privatesysconfdir=${privatesysconfdir="$pkgsysconfdir/private"}
if test "$need_pls_dir" = yes; then
pkglocalstatedir=${pkglocalstatedir="$localstatedir/lib/$INIT_PROG"}
else
pkglocalstatedir="N/A"
fi
if test "$need_loc" = yes; then
localedir=${localedir="/usr/local/share/locale//LC_MESSAGES/nagios-plugins.mo"}
fi
if test "$need_spl" = yes; then
spooldir=${spooldir="$localstatedir/spool/$INIT_PROG"}
else
spooldir="N/A"
fi
if test $need_brk = yes; then
brokersdir=${brokersdir="$libexecdir/brokers"}
else
brokersdir="N/A"
fi
if test $need_plg = yes; then
pluginsdir=${pluginsdir="$libexecdir/plugins"}
else
pluginsdir="N/A"
fi
if test $need_cgi = yes; then
if test $dist_type = freebsd; then
cgibindir=${cgibindir="$webdir/cgi-bin"}
elif test $dist_type = netbsd; then
cgibindir=${pluginsdir="$libexecdir/cgi-bin"}
elif test $dist_type = openbsd; then
cgibindir=${pluginsdir="/var/www/cgi-bin/nagios"}
fi
else
cgibindir="N/A"
fi
piddir=${piddir="$localstatedir/run/${INIT_PROG}"}
if test "$need_pipe" = yes; then
pipedir=${pipedir="$localstatedir/run/${INIT_PROG}"}
else
pipedir="N/A"
fi
if test $need_log_subdir = yes; then
logdir=${logdir="$localstatedir/log/$INIT_PROG"}
else
logdir=${logdir="$localstatedir/log"}
fi
else
#
# Unknown install
#
install_method="unknown"
webdir=unknown
pkgsysconfdir=unknown
objsysconfdir=unknown
privatesysconfdir=unknown
logdir=unknown
piddir=unknown
pipedir=unknown
pkglocalstatedir=unknown
spooldir=unknown
brokersdir=unknown
pluginsdir=unknown
cgibindir=unknown
fi
eval prefix=$prefix
eval exec_prefix=$exec_prefix
eval bindir=$bindir
eval datarootdir=$datarootdir
eval datadir=$datadir
eval libexecdir=$libexecdir
eval brokersdir=$brokersdir
eval pluginsdir=$pluginsdir
eval cgibindir=$cgibindir
eval localstatedir=$localstatedir
eval pkglocalstatedir=$pkglocalstatedir
eval webdir=$webdir
eval localedir=$localedir
eval sysconfdir=$sysconfdir
eval pkgsysconfdir=$pkgsysconfdir
eval piddir=$piddir
# We test systemd first because in case
# someone tries to install Nagios on a
# system with a newer version, that doesn't
# have the defined versions ..we can just
# (hopefully) fall back to SysV
# And if that doesn't work, well...
AS_CASE([$init_type],
[systemd],
if test -d "/lib/systemd/system"; then
initdir=${initdir="/lib/systemd/system"}
elif test -d "/usr/lib/systemd/system"; then
initdir=${initdir="/usr/lib/systemd/system"}
elif test -d "/usr/local/lib/systemd/system"; then
initdir=${initdir="/usr/local/lib/systemd/system"}
elif test -d "/run/systemd/system"; then
initdir=${initdir="/run/systemd/system"}
elif test -d "/etc/systemd/system"; then
initdir=${initdir="/etc/systemd/system"}
elif test -d "/etc/systemd/user"; then
initdir=${initdir="/etc/systemd/user"}
elif test -d "/run/systemd/user"; then
initdir=${initdir="/run/systemd/user"}
elif test -d "/usr/lib/systemd/user"; then
initdir=${initdir="/usr/lib/systemd/user"}
elif test -d "/usr/local/lib/systemd/user"; then
initdir=${initdir="/usr/local/lib/systemd/user"}
elif test -d "/usr/share/systemd/user"; then
initdir=${initdir="/usr/share/systemd/user"}
elif test -d "/usr/local/share/systemd/user"; then
initdir=${initdir="/usr/local/share/systemd/user"}
elif test -d "$HOME/.config/systemd/user"; then
initdir=${initdir="$HOME/.config/systemd/user"}
elif test -d "$HOME/.local/share/systemd/user"; then
initdir=${initdir="$HOME/.local/share/systemd/user"}
elif test -d "$XDG_CONFIG_HOME/systemd/user/"; then
initdir=${initdir="$XDG_CONFIG_HOME/systemd/user/"}
elif test -d "$XDG_RUNTIME_DIR/systemd/user/"; then
initdir=${initdir="$XDG_RUNTIME_DIR/systemd/user/"}
elif test -d "$XDG_DATA_HOME/systemd/user/"; then
initdir=${initdir="$XDG_DATA_HOME/systemd/user/"}
else
init_type="sysv"
fi
initname=${initname="$INIT_PROG.service"},
)
#
# Init scripts/files
#
AS_CASE([$init_type],
[sysv],
if test $dist_type = "hp-ux"; then
initdir=${initdir="/sbin/init.d"}
else
initdir=${initdir="/etc/init.d"}
fi
initname=${initname="$INIT_PROG"}
initconfdir=${initconfdir="/etc/conf.d"}
initconf=${initconf="$initconfdir/$INIT_PROG"},
[bsd],
if test $dist_type = "aix"; then
initdir=${initdir="/sbin/rc.d/init.d"}
initname=${initname="$INIT_PROG"}
else
initdir=${initdir="/etc/rc.d"}
initname=${initname="rc.$INIT_PROG"}
fi,
[newbsd],
initdir=${initdir="/usr/local/etc/rc.d"}
initname=${initname="$INIT_PROG"},
[gentoo],
initdir=${initdir="/etc/init.d"}
initname=${initname="$INIT_PROG"}
initconfdir=${initconfdir="/etc/init.d"}
initconf=${initconf="$initconfdir/$INIT_PROG"},
[openrc],
initdir=${initdir="/etc/init.d"}
initname=${initname="$INIT_PROG"}
initconfdir=${initconfdir="/etc/conf.d"}
initconf=${initconf="$initconfdir/$INIT_PROG"},
[smf*],
if test $init_type = smf10; then
initdir=${initdir="/var/svc/manifest/network/nagios"}
else
initdir=${initdir="/lib/svc/manifest/network/nagios"}
fi
initname=${initname="$INIT_PROG.xml"}
initconfdir=unknown
initconf=unknown,
[upstart],
initdir=${initdir="/etc/init"}
initname=${initname="$INIT_PROG.conf"}
initconfdir=${initconfdir="/etc/default"}
initconf=${initconf="$initconfdir/$INIT_PROG"},
[launchd],
initdir=${initdir="/Library/LaunchDaemons"}
initname=${initname="org.nagios.$INIT_PROG.plist"},
# initconfdir=${initconfdir="/private/etc"}
# initconf=${initconf="$initconfdir/$INIT_PROG"},
[systemd],
init_type=systemd,
[*],
initdir=unknown
initname=unknown)
# Now see if they supplied any overwriting values
initdiroverridden=no
AC_ARG_WITH(initdir,
AC_HELP_STRING([--with-initdir=],
[overrides path for initdir]),
initdir=$withval
initdiroverridden=yes,
initdir=$initdir
)
#
# Inetd (per connection) scripts/files
#
AS_CASE([$inetd_type],
[inetd*],
inetddir=${inetddir="/etc"}
inetdname=${inetdname="inetd.conf"},
[xinetd],
inetddir=${inetddir="/etc/xinetd.d"}
inetdname=${inetdname="$INIT_PROG"},
[systemd],
if test $dist_type = "debian"; then
inetddir=${inetddir="/lib/systemd/system"}
else
inetddir=${inetddir="/usr/lib/systemd/system"}
fi
netdname=${inetdname="$INIT_PROG.socket"},
[smf*],
if test $init_type = smf10; then
inetddir=${inetddir="/var/svc/manifest/network/nagios"}
else
inetddir=${inetddir="/lib/svc/manifest/network/nagios"}
fi
inetdname=${inetdname="$INIT_PROG.xml"},
# [upstart],
# inetddir=${inetddir="/etc/init.d"}
# inetdname=${inetdname="$INIT_PROG"},
[launchd],
inetddir=${inetddir="/Library/LaunchDaemons"}
inetdname=${inetdname="org.nagios.$INIT_PROG.plist"},
[*],
inetddir=${inetddir="unknown"}
inetdname=${inetdname="unknown"})
AC_MSG_RESULT($install_method)
])
nagios-4.4.6/autoconf-macros/ax_nagios_get_ssl 0000664 0000000 0000000 00000022033 13652113235 0021521 0 ustar 00root root 0000000 0000000 # ===========================================================================
# SYNOPSIS
#
# AX_NAGIOS_GET_SSL
#
# DESCRIPTION
#
# This macro finds the openssl binary, the header files directory and
# the library files directory. It will also search for the gnutls
# compatibility library/headers and the nss compatibility library/headers.
#
# LICENSE
#
# Copyright (c) 2016 Nagios Core Development Team
#
# 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, see .
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
# ===========================================================================
AU_ALIAS([AC_NAGIOS_GET_SSL], [AX_NAGIOS_GET_SSL])
AC_DEFUN([AX_NAGIOS_GET_SSL],
[
# -------------------------------
# SSL library and include paths
# -------------------------------
SSL_TYPE=openssl
try_pkg_config=1
ssl_dir=
ssl_inc_dir=
ssl_lib_dir=
SSL_INC_DIR=
SSL_INC_PREFIX=
SSL_HDR=
SSL_LIB_DIR=
AC_SUBST(HAVE_SSL)
AC_SUBST(SSL_TYPE)
AC_SUBST(SSL_INC_DIR)
AC_SUBST(SSL_HDR)
AC_SUBST(SSL_INC_PREFIX)
AC_SUBST(SSL_LIB_DIR)
# gnutls/openssl.h
# nss_compat_ossl/nss_compat_ossl.h
dnl # Which type - openssl, gnutls-openssl, nss
dnl AC_ARG_WITH([ssl-type],
dnl dnl AS_HELP_STRING([--with-ssl-type=TYPE],[replace TYPE with gnutls or nss to use one of these instead of openssl]),
dnl AS_HELP_STRING([--with-ssl-type=TYPE],[replace TYPE with gnutls to use that instead of openssl]),
dnl [SSL_TYPE=$withval])
AC_ARG_WITH([ssl],
AS_HELP_STRING([--with-ssl=DIR],[sets location of the SSL installation]),
[ssl_dir=$withval])
AC_ARG_WITH([ssl-inc],
AS_HELP_STRING([--with-ssl-inc=DIR],
[sets location of the SSL include files]),
[ssl_inc_dir=$withval])
AC_ARG_WITH([ssl-lib],
AS_HELP_STRING([--with-ssl-lib=DIR],[sets location of the SSL libraries]),
[ssl_lib_dir=$withval])
if test x$ssl_inc_dir != x -o x$ssl_lib_dir != x; then
try_pkg_config=0
fi
AC_ARG_WITH([kerberos-inc],
AS_HELP_STRING([--with-kerberos-inc=DIR],
[sets location of the Kerberos include files]),
[kerberos_inc_dir=$withval])
if test x$SSL_TYPE = xyes; then
SSL_TYPE=openssl
fi
dflt_hdrs="$ssl_inc_dir $ssl_dir $ssl_inc_dir/include $ssl_dir/include \
/usr/local/opt/{BBB} /usr/include/{BBB} /usr/local/include/{BBB} \
/usr/local/{AAA} /usr/local/{BBB} /usr/lib/{AAA} /usr/lib/{BBB} \
/usr/{AAA} /usr/pkg /usr/local /usr /usr/freeware/lib/{BBB} \
/usr/sfw /usr/sfw/include /opt/{BBB}"
dflt_libs="$ssl_lib_dir {ssldir} {ssldir}/lib {ssldir}/lib64 /usr/lib64 \
/usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/i386-linux-gnu \
/usr/local/lib /usr/lib/{AAA} /usr/{AAA}/lib /usr/{BBB}/lib \
/usr/pkg/lib /usr/freeware/lib/{BBB} /usr/sfw/lib /opt/freeware/lib \
/opt/{BBB}/lib/hpux64 /opt/{BBB}/lib/pa20_64 /opt/{BBB}/lib/hpux32 \
/opt/{BBB}/lib /opt/{BBB}";
AS_CASE([$SSL_TYPE],
[no], [SSL_TYPE=NONE],
[yes|openssl],
[ssl_hdr_dirs=`echo "$dflt_hdrs" | sed -e 's/{AAA}/ssl/g' | sed -e 's/{BBB}/openssl/g'`
ssl_lib_dirs=`echo "$dflt_libs" | sed -e 's/{AAA}/ssl/g' | sed -e 's/{BBB}/openssl/g'`
SSL_INC_PREFIX=openssl
SSL_HDR=ssl.h
ssl_lib=libssl],
[gnutls],
[ssl_hdr_dirs=`echo "$dflt_hdrs" | sed -e 's/{AAA}/gnutls/g' | sed -e 's/{BBB}/gnutls/g'`
ssl_lib_dirs=`echo "$dflt_libs" | sed -e 's/{AAA}/gnutls/g' | sed -e 's/{BBB}/gnutls/g'`
SSL_INC_PREFIX=gnutls
SSL_TYPE=gnutls_compat
SSL_HDR=compat.h
ssl_lib=libgnutls],
[nss],
[ssl_hdr_dirs=`echo "$dflt_hdrs" | sed -e 's/{AAA}/nss_compat_ossl/g' | sed -e 's/{BBB}/nss_compat_ossl/g'`
ssl_lib_dirs=`echo "$dflt_libs" | sed -e 's/{AAA}/nss_compat_ossl/g' | sed -e 's/{BBB}/nss_compat_ossl/g'`
SSL_HDR=nss_compat_ossl.h
ssl_lib=libnss_compat],
[*], echo >&6; AC_MSG_ERROR(['--with-ssl-type=$SSL_TYPE' is invalid])
)
# Check for SSL support
if test x$SSL_TYPE != xNONE; then
found_ssl=no
# RedHat 8.0 and 9.0 include openssl compiled with kerberos,
# so we must include header file
# Must come before openssl checks for Redhat EL 3
AC_MSG_CHECKING(for Kerberos include files)
found_kerberos=no
for dir in $kerberos_inc_dir /usr/kerberos/include /usr/include/krb5 \
/usr/include; do
kerbdir="$dir"
if test -f "$dir/krb5.h"; then
found_kerberos=yes
CFLAGS="$CFLAGS -I$kerbdir"
AC_DEFINE_UNQUOTED(HAVE_KRB5_H,[1],[Have the krb5.h header file])
break
fi
done
if test x_$found_kerberos != x_yes; then
AC_MSG_WARN(could not find include files)
else
AC_MSG_RESULT(found Kerberos include files in $kerbdir)
fi
# First, try using pkg_config
AC_CHECK_TOOL([PKG_CONFIG], [pkg-config])
if test x"$PKG_CONFIG" != x -a $try_pkg_config -ne 0 ; then
cflags=`$PKG_CONFIG $SSL_TYPE --cflags-only-I 2>/dev/null`
if test $? -eq 0; then
CFLAGS="$CFLAGS $cflags"
LDFLAGS="$LDFLAGS `$PKG_CONFIG $SSL_TYPE --libs-only-L 2>/dev/null`"
LIBS="$LIBS `$PKG_CONFIG $SSL_TYPE --libs-only-l 2>/dev/null`"
found_ssl=yes
AC_DEFINE_UNQUOTED(HAVE_SSL,[1],[Have SSL support])
fi
fi
if test x_$found_ssl != x_yes; then
# Find the SSL Headers
AC_MSG_CHECKING(for SSL headers)
for dir in $ssl_hdr_dirs; do
if test "$dir" = "/include"; then
continue
fi
ssldir="$dir"
if test -f "$dir/include/$SSL_INC_PREFIX/$SSL_HDR"; then
found_ssl=yes
CFLAGS="$CFLAGS -I$dir/include/$SSL_INC_PREFIX -I$ssldir/include"
SSL_INC_DIR="$dir/include/$SSL_INC_PREFIX"
break
fi
if test -f "$dir/include/$SSL_HDR"; then
found_ssl=yes
if test "$SSL_HDR" != compat.h ; then
SSL_INC_PREFIX=""
fi
CFLAGS="$CFLAGS -I$dir/include"
SSL_INC_DIR="$dir/include"
break
fi
if test -f "$dir/$SSL_HDR"; then
found_ssl=yes
SSL_INC_PREFIX=""
CFLAGS="$CFLAGS -I$dir"
SSL_INC_DIR="$dir"
break
fi
if test -f "$dir/$SSL_INC_PREFIX/$SSL_HDR"; then
found_ssl=yes
CFLAGS="$CFLAGS -I$dir/$SSL_INC_PREFIX"
SSL_INC_DIR="$dir/$SSL_INC_PREFIX"
ssldir="$dir/.."
break
fi
done
if test x_$found_ssl != x_yes; then
AC_MSG_ERROR(Cannot find ssl headers)
else
AC_MSG_RESULT(found in $ssldir)
# Now try and find SSL libraries
AC_MSG_CHECKING(for SSL libraries)
found_ssl=no
ssl_lib_dirs=`echo "$ssl_lib_dirs" | sed -e "s|{ssldir}|$ssldir|g"`
if test "`uname -s`" = "Darwin" ; then
soext="dylib"
elif test "`uname -s`" = "HP-UX" ; then
if test x$arch = "xia64"; then
soext="so"
else
soext="sl"
fi
elif test "`uname -s`" = "AIX" ; then
soext="a"
else
soext="so"
fi
for dir in $ssl_lib_dirs; do
if test -f "$dir/$ssl_lib.$soext"; then
found_ssl=yes
SSL_LIB_DIR="$dir"
break
fi
done
if test x_$found_ssl != x_yes; then
AC_MSG_ERROR(Cannot find ssl libraries)
else
AC_MSG_RESULT(found in $SSL_LIB_DIR)
LDFLAGS="$LDFLAGS -L$SSL_LIB_DIR";
LIBS="$LIBS -l`echo $ssl_lib | sed -e 's/^lib//'` -lcrypto";
AC_DEFINE_UNQUOTED(HAVE_SSL,[1],[Have SSL support])
fi
fi
fi
if test x$found_ssl = xyes ; then
if test -n "$SSL_INC_PREFIX" ; then
SSL_INC_PREFIX="${SSL_INC_PREFIX}/"
fi
# try to compile and link to see if SSL is set up properly
AC_MSG_CHECKING([whether compiling and linking against SSL works])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <${SSL_INC_PREFIX}${SSL_HDR}>], [SSL_new(NULL)])],
[
AC_MSG_RESULT([yes])
$1
], [
AC_MSG_ERROR([no])
$2
])
fi
if test x$found_ssl = xyes -a x$need_dh = xyes; then
# Find the openssl program
if test x$need_dh = xyes; then
AC_PATH_PROG(sslbin,openssl,value-if-not-found,$ssl_dir/sbin$PATH_SEPARATOR$ssl_dir/bin$PATH_SEPARATOR$PATH)
AC_DEFINE(USE_SSL_DH)
# Generate DH parameters
if test -f "$sslbin"; then
echo ""
echo "*** Generating DH Parameters for SSL/TLS ***"
# awk to strip off meta data at bottom of dhparam output
$sslbin dhparam -C 2048 | awk '/^-----/ {exit} {print}' > include/dh.h
fi
fi
fi
fi
])
nagios-4.4.6/base/ 0000775 0000000 0000000 00000000000 13652113235 0013720 5 ustar 00root root 0000000 0000000 nagios-4.4.6/base/.gitignore 0000664 0000000 0000000 00000000026 13652113235 0015706 0 ustar 00root root 0000000 0000000 *.o
nagios
nagiostats
nagios-4.4.6/base/Makefile.in 0000664 0000000 0000000 00000012176 13652113235 0015774 0 ustar 00root root 0000000 0000000 ############################
# Makefile for Nagios
#
############################
# Source code directories
SRC_COMMON=../common
SRC_INCLUDE=../include
SRC_XDATA=../xdata
SRC_LIB=../lib
CC=@CC@
CFLAGS=-Wall -I.. @CFLAGS@ @DEFS@ -DNSCORE
# Compiler flags for use with gprof
#CFLAGS=-pg -I.. -DHAVE_CONFIG_H -DNSCORE
# Compiler flags for use with Valgrind
#CFLAGS=-O0 -I.. -g -DHAVE_CONFIG_H -DNSCORE
# Compiler flags for optimization (overrides default)
#CFLAGS=-O3 -Wall -I.. -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=@cgibindir@
HTMLDIR=@webdir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
STRIP=@STRIP@
CGIURL=@cgiurl@
HTMURL=@htmurl@
MATHLIBS=-lm
SOCKETLIBS=@SOCKETLIBS@
BROKERLIBS=@BROKERLIBS@
BROKER_LDFLAGS=@BROKER_LDFLAGS@
CP=@CP@
# Extra base code
BASEEXTRALIBS=@BASEEXTRALIBS@
# Generated automatically from configure script
BROKER_O=@BROKER_O@
BROKER_H=@BROKER_H@
# Object data
ODATALIBS=objects-base.o xobjects-base.o
ODATAHDRS=
ODATADEPS=$(ODATALIBS)
# Retention data
RDATALIBS=retention-base.o xretention-base.o
RDATAHDRS=
RDATADEPS=$(RDATALIBS)
# Comment data
CDATALIBS=comments-base.o xcomments-base.o
CDATAHDRS=
CDATADEPS=$(CDATALIBS)
# Status data
SDATALIBS=statusdata-base.o xstatusdata-base.o
SDATAHDRS=
SDATADEPS=$(SDATALIBS)
# Performance data
PDATALIBS=perfdata-base.o xperfdata-base.o
PDATAHDRS=
PDATADEPS=$(PDATALIBS)
# Downtime data
DDATALIBS=downtime-base.o
DDATAHDRS=
DDATADEPS=$(DDATALIBS)
OBJS=$(BROKER_O) $(SRC_COMMON)/shared.o @NERD_O@ query-handler.o workers.o checks.o config.o commands.o events.o flapping.o logging.o macros-base.o netutils.o notifications.o sehandlers.o utils.o $(RDATALIBS) $(CDATALIBS) $(ODATALIBS) $(SDATALIBS) $(PDATALIBS) $(DDATALIBS) $(BASEEXTRALIBS)
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
objects-base.o: $(SRC_COMMON)/objects.c $(SRC_INCLUDE)/objects.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/objects.c
xobjects-base.o: $(SRC_XDATA)/xodtemplate.c $(SRC_XDATA)/xodtemplate.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xodtemplate.c
statusdata-base.o: $(SRC_COMMON)/statusdata.c $(SRC_INCLUDE)/statusdata.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/statusdata.c
xstatusdata-base.o: $(SRC_XDATA)/xsddefault.c $(SRC_XDATA)/xsddefault.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xsddefault.c
comments-base.o: $(SRC_COMMON)/comments.c $(SRC_INCLUDE)/comments.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/comments.c
xcomments-base.o: $(SRC_XDATA)/xcddefault.c $(SRC_XDATA)/xcddefault.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xcddefault.c
downtime-base.o: $(SRC_COMMON)/downtime.c $(SRC_INCLUDE)/downtime.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/downtime.c
perfdata-base.o: perfdata.c $(SRC_INCLUDE)/perfdata.h
$(CC) $(CFLAGS) -c -o $@ perfdata.c
xperfdata-base.o: $(SRC_XDATA)/xpddefault.c $(SRC_XDATA)/xpddefault.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xpddefault.c
retention-base.o: sretention.c $(SRC_INCLUDE)/sretention.h
$(CC) $(CFLAGS) -c -o $@ sretention.c
xretention-base.o: $(SRC_XDATA)/xrddefault.c $(SRC_XDATA)/xrddefault.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xrddefault.c
$(SRC_COMMON)/shared.o: $(SRC_COMMON)/shared.c
$(CC) $(CFLAGS) -c -o $@ $<
workers.o: workers.c wpres-phash.h
$(CC) $(CFLAGS) -c -o $@ $<
wpres-phash.h: wpres.gperf
gperf -S 1 -t -H wpres_key_phash -N wpres_get_key $< > $@
########## NAGIOS ##########
libnagios:
$(MAKE) -C $(SRC_LIB)
nagios.o: nagios.c $(SRC_INCLUDE)/nagios.h $(SRC_INCLUDE)/locations.h
$(CC) $(CFLAGS) -c -o $@ nagios.c
nagios: nagios.o $(OBJS) $(OBJDEPS) libnagios
$(CC) $(CFLAGS) -o $@ $< $(OBJS) $(BROKER_LDFLAGS) $(LDFLAGS) $(MATHLIBS) $(SOCKETLIBS) $(BROKERLIBS) $(LIBS) $(SRC_LIB)/libnagios.a
nagiostats: nagiostats.c $(SRC_INCLUDE)/locations.h libnagios
$(CC) $(CFLAGS) -o $@ nagiostats.c $(LDFLAGS) $(MATHLIBS) $(LIBS) $(SRC_LIB)/libnagios.a
$(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
rm -f wpres-phash.h
install:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(BINDIR)
$(INSTALL) -s -m 774 $(INSTALL_OPTS) @nagios_name@ $(DESTDIR)$(BINDIR)
$(INSTALL) -s -m 774 $(INSTALL_OPTS) @nagiostats_name@ $(DESTDIR)$(BINDIR)
install-unstripped:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(BINDIR)
$(INSTALL) -m 774 $(INSTALL_OPTS) nagios $(DESTDIR)$(BINDIR)
$(INSTALL) -m 774 $(INSTALL_OPTS) nagiostats $(DESTDIR)$(BINDIR)
.PHONY: libnagios
nagios-4.4.6/base/broker.c 0000664 0000000 0000000 00000067410 13652113235 0015360 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* BROKER.C - Event broker routines for 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/nagios.h"
#include "../include/broker.h"
#include "../include/nebcallbacks.h"
#include "../include/nebstructs.h"
#include "../include/nebmods.h"
#ifdef USE_EVENT_BROKER
/******************************************************************/
/************************* EVENT FUNCTIONS ************************/
/******************************************************************/
/* sends program data (starts, restarts, stops, etc.) to broker */
void broker_program_state(int type, int flags, int attr, struct timeval *timestamp) {
nebstruct_process_data ds;
if(!(event_broker_options & BROKER_PROGRAM_STATE))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_PROCESS_DATA, (void *)&ds);
return;
}
/* send timed event data to broker */
void broker_timed_event(int type, int flags, int attr, timed_event *event, struct timeval *timestamp) {
nebstruct_timed_event_data ds;
if(!(event_broker_options & BROKER_TIMED_EVENTS))
return;
if(event == NULL)
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.event_type = event->event_type;
ds.recurring = event->recurring;
ds.run_time = event->run_time;
ds.event_data = event->event_data;
ds.event_ptr = (void *)event;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_TIMED_EVENT_DATA, (void *)&ds);
return;
}
/* send log data to broker */
void broker_log_data(int type, int flags, int attr, char *data, unsigned long data_type, time_t entry_time, struct timeval *timestamp) {
nebstruct_log_data ds;
if(!(event_broker_options & BROKER_LOGGED_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.entry_time = entry_time;
ds.data_type = data_type;
ds.data = data;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_LOG_DATA, (void *)&ds);
return;
}
/* send system command data to broker */
void broker_system_command(int type, int flags, int attr, struct timeval start_time, struct timeval end_time, double exectime, int timeout, int early_timeout, int retcode, char *cmd, char *output, struct timeval *timestamp) {
nebstruct_system_command_data ds;
if(!(event_broker_options & BROKER_SYSTEM_COMMANDS))
return;
if(cmd == NULL)
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.start_time = start_time;
ds.end_time = end_time;
ds.timeout = timeout;
ds.command_line = cmd;
ds.early_timeout = early_timeout;
ds.execution_time = exectime;
ds.return_code = retcode;
ds.output = output;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_SYSTEM_COMMAND_DATA, (void *)&ds);
return;
}
/* send event handler data to broker */
int broker_event_handler(int type, int flags, int attr, int eventhandler_type, void *data, int state, int state_type, struct timeval start_time, struct timeval end_time, double exectime, int timeout, int early_timeout, int retcode, char *cmd, char *cmdline, char *output, struct timeval *timestamp) {
service *temp_service = NULL;
host *temp_host = NULL;
char *command_buf = NULL;
char *command_name = NULL;
char *command_args = NULL;
nebstruct_event_handler_data ds;
int return_code = OK;
if(!(event_broker_options & BROKER_EVENT_HANDLERS))
return return_code;
if(data == NULL)
return ERROR;
/* get command name/args */
if(cmd != NULL) {
command_buf = (char *)strdup(cmd);
command_name = strtok(command_buf, "!");
command_args = strtok(NULL, "\x0");
}
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.eventhandler_type = eventhandler_type;
if(eventhandler_type == SERVICE_EVENTHANDLER || eventhandler_type == GLOBAL_SERVICE_EVENTHANDLER) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
}
ds.object_ptr = data;
ds.state = state;
ds.state_type = state_type;
ds.start_time = start_time;
ds.end_time = end_time;
ds.timeout = timeout;
ds.command_name = command_name;
ds.command_args = command_args;
ds.command_line = cmdline;
ds.early_timeout = early_timeout;
ds.execution_time = exectime;
ds.return_code = retcode;
ds.output = output;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_EVENT_HANDLER_DATA, (void *)&ds);
/* free memory */
my_free(command_buf);
return return_code;
}
/* send host check data to broker */
int broker_host_check(int type, int flags, int attr, host *hst, int check_type, int state, int state_type, struct timeval start_time, struct timeval end_time, char *cmd, double latency, double exectime, int timeout, int early_timeout, int retcode, char *cmdline, char *output, char *long_output, char *perfdata, struct timeval *timestamp, check_result *cr) {
char *command_buf = NULL;
char *command_name = NULL;
char *command_args = NULL;
nebstruct_host_check_data ds;
int return_code = OK;
if(!(event_broker_options & BROKER_HOST_CHECKS))
return OK;
if(hst == NULL)
return ERROR;
/* get command name/args */
if(cmd != NULL) {
command_buf = (char *)strdup(cmd);
command_name = strtok(command_buf, "!");
command_args = strtok(NULL, "\x0");
}
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.host_name = hst->name;
ds.object_ptr = (void *)hst;
ds.check_type = check_type;
ds.current_attempt = hst->current_attempt;
ds.max_attempts = hst->max_attempts;
ds.state = state;
ds.state_type = state_type;
ds.timeout = timeout;
ds.command_name = command_name;
ds.command_args = command_args;
ds.command_line = cmdline;
ds.start_time = start_time;
ds.end_time = end_time;
ds.early_timeout = early_timeout;
ds.execution_time = exectime;
ds.latency = latency;
ds.return_code = retcode;
ds.output = output;
ds.long_output = long_output;
ds.perf_data = perfdata;
ds.check_result_ptr = cr;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_HOST_CHECK_DATA, (void *)&ds);
/* free data */
my_free(command_buf);
return return_code;
}
/* send service check data to broker */
int broker_service_check(int type, int flags, int attr, service *svc, int check_type, struct timeval start_time, struct timeval end_time, char *cmd, double latency, double exectime, int timeout, int early_timeout, int retcode, char *cmdline, struct timeval *timestamp, check_result *cr) {
char *command_buf = NULL;
char *command_name = NULL;
char *command_args = NULL;
nebstruct_service_check_data ds;
int return_code = OK;
if(!(event_broker_options & BROKER_SERVICE_CHECKS))
return OK;
if(svc == NULL)
return ERROR;
/* get command name/args */
if(cmd != NULL) {
command_buf = (char *)strdup(cmd);
command_name = strtok(command_buf, "!");
command_args = strtok(NULL, "\x0");
}
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.host_name = svc->host_name;
ds.service_description = svc->description;
ds.object_ptr = (void *)svc;
ds.check_type = check_type;
ds.current_attempt = svc->current_attempt;
ds.max_attempts = svc->max_attempts;
ds.state = svc->current_state;
ds.state_type = svc->state_type;
ds.timeout = timeout;
ds.command_name = command_name;
ds.command_args = command_args;
ds.command_line = cmdline;
ds.start_time = start_time;
ds.end_time = end_time;
ds.early_timeout = early_timeout;
ds.execution_time = exectime;
ds.latency = latency;
ds.return_code = retcode;
ds.output = svc->plugin_output;
ds.long_output = svc->long_plugin_output;
ds.perf_data = svc->perf_data;
ds.check_result_ptr = cr;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_SERVICE_CHECK_DATA, (void *)&ds);
/* free data */
my_free(command_buf);
return return_code;
}
/* send comment data to broker */
void broker_comment_data(int type, int flags, int attr, int comment_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, struct timeval *timestamp) {
nebstruct_comment_data ds;
if(!(event_broker_options & BROKER_COMMENT_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.comment_type = comment_type;
ds.entry_type = entry_type;
ds.host_name = host_name;
ds.service_description = svc_description;
ds.object_ptr = NULL; /* not implemented yet */
ds.entry_time = entry_time;
ds.author_name = author_name;
ds.comment_data = comment_data;
ds.persistent = persistent;
ds.source = source;
ds.expires = expires;
ds.expire_time = expire_time;
ds.comment_id = comment_id;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_COMMENT_DATA, (void *)&ds);
return;
}
/* send downtime data to broker */
void broker_downtime_data(int type, int flags, int attr, int downtime_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long downtime_id, struct timeval *timestamp) {
nebstruct_downtime_data ds;
if(!(event_broker_options & BROKER_DOWNTIME_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.downtime_type = downtime_type;
ds.host_name = host_name;
ds.service_description = svc_description;
ds.object_ptr = NULL; /* not implemented yet */
ds.entry_time = entry_time;
ds.author_name = author_name;
ds.comment_data = comment_data;
ds.start_time = start_time;
ds.end_time = end_time;
ds.fixed = fixed;
ds.duration = duration;
ds.triggered_by = triggered_by;
ds.downtime_id = downtime_id;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_DOWNTIME_DATA, (void *)&ds);
return;
}
/* send flapping data to broker */
void broker_flapping_data(int type, int flags, int attr, int flapping_type, void *data, double percent_change, double high_threshold, double low_threshold, struct timeval *timestamp) {
nebstruct_flapping_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
if(!(event_broker_options & BROKER_FLAPPING_DATA))
return;
if(data == NULL)
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.flapping_type = flapping_type;
if(flapping_type == SERVICE_FLAPPING) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.comment_id = temp_service->flapping_comment_id;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.comment_id = temp_host->flapping_comment_id;
}
ds.object_ptr = data;
ds.percent_change = percent_change;
ds.high_threshold = high_threshold;
ds.low_threshold = low_threshold;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_FLAPPING_DATA, (void *)&ds);
return;
}
/* sends program status updates to broker */
void broker_program_status(int type, int flags, int attr, struct timeval *timestamp) {
nebstruct_program_status_data ds;
if(!(event_broker_options & BROKER_STATUS_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.program_start = program_start;
ds.pid = nagios_pid;
ds.daemon_mode = daemon_mode;
ds.last_log_rotation = last_log_rotation;
ds.notifications_enabled = enable_notifications;
ds.active_service_checks_enabled = execute_service_checks;
ds.passive_service_checks_enabled = accept_passive_service_checks;
ds.active_host_checks_enabled = execute_host_checks;
ds.passive_host_checks_enabled = accept_passive_host_checks;
ds.event_handlers_enabled = enable_event_handlers;
ds.flap_detection_enabled = enable_flap_detection;
ds.process_performance_data = process_performance_data;
ds.obsess_over_hosts = obsess_over_hosts;
ds.obsess_over_services = obsess_over_services;
ds.modified_host_attributes = modified_host_process_attributes;
ds.modified_service_attributes = modified_service_process_attributes;
ds.global_host_event_handler = global_host_event_handler;
ds.global_service_event_handler = global_service_event_handler;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_PROGRAM_STATUS_DATA, (void *)&ds);
return;
}
/* sends host status updates to broker */
void broker_host_status(int type, int flags, int attr, host *hst, struct timeval *timestamp) {
nebstruct_host_status_data ds;
if(!(event_broker_options & BROKER_STATUS_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.object_ptr = (void *)hst;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_HOST_STATUS_DATA, (void *)&ds);
return;
}
/* sends service status updates to broker */
void broker_service_status(int type, int flags, int attr, service *svc, struct timeval *timestamp) {
nebstruct_service_status_data ds;
if(!(event_broker_options & BROKER_STATUS_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.object_ptr = (void *)svc;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_SERVICE_STATUS_DATA, (void *)&ds);
return;
}
/* sends contact status updates to broker */
void broker_contact_status(int type, int flags, int attr, contact *cntct, struct timeval *timestamp) {
nebstruct_contact_status_data ds;
if(!(event_broker_options & BROKER_STATUS_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.object_ptr = (void *)cntct;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_CONTACT_STATUS_DATA, (void *)&ds);
return;
}
/* send notification data to broker */
int broker_notification_data(int type, int flags, int attr, int notification_type, int reason_type, struct timeval start_time, struct timeval end_time, void *data, char *ack_author, char *ack_data, int escalated, int contacts_notified, struct timeval *timestamp) {
nebstruct_notification_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
int return_code = OK;
if(!(event_broker_options & BROKER_NOTIFICATIONS))
return return_code;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.notification_type = notification_type;
ds.start_time = start_time;
ds.end_time = end_time;
ds.reason_type = reason_type;
if(notification_type == SERVICE_NOTIFICATION) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.state = temp_service->current_state;
ds.output = temp_service->plugin_output;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.state = temp_host->current_state;
ds.output = temp_host->plugin_output;
}
ds.object_ptr = data;
ds.ack_author = ack_author;
ds.ack_data = ack_data;
ds.escalated = escalated;
ds.contacts_notified = contacts_notified;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_NOTIFICATION_DATA, (void *)&ds);
return return_code;
}
/* send contact notification data to broker */
int broker_contact_notification_data(int type, int flags, int attr, int notification_type, int reason_type, struct timeval start_time, struct timeval end_time, void *data, contact *cntct, char *ack_author, char *ack_data, int escalated, struct timeval *timestamp) {
nebstruct_contact_notification_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
int return_code = OK;
if(!(event_broker_options & BROKER_NOTIFICATIONS))
return return_code;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.notification_type = notification_type;
ds.start_time = start_time;
ds.end_time = end_time;
ds.reason_type = reason_type;
ds.contact_name = cntct->name;
if(notification_type == SERVICE_NOTIFICATION) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.state = temp_service->current_state;
ds.output = temp_service->plugin_output;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.state = temp_host->current_state;
ds.output = temp_host->plugin_output;
}
ds.object_ptr = data;
ds.contact_ptr = (void *)cntct;
ds.ack_author = ack_author;
ds.ack_data = ack_data;
ds.escalated = escalated;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_CONTACT_NOTIFICATION_DATA, (void *)&ds);
return return_code;
}
/* send contact notification data to broker */
int broker_contact_notification_method_data(int type, int flags, int attr, int notification_type, int reason_type, struct timeval start_time, struct timeval end_time, void *data, contact *cntct, char *cmd, char *ack_author, char *ack_data, int escalated, struct timeval *timestamp) {
nebstruct_contact_notification_method_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
char *command_buf = NULL;
char *command_name = NULL;
char *command_args = NULL;
int return_code = OK;
if(!(event_broker_options & BROKER_NOTIFICATIONS))
return return_code;
/* get command name/args */
if(cmd != NULL) {
command_buf = (char *)strdup(cmd);
command_name = strtok(command_buf, "!");
command_args = strtok(NULL, "\x0");
}
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.notification_type = notification_type;
ds.start_time = start_time;
ds.end_time = end_time;
ds.reason_type = reason_type;
ds.contact_name = cntct->name;
ds.command_name = command_name;
ds.command_args = command_args;
if(notification_type == SERVICE_NOTIFICATION) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.state = temp_service->current_state;
ds.output = temp_service->plugin_output;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.state = temp_host->current_state;
ds.output = temp_host->plugin_output;
}
ds.object_ptr = data;
ds.contact_ptr = (void *)cntct;
ds.ack_author = ack_author;
ds.ack_data = ack_data;
ds.escalated = escalated;
/* make callbacks */
return_code = neb_make_callbacks(NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA, (void *)&ds);
/* free memory */
my_free(command_buf);
return return_code;
}
/* sends adaptive programs updates to broker */
void broker_adaptive_program_data(int type, int flags, int attr, int command_type, unsigned long modhattr, unsigned long modhattrs, unsigned long modsattr, unsigned long modsattrs, struct timeval *timestamp) {
nebstruct_adaptive_program_data ds;
if(!(event_broker_options & BROKER_ADAPTIVE_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.command_type = command_type;
ds.modified_host_attribute = modhattr;
ds.modified_host_attributes = modhattrs;
ds.modified_service_attribute = modsattr;
ds.modified_service_attributes = modsattrs;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_ADAPTIVE_PROGRAM_DATA, (void *)&ds);
return;
}
/* sends adaptive host updates to broker */
void broker_adaptive_host_data(int type, int flags, int attr, host *hst, int command_type, unsigned long modattr, unsigned long modattrs, struct timeval *timestamp) {
nebstruct_adaptive_host_data ds;
if(!(event_broker_options & BROKER_ADAPTIVE_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.command_type = command_type;
ds.modified_attribute = modattr;
ds.modified_attributes = modattrs;
ds.object_ptr = (void *)hst;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_ADAPTIVE_HOST_DATA, (void *)&ds);
return;
}
/* sends adaptive service updates to broker */
void broker_adaptive_service_data(int type, int flags, int attr, service *svc, int command_type, unsigned long modattr, unsigned long modattrs, struct timeval *timestamp) {
nebstruct_adaptive_service_data ds;
if(!(event_broker_options & BROKER_ADAPTIVE_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.command_type = command_type;
ds.modified_attribute = modattr;
ds.modified_attributes = modattrs;
ds.object_ptr = (void *)svc;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_ADAPTIVE_SERVICE_DATA, (void *)&ds);
return;
}
/* sends adaptive contact updates to broker */
void broker_adaptive_contact_data(int type, int flags, int attr, contact *cntct, int command_type, unsigned long modattr, unsigned long modattrs, unsigned long modhattr, unsigned long modhattrs, unsigned long modsattr, unsigned long modsattrs, struct timeval *timestamp) {
nebstruct_adaptive_contact_data ds;
if(!(event_broker_options & BROKER_ADAPTIVE_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.command_type = command_type;
ds.modified_attribute = modattr;
ds.modified_attributes = modattrs;
ds.modified_host_attribute = modhattr;
ds.modified_host_attributes = modhattrs;
ds.modified_service_attribute = modsattr;
ds.modified_service_attributes = modsattrs;
ds.object_ptr = (void *)cntct;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_ADAPTIVE_CONTACT_DATA, (void *)&ds);
return;
}
/* sends external commands to broker */
void broker_external_command(int type, int flags, int attr, int command_type, time_t entry_time, char *command_string, char *command_args, struct timeval *timestamp) {
nebstruct_external_command_data ds;
if(!(event_broker_options & BROKER_EXTERNALCOMMAND_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.command_type = command_type;
ds.entry_time = entry_time;
ds.command_string = command_string;
ds.command_args = command_args;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_EXTERNAL_COMMAND_DATA, (void *)&ds);
return;
}
/* brokers aggregated status dumps */
void broker_aggregated_status_data(int type, int flags, int attr, struct timeval *timestamp) {
nebstruct_aggregated_status_data ds;
if(!(event_broker_options & BROKER_STATUS_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_AGGREGATED_STATUS_DATA, (void *)&ds);
return;
}
/* brokers retention data */
void broker_retention_data(int type, int flags, int attr, struct timeval *timestamp) {
nebstruct_retention_data ds;
if(!(event_broker_options & BROKER_RETENTION_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_RETENTION_DATA, (void *)&ds);
return;
}
/* send acknowledgement data to broker */
void broker_acknowledgement_data(int type, int flags, int attr, int acknowledgement_type, void *data, char *ack_author, char *ack_data, int subtype, int notify_contacts, int persistent_comment, struct timeval *timestamp) {
nebstruct_acknowledgement_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
if(!(event_broker_options & BROKER_ACKNOWLEDGEMENT_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.acknowledgement_type = acknowledgement_type;
if(acknowledgement_type == SERVICE_ACKNOWLEDGEMENT) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.state = temp_service->current_state;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.state = temp_host->current_state;
}
ds.object_ptr = data;
ds.author_name = ack_author;
ds.comment_data = ack_data;
ds.is_sticky = (subtype == ACKNOWLEDGEMENT_STICKY) ? TRUE : FALSE;
ds.notify_contacts = notify_contacts;
ds.persistent_comment = persistent_comment;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_ACKNOWLEDGEMENT_DATA, (void *)&ds);
return;
}
/* send state change data to broker */
void broker_statechange_data(int type, int flags, int attr, int statechange_type, void *data, int state, int state_type, int current_attempt, int max_attempts, struct timeval *timestamp) {
nebstruct_statechange_data ds;
host *temp_host = NULL;
service *temp_service = NULL;
if(!(event_broker_options & BROKER_STATECHANGE_DATA))
return;
/* fill struct with relevant data */
ds.type = type;
ds.flags = flags;
ds.attr = attr;
ds.timestamp = get_broker_timestamp(timestamp);
ds.statechange_type = statechange_type;
if(statechange_type == SERVICE_STATECHANGE) {
temp_service = (service *)data;
ds.host_name = temp_service->host_name;
ds.service_description = temp_service->description;
ds.output = temp_service->plugin_output;
ds.longoutput = temp_service->long_plugin_output;
}
else {
temp_host = (host *)data;
ds.host_name = temp_host->name;
ds.service_description = NULL;
ds.output = temp_host->plugin_output;
ds.longoutput = temp_host->long_plugin_output;
}
ds.object_ptr = data;
ds.state = state;
ds.state_type = state_type;
ds.current_attempt = current_attempt;
ds.max_attempts = max_attempts;
/* make callbacks */
neb_make_callbacks(NEBCALLBACK_STATE_CHANGE_DATA, (void *)&ds);
return;
}
/******************************************************************/
/************************ UTILITY FUNCTIONS ***********************/
/******************************************************************/
/* gets timestamp for use by broker */
struct timeval get_broker_timestamp(struct timeval *timestamp) {
struct timeval tv;
if(timestamp == NULL)
gettimeofday(&tv, NULL);
else
tv = *timestamp;
return tv;
}
#endif
nagios-4.4.6/base/checks.c 0000664 0000000 0000000 00000351744 13652113235 0015342 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* CHECKS.C - Service and host check functions for 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/comments.h"
#include "../include/common.h"
#include "../include/statusdata.h"
#include "../include/downtime.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/broker.h"
#include "../include/perfdata.h"
#include "../include/workers.h"
/*#define DEBUG_CHECKS*/
/*#define DEBUG_HOST_CHECKS 1*/
#define replace_semicolons(output, ptr) do { ptr = output; while ((ptr = strchr(ptr, ';')) != NULL) { * ptr = ':'; } } while (0)
#ifdef USE_EVENT_BROKER
#include "../include/neberrors.h"
#endif
/******************************************************************/
/********************** CHECK REAPER FUNCTIONS ********************/
/******************************************************************/
/* reaps host and service check results */
int reap_check_results(void)
{
int reaped_checks = 0;
log_debug_info(DEBUGL_FUNCTIONS, 0, "reap_check_results() start\n");
/* process files in the check result queue */
reaped_checks = process_check_result_queue(check_result_path);
log_debug_info(DEBUGL_FUNCTIONS, 0, "reap_check_results() reaped %d checks end\n", reaped_checks);
return OK;
}
/******************************************************************/
/****************** SERVICE MONITORING FUNCTIONS ******************/
/******************************************************************/
/* executes a scheduled service check */
int run_scheduled_service_check(service *svc, int check_options, double latency)
{
int result = OK;
time_t current_time = 0L;
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
int time_is_valid = TRUE;
if (svc == NULL) {
return ERROR;
}
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_scheduled_service_check() start\n");
log_debug_info(DEBUGL_CHECKS, 0, "Attempting to run scheduled check of service '%s' on host '%s': check options=%d, latency=%lf\n", svc->description, svc->host_name, check_options, latency);
/*
* reset the next_check_event so we know it's
* no longer in the scheduling queue
*/
svc->next_check_event = NULL;
/* attempt to run the check */
result = run_async_service_check(svc, check_options, latency, TRUE, TRUE, &time_is_valid, &preferred_time);
/* an error occurred, so reschedule the check */
if (result == ERROR) {
log_debug_info(DEBUGL_CHECKS, 1, "Unable to run scheduled service check at this time\n");
/* only attempt to (re)schedule checks that should get checked... */
if (svc->should_be_scheduled == TRUE) {
/* get current time */
time(¤t_time);
/* determine next time we should check the service if needed */
/* if service has no check interval, schedule it again for 5 minutes from now */
if (current_time >= preferred_time) {
preferred_time = current_time + ((svc->check_interval <= 0) ? 300 : (svc->check_interval * interval_length));
}
/* make sure we rescheduled the next service check at a valid time */
get_next_valid_time(preferred_time, &next_valid_time, svc->check_period_ptr);
/*
* If we really can't reschedule the service properly, we
* just push the check to preferred_time plus some reasonable
* random value and try again then.
*/
if (time_is_valid == FALSE && check_time_against_period(next_valid_time, svc->check_period_ptr) == ERROR) {
svc->next_check = preferred_time + ranged_urand(0, check_window(svc));
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of service '%s' on host '%s' could not be rescheduled properly. Scheduling check for %s...\n", svc->description, svc->host_name, ctime(&preferred_time));
log_debug_info(DEBUGL_CHECKS, 1, "Unable to find any valid times to reschedule the next service check!\n");
}
/* this service could be rescheduled... */
else {
svc->next_check = next_valid_time;
if (next_valid_time > preferred_time) {
/* Next valid time is further in the future because of
* timeperiod constraints. Add a random amount so we
* don't get all checks subject to that timeperiod
* constraint scheduled at the same time
*/
svc->next_check = reschedule_within_timeperiod(next_valid_time, svc->check_period_ptr, check_window(svc));
}
svc->should_be_scheduled = TRUE;
log_debug_info(DEBUGL_CHECKS, 1, "Rescheduled next service check for %s", ctime(&next_valid_time));
}
}
/*
* reschedule the next service check - unless we couldn't
* find a valid next check time, but keep original options
*/
if (svc->should_be_scheduled == TRUE) {
schedule_service_check(svc, svc->next_check, check_options);
}
/* update the status log */
update_service_status(svc, FALSE);
return ERROR;
}
return OK;
}
/* forks a child process to run a service check, but does not wait for the service check result */
int run_async_service_check(service *svc, int check_options, double latency, int scheduled_check, int reschedule_check, int *time_is_valid, time_t *preferred_time)
{
nagios_macros mac;
char *raw_command = NULL;
char *processed_command = NULL;
struct timeval start_time, end_time;
host *temp_host = NULL;
double old_latency = 0.0;
check_result *cr;
int runchk_result = OK;
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
#ifdef USE_EVENT_BROKER
int neb_result = OK;
#endif
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_async_service_check()\n");
/* make sure we have something */
if (svc == NULL) {
return ERROR;
}
/* is the service check viable at this time? */
if (check_service_check_viability(svc, check_options, time_is_valid, preferred_time) == ERROR) {
return ERROR;
}
/* find the host associated with this service */
if ((temp_host = svc->host_ptr) == NULL) {
return ERROR;
}
/******** GOOD TO GO FOR A REAL SERVICE CHECK AT THIS POINT ********/
#ifdef USE_EVENT_BROKER
/* initialize start/end times */
start_time.tv_sec = 0L;
start_time.tv_usec = 0L;
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
/* send data to event broker */
neb_result = broker_service_check(NEBTYPE_SERVICECHECK_ASYNC_PRECHECK, NEBFLAG_NONE, NEBATTR_NONE, svc, CHECK_TYPE_ACTIVE, start_time, end_time, svc->check_command, svc->latency, 0.0, 0, FALSE, 0, NULL, NULL, NULL);
/* neb module wants to cancel the service check - the check will be rescheduled for a later time by the scheduling logic */
if (neb_result == NEBERROR_CALLBACKCANCEL) {
log_debug_info(DEBUGL_CHECKS, 0, "Check of service '%s' on host '%s' (id=%u) was cancelled by a module\n", svc->description, svc->host_name, svc->id);
if (preferred_time) {
*preferred_time += (svc->check_interval * interval_length);
}
return ERROR;
}
/* neb module wants to override (or cancel) the service check - perhaps it will check the service itself */
/* NOTE: if a module does this, it has to do a lot of the stuff found below to make sure things don't get whacked out of shape! */
/* NOTE: if would be easier for modules to override checks when the NEBTYPE_SERVICECHECK_INITIATE event is called (later) */
if (neb_result == NEBERROR_CALLBACKOVERRIDE) {
log_debug_info(DEBUGL_CHECKS, 0, "Check of service '%s' on host '%s' (id=%u) was overridden by a module\n", svc->description, svc->host_name, svc->id);
return OK;
}
#endif
log_debug_info(DEBUGL_CHECKS, 0, "Checking service '%s' on host '%s'...\n", svc->description, svc->host_name);
/* clear check options - we don't want old check options retained */
/* only clear check options for scheduled checks - ondemand checks shouldn't affected retained check options */
if (scheduled_check == TRUE) {
svc->check_options = CHECK_OPTION_NONE;
}
/* update latency for macros, event broker, save old value for later */
old_latency = svc->latency;
svc->latency = latency;
/* grab the host and service macro variables */
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, svc->check_command_ptr, svc->check_command, &raw_command, macro_options);
if (raw_command == NULL) {
clear_volatile_macros_r(&mac);
log_debug_info(DEBUGL_CHECKS, 0, "Raw check command for service '%s' on host '%s' was NULL - aborting.\n", svc->description, svc->host_name);
if (preferred_time) {
*preferred_time += (svc->check_interval * interval_length);
}
svc->latency = old_latency;
return ERROR;
}
/* process any macros contained in the argument */
process_macros_r(&mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if (processed_command == NULL) {
clear_volatile_macros_r(&mac);
log_debug_info(DEBUGL_CHECKS, 0, "Processed check command for service '%s' on host '%s' was NULL - aborting.\n", svc->description, svc->host_name);
if (preferred_time) {
*preferred_time += (svc->check_interval * interval_length);
}
svc->latency = old_latency;
return ERROR;
}
/* get the command start time */
gettimeofday(&start_time, NULL);
cr = calloc(1, sizeof(*cr));
if (!cr) {
clear_volatile_macros_r(&mac);
svc->latency = old_latency;
my_free(processed_command);
return ERROR;
}
init_check_result(cr);
/* save check info */
cr->object_check_type = SERVICE_CHECK;
cr->check_type = CHECK_TYPE_ACTIVE;
cr->check_options = check_options;
cr->scheduled_check = scheduled_check;
cr->reschedule_check = reschedule_check;
cr->latency = latency;
cr->start_time = start_time;
cr->finish_time = start_time;
cr->early_timeout = FALSE;
cr->exited_ok = TRUE;
cr->return_code = STATE_OK;
cr->output = NULL;
cr->host_name = (char *)strdup(svc->host_name);
cr->service_description = (char *)strdup(svc->description);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
neb_result = broker_service_check(NEBTYPE_SERVICECHECK_INITIATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CHECK_TYPE_ACTIVE, start_time, end_time, svc->check_command, svc->latency, 0.0, service_check_timeout, FALSE, 0, processed_command, NULL, cr);
/* neb module wants to override the service check - perhaps it will check the service itself */
if (neb_result == NEBERROR_CALLBACKOVERRIDE) {
clear_volatile_macros_r(&mac);
svc->latency = old_latency;
free_check_result(cr);
my_free(cr);
my_free(processed_command);
return OK;
}
#endif
/* reset latency (permanent value will be set later) */
svc->latency = old_latency;
/* paw off the check to a worker to run */
runchk_result = wproc_run_check(cr, processed_command, &mac);
if (runchk_result == ERROR) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Unable to run check for service '%s' on host '%s'\n", svc->description, svc->host_name);
}
else {
/* do the book-keeping */
currently_running_service_checks++;
svc->is_executing = TRUE;
update_check_stats((scheduled_check == TRUE) ? ACTIVE_SCHEDULED_SERVICE_CHECK_STATS : ACTIVE_ONDEMAND_SERVICE_CHECK_STATS, start_time.tv_sec);
}
/* free memory */
my_free(processed_command);
clear_volatile_macros_r(&mac);
return runchk_result;
}
/* Start of inline helper functions for handle async host/service check result functions
BH 03 Dec 2017
The giant monolithic async helper functions were becoming difficult to maintain
So I broke them out into smaller manageable chunks where a side-by-side comparison
of the two functions is a bit more reasonable. This would have been a lot easier with
dynamic type casting, or even some macro magic - but at least this way it isn't as
messy as it would have been with macros.
When introducing new inline helper functions, the goal is so that both of the functions
can sit on the same screen at the same time - for obvious reasons (I hope).
Try to keep them concise */
/* Bit of logic for determining an adequate return code */
int get_service_check_return_code(service *svc, check_result *cr)
{
int rc;
log_debug_info(DEBUGL_FUNCTIONS, 0, "get_service_check_return_code()\n");
if (NULL == svc || NULL == cr) {
return STATE_UNKNOWN;
}
/* return now if it's a passive check */
if (cr->check_type != CHECK_TYPE_ACTIVE) {
return cr->return_code;
}
/* grab the return code */
rc = cr->return_code;
/* did the check result have an early timeout? */
if (cr->early_timeout == TRUE) {
my_free(svc->plugin_output);
my_free(svc->long_plugin_output);
my_free(svc->perf_data);
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of service '%s' on host '%s' timed out after %.3fs!\n", svc->description, svc->host_name, svc->execution_time);
asprintf(&svc->plugin_output, "(Service check timed out after %.2lf seconds)", svc->execution_time);
rc = service_check_timeout_state;
}
/* if there was some error running the command, just skip it (this shouldn't be happening) */
else if (cr->exited_ok == FALSE) {
my_free(svc->plugin_output);
my_free(svc->long_plugin_output);
my_free(svc->perf_data);
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of service '%s' on host '%s' did not exit properly!\n", svc->description, svc->host_name);
svc->plugin_output = (char *)strdup("(Service check did not exit properly)");
rc = STATE_CRITICAL;
}
/* 126 is a return code for non-executable */
else if (cr->return_code == 126) {
my_free(svc->plugin_output);
my_free(svc->long_plugin_output);
my_free(svc->perf_data);
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Return code of 126 for service '%s' on host '%s' may indicate a non-executable plugin.\n",
svc->description, svc->host_name);
svc->plugin_output = strdup("(Return code of 126 is out of bounds. Check if plugin is executable)");
rc = STATE_CRITICAL;
}
/* 127 is a return code for non-existent */
else if (cr->return_code == 127) {
my_free(svc->plugin_output);
my_free(svc->long_plugin_output);
my_free(svc->perf_data);
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Return code of 127 for service '%s' on host '%s' may indicate this plugin doesn't exist.\n",
svc->description, svc->host_name);
svc->plugin_output = strdup("(Return code of 127 is out of bounds. Check if plugin exists)");
rc = STATE_CRITICAL;
}
/* make sure the return code is within bounds */
else if (cr->return_code < 0 || cr->return_code > 3) {
logit(NSLOG_RUNTIME_WARNING, TRUE,
"Warning: Return code of %d for check of service '%s' on host '%s' was out of bounds.\n",
cr->return_code,
svc->description,
svc->host_name);
asprintf(&svc->plugin_output, "(Return code of %d for service '%s' on host '%s' was out of bounds)",
cr->return_code,
svc->description,
svc->host_name);
rc = STATE_CRITICAL;
}
return rc;
}
/* Bit of logic for determining an adequate return code */
int get_host_check_return_code(host *hst, check_result *cr)
{
int rc;
log_debug_info(DEBUGL_FUNCTIONS, 0, "get_host_check_return_code()\n");
if (hst == NULL || cr == NULL) {
return HOST_UNREACHABLE;
}
/* return now if it's a passive check */
if (cr->check_type != CHECK_TYPE_ACTIVE) {
return cr->return_code;
}
/* get the unprocessed return code */
rc = cr->return_code;
/* did the check result have an early timeout? */
if (cr->early_timeout) {
my_free(hst->plugin_output);
my_free(hst->long_plugin_output);
my_free(hst->perf_data);
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of host '%s' timed out after %.2lf seconds\n", hst->name, hst->execution_time);
asprintf(&hst->plugin_output, "(Host check timed out after %.2lf seconds)", hst->execution_time);
rc = HOST_UNREACHABLE;
}
/* if there was some error running the command, just skip it (this shouldn't be happening) */
else if (cr->exited_ok == FALSE) {
my_free(hst->plugin_output);
my_free(hst->long_plugin_output);
my_free(hst->perf_data);
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of host '%s' did not exit properly!\n", hst->name);
hst->plugin_output = (char *)strdup("(Host check did not exit properly)");
rc = HOST_UNREACHABLE;
}
/* 126 is a return code for non-executable */
else if (cr->return_code == 126) {
my_free(hst->plugin_output);
my_free(hst->long_plugin_output);
my_free(hst->perf_data);
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Return code of 126 for host '%s' may indicate a non-executable plugin.\n",
hst->name);
hst->plugin_output = strdup("(Return code of 126 is out of bounds. Check if plugin is executable)");
rc = HOST_UNREACHABLE;
}
/* 127 is a return code for non-existent */
else if (cr->return_code == 127) {
my_free(hst->plugin_output);
my_free(hst->long_plugin_output);
my_free(hst->perf_data);
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Return code of 127 for host '%s' may indicate this plugin doesn't exist.\n",
hst->name);
hst->plugin_output = strdup("(Return code of 127 is out of bounds. Check if plugin exists)");
rc = HOST_UNREACHABLE;
}
/* make sure the return code is within bounds */
else if (cr->return_code < 0 || cr->return_code > 3) {
my_free(hst->plugin_output);
my_free(hst->long_plugin_output);
my_free(hst->perf_data);
logit(NSLOG_RUNTIME_WARNING, TRUE,
"Warning: Return code of %d for check of host '%s' was out of bounds.\n",
cr->return_code,
hst->name);
asprintf(&hst->plugin_output, "(Return code of %d for host '%s' was out of bounds)",
cr->return_code,
hst->name);
rc = HOST_UNREACHABLE;
}
/* a NULL host check command means we should assume the host is UP */
if (hst->check_command == NULL) {
my_free(hst->plugin_output);
hst->plugin_output = (char *)strdup("(Host assumed to be UP)");
rc = HOST_UP;
}
/* if we're not doing aggressive host checking, let WARNING states indicate the host is up (fake the result to be HOST_UP) */
else if (use_aggressive_host_checking == FALSE && rc == STATE_WARNING) {
rc = HOST_UP;
}
/* any problem state indicates the host is not UP */
else if (rc != HOST_UP) {
rc = HOST_DOWN;
}
return rc;
}
/******************************************************************************
******* Calculate check result exec time
*****************************************************************************/
static inline double calculate_check_result_execution_time(check_result *cr)
{
double execution_time = 0.0;
if (cr != NULL) {
double start_s = cr->start_time.tv_sec;
double start_us = cr->start_time.tv_usec;
double finish_s = cr->finish_time.tv_sec;
double finish_us = cr->finish_time.tv_usec;
execution_time = ((finish_s - start_s) + ((finish_us - start_us) / 1000.0) / 1000.0);
if (execution_time < 0.0) {
execution_time = 0.0;
}
}
return execution_time;
}
/******************************************************************************
******* Last state ended
*****************************************************************************/
static inline void record_last_service_state_ended(service * svc)
{
switch(svc->last_state) {
case STATE_OK:
svc->last_time_ok = svc->last_check;
break;
case STATE_WARNING:
svc->last_time_warning = svc->last_check;
break;
case STATE_UNKNOWN:
svc->last_time_unknown = svc->last_check;
break;
case STATE_CRITICAL:
svc->last_time_critical = svc->last_check;
break;
default:
break;
}
}
/*****************************************************************************/
static inline void record_last_host_state_ended(host * hst)
{
switch(hst->last_state) {
case HOST_UP:
hst->last_time_up = hst->last_check;
break;
case HOST_DOWN:
hst->last_time_down = hst->last_check;
break;
case HOST_UNREACHABLE:
hst->last_time_unreachable = hst->last_check;
break;
default:
break;
}
}
/******************************************************************************
******* Logic chunks for when an object is passive
*****************************************************************************/
static inline int service_is_passive(service *svc, check_result *cr)
{
if (accept_passive_service_checks == FALSE) {
log_debug_info(DEBUGL_CHECKS, 0, "Discarding passive service check result because passive service checks are disabled globally.\n");
return FALSE;
}
if (svc->accept_passive_checks == FALSE) {
log_debug_info(DEBUGL_CHECKS, 0, "Discarding passive service check result because passive checks are disabled for this service.\n");
return FALSE;
}
svc->check_type = CHECK_TYPE_PASSIVE;
/* update check statistics for passive checks */
update_check_stats(PASSIVE_SERVICE_CHECK_STATS, cr->start_time.tv_sec);
/* log passive checks - we need to do this here, as some may bypass external commands by getting dropped in checkresults dir */
if (log_passive_checks == TRUE) {
logit(NSLOG_PASSIVE_CHECK, FALSE, "PASSIVE SERVICE CHECK: %s;%s;%d;%s\n",
svc->host_name,
svc->description,
svc->current_state,
svc->plugin_output);
}
return TRUE;
}
/*****************************************************************************/
static inline int host_is_passive(host *hst, check_result *cr)
{
if (accept_passive_host_checks == FALSE) {
log_debug_info(DEBUGL_CHECKS, 0, "Discarding passive host check result because passive host checks are disabled globally.\n");
return FALSE;
}
if (hst->accept_passive_checks == FALSE) {
log_debug_info(DEBUGL_CHECKS, 0, "Discarding passive host check result because passive checks are disabled for this host.\n");
return FALSE;
}
hst->check_type = CHECK_TYPE_PASSIVE;
/* update check stats for passive checks */
update_check_stats(PASSIVE_HOST_CHECK_STATS, cr->start_time.tv_sec);
/* log passive checks - we need to do this here as some may bypass external commands by getting dropped in checkresults dir */
/* todo - check if current_state is right - i don't think it is! */
if (log_passive_checks == TRUE) {
logit(NSLOG_PASSIVE_CHECK, FALSE, "PASSIVE HOST CHECK: %s;%d;%s\n",
hst->name,
hst->current_state,
hst->plugin_output);
}
return TRUE;
}
/******************************************************************************
******* Logic chunks for when an object is active
*****************************************************************************/
static inline void service_is_active(service *svc)
{
svc->check_type = CHECK_TYPE_ACTIVE;
/* decrement the number of service checks still out there... */
if (currently_running_service_checks > 0) {
currently_running_service_checks--;
}
svc->is_executing = FALSE;
}
/*****************************************************************************/
static inline void host_is_active(host *hst)
{
hst->check_type = CHECK_TYPE_ACTIVE;
/* decrement the number of host checks still out there... */
if (currently_running_host_checks > 0) {
currently_running_host_checks--;
}
hst->is_executing = FALSE;
}
/******************************************************************************
******* Generic debugging functions
*****************************************************************************/
static inline void debug_async_service(service *svc, check_result *cr)
{
log_debug_info(DEBUGL_CHECKS, 0, "** Handling %s async check result for service '%s' on host '%s' from '%s'... current state %d last_hard_state %d \n",
(cr->check_type == CHECK_TYPE_ACTIVE) ? "ACTIVE" : "PASSIVE",
svc->description,
svc->host_name,
check_result_source(cr),
svc->current_state,
svc->last_hard_state);
log_debug_info(DEBUGL_CHECKS, 1,
" * OPTIONS: %d, SCHEDULED: %d, RESCHEDULE: %d, EXITED OK: %d, RETURN CODE: %d, OUTPUT:\n%s\n",
cr->check_options,
cr->scheduled_check,
cr->reschedule_check,
cr->exited_ok,
cr->return_code,
(cr == NULL) ? "NULL" : cr->output);
}
/*****************************************************************************/
static inline void debug_async_host(host *hst, check_result *cr)
{
log_debug_info(DEBUGL_CHECKS, 0, "** Handling %s async check result for host '%s' from '%s'...\n",
(cr->check_type == CHECK_TYPE_ACTIVE) ? "ACTIVE" : "PASSIVE",
hst->name,
check_result_source(cr));
log_debug_info(DEBUGL_CHECKS, 1,
" * OPTIONS: %d, SCHEDULED: %d, RESCHEDULE: %d, EXITED OK: %d, RETURN CODE: %d, OUTPUT:\n%s\n",
cr->check_options,
cr->scheduled_check,
cr->reschedule_check,
cr->exited_ok,
cr->return_code,
(cr == NULL) ? "NULL" : cr->output);
}
/******************************************************************************
******* Logic chunks for checking object freshness
*****************************************************************************/
static inline void service_fresh_check(service *svc, check_result *cr, time_t current_time)
{
/* check freshness */
if (cr->check_options & CHECK_OPTION_FRESHNESS_CHECK) {
/* DISCARD INVALID FRESHNESS CHECK RESULTS */
/* If a services goes stale, Nagios will initiate a forced check in order to freshen it. There is a race condition whereby a passive check
could arrive between the 1) initiation of the forced check and 2) the time when the forced check result is processed here. This would
make the service fresh again, so we do a quick check to make sure the service is still stale before we accept the check result. */
if (is_service_result_fresh(svc, current_time, FALSE) == TRUE) {
log_debug_info(DEBUGL_CHECKS, 0, "Discarding service freshness check result because the service is currently fresh (race condition avoided).\n");
return;
}
/* clear the freshening flag (it would have been set if this service was determined to be stale) */
svc->is_being_freshened = FALSE;
}
}
/*****************************************************************************/
static inline void host_fresh_check(host *hst, check_result *cr, time_t current_time)
{
/* check freshness */
if (cr->check_options & CHECK_OPTION_FRESHNESS_CHECK) {
/* DISCARD INVALID FRESHNESS CHECK RESULTS */
/* If a host goes stale, Nagios will initiate a forced check in order to freshen it. There is a race condition whereby a passive check
could arrive between the 1) initiation of the forced check and 2) the time when the forced check result is processed here. This would
make the host fresh again, so we do a quick check to make sure the host is still stale before we accept the check result. */
if (is_host_result_fresh(hst, current_time, FALSE) == TRUE) {
log_debug_info(DEBUGL_CHECKS, 0, "Discarding host freshness check result because the host is currently fresh (race condition avoided).\n");
return;
}
/* clear the freshening flag (it would have been set if this host was determined to be stale) */
hst->is_being_freshened = FALSE;
}
}
/******************************************************************************
******* Logic chunks for setting some of the initial flags, etc.
*****************************************************************************/
static inline void service_initial_handling(service *svc, check_result *cr, char **old_plugin_output)
{
char * temp_ptr = NULL;
/* save old plugin output */
if (svc->plugin_output) {
* old_plugin_output = (char *)strdup(svc->plugin_output);
}
my_free(svc->plugin_output);
my_free(svc->long_plugin_output);
my_free(svc->perf_data);
/* parse check output to get: (1) short output, (2) long output, (3) perf data */
parse_check_output(cr->output, &svc->plugin_output, &svc->long_plugin_output, &svc->perf_data, TRUE, FALSE);
/* make sure the plugin output isn't null */
if (svc->plugin_output == NULL) {
svc->plugin_output = (char *)strdup("(No output returned from plugin)");
}
/* otherwise replace the semicolons with colons */
else {
replace_semicolons(svc->plugin_output, temp_ptr);
}
log_debug_info(DEBUGL_CHECKS, 2,
"Parsing check output...\n"
"Short Output: %s\n"
"Long Output: %s\n"
"Perf Data: %s\n",
svc->plugin_output,
(svc->long_plugin_output == NULL) ? "NULL" : svc->long_plugin_output,
(svc->perf_data == NULL) ? "NULL" : svc->perf_data);
svc->latency = cr->latency;
svc->execution_time = calculate_check_result_execution_time(cr);
svc->last_check = cr->start_time.tv_sec;
svc->should_be_scheduled = cr->reschedule_check;
svc->last_state = svc->current_state;
svc->current_state = get_service_check_return_code(svc, cr);
}
/*****************************************************************************/
static inline void host_initial_handling(host *hst, check_result *cr, char **old_plugin_output)
{
char * temp_ptr = NULL;
/* save old plugin output */
if (hst->plugin_output) {
* old_plugin_output = (char *)strdup(hst->plugin_output);
}
my_free(hst->plugin_output);
my_free(hst->long_plugin_output);
my_free(hst->perf_data);
/* parse check output to get: (1) short output, (2) long output, (3) perf data */
parse_check_output(cr->output, &hst->plugin_output, &hst->long_plugin_output, &hst->perf_data, TRUE, FALSE);
/* make sure the plugin output isn't null */
if (hst->plugin_output == NULL) {
hst->plugin_output = (char *)strdup("(No output returned from host check)");
}
/* otherwise replace the semicolons with colons */
else {
replace_semicolons(hst->plugin_output, temp_ptr);
}
log_debug_info(DEBUGL_CHECKS, 2,
"Parsing check output...\n"
"Short Output: %s\n"
"Long Output: %s\n"
"Perf Data: %s\n",
hst->plugin_output,
(hst->long_plugin_output == NULL) ? "NULL" : hst->long_plugin_output,
(hst->perf_data == NULL) ? "NULL" : hst->perf_data);
hst->latency = cr->latency;
hst->execution_time = calculate_check_result_execution_time(cr);
hst->last_check = cr->start_time.tv_sec;
hst->should_be_scheduled = cr->reschedule_check;
hst->last_state = hst->current_state;
hst->current_state = get_host_check_return_code(hst, cr);
}
/******************************************************************************
******* Logic for when an object has a notable change
******* Removes acknowledgement, advances event_id, etc.
*****************************************************************************/
static inline void service_state_or_hard_state_type_change(service * svc, int state_change, int hard_state_change, int * log_event, int * handle_event)
{
int state_or_type_change = FALSE;
/* update the event and problem ids */
if (state_change == TRUE) {
svc->last_state_change = svc->last_check;
/* always update the event id on a state change */
svc->last_event_id = svc->current_event_id;
svc->current_event_id = next_event_id;
next_event_id++;
/* update the problem id when transitioning to a problem state */
if (svc->last_state == STATE_OK) {
/* don't reset last problem id, or it will be zero the next time a problem is encountered */
svc->current_problem_id = next_problem_id;
next_problem_id++;
}
svc->state_type = SOFT_STATE;
state_or_type_change = TRUE;
}
if (hard_state_change == TRUE) {
svc->last_hard_state_change = svc->last_check;
svc->last_state_change = svc->last_check;
svc->last_hard_state = svc->current_state;
svc->state_type = HARD_STATE;
state_or_type_change = TRUE;
}
if (state_or_type_change) {
/* check if service should go into downtime from flexible downtime */
if (svc->pending_flex_downtime > 0) {
check_pending_flex_service_downtime(svc);
}
/* reset notification times and suppression option */
svc->last_notification = (time_t)0;
svc->next_notification = (time_t)0;
svc->no_more_notifications = FALSE;
if ((svc->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL && (state_change == TRUE || hard_state_change == FALSE))
|| (svc->acknowledgement_type == ACKNOWLEDGEMENT_STICKY && svc->current_state == STATE_OK)) {
/* remove any non-persistant comments associated with the ack */
svc->problem_has_been_acknowledged = FALSE;
svc->acknowledgement_type = ACKNOWLEDGEMENT_NONE;
delete_service_acknowledgement_comments(svc);
}
svc->should_be_scheduled = TRUE;
*log_event = TRUE;
*handle_event = TRUE;
}
}
/*****************************************************************************/
static inline void host_state_or_hard_state_type_change(host * hst, int state_change, int hard_state_change, int * log_event, int * handle_event, int * send_notification)
{
int state_or_type_change = FALSE;
/* check if we simulate a hard state change */
if (hst->check_type == CHECK_TYPE_PASSIVE && passive_host_checks_are_soft == FALSE) {
log_debug_info(DEBUGL_CHECKS, 2, "Check type passive and passive host checks aren't false\n");
if (state_change == TRUE) {
hst->current_attempt = 1;
hard_state_change = TRUE;
}
hst->state_type = HARD_STATE;
}
/* update event and problem ids */
if (state_change == TRUE) {
hst->last_state_change = hst->last_check;
/* always update the event id on a state change */
hst->last_event_id = hst->current_event_id;
hst->current_event_id = next_event_id;
next_event_id++;
/* update the problem id when transitioning to a problem state */
if (hst->last_state == HOST_UP) {
/* don't reset last problem id, or it will be zero the next time a problem is encountered */
hst->current_problem_id = next_problem_id;
next_problem_id++;
}
/* clear the problem id when transitioning from a problem state to an OK state */
else {
hst->last_problem_id = hst->current_problem_id;
hst->current_problem_id = 0L;
}
hst->state_type = SOFT_STATE;
state_or_type_change = TRUE;
}
if (hard_state_change == TRUE) {
hst->last_hard_state_change = hst->last_check;
hst->last_hard_state = hst->current_state;
hst->state_type = HARD_STATE;
state_or_type_change = TRUE;
/* this is in the host func, but not the service
because it can easily be missed if a passive check
comes in and passive_host_checks_are_soft == FALSE */
*send_notification = TRUE;
}
if (state_or_type_change) {
/* check if host should go into downtime from flexible downtime */
check_pending_flex_host_downtime(hst);
/* reset notification times and suppression option */
hst->last_notification = (time_t)0;
hst->next_notification = (time_t)0;
hst->no_more_notifications = FALSE;
if ((hst->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL && (state_change == TRUE || hard_state_change == FALSE))
|| (hst->acknowledgement_type == ACKNOWLEDGEMENT_STICKY && hst->current_state == STATE_OK)) {
/* remove any non-persistant comments associated with the ack */
hst->problem_has_been_acknowledged = FALSE;
hst->acknowledgement_type = ACKNOWLEDGEMENT_NONE;
delete_host_acknowledgement_comments(hst);
}
hst->should_be_scheduled = TRUE;
*log_event = TRUE;
*handle_event = TRUE;
}
}
/******************************************************************************
******* Logic for setting default state change times, etc.
*****************************************************************************/
static inline void initialize_last_service_state_change_times(service * svc, host * hst)
{
/* initialize the last host and service state change times if necessary */
if (svc->last_state_change == (time_t)0) {
svc->last_state_change = svc->last_check;
}
if (svc->last_hard_state_change == (time_t)0) {
svc->last_hard_state_change = svc->last_check;
}
if (hst->last_state_change == (time_t)0) {
hst->last_state_change = svc->last_check;
}
if (hst->last_hard_state_change == (time_t)0) {
hst->last_hard_state_change = svc->last_check;
}
}
/*****************************************************************************/
static inline void initialize_last_host_state_change_times(host * hst)
{
/* initialize last host state change times if necessary */
if (hst->last_state_change == (time_t)0) {
hst->last_state_change = hst->last_check;
}
if (hst->last_hard_state_change == (time_t)0) {
hst->last_hard_state_change = hst->last_check;
}
}
/******************************************************************************
******* Logic chunks propagating checks to host parents/children
*****************************************************************************/
static inline void host_propagate_checks_to_immediate_parents(host * hst, int parent_host_up, time_t current_time)
{
hostsmember *temp_hostsmember = NULL;
host *parent_host = NULL;
log_debug_info(DEBUGL_CHECKS, 1, "Propagating checks to parent host(s)...\n");
for(temp_hostsmember = hst->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
parent_host = temp_hostsmember->host_ptr;
if ((parent_host_up == TRUE && parent_host->current_state == HOST_UP)
|| ((parent_host_up == FALSE && parent_host->current_state != HOST_UP))) {
log_debug_info(DEBUGL_CHECKS, 1, "Check of parent host '%s' queued.\n", parent_host->name);
schedule_host_check(parent_host, current_time, CHECK_OPTION_DEPENDENCY_CHECK);
}
}
}
static inline void host_propagate_checks_to_immediate_children(host * hst, int children_none_up, int children_none_unreachable, time_t current_time)
{
hostsmember *temp_hostsmember = NULL;
host *child_host = NULL;
log_debug_info(DEBUGL_CHECKS, 1, "Propagating checks to child host(s)...\n");
for(temp_hostsmember = hst->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
child_host = temp_hostsmember->host_ptr;
if ( (children_none_up == TRUE && child_host->current_state != HOST_UP)
|| (children_none_unreachable == TRUE && child_host->current_state != HOST_UNREACHABLE)) {
log_debug_info(DEBUGL_CHECKS, 1, "Check of child host '%s' queued.\n", child_host->name);
schedule_host_check(child_host, current_time, CHECK_OPTION_DEPENDENCY_CHECK);
}
}
}
/******************************************************************************
******* Logic chunks propagating dependency checks
*****************************************************************************/
static inline void service_propagate_dependency_checks(service * svc, time_t current_time)
{
if (svc->current_attempt == (svc->max_attempts - 1)
&& execute_service_checks == TRUE
&& enable_predictive_service_dependency_checks == TRUE) {
servicedependency *temp_dependency = NULL;
service *master_service = NULL;
objectlist *list;
log_debug_info(DEBUGL_CHECKS, 1, "Propagating predictive dependency checks to services this one depends on...\n");
/* check services that THIS ONE depends on for notification AND execution */
/* we do this because we might be sending out a notification soon and we want the dependency logic to be accurate */
for(list = svc->exec_deps; list; list = list->next) {
temp_dependency = (servicedependency *)list->object_ptr;
if (temp_dependency->dependent_service_ptr == svc && temp_dependency->master_service_ptr != NULL) {
master_service = (service *)temp_dependency->master_service_ptr;
log_debug_info(DEBUGL_CHECKS, 2, "Predictive check of service '%s' on host '%s' queued.\n", master_service->description, master_service->host_name);
schedule_service_check(master_service, current_time, CHECK_OPTION_DEPENDENCY_CHECK);
}
}
for(list = svc->notify_deps; list; list = list->next) {
temp_dependency = (servicedependency *)list->object_ptr;
if (temp_dependency->dependent_service_ptr == svc && temp_dependency->master_service_ptr != NULL) {
master_service = (service *)temp_dependency->master_service_ptr;
log_debug_info(DEBUGL_CHECKS, 2, "Predictive check of service '%s' on host '%s' queued.\n", master_service->description, master_service->host_name);
schedule_service_check(master_service, current_time, CHECK_OPTION_DEPENDENCY_CHECK);
}
}
}
}
/*****************************************************************************/
static inline void host_propagate_dependency_checks(host * hst, time_t current_time)
{
/* we do to help ensure that the dependency checks are accurate before it comes time to notify */
if (hst->current_attempt == (hst->max_attempts - 1)
&& execute_host_checks == TRUE
&& enable_predictive_host_dependency_checks == TRUE) {
objectlist *list;
hostdependency *dep = NULL;
host *master_host = NULL;
log_debug_info(DEBUGL_CHECKS, 1, "Propagating predictive dependency checks to hosts this one depends on...\n");
for(list = hst->notify_deps; list; list = list->next) {
dep = (hostdependency *)list->object_ptr;
if (dep->dependent_host_ptr == hst && dep->master_host_ptr != NULL) {
master_host = (host *)dep->master_host_ptr;
log_debug_info(DEBUGL_CHECKS, 1, "Check of host '%s' queued.\n", master_host->name);
schedule_host_check(master_host, current_time, CHECK_OPTION_NONE);
}
}
for(list = hst->exec_deps; list; list = list->next) {
dep = (hostdependency *)list->object_ptr;
if (dep->dependent_host_ptr == hst && dep->master_host_ptr != NULL) {
master_host = (host *)dep->master_host_ptr;
log_debug_info(DEBUGL_CHECKS, 1, "Check of host '%s' queued.\n", master_host->name);
schedule_host_check(master_host, current_time, CHECK_OPTION_NONE);
}
}
}
}
/******************************************************************************
******* One stop shop for determining if check_result data is valid
*****************************************************************************/
static inline int is_valid_check_result_data(host * hst, check_result * cr)
{
if (hst == NULL) {
log_debug_info(DEBUGL_CHECKS, 2, "No host associated with service, bailing!\n");
return FALSE;
}
if (cr == NULL) {
log_debug_info(DEBUGL_CHECKS, 2, "No check result specified, bailing!\n");
return FALSE;
}
return TRUE;
}
/******************************************************************************
********** Fin. ************************************************************
*****************************************************************************/
/* handles asynchronous service check results */
int handle_async_service_check_result(service *svc, check_result *cr)
{
time_t current_time = 0L;
time_t next_check = 0L;
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
int state_change = FALSE;
int hard_state_change = FALSE;
int send_notification = FALSE;
int handle_event = FALSE;
int log_event = FALSE;
int check_host = FALSE;
int update_host_stats = FALSE;
char * old_plugin_output = NULL;
host * hst = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_async_service_check_result()\n");
if (svc == NULL) {
log_debug_info(DEBUGL_CHECKS, 2, "No service specified, bailing!\n");
return ERROR;
}
hst = svc->host_ptr;
if (is_valid_check_result_data(hst, cr) == FALSE) {
return ERROR;
}
int new_last_hard_state = svc->last_hard_state;
if (cr->check_type == CHECK_TYPE_PASSIVE) {
if (service_is_passive(svc, cr) == FALSE) {
return ERROR;
}
}
else {
service_is_active(svc);
}
time(¤t_time);
initialize_last_service_state_change_times(svc, hst);
debug_async_service(svc, cr);
service_fresh_check(svc, cr, current_time);
service_initial_handling(svc, cr, &old_plugin_output);
/* reschedule the next check at the regular interval - may be overridden */
next_check = (time_t)(svc->last_check + (svc->check_interval * interval_length));
/***********************************************/
/********** SCHEDULE SERVICE CHECK LOGIC **********/
/***********************************************/
if (svc->current_state == STATE_OK) {
log_debug_info(DEBUGL_CHECKS, 1, "Service is OK\n");
if (hst->has_been_checked == FALSE) {
log_debug_info(DEBUGL_CHECKS, 1, "Host has not been checked yet\n");
if (hst->next_check == 0L
|| hst->initial_state != HOST_UP
|| hst->next_check < hst->check_interval * interval_length + current_time) {
log_debug_info(DEBUGL_CHECKS, 2, "Service ok, but host hasn't been checked recently, scheduling host check\n");
check_host = TRUE;
}
}
else if (hst->current_state != HOST_UP) {
log_debug_info(DEBUGL_CHECKS, 1, "Host is NOT UP, so we'll check it to see if it recovered...\n");
if (svc->last_state == STATE_OK
&& hst->has_been_checked == TRUE
&& current_time - hst->last_check < cached_host_check_horizon) {
log_debug_info(DEBUGL_CHECKS, 2, "Service ok, but host isn't up (and has been checked). Using cached host data.\n");
update_host_stats = TRUE;
} else {
log_debug_info(DEBUGL_CHECKS, 2, "Service ok, but host isn't up and cached data isn't valid here, scheduling host check\n");
check_host = TRUE;
}
svc->host_problem_at_last_check = TRUE;
}
}
else {
log_debug_info(DEBUGL_CHECKS, 1, "Service is in a non-OK state!\n");
if (hst->current_state == HOST_UP) {
log_debug_info(DEBUGL_CHECKS, 1, "Host is currently UP, so we'll recheck its state to make sure...\n");
if (execute_host_checks == TRUE
&& svc->last_state != svc->current_state
&& hst->last_check + cached_host_check_horizon < current_time) {
log_debug_info(DEBUGL_CHECKS, 2, "Service not ok, host is up but cached data isn't valid, scheduling host check\n");
check_host = TRUE;
} else {
log_debug_info(DEBUGL_CHECKS, 2, "Service not ok, host is up, using cached host data\n");
update_host_stats = TRUE;
}
/* give the service a chance to recover */
if (svc->host_problem_at_last_check == TRUE
&& svc->state_type == SOFT_STATE) {
log_debug_info(DEBUGL_CHECKS, 2, "Service had a host problem at last check and is SOFT, so we'll reset current_attempt to 1 to give it a chance\n");
svc->current_attempt = 1;
}
svc->host_problem_at_last_check = FALSE;
}
else {
log_debug_info(DEBUGL_CHECKS, 1, "Host is currently not UP...\n");
if (execute_host_checks == FALSE || svc->current_state == svc->last_state) {
log_debug_info(DEBUGL_CHECKS, 2, "Host checks aren't enabled, so send a notification\n");
/* fake a host check */
if (hst->has_been_checked == FALSE) {
log_debug_info(DEBUGL_CHECKS, 2, "Host has never been checked, fake a host check\n");
hst->has_been_checked = TRUE;
hst->last_check = svc->last_check;
}
/* possibly re-send host notifications... */
host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
}
svc->host_problem_at_last_check = TRUE;
}
}
/* service hard state change, because if host is down/unreachable
the docs say we have a hard state change (but no notification) */
if (hst->current_state != HOST_UP && new_last_hard_state != svc->current_state) {
log_debug_info(DEBUGL_CHECKS, 2, "Host is down or unreachable, forcing service hard state change\n");
hard_state_change = TRUE;
svc->state_type = HARD_STATE;
new_last_hard_state = svc->current_state;
svc->current_attempt = svc->max_attempts;
}
if (check_host == TRUE) {
schedule_host_check(hst, current_time, CHECK_OPTION_DEPENDENCY_CHECK);
}
if (update_host_stats == TRUE) {
update_check_stats(ACTIVE_ONDEMAND_HOST_CHECK_STATS, current_time);
update_check_stats(ACTIVE_CACHED_HOST_CHECK_STATS, current_time);
}
/**************************************/
/******* SERVICE CHECK OK LOGIC *******/
/**************************************/
if (svc->last_state == STATE_OK) {
log_debug_info(DEBUGL_CHECKS, 1, "Service was OK at last check.\n");
/***** SERVICE IS STILL OK *****/
if (svc->current_state == STATE_OK) {
log_debug_info(DEBUGL_CHECKS, 1, "Service is still OK.\n");
svc->state_type = HARD_STATE;
svc->current_attempt = 1;
}
/***** SERVICE IS NOW IN PROBLEM STATE *****/
else {
log_debug_info(DEBUGL_CHECKS, 1, "Service is a non-OK state (%s)!\n", service_state_name(svc->current_state));
/* skip this service check if host is down/unreachable and state change happened */
if (svc->host_problem_at_last_check == FALSE && hard_state_change == FALSE) {
svc->state_type = SOFT_STATE;
}
svc->current_attempt = 1;
handle_event = TRUE;
}
}
/*******************************************/
/******* SERVICE CHECK PROBLEM LOGIC *******/
/*******************************************/
else {
log_debug_info(DEBUGL_CHECKS, 1, "Service was NOT OK at last check (%s).\n", service_state_name(svc->last_state));
/***** SERVICE IS NOW OK *****/
if (svc->current_state == STATE_OK) {
handle_event = TRUE;
if (svc->state_type == HARD_STATE) {
log_debug_info(DEBUGL_CHECKS, 1, "Service experienced a HARD recovery.\n");
send_notification = TRUE;
}
else {
log_debug_info(DEBUGL_CHECKS, 1, "Service experienced a SOFT recovery.\n");
}
/* there was a state change, soft or hard */
state_change = TRUE;
}
/***** SERVICE IS STILL IN PROBLEM STATE *****/
else {
log_debug_info(DEBUGL_CHECKS, 1, "Service is still in a non-OK state (%s)!\n", service_state_name(svc->current_state));
if (svc->state_type == SOFT_STATE) {
log_debug_info(DEBUGL_CHECKS, 2, "Service state type is soft, using retry_interval\n");
handle_event = TRUE;
next_check = (unsigned long) (current_time + svc->retry_interval * interval_length);
}
/* check if host is down/unreachable and don't send notifications */
else if (svc->host_problem_at_last_check == TRUE) {
log_debug_info(DEBUGL_CHECKS, 2, "Service state type is hard, but host is down or unreachable, not sending notification\n");
} else {
log_debug_info(DEBUGL_CHECKS, 2, "Service state type is hard, sending a notification\n");
send_notification = TRUE;
}
}
}
/* soft states should be using retry_interval */
if (svc->state_type == SOFT_STATE) {
log_debug_info(DEBUGL_CHECKS, 2, "Service state type is soft, using retry_interval\n");
next_check = (unsigned long) (current_time + svc->retry_interval * interval_length);
}
/* check for a state change */
if (svc->current_state != svc->last_state || (svc->current_state == STATE_OK && svc->state_type == SOFT_STATE)) {
log_debug_info(DEBUGL_CHECKS, 2, "Service experienced a state change\n");
state_change = TRUE;
}
/* adjust the current attempt */
if (svc->state_type == SOFT_STATE) {
/* this has to be first so we don't reset every time a new non-ok state comes
in (and triggers the state_change == TRUE) */
if (svc->last_state != STATE_OK && svc->current_attempt < svc->max_attempts) {
svc->current_attempt++;
}
/* historically, a soft recovery would actually get up to 2 attempts
and then immediately reset once the next check result came in */
else if (state_change == TRUE && svc->current_state != STATE_OK) {
svc->current_attempt = 1;
}
/* otherwise, just increase the attempt */
else if (svc->current_attempt < svc->max_attempts) {
svc->current_attempt++;
}
}
if (svc->current_attempt >= svc->max_attempts &&
(svc->current_state != new_last_hard_state || (svc->state_type == SOFT_STATE && svc->current_state != STATE_OK))) {
log_debug_info(DEBUGL_CHECKS, 2, "Service had a HARD STATE CHANGE!!\n");
next_check = (unsigned long)(current_time + (svc->check_interval * interval_length));
/* set both states changed, this may have been missed... */
hard_state_change = TRUE;
/* this is missed earlier */
send_notification = TRUE;
}
/* handle some acknowledgement things and update last_state_change */
/* This is a temporary fix that lets us avoid changing any function boundaries in a bugfix release */
/* @fixme 4.5.0 - refactor so that each specific struct member is only modified in */
/* service_state_or_hard_state_type_change() or handle_async_service_check_result(), not both.*/
int original_last_hard_state = svc->last_hard_state;
service_state_or_hard_state_type_change(svc, state_change, hard_state_change, &log_event, &handle_event);
if (original_last_hard_state != svc->last_hard_state) {
/* svc->last_hard_state now gets written only after the service status is brokered */
new_last_hard_state = svc->last_hard_state;
svc->last_hard_state = original_last_hard_state;
}
/* fix edge cases where log_event wouldn't have been set or won't be */
if (svc->current_state != STATE_OK && svc->state_type == SOFT_STATE) {
log_event = TRUE;
}
record_last_service_state_ended(svc);
check_for_service_flapping(svc, TRUE, TRUE);
check_for_host_flapping(hst, TRUE, FALSE, TRUE);
/* service with active checks disabled do not get rescheduled */
if (svc->checks_enabled == FALSE) {
svc->should_be_scheduled = FALSE;
}
/* hosts with non-recurring intervals do not get rescheduled if we're in a HARD or OK state */
else if (svc->check_interval == 0 && (svc->state_type == HARD_STATE || svc->current_state == STATE_OK)) {
svc->should_be_scheduled = FALSE;
}
/* schedule a non-forced check if we can */
else if (svc->should_be_scheduled == TRUE) {
log_debug_info(DEBUGL_CHECKS, 1, "Rescheduling next check of service at %s", ctime(&next_check));
/* next check time was calculated above */
/* make sure we don't get ourselves into too much trouble... */
if (current_time > next_check) {
svc->next_check = current_time;
} else {
svc->next_check = next_check;
}
/* make sure we rescheduled the next service check at a valid time */
preferred_time = svc->next_check;
get_next_valid_time(preferred_time, &next_valid_time, svc->check_period_ptr);
svc->next_check = next_valid_time;
/* Next valid time is further in the future because of timeperiod
constraints. Add a random amount so we don't get all checks
subject to that timeperiod constraint scheduled at the same time */
if (next_valid_time > preferred_time) {
svc->next_check = reschedule_within_timeperiod(next_valid_time, svc->check_period_ptr, check_window(svc));
}
schedule_service_check(svc, svc->next_check, CHECK_OPTION_NONE);
}
/* volatile service gets everything in non-ok hard state */
if ((svc->current_state != STATE_OK)
&& (svc->state_type == HARD_STATE)
&& (svc->is_volatile == TRUE)) {
log_debug_info(DEBUGL_CHECKS, 2, "Service is volatile, and we're in a non-ok hard state..\n");
send_notification = TRUE;
log_event = TRUE;
handle_event = TRUE;
}
if (send_notification == TRUE) {
/* send notification */
if (service_notification(svc, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE) == OK) {
/* log state due to notification event when stalking_options N is set */
if (should_stalk_notifications(svc)) {
log_event = TRUE;
}
}
}
/* the service recovered, so reset the current notification number and state flags (after the recovery notification has gone out) */
if(svc->current_state == STATE_OK && svc->state_type == HARD_STATE && hard_state_change == TRUE) {
svc->current_notification_number = 0;
svc->notified_on = 0;
}
if (obsess_over_services == TRUE) {
obsessive_compulsive_service_check_processor(svc);
}
/* if we're stalking this state type AND the plugin output changed since last check, log it now.. */
if (should_stalk(svc) && compare_strings(old_plugin_output, svc->plugin_output)) {
log_debug_info(DEBUGL_CHECKS, 2, "Logging due to state stalking, old: [%s], new: [%s]\n", old_plugin_output, svc->plugin_output);
log_event = TRUE;
}
if (log_event == TRUE) {
log_service_event(svc);
}
if (handle_event == TRUE) {
handle_service_event(svc);
}
/* Update OK states since they send out a soft alert but then they
switch into a HARD state and reset the attempts */
if (svc->current_state == STATE_OK && state_change == TRUE) {
/* Problem state starts regardless of SOFT/HARD status. */
svc->last_problem_id = svc->current_problem_id;
svc->current_problem_id = 0L;
/* Reset attempts */
if (hard_state_change == TRUE) {
svc->current_notification_number = 0;
svc->host_problem_at_last_check = FALSE;
}
svc->last_hard_state_change = svc->last_check;
new_last_hard_state = svc->current_state;
/* Set OK to a hard state */
svc->current_attempt = 1;
svc->state_type = HARD_STATE;
}
log_debug_info(DEBUGL_CHECKS, 2,
"STATE: %d, TYPE: %s, CUR: %d, MAX: %d, LAST_STATE: %d, LAST_HARD: %d, NOTIFY: %d, LOGGED: %d, HANDLED: %d\n",
svc->current_state,
(svc->state_type == SOFT_STATE) ? "SOFT" : "HARD",
svc->current_attempt,
svc->max_attempts,
svc->last_state,
svc->last_hard_state,
send_notification,
log_event,
handle_event);
#ifdef USE_EVENT_BROKER
broker_service_check(NEBTYPE_SERVICECHECK_PROCESSED, NEBFLAG_NONE, NEBATTR_NONE, svc, svc->check_type, cr->start_time, cr->finish_time, NULL, svc->latency, svc->execution_time, service_check_timeout, cr->early_timeout, cr->return_code, NULL, NULL, cr);
#endif
svc->has_been_checked = TRUE;
update_service_status(svc, FALSE);
update_service_performance_data(svc);
/* last_hard_state cleanup
* This occurs after being brokered so that last_hard_state refers to the previous logged hard state,
* rather than the current hard state
*/
svc->last_hard_state = new_last_hard_state;
my_free(old_plugin_output);
return OK;
}
/* schedules an immediate or delayed service check */
inline void schedule_service_check(service *svc, time_t check_time, int options)
{
timed_event *temp_event = NULL;
int use_original_event = TRUE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "schedule_service_check()\n");
if (svc == NULL)
return;
log_debug_info(DEBUGL_CHECKS, 0, "Scheduling a %s, active check of service '%s' on host '%s' @ %s", (options & CHECK_OPTION_FORCE_EXECUTION) ? "forced" : "non-forced", svc->description, svc->host_name, ctime(&check_time));
/* don't schedule a check if active checks of this service are disabled */
if (svc->checks_enabled == FALSE && !(options & CHECK_OPTION_FORCE_EXECUTION)) {
log_debug_info(DEBUGL_CHECKS, 0, "Active checks of this service are disabled.\n");
return;
}
/* we may have to nudge this check a bit */
if (options == CHECK_OPTION_DEPENDENCY_CHECK) {
if (svc->last_check + cached_service_check_horizon > check_time) {
log_debug_info(DEBUGL_CHECKS, 0, "Last check result is recent enough (%s)", ctime(&svc->last_check));
return;
}
}
/* default is to use the new event */
use_original_event = FALSE;
temp_event = (timed_event *)svc->next_check_event;
/*
* If the service already has a check scheduled,
* we need to decide which of the events to use
*/
if (temp_event != NULL) {
log_debug_info(DEBUGL_CHECKS, 2, "Found another service check event for this service @ %s", ctime(&temp_event->run_time));
/* use the originally scheduled check unless we decide otherwise */
use_original_event = TRUE;
/* the original event is a forced check... */
if ((temp_event->event_options & CHECK_OPTION_FORCE_EXECUTION)) {
/* the new event is also forced and its execution time is earlier than the original, so use it instead */
if ((options & CHECK_OPTION_FORCE_EXECUTION) && (check_time < temp_event->run_time)) {
use_original_event = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "New service check event is forced and occurs before the existing event, so the new event will be used instead.\n");
}
}
/* the original event is not a forced check... */
else {
/* the new event is a forced check, so use it instead */
if ((options & CHECK_OPTION_FORCE_EXECUTION)) {
use_original_event = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "New service check event is forced, so it will be used instead of the existing event.\n");
}
/* the new event is not forced either and its execution time is earlier than the original, so use it instead */
else if (check_time < temp_event->run_time) {
use_original_event = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "New service check event occurs before the existing (older) event, so it will be used instead.\n");
}
/* the new event is older, so override the existing one */
else {
log_debug_info(DEBUGL_CHECKS, 2, "New service check event occurs after the existing event, so we'll ignore it.\n");
}
}
}
/* schedule a new event */
if (use_original_event == FALSE) {
/* make sure we remove the old event from the queue */
if (temp_event) {
remove_event(nagios_squeue, temp_event);
}
else {
/* allocate memory for a new event item */
temp_event = (timed_event *)calloc(1, sizeof(timed_event));
if (temp_event == NULL) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not reschedule check of service '%s' on host '%s'!\n", svc->description, svc->host_name);
return;
}
}
log_debug_info(DEBUGL_CHECKS, 2, "Scheduling new service check event.\n");
/* set the next service check event and time */
svc->next_check_event = temp_event;
svc->next_check = check_time;
/* save check options for retention purposes */
svc->check_options = options;
/* place the new event in the event queue */
temp_event->event_type = EVENT_SERVICE_CHECK;
temp_event->event_data = (void *)svc;
temp_event->event_args = (void *)NULL;
temp_event->event_options = options;
temp_event->run_time = svc->next_check;
temp_event->recurring = FALSE;
temp_event->event_interval = 0L;
temp_event->timing_func = NULL;
temp_event->compensate_for_time_change = TRUE;
add_event(nagios_squeue, temp_event);
}
else {
/* reset the next check time (it may be out of sync) */
if (temp_event != NULL) {
svc->next_check = temp_event->run_time;
}
log_debug_info(DEBUGL_CHECKS, 2, "Keeping original service check event (ignoring the new one).\n");
}
/* update the status log */
update_service_status(svc, FALSE);
}
/* checks viability of performing a service check */
inline int check_service_check_viability(service *svc, int check_options, int *time_is_valid, time_t *new_time)
{
int perform_check = TRUE;
time_t current_time = 0L;
time_t preferred_time = 0L;
int check_interval = 0;
host *temp_host = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_service_check_viability()\n");
/* make sure we have a service */
if (svc == NULL) {
return ERROR;
}
/* get the check interval to use if we need to reschedule the check */
if (svc->state_type == SOFT_STATE && svc->current_state != STATE_OK) {
check_interval = (svc->retry_interval * interval_length);
}
else {
check_interval = (svc->check_interval * interval_length);
}
/* get the current time */
time(¤t_time);
/* initialize the next preferred check time */
preferred_time = current_time;
/* can we check the host right now? */
if (!(check_options & CHECK_OPTION_FORCE_EXECUTION)) {
/* if checks of the service are currently disabled... */
if (svc->checks_enabled == FALSE) {
preferred_time = current_time + check_interval;
perform_check = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "Active checks of the service are currently disabled.\n");
}
/* make sure this is a valid time to check the service */
if (check_time_against_period((unsigned long)current_time, svc->check_period_ptr) == ERROR) {
preferred_time = current_time;
if (time_is_valid) {
*time_is_valid = FALSE;
}
perform_check = FALSE;
log_debug_info(DEBUGL_CHECKS, 2, "This is not a valid time for this service to be actively checked.\n");
}
/* check service dependencies for execution */
if (check_service_dependencies(svc, EXECUTION_DEPENDENCY) == DEPENDENCIES_FAILED) {
preferred_time = current_time + check_interval;
perform_check = FALSE;
if (service_skip_check_dependency_status >= 0) {
svc->current_state = service_skip_check_dependency_status;
}
log_debug_info(DEBUGL_CHECKS, 2, "Execution dependencies for this service failed, so it will not be actively checked.\n");
}
}
/* check if parent service is OK */
if (check_service_parents(svc) == DEPENDENCIES_FAILED) {
preferred_time = current_time + check_interval;
perform_check = FALSE;
if (service_skip_check_parent_status >= 0) {
svc->current_state = service_skip_check_parent_status;
}
log_debug_info(DEBUGL_CHECKS, 2, "Execution parents for this service failed, so it will not be actively checked.\n");
}
/* check if host is up - if not, do not perform check */
if (host_down_disable_service_checks) {
if ((temp_host = svc->host_ptr) == NULL) {
log_debug_info(DEBUGL_CHECKS, 2, "Host pointer NULL in check_service_check_viability().\n");
return ERROR;
}
else {
if (temp_host->current_state != HOST_UP) {
log_debug_info(DEBUGL_CHECKS, 2, "Host state not UP, so service check will not be performed - will be rescheduled as normal.\n");
perform_check = FALSE;
if (service_skip_check_host_down_status >= 0) {
svc->current_state = service_skip_check_host_down_status;
}
}
}
}
/* pass back the next viable check time */
if (new_time) {
*new_time = preferred_time;
}
if (perform_check == TRUE) {
return OK;
}
return ERROR;
}
/* checks service parents */
int check_service_parents(service *svc)
{
servicesmember *temp_servicesmember = NULL;
int state = STATE_OK;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_service_parents()\n");
/* check all parents... */
for(temp_servicesmember = svc->parents; temp_servicesmember; temp_servicesmember = temp_servicesmember->next) {
service *parent_service;
/* find the service we depend on... */
if ((parent_service = temp_servicesmember->service_ptr) == NULL) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: service '%s' on host '%s' is NULL ptr\n",
temp_servicesmember->service_description, temp_servicesmember->host_name);
continue;
}
state = parent_service->last_hard_state;
/* is the service we depend on in a state that fails the dependency tests? */
if ((state == STATE_CRITICAL) || (state == STATE_UNKNOWN))
return DEPENDENCIES_FAILED;
if (check_service_parents(parent_service) != DEPENDENCIES_OK)
return DEPENDENCIES_FAILED;
}
return DEPENDENCIES_OK;
}
/* checks service dependencies */
int check_service_dependencies(service *svc, int dependency_type)
{
objectlist *list;
int state = STATE_OK;
time_t current_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_service_dependencies()\n");
/* only check dependencies of the desired type */
if (dependency_type == NOTIFICATION_DEPENDENCY)
list = svc->notify_deps;
else
list = svc->exec_deps;
/* check all dependencies of the desired type... */
for(; list; list = list->next) {
service *temp_service;
servicedependency *temp_dependency = (servicedependency *)list->object_ptr;
/* find the service we depend on... */
if ((temp_service = temp_dependency->master_service_ptr) == NULL) {
continue;
}
/* skip this dependency if it has a timeperiod and the current time isn't valid */
time(¤t_time);
if (temp_dependency->dependency_period != NULL
&& (check_time_against_period(current_time, temp_dependency->dependency_period_ptr) == ERROR)) {
return FALSE;
}
/* get the status to use (use last hard state if its currently in a soft state) */
if (temp_service->state_type == SOFT_STATE && soft_state_dependencies == FALSE) {
state = temp_service->last_hard_state;
}
else {
state = temp_service->current_state;
}
/* is the service we depend on in state that fails the dependency tests? */
if (flag_isset(temp_dependency->failure_options, 1 << state)) {
return DEPENDENCIES_FAILED;
}
/* immediate dependencies ok at this point - check parent dependencies if necessary */
if (temp_dependency->inherits_parent == TRUE) {
if (check_service_dependencies(temp_service, dependency_type) != DEPENDENCIES_OK) {
return DEPENDENCIES_FAILED;
}
}
}
return DEPENDENCIES_OK;
}
/* check for services that never returned from a check... */
void check_for_orphaned_services(void)
{
service *temp_service = NULL;
time_t current_time = 0L;
time_t expected_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_orphaned_services()\n");
/* get the current time */
time(¤t_time);
/* check all services... */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
/* skip services that are not currently executing */
if (temp_service->is_executing == FALSE) {
continue;
}
/* determine the time at which the check results should have come in (allow 10 minutes slack time) */
expected_time = (time_t)(temp_service->next_check + temp_service->latency + service_check_timeout + check_reaper_interval + 600);
/* this service was supposed to have executed a while ago, but for some reason the results haven't come back in... */
if (expected_time < current_time) {
/* log a warning */
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: The check of service '%s' on host '%s' looks like it was orphaned (results never came back; last_check=%lu; next_check=%lu). I'm scheduling an immediate check of the service...\n", temp_service->description, temp_service->host_name, temp_service->last_check, temp_service->next_check);
log_debug_info(DEBUGL_CHECKS, 1, "Service '%s' on host '%s' was orphaned, so we're scheduling an immediate check...\n", temp_service->description, temp_service->host_name);
log_debug_info(DEBUGL_CHECKS, 1, " next_check=%lu (%s); last_check=%lu (%s);\n",
temp_service->next_check, ctime(&temp_service->next_check),
temp_service->last_check, ctime(&temp_service->last_check));
/* decrement the number of running service checks */
if (currently_running_service_checks > 0) {
currently_running_service_checks--;
}
/* disable the executing flag */
temp_service->is_executing = FALSE;
/* schedule an immediate check of the service */
schedule_service_check(temp_service, current_time, CHECK_OPTION_ORPHAN_CHECK);
}
}
return;
}
/* check freshness of service results */
void check_service_result_freshness(void)
{
service *temp_service = NULL;
time_t current_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_service_result_freshness()\n");
log_debug_info(DEBUGL_CHECKS, 1, "Checking the freshness of service check results...\n");
/* bail out if we're not supposed to be checking freshness */
if (check_service_freshness == FALSE) {
log_debug_info(DEBUGL_CHECKS, 1, "Service freshness checking is disabled.\n");
return;
}
/* get the current time */
time(¤t_time);
/* check all services... */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
/* skip services we shouldn't be checking for freshness */
if (temp_service->check_freshness == FALSE) {
continue;
}
/* skip services that are currently executing (problems here will be caught by orphaned service check) */
if (temp_service->is_executing == TRUE) {
continue;
}
/* skip services that have both active and passive checks disabled */
if (temp_service->checks_enabled == FALSE && temp_service->accept_passive_checks == FALSE) {
continue;
}
/* skip services that are already being freshened */
if (temp_service->is_being_freshened == TRUE) {
continue;
}
/* see if the time is right... */
if (check_time_against_period(current_time, temp_service->check_period_ptr) == ERROR) {
continue;
}
/* EXCEPTION */
/* don't check freshness of services without regular check intervals if we're using auto-freshness threshold */
if ((temp_service->check_interval == 0) && (temp_service->freshness_threshold == 0)) {
continue;
}
/* the results for the last check of this service are stale! */
if (is_service_result_fresh(temp_service, current_time, TRUE) == FALSE) {
/* set the freshen flag */
temp_service->is_being_freshened = TRUE;
/* schedule an immediate forced check of the service */
schedule_service_check(temp_service, current_time, CHECK_OPTION_FORCE_EXECUTION | CHECK_OPTION_FRESHNESS_CHECK);
}
}
return;
}
/* tests whether or not a service's check results are fresh */
int is_service_result_fresh(service *temp_service, time_t current_time, int log_this)
{
int freshness_threshold = 0;
time_t expiration_time = 0L;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
int tdays = 0;
int thours = 0;
int tminutes = 0;
int tseconds = 0;
log_debug_info(DEBUGL_CHECKS, 2, "Checking freshness of service '%s' on host '%s'...\n", temp_service->description, temp_service->host_name);
/* use user-supplied freshness threshold or auto-calculate a freshness threshold to use? */
if (temp_service->freshness_threshold == 0) {
if (temp_service->state_type == HARD_STATE || temp_service->current_state == STATE_OK) {
freshness_threshold = (temp_service->check_interval * interval_length) + temp_service->latency + additional_freshness_latency;
}
else {
freshness_threshold = (temp_service->retry_interval * interval_length) + temp_service->latency + additional_freshness_latency;
}
}
else {
freshness_threshold = temp_service->freshness_threshold;
}
log_debug_info(DEBUGL_CHECKS, 2, "Freshness thresholds: service=%d, use=%d\n", temp_service->freshness_threshold, freshness_threshold);
/* calculate expiration time */
/*
* CHANGED 11/10/05 EG -
* program start is only used in expiration time calculation
* if > last check AND active checks are enabled, so active checks
* can become stale immediately upon program startup
*/
/*
* CHANGED 02/25/06 SG -
* passive checks also become stale, so remove dependence on active
* check logic
*/
if (temp_service->has_been_checked == FALSE) {
expiration_time = (time_t)(event_start + freshness_threshold);
}
/*
* CHANGED 06/19/07 EG -
* Per Ton's suggestion (and user requests), only use program start
* time over last check if no specific threshold has been set by user.
* Problems can occur if Nagios is restarted more frequently that
* freshness threshold intervals (services never go stale).
*/
/*
* CHANGED 10/07/07 EG:
* Only match next condition for services that
* have active checks enabled...
*/
/*
* CHANGED 10/07/07 EG:
* Added max_service_check_spread to expiration time as suggested
* by Altinity
*/
else if ((temp_service->checks_enabled == TRUE)
&& (event_start > temp_service->last_check)
&& (temp_service->freshness_threshold == 0)) {
expiration_time = (time_t)(event_start + freshness_threshold + (max_service_check_spread * interval_length));
}
else {
expiration_time = (time_t)(temp_service->last_check + freshness_threshold);
}
/*
* If the check was last done passively, we assume it's going
* to continue that way and we need to handle the fact that
* Nagios might have been shut off for quite a long time. If so,
* we mustn't spam freshness notifications but use event_start
* instead of last_check to determine freshness expiration time.
* The threshold for "long time" is determined as 61.8% of the normal
* freshness threshold based on vast heuristical research (ie, "some
* guy once told me the golden ratio is good for loads of stuff").
*/
if ((temp_service->check_type == CHECK_TYPE_PASSIVE)
&& (temp_service->last_check < event_start)
&& (event_start - last_program_stop > freshness_threshold * 0.618)) {
expiration_time = event_start + freshness_threshold;
}
log_debug_info(DEBUGL_CHECKS, 2, "HBC: %d, PS: %lu, ES: %lu, LC: %lu, CT: %lu, ET: %lu\n", temp_service->has_been_checked, (unsigned long)program_start, (unsigned long)event_start, (unsigned long)temp_service->last_check, (unsigned long)current_time, (unsigned long)expiration_time);
/* the results for the last check of this service are stale */
if (expiration_time < current_time) {
get_time_breakdown((current_time - expiration_time), &days, &hours, &minutes, &seconds);
get_time_breakdown(freshness_threshold, &tdays, &thours, &tminutes, &tseconds);
/* log a warning */
if (log_this == TRUE) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: The results of service '%s' on host '%s' are stale by %dd %dh %dm %ds (threshold=%dd %dh %dm %ds). I'm forcing an immediate check of the service.\n", temp_service->description, temp_service->host_name, days, hours, minutes, seconds, tdays, thours, tminutes, tseconds);
}
log_debug_info(DEBUGL_CHECKS, 1, "Check results for service '%s' on host '%s' are stale by %dd %dh %dm %ds (threshold=%dd %dh %dm %ds). Forcing an immediate check of the service...\n", temp_service->description, temp_service->host_name, days, hours, minutes, seconds, tdays, thours, tminutes, tseconds);
return FALSE;
}
log_debug_info(DEBUGL_CHECKS, 1, "Check results for service '%s' on host '%s' are fresh.\n", temp_service->description, temp_service->host_name);
return TRUE;
}
int handle_async_host_check_result(host *hst, check_result *cr)
{
time_t current_time = 0L;
time_t next_check = 0L;
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
int state_change = FALSE;
int hard_state_change = FALSE;
int send_notification = FALSE;
int handle_event = FALSE;
int log_event = FALSE;
char * old_plugin_output = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_async_host_check_result()\n");
if (is_valid_check_result_data(hst, cr) == FALSE) {
return ERROR;
}
int new_last_hard_state = hst->last_hard_state;
if (cr->check_type == CHECK_TYPE_PASSIVE) {
if (host_is_passive(hst, cr) == FALSE) {
return ERROR;
}
}
else {
host_is_active(hst);
}
time(¤t_time);
initialize_last_host_state_change_times(hst);
debug_async_host(hst, cr);
host_fresh_check(hst, cr, current_time);
host_initial_handling(hst, cr, &old_plugin_output);
/* reschedule the next check at the regular interval - may be overridden */
next_check = (time_t)(hst->last_check + (hst->check_interval * interval_length));
/**************************************/
/********* HOST CHECK OK LOGIC ********/
/**************************************/
if (hst->last_state == HOST_UP) {
log_debug_info(DEBUGL_CHECKS, 1, "Host was UP.\n");
/***** HOST IS STILL UP *****/
if (hst->current_state == HOST_UP) {
log_debug_info(DEBUGL_CHECKS, 1, "Host is still UP.\n");
hst->state_type = HARD_STATE;
hst->current_attempt = 1;
}
/***** HOST IS NOW DOWN/UNREACHABLE *****/
else {
log_debug_info(DEBUGL_CHECKS, 1, "Host is no longer UP (%s)!\n", host_state_name(hst->current_state));
hst->state_type = SOFT_STATE;
hst->current_attempt = 1;
/* propagate checks to immediate parents if they are UP */
host_propagate_checks_to_immediate_parents(hst, FALSE, current_time);
/* propagate checks to immediate children if they are not UNREACHABLE */
host_propagate_checks_to_immediate_children(hst, FALSE, TRUE, current_time);
/* propagate checks to hosts that THIS ONE depends on for notifications AND execution */
host_propagate_dependency_checks(hst, current_time);
/* we need to handle this event */
handle_event = TRUE;
}
}
/**************************************/
/****** HOST CHECK PROBLEM LOGIC ******/
/**************************************/
else {
log_debug_info(DEBUGL_CHECKS, 1, "Host was not UP last time.\n");
/***** HOST IS NOW UP *****/
if (hst->current_state == HOST_UP) {
log_debug_info(DEBUGL_CHECKS, 1, "Host is UP now.\n");
/* propagate checks to immediate parents if they are not UP */
host_propagate_checks_to_immediate_parents(hst, TRUE, current_time);
/* propagate checks to immediate children if they are not UP */
host_propagate_checks_to_immediate_children(hst, TRUE, FALSE, current_time);
/* we need to handle this event */
handle_event = TRUE;
/* but a soft recovery is not something we notify for */
if (hst->state_type == HARD_STATE) {
log_debug_info(DEBUGL_CHECKS, 1, "Host experienced a HARD recovery.\n");
send_notification = TRUE;
hard_state_change = TRUE;
hst->current_attempt = 1;
}
else {
log_debug_info(DEBUGL_CHECKS, 1, "Host experienced a SOFT recovery.\n");
}
}
/***** HOST IS STILL DOWN/UNREACHABLE *****/
else {
log_debug_info(DEBUGL_CHECKS, 1, "Host is still not UP (%s)!\n", host_state_name(hst->current_state));
if (hst->state_type == SOFT_STATE) {
log_debug_info(DEBUGL_CHECKS, 2, "Host state type is soft, using retry_interval\n");
handle_event = TRUE;
next_check = (unsigned long) (current_time + hst->retry_interval * interval_length);
}
/* if the state_type is hard, then send a notification */
else {
log_debug_info(DEBUGL_CHECKS, 2, "Host state type is hard, sending a notification\n");
send_notification = TRUE;
}
}
}
/* translate host state between DOWN/UNREACHABLE (only for passive checks if enabled) */
if (hst->current_state != HOST_UP && (hst->check_type == CHECK_TYPE_ACTIVE || translate_passive_host_checks == TRUE)) {
hst->current_state = determine_host_reachability(hst);
if (hst->state_type == SOFT_STATE)
next_check = (unsigned long)(current_time + (hst->retry_interval * interval_length));
}
/* check for state change */
if (hst->current_state != hst->last_state || (hst->current_state == HOST_UP && hst->state_type == SOFT_STATE)) {
log_debug_info(DEBUGL_CHECKS, 2, "Host experienced a state change\n");
state_change = TRUE;
}
/* adjust the current attempt */
if (hst->state_type == SOFT_STATE) {
/* this is an edge case for non-up states, it needs to be checked first */
if (hst->last_state != HOST_UP && hst->current_state != HOST_UP && hst->current_attempt < hst->max_attempts) {
hst->current_attempt++;
}
/* reset it to 1 */
else if (state_change == TRUE || hst->current_state == HOST_UP) {
hst->current_attempt = 1;
}
/* or increment if we can */
else if (hst->current_attempt < hst->max_attempts) {
hst->current_attempt++;
}
}
if (hst->current_attempt >= hst->max_attempts && hst->current_state != new_last_hard_state) {
log_debug_info(DEBUGL_CHECKS, 2, "Host had a HARD STATE CHANGE!!\n");
next_check = (unsigned long)(current_time + (hst->check_interval * interval_length));
hard_state_change = TRUE;
send_notification = TRUE;
}
/* handle some acknowledgement things and update last_state_change */
/* @fixme 4.5.0 - See similar comment in handle_async_service_check_result() */
int original_last_hard_state = hst->last_hard_state;
host_state_or_hard_state_type_change(hst, state_change, hard_state_change, &log_event, &handle_event, &send_notification);
if (original_last_hard_state != hst->last_hard_state) {
/* svc->last_hard_state now gets written only after the service status is brokered */
new_last_hard_state = hst->last_hard_state;
hst->last_hard_state = original_last_hard_state;
}
record_last_host_state_ended(hst);
check_for_host_flapping(hst, TRUE, TRUE, TRUE);
/* host with active checks disabled do not get rescheduled */
if (hst->checks_enabled == FALSE) {
hst->should_be_scheduled = FALSE;
}
/* hosts with non-recurring intervals do not get rescheduled if we're in a HARD or UP state */
else if (hst->check_interval == 0 && (hst->state_type == HARD_STATE || hst->current_state == HOST_UP)) {
hst->should_be_scheduled = FALSE;
}
/* schedule a non-forced check if we can */
else if (hst->should_be_scheduled == TRUE) {
log_debug_info(DEBUGL_CHECKS, 1, "Rescheduling next check of host at %s", ctime(&next_check));
/* next check time was calculated above */
/* make sure we don't get ourselves into too much trouble... */
if (current_time > next_check) {
hst->next_check = current_time;
} else {
hst->next_check = next_check;
}
/* make sure we rescheduled the next service check at a valid time */
preferred_time = hst->next_check;
get_next_valid_time(preferred_time, &next_valid_time, hst->check_period_ptr);
hst->next_check = next_valid_time;
/* Next valid time is further in the future because of timeperiod
constraints. Add a random amount so we don't get all checks
subject to that timeperiod constraint scheduled at the same time */
if (next_valid_time > preferred_time) {
hst->next_check = reschedule_within_timeperiod(next_valid_time, hst->check_period_ptr, check_window(hst));
}
schedule_host_check(hst, hst->next_check, CHECK_OPTION_NONE);
}
if (hst->current_attempt == HOST_UP) {
hst->current_attempt = 1;
}
if (send_notification == TRUE) {
/* send notifications */
if (host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE) == OK) {
/* log state due to notification event when stalking_options N is set */
if (should_stalk_notifications(hst)) {
log_event = TRUE;
}
}
}
/* the host recovered, so reset the current notification number and state flags (after the recovery notification has gone out) */
if(hst->current_state == HOST_UP && hst->state_type == HARD_STATE && hard_state_change == TRUE) {
hst->current_notification_number = 0;
hst->notified_on = 0;
}
if (obsess_over_hosts == TRUE) {
obsessive_compulsive_host_check_processor(hst);
}
/* if we're stalking this state type AND the plugin output changed since last check, log it now.. */
if (should_stalk(hst) && compare_strings(old_plugin_output, hst->plugin_output)) {
log_event = TRUE;
}
/* if log_host_retries is set to true, we have to log soft states too */
if (hst->state_type == SOFT_STATE && log_host_retries == TRUE) {
log_event = TRUE;
}
if (log_event == TRUE) {
log_host_event(hst);
}
if (handle_event == TRUE) {
handle_host_event(hst);
}
log_debug_info(DEBUGL_CHECKS, 2,
"STATE: %d, TYPE: %s, CUR: %d, MAX: %d, LAST_STATE: %d, LAST_HARD: %d, NOTIFY: %d, LOGGED: %d, HANDLED: %d\n",
hst->current_state,
(hst->state_type == SOFT_STATE) ? "SOFT" : "HARD",
hst->current_attempt,
hst->max_attempts,
hst->last_state,
hst->last_hard_state,
send_notification,
log_event,
handle_event);
#ifdef USE_EVENT_BROKER
broker_host_check(NEBTYPE_HOSTCHECK_PROCESSED, NEBFLAG_NONE, NEBATTR_NONE, hst, hst->check_type, hst->current_state, hst->state_type, cr->start_time, cr->finish_time, hst->check_command, hst->latency, hst->execution_time, host_check_timeout, cr->early_timeout, cr->return_code, NULL, hst->plugin_output, hst->long_plugin_output, hst->perf_data, NULL, cr);
#endif
hst->has_been_checked = TRUE;
update_host_status(hst, FALSE);
update_host_performance_data(hst);
/* last_hard_state cleanup
* This occurs after being brokered so that last_hard_state refers to the previous logged hard state,
* rather than the current hard state
*/
hst->last_hard_state = new_last_hard_state;
/* free memory */
my_free(old_plugin_output);
return OK;
}
/******************************************************************/
/*************** COMMON ROUTE/HOST CHECK FUNCTIONS ****************/
/******************************************************************/
/* schedules an immediate or delayed host check */
inline void schedule_host_check(host *hst, time_t check_time, int options)
{
timed_event *temp_event = NULL;
/* use the originally scheduled check unless we decide otherwise */
int use_original_event = TRUE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "schedule_host_check()\n");
if (hst == NULL) {
return;
}
log_debug_info(DEBUGL_CHECKS, 0, "Scheduling a %s, active check of host '%s' @ %s",
(options & CHECK_OPTION_FORCE_EXECUTION) ? "forced" : "non-forced",
hst->name,
ctime(&check_time));
/* don't schedule a check if active checks of this host are disabled */
if (hst->checks_enabled == FALSE && !(options & CHECK_OPTION_FORCE_EXECUTION)) {
log_debug_info(DEBUGL_CHECKS, 0, "Active checks are disabled for this host.\n");
return;
}
if ((options == CHECK_OPTION_DEPENDENCY_CHECK)
&& (hst->last_check + cached_host_check_horizon > check_time)) {
log_debug_info(DEBUGL_CHECKS, 0, "Last check result is recent enough (%s)\n", ctime(&hst->last_check));
return;
}
temp_event = (timed_event *)hst->next_check_event;
if (temp_event == NULL) {
use_original_event = FALSE;
}
/*
* If the host already had a check scheduled we need
* to decide which check event to use
*/
else {
log_debug_info(DEBUGL_CHECKS, 2, "Found another host check event for this host @ %s", ctime(&temp_event->run_time));
/* the original event is a forced check... */
if ((temp_event->event_options & CHECK_OPTION_FORCE_EXECUTION)) {
/* the new event is also forced and its execution time is earlier than the original, so use it instead */
if ((options & CHECK_OPTION_FORCE_EXECUTION) && (check_time < temp_event->run_time)) {
log_debug_info(DEBUGL_CHECKS, 2, "New host check event is forced and occurs before the existing event, so the new event be used instead.\n");
use_original_event = FALSE;
}
}
/* the original event is not a forced check... */
else {
/* the new event is a forced check, so use it instead */
if ((options & CHECK_OPTION_FORCE_EXECUTION)) {
log_debug_info(DEBUGL_CHECKS, 2, "New host check event is forced, so it will be used instead of the existing event.\n");
use_original_event = FALSE;
}
/* the new event is not forced either and its execution time is earlier than the original, so use it instead */
else if (check_time < temp_event->run_time) {
log_debug_info(DEBUGL_CHECKS, 2, "New host check event occurs before the existing (older) event, so it will be used instead.\n");
use_original_event = FALSE;
}
/* the new event is older, so override the existing one */
else {
log_debug_info(DEBUGL_CHECKS, 2, "New host check event occurs after the existing event, so we'll ignore it.\n");
}
}
}
/* use the new event */
if (use_original_event == FALSE) {
log_debug_info(DEBUGL_CHECKS, 2, "Scheduling new host check event.\n");
/* possibly allocate memory for a new event item */
if (temp_event) {
remove_event(nagios_squeue, temp_event);
}
else if ((temp_event = (timed_event *)calloc(1, sizeof(timed_event))) == NULL) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not reschedule check of host '%s'!\n", hst->name);
return;
}
/* set the next host check event and time */
hst->next_check_event = temp_event;
hst->next_check = check_time;
/* save check options for retention purposes */
hst->check_options = options;
/* place the new event in the event queue */
temp_event->event_type = EVENT_HOST_CHECK;
temp_event->event_data = (void *)hst;
temp_event->event_args = (void *)NULL;
temp_event->event_options = options;
temp_event->run_time = hst->next_check;
temp_event->recurring = FALSE;
temp_event->event_interval = 0L;
temp_event->timing_func = NULL;
temp_event->compensate_for_time_change = TRUE;
add_event(nagios_squeue, temp_event);
}
else {
/* reset the next check time (it may be out of sync) */
if (temp_event != NULL) {
hst->next_check = temp_event->run_time;
}
log_debug_info(DEBUGL_CHECKS, 2, "Keeping original host check event (ignoring the new one).\n");
}
/* update the status log */
update_host_status(hst, FALSE);
}
/* checks host dependencies */
int check_host_dependencies(host *hst, int dependency_type)
{
hostdependency *temp_dependency = NULL;
objectlist *list;
host *temp_host = NULL;
int state = HOST_UP;
time_t current_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_host_dependencies()\n");
if (dependency_type == NOTIFICATION_DEPENDENCY) {
list = hst->notify_deps;
}
else {
list = hst->exec_deps;
}
/* check all dependencies... */
for(; list; list = list->next) {
temp_dependency = (hostdependency *)list->object_ptr;
/* find the host we depend on... */
if ((temp_host = temp_dependency->master_host_ptr) == NULL) {
continue;
}
/* skip this dependency if it has a timeperiod and the current time isn't valid */
time(¤t_time);
if ((temp_dependency->dependency_period != NULL)
&& (check_time_against_period(current_time, temp_dependency->dependency_period_ptr) == ERROR)) {
return FALSE;
}
/* get the status to use (use last hard state if its currently in a soft state) */
if (temp_host->state_type == SOFT_STATE && soft_state_dependencies == FALSE) {
state = temp_host->last_hard_state;
}
else {
state = temp_host->current_state;
}
/* is the host we depend on in state that fails the dependency tests? */
if (flag_isset(temp_dependency->failure_options, 1 << state)) {
return DEPENDENCIES_FAILED;
}
/* immediate dependencies ok at this point - check parent dependencies if necessary */
if ((temp_dependency->inherits_parent == TRUE)
&& (check_host_dependencies(temp_host, dependency_type) != DEPENDENCIES_OK)) {
return DEPENDENCIES_FAILED;
}
}
return DEPENDENCIES_OK;
}
/* check for hosts that never returned from a check... */
void check_for_orphaned_hosts(void)
{
host *temp_host = NULL;
time_t current_time = 0L;
time_t expected_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_orphaned_hosts()\n");
/* get the current time */
time(¤t_time);
/* check all hosts... */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
/* skip hosts that don't have a set check interval (on-demand checks are missed by the orphan logic) */
if (temp_host->next_check == (time_t)0L) {
continue;
}
/* skip hosts that are not currently executing */
if (temp_host->is_executing == FALSE) {
continue;
}
/* determine the time at which the check results should have come in (allow 10 minutes slack time) */
expected_time = (time_t)(temp_host->next_check + temp_host->latency + host_check_timeout + check_reaper_interval + 600);
/* this host was supposed to have executed a while ago, but for some reason the results haven't come back in... */
if (expected_time < current_time) {
/* log a warning */
logit(NSLOG_RUNTIME_WARNING, TRUE,
"Warning: The check of host '%s' looks like it was orphaned (results never came back). I'm scheduling an immediate check of the host...\n",
temp_host->name);
log_debug_info(DEBUGL_CHECKS, 1,
"Host '%s' was orphaned, so we're scheduling an immediate check...\n",
temp_host->name);
/* decrement the number of running host checks */
if (currently_running_host_checks > 0) {
currently_running_host_checks--;
}
/* disable the executing flag */
temp_host->is_executing = FALSE;
/* schedule an immediate check of the host */
schedule_host_check(temp_host, current_time, CHECK_OPTION_ORPHAN_CHECK);
}
}
}
/* check freshness of host results */
void check_host_result_freshness(void)
{
host *temp_host = NULL;
time_t current_time = 0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_host_result_freshness()\n");
log_debug_info(DEBUGL_CHECKS, 2, "Attempting to check the freshness of host check results...\n");
/* bail out if we're not supposed to be checking freshness */
if (check_host_freshness == FALSE) {
log_debug_info(DEBUGL_CHECKS, 2, "Host freshness checking is disabled.\n");
return;
}
/* get the current time */
time(¤t_time);
/* check all hosts... */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
/* skip hosts we shouldn't be checking for freshness */
if (temp_host->check_freshness == FALSE) {
continue;
}
/* skip hosts that have both active and passive checks disabled */
if (temp_host->checks_enabled == FALSE && temp_host->accept_passive_checks == FALSE) {
continue;
}
/* skip hosts that are currently executing (problems here will be caught by orphaned host check) */
if (temp_host->is_executing == TRUE) {
continue;
}
/* skip hosts that are already being freshened */
if (temp_host->is_being_freshened == TRUE) {
continue;
}
/* see if the time is right... */
if (check_time_against_period(current_time, temp_host->check_period_ptr) == ERROR) {
continue;
}
/* the results for the last check of this host are stale */
if (is_host_result_fresh(temp_host, current_time, TRUE) == FALSE) {
/* set the freshen flag */
temp_host->is_being_freshened = TRUE;
/* schedule an immediate forced check of the host */
schedule_host_check(temp_host, current_time, CHECK_OPTION_FORCE_EXECUTION | CHECK_OPTION_FRESHNESS_CHECK);
}
}
}
/* checks to see if a hosts's check results are fresh */
int is_host_result_fresh(host *temp_host, time_t current_time, int log_this)
{
time_t expiration_time = 0L;
int freshness_threshold = 0;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
int tdays = 0;
int thours = 0;
int tminutes = 0;
int tseconds = 0;
double interval = 0;
log_debug_info(DEBUGL_CHECKS, 2, "Checking freshness of host '%s'...\n", temp_host->name);
/* use user-supplied freshness threshold or auto-calculate a freshness threshold to use? */
if (temp_host->freshness_threshold == 0) {
if (temp_host->state_type == HARD_STATE || temp_host->current_state == STATE_OK) {
interval = temp_host->check_interval;
}
else {
interval = temp_host->retry_interval;
}
freshness_threshold = (interval * interval_length) + temp_host->latency + additional_freshness_latency;
}
else {
freshness_threshold = temp_host->freshness_threshold;
}
log_debug_info(DEBUGL_CHECKS, 2, "Freshness thresholds: host=%d, use=%d\n", temp_host->freshness_threshold, freshness_threshold);
/* calculate expiration time */
/*
* CHANGED 11/10/05 EG:
* program start is only used in expiration time calculation
* if > last check AND active checks are enabled, so active checks
* can become stale immediately upon program startup
*/
if (temp_host->has_been_checked == FALSE) {
expiration_time = (time_t)(event_start + freshness_threshold);
}
/*
* CHANGED 06/19/07 EG:
* Per Ton's suggestion (and user requests), only use program start
* time over last check if no specific threshold has been set by user.
* Problems can occur if Nagios is restarted more frequently that
* freshness threshold intervals (hosts never go stale).
*/
/*
* CHANGED 10/07/07 EG:
* Added max_host_check_spread to expiration time as suggested by
* Altinity
*/
else if ((temp_host->checks_enabled == TRUE)
&& (event_start > temp_host->last_check)
&& (temp_host->freshness_threshold == 0)) {
expiration_time = (time_t)(event_start + freshness_threshold + (max_host_check_spread * interval_length));
}
else {
expiration_time = (time_t)(temp_host->last_check + freshness_threshold);
}
/*
* If the check was last done passively, we assume it's going
* to continue that way and we need to handle the fact that
* Nagios might have been shut off for quite a long time. If so,
* we mustn't spam freshness notifications but use event_start
* instead of last_check to determine freshness expiration time.
* The threshold for "long time" is determined as 61.8% of the normal
* freshness threshold based on vast heuristical research (ie, "some
* guy once told me the golden ratio is good for loads of stuff").
*/
if ((temp_host->check_type == CHECK_TYPE_PASSIVE)
&& (temp_host->last_check < event_start)
&& (event_start - last_program_stop > freshness_threshold * 0.618)) {
expiration_time = event_start + freshness_threshold;
}
log_debug_info(DEBUGL_CHECKS, 2,
"HBC: %d, PS: %lu, ES: %lu, LC: %lu, CT: %lu, ET: %lu\n",
temp_host->has_been_checked,
(unsigned long)program_start,
(unsigned long)event_start,
(unsigned long)temp_host->last_check,
(unsigned long)current_time,
(unsigned long)expiration_time);
/* the results for the last check of this host are stale */
if (expiration_time < current_time) {
get_time_breakdown((current_time - expiration_time), &days, &hours, &minutes, &seconds);
get_time_breakdown(freshness_threshold, &tdays, &thours, &tminutes, &tseconds);
/* log a warning */
if (log_this == TRUE) {
logit(NSLOG_RUNTIME_WARNING, TRUE,
"Warning: The results of host '%s' are stale by %dd %dh %dm %ds (threshold=%dd %dh %dm %ds). I'm forcing an immediate check of the host.\n",
temp_host->name,
days,
hours,
minutes,
seconds,
tdays,
thours,
tminutes,
tseconds);
}
log_debug_info(DEBUGL_CHECKS, 1,
"Check results for host '%s' are stale by %dd %dh %dm %ds (threshold=%dd %dh %dm %ds). Forcing an immediate check of the host...\n",
temp_host->name,
days,
hours,
minutes,
seconds,
tdays,
thours,
tminutes,
tseconds);
return FALSE;
}
log_debug_info(DEBUGL_CHECKS, 1, "Check results for host '%s' are fresh.\n", temp_host->name);
return TRUE;
}
/* run a scheduled host check asynchronously */
int run_scheduled_host_check(host *hst, int check_options, double latency)
{
int result = OK;
time_t current_time = 0L;
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
int time_is_valid = TRUE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_scheduled_host_check()\n");
if (hst == NULL) {
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 0, "Attempting to run scheduled check of host '%s': check options=%d, latency=%lf\n", hst->name, check_options, latency);
/*
* reset the next_check_event so we know this host
* check is no longer in the scheduling queue
*/
hst->next_check_event = NULL;
/* attempt to run the check */
result = run_async_host_check(hst, check_options, latency, TRUE, TRUE, &time_is_valid, &preferred_time);
/* an error occurred, so reschedule the check */
if (result == ERROR) {
log_debug_info(DEBUGL_CHECKS, 1, "Unable to run scheduled host check at this time\n");
/* only attempt to (re)schedule checks that should get checked... */
if (hst->should_be_scheduled == TRUE) {
/* get current time */
time(¤t_time);
/* determine next time we should check the host if needed */
/* if host has no check interval, schedule it again for 5 minutes from now */
if (current_time >= preferred_time) {
preferred_time = current_time + ((hst->check_interval <= 0) ? 300 : (hst->check_interval * interval_length));
}
/* make sure we rescheduled the next host check at a valid time */
get_next_valid_time(preferred_time, &next_valid_time, hst->check_period_ptr);
/*
* If the host really can't be rescheduled properly we
* set next check time to preferred_time and try again then
*/
if ((time_is_valid == FALSE)
&& (check_time_against_period(next_valid_time, hst->check_period_ptr) == ERROR)) {
hst->next_check = reschedule_within_timeperiod(next_valid_time, hst->check_period_ptr, check_window(hst));
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of host '%s' could not be rescheduled properly. Scheduling check for %s...\n", hst->name, ctime(&preferred_time));
log_debug_info(DEBUGL_CHECKS, 1, "Unable to find any valid times to reschedule the next host check!\n");
}
/* this service could be rescheduled... */
else {
hst->next_check = next_valid_time;
if (next_valid_time > preferred_time) {
/* Next valid time is further in the future because of
* timeperiod constraints. Add a random amount so we
* don't get all checks subject to that timeperiod
* constraint scheduled at the same time
*/
hst->next_check = reschedule_within_timeperiod(next_valid_time, hst->check_period_ptr, check_window(hst));
}
hst->should_be_scheduled = TRUE;
log_debug_info(DEBUGL_CHECKS, 1, "Rescheduled next host check for %s", ctime(&next_valid_time));
}
}
/* update the status log */
update_host_status(hst, FALSE);
/* reschedule the next host check - unless we couldn't find a valid next check time */
/* 10/19/07 EG - keep original check options */
if (hst->should_be_scheduled == TRUE) {
schedule_host_check(hst, hst->next_check, check_options);
}
return ERROR;
}
return OK;
}
/* perform an asynchronous check of a host */
/* scheduled host checks will use this, as will some checks that result from on-demand checks... */
int run_async_host_check(host *hst, int check_options, double latency, int scheduled_check, int reschedule_check, int *time_is_valid, time_t *preferred_time)
{
nagios_macros mac;
char *raw_command = NULL;
char *processed_command = NULL;
struct timeval start_time, end_time;
double old_latency = 0.0;
check_result *cr;
int runchk_result = OK;
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
#ifdef USE_EVENT_BROKER
int neb_result = OK;
#endif
log_debug_info(DEBUGL_FUNCTIONS, 0, "run_async_host_check(%s ...)\n", hst ? hst->name : "(NULL host!)");
/* make sure we have a host */
if (hst == NULL)
return ERROR;
log_debug_info(DEBUGL_CHECKS, 0, "** Running async check of host '%s'...\n", hst->name);
/* abort if check is already running or was recently completed */
if (!(check_options & CHECK_OPTION_FORCE_EXECUTION)) {
if (hst->is_executing == TRUE) {
log_debug_info(DEBUGL_CHECKS, 1, "A check of this host is already being executed, so we'll pass for the moment...\n");
return ERROR;
}
if (hst->last_check + cached_host_check_horizon > time(NULL)) {
log_debug_info(DEBUGL_CHECKS, 0, "Host '%s' was last checked within its cache horizon. Aborting check\n", hst->name);
return ERROR;
}
}
log_debug_info(DEBUGL_CHECKS, 0, "Host '%s' passed first hurdle (caching/execution)\n", hst->name);
/* is the host check viable at this time? */
if (check_host_check_viability(hst, check_options, time_is_valid, preferred_time) == ERROR) {
log_debug_info(DEBUGL_CHECKS, 0, "Host check isn't viable at this point.\n");
return ERROR;
}
/******** GOOD TO GO FOR A REAL HOST CHECK AT THIS POINT ********/
#ifdef USE_EVENT_BROKER
/* initialize start/end times */
start_time.tv_sec = 0L;
start_time.tv_usec = 0L;
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
/* send data to event broker */
neb_result = broker_host_check(NEBTYPE_HOSTCHECK_ASYNC_PRECHECK, NEBFLAG_NONE, NEBATTR_NONE, hst, CHECK_TYPE_ACTIVE, hst->current_state, hst->state_type, start_time, end_time, hst->check_command, hst->latency, 0.0, host_check_timeout, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
/* neb module wants to cancel the host check - the check will be rescheduled for a later time by the scheduling logic */
if (neb_result == NEBERROR_CALLBACKCANCEL) {
log_debug_info(DEBUGL_CHECKS, 0, "Check of host '%s' (id=%u) was cancelled by a module\n", hst->name, hst->id);
if (preferred_time) {
*preferred_time += check_window(hst);
}
return ERROR;
}
/* neb module wants to override the host check - perhaps it will check the host itself */
/* NOTE: if a module does this, it has to do a lot of the stuff found below to make sure things don't get whacked out of shape! */
/* NOTE: if would be easier for modules to override checks when the NEBTYPE_SERVICECHECK_INITIATE event is called (later) */
if (neb_result == NEBERROR_CALLBACKOVERRIDE) {
log_debug_info(DEBUGL_CHECKS, 0, "Check of host '%s' (id=%u) was overridden by a module\n", hst->name, hst->id);
return OK;
}
#endif
log_debug_info(DEBUGL_CHECKS, 0, "Checking host '%s'...\n", hst->name);
/* clear check options - we don't want old check options retained */
/* only clear options if this was a scheduled check - on demand check options shouldn't affect retained info */
if (scheduled_check == TRUE) {
hst->check_options = CHECK_OPTION_NONE;
}
/* set latency (temporarily) for macros and event broker */
old_latency = hst->latency;
hst->latency = latency;
/* grab the host macro variables */
memset(&mac, 0, sizeof(mac));
grab_host_macros_r(&mac, hst);
/* get the raw command line */
get_raw_command_line_r(&mac, hst->check_command_ptr, hst->check_command, &raw_command, macro_options);
if (raw_command == NULL) {
clear_volatile_macros_r(&mac);
log_debug_info(DEBUGL_CHECKS, 0, "Raw check command for host '%s' was NULL - aborting.\n", hst->name);
return ERROR;
}
/* process any macros contained in the argument */
process_macros_r(&mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if (processed_command == NULL) {
clear_volatile_macros_r(&mac);
log_debug_info(DEBUGL_CHECKS, 0, "Processed check command for host '%s' was NULL - aborting.\n", hst->name);
return ERROR;
}
/* get the command start time */
gettimeofday(&start_time, NULL);
cr = calloc(1, sizeof(*cr));
if (!cr) {
log_debug_info(DEBUGL_CHECKS, 0, "Failed to allocate checkresult struct\n");
clear_volatile_macros_r(&mac);
clear_host_macros_r(&mac);
return ERROR;
}
init_check_result(cr);
/* save check info */
cr->object_check_type = HOST_CHECK;
cr->host_name = (char *)strdup(hst->name);
cr->service_description = NULL;
cr->check_type = CHECK_TYPE_ACTIVE;
cr->check_options = check_options;
cr->scheduled_check = scheduled_check;
cr->reschedule_check = reschedule_check;
cr->latency = latency;
cr->start_time = start_time;
cr->finish_time = start_time;
cr->early_timeout = FALSE;
cr->exited_ok = TRUE;
cr->return_code = STATE_OK;
cr->output = NULL;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
neb_result = broker_host_check(NEBTYPE_HOSTCHECK_INITIATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CHECK_TYPE_ACTIVE, hst->current_state, hst->state_type, start_time, end_time, hst->check_command, hst->latency, 0.0, host_check_timeout, FALSE, 0, processed_command, NULL, NULL, NULL, NULL, cr);
/* neb module wants to override the service check - perhaps it will check the service itself */
if (neb_result == NEBERROR_CALLBACKOVERRIDE) {
clear_volatile_macros_r(&mac);
hst->latency = old_latency;
free_check_result(cr);
my_free(cr);
my_free(processed_command);
return OK;
}
#endif
/* reset latency (permanent value for this check will get set later) */
hst->latency = old_latency;
runchk_result = wproc_run_check(cr, processed_command, &mac);
if (runchk_result == ERROR) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Unable to send check for host '%s' to worker (ret=%d)\n", hst->name, runchk_result);
}
else {
/* do the book-keeping */
currently_running_host_checks++;
hst->is_executing = TRUE;
update_check_stats((scheduled_check == TRUE) ? ACTIVE_SCHEDULED_HOST_CHECK_STATS : ACTIVE_ONDEMAND_HOST_CHECK_STATS, start_time.tv_sec);
update_check_stats(PARALLEL_HOST_CHECK_STATS, start_time.tv_sec);
}
/* free memory */
clear_volatile_macros_r(&mac);
my_free(processed_command);
return runchk_result;
}
/* process results of an asynchronous host check */
/* checks viability of performing a host check */
int check_host_check_viability(host *hst, int check_options, int *time_is_valid, time_t *new_time)
{
int perform_check = TRUE;
time_t current_time = 0L;
time_t preferred_time = 0L;
int check_interval = 0;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_host_check_viability()\n");
/* make sure we have a host */
if (hst == NULL) {
return ERROR;
}
/* get the check interval to use if we need to reschedule the check */
if (hst->state_type == SOFT_STATE && hst->current_state != HOST_UP) {
check_interval = (hst->retry_interval * interval_length);
}
else {
check_interval = (hst->check_interval * interval_length);
}
/* make sure check interval is positive - otherwise use 5 minutes out for next check */
if (check_interval <= 0) {
check_interval = 300;
}
/* get the current time */
time(¤t_time);
/* initialize the next preferred check time */
preferred_time = current_time;
/* can we check the host right now? */
if (!(check_options & CHECK_OPTION_FORCE_EXECUTION)) {
/* if checks of the host are currently disabled... */
if (hst->checks_enabled == FALSE) {
preferred_time = current_time + check_interval;
perform_check = FALSE;
}
/* make sure this is a valid time to check the host */
if (check_time_against_period((unsigned long)current_time, hst->check_period_ptr) == ERROR) {
log_debug_info(DEBUGL_CHECKS, 0, "Timeperiod check failed\n");
preferred_time = current_time;
if (time_is_valid) {
*time_is_valid = FALSE;
}
perform_check = FALSE;
}
/* check host dependencies for execution */
if (check_host_dependencies(hst, EXECUTION_DEPENDENCY) == DEPENDENCIES_FAILED) {
log_debug_info(DEBUGL_CHECKS, 0, "Host check dependencies failed\n");
preferred_time = current_time + check_interval;
perform_check = FALSE;
if (host_skip_check_dependency_status >= 0) {
hst->current_state = host_skip_check_dependency_status;
}
}
}
/* pass back the next viable check time */
if (new_time) {
*new_time = preferred_time;
}
if (perform_check == TRUE) {
return OK;
}
return ERROR;
}
/* determination of the host's state based on route availability*/
/* used only to determine difference between DOWN and UNREACHABLE states */
inline int determine_host_reachability(host *hst)
{
host *parent_host = NULL;
hostsmember *temp_hostsmember = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "determine_host_reachability(host=%s)\n", hst ? hst->name : "(NULL host!)");
if (hst == NULL)
return HOST_DOWN;
log_debug_info(DEBUGL_CHECKS, 2, "Determining state of host '%s': current state=%d (%s)\n", hst->name, hst->current_state, host_state_name(hst->current_state));
/* host is UP - no translation needed */
if (hst->current_state == HOST_UP) {
log_debug_info(DEBUGL_CHECKS, 2, "Host is UP, no state translation needed.\n");
return HOST_UP;
}
/* host has no parents, so it is DOWN */
if (hst->check_type == CHECK_TYPE_PASSIVE && hst->current_state == HOST_UNREACHABLE) {
log_debug_info(DEBUGL_CHECKS, 2, "Passive check so keep it UNREACHABLE.\n");
return HOST_UNREACHABLE;
}
else if (hst->parent_hosts == NULL) {
log_debug_info(DEBUGL_CHECKS, 2, "Host has no parents, so it is DOWN.\n");
return HOST_DOWN;
}
/* check all parent hosts to see if we're DOWN or UNREACHABLE */
else {
for(temp_hostsmember = hst->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
parent_host = temp_hostsmember->host_ptr;
log_debug_info(DEBUGL_CHECKS, 2, " Parent '%s' is %s\n", parent_host->name, host_state_name(parent_host->current_state));
/* bail out as soon as we find one parent host that is UP */
if (parent_host->current_state == HOST_UP) {
/* set the current state */
log_debug_info(DEBUGL_CHECKS, 2, "At least one parent (%s) is up, so host is DOWN.\n", parent_host->name);
return HOST_DOWN;
}
}
}
log_debug_info(DEBUGL_CHECKS, 2, "No parents were up, so host is UNREACHABLE.\n");
return HOST_UNREACHABLE;
}
/******************************************************************/
/****************** HOST STATE HANDLER FUNCTIONS ******************/
/******************************************************************/
/* Parses raw plugin output and returns: short and long output, perf data. */
int parse_check_output(char *buf, char **short_output, char **long_output, char **perf_data, int escape_newlines_please, int newlines_are_escaped)
{
int current_line = 0;
int eof = FALSE;
int in_perf_data = FALSE;
const int dbuf_chunk = 1024;
dbuf long_text;
dbuf perf_text;
char *ptr = NULL;
int x = 0;
int y = 0;
/* Initialize output values. */
if (short_output) {
*short_output = NULL;
}
if (long_output) {
*long_output = NULL;
}
if (perf_data) {
*perf_data = NULL;
}
/* No input provided or no output requested, nothing to do. */
if (!buf
|| !*buf
|| (!short_output && !long_output && !perf_data)) {
return OK;
}
/* Initialize dynamic buffers (1KB chunk size). */
dbuf_init(&long_text, dbuf_chunk);
dbuf_init(&perf_text, dbuf_chunk);
/* We should never need to worry about unescaping here again. We assume a
* common internal plugin output format that is newline delimited. */
if (newlines_are_escaped) {
for (x = 0, y = 0; buf[x]; x++) {
if (buf[x] == '\\' && buf[x + 1] == '\\') {
x++;
buf[y++] = buf[x];
}
else if (buf[x] == '\\' && buf[x + 1] == 'n') {
x++;
buf[y++] = '\n';
}
else {
buf[y++] = buf[x];
}
}
buf[y] = '\0';
}
/* Process each line of input. */
for (x = 0; !eof && buf[0]; x++) {
/* Continue on until we reach the end of a line (or input). */
if (buf[x] == '\n') {
buf[x] = '\0';
}
else if (buf[x] == '\0') {
eof = TRUE;
}
else {
continue;
}
/* Handle this line of input. */
current_line++;
/* The first line contains short plugin output and optional perf data. */
if (current_line == 1) {
/* Get the short plugin output. If buf[0] is '|', strtok() will
* return buf+1 or NULL if buf[1] is '\0'. We use my_strtok_with_free()
* instead which returns a pointer to '\0' in this case. */
ptr = my_strtok_with_free(buf, "|", FALSE);
if (ptr != NULL) {
if (short_output) {
/* Remove leading and trailing whitespace. */
strip(ptr);
*short_output = strdup(ptr);
}
/* Get the optional perf data. */
ptr = my_strtok_with_free(NULL, "\n", FALSE);
if (ptr != NULL) {
dbuf_strcat(&perf_text, ptr);
}
/* free anything we've allocated */
my_strtok_with_free(NULL, NULL, TRUE);
}
}
/* Additional lines contain long plugin output and optional perf data.
* Once we've hit perf data, the rest of the output is perf data. */
else if (in_perf_data) {
if (perf_text.buf && *perf_text.buf) {
dbuf_strcat(&perf_text, " ");
}
dbuf_strcat(&perf_text, buf);
}
/* Look for the perf data separator. */
else if (strchr(buf, '|')) {
in_perf_data = TRUE;
ptr = my_strtok_with_free(buf, "|", FALSE);
if (ptr != NULL) {
/* Get the remaining long plugin output. */
if (current_line > 2) {
dbuf_strcat(&long_text, "\n");
}
dbuf_strcat(&long_text, ptr);
/* Get the perf data. */
ptr = my_strtok_with_free(NULL, "\n", FALSE);
if (ptr != NULL) {
if (perf_text.buf && *perf_text.buf) {
dbuf_strcat(&perf_text, " ");
}
dbuf_strcat(&perf_text, ptr);
}
/* free anything we've allocated */
my_strtok_with_free(NULL, NULL, TRUE);
}
}
/* Otherwise it's still just long output. */
else {
if (current_line > 2) {
dbuf_strcat(&long_text, "\n");
}
dbuf_strcat(&long_text, buf);
}
/* Point buf to the start of the next line. *(buf+x+1) will be a valid
* memory reference on our next iteration or we are at the end of input
* (eof == TRUE) and *(buf+x+1) will never be referenced. */
buf += x + 1;
/* x will be incremented to 0 by the loop update. */
x = -1;
}
/* Save long output. */
if (long_output && long_text.buf && *long_text.buf) {
/* Escape newlines (and backslashes) in long output if requested. */
if (escape_newlines_please) {
*long_output = escape_newlines(long_text.buf);
}
else {
*long_output = strdup(long_text.buf);
}
}
/* Save perf data. */
if (perf_data && perf_text.buf && *perf_text.buf) {
/* Remove leading and trailing whitespace. */
strip(perf_text.buf);
*perf_data = strdup(perf_text.buf);
}
/* free dynamic buffers */
dbuf_free(&long_text);
dbuf_free(&perf_text);
return OK;
}
nagios-4.4.6/base/commands.c 0000664 0000000 0000000 00000500133 13652113235 0015667 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* COMMANDS.C - External command functions for 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/comments.h"
#include "../include/downtime.h"
#include "../include/statusdata.h"
#include "../include/perfdata.h"
#include "../include/sretention.h"
#include "../include/broker.h"
#include "../include/nagios.h"
#include "../include/workers.h"
extern int sigrestart;
static int command_file_fd;
static FILE *command_file_fp;
static int command_file_created = FALSE;
/* The command file worker process */
static struct {
/* these must come first for check source detection */
const char *type;
const char *source_name;
int pid;
int sd;
iocache *ioc;
} command_worker = { "command file", "command file worker", 0, 0, NULL };
/******************************************************************/
/************* EXTERNAL COMMAND WORKER CONTROLLERS ****************/
/******************************************************************/
/* creates external command file as a named pipe (FIFO) and opens it for reading (non-blocked mode) */
int open_command_file(void)
{
struct stat st;
int result = 0;
/* if the command file was created or
we're not checking external commands, don't do anything */
if (command_file_created == TRUE || check_external_commands == FALSE) {
return OK;
}
/* reset umask (group needs write permissions) */
umask(S_IWOTH);
/* use existing FIFO if possible */
result = stat(command_file, &st);
if(!(result != -1 && (st.st_mode & S_IFIFO))) {
/* create the external command file as a named pipe (FIFO) */
result = mkfifo(command_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (result != 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Error: Could not create external command file '%s' as named pipe: (%d) -> %s. "
"If this file already exists and you are sure that another copy of Nagios is not running, you should delete this file.\n",
command_file, errno, strerror(errno));
return ERROR;
}
}
/* open the command file for reading (non-blocked) - O_TRUNC flag cannot be used due to errors on some systems */
/* NOTE: file must be opened read-write for poll() to work */
command_file_fd = open(command_file, O_RDWR | O_NONBLOCK);
if (command_file_fd < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Error: Could not open external command file for reading via open(): (%d) -> %s\n", errno, strerror(errno));
return ERROR;
}
/* set a flag to remember we already created the file */
command_file_created = TRUE;
return OK;
}
/* closes the external command file FIFO and deletes it */
int close_command_file(void)
{
/* if the command file wasn't created or was already cleaned up
or we're not checking external commands, don't do anything */
if (command_file_created == FALSE || check_external_commands == FALSE) {
return OK;
}
/* reset our flag */
command_file_created = FALSE;
/* close the command file */
fclose(command_file_fp);
/* unlink the pipe */
unlink(command_file);
return OK;
}
/* shutdown command file worker thread */
int shutdown_command_file_worker(void) {
if (!command_worker.pid)
return 0;
iocache_destroy(command_worker.ioc);
command_worker.ioc = NULL;
iobroker_close(nagios_iobs, command_worker.sd);
command_worker.sd = -1;
kill(command_worker.pid, SIGKILL);
command_worker.pid = 0;
return 0;
}
static int command_input_handler(int sd, int events, void *discard) {
int ret, cmd_ret;
char *buf;
unsigned long size;
if (sigrestart)
return 0;
ret = iocache_read(command_worker.ioc, sd);
log_debug_info(DEBUGL_COMMANDS, 2, "Read %d bytes from command worker\n", ret);
if (ret == 0) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Command file worker seems to have died. Respawning\n");
shutdown_command_file_worker();
launch_command_file_worker();
return 0;
}
while ((buf = iocache_use_delim(command_worker.ioc, "\n", 1, &size))) {
if (buf[0] == '[') {
/* raw external command */
buf[size] = 0;
log_debug_info(DEBUGL_COMMANDS, 1, "Read raw external command '%s'\n", buf);
}
if ((cmd_ret = process_external_command1(buf)) != CMD_ERROR_OK) {
logit(NSLOG_EXTERNAL_COMMAND | NSLOG_RUNTIME_WARNING, TRUE, "External command %s returned error %s\n", buf, cmd_error_strerror(cmd_ret));
}
}
return 0;
}
/* main controller of command file helper process */
static int command_file_worker(int sd) {
iocache *ioc;
if (open_command_file() == ERROR)
return (EXIT_FAILURE);
ioc = iocache_create(65536);
if (!ioc)
exit(EXIT_FAILURE);
while(1) {
struct pollfd pfd;
int pollval, ret;
char *buf;
unsigned long size;
/* if our master has gone away, we need to die */
if (kill(nagios_pid, 0) < 0 && errno == ESRCH) {
return EXIT_SUCCESS;
}
errno = 0;
/* wait for data to arrive */
/* select seems to not work, so we have to use poll instead */
/* 10-15-08 EG check into implementing William's patch @ http://blog.netways.de/2008/08/15/nagios-unter-mac-os-x-installieren/ */
/* 10-15-08 EG poll() seems broken on OSX - see Jonathan's patch a few lines down */
pfd.fd = command_file_fd;
pfd.events = POLLIN;
pollval = poll(&pfd, 1, 500);
/* loop if no data */
if(pollval == 0)
continue;
/* check for errors */
if(pollval == -1) {
/* @todo printf("Failed to poll() command file pipe: %m\n"); */
if (errno == EINTR)
continue;
return EXIT_FAILURE;
}
errno = 0;
ret = iocache_read(ioc, command_file_fd);
if (ret < 1) {
if (errno == EINTR)
continue;
return EXIT_FAILURE;
}
size = iocache_available(ioc);
buf = iocache_use_size(ioc, size);
ret = write(sd, buf, size);
/*
* @todo Add libio to get io_write_all(), which handles
* EINTR and EAGAIN properly instead of just exiting.
*/
if (ret < 0 && errno != EINTR)
return EXIT_FAILURE;
} /* while(1) */
}
int launch_command_file_worker(void) {
int ret, sv[2];
char *str;
#ifdef HAVE_SIGACTION
struct sigaction sig_action;
#endif
/*
* if we're restarting, we may well already have a command
* file worker process attached. Keep it if that's so.
*/
if (command_worker.pid && kill(command_worker.pid, 0) == 0 &&
iobroker_is_registered(nagios_iobs, command_worker.sd))
{
return 0;
}
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to create socketpair for command file worker: %m\n");
return ERROR;
}
command_worker.pid = fork();
if (command_worker.pid < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to fork() command file worker: %m\n");
goto err_close;
}
if (command_worker.pid) {
command_worker.ioc = iocache_create(512 * 1024);
if (!command_worker.ioc) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to create I/O cache for command file worker: %m\n");
goto err_close;
}
command_worker.sd = sv[0];
ret = iobroker_register(nagios_iobs, command_worker.sd, NULL, command_input_handler);
if (ret < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to register command file worker socket %d with io broker %p: %s; errno=%d: %s\n",
command_worker.sd, nagios_iobs, iobroker_strerror(ret), errno, strerror(errno));
iocache_destroy(command_worker.ioc);
goto err_close;
}
logit(NSLOG_INFO_MESSAGE, TRUE, "Successfully launched command file worker with pid %d\n",
command_worker.pid);
return OK;
}
/* child goes here */
close(sv[0]);
/* make our own process-group so we can be traced into and stuff */
setpgid(0, 0);
/* we must preserve command_file before nuking memory */
(void)chdir("/tmp");
(void)chdir("nagios-cfw");
str = strdup(command_file);
free_memory(get_global_macros());
command_file = str;
#ifdef HAVE_SIGACTION
sig_action.sa_sigaction = NULL;
sig_action.sa_handler = SIG_IGN;
sigemptyset(&sig_action.sa_mask);
sig_action.sa_flags = 0;
sigaction(SIGPIPE, &sig_action, NULL);
#else
signal(SIGPIPE, SIG_IGN);
#endif
exit(command_file_worker(sv[1]));
/* error conditions for parent */
err_close:
close(sv[0]);
close(sv[1]);
command_worker.pid = 0;
command_worker.sd = -1;
return ERROR;
}
/******************************************************************/
/****************** EXTERNAL COMMAND PROCESSING *******************/
/******************************************************************/
/*** stupid helpers ****/
static host *find_host_by_name_or_address(const char *name)
{
host *h;
if ((h = find_host(name)) || !name)
return h;
for (h = host_list; h; h = h->next)
if (!strcmp(h->address, name))
return h;
return NULL;
}
/* processes all external commands in a (regular) file */
int process_external_commands_from_file(char *fname, int delete_file) {
mmapfile *thefile = NULL;
char *input = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "process_external_commands_from_file()\n");
if(fname == NULL)
return ERROR;
log_debug_info(DEBUGL_EXTERNALCOMMANDS, 1, "Processing commands from file '%s'. File will %s deleted after processing.\n", fname, (delete_file == TRUE) ? "be" : "NOT be");
/* open the config file for reading */
if((thefile = mmap_fopen(fname)) == NULL) {
logit(NSLOG_INFO_MESSAGE, FALSE, "Error: Cannot open file '%s' to process external commands!", fname);
return ERROR;
}
/* process all commands in the file */
while(1) {
/* free memory */
my_free(input);
/* read the next line */
if((input = mmap_fgets(thefile)) == NULL)
break;
/* process the command */
process_external_command1(input);
}
/* close the file */
mmap_fclose(thefile);
/* delete the file */
if(delete_file == TRUE)
unlink(fname);
return OK;
}
/* top-level external command processor */
int process_external_command1(char *cmd) {
char *temp_buffer = NULL;
char *command_id = NULL;
char *args = NULL;
time_t entry_time = 0L;
int command_type = CMD_NONE;
char *temp_ptr = NULL;
int external_command_ret = OK;
log_debug_info(DEBUGL_FUNCTIONS, 0, "process_external_command1()\n");
if(cmd == NULL)
return CMD_ERROR_MALFORMED_COMMAND;
/* strip the command of newlines and carriage returns */
strip(cmd);
log_debug_info(DEBUGL_EXTERNALCOMMANDS, 2, "Raw command entry: %s\n", cmd);
/* get the command entry time */
if((temp_ptr = my_strtok_with_free(cmd, "[", FALSE)) == NULL)
return CMD_ERROR_MALFORMED_COMMAND;
if((temp_ptr = my_strtok_with_free(NULL, "]", FALSE)) == NULL) {
temp_ptr = my_strtok_with_free(NULL, NULL, TRUE);
return CMD_ERROR_MALFORMED_COMMAND;
}
entry_time = (time_t)strtoul(temp_ptr, NULL, 10);
/* get the command identifier */
if((temp_ptr = my_strtok_with_free(NULL, ";", FALSE)) == NULL) {
temp_ptr = my_strtok_with_free(NULL, NULL, TRUE);
return CMD_ERROR_MALFORMED_COMMAND;
}
else if((command_id = (char *)strdup(temp_ptr + 1)) == NULL) {
temp_ptr = my_strtok_with_free(NULL, NULL, TRUE);
return CMD_ERROR_INTERNAL_ERROR;
}
/* get the command arguments */
if((temp_ptr = my_strtok_with_free(NULL, "\n", FALSE)) == NULL)
args = (char *)strdup("");
else
args = (char *)strdup(temp_ptr);
temp_ptr = my_strtok_with_free(NULL, NULL, TRUE);
if(args == NULL) {
my_free(command_id);
return CMD_ERROR_INTERNAL_ERROR;
}
/* decide what type of command this is... */
/**************************/
/**** PROCESS COMMANDS ****/
/**************************/
if(!strcasecmp(command_id, "ENTER_STANDBY_MODE") || !strcasecmp(command_id, "DISABLE_NOTIFICATIONS"))
command_type = CMD_DISABLE_NOTIFICATIONS;
else if(!strcasecmp(command_id, "ENTER_ACTIVE_MODE") || !strcasecmp(command_id, "ENABLE_NOTIFICATIONS"))
command_type = CMD_ENABLE_NOTIFICATIONS;
else if(!strcasecmp(command_id, "SHUTDOWN_PROGRAM") || !strcasecmp(command_id, "SHUTDOWN_PROCESS"))
command_type = CMD_SHUTDOWN_PROCESS;
else if(!strcasecmp(command_id, "RESTART_PROGRAM") || !strcasecmp(command_id, "RESTART_PROCESS"))
command_type = CMD_RESTART_PROCESS;
else if(!strcasecmp(command_id, "SAVE_STATE_INFORMATION"))
command_type = CMD_SAVE_STATE_INFORMATION;
else if(!strcasecmp(command_id, "READ_STATE_INFORMATION"))
command_type = CMD_READ_STATE_INFORMATION;
else if(!strcasecmp(command_id, "ENABLE_EVENT_HANDLERS"))
command_type = CMD_ENABLE_EVENT_HANDLERS;
else if(!strcasecmp(command_id, "DISABLE_EVENT_HANDLERS"))
command_type = CMD_DISABLE_EVENT_HANDLERS;
else if(!strcasecmp(command_id, "ENABLE_PERFORMANCE_DATA"))
command_type = CMD_ENABLE_PERFORMANCE_DATA;
else if(!strcasecmp(command_id, "DISABLE_PERFORMANCE_DATA"))
command_type = CMD_DISABLE_PERFORMANCE_DATA;
else if(!strcasecmp(command_id, "START_EXECUTING_HOST_CHECKS"))
command_type = CMD_START_EXECUTING_HOST_CHECKS;
else if(!strcasecmp(command_id, "STOP_EXECUTING_HOST_CHECKS"))
command_type = CMD_STOP_EXECUTING_HOST_CHECKS;
else if(!strcasecmp(command_id, "START_EXECUTING_SVC_CHECKS"))
command_type = CMD_START_EXECUTING_SVC_CHECKS;
else if(!strcasecmp(command_id, "STOP_EXECUTING_SVC_CHECKS"))
command_type = CMD_STOP_EXECUTING_SVC_CHECKS;
else if(!strcasecmp(command_id, "START_ACCEPTING_PASSIVE_HOST_CHECKS"))
command_type = CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS;
else if(!strcasecmp(command_id, "STOP_ACCEPTING_PASSIVE_HOST_CHECKS"))
command_type = CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS;
else if(!strcasecmp(command_id, "START_ACCEPTING_PASSIVE_SVC_CHECKS"))
command_type = CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS;
else if(!strcasecmp(command_id, "STOP_ACCEPTING_PASSIVE_SVC_CHECKS"))
command_type = CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS;
else if(!strcasecmp(command_id, "START_OBSESSING_OVER_HOST_CHECKS"))
command_type = CMD_START_OBSESSING_OVER_HOST_CHECKS;
else if(!strcasecmp(command_id, "STOP_OBSESSING_OVER_HOST_CHECKS"))
command_type = CMD_STOP_OBSESSING_OVER_HOST_CHECKS;
else if(!strcasecmp(command_id, "START_OBSESSING_OVER_SVC_CHECKS"))
command_type = CMD_START_OBSESSING_OVER_SVC_CHECKS;
else if(!strcasecmp(command_id, "STOP_OBSESSING_OVER_SVC_CHECKS"))
command_type = CMD_STOP_OBSESSING_OVER_SVC_CHECKS;
else if(!strcasecmp(command_id, "ENABLE_FLAP_DETECTION"))
command_type = CMD_ENABLE_FLAP_DETECTION;
else if(!strcasecmp(command_id, "DISABLE_FLAP_DETECTION"))
command_type = CMD_DISABLE_FLAP_DETECTION;
else if(!strcasecmp(command_id, "CHANGE_GLOBAL_HOST_EVENT_HANDLER"))
command_type = CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER;
else if(!strcasecmp(command_id, "CHANGE_GLOBAL_SVC_EVENT_HANDLER"))
command_type = CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER;
else if(!strcasecmp(command_id, "ENABLE_SERVICE_FRESHNESS_CHECKS"))
command_type = CMD_ENABLE_SERVICE_FRESHNESS_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_SERVICE_FRESHNESS_CHECKS"))
command_type = CMD_DISABLE_SERVICE_FRESHNESS_CHECKS;
else if(!strcasecmp(command_id, "ENABLE_HOST_FRESHNESS_CHECKS"))
command_type = CMD_ENABLE_HOST_FRESHNESS_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_HOST_FRESHNESS_CHECKS"))
command_type = CMD_DISABLE_HOST_FRESHNESS_CHECKS;
/*******************************/
/**** HOST-RELATED COMMANDS ****/
/*******************************/
else if(!strcasecmp(command_id, "ADD_HOST_COMMENT"))
command_type = CMD_ADD_HOST_COMMENT;
else if(!strcasecmp(command_id, "DEL_HOST_COMMENT"))
command_type = CMD_DEL_HOST_COMMENT;
else if(!strcasecmp(command_id, "DEL_ALL_HOST_COMMENTS"))
command_type = CMD_DEL_ALL_HOST_COMMENTS;
else if(!strcasecmp(command_id, "DELAY_HOST_NOTIFICATION"))
command_type = CMD_DELAY_HOST_NOTIFICATION;
else if(!strcasecmp(command_id, "ENABLE_HOST_NOTIFICATIONS"))
command_type = CMD_ENABLE_HOST_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_HOST_NOTIFICATIONS"))
command_type = CMD_DISABLE_HOST_NOTIFICATIONS;
else if(!strcasecmp(command_id, "ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST"))
command_type = CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST;
else if(!strcasecmp(command_id, "DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST"))
command_type = CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST;
else if(!strcasecmp(command_id, "ENABLE_HOST_AND_CHILD_NOTIFICATIONS"))
command_type = CMD_ENABLE_HOST_AND_CHILD_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_HOST_AND_CHILD_NOTIFICATIONS"))
command_type = CMD_DISABLE_HOST_AND_CHILD_NOTIFICATIONS;
else if(!strcasecmp(command_id, "ENABLE_HOST_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_HOST_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_HOST_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_HOST_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "ENABLE_HOST_SVC_CHECKS"))
command_type = CMD_ENABLE_HOST_SVC_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_HOST_SVC_CHECKS"))
command_type = CMD_DISABLE_HOST_SVC_CHECKS;
else if(!strcasecmp(command_id, "ENABLE_PASSIVE_HOST_CHECKS"))
command_type = CMD_ENABLE_PASSIVE_HOST_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_PASSIVE_HOST_CHECKS"))
command_type = CMD_DISABLE_PASSIVE_HOST_CHECKS;
else if(!strcasecmp(command_id, "SCHEDULE_HOST_SVC_CHECKS"))
command_type = CMD_SCHEDULE_HOST_SVC_CHECKS;
else if(!strcasecmp(command_id, "SCHEDULE_FORCED_HOST_SVC_CHECKS"))
command_type = CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS;
else if(!strcasecmp(command_id, "ACKNOWLEDGE_HOST_PROBLEM"))
command_type = CMD_ACKNOWLEDGE_HOST_PROBLEM;
else if(!strcasecmp(command_id, "REMOVE_HOST_ACKNOWLEDGEMENT"))
command_type = CMD_REMOVE_HOST_ACKNOWLEDGEMENT;
else if(!strcasecmp(command_id, "ENABLE_HOST_EVENT_HANDLER"))
command_type = CMD_ENABLE_HOST_EVENT_HANDLER;
else if(!strcasecmp(command_id, "DISABLE_HOST_EVENT_HANDLER"))
command_type = CMD_DISABLE_HOST_EVENT_HANDLER;
else if(!strcasecmp(command_id, "ENABLE_HOST_CHECK"))
command_type = CMD_ENABLE_HOST_CHECK;
else if(!strcasecmp(command_id, "DISABLE_HOST_CHECK"))
command_type = CMD_DISABLE_HOST_CHECK;
else if(!strcasecmp(command_id, "SCHEDULE_HOST_CHECK"))
command_type = CMD_SCHEDULE_HOST_CHECK;
else if(!strcasecmp(command_id, "SCHEDULE_FORCED_HOST_CHECK"))
command_type = CMD_SCHEDULE_FORCED_HOST_CHECK;
else if(!strcasecmp(command_id, "SCHEDULE_HOST_DOWNTIME"))
command_type = CMD_SCHEDULE_HOST_DOWNTIME;
else if(!strcasecmp(command_id, "SCHEDULE_HOST_SVC_DOWNTIME"))
command_type = CMD_SCHEDULE_HOST_SVC_DOWNTIME;
else if(!strcasecmp(command_id, "DEL_HOST_DOWNTIME"))
command_type = CMD_DEL_HOST_DOWNTIME;
else if(!strcasecmp(command_id, "DEL_DOWNTIME_BY_HOST_NAME"))
command_type = CMD_DEL_DOWNTIME_BY_HOST_NAME;
else if(!strcasecmp(command_id, "DEL_DOWNTIME_BY_HOSTGROUP_NAME"))
command_type = CMD_DEL_DOWNTIME_BY_HOSTGROUP_NAME;
else if(!strcasecmp(command_id, "DEL_DOWNTIME_BY_START_TIME_COMMENT"))
command_type = CMD_DEL_DOWNTIME_BY_START_TIME_COMMENT;
else if(!strcasecmp(command_id, "ENABLE_HOST_FLAP_DETECTION"))
command_type = CMD_ENABLE_HOST_FLAP_DETECTION;
else if(!strcasecmp(command_id, "DISABLE_HOST_FLAP_DETECTION"))
command_type = CMD_DISABLE_HOST_FLAP_DETECTION;
else if(!strcasecmp(command_id, "START_OBSESSING_OVER_HOST"))
command_type = CMD_START_OBSESSING_OVER_HOST;
else if(!strcasecmp(command_id, "STOP_OBSESSING_OVER_HOST"))
command_type = CMD_STOP_OBSESSING_OVER_HOST;
else if(!strcasecmp(command_id, "CHANGE_HOST_EVENT_HANDLER"))
command_type = CMD_CHANGE_HOST_EVENT_HANDLER;
else if(!strcasecmp(command_id, "CHANGE_HOST_CHECK_COMMAND"))
command_type = CMD_CHANGE_HOST_CHECK_COMMAND;
else if(!strcasecmp(command_id, "CHANGE_NORMAL_HOST_CHECK_INTERVAL"))
command_type = CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL;
else if(!strcasecmp(command_id, "CHANGE_RETRY_HOST_CHECK_INTERVAL"))
command_type = CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL;
else if(!strcasecmp(command_id, "CHANGE_MAX_HOST_CHECK_ATTEMPTS"))
command_type = CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS;
else if(!strcasecmp(command_id, "SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME"))
command_type = CMD_SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME;
else if(!strcasecmp(command_id, "SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME"))
command_type = CMD_SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME;
else if(!strcasecmp(command_id, "SET_HOST_NOTIFICATION_NUMBER"))
command_type = CMD_SET_HOST_NOTIFICATION_NUMBER;
else if(!strcasecmp(command_id, "CHANGE_HOST_CHECK_TIMEPERIOD"))
command_type = CMD_CHANGE_HOST_CHECK_TIMEPERIOD;
else if(!strcasecmp(command_id, "CHANGE_CUSTOM_HOST_VAR"))
command_type = CMD_CHANGE_CUSTOM_HOST_VAR;
else if(!strcasecmp(command_id, "SEND_CUSTOM_HOST_NOTIFICATION"))
command_type = CMD_SEND_CUSTOM_HOST_NOTIFICATION;
else if(!strcasecmp(command_id, "CHANGE_HOST_NOTIFICATION_TIMEPERIOD"))
command_type = CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD;
else if(!strcasecmp(command_id, "CHANGE_HOST_MODATTR"))
command_type = CMD_CHANGE_HOST_MODATTR;
else if (!strcasecmp(command_id,"CLEAR_HOST_FLAPPING_STATE"))
command_type = CMD_CLEAR_HOST_FLAPPING_STATE;
/************************************/
/**** HOSTGROUP-RELATED COMMANDS ****/
/************************************/
else if(!strcasecmp(command_id, "ENABLE_HOSTGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_HOSTGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS;
else if(!strcasecmp(command_id, "ENABLE_HOSTGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_HOSTGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "ENABLE_HOSTGROUP_HOST_CHECKS"))
command_type = CMD_ENABLE_HOSTGROUP_HOST_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_HOSTGROUP_HOST_CHECKS"))
command_type = CMD_DISABLE_HOSTGROUP_HOST_CHECKS;
else if(!strcasecmp(command_id, "ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS"))
command_type = CMD_ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS"))
command_type = CMD_DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS;
else if(!strcasecmp(command_id, "ENABLE_HOSTGROUP_SVC_CHECKS"))
command_type = CMD_ENABLE_HOSTGROUP_SVC_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_HOSTGROUP_SVC_CHECKS"))
command_type = CMD_DISABLE_HOSTGROUP_SVC_CHECKS;
else if(!strcasecmp(command_id, "ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS"))
command_type = CMD_ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS"))
command_type = CMD_DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS;
else if(!strcasecmp(command_id, "SCHEDULE_HOSTGROUP_HOST_DOWNTIME"))
command_type = CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME;
else if(!strcasecmp(command_id, "SCHEDULE_HOSTGROUP_SVC_DOWNTIME"))
command_type = CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME;
/**********************************/
/**** SERVICE-RELATED COMMANDS ****/
/**********************************/
else if(!strcasecmp(command_id, "ADD_SVC_COMMENT"))
command_type = CMD_ADD_SVC_COMMENT;
else if(!strcasecmp(command_id, "DEL_SVC_COMMENT"))
command_type = CMD_DEL_SVC_COMMENT;
else if(!strcasecmp(command_id, "DEL_ALL_SVC_COMMENTS"))
command_type = CMD_DEL_ALL_SVC_COMMENTS;
else if(!strcasecmp(command_id, "SCHEDULE_SVC_CHECK"))
command_type = CMD_SCHEDULE_SVC_CHECK;
else if(!strcasecmp(command_id, "SCHEDULE_FORCED_SVC_CHECK"))
command_type = CMD_SCHEDULE_FORCED_SVC_CHECK;
else if(!strcasecmp(command_id, "ENABLE_SVC_CHECK"))
command_type = CMD_ENABLE_SVC_CHECK;
else if(!strcasecmp(command_id, "DISABLE_SVC_CHECK"))
command_type = CMD_DISABLE_SVC_CHECK;
else if(!strcasecmp(command_id, "ENABLE_PASSIVE_SVC_CHECKS"))
command_type = CMD_ENABLE_PASSIVE_SVC_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_PASSIVE_SVC_CHECKS"))
command_type = CMD_DISABLE_PASSIVE_SVC_CHECKS;
else if(!strcasecmp(command_id, "DELAY_SVC_NOTIFICATION"))
command_type = CMD_DELAY_SVC_NOTIFICATION;
else if(!strcasecmp(command_id, "ENABLE_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "PROCESS_SERVICE_CHECK_RESULT"))
command_type = CMD_PROCESS_SERVICE_CHECK_RESULT;
else if(!strcasecmp(command_id, "PROCESS_HOST_CHECK_RESULT"))
command_type = CMD_PROCESS_HOST_CHECK_RESULT;
else if(!strcasecmp(command_id, "ENABLE_SVC_EVENT_HANDLER"))
command_type = CMD_ENABLE_SVC_EVENT_HANDLER;
else if(!strcasecmp(command_id, "DISABLE_SVC_EVENT_HANDLER"))
command_type = CMD_DISABLE_SVC_EVENT_HANDLER;
else if(!strcasecmp(command_id, "ENABLE_SVC_FLAP_DETECTION"))
command_type = CMD_ENABLE_SVC_FLAP_DETECTION;
else if(!strcasecmp(command_id, "DISABLE_SVC_FLAP_DETECTION"))
command_type = CMD_DISABLE_SVC_FLAP_DETECTION;
else if(!strcasecmp(command_id, "SCHEDULE_SVC_DOWNTIME"))
command_type = CMD_SCHEDULE_SVC_DOWNTIME;
else if(!strcasecmp(command_id, "DEL_SVC_DOWNTIME"))
command_type = CMD_DEL_SVC_DOWNTIME;
else if(!strcasecmp(command_id, "ACKNOWLEDGE_SVC_PROBLEM"))
command_type = CMD_ACKNOWLEDGE_SVC_PROBLEM;
else if(!strcasecmp(command_id, "REMOVE_SVC_ACKNOWLEDGEMENT"))
command_type = CMD_REMOVE_SVC_ACKNOWLEDGEMENT;
else if(!strcasecmp(command_id, "START_OBSESSING_OVER_SVC"))
command_type = CMD_START_OBSESSING_OVER_SVC;
else if(!strcasecmp(command_id, "STOP_OBSESSING_OVER_SVC"))
command_type = CMD_STOP_OBSESSING_OVER_SVC;
else if(!strcasecmp(command_id, "CHANGE_SVC_EVENT_HANDLER"))
command_type = CMD_CHANGE_SVC_EVENT_HANDLER;
else if(!strcasecmp(command_id, "CHANGE_SVC_CHECK_COMMAND"))
command_type = CMD_CHANGE_SVC_CHECK_COMMAND;
else if(!strcasecmp(command_id, "CHANGE_NORMAL_SVC_CHECK_INTERVAL"))
command_type = CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL;
else if(!strcasecmp(command_id, "CHANGE_RETRY_SVC_CHECK_INTERVAL"))
command_type = CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL;
else if(!strcasecmp(command_id, "CHANGE_MAX_SVC_CHECK_ATTEMPTS"))
command_type = CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS;
else if(!strcasecmp(command_id, "SET_SVC_NOTIFICATION_NUMBER"))
command_type = CMD_SET_SVC_NOTIFICATION_NUMBER;
else if(!strcasecmp(command_id, "CHANGE_SVC_CHECK_TIMEPERIOD"))
command_type = CMD_CHANGE_SVC_CHECK_TIMEPERIOD;
else if(!strcasecmp(command_id, "CHANGE_CUSTOM_SVC_VAR"))
command_type = CMD_CHANGE_CUSTOM_SVC_VAR;
else if(!strcasecmp(command_id, "CHANGE_CUSTOM_CONTACT_VAR"))
command_type = CMD_CHANGE_CUSTOM_CONTACT_VAR;
else if(!strcasecmp(command_id, "SEND_CUSTOM_SVC_NOTIFICATION"))
command_type = CMD_SEND_CUSTOM_SVC_NOTIFICATION;
else if(!strcasecmp(command_id, "CHANGE_SVC_NOTIFICATION_TIMEPERIOD"))
command_type = CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD;
else if(!strcasecmp(command_id, "CHANGE_SVC_MODATTR"))
command_type = CMD_CHANGE_SVC_MODATTR;
else if (!strcasecmp(command_id,"CLEAR_SVC_FLAPPING_STATE"))
command_type = CMD_CLEAR_SVC_FLAPPING_STATE;
/***************************************/
/**** SERVICEGROUP-RELATED COMMANDS ****/
/***************************************/
else if(!strcasecmp(command_id, "ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS;
else if(!strcasecmp(command_id, "ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "ENABLE_SERVICEGROUP_HOST_CHECKS"))
command_type = CMD_ENABLE_SERVICEGROUP_HOST_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_SERVICEGROUP_HOST_CHECKS"))
command_type = CMD_DISABLE_SERVICEGROUP_HOST_CHECKS;
else if(!strcasecmp(command_id, "ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS"))
command_type = CMD_ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS"))
command_type = CMD_DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS;
else if(!strcasecmp(command_id, "ENABLE_SERVICEGROUP_SVC_CHECKS"))
command_type = CMD_ENABLE_SERVICEGROUP_SVC_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_SERVICEGROUP_SVC_CHECKS"))
command_type = CMD_DISABLE_SERVICEGROUP_SVC_CHECKS;
else if(!strcasecmp(command_id, "ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS"))
command_type = CMD_ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS;
else if(!strcasecmp(command_id, "DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS"))
command_type = CMD_DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS;
else if(!strcasecmp(command_id, "SCHEDULE_SERVICEGROUP_HOST_DOWNTIME"))
command_type = CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME;
else if(!strcasecmp(command_id, "SCHEDULE_SERVICEGROUP_SVC_DOWNTIME"))
command_type = CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME;
/**********************************/
/**** CONTACT-RELATED COMMANDS ****/
/**********************************/
else if(!strcasecmp(command_id, "ENABLE_CONTACT_HOST_NOTIFICATIONS"))
command_type = CMD_ENABLE_CONTACT_HOST_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_CONTACT_HOST_NOTIFICATIONS"))
command_type = CMD_DISABLE_CONTACT_HOST_NOTIFICATIONS;
else if(!strcasecmp(command_id, "ENABLE_CONTACT_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_CONTACT_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_CONTACT_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_CONTACT_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD"))
command_type = CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD;
else if(!strcasecmp(command_id, "CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD"))
command_type = CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD;
else if(!strcasecmp(command_id, "CHANGE_CONTACT_MODATTR"))
command_type = CMD_CHANGE_CONTACT_MODATTR;
else if(!strcasecmp(command_id, "CHANGE_CONTACT_MODHATTR"))
command_type = CMD_CHANGE_CONTACT_MODHATTR;
else if(!strcasecmp(command_id, "CHANGE_CONTACT_MODSATTR"))
command_type = CMD_CHANGE_CONTACT_MODSATTR;
/***************************************/
/**** CONTACTGROUP-RELATED COMMANDS ****/
/***************************************/
else if(!strcasecmp(command_id, "ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS"))
command_type = CMD_DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS;
else if(!strcasecmp(command_id, "ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS;
else if(!strcasecmp(command_id, "DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS"))
command_type = CMD_DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS;
/**************************/
/****** MISC COMMANDS *****/
/**************************/
else if(!strcasecmp(command_id, "PROCESS_FILE"))
command_type = CMD_PROCESS_FILE;
/****************************/
/****** CUSTOM COMMANDS *****/
/****************************/
else if(command_id[0] == '_')
command_type = CMD_CUSTOM_COMMAND;
/**** UNKNOWN COMMAND ****/
else {
/* log the bad external command */
logit(NSLOG_EXTERNAL_COMMAND | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Unrecognized external command -> %s;%s\n", command_id, args);
/* free memory */
my_free(command_id);
my_free(args);
return CMD_ERROR_UNKNOWN_COMMAND;
}
/* update statistics for external commands */
update_check_stats(EXTERNAL_COMMAND_STATS, time(NULL));
/* log the external command */
asprintf(&temp_buffer, "EXTERNAL COMMAND: %s;%s\n", command_id, args);
if(command_type == CMD_PROCESS_SERVICE_CHECK_RESULT || command_type == CMD_PROCESS_HOST_CHECK_RESULT) {
/* passive checks are logged in checks.c as well, as some my bypass external commands by getting dropped in checkresults dir */
if(log_passive_checks == TRUE)
write_to_all_logs(temp_buffer, NSLOG_PASSIVE_CHECK);
}
else {
if(log_external_commands == TRUE)
write_to_all_logs(temp_buffer, NSLOG_EXTERNAL_COMMAND);
}
my_free(temp_buffer);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_external_command(NEBTYPE_EXTERNALCOMMAND_START, NEBFLAG_NONE, NEBATTR_NONE, command_type, entry_time, command_id, args, NULL);
#endif
/* process the command */
external_command_ret = (process_external_command2(command_type, entry_time, args) == OK) ? CMD_ERROR_OK : CMD_ERROR_FAILURE;
if (external_command_ret != CMD_ERROR_OK) {
logit(NSLOG_EXTERNAL_COMMAND | NSLOG_RUNTIME_WARNING, TRUE, "Error: External command failed -> %s;%s\n", command_id, args);
}
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_external_command(NEBTYPE_EXTERNALCOMMAND_END, NEBFLAG_NONE, NEBATTR_NONE, command_type, entry_time, command_id, args, NULL);
#endif
/* free memory */
my_free(command_id);
my_free(args);
return external_command_ret;
}
const char *cmd_error_strerror(int code) {
switch(code) {
case CMD_ERROR_OK:
return "No error";
case CMD_ERROR_FAILURE:
return "Command failed";
case CMD_ERROR_INTERNAL_ERROR:
return "Internal error";
case CMD_ERROR_UNKNOWN_COMMAND:
return "Unknown or unsupported command";
case CMD_ERROR_MALFORMED_COMMAND:
return "Malformed command";
}
return "Unknown error";
}
/* top-level processor for a single external command */
int process_external_command2(int cmd, time_t entry_time, char *args) {
int ret = OK;
log_debug_info(DEBUGL_FUNCTIONS, 0, "process_external_command2()\n");
log_debug_info(DEBUGL_EXTERNALCOMMANDS, 1, "External Command Type: %d\n", cmd);
log_debug_info(DEBUGL_EXTERNALCOMMANDS, 1, "Command Entry Time: %lu\n", (unsigned long)entry_time);
log_debug_info(DEBUGL_EXTERNALCOMMANDS, 1, "Command Arguments: %s\n", (args == NULL) ? "" : args);
/* how shall we execute the command? */
switch(cmd) {
/***************************/
/***** SYSTEM COMMANDS *****/
/***************************/
case CMD_SHUTDOWN_PROCESS:
case CMD_RESTART_PROCESS:
ret = cmd_signal_process(cmd, args);
break;
case CMD_SAVE_STATE_INFORMATION:
ret = save_state_information(FALSE);
break;
case CMD_READ_STATE_INFORMATION:
ret = read_initial_state_information();
break;
case CMD_ENABLE_NOTIFICATIONS:
enable_all_notifications();
break;
case CMD_DISABLE_NOTIFICATIONS:
disable_all_notifications();
break;
case CMD_START_EXECUTING_SVC_CHECKS:
start_executing_service_checks();
break;
case CMD_STOP_EXECUTING_SVC_CHECKS:
stop_executing_service_checks();
break;
case CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS:
start_accepting_passive_service_checks();
break;
case CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS:
stop_accepting_passive_service_checks();
break;
case CMD_START_OBSESSING_OVER_SVC_CHECKS:
start_obsessing_over_service_checks();
break;
case CMD_STOP_OBSESSING_OVER_SVC_CHECKS:
stop_obsessing_over_service_checks();
break;
case CMD_START_EXECUTING_HOST_CHECKS:
start_executing_host_checks();
break;
case CMD_STOP_EXECUTING_HOST_CHECKS:
stop_executing_host_checks();
break;
case CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS:
start_accepting_passive_host_checks();
break;
case CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS:
stop_accepting_passive_host_checks();
break;
case CMD_START_OBSESSING_OVER_HOST_CHECKS:
start_obsessing_over_host_checks();
break;
case CMD_STOP_OBSESSING_OVER_HOST_CHECKS:
stop_obsessing_over_host_checks();
break;
case CMD_ENABLE_EVENT_HANDLERS:
start_using_event_handlers();
break;
case CMD_DISABLE_EVENT_HANDLERS:
stop_using_event_handlers();
break;
case CMD_ENABLE_FLAP_DETECTION:
enable_flap_detection_routines();
break;
case CMD_DISABLE_FLAP_DETECTION:
disable_flap_detection_routines();
break;
case CMD_ENABLE_SERVICE_FRESHNESS_CHECKS:
enable_service_freshness_checks();
break;
case CMD_DISABLE_SERVICE_FRESHNESS_CHECKS:
disable_service_freshness_checks();
break;
case CMD_ENABLE_HOST_FRESHNESS_CHECKS:
enable_host_freshness_checks();
break;
case CMD_DISABLE_HOST_FRESHNESS_CHECKS:
disable_host_freshness_checks();
break;
case CMD_ENABLE_PERFORMANCE_DATA:
enable_performance_data();
break;
case CMD_DISABLE_PERFORMANCE_DATA:
disable_performance_data();
break;
/***************************/
/***** HOST COMMANDS *****/
/***************************/
case CMD_ENABLE_HOST_CHECK:
case CMD_DISABLE_HOST_CHECK:
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
case CMD_ENABLE_HOST_SVC_CHECKS:
case CMD_DISABLE_HOST_SVC_CHECKS:
case CMD_ENABLE_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOST_NOTIFICATIONS:
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_ENABLE_HOST_AND_CHILD_NOTIFICATIONS:
case CMD_DISABLE_HOST_AND_CHILD_NOTIFICATIONS:
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
case CMD_ENABLE_HOST_FLAP_DETECTION:
case CMD_DISABLE_HOST_FLAP_DETECTION:
case CMD_ENABLE_HOST_EVENT_HANDLER:
case CMD_DISABLE_HOST_EVENT_HANDLER:
case CMD_START_OBSESSING_OVER_HOST:
case CMD_STOP_OBSESSING_OVER_HOST:
case CMD_SET_HOST_NOTIFICATION_NUMBER:
case CMD_SEND_CUSTOM_HOST_NOTIFICATION:
case CMD_CLEAR_HOST_FLAPPING_STATE:
ret = process_host_command(cmd, entry_time, args);
break;
/*****************************/
/***** HOSTGROUP COMMANDS ****/
/*****************************/
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_ENABLE_HOSTGROUP_HOST_CHECKS:
case CMD_DISABLE_HOSTGROUP_HOST_CHECKS:
case CMD_ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS:
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
case CMD_ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS:
ret = process_hostgroup_command(cmd, entry_time, args);
break;
/***************************/
/***** SERVICE COMMANDS ****/
/***************************/
case CMD_ENABLE_SVC_CHECK:
case CMD_DISABLE_SVC_CHECK:
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
case CMD_ENABLE_SVC_NOTIFICATIONS:
case CMD_DISABLE_SVC_NOTIFICATIONS:
case CMD_ENABLE_SVC_FLAP_DETECTION:
case CMD_DISABLE_SVC_FLAP_DETECTION:
case CMD_ENABLE_SVC_EVENT_HANDLER:
case CMD_DISABLE_SVC_EVENT_HANDLER:
case CMD_START_OBSESSING_OVER_SVC:
case CMD_STOP_OBSESSING_OVER_SVC:
case CMD_SET_SVC_NOTIFICATION_NUMBER:
case CMD_SEND_CUSTOM_SVC_NOTIFICATION:
case CMD_CLEAR_SVC_FLAPPING_STATE:
ret = process_service_command(cmd, entry_time, args);
break;
/********************************/
/***** SERVICEGROUP COMMANDS ****/
/********************************/
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_HOST_CHECKS:
case CMD_DISABLE_SERVICEGROUP_HOST_CHECKS:
case CMD_ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS:
ret = process_servicegroup_command(cmd, entry_time, args);
break;
/**********************************/
/**** CONTACT-RELATED COMMANDS ****/
/**********************************/
case CMD_ENABLE_CONTACT_HOST_NOTIFICATIONS:
case CMD_DISABLE_CONTACT_HOST_NOTIFICATIONS:
case CMD_ENABLE_CONTACT_SVC_NOTIFICATIONS:
case CMD_DISABLE_CONTACT_SVC_NOTIFICATIONS:
ret = process_contact_command(cmd, entry_time, args);
break;
/***************************************/
/**** CONTACTGROUP-RELATED COMMANDS ****/
/***************************************/
case CMD_ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS:
ret = process_contactgroup_command(cmd, entry_time, args);
break;
/***************************/
/**** UNSORTED COMMANDS ****/
/***************************/
case CMD_ADD_HOST_COMMENT:
case CMD_ADD_SVC_COMMENT:
ret= cmd_add_comment(cmd, entry_time, args);
break;
case CMD_DEL_HOST_COMMENT:
case CMD_DEL_SVC_COMMENT:
ret = cmd_delete_comment(cmd, args);
break;
case CMD_DELAY_HOST_NOTIFICATION:
case CMD_DELAY_SVC_NOTIFICATION:
ret = cmd_delay_notification(cmd, args);
break;
case CMD_SCHEDULE_SVC_CHECK:
case CMD_SCHEDULE_FORCED_SVC_CHECK:
ret =cmd_schedule_check(cmd, args);
break;
case CMD_SCHEDULE_HOST_SVC_CHECKS:
case CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS:
ret = cmd_schedule_check(cmd, args);
break;
case CMD_DEL_ALL_HOST_COMMENTS:
case CMD_DEL_ALL_SVC_COMMENTS:
ret = cmd_delete_all_comments(cmd, args);
break;
case CMD_PROCESS_SERVICE_CHECK_RESULT:
ret = cmd_process_service_check_result(cmd, entry_time, args);
break;
case CMD_PROCESS_HOST_CHECK_RESULT:
ret = cmd_process_host_check_result(cmd, entry_time, args);
break;
case CMD_ACKNOWLEDGE_HOST_PROBLEM:
case CMD_ACKNOWLEDGE_SVC_PROBLEM:
ret = cmd_acknowledge_problem(cmd, args);
break;
case CMD_REMOVE_HOST_ACKNOWLEDGEMENT:
case CMD_REMOVE_SVC_ACKNOWLEDGEMENT:
ret = cmd_remove_acknowledgement(cmd, args);
break;
case CMD_SCHEDULE_HOST_DOWNTIME:
case CMD_SCHEDULE_SVC_DOWNTIME:
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
case CMD_SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME:
case CMD_SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME:
ret = cmd_schedule_downtime(cmd, entry_time, args);
break;
case CMD_DEL_HOST_DOWNTIME:
case CMD_DEL_SVC_DOWNTIME:
ret = cmd_delete_downtime(cmd, args);
break;
case CMD_DEL_DOWNTIME_BY_HOST_NAME:
ret = cmd_delete_downtime_by_host_name(cmd, args);
break;
case CMD_DEL_DOWNTIME_BY_HOSTGROUP_NAME:
ret = cmd_delete_downtime_by_hostgroup_name(cmd, args);
break;
case CMD_DEL_DOWNTIME_BY_START_TIME_COMMENT:
ret = cmd_delete_downtime_by_start_time_comment(cmd, args);
break;
case CMD_SCHEDULE_HOST_CHECK:
case CMD_SCHEDULE_FORCED_HOST_CHECK:
ret = cmd_schedule_check(cmd, args);
break;
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_EVENT_HANDLER:
case CMD_CHANGE_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_CHECK_COMMAND:
case CMD_CHANGE_SVC_CHECK_COMMAND:
case CMD_CHANGE_HOST_CHECK_TIMEPERIOD:
case CMD_CHANGE_SVC_CHECK_TIMEPERIOD:
case CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD:
ret = cmd_change_object_char_var(cmd, args);
break;
case CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL:
case CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL:
case CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL:
case CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL:
case CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS:
case CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS:
case CMD_CHANGE_HOST_MODATTR:
case CMD_CHANGE_SVC_MODATTR:
case CMD_CHANGE_CONTACT_MODATTR:
case CMD_CHANGE_CONTACT_MODHATTR:
case CMD_CHANGE_CONTACT_MODSATTR:
ret = cmd_change_object_int_var(cmd, args);
break;
case CMD_CHANGE_CUSTOM_HOST_VAR:
case CMD_CHANGE_CUSTOM_SVC_VAR:
case CMD_CHANGE_CUSTOM_CONTACT_VAR:
ret = cmd_change_object_custom_var(cmd, args);
break;
/***********************/
/**** MISC COMMANDS ****/
/***********************/
case CMD_PROCESS_FILE:
ret = cmd_process_external_commands_from_file(cmd, args);
break;
/*************************/
/**** CUSTOM COMMANDS ****/
/*************************/
case CMD_CUSTOM_COMMAND:
/* custom commands aren't handled internally by Nagios, but may be by NEB modules */
break;
default:
return CMD_ERROR_UNKNOWN_COMMAND;
break;
}
return ret;
}
/* processes an external host command */
int process_host_command(int cmd, time_t entry_time, char *args) {
char *host_name = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
char *str = NULL;
char *buf[2] = {NULL, NULL};
char *author, *comment;
int intval = 0;
printf("ARGS: %s\n", args);
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* find the host */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
switch(cmd) {
case CMD_ENABLE_HOST_NOTIFICATIONS:
enable_host_notifications(temp_host);
break;
case CMD_DISABLE_HOST_NOTIFICATIONS:
disable_host_notifications(temp_host);
break;
case CMD_ENABLE_HOST_AND_CHILD_NOTIFICATIONS:
enable_and_propagate_notifications(temp_host, 0, TRUE, TRUE, FALSE);
break;
case CMD_DISABLE_HOST_AND_CHILD_NOTIFICATIONS:
disable_and_propagate_notifications(temp_host, 0, TRUE, TRUE, FALSE);
break;
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
enable_and_propagate_notifications(temp_host, 0, FALSE, TRUE, TRUE);
break;
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
disable_and_propagate_notifications(temp_host, 0, FALSE, TRUE, TRUE);
break;
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
if(cmd == CMD_ENABLE_HOST_SVC_NOTIFICATIONS)
enable_service_notifications(temp_service);
else
disable_service_notifications(temp_service);
}
break;
case CMD_ENABLE_HOST_SVC_CHECKS:
case CMD_DISABLE_HOST_SVC_CHECKS:
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
if(cmd == CMD_ENABLE_HOST_SVC_CHECKS)
enable_service_checks(temp_service);
else
disable_service_checks(temp_service);
}
break;
case CMD_ENABLE_HOST_CHECK:
enable_host_checks(temp_host);
break;
case CMD_DISABLE_HOST_CHECK:
disable_host_checks(temp_host);
break;
case CMD_ENABLE_HOST_EVENT_HANDLER:
enable_host_event_handler(temp_host);
break;
case CMD_DISABLE_HOST_EVENT_HANDLER:
disable_host_event_handler(temp_host);
break;
case CMD_ENABLE_HOST_FLAP_DETECTION:
enable_host_flap_detection(temp_host);
break;
case CMD_DISABLE_HOST_FLAP_DETECTION:
disable_host_flap_detection(temp_host);
break;
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
enable_passive_host_checks(temp_host);
break;
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
disable_passive_host_checks(temp_host);
break;
case CMD_START_OBSESSING_OVER_HOST:
start_obsessing_over_host(temp_host);
break;
case CMD_STOP_OBSESSING_OVER_HOST:
stop_obsessing_over_host(temp_host);
break;
case CMD_SET_HOST_NOTIFICATION_NUMBER:
if((str = my_strtok(NULL, ";"))) {
intval = atoi(str);
set_host_notification_number(temp_host, intval);
}
break;
case CMD_CLEAR_HOST_FLAPPING_STATE:
clear_host_flapping_state(temp_host);
break;
case CMD_SEND_CUSTOM_HOST_NOTIFICATION:
if((str = my_strtok(NULL, ";")))
intval = atoi(str);
str = my_strtok(NULL, ";");
if(str)
buf[0] = strdup(str);
str = my_strtok(NULL, ";");
if(str)
buf[1] = strdup(str);
if(buf[0] && buf[1])
host_notification(temp_host, NOTIFICATION_CUSTOM, buf[0], buf[1], intval);
break;
default:
break;
}
if ((author = my_strtok(NULL, ";")) != NULL) {
if ((comment = my_strtok(NULL, ";")) != NULL) {
time_t current_time = time(NULL);
add_new_host_comment(USER_COMMENT, host_name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
}
}
return OK;
}
/* processes an external hostgroup command */
int process_hostgroup_command(int cmd, time_t entry_time, char *args) {
char *hostgroup_name = NULL;
char *author = NULL, *comment = NULL;
hostgroup *temp_hostgroup = NULL;
hostsmember *temp_member = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
time_t current_time = time(NULL);
/* get the hostgroup name */
if((hostgroup_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* find the hostgroup */
if((temp_hostgroup = find_hostgroup(hostgroup_name)) == NULL)
return ERROR;
if ((author = my_strtok(NULL, ";")) != NULL)
comment = my_strtok(NULL, ";");
/* loop through all hosts in the hostgroup */
for(temp_member = temp_hostgroup->members; temp_member != NULL; temp_member = temp_member->next) {
if((temp_host = (host *)temp_member->host_ptr) == NULL)
continue;
switch(cmd) {
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
enable_host_notifications(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
disable_host_notifications(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_ENABLE_HOSTGROUP_HOST_CHECKS:
enable_host_checks(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_HOSTGROUP_HOST_CHECKS:
disable_host_checks(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_ENABLE_HOSTGROUP_PASSIVE_HOST_CHECKS:
enable_passive_host_checks(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_HOSTGROUP_PASSIVE_HOST_CHECKS:
disable_passive_host_checks(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
default:
/* loop through all services on the host */
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
switch(cmd) {
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
enable_service_notifications(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_host->name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
disable_service_notifications(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_host->name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
enable_service_checks(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_host->name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
disable_service_checks(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_host->name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS:
enable_passive_service_checks(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_host->name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS:
disable_passive_service_checks(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_host->name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
default:
break;
}
}
break;
}
}
return OK;
}
/* processes an external service command */
int process_service_command(int cmd, time_t entry_time, char *args) {
char *host_name = NULL;
char *svc_description = NULL;
service *temp_service = NULL;
char *str = NULL;
char *buf[2] = {NULL, NULL};
char *author, *comment;
int intval = 0;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* get the service description */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* find the service */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
switch(cmd) {
case CMD_ENABLE_SVC_NOTIFICATIONS:
enable_service_notifications(temp_service);
break;
case CMD_DISABLE_SVC_NOTIFICATIONS:
disable_service_notifications(temp_service);
break;
case CMD_ENABLE_SVC_CHECK:
enable_service_checks(temp_service);
break;
case CMD_DISABLE_SVC_CHECK:
disable_service_checks(temp_service);
break;
case CMD_ENABLE_SVC_EVENT_HANDLER:
enable_service_event_handler(temp_service);
break;
case CMD_DISABLE_SVC_EVENT_HANDLER:
disable_service_event_handler(temp_service);
break;
case CMD_ENABLE_SVC_FLAP_DETECTION:
enable_service_flap_detection(temp_service);
break;
case CMD_DISABLE_SVC_FLAP_DETECTION:
disable_service_flap_detection(temp_service);
break;
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
enable_passive_service_checks(temp_service);
break;
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
disable_passive_service_checks(temp_service);
break;
case CMD_START_OBSESSING_OVER_SVC:
start_obsessing_over_service(temp_service);
break;
case CMD_STOP_OBSESSING_OVER_SVC:
stop_obsessing_over_service(temp_service);
break;
case CMD_SET_SVC_NOTIFICATION_NUMBER:
if((str = my_strtok(NULL, ";"))) {
intval = atoi(str);
set_service_notification_number(temp_service, intval);
}
break;
case CMD_CLEAR_SVC_FLAPPING_STATE:
clear_service_flapping_state(temp_service);
break;
case CMD_SEND_CUSTOM_SVC_NOTIFICATION:
if((str = my_strtok(NULL, ";")))
intval = atoi(str);
str = my_strtok(NULL, ";");
if(str)
buf[0] = strdup(str);
str = my_strtok(NULL, ";");
if(str)
buf[1] = strdup(str);
if(buf[0] && buf[1])
service_notification(temp_service, NOTIFICATION_CUSTOM, buf[0], buf[1], intval);
break;
default:
break;
}
if ((author = my_strtok(NULL, ";")) != NULL) {
if ((comment = my_strtok(NULL, ";")) != NULL) {
time_t current_time = time(NULL);
add_new_service_comment(USER_COMMENT, host_name, svc_description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
}
}
return OK;
}
/* processes an external servicegroup command */
int process_servicegroup_command(int cmd, time_t entry_time, char *args) {
char *servicegroup_name = NULL;
char *author = NULL, *comment = NULL;
servicegroup *temp_servicegroup = NULL;
servicesmember *temp_member = NULL;
host *temp_host = NULL;
host *last_host = NULL;
service *temp_service = NULL;
time_t current_time = time(NULL);
/* get the servicegroup name */
if((servicegroup_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* find the servicegroup */
if((temp_servicegroup = find_servicegroup(servicegroup_name)) == NULL)
return ERROR;
if ((author = my_strtok(NULL, ";")) != NULL)
comment = my_strtok(NULL, ";");
switch(cmd) {
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS:
/* loop through all servicegroup members */
for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
temp_service = find_service(temp_member->host_name, temp_member->service_description);
if(temp_service == NULL)
continue;
switch(cmd) {
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
enable_service_notifications(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_member->host_name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
disable_service_notifications(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_member->host_name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
enable_service_checks(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_member->host_name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
disable_service_checks(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_member->host_name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS:
enable_passive_service_checks(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_member->host_name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS:
disable_passive_service_checks(temp_service);
if (comment)
add_new_service_comment(USER_COMMENT, temp_member->host_name, temp_service->description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
default:
break;
}
}
break;
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_HOST_CHECKS:
case CMD_DISABLE_SERVICEGROUP_HOST_CHECKS:
case CMD_ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
/* loop through all hosts that have services belonging to the servicegroup */
last_host = NULL;
for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
if((temp_host = find_host(temp_member->host_name)) == NULL)
continue;
if(temp_host == last_host)
continue;
switch(cmd) {
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
enable_host_notifications(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
disable_host_notifications(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_ENABLE_SERVICEGROUP_HOST_CHECKS:
enable_host_checks(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_SERVICEGROUP_HOST_CHECKS:
disable_host_checks(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_ENABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
enable_passive_host_checks(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
case CMD_DISABLE_SERVICEGROUP_PASSIVE_HOST_CHECKS:
disable_passive_host_checks(temp_host);
if (comment)
add_new_host_comment(USER_COMMENT, temp_host->name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
break;
default:
break;
}
last_host = temp_host;
}
break;
default:
break;
}
return OK;
}
/* processes an external contact command */
int process_contact_command(int cmd, time_t entry_time, char *args) {
char *contact_name = NULL;
contact *temp_contact = NULL;
/* get the contact name */
if((contact_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* find the contact */
if((temp_contact = find_contact(contact_name)) == NULL)
return ERROR;
switch(cmd) {
case CMD_ENABLE_CONTACT_HOST_NOTIFICATIONS:
enable_contact_host_notifications(temp_contact);
break;
case CMD_DISABLE_CONTACT_HOST_NOTIFICATIONS:
disable_contact_host_notifications(temp_contact);
break;
case CMD_ENABLE_CONTACT_SVC_NOTIFICATIONS:
enable_contact_service_notifications(temp_contact);
break;
case CMD_DISABLE_CONTACT_SVC_NOTIFICATIONS:
disable_contact_service_notifications(temp_contact);
break;
default:
break;
}
return OK;
}
/* processes an external contactgroup command */
int process_contactgroup_command(int cmd, time_t entry_time, char *args) {
char *contactgroup_name = NULL;
contactgroup *temp_contactgroup = NULL;
contactsmember *temp_member = NULL;
contact *temp_contact = NULL;
/* get the contactgroup name */
if((contactgroup_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* find the contactgroup */
if((temp_contactgroup = find_contactgroup(contactgroup_name)) == NULL)
return ERROR;
switch(cmd) {
case CMD_ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS:
/* loop through all contactgroup members */
for(temp_member = temp_contactgroup->members; temp_member != NULL; temp_member = temp_member->next) {
if((temp_contact = temp_member->contact_ptr) == NULL)
continue;
switch(cmd) {
case CMD_ENABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
enable_contact_host_notifications(temp_contact);
break;
case CMD_DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS:
disable_contact_host_notifications(temp_contact);
break;
case CMD_ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS:
enable_contact_service_notifications(temp_contact);
break;
case CMD_DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS:
disable_contact_service_notifications(temp_contact);
break;
default:
break;
}
}
break;
default:
break;
}
return OK;
}
/******************************************************************/
/*************** EXTERNAL COMMAND IMPLEMENTATIONS ****************/
/******************************************************************/
/* adds a host or service comment to the status log */
int cmd_add_comment(int cmd, time_t entry_time, char *args) {
char *temp_ptr = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
char *host_name = NULL;
char *svc_description = NULL;
char *user = NULL;
char *comment_data = NULL;
int persistent = 0;
int result = 0;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* if we're adding a service comment... */
if(cmd == CMD_ADD_SVC_COMMENT) {
/* get the service description */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
}
/* else verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* get the persistent flag */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
persistent = atoi(temp_ptr);
if(persistent > 1)
persistent = 1;
else if(persistent < 0)
persistent = 0;
/* get the name of the user who entered the comment */
if((user = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* get the comment */
if((comment_data = my_strtok(NULL, "\n")) == NULL)
return ERROR;
/* add the comment */
result = add_new_comment((cmd == CMD_ADD_HOST_COMMENT) ? HOST_COMMENT : SERVICE_COMMENT, USER_COMMENT, host_name, svc_description, entry_time, user, comment_data, persistent, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
if(result < 0)
return ERROR;
return OK;
}
/* removes a host or service comment from the status log */
int cmd_delete_comment(int cmd, char *args) {
unsigned long comment_id = 0L;
/* get the comment id we should delete */
if((comment_id = strtoul(args, NULL, 10)) == 0)
return ERROR;
/* delete the specified comment */
if(cmd == CMD_DEL_HOST_COMMENT)
delete_host_comment(comment_id);
else
delete_service_comment(comment_id);
return OK;
}
/* removes all comments associated with a host or service from the status log */
int cmd_delete_all_comments(int cmd, char *args) {
service *temp_service = NULL;
host *temp_host = NULL;
char *host_name = NULL;
char *svc_description = NULL;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* if we're deleting service comments... */
if(cmd == CMD_DEL_ALL_SVC_COMMENTS) {
/* get the service description */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
}
/* else verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* delete comments */
delete_all_comments((cmd == CMD_DEL_ALL_HOST_COMMENTS) ? HOST_COMMENT : SERVICE_COMMENT, host_name, svc_description);
return OK;
}
/* delays a host or service notification for given number of minutes */
int cmd_delay_notification(int cmd, char *args) {
char *temp_ptr = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
char *host_name = NULL;
char *svc_description = NULL;
char *author, *comment;
time_t delay_time = 0L;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* if this is a service notification delay... */
if(cmd == CMD_DELAY_SVC_NOTIFICATION) {
/* get the service description */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
}
/* else verify that the host is valid */
else {
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
}
/* get the time that we should delay until... */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
delay_time = strtoul(temp_ptr, NULL, 10);
/* delay the next notification... */
if(cmd == CMD_DELAY_SVC_NOTIFICATION)
temp_service->next_notification = delay_time;
else
temp_host->next_notification = delay_time;
if ((author = my_strtok(NULL, ";")) != NULL) {
if ((comment = my_strtok(NULL, ";")) != NULL) {
time_t current_time = time(NULL);
if(cmd == CMD_DELAY_SVC_NOTIFICATION)
add_new_service_comment(USER_COMMENT, host_name, svc_description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
else
add_new_host_comment(USER_COMMENT, host_name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
}
}
return OK;
}
/* schedules a host check at a particular time */
int cmd_schedule_check(int cmd, char *args) {
char *temp_ptr = NULL;
host *temp_host = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
char *host_name = NULL;
char *svc_description = NULL;
char *author, *comment;
time_t delay_time = 0L;
/* get the host name */
if((host_name = my_strtok_with_free(args, ";", FALSE)) == NULL)
return ERROR;
if(cmd == CMD_SCHEDULE_HOST_CHECK || cmd == CMD_SCHEDULE_FORCED_HOST_CHECK || cmd == CMD_SCHEDULE_HOST_SVC_CHECKS || cmd == CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS) {
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
}
else {
/* get the service description */
if((svc_description = my_strtok_with_free(NULL, ";", FALSE)) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL) {
temp_ptr = my_strtok_with_free(NULL, ";", TRUE);
return ERROR;
}
}
/* get the next check time */
if((temp_ptr = my_strtok_with_free(NULL, ";", FALSE)) == NULL) {
temp_ptr = my_strtok_with_free(NULL, ";", TRUE);
return ERROR;
}
delay_time = strtoul(temp_ptr, NULL, 10);
/* schedule the host check */
if(cmd == CMD_SCHEDULE_HOST_CHECK || cmd == CMD_SCHEDULE_FORCED_HOST_CHECK)
schedule_host_check(temp_host, delay_time, (cmd == CMD_SCHEDULE_FORCED_HOST_CHECK) ? CHECK_OPTION_FORCE_EXECUTION : CHECK_OPTION_NONE);
/* schedule service checks */
else if(cmd == CMD_SCHEDULE_HOST_SVC_CHECKS || cmd == CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS) {
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
schedule_service_check(temp_service, delay_time, (cmd == CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS) ? CHECK_OPTION_FORCE_EXECUTION : CHECK_OPTION_NONE);
}
}
else
schedule_service_check(temp_service, delay_time, (cmd == CMD_SCHEDULE_FORCED_SVC_CHECK) ? CHECK_OPTION_FORCE_EXECUTION : CHECK_OPTION_NONE);
if ((author = my_strtok_with_free(NULL, ";", FALSE)) != NULL) {
if ((comment = my_strtok_with_free(NULL, ";", FALSE)) != NULL) {
time_t current_time = time(NULL);
if (svc_description)
add_new_service_comment(USER_COMMENT, host_name, svc_description, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
else
add_new_host_comment(USER_COMMENT, host_name, current_time, author, comment, FALSE, COMMENTSOURCE_EXTERNAL, FALSE, (time_t)0, NULL);
}
}
temp_ptr = my_strtok_with_free(NULL, ";", TRUE);
return OK;
}
/* schedules all service checks on a host for a particular time */
int cmd_schedule_host_service_checks(int cmd, char *args, int force) {
char *temp_ptr = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
host *temp_host = NULL;
char *host_name = NULL;
time_t delay_time = 0L;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* get the next check time */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL)
return ERROR;
delay_time = strtoul(temp_ptr, NULL, 10);
/* reschedule all services on the specified host */
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
schedule_service_check(temp_service, delay_time, (force == TRUE) ? CHECK_OPTION_FORCE_EXECUTION : CHECK_OPTION_NONE);
}
return OK;
}
/* schedules a program shutdown or restart */
int cmd_signal_process(int cmd, char *args) {
time_t scheduled_time = 0L;
char *temp_ptr = NULL;
int event_signal = 0;
/* get the time to schedule the event */
if((temp_ptr = my_strtok(args, "\n")) == NULL)
scheduled_time = 0L;
else
scheduled_time = strtoul(temp_ptr, NULL, 10);
/* what signal are we sending? */
event_signal = EVENT_PROGRAM_RESTART;
if (cmd == CMD_SHUTDOWN_PROCESS)
event_signal = EVENT_PROGRAM_SHUTDOWN;
/* add a scheduled program shutdown or restart to the event list */
if (!schedule_new_event(event_signal, TRUE, scheduled_time, FALSE, 0, NULL, FALSE, NULL, NULL, 0))
return ERROR;
return OK;
}
/* processes results of an external service check */
int cmd_process_service_check_result(int cmd, time_t check_time, char *args) {
char *temp_ptr = NULL;
char *host_name = NULL;
char *svc_description = NULL;
int return_code = 0;
char *output = NULL;
int result = 0;
/* get the host name */
if((temp_ptr = my_strtok(args, ";")) == NULL)
return ERROR;
host_name = (char *)strdup(temp_ptr);
/* get the service description */
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(host_name);
return ERROR;
}
svc_description = (char *)strdup(temp_ptr);
/* get the service check return code */
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(host_name);
my_free(svc_description);
return ERROR;
}
return_code = atoi(temp_ptr);
/* get the plugin output (may be empty) */
temp_ptr = my_strtok(NULL, "\n");
/* Interpolate backslash and newline escape sequences to the literal
* characters they represent. This converts to the format we use internally
* so we don't have to worry about different representations later. */
output = (temp_ptr) ? unescape_check_result_output(temp_ptr) : strdup("");
/* submit the passive check result */
result = process_passive_service_check(check_time, host_name, svc_description, return_code, output);
/* free memory */
my_free(host_name);
my_free(svc_description);
my_free(output);
return result;
}
/* submits a passive service check result for later processing */
int process_passive_service_check(time_t check_time, char *host_name, char *svc_description, int return_code, char *output) {
check_result cr;
host *temp_host = NULL;
service *temp_service = NULL;
struct timeval tv;
/* skip this service check result if we aren't accepting passive service checks */
if(accept_passive_service_checks == FALSE)
return ERROR;
/* make sure we have all required data */
if(host_name == NULL || svc_description == NULL || output == NULL)
return ERROR;
/* find the host by its name or address */
temp_host = find_host_by_name_or_address(host_name);
/* we couldn't find the host */
if(temp_host == NULL) {
log_debug_info(DEBUGL_CHECKS, 0,
"Passive check result was received for service '%s' on host '%s', but the host could not be found!\n",
svc_description, host_name);
logit(NSLOG_RUNTIME_WARNING, TRUE,
"Warning: Passive check result was received for service '%s' on host '%s', but the host could not be found!\n",
svc_description, host_name);
return ERROR;
}
/* now the service */
temp_service = find_service(temp_host->name, svc_description);
/* we couldn't find the service */
if(temp_service == NULL) {
log_debug_info(DEBUGL_CHECKS, 0,
"Passive check result was received for service '%s' on host '%s', but the service could not be found!\n",
svc_description, host_name);
logit(NSLOG_RUNTIME_WARNING, TRUE,
"Warning: Passive check result was received for service '%s' on host '%s', but the service could not be found!\n",
svc_description, host_name);
return ERROR;
}
/* skip this is we aren't accepting passive checks for this service */
if(temp_service->accept_passive_checks == FALSE) {
log_debug_info(DEBUGL_CHECKS, 0, "Service '%s' on host '%s' is not accepting passive checks, bailing\n", host_name, svc_description);
return ERROR;
}
memset(&cr, 0, sizeof(cr));
cr.exited_ok = 1;
cr.check_type = CHECK_TYPE_PASSIVE;
cr.host_name = temp_host->name;
cr.service_description = temp_service->description;
cr.output = output;
cr.start_time.tv_sec = cr.finish_time.tv_sec = check_time;
cr.source = command_worker.source_name;
/* save the return code and make sure it's sane */
cr.return_code = return_code;
if (cr.return_code < 0 || cr.return_code > 3)
cr.return_code = STATE_UNKNOWN;
/* calculate latency */
gettimeofday(&tv, NULL);
cr.latency = (double)((double)(tv.tv_sec - check_time) + (double)(tv.tv_usec / 1000.0) / 1000.0);
if(cr.latency < 0.0)
cr.latency = 0.0;
return handle_async_service_check_result(temp_service, &cr);
}
/* process passive host check result */
int cmd_process_host_check_result(int cmd, time_t check_time, char *args) {
char *temp_ptr = NULL;
char *host_name = NULL;
int return_code = 0;
char *output = NULL;
int result = 0;
/* get the host name */
if((temp_ptr = my_strtok(args, ";")) == NULL)
return ERROR;
host_name = (char *)strdup(temp_ptr);
/* get the host check return code */
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(host_name);
return ERROR;
}
return_code = atoi(temp_ptr);
/* get the plugin output (may be empty) */
temp_ptr = my_strtok(NULL, "\n");
/* Interpolate backslash and newline escape sequences to the literal
* characters they represent. This converts to the format we use internally
* so we don't have to worry about different representations later. */
output = (temp_ptr) ? unescape_check_result_output(temp_ptr) : strdup("");
/* submit the check result */
result = process_passive_host_check(check_time, host_name, return_code, output);
/* free memory */
my_free(host_name);
my_free(output);
return result;
}
/* process passive host check result */
int process_passive_host_check(time_t check_time, char *host_name, int return_code, char *output) {
check_result cr;
host *temp_host = NULL;
struct timeval tv;
/* skip this host check result if we aren't accepting passive host checks */
if(accept_passive_service_checks == FALSE)
return ERROR;
/* make sure we have all required data */
if(host_name == NULL || output == NULL)
return ERROR;
/* make sure we have a reasonable return code */
if(return_code < 0 || return_code > 2)
return ERROR;
/* find the host by its name or address */
temp_host = find_host_by_name_or_address(host_name);
/* we couldn't find the host */
if(temp_host == NULL) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Passive check result was received for host '%s', but the host could not be found!\n", host_name);
log_debug_info(DEBUGL_CHECKS, 0, "Passive check result was received for host '%s', but the host could not be found!\n", host_name);
return ERROR;
}
/* skip this is we aren't accepting passive checks for this host */
if(temp_host->accept_passive_checks == FALSE) {
log_debug_info(DEBUGL_CHECKS, 0, "Host '%s' is not accepting passive checks, bailing\n", host_name);
return ERROR;
}
memset(&cr, 0, sizeof(cr));
cr.exited_ok = 1;
cr.check_type = CHECK_TYPE_PASSIVE;
cr.host_name = temp_host->name;
cr.output = output;
cr.start_time.tv_sec = cr.finish_time.tv_sec = check_time;
cr.source = command_worker.source_name;
cr.return_code = return_code;
/* calculate latency */
gettimeofday(&tv, NULL);
cr.latency = (double)((double)(tv.tv_sec - check_time) + (double)(tv.tv_usec / 1000.0) / 1000.0);
if(cr.latency < 0.0)
cr.latency = 0.0;
handle_async_host_check_result(temp_host, &cr);
return OK;
}
/* acknowledges a host or service problem */
int cmd_acknowledge_problem(int cmd, char *args) {
service *temp_service = NULL;
host *temp_host = NULL;
char *host_name = NULL;
char *svc_description = NULL;
char *ack_author = NULL;
char *ack_data = NULL;
char *temp_ptr = NULL;
int type = ACKNOWLEDGEMENT_NORMAL;
int notify = TRUE;
int persistent = TRUE;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* this is a service acknowledgement */
if(cmd == CMD_ACKNOWLEDGE_SVC_PROBLEM) {
/* get the service name */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(temp_host->name, svc_description)) == NULL)
return ERROR;
}
/* get the type */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
type = atoi(temp_ptr);
/* get the notification option */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
notify = (atoi(temp_ptr) > 0) ? TRUE : FALSE;
/* get the persistent option */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
persistent = (atoi(temp_ptr) > 0) ? TRUE : FALSE;
/* get the acknowledgement author */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
ack_author = (char *)strdup(temp_ptr);
/* get the acknowledgement data */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
my_free(ack_author);
return ERROR;
}
ack_data = (char *)strdup(temp_ptr);
/* acknowledge the host problem */
if(cmd == CMD_ACKNOWLEDGE_HOST_PROBLEM)
acknowledge_host_problem(temp_host, ack_author, ack_data, type, notify, persistent);
/* acknowledge the service problem */
else
acknowledge_service_problem(temp_service, ack_author, ack_data, type, notify, persistent);
/* free memory */
my_free(ack_author);
my_free(ack_data);
return OK;
}
/* removes a host or service acknowledgement */
int cmd_remove_acknowledgement(int cmd, char *args) {
service *temp_service = NULL;
host *temp_host = NULL;
char *host_name = NULL;
char *svc_description = NULL;
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* we are removing a service acknowledgement */
if(cmd == CMD_REMOVE_SVC_ACKNOWLEDGEMENT) {
/* get the service name */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(temp_host->name, svc_description)) == NULL)
return ERROR;
}
/* acknowledge the host problem */
if(cmd == CMD_REMOVE_HOST_ACKNOWLEDGEMENT)
remove_host_acknowledgement(temp_host);
/* acknowledge the service problem */
else
remove_service_acknowledgement(temp_service);
return OK;
}
/* schedules downtime for a specific host or service */
int cmd_schedule_downtime(int cmd, time_t entry_time, char *args) {
servicesmember *temp_servicesmember = NULL;
service *temp_service = NULL;
host *temp_host = NULL;
host *last_host = NULL;
hostgroup *temp_hostgroup = NULL;
hostsmember *temp_hgmember = NULL;
servicegroup *temp_servicegroup = NULL;
servicesmember *temp_sgmember = NULL;
char *host_name = NULL;
char *hostgroup_name = NULL;
char *servicegroup_name = NULL;
char *svc_description = NULL;
char *temp_ptr = NULL;
time_t start_time = 0L;
time_t end_time = 0L;
int fixed = 0;
unsigned long triggered_by = 0L;
unsigned long duration = 0L;
char *author = NULL;
char *comment_data = NULL;
unsigned long downtime_id = 0L;
if(cmd == CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME) {
/* get the hostgroup name */
if((hostgroup_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the hostgroup is valid */
if((temp_hostgroup = find_hostgroup(hostgroup_name)) == NULL)
return ERROR;
}
else if(cmd == CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME) {
/* get the servicegroup name */
if((servicegroup_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the servicegroup is valid */
if((temp_servicegroup = find_servicegroup(servicegroup_name)) == NULL)
return ERROR;
}
else {
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
/* this is a service downtime */
if(cmd == CMD_SCHEDULE_SVC_DOWNTIME) {
/* get the service name */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(temp_host->name, svc_description)) == NULL)
return ERROR;
}
}
/* get the start time */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
start_time = (time_t)strtoul(temp_ptr, NULL, 10);
/* get the end time */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
end_time = (time_t)strtoul(temp_ptr, NULL, 10);
/* get the fixed flag */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
fixed = atoi(temp_ptr);
/* get the trigger id */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
triggered_by = strtoul(temp_ptr, NULL, 10);
/* get the duration */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
duration = strtoul(temp_ptr, NULL, 10);
/* get the author */
if((author = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* get the comment */
if((comment_data = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* check if flexible downtime demanded and duration set
to non-zero.
according to the documentation, a flexible downtime is
started between start and end time and will last for
"duration" seconds. strtoul converts a NULL value to 0
so if set to 0, bail out as a duration>0 is needed. */
if(fixed == 0 && duration == 0)
return ERROR;
/* duration should be auto-calculated, not user-specified */
if(fixed > 0)
duration = (unsigned long)(end_time - start_time);
/* schedule downtime */
switch(cmd) {
case CMD_SCHEDULE_HOST_DOWNTIME:
schedule_downtime(HOST_DOWNTIME, host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
break;
case CMD_SCHEDULE_SVC_DOWNTIME:
schedule_downtime(SERVICE_DOWNTIME, host_name, svc_description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
break;
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
schedule_downtime(SERVICE_DOWNTIME, host_name, temp_service->description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
}
break;
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
for(temp_hgmember = temp_hostgroup->members; temp_hgmember != NULL; temp_hgmember = temp_hgmember->next)
schedule_downtime(HOST_DOWNTIME, temp_hgmember->host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
break;
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
for(temp_hgmember = temp_hostgroup->members; temp_hgmember != NULL; temp_hgmember = temp_hgmember->next) {
if((temp_host = temp_hgmember->host_ptr) == NULL)
continue;
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
schedule_downtime(SERVICE_DOWNTIME, temp_service->host_name, temp_service->description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
}
}
break;
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
last_host = NULL;
for(temp_sgmember = temp_servicegroup->members; temp_sgmember != NULL; temp_sgmember = temp_sgmember->next) {
temp_host = find_host(temp_sgmember->host_name);
if(temp_host == NULL)
continue;
if(last_host == temp_host)
continue;
schedule_downtime(HOST_DOWNTIME, temp_sgmember->host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
last_host = temp_host;
}
break;
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
for(temp_sgmember = temp_servicegroup->members; temp_sgmember != NULL; temp_sgmember = temp_sgmember->next)
schedule_downtime(SERVICE_DOWNTIME, temp_sgmember->host_name, temp_sgmember->service_description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
break;
case CMD_SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME:
/* schedule downtime for "parent" host */
schedule_downtime(HOST_DOWNTIME, host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
/* schedule (non-triggered) downtime for all child hosts */
schedule_and_propagate_downtime(temp_host, entry_time, author, comment_data, start_time, end_time, fixed, 0, duration);
break;
case CMD_SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME:
/* schedule downtime for "parent" host */
schedule_downtime(HOST_DOWNTIME, host_name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id);
/* schedule triggered downtime for all child hosts */
schedule_and_propagate_downtime(temp_host, entry_time, author, comment_data, start_time, end_time, fixed, downtime_id, duration);
break;
default:
break;
}
return OK;
}
/* deletes scheduled host or service downtime */
int cmd_delete_downtime(int cmd, char *args) {
unsigned long downtime_id = 0L;
char *temp_ptr = NULL;
/* get the id of the downtime to delete */
if((temp_ptr = my_strtok(args, "\n")) == NULL)
return ERROR;
downtime_id = strtoul(temp_ptr, NULL, 10);
if(cmd == CMD_DEL_HOST_DOWNTIME)
unschedule_downtime(HOST_DOWNTIME, downtime_id);
else
unschedule_downtime(SERVICE_DOWNTIME, downtime_id);
return OK;
}
/* Deletes scheduled host and service downtime based on hostname and optionally other filter arguments */
int cmd_delete_downtime_by_host_name(int cmd, char *args)
{
char *temp_ptr = NULL;
char *end_ptr = NULL;
char *hostname = NULL;
char *service_description = NULL;
char *downtime_comment = NULL;
time_t downtime_start_time = 0L;
int deleted = 0;
if (args == NULL) {
return ERROR;
}
/* get the host name of the downtime to delete */
temp_ptr = my_strtok(args, ";");
if (temp_ptr == NULL) {
return ERROR;
}
hostname = temp_ptr;
/* get the optional service name */
temp_ptr = my_strtok(NULL, ";");
if (temp_ptr != NULL) {
if (*temp_ptr != '\0') {
service_description = temp_ptr;
}
/* get the optional start time */
temp_ptr = my_strtok(NULL, ";");
if (temp_ptr != NULL) {
downtime_start_time = strtoul(temp_ptr, &end_ptr, 10);
/* get the optional comment */
temp_ptr = my_strtok(NULL, ";");
if (temp_ptr != NULL && *temp_ptr != '\0') {
downtime_comment = temp_ptr;
}
}
}
deleted = delete_downtime_by_hostname_service_description_start_time_comment(hostname, service_description, downtime_start_time, downtime_comment);
if (deleted == 0) {
return ERROR;
}
return OK;
}
int cmd_delete_downtime_by_hostgroup_name(int cmd, char *args) {
char *temp_ptr = NULL;
char *end_ptr = NULL;
host *temp_host = NULL;
hostgroup *temp_hostgroup = NULL;
hostsmember *temp_member = NULL;
char *service_description = NULL;
char *downtime_comment = NULL;
char *host_name = NULL;
time_t downtime_start_time = 0L;
int deleted = 0;
/* get the host group name of the downtime to delete */
temp_ptr = my_strtok(args, ";");
if(temp_ptr == NULL)
return ERROR;
temp_hostgroup = find_hostgroup(temp_ptr);
if(temp_hostgroup == NULL)
return ERROR;
/* get the optional host name */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
host_name = temp_ptr;
/* get the optional service name */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
service_description = temp_ptr;
/* get the optional start time */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
downtime_start_time = strtoul(temp_ptr, &end_ptr, 10);
/* get the optional comment */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
downtime_comment = temp_ptr;
}
}
}
/* get the optional service name */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
service_description = temp_ptr;
/* get the optional start time */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
downtime_start_time = strtoul(temp_ptr, &end_ptr, 10);
/* get the optional comment */
temp_ptr = my_strtok(NULL, ";");
if(temp_ptr != NULL) {
if(*temp_ptr != '\0')
downtime_comment = temp_ptr;
}
}
}
}
for(temp_member = temp_hostgroup->members; temp_member != NULL; temp_member = temp_member->next) {
if((temp_host = (host *)temp_member->host_ptr) == NULL)
continue;
if(host_name != NULL && strcmp(temp_host->name, host_name) != 0)
continue;
deleted = +delete_downtime_by_hostname_service_description_start_time_comment(temp_host->name, service_description, downtime_start_time, downtime_comment);
}
if(deleted == 0)
return ERROR;
return OK;
}
int cmd_delete_downtime_by_start_time_comment(int cmd, char *args) {
time_t downtime_start_time = 0L;
char *downtime_comment = NULL;
char *temp_ptr = NULL;
char *end_ptr = NULL;
int deleted = 0;
/* Get start time if set */
temp_ptr = my_strtok(args, ";");
if(temp_ptr != NULL) {
/* This will be set to 0 if no start_time is entered or data is bad */
downtime_start_time = strtoul(temp_ptr, &end_ptr, 10);
}
/* Get comment - not sure if this should be also tokenised by ; */
temp_ptr = my_strtok(NULL, "\n");
if(temp_ptr != NULL && *temp_ptr != '\0') {
downtime_comment = temp_ptr;
}
/* No args should give an error */
if(downtime_start_time == 0 && downtime_comment == NULL)
return ERROR;
deleted = delete_downtime_by_hostname_service_description_start_time_comment(NULL, NULL, downtime_start_time, downtime_comment);
if(deleted == 0)
return ERROR;
return OK;
}
/* changes a host or service (integer) variable */
int cmd_change_object_int_var(int cmd, char *args) {
service *temp_service = NULL;
host *temp_host = NULL;
contact *temp_contact = NULL;
char *host_name = NULL;
char *svc_description = NULL;
char *contact_name = NULL;
char *temp_ptr = NULL;
int intval = 0;
double dval = 0.0;
double old_dval = 0.0;
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
unsigned long attr = MODATTR_NONE;
unsigned long hattr = MODATTR_NONE;
unsigned long sattr = MODATTR_NONE;
switch(cmd) {
case CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL:
case CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL:
case CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS:
case CMD_CHANGE_SVC_MODATTR:
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* get the service name */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
break;
case CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL:
case CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL:
case CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS:
case CMD_CHANGE_HOST_MODATTR:
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
break;
case CMD_CHANGE_CONTACT_MODATTR:
case CMD_CHANGE_CONTACT_MODHATTR:
case CMD_CHANGE_CONTACT_MODSATTR:
/* get the contact name */
if((contact_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the contact is valid */
if((temp_contact = find_contact(contact_name)) == NULL)
return ERROR;
break;
default:
/* unknown command */
return ERROR;
break;
}
/* get the value */
if((temp_ptr = my_strtok(NULL, ";")) == NULL)
return ERROR;
intval = (int)strtol(temp_ptr, NULL, 0);
if(intval < 0 || (intval == 0 && errno == EINVAL))
return ERROR;
dval = (int)strtod(temp_ptr, NULL);
switch(cmd) {
case CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL:
/* save the old check interval */
old_dval = temp_host->check_interval;
/* modify the check interval */
temp_host->check_interval = dval;
attr = MODATTR_NORMAL_CHECK_INTERVAL;
/* schedule a host check if previous interval was 0 (checks were not regularly scheduled) */
if(old_dval == 0 && temp_host->checks_enabled == TRUE) {
/* set the host check flag */
temp_host->should_be_scheduled = TRUE;
/* schedule a check for right now (or as soon as possible) */
time(&preferred_time);
if(check_time_against_period(preferred_time, temp_host->check_period_ptr) == ERROR) {
get_next_valid_time(preferred_time, &next_valid_time, temp_host->check_period_ptr);
temp_host->next_check = next_valid_time;
}
else
temp_host->next_check = preferred_time;
/* schedule a check if we should */
if(temp_host->should_be_scheduled == TRUE)
schedule_host_check(temp_host, temp_host->next_check, CHECK_OPTION_NONE);
}
break;
case CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL:
temp_host->retry_interval = dval;
attr = MODATTR_RETRY_CHECK_INTERVAL;
break;
case CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS:
temp_host->max_attempts = intval;
attr = MODATTR_MAX_CHECK_ATTEMPTS;
/* adjust current attempt number if in a hard state */
if(temp_host->state_type == HARD_STATE && temp_host->current_state != HOST_UP && temp_host->current_attempt > 1)
temp_host->current_attempt = temp_host->max_attempts;
break;
case CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL:
/* save the old check interval */
old_dval = temp_service->check_interval;
/* modify the check interval */
temp_service->check_interval = dval;
attr = MODATTR_NORMAL_CHECK_INTERVAL;
/* schedule a service check if previous interval was 0 (checks were not regularly scheduled) */
if(old_dval == 0 && temp_service->checks_enabled == TRUE && temp_service->check_interval != 0) {
/* set the service check flag */
temp_service->should_be_scheduled = TRUE;
/* schedule a check for right now (or as soon as possible) */
time(&preferred_time);
if(check_time_against_period(preferred_time, temp_service->check_period_ptr) == ERROR) {
get_next_valid_time(preferred_time, &next_valid_time, temp_service->check_period_ptr);
temp_service->next_check = next_valid_time;
}
else
temp_service->next_check = preferred_time;
/* schedule a check if we should */
if(temp_service->should_be_scheduled == TRUE)
schedule_service_check(temp_service, temp_service->next_check, CHECK_OPTION_NONE);
}
break;
case CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL:
temp_service->retry_interval = dval;
attr = MODATTR_RETRY_CHECK_INTERVAL;
break;
case CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS:
temp_service->max_attempts = intval;
attr = MODATTR_MAX_CHECK_ATTEMPTS;
/* adjust current attempt number if in a hard state */
if(temp_service->state_type == HARD_STATE && temp_service->current_state != STATE_OK && temp_service->current_attempt > 1)
temp_service->current_attempt = temp_service->max_attempts;
break;
case CMD_CHANGE_HOST_MODATTR:
case CMD_CHANGE_SVC_MODATTR:
case CMD_CHANGE_CONTACT_MODATTR:
attr = intval;
break;
case CMD_CHANGE_CONTACT_MODHATTR:
hattr = intval;
break;
case CMD_CHANGE_CONTACT_MODSATTR:
sattr = intval;
break;
default:
break;
}
/* send data to event broker and update status file */
switch(cmd) {
case CMD_CHANGE_RETRY_SVC_CHECK_INTERVAL:
case CMD_CHANGE_NORMAL_SVC_CHECK_INTERVAL:
case CMD_CHANGE_MAX_SVC_CHECK_ATTEMPTS:
case CMD_CHANGE_SVC_MODATTR:
/* set the modified service attribute */
if(cmd == CMD_CHANGE_SVC_MODATTR)
temp_service->modified_attributes = attr;
else
temp_service->modified_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_service, cmd, attr, temp_service->modified_attributes, NULL);
#endif
/* update the status log with the service info */
update_service_status(temp_service, FALSE);
break;
case CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL:
case CMD_CHANGE_RETRY_HOST_CHECK_INTERVAL:
case CMD_CHANGE_MAX_HOST_CHECK_ATTEMPTS:
case CMD_CHANGE_HOST_MODATTR:
/* set the modified host attribute */
if(cmd == CMD_CHANGE_HOST_MODATTR)
temp_host->modified_attributes = attr;
else
temp_host->modified_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_host, cmd, attr, temp_host->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(temp_host, FALSE);
break;
case CMD_CHANGE_CONTACT_MODATTR:
case CMD_CHANGE_CONTACT_MODHATTR:
case CMD_CHANGE_CONTACT_MODSATTR:
/* set the modified attribute */
switch(cmd) {
case CMD_CHANGE_CONTACT_MODATTR:
temp_contact->modified_attributes = attr;
break;
case CMD_CHANGE_CONTACT_MODHATTR:
temp_contact->modified_host_attributes = hattr;
break;
case CMD_CHANGE_CONTACT_MODSATTR:
temp_contact->modified_service_attributes = sattr;
break;
default:
break;
}
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_contact, cmd, attr, temp_contact->modified_attributes, hattr, temp_contact->modified_host_attributes, sattr, temp_contact->modified_service_attributes, NULL);
#endif
/* update the status log with the contact info */
update_contact_status(temp_contact, FALSE);
break;
default:
break;
}
return OK;
}
/* changes a host or service (char) variable */
int cmd_change_object_char_var(int cmd, char *args) {
service *temp_service = NULL;
host *temp_host = NULL;
contact *temp_contact = NULL;
timeperiod *temp_timeperiod = NULL;
command *temp_command = NULL;
char *host_name = NULL;
char *svc_description = NULL;
char *contact_name = NULL;
char *charval = NULL;
char *temp_ptr = NULL;
char *temp_ptr2 = NULL;
unsigned long attr = MODATTR_NONE;
unsigned long hattr = MODATTR_NONE;
unsigned long sattr = MODATTR_NONE;
/* SECURITY PATCH - disable these for the time being */
switch(cmd) {
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_EVENT_HANDLER:
case CMD_CHANGE_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_CHECK_COMMAND:
case CMD_CHANGE_SVC_CHECK_COMMAND:
return ERROR;
}
/* get the command arguments */
switch(cmd) {
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
if((charval = my_strtok(args, "\n")) == NULL)
return ERROR;
break;
case CMD_CHANGE_HOST_EVENT_HANDLER:
case CMD_CHANGE_HOST_CHECK_COMMAND:
case CMD_CHANGE_HOST_CHECK_TIMEPERIOD:
case CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD:
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the host is valid */
if((temp_host = find_host(host_name)) == NULL)
return ERROR;
if((charval = my_strtok(NULL, "\n")) == NULL)
return ERROR;
break;
case CMD_CHANGE_SVC_EVENT_HANDLER:
case CMD_CHANGE_SVC_CHECK_COMMAND:
case CMD_CHANGE_SVC_CHECK_TIMEPERIOD:
case CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD:
/* get the host name */
if((host_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* get the service name */
if((svc_description = my_strtok(NULL, ";")) == NULL)
return ERROR;
/* verify that the service is valid */
if((temp_service = find_service(host_name, svc_description)) == NULL)
return ERROR;
if((charval = my_strtok(NULL, "\n")) == NULL)
return ERROR;
break;
case CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD:
/* get the contact name */
if((contact_name = my_strtok(args, ";")) == NULL)
return ERROR;
/* verify that the contact is valid */
if((temp_contact = find_contact(contact_name)) == NULL)
return ERROR;
if((charval = my_strtok(NULL, "\n")) == NULL)
return ERROR;
break;
default:
/* invalid command */
return ERROR;
break;
}
if((temp_ptr = (char *)strdup(charval)) == NULL)
return ERROR;
/* do some validation */
switch(cmd) {
case CMD_CHANGE_HOST_CHECK_TIMEPERIOD:
case CMD_CHANGE_SVC_CHECK_TIMEPERIOD:
case CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD:
/* make sure the timeperiod is valid */
if((temp_timeperiod = find_timeperiod(temp_ptr)) == NULL) {
my_free(temp_ptr);
return ERROR;
}
break;
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_EVENT_HANDLER:
case CMD_CHANGE_SVC_EVENT_HANDLER:
case CMD_CHANGE_HOST_CHECK_COMMAND:
case CMD_CHANGE_SVC_CHECK_COMMAND:
/* make sure the command exists */
temp_ptr2 = my_strtok(temp_ptr, "!");
if((temp_command = find_command(temp_ptr2)) == NULL) {
my_free(temp_ptr);
return ERROR;
}
my_free(temp_ptr);
if((temp_ptr = (char *)strdup(charval)) == NULL)
return ERROR;
break;
default:
break;
}
/* update the variable */
switch(cmd) {
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
my_free(global_host_event_handler);
global_host_event_handler = temp_ptr;
global_host_event_handler_ptr = temp_command;
attr = MODATTR_EVENT_HANDLER_COMMAND;
break;
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
my_free(global_service_event_handler);
global_service_event_handler = temp_ptr;
global_service_event_handler_ptr = temp_command;
attr = MODATTR_EVENT_HANDLER_COMMAND;
break;
case CMD_CHANGE_HOST_EVENT_HANDLER:
my_free(temp_host->event_handler);
temp_host->event_handler = temp_ptr;
temp_host->event_handler_ptr = temp_command;
attr = MODATTR_EVENT_HANDLER_COMMAND;
break;
case CMD_CHANGE_HOST_CHECK_COMMAND:
my_free(temp_host->check_command);
temp_host->check_command = temp_ptr;
temp_host->check_command_ptr = temp_command;
attr = MODATTR_CHECK_COMMAND;
break;
case CMD_CHANGE_HOST_CHECK_TIMEPERIOD:
my_free(temp_host->check_period);
temp_host->check_period = temp_ptr;
temp_host->check_period_ptr = temp_timeperiod;
attr = MODATTR_CHECK_TIMEPERIOD;
break;
case CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD:
my_free(temp_host->notification_period);
temp_host->notification_period = temp_ptr;
temp_host->notification_period_ptr = temp_timeperiod;
attr = MODATTR_NOTIFICATION_TIMEPERIOD;
break;
case CMD_CHANGE_SVC_EVENT_HANDLER:
my_free(temp_service->event_handler);
temp_service->event_handler = temp_ptr;
temp_service->event_handler_ptr = temp_command;
attr = MODATTR_EVENT_HANDLER_COMMAND;
break;
case CMD_CHANGE_SVC_CHECK_COMMAND:
my_free(temp_service->check_command);
temp_service->check_command = temp_ptr;
temp_service->check_command_ptr = temp_command;
attr = MODATTR_CHECK_COMMAND;
break;
case CMD_CHANGE_SVC_CHECK_TIMEPERIOD:
my_free(temp_service->check_period);
temp_service->check_period = temp_ptr;
temp_service->check_period_ptr = temp_timeperiod;
attr = MODATTR_CHECK_TIMEPERIOD;
break;
case CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD:
my_free(temp_service->notification_period);
temp_service->notification_period = temp_ptr;
temp_service->notification_period_ptr = temp_timeperiod;
attr = MODATTR_NOTIFICATION_TIMEPERIOD;
break;
case CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD:
my_free(temp_contact->host_notification_period);
temp_contact->host_notification_period = temp_ptr;
temp_contact->host_notification_period_ptr = temp_timeperiod;
hattr = MODATTR_NOTIFICATION_TIMEPERIOD;
break;
case CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD:
my_free(temp_contact->service_notification_period);
temp_contact->service_notification_period = temp_ptr;
temp_contact->service_notification_period_ptr = temp_timeperiod;
sattr = MODATTR_NOTIFICATION_TIMEPERIOD;
break;
default:
break;
}
/* send data to event broker and update status file */
switch(cmd) {
case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER:
/* set the modified host attribute */
modified_host_process_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cmd, attr, modified_host_process_attributes, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update program status */
update_program_status(FALSE);
break;
case CMD_CHANGE_GLOBAL_SVC_EVENT_HANDLER:
/* set the modified service attribute */
modified_service_process_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cmd, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update program status */
update_program_status(FALSE);
break;
case CMD_CHANGE_SVC_EVENT_HANDLER:
case CMD_CHANGE_SVC_CHECK_COMMAND:
case CMD_CHANGE_SVC_CHECK_TIMEPERIOD:
case CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD:
/* set the modified service attribute */
temp_service->modified_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_service_data(NEBTYPE_ADAPTIVESERVICE_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_service, cmd, attr, temp_service->modified_attributes, NULL);
#endif
/* update the status log with the service info */
update_service_status(temp_service, FALSE);
break;
case CMD_CHANGE_HOST_EVENT_HANDLER:
case CMD_CHANGE_HOST_CHECK_COMMAND:
case CMD_CHANGE_HOST_CHECK_TIMEPERIOD:
case CMD_CHANGE_HOST_NOTIFICATION_TIMEPERIOD:
/* set the modified host attribute */
temp_host->modified_attributes |= attr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_host_data(NEBTYPE_ADAPTIVEHOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_host, cmd, attr, temp_host->modified_attributes, NULL);
#endif
/* update the status log with the host info */
update_host_status(temp_host, FALSE);
break;
case CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD:
case CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD:
/* set the modified attributes */
temp_contact->modified_host_attributes |= hattr;
temp_contact->modified_service_attributes |= sattr;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, temp_contact, cmd, attr, temp_contact->modified_attributes, hattr, temp_contact->modified_host_attributes, sattr, temp_contact->modified_service_attributes, NULL);
#endif
/* update the status log with the contact info */
update_contact_status(temp_contact, FALSE);
break;
default:
break;
}
return OK;
}
/* changes a custom host or service variable */
int cmd_change_object_custom_var(int cmd, char *args) {
host *temp_host = NULL;
service *temp_service = NULL;
contact *temp_contact = NULL;
customvariablesmember *temp_customvariablesmember = NULL;
char *temp_ptr = NULL;
char *name1 = NULL;
char *name2 = NULL;
char *varname = NULL;
char *varvalue = NULL;
register int x = 0;
/* get the host or contact name */
if((temp_ptr = my_strtok(args, ";")) == NULL)
return ERROR;
if((name1 = (char *)strdup(temp_ptr)) == NULL)
return ERROR;
/* get the service description if necessary */
if(cmd == CMD_CHANGE_CUSTOM_SVC_VAR) {
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(name1);
return ERROR;
}
if((name2 = (char *)strdup(temp_ptr)) == NULL) {
my_free(name1);
return ERROR;
}
}
/* find the object */
switch(cmd) {
case CMD_CHANGE_CUSTOM_HOST_VAR:
if((temp_host = find_host(name1)) == NULL) {
my_free(name1);
my_free(name2);
return ERROR;
}
temp_customvariablesmember = temp_host->custom_variables;
break;
case CMD_CHANGE_CUSTOM_SVC_VAR:
if((temp_service = find_service(name1, name2)) == NULL) {
my_free(name1);
my_free(name2);
return ERROR;
}
temp_customvariablesmember = temp_service->custom_variables;
break;
case CMD_CHANGE_CUSTOM_CONTACT_VAR:
if((temp_contact = find_contact(name1)) == NULL) {
my_free(name1);
my_free(name2);
return ERROR;
}
temp_customvariablesmember = temp_contact->custom_variables;
break;
default:
break;
}
/* get the custom variable name */
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(name1);
my_free(name2);
return ERROR;
}
if((varname = (char *)strdup(temp_ptr)) == NULL) {
my_free(name1);
my_free(name2);
return ERROR;
}
/* get the custom variable value */
if((temp_ptr = my_strtok(NULL, ";")) == NULL) {
my_free(name1);
my_free(name2);
my_free(varname);
return ERROR;
}
if((varvalue = (char *)strdup(temp_ptr)) == NULL) {
my_free(name1);
my_free(name2);
my_free(varname);
return ERROR;
}
/* capitalize the custom variable name */
for(x = 0; varname[x] != '\x0'; x++)
varname[x] = toupper(varname[x]);
/* find the proper variable */
for(; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) {
/* we found the variable, so update the value */
if(!strcmp(varname, temp_customvariablesmember->variable_name)) {
/* update the value */
if(temp_customvariablesmember->variable_value)
my_free(temp_customvariablesmember->variable_value);
temp_customvariablesmember->variable_value = (char *)strdup(varvalue);
/* mark the variable value as having been changed */
temp_customvariablesmember->has_been_modified = TRUE;
break;
}
}
/* free memory */
my_free(name1);
my_free(name2);
my_free(varname);
my_free(varvalue);
/* set the modified attributes and update the status of the object */
switch(cmd) {
case CMD_CHANGE_CUSTOM_HOST_VAR:
temp_host->modified_attributes |= MODATTR_CUSTOM_VARIABLE;
update_host_status(temp_host, FALSE);
break;
case CMD_CHANGE_CUSTOM_SVC_VAR:
temp_service->modified_attributes |= MODATTR_CUSTOM_VARIABLE;
update_service_status(temp_service, FALSE);
break;
case CMD_CHANGE_CUSTOM_CONTACT_VAR:
temp_contact->modified_attributes |= MODATTR_CUSTOM_VARIABLE;
update_contact_status(temp_contact, FALSE);
break;
default:
break;
}
return OK;
}
/* processes an external host command */
int cmd_process_external_commands_from_file(int cmd, char *args) {
char *fname = NULL;
char *temp_ptr = NULL;
int delete_file = FALSE;
/* get the file name */
if((temp_ptr = my_strtok(args, ";")) == NULL)
return ERROR;
if((fname = (char *)strdup(temp_ptr)) == NULL)
return ERROR;
/* find the deletion option */
if((temp_ptr = my_strtok(NULL, "\n")) == NULL) {
my_free(fname);
return ERROR;
}
if(atoi(temp_ptr) == 0)
delete_file = FALSE;
else
delete_file = TRUE;
/* process the file */
process_external_commands_from_file(fname, delete_file);
/* free memory */
my_free(fname);
return OK;
}
/******************************************************************/
/*************** INTERNAL COMMAND IMPLEMENTATIONS ****************/
/******************************************************************/
/* temporarily disables a service check */
void disable_service_checks(service *svc) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* checks are already disabled */
if(svc->checks_enabled == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* disable the service check... */
svc->checks_enabled = FALSE;
svc->should_be_scheduled = 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
/* update the status log to reflect the new service state */
update_service_status(svc, FALSE);
return;
}
/* enables a service check */
void enable_service_checks(service *svc) {
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* checks are already enabled */
if(svc->checks_enabled == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* enable the service check... */
svc->checks_enabled = TRUE;
svc->should_be_scheduled = TRUE;
/* services with no check intervals don't get checked */
if(svc->check_interval == 0)
svc->should_be_scheduled = FALSE;
/* schedule a check for right now (or as soon as possible) */
time(&preferred_time);
if(check_time_against_period(preferred_time, svc->check_period_ptr) == ERROR) {
get_next_valid_time(preferred_time, &next_valid_time, svc->check_period_ptr);
svc->next_check = next_valid_time;
}
else
svc->next_check = preferred_time;
/* schedule a check if we should */
if(svc->should_be_scheduled == TRUE)
schedule_service_check(svc, svc->next_check, CHECK_OPTION_NONE);
#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
/* update the status log to reflect the new service state */
update_service_status(svc, FALSE);
return;
}
/* enable notifications on a program-wide basis */
void enable_all_notifications(void) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* bail out if we're already set... */
if(enable_notifications == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* update notification status */
enable_notifications = 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 the status log */
update_program_status(FALSE);
return;
}
/* disable notifications on a program-wide basis */
void disable_all_notifications(void) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* bail out if we're already set... */
if(enable_notifications == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* update notification status */
enable_notifications = 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 the status log */
update_program_status(FALSE);
return;
}
/* enables notifications for a service */
void enable_service_notifications(service *svc) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(svc->notifications_enabled == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* enable the service notifications... */
svc->notifications_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
/* update the status log to reflect the new service state */
update_service_status(svc, FALSE);
return;
}
/* disables notifications for a service */
void disable_service_notifications(service *svc) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(svc->notifications_enabled == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* disable the service notifications... */
svc->notifications_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
/* update the status log to reflect the new service state */
update_service_status(svc, FALSE);
return;
}
/* enables notifications for a host */
void enable_host_notifications(host *hst) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(hst->notifications_enabled == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* enable the host notifications... */
hst->notifications_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
/* update the status log to reflect the new host state */
update_host_status(hst, FALSE);
return;
}
/* disables notifications for a host */
void disable_host_notifications(host *hst) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(hst->notifications_enabled == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* disable the host notifications... */
hst->notifications_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
/* update the status log to reflect the new host state */
update_host_status(hst, FALSE);
return;
}
/* enables notifications for all hosts and services "beyond" a given host */
void enable_and_propagate_notifications(host *hst, int level, int affect_top_host, int affect_hosts, int affect_services) {
host *child_host = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
hostsmember *temp_hostsmember = NULL;
/* enable notification for top level host */
if(affect_top_host == TRUE && level == 0)
enable_host_notifications(hst);
/* check all child hosts... */
for(temp_hostsmember = hst->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
if((child_host = temp_hostsmember->host_ptr) == NULL)
continue;
/* recurse... */
enable_and_propagate_notifications(child_host, level + 1, affect_top_host, affect_hosts, affect_services);
/* enable notifications for this host */
if(affect_hosts == TRUE)
enable_host_notifications(child_host);
/* enable notifications for all services on this host... */
if(affect_services == TRUE) {
for(temp_servicesmember = child_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
enable_service_notifications(temp_service);
}
}
}
return;
}
/* disables notifications for all hosts and services "beyond" a given host */
void disable_and_propagate_notifications(host *hst, int level, int affect_top_host, int affect_hosts, int affect_services) {
host *child_host = NULL;
service *temp_service = NULL;
servicesmember *temp_servicesmember = NULL;
hostsmember *temp_hostsmember = NULL;
if(hst == NULL)
return;
/* disable notifications for top host */
if(affect_top_host == TRUE && level == 0)
disable_host_notifications(hst);
/* check all child hosts... */
for(temp_hostsmember = hst->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
if((child_host = temp_hostsmember->host_ptr) == NULL)
continue;
/* recurse... */
disable_and_propagate_notifications(child_host, level + 1, affect_top_host, affect_hosts, affect_services);
/* disable notifications for this host */
if(affect_hosts == TRUE)
disable_host_notifications(child_host);
/* disable notifications for all services on this host... */
if(affect_services == TRUE) {
for(temp_servicesmember = child_host->services; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) {
if((temp_service = temp_servicesmember->service_ptr) == NULL)
continue;
disable_service_notifications(temp_service);
}
}
}
return;
}
/* enables host notifications for a contact */
void enable_contact_host_notifications(contact *cntct) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(cntct->host_notifications_enabled == TRUE)
return;
/* set the attribute modified flag */
cntct->modified_host_attributes |= attr;
/* enable the host notifications... */
cntct->host_notifications_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cntct, CMD_NONE, MODATTR_NONE, cntct->modified_attributes, attr, cntct->modified_host_attributes, MODATTR_NONE, cntct->modified_service_attributes, NULL);
#endif
/* update the status log to reflect the new contact state */
update_contact_status(cntct, FALSE);
return;
}
/* disables host notifications for a contact */
void disable_contact_host_notifications(contact *cntct) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(cntct->host_notifications_enabled == FALSE)
return;
/* set the attribute modified flag */
cntct->modified_host_attributes |= attr;
/* enable the host notifications... */
cntct->host_notifications_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cntct, CMD_NONE, MODATTR_NONE, cntct->modified_attributes, attr, cntct->modified_host_attributes, MODATTR_NONE, cntct->modified_service_attributes, NULL);
#endif
/* update the status log to reflect the new contact state */
update_contact_status(cntct, FALSE);
return;
}
/* enables service notifications for a contact */
void enable_contact_service_notifications(contact *cntct) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(cntct->service_notifications_enabled == TRUE)
return;
/* set the attribute modified flag */
cntct->modified_service_attributes |= attr;
/* enable the host notifications... */
cntct->service_notifications_enabled = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cntct, CMD_NONE, MODATTR_NONE, cntct->modified_attributes, MODATTR_NONE, cntct->modified_host_attributes, attr, cntct->modified_service_attributes, NULL);
#endif
/* update the status log to reflect the new contact state */
update_contact_status(cntct, FALSE);
return;
}
/* disables service notifications for a contact */
void disable_contact_service_notifications(contact *cntct) {
unsigned long attr = MODATTR_NOTIFICATIONS_ENABLED;
/* no change */
if(cntct->service_notifications_enabled == FALSE)
return;
/* set the attribute modified flag */
cntct->modified_service_attributes |= attr;
/* enable the host notifications... */
cntct->service_notifications_enabled = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_contact_data(NEBTYPE_ADAPTIVECONTACT_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cntct, CMD_NONE, MODATTR_NONE, cntct->modified_attributes, MODATTR_NONE, cntct->modified_host_attributes, attr, cntct->modified_service_attributes, NULL);
#endif
/* update the status log to reflect the new contact state */
update_contact_status(cntct, FALSE);
return;
}
/* schedules downtime for all hosts "beyond" a given host */
void schedule_and_propagate_downtime(host *temp_host, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration) {
host *child_host = NULL;
hostsmember *temp_hostsmember = NULL;
/* check all child hosts... */
for(temp_hostsmember = temp_host->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
if((child_host = temp_hostsmember->host_ptr) == NULL)
continue;
/* recurse... */
schedule_and_propagate_downtime(child_host, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration);
/* schedule downtime for this host */
schedule_downtime(HOST_DOWNTIME, child_host->name, NULL, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, NULL);
}
return;
}
/* acknowledges a host problem */
void acknowledge_host_problem(host *hst, char *ack_author, char *ack_data, int type, int notify, int persistent) {
time_t current_time = 0L;
/* cannot acknowledge a non-existent problem */
if(hst->current_state == HOST_UP)
return;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_acknowledgement_data(NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, HOST_ACKNOWLEDGEMENT, (void *)hst, ack_author, ack_data, type, notify, persistent, NULL);
#endif
/* send out an acknowledgement notification */
if(notify == TRUE)
host_notification(hst, NOTIFICATION_ACKNOWLEDGEMENT, ack_author, ack_data, NOTIFICATION_OPTION_NONE);
/* set the acknowledgement flag */
hst->problem_has_been_acknowledged = TRUE;
/* set the acknowledgement type */
hst->acknowledgement_type = (type == ACKNOWLEDGEMENT_STICKY) ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL;
/* update the status log with the host info */
update_host_status(hst, FALSE);
/* add a comment for the acknowledgement */
time(¤t_time);
add_new_host_comment(ACKNOWLEDGEMENT_COMMENT, hst->name, current_time, ack_author, ack_data, persistent, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, NULL);
return;
}
/* acknowledges a service problem */
void acknowledge_service_problem(service *svc, char *ack_author, char *ack_data, int type, int notify, int persistent) {
time_t current_time = 0L;
/* cannot acknowledge a non-existent problem */
if(svc->current_state == STATE_OK)
return;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_acknowledgement_data(NEBTYPE_ACKNOWLEDGEMENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_ACKNOWLEDGEMENT, (void *)svc, ack_author, ack_data, type, notify, persistent, NULL);
#endif
/* send out an acknowledgement notification */
if(notify == TRUE)
service_notification(svc, NOTIFICATION_ACKNOWLEDGEMENT, ack_author, ack_data, NOTIFICATION_OPTION_NONE);
/* set the acknowledgement flag */
svc->problem_has_been_acknowledged = TRUE;
/* set the acknowledgement type */
svc->acknowledgement_type = (type == ACKNOWLEDGEMENT_STICKY) ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL;
/* update the status log with the service info */
update_service_status(svc, FALSE);
/* add a comment for the acknowledgement */
time(¤t_time);
add_new_service_comment(ACKNOWLEDGEMENT_COMMENT, svc->host_name, svc->description, current_time, ack_author, ack_data, persistent, COMMENTSOURCE_INTERNAL, FALSE, (time_t)0, NULL);
return;
}
/* removes a host acknowledgement */
void remove_host_acknowledgement(host *hst) {
/* set the acknowledgement flag */
hst->problem_has_been_acknowledged = FALSE;
/* update the status log with the host info */
update_host_status(hst, FALSE);
/* remove any non-persistant comments associated with the ack */
delete_host_acknowledgement_comments(hst);
return;
}
/* removes a service acknowledgement */
void remove_service_acknowledgement(service *svc) {
/* set the acknowledgement flag */
svc->problem_has_been_acknowledged = FALSE;
/* update the status log with the service info */
update_service_status(svc, FALSE);
/* remove any non-persistant comments associated with the ack */
delete_service_acknowledgement_comments(svc);
return;
}
/* starts executing service checks */
void start_executing_service_checks(void) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* bail out if we're already executing services */
if(execute_service_checks == TRUE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service check execution flag */
execute_service_checks = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stops executing service checks */
void stop_executing_service_checks(void) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* bail out if we're already not executing services */
if(execute_service_checks == FALSE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service check execution flag */
execute_service_checks = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* starts accepting passive service checks */
void start_accepting_passive_service_checks(void) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* bail out if we're already accepting passive services */
if(accept_passive_service_checks == TRUE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service check flag */
accept_passive_service_checks = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stops accepting passive service checks */
void stop_accepting_passive_service_checks(void) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* bail out if we're already not accepting passive services */
if(accept_passive_service_checks == FALSE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service check flag */
accept_passive_service_checks = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* enables passive service checks for a particular service */
void enable_passive_service_checks(service *svc) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* no change */
if(svc->accept_passive_checks == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the passive check flag */
svc->accept_passive_checks = 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
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* disables passive service checks for a particular service */
void disable_passive_service_checks(service *svc) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* no change */
if(svc->accept_passive_checks == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the passive check flag */
svc->accept_passive_checks = 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
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* starts executing host checks */
void start_executing_host_checks(void) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* bail out if we're already executing hosts */
if(execute_host_checks == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host check execution flag */
execute_host_checks = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stops executing host checks */
void stop_executing_host_checks(void) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* bail out if we're already not executing hosts */
if(execute_host_checks == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host check execution flag */
execute_host_checks = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* starts accepting passive host checks */
void start_accepting_passive_host_checks(void) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* bail out if we're already accepting passive hosts */
if(accept_passive_host_checks == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host check flag */
accept_passive_host_checks = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stops accepting passive host checks */
void stop_accepting_passive_host_checks(void) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* bail out if we're already not accepting passive hosts */
if(accept_passive_host_checks == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host check flag */
accept_passive_host_checks = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* enables passive host checks for a particular host */
void enable_passive_host_checks(host *hst) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* no change */
if(hst->accept_passive_checks == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the passive check flag */
hst->accept_passive_checks = 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
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* disables passive host checks for a particular host */
void disable_passive_host_checks(host *hst) {
unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED;
/* no change */
if(hst->accept_passive_checks == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the passive check flag */
hst->accept_passive_checks = 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
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* enables event handlers on a program-wide basis */
void start_using_event_handlers(void) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(enable_event_handlers == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* set the event handler flag */
enable_event_handlers = 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 the status log with the program info */
update_program_status(FALSE);
return;
}
/* disables event handlers on a program-wide basis */
void stop_using_event_handlers(void) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(enable_event_handlers == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
/* set the event handler flag */
enable_event_handlers = 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 the status log with the program info */
update_program_status(FALSE);
return;
}
/* enables the event handler for a particular service */
void enable_service_event_handler(service *svc) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(svc->event_handler_enabled == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the event handler flag */
svc->event_handler_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
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* disables the event handler for a particular service */
void disable_service_event_handler(service *svc) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(svc->event_handler_enabled == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the event handler flag */
svc->event_handler_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
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* enables the event handler for a particular host */
void enable_host_event_handler(host *hst) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(hst->event_handler_enabled == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the event handler flag */
hst->event_handler_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
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* disables the event handler for a particular host */
void disable_host_event_handler(host *hst) {
unsigned long attr = MODATTR_EVENT_HANDLER_ENABLED;
/* no change */
if(hst->event_handler_enabled == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the event handler flag */
hst->event_handler_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
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* disables checks of a particular host */
void disable_host_checks(host *hst) {
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* checks are already disabled */
if(hst->checks_enabled == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the host check flag */
hst->checks_enabled = FALSE;
hst->should_be_scheduled = 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
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* enables checks of a particular host */
void enable_host_checks(host *hst) {
time_t preferred_time = 0L;
time_t next_valid_time = 0L;
unsigned long attr = MODATTR_ACTIVE_CHECKS_ENABLED;
/* checks are already enabled */
if(hst->checks_enabled == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the host check flag */
hst->checks_enabled = TRUE;
hst->should_be_scheduled = TRUE;
/* hosts with no check intervals don't get checked */
if(hst->check_interval == 0)
hst->should_be_scheduled = FALSE;
/* schedule a check for right now (or as soon as possible) */
time(&preferred_time);
if(check_time_against_period(preferred_time, hst->check_period_ptr) == ERROR) {
get_next_valid_time(preferred_time, &next_valid_time, hst->check_period_ptr);
hst->next_check = next_valid_time;
}
else
hst->next_check = preferred_time;
/* schedule a check if we should */
if(hst->should_be_scheduled == TRUE)
schedule_host_check(hst, hst->next_check, CHECK_OPTION_NONE);
#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
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* start obsessing over service check results */
void start_obsessing_over_service_checks(void) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(obsess_over_services == TRUE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service obsession flag */
obsess_over_services = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stop obsessing over service check results */
void stop_obsessing_over_service_checks(void) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(obsess_over_services == FALSE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the service obsession flag */
obsess_over_services = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* start obsessing over host check results */
void start_obsessing_over_host_checks(void) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(obsess_over_hosts == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host obsession flag */
obsess_over_hosts = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* stop obsessing over host check results */
void stop_obsessing_over_host_checks(void) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(obsess_over_hosts == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the host obsession flag */
obsess_over_hosts = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* enables service freshness checking */
void enable_service_freshness_checks(void) {
unsigned long attr = MODATTR_FRESHNESS_CHECKS_ENABLED;
/* no change */
if(check_service_freshness == TRUE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the freshness check flag */
check_service_freshness = TRUE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* disables service freshness checking */
void disable_service_freshness_checks(void) {
unsigned long attr = MODATTR_FRESHNESS_CHECKS_ENABLED;
/* no change */
if(check_service_freshness == FALSE)
return;
/* set the attribute modified flag */
modified_service_process_attributes |= attr;
/* set the freshness check flag */
check_service_freshness = FALSE;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, MODATTR_NONE, modified_host_process_attributes, attr, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* enables host freshness checking */
void enable_host_freshness_checks(void) {
unsigned long attr = MODATTR_FRESHNESS_CHECKS_ENABLED;
/* no change */
if(check_host_freshness == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the freshness check flag */
check_host_freshness = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* disables host freshness checking */
void disable_host_freshness_checks(void) {
unsigned long attr = MODATTR_FRESHNESS_CHECKS_ENABLED;
/* no change */
if(check_host_freshness == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
/* set the freshness check flag */
check_host_freshness = 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, MODATTR_NONE, modified_service_process_attributes, NULL);
#endif
/* update the status log with the program info */
update_program_status(FALSE);
return;
}
/* enable performance data on a program-wide basis */
void enable_performance_data(void) {
unsigned long attr = MODATTR_PERFORMANCE_DATA_ENABLED;
/* bail out if we're already set... */
if(process_performance_data == TRUE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
process_performance_data = 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 the status log */
update_program_status(FALSE);
return;
}
/* disable performance data on a program-wide basis */
void disable_performance_data(void) {
unsigned long attr = MODATTR_PERFORMANCE_DATA_ENABLED;
# /* bail out if we're already set... */
if(process_performance_data == FALSE)
return;
/* set the attribute modified flag */
modified_host_process_attributes |= attr;
modified_service_process_attributes |= attr;
process_performance_data = 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 the status log */
update_program_status(FALSE);
return;
}
/* start obsessing over a particular service */
void start_obsessing_over_service(service *svc) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(svc->obsess == TRUE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the obsess over service flag */
svc->obsess = 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
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* stop obsessing over a particular service */
void stop_obsessing_over_service(service *svc) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(svc->obsess == FALSE)
return;
/* set the attribute modified flag */
svc->modified_attributes |= attr;
/* set the obsess over service flag */
svc->obsess = 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
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* start obsessing over a particular host */
void start_obsessing_over_host(host *hst) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(hst->obsess == TRUE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the obsess flag */
hst->obsess = 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
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* stop obsessing over a particular host */
void stop_obsessing_over_host(host *hst) {
unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED;
/* no change */
if(hst->obsess == FALSE)
return;
/* set the attribute modified flag */
hst->modified_attributes |= attr;
/* set the obsess over host flag */
hst->obsess = 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
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* sets the current notification number for a specific host */
void set_host_notification_number(host *hst, int num) {
/* set the notification number */
hst->current_notification_number = num;
/* update the status log with the host info */
update_host_status(hst, FALSE);
return;
}
/* sets the current notification number for a specific service */
void set_service_notification_number(service *svc, int num) {
/* set the notification number */
svc->current_notification_number = num;
/* update the status log with the service info */
update_service_status(svc, FALSE);
return;
}
/* clears the flapping state for a specific host */
void clear_host_flapping_state(host *hst) {
int i = 0;
double low_threshold = 0.0;
double high_threshold = 0.0;
if (enable_flap_detection == FALSE || hst->flap_detection_enabled == FALSE) {
return;
}
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;
if (hst->is_flapping) {
log_debug_info(DEBUGL_FLAPPING, 1, "Host '%s' flapping state cleared.\n", hst->name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE,
"HOST FLAPPING ALERT: %s;STOPPED; Flapping state cleared for host. (%2.1f%% change < %2.1f%% threshold)\n",
hst->name, hst->percent_state_change, low_threshold);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_NORMAL, HOST_FLAPPING, hst, hst->percent_state_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->current_state == HOST_UP && hst->check_flapping_recovery_notification == TRUE) {
host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
}
}
/* clear the history and state change percent */
for (i = 0; i < MAX_STATE_HISTORY_ENTRIES; ++i) {
hst->state_history[i] = 0;
}
hst->state_history_index = 0;
hst->percent_state_change = 0.0;
/* 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;
/* clear the recovery notification flag */
hst->check_flapping_recovery_notification = FALSE;
}
/* clears the flapping state for a specific service */
void clear_service_flapping_state(service *svc) {
int i = 0;
double low_threshold = 0.0;
double high_threshold = 0.0;
if (enable_flap_detection == FALSE || svc->flap_detection_enabled == FALSE) {
return;
}
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;
if (svc->is_flapping) {
log_debug_info(DEBUGL_FLAPPING, 1, "Service '%s' on host '%s' flapping state cleared.\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; Flapping state cleared for service. (%2.1f%% change < %2.1f%% threshold)\n",
svc->host_name, svc->description, svc->percent_state_change, low_threshold);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_NORMAL, SERVICE_FLAPPING, svc, svc->percent_state_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->current_state == STATE_OK && svc->check_flapping_recovery_notification == TRUE) {
service_notification(svc, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE);
}
}
/* clear the history and state change percent */
for (i = 0; i < MAX_STATE_HISTORY_ENTRIES; ++i) {
svc->state_history[i] = 0;
}
svc->state_history_index = 0;
svc->percent_state_change = 0.0;
/* 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;
/* clear the recovery notification flag */
svc->check_flapping_recovery_notification = FALSE;
}
nagios-4.4.6/base/config.c 0000664 0000000 0000000 00000220366 13652113235 0015342 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* CONFIG.C - Configuration input and verification routines for 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/macros.h"
#include "../include/nagios.h"
#include "../include/broker.h"
#include "../include/nebmods.h"
#include "../include/nebmodules.h"
/*** helpers ****/
/*
* find a command with arguments still attached
* if we're unsuccessful, the buffer pointed to by 'name' is modified
* to have only the real command name (everything up until the first '!')
*/
static command *find_bang_command(char *name)
{
char *bang;
command *cmd;
if (!name)
return NULL;
bang = strchr(name, '!');
if (!bang)
return find_command(name);
*bang = 0;
cmd = find_command(name);
*bang = '!';
return cmd;
}
/******************************************************************/
/************** CONFIGURATION INPUT FUNCTIONS *********************/
/******************************************************************/
/* read all configuration data */
int read_all_object_data(char *main_config_file) {
int result = OK;
int options = 0;
options = READ_ALL_OBJECT_DATA;
/* read in all host configuration data from external sources */
result = read_object_config_data(main_config_file, options);
if(result != OK)
return ERROR;
return OK;
}
static objectlist *deprecated = NULL;
static void obsoleted_warning(const char *key, const char *msg)
{
char *buf;
asprintf(&buf, "Warning: %s is deprecated and will be removed.%s%s\n",
key, msg ? " " : "", msg ? msg : "");
if (!buf)
return;
prepend_object_to_objectlist(&deprecated, buf);
}
/* process the main configuration file */
int read_main_config_file(char *main_config_file) {
char *input = NULL;
char *variable = NULL;
char *value = NULL;
char *error_message = NULL;
char *temp_ptr = NULL;
mmapfile *thefile = NULL;
int current_line = 0;
int error = FALSE;
char *modptr = NULL;
char *argptr = NULL;
DIR *tmpdir = NULL;
nagios_macros *mac;
objectlist *list;
mac = get_global_macros();
/* open the config file for reading */
if((thefile = mmap_fopen(main_config_file)) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Cannot open main configuration file '%s' for reading!", main_config_file);
exit(ERROR);
}
/* save the main config file macro */
my_free(mac->x[MACRO_MAINCONFIGFILE]);
if((mac->x[MACRO_MAINCONFIGFILE] = (char *)strdup(main_config_file)))
strip(mac->x[MACRO_MAINCONFIGFILE]);
/* process all lines in the config file */
while(1) {
/* free memory */
my_free(input);
my_free(variable);
my_free(value);
/* read the next line */
if((input = mmap_fgets_multiline(thefile)) == NULL)
break;
current_line = thefile->current_line;
strip(input);
/* skip blank lines and comments */
if(input[0] == '\x0' || input[0] == '#')
continue;
/* get the variable name */
if((temp_ptr = my_strtok_with_free(input, "=", FALSE)) == NULL) {
asprintf(&error_message, "NULL variable");
error = TRUE;
break;
}
if((variable = (char *)strdup(temp_ptr)) == NULL) {
asprintf(&error_message, "malloc() error");
error = TRUE;
break;
}
/* get the value */
if((temp_ptr = my_strtok_with_free(NULL, "\n", FALSE)) == NULL) {
asprintf(&error_message, "NULL value");
error = TRUE;
break;
}
if((value = (char *)strdup(temp_ptr)) == NULL) {
asprintf(&error_message, "malloc() error");
error = TRUE;
break;
}
temp_ptr = my_strtok_with_free(NULL, "\n", TRUE);
strip(variable);
strip(value);
/* process the variable/value */
if(!strcmp(variable, "resource_file")) {
/* save the macro */
my_free(mac->x[MACRO_RESOURCEFILE]);
mac->x[MACRO_RESOURCEFILE] = nspath_absolute(value, config_file_dir);
/* process the resource file */
if(read_resource_file(mac->x[MACRO_RESOURCEFILE]) == ERROR) {
error = TRUE;
}
}
else if(!strcmp(variable, "website_url")) {
int lth;
my_free(website_url);
website_url = strdup(value);
lth = strlen(website_url);
if (website_url[lth-1] == '/')
website_url[lth-1] = '\0';
}
else if(!strcmp(variable, "loadctl_options"))
error = set_loadctl_options(value, strlen(value)) != OK;
else if(!strcmp(variable, "check_workers"))
num_check_workers = atoi(value);
else if(!strcmp(variable, "query_socket")) {
my_free(qh_socket_path);
qh_socket_path = nspath_absolute(value, config_file_dir);
}
else if(!strcmp(variable, "log_file")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Log file is too long");
error = TRUE;
break;
}
my_free(log_file);
log_file = nspath_absolute(value, config_file_dir);
/* make sure the configured logfile takes effect */
close_log_file();
}
else if(!strcmp(variable, "debug_level"))
debug_level = atoi(value);
else if(!strcmp(variable, "debug_verbosity"))
debug_verbosity = atoi(value);
else if(!strcmp(variable, "debug_file")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Debug log file is too long");
error = TRUE;
break;
}
my_free(debug_file);
debug_file = nspath_absolute(value, config_file_dir);
}
else if(!strcmp(variable, "max_debug_file_size"))
max_debug_file_size = strtoul(value, NULL, 0);
else if(!strcmp(variable, "command_file")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Command file is too long");
error = TRUE;
break;
}
my_free(command_file);
command_file = nspath_absolute(value, config_file_dir);
/* save the macro */
mac->x[MACRO_COMMANDFILE] = command_file;
}
else if(!strcmp(variable, "temp_file")) {
my_free(temp_file);
temp_file = strdup(value);
}
else if(!strcmp(variable, "temp_path")) {
my_free(temp_path);
temp_path = nspath_absolute(value, config_file_dir);
}
else if(!strcmp(variable, "check_result_path")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Check result path is too long");
error = TRUE;
break;
}
my_free(check_result_path);
check_result_path = nspath_absolute(value, config_file_dir);
/* make sure we don't have a trailing slash */
if(check_result_path[strlen(check_result_path) - 1] == '/')
check_result_path[strlen(check_result_path) - 1] = '\x0';
if((tmpdir = opendir(check_result_path)) == NULL) {
asprintf(&error_message, "Check result path '%s' is not a valid directory", check_result_path);
error = TRUE;
break;
}
closedir(tmpdir);
}
else if(!strcmp(variable, "max_check_result_file_age"))
max_check_result_file_age = strtoul(value, NULL, 0);
else if(!strcmp(variable, "lock_file")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Lock file is too long");
error = TRUE;
break;
}
my_free(lock_file);
lock_file = nspath_absolute(value, config_file_dir);
}
else if(!strcmp(variable, "global_host_event_handler")) {
my_free(global_host_event_handler);
global_host_event_handler = (char *)strdup(value);
}
else if(!strcmp(variable, "global_service_event_handler")) {
my_free(global_service_event_handler);
global_service_event_handler = (char *)strdup(value);
}
else if(!strcmp(variable, "ocsp_command")) {
my_free(ocsp_command);
ocsp_command = (char *)strdup(value);
}
else if(!strcmp(variable, "ochp_command")) {
my_free(ochp_command);
ochp_command = (char *)strdup(value);
}
else if(!strcmp(variable, "nagios_user")) {
my_free(nagios_user);
nagios_user = (char *)strdup(value);
}
else if(!strcmp(variable, "nagios_group")) {
my_free(nagios_group);
nagios_group = (char *)strdup(value);
}
else if(!strcmp(variable, "admin_email")) {
/* save the macro */
my_free(mac->x[MACRO_ADMINEMAIL]);
mac->x[MACRO_ADMINEMAIL] = (char *)strdup(value);
}
else if(!strcmp(variable, "admin_pager")) {
/* save the macro */
my_free(mac->x[MACRO_ADMINPAGER]);
mac->x[MACRO_ADMINPAGER] = (char *)strdup(value);
}
else if(!strcmp(variable, "use_syslog")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for use_syslog");
error = TRUE;
break;
}
use_syslog = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_notifications")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_notifications");
error = TRUE;
break;
}
log_notifications = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_service_retries")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_service_retries");
error = TRUE;
break;
}
log_service_retries = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_host_retries")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_host_retries");
error = TRUE;
break;
}
log_host_retries = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_event_handlers")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_event_handlers");
error = TRUE;
break;
}
log_event_handlers = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_external_commands")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_external_commands");
error = TRUE;
break;
}
log_external_commands = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_passive_checks")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_passive_checks");
error = TRUE;
break;
}
log_passive_checks = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_initial_states")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_initial_states");
error = TRUE;
break;
}
log_initial_states = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_current_states")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for log_current_states");
error = TRUE;
break;
}
log_current_states = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "retain_state_information")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for retain_state_information");
error = TRUE;
break;
}
retain_state_information = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "retention_update_interval")) {
retention_update_interval = atoi(value);
if(retention_update_interval < 0) {
asprintf(&error_message, "Illegal value for retention_update_interval");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "use_retained_program_state")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for use_retained_program_state");
error = TRUE;
break;
}
use_retained_program_state = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "use_retained_scheduling_info")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for use_retained_scheduling_info");
error = TRUE;
break;
}
use_retained_scheduling_info = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "retention_scheduling_horizon")) {
retention_scheduling_horizon = atoi(value);
if(retention_scheduling_horizon <= 0) {
asprintf(&error_message, "Illegal value for retention_scheduling_horizon");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "additional_freshness_latency"))
additional_freshness_latency = atoi(value);
else if(!strcmp(variable, "retained_host_attribute_mask"))
retained_host_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "retained_service_attribute_mask"))
retained_service_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "retained_process_host_attribute_mask"))
retained_process_host_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "retained_process_service_attribute_mask"))
retained_process_service_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "retained_contact_host_attribute_mask"))
retained_contact_host_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "retained_contact_service_attribute_mask"))
retained_contact_service_attribute_mask = strtoul(value, NULL, 0);
else if(!strcmp(variable, "obsess_over_services")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for obsess_over_services");
error = TRUE;
break;
}
obsess_over_services = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "obsess_over_hosts")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for obsess_over_hosts");
error = TRUE;
break;
}
obsess_over_hosts = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "translate_passive_host_checks")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for translate_passive_host_checks");
error = TRUE;
break;
}
translate_passive_host_checks = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "passive_host_checks_are_soft"))
passive_host_checks_are_soft = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "service_check_timeout")) {
service_check_timeout = atoi(value);
if(service_check_timeout <= 0) {
asprintf(&error_message, "Illegal value for service_check_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable,"service_check_timeout_state")){
if(!strcmp(value,"o"))
service_check_timeout_state=STATE_OK;
else if(!strcmp(value,"w"))
service_check_timeout_state=STATE_WARNING;
else if(!strcmp(value,"c"))
service_check_timeout_state=STATE_CRITICAL;
else if(!strcmp(value,"u"))
service_check_timeout_state=STATE_UNKNOWN;
else{
asprintf(&error_message,"Illegal value for service_check_timeout_state");
error=TRUE;
break;
}
}
else if(!strcmp(variable, "host_check_timeout")) {
host_check_timeout = atoi(value);
if(host_check_timeout <= 0) {
asprintf(&error_message, "Illegal value for host_check_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "event_handler_timeout")) {
event_handler_timeout = atoi(value);
if(event_handler_timeout <= 0) {
asprintf(&error_message, "Illegal value for event_handler_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "notification_timeout")) {
notification_timeout = atoi(value);
if(notification_timeout <= 0) {
asprintf(&error_message, "Illegal value for notification_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "ocsp_timeout")) {
ocsp_timeout = atoi(value);
if(ocsp_timeout <= 0) {
asprintf(&error_message, "Illegal value for ocsp_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "ochp_timeout")) {
ochp_timeout = atoi(value);
if(ochp_timeout <= 0) {
asprintf(&error_message, "Illegal value for ochp_timeout");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "use_agressive_host_checking") || !strcmp(variable, "use_aggressive_host_checking")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for use_aggressive_host_checking");
error = TRUE;
break;
}
use_aggressive_host_checking = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "cached_host_check_horizon"))
cached_host_check_horizon = strtoul(value, NULL, 0);
else if(!strcmp(variable, "enable_predictive_host_dependency_checks"))
enable_predictive_host_dependency_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "cached_service_check_horizon"))
cached_service_check_horizon = strtoul(value, NULL, 0);
else if(!strcmp(variable, "enable_predictive_service_dependency_checks"))
enable_predictive_service_dependency_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "soft_state_dependencies")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for soft_state_dependencies");
error = TRUE;
break;
}
soft_state_dependencies = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "log_rotation_method")) {
if(!strcmp(value, "n"))
log_rotation_method = LOG_ROTATION_NONE;
else if(!strcmp(value, "h"))
log_rotation_method = LOG_ROTATION_HOURLY;
else if(!strcmp(value, "d"))
log_rotation_method = LOG_ROTATION_DAILY;
else if(!strcmp(value, "w"))
log_rotation_method = LOG_ROTATION_WEEKLY;
else if(!strcmp(value, "m"))
log_rotation_method = LOG_ROTATION_MONTHLY;
else {
asprintf(&error_message, "Illegal value for log_rotation_method");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "log_archive_path")) {
if(strlen(value) > MAX_FILENAME_LENGTH - 1) {
asprintf(&error_message, "Log archive path too long");
error = TRUE;
break;
}
my_free(log_archive_path);
log_archive_path = nspath_absolute(value, config_file_dir);
}
else if(!strcmp(variable, "enable_event_handlers"))
enable_event_handlers = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "enable_notifications"))
enable_notifications = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "execute_service_checks"))
execute_service_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "accept_passive_service_checks"))
accept_passive_service_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "execute_host_checks"))
execute_host_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "accept_passive_host_checks"))
accept_passive_host_checks = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "service_inter_check_delay_method")) {
if(!strcmp(value, "n"))
service_inter_check_delay_method = ICD_NONE;
else if(!strcmp(value, "d"))
service_inter_check_delay_method = ICD_DUMB;
else if(!strcmp(value, "s"))
service_inter_check_delay_method = ICD_SMART;
else {
service_inter_check_delay_method = ICD_USER;
scheduling_info.service_inter_check_delay = strtod(value, NULL);
if(scheduling_info.service_inter_check_delay <= 0.0) {
asprintf(&error_message, "Illegal value for service_inter_check_delay_method");
error = TRUE;
break;
}
}
}
else if(!strcmp(variable, "max_service_check_spread")) {
strip(value);
max_service_check_spread = atoi(value);
if(max_service_check_spread < 1) {
asprintf(&error_message, "Illegal value for max_service_check_spread");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "host_inter_check_delay_method")) {
if(!strcmp(value, "n"))
host_inter_check_delay_method = ICD_NONE;
else if(!strcmp(value, "d"))
host_inter_check_delay_method = ICD_DUMB;
else if(!strcmp(value, "s"))
host_inter_check_delay_method = ICD_SMART;
else {
host_inter_check_delay_method = ICD_USER;
scheduling_info.host_inter_check_delay = strtod(value, NULL);
if(scheduling_info.host_inter_check_delay <= 0.0) {
asprintf(&error_message, "Illegal value for host_inter_check_delay_method");
error = TRUE;
break;
}
}
}
else if(!strcmp(variable, "max_host_check_spread")) {
max_host_check_spread = atoi(value);
if(max_host_check_spread < 1) {
asprintf(&error_message, "Illegal value for max_host_check_spread");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "service_interleave_factor")) {
if(!strcmp(value, "s"))
service_interleave_factor_method = ILF_SMART;
else {
service_interleave_factor_method = ILF_USER;
scheduling_info.service_interleave_factor = atoi(value);
if(scheduling_info.service_interleave_factor < 1)
scheduling_info.service_interleave_factor = 1;
}
}
else if(!strcmp(variable, "max_concurrent_checks")) {
max_parallel_service_checks = atoi(value);
if(max_parallel_service_checks < 0) {
asprintf(&error_message, "Illegal value for max_concurrent_checks");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "check_result_reaper_frequency") || !strcmp(variable, "service_reaper_frequency")) {
check_reaper_interval = atoi(value);
if(check_reaper_interval < 1) {
asprintf(&error_message, "Illegal value for check_result_reaper_frequency");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "max_check_result_reaper_time")) {
max_check_reaper_time = atoi(value);
if(max_check_reaper_time < 1) {
asprintf(&error_message, "Illegal value for max_check_result_reaper_time");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "sleep_time")) {
obsoleted_warning(variable, NULL);
}
else if(!strcmp(variable, "interval_length")) {
interval_length = atoi(value);
if(interval_length < 1) {
asprintf(&error_message, "Illegal value for interval_length");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "check_external_commands")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for check_external_commands");
error = TRUE;
break;
}
check_external_commands = (atoi(value) > 0) ? TRUE : FALSE;
}
/* @todo Remove before Nagios 4.3 */
else if(!strcmp(variable, "command_check_interval")) {
obsoleted_warning(variable, "Commands are always handled on arrival");
}
else if(!strcmp(variable, "check_for_orphaned_services")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for check_for_orphaned_services");
error = TRUE;
break;
}
check_orphaned_services = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "check_for_orphaned_hosts")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for check_for_orphaned_hosts");
error = TRUE;
break;
}
check_orphaned_hosts = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "check_service_freshness")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for check_service_freshness");
error = TRUE;
break;
}
check_service_freshness = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "check_host_freshness")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for check_host_freshness");
error = TRUE;
break;
}
check_host_freshness = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "service_freshness_check_interval") || !strcmp(variable, "freshness_check_interval")) {
service_freshness_check_interval = atoi(value);
if(service_freshness_check_interval <= 0) {
asprintf(&error_message, "Illegal value for service_freshness_check_interval");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "host_freshness_check_interval")) {
host_freshness_check_interval = atoi(value);
if(host_freshness_check_interval <= 0) {
asprintf(&error_message, "Illegal value for host_freshness_check_interval");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "auto_reschedule_checks")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for auto_reschedule_checks");
error = TRUE;
break;
}
auto_reschedule_checks = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "auto_rescheduling_interval")) {
auto_rescheduling_interval = atoi(value);
if(auto_rescheduling_interval <= 0) {
asprintf(&error_message, "Illegal value for auto_rescheduling_interval");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "auto_rescheduling_window")) {
auto_rescheduling_window = atoi(value);
if(auto_rescheduling_window <= 0) {
asprintf(&error_message, "Illegal value for auto_rescheduling_window");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "status_update_interval")) {
status_update_interval = atoi(value);
if(status_update_interval < 1) {
asprintf(&error_message, "Illegal value for status_update_interval");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "time_change_threshold")) {
time_change_threshold = atoi(value);
if(time_change_threshold <= 5) {
asprintf(&error_message, "Illegal value for time_change_threshold");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "process_performance_data"))
process_performance_data = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "enable_flap_detection"))
enable_flap_detection = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "enable_failure_prediction"))
obsoleted_warning(variable, NULL);
else if(!strcmp(variable, "low_service_flap_threshold")) {
low_service_flap_threshold = strtod(value, NULL);
if(low_service_flap_threshold <= 0.0 || low_service_flap_threshold >= 100.0) {
asprintf(&error_message, "Illegal value for low_service_flap_threshold");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "high_service_flap_threshold")) {
high_service_flap_threshold = strtod(value, NULL);
if(high_service_flap_threshold <= 0.0 || high_service_flap_threshold > 100.0) {
asprintf(&error_message, "Illegal value for high_service_flap_threshold");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "low_host_flap_threshold")) {
low_host_flap_threshold = strtod(value, NULL);
if(low_host_flap_threshold <= 0.0 || low_host_flap_threshold >= 100.0) {
asprintf(&error_message, "Illegal value for low_host_flap_threshold");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "high_host_flap_threshold")) {
high_host_flap_threshold = strtod(value, NULL);
if(high_host_flap_threshold <= 0.0 || high_host_flap_threshold > 100.0) {
asprintf(&error_message, "Illegal value for high_host_flap_threshold");
error = TRUE;
break;
}
}
else if(!strcmp(variable, "date_format")) {
if(!strcmp(value, "euro"))
date_format = DATE_FORMAT_EURO;
else if(!strcmp(value, "iso8601"))
date_format = DATE_FORMAT_ISO8601;
else if(!strcmp(value, "strict-iso8601"))
date_format = DATE_FORMAT_STRICT_ISO8601;
else
date_format = DATE_FORMAT_US;
}
else if(!strcmp(variable, "use_timezone")) {
my_free(use_timezone);
use_timezone = (char *)strdup(value);
}
else if(!strcmp(variable, "event_broker_options")) {
if(!strcmp(value, "-1"))
event_broker_options = BROKER_EVERYTHING;
else
event_broker_options = strtoul(value, NULL, 0);
}
else if(!strcmp(variable, "illegal_object_name_chars"))
illegal_object_chars = (char *)strdup(value);
else if(!strcmp(variable, "illegal_macro_output_chars"))
illegal_output_chars = (char *)strdup(value);
else if(!strcmp(variable, "broker_module")) {
modptr = strtok(value, " \n");
argptr = strtok(NULL, "\n");
#ifdef USE_EVENT_BROKER
modptr = nspath_absolute(modptr, config_file_dir);
if (modptr) {
neb_add_module(modptr, argptr, TRUE);
free(modptr);
}
else {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to allocate module path memory for '%s'\n", value);
}
#endif
}
else if(!strcmp(variable, "use_regexp_matching"))
use_regexp_matches = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "use_true_regexp_matching"))
use_true_regexp_matching = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "daemon_dumps_core")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for daemon_dumps_core");
error = TRUE;
break;
}
daemon_dumps_core = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "use_large_installation_tweaks")) {
if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') {
asprintf(&error_message, "Illegal value for use_large_installation_tweaks ");
error = TRUE;
break;
}
use_large_installation_tweaks = (atoi(value) > 0) ? TRUE : FALSE;
}
else if(!strcmp(variable, "enable_environment_macros"))
enable_environment_macros = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "free_child_process_memory"))
free_child_process_memory = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "child_processes_fork_twice"))
child_processes_fork_twice = (atoi(value) > 0) ? TRUE : FALSE;
/*** embedded perl variables are deprecated now ***/
else if(!strcmp(variable, "enable_embedded_perl"))
obsoleted_warning(variable, NULL);
else if(!strcmp(variable, "use_embedded_perl_implicitly"))
obsoleted_warning(variable, NULL);
else if(!strcmp(variable, "auth_file"))
obsoleted_warning(variable, NULL);
else if(!strcmp(variable, "p1_file"))
obsoleted_warning(variable, NULL);
/*** as is external_command_buffer_slots */
else if(!strcmp(variable, "external_command_buffer_slots"))
obsoleted_warning(variable, "All commands are always processed upon arrival");
else if(!strcmp(variable, "check_for_updates"))
check_for_updates = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable, "bare_update_check"))
bare_update_check = (atoi(value) > 0) ? TRUE : FALSE;
/* BEGIN status data variables */
else if(!strcmp(variable, "status_file"))
status_file = nspath_absolute(value, config_file_dir);
else if(strstr(input, "state_retention_file=") == input)
retention_file = nspath_absolute(value, config_file_dir);
/* END status data variables */
/*** BEGIN perfdata variables ***/
else if(!strcmp(variable, "perfdata_timeout")) {
perfdata_timeout = atoi(value);
}
else if(!strcmp(variable, "host_perfdata_command"))
host_perfdata_command = (char *)strdup(value);
else if(!strcmp(variable, "service_perfdata_command"))
service_perfdata_command = (char *)strdup(value);
else if(!strcmp(variable, "host_perfdata_file_template"))
host_perfdata_file_template = (char *)strdup(value);
else if(!strcmp(variable, "service_perfdata_file_template"))
service_perfdata_file_template = (char *)strdup(value);
else if(!strcmp(variable, "host_perfdata_file"))
host_perfdata_file = nspath_absolute(value, config_file_dir);
else if(!strcmp(variable, "service_perfdata_file"))
service_perfdata_file = nspath_absolute(value, config_file_dir);
else if(!strcmp(variable, "host_perfdata_file_mode")) {
host_perfdata_file_pipe = FALSE;
if(strstr(value, "p") != NULL)
host_perfdata_file_pipe = TRUE;
else if(strstr(value, "w") != NULL)
host_perfdata_file_append = FALSE;
else
host_perfdata_file_append = TRUE;
}
else if(!strcmp(variable, "service_perfdata_file_mode")) {
service_perfdata_file_pipe = FALSE;
if(strstr(value, "p") != NULL)
service_perfdata_file_pipe = TRUE;
else if(strstr(value, "w") != NULL)
service_perfdata_file_append = FALSE;
else
service_perfdata_file_append = TRUE;
}
else if(!strcmp(variable, "host_perfdata_file_processing_interval"))
host_perfdata_file_processing_interval = strtoul(value, NULL, 0);
else if(!strcmp(variable, "service_perfdata_file_processing_interval"))
service_perfdata_file_processing_interval = strtoul(value, NULL, 0);
else if(!strcmp(variable, "host_perfdata_file_processing_command"))
host_perfdata_file_processing_command = (char *)strdup(value);
else if(!strcmp(variable, "service_perfdata_file_processing_command"))
service_perfdata_file_processing_command = (char *)strdup(value);
else if(!strcmp(variable,"host_perfdata_process_empty_results"))
host_perfdata_process_empty_results = (atoi(value) > 0) ? TRUE : FALSE;
else if(!strcmp(variable,"service_perfdata_process_empty_results"))
service_perfdata_process_empty_results = (atoi(value) > 0) ? TRUE : FALSE;
/*** END perfdata variables */
else if(strstr(input, "cfg_file=") == input || strstr(input, "cfg_dir=") == input)
continue;
else if(strstr(input, "object_cache_file=") == input) {
my_free(object_cache_file);
object_cache_file = nspath_absolute(value, config_file_dir);
my_free(mac->x[MACRO_OBJECTCACHEFILE]);
mac->x[MACRO_OBJECTCACHEFILE] = strdup(object_cache_file);
}
else if(strstr(input, "precached_object_file=") == input) {
my_free(object_precache_file);
object_precache_file = nspath_absolute(value, config_file_dir);
}
else if(!strcmp(variable, "allow_empty_hostgroup_assignment")) {
allow_empty_hostgroup_assignment = (atoi(value) > 0) ? TRUE : FALSE;
}
/* skip external data directives */
else if(strstr(input, "x") == input)
continue;
else if(!strcmp(variable,"host_down_disable_service_checks")) {
host_down_disable_service_checks = strtoul(value, NULL, 0);
}
else if(!strcmp(variable,"service_skip_check_dependency_status")) {
service_skip_check_dependency_status = atoi(value);
if(service_skip_check_dependency_status < -1 || service_skip_check_dependency_status > 3) {
asprintf(&error_message, "Illegal value for service_skip_check_dependency_status");
error = TRUE;
break;
}
}
else if(!strcmp(variable,"service_skip_check_parent_status")) {
service_skip_check_parent_status = atoi(value);
if(service_skip_check_parent_status < -1 || service_skip_check_parent_status > 3) {
asprintf(&error_message, "Illegal value for service_skip_check_parent_status");
error = TRUE;
break;
}
}
else if(!strcmp(variable,"service_skip_check_host_down_status")) {
service_skip_check_host_down_status = atoi(value);
if(service_skip_check_host_down_status < -1 || service_skip_check_host_down_status > 3) {
asprintf(&error_message, "Illegal value for service_skip_check_host_down_status");
error = TRUE;
break;
}
}
else if(!strcmp(variable,"host_skip_check_dependency_status")) {
host_skip_check_dependency_status = atoi(value);
if(host_skip_check_dependency_status < -1 || host_skip_check_dependency_status > 3) {
asprintf(&error_message, "Illegal value for host_skip_check_dependency_status");
error = TRUE;
break;
}
}
/* we don't know what this variable is... */
else {
asprintf(&error_message, "UNKNOWN VARIABLE");
error = TRUE;
break;
}
}
if (deprecated) {
for (list = deprecated; list; list = list->next) {
logit(NSLOG_CONFIG_WARNING, TRUE, "%s", (char *)list->object_ptr);
free(list->object_ptr);
}
free_objectlist(&deprecated);
deprecated = NULL;
}
if (!temp_path && !(temp_path = getenv("TMPDIR")) && !(temp_path = getenv("TMP"))) {
temp_path = strdup("/tmp");
}
else {
/* make sure we don't have a trailing slash */
if(temp_path[strlen(temp_path) - 1] == '/')
temp_path[strlen(temp_path) - 1] = '\x0';
}
if((strlen(temp_path) > MAX_FILENAME_LENGTH - 1)) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: temp_path is too long\n");
return ERROR;
}
if((tmpdir = opendir(temp_path)) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: temp_path '%s' is not a valid directory\n", temp_path);
return ERROR;
}
closedir(tmpdir);
/* now that we know we have temp_path, we can set temp_file properly */
if (!temp_file) {
temp_file = nspath_absolute("nagios.tmp", temp_path);
}
else if (*temp_file == '.') {
/* temp_file is relative. Make it nagios.cfg-relative */
char *foo = temp_file;
temp_file = nspath_absolute(temp_file, config_file_dir);
free(foo);
}
else if (*temp_file != '/') {
/*
* tempfile is not relative and not absolute, so
* put it in temp_path
*/
char *foo = temp_file;
temp_file = nspath_absolute(temp_file, temp_path);
free(foo);
}
if(strlen(temp_file) > MAX_FILENAME_LENGTH - 1) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Temp file '%s' is too long\n", temp_file);
return ERROR;
}
/* save the macros */
mac->x[MACRO_TEMPPATH] = temp_path;
mac->x[MACRO_TEMPFILE] = temp_file;
/* adjust timezone values */
if(use_timezone != NULL)
set_environment_var("TZ", use_timezone, 1);
tzset();
/* adjust tweaks */
if(free_child_process_memory == -1)
free_child_process_memory = (use_large_installation_tweaks == TRUE) ? FALSE : TRUE;
if(child_processes_fork_twice == -1)
child_processes_fork_twice = (use_large_installation_tweaks == TRUE) ? FALSE : TRUE;
/* handle errors */
if(error == TRUE) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error in configuration file '%s' - Line %d (%s)", main_config_file, current_line, (error_message == NULL) ? "NULL" : error_message);
return ERROR;
}
/* free leftover memory and close the file */
my_free(input);
mmap_fclose(thefile);
/* free memory */
my_free(error_message);
my_free(input);
my_free(variable);
my_free(value);
/* make sure a log file has been specified */
if(log_file == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Log file is not specified anywhere in main config file '%s'!", main_config_file);
exit(ERROR);
}
strip(log_file);
return OK;
}
/* processes macros in resource file */
int read_resource_file(char *resource_file) {
char *input = NULL;
char *variable = NULL;
char *value = NULL;
char *temp_ptr = NULL;
mmapfile *thefile = NULL;
int current_line = 1;
int error = FALSE;
int user_index = 0;
if((thefile = mmap_fopen(resource_file)) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Cannot open resource file '%s' for reading!", resource_file);
return ERROR;
}
/* process all lines in the resource file */
while(1) {
/* free memory */
my_free(input);
my_free(variable);
my_free(value);
/* read the next line */
if((input = mmap_fgets_multiline(thefile)) == NULL)
break;
current_line = thefile->current_line;
/* skip blank lines and comments */
if(input[0] == '#' || input[0] == '\x0' || input[0] == '\n' || input[0] == '\r')
continue;
strip(input);
/* get the variable name */
if((temp_ptr = my_strtok_with_free(input, "=", FALSE)) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable - Line %d of resource file '%s'", current_line, resource_file);
error = TRUE;
break;
}
if((variable = (char *)strdup(temp_ptr)) == NULL) {
error = TRUE;
break;
}
/* get the value */
if((temp_ptr = my_strtok_with_free(NULL, "\n", FALSE)) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL variable value - Line %d of resource file '%s'", current_line, resource_file);
error = TRUE;
break;
}
if((value = (char *)strdup(temp_ptr)) == NULL) {
error = TRUE;
break;
}
temp_ptr = my_strtok_with_free(NULL, "\n", TRUE);
/* what should we do with the variable/value pair? */
/* check for macro declarations */
if(variable[0] == '$' && variable[strlen(variable) - 1] == '$') {
/* $USERx$ macro declarations */
if(strstr(variable, "$USER") == variable && strlen(variable) > 5) {
user_index = atoi(variable + 5) - 1;
if(user_index >= 0 && user_index < MAX_USER_MACROS) {
my_free(macro_user[user_index]);
macro_user[user_index] = (char *)strdup(value);
}
}
}
}
/* free leftover memory and close the file */
my_free(input);
mmap_fclose(thefile);
/* free memory */
my_free(variable);
my_free(value);
if(error == TRUE)
return ERROR;
return OK;
}
/****************************************************************/
/**************** CONFIG VERIFICATION FUNCTIONS *****************/
/****************************************************************/
/* do a pre-flight check to make sure object relationships, etc. make sense */
int pre_flight_check(void) {
char *buf = NULL;
int warnings = 0;
int errors = 0;
struct timeval tv[4];
double runtime[4];
int temp_path_fd = -1;
if(test_scheduling == TRUE)
gettimeofday(&tv[0], NULL);
/********************************************/
/* check object relationships */
/********************************************/
pre_flight_object_check(&warnings, &errors);
if(test_scheduling == TRUE)
gettimeofday(&tv[1], NULL);
/********************************************/
/* check for circular paths between hosts */
/********************************************/
pre_flight_circular_check(&warnings, &errors);
if(test_scheduling == TRUE)
gettimeofday(&tv[2], NULL);
/********************************************/
/* check global event handler commands... */
/********************************************/
if(verify_config)
printf("Checking global event handlers...\n");
if(global_host_event_handler != NULL) {
global_host_event_handler_ptr = find_bang_command(global_host_event_handler);
if (global_host_event_handler_ptr == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Global host event handler command '%s' is not defined anywhere!", global_host_event_handler);
errors++;
}
}
if(global_service_event_handler != NULL) {
global_service_event_handler_ptr = find_bang_command(global_service_event_handler);
if (global_service_event_handler_ptr == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Global service event handler command '%s' is not defined anywhere!", global_service_event_handler);
errors++;
}
}
/**************************************************/
/* check obsessive processor commands... */
/**************************************************/
if(verify_config)
printf("Checking obsessive compulsive processor commands...\n");
if(ocsp_command != NULL) {
ocsp_command_ptr = find_bang_command(ocsp_command);
if (!ocsp_command_ptr) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: OCSP command '%s' is not defined anywhere!\n", ocsp_command);
errors++;
}
}
if(ochp_command != NULL) {
ochp_command_ptr = find_bang_command(ochp_command);
if (!ochp_command_ptr) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: OCHP command '%s' is not defined anywhere!\n", ochp_command);
errors++;
}
}
/**************************************************/
/* check various settings... */
/**************************************************/
if(verify_config)
printf("Checking misc settings...\n");
/* check if we can write to temp_path */
asprintf(&buf, "%s/nagiosXXXXXX", temp_path);
if((temp_path_fd = mkstemp(buf)) == -1) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "\tError: Unable to write to temp_path ('%s') - %s\n", temp_path, strerror(errno));
errors++;
}
else {
close(temp_path_fd);
remove(buf);
}
my_free(buf);
/* check if we can write to check_result_path */
asprintf(&buf, "%s/nagiosXXXXXX", check_result_path);
if((temp_path_fd = mkstemp(buf)) == -1) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "\tError: Unable to write to check_result_path ('%s') - %s\n", check_result_path, strerror(errno));
errors++;
}
else {
close(temp_path_fd);
remove(buf);
}
my_free(buf);
/* warn if user didn't specify any illegal macro output chars */
if(illegal_output_chars == NULL) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "%s", "Warning: Nothing specified for illegal_macro_output_chars variable!\n");
warnings++;
}
else {
char *p;
for(p = illegal_output_chars; *p; p++) {
illegal_output_char_map[(int)*p] = 1;
}
}
if(verify_config) {
printf("\n");
printf("Total Warnings: %d\n", warnings);
printf("Total Errors: %d\n", errors);
}
if(test_scheduling == TRUE)
gettimeofday(&tv[3], NULL);
if(test_scheduling == TRUE) {
runtime[0] = tv_delta_f(&tv[0], &tv[1]);
runtime[1] = tv_delta_f(&tv[1], &tv[2]);
runtime[2] = (double)((double)(tv[3].tv_sec - tv[2].tv_sec) + (double)((tv[3].tv_usec - tv[2].tv_usec) / 1000.0) / 1000.0);
runtime[3] = runtime[0] + runtime[1] + runtime[2];
printf("Timing information on configuration verification is listed below.\n\n");
printf("CONFIG VERIFICATION TIMES\n");
printf("----------------------------------\n");
printf("Object Relationships: %.6lf sec\n", runtime[0]);
printf("Circular Paths: %.6lf sec\n", runtime[1]);
printf("Misc: %.6lf sec\n", runtime[2]);
printf(" ============\n");
printf("TOTAL: %.6lf sec\n", runtime[3]);
printf("\n\n");
}
return (errors > 0) ? ERROR : OK;
}
/* do a pre-flight check to make sure object relationships make sense */
int pre_flight_object_check(int *w, int *e) {
contact *temp_contact = NULL;
commandsmember *temp_commandsmember = NULL;
contactgroup *temp_contactgroup = NULL;
host *temp_host = NULL;
host *temp_host2 = NULL;
hostsmember *temp_hostsmember = NULL;
servicesmember *sm = NULL;
hostgroup *temp_hostgroup = NULL;
servicegroup *temp_servicegroup = NULL;
service *temp_service = NULL;
command *temp_command = NULL;
timeperiod *temp_timeperiod = NULL;
timeperiod *temp_timeperiod2 = NULL;
timeperiodexclusion *temp_timeperiodexclusion = NULL;
int total_objects = 0;
int warnings = 0;
int errors = 0;
#ifdef TEST
void *ptr = NULL;
char *buf1 = "";
char *buf2 = "";
buf1 = "temptraxe1";
buf2 = "Probe 2";
for(temp_se = get_first_serviceescalation_by_service(buf1, buf2, &ptr); temp_se != NULL; temp_se = get_next_serviceescalation_by_service(buf1, buf2, &ptr)) {
printf("FOUND ESCALATION FOR SVC '%s'/'%s': %d-%d/%.3f, PTR=%p\n", buf1, buf2, temp_se->first_notification, temp_se->last_notification, temp_se->notification_interval, ptr);
}
for(temp_he = get_first_hostescalation_by_host(buf1, &ptr); temp_he != NULL; temp_he = get_next_hostescalation_by_host(buf1, &ptr)) {
printf("FOUND ESCALATION FOR HOST '%s': %d-%d/%d, PTR=%p\n", buf1, temp_he->first_notification, temp_he->last_notification, temp_he->notification_interval, ptr);
}
#endif
if(verify_config)
printf("Checking objects...\n");
/*****************************************/
/* check each service... */
/*****************************************/
if(get_service_count() == 0) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: There are no services defined!");
errors++;
}
total_objects = 0;
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
total_objects++;
/* check the event handler command */
if(temp_service->event_handler != NULL) {
temp_service->event_handler_ptr = find_bang_command(temp_service->event_handler);
if(temp_service->event_handler_ptr == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Event handler command '%s' specified in service '%s' for host '%s' not defined anywhere", temp_service->event_handler, temp_service->description, temp_service->host_name);
errors++;
}
}
/* check the service check_command */
temp_service->check_command_ptr = find_bang_command(temp_service->check_command);
if(temp_service->check_command_ptr == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service check command '%s' specified in service '%s' for host '%s' not defined anywhere!", temp_service->check_command, temp_service->description, temp_service->host_name);
errors++;
}
/* check for sane recovery options */
if(temp_service->notification_options == OPT_RECOVERY) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Recovery notification option in service '%s' for host '%s' doesn't make any sense - specify warning and/or critical options as well", temp_service->description, temp_service->host_name);
warnings++;
}
/* check to see if there is at least one contact/group */
if(temp_service->contacts == NULL && temp_service->contact_groups == NULL) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has no default contacts or contactgroups defined!", temp_service->description, temp_service->host_name);
warnings++;
}
/* verify service check timeperiod */
if(temp_service->check_period == NULL) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has no check time period defined!", temp_service->description, temp_service->host_name);
warnings++;
}
/* check service notification timeperiod */
if(temp_service->notification_period == NULL) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has no notification time period defined!", temp_service->description, temp_service->host_name);
warnings++;
}
/* check parent services */
for(sm = temp_service->parents; sm; sm = sm->next) {
sm->service_ptr = find_service(sm->host_name, sm->service_description);
if(sm->service_ptr == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' is not a valid parent for service '%s' on host '%s'\n",
sm->host_name, sm->service_description,
temp_service->host_name, temp_service->description);
errors++;
}
/* add a reverse (child) link to make searches faster later on */
add_child_link_to_service(sm->service_ptr, temp_service);
}
/* see if the notification interval is less than the check interval */
if(temp_service->notification_interval < temp_service->check_interval && temp_service->notification_interval != 0) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has a notification interval less than its check interval! Notifications are only re-sent after checks are made, so the effective notification interval will be that of the check interval.", temp_service->description, temp_service->host_name);
warnings++;
}
/* check for illegal characters in service description */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_service->description) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The description string for service '%s' on host '%s' contains one or more illegal characters.", temp_service->description, temp_service->host_name);
errors++;
}
}
}
if(verify_config)
printf("\tChecked %d services.\n", total_objects);
/*****************************************/
/* check all hosts... */
/*****************************************/
if(get_host_count() == 0) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: There are no hosts defined!");
errors++;
}
total_objects = 0;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
total_objects++;
/* make sure each host has at least one service associated with it */
if(temp_host->total_services == 0 && verify_config >= 2) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host '%s' has no services associated with it!", temp_host->name);
warnings++;
}
/* check the event handler command */
if(temp_host->event_handler != NULL) {
temp_host->event_handler_ptr = find_bang_command(temp_host->event_handler);
if(temp_host->event_handler_ptr == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Event handler command '%s' specified for host '%s' not defined anywhere", temp_host->event_handler, temp_host->name);
errors++;
}
}
/* hosts that don't have check commands defined shouldn't ever be checked... */
if(temp_host->check_command != NULL) {
temp_host->check_command_ptr = find_bang_command(temp_host->check_command);
if(temp_host->check_command_ptr == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host check command '%s' specified for host '%s' is not defined anywhere!", temp_host->check_command, temp_host->name);
errors++;
}
}
/* check host check timeperiod */
if(temp_host->check_period != NULL) {
temp_timeperiod = find_timeperiod(temp_host->check_period);
if(temp_timeperiod == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Check period '%s' specified for host '%s' is not defined anywhere!", temp_host->check_period, temp_host->name);
errors++;
}
/* save the pointer to the check timeperiod for later */
temp_host->check_period_ptr = temp_timeperiod;
}
/* check to see if there is at least one contact/group */
if(temp_host->contacts == NULL && temp_host->contact_groups == NULL) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host '%s' has no default contacts or contactgroups defined!", temp_host->name);
warnings++;
}
/* check notification timeperiod */
if(temp_host->notification_period != NULL) {
temp_timeperiod = find_timeperiod(temp_host->notification_period);
if(temp_timeperiod == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Notification period '%s' specified for host '%s' is not defined anywhere!", temp_host->notification_period, temp_host->name);
errors++;
}
/* save the pointer to the notification timeperiod for later */
temp_host->notification_period_ptr = temp_timeperiod;
}
/* check all parent parent host */
for(temp_hostsmember = temp_host->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) {
if((temp_host2 = find_host(temp_hostsmember->host_name)) == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: '%s' is not a valid parent for host '%s'!", temp_hostsmember->host_name, temp_host->name);
errors++;
}
/* save the parent host pointer for later */
temp_hostsmember->host_ptr = temp_host2;
/* add a reverse (child) link to make searches faster later on */
add_child_link_to_host(temp_host2, temp_host);
}
/* check for sane recovery options */
if(temp_host->notification_options == OPT_RECOVERY) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Recovery notification option in host '%s' definition doesn't make any sense - specify down and/or unreachable options as well", temp_host->name);
warnings++;
}
/* check for illegal characters in host name */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_host->name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of host '%s' contains one or more illegal characters.", temp_host->name);
errors++;
}
}
}
if(verify_config)
printf("\tChecked %d hosts.\n", total_objects);
/*****************************************/
/* check each host group... */
/*****************************************/
for(temp_hostgroup = hostgroup_list, total_objects = 0; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next, total_objects++) {
/* check for illegal characters in hostgroup name */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_hostgroup->group_name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of hostgroup '%s' contains one or more illegal characters.", temp_hostgroup->group_name);
errors++;
}
}
}
if(verify_config)
printf("\tChecked %d host groups.\n", total_objects);
/*****************************************/
/* check each service group... */
/*****************************************/
for(temp_servicegroup = servicegroup_list, total_objects = 0; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next, total_objects++) {
/* check for illegal characters in servicegroup name */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_servicegroup->group_name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of servicegroup '%s' contains one or more illegal characters.", temp_servicegroup->group_name);
errors++;
}
}
}
if(verify_config)
printf("\tChecked %d service groups.\n", total_objects);
/*****************************************/
/* check all contacts... */
/*****************************************/
if(contact_list == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: There are no contacts defined!");
errors++;
}
for(temp_contact = contact_list, total_objects = 0; temp_contact != NULL; temp_contact = temp_contact->next, total_objects++) {
/* check service notification commands */
if(temp_contact->service_notification_commands == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' has no service notification commands defined!", temp_contact->name);
errors++;
}
else for(temp_commandsmember = temp_contact->service_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) {
temp_commandsmember->command_ptr = find_bang_command(temp_commandsmember->command);
if(temp_commandsmember->command_ptr == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification command '%s' specified for contact '%s' is not defined anywhere!", temp_commandsmember->command, temp_contact->name);
errors++;
}
}
/* check host notification commands */
if(temp_contact->host_notification_commands == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' has no host notification commands defined!", temp_contact->name);
errors++;
}
else for(temp_commandsmember = temp_contact->host_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) {
temp_commandsmember->command_ptr = find_bang_command(temp_commandsmember->command);
if(temp_commandsmember->command_ptr == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification command '%s' specified for contact '%s' is not defined anywhere!", temp_commandsmember->command, temp_contact->name);
errors++;
}
}
/* check service notification timeperiod */
if(temp_contact->service_notification_period == NULL) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Contact '%s' has no service notification time period defined!", temp_contact->name);
warnings++;
}
else {
temp_timeperiod = find_timeperiod(temp_contact->service_notification_period);
if(temp_timeperiod == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification period '%s' specified for contact '%s' is not defined anywhere!", temp_contact->service_notification_period, temp_contact->name);
errors++;
}
/* save the pointer to the service notification timeperiod for later */
temp_contact->service_notification_period_ptr = temp_timeperiod;
}
/* check host notification timeperiod */
if(temp_contact->host_notification_period == NULL) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Contact '%s' has no host notification time period defined!", temp_contact->name);
warnings++;
}
else {
temp_timeperiod = find_timeperiod(temp_contact->host_notification_period);
if(temp_timeperiod == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification period '%s' specified for contact '%s' is not defined anywhere!", temp_contact->host_notification_period, temp_contact->name);
errors++;
}
/* save the pointer to the host notification timeperiod for later */
temp_contact->host_notification_period_ptr = temp_timeperiod;
}
/* check for sane host recovery options */
if(temp_contact->host_notification_options == OPT_RECOVERY) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host recovery notification option for contact '%s' doesn't make any sense - specify down and/or unreachable options as well", temp_contact->name);
warnings++;
}
/* check for sane service recovery options */
if(temp_contact->service_notification_options == OPT_RECOVERY) {
logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service recovery notification option for contact '%s' doesn't make any sense - specify critical and/or warning options as well", temp_contact->name);
warnings++;
}
/* check for illegal characters in contact name */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_contact->name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of contact '%s' contains one or more illegal characters.", temp_contact->name);
errors++;
}
}
}
if(verify_config)
printf("\tChecked %d contacts.\n", total_objects);
/*****************************************/
/* check each contact group... */
/*****************************************/
for(temp_contactgroup = contactgroup_list, total_objects = 0; temp_contactgroup != NULL; temp_contactgroup = temp_contactgroup->next, total_objects++) {
/* check for illegal characters in contactgroup name */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_contactgroup->group_name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of contact group '%s' contains one or more illegal characters.", temp_contactgroup->group_name);
errors++;
}
}
}
if(verify_config)
printf("\tChecked %d contact groups.\n", total_objects);
/*****************************************/
/* check all commands... */
/*****************************************/
for(temp_command = command_list, total_objects = 0; temp_command != NULL; temp_command = temp_command->next, total_objects++) {
/* check for illegal characters in command name */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_command->name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of command '%s' contains one or more illegal characters.", temp_command->name);
errors++;
}
}
}
if(verify_config)
printf("\tChecked %d commands.\n", total_objects);
/*****************************************/
/* check all timeperiods... */
/*****************************************/
for(temp_timeperiod = timeperiod_list, total_objects = 0; temp_timeperiod != NULL; temp_timeperiod = temp_timeperiod->next, total_objects++) {
/* check for illegal characters in timeperiod name */
if(use_precached_objects == FALSE) {
if(contains_illegal_object_chars(temp_timeperiod->name) == TRUE) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The name of time period '%s' contains one or more illegal characters.", temp_timeperiod->name);
errors++;
}
}
/* check for valid timeperiod names in exclusion list */
for(temp_timeperiodexclusion = temp_timeperiod->exclusions; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) {
temp_timeperiod2 = find_timeperiod(temp_timeperiodexclusion->timeperiod_name);
if(temp_timeperiod2 == NULL) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Excluded time period '%s' specified in timeperiod '%s' is not defined anywhere!", temp_timeperiodexclusion->timeperiod_name, temp_timeperiod->name);
errors++;
}
/* save the timeperiod pointer for later */
temp_timeperiodexclusion->timeperiod_ptr = temp_timeperiod2;
}
}
if(verify_config)
printf("\tChecked %d time periods.\n", total_objects);
/* help people use scripts to verify that objects are loaded */
if(verify_config) {
printf("\tChecked %u host escalations.\n", num_objects.hostescalations);
printf("\tChecked %u service escalations.\n", num_objects.serviceescalations);
}
/* update warning and error count */
*w += warnings;
*e += errors;
return (errors > 0) ? ERROR : OK;
}
/* dfs status values */
#define DFS_UNCHECKED 0 /* default value */
#define DFS_TEMP_CHECKED 1 /* check just one time */
#define DFS_OK 2 /* no problem */
#define DFS_NEAR_LOOP 3 /* has trouble sons */
#define DFS_LOOPY 4 /* is a part of a loop */
#define dfs_get_status(obj) (obj ? ary[obj->id] : DFS_OK)
#define dfs_set_status(obj, value) ary[obj->id] = (value)
/**
* Modified version of Depth-first Search
* http://en.wikipedia.org/wiki/Depth-first_search
*
* In a dependency tree like this (parent->child, dep->dep or whatever):
* A - B C
* \ /
* D
* / \
* E - F - G
* / \\
* H H
*
* ... we look at the nodes in the following order:
* A B D C G (marking all of them as OK)
* E F D G H F (D,G are already OK, E is marked near-loopy F and H are loopy)
* H (which is already marked as loopy, so we don't follow it)
*
* We look at each node at most once per parent, so the algorithm has
* O(nx) worst-case complexity,, where x is the average number of
* parents.
*/
/*
* same as dfs_host_path, but we flip the the tree and traverse it
* backwards, since core Nagios doesn't need the child pointer at
* later stages.
*/
static int dfs_servicedep_path(char *ary, service *root, int dep_type, int *errors)
{
objectlist *olist;
int status;
status = dfs_get_status(root);
if(status != DFS_UNCHECKED)
return status;
dfs_set_status(root, DFS_TEMP_CHECKED);
if (dep_type == NOTIFICATION_DEPENDENCY) {
olist = root->notify_deps;
} else {
olist = root->exec_deps;
}
if (!olist) { /* no children, so we can't be loopy */
dfs_set_status(root, DFS_OK);
return DFS_OK;
}
for (; olist; olist = olist->next) {
int child_status;
service *child;
servicedependency *child_dep = (servicedependency *)olist->object_ptr;
/* tree is upside down, so look to master */
child = child_dep->master_service_ptr;
child_status = dfs_servicedep_path(ary, child, dep_type, errors);
if (child_status == DFS_OK)
continue;
if(child_status == DFS_TEMP_CHECKED) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Circular %s dependency detected for services '%s;%s' and '%s;%s'\n",
dep_type == NOTIFICATION_DEPENDENCY ? "notification" : "execution",
root->host_name, root->description,
child->host_name, child->description);
(*errors)++;
dfs_set_status(child, DFS_LOOPY);
dfs_set_status(root, DFS_LOOPY);
continue;
}
}
/*
* if we've hit ourself, we'll have marked us as loopy
* above, so if we're TEMP_CHECKED still we're ok
*/
if (dfs_get_status(root) == DFS_TEMP_CHECKED)
dfs_set_status(root, DFS_OK);
return dfs_get_status(root);
}
static int dfs_hostdep_path(char *ary, host *root, int dep_type, int *errors)
{
objectlist *olist;
int status;
status = dfs_get_status(root);
if(status != DFS_UNCHECKED)
return status;
dfs_set_status(root, DFS_TEMP_CHECKED);
if (dep_type == NOTIFICATION_DEPENDENCY) {
olist = root->notify_deps;
} else {
olist = root->exec_deps;
}
for (; olist; olist = olist->next) {
int child_status;
host *child;
hostdependency *child_dep = (hostdependency *)olist->object_ptr;
child = child_dep->master_host_ptr;
child_status = dfs_hostdep_path(ary, child, dep_type, errors);
if (child_status == DFS_OK)
continue;
if(child_status == DFS_TEMP_CHECKED) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Circular %s dependency detected for hosts '%s' and '%s'\n",
dep_type == NOTIFICATION_DEPENDENCY ? "notification" : "execution",
root->name, child->name);
dfs_set_status(child, DFS_LOOPY);
dfs_set_status(root, DFS_LOOPY);
(*errors)++;
continue;
}
}
/*
* if we've hit ourself, we'll have marked us as loopy
* above, so if we're still TEMP_CHECKED we're ok
*/
if (dfs_get_status(root) == DFS_TEMP_CHECKED)
dfs_set_status(root, DFS_OK);
return dfs_get_status(root);
}
static int dfs_host_path(char *ary, host *root, int *errors) {
hostsmember *child = NULL;
if(dfs_get_status(root) != DFS_UNCHECKED)
return dfs_get_status(root);
/* Mark the root temporary checked */
dfs_set_status(root, DFS_TEMP_CHECKED);
/* We are scanning the children */
for(child = root->child_hosts; child != NULL; child = child->next) {
int child_status = dfs_host_path(ary, child->host_ptr, errors);
/* we can move on quickly if child is ok */
if(child_status == DFS_OK)
continue;
/* If a child already temporary checked, its a problem,
* loop inside, and its a acked status */
if(child_status == DFS_TEMP_CHECKED) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The hosts '%s' and '%s' form or lead into a circular parent/child chain!", root->name, child->host_ptr->name);
(*errors)++;
dfs_set_status(child->host_ptr, DFS_LOOPY);
dfs_set_status(root, DFS_LOOPY);
continue;
}
}
/*
* If root have been modified, do not set it OK
* A node is OK if and only if all of his children are OK
* If it does not have child, goes ok
*/
if(dfs_get_status(root) == DFS_TEMP_CHECKED)
dfs_set_status(root, DFS_OK);
return dfs_get_status(root);
}
static int dfs_timeperiod_path(char *ary, timeperiod *root, int *errors)
{
timeperiodexclusion *exc;
if(dfs_get_status(root) != DFS_UNCHECKED)
return dfs_get_status(root);
/* Mark the root temporary checked */
dfs_set_status(root, DFS_TEMP_CHECKED);
for (exc = root->exclusions; exc; exc = exc->next) {
int child_status = dfs_timeperiod_path(ary, exc->timeperiod_ptr, errors);
if(child_status == DFS_TEMP_CHECKED) {
logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The timeperiods '%s' and '%s' form or lead into a circular exclusion chain!",
root->name, exc->timeperiod_ptr->name);
(*errors)++;
dfs_set_status(exc->timeperiod_ptr, DFS_LOOPY);
dfs_set_status(root, DFS_LOOPY);
continue;
}
}
if(dfs_get_status(root) == DFS_TEMP_CHECKED)
dfs_set_status(root, DFS_OK);
return dfs_get_status(root);
}
/* check for circular paths and dependencies */
int pre_flight_circular_check(int *w, int *e) {
host *temp_host = NULL;
servicedependency *temp_sd = NULL;
hostdependency *temp_hd = NULL;
timeperiod *tp;
unsigned int i;
int errors = 0;
unsigned int alloc, dep_type;
char *ary[2];
if(num_objects.hosts > num_objects.services)
alloc = num_objects.hosts;
else
alloc = num_objects.services;
if(num_objects.timeperiods > alloc)
alloc = num_objects.timeperiods;
for (i = 0; i < ARRAY_SIZE(ary); i++) {
if (!(ary[i] = calloc(1, alloc))) {
while (i) {
my_free(ary[--i]);
}
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Unable to allocate memory for circular path checks.\n");
errors++;
return ERROR;
}
}
/********************************************/
/* check for circular paths between hosts */
/********************************************/
if(verify_config)
printf("Checking for circular paths...\n");
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
dfs_host_path(ary[0], temp_host, &errors);
}
if (verify_config)
printf("\tChecked %u hosts\n", num_objects.hosts);
/********************************************/
/* check for circular dependencies */
/********************************************/
/* check service dependencies */
/* We must clean the dfs status from previous check */
for (i = 0; i < ARRAY_SIZE(ary); i++)
memset(ary[i], 0, alloc);
for(i = 0; i < num_objects.servicedependencies; i++) {
temp_sd = servicedependency_ary[i];
dep_type = temp_sd->dependency_type;
/*
* this shouldn't happen, but it can in case dependencies are
* added to services on hosts in empty hostgroups (ie, nonexistent)
*/
if(dep_type < 1 || dep_type > ARRAY_SIZE(ary))
continue;
dfs_servicedep_path(ary[dep_type - 1], temp_sd->dependent_service_ptr, dep_type, &errors);
}
if(verify_config)
printf("\tChecked %u service dependencies\n", num_objects.servicedependencies);
/* check host dependencies */
for (i = 0; i < ARRAY_SIZE(ary); i++)
memset(ary[i], 0, alloc);
for(i = 0; i < num_objects.hostdependencies; i++) {
temp_hd = hostdependency_ary[i];
dep_type = temp_hd->dependency_type;
/* see above */
if(dep_type < 1 || dep_type > ARRAY_SIZE(ary))
continue;
dfs_hostdep_path(ary[dep_type - 1], temp_hd->dependent_host_ptr, dep_type, &errors);
}
if(verify_config)
printf("\tChecked %u host dependencies\n", num_objects.hostdependencies);
/* check timeperiod exclusion chains */
for (i = 0; i < ARRAY_SIZE(ary); i++)
memset(ary[i], 0, alloc);
for (tp = timeperiod_list; tp; tp = tp->next) {
dfs_timeperiod_path(ary[0], tp, &errors);
}
if (verify_config)
printf("\tChecked %u timeperiods\n", num_objects.timeperiods);
/* update warning and error count */
*e += errors;
for (i = 0; i < ARRAY_SIZE(ary); i++)
free(ary[i]);
return (errors > 0) ? ERROR : OK;
}
nagios-4.4.6/base/events.c 0000664 0000000 0000000 00000173306 13652113235 0015402 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* EVENTS.C - Timed event functions for 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/downtime.h"
#include "../include/comments.h"
#include "../include/statusdata.h"
#include "../include/nagios.h"
#include "../include/broker.h"
#include "../include/sretention.h"
#include "../include/workers.h"
#include "../lib/squeue.h"
/* the event we're currently processing */
static timed_event *current_event;
static unsigned int event_count[EVENT_USER_FUNCTION + 1];
/******************************************************************/
/************ EVENT SCHEDULING/HANDLING FUNCTIONS *****************/
/******************************************************************/
int dump_event_stats(int sd)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(event_count); i++) {
nsock_printf(sd, "%s=%u;", EVENT_TYPE_STR(i), event_count[i]);
/*
* VERSIONFIX: Make EVENT_SLEEP and EVENT_USER_FUNCTION
* appear in linear order in include/nagios.h when we go
* from 4.0 -> 4.1, so we can remove this junk.
*/
if (i == 16)
i = 97;
}
nsock_printf_nul(sd, "SQUEUE_ENTRIES=%u", squeue_size(nagios_squeue));
return OK;
}
static void track_events(unsigned int type, int add)
{
/*
* remove_event() calls track_events() with add being -1.
* add_event() calls us with add being 1
*/
if (type < ARRAY_SIZE(event_count))
event_count[type] += add;
}
/* initialize the event timing loop before we start monitoring */
void init_timing_loop(void) {
host *temp_host = NULL;
service *temp_service = NULL;
time_t current_time = 0L;
int total_interleave_blocks = 0;
int current_interleave_block = 1;
int interleave_block_index = 0;
int mult_factor = 0;
int is_valid_time = 0;
time_t next_valid_time = 0L;
int schedule_check = 0;
double max_inter_check_delay = 0.0;
struct timeval tv[9];
double runtime[9];
struct timeval now;
unsigned int fixed_hosts = 0, fixed_services = 0;
int check_delay = 0;
log_debug_info(DEBUGL_FUNCTIONS, 0, "init_timing_loop() start\n");
/* get the time and seed the prng */
gettimeofday(&now, NULL);
current_time = now.tv_sec;
srand((now.tv_sec << 10) ^ now.tv_usec);
/******** GET BASIC HOST/SERVICE INFO ********/
scheduling_info.total_services = 0;
scheduling_info.total_scheduled_services = 0;
scheduling_info.total_hosts = 0;
scheduling_info.total_scheduled_hosts = 0;
scheduling_info.average_services_per_host = 0.0;
scheduling_info.average_scheduled_services_per_host = 0.0;
scheduling_info.average_service_execution_time = 0.0;
scheduling_info.service_check_interval_total = 0;
scheduling_info.average_service_inter_check_delay = 0.0;
scheduling_info.host_check_interval_total = 0;
scheduling_info.average_host_inter_check_delay = 0.0;
if(test_scheduling == TRUE)
gettimeofday(&tv[0], NULL);
/* get info on service checks to be scheduled */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
schedule_check = TRUE;
/* service has no check interval */
if(temp_service->check_interval == 0)
schedule_check = FALSE;
/* active checks are disabled */
if(temp_service->checks_enabled == FALSE)
schedule_check = FALSE;
/* are there any valid times this service can be checked? */
is_valid_time = check_time_against_period(current_time, temp_service->check_period_ptr);
if(is_valid_time == ERROR) {
get_next_valid_time(current_time, &next_valid_time, temp_service->check_period_ptr);
if(current_time == next_valid_time)
schedule_check = FALSE;
}
if(schedule_check == TRUE) {
double exec_time;
/* get real exec time, or make a pessimistic guess */
exec_time = temp_service->execution_time ? temp_service->execution_time : 2.0;
scheduling_info.total_scheduled_services++;
/* used later in inter-check delay calculations */
scheduling_info.service_check_interval_total += temp_service->check_interval;
/* calculate rolling average execution time (available from retained state information) */
scheduling_info.average_service_execution_time = (double)(((scheduling_info.average_service_execution_time * (scheduling_info.total_scheduled_services - 1)) + exec_time) / (double)scheduling_info.total_scheduled_services);
}
else {
temp_service->should_be_scheduled = FALSE;
log_debug_info(DEBUGL_EVENTS, 1, "Service '%s' on host '%s' should not be scheduled.\n", temp_service->description, temp_service->host_name);
}
scheduling_info.total_services++;
}
if(test_scheduling == TRUE)
gettimeofday(&tv[1], NULL);
/* get info on host checks to be scheduled */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
schedule_check = TRUE;
/* host has no check interval */
if(temp_host->check_interval == 0)
schedule_check = FALSE;
/* active checks are disabled */
if(temp_host->checks_enabled == FALSE)
schedule_check = FALSE;
/* are there any valid times this host can be checked? */
is_valid_time = check_time_against_period(current_time, temp_host->check_period_ptr);
if(is_valid_time == ERROR) {
get_next_valid_time(current_time, &next_valid_time, temp_host->check_period_ptr);
if(current_time == next_valid_time)
schedule_check = FALSE;
}
if(schedule_check == TRUE) {
scheduling_info.total_scheduled_hosts++;
/* this is used later in inter-check delay calculations */
scheduling_info.host_check_interval_total += temp_host->check_interval;
}
else {
temp_host->should_be_scheduled = FALSE;
log_debug_info(DEBUGL_EVENTS, 1, "Host '%s' should not be scheduled.\n", temp_host->name);
}
scheduling_info.total_hosts++;
}
if(test_scheduling == TRUE)
gettimeofday(&tv[2], NULL);
scheduling_info.average_services_per_host = (double)((double)scheduling_info.total_services / (double)scheduling_info.total_hosts);
scheduling_info.average_scheduled_services_per_host = (double)((double)scheduling_info.total_scheduled_services / (double)scheduling_info.total_hosts);
/* adjust the check interval total to correspond to the interval length */
scheduling_info.service_check_interval_total = (scheduling_info.service_check_interval_total * interval_length);
/* calculate the average check interval for services */
scheduling_info.average_service_check_interval = (double)((double)scheduling_info.service_check_interval_total / (double)scheduling_info.total_scheduled_services);
/******** DETERMINE SERVICE SCHEDULING PARAMS ********/
log_debug_info(DEBUGL_EVENTS, 2, "Determining service scheduling parameters...\n");
/* default max service check spread (in minutes) */
scheduling_info.max_service_check_spread = max_service_check_spread;
/* how should we determine the service inter-check delay to use? */
switch(service_inter_check_delay_method) {
case ICD_NONE:
/* don't spread checks out - useful for testing parallelization code */
scheduling_info.service_inter_check_delay = 0.0;
break;
case ICD_DUMB:
/* be dumb and just schedule checks 1 second apart */
scheduling_info.service_inter_check_delay = 1.0;
break;
case ICD_USER:
/* the user specified a delay, so don't try to calculate one */
break;
case ICD_SMART:
default:
/* be smart and calculate the best delay to use to minimize local load... */
if(scheduling_info.total_scheduled_services > 0 && scheduling_info.service_check_interval_total > 0) {
/* calculate the average inter check delay (in seconds) needed to evenly space the service checks out */
scheduling_info.average_service_inter_check_delay = (double)(scheduling_info.average_service_check_interval / (double)scheduling_info.total_scheduled_services);
/* set the global inter check delay value */
scheduling_info.service_inter_check_delay = scheduling_info.average_service_inter_check_delay;
/* calculate max inter check delay and see if we should use that instead */
max_inter_check_delay = (double)((scheduling_info.max_service_check_spread * 60.0) / (double)scheduling_info.total_scheduled_services);
if(scheduling_info.service_inter_check_delay > max_inter_check_delay)
scheduling_info.service_inter_check_delay = max_inter_check_delay;
}
else
scheduling_info.service_inter_check_delay = 0.0;
log_debug_info(DEBUGL_EVENTS, 1, "Total scheduled service checks: %d\n", scheduling_info.total_scheduled_services);
log_debug_info(DEBUGL_EVENTS, 1, "Average service check interval: %0.2f sec\n", scheduling_info.average_service_check_interval);
log_debug_info(DEBUGL_EVENTS, 1, "Service inter-check delay: %0.2f sec\n", scheduling_info.service_inter_check_delay);
}
/* how should we determine the service interleave factor? */
switch(service_interleave_factor_method) {
case ILF_USER:
/* the user supplied a value, so don't do any calculation */
break;
case ILF_SMART:
default:
/* protect against a divide by zero problem - shouldn't happen, but just in case... */
if(scheduling_info.total_hosts == 0)
scheduling_info.total_hosts = 1;
scheduling_info.service_interleave_factor = (int)(ceil(scheduling_info.average_scheduled_services_per_host));
log_debug_info(DEBUGL_EVENTS, 1, "Total scheduled service checks: %d\n", scheduling_info.total_scheduled_services);
log_debug_info(DEBUGL_EVENTS, 1, "Total hosts: %d\n", scheduling_info.total_hosts);
log_debug_info(DEBUGL_EVENTS, 1, "Service Interleave factor: %d\n", scheduling_info.service_interleave_factor);
}
/* calculate number of service interleave blocks */
if(scheduling_info.service_interleave_factor == 0)
total_interleave_blocks = scheduling_info.total_scheduled_services;
else
total_interleave_blocks = (int)ceil((double)scheduling_info.total_scheduled_services / (double)scheduling_info.service_interleave_factor);
scheduling_info.first_service_check = (time_t)0L;
scheduling_info.last_service_check = (time_t)0L;
log_debug_info(DEBUGL_EVENTS, 1, "Total scheduled services: %d\n", scheduling_info.total_scheduled_services);
log_debug_info(DEBUGL_EVENTS, 1, "Service Interleave factor: %d\n", scheduling_info.service_interleave_factor);
log_debug_info(DEBUGL_EVENTS, 1, "Total service interleave blocks: %d\n", total_interleave_blocks);
log_debug_info(DEBUGL_EVENTS, 1, "Service inter-check delay: %2.1f\n", scheduling_info.service_inter_check_delay);
if(test_scheduling == TRUE)
gettimeofday(&tv[3], NULL);
/******** SCHEDULE SERVICE CHECKS ********/
log_debug_info(DEBUGL_EVENTS, 2, "Scheduling service checks...\n");
/* determine check times for service checks (with interleaving to minimize remote load) */
current_interleave_block = 0;
for(temp_service = service_list; temp_service != NULL && scheduling_info.service_interleave_factor > 0;) {
log_debug_info(DEBUGL_EVENTS, 2, "Current Interleave Block: %d\n", current_interleave_block);
for(interleave_block_index = 0; interleave_block_index < scheduling_info.service_interleave_factor && temp_service != NULL; temp_service = temp_service->next) {
log_debug_info(DEBUGL_EVENTS, 2, "Service '%s' on host '%s'\n", temp_service->description, temp_service->host_name);
/* skip this service if it shouldn't be scheduled */
if(temp_service->should_be_scheduled == FALSE) {
log_debug_info(DEBUGL_EVENTS, 2, "Service check should not be scheduled.\n");
continue;
}
/*
* skip services that are already scheduled for the (near)
* future from retention data, but reschedule ones that
* were supposed to happen while we weren't running...
* We check to make sure the check isn't scheduled to run
* far in the future to make sure checks who've hade their
* timeperiods changed during the restart aren't left
* hanging too long without being run.
*/
check_delay = temp_service->next_check - current_time;
if(check_delay > 0 && check_delay < check_window(temp_service)) {
log_debug_info(DEBUGL_EVENTS, 2, "Service is already scheduled to be checked in the future: %s\n", ctime(&temp_service->next_check));
continue;
}
/* interleave block index should only be increased when we find a schedulable service */
/* moved from for() loop 11/05/05 EG */
interleave_block_index++;
mult_factor = current_interleave_block + (interleave_block_index * total_interleave_blocks);
log_debug_info(DEBUGL_EVENTS, 2, "CIB: %d, IBI: %d, TIB: %d, SIF: %d\n", current_interleave_block, interleave_block_index, total_interleave_blocks, scheduling_info.service_interleave_factor);
log_debug_info(DEBUGL_EVENTS, 2, "Mult factor: %d\n", mult_factor);
/*
* set the preferred next check time for the service
* If we end up too far into the future, grab a random
* time within the service's window instead.
*/
check_delay =
mult_factor * scheduling_info.service_inter_check_delay;
if(check_delay > check_window(temp_service)) {
log_debug_info(DEBUGL_EVENTS, 0,
" Fixing check time %lu secs too far away\n",
check_delay - check_window(temp_service));
fixed_services++;
check_delay = check_window(temp_service);
log_debug_info(DEBUGL_EVENTS, 0, " New check offset: %d\n",
check_delay);
}
temp_service->next_check = (time_t)(current_time + check_delay);
log_debug_info(DEBUGL_EVENTS, 2, "Preferred Check Time: %lu --> %s\n", (unsigned long)temp_service->next_check, ctime(&temp_service->next_check));
/* make sure the service can actually be scheduled when we want */
is_valid_time = check_time_against_period(temp_service->next_check, temp_service->check_period_ptr);
if(is_valid_time == ERROR) {
log_debug_info(DEBUGL_EVENTS, 2, "Preferred Time is Invalid In Timeperiod '%s': %lu --> %s\n", temp_service->check_period_ptr->name, (unsigned long)temp_service->next_check, ctime(&temp_service->next_check));
get_next_valid_time(temp_service->next_check, &next_valid_time, temp_service->check_period_ptr);
temp_service->next_check =
(time_t)(next_valid_time + check_delay);
}
log_debug_info(DEBUGL_EVENTS, 2, "Actual Check Time: %lu --> %s\n", (unsigned long)temp_service->next_check, ctime(&temp_service->next_check));
if(scheduling_info.first_service_check == (time_t)0 || (temp_service->next_check < scheduling_info.first_service_check))
scheduling_info.first_service_check = temp_service->next_check;
if(temp_service->next_check > scheduling_info.last_service_check)
scheduling_info.last_service_check = temp_service->next_check;
}
current_interleave_block++;
}
if(test_scheduling == TRUE)
gettimeofday(&tv[4], NULL);
/* add scheduled service checks to event queue */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
/* Nagios XI/NDOUtils MOD */
/* update status of all services (scheduled or not) */
update_service_status(temp_service, FALSE);
/* skip most services that shouldn't be scheduled */
if(temp_service->should_be_scheduled == FALSE) {
/* passive checks are an exception if a forced check was scheduled before Nagios was restarted */
if(!(temp_service->checks_enabled == FALSE && temp_service->next_check != (time_t)0L && (temp_service->check_options & CHECK_OPTION_FORCE_EXECUTION)))
continue;
}
/* create a new service check event */
temp_service->next_check_event = schedule_new_event(EVENT_SERVICE_CHECK, FALSE, temp_service->next_check, FALSE, 0, NULL, TRUE, (void *)temp_service, NULL, temp_service->check_options);
}
if(test_scheduling == TRUE)
gettimeofday(&tv[5], NULL);
/******** DETERMINE HOST SCHEDULING PARAMS ********/
log_debug_info(DEBUGL_EVENTS, 2, "Determining host scheduling parameters...\n");
scheduling_info.first_host_check = (time_t)0L;
scheduling_info.last_host_check = (time_t)0L;
/* default max host check spread (in minutes) */
scheduling_info.max_host_check_spread = max_host_check_spread;
/* how should we determine the host inter-check delay to use? */
switch(host_inter_check_delay_method) {
case ICD_NONE:
/* don't spread checks out */
scheduling_info.host_inter_check_delay = 0.0;
break;
case ICD_DUMB:
/* be dumb and just schedule checks 1 second apart */
scheduling_info.host_inter_check_delay = 1.0;
break;
case ICD_USER:
/* the user specified a delay, so don't try to calculate one */
break;
case ICD_SMART:
default:
/* be smart and calculate the best delay to use to minimize local load... */
if(scheduling_info.total_scheduled_hosts > 0 && scheduling_info.host_check_interval_total > 0) {
/* adjust the check interval total to correspond to the interval length */
scheduling_info.host_check_interval_total = (scheduling_info.host_check_interval_total * interval_length);
/* calculate the average check interval for hosts */
scheduling_info.average_host_check_interval = (double)((double)scheduling_info.host_check_interval_total / (double)scheduling_info.total_scheduled_hosts);
/* calculate the average inter check delay (in seconds) needed to evenly space the host checks out */
scheduling_info.average_host_inter_check_delay = (double)(scheduling_info.average_host_check_interval / (double)scheduling_info.total_scheduled_hosts);
/* set the global inter check delay value */
scheduling_info.host_inter_check_delay = scheduling_info.average_host_inter_check_delay;
/* calculate max inter check delay and see if we should use that instead */
max_inter_check_delay = (double)((scheduling_info.max_host_check_spread * 60.0) / (double)scheduling_info.total_scheduled_hosts);
if(scheduling_info.host_inter_check_delay > max_inter_check_delay)
scheduling_info.host_inter_check_delay = max_inter_check_delay;
}
else
scheduling_info.host_inter_check_delay = 0.0;
log_debug_info(DEBUGL_EVENTS, 2, "Total scheduled host checks: %d\n", scheduling_info.total_scheduled_hosts);
log_debug_info(DEBUGL_EVENTS, 2, "Host check interval total: %lu\n", scheduling_info.host_check_interval_total);
log_debug_info(DEBUGL_EVENTS, 2, "Average host check interval: %0.2f sec\n", scheduling_info.average_host_check_interval);
log_debug_info(DEBUGL_EVENTS, 2, "Host inter-check delay: %0.2f sec\n", scheduling_info.host_inter_check_delay);
}
if(test_scheduling == TRUE)
gettimeofday(&tv[6], NULL);
/******** SCHEDULE HOST CHECKS ********/
log_debug_info(DEBUGL_EVENTS, 2, "Scheduling host checks...\n");
/* determine check times for host checks */
mult_factor = 0;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
log_debug_info(DEBUGL_EVENTS, 2, "Host '%s'\n", temp_host->name);
/* skip hosts that shouldn't be scheduled */
if(temp_host->should_be_scheduled == FALSE) {
log_debug_info(DEBUGL_EVENTS, 2, "Host check should not be scheduled.\n");
continue;
}
/* skip hosts that are already scheduled for the future (from retention data), but reschedule ones that were supposed to be checked before we started */
if(temp_host->next_check > current_time) {
log_debug_info(DEBUGL_EVENTS, 2, "Host is already scheduled to be checked in the future: %s\n", ctime(&temp_host->next_check));
continue;
}
/*
* calculate preferred host check time.
* If it's too far into the future, we grab a random time
* within this host's max check window instead
*/
check_delay = mult_factor * scheduling_info.host_inter_check_delay;
if(check_delay > check_window(temp_host)) {
log_debug_info(DEBUGL_EVENTS, 1, "Fixing check time (off by %lu)\n",
check_delay - check_window(temp_host));
fixed_hosts++;
check_delay = ranged_urand(0, check_window(temp_host));
}
temp_host->next_check = (time_t)(current_time + check_delay);
log_debug_info(DEBUGL_EVENTS, 2, "Preferred Check Time: %lu --> %s", (unsigned long)temp_host->next_check, ctime(&temp_host->next_check));
/* make sure the host can actually be scheduled at this time */
is_valid_time = check_time_against_period(temp_host->next_check, temp_host->check_period_ptr);
if(is_valid_time == ERROR) {
get_next_valid_time(temp_host->next_check, &next_valid_time, temp_host->check_period_ptr);
temp_host->next_check = (time_t)(next_valid_time | check_delay);
}
log_debug_info(DEBUGL_EVENTS, 2, "Actual Check Time: %lu --> %s\n", (unsigned long)temp_host->next_check, ctime(&temp_host->next_check));
if(scheduling_info.first_host_check == (time_t)0 || (temp_host->next_check < scheduling_info.first_host_check))
scheduling_info.first_host_check = temp_host->next_check;
if(temp_host->next_check > scheduling_info.last_host_check)
scheduling_info.last_host_check = temp_host->next_check;
mult_factor++;
}
log_debug_info(DEBUGL_EVENTS, 0, "Fixed scheduling for %u hosts and %u services\n", fixed_hosts, fixed_services);
if(test_scheduling == TRUE)
gettimeofday(&tv[7], NULL);
/* add scheduled host checks to event queue */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
/* Nagios XI/NDOUtils Mod */
/* update status of all hosts (scheduled or not) */
update_host_status(temp_host, FALSE);
/* skip most hosts that shouldn't be scheduled */
if(temp_host->should_be_scheduled == FALSE) {
/* passive checks are an exception if a forced check was scheduled before Nagios was restarted */
if(!(temp_host->checks_enabled == FALSE && temp_host->next_check != (time_t)0L && (temp_host->check_options & CHECK_OPTION_FORCE_EXECUTION)))
continue;
}
/* schedule a new host check event */
temp_host->next_check_event = schedule_new_event(EVENT_HOST_CHECK, FALSE, temp_host->next_check, FALSE, 0, NULL, TRUE, (void *)temp_host, NULL, temp_host->check_options);
}
if(test_scheduling == TRUE)
gettimeofday(&tv[8], NULL);
/******** SCHEDULE MISC EVENTS ********/
/* add a host and service check rescheduling event */
if(auto_reschedule_checks == TRUE)
schedule_new_event(EVENT_RESCHEDULE_CHECKS, TRUE, current_time + auto_rescheduling_interval, TRUE, auto_rescheduling_interval, NULL, TRUE, NULL, NULL, 0);
/* add a check result reaper event */
schedule_new_event(EVENT_CHECK_REAPER, TRUE, current_time + check_reaper_interval, TRUE, check_reaper_interval, NULL, TRUE, NULL, NULL, 0);
/* add an orphaned check event */
if(check_orphaned_services == TRUE || check_orphaned_hosts == TRUE)
schedule_new_event(EVENT_ORPHAN_CHECK, TRUE, current_time + DEFAULT_ORPHAN_CHECK_INTERVAL, TRUE, DEFAULT_ORPHAN_CHECK_INTERVAL, NULL, TRUE, NULL, NULL, 0);
/* add a service result "freshness" check event */
if(check_service_freshness == TRUE)
schedule_new_event(EVENT_SFRESHNESS_CHECK, TRUE, current_time + service_freshness_check_interval, TRUE, service_freshness_check_interval, NULL, TRUE, NULL, NULL, 0);
/* add a host result "freshness" check event */
if(check_host_freshness == TRUE)
schedule_new_event(EVENT_HFRESHNESS_CHECK, TRUE, current_time + host_freshness_check_interval, TRUE, host_freshness_check_interval, NULL, TRUE, NULL, NULL, 0);
/* add a status save event */
schedule_new_event(EVENT_STATUS_SAVE, TRUE, current_time + status_update_interval, TRUE, status_update_interval, NULL, TRUE, NULL, NULL, 0);
/* add a log rotation event if necessary */
if(log_rotation_method != LOG_ROTATION_NONE)
schedule_new_event(EVENT_LOG_ROTATION, TRUE, get_next_log_rotation_time(), TRUE, 0, (void *)get_next_log_rotation_time, TRUE, NULL, NULL, 0);
/* add a retention data save event if needed */
if(retain_state_information == TRUE && retention_update_interval > 0)
schedule_new_event(EVENT_RETENTION_SAVE, TRUE, current_time + (retention_update_interval * 60), TRUE, (retention_update_interval * 60), NULL, TRUE, NULL, NULL, 0);
if(test_scheduling == TRUE) {
runtime[0] = (double)((double)(tv[1].tv_sec - tv[0].tv_sec) + (double)((tv[1].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0);
runtime[1] = (double)((double)(tv[2].tv_sec - tv[1].tv_sec) + (double)((tv[2].tv_usec - tv[1].tv_usec) / 1000.0) / 1000.0);
runtime[2] = (double)((double)(tv[3].tv_sec - tv[2].tv_sec) + (double)((tv[3].tv_usec - tv[2].tv_usec) / 1000.0) / 1000.0);
runtime[3] = (double)((double)(tv[4].tv_sec - tv[3].tv_sec) + (double)((tv[4].tv_usec - tv[3].tv_usec) / 1000.0) / 1000.0);
runtime[4] = (double)((double)(tv[5].tv_sec - tv[4].tv_sec) + (double)((tv[5].tv_usec - tv[4].tv_usec) / 1000.0) / 1000.0);
runtime[5] = (double)((double)(tv[6].tv_sec - tv[5].tv_sec) + (double)((tv[6].tv_usec - tv[5].tv_usec) / 1000.0) / 1000.0);
runtime[6] = (double)((double)(tv[7].tv_sec - tv[6].tv_sec) + (double)((tv[7].tv_usec - tv[6].tv_usec) / 1000.0) / 1000.0);
runtime[7] = (double)((double)(tv[8].tv_sec - tv[7].tv_sec) + (double)((tv[8].tv_usec - tv[7].tv_usec) / 1000.0) / 1000.0);
runtime[8] = (double)((double)(tv[8].tv_sec - tv[0].tv_sec) + (double)((tv[8].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0);
printf("EVENT SCHEDULING TIMES\n");
printf("-------------------------------------\n");
printf("Get service info: %.6lf sec\n", runtime[0]);
printf("Get host info info: %.6lf sec\n", runtime[1]);
printf("Get service params: %.6lf sec\n", runtime[2]);
printf("Schedule service times: %.6lf sec\n", runtime[3]);
printf("Schedule service events: %.6lf sec\n", runtime[4]);
printf("Get host params: %.6lf sec\n", runtime[5]);
printf("Schedule host times: %.6lf sec\n", runtime[6]);
printf("Schedule host events: %.6lf sec\n", runtime[7]);
printf(" ============\n");
printf("TOTAL: %.6lf sec\n", runtime[8]);
printf("\n\n");
}
log_debug_info(DEBUGL_FUNCTIONS, 0, "init_timing_loop() end\n");
return;
}
/* displays service check scheduling information */
void display_scheduling_info(void) {
float minimum_concurrent_checks = 0.0;
int suggestions = 0;
printf("Projected scheduling information for host and service checks\n");
printf("is listed below. This information assumes that you are going\n");
printf("to start running Nagios with your current config files.\n\n");
printf("HOST SCHEDULING INFORMATION\n");
printf("---------------------------\n");
printf("Total hosts: %d\n", scheduling_info.total_hosts);
printf("Total scheduled hosts: %d\n", scheduling_info.total_scheduled_hosts);
printf("Host inter-check delay method: ");
if(host_inter_check_delay_method == ICD_NONE)
printf("NONE\n");
else if(host_inter_check_delay_method == ICD_DUMB)
printf("DUMB\n");
else if(host_inter_check_delay_method == ICD_SMART) {
printf("SMART\n");
printf("Average host check interval: %.2f sec\n", scheduling_info.average_host_check_interval);
}
else
printf("USER-SUPPLIED VALUE\n");
printf("Host inter-check delay: %.2f sec\n", scheduling_info.host_inter_check_delay);
printf("Max host check spread: %d min\n", scheduling_info.max_host_check_spread);
printf("First scheduled check: %s", (scheduling_info.total_scheduled_hosts == 0) ? "N/A\n" : ctime(&scheduling_info.first_host_check));
printf("Last scheduled check: %s", (scheduling_info.total_scheduled_hosts == 0) ? "N/A\n" : ctime(&scheduling_info.last_host_check));
printf("\n\n");
printf("SERVICE SCHEDULING INFORMATION\n");
printf("-------------------------------\n");
printf("Total services: %d\n", scheduling_info.total_services);
printf("Total scheduled services: %d\n", scheduling_info.total_scheduled_services);
printf("Service inter-check delay method: ");
if(service_inter_check_delay_method == ICD_NONE)
printf("NONE\n");
else if(service_inter_check_delay_method == ICD_DUMB)
printf("DUMB\n");
else if(service_inter_check_delay_method == ICD_SMART) {
printf("SMART\n");
printf("Average service check interval: %.2f sec\n", scheduling_info.average_service_check_interval);
}
else
printf("USER-SUPPLIED VALUE\n");
printf("Inter-check delay: %.2f sec\n", scheduling_info.service_inter_check_delay);
printf("Interleave factor method: %s\n", (service_interleave_factor_method == ILF_USER) ? "USER-SUPPLIED VALUE" : "SMART");
if(service_interleave_factor_method == ILF_SMART)
printf("Average services per host: %.2f\n", scheduling_info.average_services_per_host);
printf("Service interleave factor: %d\n", scheduling_info.service_interleave_factor);
printf("Max service check spread: %d min\n", scheduling_info.max_service_check_spread);
printf("First scheduled check: %s", ctime(&scheduling_info.first_service_check));
printf("Last scheduled check: %s", ctime(&scheduling_info.last_service_check));
printf("\n\n");
/***** MINIMUM CONCURRENT CHECKS RECOMMENDATION *****/
minimum_concurrent_checks = ceil((((scheduling_info.total_scheduled_services / scheduling_info.average_service_check_interval)
+ (scheduling_info.total_scheduled_hosts / scheduling_info.average_host_check_interval))
* 1.4 * scheduling_info.average_service_execution_time));
printf("CHECK PROCESSING INFORMATION\n");
printf("----------------------------\n");
printf("Average check execution time: %.2fs%s",
scheduling_info.average_service_execution_time,
scheduling_info.average_service_execution_time == 2.0 ? " (pessimistic guesstimate)\n" : "\n");
printf("Estimated concurrent checks: %.0f (%.2f per cpu core)\n",
minimum_concurrent_checks, (float)minimum_concurrent_checks / (float)online_cpus());
printf("Max concurrent service checks: ");
if(max_parallel_service_checks == 0)
printf("Unlimited\n");
else
printf("%d\n", max_parallel_service_checks);
printf("\n\n");
printf("PERFORMANCE SUGGESTIONS\n");
printf("-----------------------\n");
/* compare with configured value */
if(((int)minimum_concurrent_checks > max_parallel_service_checks) && max_parallel_service_checks != 0) {
printf("* Value for 'max_concurrent_checks' option should be >= %d\n", (int)minimum_concurrent_checks);
suggestions++;
}
if(loadctl.nofile_limit * 0.4 < minimum_concurrent_checks) {
printf("* Increase the \"open files\" ulimit for user '%s'\n", nagios_user);
printf(" - You can do this by adding\n %s hard nofiles %d\n to /etc/security/limits.conf\n",
nagios_user, rup2pof2(minimum_concurrent_checks * 2));
suggestions++;
}
if(loadctl.nproc_limit * 0.75 < minimum_concurrent_checks) {
printf("* Increase the \"max user processes\" ulimit for user '%s'\n", nagios_user);
printf(" - You can do this by adding\n %s hard nproc %d\n to /etc/security/limits.conf\n",
nagios_user, rup2pof2(minimum_concurrent_checks));
suggestions++;
}
if(minimum_concurrent_checks > online_cpus() * 75) {
printf("* Aim for a max of 50 concurrent checks / cpu core (current: %.2f)\n",
(float)minimum_concurrent_checks / (float)online_cpus());
suggestions++;
}
if(suggestions) {
printf("\nNOTE: These are just guidelines and *not* hard numbers.\n\n");
printf("Ultimately, only testing will tell if your settings and hardware are\n");
printf("suitable for the types and number of checks you're planning to run.\n");
}
else {
printf("I have no suggestions - things look okay.\n");
}
printf("\n");
return;
}
/*
* Create the event queue
* We oversize it somewhat to avoid unnecessary growing
*/
int init_event_queue(void)
{
unsigned int size;
size = num_objects.hosts + num_objects.services;
if (size < 4096) {
size = 4096;
}
nagios_squeue = squeue_create(size);
return 0;
}
/* schedule a new timed event */
timed_event *schedule_new_event(int event_type, int high_priority, time_t run_time,
int recurring, unsigned long event_interval, void *timing_func,
int compensate_for_time_change, void *event_data, void *event_args, int event_options)
{
timed_event * new_event = NULL;
char run_time_string[MAX_DATETIME_LENGTH] = "";
get_datetime_string(&run_time, run_time_string, MAX_DATETIME_LENGTH, SHORT_DATE_TIME);
new_event = (timed_event *)calloc(1, sizeof(timed_event));
if (new_event != NULL) {
new_event->event_type = event_type;
new_event->event_data = event_data;
new_event->event_args = event_args;
new_event->event_options = event_options;
new_event->run_time = run_time;
new_event->recurring = recurring;
new_event->event_interval = event_interval;
new_event->timing_func = timing_func;
new_event->compensate_for_time_change = compensate_for_time_change;
new_event->priority = high_priority;
}
else {
return NULL;
}
log_debug_info(DEBUGL_FUNCTIONS, 0,
"schedule_new_event()\n"
"New Event Details:\n"
" Event ID: %p\n"
" Type: EVENT_%s\n"
" High Priority: %d\n"
" Run Time: %s\n"
" Recurring: %d\n"
" Event Interval: %lu\n"
" Compensate for Time Change: %d\n"
" Event Options: %d\n",
new_event,
EVENT_TYPE_STR(event_type),
high_priority,
run_time_string,
recurring,
event_interval,
compensate_for_time_change,
event_options);
/* add the event to the event list */
add_event(nagios_squeue, new_event);
return new_event;
}
/* reschedule an event in order of execution time */
void reschedule_event(squeue_t *sq, timed_event *event)
{
time_t current_time = 0L;
time_t (*timingfunc)(void);
log_debug_info(DEBUGL_FUNCTIONS, 0, "reschedule_event()\n");
/* reschedule recurring events... */
if(event->recurring == TRUE) {
/* use custom timing function */
if(event->timing_func != NULL) {
timingfunc = event->timing_func;
event->run_time = (*timingfunc)();
}
/* normal recurring events */
else {
event->run_time = event->run_time + event->event_interval;
time(¤t_time);
if(event->run_time < current_time) {
event->run_time = current_time;
}
}
}
/* add the event to the event list */
add_event(sq, event);
}
/* add an event to list ordered by execution time */
void add_event(squeue_t *sq, timed_event *event)
{
log_debug_info(DEBUGL_FUNCTIONS, 0, "add_event()\n");
if (event->sq_event != NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Error: Adding %s event that seems to already be scheduled\n",
EVENT_TYPE_STR(event->event_type));
remove_event(sq, event);
}
if (event->priority > 0) {
event->sq_event = squeue_add_usec(sq, event->run_time, event->priority - 1, event);
}
else {
event->sq_event = squeue_add(sq, event->run_time, event);
}
if (event->sq_event == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Error: Failed to add event to squeue '%p' with prio %u: %s\n",
sq, event->priority, strerror(errno));
}
/* this specifies + just to ensure different than `-1` visually */
if (sq == nagios_squeue) {
track_events(event->event_type, +1);
}
#ifdef USE_EVENT_BROKER
else {
broker_timed_event(NEBTYPE_TIMEDEVENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, event, NULL);
}
#endif
}
/* remove an event from the queue */
void remove_event(squeue_t *sq, timed_event *event)
{
#ifdef USE_EVENT_BROKER
broker_timed_event(NEBTYPE_TIMEDEVENT_REMOVE, NEBFLAG_NONE, NEBATTR_NONE, event, NULL);
#endif
if (event == NULL || event->sq_event == NULL) {
return;
}
if (sq != NULL) {
squeue_remove(sq, event->sq_event);
}
else {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Error: remove_event() called for %s event with NULL sq parameter\n",
EVENT_TYPE_STR(event->event_type));
}
if (sq == nagios_squeue) {
track_events(event->event_type, -1);
}
/* mark this event as unscheduled */
event->sq_event = NULL;
/*
* if we catch an event from the queue which gets removed when
* we go polling for input (as might happen with f.e. downtime
* events that we get "cancel" commands for just as they are
* about to start or expire), we must make sure we mark the
* current event as no longer scheduled, or we'll run into
* segfaults and memory corruptions for sure.
*/
if (event == current_event) {
current_event = NULL;
}
}
static int should_run_event(timed_event *temp_event)
{
/* default action is to execute the event */
int run_event = TRUE;
int nudge_seconds = 0;
/* we only care about jobs that cause processes to run */
if (temp_event->event_type != EVENT_HOST_CHECK
&& temp_event->event_type != EVENT_SERVICE_CHECK) {
return TRUE;
}
/* if we can't spawn any more jobs, don't bother */
if (wproc_can_spawn(&loadctl) <= 0) {
/* Try to reap one job for one msec. */
wproc_reap(1, 1);
return FALSE;
}
/* run a few checks before executing a service check... */
if (temp_event->event_type == EVENT_SERVICE_CHECK) {
service *temp_service = (service *)temp_event->event_data;
/* forced checks override normal check logic */
if((temp_service->check_options & CHECK_OPTION_FORCE_EXECUTION)) {
return TRUE;
}
/* don't run a service check if we're already maxed out on the number of parallel service checks... */
if (max_parallel_service_checks != 0
&& currently_running_service_checks >= max_parallel_service_checks) {
nudge_seconds = ranged_urand(NUDGE_MIN, NUDGE_MAX);
logit(NSLOG_RUNTIME_WARNING, TRUE,
"\tMax concurrent service checks (%d) has been reached."
" Nudging %s:%s by %d seconds...\n",
max_parallel_service_checks, temp_service->host_name,
temp_service->description, nudge_seconds);
run_event = FALSE;
}
/* don't run a service check if active checks are disabled */
if (execute_service_checks == FALSE) {
log_debug_info(DEBUGL_EVENTS | DEBUGL_CHECKS, 1,
"We're not executing service checks right now, so we'll skip check event for service '%s;%s'.\n",
temp_service->host_name, temp_service->description);
run_event = FALSE;
}
/* reschedule the check if we can't run it now */
if (run_event == FALSE) {
remove_event(nagios_squeue, temp_event);
/* We nudge the next check time when it is
due to too many concurrent service checks */
if (nudge_seconds) {
temp_service->next_check = (time_t)(temp_service->next_check + nudge_seconds);
}
/* Otherwise just schedule as normal */
else {
temp_service->next_check += check_window(temp_service);
}
temp_event->run_time = temp_service->next_check;
reschedule_event(nagios_squeue, temp_event);
update_service_status(temp_service, FALSE);
run_event = FALSE;
}
}
/* run a few checks before executing a host check... */
else if (temp_event->event_type == EVENT_HOST_CHECK) {
host *temp_host = (host *)temp_event->event_data;
/* forced checks override normal check logic */
if ((temp_host->check_options & CHECK_OPTION_FORCE_EXECUTION)) {
return TRUE;
}
/* don't run a host check if active checks are disabled */
if (execute_host_checks == FALSE) {
log_debug_info(DEBUGL_EVENTS | DEBUGL_CHECKS, 1,
"We're not executing host checks right now, so we'll skip host check event for host '%s'.\n",
temp_host->name);
run_event = FALSE;
}
/* reschedule the host check if we can't run it right now */
if (run_event == FALSE) {
remove_event(nagios_squeue, temp_event);
temp_host->next_check += check_window(temp_host);
temp_event->run_time = temp_host->next_check;
reschedule_event(nagios_squeue, temp_event);
update_host_status(temp_host, FALSE);
run_event = FALSE;
}
}
return run_event;
}
/* this is the main event handler loop */
int event_execution_loop(void) {
timed_event *temp_event, *last_event = NULL;
time_t last_time = 0L;
time_t current_time = 0L;
time_t last_status_update = 0L;
int poll_time_ms;
log_debug_info(DEBUGL_FUNCTIONS, 0, "event_execution_loop() start\n");
time(&last_time);
while(1) {
struct timeval now;
const struct timeval *event_runtime;
int inputs;
/* super-priority (hardcoded) events come first */
/* see if we should exit or restart (a signal was encountered) */
if(sigshutdown == TRUE || sigrestart == TRUE)
break;
/* get the current time */
time(¤t_time);
/* hey, wait a second... we traveled back in time! */
if(current_time < last_time)
compensate_for_system_time_change((unsigned long)last_time, (unsigned long)current_time);
/* else if the time advanced over the specified threshold, try and compensate... */
else if((current_time - last_time) >= time_change_threshold)
compensate_for_system_time_change((unsigned long)last_time, (unsigned long)current_time);
/* get next scheduled event */
current_event = temp_event = (timed_event *)squeue_peek(nagios_squeue);
/* if we don't have any events to handle, exit */
if(!temp_event) {
log_debug_info(DEBUGL_EVENTS, 0, "There aren't any events that need to be handled! Exiting...\n");
break;
}
/* keep track of the last time */
last_time = current_time;
/* update status information occasionally - NagVis watches the NDOUtils DB to see if Nagios is alive */
if((unsigned long)(current_time - last_status_update) > 5) {
last_status_update = current_time;
update_program_status(FALSE);
}
event_runtime = squeue_event_runtime(temp_event->sq_event);
if (temp_event != last_event) {
log_debug_info(DEBUGL_EVENTS, 1, "** Event Check Loop\n");
log_debug_info(DEBUGL_EVENTS, 1, "Next Event Time: %s", ctime(&temp_event->run_time));
log_debug_info(DEBUGL_EVENTS, 1, "Current/Max Service Checks: %d/%d (%.3lf%% saturation)\n",
currently_running_service_checks, max_parallel_service_checks,
((float)currently_running_service_checks / (float)max_parallel_service_checks) * 100);
}
last_event = temp_event;
gettimeofday(&now, NULL);
poll_time_ms = tv_delta_msec(&now, event_runtime);
if (poll_time_ms < 0)
poll_time_ms = 0;
else if(poll_time_ms >= 1500)
poll_time_ms = 1500;
log_debug_info(DEBUGL_SCHEDULING | DEBUGL_IPC, 1, "## Polling %dms; sockets=%d; events=%u; iobs=%p\n",
poll_time_ms, iobroker_get_num_fds(nagios_iobs),
squeue_size(nagios_squeue), nagios_iobs);
inputs = iobroker_poll(nagios_iobs, poll_time_ms);
if (inputs < 0 && errno != EINTR) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Polling for input on %p failed: %s", nagios_iobs, iobroker_strerror(inputs));
break;
}
log_debug_info(DEBUGL_IPC, 2, "## %d descriptors had input\n", inputs);
/*
* if the event we peaked was removed from the queue from
* one of the I/O operations, we must take care not to
* try to run at, as we're (almost) sure to access free'd
* or invalid memory if we do.
*/
if (!current_event) {
log_debug_info(DEBUGL_EVENTS, 0, "Event was cancelled by iobroker input\n");
continue;
}
/* 5 milliseconds allowance for firing off events early */
gettimeofday(&now, NULL);
if (tv_delta_msec(&now, event_runtime) > 5)
continue;
/* move on if we shouldn't run this event */
if(should_run_event(temp_event) == FALSE)
continue;
/* handle the event */
handle_timed_event(temp_event);
/*
* we must remove the entry we've peeked, or
* we'll keep getting the same one over and over.
* This also maintains sync with broker modules.
*/
remove_event(nagios_squeue, temp_event);
/* reschedule the event if necessary */
if(temp_event->recurring == TRUE)
reschedule_event(nagios_squeue, temp_event);
/* else free memory associated with the event */
else
my_free(temp_event);
}
log_debug_info(DEBUGL_FUNCTIONS, 0, "event_execution_loop() end\n");
return OK;
}
/* handles a timed event */
int handle_timed_event(timed_event *event) {
host *temp_host = NULL;
service *temp_service = NULL;
void (*userfunc)(void *);
struct timeval tv;
const struct timeval *event_runtime;
double latency;
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_timed_event() start\n");
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_timed_event(NEBTYPE_TIMEDEVENT_EXECUTE, NEBFLAG_NONE, NEBATTR_NONE, event, NULL);
#endif
log_debug_info(DEBUGL_EVENTS, 0, "** Timed Event ** Type: EVENT_%s, Run Time: %s", EVENT_TYPE_STR(event->event_type), ctime(&event->run_time));
/* get event latency */
gettimeofday(&tv, NULL);
event_runtime = squeue_event_runtime(event->sq_event);
latency = (double)(tv_delta_f(event_runtime, &tv));
if (latency < 0.0) /* events may run up to 0.005 seconds early */
latency = 0.0;
/* how should we handle the event? */
switch(event->event_type) {
case EVENT_SERVICE_CHECK:
temp_service = (service *)event->event_data;
log_debug_info(DEBUGL_EVENTS, 0, "** Service Check Event ==> Host: '%s', Service: '%s', Options: %d, Latency: %f sec\n", temp_service->host_name, temp_service->description, event->event_options, latency);
/* run the service check */
run_scheduled_service_check(temp_service, event->event_options, latency);
break;
case EVENT_HOST_CHECK:
temp_host = (host *)event->event_data;
log_debug_info(DEBUGL_EVENTS, 0, "** Host Check Event ==> Host: '%s', Options: %d, Latency: %f sec\n", temp_host->name, event->event_options, latency);
/* run the host check */
run_scheduled_host_check(temp_host, event->event_options, latency);
break;
case EVENT_LOG_ROTATION:
log_debug_info(DEBUGL_EVENTS, 0, "** Log File Rotation Event. Latency: %.3fs\n", latency);
/* rotate the log file */
rotate_log_file(event->run_time);
break;
case EVENT_PROGRAM_SHUTDOWN:
log_debug_info(DEBUGL_EVENTS, 0, "** Program Shutdown Event. Latency: %.3fs\n", latency);
/* set the shutdown flag */
sigshutdown = TRUE;
/* log the shutdown */
logit(NSLOG_PROCESS_INFO, TRUE, "PROGRAM_SHUTDOWN event encountered, shutting down...\n");
break;
case EVENT_PROGRAM_RESTART:
log_debug_info(DEBUGL_EVENTS, 0, "** Program Restart Event. Latency: %.3fs\n", latency);
/* set the restart flag */
sigrestart = TRUE;
/* log the restart */
logit(NSLOG_PROCESS_INFO, TRUE, "PROGRAM_RESTART event encountered, restarting...\n");
break;
case EVENT_CHECK_REAPER:
log_debug_info(DEBUGL_EVENTS, 0, "** Check Result Reaper. Latency: %.3fs\n", latency);
/* reap host and service check results */
reap_check_results();
break;
case EVENT_ORPHAN_CHECK:
log_debug_info(DEBUGL_EVENTS, 0, "** Orphaned Host and Service Check Event. Latency: %.3fs\n", latency);
/* check for orphaned hosts and services */
if(check_orphaned_hosts == TRUE)
check_for_orphaned_hosts();
if(check_orphaned_services == TRUE)
check_for_orphaned_services();
break;
case EVENT_RETENTION_SAVE:
log_debug_info(DEBUGL_EVENTS, 0, "** Retention Data Save Event. Latency: %.3fs\n", latency);
/* save state retention data */
save_state_information(TRUE);
break;
case EVENT_STATUS_SAVE:
log_debug_info(DEBUGL_EVENTS, 0, "** Status Data Save Event. Latency: %.3fs\n", latency);
/* save all status data (program, host, and service) */
update_all_status_data();
break;
case EVENT_SCHEDULED_DOWNTIME:
log_debug_info(DEBUGL_EVENTS, 0, "** Scheduled Downtime Event. Latency: %.3fs\n", latency);
/* process scheduled downtime info */
if(event->event_data) {
handle_scheduled_downtime_by_id(*(unsigned long *)event->event_data);
free(event->event_data);
event->event_data = NULL;
}
break;
case EVENT_SFRESHNESS_CHECK:
log_debug_info(DEBUGL_EVENTS, 0, "** Service Result Freshness Check Event. Latency: %.3fs\n", latency);
/* check service result freshness */
check_service_result_freshness();
break;
case EVENT_HFRESHNESS_CHECK:
log_debug_info(DEBUGL_EVENTS, 0, "** Host Result Freshness Check Event. Latency: %.3fs\n", latency);
/* check host result freshness */
check_host_result_freshness();
break;
case EVENT_EXPIRE_DOWNTIME:
log_debug_info(DEBUGL_EVENTS, 0, "** Expire Downtime Event. Latency: %.3fs\n", latency);
/* check for expired scheduled downtime entries */
check_for_expired_downtime();
break;
case EVENT_RESCHEDULE_CHECKS:
/* adjust scheduling of host and service checks */
log_debug_info(DEBUGL_EVENTS, 0, "** Reschedule Checks Event. Latency: %.3fs\n", latency);
adjust_check_scheduling();
break;
case EVENT_EXPIRE_COMMENT:
log_debug_info(DEBUGL_EVENTS, 0, "** Expire Comment Event. Latency: %.3fs\n", latency);
/* check for expired comment */
check_for_expired_comment((unsigned long)event->event_data);
break;
case EVENT_CHECK_PROGRAM_UPDATE:
log_debug_info(DEBUGL_EVENTS, 0, "** Check For Program Update. Latency: %.3fs\n", latency);
/* check for new versions of Nagios */
check_for_nagios_updates(FALSE, TRUE);
break;
case EVENT_USER_FUNCTION:
log_debug_info(DEBUGL_EVENTS, 0, "** User Function Event. Latency: %.3fs\n", latency);
/* run a user-defined function */
if(event->event_data != NULL) {
userfunc = event->event_data;
(*userfunc)(event->event_args);
}
break;
default:
break;
}
#ifdef USE_EVENT_BROKER
/* send event data to broker */
broker_timed_event(NEBTYPE_TIMEDEVENT_END, NEBFLAG_NONE, NEBATTR_NONE, event, NULL);
#endif
log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_timed_event() end\n");
return OK;
}
/* The squeue internal event type, declared again here so we can manipulate the
* scheduling queue without a malloc/free for each add/remove.
* @todo: Refactor this to not depend so heavily on the event queue
* implementation, doing so efficiently may require a different scheduling queue
* data structure. */
struct squeue_event {
unsigned int pos;
pqueue_pri_t pri;
struct timeval when;
void *data;
};
/*
* Adjusts scheduling of active, non-forced host and service checks.
*/
void adjust_check_scheduling(void) {
pqueue_t *temp_pqueue; /* squeue_t is a typedef of pqueue_t. */
struct squeue_event *sq_event;
struct squeue_event **events_to_reschedule;
timed_event *temp_event;
service *temp_service = NULL;
host *temp_host = NULL;
const double INTER_CHECK_RESCHEDULE_THRESHOLD = scheduling_info.service_inter_check_delay * 0.25;
double inter_check_delay = 0.0;
double new_run_time_offset = 0.0;
time_t first_window_time;
time_t last_window_time;
struct timeval last_check_tv = { (time_t)0, (suseconds_t)0 };
int adjust_scheduling = FALSE;
int total_checks = 0;
int i;
log_debug_info(DEBUGL_FUNCTIONS, 0, "adjust_check_scheduling() start\n");
/* Determine our adjustment window. */
first_window_time = time(NULL);
last_window_time = first_window_time + auto_rescheduling_window;
/* Nothing to do if the first event is after the reschedule window. */
sq_event = pqueue_peek(nagios_squeue);
temp_event = sq_event ? sq_event->data : NULL;
if (!temp_event || temp_event->run_time > last_window_time)
return;
/* Get a sorted array of all check events to reschedule. First we need a
* duplicate of nagios_squeue so we can get the events in-order without
* having to remove them from the original queue. We will use
* pqueue_change_priority() to move the check events in the original queue.
* @note: This is horribly dependent on implementation details of squeue
* and pqueue, but we don't have much choice to avoid a free/malloc of each
* squeue_event from the head to last_window_time, or avoid paying the full
* O(n lg n) penalty twice to drain and rebuild the queue. */
temp_pqueue = malloc(sizeof(*temp_pqueue));
if (!temp_pqueue) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to allocate queue needed to adjust check scheduling.\n");
return;
}
*temp_pqueue = *nagios_squeue;
/* We need a separate copy of the underlying queue array. */
temp_pqueue->d = malloc(temp_pqueue->size * sizeof(void*));
if (!temp_pqueue->d) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to allocate queue data needed to adjust check scheduling.\n");
free(temp_pqueue);
return;
}
memcpy(temp_pqueue->d, nagios_squeue->d, temp_pqueue->size * sizeof(void*));
temp_pqueue->avail = temp_pqueue->size;
/* Now allocate space for a sorted array of check events. We shouldn't need
* space for all events, but we can't really calculate how many we'll need
* without looking at all events. */
events_to_reschedule = malloc((temp_pqueue->size - 1) * sizeof(void*));
if (!events_to_reschedule) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to allocate memory needed to adjust check scheduling.\n");
pqueue_free(temp_pqueue); /* pqueue_free() to keep the events. */
return;
}
/* Now we get the events to reschedule and collect some scheduling info. */
while ((sq_event = pqueue_pop(temp_pqueue))) {
/* We need a timed_event and event data. */
temp_event = sq_event->data;
if (!temp_event || !temp_event->event_data)
continue;
/* Skip events before our current window. */
if (temp_event->run_time < first_window_time)
continue;
/* We're done once past the end of the window. */
if (temp_event->run_time > last_window_time)
break;
switch (temp_event->event_type) {
case EVENT_HOST_CHECK:
temp_host = temp_event->event_data;
/* Leave forced checks. */
if (temp_host->check_options & CHECK_OPTION_FORCE_EXECUTION)
continue;
break;
case EVENT_SERVICE_CHECK:
temp_service = temp_event->event_data;
/* Leave forced checks. */
if (temp_service->check_options & CHECK_OPTION_FORCE_EXECUTION)
continue;
break;
default:
continue;
}
/* Reschedule if the last check overlap into this one. */
if (last_check_tv.tv_sec > 0 && tv_delta_msec(&last_check_tv, &sq_event->when) < INTER_CHECK_RESCHEDULE_THRESHOLD * 1000) {
/* log_debug_info(DEBUGL_SCHEDULING, 2, "Rescheduling event %d: %.3fs delay.\n", total_checks, tv_delta_f(&last_check_tv, &sq_event->when));
*/ adjust_scheduling = TRUE;
}
last_check_tv = sq_event->when;
events_to_reschedule[total_checks++] = sq_event;
}
/* Removing squeue_events from temp_pqueue invalidates the positions of
* those events in nagios_squeue, so we need to fix that up before we
* return or change their priorities. Start at i=1 since i=0 is unused. */
for (i = 1; i < (int)nagios_squeue->size; ++i) {
if ((sq_event = nagios_squeue->d[i]))
sq_event->pos = i;
}
/* No checks to reschedule, nothing to do... */
if (total_checks < 2 || !adjust_scheduling) {
log_debug_info(DEBUGL_SCHEDULING, 0, "No events need to be rescheduled (%d checks in %ds window).\n", total_checks, auto_rescheduling_window);
pqueue_free(temp_pqueue);
free(events_to_reschedule);
return;
}
inter_check_delay = auto_rescheduling_window / (double)total_checks;
log_debug_info(DEBUGL_SCHEDULING, 0, "Rescheduling events: %d checks in %ds window, ICD: %.3fs.\n", total_checks, auto_rescheduling_window, inter_check_delay);
/* Now smooth out the schedule. */
new_run_time_offset = inter_check_delay * 0.5;
for (i = 0; i < total_checks; ++i, new_run_time_offset += inter_check_delay) {
struct timeval new_run_time;
/* All events_to_reschedule are valid squeue_events with data pointers
* to timed_events for non-forced host or service checks. */
sq_event = events_to_reschedule[i];
temp_event = sq_event->data;
/* Calculate and apply a new queue 'when' time. */
new_run_time.tv_sec = first_window_time + (time_t)floor(new_run_time_offset);
new_run_time.tv_usec = (suseconds_t)(fmod(new_run_time_offset, 1.0) * 1E6);
/* log_debug_info(DEBUGL_SCHEDULING, 2, "Check %d: offset %.3fs, new run time %lu.%06ld.\n", i, new_run_time_offset, (unsigned long)new_run_time.tv_sec, (long)new_run_time.tv_usec);
*/
/* 06/2019 - moved switch earlier in the for loop because we need to check against the check_period before rescheduling the event */
switch (temp_event->event_type) {
case EVENT_HOST_CHECK:
temp_host = temp_event->event_data;
if (check_time_against_period(new_run_time.tv_sec, temp_host->check_period_ptr) == ERROR) {
continue;
}
if (temp_host->next_check != new_run_time.tv_sec) {
temp_host->next_check = new_run_time.tv_sec;
temp_event->run_time = new_run_time.tv_sec;
update_host_status(temp_host, FALSE);
}
break;
case EVENT_SERVICE_CHECK:
temp_service = temp_event->event_data;
if (check_time_against_period(new_run_time.tv_sec, temp_service->check_period_ptr) == ERROR) {
continue;
}
if (temp_service->next_check != new_run_time.tv_sec) {
temp_service->next_check = new_run_time.tv_sec;
temp_event->run_time = new_run_time.tv_sec;
update_service_status(temp_service, FALSE);
}
break;
default:
break;
}
squeue_change_priority_tv(nagios_squeue, sq_event, &new_run_time);
if (temp_event->run_time != new_run_time.tv_sec) {
temp_event->run_time = new_run_time.tv_sec;
}
} /* end for loop */
log_debug_info(DEBUGL_FUNCTIONS, 0, "adjust_check_scheduling() end\n");
pqueue_free(temp_pqueue);
free(events_to_reschedule);
return;
}
static void adjust_squeue_for_time_change(squeue_t **q, int delta) {
timed_event *event;
squeue_t *sq_new;
/*
* this is pretty inefficient in terms of free() + malloc(),
* but it should be pretty rare that we have to adjust times
* so we go with the well-tested codepath.
*/
sq_new = squeue_create(squeue_size(*q));
while ((event = squeue_pop(*q))) {
if (event->compensate_for_time_change == TRUE) {
if (event->timing_func) {
time_t (*timingfunc)(void);
timingfunc = event->timing_func;
event->run_time = timingfunc();
}
else {
event->run_time += delta;
}
}
if(event->priority) {
event->sq_event = squeue_add_usec(sq_new, event->run_time, event->priority - 1, event);
}
else {
event->sq_event = squeue_add(sq_new, event->run_time, event);
}
}
squeue_destroy(*q, 0);
*q = sq_new;
}
/* attempts to compensate for a change in the system time */
void compensate_for_system_time_change(unsigned long last_time, unsigned long current_time) {
unsigned long time_difference = 0L;
service *temp_service = NULL;
host *temp_host = NULL;
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
int delta = 0;
log_debug_info(DEBUGL_FUNCTIONS, 0, "compensate_for_system_time_change() start\n");
/*
* if current_time < last_time, delta will be negative so we can
* still use addition to all effected timestamps
*/
delta = current_time - last_time;
/* we moved back in time... */
if(last_time > current_time) {
time_difference = last_time - current_time;
get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds);
log_debug_info(DEBUGL_EVENTS, 0, "Detected a backwards time change of %dd %dh %dm %ds.\n", days, hours, minutes, seconds);
}
/* we moved into the future... */
else {
time_difference = current_time - last_time;
get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds);
log_debug_info(DEBUGL_EVENTS, 0, "Detected a forwards time change of %dd %dh %dm %ds.\n", days, hours, minutes, seconds);
}
/* log the time change */
logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_WARNING, TRUE, "Warning: A system time change of %d seconds (%dd %dh %dm %ds %s in time) has been detected. Compensating...\n",
delta, days, hours, minutes, seconds,
(last_time > current_time) ? "backwards" : "forwards");
adjust_squeue_for_time_change(&nagios_squeue, delta);
/* adjust service timestamps */
for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_notification);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_check);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->next_check);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_state_change);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_service->last_hard_state_change);
/* recalculate next re-notification time */
temp_service->next_notification = get_next_service_notification_time(temp_service, temp_service->last_notification);
/* update the status data */
update_service_status(temp_service, FALSE);
}
/* adjust host timestamps */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_notification);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_check);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->next_check);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_state_change);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_hard_state_change);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_state_history_update);
/* recalculate next re-notification time */
temp_host->next_notification = get_next_host_notification_time(temp_host, temp_host->last_notification);
/* update the status data */
update_host_status(temp_host, FALSE);
}
/* adjust program timestamps */
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &program_start);
adjust_timestamp_for_time_change(last_time, current_time, time_difference, &event_start);
/* update the status data */
update_program_status(FALSE);
return;
}
/* adjusts a timestamp variable in accordance with a system time change */
void adjust_timestamp_for_time_change(time_t last_time, time_t current_time, unsigned long time_difference, time_t *ts) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "adjust_timestamp_for_time_change()\n");
/* we shouldn't do anything with epoch values */
if(*ts == (time_t)0)
return;
/* we moved back in time... */
if(last_time > current_time) {
/* we can't precede the UNIX epoch */
if(time_difference > (unsigned long)*ts)
*ts = (time_t)0;
else
*ts = (time_t)(*ts - time_difference);
}
/* we moved into the future... */
else
*ts = (time_t)(*ts + time_difference);
return;
}
nagios-4.4.6/base/flapping.c 0000664 0000000 0000000 00000065144 13652113235 0015676 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* FLAPPING.C - State flap detection and handling routines for 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.
*
*****************************************************************************/
/*********** 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"
/******************************************************************/
/******************** 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(!should_flap_detect(svc))
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 or for this service */
if(enable_flap_detection == FALSE || svc->flap_detection_enabled == FALSE) {
if(svc->is_flapping == TRUE)
clear_service_flap(svc, curved_percent_change, high_threshold, low_threshold, 1);
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, 0);
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(¤t_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->flap_detection_options & (1 << hst->current_state)))
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 or for this service */
if(enable_flap_detection == FALSE || hst->flap_detection_enabled == FALSE) {
if(hst->is_flapping == TRUE)
clear_host_flap(hst, curved_percent_change, high_threshold, low_threshold, 1);
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, 0);
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);
if (svc->flapping_comment_id == 0) {
/* 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, int is_disabled) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "clear_service_flap()\n");
if(svc == NULL)
return;
if (is_disabled == 0) {
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);
} else {
log_debug_info(DEBUGL_FLAPPING, 1, "Disabled flap detection for service '%s' on host '%s'.\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; Disabled flap detection for service\n", svc->host_name, svc->description);
}
/* 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
if (is_disabled == 0) {
/* 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);
if (hst->flapping_comment_id == 0) {
/* 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, int is_disabled) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "clear_host_flap()\n");
if(hst == NULL)
return;
if (is_disabled == 0) {
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);
} else {
log_debug_info(DEBUGL_FLAPPING, 1, "Disabled flap detection for host '%s'.\n", hst->name);
/* log a notice - this one is parsed by the history CGI */
logit(NSLOG_INFO_MESSAGE, FALSE, "HOST FLAPPING ALERT: %s;STOPPED; Disabled flap detection\n", hst->name);
}
/* 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
if (is_disabled == 0) {
/* 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) {
unsigned int i;
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(i = 0; i < num_objects.hosts; i++)
check_for_host_flapping(host_ary[i], FALSE, FALSE, TRUE);
for(i = 0; i < num_objects.services; i++)
check_for_service_flapping(service_ary[i], FALSE, TRUE);
}
/* disables flap detection on a program wide basis */
void disable_flap_detection_routines(void) {
unsigned int i;
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(i = 0; i < num_objects.hosts; i++)
handle_host_flap_detection_disabled(host_ary[i]);
for(i = 0; i < num_objects.services; i++)
handle_service_flap_detection_disabled(service_ary[i]);
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;
}
nagios-4.4.6/base/logging.c 0000664 0000000 0000000 00000034250 13652113235 0015516 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* LOGGING.C - Log file functions for use with 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/statusdata.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/broker.h"
#include
static FILE *debug_file_fp;
static FILE *log_fp;
/******************************************************************/
/************************ 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);
}
static FILE *open_log_file(void)
{
int fh;
struct stat st;
if(log_fp) /* keep it open unless we rotate */
return log_fp;
if ((fh = open(log_file, O_RDWR|O_APPEND|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) {
if (daemon_mode == FALSE)
printf("Warning: Cannot open log file '%s' for writing\n", log_file);
return NULL;
}
log_fp = fdopen(fh, "a+");
if(log_fp == NULL) {
if (daemon_mode == FALSE)
printf("Warning: Cannot open log file '%s' for writing\n", log_file);
return NULL;
}
if ((fstat(fh, &st)) == -1) {
log_fp = NULL;
close(fh);
if (daemon_mode == FALSE)
printf("Warning: Cannot fstat log file '%s'\n", log_file);
return NULL;
}
if (st.st_nlink != 1 || (st.st_mode & S_IFMT) != S_IFREG) {
log_fp = NULL;
close(fh);
if (daemon_mode == FALSE)
printf("Warning: log file '%s' has an invalid mode\n", log_file);
return NULL;
}
(void)fcntl(fileno(log_fp), F_SETFD, FD_CLOEXEC);
return log_fp;
}
int fix_log_file_owner(uid_t uid, gid_t gid)
{
int r1 = 0, r2 = 0;
if (!(log_fp = open_log_file()))
return -1;
r1 = fchown(fileno(log_fp), uid, gid);
if (open_debug_log() != OK)
return -1;
if (debug_file_fp)
r2 = fchown(fileno(debug_file_fp), uid, gid);
/* return 0 if both are 0 and otherwise < 0 */
return r1 < r2 ? r1 : r2;
}
int close_log_file(void)
{
if(!log_fp)
return 0;
fflush(log_fp);
fclose(log_fp);
log_fp = NULL;
return 0;
}
/* write something to the nagios log file */
int write_to_log(char *buffer, unsigned long data_type, time_t *timestamp) {
FILE *fp;
time_t log_time = 0L;
if(buffer == NULL)
return ERROR;
/* don't log anything if we're not actually running... */
if(verify_config || test_scheduling == TRUE)
return OK;
/* make sure we can log this type of entry */
if(!(data_type & logging_options))
return OK;
fp = open_log_file();
if (fp == NULL)
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, "[%llu] %s\n", (unsigned long long)log_time, buffer);
fflush(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 || 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);
free(temp_buffer);
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;
struct stat archive_stat;
int archive_stat_result;
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);
close_log_file();
/* 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);
/* HACK: If the archive exists, don't overwrite it. This is a hack
because the real problem is that some log rotations are executed
early and as a result the next log rotation is scheduled for
the same time as the one that ran early */
archive_stat_result = stat(log_archive, &archive_stat);
if((0 == archive_stat_result) ||
((-1 == archive_stat_result) && (ENOENT != errno))) {
return OK;
}
/* rotate the log file */
rename_result = my_rename(log_file, log_archive);
log_fp = open_log_file();
if (log_fp == NULL)
return ERROR;
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 if activated */
if(log_current_states==TRUE) {
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)
{
int fh;
struct stat st;
/* don't do anything if we're not actually running... */
if(verify_config || test_scheduling == TRUE)
return OK;
/* don't do anything if we're not debugging */
if(debug_level == DEBUGL_NONE)
return OK;
if ((fh = open(debug_file, O_RDWR|O_APPEND|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR)) == -1)
return ERROR;
if((debug_file_fp = fdopen(fh, "a+")) == NULL)
return ERROR;
if ((fstat(fh, &st)) == -1) {
debug_file_fp = NULL;
close(fh);
return ERROR;
}
if (st.st_nlink != 1 || (st.st_mode & S_IFMT) != S_IFREG) {
debug_file_fp = NULL;
close(fh);
return ERROR;
}
(void)fcntl(fh, F_SETFD, FD_CLOEXEC);
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 *tmppath = 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;
/* write the timestamp */
gettimeofday(¤t_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(&tmppath, "%s.old", debug_file);
if(tmppath) {
/* unlink the old debug file */
unlink(tmppath);
/* rotate the debug file */
my_rename(debug_file, tmppath);
/* free memory */
my_free(tmppath);
}
/* open a new file */
open_debug_log();
}
return OK;
}
nagios-4.4.6/base/nagios.c 0000664 0000000 0000000 00000067601 13652113235 0015356 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* NAGIOS.C - Core Program Code For Nagios
*
* Program: Nagios Core
* License: GPL
*
* First Written: 01-28-1999 (start of development)
*
* 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"
#include "../include/workers.h"
/*#define DEBUG_MEMORY 1*/
#ifdef DEBUG_MEMORY
#include
#endif
static int is_worker;
static void set_loadctl_defaults(void)
{
struct rlimit rlim;
/* Workers need to up 'em, master needs to know 'em */
getrlimit(RLIMIT_NOFILE, &rlim);
rlim.rlim_cur = rlim.rlim_max;
setrlimit(RLIMIT_NOFILE, &rlim);
loadctl.nofile_limit = rlim.rlim_max;
#ifdef RLIMIT_NPROC
getrlimit(RLIMIT_NPROC, &rlim);
rlim.rlim_cur = rlim.rlim_max;
setrlimit(RLIMIT_NPROC, &rlim);
loadctl.nproc_limit = rlim.rlim_max;
#else
loadctl.nproc_limit = loadctl.nofile_limit / 2;
#endif
/*
* things may have been configured already. Otherwise we
* set some sort of sane defaults here
*/
if (!loadctl.jobs_max) {
loadctl.jobs_max = loadctl.nproc_limit - 100;
if (!is_worker && loadctl.jobs_max > (loadctl.nofile_limit - 50) * wproc_num_workers_online) {
loadctl.jobs_max = (loadctl.nofile_limit - 50) * wproc_num_workers_online;
}
}
if (!loadctl.jobs_limit)
loadctl.jobs_limit = loadctl.jobs_max;
if (!loadctl.backoff_limit)
loadctl.backoff_limit = online_cpus() * 2.5;
if (!loadctl.rampup_limit)
loadctl.rampup_limit = online_cpus() * 0.8;
if (!loadctl.backoff_change)
loadctl.backoff_change = loadctl.jobs_limit * 0.3;
if (!loadctl.rampup_change)
loadctl.rampup_change = loadctl.backoff_change * 0.25;
if (!loadctl.check_interval)
loadctl.check_interval = 60;
if (!loadctl.jobs_min)
loadctl.jobs_min = online_cpus() * 20; /* pessimistic */
}
static int test_path_access(const char *program, int mode)
{
char *envpath, *p, *colon;
int ret, our_errno = 1500; /* outside errno range */
if (program[0] == '/' || !(envpath = getenv("PATH")))
return access(program, mode);
if (!(envpath = strdup(envpath))) {
errno = ENOMEM;
return -1;
}
for (p = envpath; p; p = colon + 1) {
char *path;
colon = strchr(p, ':');
if (colon)
*colon = 0;
asprintf(&path, "%s/%s", p, program);
ret = access(path, mode);
free(path);
if (!ret)
break;
if (ret < 0) {
if (errno == ENOENT)
continue;
if (our_errno > errno)
our_errno = errno;
}
if (!colon)
break;
}
free(envpath);
if (!ret)
errno = 0;
else
errno = our_errno;
return ret;
}
static int nagios_core_worker(const char *path)
{
int sd, ret;
char response[128];
is_worker = 1;
set_loadctl_defaults();
sd = nsock_unix(path, NSOCK_TCP | NSOCK_CONNECT);
if (sd < 0) {
printf("Failed to connect to query socket '%s': %s: %s\n",
path, nsock_strerror(sd), strerror(errno));
return 1;
}
ret = nsock_printf_nul(sd, "@wproc register name=Core Worker %ld;pid=%ld", (long)getpid(), (long)getpid());
if (ret < 0) {
printf("Failed to register as worker.\n");
return 1;
}
ret = read(sd, response, 3);
if (ret != 3) {
printf("Failed to read response from wproc manager\n");
return 1;
}
if (memcmp(response, "OK", 3)) {
read(sd, response + 3, sizeof(response) - 4);
response[sizeof(response) - 2] = 0;
printf("Failed to register with wproc manager: %s\n", response);
return 1;
}
enter_worker(sd, start_cmd);
free_worker_memory(WPROC_FORCE);
free_memory(get_global_macros());
return 0;
}
/*
* only handles logfile for now, which we stash in macros to
* make sure we can log *somewhere* in case the new path is
* completely inaccessible.
*/
static int test_configured_paths(void)
{
FILE *fp;
nagios_macros *mac;
mac = get_global_macros();
fp = fopen(log_file, "a+");
if (!fp) {
/*
* we do some variable trashing here so logit() can
* open the old logfile (if any), in case we got a
* restart command or a SIGHUP
*/
char *value_absolute = log_file;
log_file = mac->x[MACRO_LOGFILE];
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to open logfile '%s' for writing: %s\n", value_absolute, strerror(errno));
return ERROR;
}
fclose(fp);
/* save the macro */
mac->x[MACRO_LOGFILE] = log_file;
return OK;
}
int main(int argc, char **argv) {
int result;
int error = FALSE;
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;
const char *worker_socket = NULL;
int i;
#ifdef HAVE_SIGACTION
struct sigaction sig_action;
#endif
#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'},
{"precache-objects", no_argument, 0, 'p'},
{"use-precached-objects", no_argument, 0, 'u'},
{"enable-timing-point", no_argument, 0, 'T'},
{"worker", required_argument, 0, 'W'},
{0, 0, 0, 0}
};
#define getopt(argc, argv, o) getopt_long(argc, argv, o, long_options, &option_index)
#endif
memset(&loadctl, 0, sizeof(loadctl));
mac = get_global_macros();
/* make sure we have the correct number of command line arguments */
if(argc < 2)
error = TRUE;
/* get all command line arguments */
while(1) {
c = getopt(argc, argv, "+hVvdspuxTW");
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++;
break;
case 's': /* scheduling check */
test_scheduling = TRUE;
break;
case 'd': /* daemon mode */
daemon_mode = TRUE;
break;
case 'p': /* precache object config */
precache_objects = TRUE;
break;
case 'u': /* use precached object config */
use_precached_objects = TRUE;
break;
case 'T':
enable_timing_point = TRUE;
break;
case 'W':
worker_socket = optarg;
break;
case 'x':
printf("Warning: -x is deprecated and will be removed\n");
break;
default:
break;
}
}
#ifdef DEBUG_MEMORY
mtrace();
#endif
/* if we're a worker we can skip everything below */
if(worker_socket) {
exit(nagios_core_worker(worker_socket));
}
/* Initialize configuration variables */
init_main_cfg_vars(1);
init_shared_cfg_vars(1);
if(daemon_mode == FALSE) {
printf("\nNagios Core %s\n", PROGRAM_VERSION);
printf("Copyright (c) 2009-present 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: https://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");
cleanup();
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] \n", argv[0]);
printf("\n");
printf("Options:\n");
printf("\n");
printf(" -v, --verify-config Verify all configuration data (-v -v for more info)\n");
printf(" -s, --test-scheduling Shows projected/recommended check scheduling and other\n");
printf(" diagnostic info based on the current configuration files.\n");
printf(" -T, --enable-timing-point Enable timed commentary on initialization\n");
printf(" -x, --dont-verify-paths Deprecated (Don't check for circular object paths)\n");
printf(" -p, --precache-objects Precache object configuration\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(" -W, --worker /path/to/socket Act as a worker for an already running daemon\n");
printf("\n");
printf("Visit the Nagios website at https://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");
cleanup();
exit(ERROR);
}
/*
* config file is last argument specified.
* Make sure it uses an absolute path
*/
config_file = nspath_absolute(argv[optind], NULL);
if(config_file == NULL) {
printf("Error allocating memory.\n");
cleanup();
exit(ERROR);
}
config_file_dir = nspath_absolute_dirname(config_file, NULL);
/*
* Set the signal handler for the SIGXFSZ signal here because
* we may encounter this signal before the other signal handlers
* are set.
*/
#ifdef HAVE_SIGACTION
sig_action.sa_sigaction = NULL;
sig_action.sa_handler = handle_sigxfsz;
sigfillset(&sig_action.sa_mask);
sig_action.sa_flags = SA_NODEFER|SA_RESTART;
sigaction(SIGXFSZ, &sig_action, NULL);
#else
signal(SIGXFSZ, handle_sigxfsz);
#endif
/*
* let's go to town. We'll be noisy if we're verifying config
* or running scheduling tests.
*/
if(verify_config || test_scheduling || precache_objects) {
reset_variables();
/*
* if we don't beef up our resource limits as much as
* we can, it's quite possible we'll run headlong into
* EAGAIN due to too many processes when we try to
* drop privileges later.
*/
set_loadctl_defaults();
if(verify_config)
printf("Reading configuration data...\n");
/* read our config file */
result = read_main_config_file(config_file);
if(result != OK) {
printf(" Error processing main config file!\n\n");
cleanup();
exit(EXIT_FAILURE);
}
if(verify_config)
printf(" Read main config file okay...\n");
/* drop privileges */
if((result = drop_privileges(nagios_user, nagios_group)) == ERROR) {
printf(" Failed to drop privileges. Aborting.");
cleanup();
exit(EXIT_FAILURE);
}
/*
* this must come after dropping privileges, so we make
* sure to test access permissions as the right user.
*/
if (!verify_config && test_configured_paths() == ERROR) {
printf(" One or more path problems detected. Aborting.\n");
cleanup();
exit(EXIT_FAILURE);
}
/* read object config files */
result = read_all_object_data(config_file);
if(result != OK) {
printf(" Error processing object config files!\n\n");
/* 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 '%s'\n", DEFAULT_CONFIG_FILE);
}
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 definitions. 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");
cleanup();
exit(EXIT_FAILURE);
}
if(verify_config) {
printf(" Read object config files okay...\n\n");
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("\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 definitions. 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");
cleanup();
exit(EXIT_FAILURE);
}
if(verify_config) {
printf("\nThings look okay - No serious problems were detected during the pre-flight check\n");
}
/* scheduling tests need a bit more than config verifications */
if(test_scheduling == TRUE) {
/* we'll need the event queue here so we can time insertions */
init_event_queue();
timing_point("Done initializing event queue\n");
/* read initial service and host state information */
initialize_retention_data(config_file);
read_initial_state_information();
timing_point("Retention data and initial state parsed\n");
/* initialize the event timing loop */
init_timing_loop();
timing_point("Timing loop initialized\n");
/* display scheduling information */
display_scheduling_info();
}
if(precache_objects) {
result = fcache_objects(object_precache_file);
timing_point("Done precaching objects\n");
if(result == OK) {
printf("Object precache file created:\n%s\n", object_precache_file);
}
else {
printf("Failed to precache objects to '%s': %s\n", object_precache_file, strerror(errno));
}
}
/* clean up after ourselves */
cleanup();
/* exit */
timing_point("Exiting\n");
/* make valgrind shut up about still reachable memory */
neb_free_module_list();
cleanup();
my_free(config_file);
my_free(config_file_dir);
exit(result);
}
/* else start to monitor things... */
else {
/*
* if we're called with a relative path we must make
* it absolute so we can launch our workers.
* If not, we needn't bother, as we're using execvp()
*/
if (strchr(argv[0], '/'))
nagios_binary_path = nspath_absolute(argv[0], NULL);
else
nagios_binary_path = strdup(argv[0]);
if (!nagios_binary_path) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to allocate memory for nagios_binary_path\n");
cleanup();
exit(EXIT_FAILURE);
}
if (!(nagios_iobs = iobroker_create())) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to create IO broker set: %s\n",
strerror(errno));
cleanup();
exit(EXIT_FAILURE);
}
/* keep monitoring things until we get a shutdown command */
do {
/* reset internal book-keeping (in case we're restarting) */
wproc_num_workers_spawned = wproc_num_workers_online = 0;
caught_signal = sigshutdown = FALSE;
sig_id = 0;
/* reset program variables */
reset_variables();
timing_point("Variables reset\n");
/* get PID */
nagios_pid = (int)getpid();
/* read in the configuration files (main and resource config files) */
result = read_main_config_file(config_file);
if (result != OK) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to process config file '%s'. Aborting\n", config_file);
cleanup();
exit(EXIT_FAILURE);
}
timing_point("Main config file read\n");
/* 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], "%llu", (unsigned long long)program_start);
/* 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());
cleanup();
exit(EXIT_FAILURE);
}
/* get new PID */
nagios_pid = (int)getpid();
}
/* 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);
}
if (test_path_access(nagios_binary_path, X_OK)) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: failed to access() %s: %s\n", nagios_binary_path, strerror(errno));
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Spawning workers will be impossible. Aborting.\n");
cleanup();
exit(EXIT_FAILURE);
}
if (test_configured_paths() == ERROR) {
/* error has already been logged */
cleanup();
exit(EXIT_FAILURE);
}
/* 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);
/* open debug log now that we're the right user */
open_debug_log();
#ifdef USE_EVENT_BROKER
/* initialize modules */
neb_init_modules();
neb_init_callback_list();
#endif
timing_point("NEB module API initialized\n");
/* handle signals (interrupts) before we do any socket I/O */
setup_sighandler();
/*
* Initialize query handler and event subscription service.
* This must be done before modules are initialized, so
* the modules can use our in-core stuff properly
*/
if (qh_init(qh_socket_path ? qh_socket_path : DEFAULT_QUERY_SOCKET) != OK) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to initialize query handler. Aborting\n");
exit(EXIT_FAILURE);
}
timing_point("Query handler initialized\n");
#ifdef ENABLE_NERD
nerd_init();
timing_point("NERD initialized\n");
#endif
/* initialize check workers */
if(init_workers(num_check_workers) < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to spawn workers. Aborting\n");
exit(EXIT_FAILURE);
}
timing_point("%u workers spawned\n", wproc_num_workers_spawned);
i = 0;
while (i < 50 && wproc_num_workers_online < wproc_num_workers_spawned) {
iobroker_poll(nagios_iobs, 50);
i++;
}
timing_point("%u workers connected\n", wproc_num_workers_online);
/* now that workers have arrived we can set the defaults */
set_loadctl_defaults();
#ifdef USE_EVENT_BROKER
/* load modules */
if (neb_load_all_modules() != OK) {
logit(NSLOG_CONFIG_ERROR, ERROR, "Error: Module loading failed. Aborting.\n");
/* if we're dumping core, we must remove all dl-files */
if (daemon_dumps_core)
neb_unload_all_modules(NEBMODULE_FORCE_UNLOAD, NEBMODULE_NEB_SHUTDOWN);
cleanup();
exit(EXIT_FAILURE);
}
timing_point("Modules loaded\n");
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_PRELAUNCH, NEBFLAG_NONE, NEBATTR_NONE, NULL);
timing_point("First callback made\n");
#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(TRUE);
}
#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);
}
timing_point("Object configuration parsed and understood\n");
#ifdef DETECT_RLIMIT_PROBLEM
/* lets do a quick system limit detection
to determine if we're likely to run into any
problems. */
rlimit_problem_detection(num_check_workers);
timing_point("Limit detection");
#endif
/* write the objects.cache file */
fcache_objects(object_cache_file);
timing_point("Objects cached\n");
init_event_queue();
timing_point("Event queue initialized\n");
#ifdef USE_EVENT_BROKER
/* send program data to broker */
broker_program_state(NEBTYPE_PROCESS_START, NEBFLAG_NONE, NEBATTR_NONE, NULL);
#endif
/* initialize status data only if we're starting (no restarts) */
if(sigrestart == FALSE) {
initialize_status_data(config_file);
timing_point("Status data initialized\n");
}
/* initialize scheduled downtime data */
initialize_downtime_data();
timing_point("Downtime data initialized\n");
/* read initial service and host state information */
initialize_retention_data(config_file);
timing_point("Retention data initialized\n");
read_initial_state_information();
timing_point("Initial state information read\n");
/* initialize comment data */
initialize_comment_data();
timing_point("Comment data initialized\n");
/* initialize performance data */
initialize_performance_data(config_file);
timing_point("Performance data initialized\n");
/* initialize the event timing loop */
init_timing_loop();
timing_point("Event timing loop initialized\n");
/* initialize check statistics */
init_check_stats();
timing_point("check stats initialized\n");
/* check for updates */
check_for_nagios_updates(FALSE, TRUE);
timing_point("Update check concluded\n");
/* update all status data (with retained information) */
update_all_status_data();
timing_point("Status data updated\n");
/* log initial host and service state */
log_host_states(INITIAL_STATES, NULL);
log_service_states(INITIAL_STATES, NULL);
timing_point("Initial states logged\n");
/* reset the restart flag */
sigrestart = FALSE;
/* fire up command file worker */
launch_command_file_worker();
timing_point("Command file worker launched\n");
#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], "%llu", (unsigned long long)event_start);
timing_point("Entering event execution loop\n");
/***** start monitoring all services *****/
/* (doesn't return until a restart or shutdown signal is encountered) */
event_execution_loop();
/*
* immediately deinitialize the query handler so it
* can remove modules that have stashed data with it
*/
qh_deinit(qh_socket_path ? qh_socket_path : DEFAULT_QUERY_SOCKET);
/* 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 lose them */
/* did we catch a signal? */
if(caught_signal == TRUE) {
if(sig_id == SIGHUP)
logit(NSLOG_PROCESS_INFO, TRUE, "Caught SIGHUP, restarting...\n");
}
#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();
/* clean up performance data */
cleanup_performance_data();
/* clean up the scheduled downtime data */
cleanup_downtime_data();
/* clean up comment data */
free_comment_data();
/* clean up the status data if we are not restarting */
if(sigrestart == FALSE) {
cleanup_status_data(TRUE);
}
free_worker_memory(WPROC_FORCE);
/* shutdown stuff... */
if(sigshutdown == TRUE) {
shutdown_command_file_worker();
iobroker_destroy(nagios_iobs, IOBROKER_CLOSE_SOCKETS);
nagios_iobs = NULL;
/* log a shutdown message */
logit(NSLOG_PROCESS_INFO, TRUE, "Successfully shutdown... (PID=%d)\n", (int)getpid());
}
/* try and collect any zombie processes */
if (sigrestart == TRUE) {
sleep(1);
int status = 0;
pid_t child_pid;
log_debug_info(DEBUGL_PROCESS, 1, "Calling waitpid() on all children...\n");
while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
log_debug_info(DEBUGL_PROCESS, 2, " * child PID: (%d), status: (%d)\n", child_pid, status);
}
log_debug_info(DEBUGL_PROCESS, 1, "All children have been wait()ed on\n");
cleanup();
}
/* close debug log */
close_debug_log();
}
while(sigrestart == TRUE && sigshutdown == FALSE);
if(daemon_mode == TRUE)
unlink(lock_file);
/* free misc memory */
cleanup();
my_free(lock_file);
my_free(config_file);
my_free(config_file_dir);
my_free(nagios_binary_path);
}
return OK;
}
nagios-4.4.6/base/nagiostats.c 0000664 0000000 0000000 00000172362 13652113235 0016253 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* NAGIOSTATS.C - Displays Nagios Statistics
*
* Program: Nagiostats
* License: GPL
*
* 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 "../lib/libnagios.h"
#include "../include/config.h"
#include "../include/common.h"
#include "../include/nagios.h"
#include "../include/locations.h"
#define STATUS_NO_DATA 0
#define STATUS_INFO_DATA 1
#define STATUS_PROGRAM_DATA 2
#define STATUS_HOST_DATA 3
#define STATUS_SERVICE_DATA 4
static char *main_config_file = NULL;
char *status_file = NULL;
static char *mrtg_variables = NULL;
static const char *mrtg_delimiter = "\n";
static int mrtg_mode = FALSE;
static time_t status_creation_date = 0L;
static char *status_version = NULL;
time_t program_start = 0L;
static int status_service_entries = 0;
static int status_host_entries = 0;
int nagios_pid = 0;
static double min_service_state_change = 0.0;
static int have_min_service_state_change = FALSE;
static double max_service_state_change = 0.0;
static int have_max_service_state_change = FALSE;
static double average_service_state_change = 0.0;
static double min_active_service_state_change = 0.0;
static int have_min_active_service_state_change = FALSE;
static double max_active_service_state_change = 0.0;
static int have_max_active_service_state_change = FALSE;
static double average_active_service_state_change = 0.0;
static double min_active_service_latency = 0.0;
static int have_min_active_service_latency = FALSE;
static double max_active_service_latency = 0.0;
static int have_max_active_service_latency = FALSE;
static double average_active_service_latency = 0.0;
static double min_active_service_execution_time = 0.0;
static int have_min_active_service_execution_time = FALSE;
static double max_active_service_execution_time = 0.0;
static int have_max_active_service_execution_time = FALSE;
static double average_active_service_execution_time = 0.0;
static double min_passive_service_state_change = 0.0;
static int have_min_passive_service_state_change = FALSE;
static double max_passive_service_state_change = 0.0;
static int have_max_passive_service_state_change = FALSE;
static double average_passive_service_state_change = 0.0;
static double min_passive_service_latency = 0.0;
static int have_min_passive_service_latency = FALSE;
static double max_passive_service_latency = 0.0;
static int have_max_passive_service_latency = FALSE;
static double average_passive_service_latency = 0.0;
static int have_min_host_state_change = FALSE;
static double min_host_state_change = 0.0;
static int have_max_host_state_change = FALSE;
static double max_host_state_change = 0.0;
static double average_host_state_change = 0.0;
static int have_min_active_host_state_change = FALSE;
static double min_active_host_state_change = 0.0;
static int have_max_active_host_state_change = FALSE;
static double max_active_host_state_change = 0.0;
static double average_active_host_state_change = 0.0;
static int have_min_active_host_latency = FALSE;
static double min_active_host_latency = 0.0;
static int have_max_active_host_latency = FALSE;
static double max_active_host_latency = 0.0;
static double average_active_host_latency = 0.0;
static int have_min_active_host_execution_time = FALSE;
static double min_active_host_execution_time = 0.0;
static int have_max_active_host_execution_time = FALSE;
static double max_active_host_execution_time = 0.0;
static double average_active_host_execution_time = 0.0;
static int have_min_passive_host_latency = FALSE;
static double min_passive_host_latency = 0.0;
static int have_max_passive_host_latency = FALSE;
static double max_passive_host_latency = 0.0;
static double average_passive_host_latency = 0.0;
static double min_passive_host_state_change = 0.0;
static int have_min_passive_host_state_change = FALSE;
static double max_passive_host_state_change = 0.0;
static int have_max_passive_host_state_change = FALSE;
static double average_passive_host_state_change = 0.0;
static int passive_service_checks = 0;
static int active_service_checks = 0;
static int services_ok = 0;
static int services_warning = 0;
static int services_unknown = 0;
static int services_critical = 0;
static int services_flapping = 0;
static int services_in_downtime = 0;
static int services_checked = 0;
static int services_scheduled = 0;
static int passive_host_checks = 0;
static int active_host_checks = 0;
static int hosts_up = 0;
static int hosts_down = 0;
static int hosts_unreachable = 0;
static int hosts_flapping = 0;
static int hosts_in_downtime = 0;
static int hosts_checked = 0;
static int hosts_scheduled = 0;
static int passive_services_checked_last_1min = 0;
static int passive_services_checked_last_5min = 0;
static int passive_services_checked_last_15min = 0;
static int passive_services_checked_last_1hour = 0;
static int active_services_checked_last_1min = 0;
static int active_services_checked_last_5min = 0;
static int active_services_checked_last_15min = 0;
static int active_services_checked_last_1hour = 0;
static int passive_hosts_checked_last_1min = 0;
static int passive_hosts_checked_last_5min = 0;
static int passive_hosts_checked_last_15min = 0;
static int passive_hosts_checked_last_1hour = 0;
static int active_hosts_checked_last_1min = 0;
static int active_hosts_checked_last_5min = 0;
static int active_hosts_checked_last_15min = 0;
static int active_hosts_checked_last_1hour = 0;
static int active_host_checks_last_1min = 0;
static int active_host_checks_last_5min = 0;
static int active_host_checks_last_15min = 0;
static int active_ondemand_host_checks_last_1min = 0;
static int active_ondemand_host_checks_last_5min = 0;
static int active_ondemand_host_checks_last_15min = 0;
static int active_scheduled_host_checks_last_1min = 0;
static int active_scheduled_host_checks_last_5min = 0;
static int active_scheduled_host_checks_last_15min = 0;
static int passive_host_checks_last_1min = 0;
static int passive_host_checks_last_5min = 0;
static int passive_host_checks_last_15min = 0;
static int active_cached_host_checks_last_1min = 0;
static int active_cached_host_checks_last_5min = 0;
static int active_cached_host_checks_last_15min = 0;
static int parallel_host_checks_last_1min = 0;
static int parallel_host_checks_last_5min = 0;
static int parallel_host_checks_last_15min = 0;
static int serial_host_checks_last_1min = 0;
static int serial_host_checks_last_5min = 0;
static int serial_host_checks_last_15min = 0;
static int active_service_checks_last_1min = 0;
static int active_service_checks_last_5min = 0;
static int active_service_checks_last_15min = 0;
static int active_ondemand_service_checks_last_1min = 0;
static int active_ondemand_service_checks_last_5min = 0;
static int active_ondemand_service_checks_last_15min = 0;
static int active_scheduled_service_checks_last_1min = 0;
static int active_scheduled_service_checks_last_5min = 0;
static int active_scheduled_service_checks_last_15min = 0;
static int passive_service_checks_last_1min = 0;
static int passive_service_checks_last_5min = 0;
static int passive_service_checks_last_15min = 0;
static int active_cached_service_checks_last_1min = 0;
static int active_cached_service_checks_last_5min = 0;
static int active_cached_service_checks_last_15min = 0;
static int external_commands_last_1min = 0;
static int external_commands_last_5min = 0;
static int external_commands_last_15min = 0;
static int display_mrtg_values(void);
static int display_stats(void);
static int read_config_file(void);
static int read_status_file(void);
int main(int argc, char **argv) {
int result;
int error = FALSE;
int display_license = FALSE;
int display_help = FALSE;
int c;
#ifdef HAVE_GETOPT_H
int option_index = 0;
static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{"license", no_argument, NULL, 'L'},
{"config", required_argument, NULL, 'c'},
{"statsfile", required_argument, NULL, 's'},
{"mrtg", no_argument, NULL, 'm'},
{"data", required_argument, NULL, 'd'},
{"delimiter", required_argument, NULL, 'D'},
{NULL, 0, NULL, 0}
};
#define getopt(argc, argv, OPTSTR) getopt_long(argc, argv, OPTSTR, long_options, &option_index)
#endif
/* defaults */
main_config_file = strdup(DEFAULT_CONFIG_FILE);
/* get all command line arguments */
while(1) {
c = getopt(argc, argv, "+hVLc:ms:d:D:");
if(c == -1 || c == EOF)
break;
switch(c) {
case '?':
case 'h':
display_help = TRUE;
break;
case 'V':
display_license = TRUE;
break;
case 'L':
display_license = TRUE;
break;
case 'c':
if(main_config_file)
free(main_config_file);
main_config_file = strdup(optarg);
break;
case 's':
status_file = strdup(optarg);
break;
case 'm':
mrtg_mode = TRUE;
break;
case 'd':
mrtg_variables = strdup(optarg);
break;
case 'D':
mrtg_delimiter = strdup(optarg);
break;
default:
break;
}
}
if(mrtg_mode == FALSE) {
printf("\nNagios Stats %s\n", PROGRAM_VERSION);
printf("Copyright (c) 2003-2008 Ethan Galstad (www.nagios.org)\n");
printf("Last Modified: %s\n", PROGRAM_MODIFICATION_DATE);
printf("License: GPL\n\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);
}
/* 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]\n", argv[0]);
printf("\n");
printf("Startup:\n");
printf(" -V, --version display program version information and exit.\n");
printf(" -L, --license display license information and exit.\n");
printf(" -h, --help display usage information and exit.\n");
printf("\n");
printf("Input file:\n");
printf(" -c, --config=FILE specifies location of main Nagios config file.\n");
printf(" -s, --statsfile=FILE specifies alternate location of file to read Nagios\n");
printf(" performance data from.\n");
printf("\n");
printf("Output:\n");
printf(" -m, --mrtg display output in MRTG compatible format.\n");
printf(" -d, --data=VARS comma-separated list of variables to output in MRTG\n");
printf(" (or compatible) format. See possible values below.\n");
printf(" Percentages are rounded, times are in milliseconds.\n");
printf(" -D, --delimiter=C character to use as delimiter in MRTG output mode.\n");
printf(" Defaults to a newline.\n");
printf("\n");
printf("MRTG DATA VARIABLES (-d option):\n");
printf(" PROGRUNTIME string with time Nagios process has been running.\n");
printf(" PROGRUNTIMETT time Nagios process has been running (time_t format).\n");
printf(" STATUSFILEAGE string with age of status data file.\n");
printf(" STATUSFILEAGETT string with age of status data file (time_t format).\n");
printf(" NAGIOSVERSION string with Nagios version.\n");
printf(" NAGIOSPID pid number of Nagios daemon.\n");
printf(" NAGIOSVERPID string with Nagios version and PID.\n");
printf(" TOTCMDBUF total number of external command buffer slots available.\n");
printf(" USEDCMDBUF number of external command buffer slots currently in use.\n");
printf(" HIGHCMDBUF highest number of external command buffer slots ever in use.\n");
printf(" NUMSERVICES total number of services.\n");
printf(" NUMHOSTS total number of hosts.\n");
printf(" NUMSVCOK number of services OK.\n");
printf(" NUMSVCWARN number of services WARNING.\n");
printf(" NUMSVCUNKN number of services UNKNOWN.\n");
printf(" NUMSVCCRIT number of services CRITICAL.\n");
printf(" NUMSVCPROB number of service problems (WARNING, UNKNOWN or CRITICAL).\n");
printf(" NUMSVCCHECKED number of services that have been checked since start.\n");
printf(" NUMSVCSCHEDULED number of services that are currently scheduled to be checked.\n");
printf(" NUMSVCFLAPPING number of services that are currently flapping.\n");
printf(" NUMSVCDOWNTIME number of services that are currently in downtime.\n");
printf(" NUMHSTUP number of hosts UP.\n");
printf(" NUMHSTDOWN number of hosts DOWN.\n");
printf(" NUMHSTUNR number of hosts UNREACHABLE.\n");
printf(" NUMHSTPROB number of host problems (DOWN or UNREACHABLE).\n");
printf(" NUMHSTCHECKED number of hosts that have been checked since start.\n");
printf(" NUMHSTSCHEDULED number of hosts that are currently scheduled to be checked.\n");
printf(" NUMHSTFLAPPING number of hosts that are currently flapping.\n");
printf(" NUMHSTDOWNTIME number of hosts that are currently in downtime.\n");
printf(" NUMHSTACTCHKxM number of hosts actively checked in last 1/5/15/60 minutes.\n");
printf(" NUMHSTPSVCHKxM number of hosts passively checked in last 1/5/15/60 minutes.\n");
printf(" NUMSVCACTCHKxM number of services actively checked in last 1/5/15/60 minutes.\n");
printf(" NUMSVCPSVCHKxM number of services passively checked in last 1/5/15/60 minutes.\n");
printf(" xxxACTSVCLAT MIN/MAX/AVG active service check latency (ms).\n");
printf(" xxxACTSVCEXT MIN/MAX/AVG active service check execution time (ms).\n");
printf(" xxxACTSVCPSC MIN/MAX/AVG active service check %% state change.\n");
printf(" xxxPSVSVCLAT MIN/MAX/AVG passive service check latency (ms).\n");
printf(" xxxPSVSVCPSC MIN/MAX/AVG passive service check %% state change.\n");
printf(" xxxSVCPSC MIN/MAX/AVG service check %% state change.\n");
printf(" xxxACTHSTLAT MIN/MAX/AVG active host check latency (ms).\n");
printf(" xxxACTHSTEXT MIN/MAX/AVG active host check execution time (ms).\n");
printf(" xxxACTHSTPSC MIN/MAX/AVG active host check %% state change.\n");
printf(" xxxPSVHSTLAT MIN/MAX/AVG passive host check latency (ms).\n");
printf(" xxxPSVHSTPSC MIN/MAX/AVG passive host check %% state change.\n");
printf(" xxxHSTPSC MIN/MAX/AVG host check %% state change.\n");
printf(" NUMACTHSTCHECKSxM number of total active host checks occurring in last 1/5/15 minutes.\n");
printf(" NUMOACTHSTCHECKSxM number of on-demand active host checks occurring in last 1/5/15 minutes.\n");
printf(" NUMCACHEDHSTCHECKSxM number of cached host checks occurring in last 1/5/15 minutes.\n");
printf(" NUMSACTHSTCHECKSxM number of scheduled active host checks occurring in last 1/5/15 minutes.\n");
printf(" NUMPARHSTCHECKSxM number of parallel host checks occurring in last 1/5/15 minutes.\n");
printf(" NUMSERHSTCHECKSxM number of serial host checks occurring in last 1/5/15 minutes.\n");
printf(" NUMPSVHSTCHECKSxM number of passive host checks occurring in last 1/5/15 minutes.\n");
printf(" NUMACTSVCCHECKSxM number of total active service checks occurring in last 1/5/15 minutes.\n");
printf(" NUMOACTSVCCHECKSxM number of on-demand active service checks occurring in last 1/5/15 minutes.\n");
printf(" NUMCACHEDSVCCHECKSxM number of cached service checks occurring in last 1/5/15 minutes.\n");
printf(" NUMSACTSVCCHECKSxM number of scheduled active service checks occurring in last 1/5/15 minutes.\n");
printf(" NUMPSVSVCCHECKSxM number of passive service checks occurring in last 1/5/15 minutes.\n");
printf(" NUMEXTCMDSxM number of external commands processed in last 1/5/15 minutes.\n");
printf("\n");
printf(" Note: Replace x's in MRTG variable names with 'MIN', 'MAX', 'AVG', or the\n");
printf(" the appropriate number (i.e. '1', '5', '15', or '60').\n");
printf("\n");
exit(ERROR);
}
/* if we got no -s option, we must read the main config file */
if (status_file == NULL) {
/* read main config file */
result = read_config_file();
if(result == ERROR && mrtg_mode == FALSE) {
printf("Error processing config file '%s'\n", main_config_file);
return ERROR;
}
}
/* read status file */
result = read_status_file();
if(result == ERROR && mrtg_mode == FALSE) {
printf("Error reading status file '%s': %s\n", status_file, strerror(errno));
return ERROR;
}
/* display stats */
if(mrtg_mode == FALSE)
display_stats();
else
display_mrtg_values();
/* Opsera patch - return based on error, because mrtg_mode was always returning OK */
if(result == ERROR)
return ERROR;
else
return OK;
}
static int display_mrtg_values(void) {
char *temp_ptr;
time_t current_time;
unsigned long time_difference;
int days;
int hours;
int minutes;
int seconds;
time(¤t_time);
if(mrtg_variables == NULL)
return OK;
/* process all variables */
for(temp_ptr = strtok(mrtg_variables, ","); temp_ptr != NULL; temp_ptr = strtok(NULL, ",")) {
if(!strcmp(temp_ptr, "PROGRUNTIME")) {
time_difference = (current_time - program_start);
get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds);
printf("%dd %dh %dm %ds%s", days, hours, minutes, seconds, mrtg_delimiter);
}
else if(!strcmp(temp_ptr, "PROGRUNTIMETT")) {
time_difference = (current_time - program_start);
printf("%lu%s", time_difference, mrtg_delimiter);
}
else if(!strcmp(temp_ptr, "STATUSFILEAGE")) {
time_difference = (current_time - status_creation_date);
get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds);
printf("%dd %dh %dm %ds%s", days, hours, minutes, seconds, mrtg_delimiter);
}
else if(!strcmp(temp_ptr, "STATUSFILEAGETT")) {
time_difference = (current_time - status_creation_date);
printf("%lu%s", time_difference, mrtg_delimiter);
}
else if(!strcmp(temp_ptr, "NAGIOSVERSION"))
printf("%s%s", status_version, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NAGIOSPID"))
printf("%d%s", nagios_pid, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NAGIOSVERPID"))
printf("Nagios %s (pid=%d)%s", status_version, nagios_pid, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSERVICES"))
printf("%d%s", status_service_entries, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHOSTS"))
printf("%d%s", status_host_entries, mrtg_delimiter);
/* active service check latency */
else if(!strcmp(temp_ptr, "MINACTSVCLAT"))
printf("%d%s", (int)(min_active_service_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTSVCLAT"))
printf("%d%s", (int)(max_active_service_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTSVCLAT"))
printf("%d%s", (int)(average_active_service_latency * 1000), mrtg_delimiter);
/* active service check execution time */
else if(!strcmp(temp_ptr, "MINACTSVCEXT"))
printf("%d%s", (int)(min_active_service_execution_time * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTSVCEXT"))
printf("%d%s", (int)(max_active_service_execution_time * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTSVCEXT"))
printf("%d%s", (int)(average_active_service_execution_time * 1000), mrtg_delimiter);
/* active service check percent state change */
else if(!strcmp(temp_ptr, "MINACTSVCPSC"))
printf("%d%s", (int)min_active_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTSVCPSC"))
printf("%d%s", (int)max_active_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTSVCPSC"))
printf("%d%s", (int)average_active_service_state_change, mrtg_delimiter);
/* passive service check latency */
else if(!strcmp(temp_ptr, "MINPSVSVCLAT"))
printf("%d%s", (int)(min_passive_service_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXPSVSVCLAT"))
printf("%d%s", (int)(max_passive_service_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGPSVSVCLAT"))
printf("%d%s", (int)(average_passive_service_latency * 1000), mrtg_delimiter);
/* passive service check percent state change */
else if(!strcmp(temp_ptr, "MINPSVSVCPSC"))
printf("%d%s", (int)min_passive_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXPSVSVCPSC"))
printf("%d%s", (int)max_passive_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGPSVSVCPSC"))
printf("%d%s", (int)average_passive_service_state_change, mrtg_delimiter);
/* service check percent state change */
else if(!strcmp(temp_ptr, "MINSVCPSC"))
printf("%d%s", (int)min_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXSVCPSC"))
printf("%d%s", (int)max_service_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGSVCPSC"))
printf("%d%s", (int)average_service_state_change, mrtg_delimiter);
/* active host check latency */
else if(!strcmp(temp_ptr, "MINACTHSTLAT"))
printf("%d%s", (int)(min_active_host_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTHSTLAT"))
printf("%d%s", (int)(max_active_host_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTHSTLAT"))
printf("%d%s", (int)(average_active_host_latency * 1000), mrtg_delimiter);
/* active host check execution time */
else if(!strcmp(temp_ptr, "MINACTHSTEXT"))
printf("%d%s", (int)(min_active_host_execution_time * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTHSTEXT"))
printf("%d%s", (int)(max_active_host_execution_time * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTHSTEXT"))
printf("%d%s", (int)(average_active_host_execution_time * 1000), mrtg_delimiter);
/* active host check percent state change */
else if(!strcmp(temp_ptr, "MINACTHSTPSC"))
printf("%d%s", (int)min_active_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXACTHSTPSC"))
printf("%d%s", (int)max_active_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGACTHSTPSC"))
printf("%d%s", (int)average_active_host_state_change, mrtg_delimiter);
/* passive host check latency */
else if(!strcmp(temp_ptr, "MINPSVHSTLAT"))
printf("%d%s", (int)(min_passive_host_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXPSVHSTLAT"))
printf("%d%s", (int)(max_passive_host_latency * 1000), mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGPSVHSTLAT"))
printf("%d%s", (int)(average_passive_host_latency * 1000), mrtg_delimiter);
/* passive host check percent state change */
else if(!strcmp(temp_ptr, "MINPSVHSTPSC"))
printf("%d%s", (int)min_passive_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXPSVHSTPSC"))
printf("%d%s", (int)max_passive_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGPSVHSTPSC"))
printf("%d%s", (int)average_passive_host_state_change, mrtg_delimiter);
/* host check percent state change */
else if(!strcmp(temp_ptr, "MINHSTPSC"))
printf("%d%s", (int)min_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "MAXHSTPSC"))
printf("%d%s", (int)max_host_state_change, mrtg_delimiter);
else if(!strcmp(temp_ptr, "AVGHSTPSC"))
printf("%d%s", (int)average_host_state_change, mrtg_delimiter);
/* active host checks over time */
else if(!strcmp(temp_ptr, "NUMHSTACTCHK1M"))
printf("%d%s", active_hosts_checked_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTACTCHK5M"))
printf("%d%s", active_hosts_checked_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTACTCHK15M"))
printf("%d%s", active_hosts_checked_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTACTCHK60M"))
printf("%d%s", active_hosts_checked_last_1hour, mrtg_delimiter);
/* passive host checks over time */
else if(!strcmp(temp_ptr, "NUMHSTPSVCHK1M"))
printf("%d%s", passive_hosts_checked_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTPSVCHK5M"))
printf("%d%s", passive_hosts_checked_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTPSVCHK15M"))
printf("%d%s", passive_hosts_checked_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTPSVCHK60M"))
printf("%d%s", passive_hosts_checked_last_1hour, mrtg_delimiter);
/* active service checks over time */
else if(!strcmp(temp_ptr, "NUMSVCACTCHK1M"))
printf("%d%s", active_services_checked_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCACTCHK5M"))
printf("%d%s", active_services_checked_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCACTCHK15M"))
printf("%d%s", active_services_checked_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCACTCHK60M"))
printf("%d%s", active_services_checked_last_1hour, mrtg_delimiter);
/* passive service checks over time */
else if(!strcmp(temp_ptr, "NUMSVCPSVCHK1M"))
printf("%d%s", passive_services_checked_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCPSVCHK5M"))
printf("%d%s", passive_services_checked_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCPSVCHK15M"))
printf("%d%s", passive_services_checked_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCPSVCHK60M"))
printf("%d%s", passive_services_checked_last_1hour, mrtg_delimiter);
/* host check statistics */
else if(!strcmp(temp_ptr, "NUMACTHSTCHECKS1M"))
printf("%d%s", active_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMACTHSTCHECKS5M"))
printf("%d%s", active_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMACTHSTCHECKS15M"))
printf("%d%s", active_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTHSTCHECKS1M"))
printf("%d%s", active_ondemand_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTHSTCHECKS5M"))
printf("%d%s", active_ondemand_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTHSTCHECKS15M"))
printf("%d%s", active_ondemand_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTHSTCHECKS1M"))
printf("%d%s", active_scheduled_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTHSTCHECKS5M"))
printf("%d%s", active_scheduled_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTHSTCHECKS15M"))
printf("%d%s", active_scheduled_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPARHSTCHECKS1M"))
printf("%d%s", parallel_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPARHSTCHECKS5M"))
printf("%d%s", parallel_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPARHSTCHECKS15M"))
printf("%d%s", parallel_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSERHSTCHECKS1M"))
printf("%d%s", serial_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSERHSTCHECKS5M"))
printf("%d%s", serial_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSERHSTCHECKS15M"))
printf("%d%s", serial_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVHSTCHECKS1M"))
printf("%d%s", passive_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVHSTCHECKS5M"))
printf("%d%s", passive_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVHSTCHECKS15M"))
printf("%d%s", passive_host_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDHSTCHECKS1M"))
printf("%d%s", active_cached_host_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDHSTCHECKS5M"))
printf("%d%s", active_cached_host_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDHSTCHECKS15M"))
printf("%d%s", active_cached_host_checks_last_15min, mrtg_delimiter);
/* service check statistics */
else if(!strcmp(temp_ptr, "NUMACTSVCCHECKS1M"))
printf("%d%s", active_service_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMACTSVCCHECKS5M"))
printf("%d%s", active_service_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMACTSVCCHECKS15M"))
printf("%d%s", active_service_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTSVCCHECKS1M"))
printf("%d%s", active_ondemand_service_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTSVCCHECKS5M"))
printf("%d%s", active_ondemand_service_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMOACTSVCCHECKS15M"))
printf("%d%s", active_ondemand_service_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTSVCCHECKS1M"))
printf("%d%s", active_scheduled_service_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTSVCCHECKS5M"))
printf("%d%s", active_scheduled_service_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSACTSVCCHECKS15M"))
printf("%d%s", active_scheduled_service_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVSVCCHECKS1M"))
printf("%d%s", passive_service_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVSVCCHECKS5M"))
printf("%d%s", passive_service_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMPSVSVCCHECKS15M"))
printf("%d%s", passive_service_checks_last_15min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDSVCCHECKS1M"))
printf("%d%s", active_cached_service_checks_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDSVCCHECKS5M"))
printf("%d%s", active_cached_service_checks_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMCACHEDSVCCHECKS15M"))
printf("%d%s", active_cached_service_checks_last_15min, mrtg_delimiter);
/* external command stats */
else if(!strcmp(temp_ptr, "NUMEXTCMDS1M"))
printf("%d%s", external_commands_last_1min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMEXTCMDS5M"))
printf("%d%s", external_commands_last_5min, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMEXTCMDS15M"))
printf("%d%s", external_commands_last_15min, mrtg_delimiter);
/* service states */
else if(!strcmp(temp_ptr, "NUMSVCOK"))
printf("%d%s", services_ok, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCWARN"))
printf("%d%s", services_warning, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCUNKN"))
printf("%d%s", services_unknown, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCCRIT"))
printf("%d%s", services_critical, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCPROB"))
printf("%d%s", services_warning + services_unknown + services_critical, mrtg_delimiter);
/* misc service info */
else if(!strcmp(temp_ptr, "NUMSVCCHECKED"))
printf("%d%s", services_checked, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCSCHEDULED"))
printf("%d%s", services_scheduled, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCFLAPPING"))
printf("%d%s", services_flapping, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMSVCDOWNTIME"))
printf("%d%s", services_in_downtime, mrtg_delimiter);
/* host states */
else if(!strcmp(temp_ptr, "NUMHSTUP"))
printf("%d%s", hosts_up, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTDOWN"))
printf("%d%s", hosts_down, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTUNR"))
printf("%d%s", hosts_unreachable, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTPROB"))
printf("%d%s", hosts_down + hosts_unreachable, mrtg_delimiter);
/* misc host info */
else if(!strcmp(temp_ptr, "NUMHSTCHECKED"))
printf("%d%s", hosts_checked, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTSCHEDULED"))
printf("%d%s", hosts_scheduled, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTFLAPPING"))
printf("%d%s", hosts_flapping, mrtg_delimiter);
else if(!strcmp(temp_ptr, "NUMHSTDOWNTIME"))
printf("%d%s", hosts_in_downtime, mrtg_delimiter);
else
printf("%s%s", temp_ptr, mrtg_delimiter);
}
/* add a newline if necessary */
if(strcmp(mrtg_delimiter, "\n"))
printf("\n");
return OK;
}
static int display_stats(void) {
time_t current_time;
unsigned long time_difference;
int days;
int hours;
int minutes;
int seconds;
time(¤t_time);
printf("CURRENT STATUS DATA\n");
printf("------------------------------------------------------\n");
printf("Status File: %s\n", status_file);
time_difference = (current_time - status_creation_date);
get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds);
printf("Status File Age: %dd %dh %dm %ds\n", days, hours, minutes, seconds);
printf("Status File Version: %s\n", status_version);
printf("\n");
time_difference = (current_time - program_start);
get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds);
printf("Program Running Time: %dd %dh %dm %ds\n", days, hours, minutes, seconds);
printf("Nagios PID: %d\n", nagios_pid);
printf("\n");
printf("Total Services: %d\n", status_service_entries);
printf("Services Checked: %d\n", services_checked);
printf("Services Scheduled: %d\n", services_scheduled);
printf("Services Actively Checked: %d\n", active_service_checks);
printf("Services Passively Checked: %d\n", passive_service_checks);
printf("Total Service State Change: %.3f / %.3f / %.3f %%\n", min_service_state_change, max_service_state_change, average_service_state_change);
printf("Active Service Latency: %.3f / %.3f / %.3f sec\n", min_active_service_latency, max_active_service_latency, average_active_service_latency);
printf("Active Service Execution Time: %.3f / %.3f / %.3f sec\n", min_active_service_execution_time, max_active_service_execution_time, average_active_service_execution_time);
printf("Active Service State Change: %.3f / %.3f / %.3f %%\n", min_active_service_state_change, max_active_service_state_change, average_active_service_state_change);
printf("Active Services Last 1/5/15/60 min: %d / %d / %d / %d\n", active_services_checked_last_1min, active_services_checked_last_5min, active_services_checked_last_15min, active_services_checked_last_1hour);
printf("Passive Service Latency: %.3f / %.3f / %.3f sec\n", min_passive_service_latency, max_passive_service_latency, average_passive_service_latency);
printf("Passive Service State Change: %.3f / %.3f / %.3f %%\n", min_passive_service_state_change, max_passive_service_state_change, average_passive_service_state_change);
printf("Passive Services Last 1/5/15/60 min: %d / %d / %d / %d\n", passive_services_checked_last_1min, passive_services_checked_last_5min, passive_services_checked_last_15min, passive_services_checked_last_1hour);
printf("Services Ok/Warn/Unk/Crit: %d / %d / %d / %d\n", services_ok, services_warning, services_unknown, services_critical);
printf("Services Flapping: %d\n", services_flapping);
printf("Services In Downtime: %d\n", services_in_downtime);
printf("\n");
printf("Total Hosts: %d\n", status_host_entries);
printf("Hosts Checked: %d\n", hosts_checked);
printf("Hosts Scheduled: %d\n", hosts_scheduled);
printf("Hosts Actively Checked: %d\n", active_host_checks);
printf("Host Passively Checked: %d\n", passive_host_checks);
printf("Total Host State Change: %.3f / %.3f / %.3f %%\n", min_host_state_change, max_host_state_change, average_host_state_change);
printf("Active Host Latency: %.3f / %.3f / %.3f sec\n", min_active_host_latency, max_active_host_latency, average_active_host_latency);
printf("Active Host Execution Time: %.3f / %.3f / %.3f sec\n", min_active_host_execution_time, max_active_host_execution_time, average_active_host_execution_time);
printf("Active Host State Change: %.3f / %.3f / %.3f %%\n", min_active_host_state_change, max_active_host_state_change, average_active_host_state_change);
printf("Active Hosts Last 1/5/15/60 min: %d / %d / %d / %d\n", active_hosts_checked_last_1min, active_hosts_checked_last_5min, active_hosts_checked_last_15min, active_hosts_checked_last_1hour);
printf("Passive Host Latency: %.3f / %.3f / %.3f sec\n", min_passive_host_latency, max_passive_host_latency, average_passive_host_latency);
printf("Passive Host State Change: %.3f / %.3f / %.3f %%\n", min_passive_host_state_change, max_passive_host_state_change, average_passive_host_state_change);
printf("Passive Hosts Last 1/5/15/60 min: %d / %d / %d / %d\n", passive_hosts_checked_last_1min, passive_hosts_checked_last_5min, passive_hosts_checked_last_15min, passive_hosts_checked_last_1hour);
printf("Hosts Up/Down/Unreach: %d / %d / %d\n", hosts_up, hosts_down, hosts_unreachable);
printf("Hosts Flapping: %d\n", hosts_flapping);
printf("Hosts In Downtime: %d\n", hosts_in_downtime);
printf("\n");
printf("Active Host Checks Last 1/5/15 min: %d / %d / %d\n", active_host_checks_last_1min, active_host_checks_last_5min, active_host_checks_last_15min);
printf(" Scheduled: %d / %d / %d\n", active_scheduled_host_checks_last_1min, active_scheduled_host_checks_last_5min, active_scheduled_host_checks_last_15min);
printf(" On-demand: %d / %d / %d\n", active_ondemand_host_checks_last_1min, active_ondemand_host_checks_last_5min, active_ondemand_host_checks_last_15min);
printf(" Parallel: %d / %d / %d\n", parallel_host_checks_last_1min, parallel_host_checks_last_5min, parallel_host_checks_last_15min);
printf(" Serial: %d / %d / %d\n", serial_host_checks_last_1min, serial_host_checks_last_5min, serial_host_checks_last_15min);
printf(" Cached: %d / %d / %d\n", active_cached_host_checks_last_1min, active_cached_host_checks_last_5min, active_cached_host_checks_last_15min);
printf("Passive Host Checks Last 1/5/15 min: %d / %d / %d\n", passive_host_checks_last_1min, passive_host_checks_last_5min, passive_host_checks_last_15min);
printf("Active Service Checks Last 1/5/15 min: %d / %d / %d\n", active_service_checks_last_1min, active_service_checks_last_5min, active_service_checks_last_15min);
printf(" Scheduled: %d / %d / %d\n", active_scheduled_service_checks_last_1min, active_scheduled_service_checks_last_5min, active_scheduled_service_checks_last_15min);
printf(" On-demand: %d / %d / %d\n", active_ondemand_service_checks_last_1min, active_ondemand_service_checks_last_5min, active_ondemand_service_checks_last_15min);
printf(" Cached: %d / %d / %d\n", active_cached_service_checks_last_1min, active_cached_service_checks_last_5min, active_cached_service_checks_last_15min);
printf("Passive Service Checks Last 1/5/15 min: %d / %d / %d\n", passive_service_checks_last_1min, passive_service_checks_last_5min, passive_service_checks_last_15min);
printf("\n");
printf("External Commands Last 1/5/15 min: %d / %d / %d\n", external_commands_last_1min, external_commands_last_5min, external_commands_last_15min);
printf("\n");
printf("\n");
/*
printf("CURRENT COMMENT DATA\n");
printf("----------------------------------------------------\n");
printf("\n");
printf("\n");
printf("CURRENT DOWNTIME DATA\n");
printf("----------------------------------------------------\n");
printf("\n");
*/
return OK;
}
static int read_config_file(void) {
char temp_buffer[MAX_INPUT_BUFFER];
FILE *fp;
char *var;
char *val;
char *main_cfg_dir = NULL;
char *slash = NULL;
main_cfg_dir = nspath_absolute(main_config_file, NULL);
if ((slash = strrchr(main_cfg_dir, '/')))
*slash = 0;
fp = fopen(main_config_file, "r");
if(fp == NULL)
return ERROR;
/* read all lines from the main nagios config file */
while(fgets(temp_buffer, sizeof(temp_buffer) - 1, fp)) {
strip(temp_buffer);
/* skip blank lines and comments */
if(temp_buffer[0] == '#' || temp_buffer[0] == '\x0')
continue;
var = strtok(temp_buffer, "=");
val = strtok(NULL, "\n");
if(val == NULL)
continue;
if(!strcmp(var, "status_file") || !strcmp(var, "status_log") || !strcmp(var, "xsddefault_status_log")) {
if(status_file)
free(status_file);
status_file = nspath_absolute(val, main_cfg_dir);
}
}
fclose(fp);
return OK;
}
static int read_status_file(void) {
char temp_buffer[MAX_INPUT_BUFFER];
FILE *fp = NULL;
int data_type = STATUS_NO_DATA;
char *var = NULL;
char *val = NULL;
char *temp_ptr = NULL;
time_t current_time;
unsigned long time_difference = 0L;
double execution_time = 0.0;
double latency = 0.0;
int check_type = CHECK_TYPE_ACTIVE;
int current_state = STATE_OK;
double state_change = 0.0;
int is_flapping = FALSE;
int downtime_depth = 0;
time_t last_check = 0L;
int should_be_scheduled = TRUE;
int has_been_checked = TRUE;
time(¤t_time);
fp = fopen(status_file, "r");
if(fp == NULL)
return ERROR;
/* read all lines in the status file */
while(fgets(temp_buffer, sizeof(temp_buffer) - 1, fp)) {
/* skip blank lines and comments */
if(temp_buffer[0] == '#' || temp_buffer[0] == '\x0')
continue;
strip(temp_buffer);
/* start of definition */
if(!strcmp(temp_buffer, "servicestatus {")) {
data_type = STATUS_SERVICE_DATA;
status_service_entries++;
}
else if(!strcmp(temp_buffer, "hoststatus {")) {
data_type = STATUS_HOST_DATA;
status_host_entries++;
}
else if(!strcmp(temp_buffer, "info {"))
data_type = STATUS_INFO_DATA;
else if(!strcmp(temp_buffer, "programstatus {"))
data_type = STATUS_PROGRAM_DATA;
/* end of definition */
else if(!strcmp(temp_buffer, "}")) {
switch(data_type) {
case STATUS_INFO_DATA:
break;
case STATUS_PROGRAM_DATA:
/* 02-15-2008 exclude cached host checks from total (they were ondemand checks that never actually executed) */
active_host_checks_last_1min = active_scheduled_host_checks_last_1min + active_ondemand_host_checks_last_1min;
active_host_checks_last_5min = active_scheduled_host_checks_last_5min + active_ondemand_host_checks_last_5min;
active_host_checks_last_15min = active_scheduled_host_checks_last_15min + active_ondemand_host_checks_last_15min;
/* 02-15-2008 exclude cached service checks from total (they were ondemand checks that never actually executed) */
active_service_checks_last_1min = active_scheduled_service_checks_last_1min + active_ondemand_service_checks_last_1min;
active_service_checks_last_5min = active_scheduled_service_checks_last_5min + active_ondemand_service_checks_last_5min;
active_service_checks_last_15min = active_scheduled_service_checks_last_15min + active_ondemand_service_checks_last_15min;
break;
case STATUS_HOST_DATA:
average_host_state_change = (((average_host_state_change * ((double)status_host_entries - 1.0)) + state_change) / (double)status_host_entries);
if(have_min_host_state_change == FALSE || min_host_state_change > state_change) {
have_min_host_state_change = TRUE;
min_host_state_change = state_change;
}
if(have_max_host_state_change == FALSE || max_host_state_change < state_change) {
have_max_host_state_change = TRUE;
max_host_state_change = state_change;
}
if(check_type == CHECK_TYPE_ACTIVE) {
active_host_checks++;
average_active_host_latency = (((average_active_host_latency * ((double)active_host_checks - 1.0)) + latency) / (double)active_host_checks);
if(have_min_active_host_latency == FALSE || min_active_host_latency > latency) {
have_min_active_host_latency = TRUE;
min_active_host_latency = latency;
}
if(have_max_active_host_latency == FALSE || max_active_host_latency < latency) {
have_max_active_host_latency = TRUE;
max_active_host_latency = latency;
}
average_active_host_execution_time = (((average_active_host_execution_time * ((double)active_host_checks - 1.0)) + execution_time) / (double)active_host_checks);
if(have_min_active_host_execution_time == FALSE || min_active_host_execution_time > execution_time) {
have_min_active_host_execution_time = TRUE;
min_active_host_execution_time = execution_time;
}
if(have_max_active_host_execution_time == FALSE || max_active_host_execution_time < execution_time) {
have_max_active_host_execution_time = TRUE;
max_active_host_execution_time = execution_time;
}
average_active_host_state_change = (((average_active_host_state_change * ((double)active_host_checks - 1.0)) + state_change) / (double)active_host_checks);
if(have_min_active_host_state_change == FALSE || min_active_host_state_change > state_change) {
have_min_active_host_state_change = TRUE;
min_active_host_state_change = state_change;
}
if(have_max_active_host_state_change == FALSE || max_active_host_state_change < state_change) {
have_max_active_host_state_change = TRUE;
max_active_host_state_change = state_change;
}
time_difference = current_time - last_check;
if(time_difference <= 3600)
active_hosts_checked_last_1hour++;
if(time_difference <= 900)
active_hosts_checked_last_15min++;
if(time_difference <= 300)
active_hosts_checked_last_5min++;
if(time_difference <= 60)
active_hosts_checked_last_1min++;
}
else {
passive_host_checks++;
average_passive_host_latency = (((average_passive_host_latency * ((double)passive_host_checks - 1.0)) + latency) / (double)passive_host_checks);
if(have_min_passive_host_latency == FALSE || min_passive_host_latency > latency) {
have_min_passive_host_latency = TRUE;
min_passive_host_latency = latency;
}
if(have_max_passive_host_latency == FALSE || max_passive_host_latency < latency) {
have_max_passive_host_latency = TRUE;
max_passive_host_latency = latency;
}
average_passive_host_state_change = (((average_passive_host_state_change * ((double)passive_host_checks - 1.0)) + state_change) / (double)passive_host_checks);
if(have_min_passive_host_state_change == FALSE || min_passive_host_state_change > state_change) {
have_min_passive_host_state_change = TRUE;
min_passive_host_state_change = state_change;
}
if(have_max_passive_host_state_change == FALSE || max_passive_host_state_change < state_change) {
have_max_passive_host_state_change = TRUE;
max_passive_host_state_change = state_change;
}
time_difference = current_time - last_check;
if(time_difference <= 3600)
passive_hosts_checked_last_1hour++;
if(time_difference <= 900)
passive_hosts_checked_last_15min++;
if(time_difference <= 300)
passive_hosts_checked_last_5min++;
if(time_difference <= 60)
passive_hosts_checked_last_1min++;
}
switch(current_state) {
case HOST_UP:
hosts_up++;
break;
case HOST_DOWN:
hosts_down++;
break;
case HOST_UNREACHABLE:
hosts_unreachable++;
break;
default:
break;
}
if(is_flapping == TRUE)
hosts_flapping++;
if(downtime_depth > 0)
hosts_in_downtime++;
if(has_been_checked == TRUE)
hosts_checked++;
if(should_be_scheduled == TRUE)
hosts_scheduled++;
break;
case STATUS_SERVICE_DATA:
average_service_state_change = (((average_service_state_change * ((double)status_service_entries - 1.0)) + state_change) / (double)status_service_entries);
if(have_min_service_state_change == FALSE || min_service_state_change > state_change) {
have_min_service_state_change = TRUE;
min_service_state_change = state_change;
}
if(have_max_service_state_change == FALSE || max_service_state_change < state_change) {
have_max_service_state_change = TRUE;
max_service_state_change = state_change;
}
if(check_type == CHECK_TYPE_ACTIVE) {
active_service_checks++;
average_active_service_latency = (((average_active_service_latency * ((double)active_service_checks - 1.0)) + latency) / (double)active_service_checks);
if(have_min_active_service_latency == FALSE || min_active_service_latency > latency) {
have_min_active_service_latency = TRUE;
min_active_service_latency = latency;
}
if(have_max_active_service_latency == FALSE || max_active_service_latency < latency) {
have_max_active_service_latency = TRUE;
max_active_service_latency = latency;
}
average_active_service_execution_time = (((average_active_service_execution_time * ((double)active_service_checks - 1.0)) + execution_time) / (double)active_service_checks);
if(have_min_active_service_execution_time == FALSE || min_active_service_execution_time > execution_time) {
have_min_active_service_execution_time = TRUE;
min_active_service_execution_time = execution_time;
}
if(have_max_active_service_execution_time == FALSE || max_active_service_execution_time < execution_time) {
have_max_active_service_execution_time = TRUE;
max_active_service_execution_time = execution_time;
}
average_active_service_state_change = (((average_active_service_state_change * ((double)active_service_checks - 1.0)) + state_change) / (double)active_service_checks);
if(have_min_active_service_state_change == FALSE || min_active_service_state_change > state_change) {
have_min_active_service_state_change = TRUE;
min_active_service_state_change = state_change;
}
if(have_max_active_service_state_change == FALSE || max_active_service_state_change < state_change) {
have_max_active_service_state_change = TRUE;
max_active_service_state_change = state_change;
}
time_difference = current_time - last_check;
if(time_difference <= 3600)
active_services_checked_last_1hour++;
if(time_difference <= 900)
active_services_checked_last_15min++;
if(time_difference <= 300)
active_services_checked_last_5min++;
if(time_difference <= 60)
active_services_checked_last_1min++;
}
else {
passive_service_checks++;
average_passive_service_latency = (((average_passive_service_latency * ((double)passive_service_checks - 1.0)) + latency) / (double)passive_service_checks);
if(have_min_passive_service_latency == FALSE || min_passive_service_latency > latency) {
have_min_passive_service_latency = TRUE;
min_passive_service_latency = latency;
}
if(have_max_passive_service_latency == FALSE || max_passive_service_latency < latency) {
have_max_passive_service_latency = TRUE;
max_passive_service_latency = latency;
}
average_passive_service_state_change = (((average_passive_service_state_change * ((double)passive_service_checks - 1.0)) + state_change) / (double)passive_service_checks);
if(have_min_passive_service_state_change == FALSE || min_passive_service_state_change > state_change) {
have_min_passive_service_state_change = TRUE;
min_passive_service_state_change = state_change;
}
if(have_max_passive_service_state_change == FALSE || max_passive_service_state_change < state_change) {
have_max_passive_service_state_change = TRUE;
max_passive_service_state_change = state_change;
}
time_difference = current_time - last_check;
if(time_difference <= 3600)
passive_services_checked_last_1hour++;
if(time_difference <= 900)
passive_services_checked_last_15min++;
if(time_difference <= 300)
passive_services_checked_last_5min++;
if(time_difference <= 60)
passive_services_checked_last_1min++;
}
switch(current_state) {
case STATE_OK:
services_ok++;
break;
case STATE_WARNING:
services_warning++;
break;
case STATE_UNKNOWN:
services_unknown++;
break;
case STATE_CRITICAL:
services_critical++;
break;
default:
break;
}
if(is_flapping == TRUE)
services_flapping++;
if(downtime_depth > 0)
services_in_downtime++;
if(has_been_checked == TRUE)
services_checked++;
if(should_be_scheduled == TRUE)
services_scheduled++;
break;
default:
break;
}
data_type = STATUS_NO_DATA;
execution_time = 0.0;
latency = 0.0;
check_type = 0;
current_state = 0;
state_change = 0.0;
is_flapping = FALSE;
downtime_depth = 0;
last_check = (time_t)0;
has_been_checked = FALSE;
should_be_scheduled = FALSE;
}
/* inside definition */
else if(data_type != STATUS_NO_DATA) {
var = strtok(temp_buffer, "=");
val = strtok(NULL, "\n");
if(val == NULL)
continue;
switch(data_type) {
case STATUS_INFO_DATA:
if(!strcmp(var, "created"))
status_creation_date = strtoul(val, NULL, 10);
else if(!strcmp(var, "version"))
status_version = strdup(val);
break;
case STATUS_PROGRAM_DATA:
if(!strcmp(var, "program_start"))
program_start = strtoul(val, NULL, 10);
else if(!strcmp(var, "nagios_pid"))
nagios_pid = strtoul(val, NULL, 10);
else if(!strcmp(var, "active_scheduled_host_check_stats")) {
if((temp_ptr = strtok(val, ",")))
active_scheduled_host_checks_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_scheduled_host_checks_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_scheduled_host_checks_last_15min = atoi(temp_ptr);
}
else if(!strcmp(var, "active_ondemand_host_check_stats")) {
if((temp_ptr = strtok(val, ",")))
active_ondemand_host_checks_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_ondemand_host_checks_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_ondemand_host_checks_last_15min = atoi(temp_ptr);
}
else if(!strcmp(var, "cached_host_check_stats")) {
if((temp_ptr = strtok(val, ",")))
active_cached_host_checks_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_cached_host_checks_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_cached_host_checks_last_15min = atoi(temp_ptr);
}
else if(!strcmp(var, "passive_host_check_stats")) {
if((temp_ptr = strtok(val, ",")))
passive_host_checks_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
passive_host_checks_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
passive_host_checks_last_15min = atoi(temp_ptr);
}
else if(!strcmp(var, "active_scheduled_service_check_stats")) {
if((temp_ptr = strtok(val, ",")))
active_scheduled_service_checks_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_scheduled_service_checks_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_scheduled_service_checks_last_15min = atoi(temp_ptr);
}
else if(!strcmp(var, "active_ondemand_service_check_stats")) {
if((temp_ptr = strtok(val, ",")))
active_ondemand_service_checks_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_ondemand_service_checks_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_ondemand_service_checks_last_15min = atoi(temp_ptr);
}
else if(!strcmp(var, "cached_service_check_stats")) {
if((temp_ptr = strtok(val, ",")))
active_cached_service_checks_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_cached_service_checks_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
active_cached_service_checks_last_15min = atoi(temp_ptr);
}
else if(!strcmp(var, "passive_service_check_stats")) {
if((temp_ptr = strtok(val, ",")))
passive_service_checks_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
passive_service_checks_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
passive_service_checks_last_15min = atoi(temp_ptr);
}
else if(!strcmp(var, "external_command_stats")) {
if((temp_ptr = strtok(val, ",")))
external_commands_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
external_commands_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
external_commands_last_15min = atoi(temp_ptr);
}
else if(!strcmp(var, "parallel_host_check_stats")) {
if((temp_ptr = strtok(val, ",")))
parallel_host_checks_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
parallel_host_checks_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
parallel_host_checks_last_15min = atoi(temp_ptr);
}
else if(!strcmp(var, "serial_host_check_stats")) {
if((temp_ptr = strtok(val, ",")))
serial_host_checks_last_1min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
serial_host_checks_last_5min = atoi(temp_ptr);
if((temp_ptr = strtok(NULL, ",")))
serial_host_checks_last_15min = atoi(temp_ptr);
}
break;
case STATUS_HOST_DATA:
if(!strcmp(var, "check_execution_time"))
execution_time = strtod(val, NULL);
else if(!strcmp(var, "check_latency"))
latency = strtod(val, NULL);
else if(!strcmp(var, "percent_state_change"))
state_change = strtod(val, NULL);
else if(!strcmp(var, "check_type"))
check_type = atoi(val);
else if(!strcmp(var, "current_state"))
current_state = atoi(val);
else if(!strcmp(var, "is_flapping"))
is_flapping = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "scheduled_downtime_depth"))
downtime_depth = atoi(val);
else if(!strcmp(var, "last_check"))
last_check = strtoul(val, NULL, 10);
else if(!strcmp(var, "has_been_checked"))
has_been_checked = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "should_be_scheduled"))
should_be_scheduled = (atoi(val) > 0) ? TRUE : FALSE;
break;
case STATUS_SERVICE_DATA:
if(!strcmp(var, "check_execution_time"))
execution_time = strtod(val, NULL);
else if(!strcmp(var, "check_latency"))
latency = strtod(val, NULL);
else if(!strcmp(var, "percent_state_change"))
state_change = strtod(val, NULL);
else if(!strcmp(var, "check_type"))
check_type = atoi(val);
else if(!strcmp(var, "current_state"))
current_state = atoi(val);
else if(!strcmp(var, "is_flapping"))
is_flapping = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "scheduled_downtime_depth"))
downtime_depth = atoi(val);
else if(!strcmp(var, "last_check"))
last_check = strtoul(val, NULL, 10);
else if(!strcmp(var, "has_been_checked"))
has_been_checked = (atoi(val) > 0) ? TRUE : FALSE;
else if(!strcmp(var, "should_be_scheduled"))
should_be_scheduled = (atoi(val) > 0) ? TRUE : FALSE;
break;
default:
break;
}
}
}
fclose(fp);
return OK;
}
/* strip newline, carriage return, and tab characters from beginning and end of a string */
void strip(char *buffer) {
register int x;
register int y;
register int z;
if(buffer == NULL || buffer[0] == '\x0')
return;
/* strip end of string */
y = (int)strlen(buffer);
for(x = y - 1; x >= 0; x--) {
if(buffer[x] == ' ' || buffer[x] == '\n' || buffer[x] == '\r' || buffer[x] == '\t' || buffer[x] == 13)
buffer[x] = '\x0';
else
break;
}
/* strip beginning of string (by shifting) */
y = (int)strlen(buffer);
for(x = 0; x < y; x++) {
if(buffer[x] == ' ' || buffer[x] == '\n' || buffer[x] == '\r' || buffer[x] == '\t' || buffer[x] == 13)
continue;
else
break;
}
if(x > 0) {
for(z = x; z < y; z++)
buffer[z - x] = buffer[z];
buffer[y - x] = '\x0';
}
return;
}
/* 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;
return;
}
nagios-4.4.6/base/nebmods.c 0000664 0000000 0000000 00000041202 13652113235 0015512 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* NEBMODS.C - Event Broker Module Functions
*
*
* 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
static nebmodule *neb_module_list;
static nebcallback **neb_callback_list;
/* compat stuff for USE_LTDL */
#ifdef USE_LTDL
# define dlopen(p, flags) lt_dlopen(p)
# define dlclose(p) lt_dlclose(p)
# define dlerror() lt_dlerror()
# define dlsym(hdl, sym) lt_dlsym(hdl, sym)
# define RTLD_NOW 0
# define RTLD_GLOBAL 0
#else
# define lt_dlinit() 0
# define lt_dlexit() 0
#endif
/****************************************************************************/
/****************************************************************************/
/* INITIALIZATION/CLEANUP FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* initialize module routines */
int neb_init_modules(void) {
if(lt_dlinit())
return ERROR;
return OK;
}
/* deinitialize module routines */
int neb_deinit_modules(void) {
if(lt_dlexit())
return ERROR;
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 *)calloc(1, 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;
/* 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;
}
int neb_add_core_module(nebmodule *mod) {
mod->should_be_loaded = FALSE;
mod->is_currently_loaded = TRUE;
mod->core_module = TRUE;
#ifdef USE_LTDL
mod->module_handle = (lt_dlhandle)mod;
#else
mod->module_handle = mod;
#endif
mod->next = neb_module_list;
neb_module_list = mod;
return 0;
}
/* 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; temp_module = next_module) {
next_module = temp_module->next;
for(x = 0; x < NEBMODULE_MODINFO_NUMITEMS; x++)
my_free(temp_module->info[x]);
/* don't free this stuff for core modules */
if (temp_module->core_module)
continue;
my_free(temp_module->filename);
my_free(temp_module->args);
my_free(temp_module);
}
neb_module_list = NULL;
return OK;
}
/****************************************************************************/
/****************************************************************************/
/* LOAD/UNLOAD FUNCTIONS */
/****************************************************************************/
/****************************************************************************/
/* load all modules */
int neb_load_all_modules(void) {
nebmodule *temp_module = NULL;
int ret, errors = 0;
for(temp_module = neb_module_list; temp_module; temp_module = temp_module->next) {
ret = neb_load_module(temp_module);
if (ret != OK) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to load module '%s'.\n", temp_module->filename ? temp_module->filename : "(no file?)");
errors++;
}
}
return errors ? ERROR : OK;
}
/* load a particular module */
int neb_load_module(nebmodule *mod) {
int (*initfunc)(int, char *, void *);
int *module_version_ptr = NULL;
int result = OK;
if(mod == 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 || mod->filename == NULL)
return ERROR;
/* load the module */
mod->module_handle = dlopen(mod->filename, RTLD_NOW | RTLD_GLOBAL);
if(mod->module_handle == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not load module '%s' -> %s\n", mod->filename, dlerror());
return ERROR;
}
/* mark the module as being loaded */
mod->is_currently_loaded = TRUE;
/* find module API version */
module_version_ptr = (int *)dlsym(mod->module_handle, "__neb_api_version");
/* check the module API version */
if(module_version_ptr == NULL || ((*module_version_ptr) != CURRENT_NEB_API_VERSION)) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "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 */
mod->init_func = dlsym(mod->module_handle, "nebmodule_init");
/* if the init function could not be located, unload the module */
if(mod->init_func == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "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, TRUE, "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, TRUE, "Event broker module '%s' initialized successfully.\n", mod->filename);
/* locate the de-initialization function (may or may not be present) */
mod->deinit_func = dlsym(mod->module_handle, "nebmodule_deinit");
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);
/* remove the module's demand-loaded file */
if(daemon_dumps_core == TRUE && mod->dl_file) {
(void)unlink(mod->dl_file);
my_free(mod->dl_file);
}
/* 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);
if(mod->core_module == FALSE) {
/* unload the module */
result = dlclose(mod->module_handle);
if (result != 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not unload module '%s' -> %s\n", mod->filename, dlerror());
return ERROR;
}
}
/* 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(temp_module->module_handle == 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(temp_module->module_handle == 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 = mod_handle;
new_callback->callback_func = callback_func;
new_callback->next = NULL;
/* add new function to callback list, sorted by priority (first come, first served for same priority) */
for(last_callback = NULL, temp_callback = neb_callback_list[callback_type];
temp_callback != NULL;
last_callback = temp_callback, temp_callback = temp_callback->next) {
if(new_callback->priority < temp_callback->priority) {
break;
}
}
new_callback->next = temp_callback;
if(last_callback == NULL) {
neb_callback_list[callback_type] = new_callback;
}
else {
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(temp_callback->module_handle == 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 == 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
nagios-4.4.6/base/nerd.c 0000664 0000000 0000000 00000030026 13652113235 0015015 0 ustar 00root root 0000000 0000000 /*
* Nagios Event Radio Dispatcher
*
* This is a subscriber service which initiates a unix domain socket,
* listens to it and lets other programs connect to it and subscribe
* to various channels using a simple text-based syntax.
*
* This code uses the eventbroker api to get its data, which means
* we're finally eating our own dogfood in that respect.
*
* Note: Disabled by default as of 4.4.0
* ./configure --enable-nerd
* to enable!
*/
#define _GNU_SOURCE 1
#include
#include "include/config.h"
#include
#include
#include "lib/libnagios.h"
#include "include/common.h"
#include "include/objects.h"
#include "include/broker.h"
#include "include/nebmods.h"
#include "include/nebmodules.h"
#include "include/nebstructs.h"
#ifdef ENABLE_NERD
struct nerd_channel {
const char *name; /* name of this channel */
const char *description; /* user-presentable string to document the purpouse of this channel */
unsigned int id; /* channel id (might vary between invocations) */
unsigned int required_options; /* event_broker_options required for this channel */
unsigned int num_callbacks;
unsigned int callbacks[NEBCALLBACK_NUMITEMS];
int (*handler)(int , void *); /* callback handler for this channel */
objectlist *subscriptions; /* subscriber list */
};
static nebmodule nerd_mod; /* fake module to get our callbacks accepted */
static struct nerd_channel **channels;
static unsigned int num_channels, alloc_channels;
static unsigned int chan_host_checks_id, chan_service_checks_id;
static unsigned int chan_opath_checks_id;
static struct nerd_channel *find_channel(const char *name)
{
unsigned int i;
for(i = 0; i < num_channels; i++) {
struct nerd_channel *chan = channels[i];
if(!strcmp(name, chan->name)) {
return chan;
}
}
return NULL;
}
int nerd_get_channel_id(const char *name)
{
struct nerd_channel *chan;
chan = find_channel(name);
if (!chan)
return -1;
return chan->id;
}
static struct nerd_channel *nerd_get_channel(unsigned int chan_id)
{
return chan_id >= num_channels ? NULL : channels[chan_id];
}
objectlist *nerd_get_subscriptions(int chan_id)
{
struct nerd_channel *chan = nerd_get_channel(chan_id);
return chan ? chan->subscriptions : NULL;
}
static int nerd_register_channel_callbacks(struct nerd_channel *chan)
{
unsigned int i;
for(i = 0; i < chan->num_callbacks; i++) {
int result = neb_register_callback(chan->callbacks[i], &nerd_mod, 0, chan->handler);
if(result != 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "nerd: Failed to register callback %d for channel '%s': %d\n",
chan->callbacks[i], chan->name, result);
return -1;
}
}
return 0;
}
static int nerd_deregister_channel_callbacks(struct nerd_channel *chan)
{
unsigned int i;
for(i = 0; i < chan->num_callbacks; i++) {
neb_deregister_callback(chan->callbacks[i], chan->handler);
}
return 0;
}
static int subscribe(int sd, struct nerd_channel *chan, char *fmt)
{
struct nerd_subscription *subscr;
if(!(subscr = calloc(1, sizeof(*subscr))))
return -1;
subscr->sd = sd;
subscr->chan = chan;
subscr->format = fmt ? strdup(fmt) : NULL;
if(!chan->subscriptions) {
nerd_register_channel_callbacks(chan);
}
prepend_object_to_objectlist(&chan->subscriptions, subscr);
return 0;
}
static int cancel_channel_subscription(struct nerd_channel *chan, int sd)
{
objectlist *list, *next, *prev = NULL;
int cancelled = 0;
if(!chan)
return -1;
for(list = chan->subscriptions; list; list = next) {
struct nerd_subscription *subscr = (struct nerd_subscription *)list->object_ptr;
next = list->next;
if(subscr->sd == sd) {
cancelled++;
free(list);
free(subscr);
if(prev) {
prev->next = next;
} else {
chan->subscriptions = next;
}
continue;
}
prev = list;
}
if(cancelled) {
logit(NSLOG_INFO_MESSAGE, TRUE, "nerd: Cancelled %d subscription%s to channel '%s' for %d\n",
cancelled, cancelled == 1 ? "" : "s", chan->name, sd);
}
if(chan->subscriptions == NULL)
nerd_deregister_channel_callbacks(chan);
return 0;
}
static int unsubscribe(int sd, struct nerd_channel *chan)
{
objectlist *list, *next, *prev = NULL;
for(list = chan->subscriptions; list; list = next) {
struct nerd_subscription *subscr = (struct nerd_subscription *)list->object_ptr;
next = list->next;
if(subscr->sd == sd) {
/* found it, so remove it */
free(subscr);
free(list);
if(!prev) {
chan->subscriptions = next;
continue;
} else {
prev->next = next;
}
continue;
}
prev = list;
}
if(chan->subscriptions == NULL) {
nerd_deregister_channel_callbacks(chan);
}
return 0;
}
/* removes a subscriber entirely and closes its socket */
int nerd_cancel_subscriber(int sd)
{
unsigned int i;
for(i = 0; i < num_channels; i++) {
cancel_channel_subscription(channels[i], sd);
}
iobroker_close(nagios_iobs, sd);
return 0;
}
int nerd_broadcast(unsigned int chan_id, void *buf, unsigned int len)
{
struct nerd_channel *chan;
objectlist *list, *next;
if (!(chan = nerd_get_channel(chan_id)))
return -1;
for(list = chan->subscriptions; list; list = next) {
struct nerd_subscription *subscr = (struct nerd_subscription *)list->object_ptr;
int result;
next = list->next;
result = send(subscr->sd, buf, len, 0);
if(result < 0) {
if (errno == EAGAIN)
return 0;
nerd_cancel_subscriber(subscr->sd);
return 500;
}
}
return 0;
}
static int chan_host_checks(int cb, void *data)
{
nebstruct_host_check_data *ds = (nebstruct_host_check_data *)data;
check_result *cr = (check_result *)ds->check_result_ptr;
host *h;
char *buf;
int len;
if(ds->type != NEBTYPE_HOSTCHECK_PROCESSED)
return 0;
if(channels[chan_host_checks_id]->subscriptions == NULL)
return 0;
h = (host *)ds->object_ptr;
len = asprintf(&buf, "%s from %d -> %d: %s\n", h->name, h->last_state, h->current_state, cr->output);
nerd_broadcast(chan_host_checks_id, buf, len);
free(buf);
return 0;
}
static int chan_service_checks(int cb, void *data)
{
nebstruct_service_check_data *ds = (nebstruct_service_check_data *)data;
check_result *cr = (check_result *)ds->check_result_ptr;
service *s;
char *buf;
int len;
if(ds->type != NEBTYPE_SERVICECHECK_PROCESSED)
return 0;
s = (service *)ds->object_ptr;
len = asprintf(&buf, "%s;%s from %d -> %d: %s\n", s->host_name, s->description, s->last_state, s->current_state, cr->output);
nerd_broadcast(chan_service_checks_id, buf, len);
free(buf);
return 0;
}
static char **host_parent_path_cache;
static const char *host_parent_path(host *leaf, char sep)
{
char *ret;
unsigned int len = 0, pos = 0;
objectlist *stack = NULL, *list, *next;
host *h = leaf;
if(!h->parent_hosts)
return h->name;
if(!host_parent_path_cache) {
host_parent_path_cache = calloc(num_objects.hosts, sizeof(char *));
}
if(host_parent_path_cache[h->id]) {
return host_parent_path_cache[h->id];
}
while(h) {
len += strlen(h->name) + 2; /* room for separator */
prepend_object_to_objectlist(&stack, h->name);
if(h->parent_hosts && h->parent_hosts->host_ptr)
h = h->parent_hosts->host_ptr;
else
break;
}
ret = malloc(len + 1);
for(list = stack; list; list = next) {
char *ppart = (char *)list->object_ptr;
next = list->next;
free(list);
ret[pos++] = sep;
memcpy(ret + pos, ppart, strlen(ppart));
pos += strlen(ppart);
}
ret[pos++] = 0;
host_parent_path_cache[leaf->id] = ret;
return ret;
}
static int chan_opath_checks(int cb, void *data)
{
const int red = 0xff0000, green = 0xff00, blue = 0xff, pale = 0x555555;
unsigned int color;
check_result *cr;
host *h;
const char *name = "_HOST_";
char *buf = NULL;
if(cb == NEBCALLBACK_HOST_CHECK_DATA) {
nebstruct_host_check_data *ds = (nebstruct_host_check_data *)data;
if(ds->type != NEBTYPE_HOSTCHECK_PROCESSED)
return 0;
cr = ds->check_result_ptr;
h = ds->object_ptr;
color = red | green;
} else if(cb == NEBCALLBACK_SERVICE_CHECK_DATA) {
nebstruct_service_check_data *ds = (nebstruct_service_check_data *)data;
service *s;
if(ds->type != NEBTYPE_SERVICECHECK_PROCESSED)
return 0;
s = (service *)ds->object_ptr;
h = s->host_ptr;
cr = ds->check_result_ptr;
color = (red | green | blue) ^ pale;
name = s->description;
} else
return 0;
asprintf(&buf, "%lu|%s|M|%s/%s|%06X\n", cr->finish_time.tv_sec,
check_result_source(cr), host_parent_path(h, '/'), name, color);
nerd_broadcast(chan_opath_checks_id, buf, strlen(buf));
free(buf);
return 0;
}
static int nerd_deinit(void)
{
unsigned int i;
if(host_parent_path_cache) {
for(i = 0; i < num_objects.hosts; i++) {
my_free(host_parent_path_cache[i]);
}
my_free(host_parent_path_cache);
}
for(i = 0; i < num_channels; i++) {
struct nerd_channel *chan = channels[i];
objectlist *list, *next;
for(list = chan->subscriptions; list; list = next) {
struct nerd_subscription *subscr = (struct nerd_subscription *)list->object_ptr;
iobroker_close(nagios_iobs, subscr->sd);
next = list->next;
free(list);
free(subscr);
}
chan->subscriptions = NULL;
my_free(chan);
}
my_free(channels);
num_channels = 0;
alloc_channels = 0;
return 0;
}
int nerd_mkchan(const char *name, const char *description, int (*handler)(int, void *), unsigned int callbacks)
{
struct nerd_channel *chan, **ptr;
int i;
if(num_channels + 1 >= alloc_channels) {
alloc_channels = alloc_nr(alloc_channels);
ptr = realloc(channels, alloc_channels * sizeof(struct nerd_channel *));
if(!ptr)
return -1;
channels = ptr;
}
if(!(chan = calloc(1, sizeof(*chan))))
return -1;
chan->name = name;
chan->description = description;
chan->handler = handler;
for(i = 0; callbacks && i < NEBCALLBACK_NUMITEMS; i++) {
if(!(callbacks & (1 << i)))
continue;
chan->callbacks[chan->num_callbacks++] = i;
}
channels[num_channels++] = chan;
logit(NSLOG_INFO_MESSAGE, TRUE, "nerd: Channel %s registered successfully\n", chan->name);
return num_channels - 1;
}
#define NERD_SUBSCRIBE 0
#define NERD_UNSUBSCRIBE 1
static int nerd_qh_handler(int sd, char *request, unsigned int len)
{
char *chan_name, *fmt;
struct nerd_channel *chan;
int action;
if (!*request || !strcmp(request, "help")) {
nsock_printf_nul(sd, "Manage subscriptions to NERD channels.\n"
"Valid commands:\n"
" list list available channels\n"
" subscribe subscribe to a channel\n"
" unsubscribe unsubscribe to a channel\n");
return 0;
}
if (!strcmp(request, "list")) {
unsigned int i;
for (i = 0; i < num_channels; i++) {
chan = channels[i];
nsock_printf(sd, "%-15s %s\n", chan->name, chan->description);
}
nsock_printf(sd, "%c", 0);
return 0;
}
chan_name = strchr(request, ' ');
if(!chan_name)
return 400;
*chan_name = 0;
chan_name++;
if(!strcmp(request, "subscribe"))
action = NERD_SUBSCRIBE;
else if(!strcmp(request, "unsubscribe"))
action = NERD_UNSUBSCRIBE;
else {
return 400;
}
/* might have a format-string */
if((fmt = strchr(chan_name, ':')))
*(fmt++) = 0;
chan = find_channel(chan_name);
if(!chan) {
return 400;
}
if(action == NERD_SUBSCRIBE)
subscribe(sd, chan, fmt);
else
unsubscribe(sd, chan);
return 0;
}
/* nebmod_init(), but loaded even if no modules are */
int nerd_init(void)
{
nerd_mod.deinit_func = nerd_deinit;
nerd_mod.filename = (char *)"NERD"; /* something to log */
if(qh_register_handler("nerd", "Nagios Event Radio Dispatcher - Subscriber Service", 0, nerd_qh_handler) < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "nerd: Failed to register with query handler\n");
return ERROR;
}
neb_add_core_module(&nerd_mod);
chan_host_checks_id = nerd_mkchan("hostchecks",
"Host check results",
chan_host_checks, nebcallback_flag(NEBCALLBACK_HOST_CHECK_DATA));
chan_service_checks_id = nerd_mkchan("servicechecks",
"Service check results",
chan_service_checks, nebcallback_flag(NEBCALLBACK_SERVICE_CHECK_DATA));
chan_opath_checks_id = nerd_mkchan("opathchecks",
"Host and service checks in gource's log format",
chan_opath_checks, nebcallback_flag(NEBCALLBACK_HOST_CHECK_DATA) | nebcallback_flag(NEBCALLBACK_SERVICE_CHECK_DATA));
logit(NSLOG_INFO_MESSAGE, TRUE, "nerd: Fully initialized and ready to rock!\n");
return 0;
}
#endif nagios-4.4.6/base/netutils.c 0000664 0000000 0000000 00000014045 13652113235 0015737 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* NETUTILS.C - Network connection utility functions for Nagios
*
* Portions Copyright (c) 1999-2008 Nagios Plugin development team
*
* 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(const 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, const 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(¤t_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(¤t_time);
if(current_time - start_time > timeout) {
result = ERROR;
break;
}
}
/* return number of bytes actually received here */
*len = total_received;
return result;
}
nagios-4.4.6/base/notifications.c 0000664 0000000 0000000 00000245521 13652113235 0016746 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* NOTIFICATIONS.C - Service and host notification functions for 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/statusdata.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/broker.h"
#include "../include/neberrors.h"
#include "../include/workers.h"
#include "../include/downtime.h"
/*** silly helpers ****/
static contact *find_contact_by_name_or_alias(const char *name)
{
contact *c = NULL;
if (!name || !(c = find_contact(name)))
return c;
for (c = contact_list; c; c = c->next)
if (!strcmp(c->alias, name))
break;
return c;
}
const char *notification_reason_name(unsigned int reason_type)
{
static const char *names[] = {
"NORMAL", "ACKNOWLEDGEMENT",
"FLAPPINGSTART", "FLAPPINGSTOP", "FLAPPINGDISABLED",
"DOWNTIMESTART", "DOWNTIMEEND", "DOWNTIMECANCELLED",
"CUSTOM"
};
if (reason_type < ARRAY_SIZE(names))
return names[reason_type];
return "(unknown)";
}
/******************************************************************/
/***************** SERVICE NOTIFICATION FUNCTIONS *****************/
/******************************************************************/
/* notify contacts about a service problem or recovery */
int service_notification(service *svc, int type, char *not_author, char *not_data, int options) {
host *temp_host = NULL;
notification *temp_notification = NULL;
contact *temp_contact = NULL;
time_t current_time;
struct timeval start_time;
struct timeval end_time;
int escalated = FALSE;
int result = OK;
int contacts_notified = 0;
int increment_notification_number = FALSE;
nagios_macros mac;
int neb_result;
log_debug_info(DEBUGL_FUNCTIONS, 0, "service_notification()\n");
/* get the current time */
time(¤t_time);
gettimeofday(&start_time, NULL);
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "** Service Notification Attempt ** Host: '%s', Service: '%s', Type: %s, Options: %d, Current State: %d, Last Notification: %s", svc->host_name, svc->description, notification_reason_name(type), options, svc->current_state, ctime(&svc->last_notification));
/* if we couldn't find the host, return an error */
if((temp_host = svc->host_ptr) == NULL) {
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Couldn't find the host associated with this service, so we won't send a notification!\n");
return ERROR;
}
/* check the viability of sending out a service notification */
if(check_service_notification_viability(svc, type, options) == ERROR) {
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Notification viability test failed. No notification will be sent out.\n");
/* Set next_notification time if we're in a downtime and
notification_interval = zero, otherwise if the service
doesn't recover after downtime ends, it will never send
the notification */
if (svc->notification_interval == 0.0) {
if (temp_host->scheduled_downtime_depth > 0 || svc->scheduled_downtime_depth > 0)
svc->next_notification = current_time;
}
return ERROR;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Notification viability test passed.\n");
/* should the notification number be increased? */
if(type == NOTIFICATION_NORMAL || (options & NOTIFICATION_OPTION_INCREMENT)) {
svc->current_notification_number++;
increment_notification_number = TRUE;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Current notification number: %d (%s)\n", svc->current_notification_number, (increment_notification_number == TRUE) ? "incremented" : "unchanged");
/* save and increase the current notification id */
svc->current_notification_id = next_notification_id;
next_notification_id++;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Creating list of contacts to be notified.\n");
#ifdef USE_EVENT_BROKER
/* send data to event broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_notification_data(NEBTYPE_NOTIFICATION_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, start_time, end_time, (void *)svc, not_author, not_data, escalated, 0, NULL);
if(neb_result == NEBERROR_CALLBACKCANCEL || neb_result == NEBERROR_CALLBACKOVERRIDE) {
log_debug_info(DEBUGL_CHECKS, 0, "Service notification to %s;%s (id=%u) was blocked by a module\n",
svc->host_name, svc->description, svc->id);
free_notification_list();
return neb_result == NEBERROR_CALLBACKOVERRIDE ? OK : ERROR;
}
#endif
/* allocate memory for macros */
memset(&mac, 0, sizeof(mac));
/* create the contact notification list for this service */
/*
* check viability before adding a contact to the notification
* list and build up the $NOTIFICATIONRECIPIENTS$ macro while
* we're at it.
* This prevents us from running through all the steps again in
* notify_contact_of_host|service.
* Furthermore the $NOTIFICATIONRECIPIENTS$ macro will contain
* only actual recipients (as the name implies), and not all
* contacts assigned to that host|service.
*
* note: checks against timeperiod will happen now(),
* and not when the notification is actually being sent.
*/
create_notification_list_from_service(&mac, svc, options, &escalated, type);
/* we have contacts to notify... */
if(notification_list != NULL) {
/* grab the macro variables */
grab_host_macros_r(&mac, temp_host);
grab_service_macros_r(&mac, svc);
/* if this notification has an author, attempt to lookup the associated contact */
if(not_author != NULL) {
temp_contact = find_contact_by_name_or_alias(not_author);
}
/* get author and comment macros */
if(not_author)
mac.x[MACRO_NOTIFICATIONAUTHOR] = strdup(not_author);
if(temp_contact != NULL) {
mac.x[MACRO_NOTIFICATIONAUTHORNAME] = strdup(temp_contact->name);
mac.x[MACRO_NOTIFICATIONAUTHORALIAS] = strdup(temp_contact->alias);
}
if(not_data)
mac.x[MACRO_NOTIFICATIONCOMMENT] = strdup(not_data);
/* NOTE: these macros are deprecated and will likely disappear in Nagios 4.x */
/* if this is an acknowledgement, get author and comment macros */
if(type == NOTIFICATION_ACKNOWLEDGEMENT) {
if(not_author)
mac.x[MACRO_SERVICEACKAUTHOR] = strdup(not_author);
if(not_data)
mac.x[MACRO_SERVICEACKCOMMENT] = strdup(not_data);
if(temp_contact != NULL) {
mac.x[MACRO_SERVICEACKAUTHORNAME] = strdup(temp_contact->name);
mac.x[MACRO_SERVICEACKAUTHORALIAS] = strdup(temp_contact->alias);
}
}
/* set the notification type macro */
if(type == NOTIFICATION_ACKNOWLEDGEMENT)
mac.x[MACRO_NOTIFICATIONTYPE] = "ACKNOWLEDGEMENT";
else if(type == NOTIFICATION_FLAPPINGSTART)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGSTART";
else if(type == NOTIFICATION_FLAPPINGSTOP)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGSTOP";
else if(type == NOTIFICATION_FLAPPINGDISABLED)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGDISABLED";
else if(type == NOTIFICATION_DOWNTIMESTART)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMESTART";
else if(type == NOTIFICATION_DOWNTIMEEND)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMEEND";
else if(type == NOTIFICATION_DOWNTIMECANCELLED)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMECANCELLED";
else if(type == NOTIFICATION_CUSTOM)
mac.x[MACRO_NOTIFICATIONTYPE] = "CUSTOM";
else if(svc->current_state == STATE_OK)
mac.x[MACRO_NOTIFICATIONTYPE] = "RECOVERY";
else
mac.x[MACRO_NOTIFICATIONTYPE] = "PROBLEM";
mac.x[MACRO_NOTIFICATIONTYPE] = strdup(mac.x[MACRO_NOTIFICATIONTYPE]);
/* set the notification number macro */
asprintf(&mac.x[MACRO_SERVICENOTIFICATIONNUMBER], "%d", svc->current_notification_number);
/* the $NOTIFICATIONNUMBER$ macro is maintained for backward compatibility */
mac.x[MACRO_NOTIFICATIONNUMBER] = strdup(mac.x[MACRO_SERVICENOTIFICATIONNUMBER]);
/* set the notification id macro */
asprintf(&mac.x[MACRO_SERVICENOTIFICATIONID], "%lu", svc->current_notification_id);
/* notify each contact (duplicates have been removed) */
for(temp_notification = notification_list; temp_notification != NULL; temp_notification = temp_notification->next) {
/* grab the macro variables for this contact */
grab_contact_macros_r(&mac, temp_notification->contact);
/* notify this contact */
result = notify_contact_of_service(&mac, temp_notification->contact, svc, type, not_author, not_data, options, escalated);
/* keep track of how many contacts were notified */
if(result == OK)
contacts_notified++;
}
/* free memory allocated to the notification list */
free_notification_list();
/* clear out all macros we created */
my_free(mac.x[MACRO_NOTIFICATIONNUMBER]);
my_free(mac.x[MACRO_SERVICENOTIFICATIONNUMBER]);
my_free(mac.x[MACRO_SERVICENOTIFICATIONID]);
my_free(mac.x[MACRO_NOTIFICATIONCOMMENT]);
my_free(mac.x[MACRO_NOTIFICATIONTYPE]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHOR]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHORNAME]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHORALIAS]);
my_free(mac.x[MACRO_SERVICEACKAUTHORNAME]);
my_free(mac.x[MACRO_SERVICEACKAUTHORALIAS]);
my_free(mac.x[MACRO_SERVICEACKAUTHOR]);
my_free(mac.x[MACRO_SERVICEACKCOMMENT]);
/* this gets set in add_notification() */
my_free(mac.x[MACRO_NOTIFICATIONRECIPIENTS]);
/*
* Clear all macros, or they will linger in memory
* now that we're done with the notifications.
*/
clear_summary_macros_r(&mac);
clear_contact_macros_r(&mac);
clear_contactgroup_macros_r(&mac);
clear_argv_macros_r(&mac);
clear_host_macros_r(&mac);
clear_hostgroup_macros_r(&mac);
clear_service_macros_r(&mac);
clear_servicegroup_macros_r(&mac);
clear_datetime_macros_r(&mac);
if(type == NOTIFICATION_NORMAL) {
/* adjust last/next notification time and notification flags if we notified someone */
if(contacts_notified > 0) {
/* calculate the next acceptable re-notification time */
svc->next_notification = get_next_service_notification_time(svc, current_time);
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "%d contacts were notified. Next possible notification time: %s", contacts_notified, ctime(&svc->next_notification));
/* update the last notification time for this service (this is needed for rescheduling later notifications) */
svc->last_notification = current_time;
/* update notifications flags */
add_notified_on(svc, svc->current_state);
}
/* we didn't end up notifying anyone */
else if(increment_notification_number == TRUE) {
/* adjust current notification number */
svc->current_notification_number--;
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "No contacts were notified. Next possible notification time: %s", ctime(&svc->next_notification));
}
}
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "%d contacts were notified.\n", contacts_notified);
}
/* there were no contacts, so no notification really occurred... */
else {
/* readjust current notification number, since one didn't go out */
if(increment_notification_number == TRUE)
svc->current_notification_number--;
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "No contacts were found for notification purposes. No notification was sent out.\n");
}
/* this gets set in create_notification_list_from_service() */
my_free(mac.x[MACRO_NOTIFICATIONISESCALATED]);
/* get the time we finished */
gettimeofday(&end_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_notification_data(NEBTYPE_NOTIFICATION_END, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, start_time, end_time, (void *)svc, not_author, not_data, escalated, contacts_notified, NULL);
#endif
/* update the status log with the service information */
update_service_status(svc, FALSE);
return OK;
}
/* checks the viability of sending out a service alert (top level filters) */
int check_service_notification_viability(service *svc, int type, int options) {
host *temp_host;
timeperiod *temp_period;
time_t current_time;
time_t timeperiod_start;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_service_notification_viability()\n");
/* forced notifications bust through everything */
if(options & NOTIFICATION_OPTION_FORCED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This is a forced service notification, so we'll send it out.\n");
return OK;
}
/* get current time */
time(¤t_time);
/* are notifications enabled? */
if(enable_notifications == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Notifications are disabled, so service notifications will not be sent out.\n");
return ERROR;
}
/* find the host this service is associated with */
if((temp_host = (host *)svc->host_ptr) == NULL)
return ERROR;
/* if we couldn't find the host, return an error */
if(temp_host == NULL) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Couldn't find the host associated with this service, so we won't send a notification.\n");
return ERROR;
}
/* if all parents are bad (usually just one), we shouldn't notify */
if(svc->parents) {
int bad_parents = 0, total_parents = 0;
servicesmember *sm;
for(sm = svc->parents; sm; sm = sm->next) {
/* @todo: tweak this so it handles hard states and whatnot */
if(sm->service_ptr->current_state == STATE_OK)
bad_parents += !!sm->service_ptr->current_state;
total_parents++;
}
if(bad_parents == total_parents) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service has no good parents, so notification will be blocked.\n");
return ERROR;
}
}
/* if the service has no notification period, inherit one from the host */
temp_period = svc->notification_period_ptr;
if(temp_period == NULL) {
temp_period = svc->host_ptr->notification_period_ptr;
}
/* see if the service can have notifications sent out at this time */
if(check_time_against_period(current_time, temp_period) == ERROR) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service shouldn't have notifications sent out at this time.\n");
/* calculate the next acceptable notification time, once the next valid time range arrives... */
if(type == NOTIFICATION_NORMAL) {
get_next_valid_time(current_time, &timeperiod_start, svc->notification_period_ptr);
/* looks like there are no valid notification times defined, so schedule the next one far into the future (one year)... */
if(timeperiod_start == (time_t)0)
svc->next_notification = (time_t)(current_time + (60 * 60 * 24 * 365));
/* else use the next valid notification time */
else
svc->next_notification = timeperiod_start;
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next possible notification time: %s\n", ctime(&svc->next_notification));
}
return ERROR;
}
/* are notifications temporarily disabled for this service? */
if(svc->notifications_enabled == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Notifications are temporarily disabled for this service, so we won't send one out.\n");
return ERROR;
}
/*********************************************/
/*** SPECIAL CASE FOR CUSTOM NOTIFICATIONS ***/
/*********************************************/
/* custom notifications are good to go at this point... */
if(type == NOTIFICATION_CUSTOM) {
if(svc->scheduled_downtime_depth > 0 || temp_host->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't send custom notification during scheduled downtime.\n");
return ERROR;
}
return OK;
}
/*****************************************/
/*** SPECIAL CASE FOR ACKNOWLEDGEMENTS ***/
/*****************************************/
/* acknowledgements only have to pass three general filters, although they have another test of their own... */
if(type == NOTIFICATION_ACKNOWLEDGEMENT) {
/* don't send an acknowledgement if there isn't a problem... */
if(svc->current_state == STATE_OK) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "The service is currently OK, so we won't send an acknowledgement.\n");
return ERROR;
}
/* acknowledgement viability test passed, so the notification can be sent out */
return OK;
}
/****************************************/
/*** SPECIAL CASE FOR FLAPPING ALERTS ***/
/****************************************/
/* flapping notifications only have to pass three general filters */
if(type == NOTIFICATION_FLAPPINGSTART || type == NOTIFICATION_FLAPPINGSTOP || type == NOTIFICATION_FLAPPINGDISABLED) {
/* don't send a notification if we're not supposed to... */
if(flag_isset(svc->notification_options, OPT_FLAPPING) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about FLAPPING events for this service.\n");
return ERROR;
}
/* don't send notifications during scheduled downtime */
if(svc->scheduled_downtime_depth > 0 || temp_host->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about FLAPPING events during scheduled downtime.\n");
return ERROR;
}
/* flapping viability test passed, so the notification can be sent out */
return OK;
}
/****************************************/
/*** SPECIAL CASE FOR DOWNTIME ALERTS ***/
/****************************************/
/* downtime notifications only have to pass three general filters */
if(type == NOTIFICATION_DOWNTIMESTART || type == NOTIFICATION_DOWNTIMEEND || type == NOTIFICATION_DOWNTIMECANCELLED) {
/* don't send a notification if we're not supposed to... */
if(flag_isset(svc->notification_options, OPT_DOWNTIME) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWNTIME events for this service.\n");
return ERROR;
}
/* don't send notifications during scheduled downtime (for service only, not host) */
if(svc->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWNTIME events during scheduled downtime.\n");
return ERROR;
}
/* downtime viability test passed, so the notification can be sent out */
return OK;
}
/****************************************/
/*** NORMAL NOTIFICATIONS ***************/
/****************************************/
/* is this a hard problem/recovery? */
if(svc->state_type == SOFT_STATE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service is in a soft state, so we won't send a notification out.\n");
return ERROR;
}
/* has this problem already been acknowledged? */
if(svc->problem_has_been_acknowledged == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service problem has already been acknowledged, so we won't send a notification out.\n");
return ERROR;
}
/* check service notification dependencies */
if(check_service_dependencies(svc, NOTIFICATION_DEPENDENCY) == DEPENDENCIES_FAILED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Service notification dependencies for this service have failed, so we won't sent a notification out.\n");
return ERROR;
}
/* check host notification dependencies */
if(check_host_dependencies(temp_host, NOTIFICATION_DEPENDENCY) == DEPENDENCIES_FAILED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Host notification dependencies for this service have failed, so we won't sent a notification out.\n");
return ERROR;
}
/* see if we should notify about problems with this service */
if(should_notify(svc) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about %s states for this service.\n", service_state_name(svc->current_state));
return ERROR;
}
if(svc->current_state == STATE_OK && svc->notified_on == 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about this recovery.\n");
return ERROR;
}
/* see if enough time has elapsed for first notification (Mathias Sundman) */
/* 10/02/07 don't place restrictions on recoveries or non-normal notifications, must use last time ok (or program start) in calculation */
/* it is reasonable to assume that if the service was never up, the program start time should be used in this calculation */
/* check if delay of notifications is activated (ccztux) */
if(type == NOTIFICATION_NORMAL
&& svc->first_notification_delay > 0
&& svc->current_notification_number == 0
&& svc->current_state != STATE_OK)
{
time_t last_problem_time = svc->last_hard_state_change > 0 ? svc->last_hard_state_change : program_start;
/* determine the time to use of the last problem point */
if(current_time < last_problem_time + (time_t)(svc->first_notification_delay * interval_length)) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Not enough time has elapsed since the service changed to a non-OK state, so we should not notify about this problem yet\n");
return ERROR;
}
}
/* if this service is currently flapping, don't send the notification */
if(svc->is_flapping == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service is currently flapping, so we won't send notifications.\n");
return ERROR;
}
/* if this service is currently in a scheduled downtime period, don't send the notification */
if(svc->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service is currently in a scheduled downtime, so we won't send notifications.\n");
return ERROR;
}
/* if this host is currently in a scheduled downtime period, don't send the notification */
if(temp_host->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "The host this service is associated with is currently in a scheduled downtime, so we won't send notifications.\n");
return ERROR;
}
/* if this service is currently in a flex downtime period, don't send the notification */
if(svc->pending_flex_downtime > 0 && is_service_in_pending_flex_downtime(svc) == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service is starting a flex downtime, so we won't send notifications.\n");
return ERROR;
}
/* if this host is currently in a flex downtime period, don't send the notification */
if(temp_host->pending_flex_downtime > 0 && is_host_in_pending_flex_downtime(temp_host) == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "The host this service is associated with is starting a flex downtime, so we won't send notifications.\n");
return ERROR;
}
/* don't notify contacts about this service problem again if the notification interval is set to 0 */
if(svc->no_more_notifications == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't re-notify contacts about this service problem.\n");
return ERROR;
}
/* if the host is down or unreachable, don't notify contacts about service failures */
if(temp_host->current_state != STATE_UP && temp_host->state_type == HARD_STATE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "The host is either down or unreachable, so we won't notify contacts about this service.\n");
return ERROR;
}
/* don't notify if we haven't waited long enough since the last time (and the service is not marked as being volatile) */
if((current_time < svc->next_notification) && svc->is_volatile == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We haven't waited long enough to re-notify contacts about this service.\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next valid notification time: %s", ctime(&svc->next_notification));
return ERROR;
}
return OK;
}
/* check viability of sending out a service notification to a specific contact (contact-specific filters) */
int check_contact_service_notification_viability(contact *cntct, service *svc, int type, int options) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_contact_service_notification_viability()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Checking service notification viability for contact '%s'...\n", cntct->name);
/* forced notifications bust through everything */
if(options & NOTIFICATION_OPTION_FORCED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This is a forced service notification, so we'll send it out to this contact.\n");
return OK;
}
/* is this service not important enough? */
if(cntct->minimum_value > svc->hourly_value) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Contact's minimum_importance is higher than service's importance. Notification will be blocked\n");
return ERROR;
}
/* are notifications enabled? */
if(cntct->service_notifications_enabled == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Service notifications are disabled for this contact.\n");
return ERROR;
}
/* see if the contact can be notified at this time */
if(check_time_against_period(time(NULL), cntct->service_notification_period_ptr) == ERROR) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "This contact shouldn't be notified at this time.\n");
return ERROR;
}
/*********************************************/
/*** SPECIAL CASE FOR CUSTOM NOTIFICATIONS ***/
/*********************************************/
/* custom notifications are good to go at this point... */
if(type == NOTIFICATION_CUSTOM)
return OK;
/****************************************/
/*** SPECIAL CASE FOR FLAPPING ALERTS ***/
/****************************************/
if(type == NOTIFICATION_FLAPPINGSTART || type == NOTIFICATION_FLAPPINGSTOP || type == NOTIFICATION_FLAPPINGDISABLED) {
if((cntct->service_notification_options & OPT_FLAPPING) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about FLAPPING service events.\n");
return ERROR;
}
return OK;
}
/****************************************/
/*** SPECIAL CASE FOR DOWNTIME ALERTS ***/
/****************************************/
if(type == NOTIFICATION_DOWNTIMESTART || type == NOTIFICATION_DOWNTIMEEND || type == NOTIFICATION_DOWNTIMECANCELLED) {
if((cntct->service_notification_options & OPT_DOWNTIME) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about DOWNTIME service events.\n");
return ERROR;
}
return OK;
}
/*************************************/
/*** ACKS AND NORMAL NOTIFICATIONS ***/
/*************************************/
/* see if we should notify about problems with this service */
if(!(cntct->service_notification_options & (1 << svc->current_state))) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about %s service states.\n", service_state_name(svc->current_state));
return ERROR;
}
if(svc->current_state == STATE_OK) {
if((cntct->service_notification_options & OPT_RECOVERY) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about RECOVERY service states.\n");
return ERROR;
}
if(!(svc->notified_on & cntct->service_notification_options)) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify about this recovery.\n");
return ERROR;
}
}
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Service notification viability for contact '%s' PASSED.\n", cntct->name);
return OK;
}
/* notify a specific contact about a service problem or recovery */
int notify_contact_of_service(nagios_macros *mac, contact *cntct, service *svc, int type, char *not_author, char *not_data, int options, int escalated) {
commandsmember *temp_commandsmember = NULL;
char *command_name = NULL;
char *command_name_ptr = NULL;
char *raw_command = NULL;
char *processed_command = NULL;
char *temp_buffer = NULL;
char *processed_buffer = NULL;
struct timeval start_time, end_time;
struct timeval method_start_time, method_end_time;
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
int neb_result;
log_debug_info(DEBUGL_FUNCTIONS, 0, "notify_contact_of_service()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Notifying contact '%s'\n", cntct->name);
/* get start time */
gettimeofday(&start_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_contact_notification_data(NEBTYPE_CONTACTNOTIFICATION_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, start_time, end_time, (void *)svc, cntct, not_author, not_data, escalated, NULL);
if(NEBERROR_CALLBACKCANCEL == neb_result)
return ERROR;
else if(NEBERROR_CALLBACKOVERRIDE == neb_result)
return OK;
#endif
/* process all the notification commands this user has */
for(temp_commandsmember = cntct->service_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) {
/* get start time */
gettimeofday(&method_start_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
method_end_time.tv_sec = 0L;
method_end_time.tv_usec = 0L;
neb_result = broker_contact_notification_method_data(NEBTYPE_CONTACTNOTIFICATIONMETHOD_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, method_start_time, method_end_time, (void *)svc, cntct, temp_commandsmember->command, not_author, not_data, escalated, NULL);
if(NEBERROR_CALLBACKCANCEL == neb_result)
break ;
else if(NEBERROR_CALLBACKOVERRIDE == neb_result)
continue ;
#endif
/* get the raw command line */
get_raw_command_line_r(mac, temp_commandsmember->command_ptr, temp_commandsmember->command, &raw_command, macro_options);
if(raw_command == NULL)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Raw notification command: %s\n", raw_command);
/* process any macros contained in the argument */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
continue;
/* get the command name */
command_name = (char *)strdup(temp_commandsmember->command);
command_name_ptr = strtok(command_name, "!");
/* run the notification command... */
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Processed notification command: %s\n", processed_command);
/* log the notification to program log file */
if(log_notifications == TRUE) {
switch(type) {
case NOTIFICATION_CUSTOM:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;CUSTOM ($SERVICESTATE$);%s;$SERVICEOUTPUT$;$NOTIFICATIONAUTHOR$;$NOTIFICATIONCOMMENT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_ACKNOWLEDGEMENT:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;ACKNOWLEDGEMENT ($SERVICESTATE$);%s;$SERVICEOUTPUT$;$NOTIFICATIONAUTHOR$;$NOTIFICATIONCOMMENT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGSTART:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;FLAPPINGSTART ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGSTOP:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;FLAPPINGSTOP ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGDISABLED:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;FLAPPINGDISABLED ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMESTART:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;DOWNTIMESTART ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMEEND:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;DOWNTIMEEND ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMECANCELLED:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;DOWNTIMECANCELLED ($SERVICESTATE$);%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
default:
asprintf(&temp_buffer, "SERVICE NOTIFICATION: %s;%s;%s;$SERVICESTATE$;%s;$SERVICEOUTPUT$\n", cntct->name, svc->host_name, svc->description, command_name_ptr);
break;
}
process_macros_r(mac, temp_buffer, &processed_buffer, 0);
write_to_all_logs(processed_buffer, NSLOG_SERVICE_NOTIFICATION);
my_free(temp_buffer);
my_free(processed_buffer);
}
/* run the notification command */
wproc_notify(cntct->name, svc->host_name, svc->description, processed_command, mac);
/* free memory */
my_free(command_name);
my_free(processed_command);
/* get end time */
gettimeofday(&method_end_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_contact_notification_method_data(NEBTYPE_CONTACTNOTIFICATIONMETHOD_END, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, method_start_time, method_end_time, (void *)svc, cntct, temp_commandsmember->command, not_author, not_data, escalated, NULL);
#endif
}
/* get end time */
gettimeofday(&end_time, NULL);
/* update the contact's last service notification time */
cntct->last_service_notification = start_time.tv_sec;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_contact_notification_data(NEBTYPE_CONTACTNOTIFICATION_END, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, start_time, end_time, (void *)svc, cntct, not_author, not_data, escalated, NULL);
#endif
return OK;
}
/* checks to see if a service escalation entry is a match for the current service notification */
int is_valid_escalation_for_service_notification(service *svc, serviceescalation *se, int options) {
int notification_number = 0;
time_t current_time = 0L;
service *temp_service = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "is_valid_escalation_for_service_notification()\n");
/* get the current time */
time(¤t_time);
/* if this is a recovery, really we check for who got notified about a previous problem */
if(svc->current_state == STATE_OK)
notification_number = svc->current_notification_number - 1;
else
notification_number = svc->current_notification_number;
/* this entry if it is not for this service */
temp_service = se->service_ptr;
if(temp_service == NULL || temp_service != svc)
return FALSE;
/*** EXCEPTION ***/
/* broadcast options go to everyone, so this escalation is valid */
if(options & NOTIFICATION_OPTION_BROADCAST)
return TRUE;
/* skip this escalation if it happens later */
if(se->first_notification > notification_number)
return FALSE;
/* skip this escalation if it has already passed */
if(se->last_notification != 0 && se->last_notification < notification_number)
return FALSE;
/* skip this escalation if the state options don't match */
if(flag_isset(se->escalation_options, 1 << svc->current_state) == FALSE)
return FALSE;
/* skip this escalation if it has a timeperiod and the current time isn't valid */
if(se->escalation_period != NULL && check_time_against_period(current_time, se->escalation_period_ptr) == ERROR)
return FALSE;
return TRUE;
}
/* checks to see whether a service notification should be escalation */
int should_service_notification_be_escalated(service *svc) {
objectlist *list;
log_debug_info(DEBUGL_FUNCTIONS, 0, "should_service_notification_be_escalated()\n");
/* search the service escalation list */
for (list = svc->escalation_list; list; list = list->next) {
serviceescalation *temp_se = (serviceescalation *)list->object_ptr;
/* we found a matching entry, so escalate this notification! */
if(is_valid_escalation_for_service_notification(svc, temp_se, NOTIFICATION_OPTION_NONE) == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Service notification WILL be escalated.\n");
return TRUE;
}
}
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Service notification will NOT be escalated.\n");
return FALSE;
}
/* given a service, create a list of contacts to be notified, removing duplicates, checking contact notification viability */
int create_notification_list_from_service(nagios_macros *mac, service *svc, int options, int *escalated, int type) {
serviceescalation *temp_se = NULL;
contactsmember *temp_contactsmember = NULL;
contact *temp_contact = NULL;
contactgroupsmember *temp_contactgroupsmember = NULL;
contactgroup *temp_contactgroup = NULL;
int escalate_notification = FALSE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "create_notification_list_from_service()\n");
/* see if this notification should be escalated */
escalate_notification = should_service_notification_be_escalated(svc);
/* set the escalation flag */
*escalated = escalate_notification;
/* make sure there aren't any leftover contacts */
free_notification_list();
/* set the escalation macro */
mac->x[MACRO_NOTIFICATIONISESCALATED] = strdup(escalate_notification ? "1" : "0");
if(options & NOTIFICATION_OPTION_BROADCAST)
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This notification will be BROADCAST to all (escalated and normal) contacts...\n");
/* use escalated contacts for this notification */
if(escalate_notification == TRUE || (options & NOTIFICATION_OPTION_BROADCAST)) {
objectlist *list;
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Adding contacts from service escalation(s) to notification list.\n");
/* search all the escalation entries for valid matches */
for(list = svc->escalation_list; list; list = list->next) {
temp_se = (serviceescalation *)list->object_ptr;
/* skip this entry if it isn't appropriate */
if(is_valid_escalation_for_service_notification(svc, temp_se, options) == FALSE)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding individual contacts from service escalation(s) to notification list.\n");
/* add all individual contacts for this escalation entry */
for(temp_contactsmember = temp_se->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
if((temp_contact = temp_contactsmember->contact_ptr) == NULL)
continue;
/* check now if the contact can be notified */
if (check_contact_service_notification_viability(temp_contact, svc, type, options) == OK)
add_notification(mac, temp_contact);
else
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n",temp_contact->name);
}
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact groups from service escalation(s) to notification list.\n");
/* add all contacts that belong to contactgroups for this escalation */
for(temp_contactgroupsmember = temp_se->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact group '%s' for service escalation to notification list.\n", temp_contactgroupsmember->group_name);
if((temp_contactgroup = temp_contactgroupsmember->group_ptr) == NULL)
continue;
for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
if((temp_contact = temp_contactsmember->contact_ptr) == NULL)
continue;
/* check now if the contact can be notified */
if (check_contact_service_notification_viability(temp_contact, svc, type, options) == OK)
add_notification(mac, temp_contact);
else
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n",temp_contact->name);
}
}
}
}
/* else use normal, non-escalated contacts */
if(escalate_notification == FALSE || (options & NOTIFICATION_OPTION_BROADCAST)) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Adding normal contacts for service to notification list.\n");
/* add all individual contacts for this service */
for(temp_contactsmember = svc->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
if((temp_contact = temp_contactsmember->contact_ptr) == NULL)
continue;
/* check now if the contact can be notified */
if (check_contact_service_notification_viability(temp_contact, svc, type, options) == OK)
add_notification(mac, temp_contact);
else
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n",temp_contact->name);
}
/* add all contacts that belong to contactgroups for this service */
for(temp_contactgroupsmember = svc->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact group '%s' for service to notification list.\n", temp_contactgroupsmember->group_name);
if((temp_contactgroup = temp_contactgroupsmember->group_ptr) == NULL)
continue;
for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
if((temp_contact = temp_contactsmember->contact_ptr) == NULL)
continue;
/* check now if the contact can be notified */
if (check_contact_service_notification_viability(temp_contact, svc, type, options) == OK)
add_notification(mac, temp_contact);
else
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n",temp_contact->name);
}
}
}
return OK;
}
/******************************************************************/
/******************* HOST NOTIFICATION FUNCTIONS ******************/
/******************************************************************/
/* notify all contacts for a host that the entire host is down or up */
int host_notification(host *hst, int type, char *not_author, char *not_data, int options) {
notification *temp_notification = NULL;
contact *temp_contact = NULL;
time_t current_time;
struct timeval start_time;
struct timeval end_time;
int escalated = FALSE;
int result = OK;
int contacts_notified = 0;
int increment_notification_number = FALSE;
nagios_macros mac;
int neb_result;
/* get the current time */
time(¤t_time);
gettimeofday(&start_time, NULL);
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "** Host Notification Attempt ** Host: '%s', Type: %s, Options: %d, Current State: %d, Last Notification: %s", hst->name, notification_reason_name(type), options, hst->current_state, ctime(&hst->last_notification));
/* check viability of sending out a host notification */
if(check_host_notification_viability(hst, type, options) == ERROR) {
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Notification viability test failed. No notification will be sent out.\n");
return ERROR;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Notification viability test passed.\n");
/* should the notification number be increased? */
if(type == NOTIFICATION_NORMAL || (options & NOTIFICATION_OPTION_INCREMENT)) {
hst->current_notification_number++;
increment_notification_number = TRUE;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Current notification number: %d (%s)\n", hst->current_notification_number, (increment_notification_number == TRUE) ? "incremented" : "unchanged");
/* save and increase the current notification id */
hst->current_notification_id = next_notification_id;
next_notification_id++;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Creating list of contacts to be notified.\n");
#ifdef USE_EVENT_BROKER
/* send data to event broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_notification_data(NEBTYPE_NOTIFICATION_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, start_time, end_time, (void *)hst, not_author, not_data, escalated, 0, NULL);
if(neb_result == NEBERROR_CALLBACKCANCEL || neb_result == NEBERROR_CALLBACKOVERRIDE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Host notification to %s (id=%u) was blocked by a module.\n", hst->name, hst->id);
free_notification_list();
return neb_result == NEBERROR_CALLBACKOVERRIDE ? OK : ERROR;
}
#endif
/* reset memory for local macro data */
memset(&mac, 0, sizeof(mac));
/*
* check viability before adding a contact to the notification
* list and build up the $NOTIFICATIONRECIPIENTS$ macro while
* we're at it.
* This prevents us from running through all the steps again in
* notify_contact_of_host|service.
* Furthermore the $NOTIFICATIONRECIPIENTS$ macro will contain
* only actual recipients (as the name implies), and not all
* contacts assigned to that host|service.
*
* note: checks against timeperiod will happen now(),
* and not when the notification is actually being sent.
*/
create_notification_list_from_host(&mac, hst, options, &escalated, type);
/* there are contacts to be notified... */
if(notification_list != NULL) {
/* grab the macro variables */
grab_host_macros_r(&mac, hst);
/* if this notification has an author, attempt to lookup the associated contact */
if(not_author != NULL) {
temp_contact = find_contact_by_name_or_alias(not_author);
}
/* get author and comment macros */
if(not_author)
mac.x[MACRO_NOTIFICATIONAUTHOR] = strdup(not_author);
if(temp_contact != NULL) {
mac.x[MACRO_NOTIFICATIONAUTHORNAME] = strdup(temp_contact->name);
mac.x[MACRO_NOTIFICATIONAUTHORALIAS] = strdup(temp_contact->alias);
}
if(not_data)
mac.x[MACRO_NOTIFICATIONCOMMENT] = strdup(not_data);
/* NOTE: these macros are deprecated and will likely disappear in Nagios 4.x */
/* if this is an acknowledgement, get author and comment macros */
if(type == NOTIFICATION_ACKNOWLEDGEMENT) {
if(not_author)
mac.x[MACRO_HOSTACKAUTHOR] = strdup(not_author);
if(not_data)
mac.x[MACRO_HOSTACKCOMMENT] = strdup(not_data);
if(temp_contact != NULL) {
mac.x[MACRO_HOSTACKAUTHORNAME] = strdup(temp_contact->name);
mac.x[MACRO_HOSTACKAUTHORALIAS] = strdup(temp_contact->alias);
}
}
/* set the notification type macro */
if(type == NOTIFICATION_ACKNOWLEDGEMENT)
mac.x[MACRO_NOTIFICATIONTYPE] = "ACKNOWLEDGEMENT";
else if(type == NOTIFICATION_FLAPPINGSTART)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGSTART";
else if(type == NOTIFICATION_FLAPPINGSTOP)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGSTOP";
else if(type == NOTIFICATION_FLAPPINGDISABLED)
mac.x[MACRO_NOTIFICATIONTYPE] = "FLAPPINGDISABLED";
else if(type == NOTIFICATION_DOWNTIMESTART)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMESTART";
else if(type == NOTIFICATION_DOWNTIMEEND)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMEEND";
else if(type == NOTIFICATION_DOWNTIMECANCELLED)
mac.x[MACRO_NOTIFICATIONTYPE] = "DOWNTIMECANCELLED";
else if(type == NOTIFICATION_CUSTOM)
mac.x[MACRO_NOTIFICATIONTYPE] = "CUSTOM";
else if(hst->current_state == HOST_UP)
mac.x[MACRO_NOTIFICATIONTYPE] = "RECOVERY";
else
mac.x[MACRO_NOTIFICATIONTYPE] = "PROBLEM";
mac.x[MACRO_NOTIFICATIONTYPE] = strdup(mac.x[MACRO_NOTIFICATIONTYPE]);
/* set the notification number macro */
asprintf(&mac.x[MACRO_HOSTNOTIFICATIONNUMBER], "%d", hst->current_notification_number);
/* the $NOTIFICATIONNUMBER$ macro is maintained for backward compatibility */
mac.x[MACRO_NOTIFICATIONNUMBER] = strdup(mac.x[MACRO_HOSTNOTIFICATIONNUMBER]);
/* set the notification id macro */
asprintf(&mac.x[MACRO_HOSTNOTIFICATIONID], "%lu", hst->current_notification_id);
/* notify each contact (duplicates have been removed) */
for(temp_notification = notification_list; temp_notification != NULL; temp_notification = temp_notification->next) {
/* grab the macro variables for this contact */
grab_contact_macros_r(&mac, temp_notification->contact);
/* clear summary macros (they are customized for each contact) */
clear_summary_macros_r(&mac);
/* notify this contact */
result = notify_contact_of_host(&mac, temp_notification->contact, hst, type, not_author, not_data, options, escalated);
/* keep track of how many contacts were notified */
if(result == OK)
contacts_notified++;
}
/* free memory allocated to the notification list */
free_notification_list();
/* clear out all macros we created */
my_free(mac.x[MACRO_HOSTNOTIFICATIONID]);
my_free(mac.x[MACRO_NOTIFICATIONNUMBER]);
my_free(mac.x[MACRO_NOTIFICATIONCOMMENT]);
my_free(mac.x[MACRO_HOSTNOTIFICATIONNUMBER]);
my_free(mac.x[MACRO_NOTIFICATIONTYPE]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHOR]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHORNAME]);
my_free(mac.x[MACRO_NOTIFICATIONAUTHORALIAS]);
my_free(mac.x[MACRO_HOSTACKAUTHORNAME]);
my_free(mac.x[MACRO_HOSTACKAUTHORALIAS]);
my_free(mac.x[MACRO_HOSTACKAUTHOR]);
my_free(mac.x[MACRO_HOSTACKCOMMENT]);
/* this gets set in add_notification() */
my_free(mac.x[MACRO_NOTIFICATIONRECIPIENTS]);
/*
* Clear all macros, or they will linger in memory
* now that we're done with the notifications.
*/
clear_summary_macros_r(&mac);
clear_contact_macros_r(&mac);
clear_contactgroup_macros_r(&mac);
clear_argv_macros_r(&mac);
clear_host_macros_r(&mac);
clear_hostgroup_macros_r(&mac);
clear_datetime_macros_r(&mac);
if(type == NOTIFICATION_NORMAL) {
/* adjust last/next notification time and notification flags if we notified someone */
if(contacts_notified > 0) {
/* calculate the next acceptable re-notification time */
hst->next_notification = get_next_host_notification_time(hst, current_time);
/* update the last notification time for this host (this is needed for scheduling the next problem notification) */
hst->last_notification = current_time;
/* update notifications flags */
add_notified_on(hst, hst->current_state);
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "%d contacts were notified. Next possible notification time: %s", contacts_notified, ctime(&hst->next_notification));
}
/* we didn't end up notifying anyone */
else if(increment_notification_number == TRUE) {
/* adjust current notification number */
hst->current_notification_number--;
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "No contacts were notified. Next possible notification time: %s", ctime(&hst->next_notification));
}
}
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "%d contacts were notified.\n", contacts_notified);
}
/* there were no contacts, so no notification really occurred... */
else {
/* adjust notification number, since no notification actually went out */
if(increment_notification_number == TRUE)
hst->current_notification_number--;
log_debug_info(DEBUGL_NOTIFICATIONS, 0, "No contacts were found for notification purposes. No notification was sent out.\n");
}
/* this gets set in create_notification_list_from_host() */
my_free(mac.x[MACRO_NOTIFICATIONISESCALATED]);
/* get the time we finished */
gettimeofday(&end_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_notification_data(NEBTYPE_NOTIFICATION_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, start_time, end_time, (void *)hst, not_author, not_data, escalated, contacts_notified, NULL);
#endif
/* update the status log with the host info */
update_host_status(hst, FALSE);
return OK;
}
/* checks viability of sending a host notification */
int check_host_notification_viability(host *hst, int type, int options) {
time_t current_time;
time_t timeperiod_start;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_host_notification_viability()\n");
/* forced notifications bust through everything */
if(options & NOTIFICATION_OPTION_FORCED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This is a forced host notification, so we'll send it out.\n");
return OK;
}
/* get current time */
time(¤t_time);
/* are notifications enabled? */
if(enable_notifications == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Notifications are disabled, so host notifications will not be sent out.\n");
return ERROR;
}
/* see if the host can have notifications sent out at this time */
if(check_time_against_period(current_time, hst->notification_period_ptr) == ERROR) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This host shouldn't have notifications sent out at this time.\n");
/* if this is a normal notification, calculate the next acceptable notification time, once the next valid time range arrives... */
if(type == NOTIFICATION_NORMAL) {
get_next_valid_time(current_time, &timeperiod_start, hst->notification_period_ptr);
/* it looks like there is no notification time defined, so schedule next one far into the future (one year)... */
if(timeperiod_start == (time_t)0)
hst->next_notification = (time_t)(current_time + (60 * 60 * 24 * 365));
/* else use the next valid notification time */
else
hst->next_notification = timeperiod_start;
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next possible notification time: %s\n", ctime(&hst->next_notification));
}
return ERROR;
}
/* are notifications temporarily disabled for this host? */
if(hst->notifications_enabled == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Notifications are temporarily disabled for this host, so we won't send one out.\n");
return ERROR;
}
/*********************************************/
/*** SPECIAL CASE FOR CUSTOM NOTIFICATIONS ***/
/*********************************************/
/* custom notifications are good to go at this point... */
if(type == NOTIFICATION_CUSTOM) {
if(hst->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't send custom notification during scheduled downtime.\n");
return ERROR;
}
return OK;
}
/*****************************************/
/*** SPECIAL CASE FOR ACKNOWLEDGEMENTS ***/
/*****************************************/
/* acknowledgements only have to pass three general filters, although they have another test of their own... */
if(type == NOTIFICATION_ACKNOWLEDGEMENT) {
/* don't send an acknowledgement if there isn't a problem... */
if(hst->current_state == HOST_UP) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "The host is currently UP, so we won't send an acknowledgement.\n");
return ERROR;
}
/* acknowledgement viability test passed, so the notification can be sent out */
return OK;
}
/*****************************************/
/*** SPECIAL CASE FOR FLAPPING ALERTS ***/
/*****************************************/
/* flapping notifications only have to pass three general filters */
if(type == NOTIFICATION_FLAPPINGSTART || type == NOTIFICATION_FLAPPINGSTOP || type == NOTIFICATION_FLAPPINGDISABLED) {
/* don't send a notification if we're not supposed to... */
if(!(hst->notification_options & OPT_FLAPPING)) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about FLAPPING events for this host.\n");
return ERROR;
}
/* don't send notifications during scheduled downtime */
if(hst->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about FLAPPING events during scheduled downtime.\n");
return ERROR;
}
/* flapping viability test passed, so the notification can be sent out */
return OK;
}
/*****************************************/
/*** SPECIAL CASE FOR DOWNTIME ALERTS ***/
/*****************************************/
/* flapping notifications only have to pass three general filters */
if(type == NOTIFICATION_DOWNTIMESTART || type == NOTIFICATION_DOWNTIMEEND || type == NOTIFICATION_DOWNTIMECANCELLED) {
/* don't send a notification if we're not supposed to... */
if((hst->notification_options & OPT_DOWNTIME) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWNTIME events for this host.\n");
return ERROR;
}
/* don't send notifications during scheduled downtime */
if(hst->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWNTIME events during scheduled downtime!\n");
return ERROR;
}
/* downtime viability test passed, so the notification can be sent out */
return OK;
}
/****************************************/
/*** NORMAL NOTIFICATIONS ***************/
/****************************************/
/* is this a hard problem/recovery? */
if(hst->state_type == SOFT_STATE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This host is in a soft state, so we won't send a notification out.\n");
return ERROR;
}
/* has this problem already been acknowledged? */
if(hst->problem_has_been_acknowledged == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This host problem has already been acknowledged, so we won't send a notification out!\n");
return ERROR;
}
/* check notification dependencies */
if(check_host_dependencies(hst, NOTIFICATION_DEPENDENCY) == DEPENDENCIES_FAILED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Notification dependencies for this host have failed, so we won't sent a notification out!\n");
return ERROR;
}
/* see if we should notify about problems with this host */
if((hst->notification_options & (1 << hst->current_state)) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about %s status for this host.\n", host_state_name(hst->current_state));
return ERROR;
}
if(hst->current_state == HOST_UP) {
if((hst->notification_options & OPT_RECOVERY) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about RECOVERY states for this host.\n");
return ERROR;
}
if(!hst->notified_on) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about this recovery.\n");
return ERROR;
}
}
/* see if enough time has elapsed for first notification (Mathias Sundman) */
/* 10/02/07 don't place restrictions on recoveries or non-normal notifications, must use last time up (or program start) in calculation */
/* it is reasonable to assume that if the host was never up, the program start time should be used in this calculation */
/* check if delay of notifications is activated (ccztux) */
if(type == NOTIFICATION_NORMAL
&& hst->first_notification_delay > 0
&& hst->current_notification_number == 0
&& hst->current_state != STATE_OK)
{
time_t last_problem_time = hst->last_hard_state_change > 0 ? hst->last_hard_state_change : program_start;
/* determine the time to use of the last problem point */
if(current_time < last_problem_time + (time_t)(hst->first_notification_delay * interval_length)) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Not enough time has elapsed since the host changed to a non-UP state (or since program start), so we shouldn't notify about this problem yet.\n");
return ERROR;
}
}
/* if this host is currently flapping, don't send the notification */
if(hst->is_flapping == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This host is currently flapping, so we won't send notifications.\n");
return ERROR;
}
/* if this host is currently in a scheduled downtime period, don't send the notification */
if(hst->scheduled_downtime_depth > 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This host is currently in a scheduled downtime, so we won't send notifications.\n");
return ERROR;
}
/* check if we shouldn't renotify contacts about the host problem */
if(hst->no_more_notifications == TRUE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't re-notify contacts about this host problem.\n");
return ERROR;
}
/* check if its time to re-notify the contacts about the host... */
if(current_time < hst->next_notification) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Its not yet time to re-notify the contacts about this host problem...\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next acceptable notification time: %s", ctime(&hst->next_notification));
return ERROR;
}
return OK;
}
/* checks the viability of notifying a specific contact about a host */
int check_contact_host_notification_viability(contact *cntct, host *hst, int type, int options) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_contact_host_notification_viability()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Checking host notification viability for contact '%s'...\n", cntct->name);
/* forced notifications bust through everything */
if(options & NOTIFICATION_OPTION_FORCED) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "This is a forced host notification, so we'll send it out for this contact.\n");
return OK;
}
/* are notifications enabled? */
if(cntct->host_notifications_enabled == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Host notifications are disabled for this contact.\n");
return ERROR;
}
/* is this host important enough? */
if(cntct->minimum_value > hst->hourly_value + host_services_value(hst)) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Contact's minimum_importance is greater than the importance of the host and all its services. Notification will be blocked\n");
return ERROR;
}
/* see if the contact can be notified at this time */
if(check_time_against_period(time(NULL), cntct->host_notification_period_ptr) == ERROR) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "This contact shouldn't be notified at this time.\n");
return ERROR;
}
/*********************************************/
/*** SPECIAL CASE FOR CUSTOM NOTIFICATIONS ***/
/*********************************************/
/* custom notifications are good to go at this point... */
if(type == NOTIFICATION_CUSTOM)
return OK;
/****************************************/
/*** SPECIAL CASE FOR FLAPPING ALERTS ***/
/****************************************/
if(type == NOTIFICATION_FLAPPINGSTART || type == NOTIFICATION_FLAPPINGSTOP || type == NOTIFICATION_FLAPPINGDISABLED) {
if((cntct->host_notification_options & OPT_FLAPPING) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about FLAPPING host events.\n");
return ERROR;
}
return OK;
}
/****************************************/
/*** SPECIAL CASE FOR DOWNTIME ALERTS ***/
/****************************************/
if(type == NOTIFICATION_DOWNTIMESTART || type == NOTIFICATION_DOWNTIMEEND || type == NOTIFICATION_DOWNTIMECANCELLED) {
if(flag_isset(cntct->host_notification_options, OPT_DOWNTIME) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about DOWNTIME host events.\n");
return ERROR;
}
return OK;
}
/*************************************/
/*** ACKS AND NORMAL NOTIFICATIONS ***/
/*************************************/
/* see if we should notify about problems with this host */
if(flag_isset(cntct->host_notification_options, 1 << hst->current_state) == FALSE) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about %s states.\n", host_state_name(hst->current_state));
return ERROR;
}
if(hst->current_state == HOST_UP && hst->notified_on == 0) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify about this recovery.\n");
return ERROR;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Host notification viability for contact '%s' PASSED.\n", cntct->name);
return OK;
}
/* notify a specific contact that an entire host is down or up */
int notify_contact_of_host(nagios_macros *mac, contact *cntct, host *hst, int type, char *not_author, char *not_data, int options, int escalated) {
commandsmember *temp_commandsmember = NULL;
char *command_name = NULL;
char *command_name_ptr = NULL;
char *temp_buffer = NULL;
char *processed_buffer = NULL;
char *raw_command = NULL;
char *processed_command = NULL;
struct timeval start_time;
struct timeval end_time;
struct timeval method_start_time;
struct timeval method_end_time;
int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS;
int neb_result;
log_debug_info(DEBUGL_FUNCTIONS, 0, "notify_contact_of_host()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Notifying contact '%s'\n", cntct->name);
/* get start time */
gettimeofday(&start_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
neb_result = broker_contact_notification_data(NEBTYPE_CONTACTNOTIFICATION_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, start_time, end_time, (void *)hst, cntct, not_author, not_data, escalated, NULL);
if(NEBERROR_CALLBACKCANCEL == neb_result)
return ERROR;
else if(NEBERROR_CALLBACKOVERRIDE == neb_result)
return OK;
#endif
/* process all the notification commands this user has */
for(temp_commandsmember = cntct->host_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) {
/* get start time */
gettimeofday(&method_start_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
method_end_time.tv_sec = 0L;
method_end_time.tv_usec = 0L;
neb_result = broker_contact_notification_method_data(NEBTYPE_CONTACTNOTIFICATIONMETHOD_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, method_start_time, method_end_time, (void *)hst, cntct, temp_commandsmember->command, not_author, not_data, escalated, NULL);
if(NEBERROR_CALLBACKCANCEL == neb_result)
break ;
else if(NEBERROR_CALLBACKOVERRIDE == neb_result)
continue ;
#endif
/* get the raw command line */
get_raw_command_line_r(mac, temp_commandsmember->command_ptr, temp_commandsmember->command, &raw_command, macro_options);
if(raw_command == NULL)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Raw notification command: %s\n", raw_command);
/* process any macros contained in the argument */
process_macros_r(mac, raw_command, &processed_command, macro_options);
my_free(raw_command);
if(processed_command == NULL)
continue;
/* get the command name */
command_name = (char *)strdup(temp_commandsmember->command);
command_name_ptr = strtok(command_name, "!");
/* run the notification command... */
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Processed notification command: %s\n", processed_command);
/* log the notification to program log file */
if(log_notifications == TRUE) {
switch(type) {
case NOTIFICATION_CUSTOM:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;CUSTOM ($HOSTSTATE$);%s;$HOSTOUTPUT$;$NOTIFICATIONAUTHOR$;$NOTIFICATIONCOMMENT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_ACKNOWLEDGEMENT:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;ACKNOWLEDGEMENT ($HOSTSTATE$);%s;$HOSTOUTPUT$;$NOTIFICATIONAUTHOR$;$NOTIFICATIONCOMMENT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGSTART:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;FLAPPINGSTART ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGSTOP:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;FLAPPINGSTOP ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_FLAPPINGDISABLED:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;FLAPPINGDISABLED ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMESTART:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;DOWNTIMESTART ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMEEND:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;DOWNTIMEEND ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
case NOTIFICATION_DOWNTIMECANCELLED:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;DOWNTIMECANCELLED ($HOSTSTATE$);%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
default:
asprintf(&temp_buffer, "HOST NOTIFICATION: %s;%s;$HOSTSTATE$;%s;$HOSTOUTPUT$\n", cntct->name, hst->name, command_name_ptr);
break;
}
process_macros_r(mac, temp_buffer, &processed_buffer, 0);
write_to_all_logs(processed_buffer, NSLOG_HOST_NOTIFICATION);
my_free(temp_buffer);
my_free(processed_buffer);
}
/* run the notification command */
wproc_notify(cntct->name, hst->name, NULL, processed_command, mac);
/* @todo Handle nebmod stuff when getting results from workers */
/* free memory */
my_free(command_name);
my_free(processed_command);
/* get end time */
gettimeofday(&method_end_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_contact_notification_method_data(NEBTYPE_CONTACTNOTIFICATIONMETHOD_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, method_start_time, method_end_time, (void *)hst, cntct, temp_commandsmember->command, not_author, not_data, escalated, NULL);
#endif
}
/* get end time */
gettimeofday(&end_time, NULL);
/* update the contact's last host notification time */
cntct->last_host_notification = start_time.tv_sec;
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_contact_notification_data(NEBTYPE_CONTACTNOTIFICATION_END, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, start_time, end_time, (void *)hst, cntct, not_author, not_data, escalated, NULL);
#endif
return OK;
}
/* checks to see if a host escalation entry is a match for the current host notification */
int is_valid_escalation_for_host_notification(host *hst, hostescalation *he, int options) {
int notification_number = 0;
time_t current_time = 0L;
host *temp_host = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "is_valid_escalation_for_host_notification()\n");
/* get the current time */
time(¤t_time);
/* if this is a recovery, really we check for who got notified about a previous problem */
if(hst->current_state == HOST_UP)
notification_number = hst->current_notification_number - 1;
else
notification_number = hst->current_notification_number;
/* find the host this escalation entry is associated with */
temp_host = he->host_ptr;
if(temp_host == NULL || temp_host != hst)
return FALSE;
/*** EXCEPTION ***/
/* broadcast options go to everyone, so this escalation is valid */
if(options & NOTIFICATION_OPTION_BROADCAST)
return TRUE;
/* skip this escalation if it happens later */
if(he->first_notification > notification_number)
return FALSE;
/* skip this escalation if it has already passed */
if(he->last_notification != 0 && he->last_notification < notification_number)
return FALSE;
/* skip this escalation if the state options don't match */
if(flag_isset(he->escalation_options, 1 << hst->current_state) == FALSE)
return FALSE;
/* skip this escalation if it has a timeperiod and the current time isn't valid */
if(he->escalation_period != NULL && check_time_against_period(current_time, he->escalation_period_ptr) == ERROR)
return FALSE;
return TRUE;
}
/* checks to see whether a host notification should be escalation */
int should_host_notification_be_escalated(host *hst) {
objectlist *list;
log_debug_info(DEBUGL_FUNCTIONS, 0, "should_host_notification_be_escalated()\n");
if(hst == NULL)
return FALSE;
/* search the host escalation list */
for (list = hst->escalation_list; list; list = list->next) {
hostescalation *temp_he = (hostescalation *)list->object_ptr;
/* we found a matching entry, so escalate this notification! */
if(is_valid_escalation_for_host_notification(hst, temp_he, NOTIFICATION_OPTION_NONE) == TRUE)
return TRUE;
}
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Host notification will NOT be escalated.\n");
return FALSE;
}
/* given a host, create a list of contacts to be notified, removing duplicates, checking contact notification viability */
int create_notification_list_from_host(nagios_macros *mac, host *hst, int options, int *escalated, int type) {
hostescalation *temp_he = NULL;
contactsmember *temp_contactsmember = NULL;
contact *temp_contact = NULL;
contactgroupsmember *temp_contactgroupsmember = NULL;
contactgroup *temp_contactgroup = NULL;
int escalate_notification = FALSE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "create_notification_list_from_host()\n");
/* see if this notification should be escalated */
escalate_notification = should_host_notification_be_escalated(hst);
/* set the escalation flag */
*escalated = escalate_notification;
/* make sure there aren't any leftover contacts */
free_notification_list();
/* set the escalation macro */
mac->x[MACRO_NOTIFICATIONISESCALATED] = strdup(escalate_notification ? "1" : "0");
if(options & NOTIFICATION_OPTION_BROADCAST)
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This notification will be BROADCAST to all (escalated and normal) contacts...\n");
/* use escalated contacts for this notification */
if(escalate_notification == TRUE || (options & NOTIFICATION_OPTION_BROADCAST)) {
objectlist *list;
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Adding contacts from host escalation(s) to notification list.\n");
/* check all the host escalation entries */
for(list = hst->escalation_list; list; list = list->next) {
temp_he = (hostescalation *)list->object_ptr;
/* see if this escalation if valid for this notification */
if(is_valid_escalation_for_host_notification(hst, temp_he, options) == FALSE)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding individual contacts from host escalation(s) to notification list.\n");
/* add all individual contacts for this escalation */
for(temp_contactsmember = temp_he->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
if((temp_contact = temp_contactsmember->contact_ptr) == NULL)
continue;
/* check now if the contact can be notified */
if (check_contact_host_notification_viability(temp_contact, hst, type, options) == OK)
add_notification(mac, temp_contact);
else
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name);
}
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact groups from host escalation(s) to notification list.\n");
/* add all contacts that belong to contactgroups for this escalation */
for(temp_contactgroupsmember = temp_he->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact group '%s' for host escalation to notification list.\n", temp_contactgroupsmember->group_name);
if((temp_contactgroup = temp_contactgroupsmember->group_ptr) == NULL)
continue;
for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
if((temp_contact = temp_contactsmember->contact_ptr) == NULL)
continue;
/* check now if the contact can be notified */
if (check_contact_host_notification_viability(temp_contact, hst, type, options) == OK)
add_notification(mac, temp_contact);
else
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name);
}
}
}
}
/* use normal, non-escalated contacts for this notification */
if(escalate_notification == FALSE || (options & NOTIFICATION_OPTION_BROADCAST)) {
log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Adding normal contacts for host to notification list.\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding individual contacts for host to notification list.\n");
/* add all individual contacts for this host */
for(temp_contactsmember = hst->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
if((temp_contact = temp_contactsmember->contact_ptr) == NULL)
continue;
/* check now if the contact can be notified */
if (check_contact_host_notification_viability(temp_contact, hst, type, options) == OK)
add_notification(mac, temp_contact);
else
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name);
}
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact groups for host to notification list.\n");
/* add all contacts that belong to contactgroups for this host */
for(temp_contactgroupsmember = hst->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) {
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact group '%s' for host to notification list.\n", temp_contactgroupsmember->group_name);
if((temp_contactgroup = temp_contactgroupsmember->group_ptr) == NULL)
continue;
for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) {
if((temp_contact = temp_contactsmember->contact_ptr) == NULL)
continue;
/* check now if the contact can be notified */
if (check_contact_host_notification_viability(temp_contact, hst, type, options) == OK)
add_notification(mac, temp_contact);
else
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name);
}
}
}
return OK;
}
/******************************************************************/
/***************** NOTIFICATION TIMING FUNCTIONS ******************/
/******************************************************************/
/* calculates next acceptable re-notification time for a service */
time_t get_next_service_notification_time(service *svc, time_t offset) {
time_t next_notification = 0L;
double interval_to_use = 0.0;
objectlist *list;
int have_escalated_interval = FALSE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "get_next_service_notification_time()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Calculating next valid notification time...\n");
/* default notification interval */
interval_to_use = svc->notification_interval;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Default interval: %f\n", interval_to_use);
/* search all the escalation entries for valid matches for this service (at its current notification number) */
for(list = svc->escalation_list; list; list = list->next) {
serviceescalation *temp_se = (serviceescalation *)list->object_ptr;
/* interval < 0 means to use non-escalated interval */
if(temp_se->notification_interval < 0.0)
continue;
/* skip this entry if it isn't appropriate */
if(is_valid_escalation_for_service_notification(svc, temp_se, NOTIFICATION_OPTION_NONE) == FALSE)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Found a valid escalation w/ interval of %f\n", temp_se->notification_interval);
/* if we haven't used a notification interval from an escalation yet, use this one */
if(have_escalated_interval == FALSE) {
have_escalated_interval = TRUE;
interval_to_use = temp_se->notification_interval;
}
/* else use the shortest of all valid escalation intervals */
else if(temp_se->notification_interval < interval_to_use)
interval_to_use = temp_se->notification_interval;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "New interval: %f\n", interval_to_use);
}
/* if notification interval is 0, we shouldn't send any more problem notifications (unless service is volatile) */
if(interval_to_use == 0.0 && svc->is_volatile == FALSE)
svc->no_more_notifications = TRUE;
else
svc->no_more_notifications = FALSE;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Interval used for calculating next valid notification time: %f\n", interval_to_use);
/* calculate next notification time */
next_notification = offset + (interval_to_use * interval_length);
return next_notification;
}
/* calculates next acceptable re-notification time for a host */
time_t get_next_host_notification_time(host *hst, time_t offset) {
time_t next_notification = 0L;
double interval_to_use = 0.0;
objectlist *list;
int have_escalated_interval = FALSE;
log_debug_info(DEBUGL_FUNCTIONS, 0, "get_next_host_notification_time()\n");
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Calculating next valid notification time...\n");
/* default notification interval */
interval_to_use = hst->notification_interval;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Default interval: %f\n", interval_to_use);
/* check all the host escalation entries for valid matches for this host (at its current notification number) */
for(list = hst->escalation_list; list; list = list->next) {
hostescalation *temp_he = (hostescalation *)list->object_ptr;
/* interval < 0 means to use non-escalated interval */
if(temp_he->notification_interval < 0.0)
continue;
/* skip this entry if it isn't appropriate */
if(is_valid_escalation_for_host_notification(hst, temp_he, NOTIFICATION_OPTION_NONE) == FALSE)
continue;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Found a valid escalation w/ interval of %f\n", temp_he->notification_interval);
/* if we haven't used a notification interval from an escalation yet, use this one */
if(have_escalated_interval == FALSE) {
have_escalated_interval = TRUE;
interval_to_use = temp_he->notification_interval;
}
/* else use the shortest of all valid escalation intervals */
else if(temp_he->notification_interval < interval_to_use)
interval_to_use = temp_he->notification_interval;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "New interval: %f\n", interval_to_use);
}
/* if interval is 0, no more notifications should be sent */
if(interval_to_use == 0.0)
hst->no_more_notifications = TRUE;
else
hst->no_more_notifications = FALSE;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Interval used for calculating next valid notification time: %f\n", interval_to_use);
/* calculate next notification time */
next_notification = offset + (interval_to_use * interval_length);
return next_notification;
}
/******************************************************************/
/***************** NOTIFICATION OBJECT FUNCTIONS ******************/
/******************************************************************/
/* given a contact name, find the notification entry for them for the list in memory */
notification * find_notification(contact *cntct) {
notification *temp_notification = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "find_notification() start\n");
if(cntct == NULL)
return NULL;
for(temp_notification = notification_list; temp_notification != NULL; temp_notification = temp_notification->next) {
if(temp_notification->contact == cntct)
return temp_notification;
}
/* we couldn't find the contact in the notification list */
return NULL;
}
/* add a new notification to the list in memory */
int add_notification(nagios_macros *mac, contact *cntct) {
notification *new_notification = NULL;
notification *temp_notification = NULL;
log_debug_info(DEBUGL_FUNCTIONS, 0, "add_notification() start\n");
if(cntct == NULL)
return ERROR;
log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding contact '%s' to notification list.\n", cntct->name);
/* don't add anything if this contact is already on the notification list */
if((temp_notification = find_notification(cntct)) != NULL)
return OK;
/* allocate memory for a new contact in the notification list */
if((new_notification = malloc(sizeof(notification))) == NULL)
return ERROR;
/* fill in the contact info */
new_notification->contact = cntct;
/* add new notification to head of list */
new_notification->next = notification_list;
notification_list = new_notification;
/* add contact to notification recipients macro */
if(mac->x[MACRO_NOTIFICATIONRECIPIENTS] == NULL)
mac->x[MACRO_NOTIFICATIONRECIPIENTS] = (char *)strdup(cntct->name);
else {
if((mac->x[MACRO_NOTIFICATIONRECIPIENTS] = (char *)realloc(mac->x[MACRO_NOTIFICATIONRECIPIENTS], strlen(mac->x[MACRO_NOTIFICATIONRECIPIENTS]) + strlen(cntct->name) + 2))) {
strcat(mac->x[MACRO_NOTIFICATIONRECIPIENTS], ",");
strcat(mac->x[MACRO_NOTIFICATIONRECIPIENTS], cntct->name);
}
}
return OK;
}
nagios-4.4.6/base/perfdata.c 0000664 0000000 0000000 00000005132 13652113235 0015653 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* PERFDATA.C - Performance data routines for 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.
*
*****************************************************************************/
/*********** COMMON HEADER FILES ***********/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/perfdata.h"
#include "../include/macros.h"
#include "../xdata/xpddefault.h"
/******************************************************************/
/************** INITIALIZATION & CLEANUP FUNCTIONS ****************/
/******************************************************************/
/* initializes performance data */
int initialize_performance_data(const char *cfgfile) {
return xpddefault_initialize_performance_data(cfgfile);
}
/* cleans up performance data */
int cleanup_performance_data(void) {
return xpddefault_cleanup_performance_data();
}
/******************************************************************/
/****************** 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! */
xpddefault_update_service_performance_data(svc);
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! */
xpddefault_update_host_performance_data(hst);
return OK;
}
nagios-4.4.6/base/query-handler.c 0000664 0000000 0000000 00000031164 13652113235 0016651 0 ustar 00root root 0000000 0000000 #include "include/config.h"
#include "include/nagios.h"
#include "lib/libnagios.h"
#include "lib/nsock.h"
#include
#include
#include
/* A registered handler */
struct query_handler {
const char *name; /* also "address" of this handler. Must be unique */
const char *description; /* short description of this handler */
unsigned int options;
qh_handler handler;
struct query_handler *prev_qh, *next_qh;
};
static struct query_handler *qhandlers;
static int qh_listen_sock = -1; /* the listening socket */
static unsigned int qh_running;
unsigned int qh_max_running = 0; /* defaults to unlimited */
static dkhash_table *qh_table;
/* the echo service. stupid, but useful for testing */
static int qh_echo(int sd, char *buf, unsigned int len)
{
int result = 0;
if (buf == NULL || !strcmp(buf, "help")) {
nsock_printf_nul(sd,
"Query handler that simply echoes back what you send it.");
return 0;
}
result = write(sd, buf, len);
if (result == -1) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: qh_echo() error on write(sd,buf=[%s],len=%d): %s\n", buf, len, strerror(errno));
}
return 0;
}
static struct query_handler *qh_find_handler(const char *name)
{
return (struct query_handler *)dkhash_get(qh_table, name, NULL);
}
/* subset of http error codes */
const char *qh_strerror(int code)
{
if (code < 0) {
return "Low-level system error";
}
if (code == 100) {
return "Continue";
}
if (code == 101) {
return "Switching protocols";
}
if (code < 300) {
return "OK";
}
if (code < 400) {
return "Redirected (possibly deprecated address)";
}
switch (code) {
/* client errors */
case 400: return "Bad request";
case 401: return "Unauthorized";
case 403: return "Forbidden (disabled by config)";
case 404: return "Not found";
case 405: return "Method not allowed";
case 406: return "Not acceptable";
case 407: return "Proxy authentication required";
case 408: return "Request timed out";
case 409: return "Conflict";
case 410: return "Gone";
case 411: return "Length required";
case 412: return "Precondition failed";
case 413: return "Request too large";
case 414: return "Request-URI too long";
/* server errors */
case 500: return "Internal server error";
case 501: return "Not implemented";
case 502: return "Bad gateway";
case 503: return "Service unavailable";
case 504: return "Gateway timeout";
case 505: return "Version not supported";
}
return "Unknown error";
}
static int qh_input(int sd, int events, void *ioc_)
{
iocache * ioc = (iocache *) ioc_;
int result = 0;
/*
input on main socket, so accept one
this is when a worker initially connects
we create the iocache and then register
that to a new socket descriptor and this function
so that ioc_ != NULL next time
*/
if (sd == qh_listen_sock) {
struct sockaddr sa;
socklen_t slen = 0;
int nsd = 0;
/* shut valgrind up */
memset(&sa, 0, sizeof(sa));
nsd = accept(sd, &sa, &slen);
if (qh_max_running && qh_running >= qh_max_running) {
nsock_printf(nsd, "503: Server full");
close(nsd);
return 0;
}
ioc = iocache_create(16384);
if (ioc == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to create iocache for inbound request\n");
nsock_printf(nsd, "500: Internal server error");
close(nsd);
return 0;
}
/*
* @todo: Stash the iocache and the socket in some
* addressable list so we can release them on deinit
*/
result = iobroker_register(nagios_iobs, nsd, ioc, qh_input);
if (result < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to register input socket %d with I/O broker: %s\n", nsd, strerror(errno));
iocache_destroy(ioc);
close(nsd);
return 0;
}
/* make it non-blocking, but leave kernel buffers unchanged */
worker_set_sockopts(nsd, 0);
qh_running++;
return 0;
}
/*
this is when an existing connection
sends more data after they've already made
the connection
*/
else {
unsigned long len = 0;
unsigned int query_len = 0;
struct query_handler * qh = NULL;
char * buf = NULL;
char * space = NULL;
char * handler = NULL;
char * query = NULL;
result = iocache_read(ioc, sd);
/* disconnect? */
if (result == 0 || (result < 0 && errno == EPIPE)) {
iocache_destroy(ioc);
iobroker_close(nagios_iobs, sd);
qh_running--;
return 0;
}
/*
* A request looks like this: '[@|#][][]\0'.
* That is, optional '#' (oneshot) or '@' (keepalive),
* followed by the name of a registered handler, followed by
* an optional space and an optional query. If the handler
* has no "default" handler, a query is required or an error
* will be thrown.
*/
/* Use data up to the first nul byte */
buf = iocache_use_delim(ioc, "\0", 1, &len);
if (buf == NULL) {
return 0;
}
/* Identify handler part and any magic query bytes */
if (*buf == '@' || *buf == '#') {
handler = buf + 1;
}
/* Locate query (if any) */
space = strchr(buf, ' ');
if (space != NULL) {
*space = 0;
query = space + 1;
query_len = len - (unsigned long)(query - buf);
}
/* locate the handler */
qh = qh_find_handler(handler);
/* not found. that's a 404 */
if (qh == NULL) {
nsock_printf(sd, "404: %s: No such handler", handler);
iobroker_close(nagios_iobs, sd);
iocache_destroy(ioc);
return 0;
}
/* strip trailing newlines */
while (query_len > 0
&& (query[query_len - 1] == 0 || query[query_len - 1] == '\n')) {
query[--query_len] = 0;
}
/* now pass the query to the handler */
result = qh->handler(sd, query, query_len);
if (result >= 100) {
nsock_printf_nul(sd, "%d: %s", result, qh_strerror(result));
}
/* error code or one-shot query */
if (result >= 300 || *buf == '#') {
iobroker_close(nagios_iobs, sd);
iocache_destroy(ioc);
return 0;
}
/* check for magic handler codes */
switch (result) {
/* oneshot handler */
case QH_CLOSE:
/* general error */
case -1:
iobroker_close(nagios_iobs, sd);
/* fallthrough */
/* handler takes over */
case QH_TAKEOVER:
/* switch protocol (takeover + message) */
case 101:
iocache_destroy(ioc);
break;
}
}
return 0;
}
int qh_deregister_handler(const char *name)
{
struct query_handler *qh = NULL;
struct query_handler *next = NULL;
struct query_handler *prev = NULL;
qh = dkhash_remove(qh_table, name, NULL);
if (qh != NULL) {
return 0;
}
next = qh->next_qh;
prev = qh->prev_qh;
if (next != NULL) {
next->prev_qh = prev;
}
if (prev != NULL) {
prev->next_qh = next;
}
else {
qhandlers = next;
}
free(qh);
return 0;
}
int qh_register_handler(const char *name, const char *description, unsigned int options, qh_handler handler)
{
struct query_handler *qh = NULL;
int result = 0;
if (name == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to register handler with no name\n");
return -1;
}
if (handler == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to register handler '%s': No handler function specified\n", name);
return -1;
}
if (strlen(name) > 128) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to register handler '%s': Name too long\n", name);
return -ENAMETOOLONG;
}
/* names must be unique */
if (qh_find_handler(name)) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "qh: Handler '%s' registered more than once\n", name);
return -1;
}
qh = calloc(1, sizeof(*qh));
if (qh == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to allocate memory for handler '%s'\n", name);
return -errno;
}
qh->name = name;
qh->description = description;
qh->handler = handler;
qh->options = options;
qh->next_qh = qhandlers;
if (qhandlers) {
qhandlers->prev_qh = qh;
}
qhandlers = qh;
result = dkhash_insert(qh_table, qh->name, NULL, qh);
if (result < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"qh: Failed to insert query handler '%s' (%p) into hash table %p (%d): %s\n",
name, qh, qh_table, result, strerror(errno));
free(qh);
return result;
}
return 0;
}
void qh_deinit(const char *path)
{
struct query_handler *qh = NULL;
for (qh = qhandlers; qh != NULL; qh = qh->next_qh) {
qh_deregister_handler(qh->name);
}
dkhash_destroy(qh_table);
qh_table = NULL;
qhandlers = NULL;
if (path == NULL) {
return;
}
unlink(path);
}
static int qh_help(int sd, char *buf, unsigned int len)
{
struct query_handler *qh = NULL;
if (buf == NULL || !strcmp(buf, "help")) {
nsock_printf_nul(sd,
" help show help for handler \n"
" help list list registered handlers\n");
return 0;
}
if (!strcmp(buf, "list")) {
for (qh = qhandlers; qh != NULL; qh = qh->next_qh) {
nsock_printf(sd, "%-10s %s\n", qh->name, qh->description ? qh->description : "(No description available)");
}
nsock_printf(sd, "%c", 0);
return 0;
}
qh = qh_find_handler(buf);
if (qh == NULL) {
nsock_printf_nul(sd, "No handler named '%s' is registered\n", buf);
} else if (qh->handler(sd, "help", 4) > 200) {
nsock_printf_nul(sd, "The handler %s doesn't have any help yet.", buf);
}
return 0;
}
static int qh_core(int sd, char *buf, unsigned int len)
{
char *space;
if (buf == NULL || !strcmp(buf, "help")) {
nsock_printf_nul(sd,
"Query handler for manipulating nagios core.\n"
"Available commands:\n"
" loadctl Print information about current load control settings\n"
" loadctl Configure nagios load control.\n"
" The options are the same parameters and format as\n"
" returned above.\n"
" squeuestats scheduling queue statistics\n"
);
return 0;
}
space = memchr(buf, ' ', len);
if (space != NULL) {
*(space++) = 0;
}
if (space == NULL) {
if (!strcmp(buf, "loadctl")) {
nsock_printf_nul(sd,
"jobs_max=%u;jobs_min=%u;"
"jobs_running=%u;jobs_limit=%u;"
"load=%.2f;"
"backoff_limit=%.2f;backoff_change=%u;"
"rampup_limit=%.2f;rampup_change=%u;"
"nproc_limit=%u;nofile_limit=%u;"
"options=%u;changes=%u;",
loadctl.jobs_max, loadctl.jobs_min,
loadctl.jobs_running, loadctl.jobs_limit,
loadctl.load[0],
loadctl.backoff_limit, loadctl.backoff_change,
loadctl.rampup_limit, loadctl.rampup_change,
loadctl.nproc_limit, loadctl.nofile_limit,
loadctl.options, loadctl.changes
);
return 0;
}
else if (!strcmp(buf, "squeuestats")) {
return dump_event_stats(sd);
}
}
/* space != NULL: */
else {
len -= (unsigned long)(space - buf);
if (!strcmp(buf, "loadctl")) {
return set_loadctl_options(space, len) == OK ? 200 : 400;
}
}
/* No matching command found */
return 404;
}
int qh_init(const char *path)
{
int result = 0;
int old_umask = 0;
if (qh_listen_sock >= 0) {
iobroker_close(nagios_iobs, qh_listen_sock);
}
if (path == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: query_socket is NULL. What voodoo is this?\n");
return ERROR;
}
old_umask = umask(0117);
errno = 0;
qh_listen_sock = nsock_unix(path, NSOCK_TCP | NSOCK_UNLINK);
umask(old_umask);
if (qh_listen_sock < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to init socket '%s'. %s: %s\n",
path, nsock_strerror(qh_listen_sock), strerror(errno));
return ERROR;
}
/* plugins shouldn't have this socket */
result = fcntl(qh_listen_sock, F_SETFD, FD_CLOEXEC);
if (result == -1) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to fcntl() query handler socket\n");
}
/* most likely overkill, but it's small, so... */
qh_table = dkhash_create(1024);
if (qh_table == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to create hash table\n");
close(qh_listen_sock);
return ERROR;
}
errno = 0;
result = iobroker_register(nagios_iobs, qh_listen_sock, NULL, qh_input);
if (result < 0) {
dkhash_destroy(qh_table);
close(qh_listen_sock);
logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to register socket with io broker: %s; errno=%d: %s\n", iobroker_strerror(result), errno, strerror(errno));
return ERROR;
}
logit(NSLOG_INFO_MESSAGE, FALSE, "qh: Socket '%s' successfully initialized\n", path);
/* now register our the in-core handlers */
result = qh_register_handler("core", "Nagios Core control and info", 0, qh_core);
if (result == OK) {
logit(NSLOG_INFO_MESSAGE, FALSE, "qh: core query handler registered\n");
}
result = qh_register_handler("echo", "The Echo Service - What You Put Is What You Get", 0, qh_echo);
if (result == OK) {
logit(NSLOG_INFO_MESSAGE, FALSE, "qh: echo service query handler registered\n");
}
result = qh_register_handler("help", "Help for the query handler", 0, qh_help);
if (result == OK) {
logit(NSLOG_INFO_MESSAGE, FALSE, "qh: help for the query handler registered\n");
}
return 0;
}
nagios-4.4.6/base/sehandlers.c 0000664 0000000 0000000 00000052554 13652113235 0016227 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* SEHANDLERS.C - Service and host event and state handlers for 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/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"
#include "../include/workers.h"
#ifdef USE_EVENT_BROKER
#include "../include/neberrors.h"
#endif
/******************************************************************/
/************* 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 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 || svc->obsess == 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 through a worker */
wproc_run_service_job(WPJOB_OCSP, ocsp_timeout, svc, processed_command, &mac);
/* free memory */
clear_volatile_macros_r(&mac);
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 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 || hst->obsess == 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 through a worker */
wproc_run_host_job(WPJOB_OCHP, ochp_timeout, hst, processed_command, &mac);
/* free memory */
clear_volatile_macros_r(&mac);
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);
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 through a worker */
/* XXX FIXME make base/workers.c handle the eventbroker stuff below */
result = wproc_run(WPJOB_GLOBAL_SVC_EVTHANDLER, processed_command, event_handler_timeout, mac);
/* 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 through a worker */
/* XXX FIXME make base/workers.c handle the eventbroker stuff below */
result = wproc_run(WPJOB_SVC_EVTHANDLER, processed_command, event_handler_timeout, mac);
/* 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);
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 through a worker */
/* XXX FIXME make base/workers.c handle the eventbroker stuff below */
wproc_run(WPJOB_GLOBAL_HOST_EVTHANDLER, processed_command, event_handler_timeout, mac);
/* 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 through a worker */
result = wproc_run(WPJOB_HOST_EVTHANDLER, processed_command, event_handler_timeout, mac);
/* 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;
}
nagios-4.4.6/base/sretention.c 0000664 0000000 0000000 00000005661 13652113235 0016266 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* SRETENTION.C - State retention routines for 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.
*
*****************************************************************************/
/*********** 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"
#include "../xdata/xrddefault.h" /* default routines */
/******************************************************************/
/************* TOP-LEVEL STATE INFORMATION FUNCTIONS **************/
/******************************************************************/
/* initializes retention data at program start */
int initialize_retention_data(const char *cfgfile) {
return xrddefault_initialize_retention_data(cfgfile);
}
/* cleans up retention data before program termination */
int cleanup_retention_data(void) {
return xrddefault_cleanup_retention_data();
}
/* 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
result = xrddefault_save_state_information();
#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
result = xrddefault_read_state_information();
#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;
}
nagios-4.4.6/base/utils.c 0000664 0000000 0000000 00000327574 13652113235 0015246 0 ustar 00root root 0000000 0000000 /*****************************************************************************
*
* UTILS.C - Miscellaneous utility functions for 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/statusdata.h"
#include "../include/comments.h"
#include "../include/downtime.h"
#include "../include/macros.h"
#include "../include/nagios.h"
#include "../include/netutils.h"
#include "../include/perfdata.h"
#include "../include/broker.h"
#include "../include/nebmods.h"
#include "../include/nebmodules.h"
#include "../include/workers.h"
#include "../xdata/xodtemplate.h"
#include
#include
/* global variables only used by the daemon */
char *nagios_binary_path = NULL;
char *config_file = NULL;
char *command_file;
char *temp_file;
char *temp_path;
char *check_result_path;
char *lock_file;
int num_check_workers;
char *qh_socket_path;
char *nagios_user;
char *nagios_group;
char *ocsp_command;
char *ochp_command;
command *ocsp_command_ptr = NULL;
command *ochp_command_ptr = NULL;
int ocsp_timeout;
int ochp_timeout;
char *illegal_object_chars;
int use_regexp_matches;
int use_true_regexp_matching;
int use_syslog;
char *log_file;
char *log_archive_path;
int log_notifications;
int log_service_retries;
int log_host_retries;
int log_event_handlers;
int log_initial_states;
int log_current_states;
int log_external_commands;
int log_passive_checks;
unsigned long logging_options = 0;
unsigned long syslog_options = 0;
int service_check_timeout;
int service_check_timeout_state;
int host_check_timeout;
int event_handler_timeout;
int notification_timeout;
char *object_precache_file;
char *global_host_event_handler;
char *global_service_event_handler;
command *global_host_event_handler_ptr = NULL;
command *global_service_event_handler_ptr = NULL;
int service_inter_check_delay_method;
int host_inter_check_delay_method;
int service_interleave_factor_method;
int max_host_check_spread;
int max_service_check_spread;
int check_reaper_interval;
int max_check_reaper_time;
int service_freshness_check_interval;
int host_freshness_check_interval;
int auto_rescheduling_interval;
struct load_control loadctl;
int check_orphaned_services;
int check_orphaned_hosts;
int check_service_freshness;
int check_host_freshness;
int auto_reschedule_checks;
int auto_rescheduling_window;
int additional_freshness_latency;
int check_for_updates;
int 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_program_stop = 0L;
int use_aggressive_host_checking;
time_t cached_host_check_horizon;
time_t cached_service_check_horizon;
int enable_predictive_host_dependency_checks;
int enable_predictive_service_dependency_checks;
int soft_state_dependencies;
int retain_state_information;
int retention_update_interval;
int use_retained_program_state;
int use_retained_scheduling_info;
int retention_scheduling_horizon;
char *retention_file;
unsigned long modified_process_attributes = MODATTR_NONE;
unsigned long modified_host_process_attributes = MODATTR_NONE;
unsigned long modified_service_process_attributes = MODATTR_NONE;
unsigned long retained_host_attribute_mask;
unsigned long retained_service_attribute_mask;
unsigned long retained_contact_host_attribute_mask;
unsigned long retained_contact_service_attribute_mask;
unsigned long retained_process_host_attribute_mask;
unsigned long retained_process_service_attribute_mask;
unsigned long next_event_id = 0L;
unsigned long next_problem_id = 1L;
unsigned long next_comment_id = 0L;
unsigned long next_notification_id = 0L;
int verify_config = FALSE;
int test_scheduling = FALSE;
int precache_objects = FALSE;
int use_precached_objects = FALSE;
int sigshutdown = FALSE;
int sigrestart = FALSE;
int caught_signal = FALSE;
int sig_id = 0;
int daemon_dumps_core;
int max_parallel_service_checks;
int currently_running_service_checks = 0;
int currently_running_host_checks = 0;
time_t event_start = 0L;
int translate_passive_host_checks;
int passive_host_checks_are_soft;
int status_update_interval;
int time_change_threshold;
unsigned long event_broker_options;
double low_service_flap_threshold;
double high_service_flap_threshold;
double low_host_flap_threshold;
double high_host_flap_threshold;
int use_large_installation_tweaks;
int enable_environment_macros;
int free_child_process_memory;
int child_processes_fork_twice;
char *use_timezone;
char *website_url;
int allow_empty_hostgroup_assignment;
int host_down_disable_service_checks;
int service_skip_check_dependency_status;
int service_skip_check_parent_status;
int service_skip_check_host_down_status;
int host_skip_check_dependency_status;
/*** perfdata variables ***/
int perfdata_timeout;
char *host_perfdata_command;
char *service_perfdata_command;
char *host_perfdata_file_template;
char *service_perfdata_file_template;
char *host_perfdata_file;
char *service_perfdata_file;
int host_perfdata_file_append;
int service_perfdata_file_append;
int host_perfdata_file_pipe;
int service_perfdata_file_pipe;
unsigned long host_perfdata_file_processing_interval;
unsigned long service_perfdata_file_processing_interval;
char *host_perfdata_file_processing_command;
char *service_perfdata_file_processing_command;
int host_perfdata_process_empty_results;
int service_perfdata_process_empty_results;
/*** end perfdata variables */
/* Filename variables used by handle_sigxfsz */
extern char *status_file;
static long long check_file_size(char *, unsigned long, struct rlimit);
notification *notification_list;
time_t max_check_result_file_age;
check_stats check_statistics[MAX_CHECK_STATS_TYPES];
char *debug_file;
int debug_level;
int debug_verbosity;
unsigned long max_debug_file_size;
iobroker_set *nagios_iobs = NULL;
squeue_t *nagios_squeue = NULL; /* our scheduling queue */
sched_info scheduling_info;
/* from GNU defines errno as a macro, since it's a per-thread variable */
#ifndef errno
extern int errno;
#endif
/* Initialize the non-shared main configuration variables */
void init_main_cfg_vars(int first_time) {
/* Initialize only the first time */
if(first_time) {
num_check_workers = 0; /* auto-decide */
qh_socket_path = NULL; /* disabled */
}
log_file = NULL;
temp_file = NULL;
temp_path = NULL;
check_result_path = NULL;
command_file = NULL;
lock_file = NULL;
log_archive_path = NULL;
debug_file = NULL;
object_precache_file = (char *)strdup(DEFAULT_PRECACHED_OBJECT_FILE);
nagios_user = NULL;
nagios_group = NULL;
website_url = NULL;
use_regexp_matches = FALSE;
use_true_regexp_matching = FALSE;
use_syslog = DEFAULT_USE_SYSLOG;
log_service_retries = DEFAULT_LOG_SERVICE_RETRIES;
log_host_retries = DEFAULT_LOG_HOST_RETRIES;
log_initial_states = DEFAULT_LOG_INITIAL_STATES;
if(first_time) {
/* Not sure why this is not reset in reset_variables() */
log_current_states = DEFAULT_LOG_CURRENT_STATES;
}
log_notifications = DEFAULT_NOTIFICATION_LOGGING;
log_event_handlers = DEFAULT_LOG_EVENT_HANDLERS;
log_external_commands = DEFAULT_LOG_EXTERNAL_COMMANDS;
log_passive_checks = DEFAULT_LOG_PASSIVE_CHECKS;
service_check_timeout = DEFAULT_SERVICE_CHECK_TIMEOUT;
if(first_time) {
/* Not sure why this is not reset in reset_variables() */
service_check_timeout_state = STATE_CRITICAL;
}
host_check_timeout = DEFAULT_HOST_CHECK_TIMEOUT;
event_handler_timeout = DEFAULT_EVENT_HANDLER_TIMEOUT;
notification_timeout = DEFAULT_NOTIFICATION_TIMEOUT;
ocsp_timeout = DEFAULT_OCSP_TIMEOUT;
ochp_timeout = DEFAULT_OCHP_TIMEOUT;
if(first_time) {
/* Not sure why this is not reset in reset_variables() */
illegal_object_chars = NULL;
}
service_inter_check_delay_method = ICD_SMART;
host_inter_check_delay_method = ICD_SMART;
service_interleave_factor_method = ILF_SMART;
max_service_check_spread = DEFAULT_SERVICE_CHECK_SPREAD;
max_host_check_spread = DEFAULT_HOST_CHECK_SPREAD;
use_aggressive_host_checking = DEFAULT_AGGRESSIVE_HOST_CHECKING;
cached_host_check_horizon = DEFAULT_CACHED_HOST_CHECK_HORIZON;
cached_service_check_horizon = DEFAULT_CACHED_SERVICE_CHECK_HORIZON;
enable_predictive_host_dependency_checks =
DEFAULT_ENABLE_PREDICTIVE_HOST_DEPENDENCY_CHECKS;
enable_predictive_service_dependency_checks =
DEFAULT_ENABLE_PREDICTIVE_SERVICE_DEPENDENCY_CHECKS;
soft_state_dependencies = FALSE;
retain_state_information = FALSE;
retention_update_interval = DEFAULT_RETENTION_UPDATE_INTERVAL;
use_retained_program_state = TRUE;
use_retained_scheduling_info = FALSE;
retention_scheduling_horizon = DEFAULT_RETENTION_SCHEDULING_HORIZON;
if(first_time) {
/* Not sure why this is not reset in reset_variables() */
retention_file = NULL;
}
retained_host_attribute_mask = 0L;
retained_service_attribute_mask = 0L;
retained_process_host_attribute_mask = 0L;
retained_process_service_attribute_mask = 0L;
retained_contact_host_attribute_mask = 0L;
retained_contact_service_attribute_mask = 0L;
check_reaper_interval = DEFAULT_CHECK_REAPER_INTERVAL;
max_check_reaper_time = DEFAULT_MAX_REAPER_TIME;
max_check_result_file_age = DEFAULT_MAX_CHECK_RESULT_AGE;
service_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL;
host_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL;
auto_rescheduling_interval = DEFAULT_AUTO_RESCHEDULING_INTERVAL;
auto_rescheduling_window = DEFAULT_AUTO_RESCHEDULING_WINDOW;
check_orphaned_services = DEFAULT_CHECK_ORPHANED_SERVICES;
check_orphaned_hosts = DEFAULT_CHECK_ORPHANED_HOSTS;
check_service_freshness = DEFAULT_CHECK_SERVICE_FRESHNESS;
check_host_freshness = DEFAULT_CHECK_HOST_FRESHNESS;
auto_reschedule_checks = DEFAULT_AUTO_RESCHEDULE_CHECKS;
if(first_time) {
/* Not sure why this is not reset in reset_variables() */
daemon_dumps_core = TRUE;
}
max_parallel_service_checks = DEFAULT_MAX_PARALLEL_SERVICE_CHECKS;
status_update_interval = DEFAULT_STATUS_UPDATE_INTERVAL;
event_broker_options = BROKER_NOTHING;
time_change_threshold = DEFAULT_TIME_CHANGE_THRESHOLD;
low_service_flap_threshold = DEFAULT_LOW_SERVICE_FLAP_THRESHOLD;
high_service_flap_threshold = DEFAULT_HIGH_SERVICE_FLAP_THRESHOLD;
low_host_flap_threshold = DEFAULT_LOW_HOST_FLAP_THRESHOLD;
high_host_flap_threshold = DEFAULT_HIGH_HOST_FLAP_THRESHOLD;
translate_passive_host_checks = DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS;
passive_host_checks_are_soft = DEFAULT_PASSIVE_HOST_CHECKS_SOFT;
use_large_installation_tweaks = DEFAULT_USE_LARGE_INSTALLATION_TWEAKS;
enable_environment_macros = FALSE;
free_child_process_memory = -1;
child_processes_fork_twice = -1;
if(first_time) {
/* Not sure why these are not reset in reset_variables() */
use_timezone = NULL;
allow_empty_hostgroup_assignment =
DEFAULT_ALLOW_EMPTY_HOSTGROUP_ASSIGNMENT;
host_down_disable_service_checks = FALSE;
service_skip_check_dependency_status = -1;
service_skip_check_parent_status = -1;
service_skip_check_host_down_status = -1;
host_skip_check_dependency_status = -1;
perfdata_timeout = 0;
host_perfdata_command = NULL;
service_perfdata_command = NULL;
host_perfdata_file_template = NULL;
service_perfdata_file_template = NULL;
host_perfdata_file = NULL;
service_perfdata_file = NULL;
host_perfdata_file_pipe = FALSE;
host_perfdata_file_append = TRUE;
service_perfdata_file_pipe = FALSE;
service_perfdata_file_append = TRUE;
host_perfdata_file_processing_interval = 0L;
service_perfdata_file_processing_interval = 0L;
host_perfdata_file_processing_command = NULL;
service_perfdata_file_processing_command = NULL;
host_perfdata_process_empty_results =
DEFAULT_HOST_PERFDATA_PROCESS_EMPTY_RESULTS;
service_perfdata_process_empty_results =
DEFAULT_SERVICE_PERFDATA_PROCESS_EMPTY_RESULTS;
}
additional_freshness_latency = DEFAULT_ADDITIONAL_FRESHNESS_LATENCY;
if(first_time) {
/* Not sure why these are not reset in reset_variables() */
check_for_updates = DEFAULT_CHECK_FOR_UPDATES;
bare_update_check = DEFAULT_BARE_UPDATE_CHECK;
debug_level = DEFAULT_DEBUG_LEVEL;
debug_verbosity = DEFAULT_DEBUG_VERBOSITY;
max_debug_file_size = DEFAULT_MAX_DEBUG_FILE_SIZE;
}
global_host_event_handler = NULL;
global_service_event_handler = NULL;
ocsp_command = NULL;
ochp_command = NULL;
return;
}
static const char *worker_source_name(const void *source) {
return source ? (const char *)source : "unknown internal source (voodoo, perhaps?)";
}
static const char *spool_file_source_name(const void *source) {
return "check result spool dir";
}
struct check_engine nagios_check_engine = {
"Nagios Core",
worker_source_name,
NULL,
};
static struct check_engine nagios_spool_check_engine = {
"Spooled checkresult file",
spool_file_source_name,
NULL,
};
const char *check_result_source(check_result *cr) {
if(cr->engine)
return cr->engine->source_name(cr->source);
return cr->source ? (const char *)cr->source : "(unknown engine)";
}
int set_loadctl_options(char *opts, unsigned int len)
{
struct kvvec *kvv;
int i;
kvv = buf2kvvec(opts, len, '=', ';', 0);
for (i = 0; i < kvv->kv_pairs; i++) {
struct key_value *kv = &kvv->kv[i];
if (!strcmp(kv->key, "enabled")) {
if (*kv->value == '1') {
if (!(loadctl.options & LOADCTL_ENABLED))
logit(0, 0, "Warning: Enabling experimental load control\n");
loadctl.options |= LOADCTL_ENABLED;
}
else {
if (loadctl.options & LOADCTL_ENABLED)
logit(0, 0, "Warning: Disabling experimental load control\n");
loadctl.options &= (~LOADCTL_ENABLED);
}
} else if (!strcmp(kv->key, "jobs_max")) {
loadctl.jobs_max = atoi(kv->value);
} else if (!strcmp(kv->key, "jobs_min")) {
loadctl.jobs_min = atoi(kv->value);
} else if (!strcmp(kv->key, "jobs_limit")) {
loadctl.jobs_limit = atoi(kv->value);
} else if (!strcmp(kv->key, "check_interval")) {
loadctl.check_interval = strtoul(kv->value, NULL, 10);
} else if (!strcmp(kv->key, "backoff_limit")) {
loadctl.backoff_limit = strtod(kv->value, NULL);
} else if (!strcmp(kv->key, "rampup_limit")) {
loadctl.rampup_limit = strtod(kv->value, NULL);
} else if (!strcmp(kv->key, "backoff_change")) {
loadctl.backoff_change = atoi(kv->value);
} else if (!strcmp(kv->key, "rampup_change")) {
loadctl.rampup_change = atoi(kv->value);
} else {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Bad loadctl option; %s = %s\n", kv->key, kv->value);
return 400;
}
}
/* precedence order is "jobs_min -> jobs_max -> jobs_limit" */
if (loadctl.jobs_max < loadctl.jobs_min)
loadctl.jobs_max = loadctl.jobs_min;
if (loadctl.jobs_limit > loadctl.jobs_max)
loadctl.jobs_limit = loadctl.jobs_max;
if (loadctl.jobs_limit < loadctl.jobs_min)
loadctl.jobs_limit = loadctl.jobs_min;
kvvec_destroy(kvv, 0);
return 0;
}
/******************************************************************/
/******************** SYSTEM COMMAND FUNCTIONS ********************/
/******************************************************************/
/* executes a system command - used for notifications, event handlers, etc. */
int my_system_r(nagios_macros *mac, char *cmd, int timeout, int *early_timeout, double *exectime, char **output, int max_output_length) {
pid_t pid = 0;
int status = 0;
int result = 0;
char buffer[MAX_INPUT_BUFFER] = "";
int fd[2];
FILE *fp = NULL;
int bytes_read = 0;
struct timeval start_time, end_time;
dbuf output_dbuf;
int dbuf_chunk = 1024;
int flags;
#ifdef HAVE_SIGACTION
struct sigaction sig_action;
#endif
log_debug_info(DEBUGL_FUNCTIONS, 0, "my_system_r()\n");
/* initialize return variables */
if(output != NULL)
*output = NULL;
*early_timeout = FALSE;
*exectime = 0.0;
/* if no command was passed, return with no error */
if(cmd == NULL)
return STATE_OK;
log_debug_info(DEBUGL_COMMANDS, 1, "Running command '%s'...\n", cmd);
/* create a pipe */
pipe(fd);
/* make the pipe non-blocking */
fcntl(fd[0], F_SETFL, O_NONBLOCK);
fcntl(fd[1], F_SETFL, O_NONBLOCK);
/* get the command start time */
gettimeofday(&start_time, NULL);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
end_time.tv_sec = 0L;
end_time.tv_usec = 0L;
broker_system_command(NEBTYPE_SYSTEM_COMMAND_START, NEBFLAG_NONE, NEBATTR_NONE, start_time, end_time, *exectime, timeout, *early_timeout, result, cmd, NULL, NULL);
#endif
/* fork */
pid = fork();
/* return an error if we couldn't fork */
if(pid == -1) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: fork() in my_system_r() failed for command \"%s\" - errno: %s\n", cmd, strerror(errno));
/* close both ends of the pipe */
close(fd[0]);
close(fd[1]);
return STATE_UNKNOWN;
}
/* execute the command in the child process */
if(pid == 0) {
/* become process group leader */
setpgid(0, 0);
/* set environment variables */
set_all_macro_environment_vars_r(mac, TRUE);
/* ADDED 11/12/07 EG */
/* close external command file and shut down worker thread */
close_command_file();
/* reset signal handling */
reset_sighandler();
/* close pipe for reading */
close(fd[0]);
/* prevent fd from being inherited by child processed */
flags = fcntl(fd[1], F_GETFD, 0);
flags |= FD_CLOEXEC;
fcntl(fd[1], F_SETFD, flags);
/* trap commands that timeout */
#ifdef HAVE_SIGACTION
sig_action.sa_sigaction = NULL;
sig_action.sa_handler = my_system_sighandler;
sigfillset(&sig_action.sa_mask);
sig_action.sa_flags = SA_NODEFER|SA_RESTART;
sigaction(SIGALRM, &sig_action, NULL);
#else
signal(SIGALRM, my_system_sighandler);
#endif /* HAVE_SIGACTION */
alarm(timeout);
/* run the command */
fp = (FILE *)popen(cmd, "r");
/* report an error if we couldn't run the command */
if(fp == NULL) {
strncpy(buffer, "(Error: Could not execute command)\n", sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\x0';
/* write the error back to the parent process */
write(fd[1], buffer, strlen(buffer) + 1);
result = STATE_CRITICAL;
}
else {
/* write all the lines of output back to the parent process */
while(fgets(buffer, sizeof(buffer) - 1, fp))
write(fd[1], buffer, strlen(buffer));
/* close the command and get termination status */
status = pclose(fp);
/* report an error if we couldn't close the command */
if(status == -1)
result = STATE_CRITICAL;
else {
if(WEXITSTATUS(status) == 0 && WIFSIGNALED(status))
result = 128 + WTERMSIG(status);
result = WEXITSTATUS(status);
}
}
/* close pipe for writing */
close(fd[1]);
/* reset the alarm */
alarm(0);
/* clear environment variables */
set_all_macro_environment_vars_r(mac, FALSE);
#ifndef DONT_USE_MEMORY_PERFORMANCE_TWEAKS
/* free allocated memory */
/* this needs to be done last, so we don't free memory for variables before they're used above */
if(free_child_process_memory == TRUE)
free_memory(mac);
#endif
_exit(result);
}
/* parent waits for child to finish executing command */
else {
/* close pipe for writing */
close(fd[1]);
/* wait for child to exit */
waitpid(pid, &status, 0);
/* get the end time for running the command */
gettimeofday(&end_time, NULL);
/* return execution time in milliseconds */
*exectime = (double)((double)(end_time.tv_sec - start_time.tv_sec) + (double)((end_time.tv_usec - start_time.tv_usec) / 1000) / 1000.0);
if(*exectime < 0.0)
*exectime = 0.0;
/* get the exit code returned from the program */
result = WEXITSTATUS(status);
/* check for possibly missing scripts/binaries/etc */
if(result == 126 || result == 127) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Attempting to execute the command \"%s\" resulted in a return code of %d. Make sure the script or binary you are trying to execute actually exists...\n", cmd, result);
}
/* check bounds on the return value */
if(result < -1 || result > 3)
result = STATE_UNKNOWN;
/* initialize dynamic buffer */
dbuf_init(&output_dbuf, dbuf_chunk);
/* Opsera patch to check timeout before attempting to read output via pipe. Originally by Sven Nierlein */
/* if there was a critical return code AND the command time exceeded the timeout thresholds, assume a timeout */
if(result == STATE_CRITICAL && (end_time.tv_sec - start_time.tv_sec) >= timeout) {
/* set the early timeout flag */
*early_timeout = TRUE;
/* try to kill the command that timed out by sending termination signal to child process group */
kill((pid_t)(-pid), SIGTERM);
sleep(1);
kill((pid_t)(-pid), SIGKILL);
}
/* read output if timeout has not occurred */
else {
/* initialize output */
strcpy(buffer, "");
/* try and read the results from the command output (retry if we encountered a signal) */
do {
bytes_read = read(fd[0], buffer, sizeof(buffer) - 1);
/* append data we just read to dynamic buffer */
if(bytes_read > 0) {
buffer[bytes_read] = '\x0';
dbuf_strcat(&output_dbuf, buffer);
}
/* handle errors */
if(bytes_read == -1) {
/* we encountered a recoverable error, so try again */
if(errno == EINTR)
continue;
/* patch by Henning Brauer to prevent CPU hogging */
else if(errno == EAGAIN) {
struct pollfd pfd;
pfd.fd = fd[0];
pfd.events = POLLIN;
poll(&pfd, 1, -1);
continue;
}
else
break;
}
/* we're done */
if(bytes_read == 0)
break;
}
while(1);
/* cap output length - this isn't necessary, but it keeps runaway plugin output from causing problems */
if(max_output_length > 0 && (int)output_dbuf.used_size > max_output_length)
output_dbuf.buf[max_output_length] = '\x0';
if(output != NULL && output_dbuf.buf)
*output = (char *)strdup(output_dbuf.buf);
}
log_debug_info(DEBUGL_COMMANDS, 1, "Execution time=%.3f sec, early timeout=%d, result=%d, output=%s\n", *exectime, *early_timeout, result, (output_dbuf.buf == NULL) ? "(null)" : output_dbuf.buf);
#ifdef USE_EVENT_BROKER
/* send data to event broker */
broker_system_command(NEBTYPE_SYSTEM_COMMAND_END, NEBFLAG_NONE, NEBATTR_NONE, start_time, end_time, *exectime, timeout, *early_timeout, result, cmd, (output_dbuf.buf == NULL) ? NULL : output_dbuf.buf, NULL);
#endif
/* free memory */
dbuf_free(&output_dbuf);
/* close the pipe for reading */
close(fd[0]);
}
return result;
}
/*
* For API compatibility, we must include a my_system() whose
* signature doesn't include the nagios_macros variable.
* NDOUtils uses this. Possibly other modules as well.
*/
int my_system(char *cmd, int timeout, int *early_timeout, double *exectime, char **output, int max_output_length) {
return my_system_r(get_global_macros(), cmd, timeout, early_timeout, exectime, output, max_output_length);
}
/* given a "raw" command, return the "expanded" or "whole" command line */
int get_raw_command_line_r(nagios_macros *mac, command *cmd_ptr, char *cmd, char **full_command, int macro_options) {
char temp_arg[MAX_COMMAND_BUFFER] = "";
char *arg_buffer = NULL;
register int x = 0;
register int y = 0;
register int arg_index = 0;
log_debug_info(DEBUGL_FUNCTIONS, 0, "get_raw_command_line_r()\n");
/* clear the argv macros */
clear_argv_macros_r(mac);
/* make sure we've got all the requirements */
if(cmd_ptr == NULL || full_command == NULL)
return ERROR;
log_debug_info(DEBUGL_COMMANDS | DEBUGL_CHECKS | DEBUGL_MACROS, 2, "Raw Command Input: %s\n", cmd_ptr->command_line);
/* get the full command line */
*full_command = (char *)strdup((cmd_ptr->command_line == NULL) ? "" : cmd_ptr->command_line);
/* XXX: Crazy indent */
/* get the command arguments */
if(cmd != NULL) {
/* skip the command name (we're about to get the arguments)... */
for(arg_index = 0;; arg_index++) {
if(cmd[arg_index] == '!' || cmd[arg_index] == '\x0')
break;
}
/* get each command argument */
for(x = 0; x < MAX_COMMAND_ARGUMENTS; x++) {
/* we reached the end of the arguments... */
if(cmd[arg_index] == '\x0')
break;
/* get the next argument */
/* can't use strtok(), as that's used in process_macros... */
for(arg_index++, y = 0; y < (int)sizeof(temp_arg) - 1; arg_index++) {
/* handle escaped argument delimiters */
if(cmd[arg_index] == '\\' && cmd[arg_index+1] == '!') {
arg_index++;
} else if(cmd[arg_index] == '!' || cmd[arg_index] == '\x0') {
/* end of argument */
break;
}
/* copy the character */
temp_arg[y] = cmd[arg_index];
y++;
}
temp_arg[y] = '\x0';
/* ADDED 01/29/04 EG */
/* process any macros we find in the argument */
process_macros_r(mac, temp_arg, &arg_buffer, macro_options);
mac->argv[x] = arg_buffer;
}
}
log_debug_info(DEBUGL_COMMANDS | DEBUGL_CHECKS | DEBUGL_MACROS, 2, "Expanded Command Output: %s\n", *full_command);
return OK;
}
/*
* This function modifies the global macro struct and is thus not
* threadsafe
*/
int get_raw_command_line(command *cmd_ptr, char *cmd, char **full_command, int macro_options) {
nagios_macros *mac;
mac = get_global_macros();
return get_raw_command_line_r(mac, cmd_ptr, cmd, full_command, macro_options);
}
/******************************************************************/
/******************** ENVIRONMENT FUNCTIONS ***********************/
/******************************************************************/
/* sets or unsets an environment variable */
int set_environment_var(char *name, char *value, int set) {
#ifndef HAVE_SETENV
char *env_string = NULL;
#endif
/* we won't mess with null variable names */
if(name == NULL)
return ERROR;
/* set the environment variable */
if(set == TRUE) {
#ifdef HAVE_SETENV
setenv(name, (value == NULL) ? "" : value, 1);
#else
/* needed for Solaris and systems that don't have setenv() */
/* this will leak memory, but in a "controlled" way, since lost memory should be freed when the child process exits */
asprintf(&env_string, "%s=%s", name, (value == NULL) ? "" : value);
if(env_string)
putenv(env_string);
#endif
}
/* clear the variable */
else {
#ifdef HAVE_UNSETENV
unsetenv(name);
#endif
}
return OK;
}
/******************************************************************/
/************************* TIME FUNCTIONS *************************/
/******************************************************************/
/* Checks if the given time is in daylight time saving period */
static int is_dst_time(time_t *time) {
struct tm *bt = localtime(time);
return bt->tm_isdst;
}
/* Returns the shift in seconds if the given times are across the daylight time saving period change */
static int get_dst_shift(time_t *start, time_t *end) {
int shift = 0, dst_end, dst_start;
dst_start = is_dst_time(start);
dst_end = is_dst_time(end);
if(dst_start < dst_end) {
shift = 3600;
}
else if(dst_start > dst_end) {
shift = -3600;
}
return shift;
}
/*#define TEST_TIMEPERIODS_A 1*/
static timerange* _get_matching_timerange(time_t test_time, timeperiod *tperiod) {
daterange *temp_daterange = NULL;
time_t start_time = (time_t)0L;
time_t end_time = (time_t)0L;
unsigned long days = 0L;
int year = 0;
int shift = 0;
time_t midnight = (time_t)0L;
struct tm *t, tm_s;
int daterange_type = 0;
int test_time_year = 0;
int test_time_mon = 0;
int test_time_wday = 0;
log_debug_info(DEBUGL_FUNCTIONS, 0, "_get_matching_timerange()\n");
if(tperiod == NULL)
return NULL;
t = localtime_r((time_t *)&test_time, &tm_s);
test_time_year = t->tm_year;
test_time_mon = t->tm_mon;
test_time_wday = t->tm_wday;
/* calculate the start of the day (midnight, 00:00 hours) when the specified test time occurs */
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
midnight = mktime(t);
/**** check exceptions first ****/
for(daterange_type = 0; daterange_type < DATERANGE_TYPES; daterange_type++) {
for(temp_daterange = tperiod->exceptions[daterange_type]; temp_daterange != NULL; temp_daterange = temp_daterange->next) {
#ifdef TEST_TIMEPERIODS_A
printf("TYPE: %d\n", daterange_type);
printf("TEST: %llu = %s", (unsigned long long)test_time, ctime(&test_time));
printf("MIDNIGHT: %llu = %s", (unsigned long long)midnight, ctime(&midnight));
#endif
/* get the start time */
switch(daterange_type) {
case DATERANGE_CALENDAR_DATE:
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
t->tm_wday = 0;
t->tm_mday = temp_daterange->smday;
t->tm_mon = temp_daterange->smon;
t->tm_year = (temp_daterange->syear - 1900);
t->tm_isdst = -1;
start_time = mktime(t);
break;
case DATERANGE_MONTH_DATE:
start_time = calculate_time_from_day_of_month(test_time_year, temp_daterange->smon, temp_daterange->smday);
break;
case DATERANGE_MONTH_DAY:
start_time = calculate_time_from_day_of_month(test_time_year, test_time_mon, temp_daterange->smday);
break;
case DATERANGE_MONTH_WEEK_DAY:
start_time = calculate_time_from_weekday_of_month(test_time_year, temp_daterange->smon, temp_daterange->swday, temp_daterange->swday_offset);
break;
case DATERANGE_WEEK_DAY:
start_time = calculate_time_from_weekday_of_month(test_time_year, test_time_mon, temp_daterange->swday, temp_daterange->swday_offset);
break;
default:
continue;
break;
}
/* get the end time */
switch(daterange_type) {
case DATERANGE_CALENDAR_DATE:
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
t->tm_wday = 0;
t->tm_mday = temp_daterange->emday;
t->tm_mon = temp_daterange->emon;
t->tm_year = (temp_daterange->eyear - 1900);
t->tm_isdst = -1;
end_time = mktime(t);
break;
case DATERANGE_MONTH_DATE:
year = test_time_year;
end_time = calculate_time_from_day_of_month(year, temp_daterange->emon, temp_daterange->emday);
/* advance a year if necessary: august 2 - february 5 */
if(end_time < start_time) {
year++;
end_time = calculate_time_from_day_of_month(year, temp_daterange->emon, temp_daterange->emday);
}
break;
case DATERANGE_MONTH_DAY:
end_time = calculate_time_from_day_of_month(test_time_year, test_time_mon, temp_daterange->emday);
break;
case DATERANGE_MONTH_WEEK_DAY:
year = test_time_year;
end_time = calculate_time_from_weekday_of_month(year, temp_daterange->emon, temp_daterange->ewday, temp_daterange->ewday_offset);
/* advance a year if necessary: thursday 2 august - monday 3 february */
if(end_time < start_time) {
year++;
end_time = calculate_time_from_weekday_of_month(year, temp_daterange->emon, temp_daterange->ewday, temp_daterange->ewday_offset);
}
break;
case DATERANGE_WEEK_DAY:
end_time = calculate_time_from_weekday_of_month(test_time_year, test_time_mon, temp_daterange->ewday, temp_daterange->ewday_offset);
break;
default:
continue;
break;
}
#ifdef TEST_TIMEPERIODS_A
printf("START: %llu = %s", (unsigned long long)start_time, ctime(&start_time));
printf("END: %llu = %s", (unsigned long long)end_time, ctime(&end_time));
#endif
/* start date was bad, so skip this date range */
if((unsigned long)start_time == 0L)
continue;
/* end date was bad - see if we can handle the error */
if((unsigned long)end_time == 0L) {
switch(daterange_type) {
case DATERANGE_CALENDAR_DATE:
continue;
break;
case DATERANGE_MONTH_DATE:
/* end date can't be helped, so skip it */
if(temp_daterange->emday < 0)
continue;
/* else end date slipped past end of month, so use last day of month as end date */
/* use same year calculated above */
end_time = calculate_time_from_day_of_month(year, temp_daterange->emon, -1);
break;
case DATERANGE_MONTH_DAY:
/* end date can't be helped, so skip it */
if(temp_daterange->emday < 0)
continue;
/* else end date slipped past end of month, so use last day of month as end date */
end_time = calculate_time_from_day_of_month(test_time_year, test_time_mon, -1);
break;
case DATERANGE_MONTH_WEEK_DAY:
/* end date can't be helped, so skip it */
if(temp_daterange->ewday_offset < 0)
continue;
/* else end date slipped past end of month, so use last day of month as end date */
/* use same year calculated above */
end_time = calculate_time_from_day_of_month(year, test_time_mon, -1);
break;
case DATERANGE_WEEK_DAY:
/* end date can't be helped, so skip it */
if(temp_daterange->ewday_offset < 0)
continue;
/* else end date slipped past end of month, so use last day of month as end date */
end_time = calculate_time_from_day_of_month(test_time_year, test_time_mon, -1);
break;
default:
continue;
break;
}
}
/* calculate skip date start (and end) */
if(temp_daterange->skip_interval > 1) {
/* skip start date must be before test time */
if(start_time > test_time)
continue;
/* check if interval is across dlst change and gets the compensation */
shift = get_dst_shift(&start_time, &midnight);
/* how many days have passed between skip start date and test time? */
days = (shift + (unsigned long)midnight - (unsigned long)start_time) / (3600 * 24);
/* if test date doesn't fall on a skip interval day, bail out early */
if((days % temp_daterange->skip_interval) != 0)
continue;
/* use midnight of test date as start time */
else
start_time = midnight;
/* if skipping range has no end, use test date as end */
if((daterange_type == DATERANGE_CALENDAR_DATE) && (is_daterange_single_day(temp_daterange) == TRUE))
end_time = midnight;
}
#ifdef TEST_TIMEPERIODS_A
printf("NEW START: %llu = %s", (unsigned long long)start_time, ctime(&start_time));
printf("NEW END: %llu = %s", (unsigned long long)end_time, ctime(&end_time));
printf("%d DAYS PASSED\n", days);
printf("DLST SHIFT: %i\n", shift);
#endif
/* time falls inside the range of days
* end time < start_time when range covers end-of-$unit
* (fe. end-of-month) */
if((midnight + 84800UL >= start_time && (midnight <= end_time || start_time > end_time)) || (midnight <= end_time && start_time > end_time)) {
#ifdef TEST_TIMEPERIODS_A
printf("(MATCH)\n");
#endif
return temp_daterange->times;
}
}
}
return tperiod->days[test_time_wday];
}
/* see if the specified time falls into a valid time range in the given time period */
int check_time_against_period(time_t test_time, timeperiod *tperiod) {
timerange *temp_timerange = NULL;
timeperiodexclusion *temp_timeperiodexclusion = NULL;
struct tm *t, tm_s;
time_t midnight = (time_t)0L;
time_t day_range_start = (time_t)0L;
time_t day_range_end = (time_t)0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "check_time_against_period()\n");
t = localtime_r((time_t *)&test_time, &tm_s);
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
midnight = mktime(t);
/* if no period was specified, assume the time is good */
if(tperiod == NULL)
return OK;
for(temp_timeperiodexclusion = tperiod->exclusions; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) {
if(check_time_against_period(test_time, temp_timeperiodexclusion->timeperiod_ptr) == OK) {
return ERROR;
}
}
for(temp_timerange = _get_matching_timerange(test_time, tperiod); temp_timerange != NULL; temp_timerange = temp_timerange->next) {
day_range_start = (time_t)(midnight + temp_timerange->range_start);
day_range_end = (time_t)(midnight + temp_timerange->range_end);
if(test_time >= day_range_start && test_time <= day_range_end)
return OK;
}
return ERROR;
}
/*#define TEST_TIMEPERIODS_B 1*/
void _get_next_valid_time(time_t pref_time, time_t *valid_time, timeperiod *tperiod);
static void _get_next_invalid_time(time_t pref_time, time_t *invalid_time, timeperiod *tperiod) {
timeperiodexclusion *temp_timeperiodexclusion = NULL;
int depth = 0;
int max_depth = 300; // commonly roughly equal to "days in the future"
struct tm *t, tm_s;
time_t earliest_time = pref_time;
time_t last_earliest_time = 0;
time_t midnight = (time_t)0L;
time_t day_range_start = (time_t)0L;
time_t day_range_end = (time_t)0L;
/* if no period was specified, assume the time is good */
if(tperiod == NULL) {
*invalid_time = pref_time;
return;
}
while (earliest_time != last_earliest_time && depth < max_depth) {
time_t potential_time = 0;
depth++;
last_earliest_time = earliest_time;
t = localtime_r((time_t *)&earliest_time, &tm_s);
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
midnight = mktime(t);
timerange *temp_timerange = _get_matching_timerange(earliest_time, tperiod);
for(; temp_timerange != NULL; temp_timerange = temp_timerange->next) {
/* ranges with start/end of zero mean exclude this day */
if(temp_timerange->range_start == 0 && temp_timerange->range_end == 0)
continue;
day_range_start = (time_t)(midnight + temp_timerange->range_start);
day_range_end = (time_t)(midnight + temp_timerange->range_end);
#ifdef TEST_TIMEPERIODS_B
printf(" INVALID RANGE START: %lu (%lu) = %s", temp_timerange->range_start, (unsigned long)day_range_start, ctime(&day_range_start));
printf(" INVALID RANGE END: %lu (%lu) = %s", temp_timerange->range_end, (unsigned long)day_range_end, ctime(&day_range_end));
#endif
if(day_range_start <= earliest_time && day_range_end > earliest_time)
potential_time = day_range_end + 60;
else
potential_time = earliest_time;
if(potential_time > earliest_time) {
earliest_time = potential_time;
#ifdef TEST_TIMEPERIODS_B
printf(" EARLIEST INVALID TIME: %llu = %s", (unsigned long long)earliest_time, ctime(&earliest_time));
#endif
}
}
for(temp_timeperiodexclusion = tperiod->exclusions; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) {
_get_next_valid_time(last_earliest_time, &potential_time, temp_timeperiodexclusion->timeperiod_ptr);
if (potential_time + 60 < earliest_time)
earliest_time = potential_time + 60;
}
}
#ifdef TEST_TIMEPERIODS_B
printf(" FINAL EARLIEST INVALID TIME: %llu = %s", (unsigned long long)earliest_time, ctime(&earliest_time));
#endif
if (depth == max_depth)
*invalid_time = pref_time;
else
*invalid_time = earliest_time;
}
/* Separate this out from public get_next_valid_time for testing */
void _get_next_valid_time(time_t pref_time, time_t *valid_time, timeperiod *tperiod) {
timeperiodexclusion *temp_timeperiodexclusion = NULL;
int depth = 0;
int max_depth = 300; // commonly roughly equal to "days in the future"
time_t earliest_time = pref_time;
time_t last_earliest_time = 0;
struct tm *t, tm_s;
time_t midnight = (time_t)0L;
time_t day_range_start = (time_t)0L;
time_t day_range_end = (time_t)0L;
int have_earliest_time = FALSE;
/* if no period was specified, assume the time is good */
if(tperiod == NULL) {
*valid_time = pref_time;
return;
}
while (earliest_time != last_earliest_time && depth < max_depth) {
time_t potential_time = 0;
have_earliest_time = FALSE;
depth++;
last_earliest_time = earliest_time;
t = localtime_r((time_t *)&earliest_time, &tm_s);
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
midnight = mktime(t);
timerange *temp_timerange = _get_matching_timerange(earliest_time, tperiod);
#ifdef TEST_TIMEPERIODS_B
printf(" RANGE START: %lu\n", temp_timerange ? temp_timerange->range_start : 0);
printf(" RANGE END: %lu\n", temp_timerange ? temp_timerange->range_end : 0);
#endif
for(; temp_timerange != NULL; temp_timerange = temp_timerange->next) {
/* ranges with start/end of zero mean exclude this day */
if(temp_timerange->range_start == 0 && temp_timerange->range_end == 0)
continue;
day_range_start = (time_t)(midnight + temp_timerange->range_start);
day_range_end = (time_t)(midnight + temp_timerange->range_end);
#ifdef TEST_TIMEPERIODS_B
printf(" RANGE START: %lu (%lu) = %s", temp_timerange->range_start, (unsigned long)day_range_start, ctime(&day_range_start));
printf(" RANGE END: %lu (%lu) = %s", temp_timerange->range_end, (unsigned long)day_range_end, ctime(&day_range_end));
#endif
/* range is out of bounds */
if(day_range_end < last_earliest_time)
continue;
/* preferred time occurs before range start, so use range start time as earliest potential time */
if(day_range_start >= last_earliest_time)
potential_time = day_range_start;
/* preferred time occurs between range start/end, so use preferred time as earliest potential time */
else if(day_range_end >= last_earliest_time)
potential_time = last_earliest_time;
/* is this the earliest time found thus far? */
if(have_earliest_time == FALSE || potential_time < earliest_time) {
earliest_time = potential_time;
#ifdef TEST_TIMEPERIODS_B
printf(" EARLIEST TIME: %llu = %s", (unsigned long long)earliest_time, ctime(&earliest_time));
#endif
}
have_earliest_time = TRUE;
}
if (have_earliest_time == FALSE) {
earliest_time = midnight + 86400;
} else {
for(temp_timeperiodexclusion = tperiod->exclusions; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) {
_get_next_invalid_time(earliest_time, &earliest_time, temp_timeperiodexclusion->timeperiod_ptr);
#ifdef TEST_TIMEPERIODS_B
printf(" FINAL EARLIEST TIME: %llu = %s", (unsigned long long)earliest_time, ctime(&earliest_time));
#endif
}
}
}
if (depth == max_depth)
*valid_time = pref_time;
else
*valid_time = earliest_time;
}
/* given a preferred time, get the next valid time within a time period */
void get_next_valid_time(time_t pref_time, time_t *valid_time, timeperiod *tperiod) {
time_t current_time = (time_t)0L;
log_debug_info(DEBUGL_FUNCTIONS, 0, "get_next_valid_time()\n");
/* get time right now, preferred time must be now or in the future */
time(¤t_time);
pref_time = (pref_time < current_time) ? current_time : pref_time;
_get_next_valid_time(pref_time, valid_time, tperiod);
}
/* Given the next valid time in a timeperiod, the timeperiod itself, and the normal rescheduling window, */
/* return the next check time */
time_t reschedule_within_timeperiod(time_t starting_valid_time, timeperiod* check_period_ptr, time_t check_window) {
log_debug_info(DEBUGL_FUNCTIONS, 0, "reschedule_within_timeperiod");
/* First, find the next time that is outside the timeperiod */
time_t ending_valid_time;
_get_next_invalid_time(starting_valid_time, &ending_valid_time, check_period_ptr);
/* _get_next_invalid_time returns the first invalid minute. The maximum allowable should be a minute earlier */
ending_valid_time -= 60;
/* Determine whether the next invalid time or the outside of the check_window is closer */
time_t max_nudge = ending_valid_time - starting_valid_time;
/* max_nudge will be less than zero when there's no 'invalid' time */
/* Otherwise, use the closest of the two times to reschedule the check */
if (max_nudge <= 0 || max_nudge > check_window) {
log_debug_info(DEBUGL_CHECKS, 0, "Using raw check_window instead of timeperiod for scheduling \n");
max_nudge = check_window;
}
/* Reschedule within the smaller range */
return starting_valid_time + ranged_urand(0, max_nudge);
}
/* tests if a date range covers just a single day */
int is_daterange_single_day(daterange *dr) {
if(dr == NULL)
return FALSE;
if(dr->syear != dr->eyear)
return FALSE;
if(dr->smon != dr->emon)
return FALSE;
if(dr->smday != dr->emday)
return FALSE;
if(dr->swday != dr->ewday)
return FALSE;
if(dr->swday_offset != dr->ewday_offset)
return FALSE;
return TRUE;
}
/* returns a time (midnight) of particular (3rd, last) day in a given month */
time_t calculate_time_from_day_of_month(int year, int month, int monthday) {
time_t midnight;
int day = 0;
struct tm t;
#ifdef TEST_TIMEPERIODS
printf("YEAR: %d, MON: %d, MDAY: %d\n", year, month, monthday);
#endif
/* positive day (3rd day) */
if(monthday > 0) {
t.tm_sec = 0;
t.tm_min = 0;
t.tm_hour = 0;
t.tm_year = year;
t.tm_mon = month;
t.tm_mday = monthday;
t.tm_isdst = -1;
midnight = mktime(&t);
#ifdef TEST_TIMEPERIODS
printf("MIDNIGHT CALC: %s", ctime(&midnight));
#endif
/* if we rolled over to the next month, time is invalid */
/* assume the user's intention is to keep it in the current month */
if(t.tm_mon != month)
midnight = (time_t)0L;
}
/* negative offset (last day, 3rd to last day) */
else {
/* find last day in the month */
day = 32;
do {
/* back up a day */
day--;
/* make the new time */
t.tm_sec = 0;
t.tm_min = 0;
t.tm_hour = 0;
t.tm_mon = month;
t.tm_year = year;
t.tm_mday = day;
t.tm_isdst = -1;
midnight = mktime(&t);
}
while(t.tm_mon != month);
/* now that we know the last day, back up more */
/* make the new time */
t.tm_mon = month;
t.tm_year = year;
/* -1 means last day of month, so add one to to make this correct - Mike Bird */
t.tm_mday += (monthday < -30) ? -30 : monthday + 1;
t.tm_isdst = -1;
midnight = mktime(&t);
/* if we rolled over to the previous month, time is invalid */
/* assume the user's intention is to keep it in the current month */
if(t.tm_mon != month)
midnight = (time_t)0L;
}
return midnight;
}
/* returns a time (midnight) of particular (3rd, last) weekday in a given month */
time_t calculate_time_from_weekday_of_month(int year, int month, int weekday, int weekday_offset) {
time_t midnight;
int days = 0;
int weeks = 0;
struct tm t;
t.tm_sec = 0;
t.tm_min = 0;
t.tm_hour = 0;
t.tm_year = year;
t.tm_mon = month;
t.tm_mday = 1;
t.tm_isdst = -1;
midnight = mktime(&t);
/* how many days must we advance to reach the first instance of the weekday this month? */
days = weekday - (t.tm_wday);
if(days < 0)
days += 7;
/* positive offset (3rd thursday) */
if(weekday_offset > 0) {
/* how many weeks must we advance (no more than 5 possible) */
weeks = (weekday_offset > 5) ? 5 : weekday_offset;
days += ((weeks - 1) * 7);
/* make the new time */
t.tm_mon = month;
t.tm_year = year;
t.tm_mday = days + 1;
t.tm_isdst = -1;
midnight = mktime(&t);
/* if we rolled over to the next month, time is invalid */
/* assume the user's intention is to keep it in the current month */
if(t.tm_mon != month)
midnight = (time_t)0L;
}
/* negative offset (last thursday, 3rd to last tuesday) */
else {
/* find last instance of weekday in the month */
days += (5 * 7);
do {
/* back up a week */
days -= 7;
/* make the new time */
t.tm_mon = month;
t.tm_year = year;
t.tm_mday = days + 1;
t.tm_isdst = -1;
midnight = mktime(&t);
}
while(t.tm_mon != month);
/* now that we know the last instance of the weekday, back up more */
weeks = (weekday_offset < -5) ? -5 : weekday_offset;
days = ((weeks + 1) * 7);
/* make the new time */
t.tm_mon = month;
t.tm_year = year;
t.tm_mday += days;
t.tm_isdst = -1;
midnight = mktime(&t);
/* if we rolled over to the previous month, time is invalid */
/* assume the user's intention is to keep it in the current month */
if(t.tm_mon != month)
midnight = (time_t)0L;
}
return midnight;
}
/* get the next time to schedule a log rotation */
time_t get_next_log_rotation_time(void) {
time_t current_time;
struct tm *t, tm_s;
int is_dst_now = FALSE;
time_t run_time;
time(¤t_time);
t = localtime_r(¤t_time, &tm_s);
t->tm_min = 0;
t->tm_sec = 0;
is_dst_now = (t->tm_isdst > 0) ? TRUE : FALSE;
switch(log_rotation_method) {
case LOG_ROTATION_HOURLY:
t->tm_hour++;
run_time = mktime(t);
break;
case LOG_ROTATION_DAILY:
t->tm_mday++;
t->tm_hour = 0;
run_time = mktime(t);
break;
case LOG_ROTATION_WEEKLY:
t->tm_mday += (7 - t->tm_wday);
t->tm_hour = 0;
run_time = mktime(t);
break;
case LOG_ROTATION_MONTHLY:
default:
t->tm_mon++;
t->tm_mday = 1;
t->tm_hour = 0;
run_time = mktime(t);
break;
}
if(is_dst_now == TRUE && t->tm_isdst == 0)
run_time += 3600;
return run_time;
}
/******************************************************************/
/******************** SIGNAL HANDLER FUNCTIONS ********************/
/******************************************************************/
/* trap signals so we can exit gracefully */
void setup_sighandler(void) {
#ifdef HAVE_SIGACTION
struct sigaction sig_action;
#endif
/* reset the shutdown flag */
sigshutdown = FALSE;
/* remove buffering from stderr, stdin, and stdout */
setbuf(stdin, (char *)NULL);
setbuf(stdout, (char *)NULL);
setbuf(stderr, (char *)NULL);
/* initialize signal handling */
#ifdef HAVE_SIGACTION
sig_action.sa_sigaction = NULL;
sig_action.sa_handler = SIG_IGN;
sigemptyset(&sig_action.sa_mask);
sig_action.sa_flags = 0;
sigaction(SIGPIPE, &sig_action, NULL);
sig_action.sa_handler = sighandler;
sigfillset(&sig_action.sa_mask);
sig_action.sa_flags = SA_NODEFER|SA_RESTART;
sigaction(SIGQUIT, &sig_action, NULL);
sigaction(SIGTERM, &sig_action, NULL);
sigaction(SIGHUP, &sig_action, NULL);
if(daemon_dumps_core == FALSE && daemon_mode == TRUE)
sigaction(SIGSEGV, &sig_action, NULL);
sig_action.sa_flags = SA_NOCLDWAIT;
#else /* HAVE_SIGACTION */
signal(SIGPIPE, SIG_IGN);
signal(SIGQUIT, sighandler);
signal(SIGTERM, sighandler);
signal(SIGHUP, sighandler);
if(daemon_dumps_core == FALSE && daemon_mode == TRUE)
signal(SIGSEGV, sighandler);
#endif /* HAVE_SIGACTION */
return;
}
/* reset signal handling... */
void reset_sighandler(void) {
/* set signal handling to default actions */
#ifdef HAVE_SIGACTION
struct sigaction sig_action;
sig_action.sa_sigaction = NULL;
sig_action.sa_handler = SIG_DFL;
sigemptyset(&sig_action.sa_mask);
sig_action.sa_flags = 0;
sigaction(SIGQUIT, &sig_action, NULL);
sigaction(SIGTERM, &sig_action, NULL);
sigaction(SIGHUP, &sig_action, NULL);
sigaction(SIGSEGV, &sig_action, NULL);
sigaction(SIGPIPE, &sig_action, NULL);
sigaction(SIGXFSZ, &sig_action, NULL);
#else /* HAVE_SIGACTION */
signal(SIGQUIT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGHUP, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
signal(SIGXFSZ, SIG_DFL);
#endif /* HAVE_SIGACTION */
return;
}
/* handle signals */
void sighandler(int sig) {
const 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 x = 0;
/* if shutdown is already true, we're in a signal trap loop! */
/* changed 09/07/06 to only exit on segfaults */
if(sigshutdown == TRUE && sig == SIGSEGV)
exit(ERROR);
caught_signal = TRUE;
if(sig < 0)
sig = -sig;
for(x = 0; sigs[x] != (char *)NULL; x++);
sig %= x;
sig_id = sig;
/* we received a SIGHUP, so restart... */
if(sig == SIGHUP)
sigrestart = TRUE;
/* else begin shutting down... */
else if(sig < 16) {
logit(NSLOG_PROCESS_INFO, TRUE, "Caught SIG%s, shutting down...\n", sigs[sig]);
sigshutdown = TRUE;
}
return;
}
/* handle timeouts when executing commands via my_system_r() */
void my_system_sighandler(int sig) {
/* force the child process to exit... */
_exit(STATE_CRITICAL);
}
/* Handle the SIGXFSZ signal. A SIGXFSZ signal is received when a file exceeds
the maximum allowable size either as dictated by the fsize parameter in
/etc/security/limits.conf (ulimit -f) or by the maximum size allowed by
the filesystem */
void handle_sigxfsz(int sig) {
static time_t lastlog_time = (time_t)0; /* Save the last log time so we
don't log too often. */
unsigned long log_interval = 300; /* How frequently to log messages
about receiving the signal */
struct rlimit rlim;
time_t now;
char *files[] = {
log_file,
debug_file,
host_perfdata_file,
service_perfdata_file,
object_cache_file,
object_precache_file,
status_file,
retention_file,
};
int x;
char **filep;
long long size;
long long max_size = 0LL;
char *max_name = NULL;
if(SIGXFSZ == sig) { /* Make sure we're handling the correct signal */
/* Check the current time and if less time has passed since the last
time the signal was received, ignore it */
time(&now);
if((unsigned long)(now - lastlog_time) < log_interval) return;
/* Get the current file size limit */
if(getrlimit(RLIMIT_FSIZE, &rlim) != 0) {
/* Attempt to log the error, realizing that the logging may fail
if it is the log file that is over the size limit. */
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Unable to determine current resource limits: %s\n",
strerror(errno));
}
/* Try to figure out which file caused the signal and react
appropriately */
for(x = 0, filep = files; x < (sizeof(files) / sizeof(files[0]));
x++, filep++) {
if((*filep != NULL) && strcmp(*filep, "/dev/null")) {
if((size = check_file_size(*filep, 1024, rlim)) == -1) {
lastlog_time = now;
return;
}
else if(size > max_size) {
max_size = size;
max_name = log_file;
}
}
}
if((max_size > 0) && (max_name != NULL)) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "SIGXFSZ received because a "
"file's size may have exceeded the file size limits of "
"the filesystem. The largest file checked, '%s', has a "
"size of %lld bytes", max_name, max_size);
}
else {
logit(NSLOG_RUNTIME_ERROR, TRUE, "SIGXFSZ received but unable to "
"determine which file may have caused it.");
}
}
return;
}
/* Checks a file to determine whether it exceeds resource limit imposed
limits. Returns the file size if file is OK, 0 if it's status could not
be determined, or -1 if not OK. fudge is the fudge factor (in bytes) for
checking the file size */
static long long check_file_size(char *path, unsigned long fudge,
struct rlimit rlim) {
struct stat status;
/* Make sure we were passed a legitimate file path */
if(NULL == path) {
return 0;
}
/* Get the status of the file */
if(stat(path, &status) == 0) {
/* Make sure it is a file */
if(S_ISREG(status.st_mode)) {
/* If the file size plus the fudge factor exceeds the
current resource limit imposed size limit, log an error */
if(status.st_size + fudge > rlim.rlim_cur) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Size of file '%s' (%llu) "
"exceeds (or nearly exceeds) size imposed by resource "
"limits (%llu). Consider increasing limits with "
"ulimit(1).\n", path,
(unsigned long long)status.st_size,
(unsigned long long)rlim.rlim_cur);
return -1;
}
else {
return status.st_size;
}
}
else {
return 0;
}
}
else {
/* If we could not determine the file status, log an error message */
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Unable to determine status of file %s: %s\n",
log_file, strerror(errno));
return 0;
}
}
/******************************************************************/
/************************ DAEMON FUNCTIONS ************************/
/******************************************************************/
int daemon_init(void)
{
pid_t pid = -1;
int pidno = 0;
int lockfile = 0;
int val = 0;
char buf[256] = { 0 };
char *homedir = NULL;
char *cp = NULL;
struct flock lock;
#ifdef RLIMIT_CORE
struct rlimit limit;
#endif
/* change working directory. scuttle home if we're dumping core */
if (daemon_dumps_core == TRUE) {
homedir = getenv("HOME");
if (homedir && *homedir) {
chdir(homedir);
}
else if (log_file && *log_file) {
homedir = strdup(log_file);
cp = strrchr(homedir, '/');
if (cp) {
*cp = '\0';
}
else {
strcpy(homedir, "/");
}
chdir(homedir);
free(homedir);
} else {
chdir("/");
}
}
umask(S_IWGRP | S_IWOTH);
/* close existing stdin, stdout, stderr */
close(0);
close(1);
close(2);
/* THIS HAS TO BE DONE TO AVOID PROBLEMS WITH STDERR BEING REDIRECTED TO SERVICE MESSAGE PIPE! */
/* re-open stdin, stdout, stderr with known values */
open("/dev/null", O_RDONLY);
open("/dev/null", O_WRONLY);
open("/dev/null", O_WRONLY);
lockfile = open(lock_file, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
if (lockfile < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Failed to obtain lock on file %s: %s\n", lock_file, strerror(errno));
logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, TRUE,
"Bailing out due to errors encountered while attempting to daemonize... (PID=%d)", (int)getpid());
cleanup();
exit(ERROR);
}
/* see if we can read the contents of the lockfile */
val = read(lockfile, buf, (size_t)10);
if (val < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Lockfile exists but cannot be read");
cleanup();
exit(ERROR);
}
/* we read something - check the PID */
if (val > 0) {
val = sscanf(buf, "%d", &pidno);
if (val < 1) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Lockfile '%s' does not contain a valid PID (%s)", lock_file, buf);
cleanup();
exit(ERROR);
}
}
pid = (pid_t)pidno;
if (val == 1) {
/* check for SIGHUP */
if (pid == getpid()) {
close(lockfile);
return OK;
}
/* send a signal to see if pid alive */
val = kill(pid, 0);
/* is this process alive? */
if (val == 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Lockfile '%s' contains PID of running process (%d)", lock_file, pidno);
cleanup();
exit(ERROR);
}
}
/* exit on errors... */
pid = fork();
if (pid < 0) {
return(ERROR);
}
/* parent process goes away.. */
else if (pid != 0) {
iobroker_destroy(nagios_iobs, IOBROKER_CLOSE_SOCKETS);
cleanup();
cleanup_performance_data();
cleanup_downtime_data();
my_free(lock_file);
my_free(config_file);
my_free(config_file_dir);
my_free(nagios_binary_path);
exit(OK);
}
/* child continues... */
/* child becomes session leader... */
setsid();
/* place a file lock on the lock file */
lock.l_type = F_WRLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
val = fcntl(lockfile, F_SETLK, &lock);
if (val < 0) {
if (errno == EACCES || errno == EAGAIN) {
fcntl(lockfile, F_GETLK, &lock);
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Lockfile '%s' looks like its already held by another instance of Nagios (PID %d). Bailing out...",
lock_file, (int)lock.l_pid);
}
else {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"Cannot lock lockfile '%s': %s. Bailing out...",
lock_file, strerror(errno));
}
cleanup();
exit(ERROR);
}
/* prevent daemon from dumping a core file... */
#ifdef RLIMIT_CORE
if(daemon_dumps_core == FALSE) {
getrlimit(RLIMIT_CORE, &limit);
limit.rlim_cur = 0;
setrlimit(RLIMIT_CORE, &limit);
}
#endif
/* write PID to lockfile... */
lseek(lockfile, 0, SEEK_SET);
ftruncate(lockfile, 0);
sprintf(buf, "%d\n", (int)getpid());
write(lockfile, buf, strlen(buf));
/* make sure lock file stays open while program is executing... */
val = fcntl(lockfile, F_GETFD, 0);
val |= FD_CLOEXEC;
fcntl(lockfile, F_SETFD, val);
return OK;
}
/******************************************************************/
/*********************** SECURITY FUNCTIONS ***********************/
/******************************************************************/
/* drops privileges */
int drop_privileges(char *user, char *group) {
uid_t uid = -1;
gid_t gid = -1;
struct group *grp = NULL;
struct passwd *pw = NULL;
int result = OK;
#ifdef HAVE_SYS_RESOURCE_H
struct rlimit rl;
#endif
/* only drop privileges if we're running as root, so we don't interfere with being debugged while running as some random user */
if(getuid() != 0)
return OK;
/* set effective group ID */
if(group != NULL) {
/* see if this is a group name */
if(strspn(group, "0123456789") < strlen(group)) {
grp = (struct group *)getgrnam(group);
if(grp != NULL)
gid = (gid_t)(grp->gr_gid);
else
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not get group entry for '%s'", group);
}
/* else we were passed the GID */
else
gid = (gid_t)atoi(group);
}
/* set effective user ID */
if(user != NULL) {
/* see if this is a user name */
if(strspn(user, "0123456789") < strlen(user)) {
pw = (struct passwd *)getpwnam(user);
if(pw != NULL)
uid = (uid_t)(pw->pw_uid);
else
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not get passwd entry for '%s'", user);
}
/* else we were passed the UID */
else
uid = (uid_t)atoi(user);
}
/* now that we know what to change to, we fix log file permissions */
fix_log_file_owner(uid, gid);
/* set effective group ID if other than current EGID */
if(gid != getegid()) {
if(setgid(gid) == -1) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not set effective GID=%d", (int)gid);
result = ERROR;
}
}
#ifdef HAVE_INITGROUPS
if(uid != geteuid()) {
/* initialize supplementary groups */
if(initgroups(user, gid) == -1) {
if(errno == EPERM)
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Unable to change supplementary groups using initgroups() -- I hope you know what you're doing");
else {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Possibly root user failed dropping privileges with initgroups()");
return ERROR;
}
}
}
#endif
#ifdef HAVE_SYS_RESOURCE_H
if (result == OK && daemon_dumps_core == TRUE) {
rl.rlim_cur = RLIM_INFINITY;
rl.rlim_max = RLIM_INFINITY;
setrlimit(RLIMIT_CORE, &rl);
}
#endif
if(setuid(uid) == -1) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not set effective UID=%d", (int)uid);
result = ERROR;
}
#ifdef HAVE_SYS_PRCTL_H
if (result == OK && daemon_dumps_core == TRUE) {
if (prctl(PR_SET_DUMPABLE, 1))
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Call to prctl(PR_SET_DUMPABLE, 1) failed with error %d", errno);
}
#endif
return result;
}
/******************************************************************/
/************************* IPC FUNCTIONS **************************/
/******************************************************************/
/* processes files in the check result queue directory */
int process_check_result_queue(char *dirname) {
char file[MAX_FILENAME_LENGTH];
DIR *dirp = NULL;
struct dirent *dirfile = NULL;
register int x = 0;
struct stat stat_buf;
struct stat ok_stat_buf;
char *temp_buffer = NULL;
int result = OK, check_result_files = 0;
time_t start;
/* make sure we have what we need */
if(dirname == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: No check result queue directory specified.\n");
return ERROR;
}
/* open the directory for reading */
if((dirp = opendir(dirname)) == NULL) {
logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not open check result queue directory '%s' for reading.\n", dirname);
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 0, "Starting to read check result queue '%s'...\n", dirname);
start = time(NULL);
/* process all files in the directory... */
while((dirfile = readdir(dirp)) != NULL) {
/* bail out if we encountered a signal */
if (sigshutdown == TRUE || sigrestart == TRUE) {
log_debug_info(DEBUGL_CHECKS, 0, "Breaking out of check result reaper: signal encountered\n");
break;
}
/* break out if we've been here too long */
if (start + max_check_reaper_time < time(NULL)) {
log_debug_info(DEBUGL_CHECKS, 0, "Breaking out of check result reaper: max time (%ds) exceeded\n", max_check_reaper_time);
break;
}
/* create /path/to/file */
snprintf(file, sizeof(file), "%s/%s", dirname, dirfile->d_name);
file[sizeof(file) - 1] = '\x0';
/* process this if it's a check result file...
remember it needs to be in the format of
filename = cXXXXXX
where X is any integer
there must also be a filename present
okfile = cXXXXXX.ok
where the XXXXXX is the same as in the filename */
x = strlen(dirfile->d_name);
if(x == 7 && dirfile->d_name[0] == 'c') {
if(stat(file, &stat_buf) == -1) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not stat() check result file '%s'.\n", file);
continue;
}
/* we only care about real files */
if (!S_ISREG(stat_buf.st_mode))
continue;
/* at this point we have a regular file... */
/* if the file is too old, we delete it */
if (stat_buf.st_mtime + max_check_result_file_age < time(NULL)) {
if (delete_check_result_file(file) != OK
&& delete_check_result_file(dirfile->d_name) != OK)
logit(NSLOG_RUNTIME_WARNING, TRUE, "Error: Unable to delete '%s' or '%s'!", file, dirfile->d_name);
continue;
}
/* can we find the associated ok-to-go file ? */
asprintf(&temp_buffer, "%s.ok", file);
result = stat(temp_buffer, &ok_stat_buf);
my_free(temp_buffer);
if(result == -1)
continue;
/* process the file */
result = process_check_result_file(file);
/* break out if we encountered an error */
if(result == ERROR) {
log_debug_info(DEBUGL_CHECKS, 0, "Encountered an error processing the check result file\n");
break;
}
check_result_files++;
}
}
closedir(dirp);
log_debug_info(DEBUGL_CHECKS, 0, "Finished reaping %d check results\n", check_result_files);
return check_result_files;
}
int process_check_result(check_result *cr)
{
const char *source_name;
if (!cr)
return ERROR;
source_name = check_result_source(cr);
if (cr->object_check_type == SERVICE_CHECK) {
service *svc;
svc = find_service(cr->host_name, cr->service_description);
if (!svc) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Got check result for service '%s' on host '%s'. Unable to find service\n",
cr->service_description, cr->host_name);
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 2, "Processing check result for service '%s' on host '%s'\n",
svc->description, svc->host_name);
svc->check_source = source_name;
return handle_async_service_check_result(svc, cr);
}
if (cr->object_check_type == HOST_CHECK) {
host *hst;
hst = find_host(cr->host_name);
if (!hst) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Got host checkresult for '%s', but no such host can be found\n", cr->host_name);
return ERROR;
}
log_debug_info(DEBUGL_CHECKS, 2, "Processing check result for host '%s'\n", hst->name);
hst->check_source = source_name;
return handle_async_host_check_result(hst, cr);
}
/* We should never end up here */
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unknown object check type for checkresult: %d; (host_name: %s; service_description: %s)\n",
cr->object_check_type,
cr->host_name ? cr->host_name : "(null)",
cr->service_description ? cr->service_description : "(null)");
return ERROR;
}
/* Unescapes newlines in a string. Declared here for now as it's not used
* elsewhere. */
/* static char *unescape_check_result_file_output(char*); */
/* reads check result(s) from a file */
int process_check_result_file(char *fname)
{
mmapfile *thefile = NULL;
char *input = NULL;
char *var = NULL;
char *val = NULL;
char *vartok = NULL;
char *valtok = NULL;
char *v1 = NULL, *v2 = NULL;
time_t current_time;
check_result cr;
if (fname == NULL) {
return ERROR;
}
init_check_result(&cr);
cr.engine = &nagios_spool_check_engine;
time(¤t_time);
log_debug_info(DEBUGL_CHECKS, 1, "Processing check result file: '%s'\n", fname);
/* open the file for reading */
thefile = mmap_fopen(fname);
if (thefile == NULL) {
/* try removing the file - zero length files can't be mmap()'ed, so it might exist */
log_debug_info(DEBUGL_CHECKS, 1, "Failed to open check result file for reading: '%s'\n", fname);
delete_check_result_file(fname);
return ERROR;
}
/* read in all lines from the file */
while(1) {
/* free memory */
my_free(input);
my_free(var);
my_free(val);
/* read the next line */
input = mmap_fgets_multiline(thefile);
if (input == NULL) {
break;
}
/* skip comments */
if (input[0] == '#') {
continue;
}
/* empty line indicates end of record */
else if (input[0] == '\n') {
/* do we have the minimum amount of data? */
if (cr.host_name != NULL && cr.output != NULL) {
/* process the check result */
process_check_result(&cr);
}
/* cleanse for next check result */
free_check_result(&cr);
init_check_result(&cr);
cr.output_file = fname;
}
vartok = my_strtok_with_free(input, "=", FALSE);
if (vartok == NULL) {
continue;
}
valtok = my_strtok_with_free(NULL, "\n", FALSE);
if (valtok == NULL) {
vartok = my_strtok_with_free(NULL, NULL, TRUE);
continue;
}
/* clean up some memory before we go any further */
var = strdup(vartok);
val = strdup(valtok);
vartok = my_strtok_with_free(NULL, NULL, TRUE);
log_debug_info(DEBUGL_CHECKS, 2, " * %25s: %s\n", var, val);
/* found the file time */
if (!strcmp(var, "file_time")) {
/* file is too old - ignore check results it contains and delete it */
/* this will only work as intended if file_time comes before check results */
if ((max_check_result_file_age > 0)
&& (current_time - (strtoul(val, NULL, 0)) > max_check_result_file_age)) {
log_debug_info(DEBUGL_CHECKS, 1,
"Skipping check_result because file_time is %s and max cr file age is %lu",
val, max_check_result_file_age);
break;
}
}
/* else we have check result data */
else {
if (!strcmp(var, "host_name")) {
cr.host_name = (char *)strdup(val);
}
else if (!strcmp(var, "service_description")) {
cr.service_description = (char *)strdup(val);
cr.object_check_type = SERVICE_CHECK;
}
else if (!strcmp(var, "check_type")) {
cr.check_type = atoi(val);
}
else if (!strcmp(var, "check_options")) {
cr.check_options = atoi(val);
}
else if (!strcmp(var, "scheduled_check")) {
cr.scheduled_check = atoi(val);
}
else if (!strcmp(var, "reschedule_check")) {
cr.reschedule_check = atoi(val);
}
else if (!strcmp(var, "latency")) {
cr.latency = strtod(val, NULL);
}
else if (!strcmp(var, "start_time") || !strcmp(var, "finish_time")) {
v1 = strtok(val, ".");
if (v1 == NULL) {
continue;
}
v2 = strtok(NULL, "\n");
if (v2 == NULL) {
continue;
}
if (!strcmp(var, "start_time")) {
cr.start_time.tv_sec = strtoul(v1, NULL, 0);
cr.start_time.tv_usec = strtoul(v2, NULL, 0);
}
else {
cr.finish_time.tv_sec = strtoul(v1, NULL, 0);
cr.finish_time.tv_usec = strtoul(v2, NULL, 0);
}
}
else if (!strcmp(var, "early_timeout")) {
cr.early_timeout = atoi(val);
}
else if (!strcmp(var, "exited_ok")) {
cr.exited_ok = atoi(val);
}
else if (!strcmp(var, "return_code")) {
cr.return_code = atoi(val);
}
else if (!strcmp(var, "output")) {
/* Interpolate "\\\\" and "\\n" escape sequences to the literal
* characters they represent. This converts from the single line
* format used to store the output in a checkresult file, to the
* newline delimited format we use internally. By converting as
* soon as possible after reading from the file we don't have
* to worry about two different representations later. */
cr.output = unescape_check_result_output(val);
}
}
}
my_free(var);
my_free(val);
log_debug_info(DEBUGL_CHECKS, 2, " **************\n");
/* do we have the minimum amount of data? */
if (cr.host_name != NULL && cr.output != NULL) {
/* process check result */
process_check_result(&cr);
}
else {
/* log a debug message */
log_debug_info(DEBUGL_CHECKS, 1, "Minimum amount of data not present; Skipped check result file: '%s'\n", fname);
}
free_check_result(&cr);
/* free memory and close file */
my_free(input);
mmap_fclose(thefile);
/* delete the file (as well its ok-to-go file) */
delete_check_result_file(fname);
return OK;
}
/* deletes as check result file, as well as its ok-to-go file */
int delete_check_result_file(char *fname)
{
char *temp_buffer = NULL;
int result = OK;
/* delete the result file */
result = unlink(fname);
/* delete the ok-to-go file */
asprintf(&temp_buffer, "%s.ok", fname);
result |= unlink(temp_buffer);
my_free(temp_buffer);
return result;
}
/* initializes a host/service check result */
int init_check_result(check_result *info)
{
if (info == NULL) {
return ERROR;
}
/* reset vars */
info->object_check_type = HOST_CHECK;
info->host_name = NULL;
info->service_description = NULL;
info->check_type = CHECK_TYPE_ACTIVE;
info->check_options = CHECK_OPTION_NONE;
info->scheduled_check = FALSE;
info->reschedule_check = FALSE;
info->output_file_fp = NULL;
info->latency = 0.0;
info->start_time.tv_sec = 0;
info->start_time.tv_usec = 0;
info->finish_time.tv_sec = 0;
info->finish_time.tv_usec = 0;
info->early_timeout = FALSE;
info->exited_ok = TRUE;
info->return_code = 0;
info->output = NULL;
info->source = NULL;
info->engine = NULL;
return OK;
}
/* frees memory associated with a host/service check result */
int free_check_result(check_result *info)
{
if (info == NULL) {
return OK;
}
my_free(info->host_name);
my_free(info->service_description);
my_free(info->output);
return OK;
}
/******************************************************************/
/************************ STRING FUNCTIONS ************************/
/******************************************************************/
/* gets the next string from a buffer in memory - strings are terminated by newlines, which are removed */
char *get_next_string_from_buf(char *buf, int *start_index, int bufsize) {
char *sptr = NULL;
const char *nl = "\n";
int x;
if(buf == NULL || start_index == NULL)
return NULL;
if(bufsize < 0)
return NULL;
if(*start_index >= (bufsize - 1))
return NULL;
sptr = buf + *start_index;
/* end of buffer */
if(sptr[0] == '\x0')
return NULL;
x = strcspn(sptr, nl);
sptr[x] = '\x0';
*start_index += x + 1;
return sptr;
}
/* determines whether or not an object name (host, service, etc) contains illegal characters */
int contains_illegal_object_chars(char *name) {
register int x = 0;
register int y = 0;
if(name == NULL || illegal_object_chars == NULL)
return FALSE;
x = (int)strlen(name) - 1;
for(; x >= 0; x--) {
/* illegal user-specified characters */
if(illegal_object_chars != NULL)
for(y = 0; illegal_object_chars[y]; y++)
if(name[x] == illegal_object_chars[y])
return TRUE;
}
return FALSE;
}
/* Escapes newlines in a string. */
char *escape_newlines(char *rawbuf) {
char *newbuf = NULL;
int x;
int y;
if (rawbuf == NULL)
return NULL;
/* Count the escapes we need to make. */
for (x = 0, y = 0; rawbuf[x]; x++) {
if (rawbuf[x] == '\\' || rawbuf[x] == '\n')
y++;
}
/* Just duplicate the string if we have nothing to escape. */
if (y == 0)
return strdup(rawbuf);
/* Allocate memory for the new string with escapes. */
if ((newbuf = malloc(x + y + 1)) == NULL)
return NULL;
for (x = 0, y = 0; rawbuf[x]; x++) {
/* Escape backslashes. */
if (rawbuf[x] == '\\') {
newbuf[y++] = '\\';
newbuf[y++] = '\\';
}
/* Escape newlines. */
else if (rawbuf[x] == '\n') {
newbuf[y++] = '\\';
newbuf[y++] = 'n';
}
else
newbuf[y++] = rawbuf[x];
}
newbuf[y] = '\0';
return newbuf;
}
/* Unescapes newlines (and backslashes) in a string. */
char *unescape_check_result_output(const char *rawbuf) {
char *newbuf = NULL;
int x;
int y;
if (rawbuf == NULL)
return NULL;
/* Count the replacements we need to make. */
for (x = 0, y = 0; rawbuf[x]; x++) {
if (rawbuf[x] == '\\' && (rawbuf[x + 1] == '\\' || rawbuf[x + 1] == 'n'))
x++, y++; /* Consume one more char for each replacement. */
}
/* Just duplicate the string if we have nothing to replace. */
if (y == 0)
return strdup(rawbuf);
/* Allocate memory for the new string, with our escape sequences replaced. */
if ((newbuf = malloc(x - y + 1)) == NULL)
return NULL;
for (x = 0, y = 0; rawbuf[x]; x++) {
/* Unescape backslashes. */
if (rawbuf[x] == '\\' && rawbuf[x + 1] == '\\') {
x++;
newbuf[y++] = '\\';
}
/* Unescape newlines. */
else if (rawbuf[x] == '\\' && rawbuf[x + 1] == 'n') {
x++;
newbuf[y++] = '\n';
}
else
newbuf[y++] = rawbuf[x];
}
newbuf[y] = '\0';
return newbuf;
}
/* compares strings */
int compare_strings(char *val1a, char *val2a) {
/* use the compare_hashdata() function */
return compare_hashdata(val1a, NULL, val2a, NULL);
}
/******************************************************************/
/************************* FILE FUNCTIONS *************************/
/******************************************************************/
/* renames a file - works across filesystems (Mike Wiacek) */
int my_rename(char *source, char *dest) {
int rename_result = 0;
/* make sure we have something */
if(source == NULL || dest == NULL)
return -1;
/* first see if we can rename file with standard function */
rename_result = rename(source, dest);
/* handle any errors... */
if(rename_result == -1) {
/* an error occurred because the source and dest files are on different filesystems */
if(errno == EXDEV) {
/* try copying the file */
if(my_fcopy(source, dest) == ERROR) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to rename file '%s' to '%s': %s\n", source, dest, strerror(errno));
return -1;
}
/* delete the original file */
unlink(source);
/* reset result since we successfully copied file */
rename_result = 0;
}
/* some other error occurred */
else {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to rename file '%s' to '%s': %s\n", source, dest, strerror(errno));
return rename_result;
}
}
return rename_result;
}
/*
* copy a file from the path at source to the already opened
* destination file dest.
* This is handy when creating tempfiles with mkstemp()
*/
int my_fdcopy(char *source, char *dest, int dest_fd) {
int source_fd, rd_result = 0, wr_result = 0;
int tot_written = 0, tot_read = 0, buf_size = 0;
struct stat st;
char *buf;
/* open source file for reading */
if((source_fd = open(source, O_RDONLY, 0644)) < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to open file '%s' for reading: %s\n", source, strerror(errno));
return ERROR;
}
/*
* find out how large the source-file is so we can be sure
* we've written all of it
*/
if(fstat(source_fd, &st) < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to stat source file '%s' for my_fcopy(): %s\n", source, strerror(errno));
close(source_fd);
return ERROR;
}
/*
* If the file is huge, read it and write it in chunks.
* This value (128K) is the result of "pick-one-at-random"
* with some minimal testing and may not be optimal for all
* hardware setups, but it should work ok for most. It's
* faster than 1K buffers and 1M buffers, so change at your
* own peril. Note that it's useful to make it fit in the L2
* cache, so larger isn't necessarily better.
*/
buf_size = st.st_size > 128 << 10 ? 128 << 10 : st.st_size;
buf = malloc(buf_size);
if(!buf) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to malloc(%d) bytes: %s\n", buf_size, strerror(errno));
close(source_fd);
return ERROR;
}
/* most of the times, this loop will be gone through once */
while(tot_written < st.st_size) {
int loop_wr = 0;
rd_result = read(source_fd, buf, buf_size);
if(rd_result < 0) {
if(errno == EAGAIN || errno == EINTR)
continue;
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: my_fcopy() failed to read from '%s': %s\n", source, strerror(errno));
break;
}
tot_read += rd_result;
while(loop_wr < rd_result) {
wr_result = write(dest_fd, buf + loop_wr, rd_result - loop_wr);
if(wr_result < 0) {
if(errno == EAGAIN || errno == EINTR)
continue;
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: my_fcopy() failed to write to '%s': %s\n", dest, strerror(errno));
break;
}
loop_wr += wr_result;
}
if(wr_result < 0)
break;
tot_written += loop_wr;
}
/*
* clean up irregardless of how things went. dest_fd comes from
* our caller, so we mustn't close it.
*/
close(source_fd);
free(buf);
if(rd_result < 0 || wr_result < 0) {
/* don't leave half-written files around */
unlink(dest);
return ERROR;
}
return OK;
}
/* copies a file */
int my_fcopy(char *source, char *dest) {
int dest_fd, result;
/* make sure we have something */
if(source == NULL || dest == NULL)
return ERROR;
/* unlink destination file first (not doing so can cause problems on network file systems like CIFS) */
unlink(dest);
/* open destination file for writing */
if((dest_fd = open(dest, O_WRONLY | O_TRUNC | O_CREAT | O_APPEND, 0644)) < 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to open file '%s' for writing: %s\n", dest, strerror(errno));
return ERROR;
}
result = my_fdcopy(source, dest, dest_fd);
close(dest_fd);
return result;
}
/******************************************************************/
/******************** DYNAMIC BUFFER FUNCTIONS ********************/
/******************************************************************/
/* initializes a dynamic buffer */
int dbuf_init(dbuf *db, int chunk_size) {
if(db == NULL)
return ERROR;
db->buf = NULL;
db->used_size = 0L;
db->allocated_size = 0L;
db->chunk_size = chunk_size;
return OK;
}
/* frees a dynamic buffer */
int dbuf_free(dbuf *db) {
if(db == NULL)
return ERROR;
if(db->buf != NULL)
my_free(db->buf);
db->buf = NULL;
db->used_size = 0L;
db->allocated_size = 0L;
return OK;
}
/* dynamically expands a string */
int dbuf_strcat(dbuf *db, const char *buf) {
char *newbuf = NULL;
unsigned long buflen = 0L;
unsigned long new_size = 0L;
unsigned long memory_needed = 0L;
if(db == NULL || buf == NULL)
return ERROR;
/* how much memory should we allocate (if any)? */
buflen = strlen(buf);
new_size = db->used_size + buflen + 1;
/* we need more memory */
if(db->allocated_size < new_size) {
memory_needed = ((ceil(new_size / db->chunk_size) + 1) * db->chunk_size);
/* allocate memory to store old and new string */
if((newbuf = (char *)realloc((void *)db->buf, (size_t)memory_needed)) == NULL)
return ERROR;
/* update buffer pointer */
db->buf = newbuf;
/* update allocated size */
db->allocated_size = memory_needed;
/* terminate buffer */
db->buf[db->used_size] = '\x0';
}
/* append the new string */
strcat(db->buf, buf);
/* update size allocated */
db->used_size += buflen;
return OK;
}
/******************************************************************/
/********************** CHECK STATS FUNCTIONS *********************/
/******************************************************************/
/* initialize check statistics data structures */
int init_check_stats(void) {
int x = 0;
int y = 0;
for(x = 0; x < MAX_CHECK_STATS_TYPES; x++) {
check_statistics[x].current_bucket = 0;
for(y = 0; y < CHECK_STATS_BUCKETS; y++)
check_statistics[x].bucket[y] = 0;
check_statistics[x].overflow_bucket = 0;
for(y = 0; y < 3; y++)
check_statistics[x].minute_stats[y] = 0;
check_statistics[x].last_update = (time_t)0L;
}
return OK;
}
/* records stats for a given type of check */
int update_check_stats(int check_type, time_t check_time) {
time_t current_time;
unsigned long minutes = 0L;
int new_current_bucket = 0;
int this_bucket = 0;
int x = 0;
if(check_type < 0 || check_type >= MAX_CHECK_STATS_TYPES)
return ERROR;
time(¤t_time);
if((unsigned long)check_time == 0L) {
#ifdef DEBUG_CHECK_STATS
printf("TYPE[%d] CHECK TIME==0!\n", check_type);
#endif
check_time = current_time;
}
/* do some sanity checks on the age of the stats data before we start... */
/* get the new current bucket number */
minutes = ((unsigned long)check_time - (unsigned long)program_start) / 60;
new_current_bucket = minutes % CHECK_STATS_BUCKETS;
/* its been more than 15 minutes since stats were updated, so clear the stats */
if((((unsigned long)current_time - (unsigned long)check_statistics[check_type].last_update) / 60) > CHECK_STATS_BUCKETS) {
for(x = 0; x < CHECK_STATS_BUCKETS; x++)
check_statistics[check_type].bucket[x] = 0;
check_statistics[check_type].overflow_bucket = 0;
#ifdef DEBUG_CHECK_STATS
printf("CLEARING ALL: TYPE[%d], CURRENT=%llu, LASTUPDATE=%llu\n", check_type, (unsigned long long)current_time, (unsigned long long)check_statistics[check_type].last_update);
#endif
}
/* different current bucket number than last time */
else if(new_current_bucket != check_statistics[check_type].current_bucket) {
/* clear stats in buckets between last current bucket and new current bucket - stats haven't been updated in a while */
for(x = check_statistics[check_type].current_bucket; x < (CHECK_STATS_BUCKETS * 2); x++) {
this_bucket = (x + CHECK_STATS_BUCKETS + 1) % CHECK_STATS_BUCKETS;
if(this_bucket == new_current_bucket)
break;
#ifdef DEBUG_CHECK_STATS
printf("CLEARING BUCKET %d, (NEW=%d, OLD=%d)\n", this_bucket, new_current_bucket, check_statistics[check_type].current_bucket);
#endif
/* clear old bucket value */
check_statistics[check_type].bucket[this_bucket] = 0;
}
/* update the current bucket number, push old value to overflow bucket */
check_statistics[check_type].overflow_bucket = check_statistics[check_type].bucket[new_current_bucket];
check_statistics[check_type].current_bucket = new_current_bucket;
check_statistics[check_type].bucket[new_current_bucket] = 0;
}
#ifdef DEBUG_CHECK_STATS
else
printf("NO CLEARING NEEDED\n");
#endif
/* increment the value of the current bucket */
check_statistics[check_type].bucket[new_current_bucket]++;
#ifdef DEBUG_CHECK_STATS
printf("TYPE[%d].BUCKET[%d]=%d\n", check_type, new_current_bucket, check_statistics[check_type].bucket[new_current_bucket]);
printf(" ");
for(x = 0; x < CHECK_STATS_BUCKETS; x++)
printf("[%d] ", check_statistics[check_type].bucket[x]);
printf(" (%d)\n", check_statistics[check_type].overflow_bucket);
#endif
/* record last update time */
check_statistics[check_type].last_update = current_time;
return OK;
}
/* generate 1/5/15 minute stats for a given type of check */
int generate_check_stats(void) {
time_t current_time;
int x = 0;
int new_current_bucket = 0;
int this_bucket = 0;
int last_bucket = 0;
int this_bucket_value = 0;
int last_bucket_value = 0;
int bucket_value = 0;
int seconds = 0;
int minutes = 0;
int check_type = 0;
float this_bucket_weight = 0.0;
float last_bucket_weight = 0.0;
time(¤t_time);
/* do some sanity checks on the age of the stats data before we start... */
/* get the new current bucket number */
minutes = ((unsigned long)current_time - (unsigned long)program_start) / 60;
new_current_bucket = minutes % CHECK_STATS_BUCKETS;
for(check_type = 0; check_type < MAX_CHECK_STATS_TYPES; check_type++) {
/* its been more than 15 minutes since stats were updated, so clear the stats */
if((((unsigned long)current_time - (unsigned long)check_statistics[check_type].last_update) / 60) > CHECK_STATS_BUCKETS) {
for(x = 0; x < CHECK_STATS_BUCKETS; x++)
check_statistics[check_type].bucket[x] = 0;
check_statistics[check_type].overflow_bucket = 0;
#ifdef DEBUG_CHECK_STATS
printf("GEN CLEARING ALL: TYPE[%d], CURRENT=%llu, LASTUPDATE=%llu\n", check_type, (unsigned long long)current_time, (unsigned long long)check_statistics[check_type].last_update);
#endif
}
/* different current bucket number than last time */
else if(new_current_bucket != check_statistics[check_type].current_bucket) {
/* clear stats in buckets between last current bucket and new current bucket - stats haven't been updated in a while */
for(x = check_statistics[check_type].current_bucket; x < (CHECK_STATS_BUCKETS * 2); x++) {
this_bucket = (x + CHECK_STATS_BUCKETS + 1) % CHECK_STATS_BUCKETS;
if(this_bucket == new_current_bucket)
break;
#ifdef DEBUG_CHECK_STATS
printf("GEN CLEARING BUCKET %d, (NEW=%d, OLD=%d), CURRENT=%llu, LASTUPDATE=%llu\n", this_bucket, new_current_bucket, check_statistics[check_type].current_bucket, (unsigned long long)current_time, (unsigned long long)check_statistics[check_type].last_update);
#endif
/* clear old bucket value */
check_statistics[check_type].bucket[this_bucket] = 0;
}
/* update the current bucket number, push old value to overflow bucket */
check_statistics[check_type].overflow_bucket = check_statistics[check_type].bucket[new_current_bucket];
check_statistics[check_type].current_bucket = new_current_bucket;
check_statistics[check_type].bucket[new_current_bucket] = 0;
}
#ifdef DEBUG_CHECK_STATS
else
printf("GEN NO CLEARING NEEDED: TYPE[%d], CURRENT=%llu, LASTUPDATE=%llu\n", check_type, (unsigned long long)current_time, (unsigned long long)check_statistics[check_type].last_update);
#endif
/* update last check time */
check_statistics[check_type].last_update = current_time;
}
/* determine weights to use for this/last buckets */
seconds = ((unsigned long)current_time - (unsigned long)program_start) % 60;
this_bucket_weight = (seconds / 60.0);
last_bucket_weight = ((60 - seconds) / 60.0);
/* update statistics for all check types */
for(check_type = 0; check_type < MAX_CHECK_STATS_TYPES; check_type++) {
/* clear the old statistics */
for(x = 0; x < 3; x++)
check_statistics[check_type].minute_stats[x] = 0;
/* loop through each bucket */
for(x = 0; x < CHECK_STATS_BUCKETS; x++) {
/* which buckets should we use for this/last bucket? */
this_bucket = (check_statistics[check_type].current_bucket + CHECK_STATS_BUCKETS - x) % CHECK_STATS_BUCKETS;
last_bucket = (this_bucket + CHECK_STATS_BUCKETS - 1) % CHECK_STATS_BUCKETS;
/* raw/unweighted value for this bucket */
this_bucket_value = check_statistics[check_type].bucket[this_bucket];
/* raw/unweighted value for last bucket - use overflow bucket if last bucket is current bucket */
if(last_bucket == check_statistics[check_type].current_bucket)
last_bucket_value = check_statistics[check_type].overflow_bucket;
else
last_bucket_value = check_statistics[check_type].bucket[last_bucket];
/* determine value by weighting this/last buckets... */
/* if this is the current bucket, use its full value + weighted % of last bucket */
if(x == 0) {
bucket_value = (int)(this_bucket_value + floor(last_bucket_value * last_bucket_weight));
}
/* otherwise use weighted % of this and last bucket */
else {
bucket_value = (int)(ceil(this_bucket_value * this_bucket_weight) + floor(last_bucket_value * last_bucket_weight));
}
/* 1 minute stats */
if(x == 0)
check_statistics[check_type].minute_stats[0] = bucket_value;
/* 5 minute stats */
if(x < 5)
check_statistics[check_type].minute_stats[1] += bucket_value;
/* 15 minute stats */
if(x < 15)
check_statistics[check_type].minute_stats[2] += bucket_value;
#ifdef DEBUG_CHECK_STATS2
printf("X=%d, THIS[%d]=%d, LAST[%d]=%d, 1/5/15=%d,%d,%d L=%d R=%d\n", x, this_bucket, this_bucket_value, last_bucket, last_bucket_value, check_statistics[check_type].minute_stats[0], check_statistics[check_type].minute_stats[1], check_statistics[check_type].minute_stats[2], left_value, right_value);
#endif
/* record last update time */
check_statistics[check_type].last_update = current_time;
}
#ifdef DEBUG_CHECK_STATS
printf("TYPE[%d] 1/5/15 = %d, %d, %d (seconds=%d, this_weight=%f, last_weight=%f)\n", check_type, check_statistics[check_type].minute_stats[0], check_statistics[check_type].minute_stats[1], check_statistics[check_type].minute_stats[2], seconds, this_bucket_weight, last_bucket_weight);
#endif
}
return OK;
}
/******************************************************************/
/************************ UPDATE FUNCTIONS ************************/
/******************************************************************/
/* check for new releases of Nagios */
int check_for_nagios_updates(int force, int reschedule) {
time_t current_time;
int result = OK;
int api_result = OK;
int do_check = TRUE;
time_t next_check = 0L;
unsigned int rand_seed = 0;
int randnum = 0;
time(¤t_time);
/*
printf("NOW: %s",ctime(¤t_time));
printf("LAST CHECK: %s",ctime(&last_update_check));
*/
/* seed the random generator */
rand_seed = (unsigned int)(current_time + nagios_pid);
srand(rand_seed);
/* generate a (probably) unique ID for this nagios install */
/* the server api currently sees thousands of nagios installs behind single ip addresses, so this help determine if there are really thousands of servers out there, or if some nagios installs are misbehaving */
if(update_uid == 0L)
update_uid = current_time;
/* update checks are disabled */
if(check_for_updates == FALSE)
do_check = FALSE;
/* we checked for updates recently, so don't do it again */
if((current_time - last_update_check) < MINIMUM_UPDATE_CHECK_INTERVAL)
do_check = FALSE;
/* the check is being forced */
if(force == TRUE)
do_check = TRUE;
/* do a check */
if(do_check == TRUE) {
/*printf("RUNNING QUERY...\n");*/
/* query api */
api_result = query_update_api();
}
/* should we reschedule the update check? */
if(reschedule == TRUE) {
/*printf("RESCHEDULING...\n");*/
randnum = rand();
/*
printf("RAND: %d\n",randnum);
printf("RANDMAX: %d\n",RAND_MAX);
printf("UCIW: %d\n",UPDATE_CHECK_INTERVAL_WOBBLE);
printf("MULT: %f\n",(float)randnum/RAND_MAX);
*/
/* we didn't do an update, so calculate next possible update time */
if(do_check == FALSE) {
next_check = last_update_check + BASE_UPDATE_CHECK_INTERVAL;
next_check = next_check + (unsigned long)(((float)randnum / RAND_MAX) * UPDATE_CHECK_INTERVAL_WOBBLE);
}
/* we tried to check for an update */
else {
/* api query was okay */
if(api_result == OK) {
next_check = current_time + BASE_UPDATE_CHECK_INTERVAL;
next_check += (unsigned long)(((float)randnum / RAND_MAX) * UPDATE_CHECK_INTERVAL_WOBBLE);
}
/* query resulted in an error - retry at a shorter interval */
else {
next_check = current_time + BASE_UPDATE_CHECK_RETRY_INTERVAL;
next_check += (unsigned long)(((float)randnum / RAND_MAX) * UPDATE_CHECK_RETRY_INTERVAL_WOBBLE);
}
}
/* make sure next check isn't in the past - if it is, schedule a check in 1 minute */
if(next_check < current_time)
next_check = current_time + 60;
/*printf("NEXT CHECK: %s",ctime(&next_check));*/
/* schedule the next update event */
schedule_new_event(EVENT_CHECK_PROGRAM_UPDATE, TRUE, next_check, FALSE, BASE_UPDATE_CHECK_INTERVAL, NULL, TRUE, NULL, NULL, 0);
}
return result;
}
/* checks for updates at api.nagios.org */
int query_update_api(void) {
const char *api_server = "api.nagios.org";
const char *api_path = "/versioncheck/";
char *api_query = NULL;
char *api_query_opts = NULL;
char *buf = NULL;
char recv_buf[1024];
int report_install = FALSE;
char *ptr = NULL;
int current_line = 0;
int buf_index = 0;
int in_header = TRUE;
char *var = NULL;
char *val = NULL;
int sd = 0;
int send_len = 0;
int recv_len = 0;
int update_check_succeeded = FALSE;
/* report a new install, upgrade, or rollback */
/* Nagios monitors the world and we monitor Nagios taking over the world. :-) */
if(last_update_check == (time_t)0L)
report_install = TRUE;
if(last_program_version == NULL || strcmp(PROGRAM_VERSION, last_program_version))
report_install = TRUE;
if(report_install == TRUE) {
asprintf(&api_query_opts, "&firstcheck=1");
if(last_program_version != NULL) {
char *qopts2 = NULL;
asprintf(&qopts2, "%s&last_version=%s", api_query_opts, last_program_version);
my_free(api_query_opts);
api_query_opts = qopts2;
}
}
/* generate the query */
asprintf(&api_query, "v=1&product=nagios&tinycheck=1&stableonly=1&uid=%lu", update_uid);
if(bare_update_check == FALSE) {
char *api_query2 = NULL;
asprintf(&api_query2, "%s&version=%s%s", api_query, PROGRAM_VERSION, (api_query_opts == NULL) ? "" : api_query_opts);
my_free(api_query);
api_query = api_query2;
}
/* generate the HTTP request */
asprintf(&buf,
"POST %s HTTP/1.0\r\nUser-Agent: Nagios/%s\r\n"
"Connection: close\r\nHost: %s\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: %lu\r\n\r\n%s",
api_path, PROGRAM_VERSION, api_server,
(unsigned long) strlen(api_query), api_query);
if (buf == NULL) {
abort();
}
my_tcp_connect(api_server, 80, &sd, 2);
if(sd > 0) {
/* send request */
send_len = strlen(buf);
my_sendall(sd, buf, &send_len, 2);
/* get response */
recv_len = sizeof(recv_buf);
my_recvall(sd, recv_buf, &recv_len, 2);
recv_buf[sizeof(recv_buf) - 1] = '\x0';
/* close connection */
close(sd);
/* parse the result */
in_header = TRUE;
while((ptr = get_next_string_from_buf(recv_buf, &buf_index, sizeof(recv_buf)))) {
strip(ptr);
current_line++;
if(!strcmp(ptr, "")) {
in_header = FALSE;
continue;
}
if(in_header == TRUE)
continue;
var = strtok(ptr, "=");
val = strtok(NULL, "\n");
if(!strcmp(var, "UPDATE_AVAILABLE")) {
update_available = atoi(val);
/* we were successful */
update_check_succeeded = TRUE;
}
else if(!strcmp(var, "UPDATE_VERSION")) {
if(new_program_version)
my_free(new_program_version);
new_program_version = strdup(val);
}
else if(!strcmp(var, "UPDATE_RELEASEDATE")) {
}
}
}
/* cleanup */
my_free(buf);
my_free(api_query);
my_free(api_query_opts);
/* we were successful! */
if(update_check_succeeded == TRUE) {
time(&last_update_check);
if(last_program_version)
free(last_program_version);
last_program_version = (char *)strdup(PROGRAM_VERSION);
}
return OK;
}
/******************************************************************/
/************************* MISC FUNCTIONS *************************/
/******************************************************************/
/* returns Nagios version */
char *get_program_version(void) {
return (char *)PROGRAM_VERSION;
}
/* returns Nagios modification date */
char *get_program_modification_date(void) {
return (char *)PROGRAM_MODIFICATION_DATE;
}
/******************************************************************/
/*********************** CLEANUP FUNCTIONS ************************/
/******************************************************************/
/* do some cleanup before we exit */
void cleanup(void) {
xodtemplate_free_memory();
#ifdef USE_EVENT_BROKER
/* unload modules */
if(test_scheduling == FALSE && verify_config == FALSE) {
neb_free_callback_list();
neb_unload_all_modules(NEBMODULE_FORCE_UNLOAD, (sigshutdown == TRUE) ? NEBMODULE_NEB_SHUTDOWN : NEBMODULE_NEB_RESTART);
neb_free_module_list();
neb_deinit_modules();
}
#endif
/* free all allocated memory - including macros */
free_memory(get_global_macros());
close_log_file();
return;
}
/* free the memory allocated to the linked lists */
void free_memory(nagios_macros *mac) {
int i;
/* free all allocated memory for the object definitions */
free_object_data();
free_comment_data();
/* free event queue data */
squeue_destroy(nagios_squeue, SQUEUE_FREE_DATA);
nagios_squeue = NULL;
/* free memory for global event handlers */
my_free(global_host_event_handler);
my_free(global_service_event_handler);
/* free any notification list that may have been overlooked */
free_notification_list();
/* free obsessive compulsive commands */
my_free(ocsp_command);
my_free(ochp_command);
my_free(object_cache_file);
my_free(object_precache_file);
/*
* free memory associated with macros.
* It's ok to only free the volatile ones, as the non-volatile
* are always free()'d before assignment if they're set.
* Doing a full free of them here means we'll wipe the constant
* macros when we get a reload or restart request through the
* command pipe, or when we receive a SIGHUP.
*/
clear_volatile_macros_r(mac);
free_macrox_names();
/* free illegal char strings */
my_free(illegal_object_chars);
my_free(illegal_output_chars);
/* free nagios user and group */
my_free(nagios_user);
my_free(nagios_group);
/* free version strings */
my_free(last_program_version);
my_free(new_program_version);
/* free file/path variables */
my_free(debug_file);
my_free(log_file);
mac->x[MACRO_LOGFILE] = NULL; /* assigned from 'log_file' */
my_free(temp_file);
mac->x[MACRO_TEMPFILE] = NULL; /* assigned from temp_file */
my_free(temp_path);
mac->x[MACRO_TEMPPATH] = NULL; /*assigned from temp_path */
my_free(command_file);
mac->x[MACRO_COMMANDFILE] = NULL; /* assigned from command_file */
my_free(check_result_path);
my_free(log_archive_path);
my_free(website_url);
my_free(status_file);
my_free(retention_file);
for (i = 0; i < MAX_USER_MACROS; i++) {
my_free(macro_user[i]);
}
/* these have no other reference */
my_free(mac->x[MACRO_PROCESSSTARTTIME]);
my_free(mac->x[MACRO_EVENTSTARTTIME]);
my_free(mac->x[MACRO_ADMINEMAIL]);
my_free(mac->x[MACRO_ADMINPAGER]);
my_free(mac->x[MACRO_RESOURCEFILE]);
my_free(mac->x[MACRO_OBJECTCACHEFILE]);
my_free(mac->x[MACRO_MAINCONFIGFILE]);
my_free(mac->x[MACRO_RETENTIONDATAFILE]);
my_free(mac->x[MACRO_HOSTPERFDATAFILE]);
my_free(mac->x[MACRO_STATUSDATAFILE]);
my_free(mac->x[MACRO_SERVICEPERFDATAFILE]);
return;
}
/* free a notification list that was created */
void free_notification_list(void) {
notification *temp_notification = NULL;
notification *next_notification = NULL;
temp_notification = notification_list;
while(temp_notification != NULL) {
next_notification = temp_notification->next;
my_free(temp_notification);
temp_notification = next_notification;
}
/* reset notification list pointer */
notification_list = NULL;
return;
}
/* reset all system-wide variables, so when we've receive a SIGHUP we can restart cleanly */
int reset_variables(void) {
/* First free any variables previously set */
my_free(log_file);
my_free(temp_file);
my_free(temp_path);
my_free(check_result_path);
my_free(command_file);
my_free(lock_file);
my_free(log_archive_path);
my_free(debug_file);
my_free(object_cache_file);
my_free(object_precache_file);
my_free(nagios_user);
my_free(nagios_group);
my_free(global_host_event_handler);
my_free(global_service_event_handler);
my_free(ocsp_command);
my_free(ochp_command);
my_free(website_url);
/* Next re-initialize configuration variables */
init_main_cfg_vars(0);
init_shared_cfg_vars(0);
/* Finally, set anything not set in the initialization routines */
log_file = (char *)strdup(DEFAULT_LOG_FILE);
temp_file = (char *)strdup(DEFAULT_TEMP_FILE);
temp_path = (char *)strdup(DEFAULT_TEMP_PATH);
check_result_path = (char *)strdup(DEFAULT_CHECK_RESULT_PATH);
command_file = (char *)strdup(DEFAULT_COMMAND_FILE);
lock_file = (char *)strdup(DEFAULT_LOCK_FILE); /* this is kept across restarts */
log_archive_path = (char *)strdup(DEFAULT_LOG_ARCHIVE_PATH);
debug_file = (char *)strdup(DEFAULT_DEBUG_FILE);
/* init_main_cfg_vars(0) sets object_precache_file = strdup(DEFAULT_PRECACHED_OBJECT_FILE); */
nagios_user = (char *)strdup(DEFAULT_NAGIOS_USER);
nagios_group = (char *)strdup(DEFAULT_NAGIOS_GROUP);
logging_options = NSLOG_RUNTIME_ERROR | NSLOG_RUNTIME_WARNING | NSLOG_VERIFICATION_ERROR | NSLOG_VERIFICATION_WARNING | NSLOG_CONFIG_ERROR | NSLOG_CONFIG_WARNING | NSLOG_PROCESS_INFO | NSLOG_HOST_NOTIFICATION | NSLOG_SERVICE_NOTIFICATION | NSLOG_EVENT_HANDLER | NSLOG_EXTERNAL_COMMAND | NSLOG_PASSIVE_CHECK | NSLOG_HOST_UP | NSLOG_HOST_DOWN | NSLOG_HOST_UNREACHABLE | NSLOG_SERVICE_OK | NSLOG_SERVICE_WARNING | NSLOG_SERVICE_UNKNOWN | NSLOG_SERVICE_CRITICAL | NSLOG_INFO_MESSAGE;
syslog_options = NSLOG_RUNTIME_ERROR | NSLOG_RUNTIME_WARNING | NSLOG_VERIFICATION_ERROR | NSLOG_VERIFICATION_WARNING | NSLOG_CONFIG_ERROR | NSLOG_CONFIG_WARNING | NSLOG_PROCESS_INFO | NSLOG_HOST_NOTIFICATION | NSLOG_SERVICE_NOTIFICATION | NSLOG_EVENT_HANDLER | NSLOG_EXTERNAL_COMMAND | NSLOG_PASSIVE_CHECK | NSLOG_HOST_UP | NSLOG_HOST_DOWN | NSLOG_HOST_UNREACHABLE | NSLOG_SERVICE_OK | NSLOG_SERVICE_WARNING | NSLOG_SERVICE_UNKNOWN | NSLOG_SERVICE_CRITICAL | NSLOG_INFO_MESSAGE;
modified_host_process_attributes = MODATTR_NONE;
modified_service_process_attributes = MODATTR_NONE;
last_log_rotation = 0L;
currently_running_service_checks = 0;
next_comment_id = 0L; /* comment and downtime id get initialized to nonzero elsewhere */
next_downtime_id = 0L;
next_event_id = 1;
next_notification_id = 1;
free_child_process_memory = FALSE;
child_processes_fork_twice = FALSE;
/* initialize macros */
init_macros();
global_host_event_handler_ptr = NULL;
global_service_event_handler_ptr = NULL;
ocsp_command_ptr = NULL;
ochp_command_ptr = NULL;
/* reset umask */
umask(S_IWGRP | S_IWOTH);
return OK;
}
/* try and detect any problems with sys limits
we're specifically interested in NPROC
but could easily add NOFILE here if necessary */
#ifdef DETECT_RLIMIT_PROBLEM
void rlimit_problem_detection(int desired_workers) {
log_debug_info(DEBUGL_PROCESS, 2, "rlimit_problem_detection()\n");
struct rlimit rlim;
int ilim;
host * temp_host = NULL;
service * temp_service = NULL;
/* how many times a worker forks/execs to run a plugin */
int forks_per_worker_per_check = 2;
/* time period to calculate over (in minutes) */
int time_period_calc = 5;
/* how many processes do we just want to account for? */
int arbitrary_user_processes = 300;
double checks_per_time_period = 0.0;
double this_interval = 0.0;
int total_num_procs = 0;
/* first, we grab the NPROC limit, then we check if it isn't unlimited
if it isn't, but the max is, then we set the soft limit to the max
if that doesn't work, or the max isn't unlimited, then we try and
calculate what the current usage is really, and how many workers
we expect to have, and calculate what our usage (generally) is
going to be */
ilim = getrlimit(RLIMIT_NPROC, &rlim);
if (ilim != 0) {
/* nothing we can do here, so just let it keep moving along */
logit(NSLOG_PROCESS_INFO, TRUE, "WARNING: getrlimit(RLIMIT_NPROC) failed with errno: %s\n", strerror(errno));
return;
}
if (rlim.rlim_cur == RLIM_INFINITY) {
/* we won't have any problems due to fork constraints */
log_debug_info(DEBUGL_PROCESS, 0, " * RLIMIT_NPROC is unlimited, no need to continue checking.\n");
return;
}
desired_workers = get_desired_workers(desired_workers);
/* calculate the amount of checks
and the worst-case (estimation) frequency in which they repeat */
for (temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
this_interval = 0;
if (!(temp_host->checks_enabled)) {
continue;
}
/* get the smallest possible */
if (temp_host->check_interval > temp_host->retry_interval
&& temp_host->retry_interval != 0) {
this_interval = temp_host->retry_interval;
} else {
this_interval = temp_host->check_interval;
}
/* get them on an average scale (5 min) */
if (this_interval > 0) {
this_interval = ceil((double) time_period_calc / this_interval);
}
checks_per_time_period += this_interval;
}
for (temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
this_interval = 0;
if (!(temp_service->checks_enabled)) {
continue;
}
/* get the smallest possible */
if (temp_service->check_interval > temp_service->retry_interval
&& temp_service->retry_interval != 0) {
this_interval = temp_service->retry_interval;
} else {
this_interval = temp_service->check_interval;
}
/* get them on an average scale (5 min) */
if (this_interval > 0) {
this_interval = ceil(time_period_calc / this_interval);
}
checks_per_time_period += this_interval;
}
total_num_procs = checks_per_time_period * forks_per_worker_per_check;
total_num_procs += desired_workers;
total_num_procs += arbitrary_user_processes;
log_debug_info(DEBUGL_PROCESS, 0, " * total_num_procs is: %d\n", total_num_procs);
log_debug_info(DEBUGL_PROCESS, 0, " * using forks_per_worker_per_check: %d\n", forks_per_worker_per_check);
log_debug_info(DEBUGL_PROCESS, 0, " * using desired_workers: %d\n", desired_workers);
log_debug_info(DEBUGL_PROCESS, 0, " * using arbitrary_user_processes: %d\n", arbitrary_user_processes);
if (rlim.rlim_cur > total_num_procs) {
log_debug_info(DEBUGL_PROCESS, 0, " * RLIMIT_NPROC is %d, total max estimated processes is %d, everything looks okay!\n",
(int) rlim.rlim_cur, total_num_procs);
} else {
/* just warn the user - no need to bail out */
logit(NSLOG_RUNTIME_WARNING, TRUE, "WARNING: RLIMIT_NPROC is %d, total max estimated processes is %d! You should increase your limits (ulimit -u, or limits.conf)\n",
(int) rlim.rlim_cur, total_num_procs);
}
}
#endif
nagios-4.4.6/base/workers.c 0000664 0000000 0000000 00000100613 13652113235 0015561 0 ustar 00root root 0000000 0000000 /*
* This file holds all nagios<->libnagios integration stuff, so that
* libnagios itself is usable as a standalone library for addon
* writers to use as they see fit.
*
* This means apis inside libnagios can be tested without compiling
* all of Nagios into it, and that they can remain general-purpose
* code that can be reused for other things later.
*/
#include "../include/config.h"
#include
#include "../include/nagios.h"
#include "../include/workers.h"
/* perfect hash function for wproc response codes */
#include "wpres-phash.h"
struct wproc_worker;
struct wproc_job {
unsigned int id;
unsigned int type;
unsigned int timeout;
char *command;
void *arg;
struct wproc_worker *wp;
};
struct wproc_list;
struct wproc_worker {
char *name; /**< check-source name of this worker */
int sd; /**< communication socket */
pid_t pid; /**< pid */
int max_jobs; /**< Max number of jobs the worker can handle */
int jobs_running; /**< jobs running */
int jobs_started; /**< jobs started */
int job_index; /**< round-robin slot allocator (this wraps) */
iocache *ioc; /**< iocache for reading from worker */
fanout_table *jobs; /**< array of jobs */
struct wproc_list *wp_list;
};
struct wproc_list {
unsigned int len;
unsigned int idx;
struct wproc_worker **wps;
};
static struct wproc_list workers = {0, 0, NULL};
static dkhash_table *specialized_workers;
static struct wproc_list *to_remove = NULL;
typedef struct wproc_callback_job {
void *data;
void (*callback)(struct wproc_result *, void *, int);
} wproc_callback_job;
typedef struct wproc_object_job {
char *contact_name;
char *host_name;
char *service_description;
} wproc_object_job;
unsigned int wproc_num_workers_online = 0, wproc_num_workers_desired = 0;
unsigned int wproc_num_workers_spawned = 0;
extern struct kvvec * macros_to_kvv(nagios_macros *);
#define tv2float(tv) ((float)((tv)->tv_sec) + ((float)(tv)->tv_usec) / 1000000.0)
static const char *wpjob_type_name(unsigned int type)
{
switch (type) {
case WPJOB_CHECK:
return "CHECK";
case WPJOB_NOTIFY:
return "NOTIFY";
case WPJOB_OCSP:
return "OCSP";
case WPJOB_OCHP:
return "OCHP";
case WPJOB_GLOBAL_SVC_EVTHANDLER:
return "GLOBAL SERVICE EVENTHANDLER";
case WPJOB_SVC_EVTHANDLER:
return "SERVICE EVENTHANDLER";
case WPJOB_GLOBAL_HOST_EVTHANDLER:
return "GLOBAL HOST EVENTHANDLER";
case WPJOB_HOST_EVTHANDLER:
return "HOST EVENTHANDLER";
case WPJOB_CALLBACK:
return "CALLBACK";
case WPJOB_HOST_PERFDATA:
return "HOST PERFDATA";
case WPJOB_SVC_PERFDATA:
return "SERVICE PERFDATA";
}
return "UNKNOWN";
}
static void wproc_logdump_buffer(int level, int show, const char *prefix, char *buf)
{
char *ptr, *eol;
unsigned int line = 1;
if (!buf || !*buf) {
return;
}
for (ptr = buf; ptr && *ptr; ptr = eol ? eol + 1 : NULL) {
if ((eol = strchr(ptr, '\n'))) {
*eol = 0;
}
logit(level, show, "%s line %.02d: %s\n", prefix, line++, ptr);
if (eol) {
*eol = '\n';
}
else {
break;
}
}
}
/* Try to reap 'jobs' jobs for 'msecs' milliseconds. Return early on error. */
void wproc_reap(int jobs, int msecs)
{
struct timeval start;
gettimeofday(&start, NULL);
while (jobs > 0 && msecs > 0) {
int inputs = iobroker_poll(nagios_iobs, msecs);
if (inputs < 0) {
return;
}
jobs -= inputs; /* One input is roughly equivalent to one job. */
struct timeval now;
gettimeofday(&now, NULL);
msecs -= tv_delta_msec(&start, &now);
start = now;
}
}
int wproc_can_spawn(struct load_control *lc)
{
unsigned int old = 0;
time_t now;
/* if no load control is enabled, we can safely run this job */
if (!(lc->options & LOADCTL_ENABLED)) {
return 1;
}
now = time(NULL);
if (lc->last_check + lc->check_interval > now) {
lc->last_check = now;
if (getloadavg(lc->load, 3) < 0) {
return lc->jobs_limit > lc->jobs_running;
}
if (lc->load[0] > lc->backoff_limit) {
old = lc->jobs_limit;
lc->jobs_limit -= lc->backoff_change;
}
else if (lc->load[0] < lc->rampup_limit) {
old = lc->jobs_limit;
lc->jobs_limit += lc->rampup_change;
}
if (lc->jobs_limit > lc->jobs_max) {
lc->jobs_limit = lc->jobs_max;
}
else if (lc->jobs_limit < lc->jobs_min) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Tried to set jobs_limit to %u, below jobs_min (%u)\n",
lc->jobs_limit, lc->jobs_min);
lc->jobs_limit = lc->jobs_min;
}
if (old && old != lc->jobs_limit) {
if (lc->jobs_limit < old) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: loadctl.jobs_limit changed from %u to %u\n", old, lc->jobs_limit);
} else {
logit(NSLOG_INFO_MESSAGE, FALSE, "wproc: loadctl.jobs_limit changed from %u to %u\n", old, lc->jobs_limit);
}
}
}
return lc->jobs_limit > lc->jobs_running;
}
static int get_job_id(struct wproc_worker *wp)
{
return wp->job_index++;
}
static struct wproc_job *get_job(struct wproc_worker *wp, int job_id)
{
return fanout_remove(wp->jobs, job_id);
}
static struct wproc_list *get_wproc_list(const char *cmd)
{
struct wproc_list *wp_list = NULL;
char *cmd_name = NULL;
char *slash = NULL;
char *space = NULL;
if (!specialized_workers) {
return &workers;
}
/* first, look for a specialized worker for this command */
space = strchr(cmd, ' ');
if (space != NULL) {
int namelen = (unsigned long) space - (unsigned long) cmd;
cmd_name = calloc(1, namelen + 1);
/* not exactly optimal, but what the hells */
if (!cmd_name) {
return &workers;
}
memcpy(cmd_name, cmd, namelen);
slash = strrchr(cmd_name, '/');
}
wp_list = dkhash_get(specialized_workers, cmd_name ? cmd_name : cmd, NULL);
if (!wp_list && slash) {
wp_list = dkhash_get(specialized_workers, ++slash, NULL);
}
if (wp_list != NULL) {
log_debug_info(DEBUGL_CHECKS, 1, "Found specialized worker(s) for '%s'", (slash && *slash != '/') ? slash : cmd_name);
}
if (cmd_name) {
free(cmd_name);
}
if (wp_list) {
return wp_list;
}
return &workers;
}
static struct wproc_worker *get_worker(const char *cmd)
{
struct wproc_list *wp_list = NULL;
log_debug_info(DEBUGL_WORKERS, 0, "get_worker()\n");
if (!cmd) {
log_debug_info(DEBUGL_WORKERS, 1, " * cmd is null, bailing\n");
return NULL;
}
wp_list = get_wproc_list(cmd);
if (!wp_list) {
log_debug_info(DEBUGL_WORKERS, 1, " * wp_list is null, bailing\n");
return NULL;
}
if (!wp_list->wps) {
log_debug_info(DEBUGL_WORKERS, 1, " * wp_list->wps is null, bailing\n");
return NULL;
}
if (!wp_list->len) {
log_debug_info(DEBUGL_WORKERS, 2, " * wp_list->len is <= 0, bailing\n");
return NULL;
}
return wp_list->wps[wp_list->idx++ % wp_list->len];
}
static struct wproc_job *create_job(int type, void *arg, time_t timeout, const char *cmd)
{
struct wproc_job *job = NULL;
struct wproc_worker *wp = NULL;
int result = 0;
log_debug_info(DEBUGL_WORKERS, 0, "create_job()\n");
wp = get_worker(cmd);
if (wp == NULL) {
return NULL;
}
job = calloc(1, sizeof(*job));
if (job == NULL) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to allocate memory for worker job: %s\n", strerror(errno));
return NULL;
}
job->wp = wp;
job->id = get_job_id(wp);
job->type = type;
job->arg = arg;
job->timeout = timeout;
result = fanout_add(wp->jobs, job->id, job);
if (result < 0) {
log_debug_info(DEBUGL_WORKERS, 1, " * Can't add job to wp->jobs, bailing\n");
free(job);
return NULL;
}
job->command = strdup(cmd);
if (job->command == NULL) {
log_debug_info(DEBUGL_WORKERS, 1, " * job command can't be null, bailing\n");
free(job);
return NULL;
}
return job;
}
static void run_job_callback(struct wproc_job *job, struct wproc_result *wpres, int val)
{
wproc_callback_job *cj;
log_debug_info(DEBUGL_WORKERS, 0, "run_job_callback()\n");
if (job == NULL) {
log_debug_info(DEBUGL_WORKERS, 1, " * job is null, bailing\n");
return;
}
if (job->arg == NULL) {
log_debug_info(DEBUGL_WORKERS, 1, " * job arg is null, bailing\n");
return;
}
cj = (struct wproc_callback_job *)job->arg;
if (cj->callback == NULL) {
log_debug_info(DEBUGL_WORKERS, 1, " * callback_job callback is null, bailing\n");
return;
}
cj->callback(wpres, cj->data, val);
cj->callback = NULL;
}
static void destroy_job(struct wproc_job *job)
{
if (job == NULL) {
log_debug_info(DEBUGL_WORKERS, 1, " * destroy_job -> job is null, bailing\n");
return;
}
log_debug_info(DEBUGL_WORKERS, 0, "destroy_job(%d=%s)\n", job->type, wpjob_type_name(job->type));
switch (job->type) {
case WPJOB_CHECK:
free_check_result(job->arg);
free(job->arg);
break;
case WPJOB_NOTIFY:
case WPJOB_OCSP:
case WPJOB_OCHP:
free(job->arg);
break;
case WPJOB_GLOBAL_SVC_EVTHANDLER:
case WPJOB_SVC_EVTHANDLER:
case WPJOB_GLOBAL_HOST_EVTHANDLER:
case WPJOB_HOST_EVTHANDLER:
case WPJOB_HOST_PERFDATA:
case WPJOB_SVC_PERFDATA:
/* these require nothing special */
break;
case WPJOB_CALLBACK:
/* call with NULL result to make callback clean things up */
run_job_callback(job, NULL, 0);
break;
default:
logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: Unknown job type: %d\n", job->type);
break;
}
my_free(job->command);
if (job->wp != NULL) {
log_debug_info(DEBUGL_WORKERS, 1, " * removing job->wp\n");
fanout_remove(job->wp->jobs, job->id);
job->wp->jobs_running--;
}
loadctl.jobs_running--;
free(job);
}
static void fo_destroy_job(void *job)
{
destroy_job((struct wproc_job *)job);
}
static int wproc_is_alive(struct wproc_worker *wp)
{
if (wp == NULL || wp->pid <= 0) {
return 0;
}
if (kill(wp->pid, 0) == 0 && iobroker_is_registered(nagios_iobs, wp->sd))
return 1;
return 0;
}
static int wproc_destroy(struct wproc_worker *wp, int flags)
{
int i = 0;
int force = 0;
int self = 0;
if (!wp) {
return 0;
}
force = !!(flags & WPROC_FORCE);
self = getpid();
/* master retains workers through restarts */
if (self == nagios_pid && !force) {
return 0;
}
/* free all memory when either forcing or a worker called us */
iocache_destroy(wp->ioc);
wp->ioc = NULL;
my_free(wp->name);
fanout_destroy(wp->jobs, fo_destroy_job);
wp->jobs = NULL;
/* workers must never control other workers, so they return early */
if (self != nagios_pid) {
return 0;
}
/* kill(0, SIGKILL) equals suicide, so we avoid it */
if (wp->pid) {
kill(wp->pid, SIGKILL);
}
iobroker_close(nagios_iobs, wp->sd);
/* reap our possibly lost children */
while (waitpid(-1, &i, WNOHANG) > 0)
; /* do nothing */
free(wp);
return 0;
}
/* remove the worker list pointed to by to_remove */
static int remove_specialized(void *data)
{
if (data == to_remove) {
return DKHASH_WALK_REMOVE;
}
else if (to_remove == NULL) {
/* remove all specialised workers and their lists */
struct wproc_list *h = data;
int i;
for (i = 0; i < h->len; i++) {
/* not sure what WPROC_FORCE is actually for.
* Nagios does *not* retain workers across
* restarts, as stated in wproc_destroy?
*/
wproc_destroy(h->wps[i], WPROC_FORCE);
}
h->len = 0;
free(h->wps);
free(h);
return DKHASH_WALK_REMOVE;
}
return 0;
}
/* remove worker from job assignment list */
static void remove_worker(struct wproc_worker *worker)
{
unsigned int i = 0;
unsigned int j = 0;
struct wproc_list *wpl = worker->wp_list;
for (i = 0; i < wpl->len; i++) {
if (wpl->wps[i] == worker) {
continue;
}
wpl->wps[j++] = wpl->wps[i];
}
wpl->len = j;
if (specialized_workers == NULL || wpl->len > 0) {
return;
}
to_remove = wpl;
dkhash_walk_data(specialized_workers, remove_specialized);
}
/*
* This gets called from both parent and worker process, so
* we must take care not to blindly shut down everything here
*/
void free_worker_memory(int flags)
{
if (workers.wps) {
unsigned int i;
for (i = 0; i < workers.len; i++) {
if (!workers.wps[i])
continue;
wproc_destroy(workers.wps[i], flags);
workers.wps[i] = NULL;
}
my_free(workers.wps);
}
workers.len = 0;
workers.idx = 0;
to_remove = NULL;
dkhash_walk_data(specialized_workers, remove_specialized);
dkhash_destroy(specialized_workers);
/* Don't leave pointers to freed memory. */
specialized_workers = NULL;
}
static int str2timeval(char *str, struct timeval *tv)
{
char *ptr = NULL;
char *ptr2 = NULL;
tv->tv_sec = strtoul(str, &ptr, 10);
if (ptr == str) {
tv->tv_sec = tv->tv_usec = 0;
return -1;
}
if (*ptr == '.' || *ptr == ',') {
ptr2 = ptr + 1;
tv->tv_usec = strtoul(ptr2, &ptr, 10);
}
return 0;
}
static int handle_worker_check(wproc_result *wpres, struct wproc_worker *wp, struct wproc_job *job)
{
int result = ERROR;
check_result *cr = (check_result *)job->arg;
cr->start_time.tv_sec = wpres->start.tv_sec;
cr->start_time.tv_usec = wpres->start.tv_usec;
cr->finish_time.tv_sec = wpres->stop.tv_sec;
cr->finish_time.tv_usec = wpres->stop.tv_usec;
if (WIFEXITED(wpres->wait_status)) {
cr->return_code = WEXITSTATUS(wpres->wait_status);
}
else {
cr->return_code = STATE_UNKNOWN;
}
if (wpres->outstd && *wpres->outstd) {
cr->output = strdup(wpres->outstd);
}
else if (wpres->outerr) {
asprintf(&cr->output, "(No output on stdout) stderr: %s", wpres->outerr);
}
else {
cr->output = NULL;
}
cr->early_timeout = wpres->early_timeout;
cr->exited_ok = wpres->exited_ok;
cr->engine = NULL;
cr->source = wp->name;
process_check_result(cr);
free_check_result(cr);
return result;
}
/*
* parses a worker result. We do no strdup()'s here, so when
* kvv is destroyed, all references to strings will become
* invalid
*/
static int parse_worker_result(wproc_result *wpres, struct kvvec *kvv)
{
int i;
for (i = 0; i < kvv->kv_pairs; i++) {
struct wpres_key *k;
char *key, *value;
key = kvv->kv[i].key;
value = kvv->kv[i].value;
k = wpres_get_key(key, kvv->kv[i].key_len);
if (!k) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: Unrecognized result variable: (i=%d) %s=%s\n", i, key, value);
continue;
}
switch (k->code) {
case WPRES_job_id:
wpres->job_id = atoi(value);
break;
case WPRES_type:
wpres->type = atoi(value);
break;
case WPRES_command:
wpres->command = value;
break;
case WPRES_timeout:
wpres->timeout = atoi(value);
break;
case WPRES_wait_status:
wpres->wait_status = atoi(value);
break;
case WPRES_start:
str2timeval(value, &wpres->start);
break;
case WPRES_stop:
str2timeval(value, &wpres->stop);
break;
case WPRES_outstd:
wpres->outstd = value;
break;
case WPRES_outerr:
wpres->outerr = value;
break;
case WPRES_exited_ok:
wpres->exited_ok = atoi(value);
break;
case WPRES_error_msg:
wpres->exited_ok = FALSE;
wpres->error_msg = value;
break;
case WPRES_error_code:
wpres->exited_ok = FALSE;
wpres->error_code = atoi(value);
break;
case WPRES_runtime:
/* ignored */
break;
default:
logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: Recognized but unhandled result variable: %s=%s\n", key, value);
break;
}
}
return 0;
}
static int wproc_run_job(struct wproc_job *job, nagios_macros *mac);
static void fo_reassign_wproc_job(void *job_)
{
struct wproc_job *job = (struct wproc_job *)job_;
job->wp = get_worker(job->command);
if (job->wp != NULL) {
job->id = get_job_id(job->wp);
/* macros aren't used right now anyways */
wproc_run_job(job, NULL);
} else {
logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: Error: can't get_worker() in fo_reassign_wproc_job\n");
}
}
static int handle_worker_result(int sd, int events, void *arg)
{
wproc_object_job *oj = NULL;
char *buf, *error_reason = NULL;
unsigned long size;
int ret;
static struct kvvec kvv = KVVEC_INITIALIZER;
struct wproc_worker *wp = (struct wproc_worker *)arg;
if((ret = iocache_capacity(wp->ioc)) < 0) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: iocache_capacity() is %d for worker %s.\n", ret, wp->name);
}
ret = iocache_read(wp->ioc, wp->sd);
if (ret < 0) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: iocache_read() from %s returned %d: %s\n",
wp->name, ret, strerror(errno));
return 0;
} else if (ret == 0) {
logit(NSLOG_INFO_MESSAGE, TRUE, "wproc: Socket to worker %s broken, removing", wp->name);
wproc_num_workers_online--;
iobroker_unregister(nagios_iobs, sd);
if (workers.len <= 0) {
/* there aren't global workers left, we can't run any more checks
* we should try respawning a few of the standard ones
*/
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: All our workers are dead, we can't do anything!");
}
remove_worker(wp);
fanout_destroy(wp->jobs, fo_reassign_wproc_job);
wp->jobs = NULL;
wproc_destroy(wp, WPROC_FORCE);
return 0;
}
while ((buf = worker_ioc2msg(wp->ioc, &size, 0))) {
struct wproc_job *job;
wproc_result wpres;
/* log messages are handled first */
if (size > 5 && !memcmp(buf, "log=", 4)) {
logit(NSLOG_INFO_MESSAGE, TRUE, "wproc: %s: %s\n", wp->name, buf + 4);
continue;
}
/* for everything else we need to actually parse */
if (buf2kvvec_prealloc(&kvv, buf, size, '=', '\0', KVVEC_ASSIGN) <= 0) {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"wproc: Failed to parse key/value vector from worker response with len %lu. First kv=%s",
size, buf ? buf : "(NULL)");
continue;
}
memset(&wpres, 0, sizeof(wpres));
wpres.job_id = -1;
wpres.type = -1;
wpres.response = &kvv;
parse_worker_result(&wpres, &kvv);
job = get_job(wp, wpres.job_id);
if (!job) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: Job with id '%d' doesn't exist on %s.\n",
wpres.job_id, wp->name);
continue;
}
if (wpres.type != job->type) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: %s claims job %d is type %d, but we think it's type %d\n",
wp->name, job->id, wpres.type, job->type);
break;
}
oj = (wproc_object_job *)job->arg;
/*
* ETIME ("Timer expired") doesn't really happen
* on any modern systems, so we reuse it to mean
* "program timed out"
*/
if (wpres.error_code == ETIME) {
wpres.early_timeout = TRUE;
}
if (wpres.early_timeout) {
asprintf(&error_reason, "timed out after %.2fs", tv_delta_f(&wpres.start, &wpres.stop));
}
else if (WIFSIGNALED(wpres.wait_status)) {
asprintf(&error_reason, "died by signal %d%s after %.2f seconds",
WTERMSIG(wpres.wait_status),
WCOREDUMP(wpres.wait_status) ? " (core dumped)" : "",
tv_delta_f(&wpres.start, &wpres.stop));
}
else if (job->type != WPJOB_CHECK && WEXITSTATUS(wpres.wait_status) != 0) {
asprintf(&error_reason, "is a non-check helper but exited with return code %d",
WEXITSTATUS(wpres.wait_status));
}
if (error_reason) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: %s job %d from worker %s %s",
wpjob_type_name(job->type), job->id, wp->name, error_reason);
#ifdef DEBUG
/* The log below could leak sensitive information, such as
passwords, so only enable it if you really need it */
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: command: %s\n", job->command);
#endif
if (job->type != WPJOB_CHECK && oj) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: host=%s; service=%s; contact=%s\n",
oj->host_name ? oj->host_name : "(none)",
oj->service_description ? oj->service_description : "(none)",
oj->contact_name ? oj->contact_name : "(none)");
} else if (oj) {
struct check_result *cr = (struct check_result *)job->arg;
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: host=%s; service=%s;\n",
cr->host_name, cr->service_description);
}
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: early_timeout=%d; exited_ok=%d; wait_status=%d; error_code=%d;\n",
wpres.early_timeout, wpres.exited_ok, wpres.wait_status, wpres.error_code);
wproc_logdump_buffer(NSLOG_RUNTIME_ERROR, TRUE, "wproc: stderr", wpres.outerr);
wproc_logdump_buffer(NSLOG_RUNTIME_ERROR, TRUE, "wproc: stdout", wpres.outstd);
}
my_free(error_reason);
switch (job->type) {
case WPJOB_CHECK:
ret = handle_worker_check(&wpres, wp, job);
break;
case WPJOB_NOTIFY:
if (wpres.early_timeout) {
if (oj->service_description) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Notifying contact '%s' of service '%s' on host '%s' by command '%s' timed out after %.2f seconds\n",
oj->contact_name, oj->service_description,
oj->host_name, job->command,
tv2float(&wpres.runtime));
} else {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Notifying contact '%s' of host '%s' by command '%s' timed out after %.2f seconds\n",
oj->contact_name, oj->host_name,
job->command, tv2float(&wpres.runtime));
}
}
break;
case WPJOB_OCSP:
if (wpres.early_timeout) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: OCSP command '%s' for service '%s' on host '%s' timed out after %.2f seconds\n",
job->command, oj->service_description, oj->host_name,
tv2float(&wpres.runtime));
}
break;
case WPJOB_OCHP:
if (wpres.early_timeout) {
logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: OCHP command '%s' for host '%s' timed out after %.2f seconds\n",
job->command, oj->host_name, tv2float(&wpres.runtime));
}
break;
case WPJOB_GLOBAL_SVC_EVTHANDLER:
if (wpres.early_timeout) {
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE,
"Warning: Global service event handler command '%s' timed out after %.2f seconds\n",
job->command, tv2float(&wpres.runtime));
}
break;
case WPJOB_SVC_EVTHANDLER:
if (wpres.early_timeout) {
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE,
"Warning: Service event handler command '%s' timed out after %.2f seconds\n",
job->command, tv2float(&wpres.runtime));
}
break;
case WPJOB_GLOBAL_HOST_EVTHANDLER:
if (wpres.early_timeout) {
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE,
"Warning: Global host event handler command '%s' timed out after %.2f seconds\n",
job->command, tv2float(&wpres.runtime));
}
break;
case WPJOB_HOST_EVTHANDLER:
if (wpres.early_timeout) {
logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE,
"Warning: Host event handler command '%s' timed out after %.2f seconds\n",
job->command, tv2float(&wpres.runtime));
}
break;
case WPJOB_CALLBACK:
run_job_callback(job, &wpres, 0);
break;
case WPJOB_HOST_PERFDATA:
case WPJOB_SVC_PERFDATA:
/* these require nothing special */
break;
default:
logit(NSLOG_RUNTIME_WARNING, TRUE, "Worker %ld: Unknown jobtype: %d\n", (long)wp->pid, job->type);
break;
}
destroy_job(job);
}
return 0;
}
int workers_alive(void)
{
unsigned int i;
int alive = 0;
for (i = 0; i < workers.len; i++) {
if (wproc_is_alive(workers.wps[i]))
alive++;
}
return alive;
}
/* a service for registering workers */
static int register_worker(int sd, char *buf, unsigned int len)
{
int i, is_global = 1;
struct kvvec *info;
struct wproc_worker *worker;
logit(NSLOG_INFO_MESSAGE, TRUE, "wproc: Registry request: %s\n", buf);
if (!(worker = calloc(1, sizeof(*worker)))) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to allocate worker: %s\n", strerror(errno));
return 500;
}
info = buf2kvvec(buf, len, '=', ';', 0);
if (info == NULL) {
free(worker);
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to parse registration request\n");
return 500;
}
worker->sd = sd;
worker->ioc = iocache_create(1 * 1024 * 1024);
iobroker_unregister(nagios_iobs, sd);
iobroker_register(nagios_iobs, sd, worker, handle_worker_result);
for(i = 0; i < info->kv_pairs; i++) {
struct key_value *kv = &info->kv[i];
if (!strcmp(kv->key, "name")) {
worker->name = strdup(kv->value);
}
else if (!strcmp(kv->key, "pid")) {
worker->pid = atoi(kv->value);
}
else if (!strcmp(kv->key, "max_jobs")) {
worker->max_jobs = atoi(kv->value);
}
else if (!strcmp(kv->key, "plugin")) {
struct wproc_list *command_handlers;
is_global = 0;
if (!(command_handlers = dkhash_get(specialized_workers, kv->value, NULL))) {
command_handlers = calloc(1, sizeof(struct wproc_list));
command_handlers->wps = calloc(1, sizeof(struct wproc_worker**));
command_handlers->len = 1;
command_handlers->wps[0] = worker;
dkhash_insert(specialized_workers, strdup(kv->value), NULL, command_handlers);
}
else {
command_handlers->len++;
command_handlers->wps = realloc(command_handlers->wps, command_handlers->len * sizeof(struct wproc_worker**));
command_handlers->wps[command_handlers->len - 1] = worker;
}
worker->wp_list = command_handlers;
}
}
if (!worker->max_jobs) {
/*
* each worker uses two filedescriptors per job, one to
* connect to the master and about 13 to handle libraries
* and memory allocation, so this guesstimate shouldn't
* be too far off (for local workers, at least).
*/
worker->max_jobs = (iobroker_max_usable_fds() / 2) - 50;
}
worker->jobs = fanout_create(worker->max_jobs);
if (is_global) {
workers.len++;
workers.wps = realloc(workers.wps, workers.len * sizeof(struct wproc_worker *));
workers.wps[workers.len - 1] = worker;
worker->wp_list = &workers;
}
wproc_num_workers_online++;
kvvec_destroy(info, 0);
nsock_printf_nul(sd, "OK");
/* signal query handler to release its iocache for this one */
return QH_TAKEOVER;
}
static int wproc_query_handler(int sd, char *buf, unsigned int len)
{
char *space, *rbuf = NULL;
if (!*buf || !strcmp(buf, "help")) {
nsock_printf_nul(sd, "Control worker processes.\n"
"Valid commands:\n"
" wpstats Print general job information\n"
" register Register a new worker\n"
" can be name, pid, max_jobs and/or plugin.\n"
" There can be many plugin args.");
return 0;
}
if ((space = memchr(buf, ' ', len)) != NULL)
*space = 0;
rbuf = space ? space + 1 : buf;
len -= (unsigned long)rbuf - (unsigned long)buf;
if (!strcmp(buf, "register"))
return register_worker(sd, rbuf, len);
if (!strcmp(buf, "wpstats")) {
unsigned int i;
for (i = 0; i < workers.len; i++) {
struct wproc_worker *wp = workers.wps[i];
nsock_printf(sd, "name=%s;pid=%ld;jobs_running=%u;jobs_started=%u\n",
wp->name, (long)wp->pid,
wp->jobs_running, wp->jobs_started);
}
return 0;
}
return 400;
}
static int spawn_core_worker(void)
{
char *argvec[] = {nagios_binary_path, "--worker", qh_socket_path ? qh_socket_path : DEFAULT_QUERY_SOCKET, NULL};
int ret;
if ((ret = spawn_helper(argvec)) < 0)
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to launch core worker: %s\n", strerror(errno));
else
wproc_num_workers_spawned++;
return ret;
}
int get_desired_workers(int desired_workers) {
if (desired_workers <= 0) {
int cpus = online_cpus(); /* Always at least 1 CPU. */
if (desired_workers < 0) {
/* @note This is an undocumented case of questionable utility, and
* should be removed. Users reading this note have been warned. */
desired_workers = cpus - desired_workers;
/* desired_workers is now > 0. */
} else {
desired_workers = cpus * 1.5;
if (desired_workers < 4) {
/* Use at least 4 workers when autocalculating so we have some
* level of parallelism. */
desired_workers = 4;
} else if (desired_workers > 48) {
/* Limit the autocalculated workers so we don't spawn too many
* on systems with many schedulable cores (>32). */
desired_workers = 48;
}
}
}
return desired_workers;
}
/* if this function is updated, the function rlimit_problem_detection()
must be updated as well */
int init_workers(int desired_workers)
{
specialized_workers = dkhash_create(512);
if (!specialized_workers) {
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to allocate specialized worker table.\n");
return -1;
}
/* Register our query handler before launching workers, so other workers
* can join us whenever they're ready. */
if (!qh_register_handler("wproc", "Worker process management and info", 0, wproc_query_handler))
logit(NSLOG_INFO_MESSAGE, TRUE, "wproc: Successfully registered manager as @wproc with query handler\n");
else
logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to register manager with query handler\n");
desired_workers = get_desired_workers(desired_workers);
wproc_num_workers_desired = desired_workers;
if (workers_alive() == desired_workers)
return 0;
/* can't shrink the number of workers (yet) */
if (desired_workers < (int)workers.len)
return -1;
while (desired_workers-- > 0) {
int worker_pid = spawn_core_worker();
log_debug_info(DEBUGL_WORKERS, 2, "Spawned new worker with pid: (%d)\n", worker_pid);
}
return 0;
}
/*
* Handles adding the command and macros to the kvvec,
* as well as shipping the command off to a designated
* worker
*/
static int wproc_run_job(struct wproc_job *job, nagios_macros *mac)
{
static struct kvvec kvv = KVVEC_INITIALIZER;
struct kvvec_buf *kvvb = NULL;
struct kvvec *env_kvvp = NULL;
struct kvvec_buf *env_kvvb = NULL;
struct wproc_worker *wp = NULL;
int ret = OK;
int result = OK;
ssize_t written = 0;
log_debug_info(DEBUGL_WORKERS, 1, "wproc_run_job()\n");
if (job == NULL) {
log_debug_info(DEBUGL_WORKERS, 1, " * failed because job was null\n");
return ERROR;
}
if (job->wp == NULL) {
log_debug_info(DEBUGL_WORKERS, 1, " * failed because job worker process was null\n");
return ERROR;
}
wp = job->wp;
/* job_id, type, command and timeout */
if (!kvvec_init(&kvv, 4)) {
return ERROR;
}
kvvec_addkv(&kvv, "job_id", (char *)mkstr("%d", job->id));
kvvec_addkv(&kvv, "type", (char *)mkstr("%d", job->type));
kvvec_addkv(&kvv, "command", job->command);
kvvec_addkv(&kvv, "timeout", (char *)mkstr("%u", job->timeout));
/* Add the macro environment variables */
if (mac != NULL) {
env_kvvp = macros_to_kvv(mac);
if (env_kvvp != NULL) {
env_kvvb = kvvec2buf(env_kvvp, '=', '\n', 0);
if (env_kvvb == NULL) {
kvvec_destroy(env_kvvp, KVVEC_FREE_KEYS);
}
else {
/* no reason to call strlen("env")
when we know it's 3 characters */
kvvec_addkv_wlen(&kvv, "env", 3, env_kvvb->buf, env_kvvb->buflen);
}
}
}
kvvb = build_kvvec_buf(&kvv);
/* ret = write(wp->sd, kvvb->buf, kvvb->bufsize); */
ret = nwrite(wp->sd, kvvb->buf, kvvb->bufsize, &written);
if (ret != (int) kvvb->bufsize) {
logit(NSLOG_RUNTIME_ERROR, TRUE,
"wproc: '%s' seems to be choked. ret = %d; bufsize = %lu: written = %lu; errno = %d (%s)\n",
wp->name, ret, kvvb->bufsize, (long unsigned int) written, errno, strerror(errno));
destroy_job(job);
result = ERROR;
} else {
wp->jobs_running++;
wp->jobs_started++;
loadctl.jobs_running++;
}
if (env_kvvp != NULL) {
kvvec_destroy(env_kvvp, KVVEC_FREE_KEYS);
}
if (env_kvvb != NULL) {
free(env_kvvb->buf);
free(env_kvvb);
}
free(kvvb->buf);
free(kvvb);
return result;
}
static wproc_object_job *create_object_job(char *cname, char *hname, char *sdesc)
{
wproc_object_job *oj;
oj = calloc(1, sizeof(*oj));
if (oj) {
oj->host_name = hname;
if (cname)
oj->contact_name = cname;
if (sdesc)
oj->service_description = sdesc;
}
return oj;
}
int wproc_notify(char *cname, char *hname, char *sdesc, char *cmd, nagios_macros *mac)
{
struct wproc_job *job;
wproc_object_job *oj;
if (!(oj = create_object_job(cname, hname, sdesc)))
return ERROR;
job = create_job(WPJOB_NOTIFY, oj, notification_timeout, cmd);
return wproc_run_job(job, mac);
}
int wproc_run_service_job(int jtype, int timeout, service *svc, char *cmd, nagios_macros *mac)
{
struct wproc_job *job;
wproc_object_job *oj;
if (!(oj = create_object_job(NULL, svc->host_name, svc->description)))
return ERROR;
job = create_job(jtype, oj, timeout, cmd);
return wproc_run_job(job, mac);
}
int wproc_run_host_job(int jtype, int timeout, host *hst, char *cmd, nagios_macros *mac)
{
struct wproc_job *job;
wproc_object_job *oj;
if (!(oj = create_object_job(NULL, hst->name, NULL)))
return ERROR;
job = create_job(jtype, oj, timeout, cmd);
return wproc_run_job(job, mac);
}
int wproc_run_check(check_result *cr, char *cmd, nagios_macros *mac)
{
struct wproc_job *job;
int timeout;
if (cr->service_description)
timeout = service_check_timeout;
else
timeout = host_check_timeout;
job = create_job(WPJOB_CHECK, cr, timeout, cmd);
return wproc_run_job(job, mac);
}
int wproc_run(int jtype, char *cmd, int timeout, nagios_macros *mac)
{
struct wproc_job *job;
job = create_job(jtype, NULL, timeout, cmd);
return wproc_run_job(job, mac);
}
int wproc_run_callback(char *cmd, int timeout,
void (*cb)(struct wproc_result *, void *, int), void *data,
nagios_macros *mac)
{
struct wproc_job *job;
struct wproc_callback_job *cj;
if (!(cj = calloc(1, sizeof(*cj))))
return ERROR;
cj->callback = cb;
cj->data = data;
job = create_job(WPJOB_CALLBACK, cj, timeout, cmd);
return wproc_run_job(job, mac);
}
nagios-4.4.6/base/wp-phash.c 0000664 0000000 0000000 00000007435 13652113235 0015624 0 ustar 00root root 0000000 0000000 #define WPRES_type 4
#define WPRES_outerr 6
#define WPRES_timeout 7
#define WPRES_ru_nswap 8
#define WPRES_error_msg 9
#define WPRES_error_code 10
#define WPRES_ru_nsignals 11
#define WPRES_command 12
#define WPRES_ru_majflt 14
#define WPRES_start 15
#define WPRES_outstd 16
#define WPRES_ru_stime 18
#define WPRES_exited_ok 19
#define WPRES_ru_inblock 20
#define WPRES_job_id 21
#define WPRES_ru_minflt 24
#define WPRES_ru_oublock 25
#define WPRES_wait_status 26
#define WPRES_runtime 27
#define WPRES_stop 29
#define WPRES_ru_utime 33
/* C code produced by gperf version 3.0.4 */
/* Command-line: gperf -H wp_phash wproc-strings */
/* Computed positions: -k'4-5' */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
/* The character set is not based on ISO-646. */
error "gperf generated tables don't work with this execution character set. Please report a bug to ."
#endif
static inline unsigned int
wp_phash(register const char *str, register unsigned int len)
{
/* the last 136 entries have been cut, as we don't need them */
static unsigned char asso_values[256] =
{
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 5, 34, 0, 34, 34,
34, 0, 34, 34, 34, 10, 34, 34, 34, 5,
0, 0, 25, 34, 0, 0, 10, 15, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
34, 34, 34, 34, 34, 34,
};
register int hval = len;
switch (hval) {
default:
hval += asso_values[(unsigned char)str[4]];
/*FALLTHROUGH*/
case 4:
hval += asso_values[(unsigned char)str[3]];
break;
}
return hval;
}
nagios-4.4.6/base/wpres-phash.h 0000664 0000000 0000000 00000022754 13652113235 0016344 0 ustar 00root root 0000000 0000000 /* C code produced by gperf version 3.0.3 */
/* Command-line: gperf -S 1 -t -H wpres_key_phash -N wpres_get_key wpres.gperf */
/* Computed positions: -k'4-5,7' */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
/* The character set is not based on ISO-646. */
error "gperf generated tables don't work with this execution character set. Please report a bug to ."
#endif
#line 1 "wpres.gperf"
enum {
WPRES_job_id,
WPRES_type,
WPRES_command,
WPRES_timeout,
WPRES_wait_status,
WPRES_start,
WPRES_stop,
WPRES_outstd,
WPRES_outerr,
WPRES_exited_ok,
WPRES_error_msg,
WPRES_error_code,
WPRES_runtime,
WPRES_ru_utime,
WPRES_ru_stime,
WPRES_ru_maxrss,
WPRES_ru_ixrss,
WPRES_ru_idrss,
WPRES_ru_isrss,
WPRES_ru_minflt,
WPRES_ru_majflt,
WPRES_ru_nswap,
WPRES_ru_inblock,
WPRES_ru_oublock,
WPRES_ru_msgsnd,
WPRES_ru_msgrcv,
WPRES_ru_nsignals,
WPRES_ru_nvcsw,
WPRES_ru_nivcsw,
};
#include /* for strcmp() */
#line 35 "wpres.gperf"
struct wpres_key {
const char *name;
int code;
};
#define TOTAL_KEYWORDS 29
#define MIN_WORD_LENGTH 4
#define MAX_WORD_LENGTH 11
#define MIN_HASH_VALUE 4
#define MAX_HASH_VALUE 64
/* maximum key range = 61, duplicates = 0 */
#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static unsigned int
wpres_key_phash (str, len)
register const char *str;
register unsigned int len;
{
static unsigned char asso_values[] =
{
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 15, 65, 25, 65, 3,
10, 0, 30, 0, 65, 0, 65, 65, 0, 0,
0, 20, 5, 65, 0, 5, 0, 0, 30, 65,
15, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
65, 65, 65, 65, 65, 65
};
register int hval = len;
switch (hval)
{
default:
hval += asso_values[(unsigned char)str[6]];
/*FALLTHROUGH*/
case 6:
case 5:
hval += asso_values[(unsigned char)str[4]];
/*FALLTHROUGH*/
case 4:
hval += asso_values[(unsigned char)str[3]];
break;
}
return hval;
}
#ifdef __GNUC__
__inline
#ifdef __GNUC_STDC_INLINE__
__attribute__ ((__gnu_inline__))
#endif
#endif
struct wpres_key *
wpres_get_key (str, len)
register const char *str;
register unsigned int len;
{
static struct wpres_key wordlist[] =
{
#line 41 "wpres.gperf"
{"type", WPRES_type},
#line 45 "wpres.gperf"
{"start", WPRES_start},
#line 48 "wpres.gperf"
{"outerr", WPRES_outerr},
#line 52 "wpres.gperf"
{"runtime", WPRES_runtime},
#line 53 "wpres.gperf"
{"ru_utime", WPRES_ru_utime},
#line 46 "wpres.gperf"
{"stop", WPRES_stop},
#line 62 "wpres.gperf"
{"ru_inblock", WPRES_ru_inblock},
#line 47 "wpres.gperf"
{"outstd", WPRES_outstd},
#line 68 "wpres.gperf"
{"ru_nivcsw", WPRES_ru_nivcsw},
#line 54 "wpres.gperf"
{"ru_stime", WPRES_ru_stime},
#line 65 "wpres.gperf"
{"ru_msgrcv", WPRES_ru_msgrcv},
#line 66 "wpres.gperf"
{"ru_nsignals", WPRES_ru_nsignals},
#line 58 "wpres.gperf"
{"ru_isrss", WPRES_ru_isrss},
#line 64 "wpres.gperf"
{"ru_msgsnd", WPRES_ru_msgsnd},
#line 40 "wpres.gperf"
{"job_id", WPRES_job_id},
#line 57 "wpres.gperf"
{"ru_idrss", WPRES_ru_idrss},
#line 49 "wpres.gperf"
{"exited_ok", WPRES_exited_ok},
#line 44 "wpres.gperf"
{"wait_status", WPRES_wait_status},
#line 43 "wpres.gperf"
{"timeout", WPRES_timeout},
#line 56 "wpres.gperf"
{"ru_ixrss", WPRES_ru_ixrss},
#line 50 "wpres.gperf"
{"error_msg", WPRES_error_msg},
#line 63 "wpres.gperf"
{"ru_oublock", WPRES_ru_oublock},
#line 51 "wpres.gperf"
{"error_code", WPRES_error_code},
#line 55 "wpres.gperf"
{"ru_maxrss", WPRES_ru_maxrss},
#line 61 "wpres.gperf"
{"ru_nswap", WPRES_ru_nswap},
#line 59 "wpres.gperf"
{"ru_minflt", WPRES_ru_minflt},
#line 42 "wpres.gperf"
{"command", WPRES_command},
#line 67 "wpres.gperf"
{"ru_nvcsw", WPRES_ru_nvcsw},
#line 60 "wpres.gperf"
{"ru_majflt", WPRES_ru_majflt}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
register int key = wpres_key_phash (str, len);
if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
{
register struct wpres_key *resword;
switch (key - 4)
{
case 0:
resword = &wordlist[0];
goto compare;
case 1:
resword = &wordlist[1];
goto compare;
case 2:
resword = &wordlist[2];
goto compare;
case 3:
resword = &wordlist[3];
goto compare;
case 4:
resword = &wordlist[4];
goto compare;
case 5:
resword = &wordlist[5];
goto compare;
case 6:
resword = &wordlist[6];
goto compare;
case 7:
resword = &wordlist[7];
goto compare;
case 8:
resword = &wordlist[8];
goto compare;
case 9:
resword = &wordlist[9];
goto compare;
case 10:
resword = &wordlist[10];
goto compare;
case 12:
resword = &wordlist[11];
goto compare;
case 14:
resword = &wordlist[12];
goto compare;
case 15:
resword = &wordlist[13];
goto compare;
case 17:
resword = &wordlist[14];
goto compare;
case 19:
resword = &wordlist[15];
goto compare;
case 20:
resword = &wordlist[16];
goto compare;
case 22:
resword = &wordlist[17];
goto compare;
case 23:
resword = &wordlist[18];
goto compare;
case 24:
resword = &wordlist[19];
goto compare;
case 25:
resword = &wordlist[20];
goto compare;
case 26:
resword = &wordlist[21];
goto compare;
case 29:
resword = &wordlist[22];
goto compare;
case 30:
resword = &wordlist[23];
goto compare;
case 34:
resword = &wordlist[24];
goto compare;
case 35:
resword = &wordlist[25];
goto compare;
case 38:
resword = &wordlist[26];
goto compare;
case 39:
resword = &wordlist[27];
goto compare;
case 60:
resword = &wordlist[28];
goto compare;
}
return 0;
compare:
{
register const char *s = resword->name;
if (*str == *s && !strcmp (str + 1, s + 1))
return resword;
}
}
}
return 0;
}
nagios-4.4.6/base/wpres.gperf 0000664 0000000 0000000 00000002460 13652113235 0016107 0 ustar 00root root 0000000 0000000 %{
enum {
WPRES_job_id,
WPRES_type,
WPRES_command,
WPRES_timeout,
WPRES_wait_status,
WPRES_start,
WPRES_stop,
WPRES_outstd,
WPRES_outerr,
WPRES_exited_ok,
WPRES_error_msg,
WPRES_error_code,
WPRES_runtime,
WPRES_ru_utime,
WPRES_ru_stime,
WPRES_ru_maxrss,
WPRES_ru_ixrss,
WPRES_ru_idrss,
WPRES_ru_isrss,
WPRES_ru_minflt,
WPRES_ru_majflt,
WPRES_ru_nswap,
WPRES_ru_inblock,
WPRES_ru_oublock,
WPRES_ru_msgsnd,
WPRES_ru_msgrcv,
WPRES_ru_nsignals,
WPRES_ru_nvcsw,
WPRES_ru_nivcsw,
};
#include /* for strcmp() */
%}
struct wpres_key {
const char *name;
int code;
};
%%
job_id, WPRES_job_id
type, WPRES_type
command, WPRES_command
timeout, WPRES_timeout
wait_status, WPRES_wait_status
start, WPRES_start
stop, WPRES_stop
outstd, WPRES_outstd
outerr, WPRES_outerr
exited_ok, WPRES_exited_ok
error_msg, WPRES_error_msg
error_code, WPRES_error_code
runtime, WPRES_runtime
ru_utime, WPRES_ru_utime
ru_stime, WPRES_ru_stime
ru_maxrss, WPRES_ru_maxrss
ru_ixrss, WPRES_ru_ixrss
ru_idrss, WPRES_ru_idrss
ru_isrss, WPRES_ru_isrss
ru_minflt, WPRES_ru_minflt
ru_majflt, WPRES_ru_majflt
ru_nswap, WPRES_ru_nswap
ru_inblock, WPRES_ru_inblock
ru_oublock, WPRES_ru_oublock
ru_msgsnd, WPRES_ru_msgsnd
ru_msgrcv, WPRES_ru_msgrcv
ru_nsignals, WPRES_ru_nsignals
ru_nvcsw, WPRES_ru_nvcsw
ru_nivcsw, WPRES_ru_nivcsw
nagios-4.4.6/cgi/ 0000775 0000000 0000000 00000000000 13652113235 0013550 5 ustar 00root root 0000000 0000000 nagios-4.4.6/cgi/.gitignore 0000664 0000000 0000000 00000000023 13652113235 0015533 0 ustar 00root root 0000000 0000000 *.o
*.cgi
Makefile
nagios-4.4.6/cgi/Makefile.in 0000664 0000000 0000000 00000014773 13652113235 0015631 0 ustar 00root root 0000000 0000000 ###############################
# Makefile for Nagios CGIs
#
###############################
# Source code directories
SRC_COMMON=../common
SRC_INCLUDE=../include
SRC_XDATA=../xdata
SRC_LIB=../lib
prefix=@prefix@
exec_prefix=@exec_prefix@
LOGDIR=@localstatedir@
CFGDIR=@sysconfdir@
BINDIR=@bindir@
CGIDIR=@cgibindir@
HTMLDIR=@webdir@
INSTALL=@INSTALL@
INSTALL_OPTS=@INSTALL_OPTS@
COMMAND_OPTS=@COMMAND_OPTS@
STRIP=@STRIP@
CGIEXTRAS=@CGIEXTRAS@
CP=@CP@
CC=@CC@
CFLAGS=-Wall -I.. @CFLAGS@ @DEFS@ -DNSCGI
JSONFLAGS=-DJSON_NAGIOS_4X
# 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=archivejson.cgi avail.cgi cmd.cgi config.cgi extinfo.cgi history.cgi notifications.cgi objectjson.cgi outages.cgi showlog.cgi status.cgi statusjson.cgi statuswml.cgi summary.cgi tac.cgi $(CGIEXTRAS)
# 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 $(SNPRINTF_O) $(ODATALIBS) $(SDATALIBS) $(SRC_LIB)/libnagios.a
CGIHDRS=$(SRC_INCLUDE)/config.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/locations.h
CGIDEPS=$(CGILIBS) $(ODATADEPS) $(SDATADEPS) $(SRC_LIB)/libnagios.a
MATHLIBS=-lm
GDLIBS=@GDLIBS@
all cgis: $(CGIS)
$(CGILIBS): $(CGIHDRS)
######## REQUIRED LIBRARIES ##########
$(SRC_LIB)/libnagios.a:
$(MAKE) -C $(SRC_LIB)
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)/xodtemplate.c $(SRC_XDATA)/xodtemplate.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xodtemplate.c
statusdata-cgi.o: $(SRC_COMMON)/statusdata.c $(SRC_INCLUDE)/statusdata.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/statusdata.c
xstatusdata-cgi.o: $(SRC_XDATA)/xsddefault.c $(SRC_XDATA)/xsddefault.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xsddefault.c
comments-cgi.o: $(SRC_COMMON)/comments.c $(SRC_INCLUDE)/comments.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/comments.c
downtime-cgi.o: $(SRC_COMMON)/downtime.c $(SRC_INCLUDE)/downtime.h
$(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/downtime.c
$(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)
########## JSON CGIS ##########
jsonutils.o: jsonutils.c $(SRC_INCLUDE)/jsonutils.h
$(CC) $(CFLAGS) $(JSONFLAGS) -c -o $@ jsonutils.c
archiveutils.o: archiveutils.c $(SRC_INCLUDE)/archiveutils.h
$(CC) $(CFLAGS) $(JSONFLAGS) -c -o $@ archiveutils.c
archivejson.cgi: archivejson.c $(CGIDEPS) archiveutils.o jsonutils.o $(SRC_INCLUDE)/archivejson.h
$(CC) $(CFLAGS) $(JSONFLAGS) $(LDFLAGS) -o $@ archivejson.c $(CGILIBS) archiveutils.o jsonutils.o $(LIBS)
objectjson.cgi: objectjson.c $(CGIDEPS) jsonutils.o $(SRC_INCLUDE)/objectjson.h
$(CC) $(CFLAGS) $(JSONFLAGS) $(LDFLAGS) -o $@ objectjson.c $(CGILIBS) jsonutils.o $(LIBS)
statusjson.cgi: statusjson.c $(CGIDEPS) jsonutils.o $(SRC_INCLUDE)/statusjson.h
$(CC) $(CFLAGS) $(JSONFLAGS) $(LDFLAGS) -o $@ statusjson.c $(CGILIBS) jsonutils.o $(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
install-unstripped:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CGIDIR)
for file in *.cgi; do \
$(INSTALL) -m 775 $(INSTALL_OPTS) $$file $(DESTDIR)$(CGIDIR); \
done
install-basic:
$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CGIDIR)
for file in *.cgi; do \
$(INSTALL) -s -m 775 $(INSTALL_OPTS) $$file $(DESTDIR)$(CGIDIR); \
done
.PHONY: libnagios
nagios-4.4.6/cgi/archivejson.c 0000664 0000000 0000000 00000456154 13652113235 0016246 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* ARCHIVEJSON.C - Nagios CGI for returning JSON-formatted archive data
*
* Copyright (c) 2013 Nagios Enterprises, LLC
* Last Modified: 04-13-2013
*
* 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/statusdata.h"
#include "../include/cgiutils.h"
#include "../include/getcgi.h"
#include "../include/cgiauth.h"
#include "../include/jsonutils.h"
#include "../include/archiveutils.h"
#include "../include/archivejson.h"
#define THISCGI "archivejson.cgi"
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
extern char main_config_file[MAX_FILENAME_LENGTH];
extern int log_rotation_method;
extern char *status_file;
extern host *host_list;
extern hostgroup *hostgroup_list;
extern service *service_list;
extern servicegroup *servicegroup_list;
#if 0
extern contact *contact_list;
extern contactgroup *contactgroup_list;
extern timeperiod *timeperiod_list;
extern command *command_list;
extern servicedependency *servicedependency_list;
extern serviceescalation *serviceescalation_list;
extern hostdependency *hostdependency_list;
extern hostescalation *hostescalation_list;
#endif
void document_header();
void document_footer(void);
void init_cgi_data(archive_json_cgi_data *);
int process_cgivars(json_object *, archive_json_cgi_data *, time_t);
void free_cgi_data(archive_json_cgi_data *);
int validate_arguments(json_object *, archive_json_cgi_data *, time_t);
authdata current_authdata;
const string_value_mapping valid_queries[] = {
{ "help", ARCHIVE_QUERY_HELP,
"Display help for this CGI" },
{ "alertcount", ARCHIVE_QUERY_ALERTCOUNT,
"Return the number of alerts" },
{ "alertlist", ARCHIVE_QUERY_ALERTLIST,
"Return a list of alerts" },
{ "notificationcount", ARCHIVE_QUERY_NOTIFICATIONCOUNT,
"Return the number of notifications" },
{ "notificationlist", ARCHIVE_QUERY_NOTIFICATIONLIST,
"Return a list of notifications" },
{ "statechangelist", ARCHIVE_QUERY_STATECHANGELIST,
"Return a list of state changes" },
{ "availability", ARCHIVE_QUERY_AVAILABILITY,
"Return an availability report" },
{ NULL, -1, NULL },
};
static const int query_status[][2] = {
{ ARCHIVE_QUERY_HELP, QUERY_STATUS_RELEASED },
{ ARCHIVE_QUERY_ALERTCOUNT, QUERY_STATUS_RELEASED },
{ ARCHIVE_QUERY_ALERTLIST, QUERY_STATUS_RELEASED },
{ ARCHIVE_QUERY_NOTIFICATIONCOUNT, QUERY_STATUS_RELEASED },
{ ARCHIVE_QUERY_NOTIFICATIONLIST, QUERY_STATUS_RELEASED },
{ ARCHIVE_QUERY_STATECHANGELIST, QUERY_STATUS_RELEASED },
{ ARCHIVE_QUERY_AVAILABILITY, QUERY_STATUS_RELEASED },
{ -1, -1 },
};
const string_value_mapping valid_object_types[] = {
{ "host", AU_OBJTYPE_HOST, "Host" },
{ "service", AU_OBJTYPE_SERVICE, "Service" },
{ NULL, -1, NULL },
};
const string_value_mapping valid_availability_object_types[] = {
{ "hosts", AU_OBJTYPE_HOST, "Hosts" },
{ "hostgroups", AU_OBJTYPE_HOSTGROUP, "Hostgroups" },
{ "services", AU_OBJTYPE_SERVICE, "Services" },
{ "servicegroups", AU_OBJTYPE_SERVICEGROUP, "Servicegroups" },
{ NULL, -1, NULL },
};
const string_value_mapping valid_state_types[] = {
{ "hard", AU_STATETYPE_HARD, "Hard" },
{ "soft", AU_STATETYPE_SOFT, "Soft" },
{ NULL, -1, NULL },
};
const string_value_mapping valid_states[] = {
{ "no_data", AU_STATE_NO_DATA, "No Data" },
{ "host_up", AU_STATE_HOST_UP, "Host Up" },
{ "host_down", AU_STATE_HOST_DOWN, "Host Down" },
{ "host_unreachable", AU_STATE_HOST_UNREACHABLE, "Host Unreachable" },
{ "service_ok", AU_STATE_SERVICE_OK, "Service OK" },
{ "service_warning", AU_STATE_SERVICE_WARNING, "Service Warning" },
{ "service_critical", AU_STATE_SERVICE_CRITICAL, "Service Critical" },
{ "service_unknown", AU_STATE_SERVICE_UNKNOWN, "Service Unknown" },
{ "program_start", AU_STATE_PROGRAM_START, "Program Start" },
{ "program_end", AU_STATE_PROGRAM_END, "Program End" },
{ "downtime_start", AU_STATE_DOWNTIME_START, "Downtime Start" },
{ "downtime_end", AU_STATE_DOWNTIME_END, "Downtime End" },
};
const string_value_mapping valid_host_states[] = {
{ "up", AU_STATE_HOST_UP, "Up" },
{ "down", AU_STATE_HOST_DOWN, "Down" },
{ "unreachable", AU_STATE_HOST_UNREACHABLE, "Unreachable" },
{ NULL, -1, NULL },
};
const string_value_mapping valid_initial_host_states[] = {
{ "up", AU_STATE_HOST_UP, "Up" },
{ "down", AU_STATE_HOST_DOWN, "Down" },
{ "unreachable", AU_STATE_HOST_UNREACHABLE, "Unreachable" },
{ "current", AU_STATE_CURRENT_STATE, "Current State" },
{ NULL, -1, NULL },
};
const string_value_mapping valid_service_states[] = {
{ "ok", AU_STATE_SERVICE_OK, "Ok" },
{ "warning", AU_STATE_SERVICE_WARNING, "Warning" },
{ "critical", AU_STATE_SERVICE_CRITICAL, "Critical" },
{ "unknown", AU_STATE_SERVICE_UNKNOWN, "Unknown" },
{ NULL, -1, NULL },
};
const string_value_mapping valid_initial_service_states[] = {
{ "ok", AU_STATE_SERVICE_OK, "Ok" },
{ "warning", AU_STATE_SERVICE_WARNING, "Warning" },
{ "critical", AU_STATE_SERVICE_CRITICAL, "Critical" },
{ "unknown", AU_STATE_SERVICE_UNKNOWN, "Unknown" },
{ "current", AU_STATE_CURRENT_STATE, "Current State" },
{ NULL, -1, NULL },
};
const string_value_mapping valid_host_notification_types[] = {
{ "nodata", AU_NOTIFICATION_NO_DATA,
"No Data" },
{ "down", AU_NOTIFICATION_HOST_DOWN,
"Host Down" },
{ "unreachable", AU_NOTIFICATION_HOST_UNREACHABLE,
"Host Unreachable" },
{ "recovery", AU_NOTIFICATION_HOST_RECOVERY,
"Host Recovery" },
{ "hostcustom", AU_NOTIFICATION_HOST_CUSTOM,
"Host Custom" },
{ "hostack", AU_NOTIFICATION_HOST_ACK,
"Host Acknowledgement" },
{ "hostflapstart", AU_NOTIFICATION_HOST_FLAPPING_START,
"Host Flapping Start" },
{ "hostflapstop", AU_NOTIFICATION_HOST_FLAPPING_STOP,
"Host Flapping Stop" },
{ NULL, -1, NULL },
};
const string_value_mapping valid_service_notification_types[] = {
{ "nodata", AU_NOTIFICATION_NO_DATA,
"No Data" },
{ "critical", AU_NOTIFICATION_SERVICE_CRITICAL,
"Service Critical" },
{ "warning", AU_NOTIFICATION_SERVICE_WARNING,
"Service Warning" },
{ "recovery", AU_NOTIFICATION_SERVICE_RECOVERY,
"Service Recovery" },
{ "custom", AU_NOTIFICATION_SERVICE_CUSTOM,
"Service Custom" },
{ "serviceack", AU_NOTIFICATION_SERVICE_ACK,
"Service Acknowledgement" },
{ "serviceflapstart", AU_NOTIFICATION_SERVICE_FLAPPING_START,
"Service Flapping Start" },
{ "serviceflapstop", AU_NOTIFICATION_SERVICE_FLAPPING_STOP,
"Service Flapping Stop" },
{ "unknown", AU_NOTIFICATION_SERVICE_UNKNOWN,
"Service Unknown" },
{ NULL, -1, NULL },
};
option_help archive_json_help[] = {
{
"query",
"Query",
"enumeration",
{ "all", NULL },
{ NULL },
NULL,
"Specifies the type of query to be executed.",
valid_queries
},
{
"formatoptions",
"Format Options",
"list",
{ NULL },
{ "all", NULL },
NULL,
"Specifies the formatting options to be used when displaying the results. Multiple options are allowed and are separated by a plus (+) sign..",
svm_format_options
},
{
"start",
"Start",
"integer",
{ NULL },
{ "alertlist", "notificationlist", "statechangelist", NULL },
NULL,
"Specifies the index (zero-based) of the first object in the list to be returned.",
NULL
},
{
"count",
"Count",
"integer",
{ NULL },
{ "alertlist", "notificationlist", "statechangelist", NULL },
NULL,
"Specifies the number of objects in the list to be returned.",
NULL
},
{
"dateformat",
"Date Format",
"string",
{ NULL },
{ "all", NULL },
NULL,
"strftime format string for values of type time_t. In the absence of a format, the Javascript default format of the number of milliseconds since the beginning of the Unix epoch is used. Because of URL encoding, percent signs must be encoded as %25 and a space must be encoded as a plus (+) sign.",
NULL
},
{
"objecttypes",
"Object Types",
"list",
{ NULL },
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
NULL },
NULL,
"Type(s) of object to be included in query results.",
valid_object_types
},
{
"objecttype",
"Object Type",
"enumeration",
{ "statechangelist", NULL },
{ NULL },
NULL,
"Type of object to be included in query results.",
valid_object_types
},
{
"availabilityobjecttype",
"Availability Object Type",
"enumeration",
{ "availability", NULL },
{ NULL },
NULL,
"Type of object to be included in query results.",
valid_availability_object_types
},
{
"statetypes",
"State Types",
"list",
{ NULL },
{ "alertcount", "alertlist", "statechangelist", "availability", NULL },
NULL,
"Type(s) of states to be included in query results.",
valid_state_types
},
{
"hoststates",
"Host States",
"list",
{ NULL },
{ "alertcount", "alertlist", NULL },
NULL,
"Host states to be included in query results.",
valid_host_states
},
{
"servicestates",
"Service States",
"list",
{ NULL },
{ "alertcount", "alertlist", NULL },
NULL,
"Service states to be included in query results.",
valid_service_states
},
{
"hostnotificationtypes",
"Host Notification Types",
"list",
{ NULL },
{ "notificationcount", "notificationlist", NULL },
NULL,
"Host notification types to be included in query results.",
valid_host_notification_types
},
{
"servicenotificationtypes",
"Service Notification Types",
"list",
{ NULL },
{ "notificationcount", "notificationlist", NULL },
NULL,
"Service notification types to be included in query results.",
valid_service_notification_types
},
{
"parenthost",
"Parent Host",
"nagios:objectjson/hostlist",
{ NULL },
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
NULL },
NULL,
"Limits the hosts or services returned to those whose host parent is specified. A value of 'none' returns all hosts or services reachable directly by the Nagios core host.",
parent_host_extras
},
{
"childhost",
"Child Host",
"nagios:objectjson/hostlist",
{ NULL },
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
NULL },
NULL,
"Limits the hosts or services returned to those whose having the host specified as a child host. A value of 'none' returns all hosts or services with no child hosts.",
child_host_extras
},
{
"hostname",
"Host Name",
"nagios:objectjson/hostlist",
{ "statechangelist", NULL },
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
"availability", NULL },
NULL,
"Name for the host requested. For availability reports if the "
"availability object type is hosts and the hostname is not "
"specified, the report will be generated for all hosts. Likewise, "
"if the availability object type is services and the hostname is not "
"specified, the report will be generated for all services or all "
"services with the same description, depending on the value for "
"service description.",
NULL
},
{
"hostgroup",
"Host Group",
"nagios:objectjson/hostgrouplist",
{ NULL },
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
"availability", NULL },
NULL,
"Returns information applicable to the hosts in the hostgroup.",
NULL
},
{
"servicegroup",
"Service Group",
"nagios:objectjson/servicegrouplist",
{ NULL },
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
"availability", NULL },
NULL,
"Returns information applicable to the services in the servicegroup.",
NULL
},
{
"servicedescription",
"Service Description",
"nagios:objectjson/servicelist",
{ NULL },
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
"statechangelist", "availability", NULL },
"hostname",
"Description for the service requested. For availability reports, "
"if the availability object type is services and the "
"servicedescription is not specified, the report will be generated "
"either for all services or for all services on the specified host, "
"depending on the value specified for hostname",
NULL
},
{
"contactname",
"Contact Name",
"nagios:objectjson/contactlist",
{ NULL },
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
NULL },
NULL,
"Name for the contact requested.",
NULL
},
{
"contactgroup",
"Contact Group",
"nagios:objectjson/contactgrouplist",
{ NULL },
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
NULL },
NULL,
"Returns information applicable to the contacts in the contactgroup.",
NULL
},
{
"notificationmethod",
"Notification Method",
"nagios:objectjson/commandlist",
{ NULL },
{ "notificationcount", "notificationlist", NULL },
NULL,
"Returns objects that match the notification method.",
NULL
},
{
"timeperiod",
"Report Time Period",
"nagios:objectjson/timeperiodlist",
{ NULL },
{ "availability", NULL },
NULL,
"Timeperiod to use for the report.",
NULL
},
{
"assumeinitialstate",
"Assume Initial State",
"boolean",
{ NULL },
{ "availability", NULL },
NULL,
"Assume the initial state for the host(s) or service(s). Note that if true, assuming the initial state will be done only if the initial state could not be discovered by looking through the backtracked logs.",
NULL
},
{
"assumestateretention",
"Assume State Retention",
"boolean",
{ NULL },
{ "availability", NULL },
NULL,
"Assume states are retained.",
NULL
},
{
"assumestatesduringnagiosdowntime",
"Assume States During Nagios Downtime",
"boolean",
{ NULL },
{ "availability", NULL },
NULL,
"Assume states are retained during Nagios downtime.",
NULL
},
{
"assumedinitialhoststate",
"Assumed Initial Host State",
"enumeration",
{ NULL },
{ "availability", NULL },
NULL,
"Host state assumed when it is not possible to determine the initial host state.",
valid_initial_host_states
},
{
"assumedinitialservicestate",
"Assumed Initial Service State",
"enumeration",
{ NULL },
{ "availability", NULL },
NULL,
"Service state assumed when it is not possible to determine the initial service state.",
valid_initial_service_states
},
{
"backtrackedarchives",
"Backtracked Archives",
"integer",
{ NULL },
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
"statechangelist", "availability", NULL },
NULL,
"Number of backtracked archives to read in an attempt to find initial states.",
NULL,
},
{
"starttime",
"Start Time",
"integer",
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
"statechangelist", "availability", NULL },
{ NULL },
NULL,
"Starting time to use. Supplying a plus or minus sign means times relative to the query time.",
NULL,
},
{
"endtime",
"End Time",
"integer",
{ "alertcount", "alertlist", "notificationcount", "notificationlist",
"statechangelist", "availability", NULL },
{ NULL },
NULL,
"Ending time to use. Specifying plus or minus sign means times relative to the query time.",
NULL,
},
{ /* The last entry must contain all NULL entries */
NULL,
NULL,
NULL,
{ NULL },
{ NULL },
NULL,
NULL,
NULL
},
};
extern const json_escape percent_escapes;
int json_archive_alert_passes_selection(time_t, time_t, time_t, int, int,
au_host *, char *, au_service *, char *, int, host *, int, host *,
hostgroup *, servicegroup *, contact *, contactgroup *, unsigned,
unsigned, unsigned, unsigned, unsigned);
json_object *json_archive_alert_selectors(unsigned, int, int, time_t, time_t,
int, char *, char *, int, host *, int, host *, hostgroup *,
servicegroup *, contact *, contactgroup *, unsigned, unsigned,
unsigned);
int json_archive_notification_passes_selection(time_t, time_t, time_t, int,
int, au_host *, char *, au_service *, char *, int, host *, int, host *,
hostgroup *, servicegroup *, au_contact *, char *, contactgroup *,
unsigned, unsigned, unsigned, char *, char *);
json_object *json_archive_notification_selectors(unsigned, int, int, time_t,
time_t, int, char *, char *, int, host *, int, host *, hostgroup *,
servicegroup *, char *, contactgroup *, unsigned, unsigned, char *);
int json_archive_statechange_passes_selection(time_t, time_t, int, int,
au_host *, char *, au_service *, char *, unsigned, unsigned);
json_object *json_archive_statechange_selectors(unsigned, int, int, time_t,
time_t, int, char *, char *, unsigned);
int get_initial_nagios_state(au_linked_list *, time_t, time_t);
int get_initial_downtime_state(au_linked_list *, time_t, time_t);
int get_initial_subject_state(au_linked_list *, time_t, time_t);
int get_log_entry_state(au_log_entry *);
int have_data(au_linked_list *, int);
void compute_window_availability(time_t, time_t, int, int, int, timeperiod *,
au_availability *, int, int, int);
static void compute_availability(au_linked_list *, time_t, time_t, time_t,
timeperiod *, au_availability *, int, int, int, int);
void compute_host_availability(time_t, time_t, time_t, au_log *, au_host *,
timeperiod *, int, int, int, int);
void compute_service_availability(time_t, time_t, time_t, au_log *,
au_service *, timeperiod *, int, int, int, int);
json_object *json_archive_single_host_availability(unsigned, time_t, time_t,
time_t, char *, timeperiod *, int, int, int, int, unsigned, au_log *);
json_object *json_archive_single_service_availability(unsigned, time_t, time_t,
time_t, char *, char *, timeperiod *, int, int, int, int, unsigned,
au_log *);
json_object *json_archive_host_availability(unsigned, char *,
au_availability *);
json_object *json_archive_service_availability(unsigned, char *, char *,
au_availability *);
int main(void) {
int result = OK;
time_t query_time;
archive_json_cgi_data cgi_data;
json_object *json_root;
au_log *log;
time_t last_archive_data_update = (time_t)0;
json_object_member *romp = NULL;
/* The official time of the query */
time(&query_time);
json_root = json_new_object();
if(NULL == json_root) {
printf( "Failed to create new json object\n");
exit( 1);
}
json_object_append_integer(json_root, "format_version",
OUTPUT_FORMAT_VERSION);
/* Initialize shared configuration variables */
init_shared_cfg_vars(1);
init_cgi_data(&cgi_data);
document_header();
/* get the arguments passed in the URL */
result = process_cgivars(json_root, &cgi_data, query_time);
if(result != RESULT_SUCCESS) {
json_object_append_object(json_root, "data",
json_help(archive_json_help));
json_object_print(json_root, 0, 1, cgi_data.strftime_format,
cgi_data.format_options);
document_footer();
return result;
}
/* reset internal variables */
reset_cgi_vars();
/* read the CGI configuration file */
result = read_cgi_config_file(get_cgi_config_location(), NULL);
if(result == ERROR) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR,
"Error: Could not open CGI configuration file '%s' for reading!",
get_cgi_config_location()));
json_object_append_object(json_root, "data",
json_help(archive_json_help));
json_object_print(json_root, 0, 1, cgi_data.strftime_format,
cgi_data.format_options);
document_footer();
return ERROR;
}
/* read the main configuration file */
result = read_main_config_file(main_config_file);
if(result == ERROR) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR,
"Error: Could not open main configuration file '%s' for reading!",
main_config_file));
json_object_append_object(json_root, "data",
json_help(archive_json_help));
document_footer();
return ERROR;
}
/* Set the number of backtracked archives if it wasn't specified by the
user */
if(0 == cgi_data.backtracked_archives) {
switch(log_rotation_method) {
case LOG_ROTATION_MONTHLY:
cgi_data.backtracked_archives = 1;
break;
case LOG_ROTATION_WEEKLY:
cgi_data.backtracked_archives = 2;
break;
case LOG_ROTATION_DAILY:
cgi_data.backtracked_archives = 4;
break;
case LOG_ROTATION_HOURLY:
cgi_data.backtracked_archives = 8;
break;
default:
cgi_data.backtracked_archives = 2;
break;
}
}
/* read all object configuration data */
result = read_all_object_configuration_data(main_config_file,
READ_ALL_OBJECT_DATA);
if(result == ERROR) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR,
"Error: Could not read some or all object configuration data!"));
json_object_append_object(json_root, "data",
json_help(archive_json_help));
document_footer();
return ERROR;
}
/* read all status data */
result = read_all_status_data(status_file, READ_ALL_STATUS_DATA);
if(result == ERROR) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR,
"Error: Could not read host and service status information!"));
json_object_append_object(json_root, "data",
json_help(archive_json_help));
document_footer();
return ERROR;
}
/* validate arguments in URL */
result = validate_arguments(json_root, &cgi_data, query_time);
if((result != RESULT_SUCCESS) && (result != RESULT_OPTION_IGNORED)) {
json_object_append_object(json_root, "data",
json_help(archive_json_help));
json_object_print(json_root, 0, 1, cgi_data.strftime_format,
cgi_data.format_options);
document_footer();
return ERROR;
}
/* get authentication information */
get_authentication_information(¤t_authdata);
/* Allocate the structure for the logs */
if((log = au_init_log()) == NULL) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, ¤t_authdata, RESULT_MEMORY_ALLOCATION_ERROR,
"Unable to allocate memory for log data."));
json_object_append_object(json_root, "data",
json_help(archive_json_help));
document_footer();
return ERROR;
}
/* Return something to the user */
switch( cgi_data.query) {
case ARCHIVE_QUERY_HELP:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
compile_time(__DATE__, __TIME__), ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_help(archive_json_help));
break;
case ARCHIVE_QUERY_ALERTCOUNT:
read_archived_data(cgi_data.start_time, cgi_data.end_time,
cgi_data.backtracked_archives, AU_OBJTYPE_ALL,
AU_STATETYPE_ALL, AU_LOGTYPE_ALERT | AU_LOGTYPE_STATE, log,
&last_archive_data_update);
if(result != RESULT_OPTION_IGNORED) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_archive_data_update, ¤t_authdata,
RESULT_SUCCESS, ""));
}
else {
romp = json_get_object_member(json_root, "result");
json_object_append_time_t(romp->value.object, "last_data_update",
last_archive_data_update);
}
json_object_append_object(json_root, "data",
json_archive_alertcount(cgi_data.format_options,
cgi_data.start_time, cgi_data.end_time, cgi_data.object_types,
cgi_data.host_name, cgi_data.service_description,
cgi_data.use_parent_host, cgi_data.parent_host,
cgi_data.use_child_host, cgi_data.child_host,
cgi_data.hostgroup, cgi_data.servicegroup, cgi_data.contact,
cgi_data.contactgroup, cgi_data.state_types,
cgi_data.host_states, cgi_data.service_states, log));
break;
case ARCHIVE_QUERY_ALERTLIST:
read_archived_data(cgi_data.start_time, cgi_data.end_time,
cgi_data.backtracked_archives, AU_OBJTYPE_ALL,
AU_STATETYPE_ALL, AU_LOGTYPE_ALERT | AU_LOGTYPE_STATE, log,
&last_archive_data_update);
if(result != RESULT_OPTION_IGNORED) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_archive_data_update, ¤t_authdata,
RESULT_SUCCESS, ""));
}
else {
romp = json_get_object_member(json_root, "result");
json_object_append_time_t(romp->value.object, "last_data_update",
last_archive_data_update);
}
json_object_append_object(json_root, "data",
json_archive_alertlist(cgi_data.format_options, cgi_data.start,
cgi_data.count, cgi_data.start_time, cgi_data.end_time,
cgi_data.object_types, cgi_data.host_name,
cgi_data.service_description, cgi_data.use_parent_host,
cgi_data.parent_host, cgi_data.use_child_host,
cgi_data.child_host, cgi_data.hostgroup, cgi_data.servicegroup,
cgi_data.contact, cgi_data.contactgroup, cgi_data.state_types,
cgi_data.host_states, cgi_data.service_states, log));
break;
case ARCHIVE_QUERY_NOTIFICATIONCOUNT:
read_archived_data(cgi_data.start_time, cgi_data.end_time,
cgi_data.backtracked_archives, AU_OBJTYPE_ALL,
AU_STATETYPE_ALL, AU_LOGTYPE_NOTIFICATION, log,
&last_archive_data_update);
if(result != RESULT_OPTION_IGNORED) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_archive_data_update, ¤t_authdata,
RESULT_SUCCESS, ""));
}
else {
romp = json_get_object_member(json_root, "result");
json_object_append_time_t(romp->value.object, "last_data_update",
last_archive_data_update);
}
json_object_append_object(json_root, "data",
json_archive_notificationcount(cgi_data.format_options,
cgi_data.start_time, cgi_data.end_time, cgi_data.object_types,
cgi_data.host_name, cgi_data.service_description,
cgi_data.use_parent_host, cgi_data.parent_host,
cgi_data.use_child_host, cgi_data.child_host,
cgi_data.hostgroup, cgi_data.servicegroup,
cgi_data.contact_name, cgi_data.contactgroup,
cgi_data.host_notification_types,
cgi_data.service_notification_types,
cgi_data.notification_method, log));
break;
case ARCHIVE_QUERY_NOTIFICATIONLIST:
read_archived_data(cgi_data.start_time, cgi_data.end_time,
cgi_data.backtracked_archives, AU_OBJTYPE_ALL,
AU_STATETYPE_ALL, AU_LOGTYPE_NOTIFICATION, log,
&last_archive_data_update);
if(result != RESULT_OPTION_IGNORED) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_archive_data_update, ¤t_authdata,
RESULT_SUCCESS, ""));
}
else {
romp = json_get_object_member(json_root, "result");
json_object_append_time_t(romp->value.object, "last_data_update",
last_archive_data_update);
}
json_object_append_object(json_root, "data",
json_archive_notificationlist(cgi_data.format_options,
cgi_data.start, cgi_data.count, cgi_data.start_time,
cgi_data.end_time, cgi_data.object_types, cgi_data.host_name,
cgi_data.service_description, cgi_data.use_parent_host,
cgi_data.parent_host, cgi_data.use_child_host,
cgi_data.child_host, cgi_data.hostgroup, cgi_data.servicegroup,
cgi_data.contact_name, cgi_data.contactgroup,
cgi_data.host_notification_types,
cgi_data.service_notification_types,
cgi_data.notification_method, log));
break;
case ARCHIVE_QUERY_STATECHANGELIST:
read_archived_data(cgi_data.start_time, cgi_data.end_time,
cgi_data.backtracked_archives, cgi_data.object_type,
AU_STATETYPE_ALL, (AU_LOGTYPE_ALERT | AU_LOGTYPE_STATE), log,
&last_archive_data_update);
if(result != RESULT_OPTION_IGNORED) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_archive_data_update, ¤t_authdata,
RESULT_SUCCESS, ""));
}
else {
romp = json_get_object_member(json_root, "result");
json_object_append_time_t(romp->value.object, "last_data_update",
last_archive_data_update);
}
json_object_append_object(json_root, "data",
json_archive_statechangelist(cgi_data.format_options,
cgi_data.start, cgi_data.count, cgi_data.start_time,
cgi_data.end_time, cgi_data.object_type, cgi_data.host_name,
cgi_data.service_description,
cgi_data.assumed_initial_host_state,
cgi_data.assumed_initial_service_state, cgi_data.state_types,
log));
break;
case ARCHIVE_QUERY_AVAILABILITY:
switch(cgi_data.object_type) {
case AU_OBJTYPE_HOST:
case AU_OBJTYPE_HOSTGROUP:
read_archived_data(cgi_data.start_time, cgi_data.end_time,
cgi_data.backtracked_archives, AU_OBJTYPE_HOST,
cgi_data.state_types, (AU_LOGTYPE_NAGIOS | AU_LOGTYPE_ALERT
| AU_LOGTYPE_STATE | AU_LOGTYPE_DOWNTIME), log,
&last_archive_data_update);
break;
case AU_OBJTYPE_SERVICE:
case AU_OBJTYPE_SERVICEGROUP:
read_archived_data(cgi_data.start_time, cgi_data.end_time,
cgi_data.backtracked_archives, AU_OBJTYPE_SERVICE,
cgi_data.state_types, (AU_LOGTYPE_NAGIOS | AU_LOGTYPE_ALERT
| AU_LOGTYPE_STATE | AU_LOGTYPE_DOWNTIME), log,
&last_archive_data_update);
break;
}
if(result != RESULT_OPTION_IGNORED) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_archive_data_update, ¤t_authdata,
RESULT_SUCCESS, ""));
}
else {
romp = json_get_object_member(json_root, "result");
json_object_append_time_t(romp->value.object, "last_data_update",
last_archive_data_update);
}
json_object_append_object(json_root, "data",
json_archive_availability(cgi_data.format_options, query_time,
cgi_data.start_time, cgi_data.end_time,
cgi_data.object_type, cgi_data.host_name,
cgi_data.service_description, cgi_data.hostgroup,
cgi_data.servicegroup, cgi_data.timeperiod,
cgi_data.assume_initial_state, cgi_data.assume_state_retention,
cgi_data.assume_states_during_nagios_downtime,
cgi_data.assumed_initial_host_state,
cgi_data.assumed_initial_service_state, cgi_data.state_types,
log));
break;
default:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, ¤t_authdata, RESULT_OPTION_MISSING,
"Error: Object Type not specified. See data for help."));
json_object_append_object(json_root, "data",
json_help(archive_json_help));
break;
}
json_object_print(json_root, 0, 1, cgi_data.strftime_format,
cgi_data.format_options);
document_footer();
/* free all allocated memory */
free_cgi_data( &cgi_data);
json_free_object(json_root, 1);
au_free_log(log);
free_memory();
return OK;
}
void document_header() {
char date_time[MAX_DATETIME_LENGTH];
time_t expire_time;
time_t current_time;
time(¤t_time);
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
get_time_string(¤t_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: application/json; charset=utf-8\r\n\r\n");
return;
}
void document_footer(void) {
printf( "\n");
return;
}
void init_cgi_data(archive_json_cgi_data *cgi_data) {
cgi_data->format_options = 0;
cgi_data->query = ARCHIVE_QUERY_INVALID;
cgi_data->start = 0;
cgi_data->count = 0;
cgi_data->object_types = AU_OBJTYPE_ALL;
cgi_data->object_type = 0;
cgi_data->state_types = AU_STATETYPE_ALL;
cgi_data->host_states = AU_STATE_HOST_ALL;
cgi_data->service_states = AU_STATE_SERVICE_ALL;
cgi_data->host_notification_types = AU_NOTIFICATION_HOST_ALL;
cgi_data->service_notification_types = AU_NOTIFICATION_SERVICE_ALL;
#if 0
cgi_data->details = 0;
#endif
cgi_data->strftime_format = NULL;
cgi_data->start_time = (time_t)0;
cgi_data->end_time = (time_t)0;
cgi_data->parent_host_name = NULL;
cgi_data->use_parent_host = 0;
cgi_data->parent_host = NULL;
cgi_data->child_host_name = NULL;
cgi_data->use_child_host = 0;
cgi_data->child_host = NULL;
cgi_data->host_name = NULL;
cgi_data->host = NULL;
cgi_data->hostgroup_name = NULL;
cgi_data->hostgroup = NULL;
cgi_data->servicegroup_name = NULL;
cgi_data->servicegroup = NULL;
cgi_data->service_description = NULL;
cgi_data->service = NULL;
cgi_data->contact_name = NULL;
cgi_data->contact = NULL;
cgi_data->contactgroup_name = NULL;
cgi_data->contactgroup = NULL;
cgi_data->notification_method = NULL;
cgi_data->timeperiod_name = NULL;
cgi_data->timeperiod = NULL;
cgi_data->assumed_initial_host_state = AU_STATE_NO_DATA;
cgi_data->assumed_initial_service_state = AU_STATE_NO_DATA;
cgi_data->assume_initial_state = 1;
cgi_data->assume_state_retention = 1;
cgi_data->assume_states_during_nagios_downtime = 1;
cgi_data->backtracked_archives = 0;
}
void free_cgi_data(archive_json_cgi_data *cgi_data) {
if(NULL != cgi_data->strftime_format) free( cgi_data->strftime_format);
if(NULL != cgi_data->parent_host_name) free( cgi_data->parent_host_name);
if(NULL != cgi_data->child_host_name) free( cgi_data->child_host_name);
if(NULL != cgi_data->host_name) free( cgi_data->host_name);
if(NULL != cgi_data->hostgroup_name) free( cgi_data->hostgroup_name);
if(NULL != cgi_data->servicegroup_name) free(cgi_data->servicegroup_name);
if(NULL != cgi_data->service_description) free(cgi_data->service_description);
if(NULL != cgi_data->contact_name) free(cgi_data->contact_name);
if(NULL != cgi_data->contactgroup_name) free(cgi_data->contactgroup_name);
if(NULL != cgi_data->notification_method) free(cgi_data->notification_method);
if(NULL != cgi_data->timeperiod_name) free(cgi_data->timeperiod_name);
}
int process_cgivars(json_object *json_root, archive_json_cgi_data *cgi_data,
time_t query_time) {
char **variables;
int result = RESULT_SUCCESS;
int x;
authdata *authinfo = NULL; /* Currently always NULL because
get_authentication_information() hasn't
been called yet, but in case we want to
use it in the future... */
variables = getcgivars();
for(x = 0; variables[x]; x++) {
/* We set these each iteration because they could change with each
iteration */
if(!strcmp(variables[x], "query")) {
if((result = parse_enumeration_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_queries, &(cgi_data->query)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "formatoptions")) {
cgi_data->format_options = 0;
if((result = parse_bitmask_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], svm_format_options,
&(cgi_data->format_options))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "backtrackedarchives")) {
if((result = parse_int_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->backtracked_archives)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "start")) {
if((result = parse_int_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->start))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "count")) {
if((result = parse_int_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->count))) != RESULT_SUCCESS) {
break;
}
if(cgi_data->count == 0) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query,
valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID,
"The count option value is invalid. "
"It must be an integer greater than zero"));
result = RESULT_OPTION_VALUE_INVALID;
break;
}
x++;
}
else if(!strcmp(variables[x], "objecttype")) {
if((result = parse_enumeration_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_object_types,
&(cgi_data->object_type))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "objecttypes")) {
cgi_data->object_types = 0;
if((result = parse_bitmask_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_object_types,
&(cgi_data->object_types))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "availabilityobjecttype")) {
if((result = parse_enumeration_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_availability_object_types,
&(cgi_data->object_type))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "statetypes")) {
cgi_data->state_types = 0;
if((result = parse_bitmask_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_state_types,
&(cgi_data->state_types))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "hoststates")) {
cgi_data->host_states = 0;
if((result = parse_bitmask_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_host_states,
&(cgi_data->host_states))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "servicestates")) {
cgi_data->service_states = 0;
if((result = parse_bitmask_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_service_states,
&(cgi_data->service_states))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "hostnotificationtypes")) {
cgi_data->host_notification_types = 0;
if((result = parse_bitmask_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_host_notification_types,
&(cgi_data->host_notification_types))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "servicenotificationtypes")) {
cgi_data->service_notification_types = 0;
if((result = parse_bitmask_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_service_notification_types,
&(cgi_data->service_notification_types)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "parenthost")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->parent_host_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "childhost")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->child_host_name)))
!= RESULT_SUCCESS) {
}
x++;
}
else if(!strcmp(variables[x], "hostname")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->host_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "hostgroup")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->hostgroup_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "servicegroup")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->servicegroup_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "servicedescription")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->service_description)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "contactname")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->contact_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "contactgroup")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->contactgroup_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "notificationmethod")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->notification_method)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "timeperiod")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->timeperiod_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "assumeinitialstate")) {
if((result = parse_boolean_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->assume_initial_state)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "assumestateretention")) {
if((result = parse_boolean_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->assume_state_retention)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "assumestatesduringnagiosdowntime")) {
if((result = parse_boolean_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1],
&(cgi_data->assume_states_during_nagios_downtime)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "assumedinitialhoststate")) {
if((result = parse_enumeration_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_initial_host_states,
&(cgi_data->assumed_initial_host_state)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "assumedinitialservicestate")) {
if((result = parse_enumeration_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_initial_service_states,
&(cgi_data->assumed_initial_service_state)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "dateformat")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->strftime_format)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "starttime")) {
if((result = parse_time_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->start_time)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "endtime")) {
if((result = parse_time_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->end_time))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "NagFormId"))
++x;
else if(!strcmp(variables[x], ""));
else {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, RESULT_OPTION_INVALID,
"Invalid option: '%s'.", variables[x]));
result = RESULT_OPTION_INVALID;
break;
}
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return result;
}
int validate_arguments(json_object *json_root, archive_json_cgi_data *cgi_data,
time_t query_time) {
int result = RESULT_SUCCESS;
host *temp_host = NULL;
hostgroup *temp_hostgroup = NULL;
servicegroup *temp_servicegroup = NULL;
contactgroup *temp_contactgroup = NULL;
timeperiod *temp_timeperiod = NULL;
#if 0
service *temp_service = NULL;
contact *temp_contact = NULL;
command *temp_command = NULL;
#endif
authdata *authinfo = NULL; /* Currently always NULL because
get_authentication_information() hasn't
been called yet, but in case we want to
use it in the future... */
/* Validate that required parameters were supplied */
switch(cgi_data->query) {
case ARCHIVE_QUERY_HELP:
break;
case ARCHIVE_QUERY_ALERTCOUNT:
case ARCHIVE_QUERY_ALERTLIST:
if((0 == cgi_data->start_time) && (0 == cgi_data->end_time)) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Start and/or end time must be supplied."));
}
if(!(cgi_data->object_types & (AU_OBJTYPE_HOST | AU_OBJTYPE_SERVICE))) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"At least one object type must be supplied."));
}
break;
case ARCHIVE_QUERY_NOTIFICATIONCOUNT:
case ARCHIVE_QUERY_NOTIFICATIONLIST:
if((0 == cgi_data->start_time) && (0 == cgi_data->end_time)) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Start and/or end time must be supplied."));
}
if(!(cgi_data->object_types & (AU_OBJTYPE_HOST | AU_OBJTYPE_SERVICE))) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"At least one object type must be supplied."));
}
break;
case ARCHIVE_QUERY_STATECHANGELIST:
if((0 == cgi_data->start_time) && (0 == cgi_data->end_time)) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Start and/or end time must be supplied."));
}
if(0 == cgi_data->object_type) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Object type must be supplied."));
}
if(NULL == cgi_data->host_name) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Host name must be supplied."));
}
if((AU_OBJTYPE_SERVICE == cgi_data->object_type) &&
(NULL == cgi_data->service_description)) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Service description must be supplied."));
}
break;
case ARCHIVE_QUERY_AVAILABILITY:
if((0 == cgi_data->start_time) && (0 == cgi_data->end_time)) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Start and/or end time must be supplied."));
}
if(0 == cgi_data->object_type) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Availability object type must be supplied."));
}
break;
default:
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result", json_result(query_time,
THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Missing validation for object type %u.", cgi_data->query));
break;
}
/* Attempt to find the host object associated with host_name. Because
we're looking at historical data, the host may no longer
exist. */
if(NULL != cgi_data->host_name) {
cgi_data->host = find_host(cgi_data->host_name);
}
/* Attempt to find the service object associated with host_name and
service_description. Because we're looking at historical data,
the service may no longer exist. */
if((NULL != cgi_data->host_name) &&
(NULL != cgi_data->service_description)) {
cgi_data->service = find_service(cgi_data->host_name,
cgi_data->service_description);
}
/* Validate the requested parent host */
if( NULL != cgi_data->parent_host_name) {
if(strcmp(cgi_data->parent_host_name, "none")) {
temp_host = find_host(cgi_data->parent_host_name);
if( NULL == temp_host) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query,
valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The parenthost '%s' could not be found.",
cgi_data->parent_host_name));
}
else {
cgi_data->use_parent_host = 1;
cgi_data->parent_host = temp_host;
}
}
else {
cgi_data->use_parent_host = 1;
cgi_data->parent_host = NULL;
}
}
/* Validate the requested child host */
if( NULL != cgi_data->child_host_name) {
if(strcmp(cgi_data->child_host_name, "none")) {
temp_host = find_host(cgi_data->child_host_name);
if( NULL == temp_host) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query,
valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The childhost '%s' could not be found.",
cgi_data->child_host_name));
}
else {
cgi_data->use_child_host = 1;
cgi_data->child_host = temp_host;
}
}
else {
cgi_data->use_child_host = 1;
cgi_data->child_host = NULL;
}
}
/* Validate the requested hostgroup */
if( NULL != cgi_data->hostgroup_name) {
temp_hostgroup = find_hostgroup(cgi_data->hostgroup_name);
if( NULL == temp_hostgroup) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The hostgroup '%s' could not be found.",
cgi_data->hostgroup_name));
}
else {
cgi_data->hostgroup = temp_hostgroup;
}
}
/* Validate the requested servicegroup */
if( NULL != cgi_data->servicegroup_name) {
temp_servicegroup = find_servicegroup(cgi_data->servicegroup_name);
if( NULL == temp_servicegroup) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The servicegroup '%s' could not be found.",
cgi_data->servicegroup_name));
}
else {
cgi_data->servicegroup = temp_servicegroup;
}
}
/* Attempt to find the contact object associated with contact_name.
Because we're looking at historical data, the contact may
no longer exist. */
if(NULL != cgi_data->contact_name) {
cgi_data->contact = find_contact(cgi_data->contact_name);
}
/* Validate the requested contactgroup */
if( NULL != cgi_data->contactgroup_name) {
temp_contactgroup = find_contactgroup(cgi_data->contactgroup_name);
if( NULL == temp_contactgroup) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The contactgroup '%s' could not be found.",
cgi_data->contactgroup_name));
}
else {
cgi_data->contactgroup = temp_contactgroup;
}
}
/* Validate the requested timeperiod */
if( NULL != cgi_data->timeperiod_name) {
temp_timeperiod = find_timeperiod(cgi_data->timeperiod_name);
if( NULL == temp_timeperiod) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The timeperiod '%s' could not be found.",
cgi_data->timeperiod_name));
}
else {
cgi_data->timeperiod = temp_timeperiod;
}
}
/* Validate the requested start time is before the requested end time */
if((cgi_data->start_time > 0) && (cgi_data->end_time > 0) && (
cgi_data->start_time >= cgi_data->end_time)) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The requested start time must be before the end time."));
}
/* If one or more host states were selected, but host objects were not,
notify the user, but continue */
if((cgi_data->host_states != AU_STATE_HOST_ALL) &&
(!(cgi_data->object_types & AU_OBJTYPE_HOST))) {
result = RESULT_OPTION_IGNORED;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result, "The requested host states "
"were ignored because host objects were not selected."));
}
/* If one or more service states were selected, but service objects
were not, notify the user but continue */
else if((cgi_data->service_states != AU_STATE_SERVICE_ALL) &&
(!(cgi_data->object_types & AU_OBJTYPE_SERVICE))) {
result = RESULT_OPTION_IGNORED;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result, "The requested service states "
"were ignored because service objects were not selected."));
}
/* If one or more host notification types were selected, but host
objects were not, notify the user, but continue */
if((cgi_data->host_notification_types != AU_NOTIFICATION_HOST_ALL) &&
(!(cgi_data->object_types & AU_OBJTYPE_HOST))) {
result = RESULT_OPTION_IGNORED;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The requested host notification types were ignored because host objects were not selected."));
}
/* If one or more service notification types were selected, but
service objects were not, notify the user but continue */
else if((cgi_data->service_notification_types !=
AU_NOTIFICATION_SERVICE_ALL) &&
(!(cgi_data->object_types & AU_OBJTYPE_SERVICE))) {
result = RESULT_OPTION_IGNORED;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The requested service notification types were ignored because service objects were not selected."));
}
return result;
}
int json_archive_alert_passes_selection(time_t timestamp, time_t start_time,
time_t end_time, int current_object_type, int match_object_types,
au_host *current_host, char *match_host, au_service *current_service,
char *match_service, int use_parent_host, host *parent_host,
int use_child_host, host *child_host, hostgroup *match_hostgroup,
servicegroup *match_servicegroup, contact *match_contact,
contactgroup *match_contactgroup, unsigned current_state_type,
unsigned match_state_types, unsigned current_state,
unsigned match_host_states, unsigned match_service_states) {
host *temp_host;
host *temp_host2;
service *temp_service;
contactgroupsmember *temp_contact_groupsmember;
int found;
if((start_time > 0) && (timestamp < start_time)) {
return 0;
}
if((end_time > 0) && (timestamp > end_time)) {
return 0;
}
/* Skip if we're not interested in the current state type */
if(!(current_state_type & match_state_types)) {
return 0;
}
switch(current_object_type) {
case AU_OBJTYPE_HOST:
/* Skip if we're not interested in hosts */
if(!(match_object_types & AU_OBJTYPE_HOST)) {
return 0;
}
/* Skip if user is not authorized for this host */
if((NULL != current_host->hostp) && (FALSE ==
is_authorized_for_host(current_host->hostp,
¤t_authdata))) {
return 0;
}
/* Skip if we're not interested in the current host state */
if(!(current_state & match_host_states)) {
return 0;
}
/* If a specific host name was specified, skip this host if it's
name does not match the one specified */
if((NULL != match_host) && strcmp(current_host->name, match_host)) {
return 0;
}
/* If a host parent was specified, skip this host if it's parent is
not the parent host specified */
if((1 == use_parent_host) && (NULL != current_host->hostp) &&
FALSE == is_host_immediate_child_of_host(parent_host,
current_host->hostp)) {
return 0;
}
/* If a hostgroup was specified, skip this host if it is not a member
of the hostgroup specified */
if((NULL != match_hostgroup) && (NULL != current_host->hostp) &&
( FALSE == is_host_member_of_hostgroup(match_hostgroup,
current_host->hostp))) {
return 0;
}
/* If the contact was specified, skip this host if it does not have
the contact specified */
if((NULL != match_contact) && (NULL != current_host->hostp) &&
(FALSE == is_contact_for_host(current_host->hostp,
match_contact))) {
return 0;
}
/* If the contact group was specified, skip this host if it does not
have the contact group specified */
if((NULL != match_contactgroup) && (NULL != current_host->hostp)) {
found = 0;
for(temp_contact_groupsmember =
current_host->hostp->contact_groups;
temp_contact_groupsmember != NULL;
temp_contact_groupsmember =
temp_contact_groupsmember->next) {
if(!strcmp(temp_contact_groupsmember->group_name,
match_contactgroup->group_name)) {
found = 1;
break;
}
}
if(0 == found) return 0;
}
/* If a child host was specified... */
if((1 == use_child_host) && (NULL != current_host->hostp)) {
/* If the child host is "none", skip this host if it has children */
if(NULL == child_host) {
for(temp_host2 = host_list; temp_host2 != NULL;
temp_host2 = temp_host2->next) {
if(TRUE ==
is_host_immediate_child_of_host(current_host->hostp,
temp_host2)) {
return 0;
}
}
}
/* Otherwise, skip this host if it does not have the specified host
as a child */
else if(FALSE ==
is_host_immediate_child_of_host(current_host->hostp,
child_host)) {
return 0;
}
}
break;
case AU_OBJTYPE_SERVICE:
/* Skip if we're not interested in services */
if(!(match_object_types & AU_OBJTYPE_SERVICE)) {
return 0;
}
/* Skip if user is not authorized for this service */
if((NULL != current_service->servicep) && (FALSE ==
is_authorized_for_service(current_service->servicep,
¤t_authdata))) {
return 0;
}
/* Skip if we're not interested in the current service state */
if(!(current_state & match_service_states)) {
return 0;
}
/* If a specific host name was specified, skip this service if it's
host name does not match the one specified */
if((NULL != match_host) && strcmp(current_service->host_name,
match_host)) {
return 0;
}
/* If a specific service description was specified, skip this service
if it's description does not match the one specified */
if((NULL != match_service) && strcmp(current_service->description,
match_service)) {
return 0;
}
/* If a host parent was specified, skip this service if the parent
of the host associated with it is not the parent host specified */
if((1 == use_parent_host) && (NULL != current_service->servicep)) {
temp_host = find_host(current_service->servicep->host_name);
if((NULL != temp_host) && (FALSE ==
is_host_immediate_child_of_host(parent_host, temp_host))) {
return 0;
}
}
/* If a hostgroup was specified, skip this service if it's host is not
a member of the hostgroup specified */
if((NULL != match_hostgroup) && (NULL != current_service->servicep)) {
temp_host = find_host(current_service->servicep->host_name);
if((NULL != temp_host) && (FALSE ==
is_host_member_of_hostgroup(match_hostgroup, temp_host))) {
return 0;
}
}
/* If a servicegroup was specified, skip this service if it is not
a member of the servicegroup specified */
if((NULL != match_servicegroup) &&
(NULL != current_service->servicep)) {
temp_service = find_service(current_service->servicep->host_name,
current_service->description);
if((NULL != temp_service) && (FALSE ==
is_service_member_of_servicegroup(match_servicegroup,
temp_service))) {
return 0;
}
}
/* If the contact was specified, skip this service if it does not have
the contact specified */
if((NULL != match_contact) && (NULL != current_service->servicep) &&
(FALSE == is_contact_for_service(current_service->servicep,
match_contact))) {
return 0;
}
/* If the contact group was specified, skip this service if it does not
have the contact group specified */
if((NULL != match_contactgroup) &&
(NULL != current_service->servicep)) {
found = 0;
for(temp_contact_groupsmember =
current_service->servicep->contact_groups;
temp_contact_groupsmember != NULL;
temp_contact_groupsmember =
temp_contact_groupsmember->next) {
if(!strcmp(temp_contact_groupsmember->group_name,
match_contactgroup->group_name)) {
found = 1;
break;
}
}
if(0 == found) return 0;
}
/* If a child host was specified... */
if((1 == use_child_host) && (NULL != current_service->servicep)) {
temp_host = find_host(current_service->servicep->host_name);
if(NULL != temp_host) {
/* If the child host is "none", skip this service if it's
host has children */
if(NULL == child_host) {
for(temp_host2 = host_list; temp_host2 != NULL;
temp_host2 = temp_host2->next) {
if(TRUE == is_host_immediate_child_of_host(temp_host,
temp_host2)) {
return 0;
}
}
}
/* Otherwise, skip this service if it's host does not have the
specified host as a child */
else if(FALSE == is_host_immediate_child_of_host(temp_host,
child_host)) {
return 0;
}
}
}
break;
}
return 1;
}
json_object * json_archive_alert_selectors(unsigned format_options, int start,
int count, time_t start_time, time_t end_time, int object_types,
char *match_host, char *match_service, int use_parent_host,
host *parent_host, int use_child_host, host *child_host,
hostgroup *match_hostgroup, servicegroup *match_servicegroup,
contact *match_contact, contactgroup *match_contactgroup,
unsigned match_state_types, unsigned match_host_states,
unsigned match_service_states) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if(start_time > 0) {
json_object_append_time_t(json_selectors, "starttime", start_time);
}
if(end_time > 0) {
json_object_append_time_t(json_selectors, "endtime", end_time);
}
if(object_types != AU_OBJTYPE_ALL) {
json_bitmask(json_selectors, format_options, "objecttypes",
object_types, valid_object_types);
}
if(match_state_types != AU_STATETYPE_ALL) {
json_bitmask(json_selectors, format_options, "statetypes",
match_state_types, valid_state_types);
}
if((object_types & AU_OBJTYPE_HOST) &&
(match_host_states != AU_STATE_HOST_ALL)) {
json_bitmask(json_selectors, format_options, "hoststates",
match_host_states, valid_host_states);
}
if((object_types & AU_OBJTYPE_SERVICE) &&
(match_service_states != AU_STATE_SERVICE_ALL)) {
json_bitmask(json_selectors, format_options, "servicestates",
match_service_states, valid_service_states);
}
if(NULL != match_host) {
json_object_append_string(json_selectors, "hostname", &percent_escapes,
match_host);
}
if(NULL != match_service) {
json_object_append_string(json_selectors, "servicedescription",
&percent_escapes, match_service);
}
if(1 == use_parent_host) {
json_object_append_string(json_selectors, "parenthost",
&percent_escapes,
( NULL == parent_host ? "none" : parent_host->name));
}
if( 1 == use_child_host) {
json_object_append_string(json_selectors, "childhost", &percent_escapes,
( NULL == child_host ? "none" : child_host->name));
}
if(NULL != match_hostgroup) {
json_object_append_string(json_selectors, "hostgroup", &percent_escapes,
match_hostgroup->group_name);
}
if((object_types & AU_OBJTYPE_SERVICE) && (NULL != match_servicegroup)) {
json_object_append_string(json_selectors, "servicegroup",
&percent_escapes, match_servicegroup->group_name);
}
if(NULL != match_contact) {
json_object_append_string(json_selectors, "contact", &percent_escapes,
match_contact->name);
}
if(NULL != match_contactgroup) {
json_object_append_string(json_selectors, "contactgroup",
&percent_escapes, match_contactgroup->group_name);
}
return json_selectors;
}
json_object * json_archive_alertcount(unsigned format_options,
time_t start_time, time_t end_time, int object_types,
char *match_host, char *match_service, int use_parent_host,
host *parent_host, int use_child_host, host *child_host,
hostgroup *match_hostgroup, servicegroup *match_servicegroup,
contact *match_contact, contactgroup *match_contactgroup,
unsigned match_state_types, unsigned match_host_states,
unsigned match_service_states, au_log *log) {
json_object *json_data;
au_node *temp_node;
au_log_entry *temp_entry;
au_log_alert *temp_alert_log;
au_host *temp_host = NULL;
au_service *temp_service = NULL;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_archive_alert_selectors(format_options, 0, 0, start_time,
end_time, object_types, match_host, match_service, use_parent_host,
parent_host, use_child_host, child_host, match_hostgroup,
match_servicegroup, match_contact, match_contactgroup,
match_state_types, match_host_states, match_service_states));
for(temp_node = log->entry_list->head; temp_node != NULL;
temp_node = temp_node->next) {
temp_entry = (au_log_entry *)temp_node->data;
/* Skip all but alert type messages */
if(AU_LOGTYPE_ALERT != temp_entry->entry_type) continue;
/* Get the host/service object */
temp_alert_log = (au_log_alert *)temp_entry->entry;
switch(temp_alert_log->obj_type) {
case AU_OBJTYPE_HOST:
temp_host = (au_host *)temp_alert_log->object;
temp_service = NULL;
break;
case AU_OBJTYPE_SERVICE:
temp_host = NULL;
temp_service = (au_service *)temp_alert_log->object;
break;
}
/* Skip anything that does not pass the alert selection criteria */
if(json_archive_alert_passes_selection(temp_entry->timestamp,
start_time, end_time, temp_alert_log->obj_type,
object_types, temp_host, match_host, temp_service,
match_service, use_parent_host, parent_host, use_child_host,
child_host, match_hostgroup, match_servicegroup,
match_contact, match_contactgroup, temp_alert_log->state_type,
match_state_types, temp_alert_log->state, match_host_states,
match_service_states) == 0) {
continue;
}
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object * json_archive_alertlist(unsigned format_options, int start,
int count, time_t start_time, time_t end_time, int object_types,
char *match_host, char *match_service, int use_parent_host,
host *parent_host, int use_child_host, host *child_host,
hostgroup *match_hostgroup, servicegroup *match_servicegroup,
contact *match_contact, contactgroup *match_contactgroup,
unsigned match_state_types, unsigned match_host_states,
unsigned match_service_states, au_log *log) {
json_object *json_data;
json_array *json_alertlist;
json_object *json_alert_details;
au_node *temp_node;
au_log_entry *temp_entry;
au_log_alert *temp_alert_log;
au_host *temp_host = NULL;
au_service *temp_service = NULL;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_archive_alert_selectors(format_options, start, count,
start_time, end_time, object_types, match_host, match_service,
use_parent_host, parent_host, use_child_host, child_host,
match_hostgroup, match_servicegroup, match_contact,
match_contactgroup, match_state_types, match_host_states,
match_service_states));
json_alertlist = json_new_array();
for(temp_node = log->entry_list->head; temp_node != NULL;
temp_node = temp_node->next) {
temp_entry = (au_log_entry *)temp_node->data;
/* Skip all but alert type messages */
if(AU_LOGTYPE_ALERT != temp_entry->entry_type) continue;
/* Get the host/service object */
temp_alert_log = (au_log_alert *)temp_entry->entry;
switch(temp_alert_log->obj_type) {
case AU_OBJTYPE_HOST:
temp_host = (au_host *)temp_alert_log->object;
temp_service = NULL;
break;
case AU_OBJTYPE_SERVICE:
temp_host = NULL;
temp_service = (au_service *)temp_alert_log->object;
break;
}
/* Skip anything that does not pass the alert selection criteria */
if(json_archive_alert_passes_selection(temp_entry->timestamp,
start_time, end_time, temp_alert_log->obj_type,
object_types, temp_host, match_host, temp_service,
match_service, use_parent_host, parent_host, use_child_host,
child_host, match_hostgroup, match_servicegroup,
match_contact, match_contactgroup, temp_alert_log->state_type,
match_state_types, temp_alert_log->state, match_host_states,
match_service_states) == 0) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
json_alert_details = json_new_object();
json_archive_alert_details(json_alert_details, format_options,
temp_entry->timestamp, (au_log_alert *)temp_entry->entry);
json_array_append_object(json_alertlist, json_alert_details);
counted++;
}
current++;
}
json_object_append_array(json_data, "alertlist", json_alertlist);
return json_data;
}
void json_archive_alert_details(json_object *json_details,
unsigned format_options, time_t timestamp, au_log_alert *temp_alert) {
au_host *temp_host;
au_service *temp_service;
json_object_append_time_t(json_details, "timestamp", timestamp);
json_enumeration(json_details, format_options, "object_type",
temp_alert->obj_type, svm_au_object_types);
switch(temp_alert->obj_type) {
case AU_OBJTYPE_HOST:
temp_host = (au_host *)temp_alert->object;
json_object_append_string(json_details, "name", &percent_escapes,
temp_host->name);
break;
case AU_OBJTYPE_SERVICE:
temp_service = (au_service *)temp_alert->object;
json_object_append_string(json_details, "host_name", &percent_escapes,
temp_service->host_name);
json_object_append_string(json_details, "description", &percent_escapes,
temp_service->description);
break;
}
json_enumeration(json_details, format_options, "state_type",
temp_alert->state_type, svm_au_state_types);
json_enumeration(json_details, format_options, "state", temp_alert->state,
svm_au_states);
json_object_append_string(json_details, "plugin_output", &percent_escapes,
temp_alert->plugin_output);
}
int json_archive_notification_passes_selection(time_t timestamp,
time_t start_time, time_t end_time, int current_object_type,
int match_object_types, au_host *current_host, char *match_host,
au_service *current_service, char *match_service, int use_parent_host,
host *parent_host, int use_child_host, host *child_host,
hostgroup *match_hostgroup, servicegroup *match_servicegroup,
au_contact *current_contact, char *match_contact,
contactgroup *match_contactgroup,
unsigned current_notification_type,
unsigned match_host_notification_types,
unsigned match_service_notification_types,
char *current_notification_method, char *match_notification_method) {
host *temp_host;
host *temp_host2;
service *temp_service;
contactgroupsmember *temp_contact_groupsmember;
int found;
if((start_time > 0) && (timestamp < start_time)) {
return 0;
}
if((end_time > 0) && (timestamp > end_time)) {
return 0;
}
/* If the contact was specified, skip this notification if it does not have
the contact specified */
if((NULL != match_contact) && (NULL != current_contact) &&
strcmp(current_contact->name, match_contact)) {
return 0;
}
/* If the notification method was specified, skip this notification if
it does not have the method specified */
if((NULL != match_notification_method) &&
(NULL != current_notification_method) &&
strcmp(current_notification_method, match_notification_method)) {
return 0;
}
switch(current_object_type) {
case AU_OBJTYPE_HOST:
/* Skip if we're not interested in hosts */
if(!(match_object_types & AU_OBJTYPE_HOST)) {
return 0;
}
/* Skip if user is not authorized for this host */
if((NULL != current_host->hostp) && (FALSE ==
is_authorized_for_host(current_host->hostp,
¤t_authdata))) {
return 0;
}
/* Skip if we're not interested in the current host notification type */
if(!(current_notification_type & match_host_notification_types)) {
return 0;
}
/* If a specific host name was specified, skip this host if it's
name does not match the one specified */
if((NULL != match_host) && strcmp(current_host->name, match_host)) {
return 0;
}
/* If a host parent was specified, skip this host if it's parent is
not the parent host specified */
if((1 == use_parent_host) && (NULL != current_host->hostp) &&
FALSE == is_host_immediate_child_of_host(parent_host,
current_host->hostp)) {
return 0;
}
/* If a hostgroup was specified, skip this host if it is not a member
of the hostgroup specified */
if((NULL != match_hostgroup) && (NULL != current_host->hostp) &&
( FALSE == is_host_member_of_hostgroup(match_hostgroup,
current_host->hostp))) {
return 0;
}
/* If the contact group was specified, skip this host if it does not
have the contact group specified */
if((NULL != match_contactgroup) && (NULL != current_host->hostp)) {
found = 0;
for(temp_contact_groupsmember =
current_host->hostp->contact_groups;
temp_contact_groupsmember != NULL;
temp_contact_groupsmember =
temp_contact_groupsmember->next) {
if(!strcmp(temp_contact_groupsmember->group_name,
match_contactgroup->group_name)) {
found = 1;
break;
}
}
if(0 == found) return 0;
}
/* If a child host was specified... */
if((1 == use_child_host) && (NULL != current_host->hostp)) {
/* If the child host is "none", skip this host if it has children */
if(NULL == child_host) {
for(temp_host2 = host_list; temp_host2 != NULL;
temp_host2 = temp_host2->next) {
if(TRUE ==
is_host_immediate_child_of_host(current_host->hostp,
temp_host2)) {
return 0;
}
}
}
/* Otherwise, skip this host if it does not have the specified host
as a child */
else if(FALSE ==
is_host_immediate_child_of_host(current_host->hostp,
child_host)) {
return 0;
}
}
break;
case AU_OBJTYPE_SERVICE:
/* Skip if we're not interested in services */
if(!(match_object_types & AU_OBJTYPE_SERVICE)) {
return 0;
}
/* Skip if user is not authorized for this service */
if((NULL != current_service->servicep) && (FALSE ==
is_authorized_for_service(current_service->servicep,
¤t_authdata))) {
return 0;
}
/* Skip if we're not interested in the current service notification
type */
if(!(current_notification_type & match_service_notification_types)) {
return 0;
}
/* If a specific host name was specified, skip this service if it's
host name does not match the one specified */
if((NULL != match_host) && strcmp(current_service->host_name,
match_host)) {
return 0;
}
/* If a specific service description was specified, skip this service
if it's description does not match the one specified */
if((NULL != match_service) && strcmp(current_service->description,
match_service)) {
return 0;
}
/* If a host parent was specified, skip this service if the parent
of the host associated with it is not the parent host specified */
if((1 == use_parent_host) && (NULL != current_service->servicep)) {
temp_host = find_host(current_service->servicep->host_name);
if((NULL != temp_host) && (FALSE ==
is_host_immediate_child_of_host(parent_host, temp_host))) {
return 0;
}
}
/* If a hostgroup was specified, skip this service if it's host is not
a member of the hostgroup specified */
if((NULL != match_hostgroup) && (NULL != current_service->servicep)) {
temp_host = find_host(current_service->servicep->host_name);
if((NULL != temp_host) && (FALSE ==
is_host_member_of_hostgroup(match_hostgroup, temp_host))) {
return 0;
}
}
/* If a servicegroup was specified, skip this service if it is not
a member of the servicegroup specified */
if((NULL != match_servicegroup) &&
(NULL != current_service->servicep)) {
temp_service = find_service(current_service->servicep->host_name,
current_service->description);
if((NULL != temp_service) && (FALSE ==
is_service_member_of_servicegroup(match_servicegroup,
temp_service))) {
return 0;
}
}
/* If the contact group was specified, skip this service if it does not
have the contact group specified */
if((NULL != match_contactgroup) &&
(NULL != current_service->servicep)) {
found = 0;
for(temp_contact_groupsmember =
current_service->servicep->contact_groups;
temp_contact_groupsmember != NULL;
temp_contact_groupsmember =
temp_contact_groupsmember->next) {
if(!strcmp(temp_contact_groupsmember->group_name,
match_contactgroup->group_name)) {
found = 1;
break;
}
}
if(0 == found) return 0;
}
/* If a child host was specified... */
if((1 == use_child_host) && (NULL != current_service->servicep)) {
temp_host = find_host(current_service->servicep->host_name);
if(NULL != temp_host) {
/* If the child host is "none", skip this service if it's
host has children */
if(NULL == child_host) {
for(temp_host2 = host_list; temp_host2 != NULL;
temp_host2 = temp_host2->next) {
if(TRUE == is_host_immediate_child_of_host(temp_host,
temp_host2)) {
return 0;
}
}
}
/* Otherwise, skip this service if it's host does not have the
specified host as a child */
else if(FALSE == is_host_immediate_child_of_host(temp_host,
child_host)) {
return 0;
}
}
}
break;
}
return 1;
}
json_object * json_archive_notification_selectors(unsigned format_options,
int start, int count, time_t start_time, time_t end_time,
int match_object_types, char *match_host, char *match_service,
int use_parent_host, host *parent_host, int use_child_host,
host *child_host, hostgroup *match_hostgroup,
servicegroup *match_servicegroup, char *match_contact,
contactgroup *match_contactgroup,
unsigned match_host_notification_types,
unsigned match_service_notification_types,
char *match_notification_method) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if(start_time > 0) {
json_object_append_time_t(json_selectors, "starttime", start_time);
}
if(end_time > 0) {
json_object_append_time_t(json_selectors, "endtime", end_time);
}
if(match_object_types != AU_OBJTYPE_ALL) {
json_bitmask(json_selectors, format_options, "objecttypes",
match_object_types, valid_object_types);
}
if((match_object_types & AU_OBJTYPE_HOST) &&
(match_host_notification_types != AU_NOTIFICATION_HOST_ALL)) {
json_bitmask(json_selectors, format_options, "hostnotificationtypes",
match_host_notification_types,
valid_host_notification_types);
}
if((match_object_types & AU_OBJTYPE_SERVICE) &&
(match_service_notification_types != AU_NOTIFICATION_SERVICE_ALL)) {
json_bitmask(json_selectors, format_options, "servicenotificationtypes",
match_service_notification_types,
valid_service_notification_types);
}
if(NULL != match_host) {
json_object_append_string(json_selectors, "hostname", &percent_escapes,
match_host);
}
if(NULL != match_service) {
json_object_append_string(json_selectors, "servicedescription",
&percent_escapes, match_service);
}
if(1 == use_parent_host) {
json_object_append_string(json_selectors, "parenthost",
&percent_escapes,
( NULL == parent_host ? "none" : parent_host->name));
}
if( 1 == use_child_host) {
json_object_append_string(json_selectors, "childhost",
&percent_escapes,
( NULL == child_host ? "none" : child_host->name));
}
if(NULL != match_hostgroup) {
json_object_append_string(json_selectors, "hostgroup", &percent_escapes,
match_hostgroup->group_name);
}
if((match_object_types & AU_OBJTYPE_SERVICE) &&
(NULL != match_servicegroup)) {
json_object_append_string(json_selectors, "servicegroup",
&percent_escapes, match_servicegroup->group_name);
}
if(NULL != match_contact) {
json_object_append_string(json_selectors, "contact", &percent_escapes,
match_contact);
}
if(NULL != match_contactgroup) {
json_object_append_string(json_selectors, "contactgroup",
&percent_escapes, match_contactgroup->group_name);
}
if(NULL != match_notification_method) {
json_object_append_string(json_selectors, "notificationmethod",
&percent_escapes, match_notification_method);
}
return json_selectors;
}
json_object * json_archive_notificationcount(unsigned format_options,
time_t start_time, time_t end_time, int match_object_types,
char *match_host, char *match_service, int use_parent_host,
host *parent_host, int use_child_host, host *child_host,
hostgroup *match_hostgroup, servicegroup *match_servicegroup,
char *match_contact, contactgroup *match_contactgroup,
unsigned match_host_notification_types,
unsigned match_service_notification_types,
char *match_notification_method, au_log *log) {
json_object *json_data;
au_node *temp_node;
au_log_entry *temp_entry;
au_log_notification *temp_notification_log;
au_host *temp_host = NULL;
au_service *temp_service = NULL;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_archive_notification_selectors(format_options, 0, 0,
start_time, end_time, match_object_types, match_host,
match_service, use_parent_host, parent_host, use_child_host,
child_host, match_hostgroup, match_servicegroup, match_contact,
match_contactgroup, match_host_notification_types,
match_service_notification_types, match_notification_method));
for(temp_node = log->entry_list->head; temp_node != NULL;
temp_node = temp_node->next) {
temp_entry = (au_log_entry *)temp_node->data;
/* Skip all but notification type messages */
if(AU_LOGTYPE_NOTIFICATION != temp_entry->entry_type) continue;
/* Get the host/service object */
temp_notification_log = (au_log_notification *)temp_entry->entry;
switch(temp_notification_log->obj_type) {
case AU_OBJTYPE_HOST:
temp_host = (au_host *)temp_notification_log->object;
temp_service = NULL;
break;
case AU_OBJTYPE_SERVICE:
temp_host = NULL;
temp_service = (au_service *)temp_notification_log->object;
break;
}
/* Skip anything that does not pass the notification selection
criteria */
if(json_archive_notification_passes_selection(temp_entry->timestamp,
start_time, end_time, temp_notification_log->obj_type,
match_object_types, temp_host, match_host, temp_service,
match_service, use_parent_host, parent_host, use_child_host,
child_host, match_hostgroup, match_servicegroup,
temp_notification_log->contact, match_contact,
match_contactgroup, temp_notification_log->notification_type,
match_host_notification_types,
match_service_notification_types, temp_notification_log->method, match_notification_method) == 0) {
continue;
}
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object * json_archive_notificationlist(unsigned format_options, int start,
int count, time_t start_time, time_t end_time, int match_object_types,
char *match_host, char *match_service, int use_parent_host,
host *parent_host, int use_child_host, host *child_host,
hostgroup *match_hostgroup, servicegroup *match_servicegroup,
char *match_contact, contactgroup *match_contactgroup,
unsigned match_host_notification_types,
unsigned match_service_notification_types,
char *match_notification_method, au_log *log) {
json_object *json_data;
json_array *json_notificationlist;
json_object *json_notification_details;
au_node *temp_node;
au_log_entry *temp_entry;
au_log_notification *temp_notification_log;
au_host *temp_host = NULL;
au_service *temp_service = NULL;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_archive_notification_selectors(format_options, start, count,
start_time, end_time, match_object_types, match_host,
match_service, use_parent_host, parent_host, use_child_host,
child_host, match_hostgroup, match_servicegroup, match_contact,
match_contactgroup, match_host_notification_types,
match_service_notification_types, match_notification_method));
json_notificationlist = json_new_array();
for(temp_node = log->entry_list->head; temp_node != NULL;
temp_node = temp_node->next) {
temp_entry = (au_log_entry *)temp_node->data;
/* Skip all but notification type messages */
if(AU_LOGTYPE_NOTIFICATION != temp_entry->entry_type) continue;
/* Get the host/service object */
temp_notification_log = (au_log_notification *)temp_entry->entry;
switch(temp_notification_log->obj_type) {
case AU_OBJTYPE_HOST:
temp_host = (au_host *)temp_notification_log->object;
temp_service = NULL;
break;
case AU_OBJTYPE_SERVICE:
temp_host = NULL;
temp_service = (au_service *)temp_notification_log->object;
break;
}
/* Skip anything that does not pass the notification selection
criteria */
if(json_archive_notification_passes_selection(temp_entry->timestamp,
start_time, end_time, temp_notification_log->obj_type,
match_object_types, temp_host, match_host, temp_service,
match_service, use_parent_host, parent_host, use_child_host,
child_host, match_hostgroup, match_servicegroup,
temp_notification_log->contact, match_contact,
match_contactgroup, temp_notification_log->notification_type,
match_host_notification_types,
match_service_notification_types, temp_notification_log->method,
match_notification_method) == 0) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
json_notification_details = json_new_object();
json_archive_notification_details(json_notification_details,
format_options, temp_entry->timestamp,
(au_log_notification *)temp_entry->entry);
json_array_append_object(json_notificationlist,
json_notification_details);
counted++;
}
current++;
}
json_object_append_array(json_data, "notificationlist",
json_notificationlist);
return json_data;
}
void json_archive_notification_details(json_object *json_details,
unsigned format_options, time_t timestamp,
au_log_notification *temp_notification) {
au_host *temp_host;
au_service *temp_service;
json_object_append_time_t(json_details, "timestamp", timestamp);
json_enumeration(json_details, format_options, "object_type",
temp_notification->obj_type,
svm_au_object_types);
switch(temp_notification->obj_type) {
case AU_OBJTYPE_HOST:
temp_host = (au_host *)temp_notification->object;
json_object_append_string(json_details, "name", &percent_escapes,
temp_host->name);
break;
case AU_OBJTYPE_SERVICE:
temp_service = (au_service *)temp_notification->object;
json_object_append_string(json_details, "host_name", &percent_escapes,
temp_service->host_name);
json_object_append_string(json_details, "description", &percent_escapes,
temp_service->description);
break;
}
json_object_append_string(json_details, "contact", &percent_escapes,
temp_notification->contact->name);
json_enumeration(json_details, format_options, "notification_type",
temp_notification->notification_type, svm_au_notification_types);
json_object_append_string(json_details, "method", &percent_escapes,
temp_notification->method);
json_object_append_string(json_details, "message", &percent_escapes,
temp_notification->message);
}
int json_archive_statechange_passes_selection(time_t timestamp,
time_t end_time, int current_object_type,
int match_object_type, au_host *current_host, char *match_host,
au_service *current_service, char *match_service,
unsigned current_state_type, unsigned match_state_types) {
if((end_time > 0) && (timestamp > end_time)) {
return 0;
}
/* Skip if we're not interested in the current state type */
if(!(current_state_type & match_state_types)) {
return 0;
}
switch(current_object_type) {
case AU_OBJTYPE_HOST:
/* Skip if we're not interested in hosts */
if(match_object_type != AU_OBJTYPE_HOST) {
return 0;
}
/* Skip if user is not authorized for this host */
if((NULL != current_host->hostp) && (FALSE ==
is_authorized_for_host(current_host->hostp,
¤t_authdata))) {
return 0;
}
/* If a specific host name was specified, skip this host if it's
name does not match the one specified */
if((NULL != match_host) && (NULL != current_host) &&
strcmp(current_host->name, match_host)) {
return 0;
}
break;
case AU_OBJTYPE_SERVICE:
/* Skip if we're not interested in services */
if(match_object_type != AU_OBJTYPE_SERVICE) {
return 0;
}
/* Skip if user is not authorized for this service */
if((NULL != current_service->servicep) && (FALSE ==
is_authorized_for_service(current_service->servicep,
¤t_authdata))) {
return 0;
}
/* If a specific service was specified, skip this service if it's
host name and service description do not match the one specified */
if((NULL != match_host) && (NULL != match_service) &&
(NULL != current_service) &&
( strcmp(current_service->host_name, match_host) ||
strcmp(current_service->description, match_service))) {
return 0;
}
break;
}
return 1;
}
json_object *json_archive_statechange_selectors(unsigned format_options,
int start, int count, time_t start_time, time_t end_time,
int object_type, char *host_name, char *service_description,
unsigned state_types) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if(start_time > 0) {
json_object_append_time_t(json_selectors, "starttime", start_time);
}
if(end_time > 0) {
json_object_append_time_t(json_selectors, "endtime", end_time);
}
if(NULL != host_name) {
json_object_append_string(json_selectors, "hostname", &percent_escapes,
host_name);
}
if(NULL != service_description) {
json_object_append_string(json_selectors, "servicedescription",
&percent_escapes, service_description);
}
if(state_types != AU_STATETYPE_ALL) {
json_bitmask(json_selectors, format_options, "statetypes", state_types,
valid_state_types);
}
return json_selectors;
}
json_object *json_archive_statechangelist(unsigned format_options,
int start, int count, time_t start_time, time_t end_time,
int object_type, char *host_name, char *service_description,
int assumed_initial_host_state, int assumed_initial_service_state,
unsigned state_types, au_log *log) {
json_object *json_data;
json_array *json_statechangelist;
json_object *json_statechange_details;
au_node *temp_node;
int initial_host_state = AU_STATE_NO_DATA;
int initial_service_state = AU_STATE_NO_DATA;
au_log_entry *temp_entry = NULL;
au_log_alert *temp_state_log = NULL;
au_log_alert *start_log = NULL;
au_log_alert *end_log = NULL;
au_host *temp_host = NULL;
au_service *temp_service = NULL;
int have_seen_first_entry = 0;
int current = 0;
int counted = 0;
if(assumed_initial_host_state != AU_STATE_NO_DATA)
initial_host_state = assumed_initial_host_state;
if(assumed_initial_service_state != AU_STATE_NO_DATA)
initial_service_state = assumed_initial_service_state;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_archive_statechange_selectors(format_options, start, count,
start_time, end_time, object_type, host_name, service_description,
state_types));
json_statechangelist = json_new_array();
for(temp_node = log->entry_list->head; temp_node != NULL;
temp_node = temp_node->next) {
/* Skip all but notification type messages */
temp_entry = (au_log_entry *)temp_node->data;
if(!(temp_entry->entry_type & (AU_LOGTYPE_STATE | AU_LOGTYPE_ALERT))) {
continue;
}
/* Get the host/service object */
temp_state_log = (au_log_alert *)temp_entry->entry;
switch(temp_state_log->obj_type) {
case AU_OBJTYPE_HOST:
temp_host = (au_host *)temp_state_log->object;
temp_service = NULL;
break;
case AU_OBJTYPE_SERVICE:
temp_host = NULL;
temp_service = (au_service *)temp_state_log->object;
break;
}
/* Skip any entries not passing the selectors */
if(json_archive_statechange_passes_selection(temp_entry->timestamp,
end_time, temp_state_log->obj_type,
object_type, temp_host, host_name, temp_service,
service_description, temp_state_log->state_type,
state_types) == 0) {
continue;
}
if((start_time > 0) && (temp_entry->timestamp < start_time)) {
/* If we're before the start time and no initial assumed state
was provided, record the state to be used as the initial
state */
switch(temp_state_log->obj_type) {
case AU_OBJTYPE_HOST:
if(AU_STATE_NO_DATA == assumed_initial_host_state)
initial_host_state = temp_state_log->state;
break;
case AU_OBJTYPE_SERVICE:
if(AU_STATE_NO_DATA == assumed_initial_service_state)
initial_service_state = temp_state_log->state;
break;
}
continue;
}
else if(0 == have_seen_first_entry) {
/* When we get to the first entry after the start, inject a
pseudo entry with the initial state */
switch(object_type) {
case AU_OBJTYPE_HOST:
start_log = au_create_alert_or_state_log(object_type,
temp_host, AU_STATETYPE_HARD, initial_host_state,
"Initial Host Pseudo-State");
break;
case AU_OBJTYPE_SERVICE:
start_log = au_create_alert_or_state_log(object_type,
temp_service, AU_STATETYPE_HARD, initial_service_state,
"Initial Service Pseudo-State");
break;
}
if(start_log != NULL) {
json_statechange_details = json_new_object();
json_archive_alert_details(json_statechange_details,
format_options, start_time, start_log);
json_array_append_object(json_statechangelist,
json_statechange_details);
au_free_alert_log(start_log);
}
have_seen_first_entry = 1;
}
#if 0
else {
/* Ignore ALERT logs if their state is not different from the
previous state */
switch(object_type) {
case AU_OBJTYPE_HOST:
// if((temp_entry->entry_type & (AU_LOGTYPE_ALERT |
// AU_LOGTYPE_STATE_INITIAL)) &&
if((temp_entry->entry_type & AU_LOGTYPE_ALERT) &&
(last_host_state == temp_state_log->state)) {
continue;
}
last_host_state = temp_state_log->state;
break;
case AU_OBJTYPE_SERVICE:
// if((temp_entry->entry_type & (AU_LOGTYPE_ALERT |
// AU_LOGTYPE_STATE_INITIAL)) &&
if((temp_entry->entry_type & AU_LOGTYPE_ALERT) &&
(last_service_state == temp_state_log->state)) {
continue;
}
last_service_state = temp_state_log->state;
break;
}
}
#endif
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
json_statechange_details = json_new_object();
json_archive_alert_details(json_statechange_details,
format_options, temp_entry->timestamp, temp_state_log);
json_array_append_object(json_statechangelist,
json_statechange_details);
counted++;
}
current++;
}
/* Inject a pseudo entry with the final state */
switch(object_type) {
case AU_OBJTYPE_HOST:
temp_host = au_find_host(log->hosts, host_name);
if(NULL != temp_host) {
end_log = au_create_alert_or_state_log(object_type,
temp_host, AU_STATETYPE_HARD, temp_state_log->state,
"Final Host Pseudo-State");
}
break;
case AU_OBJTYPE_SERVICE:
temp_service = au_find_service(log->hosts, host_name,
service_description);
if(NULL != temp_service) {
end_log = au_create_alert_or_state_log(object_type,
temp_service, AU_STATETYPE_HARD, temp_state_log->state,
"Final Service Pseudo-State");
}
break;
}
if(end_log != NULL) {
json_statechange_details = json_new_object();
json_archive_alert_details(json_statechange_details, format_options,
end_time, end_log);
json_array_append_object(json_statechangelist,
json_statechange_details);
au_free_alert_log(end_log);
}
json_object_append_array(json_data, "statechangelist",
json_statechangelist);
return json_data;
}
/*
Return the initial state of Nagios itself.
*/
int get_initial_nagios_state(au_linked_list *log_entries, time_t start_time,
time_t end_time) {
au_node *temp_node;
au_log_entry *current_log_entry;
au_log_nagios *temp_nagios_log;
int initial_state = AU_STATE_NO_DATA;
for(temp_node = log_entries->head; temp_node != NULL;
temp_node = temp_node->next) {
current_log_entry = (au_log_entry *)temp_node->data;
if(current_log_entry->timestamp < start_time) {
/* Any log entries prior to the start time tell us something
about the initial state of Nagios so look at all of them */
switch(current_log_entry->entry_type) {
case AU_LOGTYPE_NAGIOS:
/* If the log is a Nagios start or stop log, that is the
current program state */
temp_nagios_log = (au_log_nagios *)current_log_entry->entry;
initial_state = temp_nagios_log->type;
break;
default:
/* Any other log indicates that Nagios is running */
initial_state = AU_STATE_PROGRAM_START;
break;
}
}
else {
if(AU_STATE_NO_DATA != initial_state) {
/* Once we cross the threshold of the start time, if we have
an initial state, that is THE initial state */
return initial_state;
}
else {
/* Otherwise the first log encountered tells us the initial
state of Nagios */
switch(current_log_entry->entry_type) {
case AU_LOGTYPE_NAGIOS:
/* If the log is a Nagios start or stop log, that is
opposite the initial state */
temp_nagios_log = (au_log_nagios *)current_log_entry->entry;
switch(temp_nagios_log->type) {
case AU_STATE_PROGRAM_START:
return AU_STATE_PROGRAM_END;
break;
case AU_STATE_PROGRAM_END:
return AU_STATE_PROGRAM_START;
break;
}
break;
default:
/* Any other log indicates that Nagios was running at
the start time */
return AU_STATE_PROGRAM_START;
break;
}
}
}
}
/* If we reach this point, we are in bad shape because we had nothing
in the logs and the initial state should still be AU_STATE_NO_DATA,
which we return as an error indication */
return initial_state;
}
/*
Return the initial downtime state of the host or service.
*/
int get_initial_downtime_state(au_linked_list *log_entries, time_t start_time,
time_t end_time) {
au_node *temp_node;
au_log_entry *current_log_entry;
au_log_downtime *temp_downtime_log;
int initial_state = AU_STATE_NO_DATA;
for(temp_node = log_entries->head; temp_node != NULL;
temp_node = temp_node->next) {
current_log_entry = (au_log_entry *)temp_node->data;
if(current_log_entry->timestamp < start_time) {
/* Any downtime log prior to the start time may indicate the
initial downtime state so look at all of them */
if(AU_LOGTYPE_DOWNTIME == current_log_entry->entry_type) {
temp_downtime_log = (au_log_downtime *)current_log_entry->entry;
initial_state = temp_downtime_log->downtime_type;
}
}
else if(current_log_entry->timestamp <= end_time) {
if(AU_STATE_NO_DATA != initial_state) {
/* Once we cross the start time, if we have a downtime state,
we have THE initial downtime state */
return initial_state;
}
else {
/* If we don't have a downtime state yet, the first downtime
state we encounter will be opposite the initial downtime
state */
if(AU_LOGTYPE_NOTIFICATION == current_log_entry->entry_type) {
temp_downtime_log = (au_log_downtime *)current_log_entry->entry;
switch(temp_downtime_log->downtime_type) {
case AU_STATE_DOWNTIME_START:
return AU_STATE_DOWNTIME_END;
break;
case AU_STATE_DOWNTIME_END:
return AU_STATE_DOWNTIME_START;
break;
}
}
}
}
}
/* If we haven't encountered any indication of downtime yet, assume
we were not initially in downtime */
if(AU_STATE_NO_DATA == initial_state) {
initial_state = AU_STATE_DOWNTIME_END;
}
return initial_state;
}
/*
Return the initial state of the host or service.
*/
int get_initial_subject_state(au_linked_list *log_entries, time_t start_time,
time_t end_time) {
au_node *temp_node;
au_log_entry *current_log_entry;
int initial_state = AU_STATE_NO_DATA;
for(temp_node = log_entries->head; temp_node != NULL;
temp_node = temp_node->next) {
current_log_entry = (au_log_entry *)temp_node->data;
if(current_log_entry->timestamp < start_time) {
/* Any state log prior to the start time may indicate the
initial state of the subject so look at all of them */
switch(current_log_entry->entry_type) {
case AU_LOGTYPE_ALERT:
case AU_LOGTYPE_STATE_INITIAL:
case AU_LOGTYPE_STATE_CURRENT:
initial_state = get_log_entry_state(current_log_entry);
break;
}
}
}
return initial_state;
}
int get_log_entry_state(au_log_entry *log_entry) {
switch(log_entry->entry_type) {
case AU_LOGTYPE_ALERT:
case AU_LOGTYPE_STATE_INITIAL:
case AU_LOGTYPE_STATE_CURRENT:
return ((au_log_alert *)log_entry->entry)->state;
break;
case AU_LOGTYPE_DOWNTIME:
return ((au_log_downtime *)log_entry->entry)->downtime_type;
break;
case AU_LOGTYPE_NAGIOS:
return ((au_log_nagios *)log_entry->entry)->type;
break;
case AU_LOGTYPE_NOTIFICATION:
return ((au_log_notification *)log_entry->entry)->notification_type;
break;
default:
return AU_STATE_NO_DATA;
break;
}
}
#define have_real_data(a) have_data((a), \
~(AU_STATE_NO_DATA | AU_STATE_PROGRAM_START | AU_STATE_PROGRAM_END))
#define have_state_data(a) have_data((a), AU_STATE_ALL)
int have_data(au_linked_list *log_entries, int mask) {
au_node *temp_node;
int state;
for(temp_node = log_entries->head; temp_node != NULL;
temp_node = temp_node->next) {
state = get_log_entry_state((au_log_entry *)temp_node->data);
if(state & mask) return TRUE;
}
return FALSE;
}
unsigned long calculate_window_duration(time_t start_time, time_t end_time,
timeperiod *report_timeperiod) {
struct tm *t;
unsigned long state_duration;
time_t midnight;
int weekday;
timerange *temp_timerange;
unsigned long temp_duration;
unsigned long temp_end;
unsigned long temp_start;
unsigned long start;
unsigned long end;
/* MickeM - attempt to handle the the report time_period (if any) */
if(report_timeperiod != NULL) {
t = localtime((time_t *)&start_time);
state_duration = 0;
/* calculate the start of the day (midnight, 00:00 hours) */
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
t->tm_isdst = -1;
midnight = mktime(t);
weekday = t->tm_wday;
while(midnight < end_time) {
temp_duration = 0;
temp_end = min(86400, end_time - midnight);
temp_start = 0;
if(start_time > midnight) {
temp_start = start_time - midnight;
}
#ifdef DEBUG
printf("Matching: %ld -> %ld. (%ld -> %ld)\n", temp_start,
temp_end, midnight + temp_start, midnight + temp_end);
#endif
/* check all time ranges for this day of the week */
for(temp_timerange = report_timeperiod->days[weekday];
temp_timerange != NULL;
temp_timerange = temp_timerange->next) {
#ifdef DEBUG
printf("Matching in timerange[%d]: %lu -> %lu (%lu -> %lu)\n",
weekday, temp_timerange->range_start,
temp_timerange->range_end, temp_start, temp_end);
#endif
start = max(temp_timerange->range_start, temp_start);
end = min(temp_timerange->range_end, temp_end);
if(start < end) {
temp_duration += end - start;
#ifdef DEBUG
printf("Matched time: %ld -> %ld = %lu\n", start, end,
temp_duration);
#endif
}
#ifdef DEBUG
else {
printf("Ignored time: %ld -> %ld\n", start, end);
}
#endif
}
state_duration += temp_duration;
temp_start = 0;
midnight += 86400;
if(++weekday > 6) weekday = 0;
}
}
/* No report timeperiod was requested; assume 24x7 */
else {
/* Calculate time in this state */
state_duration = (unsigned long)(end_time - start_time);
}
return state_duration;
}
#ifdef DEBUG
void print_availability(au_availability *availability, const char *padding) {
printf("%sAll:: up: %10lu\n", padding,
availability->time_up);
printf("%s down: %10lu\n", padding,
availability->time_down);
printf("%s unreachable: %10lu\n", padding,
availability->time_unreachable);
printf("%s ok: %10lu\n", padding,
availability->time_ok);
printf("%s warning: %10lu\n", padding,
availability->time_warning);
printf("%s critical: %10lu\n", padding,
availability->time_critical);
printf("%s unknown: %10lu\n", padding,
availability->time_unknown);
printf("%sScheduled:: up: %10lu\n", padding,
availability->scheduled_time_up);
printf("%s down: %10lu\n", padding,
availability->scheduled_time_down);
printf("%s unreachable: %10lu\n", padding,
availability->scheduled_time_unreachable);
printf("%s ok: %10lu\n", padding,
availability->scheduled_time_ok);
printf("%s warning: %10lu\n", padding,
availability->scheduled_time_warning);
printf("%s critical: %10lu\n", padding,
availability->scheduled_time_critical);
printf("%s unknown: %10lu\n", padding,
availability->scheduled_time_unknown);
printf("%sIndeterminate:: scheduled: %10lu\n", padding,
availability->scheduled_time_indeterminate);
printf("%s nodata: %10lu\n", padding,
availability->time_indeterminate_nodata);
printf("%s notrunning: %10lu\n", padding,
availability->time_indeterminate_notrunning);
}
#endif
void compute_window_availability(time_t start_time, time_t end_time,
int last_subject_state, int last_downtime_state, int last_nagios_state,
timeperiod *report_timeperiod, au_availability *availability,
int assume_state_during_nagios_downtime, int object_type,
int assume_state_retention) {
unsigned long state_duration;
#ifdef DEBUG
printf( " %lu to %lu (%lus): %s/%s/%s\n", start_time, end_time,
(end_time - start_time),
svm_get_string_from_value(last_subject_state, svm_au_states),
svm_get_string_from_value(last_downtime_state, svm_au_states),
svm_get_string_from_value(last_nagios_state, svm_au_states));
#endif
/* Get the duration of this window as adjusted for the report timeperiod */
state_duration = calculate_window_duration(start_time, end_time,
report_timeperiod);
/* Determine the appropriate state */
switch(last_nagios_state) {
case AU_STATE_PROGRAM_START:
switch(last_downtime_state) {
case AU_STATE_DOWNTIME_START:
switch(last_subject_state) {
case AU_STATE_NO_DATA:
availability->time_indeterminate_nodata += state_duration;
break;
case AU_STATE_HOST_UP:
availability->scheduled_time_up += state_duration;
break;
case AU_STATE_HOST_DOWN:
availability->scheduled_time_down += state_duration;
break;
case AU_STATE_HOST_UNREACHABLE:
availability->scheduled_time_unreachable += state_duration;
break;
case AU_STATE_SERVICE_OK:
availability->scheduled_time_ok += state_duration;
break;
case AU_STATE_SERVICE_WARNING:
availability->scheduled_time_warning += state_duration;
break;
case AU_STATE_SERVICE_UNKNOWN:
availability->scheduled_time_unknown += state_duration;
break;
case AU_STATE_SERVICE_CRITICAL:
availability->scheduled_time_critical += state_duration;
break;
}
break;
case AU_STATE_DOWNTIME_END:
switch(last_subject_state) {
case AU_STATE_NO_DATA:
availability->time_indeterminate_nodata += state_duration;
break;
case AU_STATE_HOST_UP:
availability->time_up += state_duration;
break;
case AU_STATE_HOST_DOWN:
availability->time_down += state_duration;
break;
case AU_STATE_HOST_UNREACHABLE:
availability->time_unreachable += state_duration;
break;
case AU_STATE_SERVICE_OK:
availability->time_ok += state_duration;
break;
case AU_STATE_SERVICE_WARNING:
availability->time_warning += state_duration;
break;
case AU_STATE_SERVICE_UNKNOWN:
availability->time_unknown += state_duration;
break;
case AU_STATE_SERVICE_CRITICAL:
availability->time_critical += state_duration;
break;
}
break;
}
break;
case AU_STATE_PROGRAM_END:
if(assume_state_during_nagios_downtime) {
switch(last_downtime_state) {
case AU_STATE_DOWNTIME_START:
switch(last_subject_state) {
case AU_STATE_NO_DATA:
availability->time_indeterminate_nodata += state_duration;
break;
case AU_STATE_HOST_UP:
availability->scheduled_time_up += state_duration;
break;
case AU_STATE_HOST_DOWN:
availability->scheduled_time_down += state_duration;
break;
case AU_STATE_HOST_UNREACHABLE:
availability->scheduled_time_unreachable += state_duration;
break;
case AU_STATE_SERVICE_OK:
availability->scheduled_time_ok += state_duration;
break;
case AU_STATE_SERVICE_WARNING:
availability->scheduled_time_warning += state_duration;
break;
case AU_STATE_SERVICE_UNKNOWN:
availability->scheduled_time_unknown += state_duration;
break;
case AU_STATE_SERVICE_CRITICAL:
availability->scheduled_time_critical += state_duration;
break;
}
break;
case AU_STATE_DOWNTIME_END:
switch(last_subject_state) {
case AU_STATE_NO_DATA:
availability->time_indeterminate_nodata += state_duration;
break;
case AU_STATE_HOST_UP:
availability->time_up += state_duration;
break;
case AU_STATE_HOST_DOWN:
availability->time_down += state_duration;
break;
case AU_STATE_HOST_UNREACHABLE:
availability->time_unreachable += state_duration;
break;
case AU_STATE_SERVICE_OK:
availability->time_ok += state_duration;
break;
case AU_STATE_SERVICE_WARNING:
availability->time_warning += state_duration;
break;
case AU_STATE_SERVICE_UNKNOWN:
availability->time_unknown += state_duration;
break;
case AU_STATE_SERVICE_CRITICAL:
availability->time_critical += state_duration;
break;
}
break;
}
}
else {
availability->time_indeterminate_notrunning += state_duration;
}
break;
}
#ifdef DEBUG
print_availability(availability, " ");
#endif
return;
}
static void compute_availability(au_linked_list *log_entries, time_t query_time,
time_t start_time, time_t end_time, timeperiod *report_timeperiod,
au_availability *availability, int initial_subject_state,
int assume_state_during_nagios_downtime, int object_type,
int assume_state_retention) {
int current_nagios_state;
int last_nagios_state;
int current_downtime_state;
int last_downtime_state;
int current_subject_state = initial_subject_state;
int last_subject_state = AU_STATE_NO_DATA;
au_node *temp_node;
au_log_entry *current_log_entry;
au_log_entry *last_log_entry = NULL;
au_log_alert *temp_alert_log;
au_log_downtime *temp_downtime_log;
au_log_nagios *temp_nagios_log;
time_t last_time = start_time;
time_t current_time;
#ifdef DEBUG
printf(" initial state: %s\n",
svm_get_string_from_value(initial_subject_state, valid_states));
#endif
/* Determine the initial Nagios state */
if((last_nagios_state = current_nagios_state =
get_initial_nagios_state(log_entries, start_time, end_time))
== AU_STATE_NO_DATA) {
/* This is bad; I'm giving up. */
return;
}
#ifdef DEBUG
printf(" initial nagios state: %s\n",
svm_get_string_from_value(last_nagios_state, valid_states));
#endif
/* Determine the initial downtime state */
if((last_downtime_state = current_downtime_state =
get_initial_downtime_state(log_entries, start_time, end_time))
== AU_STATE_NO_DATA) {
/* This is bad; I'm giving up. */
return;
}
#ifdef DEBUG
printf(" initial downtime state: %s\n",
svm_get_string_from_value(last_downtime_state, valid_states));
#endif
/* Process all entry pairs */
for(temp_node = log_entries->head; temp_node != NULL;
temp_node = temp_node->next) {
current_log_entry = (au_log_entry *)temp_node->data;
/* Skip everything before the start of the requested query window */
if(current_log_entry->timestamp < start_time) continue;
#ifdef DEBUG
printf(" Got log of type \"%s\" at %lu\n",
svm_get_string_from_value(current_log_entry->entry_type,
svm_au_log_types), current_log_entry->timestamp);
#endif
/* Update states */
last_subject_state = current_subject_state;
last_downtime_state = current_downtime_state;
last_nagios_state = current_nagios_state;
switch(current_log_entry->entry_type) {
case AU_LOGTYPE_ALERT:
case AU_LOGTYPE_STATE_INITIAL:
case AU_LOGTYPE_STATE_CURRENT:
temp_alert_log = (au_log_alert *)current_log_entry->entry;
current_subject_state = temp_alert_log->state;
#ifdef DEBUG
printf(" Current alert state: \"%s\"\n",
svm_get_string_from_value(current_subject_state,
valid_states));
#endif
break;
case AU_LOGTYPE_DOWNTIME:
temp_downtime_log = (au_log_downtime *)current_log_entry->entry;
current_downtime_state = temp_downtime_log->downtime_type;
#ifdef DEBUG
printf(" Current downtime state: \"%s\"\n",
svm_get_string_from_value(current_downtime_state,
valid_states));
#endif
break;
case AU_LOGTYPE_NAGIOS:
temp_nagios_log = (au_log_nagios *)current_log_entry->entry;
current_nagios_state = temp_nagios_log->type;
#ifdef DEBUG
printf(" Current nagios state: \"%s\"\n",
svm_get_string_from_value(current_nagios_state,
valid_states));
#endif
break;
default:
continue;
break;
}
/* Record the time ranges for the current log pair */
if(NULL != last_log_entry) last_time = last_log_entry->timestamp;
current_time = current_log_entry->timestamp;
/* Bail out if we've already passed the end of the requested time
range*/
if(last_time > end_time) break;
/* Clip last time if it extends beyond the end of the requested
time range */
if(current_time > end_time) current_time = end_time;
/* Clip first time if it precedes the start of the requested
time range */
if(last_time < start_time) last_time = start_time;
/* compute availability times for this chunk */
compute_window_availability(last_time, current_time, last_subject_state,
last_downtime_state, last_nagios_state, report_timeperiod,
availability, assume_state_during_nagios_downtime, object_type,
assume_state_retention);
/* Return if we've reached the end of the requested time
range */
if(current_time >= end_time) {
last_log_entry = current_log_entry;
break;
}
/* Keep track of the last item */
last_log_entry = current_log_entry;
}
/* Process the last entry */
if(last_log_entry != NULL) {
/* Update states */
last_subject_state = current_subject_state;
last_downtime_state = current_downtime_state;
last_nagios_state = current_nagios_state;
/* Don't process an entry that is beyond the end of the requested
time range */
if(last_log_entry->timestamp < end_time) {
current_time = query_time;
if(current_time > end_time) current_time = end_time;
last_time = last_log_entry->timestamp;
if(last_time < start_time) last_time = start_time;
/* compute availability times for last state */
compute_window_availability(last_time, current_time,
last_subject_state, last_downtime_state, last_nagios_state,
report_timeperiod, availability,
assume_state_during_nagios_downtime, object_type,
assume_state_retention);
}
}
else {
/* There were no log entries for the entire queried time, therefore
the whole query window was the same state */
compute_window_availability(start_time, end_time, initial_subject_state,
last_downtime_state, last_nagios_state, report_timeperiod,
availability, assume_state_during_nagios_downtime, object_type,
assume_state_retention);
}
}
void compute_host_availability(time_t query_time, time_t start_time,
time_t end_time, au_log *log, au_host *host,
timeperiod *report_timeperiod, int assume_initial_state,
int assumed_initial_host_state,
int assume_state_during_nagios_downtime, int assume_state_retention) {
hoststatus *host_status = NULL;
int last_known_state = AU_STATE_NO_DATA;
int initial_host_state = AU_STATE_NO_DATA;
#ifdef DEBUG
printf("Computing availability for host %s\n from %lu to %lu\n",
host->name, start_time, end_time);
#endif
/* If the start time is in the future, we can't compute anything */
if(start_time > query_time) return;
/* Get current host status if possible */
host_status = find_hoststatus(host->name);
/* If we don't have any data, the query time falls within the requested
query window, and we have the current host status, insert the
current state as the pseudo state at the start of the requested
query window. */
if((have_state_data(host->log_entries) == FALSE) &&
(query_time > start_time) && (query_time <= end_time) &&
(host_status != NULL)) {
switch(host_status->status) {
case HOST_DOWN:
last_known_state = AU_STATE_HOST_DOWN;
break;
case HOST_UNREACHABLE:
last_known_state = AU_STATE_HOST_UNREACHABLE;
break;
case HOST_UP:
last_known_state = AU_STATE_HOST_UP;
break;
default:
last_known_state = AU_STATE_NO_DATA;
break;
}
if(last_known_state != AU_STATE_NO_DATA) {
/* Add a dummy current state item */
#ifdef DEBUG
printf(" Inserting %s as current service pseudo-state\n",
svm_get_string_from_value(last_known_state, valid_states));
#endif
(void)au_add_alert_or_state_log(log, start_time,
AU_LOGTYPE_STATE_CURRENT, AU_OBJTYPE_HOST, host,
AU_STATETYPE_HARD, last_known_state,
"Current Host Pseudo-State");
}
}
/* Next determine the initial state of the host */
initial_host_state = get_initial_subject_state(host->log_entries,
start_time, end_time);
#ifdef DEBUG
printf(" Initial state from logs: %s\n",
svm_get_string_from_value(initial_host_state, valid_states));
#endif
if((AU_STATE_NO_DATA == initial_host_state) &&
(1 == assume_initial_state)) {
switch(assumed_initial_host_state) {
case AU_STATE_HOST_UP:
case AU_STATE_HOST_DOWN:
case AU_STATE_HOST_UNREACHABLE:
initial_host_state = assumed_initial_host_state;
break;
case AU_STATE_CURRENT_STATE:
if(host_status != NULL) {
switch(host_status->status) {
case HOST_DOWN:
initial_host_state = AU_STATE_HOST_DOWN;
break;
case HOST_UNREACHABLE:
initial_host_state = AU_STATE_HOST_UNREACHABLE;
break;
case HOST_UP:
initial_host_state = AU_STATE_HOST_UP;
break;
}
}
break;
}
}
/* At this point, if we still don't have any real data, we can't compute
anything, so return */
if((have_real_data(host->log_entries) != TRUE) &&
(AU_STATE_NO_DATA == initial_host_state)) return;
/* Compute the availability for every entry in the host's list of log
entries */
compute_availability(host->log_entries, query_time, start_time, end_time,
report_timeperiod, host->availability, initial_host_state,
assume_state_during_nagios_downtime, AU_OBJTYPE_HOST,
assume_state_retention);
}
void compute_service_availability(time_t query_time, time_t start_time,
time_t end_time, au_log *log, au_service *service,
timeperiod *report_timeperiod, int assume_initial_state,
int assumed_initial_service_state,
int assume_state_during_nagios_downtime, int assume_state_retention) {
servicestatus *service_status = NULL;
int last_known_state = AU_STATE_NO_DATA;
int initial_service_state = AU_STATE_NO_DATA;
#ifdef DEBUG
printf("Computing availability for service %s:%s\n from %lu to %lu\n",
service->host_name, service->description, start_time, end_time);
#endif
/* If the start time is in the future, we can't compute anything */
if(start_time > query_time) return;
/* Get current service status if possible */
service_status = find_servicestatus(service->host_name,
service->description);
/* If we don't have any data, the query time falls within the requested
query window, and we have the current service status, insert the
current state as the pseudo state at the start of the requested
query window. */
if((have_state_data(service->log_entries) == FALSE) &&
(query_time > start_time) && (query_time <= end_time) &&
(service_status != NULL)) {
switch(service_status->status) {
case SERVICE_OK:
last_known_state = AU_STATE_SERVICE_OK;
break;
case SERVICE_WARNING:
last_known_state = AU_STATE_SERVICE_WARNING;
break;
case SERVICE_CRITICAL:
last_known_state = AU_STATE_SERVICE_CRITICAL;
break;
case SERVICE_UNKNOWN:
last_known_state = AU_STATE_SERVICE_UNKNOWN;
break;
default:
last_known_state = AU_STATE_NO_DATA;
break;
}
if(last_known_state != AU_STATE_NO_DATA) {
/* Add a dummy current state item */
#ifdef DEBUG
printf(" Inserting %s as current service pseudo-state\n",
svm_get_string_from_value(last_known_state, valid_states));
#endif
(void)au_add_alert_or_state_log(log, start_time,
AU_LOGTYPE_STATE_CURRENT, AU_OBJTYPE_SERVICE, service,
AU_STATETYPE_HARD, last_known_state,
"Current Service Pseudo-State");
}
}
/* Next determine the initial state of the service */
initial_service_state = get_initial_subject_state(service->log_entries,
start_time, end_time);
#ifdef DEBUG
printf(" Initial state from logs: %s\n",
svm_get_string_from_value(initial_service_state, valid_states));
#endif
if((AU_STATE_NO_DATA == initial_service_state) &&
(1 == assume_initial_state)) {
switch(assumed_initial_service_state) {
case AU_STATE_SERVICE_OK:
case AU_STATE_SERVICE_WARNING:
case AU_STATE_SERVICE_UNKNOWN:
case AU_STATE_SERVICE_CRITICAL:
initial_service_state = assumed_initial_service_state;
break;
case AU_STATE_CURRENT_STATE:
if(service_status == NULL) {
switch(service_status->status) {
case SERVICE_OK:
initial_service_state = AU_STATE_SERVICE_OK;
break;
case SERVICE_WARNING:
initial_service_state = AU_STATE_SERVICE_WARNING;
break;
case SERVICE_UNKNOWN:
initial_service_state = AU_STATE_SERVICE_UNKNOWN;
break;
case SERVICE_CRITICAL:
initial_service_state = AU_STATE_SERVICE_CRITICAL;
break;
}
}
break;
}
}
/* At this point, if we still don't have any real data, we can't compute
anything, so return */
if((have_real_data(service->log_entries) != TRUE) &&
(AU_STATE_NO_DATA == initial_service_state)) return;
/* Compute the availability for every entry in the service's list of log
entries */
compute_availability(service->log_entries, query_time, start_time, end_time,
report_timeperiod, service->availability, initial_service_state,
assume_state_during_nagios_downtime, AU_OBJTYPE_SERVICE,
assume_state_retention);
}
json_object *json_archive_availability_selectors(unsigned format_options,
time_t start_time, time_t end_time, int availability_object_type,
char *host_name, char *service_description, hostgroup *hostgroup,
servicegroup *servicegroup, timeperiod *report_timeperiod,
int assume_initial_state, int assume_state_retention,
int assume_state_during_nagios_downtime,
int assumed_initial_host_state, int assumed_initial_service_state,
unsigned state_types) {
json_object *json_selectors;
json_selectors = json_new_object();
json_enumeration(json_selectors, format_options, "availabilityobjecttype",
availability_object_type, valid_availability_object_types);
if(start_time > 0) {
json_object_append_time_t(json_selectors, "starttime", start_time);
}
if(end_time > 0) {
json_object_append_time_t(json_selectors, "endtime", end_time);
}
if(NULL != host_name) {
json_object_append_string(json_selectors, "hostname", &percent_escapes,
host_name);
}
if(NULL != service_description) {
json_object_append_string(json_selectors, "servicedescription",
&percent_escapes, service_description);
}
if(NULL != hostgroup) {
json_object_append_string(json_selectors, "hostgroup", &percent_escapes,
hostgroup->group_name);
}
if(NULL != servicegroup) {
json_object_append_string(json_selectors, "servicegroup",
&percent_escapes, servicegroup->group_name);
}
if(NULL != report_timeperiod) {
json_object_append_string(json_selectors, "timeperiod",
&percent_escapes, report_timeperiod->name);
}
json_object_append_boolean(json_selectors, "assumeinitialstate",
assume_initial_state);
json_object_append_boolean(json_selectors, "assumestateretention",
assume_state_retention);
json_object_append_boolean(json_selectors,
"assumestateduringnagiosdowntime",
assume_state_during_nagios_downtime);
if(assumed_initial_host_state != AU_STATE_NO_DATA) {
json_enumeration(json_selectors, format_options,
"assumedinitialhoststate", assumed_initial_host_state,
valid_initial_host_states);
}
if(assumed_initial_service_state != AU_STATE_NO_DATA) {
json_enumeration(json_selectors, format_options,
"assumedinitialservicestate", assumed_initial_service_state,
valid_initial_service_states);
}
if(state_types != AU_STATETYPE_ALL) {
json_bitmask(json_selectors, format_options, "statetypes", state_types,
valid_state_types);
}
return json_selectors;
}
json_object *json_archive_availability(unsigned format_options,
time_t query_time, time_t start_time, time_t end_time,
int availability_object_type, char *host_name,
char *service_description, hostgroup *hostgroup_selector,
servicegroup *servicegroup_selector, timeperiod *report_timeperiod,
int assume_initial_state, int assume_state_retention,
int assume_state_during_nagios_downtime,
int assumed_initial_host_state, int assumed_initial_service_state,
unsigned state_types, au_log *log) {
json_object *json_data;
host *temp_host;
json_array *json_host_list;
json_object *json_host_object;
service *temp_service;
json_array *json_service_list;
json_object *json_service_object;
hostgroup *temp_hostgroup;
json_object *json_hostgroup_object;
json_array *json_hostgroup_list;
hostsmember *temp_hostgroup_member;
servicegroup *temp_servicegroup;
json_object *json_servicegroup_object;
json_array *json_servicegroup_list;
servicesmember *temp_servicegroup_member;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_archive_availability_selectors(format_options, start_time,
end_time, availability_object_type, host_name, service_description,
hostgroup_selector, servicegroup_selector, report_timeperiod,
assume_initial_state, assume_state_retention,
assume_state_during_nagios_downtime, assumed_initial_host_state,
assumed_initial_service_state, state_types));
/* First compute the availability */
switch(availability_object_type) {
case AU_OBJTYPE_HOST:
if(NULL == host_name) { /* compute for all hosts */
json_host_list = json_new_array();
for(temp_host = host_list; temp_host != NULL;
temp_host = temp_host->next) {
if(FALSE == is_authorized_for_host(temp_host,
¤t_authdata)) {
continue;
}
json_host_object =
json_archive_single_host_availability(
format_options, query_time, start_time, end_time,
temp_host->name, report_timeperiod,
assume_initial_state, assume_state_retention,
assume_state_during_nagios_downtime,
assumed_initial_host_state, state_types, log);
if(NULL != json_host_object) {
json_array_append_object(json_host_list,
json_host_object);
}
}
json_object_append_array(json_data, "hosts", json_host_list);
}
else {
temp_host = find_host(host_name);
if((NULL != temp_host) &&
(TRUE == is_authorized_for_host(temp_host,
¤t_authdata))) {
json_host_object =
json_archive_single_host_availability(format_options,
query_time, start_time, end_time, host_name,
report_timeperiod, assume_initial_state,
assume_state_retention,
assume_state_during_nagios_downtime,
assumed_initial_host_state, state_types, log);
if(NULL != json_host_object) {
json_object_append_object(json_data, "host",
json_host_object);
}
}
}
break;
case AU_OBJTYPE_SERVICE:
if((NULL == host_name) && (NULL == service_description)) {
/* compute for all services on all hosts */
json_service_list = json_new_array();
for(temp_service = service_list; temp_service != NULL;
temp_service = temp_service->next) {
if(FALSE == is_authorized_for_service(temp_service,
¤t_authdata)) {
continue;
}
json_service_object =
json_archive_single_service_availability(
format_options, query_time, start_time, end_time,
temp_service->host_name, temp_service->description,
report_timeperiod, assume_initial_state,
assume_state_retention,
assume_state_during_nagios_downtime,
assumed_initial_service_state, state_types, log);
if(NULL != json_service_object) {
json_array_append_object(json_service_list,
json_service_object);
}
}
json_object_append_array(json_data, "services",
json_service_list);
}
else if(NULL == service_description) {
/* compute for all services on the specified host */
json_service_list = json_new_array();
for(temp_service = service_list; temp_service != NULL;
temp_service = temp_service->next) {
if(!strcmp(temp_service->host_name, host_name) &&
(TRUE == is_authorized_for_service(temp_service,
¤t_authdata))) {
json_service_object =
json_archive_single_service_availability(
format_options, query_time, start_time,
end_time, temp_service->host_name,
temp_service->description, report_timeperiod,
assume_initial_state, assume_state_retention,
assume_state_during_nagios_downtime,
assumed_initial_service_state, state_types,
log);
if(NULL != json_service_object) {
json_array_append_object(json_service_list,
json_service_object);
}
}
}
json_object_append_array(json_data, "services",
json_service_list);
}
else if(NULL == host_name) {
/* compute for all services on the specified host */
json_service_list = json_new_array();
for(temp_service = service_list; temp_service != NULL;
temp_service = temp_service->next) {
if(!strcmp(temp_service->description,
service_description) &&
(TRUE == is_authorized_for_service(temp_service,
¤t_authdata))) {
json_service_object =
json_archive_single_service_availability(
format_options, query_time, start_time,
end_time, temp_service->host_name,
temp_service->description, report_timeperiod,
assume_initial_state, assume_state_retention,
assume_state_during_nagios_downtime,
assumed_initial_service_state, state_types,
log);
if(NULL != json_service_object) {
json_array_append_object(json_service_list,
json_service_object);
}
}
}
json_object_append_array(json_data, "services",
json_service_list);
}
else {
temp_service = find_service(host_name, service_description);
if((NULL != temp_service) &&
(TRUE == is_authorized_for_service(temp_service,
¤t_authdata))) {
json_service_object =
json_archive_single_service_availability(format_options,
query_time, start_time, end_time, host_name,
service_description, report_timeperiod,
assume_initial_state, assume_state_retention,
assume_state_during_nagios_downtime,
assumed_initial_service_state, state_types, log);
if(NULL != json_service_object) {
json_object_append_object(json_data, "service",
json_service_object);
}
}
}
break;
case AU_OBJTYPE_HOSTGROUP:
if(NULL == hostgroup_selector) {
/* compute for all hosts in all hostgroups */
json_hostgroup_list = json_new_array();
for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL;
temp_hostgroup = temp_hostgroup->next) {
json_host_list = json_new_array();
for(temp_hostgroup_member = temp_hostgroup->members;
temp_hostgroup_member != NULL;
temp_hostgroup_member =
temp_hostgroup_member->next) {
if(FALSE == is_authorized_for_host(temp_hostgroup_member->host_ptr,
¤t_authdata)) {
continue;
}
json_host_object =
json_archive_single_host_availability(
format_options, query_time, start_time,
end_time, temp_hostgroup_member->host_name,
report_timeperiod, assume_initial_state,
assume_state_retention,
assume_state_during_nagios_downtime,
assumed_initial_host_state, state_types, log);
if(NULL != json_host_object) {
json_array_append_object(json_host_list,
json_host_object);
}
}
json_hostgroup_object = json_new_object();
json_object_append_string(json_hostgroup_object, "name",
&percent_escapes, temp_hostgroup->group_name);
json_object_append_array(json_hostgroup_object, "hosts",
json_host_list);
json_array_append_object(json_hostgroup_list,
json_hostgroup_object);
}
json_object_append_array(json_data, "hostgroups",
json_hostgroup_list);
}
else {
/* compute for all hosts in the specified hostgroup */
json_host_list = json_new_array();
for(temp_hostgroup_member = hostgroup_selector->members;
temp_hostgroup_member != NULL;
temp_hostgroup_member = temp_hostgroup_member->next) {
if(FALSE == is_authorized_for_host(temp_hostgroup_member->host_ptr,
¤t_authdata)) {
continue;
}
json_host_object =
json_archive_single_host_availability(
format_options, query_time, start_time, end_time,
temp_hostgroup_member->host_name, report_timeperiod,
assume_initial_state, assume_state_retention,
assume_state_during_nagios_downtime,
assumed_initial_host_state, state_types, log);
if(NULL != json_host_object) {
json_array_append_object(json_host_list,
json_host_object);
}
}
json_hostgroup_object = json_new_object();
json_object_append_string(json_hostgroup_object, "name",
&percent_escapes, hostgroup_selector->group_name);
json_object_append_array(json_hostgroup_object, "hosts",
json_host_list);
json_object_append_object(json_data, "hostgroup",
json_hostgroup_object);
}
break;
case AU_OBJTYPE_SERVICEGROUP:
if(NULL == servicegroup_selector) {
/* compute for all hosts in all hostgroups */
json_servicegroup_list = json_new_array();
for(temp_servicegroup = servicegroup_list;
temp_servicegroup != NULL;
temp_servicegroup = temp_servicegroup->next) {
json_service_list = json_new_array();
for(temp_servicegroup_member = temp_servicegroup->members;
temp_servicegroup_member != NULL;
temp_servicegroup_member =
temp_servicegroup_member->next) {
if(FALSE == is_authorized_for_service(temp_servicegroup_member->service_ptr,
¤t_authdata)) {
continue;
}
json_service_object =
json_archive_single_service_availability(
format_options, query_time, start_time,
end_time, temp_servicegroup_member->host_name,
temp_servicegroup_member->service_description,
report_timeperiod, assume_initial_state,
assume_state_retention,
assume_state_during_nagios_downtime,
assumed_initial_service_state, state_types,
log);
if(NULL != json_service_object) {
json_array_append_object(json_service_list,
json_service_object);
}
}
json_servicegroup_object = json_new_object();
json_object_append_string(json_servicegroup_object, "name",
&percent_escapes, temp_servicegroup->group_name);
json_object_append_array(json_servicegroup_object, "hosts",
json_service_list);
json_array_append_object(json_servicegroup_list,
json_servicegroup_object);
}
json_object_append_array(json_data, "servicegroups",
json_servicegroup_list);
}
else {
/* compute for all services in the specified servicegroup */
json_service_list = json_new_array();
for(temp_servicegroup_member = servicegroup_selector->members;
temp_servicegroup_member != NULL;
temp_servicegroup_member =
temp_servicegroup_member->next) {
if(FALSE == is_authorized_for_service(temp_servicegroup_member->service_ptr,
¤t_authdata)) {
continue;
}
json_service_object =
json_archive_single_service_availability(
format_options, query_time, start_time, end_time,
temp_servicegroup_member->host_name,
temp_servicegroup_member->service_description,
report_timeperiod, assume_initial_state,
assume_state_retention,
assume_state_during_nagios_downtime,
assumed_initial_service_state, state_types, log);
if(NULL != json_service_object) {
json_array_append_object(json_service_list,
json_service_object);
}
}
json_servicegroup_object = json_new_object();
json_object_append_string(json_servicegroup_object, "name",
&percent_escapes, servicegroup_selector->group_name);
json_object_append_array(json_servicegroup_object, "services",
json_service_list);
json_object_append_object(json_data, "servicegroup",
json_servicegroup_object);
}
break;
default:
break;
}
return json_data;
}
json_object *json_archive_single_host_availability(unsigned format_options,
time_t query_time, time_t start_time, time_t end_time, char *host_name,
timeperiod *report_timeperiod, int assume_initial_state,
int assume_state_retention, int assume_state_during_nagios_downtime,
int assumed_initial_host_state, unsigned state_types, au_log *log) {
au_host *host = NULL;
au_node *temp_entry = NULL;
au_host *global_host = NULL;
json_object *json_host_availability = NULL;
host = au_find_host(log->hosts, host_name);
if(NULL == host) {
/* host has no log entries, so create the host */
host = au_add_host(log->hosts, host_name);
/* Add global events to this new host */
global_host = au_find_host(log->hosts, "*");
if(NULL != global_host) {
for(temp_entry = global_host->log_entries->head; NULL != temp_entry;
temp_entry = temp_entry->next) {
if(au_list_add_node(host->log_entries, temp_entry->data,
au_cmp_log_entries) == 0) {
break;
}
}
}
}
if((host->availability = calloc(1, sizeof(au_availability))) != NULL) {
compute_host_availability(query_time, start_time, end_time, log, host,
report_timeperiod, assume_initial_state,
assumed_initial_host_state,
assume_state_during_nagios_downtime, assume_state_retention);
json_host_availability = json_archive_host_availability(format_options,
host->name, host->availability);
}
return json_host_availability;
}
json_object *json_archive_single_service_availability(unsigned format_options,
time_t query_time, time_t start_time, time_t end_time, char *host_name,
char *service_description, timeperiod *report_timeperiod,
int assume_initial_state, int assume_state_retention,
int assume_state_during_nagios_downtime,
int assumed_initial_service_state, unsigned state_types, au_log *log) {
au_service *service = NULL;
au_node *temp_entry = NULL;
au_host *global_host = NULL;
json_object *json_service_availability = NULL;
service = au_find_service(log->services, host_name, service_description);
if(NULL == service) {
/* service has no log entries, so create the service */
service = au_add_service(log->services, host_name, service_description);
/* Add global events to this new service */
global_host = au_find_host(log->hosts, "*");
if(NULL != global_host) {
for(temp_entry = global_host->log_entries->head; NULL != temp_entry;
temp_entry = temp_entry->next) {
if(au_list_add_node(service->log_entries, temp_entry->data,
au_cmp_log_entries) == 0) {
break;
}
}
}
}
if((service->availability = calloc(1, sizeof(au_availability))) != NULL) {
compute_service_availability(query_time, start_time, end_time, log,
service, report_timeperiod, assume_initial_state,
assumed_initial_service_state,
assume_state_during_nagios_downtime, assume_state_retention);
json_service_availability =
json_archive_service_availability(format_options,
service->host_name, service->description,
service->availability);
}
return json_service_availability;
}
json_object *json_archive_host_availability(unsigned format_options,
char *name, au_availability *availability) {
json_object *json_host_availability;
json_host_availability = json_new_object();
if(name != NULL) {
json_object_append_string(json_host_availability, "name",
&percent_escapes, name);
}
json_object_append_duration(json_host_availability, "time_up",
availability->time_up);
json_object_append_duration(json_host_availability, "time_down",
availability->time_down);
json_object_append_duration(json_host_availability, "time_unreachable",
availability->time_unreachable);
json_object_append_duration(json_host_availability, "scheduled_time_up",
availability->scheduled_time_up);
json_object_append_duration(json_host_availability, "scheduled_time_down",
availability->scheduled_time_down);
json_object_append_duration(json_host_availability,
"scheduled_time_unreachable",
availability->scheduled_time_unreachable);
json_object_append_duration(json_host_availability,
"time_indeterminate_nodata",
availability->time_indeterminate_nodata);
json_object_append_duration(json_host_availability,
"time_indeterminate_notrunning",
availability->time_indeterminate_notrunning);
return json_host_availability;
}
json_object *json_archive_service_availability(unsigned format_options,
char *host_name, char *description, au_availability *availability) {
json_object *json_service_availability;
json_service_availability = json_new_object();
if(host_name != NULL) {
json_object_append_string(json_service_availability, "host_name",
&percent_escapes, host_name);
}
if(description != NULL) {
json_object_append_string(json_service_availability, "description",
&percent_escapes, description);
}
json_object_append_duration(json_service_availability, "time_ok",
availability->time_ok);
json_object_append_duration(json_service_availability, "time_warning",
availability->time_warning);
json_object_append_duration(json_service_availability, "time_critical",
availability->time_critical);
json_object_append_duration(json_service_availability, "time_unknown",
availability->time_unknown);
json_object_append_duration(json_service_availability, "scheduled_time_ok",
availability->scheduled_time_ok);
json_object_append_duration(json_service_availability,
"scheduled_time_warning", availability->scheduled_time_warning);
json_object_append_duration(json_service_availability,
"scheduled_time_critical", availability->scheduled_time_critical);
json_object_append_duration(json_service_availability,
"scheduled_time_unknown", availability->scheduled_time_unknown);
json_object_append_duration(json_service_availability,
"time_indeterminate_nodata",
availability->time_indeterminate_nodata);
json_object_append_duration(json_service_availability,
"time_indeterminate_notrunning",
availability->time_indeterminate_notrunning);
return json_service_availability;
}
nagios-4.4.6/cgi/archiveutils.c 0000664 0000000 0000000 00000132572 13652113235 0016430 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* ARCHIVEUTILS.C - Utilities for Nagios CGIs that read archive logs
*
* Copyright (c) 2013 Nagios Enterprises, LLC
* Last Modified: 06-30-2013
*
* 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/statusdata.h"
#include "../include/comments.h"
#include "../include/cgiutils.h"
#include "../include/statusdata.h"
#include "../include/archiveutils.h"
#define AU_INITIAL_LIST_SIZE 16
const string_value_mapping svm_au_object_types[] = {
{ "none", AU_OBJTYPE_NONE, "None" },
{ "host", AU_OBJTYPE_HOST, "Host" },
{ "service", AU_OBJTYPE_SERVICE, "Service" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_au_state_types[] = {
{ "hard", AU_STATETYPE_HARD, "Hard" },
{ "soft", AU_STATETYPE_SOFT, "Soft" },
{ "nodata", AU_STATETYPE_NO_DATA, "No Data" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_au_states[] = {
{ "nodata", AU_STATE_NO_DATA, "No Data" },
{ "up", AU_STATE_HOST_UP, "Host Up" },
{ "down", AU_STATE_HOST_DOWN, "How Down" },
{ "unreachable", AU_STATE_HOST_UNREACHABLE, "Host Unreachable" },
{ "ok", AU_STATE_SERVICE_OK, "Service OK" },
{ "warning", AU_STATE_SERVICE_WARNING, "Service Warning" },
{ "critical", AU_STATE_SERVICE_CRITICAL, "Service Critical" },
{ "unknown", AU_STATE_SERVICE_UNKNOWN, "Service Unknown" },
{ "programstart", AU_STATE_PROGRAM_START, "Program Start"},
{ "programend", AU_STATE_PROGRAM_END, "Program End"},
{ "downtimestart", AU_STATE_DOWNTIME_START, "Downtime Start"},
{ "downtimeend", AU_STATE_DOWNTIME_END, "Downtime End"},
{ "currentstate", AU_STATE_CURRENT_STATE, "Current State"},
{ NULL, -1, NULL },
};
const string_value_mapping svm_au_log_types[] = {
{ "alert", AU_LOGTYPE_ALERT, "Alert" },
{ "initialstate", AU_LOGTYPE_STATE_INITIAL, "Initial State" },
{ "currentstate", AU_LOGTYPE_STATE_CURRENT, "Current State" },
{ "notification", AU_LOGTYPE_NOTIFICATION, "Notification" },
{ "downtime", AU_LOGTYPE_DOWNTIME, "Downtime" },
{ "nagios", AU_LOGTYPE_NAGIOS, "Nagios" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_au_notification_types[] = {
{ "nodata", AU_NOTIFICATION_NO_DATA,
"No Data" },
{ "down", AU_NOTIFICATION_HOST_DOWN,
"Host Down" },
{ "unreachable", AU_NOTIFICATION_HOST_UNREACHABLE,
"Host Unreachable" },
{ "recovery", AU_NOTIFICATION_HOST_RECOVERY,
"Host Recovery" },
{ "hostcustom", AU_NOTIFICATION_HOST_CUSTOM,
"Host Custom" },
{ "hostack", AU_NOTIFICATION_HOST_ACK,
"Host Acknowledgement" },
{ "hostflapstart", AU_NOTIFICATION_HOST_FLAPPING_START,
"Host Flapping Start" },
{ "hostflapstop", AU_NOTIFICATION_HOST_FLAPPING_STOP,
"Host Flapping Stop" },
{ "critical", AU_NOTIFICATION_SERVICE_CRITICAL,
"Service Critical" },
{ "warning", AU_NOTIFICATION_SERVICE_WARNING,
"Service Warning" },
{ "recovery", AU_NOTIFICATION_SERVICE_RECOVERY,
"Service Recovery" },
{ "custom", AU_NOTIFICATION_SERVICE_CUSTOM,
"Service Custom" },
{ "serviceack", AU_NOTIFICATION_SERVICE_ACK,
"Service Acknowledgement" },
{ "serviceflapstart", AU_NOTIFICATION_SERVICE_FLAPPING_START,
"Service Flapping Start" },
{ "serviceflapstop", AU_NOTIFICATION_SERVICE_FLAPPING_STOP,
"Service Flapping Stop" },
{ "unknown", AU_NOTIFICATION_SERVICE_UNKNOWN,
"Service Unknown" },
{ NULL, -1, NULL },
};
/* Function prototypes */
int read_log_file(char *, unsigned, unsigned, unsigned, au_log *);
int au_add_nagios_log(au_log *, time_t, int, char *);
void au_free_nagios_log(au_log_nagios *);
int parse_states_and_alerts(char *, time_t, int, unsigned, unsigned, au_log *);
int parse_downtime_alerts(char *, time_t, unsigned, au_log *);
int au_add_downtime_log(au_log *, time_t, int, void *, int);
void au_free_downtime_log(au_log_downtime *);
int parse_notification_log(char *, time_t, int, au_log *);
int au_add_notification_log(au_log *, time_t, int, void *, au_contact *, int,
char *, char *);
void au_free_notification_log(au_log_notification *);
au_log_entry *au_add_log_entry(au_log *, time_t, int, void *);
void au_free_log_entry_void(void *);
void au_free_log_entry(au_log_entry *);
au_host *au_add_host_and_sort(au_array *, char *);
void au_free_host_void(void *);
void au_free_host(au_host *);
int au_cmp_hosts(const void *, const void *);
au_service *au_add_service_and_sort(au_array *, char *, char *);
int au_cmp_services(const void *, const void *);
void au_free_service_void(void *);
void au_free_service(au_service *);
au_contact *au_add_contact_and_sort(au_array *, char *);
au_contact *au_add_contact(au_array *, char *);
void au_free_contact_void(void *);
void au_free_contact(au_contact *);
int au_cmp_contacts(const void *, const void *);
au_contact *au_find_contact(au_array *, char *);
void au_sort_array(au_array *, int(*cmp)(const void *, const void *));
void *au_find_in_array(au_array *, void *,
int(*cmp)(const void *, const void *));
au_linked_list *au_init_list(char *);
void au_empty_list(au_linked_list *, void(*)(void *));
void au_free_list(au_linked_list *, void(*)(void *));
/* External variables */
extern int log_rotation_method;
/* Initialize log structure */
au_log *au_init_log(void) {
au_log *log;
/* Initialize the log structure itself */
if((log = calloc(1, sizeof( au_log))) == NULL) {
return NULL;
}
/* Initialize the host subjects */
if((log->host_subjects = au_init_array("host_subjects")) == NULL) {
au_free_log(log);
return NULL;
}
/* Initialize the service subjects */
if((log->service_subjects = au_init_array("service_subjects")) == NULL) {
au_free_log(log);
return NULL;
}
/* Initialize the log entry list */
if((log->entry_list = au_init_list("global log entries")) == NULL) {
au_free_log(log);
return NULL;
}
/* Initialize the host list */
if((log->hosts = au_init_array("hosts")) == NULL) {
au_free_log(log);
return NULL;
}
/* Initialize the service list */
if((log->services = au_init_array("services")) == NULL) {
au_free_log(log);
return NULL;
}
/* Initialize the contact list */
if((log->contacts = au_init_array("contacts")) == NULL) {
au_free_log(log);
return NULL;
}
return log;
}
void au_free_log(au_log *log) {
if(NULL == log) return;
if(NULL != log->host_subjects) {
au_free_array(log->host_subjects, au_free_host_void);
}
if(NULL != log->service_subjects) {
au_free_array(log->service_subjects, au_free_service_void);
}
if(NULL != log->hosts) {
au_free_array(log->hosts, au_free_host_void);
}
if(NULL != log->services) {
au_free_array(log->services, au_free_service_void);
}
if(NULL != log->contacts) {
au_free_array(log->contacts, au_free_contact_void);
}
if(NULL != log->entry_list) {
au_free_list(log->entry_list, au_free_log_entry_void);
}
free(log);
}
/* reads log files for archived data */
int read_archived_data(time_t start_time, time_t end_time,
int backtrack_archives, unsigned obj_types, unsigned state_types,
unsigned log_types, au_log *log, time_t *last_archive_data_update) {
char filename[MAX_FILENAME_LENGTH];
int oldest_archive = 0;
int newest_archive = 0;
int current_archive = 0;
int x;
int retval = 1;
au_host *global_host;
au_host *temp_host;
au_service *temp_service;
au_node *temp_entry;
struct stat adstat;
/* Determine oldest archive to use when scanning for data
(include backtracked archives as well) */
oldest_archive = determine_archive_to_use_from_time(start_time);
if(log_rotation_method != LOG_ROTATION_NONE) {
oldest_archive += backtrack_archives;
}
/* determine most recent archive to use when scanning for data */
newest_archive = determine_archive_to_use_from_time(end_time);
if(oldest_archive < newest_archive) {
oldest_archive = newest_archive;
}
/* read in all the necessary archived logs (from most recent to earliest) */
for(current_archive = newest_archive; current_archive <= oldest_archive;
current_archive++) {
#ifdef DEBUG
printf("Reading archive #%d... ", current_archive);
#endif
/* get the name of the log file that contains this archive */
get_log_archive_to_use(current_archive, filename, sizeof(filename) - 1);
#ifdef DEBUG
printf("Archive name: '%s'\n", filename);
#endif
/* Record the last modification time of the the archive file */
if(stat(filename, &adstat) < 0) {
/* ENOENT is OK because Nagios may have been down when the
logs were being rotated */
if(ENOENT != errno) return -1;
}
else {
if(*last_archive_data_update < adstat.st_mtime) {
*last_archive_data_update = adstat.st_mtime;
}
/* scan the log file for archived state data */
if(read_log_file(filename, obj_types, state_types, log_types,
log) == 0) {
return 0; /* Memory allocation error */
}
}
}
/* Add Nagios log events to all hosts and services found */
global_host = au_find_host(log->hosts, "*");
if(NULL != global_host) {
for(temp_entry = global_host->log_entries->head; NULL != temp_entry;
temp_entry = temp_entry->next) {
for(x = 0; x < log->hosts->count; x++) {
temp_host = log->hosts->members[x];
if(temp_host == global_host) continue;
if(au_list_add_node(temp_host->log_entries,
temp_entry->data, au_cmp_log_entries) == 0) {
retval = 0;
break;
}
}
if(0 == retval) break;
for(x = 0; x < log->services->count; x++) {
temp_service = log->services->members[x];
if(au_list_add_node(temp_service->log_entries,
temp_entry->data, au_cmp_log_entries) == 0) {
retval = 0;
break;
}
}
if(0 == retval) break;
}
}
return 1;
}
/* grabs archives state data from a log file */
int read_log_file(char *filename, unsigned obj_types, unsigned state_types,
unsigned log_types, au_log *log) {
char *input = NULL;
char *input2 = NULL;
char *temp_buffer = NULL;
time_t time_stamp;
mmapfile *thefile = NULL;
int retval = 1;
if((thefile = mmap_fopen(filename)) == NULL) {
return 1;
}
while(1) {
/* free memory */
free(input);
free(input2);
input = NULL;
input2 = NULL;
/* read the next line */
if((input = mmap_fgets(thefile)) == NULL) break;
strip(input);
if((input2 = strdup(input)) == NULL) continue;
temp_buffer = my_strtok(input2, "]");
time_stamp = (temp_buffer == NULL) ? (time_t)0 :
(time_t)strtoul(temp_buffer + 1, NULL, 10);
/* program starts/restarts */
if(strstr(input, " starting...")) {
if(au_add_nagios_log(log, time_stamp, AU_STATE_PROGRAM_START,
"Program start") == 0) {
retval = 0;
break;
}
}
if(strstr(input, " restarting...")) {
if(au_add_nagios_log(log, time_stamp, AU_STATE_PROGRAM_START,
"Program restart") == 0) {
retval = 0;
break;
}
}
/* program stops */
if(strstr(input, " shutting down...")) {
if(au_add_nagios_log(log, time_stamp, AU_STATE_PROGRAM_END,
"Normal program termination") == 0) {
retval = 0;
break;
}
}
if(strstr(input, "Bailing out")) {
if(au_add_nagios_log(log, time_stamp, AU_STATE_PROGRAM_END,
"Abnormal program termination") == 0) {
retval = 0;
break;
}
}
if(obj_types & AU_OBJTYPE_HOST) {
/* normal host alerts */
if((log_types & AU_LOGTYPE_ALERT) && strstr(input, "HOST ALERT:")) {
if(parse_states_and_alerts(input, time_stamp, AU_LOGTYPE_ALERT,
AU_OBJTYPE_HOST, state_types, log) == 0) {
retval = 0;
break;
}
}
/* host initial states */
else if((log_types & AU_LOGTYPE_STATE) &&
strstr(input, "INITIAL HOST STATE:")) {
if(parse_states_and_alerts(input, time_stamp,
AU_LOGTYPE_STATE_INITIAL, AU_OBJTYPE_HOST, state_types,
log) == 0) {
retval = 0;
break;
}
}
/* host current states */
else if((log_types & AU_LOGTYPE_STATE) &&
strstr(input, "CURRENT HOST STATE:")) {
if(parse_states_and_alerts(input, time_stamp,
AU_LOGTYPE_STATE_CURRENT, AU_OBJTYPE_HOST, state_types,
log) == 0) {
retval = 0;
break;
}
}
/* scheduled downtime notices */
else if((log_types & AU_LOGTYPE_DOWNTIME) &&
strstr(input, "HOST DOWNTIME ALERT:")) {
if(parse_downtime_alerts(input, time_stamp, AU_OBJTYPE_HOST,
log) == 0) {
retval = 0;
break;
}
}
/* host notifications */
else if((log_types & AU_LOGTYPE_NOTIFICATION) &&
strstr(input, "HOST NOTIFICATION:")) {
if(parse_notification_log(input, time_stamp, AU_OBJTYPE_HOST,
log) ==0) {
retval = 0;
break;
}
}
}
if(obj_types & AU_OBJTYPE_SERVICE) {
/* normal service alerts */
if((log_types & AU_LOGTYPE_ALERT) &&
strstr(input, "SERVICE ALERT:")) {
if(parse_states_and_alerts(input, time_stamp, AU_LOGTYPE_ALERT,
AU_OBJTYPE_SERVICE, state_types, log) == 0) {
retval = 0;
break;
}
}
/* service initial states */
else if((log_types & AU_LOGTYPE_STATE) &&
strstr(input, "INITIAL SERVICE STATE:")) {
if(parse_states_and_alerts(input, time_stamp,
AU_LOGTYPE_STATE_INITIAL, AU_OBJTYPE_SERVICE,
state_types, log) == 0) {
retval = 0;
break;
}
}
/* service current states */
else if((log_types & AU_LOGTYPE_STATE) &&
strstr(input, "CURRENT SERVICE STATE:")) {
if(parse_states_and_alerts(input, time_stamp,
AU_LOGTYPE_STATE_CURRENT, AU_OBJTYPE_SERVICE,
state_types, log) == 0) {
retval = 0;
break;
}
}
/* scheduled service downtime notices */
else if((log_types & AU_LOGTYPE_DOWNTIME) &&
strstr(input, "SERVICE DOWNTIME ALERT:")) {
if(parse_downtime_alerts(input, time_stamp, AU_OBJTYPE_SERVICE,
log) == 0) {
retval = 0;
break;
}
}
/* service notifications */
else if((log_types & AU_LOGTYPE_NOTIFICATION) &&
strstr(input, "SERVICE NOTIFICATION:")) {
if(parse_notification_log(input, time_stamp,
AU_OBJTYPE_SERVICE, log) ==0) {
retval = 0;
break;
}
}
}
}
/* free memory and close the file */
free(input);
free(input2);
mmap_fclose(thefile);
return retval;
}
int au_cmp_log_entries(const void *a, const void *b) {
au_log_entry *lea = *(au_log_entry **)a;
au_log_entry *leb = *(au_log_entry **)b;
if(lea->timestamp == leb->timestamp) return 0;
else if(lea->timestamp < leb->timestamp) return -1;
else return 1;
}
int au_add_nagios_log(au_log *log, time_t timestamp, int type,
char *description) {
au_log_nagios *nagios_log;
au_log_entry *new_log_entry;
au_host *global_host;
/* Create the au_log_nagios */
if((nagios_log = calloc(1, sizeof(au_log_nagios))) == NULL) {
return 0;
}
nagios_log->type = type;
if((nagios_log->description = strdup(description)) == NULL) {
au_free_nagios_log(nagios_log);
return 0;
}
/* Create the log entry */
if((new_log_entry = au_add_log_entry(log, timestamp, AU_LOGTYPE_NAGIOS,
(void *)nagios_log)) == NULL) {
au_free_nagios_log(nagios_log);
return 0;
}
/* Find the au_host object associated with the global host */
global_host = au_find_host(log->hosts, "*");
if(NULL == global_host) {
global_host = au_add_host_and_sort(log->hosts, "*");
if(NULL == global_host) { /* Could not allocate memory */
return 0;
}
}
/* Add the entry to the global host */
if(au_list_add_node(global_host->log_entries, new_log_entry,
au_cmp_log_entries) == 0) {
return 0;
}
return 1;
}
void au_free_nagios_log(au_log_nagios *nagios_log) {
if(NULL == nagios_log) return;
if(NULL != nagios_log->description) free(nagios_log->description);
free(nagios_log);
}
/* parse state and alert log entries */
int parse_states_and_alerts(char *input, time_t timestamp, int log_type,
unsigned obj_type, unsigned state_types, au_log *log) {
char *temp_buffer = NULL;
char entry_host_name[MAX_INPUT_BUFFER];
char entry_svc_description[MAX_INPUT_BUFFER];
char *plugin_output;
au_host *temp_host_subject;
au_host *temp_host = NULL;
au_service *temp_service_subject;
au_service *temp_service = NULL;
int state_type;
int state;
/* get host name */
temp_buffer = my_strtok(NULL, ":");
temp_buffer = my_strtok(NULL, ";");
strncpy(entry_host_name, (temp_buffer == NULL) ? "" :
temp_buffer + 1, sizeof(entry_host_name));
entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
switch(obj_type) {
case AU_OBJTYPE_HOST:
if(log->host_subjects->count > 0) {
/* see if there is a corresponding subject for this host */
temp_host_subject = au_find_host(log->host_subjects,
entry_host_name);
if(temp_host_subject == NULL) return 1;
}
/* Find the au_host object associated with the host name */
temp_host = au_find_host(log->hosts, entry_host_name);
if(NULL == temp_host) {
temp_host = au_add_host_and_sort(log->hosts, entry_host_name);
if(NULL == temp_host) { /* Could not allocate memory */
return 0;
}
}
break;
case AU_OBJTYPE_SERVICE:
/* get service description */
temp_buffer = my_strtok(NULL, ";");
strncpy(entry_svc_description, (temp_buffer == NULL) ? "" :
temp_buffer, sizeof(entry_svc_description));
entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0';
if(log->service_subjects->count > 0) {
/* see if there is a corresponding subject for this service */
temp_service_subject = au_find_service(log->service_subjects,
entry_host_name, entry_svc_description);
if(temp_service_subject == NULL) return 1;
}
/* Find the au_service object associated with the service */
temp_service = au_find_service(log->services, entry_host_name,
entry_svc_description);
if(NULL == temp_service) {
temp_service = au_add_service_and_sort(log->services,
entry_host_name, entry_svc_description);
if(NULL == temp_service) { /* Could not allocate memory */
return 0;
}
}
break;
}
/* state types */
if(strstr(input, ";SOFT;")) {
if(!(state_types & AU_STATETYPE_SOFT)) return 1;
state_type = AU_STATETYPE_SOFT;
}
if(strstr(input, ";HARD;")) {
if(!(state_types & AU_STATETYPE_HARD)) return 1;
state_type = AU_STATETYPE_HARD;
}
/* get the plugin output */
temp_buffer = my_strtok(NULL, ";");
temp_buffer = my_strtok(NULL, ";");
temp_buffer = my_strtok(NULL, ";");
plugin_output = my_strtok(NULL, "\n");
switch(obj_type) {
case AU_OBJTYPE_HOST:
if(strstr(input, ";DOWN;")) {
state = AU_STATE_HOST_DOWN;
}
else if(strstr(input, ";UNREACHABLE;")) {
state = AU_STATE_HOST_UNREACHABLE;
}
else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;")) {
state = AU_STATE_HOST_UP;
}
else {
state = AU_STATE_NO_DATA;
state_type = AU_STATETYPE_NO_DATA;
}
if(au_add_alert_or_state_log(log, timestamp, log_type, AU_OBJTYPE_HOST,
(void *)temp_host, state_type, state, plugin_output) == 0) {
return 0;
}
break;
case AU_OBJTYPE_SERVICE:
if(strstr(input, ";CRITICAL;")) {
state = AU_STATE_SERVICE_CRITICAL;
}
else if(strstr(input, ";WARNING;")) {
state = AU_STATE_SERVICE_WARNING;
}
else if(strstr(input, ";UNKNOWN;")) {
state = AU_STATE_SERVICE_UNKNOWN;
}
else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;")) {
state = AU_STATE_SERVICE_OK;
}
else {
state = AU_STATE_NO_DATA;
state_type = AU_STATETYPE_NO_DATA;
}
if(au_add_alert_or_state_log(log, timestamp, log_type,
AU_OBJTYPE_SERVICE, (void *)temp_service, state_type, state,
plugin_output) == 0) {
return 0;
}
break;
}
return 1;
}
int au_add_alert_or_state_log(au_log *log, time_t timestamp, int log_type,
int obj_type, void *object, int state_type, int state,
char *plugin_output) {
au_log_alert *alert_log;
au_log_entry *new_log_entry;
/* Create the au_log_alert */
if((alert_log = au_create_alert_or_state_log(obj_type, object, state_type,
state, plugin_output)) == NULL) {
return 0;
}
/* Create the log entry */
if((new_log_entry = au_add_log_entry(log, timestamp, log_type,
(void *)alert_log)) == NULL) {
au_free_alert_log(alert_log);
return 0;
}
/* Add the log entry to the logs for the object supplied */
switch(obj_type) {
case AU_OBJTYPE_HOST:
if(au_list_add_node(((au_host *)object)->log_entries,
new_log_entry, au_cmp_log_entries) == 0) {
return 0;
}
break;
case AU_OBJTYPE_SERVICE:
if(au_list_add_node(((au_service *)object)->log_entries,
new_log_entry, au_cmp_log_entries) == 0) {
return 0;
}
break;
}
return 1;
}
au_log_alert *au_create_alert_or_state_log(int obj_type, void *object,
int state_type, int state, char *plugin_output) {
au_log_alert *alert_log;
/* Create the au_log_alert */
if((alert_log = calloc(1, sizeof(au_log_alert))) == NULL) {
return NULL;
}
alert_log->obj_type = obj_type;
alert_log->object = object;
alert_log->state_type = state_type;
alert_log->state = state;
alert_log->plugin_output = NULL;
if(plugin_output != NULL) {
if((alert_log->plugin_output = strdup(plugin_output)) == NULL) {
au_free_alert_log(alert_log);
return NULL;
}
}
return alert_log;
}
void au_free_alert_log(au_log_alert *alert_log) {
if(NULL == alert_log) return;
if(NULL != alert_log->plugin_output) free(alert_log->plugin_output);
free(alert_log);
}
/* parse archive log downtime notifications */
int parse_downtime_alerts(char *input, time_t timestamp, unsigned obj_type,
au_log *log) {
char *temp_buffer = NULL;
char entry_host_name[MAX_INPUT_BUFFER];
char entry_svc_description[MAX_INPUT_BUFFER];
au_host *temp_host_subject;
au_host *temp_host = NULL;
au_service *temp_service_subject;
au_service *temp_service = NULL;
/* get host name */
temp_buffer = my_strtok(NULL, ":");
temp_buffer = my_strtok(NULL, ";");
strncpy(entry_host_name, (temp_buffer == NULL) ? "" :
temp_buffer + 1, sizeof(entry_host_name));
entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
switch(obj_type) {
case AU_OBJTYPE_HOST:
if(log->host_subjects->count > 0) {
/* see if there is a corresponding subject for this host */
temp_host_subject = au_find_host(log->host_subjects,
entry_host_name);
if(temp_host_subject == NULL) return 1;
}
/* Find the au_host object associated with the host name */
temp_host = au_find_host(log->hosts, entry_host_name);
if(NULL == temp_host) {
temp_host = au_add_host_and_sort(log->hosts, entry_host_name);
if(NULL == temp_host) { /* Could not allocate memory */
return 0;
}
}
break;
case AU_OBJTYPE_SERVICE:
/* get service description */
temp_buffer = my_strtok(NULL, ";");
strncpy(entry_svc_description, (temp_buffer == NULL) ? "" :
temp_buffer, sizeof(entry_svc_description));
entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0';
if(log->service_subjects->count > 0) {
/* see if there is a corresponding subject for this service */
temp_service_subject = au_find_service(log->service_subjects,
entry_host_name, entry_svc_description);
if(temp_service_subject == NULL) return 1;
}
/* Find the au_service object associated with the service */
temp_service = au_find_service(log->services, entry_host_name,
entry_svc_description);
if(NULL == temp_service) {
temp_service = au_add_service_and_sort(log->services,
entry_host_name, entry_svc_description);
if(NULL == temp_service) { /* Could not allocate memory */
return 0;
}
}
break;
}
switch(obj_type) {
case AU_OBJTYPE_HOST:
if(strstr(input, ";STARTED;")) {
if(au_add_downtime_log(log, timestamp, AU_OBJTYPE_HOST,
(void *)temp_host, AU_STATE_DOWNTIME_START) == 0) {
return 0;
}
}
else {
if(au_add_downtime_log(log, timestamp, AU_OBJTYPE_HOST,
(void *)temp_host, AU_STATE_DOWNTIME_END) == 0) {
return 0;
}
}
break;
case AU_OBJTYPE_SERVICE:
if(strstr(input, ";STARTED;")) {
if(au_add_downtime_log(log, timestamp, AU_OBJTYPE_SERVICE,
(void *)temp_service, AU_STATE_DOWNTIME_START) == 0) {
return 0;
}
}
else {
if(au_add_downtime_log(log, timestamp, AU_OBJTYPE_SERVICE,
(void *)temp_service, AU_STATE_DOWNTIME_END) == 0) {
return 0;
}
}
break;
}
return 1;
}
int au_add_downtime_log(au_log *log, time_t timestamp, int obj_type,
void *object, int downtime_type) {
au_log_downtime *downtime_log;
au_log_entry *new_log_entry;
/* Create the au_log_downtime */
if((downtime_log = calloc(1, sizeof(au_log_downtime))) == NULL) {
return 0;
}
downtime_log->obj_type = obj_type;
downtime_log->object = object;
downtime_log->downtime_type = downtime_type;
/* Create the log entry */
if((new_log_entry = au_add_log_entry(log, timestamp, AU_LOGTYPE_DOWNTIME,
(void *)downtime_log)) == NULL) {
au_free_downtime_log(downtime_log);
return 0;
}
/* Add the log entry to the logs for the object supplied */
switch(obj_type) {
case AU_OBJTYPE_HOST:
if(au_list_add_node(((au_host *)object)->log_entries,
new_log_entry, au_cmp_log_entries) == 0) {
return 0;
}
break;
case AU_OBJTYPE_SERVICE:
if(au_list_add_node(((au_service *)object)->log_entries,
new_log_entry, au_cmp_log_entries) == 0) {
return 0;
}
break;
}
return 1;
}
void au_free_downtime_log(au_log_downtime *downtime_log) {
if(NULL == downtime_log) return;
free(downtime_log);
}
int parse_notification_log(char *input, time_t timestamp, int obj_type,
au_log *log) {
char entry_contact_name[MAX_INPUT_BUFFER];
char entry_host_name[MAX_INPUT_BUFFER];
char entry_svc_description[MAX_INPUT_BUFFER];
char alert_level[MAX_INPUT_BUFFER];
char method_name[MAX_INPUT_BUFFER];
int notification_detail_type = AU_NOTIFICATION_NO_DATA;
char *temp_buffer = NULL;
au_host *temp_host_subject;
au_service *temp_service_subject;
au_contact *temp_contact;
au_host *temp_host = NULL;
au_service *temp_service = NULL;
/* get the contact name */
temp_buffer = my_strtok(NULL, ":");
temp_buffer = my_strtok(NULL, ";");
strncpy(entry_contact_name, (temp_buffer == NULL) ? "" :
temp_buffer + 1, sizeof(entry_contact_name));
entry_contact_name[sizeof(entry_contact_name) - 1] = '\x0';
/* Find the au_contact object associated with the contact name */
temp_contact = au_find_contact(log->contacts, entry_contact_name);
if(NULL == temp_contact) {
temp_contact = au_add_contact_and_sort(log->contacts,
entry_contact_name);
if(NULL == temp_contact) { /* Could not allocate memory */
return 0;
}
}
/* get the host name */
temp_buffer = (char *)my_strtok(NULL, ";");
snprintf(entry_host_name, sizeof(entry_host_name), "%s",
(temp_buffer == NULL) ? "" : temp_buffer);
entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
switch(obj_type) {
case AU_OBJTYPE_HOST:
if(log->host_subjects->count > 0) {
/* see if there is a corresponding subject for this host */
temp_host_subject = au_find_host(log->host_subjects,
entry_host_name);
if(temp_host_subject == NULL) return 1;
}
/* Find the au_host object associated with the host name */
temp_host = au_find_host(log->hosts, entry_host_name);
if(NULL == temp_host) {
temp_host = au_add_host_and_sort(log->hosts, entry_host_name);
if(NULL == temp_host) { /* Could not allocate memory */
return 0;
}
}
break;
case AU_OBJTYPE_SERVICE:
/* get service description */
temp_buffer = my_strtok(NULL, ";");
strncpy(entry_svc_description, (temp_buffer == NULL) ? "" :
temp_buffer, sizeof(entry_svc_description));
entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0';
if(log->service_subjects->count > 0) {
/* see if there is a corresponding subject for this service */
temp_service_subject = au_find_service(log->service_subjects,
entry_host_name, entry_svc_description);
if(temp_service_subject == NULL) return 1;
}
/* Find the au_service object associated with the service */
temp_service = au_find_service(log->services, entry_host_name,
entry_svc_description);
if(NULL == temp_service) {
temp_service = au_add_service_and_sort(log->services,
entry_host_name, entry_svc_description);
if(NULL == temp_service) { /* Could not allocate memory */
return 0;
}
}
break;
}
/* get the alert level */
temp_buffer = (char *)my_strtok(NULL, ";");
snprintf(alert_level, sizeof(alert_level), "%s",
(temp_buffer == NULL) ? "" : temp_buffer);
alert_level[sizeof(alert_level) - 1] = '\x0';
switch(obj_type) {
case AU_OBJTYPE_HOST:
if(!strcmp(alert_level, "DOWN")) {
notification_detail_type = AU_NOTIFICATION_HOST_DOWN;
}
else if(!strcmp(alert_level, "UNREACHABLE")) {
notification_detail_type = AU_NOTIFICATION_HOST_UNREACHABLE;
}
else if(!strcmp(alert_level, "RECOVERY") ||
!strcmp(alert_level, "UP")) {
notification_detail_type = AU_NOTIFICATION_HOST_RECOVERY;
}
else if(strstr(alert_level, "CUSTOM (")) {
notification_detail_type = AU_NOTIFICATION_HOST_CUSTOM;
}
else if(strstr(alert_level, "ACKNOWLEDGEMENT (")) {
notification_detail_type = AU_NOTIFICATION_HOST_ACK;
}
else if(strstr(alert_level, "FLAPPINGSTART (")) {
notification_detail_type = AU_NOTIFICATION_HOST_FLAPPING_START;
}
else if(strstr(alert_level, "FLAPPINGSTOP (")) {
notification_detail_type = AU_NOTIFICATION_HOST_FLAPPING_STOP;
}
break;
case AU_OBJTYPE_SERVICE:
if(!strcmp(alert_level, "CRITICAL")) {
notification_detail_type = AU_NOTIFICATION_SERVICE_CRITICAL;
}
else if(!strcmp(alert_level, "WARNING")) {
notification_detail_type = AU_NOTIFICATION_SERVICE_WARNING;
}
else if(!strcmp(alert_level, "RECOVERY") ||
!strcmp(alert_level, "OK")) {
notification_detail_type = AU_NOTIFICATION_SERVICE_RECOVERY;
}
else if(strstr(alert_level, "CUSTOM (")) {
notification_detail_type = AU_NOTIFICATION_SERVICE_CUSTOM;
}
else if(strstr(alert_level, "ACKNOWLEDGEMENT (")) {
notification_detail_type = AU_NOTIFICATION_SERVICE_ACK;
}
else if(strstr(alert_level, "FLAPPINGSTART (")) {
notification_detail_type = AU_NOTIFICATION_SERVICE_FLAPPING_START;
}
else if(strstr(alert_level, "FLAPPINGSTOP (")) {
notification_detail_type = AU_NOTIFICATION_SERVICE_FLAPPING_STOP;
}
else {
notification_detail_type = AU_NOTIFICATION_SERVICE_UNKNOWN;
}
break;
}
/* get the method name */
temp_buffer = (char *)my_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 = my_strtok(NULL, ";");
/* Create the log entry */
switch(obj_type) {
case AU_OBJTYPE_HOST:
if(au_add_notification_log(log, timestamp, AU_OBJTYPE_HOST,
(void *)temp_host, temp_contact, notification_detail_type,
method_name, temp_buffer) == 0) {
return 0;
}
break;
case AU_OBJTYPE_SERVICE:
if(au_add_notification_log(log, timestamp, AU_OBJTYPE_SERVICE,
(void *)temp_service, temp_contact, notification_detail_type,
method_name, temp_buffer) == 0) {
return 0;
}
break;
}
return 1;
}
int au_add_notification_log(au_log *log, time_t timestamp, int obj_type,
void *object, au_contact *contact, int notification_type,
char *method, char *message) {
au_log_notification *notification_log;
au_log_entry *new_log_entry;
/* Create the au_log_downtime */
if((notification_log = calloc(1, sizeof(au_log_notification))) == NULL) {
return 0;
}
notification_log->obj_type = obj_type;
notification_log->object = object;
notification_log->contact = contact;
notification_log->notification_type = notification_type;
if((notification_log->method = strdup(method))
== NULL) {
au_free_notification_log(notification_log);
return 0;
}
if((notification_log->message = strdup(message)) == NULL) {
au_free_notification_log(notification_log);
return 0;
}
/* Create the log entry */
if((new_log_entry = au_add_log_entry(log, timestamp,
AU_LOGTYPE_NOTIFICATION, (void *)notification_log)) == NULL) {
au_free_notification_log(notification_log);
return 0;
}
/* Add the log entry to the logs for the object supplied */
switch(obj_type) {
case AU_OBJTYPE_HOST:
if(au_list_add_node((void *)((au_host *)object)->log_entries,
new_log_entry, au_cmp_log_entries) == 0) {
return 0;
}
break;
case AU_OBJTYPE_SERVICE:
if(au_list_add_node((void *)((au_service *)object)->log_entries,
new_log_entry, au_cmp_log_entries) == 0) {
return 0;
}
break;
}
return 1;
}
void au_free_notification_log(au_log_notification *notification_log) {
if(NULL == notification_log) return;
if(NULL != notification_log->method) free(notification_log->method);
if(NULL != notification_log->message) free(notification_log->message);
free(notification_log);
}
au_log_entry *au_add_log_entry(au_log *log, time_t timestamp, int entry_type,
void *entry) {
au_log_entry *new_log_entry;
/* Create the au_log_entry */
if((new_log_entry = calloc(1, sizeof(au_log_entry))) == NULL) {
return NULL;
}
new_log_entry->timestamp = timestamp;
new_log_entry->entry_type = entry_type;
new_log_entry->entry = entry;
if(au_list_add_node(log->entry_list, (void *)new_log_entry,
au_cmp_log_entries) == NULL) {
au_free_log_entry(new_log_entry);
return NULL;
}
return new_log_entry;
}
void au_free_log_entry_void(void *log_entry) {
au_free_log_entry((au_log_entry *)log_entry);
}
void au_free_log_entry(au_log_entry *log_entry) {
if(NULL == log_entry) return;
switch(log_entry->entry_type) {
case AU_LOGTYPE_ALERT:
case AU_LOGTYPE_STATE:
au_free_alert_log((au_log_alert *)log_entry->entry);
break;
case AU_LOGTYPE_NOTIFICATION:
au_free_notification_log((au_log_notification *)log_entry->entry);
break;
case AU_LOGTYPE_DOWNTIME:
au_free_downtime_log((au_log_downtime *)log_entry->entry);
break;
case AU_LOGTYPE_NAGIOS:
au_free_nagios_log((au_log_nagios *)log_entry->entry);
break;
}
free(log_entry);
}
/* Add a host to a host list and sort the list */
au_host *au_add_host_and_sort(au_array *host_list, char *name) {
au_host *temp_host;
temp_host = au_add_host(host_list, name);
if(NULL != temp_host) {
au_sort_array(host_list, au_cmp_hosts);
}
return temp_host;
}
/* Add a host to a host list */
au_host *au_add_host(au_array *host_list, char *name) {
au_host *new_host;
char buf[8192];
/* Should have been allocated during au_log_init() */
if(NULL == host_list) {
return NULL;
}
/* Create the host */
if((new_host = calloc(1, sizeof(au_host))) == NULL) {
return NULL;
}
if((new_host->name = strdup(name)) == NULL) {
au_free_host(new_host);
return NULL;
}
new_host->hostp = find_host(name);
new_host->availability = NULL;
snprintf(buf, sizeof(buf) - 1, "Host %s log entries", name);
if((new_host->log_entries = au_init_list(buf)) == NULL) {
au_free_host(new_host);
return NULL;
}
/* Add it to the list of hosts */
if(0 == au_array_append_member(host_list, (void *)new_host)) {
au_free_host(new_host);
return NULL;
}
return new_host;
}
void au_free_host_void(void *host) {
au_free_host((au_host *)host);
}
void au_free_host(au_host *host) {
if(NULL == host) return;
if(NULL != host->name) free(host->name);
/* Do not free the log entry data here because they are freed when the
master list's log entries are freed */
if(NULL != host->log_entries) au_free_list(host->log_entries, NULL);
if(NULL != host->availability) free(host->availability);
free(host);
return;
}
int au_cmp_hosts(const void *a, const void *b) {
au_host *hosta = *(au_host **)a;
au_host *hostb = *(au_host **)b;
return strcmp(hosta->name, hostb->name);
}
au_host *au_find_host(au_array *host_list, char *name) {
au_host key;
void *found;
if(NULL == host_list) return NULL;
key.name = name;
found = au_find_in_array(host_list, (void *)&key, au_cmp_hosts);
if(NULL == found) return NULL;
return *(au_host **)found;
}
au_service *au_add_service_and_sort(au_array *service_list, char *host_name,
char *description) {
au_service *temp_service;
temp_service = au_add_service(service_list, host_name, description);
if(NULL != temp_service) {
au_sort_array(service_list, au_cmp_services);
}
return temp_service;
}
au_service *au_add_service(au_array *service_list, char *host_name,
char *description) {
au_service *new_service;
char buf[8192];
/* Should have been allocated during au_log_init() */
if(NULL == service_list) {
return NULL;
}
/* Create the service */
if((new_service = calloc(1, sizeof(au_service))) == NULL) {
return NULL;
}
if((new_service->host_name = strdup(host_name)) == NULL) {
au_free_service(new_service);
return NULL;
}
if((new_service->description = strdup(description)) == NULL) {
au_free_service(new_service);
return NULL;
}
new_service->servicep = find_service(host_name, description);
new_service->availability = NULL;
snprintf(buf, sizeof(buf) - 1, "Service %s:%s log entries", host_name,
description);
if((new_service->log_entries = au_init_list(buf)) == NULL) {
au_free_service(new_service);
return NULL;
}
/* Add it to the list of services */
if(0 == au_array_append_member(service_list, (void *)new_service)) {
au_free_service(new_service);
return NULL;
}
return new_service;
}
void au_free_service_void(void *service) {
au_free_service((au_service *)service);
}
void au_free_service(au_service *service) {
if(NULL == service) return;
if(NULL != service->host_name) free(service->host_name);
if(NULL != service->description) free(service->description);
/* Do not free the log entry data here because they are freed when the
master list's log entries are freed */
if(NULL != service->log_entries) au_free_list(service->log_entries, NULL);
if(NULL != service->availability) free(service->availability);
free(service);
return;
}
au_service *au_find_service(au_array *service_list, char *host_name,
char *description) {
au_service key;
void *found;
if(NULL == service_list) return NULL;
key.host_name = host_name;
key.description = description;
found = (au_service *)au_find_in_array(service_list, (void *)&key,
au_cmp_services);
if(NULL == found) return NULL;
return *(au_service **)found;
}
int au_cmp_services(const void *a, const void *b) {
au_service *servicea = *(au_service **)a;
au_service *serviceb = *(au_service **)b;
int host_result;
host_result = strcmp(servicea->host_name, serviceb->host_name);
if(0 == host_result) {
return strcmp(servicea->description, serviceb->description);
}
else {
return host_result;
}
}
/* Add a contact to a contact list and sort the list */
au_contact *au_add_contact_and_sort(au_array *contact_list, char *name) {
au_contact *temp_contact;
temp_contact = au_add_contact(contact_list, name);
if(NULL != temp_contact) {
au_sort_array(contact_list, au_cmp_contacts);
}
return temp_contact;
}
/* Add a contact to a contact list */
au_contact *au_add_contact(au_array *contact_list, char *name) {
au_contact *new_contact;
/* Should have been allocated during au_log_init() */
if(NULL == contact_list) {
return NULL;
}
/* Create the contact */
if((new_contact = calloc(1, sizeof(au_contact))) == NULL) {
return NULL;
}
if((new_contact->name = strdup(name)) == NULL) {
au_free_contact(new_contact);
return NULL;
}
/* Add it to the list of contacts */
if(0 == au_array_append_member(contact_list, (void *)new_contact)) {
au_free_contact(new_contact);
return NULL;
}
return new_contact;
}
void au_free_contact_void(void *contact) {
au_free_contact((au_contact *)contact);
}
void au_free_contact(au_contact *contact) {
if(NULL == contact) return;
if(NULL != contact->name) free(contact->name);
free(contact);
return;
}
int au_cmp_contacts(const void *a, const void *b) {
au_contact *contacta = (au_contact *)a;
au_contact *contactb = (au_contact *)b;
return strcmp(contacta->name, contactb->name);
}
au_contact *au_find_contact(au_array *contact_list, char *name) {
au_contact key;
void *found;
if(NULL == contact_list) return NULL;
key.name = name;
found = (au_contact *)au_find_in_array(contact_list, (void *)&key,
au_cmp_contacts);
if(NULL == found) return NULL;
return *(au_contact **)found;
}
au_array *au_init_array(char *label) {
au_array *array;
if((array = calloc(1, sizeof(au_array))) == NULL) {
return NULL;
}
array->label = NULL;
if(NULL != label) {
if((array->label = strdup(label)) == NULL) {
free(array);
return NULL;
}
}
array->size = 0;
array->count = 0;
array->members = (void **)NULL;
array->new = 0;
return array;
}
void au_free_array(au_array *array, void(*datafree)(void *)) {
int x;
if(NULL == array) return;
if(NULL != array->label) free(array->label);
for(x = 0; x < array->count; x++) {
if((NULL != datafree) && (NULL != array->members[x])) {
datafree(array->members[x]);
}
}
if(NULL != array->members) free(array->members);
free(array);
return;
}
int au_array_append_member(au_array *array, void *member) {
/* Check whether the list needs to be grown before adding the member */
if(array->count == array->size) {
/* Need to grow the list */
if(0 == array->count) {
/* Never had any members */
if((array->members = (void **)calloc(AU_INITIAL_LIST_SIZE,
sizeof(void *))) == NULL) {
return 0;
}
array->size = AU_INITIAL_LIST_SIZE;
}
else {
/* Double the size of the list */
if((array->members = (void **)realloc(array->members,
sizeof(void *) * array->size * 2)) == NULL) {
return 0;
}
array->size *= 2;
}
}
array->members[array->count] = member;
array->new++; /* Number of appends since last sort */
array->count++;
return 1;
}
void au_sort_array(au_array *array, int(*cmp)(const void *, const void *)) {
/* TODO: Use array->new to determine whether to do a quick sort or a
bubble sort */
qsort(array->members, array->count, sizeof(void *), cmp);
array->new = 0;
}
void *au_find_in_array(au_array *array, void *key,
int(*cmp)(const void *, const void *)) {
return bsearch(&key, array->members, array->count, sizeof(void *), cmp);
}
au_linked_list *au_init_list(char *label) {
au_linked_list *list;
if((list = calloc(1, sizeof(au_linked_list))) == NULL) {
return NULL;
}
list->label = NULL;
if(NULL != label) {
if((list->label = strdup(label)) == NULL) {
free(list);
return NULL;
}
}
list->head = (au_node *)0;
list->last_new = (au_node *)0;
return list;
}
au_node *au_list_add_node(au_linked_list *list, void *data,
int(*cmp)(const void *, const void *)) {
au_node *new_node;
au_node *temp_node;
/* Create the new node */
if((new_node = calloc(1, sizeof(au_node))) == NULL) {
return NULL;
}
new_node->data = data;
new_node->next = NULL;
/* Add it to the list */
if(NULL == list->head) {
/* If the list is empty, add this node as the only item in the list */
list->head = new_node;
}
else if(cmp(&(list->last_new->data), &(new_node->data)) <= 0) {
/* The new node goes somewhere on the list downstream of the most
recently added node */
if(NULL == list->last_new->next) {
/* If the most recently added node is the last one on the list,
append the list with this node */
list->last_new->next = new_node;
}
else if(cmp(&(list->last_new->next->data), &(new_node->data)) > 0) {
/* If the next node is "greater than" the new node, the new
node goes here */
new_node->next = list->last_new->next;
list->last_new->next = new_node;
}
else {
/* Visit each node downstream in the list until we reach the
end of the list or until we find a node whose next
node is "greater than" the new node */
temp_node = list->last_new;
while((NULL != temp_node->next) && (cmp(&(temp_node->next->data),
&(new_node->data)) <= 0)) {
temp_node = temp_node->next;
}
if(NULL == temp_node->next) {
/* If we reach the end of the list, the new node gets
appended */
temp_node->next = new_node;
}
else {
/* Otherwise, the new node gets inserted here */
new_node->next = temp_node->next;
temp_node->next = new_node;
}
}
}
else {
/* The new node is "less than" the last new node. Visit each node
starting at the beginning of the list until we reach the end of
the list (which shouldn't happen because that case was covered
earlier) or we find a node whose next node is is "greater than"
the new node. */
temp_node = list->head;
while((NULL != temp_node->next) && (cmp(&(temp_node->next->data),
&(new_node->data)) <= 0)) {
temp_node = temp_node->next;
}
if(temp_node == list->head) {
/* We insert at the beginning of the list */
new_node->next = list->head;
list->head = new_node;
}
else if(NULL == temp_node->next) {
/* If we reach the end of the list, the new node gets appended */
temp_node->next = new_node;
}
else {
/* Otherwise, the new node gets inserted here */
new_node->next = temp_node->next;
temp_node->next = new_node;
}
}
list->last_new = new_node;
return new_node;
}
void au_empty_list(au_linked_list *list, void(*datafree)(void *)) {
au_node *temp_node1;
au_node *temp_node2;
temp_node1 = list->head;
while(NULL != temp_node1) {
temp_node2 = temp_node1->next;
if((NULL != datafree) && (NULL != temp_node1->data)) {
datafree(temp_node1->data);
}
free(temp_node1);
temp_node1 = temp_node2;
}
list->head = NULL;
list->last_new = NULL;
}
void au_free_list(au_linked_list *list, void(*datafree)(void *)) {
if(NULL == list) return;
if(NULL != list->label) free(list->label);
au_empty_list(list, datafree);
free(list);
}
nagios-4.4.6/cgi/avail.c 0000664 0000000 0000000 00000625306 13652113235 0015024 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* AVAIL.C - Nagios Availability CGI
*
*
* 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/cgiauth.h"
#include "../include/getcgi.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];
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
/* output types */
#define HTML_OUTPUT 0
#define CSV_OUTPUT 1
/* archived state types */
#define AS_CURRENT_STATE -1 /* special case for initial assumed state */
#define AS_NO_DATA 0
#define AS_PROGRAM_END 1
#define AS_PROGRAM_START 2
#define AS_HOST_UP 3
#define AS_HOST_DOWN 4
#define AS_HOST_UNREACHABLE 5
#define AS_SVC_OK 6
#define AS_SVC_UNKNOWN 7
#define AS_SVC_WARNING 8
#define AS_SVC_CRITICAL 9
#define AS_SVC_DOWNTIME_START 10
#define AS_SVC_DOWNTIME_END 11
#define AS_HOST_DOWNTIME_START 12
#define AS_HOST_DOWNTIME_END 13
#define AS_SOFT_STATE 1
#define AS_HARD_STATE 2
/* display types */
#define DISPLAY_NO_AVAIL 0
#define DISPLAY_HOSTGROUP_AVAIL 1
#define DISPLAY_HOST_AVAIL 2
#define DISPLAY_SERVICE_AVAIL 3
#define DISPLAY_SERVICEGROUP_AVAIL 4
/* subject types */
#define HOST_SUBJECT 0
#define SERVICE_SUBJECT 1
/* standard report times */
#define TIMEPERIOD_CUSTOM 0
#define TIMEPERIOD_TODAY 1
#define TIMEPERIOD_YESTERDAY 2
#define TIMEPERIOD_THISWEEK 3
#define TIMEPERIOD_LASTWEEK 4
#define TIMEPERIOD_THISMONTH 5
#define TIMEPERIOD_LASTMONTH 6
#define TIMEPERIOD_THISQUARTER 7
#define TIMEPERIOD_LASTQUARTER 8
#define TIMEPERIOD_THISYEAR 9
#define TIMEPERIOD_LASTYEAR 10
#define TIMEPERIOD_LAST24HOURS 11
#define TIMEPERIOD_LAST7DAYS 12
#define TIMEPERIOD_LAST31DAYS 13
#define MIN_TIMESTAMP_SPACING 10
#define MAX_ARCHIVE_SPREAD 65
#define MAX_ARCHIVE 65
#define MAX_ARCHIVE_BACKTRACKS 60
authdata current_authdata;
typedef struct archived_state_struct {
time_t time_stamp;
int entry_type;
int state_type;
char *state_info;
int processed_state;
struct archived_state_struct *misc_ptr;
struct archived_state_struct *next;
} archived_state;
typedef struct avail_subject_struct {
int type;
char *host_name;
char *service_description;
archived_state *as_list; /* archived state list */
archived_state *as_list_tail;
archived_state *sd_list; /* scheduled downtime list */
int last_known_state;
time_t earliest_time;
time_t latest_time;
int earliest_state;
int latest_state;
unsigned long time_up;
unsigned long time_down;
unsigned long time_unreachable;
unsigned long time_ok;
unsigned long time_warning;
unsigned long time_unknown;
unsigned long time_critical;
unsigned long scheduled_time_up;
unsigned long scheduled_time_down;
unsigned long scheduled_time_unreachable;
unsigned long scheduled_time_ok;
unsigned long scheduled_time_warning;
unsigned long scheduled_time_unknown;
unsigned long scheduled_time_critical;
unsigned long scheduled_time_indeterminate;
unsigned long time_indeterminate_nodata;
unsigned long time_indeterminate_notrunning;
struct avail_subject_struct *next;
} avail_subject;
avail_subject *subject_list = NULL;
time_t t1;
time_t t2;
int display_type = DISPLAY_NO_AVAIL;
int timeperiod_type = TIMEPERIOD_LAST24HOURS;
int show_log_entries = FALSE;
int full_log_entries = FALSE;
int show_scheduled_downtime = TRUE;
int start_second = 0;
int start_minute = 0;
int start_hour = 0;
int start_day = 1;
int start_month = 1;
int start_year = 2000;
int end_second = 0;
int end_minute = 0;
int end_hour = 24;
int end_day = 1;
int end_month = 1;
int end_year = 2000;
int get_date_parts = FALSE;
int select_hostgroups = FALSE;
int select_hosts = FALSE;
int select_servicegroups = FALSE;
int select_services = FALSE;
int select_output_format = FALSE;
int compute_time_from_parts = FALSE;
int show_all_hostgroups = FALSE;
int show_all_hosts = FALSE;
int show_all_servicegroups = FALSE;
int show_all_services = FALSE;
int assume_initial_states = TRUE;
int assume_state_retention = TRUE;
int assume_states_during_notrunning = TRUE;
int initial_assumed_host_state = AS_NO_DATA;
int initial_assumed_service_state = AS_NO_DATA;
int include_soft_states = FALSE;
char *hostgroup_name = "";
char *host_name = "";
char *servicegroup_name = "";
char *svc_description = "";
void create_subject_list(void);
void add_subject(int, char *, char *);
avail_subject *find_subject(int, char *, char *);
void compute_availability(void);
void compute_subject_availability(avail_subject *, time_t);
void compute_subject_availability_times(int, int, time_t, time_t, time_t, avail_subject *, archived_state *);
void compute_subject_downtime(avail_subject *, time_t);
void compute_subject_downtime_times(time_t, time_t, avail_subject *, archived_state *);
void compute_subject_downtime_part_times(time_t, time_t, int, avail_subject *);
void display_hostgroup_availability(void);
void display_specific_hostgroup_availability(hostgroup *);
void display_servicegroup_availability(void);
void display_specific_servicegroup_availability(servicegroup *);
void display_host_availability(void);
void display_service_availability(void);
void write_log_entries(avail_subject *);
void get_running_average(double *, double, int);
void host_report_url(const char *, const char *);
void service_report_url(const char *, const char *, const char *);
void compute_report_times(void);
int convert_host_state_to_archived_state(int);
int convert_service_state_to_archived_state(int);
void add_global_archived_state(int, int, time_t, const char *);
void add_archived_state(int, int, time_t, const char *, avail_subject *);
void add_scheduled_downtime(int, time_t, avail_subject *);
void free_availability_data(void);
void free_archived_state_list(archived_state *);
void read_archived_state_data(void);
void scan_log_file_for_archived_state_data(char *);
void convert_timeperiod_to_times(int);
unsigned long calculate_total_time(time_t, time_t);
void document_header(int);
void document_footer(void);
int process_cgivars(void);
int backtrack_archives = 2;
int earliest_archive = 0;
int embedded = FALSE;
int display_header = TRUE;
timeperiod *current_timeperiod = NULL;
int output_format = HTML_OUTPUT;
int main(int argc, char **argv) {
char temp_buffer[MAX_INPUT_BUFFER];
char start_timestring[MAX_DATETIME_LENGTH];
char end_timestring[MAX_DATETIME_LENGTH];
host *temp_host;
service *temp_service;
int is_authorized = TRUE;
time_t report_start_time;
time_t report_end_time;
int days, hours, minutes, seconds;
hostgroup *temp_hostgroup;
servicegroup *temp_servicegroup;
timeperiod *temp_timeperiod;
time_t t3;
time_t current_time;
struct tm *t;
char *firsthostpointer;
/* reset internal CGI variables */
reset_cgi_vars();
cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, READ_ALL_STATUS_DATA);
/* initialize time period to last 24 hours */
time(¤t_time);
t2 = current_time;
t1 = (time_t)(current_time - (60 * 60 * 24));
/* default number of backtracked archives */
switch (log_rotation_method) {
case LOG_ROTATION_MONTHLY:
backtrack_archives = 1;
break;
case LOG_ROTATION_WEEKLY:
backtrack_archives = 2;
break;
case LOG_ROTATION_DAILY:
backtrack_archives = 4;
break;
case LOG_ROTATION_HOURLY:
backtrack_archives = 8;
break;
default:
backtrack_archives = 2;
break;
}
/* get the arguments passed in the URL */
process_cgivars();
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_authdata);
if (compute_time_from_parts == TRUE)
compute_report_times();
/* make sure times are sane, otherwise swap them */
if (t2 < t1) {
t3 = t2;
t2 = t1;
t1 = t3;
}
/* don't let user create reports in the future */
if (t2 > current_time) {
t2 = current_time;
if (t1 > t2)
t1 = t2 - (60 * 60 * 24);
}
if (display_header == TRUE) {
/* begin top table */
printf("
\n");
}
/* step 3 - ask user for report date range */
if (get_date_parts == TRUE) {
time(¤t_time);
t = localtime(¤t_time);
start_day = 1;
start_year = t->tm_year + 1900;
end_day = t->tm_mday;
end_year = t->tm_year + 1900;
printf("
Step 3: Select Report Options
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
/* step 2 - the user wants to select a hostgroup */
else if (select_hostgroups == TRUE) {
printf("
Step 2: Select Hostgroup
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
/* step 2 - the user wants to select a host */
else if (select_hosts == TRUE) {
printf("
Step 2: Select Host
\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("
Tip: If you want to have the option of getting the availability data in CSV format, select '** ALL HOSTS **' from the pull-down menu.\n");
}
/* step 2 - the user wants to select a servicegroup */
else if (select_servicegroups == TRUE) {
printf("
Step 2: Select Servicegroup
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
/* step 2 - the user wants to select a service */
else if (select_services == TRUE) {
printf("\n");
printf("
Step 2: Select Service
\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("
Tip: If you want to have the option of getting the availability data in CSV format, select '** ALL SERVICES **' from the pull-down menu.\n");
}
/* generate availability report */
else if (display_type != DISPLAY_NO_AVAIL) {
/* check authorization */
is_authorized = TRUE;
if ((display_type == DISPLAY_HOST_AVAIL && show_all_hosts == FALSE) || (display_type == DISPLAY_SERVICE_AVAIL && show_all_services == FALSE)) {
if (display_type == DISPLAY_HOST_AVAIL && show_all_hosts == FALSE)
is_authorized = is_authorized_for_host(find_host(host_name), ¤t_authdata);
else
is_authorized = is_authorized_for_service(find_service(host_name, svc_description), ¤t_authdata);
}
if (is_authorized == FALSE)
printf("
It appears as though you are not authorized to view information for the specified %s...
\n", (display_type == DISPLAY_HOST_AVAIL) ? "host" : "service");
else {
time(&report_start_time);
/* create list of subjects to collect availability data for */
create_subject_list();
/* read in all necessary archived state data */
read_archived_state_data();
/* compute availability data */
compute_availability();
time(&report_end_time);
if (output_format == HTML_OUTPUT) {
get_time_breakdown((time_t)(report_end_time - report_start_time), &days, &hours, &minutes, &seconds);
printf("
[ Availability report completed in %d min %d sec ]
\n", minutes, seconds);
printf("
\n");
}
/* display availability data */
if (display_type == DISPLAY_HOST_AVAIL)
display_host_availability();
else if (display_type == DISPLAY_SERVICE_AVAIL)
display_service_availability();
else if (display_type == DISPLAY_HOSTGROUP_AVAIL)
display_hostgroup_availability();
else if (display_type == DISPLAY_SERVICEGROUP_AVAIL)
display_servicegroup_availability();
/* free memory allocated to availability data */
free_availability_data();
}
}
/* step 1 - ask the user what kind of report they want */
else {
printf("
Step 1: Select Report Type
\n");
printf("
\n");
printf("\n");
printf("
\n");
}
document_footer();
/* free all other 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(¤t_time);
get_time_string(¤t_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
printf("Last-Modified: %s\r\n", date_time);
expire_time = (time_t)0;
get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
printf("Expires: %s\r\n", date_time);
if (output_format == HTML_OUTPUT)
printf("Content-type: text/html; charset=utf-8\r\n\r\n");
else {
printf("Content-type: text/csv\r\n");
printf("Content-Disposition: attachment; filename=\"avail.csv\"\r\n\r\n");
return;
}
if (embedded == TRUE || output_format == CSV_OUTPUT)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Nagios Availability\n");
printf("\n");
if (use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, AVAIL_CSS);
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(AVAIL_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if (output_format != HTML_OUTPUT)
return;
if (embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(AVAIL_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
for (x = 0; variables[x]; 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 hostgroup argument */
else if (!strcmp(variables[x], "hostgroup")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if ((hostgroup_name = (char *)strdup(variables[x])) == NULL)
hostgroup_name = "";
strip_html_brackets(hostgroup_name);
display_type = DISPLAY_HOSTGROUP_AVAIL;
show_all_hostgroups = (strcmp(hostgroup_name, "all")) ? FALSE : TRUE;
}
/* we found the servicegroup argument */
else if (!strcmp(variables[x], "servicegroup")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if ((servicegroup_name = (char *)strdup(variables[x])) == NULL)
servicegroup_name = "";
strip_html_brackets(servicegroup_name);
display_type = DISPLAY_SERVICEGROUP_AVAIL;
show_all_servicegroups = (strcmp(servicegroup_name, "all")) ? FALSE : TRUE;
}
/* 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_HOST_AVAIL;
show_all_hosts = (strcmp(host_name, "all")) ? FALSE : TRUE;
}
/* we found the service description 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_SERVICE_AVAIL;
show_all_services = (strcmp(svc_description, "all")) ? FALSE : TRUE;
}
/* we found first time argument */
else if (!strcmp(variables[x], "t1")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
t1 = (time_t)strtoul(variables[x], NULL, 10);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = FALSE;
}
/* we found first time argument */
else if (!strcmp(variables[x], "t2")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
t2 = (time_t)strtoul(variables[x], NULL, 10);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = FALSE;
}
/* we found the assume initial states option */
else if (!strcmp(variables[x], "assumeinitialstates")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (!strcmp(variables[x], "yes"))
assume_initial_states = TRUE;
else
assume_initial_states = FALSE;
}
/* we found the assume state during program not running option */
else if (!strcmp(variables[x], "assumestatesduringnotrunning")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (!strcmp(variables[x], "yes"))
assume_states_during_notrunning = TRUE;
else
assume_states_during_notrunning = FALSE;
}
/* we found the initial assumed host state option */
else if (!strcmp(variables[x], "initialassumedhoststate")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
initial_assumed_host_state = atoi(variables[x]);
}
/* we found the initial assumed service state option */
else if (!strcmp(variables[x], "initialassumedservicestate")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
initial_assumed_service_state = atoi(variables[x]);
}
/* we found the assume state retention option */
else if (!strcmp(variables[x], "assumestateretention")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (!strcmp(variables[x], "yes"))
assume_state_retention = TRUE;
else
assume_state_retention = FALSE;
}
/* we found the include soft states option */
else if (!strcmp(variables[x], "includesoftstates")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (!strcmp(variables[x], "yes"))
include_soft_states = TRUE;
else
include_soft_states = FALSE;
}
/* we found the backtrack archives argument */
else if (!strcmp(variables[x], "backtrack")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
backtrack_archives = atoi(variables[x]);
if (backtrack_archives < 0)
backtrack_archives = 0;
if (backtrack_archives > MAX_ARCHIVE_BACKTRACKS)
backtrack_archives = MAX_ARCHIVE_BACKTRACKS;
#ifdef DEBUG
printf("BACKTRACK ARCHIVES: %d\n", backtrack_archives);
#endif
}
/* we found the standard timeperiod argument */
else if (!strcmp(variables[x], "timeperiod")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (!strcmp(variables[x], "today"))
timeperiod_type = TIMEPERIOD_TODAY;
else if (!strcmp(variables[x], "yesterday"))
timeperiod_type = TIMEPERIOD_YESTERDAY;
else if (!strcmp(variables[x], "thisweek"))
timeperiod_type = TIMEPERIOD_THISWEEK;
else if (!strcmp(variables[x], "lastweek"))
timeperiod_type = TIMEPERIOD_LASTWEEK;
else if (!strcmp(variables[x], "thismonth"))
timeperiod_type = TIMEPERIOD_THISMONTH;
else if (!strcmp(variables[x], "lastmonth"))
timeperiod_type = TIMEPERIOD_LASTMONTH;
else if (!strcmp(variables[x], "thisquarter"))
timeperiod_type = TIMEPERIOD_THISQUARTER;
else if (!strcmp(variables[x], "lastquarter"))
timeperiod_type = TIMEPERIOD_LASTQUARTER;
else if (!strcmp(variables[x], "thisyear"))
timeperiod_type = TIMEPERIOD_THISYEAR;
else if (!strcmp(variables[x], "lastyear"))
timeperiod_type = TIMEPERIOD_LASTYEAR;
else if (!strcmp(variables[x], "last24hours"))
timeperiod_type = TIMEPERIOD_LAST24HOURS;
else if (!strcmp(variables[x], "last7days"))
timeperiod_type = TIMEPERIOD_LAST7DAYS;
else if (!strcmp(variables[x], "last31days"))
timeperiod_type = TIMEPERIOD_LAST31DAYS;
else if (!strcmp(variables[x], "custom"))
timeperiod_type = TIMEPERIOD_CUSTOM;
else
continue;
convert_timeperiod_to_times(timeperiod_type);
compute_time_from_parts = 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 CSV output option */
else if (!strcmp(variables[x], "csvoutput")) {
display_header = FALSE;
output_format = CSV_OUTPUT;
}
/* we found the log entries option */
else if (!strcmp(variables[x], "show_log_entries"))
show_log_entries = TRUE;
/* we found the full log entries option */
else if (!strcmp(variables[x], "full_log_entries"))
full_log_entries = TRUE;
/* we found the get date parts option */
else if (!strcmp(variables[x], "get_date_parts"))
get_date_parts = TRUE;
/* we found the report type selection option */
else if (!strcmp(variables[x], "report_type")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (!strcmp(variables[x], "hostgroups"))
select_hostgroups = TRUE;
else if (!strcmp(variables[x], "servicegroups"))
select_servicegroups = TRUE;
else if (!strcmp(variables[x], "hosts"))
select_hosts = TRUE;
else
select_services = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "smon")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_month = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "sday")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_day = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "syear")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_year = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "smin")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_minute = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "ssec")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_second = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "shour")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
start_hour = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "emon")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_month = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "eday")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_day = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "eyear")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_year = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "emin")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_minute = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "esec")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_second = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found time argument */
else if (!strcmp(variables[x], "ehour")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (timeperiod_type != TIMEPERIOD_CUSTOM)
continue;
end_hour = atoi(variables[x]);
timeperiod_type = TIMEPERIOD_CUSTOM;
compute_time_from_parts = TRUE;
}
/* we found the show scheduled downtime option */
else if (!strcmp(variables[x], "showscheduleddowntime")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
if (!strcmp(variables[x], "yes"))
show_scheduled_downtime = TRUE;
else
show_scheduled_downtime = FALSE;
}
/* we found the report timeperiod option */
else if (!strcmp(variables[x], "rpttimeperiod")) {
timeperiod *temp_timeperiod;
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
for (temp_timeperiod = timeperiod_list; temp_timeperiod != NULL; temp_timeperiod = temp_timeperiod->next) {
if (!strcmp(temp_timeperiod->name, variables[x])) {
current_timeperiod = temp_timeperiod;
break;
}
}
}
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
/* computes availability data for all subjects */
void compute_availability(void) {
avail_subject *temp_subject;
time_t current_time;
time(¤t_time);
for (temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) {
compute_subject_availability(temp_subject, current_time);
compute_subject_downtime(temp_subject, current_time);
}
return;
}
/* computes availability data for a given subject */
void compute_subject_availability(avail_subject *subject, time_t current_time) {
archived_state *temp_as;
archived_state *last_as;
time_t a;
time_t b;
int current_state = AS_NO_DATA;
int have_some_real_data = FALSE;
hoststatus *hststatus = NULL;
servicestatus *svcstatus = NULL;
time_t initial_assumed_time;
int initial_assumed_state = AS_NO_DATA;
int error;
/* if left hand of graph is after current time, we can't do anything at all.... */
if (t1 > current_time)
return;
/* get current state of host or service if possible */
if (subject->type == HOST_SUBJECT)
hststatus = find_hoststatus(subject->host_name);
else
svcstatus = find_servicestatus(subject->host_name, subject->service_description);
/************************************/
/* INSERT CURRENT STATE (IF WE CAN) */
/************************************/
/* if current time DOES NOT fall within graph bounds, so we can't do anything as far as assuming current state */
/* if we don't have any data, assume current state (if possible) */
if (subject->as_list == NULL && current_time > t1 && current_time <= t2) {
/* we don't have any historical information, but the current time falls within the reporting period, so use */
/* the current status of the host/service as the starting data */
if (subject->type == HOST_SUBJECT) {
if (hststatus != NULL) {
if (hststatus->status == SD_HOST_DOWN)
subject->last_known_state = AS_HOST_DOWN;
else if (hststatus->status == SD_HOST_UNREACHABLE)
subject->last_known_state = AS_HOST_UNREACHABLE;
else if (hststatus->status == SD_HOST_UP)
subject->last_known_state = AS_HOST_UP;
else
subject->last_known_state = AS_NO_DATA;
if (subject->last_known_state != AS_NO_DATA) {
/* add a dummy archived state item, so something can get graphed */
add_archived_state(subject->last_known_state, AS_HARD_STATE, t1, "Current Host State Assumed (Faked Log Entry)", subject);
}
}
}
else {
if (svcstatus != NULL) {
if (svcstatus->status == SERVICE_OK)
subject->last_known_state = AS_SVC_OK;
else if (svcstatus->status == SERVICE_WARNING)
subject->last_known_state = AS_SVC_WARNING;
else if (svcstatus->status == SERVICE_CRITICAL)
subject->last_known_state = AS_SVC_CRITICAL;
else if (svcstatus->status == SERVICE_UNKNOWN)
subject->last_known_state = AS_SVC_UNKNOWN;
else
subject->last_known_state = AS_NO_DATA;
if (subject->last_known_state != AS_NO_DATA) {
/* add a dummy archived state item, so something can get graphed */
add_archived_state(subject->last_known_state, AS_HARD_STATE, t1, "Current Service State Assumed (Faked Log Entry)", subject);
}
}
}
}
/******************************************/
/* INSERT FIRST ASSUMED STATE (IF WE CAN) */
/******************************************/
if ((subject->type == HOST_SUBJECT && initial_assumed_host_state != AS_NO_DATA) || (subject->type == SERVICE_SUBJECT && initial_assumed_service_state != AS_NO_DATA)) {
/* see if its okay to assume initial state for this subject */
error = FALSE;
if (subject->type == SERVICE_SUBJECT) {
if (initial_assumed_service_state != AS_SVC_OK && initial_assumed_service_state != AS_SVC_WARNING && initial_assumed_service_state != AS_SVC_UNKNOWN && initial_assumed_service_state != AS_SVC_CRITICAL && initial_assumed_service_state != AS_CURRENT_STATE)
error = TRUE;
else
initial_assumed_state = initial_assumed_service_state;
if (initial_assumed_service_state == AS_CURRENT_STATE && svcstatus == NULL)
error = TRUE;
}
else {
if (initial_assumed_host_state != AS_HOST_UP && initial_assumed_host_state != AS_HOST_DOWN && initial_assumed_host_state != AS_HOST_UNREACHABLE && initial_assumed_host_state != AS_CURRENT_STATE)
error = TRUE;
else
initial_assumed_state = initial_assumed_host_state;
if (initial_assumed_host_state == AS_CURRENT_STATE && hststatus == NULL)
error = TRUE;
}
/* get the current state if applicable */
if (((subject->type == HOST_SUBJECT && initial_assumed_host_state == AS_CURRENT_STATE) || (subject->type == SERVICE_SUBJECT && initial_assumed_service_state == AS_CURRENT_STATE)) && error == FALSE) {
if (subject->type == SERVICE_SUBJECT) {
switch (svcstatus->status) {
case SERVICE_OK:
initial_assumed_state = AS_SVC_OK;
break;
case SERVICE_WARNING:
initial_assumed_state = AS_SVC_WARNING;
break;
case SERVICE_UNKNOWN:
initial_assumed_state = AS_SVC_UNKNOWN;
break;
case SERVICE_CRITICAL:
initial_assumed_state = AS_SVC_CRITICAL;
break;
default:
error = TRUE;
break;
}
}
else {
switch (hststatus->status) {
case SD_HOST_DOWN:
initial_assumed_state = AS_HOST_DOWN;
break;
case SD_HOST_UNREACHABLE:
initial_assumed_state = AS_HOST_UNREACHABLE;
break;
case SD_HOST_UP:
initial_assumed_state = AS_HOST_UP;
break;
default:
error = TRUE;
break;
}
}
}
if (error == FALSE) {
/* add this assumed state entry before any entries in the list and <= t1 */
if (subject->as_list == NULL)
initial_assumed_time = t1;
else if (subject->as_list->time_stamp > t1)
initial_assumed_time = t1;
else
initial_assumed_time = subject->as_list->time_stamp - 1;
if (subject->type == HOST_SUBJECT)
add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Host State Assumed (Faked Log Entry)", subject);
else
add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Service State Assumed (Faked Log Entry)", subject);
}
}
/**************************************/
/* BAIL OUT IF WE DON'T HAVE ANYTHING */
/**************************************/
have_some_real_data = FALSE;
for (temp_as = subject->as_list; temp_as != NULL; temp_as = temp_as->next) {
if (temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_START && temp_as->entry_type != AS_PROGRAM_END) {
have_some_real_data = TRUE;
break;
}
}
if (have_some_real_data == FALSE)
return;
last_as = NULL;
subject->earliest_time = t2;
subject->latest_time = t1;
#ifdef DEBUG
printf("--- BEGINNING/MIDDLE SECTION --- \n");
#endif
#ifdef DEBUG2
printf("
");
#endif
/**********************************/
/* BEGINNING/MIDDLE SECTION */
/**********************************/
for (temp_as = subject->as_list; temp_as != NULL; temp_as = temp_as->next) {
/* keep this as last known state if this is the first entry or if it occurs before the starting point of the graph */
if ((temp_as->time_stamp <= t1 || temp_as == subject->as_list) && (temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_END && temp_as->entry_type != AS_PROGRAM_START)) {
subject->last_known_state = temp_as->entry_type;
#ifdef DEBUG
printf("SETTING LAST KNOWN STATE=%d \n", subject->last_known_state);
#endif
}
/* skip this entry if it occurs before the starting point of the graph */
if (temp_as->time_stamp <= t1) {
#ifdef DEBUG
printf("SKIPPING PRE-EVENT: %d @ %lu \n", temp_as->entry_type, temp_as->time_stamp);
#endif
last_as = temp_as;
continue;
}
/* graph this span if we're not on the first item */
if (last_as != NULL) {
a = last_as->time_stamp;
b = temp_as->time_stamp;
/* we've already passed the last time displayed in the graph */
if (a > t2)
break;
/* only graph this data if its on the graph */
else if (b > t1) {
/* clip last time if it exceeds graph limits */
if (b > t2)
b = t2;
/* clip first time if it precedes graph limits */
if (a < t1)
a = t1;
/* save this time if its the earliest we've graphed */
if (a < subject->earliest_time) {
subject->earliest_time = a;
subject->earliest_state = last_as->entry_type;
}
/* save this time if its the latest we've graphed */
if (b > subject->latest_time) {
subject->latest_time = b;
subject->latest_state = last_as->entry_type;
}
/* compute availability times for this chunk */
compute_subject_availability_times(last_as->entry_type, temp_as->entry_type, last_as->time_stamp, a, b, subject, temp_as);
/* return if we've reached the end of the graph limits */
if (b >= t2) {
last_as = temp_as;
break;
}
}
}
/* keep track of the last item */
last_as = temp_as;
}
#ifdef DEBUG
printf("--- END SECTION --- \n");
#endif
/**********************************/
/* END SECTION */
/**********************************/
if (last_as != NULL) {
/* don't process an entry that is beyond the limits of the graph */
if (last_as->time_stamp < t2) {
time(¤t_time);
b = current_time;
if (b > t2)
b = t2;
a = last_as->time_stamp;
if (a < t1)
a = t1;
/* fake the current state (it doesn't really matter for graphing) */
if (subject->type == HOST_SUBJECT)
current_state = AS_HOST_UP;
else
current_state = AS_SVC_OK;
/* compute availability times for last state */
compute_subject_availability_times(last_as->entry_type, current_state, last_as->time_stamp, a, b, subject, last_as);
}
}
#ifdef DEBUG2
printf("
");
#endif
return;
}
/* computes availability times */
void compute_subject_availability_times(int first_state, int last_state, time_t real_start_time, time_t start_time, time_t end_time, avail_subject *subject, archived_state *as)
{
int start_state = 0;
unsigned long state_duration = 0L;
struct tm *t = NULL;
time_t midnight_today = 0L;
int weekday = 0;
timerange *temp_timerange = NULL;
unsigned long temp_duration = 0L;
unsigned long temp_end = 0L;
unsigned long temp_start = 0L;
unsigned long start = 0L;
unsigned long end = 0L;
#ifdef DEBUG2
if (subject->type == HOST_SUBJECT) {
printf("\nHOST '%s'...\n", subject->host_name);
}
else {
printf("\nSERVICE '%s' ON HOST '%s'...\n", subject->service_description, subject->host_name);
}
printf("COMPUTING %d->%d FROM %lu to %lu (%lu seconds) FOR %s\n", first_state, last_state, start_time, end_time, (end_time - start_time), (subject->type == HOST_SUBJECT) ? "HOST" : "SERVICE");
#endif
/* clip times if necessary */
if (start_time < t1) {
start_time = t1;
}
if (end_time > t2) {
end_time = t2;
}
/* make sure this is a valid time */
if (start_time > t2) {
return;
}
if (end_time < t1) {
return;
}
/* MickeM - attempt to handle the current time_period (if any) */
if (current_timeperiod != NULL) {
t = localtime((time_t *)&start_time);
state_duration = 0;
/* calculate the start of the day (midnight, 00:00 hours) */
t->tm_sec = 0;
t->tm_min = 0;
t->tm_hour = 0;
t->tm_isdst = -1;
midnight_today = (unsigned long)mktime(t);
weekday = t->tm_wday;
while (midnight_today < end_time) {
temp_duration = 0;
temp_end = min(86400, end_time - midnight_today);
temp_start = 0;
if (start_time > midnight_today) {
temp_start = start_time - midnight_today;
}
#ifdef DEBUG
printf("Matching: %ld -> %ld. (%ld -> %ld) \n", temp_start, temp_end, midnight_today + temp_start, midnight_today + temp_end);
#endif
/* check all time ranges for this day of the week */
for (temp_timerange = current_timeperiod->days[weekday]; temp_timerange != NULL; temp_timerange = temp_timerange->next) {
#ifdef DEBUG
printf("
Matching in timerange[%d]: %d -> %d (%ld -> %ld) \n", weekday, temp_timerange->range_start, temp_timerange->range_end, temp_start, temp_end);
#endif
start = max(temp_timerange->range_start, temp_start);
end = min(temp_timerange->range_end, temp_end);
if (start < end) {
temp_duration += end - start;
#ifdef DEBUG
printf("
\n");
}
/* get archive to use */
get_log_archive_to_use(archive, archive_file, sizeof(archive_file) - 1);
/* cut the pathname for security, and the remaining slash for clarity */
archive_basename = (char *)&archive_file;
if(strrchr((char *)&archive_basename, '/') != NULL)
archive_basename = strrchr((char *)&archive_file, '/') + 1;
/* now it's safe to print the filename */
printf("
File: %s
\n", archive_basename);
return;
}
/* prints the additional notes or action url for a hostgroup (with macros substituted) */
void print_extra_hostgroup_url(char *group_name, char *url) {
char input_buffer[MAX_INPUT_BUFFER] = "";
char output_buffer[MAX_INPUT_BUFFER] = "";
char *temp_buffer;
int in_macro = FALSE;
hostgroup *temp_hostgroup = NULL;
if(group_name == NULL || url == NULL)
return;
temp_hostgroup = find_hostgroup(group_name);
if(temp_hostgroup == NULL) {
printf("%s", url);
return;
}
strncpy(input_buffer, url, sizeof(input_buffer) - 1);
input_buffer[sizeof(input_buffer) - 1] = '\x0';
for(temp_buffer = my_strtok(input_buffer, "$"); temp_buffer != NULL; temp_buffer = my_strtok(NULL, "$")) {
if(in_macro == FALSE) {
if(strlen(output_buffer) + strlen(temp_buffer) < sizeof(output_buffer) - 1) {
strncat(output_buffer, temp_buffer, sizeof(output_buffer) - strlen(output_buffer) - 1);
output_buffer[sizeof(output_buffer) - 1] = '\x0';
}
in_macro = TRUE;
}
else {
if(strlen(output_buffer) + strlen(temp_buffer) < sizeof(output_buffer) - 1) {
if(!strcmp(temp_buffer, "HOSTGROUPNAME"))
strncat(output_buffer, url_encode(temp_hostgroup->group_name), sizeof(output_buffer) - strlen(output_buffer) - 1);
}
in_macro = FALSE;
}
}
printf("%s", output_buffer);
return;
}
/* prints the additional notes or action url for a servicegroup (with macros substituted) */
void print_extra_servicegroup_url(char *group_name, char *url) {
char input_buffer[MAX_INPUT_BUFFER] = "";
char output_buffer[MAX_INPUT_BUFFER] = "";
char *temp_buffer;
int in_macro = FALSE;
servicegroup *temp_servicegroup = NULL;
if(group_name == NULL || url == NULL)
return;
temp_servicegroup = find_servicegroup(group_name);
if(temp_servicegroup == NULL) {
printf("%s", url);
return;
}
strncpy(input_buffer, url, sizeof(input_buffer) - 1);
input_buffer[sizeof(input_buffer) - 1] = '\x0';
for(temp_buffer = my_strtok(input_buffer, "$"); temp_buffer != NULL; temp_buffer = my_strtok(NULL, "$")) {
if(in_macro == FALSE) {
if(strlen(output_buffer) + strlen(temp_buffer) < sizeof(output_buffer) - 1) {
strncat(output_buffer, temp_buffer, sizeof(output_buffer) - strlen(output_buffer) - 1);
output_buffer[sizeof(output_buffer) - 1] = '\x0';
}
in_macro = TRUE;
}
else {
if(strlen(output_buffer) + strlen(temp_buffer) < sizeof(output_buffer) - 1) {
if(!strcmp(temp_buffer, "SERVICEGROUPNAME"))
strncat(output_buffer, url_encode(temp_servicegroup->group_name), sizeof(output_buffer) - strlen(output_buffer) - 1);
}
in_macro = FALSE;
}
}
printf("%s", output_buffer);
return;
}
/* include user-defined SSI footers or headers */
void include_ssi_files(const char *cgi_name, int type) {
char common_ssi_file[MAX_INPUT_BUFFER];
char cgi_ssi_file[MAX_INPUT_BUFFER];
char raw_cgi_name[MAX_INPUT_BUFFER];
char *stripped_cgi_name;
/* common header or footer */
snprintf(common_ssi_file, sizeof(common_ssi_file) - 1, "%scommon-%s.ssi", physical_ssi_path, (type == SSI_HEADER) ? "header" : "footer");
common_ssi_file[sizeof(common_ssi_file) - 1] = '\x0';
/* CGI-specific header or footer */
strncpy(raw_cgi_name, cgi_name, sizeof(raw_cgi_name) - 1);
raw_cgi_name[sizeof(raw_cgi_name) - 1] = '\x0';
stripped_cgi_name = strtok(raw_cgi_name, ".");
snprintf(cgi_ssi_file, sizeof(cgi_ssi_file) - 1, "%s%s-%s.ssi", physical_ssi_path, (stripped_cgi_name == NULL) ? "" : stripped_cgi_name, (type == SSI_HEADER) ? "header" : "footer");
cgi_ssi_file[sizeof(cgi_ssi_file) - 1] = '\x0';
if(type == SSI_HEADER) {
printf("\n\n");
include_ssi_file(common_ssi_file);
include_ssi_file(cgi_ssi_file);
}
else {
include_ssi_file(cgi_ssi_file);
include_ssi_file(common_ssi_file);
printf("\n\n");
}
return;
}
/* include user-defined SSI footer or header */
void include_ssi_file(const char *filename) {
char buffer[MAX_INPUT_BUFFER];
FILE *fp;
struct stat stat_result;
int call_return;
/* if file is executable, we want to run it rather than print it */
call_return = stat(filename, &stat_result);
/* file is executable */
if(call_return == 0 && (stat_result.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
/* must flush output stream first so that output
from script shows up in correct place. Other choice
is to open program under pipe and copy the data from
the program to our output stream.
*/
fflush(stdout);
/* ignore return status from system call. */
call_return = system(filename);
return;
}
/* an error occurred trying to stat() the file */
else if(call_return != 0) {
/* Handle error conditions. Assume that standard posix error codes and errno are available. If not, comment this section out. */
switch(errno) {
case ENOTDIR: /* - A component of the path is not a directory. */
case ELOOP: /* Too many symbolic links encountered while traversing the path. */
case EFAULT: /* Bad address. */
case ENOMEM: /* Out of memory (i.e. kernel memory). */
case ENAMETOOLONG: /* File name too long. */
printf(" A stat call returned %d while looking for the file %s. ", errno, filename);
return;
case EACCES: /* Permission denied. -- The file should be accessible by nagios. */
printf(" A stat call returned a permissions error(%d) while looking for the file %s. ", errno, filename);
return;
case ENOENT: /* A component of the path file_name does not exist, or the path is an empty string. Just return if the file doesn't exist. */
return;
default:
return;
}
}
fp = fopen(filename, "r");
if(fp == NULL)
return;
/* print all lines in the SSI file */
while(fgets(buffer, (int)(sizeof(buffer) - 1), fp) != NULL)
printf("%s", buffer);
fclose(fp);
return;
}
/* displays an error if CGI config file could not be read */
void cgi_config_file_error(const char *config_file) {
printf("
Whoops!
\n");
printf("
Error: Could not open CGI config file '%s' for reading!
\n", config_file);
printf("
\n");
printf("Here are some things you should check in order to resolve this error:\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Make sure you've installed a CGI config file in its proper location. See the error message about for details on where the CGI is expecting to find the configuration file. A sample CGI configuration file (named cgi.cfg) can be found in the sample-config/ subdirectory of the Nagios source code distribution.\n");
printf("
Make sure the user your web server is running as has permission to read the CGI config file.\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("Make sure you read the documentation on installing and configuring Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at https://www.nagios.org.\n");
printf("
\n");
return;
}
/* displays an error if main config file could not be read */
void main_config_file_error(const char *config_file) {
printf("
Whoops!
\n");
printf("
Error: Could not open main config file '%s' for reading!
\n", config_file);
printf("
\n");
printf("Here are some things you should check in order to resolve this error:\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Make sure you've installed a main config file in its proper location. See the error message about for details on where the CGI is expecting to find the configuration file. A sample main configuration file (named nagios.cfg) can be found in the sample-config/ subdirectory of the Nagios source code distribution.\n");
printf("
Make sure the user your web server is running as has permission to read the main config file.\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("Make sure you read the documentation on installing and configuring Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at https://www.nagios.org.\n");
printf("
\n");
return;
}
/* displays an error if object data could not be read */
void object_data_error(void) {
printf("
Whoops!
\n");
printf("
Error: Could not read object configuration data!
\n");
printf("
\n");
printf("Here are some things you should check in order to resolve this error:\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Verify configuration options using the -v command-line option to check for errors.\n");
printf("
Check the Nagios log file for messages relating to startup or status data errors.\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("Make sure you read the documentation on installing, configuring and running Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at https://www.nagios.org.\n");
printf("
\n");
return;
}
/* displays an error if status data could not be read */
void status_data_error(void) {
printf("
Whoops!
\n");
printf("
Error: Could not read host and service status information!
\n");
printf("
\n");
printf("The most common cause of this error message (especially for new users), is the fact that Nagios is not actually running. If Nagios is indeed not running, this is a normal error message. It simply indicates that the CGIs could not obtain the current status of hosts and services that are being monitored. If you've just installed things, make sure you read the documentation on starting Nagios.\n");
printf("
\n");
printf("
\n");
printf("Some other things you should check in order to resolve this error include:\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Check the Nagios log file for messages relating to startup or status data errors.\n");
printf("
Always verify configuration options using the -v command-line option before starting or restarting Nagios!\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("Make sure you read the documentation on installing, configuring and running Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at https://www.nagios.org.\n");
printf("
\n");
return;
}
/* displays context-sensitive help window */
void display_context_help(const char *chid) {
const char *icon = CONTEXT_HELP_ICON1;
if(show_context_help == FALSE)
return;
/* change icon if necessary */
if(!strcmp(chid, CONTEXTHELP_TAC))
icon = CONTEXT_HELP_ICON2;
printf("\n", url_context_help_path, chid, url_context_help_path, chid, url_images_path, icon);
return;
}
void display_splunk_host_url(host *hst) {
if(enable_splunk_integration == FALSE)
return;
if(hst == NULL)
return;
printf("\n", splunk_url, url_encode(hst->name), url_images_path, SPLUNK_SMALL_WHITE_ICON);
return;
}
void display_splunk_service_url(service *svc) {
if(enable_splunk_integration == FALSE)
return;
if(svc == NULL)
return;
printf("\n", url_encode(svc->description), url_images_path, SPLUNK_SMALL_WHITE_ICON);
return;
}
void display_splunk_generic_url(char *buf, int icon) {
char *newbuf = NULL;
if(enable_splunk_integration == FALSE)
return;
if(buf == NULL)
return;
if((newbuf = (char *)strdup(buf)) == NULL)
return;
strip_splunk_query_terms(newbuf);
printf("", splunk_url, url_encode(newbuf));
if(icon > 0)
printf("", url_images_path, (icon == 1) ? SPLUNK_SMALL_WHITE_ICON : SPLUNK_SMALL_BLACK_ICON);
printf("\n");
free(newbuf);
return;
}
/* strip quotes and from string */
void strip_splunk_query_terms(char *buffer) {
register int x;
register int y;
register int z;
if(buffer == NULL || buffer[0] == '\x0')
return;
/* remove all occurrences in string */
z = (int)strlen(buffer);
for(x = 0, y = 0; x < z; x++) {
if(buffer[x] == '\'' || buffer[x] == '\"' || buffer[x] == ';' || buffer[x] == ':' || buffer[x] == ',' || buffer[x] == '-' || buffer[x] == '=')
buffer[y++] = ' ';
else
buffer[y++] = buffer[x];
}
buffer[y++] = '\x0';
return;
}
nagios-4.4.6/cgi/cmd.c 0000664 0000000 0000000 00000330754 13652113235 0014473 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* CMD.C - Nagios Command CGI
*
*
* 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/cgiutils.h"
#include "../include/cgiauth.h"
#include "../include/getcgi.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 command_file[MAX_FILENAME_LENGTH];
extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
extern int nagios_process_state;
extern int use_authentication;
extern int lock_author_names;
extern int ack_no_sticky;
extern int ack_no_send;
#define MAX_AUTHOR_LENGTH 64
#define MAX_COMMENT_LENGTH 1024
#define HTML_CONTENT 0
#define WML_CONTENT 1
char *host_name = "";
char *hostgroup_name = "";
char *servicegroup_name = "";
char *service_desc = "";
char *comment_author = "";
char *comment_data = "";
char *start_time_string = "";
char *end_time_string = "";
char *cookie_form_id = NULL, *form_id = NULL;
unsigned long comment_id = 0;
unsigned long downtime_id = 0;
int notification_delay = 0;
int schedule_delay = 0;
int persistent_comment = FALSE;
int sticky_ack = FALSE;
int send_notification = FALSE;
int force_check = FALSE;
int plugin_state = STATE_OK;
char plugin_output[MAX_INPUT_BUFFER] = "";
char performance_data[MAX_INPUT_BUFFER] = "";
time_t start_time = 0L;
time_t end_time = 0L;
int affect_host_and_services = FALSE;
int propagate_to_children = FALSE;
int fixed = FALSE;
unsigned long duration = 0L;
unsigned long triggered_by = 0L;
int child_options = 0;
int force_notification = 0;
int broadcast_notification = 0;
int command_type = CMD_NONE;
int command_mode = CMDMODE_REQUEST;
int content_type = HTML_CONTENT;
int display_header = TRUE;
authdata current_authdata;
void show_command_help(int);
void request_command_data(int);
void commit_command_data(int);
int print_comment_field(int cmd_id);
int commit_command(int);
int write_command_to_file(char *);
void clean_comment_data(char *);
void cgicfg_callback(const char*, const char*);
void document_header(int);
void document_footer(void);
int process_cgivars(void);
int string_to_time(char *, time_t *);
int main(void) {
int result = OK;
int formid_ok = OK;
/* Initialize shared configuration variables */
init_shared_cfg_vars(1);
/* 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(), cgicfg_callback);
if(result == ERROR) {
document_header(FALSE);
if(content_type == WML_CONTENT)
printf("
Error: Could not open CGI config file!
\n");
else
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);
if(content_type == WML_CONTENT)
printf("
Error: Could not open main config file!
\n");
else
main_config_file_error(main_config_file);
document_footer();
return ERROR;
}
/* This requires the date_format parameter in the main config file */
if(strcmp(start_time_string, ""))
string_to_time(start_time_string, &start_time);
if(strcmp(end_time_string, ""))
string_to_time(end_time_string, &end_time);
/* read all object configuration data */
result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
if(result == ERROR) {
document_header(FALSE);
if(content_type == WML_CONTENT)
printf("
Error: Could not read object config data!
\n");
else
object_data_error();
document_footer();
return ERROR;
}
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_authdata);
if(display_header == TRUE) {
/* begin top table */
printf("
\n");
}
/* authorized_for_read_only should take priority */
if(is_authorized_for_read_only(¤t_authdata) == TRUE) {
printf("
It appears as though you do not have permission to submit the command you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
document_footer();
/* free allocated memory */
free_memory();
free_object_data();
return OK;
}
if (cookie_form_id && *cookie_form_id) {
formid_ok = ERROR;
if (form_id && *form_id) {
if (!strcmp(form_id, cookie_form_id))
formid_ok = OK;
}
}
/* if no command was specified... */
if(command_type == CMD_NONE) {
if(content_type == WML_CONTENT)
printf("
Error: No command specified!
\n");
else
printf("
Error: No command was specified
\n");
}
/* if this is the first request for a command, present option */
else if(command_mode == CMDMODE_REQUEST)
request_command_data(command_type);
/* the user wants to commit the command */
else if(command_mode == CMDMODE_COMMIT) {
if (formid_ok == ERROR) /* we're expecting an id but it wasn't there... */
printf("
Error: Invalid form id!
\n");
else
commit_command_data(command_type);
}
document_footer();
/* free allocated memory */
free_memory();
free_object_data();
return OK;
}
void cgicfg_callback(const char *var, const char *val)
{
struct nagios_extcmd *ecmd;
const char *cp = val;
if (strncmp(var, "CMT_", 4))
return;
ecmd = extcmd_get_command_name(&var[4]);
if (!ecmd)
return;
if (!isdigit(*val))
return;
ecmd->cmt_opt = atoi(val);
while (isdigit(*cp) || *cp == ',' || *cp == ' ' || *cp == '\t')
++cp;
if (!*cp)
return;
ecmd->default_comment = strdup(cp);
strip_html_brackets(ecmd->default_comment);
}
void document_header(int use_stylesheet) {
if(content_type == WML_CONTENT) {
printf("Content-type: text/vnd.wap.wml\r\n\r\n");
printf("\n");
printf("\n");
printf("\n");
printf("\n");
}
else {
printf("Content-type: text/html; charset=utf-8\r\n\r\n");
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("External Command Interface\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, COMMAND_CSS);
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(COMMAND_CGI, SSI_HEADER);
}
return;
}
void document_footer(void) {
if(content_type == WML_CONTENT) {
printf("\n");
printf("\n");
}
else {
/* include user SSI footer */
include_ssi_files(COMMAND_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
}
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
for(x = 0; variables[x]; 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 command type */
else if(!strcmp(variables[x], "cmd_typ")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
command_type = atoi(variables[x]);
}
/* we found the command mode */
else if(!strcmp(variables[x], "cmd_mod")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
command_mode = atoi(variables[x]);
}
/* we found the comment id */
else if(!strcmp(variables[x], "com_id")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
comment_id = strtoul(variables[x], NULL, 10);
}
/* we found the downtime id */
else if(!strcmp(variables[x], "down_id")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
downtime_id = strtoul(variables[x], NULL, 10);
}
/* we found the notification delay */
else if(!strcmp(variables[x], "not_dly")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
notification_delay = atoi(variables[x]);
}
/* we found the schedule delay */
else if(!strcmp(variables[x], "sched_dly")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
schedule_delay = atoi(variables[x]);
}
/* we found the comment author */
else if(!strcmp(variables[x], "com_author")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((comment_author = (char *)strdup(variables[x])) == NULL)
comment_author = "";
strip_html_brackets(comment_author);
}
/* we found the comment data */
else if(!strcmp(variables[x], "com_data")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((comment_data = (char *)strdup(variables[x])) == NULL)
comment_data = "";
strip_html_brackets(comment_data);
}
/* we found the host name */
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);
}
/* we found the hostgroup name */
else if(!strcmp(variables[x], "hostgroup")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((hostgroup_name = (char *)strdup(variables[x])) == NULL)
hostgroup_name = "";
strip_html_brackets(hostgroup_name);
}
/* we found the service name */
else if(!strcmp(variables[x], "service")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((service_desc = (char *)strdup(variables[x])) == NULL)
service_desc = "";
strip_html_brackets(service_desc);
}
/* we found the servicegroup name */
else if(!strcmp(variables[x], "servicegroup")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if((servicegroup_name = (char *)strdup(variables[x])) == NULL)
servicegroup_name = "";
strip_html_brackets(servicegroup_name);
}
/* we got the persistence option for a comment */
else if(!strcmp(variables[x], "persistent"))
persistent_comment = TRUE;
/* we got the notification option for an acknowledgement */
else if(!strcmp(variables[x], "send_notification"))
send_notification = TRUE;
/* we got the acknowledgement type */
else if(!strcmp(variables[x], "sticky_ack"))
sticky_ack = TRUE;
/* we got the service check force option */
else if(!strcmp(variables[x], "force_check"))
force_check = TRUE;
/* we got the option to affect host and all its services */
else if(!strcmp(variables[x], "ahas"))
affect_host_and_services = TRUE;
/* we got the option to propagate to child hosts */
else if(!strcmp(variables[x], "ptc"))
propagate_to_children = TRUE;
/* we got the option for fixed downtime */
else if(!strcmp(variables[x], "fixed")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
fixed = (atoi(variables[x]) > 0) ? TRUE : FALSE;
}
/* we got the triggered by downtime option */
else if(!strcmp(variables[x], "trigger")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
triggered_by = strtoul(variables[x], NULL, 10);
}
/* we got the child options */
else if(!strcmp(variables[x], "childoptions")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
child_options = atoi(variables[x]);
}
/* we found the plugin output */
else if(!strcmp(variables[x], "plugin_output")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
/* protect against buffer overflows */
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
error = TRUE;
break;
}
else
strcpy(plugin_output, variables[x]);
}
/* we found the performance data */
else if(!strcmp(variables[x], "performance_data")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
/* protect against buffer overflows */
if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
error = TRUE;
break;
}
else
strcpy(performance_data, variables[x]);
}
/* we found the plugin state */
else if(!strcmp(variables[x], "plugin_state")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
plugin_state = atoi(variables[x]);
}
/* we found the hour duration */
else if(!strcmp(variables[x], "hours")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(atoi(variables[x]) < 0) {
error = TRUE;
break;
}
duration += (unsigned long)(atoi(variables[x]) * 3600);
}
/* we found the minute duration */
else if(!strcmp(variables[x], "minutes")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(atoi(variables[x]) < 0) {
error = TRUE;
break;
}
duration += (unsigned long)(atoi(variables[x]) * 60);
}
/* we found the start time */
else if(!strcmp(variables[x], "start_time")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
start_time_string = (char *)malloc(strlen(variables[x]) + 1);
if(start_time_string == NULL)
start_time_string = "";
else
strcpy(start_time_string, variables[x]);
}
/* we found the end time */
else if(!strcmp(variables[x], "end_time")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
end_time_string = (char *)malloc(strlen(variables[x]) + 1);
if(end_time_string == NULL)
end_time_string = "";
else
strcpy(end_time_string, variables[x]);
}
/* we found the content type argument */
else if(!strcmp(variables[x], "content")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
if(!strcmp(variables[x], "wml")) {
content_type = WML_CONTENT;
display_header = FALSE;
}
else
content_type = HTML_CONTENT;
}
/* we found the forced notification option */
else if(!strcmp(variables[x], "force_notification"))
force_notification = NOTIFICATION_OPTION_FORCED;
/* we found the broadcast notification option */
else if(!strcmp(variables[x], "broadcast_notification"))
broadcast_notification = NOTIFICATION_OPTION_BROADCAST;
/* we found the cookie form id */
else if (!strcmp(variables[x], "NagFormId")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
cookie_form_id = (char*)strdup(variables[x]);
}
/* we found the form id on the form */
else if (!strcmp(variables[x], "nagFormId")) {
x++;
if (variables[x] == NULL) {
error = TRUE;
break;
}
form_id = (char*)strdup(variables[x]);
}
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
void request_command_data(int cmd) {
time_t t;
char start_time_str[MAX_DATETIME_LENGTH];
char buffer[MAX_INPUT_BUFFER];
contact *temp_contact;
scheduled_downtime *temp_downtime;
/* get default name to use for comment author */
temp_contact = find_contact(current_authdata.username);
if(temp_contact != NULL && temp_contact->alias != NULL)
comment_author = temp_contact->alias;
else
comment_author = current_authdata.username;
printf("
You are requesting to ");
switch(cmd) {
case CMD_ADD_HOST_COMMENT:
case CMD_ADD_SVC_COMMENT:
printf("add a %s comment", (cmd == CMD_ADD_HOST_COMMENT) ? "host" : "service");
break;
case CMD_DEL_HOST_COMMENT:
case CMD_DEL_SVC_COMMENT:
printf("delete a %s comment", (cmd == CMD_DEL_HOST_COMMENT) ? "host" : "service");
break;
case CMD_DELAY_HOST_NOTIFICATION:
case CMD_DELAY_SVC_NOTIFICATION:
printf("delay a %s notification", (cmd == CMD_DELAY_HOST_NOTIFICATION) ? "host" : "service");
break;
case CMD_SCHEDULE_SVC_CHECK:
printf("schedule a service check");
break;
case CMD_ENABLE_SVC_CHECK:
case CMD_DISABLE_SVC_CHECK:
printf("%s active checks of a particular service", (cmd == CMD_ENABLE_SVC_CHECK) ? "enable" : "disable");
break;
case CMD_ENABLE_NOTIFICATIONS:
case CMD_DISABLE_NOTIFICATIONS:
printf("%s notifications", (cmd == CMD_ENABLE_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_SHUTDOWN_PROCESS:
case CMD_RESTART_PROCESS:
printf("%s the Nagios process", (cmd == CMD_SHUTDOWN_PROCESS) ? "shutdown" : "restart");
break;
case CMD_ENABLE_HOST_SVC_CHECKS:
case CMD_DISABLE_HOST_SVC_CHECKS:
printf("%s active checks of all services on a host", (cmd == CMD_ENABLE_HOST_SVC_CHECKS) ? "enable" : "disable");
break;
case CMD_SCHEDULE_HOST_SVC_CHECKS:
printf("schedule a check of all services for a host");
break;
case CMD_DEL_ALL_HOST_COMMENTS:
case CMD_DEL_ALL_SVC_COMMENTS:
printf("delete all comments for a %s", (cmd == CMD_DEL_ALL_HOST_COMMENTS) ? "host" : "service");
break;
case CMD_ENABLE_SVC_NOTIFICATIONS:
case CMD_DISABLE_SVC_NOTIFICATIONS:
printf("%s notifications for a service", (cmd == CMD_ENABLE_SVC_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOST_NOTIFICATIONS:
printf("%s notifications for a host", (cmd == CMD_ENABLE_HOST_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
printf("%s notifications for all hosts and services beyond a host", (cmd == CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST) ? "enable" : "disable");
break;
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
printf("%s notifications for all services on a host", (cmd == CMD_ENABLE_HOST_SVC_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ACKNOWLEDGE_HOST_PROBLEM:
case CMD_ACKNOWLEDGE_SVC_PROBLEM:
printf("acknowledge a %s problem", (cmd == CMD_ACKNOWLEDGE_HOST_PROBLEM) ? "host" : "service");
break;
case CMD_START_EXECUTING_SVC_CHECKS:
case CMD_STOP_EXECUTING_SVC_CHECKS:
printf("%s executing active service checks", (cmd == CMD_START_EXECUTING_SVC_CHECKS) ? "start" : "stop");
break;
case CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS:
printf("%s accepting passive service checks", (cmd == CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS) ? "start" : "stop");
break;
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
printf("%s accepting passive service checks for a particular service", (cmd == CMD_ENABLE_PASSIVE_SVC_CHECKS) ? "start" : "stop");
break;
case CMD_ENABLE_EVENT_HANDLERS:
case CMD_DISABLE_EVENT_HANDLERS:
printf("%s event handlers", (cmd == CMD_ENABLE_EVENT_HANDLERS) ? "enable" : "disable");
break;
case CMD_ENABLE_HOST_EVENT_HANDLER:
case CMD_DISABLE_HOST_EVENT_HANDLER:
printf("%s the event handler for a particular host", (cmd == CMD_ENABLE_HOST_EVENT_HANDLER) ? "enable" : "disable");
break;
case CMD_ENABLE_SVC_EVENT_HANDLER:
case CMD_DISABLE_SVC_EVENT_HANDLER:
printf("%s the event handler for a particular service", (cmd == CMD_ENABLE_SVC_EVENT_HANDLER) ? "enable" : "disable");
break;
case CMD_ENABLE_HOST_CHECK:
case CMD_DISABLE_HOST_CHECK:
printf("%s active checks of a particular host", (cmd == CMD_ENABLE_HOST_CHECK) ? "enable" : "disable");
break;
case CMD_STOP_OBSESSING_OVER_SVC_CHECKS:
case CMD_START_OBSESSING_OVER_SVC_CHECKS:
printf("%s obsessing over service checks", (cmd == CMD_STOP_OBSESSING_OVER_SVC_CHECKS) ? "stop" : "start");
break;
case CMD_REMOVE_HOST_ACKNOWLEDGEMENT:
case CMD_REMOVE_SVC_ACKNOWLEDGEMENT:
printf("remove a %s acknowledgement", (cmd == CMD_REMOVE_HOST_ACKNOWLEDGEMENT) ? "host" : "service");
break;
case CMD_SCHEDULE_HOST_DOWNTIME:
case CMD_SCHEDULE_SVC_DOWNTIME:
printf("schedule downtime for a particular %s", (cmd == CMD_SCHEDULE_HOST_DOWNTIME) ? "host" : "service");
break;
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
printf("schedule downtime for all services for a particular host");
break;
case CMD_PROCESS_HOST_CHECK_RESULT:
case CMD_PROCESS_SERVICE_CHECK_RESULT:
printf("submit a passive check result for a particular %s", (cmd == CMD_PROCESS_HOST_CHECK_RESULT) ? "host" : "service");
break;
case CMD_ENABLE_HOST_FLAP_DETECTION:
case CMD_DISABLE_HOST_FLAP_DETECTION:
printf("%s flap detection for a particular host", (cmd == CMD_ENABLE_HOST_FLAP_DETECTION) ? "enable" : "disable");
break;
case CMD_ENABLE_SVC_FLAP_DETECTION:
case CMD_DISABLE_SVC_FLAP_DETECTION:
printf("%s flap detection for a particular service", (cmd == CMD_ENABLE_SVC_FLAP_DETECTION) ? "enable" : "disable");
break;
case CMD_ENABLE_FLAP_DETECTION:
case CMD_DISABLE_FLAP_DETECTION:
printf("%s flap detection for hosts and services", (cmd == CMD_ENABLE_FLAP_DETECTION) ? "enable" : "disable");
break;
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
printf("%s notifications for all services in a particular hostgroup", (cmd == CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
printf("%s notifications for all hosts in a particular hostgroup", (cmd == CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
printf("%s active checks of all services in a particular hostgroup", (cmd == CMD_ENABLE_HOSTGROUP_SVC_CHECKS) ? "enable" : "disable");
break;
case CMD_DEL_HOST_DOWNTIME:
case CMD_DEL_SVC_DOWNTIME:
printf("cancel scheduled downtime for a particular %s", (cmd == CMD_DEL_HOST_DOWNTIME) ? "host" : "service");
break;
case CMD_ENABLE_PERFORMANCE_DATA:
case CMD_DISABLE_PERFORMANCE_DATA:
printf("%s performance data processing for hosts and services", (cmd == CMD_ENABLE_PERFORMANCE_DATA) ? "enable" : "disable");
break;
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
printf("schedule downtime for all hosts in a particular hostgroup");
break;
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
printf("schedule downtime for all services in a particular hostgroup");
break;
case CMD_START_EXECUTING_HOST_CHECKS:
case CMD_STOP_EXECUTING_HOST_CHECKS:
printf("%s executing host checks", (cmd == CMD_START_EXECUTING_HOST_CHECKS) ? "start" : "stop");
break;
case CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS:
printf("%s accepting passive host checks", (cmd == CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS) ? "start" : "stop");
break;
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
printf("%s accepting passive checks for a particular host", (cmd == CMD_ENABLE_PASSIVE_HOST_CHECKS) ? "start" : "stop");
break;
case CMD_START_OBSESSING_OVER_HOST_CHECKS:
case CMD_STOP_OBSESSING_OVER_HOST_CHECKS:
printf("%s obsessing over host checks", (cmd == CMD_START_OBSESSING_OVER_HOST_CHECKS) ? "start" : "stop");
break;
case CMD_SCHEDULE_HOST_CHECK:
printf("schedule a host check");
break;
case CMD_START_OBSESSING_OVER_SVC:
case CMD_STOP_OBSESSING_OVER_SVC:
printf("%s obsessing over a particular service", (cmd == CMD_START_OBSESSING_OVER_SVC) ? "start" : "stop");
break;
case CMD_START_OBSESSING_OVER_HOST:
case CMD_STOP_OBSESSING_OVER_HOST:
printf("%s obsessing over a particular host", (cmd == CMD_START_OBSESSING_OVER_HOST) ? "start" : "stop");
break;
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
printf("%s notifications for all services in a particular servicegroup", (cmd == CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
printf("%s notifications for all hosts in a particular servicegroup", (cmd == CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS) ? "enable" : "disable");
break;
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
printf("%s active checks of all services in a particular servicegroup", (cmd == CMD_ENABLE_SERVICEGROUP_SVC_CHECKS) ? "enable" : "disable");
break;
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
printf("schedule downtime for all hosts in a particular servicegroup");
break;
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
printf("schedule downtime for all services in a particular servicegroup");
break;
case CMD_CLEAR_HOST_FLAPPING_STATE:
case CMD_CLEAR_SVC_FLAPPING_STATE:
printf("clear flapping state for a %s", (cmd == CMD_CLEAR_HOST_FLAPPING_STATE) ? "host" : "service");
break;
case CMD_SEND_CUSTOM_HOST_NOTIFICATION:
case CMD_SEND_CUSTOM_SVC_NOTIFICATION:
printf("send a custom %s notification", (cmd == CMD_SEND_CUSTOM_HOST_NOTIFICATION) ? "host" : "service");
break;
default:
printf("execute an unknown command. Shame on you!
");
return;
}
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Command Options
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
/* show information about the command... */
show_command_help(cmd);
printf("
\n");
printf("\n");
printf("\n");
printf("
\n");
printf("\n");
printf("
Please enter all required information before committing the command. Required fields are marked in red. Failure to supply all required values will result in an error.
");
return;
}
int print_comment_field(int cmd_id)
{
char *reqtext = "optBoxItem";
char *comment = comment_data;
struct nagios_extcmd *ecmd = extcmd_get_command_id(cmd_id);
if (!ecmd || ecmd->cmt_opt == 0)
return FALSE;
if (ecmd->cmt_opt == 2)
reqtext = "optBoxRequiredItem";
if (!comment || !*comment) {
if (ecmd->default_comment)
comment = ecmd->default_comment;
}
printf("
\n");
return TRUE;
}
void commit_command_data(int cmd) {
char *error_string = NULL;
int result = OK;
int authorized = FALSE;
service *temp_service;
host *temp_host;
hostgroup *temp_hostgroup;
nagios_comment *temp_comment;
scheduled_downtime *temp_downtime;
servicegroup *temp_servicegroup = NULL;
contact *temp_contact = NULL;
struct nagios_extcmd *ecmd = extcmd_get_command_id(cmd);
/* get authentication information */
get_authentication_information(¤t_authdata);
/* get name to use for author */
if(lock_author_names == TRUE) {
temp_contact = find_contact(current_authdata.username);
if(temp_contact != NULL && temp_contact->alias != NULL) {
comment_author = temp_contact->alias;
}
else {
comment_author = current_authdata.username;
}
}
if (ecmd->cmt_opt == 2 && *comment_data == '\0') {
if(!error_string) {
error_string = strdup("Comment was not entered");
}
}
clean_comment_data(comment_data);
if (*comment_data != '\0' && *comment_author == '\0') {
if(!error_string) {
error_string = strdup("Author was not entered");
}
}
clean_comment_data(comment_author);
switch(cmd) {
case CMD_ADD_HOST_COMMENT:
case CMD_ACKNOWLEDGE_HOST_PROBLEM:
/* see if the user is authorized to issue a command... */
temp_host = find_host(host_name);
if(is_authorized_for_host_commands(temp_host, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
break;
case CMD_ADD_SVC_COMMENT:
case CMD_ACKNOWLEDGE_SVC_PROBLEM:
/* see if the user is authorized to issue a command... */
temp_service = find_service(host_name, service_desc);
if(is_authorized_for_service_commands(temp_service, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
break;
case CMD_DEL_HOST_COMMENT:
case CMD_DEL_SVC_COMMENT:
/* check the sanity of the comment id */
if(comment_id == 0) {
if(!error_string) {
error_string = strdup("Comment id cannot be 0");
}
}
/* find the comment */
if(cmd == CMD_DEL_HOST_COMMENT) {
temp_comment = find_host_comment(comment_id);
}
else {
temp_comment = find_service_comment(comment_id);
}
/* see if the user is authorized to issue a command... */
if(cmd == CMD_DEL_HOST_COMMENT && temp_comment != NULL) {
temp_host = find_host(temp_comment->host_name);
if(is_authorized_for_host_commands(temp_host, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
}
if(cmd == CMD_DEL_SVC_COMMENT && temp_comment != NULL) {
temp_service = find_service(temp_comment->host_name, temp_comment->service_description);
if(is_authorized_for_service_commands(temp_service, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
}
/* free comment data */
free_comment_data();
break;
case CMD_DEL_HOST_DOWNTIME:
case CMD_DEL_SVC_DOWNTIME:
/* check the sanity of the downtime id */
if(downtime_id == 0) {
if(!error_string) {
error_string = strdup("Downtime id cannot be 0");
}
}
/* find the downtime entry */
if(cmd == CMD_DEL_HOST_DOWNTIME) {
temp_downtime = find_host_downtime(downtime_id);
}
else {
temp_downtime = find_service_downtime(downtime_id);
}
/* see if the user is authorized to issue a command... */
if(cmd == CMD_DEL_HOST_DOWNTIME && temp_downtime != NULL) {
temp_host = find_host(temp_downtime->host_name);
if(is_authorized_for_host_commands(temp_host, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
}
if(cmd == CMD_DEL_SVC_DOWNTIME && temp_downtime != NULL) {
temp_service = find_service(temp_downtime->host_name, temp_downtime->service_description);
if(is_authorized_for_service_commands(temp_service, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
}
/* free downtime data */
free_downtime_data();
break;
case CMD_SCHEDULE_SVC_CHECK:
case CMD_ENABLE_SVC_CHECK:
case CMD_DISABLE_SVC_CHECK:
case CMD_DEL_ALL_SVC_COMMENTS:
case CMD_ENABLE_SVC_NOTIFICATIONS:
case CMD_DISABLE_SVC_NOTIFICATIONS:
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
case CMD_ENABLE_SVC_EVENT_HANDLER:
case CMD_DISABLE_SVC_EVENT_HANDLER:
case CMD_REMOVE_SVC_ACKNOWLEDGEMENT:
case CMD_PROCESS_SERVICE_CHECK_RESULT:
case CMD_SCHEDULE_SVC_DOWNTIME:
case CMD_DELAY_SVC_NOTIFICATION:
case CMD_ENABLE_SVC_FLAP_DETECTION:
case CMD_DISABLE_SVC_FLAP_DETECTION:
case CMD_START_OBSESSING_OVER_SVC:
case CMD_STOP_OBSESSING_OVER_SVC:
case CMD_CLEAR_SVC_FLAPPING_STATE:
/* see if the user is authorized to issue a command... */
temp_service = find_service(host_name, service_desc);
if(is_authorized_for_service_commands(temp_service, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
/* make sure we have passive check info (if necessary) */
if(cmd == CMD_PROCESS_SERVICE_CHECK_RESULT && !strcmp(plugin_output, "")) {
if(!error_string) {
error_string = strdup("Plugin output cannot be blank");
}
}
/* make sure we have a notification delay (if necessary) */
if(cmd == CMD_DELAY_SVC_NOTIFICATION && notification_delay <= 0) {
if(!error_string) {
error_string = strdup("Notification delay must be greater than 0");
}
}
/* make sure we have check time (if necessary) */
if(cmd == CMD_SCHEDULE_SVC_CHECK && start_time == (time_t)0) {
if(!error_string) {
error_string = strdup("Start time must be non-zero or bad format has been submitted.");
}
}
/* make sure we have start/end times for downtime (if necessary) */
if(cmd == CMD_SCHEDULE_SVC_DOWNTIME && (start_time == (time_t)0 || end_time == (time_t)0 || end_time < start_time)) {
if(!error_string) {
error_string = strdup("Start or end time not valid");
}
}
break;
case CMD_ENABLE_NOTIFICATIONS:
case CMD_DISABLE_NOTIFICATIONS:
case CMD_SHUTDOWN_PROCESS:
case CMD_RESTART_PROCESS:
case CMD_START_EXECUTING_SVC_CHECKS:
case CMD_STOP_EXECUTING_SVC_CHECKS:
case CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS:
case CMD_ENABLE_EVENT_HANDLERS:
case CMD_DISABLE_EVENT_HANDLERS:
case CMD_START_OBSESSING_OVER_SVC_CHECKS:
case CMD_STOP_OBSESSING_OVER_SVC_CHECKS:
case CMD_ENABLE_FLAP_DETECTION:
case CMD_DISABLE_FLAP_DETECTION:
case CMD_ENABLE_PERFORMANCE_DATA:
case CMD_DISABLE_PERFORMANCE_DATA:
case CMD_START_EXECUTING_HOST_CHECKS:
case CMD_STOP_EXECUTING_HOST_CHECKS:
case CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS:
case CMD_START_OBSESSING_OVER_HOST_CHECKS:
case CMD_STOP_OBSESSING_OVER_HOST_CHECKS:
/* see if the user is authorized to issue a command... */
if(is_authorized_for_system_commands(¤t_authdata) == TRUE) {
authorized = TRUE;
}
break;
case CMD_ENABLE_HOST_SVC_CHECKS:
case CMD_DISABLE_HOST_SVC_CHECKS:
case CMD_DEL_ALL_HOST_COMMENTS:
case CMD_SCHEDULE_HOST_SVC_CHECKS:
case CMD_ENABLE_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOST_NOTIFICATIONS:
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
case CMD_ENABLE_HOST_EVENT_HANDLER:
case CMD_DISABLE_HOST_EVENT_HANDLER:
case CMD_ENABLE_HOST_CHECK:
case CMD_DISABLE_HOST_CHECK:
case CMD_REMOVE_HOST_ACKNOWLEDGEMENT:
case CMD_SCHEDULE_HOST_DOWNTIME:
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
case CMD_DELAY_HOST_NOTIFICATION:
case CMD_ENABLE_HOST_FLAP_DETECTION:
case CMD_DISABLE_HOST_FLAP_DETECTION:
case CMD_PROCESS_HOST_CHECK_RESULT:
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
case CMD_SCHEDULE_HOST_CHECK:
case CMD_START_OBSESSING_OVER_HOST:
case CMD_STOP_OBSESSING_OVER_HOST:
case CMD_CLEAR_HOST_FLAPPING_STATE:
/* see if the user is authorized to issue a command... */
temp_host = find_host(host_name);
if(is_authorized_for_host_commands(temp_host, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
/* make sure we have a notification delay (if necessary) */
if(cmd == CMD_DELAY_HOST_NOTIFICATION && notification_delay <= 0) {
if(!error_string) {
error_string = strdup("Notification delay must be greater than 0");
}
}
/* make sure we have start/end times for downtime (if necessary) */
if((cmd == CMD_SCHEDULE_HOST_DOWNTIME || cmd == CMD_SCHEDULE_HOST_SVC_DOWNTIME) && (start_time == (time_t)0 || end_time == (time_t)0 || start_time > end_time)) {
if(!error_string) {
error_string = strdup("Start or end time not valid");
}
}
/* make sure we have check time (if necessary) */
if((cmd == CMD_SCHEDULE_HOST_CHECK || cmd == CMD_SCHEDULE_HOST_SVC_CHECKS) && start_time == (time_t)0) {
if(!error_string) {
error_string = strdup("Start time must be non-zero or bad format has been submitted.");
}
}
/* make sure we have passive check info (if necessary) */
if(cmd == CMD_PROCESS_HOST_CHECK_RESULT && !strcmp(plugin_output, "")) {
if(!error_string) {
error_string = strdup("Plugin output cannot be blank");
}
}
break;
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
/* make sure we have start/end times for downtime */
if((cmd == CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME) && (start_time == (time_t)0 || end_time == (time_t)0 || start_time > end_time)) {
if(!error_string) {
error_string = strdup("Start or end time not valid");
}
}
/* see if the user is authorized to issue a command... */
temp_hostgroup = find_hostgroup(hostgroup_name);
if(is_authorized_for_hostgroup_commands(temp_hostgroup, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
break;
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
/* make sure we have start/end times for downtime */
if((cmd == CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME || cmd == CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME) && (start_time == (time_t)0 || end_time == (time_t)0 || start_time > end_time)) {
if(!error_string) {
error_string = strdup("Start or end time not valid");
}
}
/* see if the user is authorized to issue a command... */
temp_servicegroup = find_servicegroup(servicegroup_name);
if(is_authorized_for_servicegroup_commands(temp_servicegroup, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
break;
case CMD_SEND_CUSTOM_HOST_NOTIFICATION:
case CMD_SEND_CUSTOM_SVC_NOTIFICATION:
/* see if the user is authorized to issue a command... */
if(cmd == CMD_SEND_CUSTOM_HOST_NOTIFICATION) {
temp_host = find_host(host_name);
if(is_authorized_for_host_commands(temp_host, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
}
else {
temp_service = find_service(host_name, service_desc);
if(is_authorized_for_service_commands(temp_service, ¤t_authdata) == TRUE) {
authorized = TRUE;
}
}
break;
default:
if(!error_string) {
error_string = strdup("An error occurred while processing your command!");
}
}
/* to be safe, we are going to REQUIRE that the authentication functionality is enabled... */
if(use_authentication == FALSE) {
if(content_type == WML_CONTENT) {
printf("
Error: Authentication is not enabled!
\n");
}
else {
printf("
\n");
printf("
Sorry Dave, I can't let you do that...
");
printf("
");
printf("It seems that you have chosen to not use the authentication functionality of the CGIs.
");
printf("I don't want to be personally responsible for what may happen as a result of allowing unauthorized users to issue commands to Nagios,");
printf("so you'll have to disable this safeguard if you are really stubborn and want to invite trouble.
");
printf("Read the section on CGI authentication in the HTML documentation to learn how you can enable authentication and why you should want to.\n");
printf("
\n");
printf("\n");
}
}
/* the user is not authorized to issue the given command */
else if(authorized == FALSE) {
if(content_type == WML_CONTENT) {
printf("
Error: You're not authorized to commit that command!
\n");
}
else {
printf("
Sorry, but you are not authorized to commit the specified command.
\n");
printf("
Read the section of the documentation that deals with authentication and authorization in the CGIs for more information.
\n");
}
}
}
my_free(error_string);
}
__attribute__((format(printf, 2, 3)))
static int cmd_submitf(int id, const char *fmt, ...) {
char cmd[MAX_EXTERNAL_COMMAND_LENGTH];
const char *command_name;
int len;
int len2;
va_list ap;
command_name = extcmd_get_name(id);
/*
* We disallow sending 'CHANGE' commands from the cgi's
* until we do proper session handling to prevent cross-site
* request forgery
*/
if(!command_name || (strlen(command_name) > 6 && !memcmp("CHANGE", command_name, 6)))
return ERROR;
len = snprintf(cmd, sizeof(cmd), "[%lu] %s;", time(NULL), command_name);
if(len < 0 || len >= sizeof(cmd))
return ERROR;
if(fmt) {
va_start(ap, fmt);
len2 = vsnprintf(cmd + len, sizeof(cmd) - len, fmt, ap);
va_end(ap);
len += len2;
if(len2 < 0 || len >= sizeof(cmd))
return ERROR;
}
if (*comment_data != '\0') {
len2 = snprintf(cmd + len, sizeof(cmd) - len, ";%s;%s", comment_author, comment_data);
len += len2;
if(len2 < 0 || len >= sizeof(cmd))
return ERROR;
}
cmd[len] = 0; /* 0 <= len < sizeof(cmd) */
return write_command_to_file(cmd);
}
/* commits a command for processing */
int commit_command(int cmd) {
time_t current_time;
time_t scheduled_time;
time_t notification_time;
int result;
/* get the current time */
time(¤t_time);
/* get the scheduled time */
scheduled_time = current_time + (schedule_delay * 60);
/* get the notification time */
notification_time = current_time + (notification_delay * 60);
/*
* these are supposed to be implanted inside the
* completed commands shipped off to nagios and
* must therefore never contain ';'
*/
if(host_name && strchr(host_name, ';'))
return ERROR;
if(service_desc && strchr(service_desc, ';'))
return ERROR;
if(comment_author && strchr(comment_author, ';'))
return ERROR;
if(hostgroup_name && strchr(hostgroup_name, ';'))
return ERROR;
if(servicegroup_name && strchr(servicegroup_name, ';'))
return ERROR;
/* decide how to form the command line... */
switch(cmd) {
/* commands without arguments */
case CMD_START_EXECUTING_SVC_CHECKS:
case CMD_STOP_EXECUTING_SVC_CHECKS:
case CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS:
case CMD_ENABLE_EVENT_HANDLERS:
case CMD_DISABLE_EVENT_HANDLERS:
case CMD_START_OBSESSING_OVER_SVC_CHECKS:
case CMD_STOP_OBSESSING_OVER_SVC_CHECKS:
case CMD_ENABLE_FLAP_DETECTION:
case CMD_DISABLE_FLAP_DETECTION:
case CMD_ENABLE_PERFORMANCE_DATA:
case CMD_DISABLE_PERFORMANCE_DATA:
case CMD_START_EXECUTING_HOST_CHECKS:
case CMD_STOP_EXECUTING_HOST_CHECKS:
case CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS:
case CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS:
case CMD_START_OBSESSING_OVER_HOST_CHECKS:
case CMD_STOP_OBSESSING_OVER_HOST_CHECKS:
result = cmd_submitf(cmd, NULL);
break;
/** simple host commands **/
case CMD_ENABLE_HOST_FLAP_DETECTION:
case CMD_DISABLE_HOST_FLAP_DETECTION:
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
case CMD_START_OBSESSING_OVER_HOST:
case CMD_STOP_OBSESSING_OVER_HOST:
case CMD_DEL_ALL_HOST_COMMENTS:
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
case CMD_ENABLE_HOST_EVENT_HANDLER:
case CMD_DISABLE_HOST_EVENT_HANDLER:
case CMD_ENABLE_HOST_CHECK:
case CMD_DISABLE_HOST_CHECK:
case CMD_REMOVE_HOST_ACKNOWLEDGEMENT:
case CMD_CLEAR_HOST_FLAPPING_STATE:
result = cmd_submitf(cmd, "%s", host_name);
break;
/** simple service commands **/
case CMD_ENABLE_SVC_FLAP_DETECTION:
case CMD_DISABLE_SVC_FLAP_DETECTION:
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
case CMD_START_OBSESSING_OVER_SVC:
case CMD_STOP_OBSESSING_OVER_SVC:
case CMD_DEL_ALL_SVC_COMMENTS:
case CMD_ENABLE_SVC_NOTIFICATIONS:
case CMD_DISABLE_SVC_NOTIFICATIONS:
case CMD_ENABLE_SVC_EVENT_HANDLER:
case CMD_DISABLE_SVC_EVENT_HANDLER:
case CMD_ENABLE_SVC_CHECK:
case CMD_DISABLE_SVC_CHECK:
case CMD_REMOVE_SVC_ACKNOWLEDGEMENT:
case CMD_CLEAR_SVC_FLAPPING_STATE:
result = cmd_submitf(cmd, "%s;%s", host_name, service_desc);
break;
case CMD_ADD_HOST_COMMENT:
result = cmd_submitf(cmd, "%s;%d", host_name, persistent_comment);
break;
case CMD_ADD_SVC_COMMENT:
result = cmd_submitf(cmd, "%s;%s;%d", host_name, service_desc, persistent_comment);
break;
case CMD_DEL_HOST_COMMENT:
case CMD_DEL_SVC_COMMENT:
result = cmd_submitf(cmd, "%lu", comment_id);
break;
case CMD_DELAY_HOST_NOTIFICATION:
result = cmd_submitf(cmd, "%s;%lu", host_name, notification_time);
break;
case CMD_DELAY_SVC_NOTIFICATION:
result = cmd_submitf(cmd, "%s;%s;%lu", host_name, service_desc, notification_time);
break;
case CMD_SCHEDULE_SVC_CHECK:
case CMD_SCHEDULE_FORCED_SVC_CHECK:
if(force_check == TRUE)
cmd = CMD_SCHEDULE_FORCED_SVC_CHECK;
result = cmd_submitf(cmd, "%s;%s;%lu", host_name, service_desc, start_time);
break;
case CMD_DISABLE_NOTIFICATIONS:
case CMD_ENABLE_NOTIFICATIONS:
case CMD_SHUTDOWN_PROCESS:
case CMD_RESTART_PROCESS:
result = cmd_submitf(cmd, "%lu", scheduled_time);
break;
case CMD_ENABLE_HOST_SVC_CHECKS:
case CMD_DISABLE_HOST_SVC_CHECKS:
result = cmd_submitf(cmd, "%s", host_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_HOST_SVC_CHECKS) ? CMD_ENABLE_HOST_CHECK : CMD_DISABLE_HOST_CHECK;
result |= cmd_submitf(cmd, "%s", host_name);
}
break;
case CMD_SCHEDULE_HOST_SVC_CHECKS:
if(force_check == TRUE)
cmd = CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS;
result = cmd_submitf(cmd, "%s;%lu", host_name, scheduled_time);
break;
case CMD_ENABLE_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOST_NOTIFICATIONS:
if(propagate_to_children == TRUE)
cmd = (cmd == CMD_ENABLE_HOST_NOTIFICATIONS) ? CMD_ENABLE_HOST_AND_CHILD_NOTIFICATIONS : CMD_DISABLE_HOST_AND_CHILD_NOTIFICATIONS;
result = cmd_submitf(cmd, "%s", host_name);
break;
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
result = cmd_submitf(cmd, "%s", host_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_HOST_SVC_NOTIFICATIONS) ? CMD_ENABLE_HOST_NOTIFICATIONS : CMD_DISABLE_HOST_NOTIFICATIONS;
result |= cmd_submitf(cmd, "%s", host_name);
}
break;
case CMD_ACKNOWLEDGE_HOST_PROBLEM:
result = cmd_submitf(cmd, "%s;%d;%d;%d", host_name, (sticky_ack == TRUE) ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL, send_notification, persistent_comment);
break;
case CMD_ACKNOWLEDGE_SVC_PROBLEM:
result = cmd_submitf(cmd, "%s;%s;%d;%d;%d", host_name, service_desc, (sticky_ack == TRUE) ? ACKNOWLEDGEMENT_STICKY : ACKNOWLEDGEMENT_NORMAL, send_notification, persistent_comment);
break;
case CMD_PROCESS_SERVICE_CHECK_RESULT:
result = cmd_submitf(cmd, "%s;%s;%d;%s|%s", host_name, service_desc, plugin_state, plugin_output, performance_data);
break;
case CMD_PROCESS_HOST_CHECK_RESULT:
result = cmd_submitf(cmd, "%s;%d;%s|%s", host_name, plugin_state, plugin_output, performance_data);
break;
case CMD_SCHEDULE_HOST_DOWNTIME:
if(child_options == 1)
cmd = CMD_SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME;
else if(child_options == 2)
cmd = CMD_SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME;
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;%lu;%lu", host_name, start_time, end_time, fixed, triggered_by, duration);
break;
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;%lu;%lu", host_name, start_time, end_time, fixed, triggered_by, duration);
break;
case CMD_SCHEDULE_SVC_DOWNTIME:
result = cmd_submitf(cmd, "%s;%s;%lu;%lu;%d;%lu;%lu", host_name, service_desc, start_time, end_time, fixed, triggered_by, duration);
break;
case CMD_DEL_HOST_DOWNTIME:
case CMD_DEL_SVC_DOWNTIME:
result = cmd_submitf(cmd, "%lu", downtime_id);
break;
case CMD_SCHEDULE_HOST_CHECK:
if(force_check == TRUE)
cmd = CMD_SCHEDULE_FORCED_HOST_CHECK;
result = cmd_submitf(cmd, "%s;%lu", host_name, start_time);
break;
case CMD_SEND_CUSTOM_HOST_NOTIFICATION:
result = cmd_submitf(cmd, "%s;%d", host_name, (force_notification | broadcast_notification));
break;
case CMD_SEND_CUSTOM_SVC_NOTIFICATION:
result = cmd_submitf(cmd, "%s;%s;%d", host_name, service_desc, (force_notification | broadcast_notification));
break;
/***** HOSTGROUP COMMANDS *****/
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
result = cmd_submitf(cmd, "%s", hostgroup_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS) ? CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS : CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS;
result |= cmd_submitf(cmd, "%s", hostgroup_name);
}
break;
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
result = cmd_submitf(cmd, "%s", hostgroup_name);
break;
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
result = cmd_submitf(cmd, "%s", hostgroup_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_HOSTGROUP_SVC_CHECKS) ? CMD_ENABLE_HOSTGROUP_HOST_CHECKS : CMD_DISABLE_HOSTGROUP_HOST_CHECKS;
result |= cmd_submitf(cmd, "%s", hostgroup_name);
}
break;
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;0;%lu", hostgroup_name, start_time, end_time, fixed, duration);
break;
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;0;%lu", hostgroup_name, start_time, end_time, fixed, duration);
if(affect_host_and_services == TRUE)
result |= cmd_submitf(CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME, "%s;%lu;%lu;%d;0;%lu", hostgroup_name, start_time, end_time, fixed, duration);
break;
/***** SERVICEGROUP COMMANDS *****/
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
result = cmd_submitf(cmd, "%s", servicegroup_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS) ? CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS : CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS;
result |= cmd_submitf(cmd, "%s", servicegroup_name);
}
break;
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
result = cmd_submitf(cmd, "%s", servicegroup_name);
break;
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
result = cmd_submitf(cmd, "%s", servicegroup_name);
if(affect_host_and_services == TRUE) {
cmd = (cmd == CMD_ENABLE_SERVICEGROUP_SVC_CHECKS) ? CMD_ENABLE_SERVICEGROUP_HOST_CHECKS : CMD_DISABLE_SERVICEGROUP_HOST_CHECKS;
result |= cmd_submitf(cmd, "%s", servicegroup_name);
}
break;
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;0;%lu", servicegroup_name, start_time, end_time, fixed, duration);
break;
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
result = cmd_submitf(cmd, "%s;%lu;%lu;%d;0;%lu", servicegroup_name, start_time, end_time, fixed, duration);
if(affect_host_and_services == TRUE)
result |= cmd_submitf(CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME, "%s;%lu;%lu;%d;0;%lu", servicegroup_name, start_time, end_time, fixed, duration);
break;
default:
return ERROR;
break;
}
return result;
}
/* write a command entry to the command file */
int write_command_to_file(char *cmd) {
FILE *fp;
struct stat statbuf;
/*
* Commands are not allowed to have newlines in them, as
* that allows malicious users to hand-craft requests that
* bypass the access-restrictions.
*/
if(!cmd || !*cmd || strchr(cmd, '\n'))
return ERROR;
/* bail out if the external command file doesn't exist */
if(stat(command_file, &statbuf)) {
if(content_type == WML_CONTENT)
printf("
Error: Could not stat() external command file!
\n");
else {
printf("
Error: Could not stat() command file '%s'!
\n", command_file);
printf("
");
printf("The external command file may be missing, Nagios may not be running, and/or Nagios may not be checking external commands.\n");
printf("
\n");
}
return ERROR;
}
/* open the command for writing (since this is a pipe, it will really be appended) */
fp = fopen(command_file, "w");
if(fp == NULL) {
if(content_type == WML_CONTENT)
printf("
Error: Could not open command file for update!
\n");
else {
printf("
Error: Could not open command file '%s' for update!
\n", command_file);
printf("
");
printf("The permissions on the external command file and/or directory may be incorrect. Read the FAQs on how to setup proper permissions.\n");
printf("
\n");
}
return ERROR;
}
/* write the command to file */
fprintf(fp, "%s\n", cmd);
/* flush buffer */
fflush(fp);
fclose(fp);
return OK;
}
/* strips out semicolons from comment data */
void clean_comment_data(char *buffer) {
int x;
int y;
if (!buffer || !*buffer)
return;
y = (int)strlen(buffer);
for(x = 0; x < y; x++) {
if(buffer[x] == ';')
buffer[x] = ' ';
}
return;
}
/* display information about a command */
void show_command_help(int cmd) {
printf("
Command Description
\n");
printf("
\n");
printf("
\n");
/* decide what information to print out... */
switch(cmd) {
case CMD_ADD_HOST_COMMENT:
printf("This command is used to add a comment for the specified host. If you work with other administrators, you may find it useful to share information about a host\n");
printf("that is having problems if more than one of you may be working on it. If you do not check the 'persistent' option, the comment will be automatically be deleted\n");
printf("the next time Nagios is restarted.\n");
break;
case CMD_ADD_SVC_COMMENT:
printf("This command is used to add a comment for the specified service. If you work with other administrators, you may find it useful to share information about a host\n");
printf("or service that is having problems if more than one of you may be working on it. If you do not check the 'persistent' option, the comment will automatically be\n");
printf("deleted the next time Nagios is restarted.\n");
break;
case CMD_DEL_HOST_COMMENT:
printf("This command is used to delete a specific host comment.\n");
break;
case CMD_DEL_SVC_COMMENT:
printf("This command is used to delete a specific service comment.\n");
break;
case CMD_DELAY_HOST_NOTIFICATION:
printf("This command is used to delay the next problem notification that is sent out for the specified host. The notification delay will be disregarded if\n");
printf("the host changes state before the next notification is scheduled to be sent out. This command has no effect if the host is currently UP.\n");
break;
case CMD_DELAY_SVC_NOTIFICATION:
printf("This command is used to delay the next problem notification that is sent out for the specified service. The notification delay will be disregarded if\n");
printf("the service changes state before the next notification is scheduled to be sent out. This command has no effect if the service is currently in an OK state.\n");
break;
case CMD_SCHEDULE_SVC_CHECK:
printf("This command is used to schedule the next check of a particular service. Nagios will re-queue the service to be checked at the time you specify.\n");
printf("If you select the force check option, Nagios will force a check of the service regardless of both what time the scheduled check occurs and whether or not checks are enabled for the service.\n");
break;
case CMD_ENABLE_SVC_CHECK:
printf("This command is used to enable active checks of a service.\n");
break;
case CMD_DISABLE_SVC_CHECK:
printf("This command is used to disable active checks of a service.\n");
break;
case CMD_DISABLE_NOTIFICATIONS:
printf("This command is used to disable host and service notifications on a program-wide basis.\n");
break;
case CMD_ENABLE_NOTIFICATIONS:
printf("This command is used to enable host and service notifications on a program-wide basis.\n");
break;
case CMD_SHUTDOWN_PROCESS:
printf("This command is used to shutdown the Nagios process. Note: Once the Nagios has been shutdown, it cannot be restarted via the web interface!\n");
break;
case CMD_RESTART_PROCESS:
printf("This command is used to restart the Nagios process. Executing a restart command is equivalent to sending the process a HUP signal.\n");
printf("All information will be flushed from memory, the configuration files will be re-read, and Nagios will start monitoring with the new configuration information.\n");
break;
case CMD_ENABLE_HOST_SVC_CHECKS:
printf("This command is used to enable active checks of all services associated with the specified host. This does not enable checks of the host unless you check the 'Enable for host too' option.\n");
break;
case CMD_DISABLE_HOST_SVC_CHECKS:
printf("This command is used to disable active checks of all services associated with the specified host. When a service is disabled Nagios will not monitor the service. Doing this will prevent any notifications being sent out for\n");
printf("the specified service while it is disabled. In order to have Nagios check the service in the future you will have to re-enable the service.\n");
printf("Note that disabling service checks may not necessarily prevent notifications from being sent out about the host which those services are associated with. This does not disable checks of the host unless you check the 'Disable for host too' option.\n");
break;
case CMD_SCHEDULE_HOST_SVC_CHECKS:
printf("This command is used to scheduled the next check of all services on the specified host. If you select the force check option, Nagios will force a check of all services on the host regardless of both what time the scheduled checks occur and whether or not checks are enabled for those services.\n");
break;
case CMD_DEL_ALL_HOST_COMMENTS:
printf("This command is used to delete all comments associated with the specified host.\n");
break;
case CMD_DEL_ALL_SVC_COMMENTS:
printf("This command is used to delete all comments associated with the specified service.\n");
break;
case CMD_ENABLE_SVC_NOTIFICATIONS:
printf("This command is used to enable notifications for the specified service. Notifications will only be sent out for the\n");
printf("service state types you defined in your service definition.\n");
break;
case CMD_DISABLE_SVC_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for the specified service. You will have to re-enable notifications\n");
printf("for this service before any alerts can be sent out in the future.\n");
break;
case CMD_ENABLE_HOST_NOTIFICATIONS:
printf("This command is used to enable notifications for the specified host. Notifications will only be sent out for the\n");
printf("host state types you defined in your host definition. Note that this command does not enable notifications\n");
printf("for services associated with this host.\n");
break;
case CMD_DISABLE_HOST_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for the specified host. You will have to re-enable notifications for this host\n");
printf("before any alerts can be sent out in the future. Note that this command does not disable notifications for services associated with this host.\n");
break;
case CMD_ENABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
printf("This command is used to enable notifications for all hosts and services that lie \"beyond\" the specified host\n");
printf("(from the view of Nagios).\n");
break;
case CMD_DISABLE_ALL_NOTIFICATIONS_BEYOND_HOST:
printf("This command is used to temporarily prevent notifications from being sent out for all hosts and services that lie\n");
printf("\"beyond\" the specified host (from the view of Nagios).\n");
break;
case CMD_ENABLE_HOST_SVC_NOTIFICATIONS:
printf("This command is used to enable notifications for all services on the specified host. Notifications will only be sent out for the\n");
printf("service state types you defined in your service definition. This does not enable notifications for the host unless you check the 'Enable for host too' option.\n");
break;
case CMD_DISABLE_HOST_SVC_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for all services on the specified host. You will have to re-enable notifications for\n");
printf("all services associated with this host before any alerts can be sent out in the future. This does not prevent notifications from being sent out about the host unless you check the 'Disable for host too' option.\n");
break;
case CMD_ACKNOWLEDGE_HOST_PROBLEM:
printf("This command is used to acknowledge a host problem. When a host problem is acknowledged, future notifications about problems are temporarily disabled until the host changes from its current state.\n");
printf("If you want acknowledgement to disable notifications until the host recovers, check the 'Sticky Acknowledgement' checkbox.\n");
printf("Contacts for this host will receive a notification about the acknowledgement, so they are aware that someone is working on the problem. Additionally, a comment will also be added to the host.\n");
printf("Make sure to enter your name and fill in a brief description of what you are doing in the comment field. If you would like the host comment to remain once the acknowledgement is removed, check\n");
printf("the 'Persistent Comment' checkbox. If you do not want an acknowledgement notification sent out to the appropriate contacts, uncheck the 'Send Notification' checkbox.\n");
break;
case CMD_ACKNOWLEDGE_SVC_PROBLEM:
printf("This command is used to acknowledge a service problem. When a service problem is acknowledged, future notifications about problems are temporarily disabled until the service changes from its current state.\n");
printf("If you want acknowledgement to disable notifications until the service recovers, check the 'Sticky Acknowledgement' checkbox.\n");
printf("Contacts for this service will receive a notification about the acknowledgement, so they are aware that someone is working on the problem. Additionally, a comment will also be added to the service.\n");
printf("Make sure to enter your name and fill in a brief description of what you are doing in the comment field. If you would like the service comment to remain once the acknowledgement is removed, check\n");
printf("the 'Persistent Comment' checkbox. If you do not want an acknowledgement notification sent out to the appropriate contacts, uncheck the 'Send Notification' checkbox.\n");
break;
case CMD_START_EXECUTING_SVC_CHECKS:
printf("This command is used to resume execution of active service checks on a program-wide basis. Individual services which are disabled will still not be checked.\n");
break;
case CMD_STOP_EXECUTING_SVC_CHECKS:
printf("This command is used to temporarily stop Nagios from actively executing any service checks. This will have the side effect of preventing any notifications from being sent out (for any and all services and hosts).\n");
printf("Service checks will not be executed again until you issue a command to resume service check execution.\n");
break;
case CMD_START_ACCEPTING_PASSIVE_SVC_CHECKS:
printf("This command is used to make Nagios start accepting passive service check results that it finds in the external command file\n");
break;
case CMD_STOP_ACCEPTING_PASSIVE_SVC_CHECKS:
printf("This command is use to make Nagios stop accepting passive service check results that it finds in the external command file. All passive check results that are found will be ignored.\n");
break;
case CMD_ENABLE_PASSIVE_SVC_CHECKS:
printf("This command is used to allow Nagios to accept passive service check results that it finds in the external command file for this particular service.\n");
break;
case CMD_DISABLE_PASSIVE_SVC_CHECKS:
printf("This command is used to stop Nagios accepting passive service check results that it finds in the external command file for this particular service. All passive check results that are found for this service will be ignored.\n");
break;
case CMD_ENABLE_EVENT_HANDLERS:
printf("This command is used to allow Nagios to run host and service event handlers.\n");
break;
case CMD_DISABLE_EVENT_HANDLERS:
printf("This command is used to temporarily prevent Nagios from running any host or service event handlers.\n");
break;
case CMD_ENABLE_SVC_EVENT_HANDLER:
printf("This command is used to allow Nagios to run the service event handler for a particular service when necessary (if one is defined).\n");
break;
case CMD_DISABLE_SVC_EVENT_HANDLER:
printf("This command is used to temporarily prevent Nagios from running the service event handler for a particular service.\n");
break;
case CMD_ENABLE_HOST_EVENT_HANDLER:
printf("This command is used to allow Nagios to run the host event handler for a particular service when necessary (if one is defined).\n");
break;
case CMD_DISABLE_HOST_EVENT_HANDLER:
printf("This command is used to temporarily prevent Nagios from running the host event handler for a particular host.\n");
break;
case CMD_ENABLE_HOST_CHECK:
printf("This command is used to enable active checks of this host.\n");
break;
case CMD_DISABLE_HOST_CHECK:
printf("This command is used to temporarily prevent Nagios from actively checking the status of a particular host. If Nagios needs to check the status of this host, it will assume that it is in the same state that it was in before checks were disabled.\n");
break;
case CMD_START_OBSESSING_OVER_SVC_CHECKS:
printf("This command is used to have Nagios start obsessing over service checks. Read the documentation on distributed monitoring for more information on this.\n");
break;
case CMD_STOP_OBSESSING_OVER_SVC_CHECKS:
printf("This command is used stop Nagios from obsessing over service checks.\n");
break;
case CMD_REMOVE_HOST_ACKNOWLEDGEMENT:
printf("This command is used to remove an acknowledgement for a particular host problem. Once the acknowledgement is removed, notifications may start being\n");
printf("sent out about the host problem. \n");
break;
case CMD_REMOVE_SVC_ACKNOWLEDGEMENT:
printf("This command is used to remove an acknowledgement for a particular service problem. Once the acknowledgement is removed, notifications may start being\n");
printf("sent out about the service problem.\n");
break;
case CMD_PROCESS_SERVICE_CHECK_RESULT:
printf("This command is used to submit a passive check result for a particular service. It is particularly useful for resetting security-related services to OK states once they have been dealt with.\n");
break;
case CMD_PROCESS_HOST_CHECK_RESULT:
printf("This command is used to submit a passive check result for a particular host.\n");
break;
case CMD_SCHEDULE_HOST_DOWNTIME:
printf("This command is used to schedule downtime for a particular host. During the specified downtime, Nagios will not send notifications out about the host.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for this host as it normally would. Scheduled downtimes are preserved\n");
printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n");
printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n");
printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when the host goes down or becomes unreachable (sometime between the\n");
printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n");
break;
case CMD_SCHEDULE_HOST_SVC_DOWNTIME:
printf("This command is used to schedule downtime for all services on a particular host. During the specified downtime, Nagios will not send notifications out about the host.\n");
printf("Normally, a host in downtime will not send alerts about any services in a failed state. This option will explicitly set downtime for all services for this host.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for this host as it normally would. Scheduled downtimes are preserved\n");
printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n");
printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n");
printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when the host goes down or becomes unreachable (sometime between the\n");
printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n");
break;
case CMD_SCHEDULE_SVC_DOWNTIME:
printf("This command is used to schedule downtime for a particular service. During the specified downtime, Nagios will not send notifications out about the service.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for this service as it normally would. Scheduled downtimes are preserved\n");
printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n");
printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n");
printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when the service enters a non-OK state (sometime between the\n");
printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n");
break;
case CMD_ENABLE_HOST_FLAP_DETECTION:
printf("This command is used to enable flap detection for a specific host. If flap detection is disabled on a program-wide basis, this will have no effect,\n");
break;
case CMD_DISABLE_HOST_FLAP_DETECTION:
printf("This command is used to disable flap detection for a specific host.\n");
break;
case CMD_ENABLE_SVC_FLAP_DETECTION:
printf("This command is used to enable flap detection for a specific service. If flap detection is disabled on a program-wide basis, this will have no effect,\n");
break;
case CMD_DISABLE_SVC_FLAP_DETECTION:
printf("This command is used to disable flap detection for a specific service.\n");
break;
case CMD_ENABLE_FLAP_DETECTION:
printf("This command is used to enable flap detection for hosts and services on a program-wide basis. Individual hosts and services may have flap detection disabled.\n");
break;
case CMD_DISABLE_FLAP_DETECTION:
printf("This command is used to disable flap detection for hosts and services on a program-wide basis.\n");
break;
case CMD_ENABLE_HOSTGROUP_SVC_NOTIFICATIONS:
printf("This command is used to enable notifications for all services in the specified hostgroup. Notifications will only be sent out for the\n");
printf("service state types you defined in your service definitions. This does not enable notifications for the hosts in this hostgroup unless you check the 'Enable for hosts too' option.\n");
break;
case CMD_DISABLE_HOSTGROUP_SVC_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for all services in the specified hostgroup. You will have to re-enable notifications for\n");
printf("all services in this hostgroup before any alerts can be sent out in the future. This does not prevent notifications from being sent out about the hosts in this hostgroup unless you check the 'Disable for hosts too' option.\n");
break;
case CMD_ENABLE_HOSTGROUP_HOST_NOTIFICATIONS:
printf("This command is used to enable notifications for all hosts in the specified hostgroup. Notifications will only be sent out for the\n");
printf("host state types you defined in your host definitions.\n");
break;
case CMD_DISABLE_HOSTGROUP_HOST_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for all hosts in the specified hostgroup. You will have to re-enable notifications for\n");
printf("all hosts in this hostgroup before any alerts can be sent out in the future.\n");
break;
case CMD_ENABLE_HOSTGROUP_SVC_CHECKS:
printf("This command is used to enable active checks of all services in the specified hostgroup. This does not enable active checks of the hosts in the hostgroup unless you check the 'Enable for hosts too' option.\n");
break;
case CMD_DISABLE_HOSTGROUP_SVC_CHECKS:
printf("This command is used to disable active checks of all services in the specified hostgroup. This does not disable checks of the hosts in the hostgroup unless you check the 'Disable for hosts too' option.\n");
break;
case CMD_DEL_HOST_DOWNTIME:
printf("This command is used to cancel active or pending scheduled downtime for the specified host.\n");
break;
case CMD_DEL_SVC_DOWNTIME:
printf("This command is used to cancel active or pending scheduled downtime for the specified service.\n");
break;
case CMD_ENABLE_PERFORMANCE_DATA:
printf("This command is used to enable the processing of performance data for hosts and services on a program-wide basis. Individual hosts and services may have performance data processing disabled.\n");
break;
case CMD_DISABLE_PERFORMANCE_DATA:
printf("This command is used to disable the processing of performance data for hosts and services on a program-wide basis.\n");
break;
case CMD_SCHEDULE_HOSTGROUP_HOST_DOWNTIME:
printf("This command is used to schedule downtime for all hosts in a particular hostgroup. During the specified downtime, Nagios will not send notifications out about the hosts.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for the hosts as it normally would. Scheduled downtimes are preserved\n");
printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n");
printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n");
printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when a host goes down or becomes unreachable (sometime between the\n");
printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n");
break;
case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME:
printf("This command is used to schedule downtime for all services in a particular hostgroup. During the specified downtime, Nagios will not send notifications out about the services.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for the services as it normally would. Scheduled downtimes are preserved\n");
printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n");
printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n");
printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when a service enters a non-OK state (sometime between the\n");
printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n");
printf("Note that scheduling downtime for services does not automatically schedule downtime for the hosts those services are associated with. If you want to also schedule downtime for all hosts in the hostgroup, check the 'Schedule downtime for hosts too' option.\n");
break;
case CMD_START_EXECUTING_HOST_CHECKS:
printf("This command is used to enable active host checks on a program-wide basis.\n");
break;
case CMD_STOP_EXECUTING_HOST_CHECKS:
printf("This command is used to disable active host checks on a program-wide basis.\n");
break;
case CMD_START_ACCEPTING_PASSIVE_HOST_CHECKS:
printf("This command is used to have Nagios start obsessing over host checks. Read the documentation on distributed monitoring for more information on this.\n");
break;
case CMD_STOP_ACCEPTING_PASSIVE_HOST_CHECKS:
printf("This command is used to stop Nagios from obsessing over host checks.\n");
break;
case CMD_ENABLE_PASSIVE_HOST_CHECKS:
printf("This command is used to allow Nagios to accept passive host check results that it finds in the external command file for a particular host.\n");
break;
case CMD_DISABLE_PASSIVE_HOST_CHECKS:
printf("This command is used to stop Nagios from accepting passive host check results that it finds in the external command file for a particular host. All passive check results that are found for this host will be ignored.\n");
break;
case CMD_START_OBSESSING_OVER_HOST_CHECKS:
printf("This command is used to have Nagios start obsessing over host checks. Read the documentation on distributed monitoring for more information on this.\n");
break;
case CMD_STOP_OBSESSING_OVER_HOST_CHECKS:
printf("This command is used to stop Nagios from obsessing over host checks.\n");
break;
case CMD_SCHEDULE_HOST_CHECK:
printf("This command is used to schedule the next check of a particular host. Nagios will re-queue the host to be checked at the time you specify.\n");
printf("If you select the force check option, Nagios will force a check of the host regardless of both what time the scheduled check occurs and whether or not checks are enabled for the host.\n");
break;
case CMD_START_OBSESSING_OVER_SVC:
printf("This command is used to have Nagios start obsessing over a particular service.\n");
break;
case CMD_STOP_OBSESSING_OVER_SVC:
printf("This command is used to stop Nagios from obsessing over a particular service.\n");
break;
case CMD_START_OBSESSING_OVER_HOST:
printf("This command is used to have Nagios start obsessing over a particular host.\n");
break;
case CMD_STOP_OBSESSING_OVER_HOST:
printf("This command is used to stop Nagios from obsessing over a particular host.\n");
break;
case CMD_ENABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
printf("This command is used to enable notifications for all services in the specified servicegroup. Notifications will only be sent out for the\n");
printf("service state types you defined in your service definitions. This does not enable notifications for the hosts in this servicegroup unless you check the 'Enable for hosts too' option.\n");
break;
case CMD_DISABLE_SERVICEGROUP_SVC_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for all services in the specified servicegroup. You will have to re-enable notifications for\n");
printf("all services in this servicegroup before any alerts can be sent out in the future. This does not prevent notifications from being sent out about the hosts in this servicegroup unless you check the 'Disable for hosts too' option.\n");
break;
case CMD_ENABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
printf("This command is used to enable notifications for all hosts in the specified servicegroup. Notifications will only be sent out for the\n");
printf("host state types you defined in your host definitions.\n");
break;
case CMD_DISABLE_SERVICEGROUP_HOST_NOTIFICATIONS:
printf("This command is used to prevent notifications from being sent out for all hosts in the specified servicegroup. You will have to re-enable notifications for\n");
printf("all hosts in this servicegroup before any alerts can be sent out in the future.\n");
break;
case CMD_ENABLE_SERVICEGROUP_SVC_CHECKS:
printf("This command is used to enable active checks of all services in the specified servicegroup. This does not enable active checks of the hosts in the servicegroup unless you check the 'Enable for hosts too' option.\n");
break;
case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS:
printf("This command is used to disable active checks of all services in the specified servicegroup. This does not disable checks of the hosts in the servicegroup unless you check the 'Disable for hosts too' option.\n");
break;
case CMD_SCHEDULE_SERVICEGROUP_HOST_DOWNTIME:
printf("This command is used to schedule downtime for all hosts in a particular servicegroup. During the specified downtime, Nagios will not send notifications out about the hosts.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for the hosts as it normally would. Scheduled downtimes are preserved\n");
printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n");
printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n");
printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when a host goes down or becomes unreachable (sometime between the\n");
printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n");
break;
case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME:
printf("This command is used to schedule downtime for all services in a particular servicegroup. During the specified downtime, Nagios will not send notifications out about the services.\n");
printf("When the scheduled downtime expires, Nagios will send out notifications for the services as it normally would. Scheduled downtimes are preserved\n");
printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n");
printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n");
printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when a service enters a non-OK state (sometime between the\n");
printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n");
printf("Note that scheduling downtime for services does not automatically schedule downtime for the hosts those services are associated with. If you want to also schedule downtime for all hosts in the servicegroup, check the 'Schedule downtime for hosts too' option.\n");
break;
case CMD_CLEAR_HOST_FLAPPING_STATE:
case CMD_CLEAR_SVC_FLAPPING_STATE:
printf("This command is used to reset the flapping state for the specified %s.\n",
(cmd == CMD_CLEAR_HOST_FLAPPING_STATE) ? "host" : "service");
printf("All state history for the specified %s will be cleared.\n",
(cmd == CMD_CLEAR_HOST_FLAPPING_STATE) ? "host" : "service");
break;
case CMD_SEND_CUSTOM_HOST_NOTIFICATION:
case CMD_SEND_CUSTOM_SVC_NOTIFICATION:
printf("This command is used to send a custom notification about the specified %s. Useful in emergencies when you need to notify admins of an issue regarding a monitored system or service.\n", (cmd == CMD_SEND_CUSTOM_HOST_NOTIFICATION) ? "host" : "service");
printf("Custom notifications normally follow the regular notification logic in Nagios. Selecting the Forced option will force the notification to be sent out, regardless of the time restrictions, whether or not notifications are enabled, etc. Selecting the Broadcast option causes the notification to be sent out to all normal (non-escalated) and escalated contacts. These options allow you to override the normal notification logic if you need to get an important message out.\n");
break;
default:
printf("Sorry, but no information is available for this command.");
}
printf("
\n");
printf("
\n");
return;
}
/* converts a time string to a UNIX timestamp, respecting the date_format option */
int string_to_time(char *buffer, time_t *t) {
struct tm lt;
int ret = 0;
/* Initialize some variables just in case they don't get parsed
by the sscanf() call. A better solution is to also check the
CGI input for validity, but this should suffice to prevent
strange problems if the input is not valid.
Jan 15 2003 Steve Bonds */
lt.tm_mon = 0;
lt.tm_mday = 1;
lt.tm_year = 1900;
lt.tm_hour = 0;
lt.tm_min = 0;
lt.tm_sec = 0;
lt.tm_wday = 0;
lt.tm_yday = 0;
if(date_format == DATE_FORMAT_EURO)
ret = sscanf(buffer, "%02d-%02d-%04d %02d:%02d:%02d", <.tm_mday, <.tm_mon, <.tm_year, <.tm_hour, <.tm_min, <.tm_sec);
else if(date_format == DATE_FORMAT_ISO8601 || date_format == DATE_FORMAT_STRICT_ISO8601)
ret = sscanf(buffer, "%04d-%02d-%02d%*[ T]%02d:%02d:%02d", <.tm_year, <.tm_mon, <.tm_mday, <.tm_hour, <.tm_min, <.tm_sec);
else
ret = sscanf(buffer, "%02d-%02d-%04d %02d:%02d:%02d", <.tm_mon, <.tm_mday, <.tm_year, <.tm_hour, <.tm_min, <.tm_sec);
if(ret != 6)
return ERROR;
lt.tm_mon--;
lt.tm_year -= 1900;
/* tell mktime() to try and compute DST automatically */
lt.tm_isdst = -1;
*t = mktime(<);
return OK;
}
nagios-4.4.6/cgi/config.c 0000664 0000000 0000000 00000255343 13652113235 0015175 0 ustar 00root root 0000000 0000000 /***********************************************************************
*
* CONFIG.C - Nagios Configuration CGI (View Only)
*
*
* This CGI program will display various configuration information.
*
*
* 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/macros.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
#include "../include/getcgi.h"
static nagios_macros *mac;
extern char main_config_file[MAX_FILENAME_LENGTH];
extern char url_html_path[MAX_FILENAME_LENGTH];
extern char url_docs_path[MAX_FILENAME_LENGTH];
extern char url_images_path[MAX_FILENAME_LENGTH];
extern char url_logo_images_path[MAX_FILENAME_LENGTH];
extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
#define DISPLAY_NONE 0
#define DISPLAY_HOSTS 1
#define DISPLAY_HOSTGROUPS 2
#define DISPLAY_CONTACTS 3
#define DISPLAY_CONTACTGROUPS 4
#define DISPLAY_SERVICES 5
#define DISPLAY_TIMEPERIODS 6
#define DISPLAY_COMMANDS 7
#define DISPLAY_HOSTGROUPESCALATIONS 8 /* no longer implemented */
#define DISPLAY_SERVICEDEPENDENCIES 9
#define DISPLAY_SERVICEESCALATIONS 10
#define DISPLAY_HOSTDEPENDENCIES 11
#define DISPLAY_HOSTESCALATIONS 12
#define DISPLAY_SERVICEGROUPS 15
#define DISPLAY_COMMAND_EXPANSION 16211
void document_header(int);
void document_footer(void);
int process_cgivars(void);
void display_options(void);
void display_hosts(void);
void display_hostgroups(void);
void display_servicegroups(void);
void display_contacts(void);
void display_contactgroups(void);
void display_services(void);
void display_timeperiods(void);
void display_commands(void);
void display_servicedependencies(void);
void display_serviceescalations(void);
void display_hostdependencies(void);
void display_hostescalations(void);
void display_command_expansion(void);
void unauthorized_message(void);
authdata current_authdata;
int display_type = DISPLAY_NONE;
char to_expand[MAX_COMMAND_BUFFER];
char hashed_color[8];
int embedded = FALSE;
static void print_expand_input(int type) {
const char *seldesc = "";
if(type == DISPLAY_COMMAND_EXPANSION) return; /* Has its own form, w/ larger */
else if(type == DISPLAY_SERVICES) {
seldesc = " Services Named or on Host";
}
else if(type == DISPLAY_SERVICEDEPENDENCIES) {
seldesc = " Dependencies with Host";
}
else if(type == DISPLAY_SERVICEESCALATIONS) {
seldesc = " Escalations on Host";
}
else if(type == DISPLAY_HOSTDEPENDENCIES) {
seldesc = " Dependencies on/of Host";
}
else if(type == DISPLAY_HOSTESCALATIONS) {
seldesc = " Escalations for Host";
}
printf("
Show Only%s:
\n", seldesc);
printf("
", html_encode(to_expand, FALSE));
}
int main(void) {
mac = get_global_macros();
/* get the arguments passed in the URL */
process_cgivars();
/* reset internal variables */
reset_cgi_vars();
cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, 0);
/* initialize macros */
init_macros();
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_authdata);
/* begin top table */
printf("
\n");
if(display_type != DISPLAY_NONE) {
printf("\n");
}
/* display context-sensitive help */
switch(display_type) {
case DISPLAY_HOSTS:
display_context_help(CONTEXTHELP_CONFIG_HOSTS);
break;
case DISPLAY_HOSTGROUPS:
display_context_help(CONTEXTHELP_CONFIG_HOSTGROUPS);
break;
case DISPLAY_SERVICEGROUPS:
display_context_help(CONTEXTHELP_CONFIG_SERVICEGROUPS);
break;
case DISPLAY_CONTACTS:
display_context_help(CONTEXTHELP_CONFIG_CONTACTS);
break;
case DISPLAY_CONTACTGROUPS:
display_context_help(CONTEXTHELP_CONFIG_CONTACTGROUPS);
break;
case DISPLAY_SERVICES:
display_context_help(CONTEXTHELP_CONFIG_SERVICES);
break;
case DISPLAY_TIMEPERIODS:
display_context_help(CONTEXTHELP_CONFIG_TIMEPERIODS);
break;
case DISPLAY_COMMANDS:
display_context_help(CONTEXTHELP_CONFIG_COMMANDS);
break;
case DISPLAY_SERVICEDEPENDENCIES:
display_context_help(CONTEXTHELP_CONFIG_SERVICEDEPENDENCIES);
break;
case DISPLAY_SERVICEESCALATIONS:
display_context_help(CONTEXTHELP_CONFIG_HOSTESCALATIONS);
break;
case DISPLAY_HOSTDEPENDENCIES:
display_context_help(CONTEXTHELP_CONFIG_HOSTDEPENDENCIES);
break;
case DISPLAY_HOSTESCALATIONS:
display_context_help(CONTEXTHELP_CONFIG_HOSTESCALATIONS);
break;
case DISPLAY_COMMAND_EXPANSION:
/* Reusing DISPLAY_COMMANDS help until further notice */
display_context_help(CONTEXTHELP_CONFIG_COMMANDS);
break;
default:
display_context_help(CONTEXTHELP_CONFIG_MENU);
break;
}
printf("
\n");
/* end of top table */
printf("
\n");
printf("
\n");
switch(display_type) {
case DISPLAY_HOSTS:
display_hosts();
break;
case DISPLAY_HOSTGROUPS:
display_hostgroups();
break;
case DISPLAY_SERVICEGROUPS:
display_servicegroups();
break;
case DISPLAY_CONTACTS:
display_contacts();
break;
case DISPLAY_CONTACTGROUPS:
display_contactgroups();
break;
case DISPLAY_SERVICES:
display_services();
break;
case DISPLAY_TIMEPERIODS:
display_timeperiods();
break;
case DISPLAY_COMMANDS:
display_commands();
break;
case DISPLAY_SERVICEDEPENDENCIES:
display_servicedependencies();
break;
case DISPLAY_SERVICEESCALATIONS:
display_serviceescalations();
break;
case DISPLAY_HOSTDEPENDENCIES:
display_hostdependencies();
break;
case DISPLAY_HOSTESCALATIONS:
display_hostescalations();
break;
case DISPLAY_COMMAND_EXPANSION:
display_command_expansion();
break;
default:
display_options();
break;
}
document_footer();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
time_t t;
if(embedded == TRUE)
return;
time(&t);
get_time_string(&t, date_time, sizeof(date_time), HTTP_DATE_TIME);
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
printf("Last-Modified: %s\r\n", date_time);
printf("Expires: %s\r\n", date_time);
printf("Content-type: text/html; charset=utf-8\r\n\r\n");
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("\n");
printf("Configuration\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, CONFIG_CSS);
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(CONFIG_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(CONFIG_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
to_expand[0] = '\0';
for(x = 0; variables[x]; 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 configuration type argument */
else if(!strcmp(variables[x], "type")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
/* what information should we display? */
if(!strcmp(variables[x], "hosts"))
display_type = DISPLAY_HOSTS;
else if(!strcmp(variables[x], "hostgroups"))
display_type = DISPLAY_HOSTGROUPS;
else if(!strcmp(variables[x], "servicegroups"))
display_type = DISPLAY_SERVICEGROUPS;
else if(!strcmp(variables[x], "contacts"))
display_type = DISPLAY_CONTACTS;
else if(!strcmp(variables[x], "contactgroups"))
display_type = DISPLAY_CONTACTGROUPS;
else if(!strcmp(variables[x], "services"))
display_type = DISPLAY_SERVICES;
else if(!strcmp(variables[x], "timeperiods"))
display_type = DISPLAY_TIMEPERIODS;
else if(!strcmp(variables[x], "commands"))
display_type = DISPLAY_COMMANDS;
else if(!strcmp(variables[x], "servicedependencies"))
display_type = DISPLAY_SERVICEDEPENDENCIES;
else if(!strcmp(variables[x], "serviceescalations"))
display_type = DISPLAY_SERVICEESCALATIONS;
else if(!strcmp(variables[x], "hostdependencies"))
display_type = DISPLAY_HOSTDEPENDENCIES;
else if(!strcmp(variables[x], "hostescalations"))
display_type = DISPLAY_HOSTESCALATIONS;
else if(!strcmp(variables[x], "command"))
display_type = DISPLAY_COMMAND_EXPANSION;
/* we found the embed option */
else if(!strcmp(variables[x], "embedded"))
embedded = TRUE;
}
/* we found the string-to-expand argument */
else if(!strcmp(variables[x], "expand")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
strncpy(to_expand, variables[x], MAX_COMMAND_BUFFER);
to_expand[MAX_COMMAND_BUFFER - 1] = '\0';
}
/* we received an invalid argument */
else
error = TRUE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
void display_hosts(void) {
host *temp_host = NULL;
hostsmember *temp_hostsmember = NULL;
contactsmember *temp_contactsmember = NULL;
contactgroupsmember *temp_contactgroupsmember = NULL;
char *processed_string = NULL;
int options = 0;
int odd = 0;
char time_string[16];
const char *bg_class = "";
int num_contacts = 0;
/* see if user is authorized to view host information... */
if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) {
unauthorized_message();
return;
}
printf("
\n");
}
void display_servicedependencies(void) {
unsigned int i;
/* see if user is authorized to view hostgroup information... */
if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) {
unauthorized_message();
return;
}
printf("
\n");
}
void display_hostdependencies(void) {
unsigned int i;
/* see if user is authorized to view hostdependency information... */
if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) {
unauthorized_message();
return;
}
printf("
It appears as though you do not have permission to view the configuration information you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
return;
}
static const char *hash_color(int i) {
char c;
/* This is actually optimized for MAX_COMMAND_ARGUMENTS==32 ... */
if((i % 32) < 16) {
if((i % 32) < 8) c = '7';
else c = '4';
}
else {
if((i % 32) < 24) c = '6';
else c = '5';
}
/* Computation for standard case */
hashed_color[0] = '#';
hashed_color[1] = hashed_color[2] = ((i % 2) ? c : '0');
hashed_color[3] = hashed_color[4] = (((i / 2) % 2) ? c : '0');
hashed_color[5] = hashed_color[6] = (((i / 4) % 2) ? c : '0');
hashed_color[7] = '\0';
/* Override shades of grey */
if((i % 8) == 7) hashed_color[1] = hashed_color[3] = '0';
if((i % 8) == 0) hashed_color[2] = hashed_color[3] = hashed_color[4] = hashed_color[6] = c;
return(hashed_color);
}
void display_command_expansion(void) {
command *temp_command;
int odd = 0;
const char *bg_class = "";
int i, j;
char *c, *cc;
char commandline[MAX_COMMAND_BUFFER];
char *command_args[MAX_COMMAND_ARGUMENTS];
int arg_count[MAX_COMMAND_ARGUMENTS],
lead_space[MAX_COMMAND_ARGUMENTS],
trail_space[MAX_COMMAND_ARGUMENTS];
/* see if user is authorized to view command information... */
if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) {
unauthorized_message();
return;
}
printf("
Command Expansion
\n");
/* Parse to_expand into parts */
for(i = 0; i < MAX_COMMAND_ARGUMENTS; i++) command_args[i] = NULL;
for(i = 0, command_args[0] = cc = c = strdup(to_expand); c && ((*c) != '\0') && (i < MAX_COMMAND_ARGUMENTS); c++, cc++) {
if((*c) == '\\') c++;
else if((*c) == '!') {
(*cc) = '\0';
cc = c++;
command_args[++i] = (c--);
}
(*cc) = (*c);
}
if((*c) == '\0')(*cc) = '\0';
/* Precompute indexes of dangling whitespace */
for(i = 0; i < MAX_COMMAND_ARGUMENTS; i++) {
for(cc = command_args[i], lead_space[i] = 0; cc && isspace(*cc); cc++, lead_space[i]++) ;
trail_space[i] = 0;
for(; cc && ((*cc) != '\0'); cc++) if(isspace(*cc)) trail_space[i]++;
else trail_space[i] = 0;
}
printf("
\n");
}
printf(" \n");
if(display_type == DISPLAY_HOST_INFO)
show_host_info();
else if(display_type == DISPLAY_SERVICE_INFO)
show_service_info();
else if(display_type == DISPLAY_COMMENTS)
show_all_comments();
else if(display_type == DISPLAY_PERFORMANCE)
show_performance_data();
else if(display_type == DISPLAY_HOSTGROUP_INFO)
show_hostgroup_info();
else if(display_type == DISPLAY_SERVICEGROUP_INFO)
show_servicegroup_info();
else if(display_type == DISPLAY_DOWNTIME)
show_all_downtime();
else if(display_type == DISPLAY_SCHEDULING_QUEUE)
show_scheduling_queue();
else
show_process_info();
document_footer();
/* free all allocated memory */
free_memory();
free_comment_data();
free_downtime_data();
return OK;
}
void document_header(int use_stylesheet) {
char date_time[MAX_DATETIME_LENGTH];
char *vidurl = NULL;
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(¤t_time);
get_time_string(¤t_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; charset=utf-8\r\n\r\n");
if(embedded == TRUE)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Extended Information\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("", url_stylesheets_path, COMMON_CSS);
printf("", url_stylesheets_path, EXTINFO_CSS);
printf("\n", url_stylesheets_path, NAGFUNCS_CSS);
}
if (display_type == DISPLAY_HOST_INFO)
vidurl = "https://www.youtube.com/embed/n3QEAf-MxY4";
else if(display_type == DISPLAY_SERVICE_INFO)
vidurl = "https://www.youtube.com/embed/f_knwQOS6FI";
if (enable_page_tour == TRUE && vidurl) {
printf("\n", url_js_path, JQUERY_JS);
printf("\n", url_js_path, NAGFUNCS_JS);
printf("\n");
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(EXTINFO_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(EXTINFO_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int temp_type;
int x;
variables = getcgivars();
for(x = 0; variables[x]; 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 display type */
else if(!strcmp(variables[x], "type")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
temp_type = atoi(variables[x]);
if(temp_type == DISPLAY_HOST_INFO)
display_type = DISPLAY_HOST_INFO;
else if(temp_type == DISPLAY_SERVICE_INFO)
display_type = DISPLAY_SERVICE_INFO;
else if(temp_type == DISPLAY_COMMENTS)
display_type = DISPLAY_COMMENTS;
else if(temp_type == DISPLAY_PERFORMANCE)
display_type = DISPLAY_PERFORMANCE;
else if(temp_type == DISPLAY_HOSTGROUP_INFO)
display_type = DISPLAY_HOSTGROUP_INFO;
else if(temp_type == DISPLAY_SERVICEGROUP_INFO)
display_type = DISPLAY_SERVICEGROUP_INFO;
else if(temp_type == DISPLAY_DOWNTIME)
display_type = DISPLAY_DOWNTIME;
else if(temp_type == DISPLAY_SCHEDULING_QUEUE)
display_type = DISPLAY_SCHEDULING_QUEUE;
else
display_type = DISPLAY_PROCESS_INFO;
}
/* we found the host name */
else if(!strcmp(variables[x], "host")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
host_name = strdup(variables[x]);
if(host_name == NULL)
host_name = "";
strip_html_brackets(host_name);
}
/* we found the hostgroup name */
else if(!strcmp(variables[x], "hostgroup")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
hostgroup_name = strdup(variables[x]);
if(hostgroup_name == NULL)
hostgroup_name = "";
strip_html_brackets(hostgroup_name);
}
/* we found the service name */
else if(!strcmp(variables[x], "service")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
service_desc = strdup(variables[x]);
if(service_desc == NULL)
service_desc = "";
strip_html_brackets(service_desc);
}
/* we found the servicegroup name */
else if(!strcmp(variables[x], "servicegroup")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
servicegroup_name = strdup(variables[x]);
if(servicegroup_name == NULL)
servicegroup_name = "";
strip_html_brackets(servicegroup_name);
}
/* we found the sort type argument */
else if(!strcmp(variables[x], "sorttype")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
sort_type = atoi(variables[x]);
}
/* we found the sort option argument */
else if(!strcmp(variables[x], "sortoption")) {
x++;
if(variables[x] == NULL) {
error = TRUE;
break;
}
sort_option = atoi(variables[x]);
}
/* 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;
}
void show_process_info(void) {
char date_time[MAX_DATETIME_LENGTH];
time_t current_time;
unsigned long run_time;
char run_time_string[24];
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
/* make sure the user has rights to view system information */
if(is_authorized_for_system_information(¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view process information...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
return;
}
printf(" \n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Process Information
\n");
printf("
\n");
printf("
\n");
printf("
\n");
/* program version */
printf("
Program Version:
%s
\n", PROGRAM_VERSION);
/* program start time */
get_time_string(&program_start, date_time, (int)sizeof(date_time), SHORT_DATE_TIME);
printf("
It appears as though Nagios is not running, so commands are temporarily unavailable...\n");
printf("
\n");
}
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
}
void show_host_info(void) {
hoststatus *temp_hoststatus;
host *temp_host;
char date_time[MAX_DATETIME_LENGTH];
char state_duration[48];
char status_age[48];
char state_string[MAX_INPUT_BUFFER];
const char *bg_class = "";
char *buf = NULL;
int days;
int hours;
int minutes;
int seconds;
time_t current_time;
time_t t;
int duration_error = FALSE;
/* get host info */
temp_host = find_host(host_name);
/* make sure the user has rights to view host information */
if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view information for this host...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
return;
}
/* get host status info */
temp_hoststatus = find_hoststatus(host_name);
/* make sure host information exists */
if(temp_host == NULL) {
printf("
\n");
return;
}
void show_service_info(void) {
service *temp_service;
char date_time[MAX_DATETIME_LENGTH];
char status_age[48];
char state_duration[48];
servicestatus *temp_svcstatus;
char state_string[MAX_INPUT_BUFFER];
const char *bg_class = "";
char *buf = NULL;
int days;
int hours;
int minutes;
int seconds;
time_t t;
time_t current_time;
int duration_error = FALSE;
/* find the service */
temp_service = find_service(host_name, service_desc);
/* make sure the user has rights to view service information */
if(is_authorized_for_service(temp_service, ¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view information for this service...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
return;
}
/* get service status info */
temp_svcstatus = find_servicestatus(host_name, service_desc);
/* make sure service information exists */
if(temp_service == NULL) {
printf("
\n");
return;
}
void show_hostgroup_info(void) {
hostgroup *temp_hostgroup;
/* get hostgroup info */
temp_hostgroup = find_hostgroup(hostgroup_name);
/* make sure the user has rights to view hostgroup information */
if(is_authorized_for_hostgroup(temp_hostgroup, ¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view information for this hostgroup...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
return;
}
/* make sure hostgroup information exists */
if(temp_hostgroup == NULL) {
printf("
\n");
printf("\n");
printf("\n");
return;
}
void show_servicegroup_info() {
servicegroup *temp_servicegroup;
/* get servicegroup info */
temp_servicegroup = find_servicegroup(servicegroup_name);
/* make sure the user has rights to view servicegroup information */
if(is_authorized_for_servicegroup(temp_servicegroup, ¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view information for this servicegroup...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
return;
}
/* make sure servicegroup information exists */
if(temp_servicegroup == NULL) {
printf("
\n");
/***** ACTIVE SERVICE CHECKS *****/
printf("
\n");
printf("
Services Actively Checked:
\n");
printf("
\n");
/* fake this so we don't divide by zero for just showing the table */
if(total_active_service_checks == 0)
total_active_service_checks = 1;
printf("
\n");
/***** PASSIVE SERVICE CHECKS *****/
printf("
\n");
printf("
Services Passively Checked:
\n");
printf("
\n");
/* fake this so we don't divide by zero for just showing the table */
if(total_passive_service_checks == 0)
total_passive_service_checks = 1;
printf("
\n");
return;
}
/* shows all service and host scheduled downtime */
void show_all_downtime(void) {
int total_downtime = 0;
const char *bg_class = "";
int odd = 0;
char date_time[MAX_DATETIME_LENGTH];
scheduled_downtime *temp_downtime;
host *temp_host;
service *temp_service;
int days;
int hours;
int minutes;
int seconds;
printf(" \n");
printf("
\n");
return;
}
/* shows check scheduling queue */
void show_scheduling_queue(void) {
sortdata *temp_sortdata;
servicestatus *temp_svcstatus = NULL;
hoststatus *temp_hststatus = NULL;
char date_time[MAX_DATETIME_LENGTH];
char temp_url[MAX_INPUT_BUFFER];
int odd = 0;
const char *bgclass = "";
/* make sure the user has rights to view system information */
if(is_authorized_for_system_information(¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view process information...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
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
", (log_archive == 0) ? "the current" : "this archived");
}
printf("\n");
my_free(input);
my_free(input2);
if(use_lifo == TRUE)
free_lifo_memory();
else
mmap_fclose(thefile);
return;
}
nagios-4.4.6/cgi/jsonutils.c 0000664 0000000 0000000 00000116406 13652113235 0015756 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* JSONUTILS.C - Utilities for Nagios CGIs for returning JSON-formatted
* object data
*
* Copyright (c) 2013 Nagios Enterprises, LLC
* Last Modified: 04-13-2013
*
* 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/statusdata.h"
#include "../include/comments.h"
#include "../include/cgiutils.h"
#include "../include/getcgi.h"
#include "../include/cgiauth.h"
#include "../include/jsonutils.h"
/* Multiplier to increment the buffer in json_escape_string() to avoid frequent
repeated reallocations */
#define BUF_REALLOC_MULTIPLIER 16
const char *result_types[] = {
"Success",
"Unable to Allocate Memory",
"Unable to Open File for Reading",
"Option Invalid",
"Option Missing",
"Option Value Missing",
"Option Value Invalid",
"Option Ignored"
};
const string_value_mapping svm_format_options[] = {
{ "whitespace", JSON_FORMAT_WHITESPACE,
"Pad with whitespace to increase readability" },
{ "enumerate", JSON_FORMAT_ENUMERATE,
"Use textual representations of enumerated values rather than "
"raw numeric values" },
{ "bitmask", JSON_FORMAT_BITMASK,
"Use textual representations of bitmask values rather than "
"raw numeric values" },
{ "duration", JSON_FORMAT_DURATION,
"Use textual representations (xd xh xm xs) of duration values rather "
"than raw number of seconds" },
#if 0
{ "datetime", JSON_FORMAT_DATETIME,
"Format date/time values according to the supplied strftime format "
"or '%%Y-%%m-%%d %%H:%%M:%%S' if no format specified" },
{ "date", JSON_FORMAT_DATE,
"Format dates according to the supplied strftime format or "
"default Javascript format (number of ms since the beginning of the "
"Unix epoch) if no format specified" },
{ "time", JSON_FORMAT_TIME,
"Format times according the supplied strftime format or "
"'%%H:%%M:%%S' in for format specified" },
#endif
{ NULL, -1, NULL },
};
const string_value_mapping query_statuses[] = {
{ "alpha", QUERY_STATUS_ALPHA, "Alpha" },
{ "beta", QUERY_STATUS_BETA, "Beta" },
{ "released", QUERY_STATUS_RELEASED, "Released" },
{ "deprecated", QUERY_STATUS_DEPRECATED, "Deprecated" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_host_statuses[] = {
#ifdef JSON_NAGIOS_4X
{ "up", SD_HOST_UP, "HOST_UP" },
{ "down", SD_HOST_DOWN, "HOST_DOWN" },
{ "unreachable", SD_HOST_UNREACHABLE, "HOST_UNREACHABLE" },
#else
{ "up", HOST_UP, "HOST_UP" },
{ "down", HOST_DOWN, "HOST_DOWN" },
{ "unreachable", HOST_UNREACHABLE, "HOST_UNREACHABLE" },
#endif
{ "pending", HOST_PENDING, "HOST_PENDING" },
{ NULL, -1, NULL },
};
/* Hard-coded values used because the HOST_UP/DOWN/UNREACHABLE
macros are host status (and include PENDING), not host state */
const string_value_mapping svm_host_states[] = {
{ "up", 0, "HOST_UP" },
{ "down", 1, "HOST_DOWN" },
{ "unreachable", 2, "HOST_UNREACHABLE" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_service_statuses[] = {
{ "ok", SERVICE_OK, "SERVICE_OK" },
{ "warning", SERVICE_WARNING, "SERVICE_WARNING" },
{ "critical", SERVICE_CRITICAL, "SERVICE_CRITICAL" },
{ "unknown", SERVICE_UNKNOWN, "SERVICE_UNKNOWN" },
{ "pending", SERVICE_PENDING, "SERVICE_PENDING" },
{ NULL, -1, NULL },
};
/* Hard-coded values used because the SERVICE_OK/WARNING/CRITICAL/UNKNOWN
macros are service status (and include PENDING), not service state */
const string_value_mapping svm_service_states[] = {
{ "ok", 0, "SERVICE_OK" },
{ "warning", 1, "SERVICE_WARNING" },
{ "critical", 2, "SERVICE_CRITICAL" },
{ "unknown", 3, "SERVICE_UNKNOWN" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_check_options[] = {
{ "force_execution", CHECK_OPTION_FORCE_EXECUTION, "FORCE_EXECUTION" },
{ "freshness_check", CHECK_OPTION_FRESHNESS_CHECK, "FRESHNESS_CHECK" },
{ "orphan_check", CHECK_OPTION_ORPHAN_CHECK, "ORPHAN_CHECK" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_host_check_types[] = {
{ "active", HOST_CHECK_ACTIVE, "ACTIVE" },
{ "passive", HOST_CHECK_PASSIVE, "PASSIVE" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_service_check_types[] = {
{ "active", SERVICE_CHECK_ACTIVE, "ACTIVE" },
{ "passive", SERVICE_CHECK_PASSIVE, "PASSIVE" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_state_types[] = {
{ "soft", SOFT_STATE, "SOFT" },
{ "hard", HARD_STATE, "HARD" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_acknowledgement_types[] = {
{ "none", ACKNOWLEDGEMENT_NONE, "NONE" },
{ "normal", ACKNOWLEDGEMENT_NORMAL, "NORMAL" },
{ "sticky", ACKNOWLEDGEMENT_STICKY, "STICKY" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_comment_types[] = {
{ "host", HOST_COMMENT, "Host Comment" },
{ "service", SERVICE_COMMENT, "Service Comment" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_comment_entry_types[] = {
{ "user", USER_COMMENT, "User Comment" },
{ "downtime", DOWNTIME_COMMENT, "Downtime Comment" },
{ "flapping", FLAPPING_COMMENT, "Flapping Comment" },
{ "acknowledgement", ACKNOWLEDGEMENT_COMMENT, "Acknowledgement Comment" },
{ NULL, -1, NULL },
};
const string_value_mapping svm_downtime_types[] = {
{ "service", SERVICE_DOWNTIME, "Service Downtime" },
{ "host", HOST_DOWNTIME, "Host Downtime" },
{ "any", ANY_DOWNTIME, "Any Downtime" },
{ NULL, -1, NULL },
};
#ifdef JSON_NAGIOS_4X
const string_value_mapping svm_option_types[] = {
{ "up", OPT_UP, "Up" },
{ "down", OPT_DOWN, "Down" },
{ "unreachable", OPT_UNREACHABLE, "Unreachable" },
{ "ok", OPT_OK, "OK" },
{ "unknown", OPT_UNKNOWN, "Unknown" },
{ "warning", OPT_WARNING, "Warning" },
{ "critical", OPT_CRITICAL, "Critical" },
{ "recovery", OPT_RECOVERY, "Recovery" },
{ "pending", OPT_PENDING, "Pending" },
{ "flapping", OPT_FLAPPING, "Flapping" },
{ "downtime", OPT_DOWNTIME, "Downtime" },
{ NULL, -1, NULL },
};
#endif
const string_value_mapping parent_host_extras[] = {
{ "none", 0, "Hosts that are directly reachable by the Nagios Core host" },
{ NULL, -1, NULL },
};
const string_value_mapping child_host_extras[] = {
{ "none", 0, "Hosts that have no child hosts" },
{ NULL, -1, NULL },
};
const string_value_mapping parent_service_extras[] = {
{ "none", 0, "Services that have no parent services" },
{ NULL, -1, NULL },
};
const string_value_mapping child_service_extras[] = {
{ "none", 0, "Services that have no child services" },
{ NULL, -1, NULL },
};
const char *dayofweek[7] = { "Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday" };
const char *month[12] = { "January", "February", "March", "April", "May",
"June", "July", "August", "September", "October", "November",
"December" };
static const json_escape_pair string_escape_pairs[] = {
{ L"\\", L"\\\\" },
{ L"\x01", L"\\u0001" },
{ L"\x02", L"\\u0002" },
{ L"\x03", L"\\u0003" },
{ L"\x04", L"\\u0004" },
{ L"\x05", L"\\u0004" },
{ L"\x06", L"\\u0006" },
{ L"\a", L"\\a" },
{ L"\b", L"\\b" },
{ L"\t", L"\\t" },
{ L"\n", L"\\n" },
{ L"\v", L"\\v" },
{ L"\f", L"\\f" },
{ L"\r", L"\\r" },
{ L"\x0e", L"\\u000e" },
{ L"\x0f", L"\\u000f" },
{ L"\x10", L"\\u0010" },
{ L"\x11", L"\\u0011" },
{ L"\x12", L"\\u0012" },
{ L"\x13", L"\\u0013" },
{ L"\x14", L"\\u0014" },
{ L"\x15", L"\\u0015" },
{ L"\x16", L"\\u0016" },
{ L"\x17", L"\\u0017" },
{ L"\x18", L"\\u0018" },
{ L"\x19", L"\\u0019" },
{ L"\x1a", L"\\u001a" },
{ L"\x1b", L"\\u001b" },
{ L"\x1c", L"\\u001c" },
{ L"\x1d", L"\\u001d" },
{ L"\x1e", L"\\u001e" },
{ L"\x1f", L"\\u001f" },
{ L"\"", L"\\\"" },
};
static const json_escape string_escapes = {
(sizeof(string_escape_pairs) / sizeof(string_escape_pairs[0])),
string_escape_pairs
};
const json_escape_pair percent_escape_pairs[] = {
{ L"%", L"%%" },
};
const json_escape percent_escapes = {
(sizeof(percent_escape_pairs) / sizeof(percent_escape_pairs[0])),
percent_escape_pairs
};
extern char main_config_file[MAX_FILENAME_LENGTH];
extern time_t program_start;
static json_object_member * json_object_add_member(json_object *);
json_object *json_new_object(void) {
json_object *new;
new = calloc(1, sizeof(json_object));
return new;
}
void json_free_object(json_object *obj, int free_children) {
int x;
json_object_member **mpp;
if(1 == free_children) {
for(x = 0, mpp = obj->members; x < obj->member_count; x++, mpp++) {
json_free_member(*mpp, free_children);
}
}
free(obj->members);
free(obj);
}
json_array *json_new_array(void) {
return (json_array *)json_new_object();
}
void json_free_member(json_object_member *mp, int free_children) {
if(NULL != mp->key) free(mp->key);
switch(mp->type) {
case JSON_TYPE_OBJECT:
case JSON_TYPE_ARRAY:
if(NULL != mp->value.object) {
json_free_object(mp->value.object, free_children);
}
break;
case JSON_TYPE_STRING:
if(NULL != mp->value.string) {
free(mp->value.string);
}
break;
case JSON_TYPE_INTEGER:
case JSON_TYPE_REAL:
case JSON_TYPE_TIME_T:
case JSON_TYPE_BOOLEAN:
break;
default:
break;
}
free(mp);
}
/* Adds a member to a JSON object and returns a pointer to the new member.
Returns NULL on failure. */
static json_object_member * json_object_add_member(json_object *obj) {
if(0 == obj->member_count) {
obj->members = calloc(1, sizeof(json_object_member *));
if(NULL == obj->members) {
obj->member_count = 0;
return NULL;
}
}
else {
obj->members = realloc(obj->members,
((obj->member_count + 1) * sizeof(json_object_member *)));
if(NULL == obj->members) {
obj->member_count = 0;
return NULL;
}
}
obj->members[ obj->member_count] = calloc(1, sizeof(json_object_member));
if(NULL == obj->members[ obj->member_count]) {
return NULL;
}
obj->member_count++;
return obj->members[ obj->member_count - 1];
}
void json_object_append_object(json_object *obj, char *key, json_object *value) {
json_object_member *mp;
if(NULL == obj) return;
if(NULL == value) return;
if((mp = json_object_add_member(obj)) == NULL) {
return;
}
mp->type = JSON_TYPE_OBJECT;
if(NULL != key) {
mp->key = strdup(key);
if(NULL == mp->key) {
obj->member_count--;
return;
}
}
mp->value.object = value;
}
void json_array_append_object(json_object *obj, json_object *value) {
json_object_append_object(obj, NULL, value);
}
void json_object_append_array(json_object *obj, char *key, json_array *value) {
json_object_member *mp;
if(NULL == obj) return;
if(NULL == value) return;
if((mp = json_object_add_member(obj)) == NULL) {
return;
}
mp->type = JSON_TYPE_ARRAY;
if(NULL != key) {
mp->key = strdup(key);
if(NULL == mp->key) {
obj->member_count--;
return;
}
}
mp->value.object = value;
}
void json_array_append_array(json_array *obj, json_array *value) {
json_object_append_array((json_object *)obj, NULL, value);
}
void json_object_append_integer(json_object *obj, char *key, int value) {
json_object_member *mp;
if(NULL == obj) return;
if((mp = json_object_add_member(obj)) == NULL) {
return;
}
mp->type = JSON_TYPE_INTEGER;
if(NULL != key) {
mp->key = strdup(key);
if(NULL == mp->key) {
obj->member_count--;
return;
}
}
mp->value.integer = value;
}
void json_array_append_integer(json_object *obj, int value) {
json_object_append_integer(obj, NULL, value);
}
void json_object_append_real(json_object *obj, char *key, double value) {
json_object_member *mp;
if(NULL == obj) return;
if((mp = json_object_add_member(obj)) == NULL) {
return;
}
mp->type = JSON_TYPE_REAL;
if(NULL != key) {
mp->key = strdup(key);
if(NULL == mp->key) {
obj->member_count--;
return;
}
}
mp->value.real = value;
}
void json_array_append_real(json_array *obj, double value) {
json_object_append_real(obj, NULL, value);
}
void json_object_append_time(json_object *obj, char *key, unsigned long value) {
unsigned hours;
unsigned minutes;
unsigned seconds;
hours = (unsigned)(value / 3600);
value -= hours * 3600;
minutes = (unsigned)(value / 60);
value -= minutes * 60;
seconds = value;
json_object_append_string(obj, key, NULL, "%02u:%02u:%02u", hours, minutes,
seconds);
}
void json_array_append_time(json_array *obj, unsigned long value) {
json_object_append_time(obj, NULL, value);
}
void json_object_append_time_t(json_object *obj, char *key, time_t value) {
json_object_member *mp;
if(NULL == obj) return;
if((mp = json_object_add_member(obj)) == NULL) {
return;
}
mp->type = JSON_TYPE_TIME_T;
if(NULL != key) {
mp->key = strdup(key);
if(NULL == mp->key) {
obj->member_count--;
return;
}
}
mp->value.time = value;
}
void json_set_time_t(json_object_member *mp, time_t value) {
if(NULL == mp) return;
mp->value.time = value;
}
void json_object_append_string(json_object *obj, char *key,
const json_escape *format_escapes, char *format, ...) {
json_object_member *mp;
va_list a_list;
int result;
char *escaped_format;
char *buf;
if(NULL == obj) return;
if((mp = json_object_add_member(obj)) == NULL) {
return;
}
mp->type = JSON_TYPE_STRING;
if(NULL != key) {
mp->key = strdup(key);
if(NULL == mp->key) {
obj->member_count--;
return;
}
}
if((NULL != format_escapes) && (NULL != format)) {
escaped_format = json_escape_string(format, format_escapes);
}
else {
escaped_format = format;
}
if(NULL != escaped_format) {
va_start(a_list, format);
result = vasprintf(&buf, escaped_format, a_list);
va_end(a_list);
if(result >= 0) {
mp->value.string = buf;
}
}
if((NULL != format_escapes) && (NULL != escaped_format)) {
/* free only if format_escapes were passed and the escaping succeeded */
free(escaped_format);
}
}
void json_array_append_string(json_object *obj,
const json_escape *format_escapes, char *format, ...) {
va_list a_list;
int result;
char *buf;
va_start( a_list, format);
result = vasprintf(&buf, format, a_list);
va_end( a_list);
if(result >= 0) {
json_object_append_string(obj, NULL, format_escapes, buf);
}
}
void json_object_append_boolean(json_object *obj, char *key, int value) {
json_object_member *mp;
if(NULL == obj) return;
if((mp = json_object_add_member(obj)) == NULL) {
return;
}
mp->type = JSON_TYPE_BOOLEAN;
if(NULL != key) {
mp->key = strdup(key);
if(NULL == mp->key) {
obj->member_count--;
return;
}
}
mp->value.boolean = value;
}
void json_array_append_boolean(json_object *obj, int value) {
json_object_append_boolean(obj, NULL, value);
}
void json_object_append_duration(json_object *obj, char *key,
unsigned long value) {
json_object_member *mp;
if(NULL == obj) return;
if((mp = json_object_add_member(obj)) == NULL) {
return;
}
mp->type = JSON_TYPE_DURATION;
if(NULL != key) {
mp->key = strdup(key);
if(NULL == mp->key) {
obj->member_count--;
return;
}
}
mp->value.unsigned_integer = value;
}
void json_array_append_duration(json_object *obj, unsigned long value) {
json_object_append_duration(obj, NULL, value);
}
/*
Fetch an object member based on the path. The path is a dot-separated
list of nodes. Nodes may be either a key or a zero-based array index.
For example to return the query_time key in the result object, the
path would be "result.query_time". To find the 2nd host host in
the list of hosts for a hostlist query, the path would be
"data.hostlist.1"
*/
json_object_member *json_get_object_member(json_object *root, char *path) {
char *dot;
char node[1024];
int x;
json_object_member **mpp;
/* Parse the path to get the first node */
dot = strchr(path, '.');
if(NULL == dot) { /* single node path */
strcpy(node, path);
}
else {
strncpy(node, path, (dot - path));
node[dot - path] = '\0';
}
/* Loop over the members of the passed root looking for the node name */
for(x = 0, mpp = root->members; x < root->member_count; x++, mpp++) {
if(!strcmp((*mpp)->key, node)) {
if(NULL == dot) { /* return this node */
return *mpp;
}
else {
switch((*mpp)->type) {
case JSON_TYPE_OBJECT:
return json_get_object_member((*mpp)->value.object, dot + 1);
break;
case JSON_TYPE_ARRAY:
return json_get_array_member((*mpp)->value.object, dot + 1);
break;
default:
/* It should never happen that we want the child of a
childless node */
return NULL;
break;
}
}
}
}
return NULL;
}
json_object_member *json_get_array_member(json_object *root, char *path) {
char *dot;
char node[1024];
int index;
json_object_member *mp;
/* Parse the path to get the first node */
dot = strchr(path, '.');
if(NULL == dot) { /* single node path */
strcpy(node, path);
}
else {
strncpy(node, path, (dot - path));
node[dot - path] = '\0';
}
index = (int)strtol(node, NULL, 10);
/* Verify that we have a reasonable index */
if(index < 0 || index >= root->member_count) {
return NULL;
}
/* Find the requested member and deal with it appropriately */
mp = root->members[ index];
if(NULL == dot) { /* return this node */
return mp;
}
else {
switch(mp->type) {
case JSON_TYPE_OBJECT:
return json_get_object_member(mp->value.object, dot + 1);
break;
case JSON_TYPE_ARRAY:
return json_get_array_member(mp->value.object, dot + 1);
break;
default:
/* It should never happen that we want the child of a
childless node */
return NULL;
break;
}
}
return NULL;
}
void json_object_print(json_object *obj, int padding, int whitespace,
char *strftime_format, unsigned format_options) {
int x;
json_object_member **mpp;
//indentf(padding, whitespace, "{%s", (whitespace ? "\n" : ""));
printf( "{%s", (whitespace ? "\n" : ""));
padding++;
for(x = 0, mpp = obj->members; x < obj->member_count; x++, mpp++) {
json_member_print(*mpp, padding, whitespace, strftime_format,
format_options);
if(x != obj->member_count - 1) printf(",");
if(whitespace) printf("\n");
}
padding--;
indentf(padding, whitespace, "}");
}
void json_array_print(json_array *obj, int padding, int whitespace,
char *strftime_format, unsigned format_options) {
int x;
json_object_member **mpp;
printf( "[%s", (whitespace ? "\n" : ""));
padding++;
for(x = 0, mpp = obj->members; x < obj->member_count; x++, mpp++) {
json_member_print(*mpp, padding, whitespace, strftime_format,
format_options);
if(x != obj->member_count - 1) printf(",");
if(whitespace) printf("\n");
}
padding--;
indentf(padding, whitespace, "]");
}
void json_member_print(json_object_member *mp, int padding, int whitespace,
char *strftime_format, unsigned format_options) {
char *buf = NULL;
switch(mp->type) {
case JSON_TYPE_OBJECT:
if(NULL != mp->key) {
buf = json_escape_string(mp->key, &string_escapes);
indentf(padding, whitespace, "\"%s\": ", buf);
if(NULL != buf) free(buf);
}
else {
indentf(padding, whitespace, "");
}
json_object_print(mp->value.object, padding, whitespace,
strftime_format, format_options);
break;
case JSON_TYPE_ARRAY:
if(NULL != mp->key) {
buf = json_escape_string(mp->key, &string_escapes);
indentf(padding, whitespace, "\"%s\": ", buf);
if(NULL != buf) free(buf);
}
else {
indentf(padding, whitespace, "");
}
json_array_print(mp->value.object, padding, whitespace, strftime_format,
format_options);
break;
case JSON_TYPE_INTEGER:
json_int(padding, whitespace, mp->key, mp->value.integer);
break;
case JSON_TYPE_REAL:
json_float(padding, whitespace, mp->key, mp->value.real);
break;
case JSON_TYPE_TIME_T:
json_time_t(padding, whitespace, mp->key, mp->value.time,
strftime_format);
break;
case JSON_TYPE_STRING:
json_string(padding, whitespace, mp->key, mp->value.string);
break;
case JSON_TYPE_BOOLEAN:
json_boolean(padding, whitespace, mp->key, mp->value.boolean);
break;
case JSON_TYPE_DURATION:
json_duration(padding, whitespace, mp->key, mp->value.unsigned_integer,
format_options & JSON_FORMAT_DURATION);
break;
default:
break;
}
}
void indentf(int padding, int whitespace, char *format, ...) {
va_list a_list;
int padvar;
if( whitespace > 0) {
for(padvar = 0; padvar < padding; padvar++) printf( " ");
}
va_start( a_list, format);
vprintf(format, a_list);
va_end( a_list);
}
json_object * json_result(time_t query_time, char *cgi, char *query,
int query_status, time_t last_data_update, authdata *authinfo, int type,
char *message, ...) {
json_object *json_result;
va_list a_list;
char *buf;
json_result = json_new_object();
json_object_append_time_t(json_result, "query_time", query_time);
json_object_append_string(json_result, "cgi", &percent_escapes, cgi);
if(NULL != authinfo) {
json_object_append_string(json_result, "user", &percent_escapes,
authinfo->username);
}
if(NULL != query) {
json_object_append_string(json_result, "query", &percent_escapes,
query);
json_object_append_string(json_result, "query_status", &percent_escapes,
svm_get_string_from_value(query_status, query_statuses));
}
json_object_append_time_t(json_result, "program_start", program_start);
if(last_data_update != (time_t)-1) {
json_object_append_time_t(json_result, "last_data_update",
last_data_update);
}
json_object_append_integer(json_result, "type_code", type);
json_object_append_string(json_result, "type_text", &percent_escapes,
(char *)result_types[ type]);
va_start( a_list, message);
if(vasprintf(&buf, message, a_list) == -1) {
buf = NULL;
}
va_end( a_list);
json_object_append_string(json_result, "message", &percent_escapes, buf);
if(NULL != buf) free(buf);
return json_result;
}
json_object *json_help(option_help *help) {
json_object *json_data = json_new_object();
json_object *json_options = json_new_object();
json_object *json_option;
json_array *json_required;
json_array *json_optional;
json_object *json_validvalues;
json_object *json_validvalue;
int x;
char ** stpp;
string_value_mapping *svmp;
while(NULL != help->name) {
json_option = json_new_object();
json_object_append_string(json_option, "label", &percent_escapes,
(char *)help->label);
json_object_append_string(json_option, "type", &percent_escapes,
(char *)help->type);
json_required = json_new_array();
for(x = 0, stpp = (char **)help->required;
(( x < sizeof( help->required) /
sizeof( help->required[ 0])) && ( NULL != *stpp));
x++, stpp++) {
json_array_append_string(json_required, &percent_escapes, *stpp);
}
json_object_append_array(json_option, "required",
json_required);
json_optional = json_new_array();
for(x = 0, stpp = (char **)help->optional;
(( x < sizeof( help->optional) /
sizeof( help->optional[ 0])) && ( NULL != *stpp));
x++, stpp++) {
json_array_append_string(json_optional, &percent_escapes, *stpp);
}
json_object_append_array(json_option, "optional",
json_optional);
json_object_append_string(json_option, "depends_on",
&percent_escapes, (char *)help->depends_on);
json_object_append_string(json_option, "description",
&percent_escapes, (char *)help->description);
if( NULL != help->valid_values) {
json_validvalues = json_new_object();
for(svmp = (string_value_mapping *)help->valid_values;
NULL != svmp->string; svmp++) {
if( NULL != svmp->description) {
json_validvalue = json_new_object();
json_object_append_string(json_validvalue, "description",
&percent_escapes, svmp->description);
json_object_append_object(json_validvalues, svmp->string,
json_validvalue);
}
else {
json_array_append_string(json_validvalues, &percent_escapes,
svmp->string);
}
}
json_object_append_object(json_option, "valid_values",
json_validvalues);
}
json_object_append_object(json_options, (char *)help->name, json_option);
help++;
}
json_object_append_object(json_data, "options", json_options);
return json_data;
}
int passes_start_and_count_limits(int start, int max, int current, int counted) {
int result = FALSE;
if(start > 0) {
/* The user requested we start at a specific index */
if(current >= start) {
if(max > 0) {
/* The user requested a limit on the number of items returned */
if(counted < max) {
result = TRUE;
}
}
else {
/* The user did not request a limit on the number of items
returned */
result = TRUE;
}
}
}
else {
/* The user did not request we start at a specific index */
if(max > 0) {
/* The user requested a limit on the number of items returned */
if(counted < max) {
result = TRUE;
}
}
else {
/* The user did not request a limit on the number of items
returned */
result = TRUE;
}
}
return result;
}
void json_string(int padding, int whitespace, char *key, char *value) {
char *keybuf = NULL;
char *valbuf = NULL;
valbuf = json_escape_string(value, &string_escapes);
if( NULL == key) {
indentf(padding, whitespace, "\"%s\"",
(( NULL == valbuf) ? "" : valbuf));
}
else {
keybuf = json_escape_string(key, &string_escapes);
indentf(padding, whitespace, "\"%s\":%s\"%s\"", keybuf,
(( whitespace> 0) ? " " : ""),
(( NULL == valbuf) ? "" : valbuf));
}
if(NULL != keybuf) free(keybuf);
if(NULL != valbuf) free(valbuf);
}
void json_boolean(int padding, int whitespace, char *key, int value) {
char *keybuf = NULL;
if( NULL == key) {
indentf(padding, whitespace, "%s",
(( 0 == value) ? "false" : "true"));
}
else {
keybuf = json_escape_string(key, &string_escapes);
indentf(padding, whitespace, "\"%s\":%s%s", keybuf,
(( whitespace > 0) ? " " : ""),
(( 0 == value) ? "false" : "true"));
}
if(NULL != keybuf) free(keybuf);
}
void json_int(int padding, int whitespace, char *key, int value) {
char *keybuf = NULL;
if( NULL == key) {
indentf(padding, whitespace, "%d", value);
}
else {
keybuf = json_escape_string(key, &string_escapes);
indentf(padding, whitespace, "\"%s\":%s%d", keybuf,
(( whitespace > 0) ? " " : ""), value);
}
if(NULL != keybuf) free(keybuf);
}
void json_unsigned(int padding, int whitespace, char *key,
unsigned long long value) {
char *keybuf = NULL;
if( NULL == key) {
indentf(padding, whitespace, "%llu", value);
}
else {
keybuf = json_escape_string(key, &string_escapes);
indentf(padding, whitespace, "\"%s\":%s%llu", keybuf,
(( whitespace > 0) ? " " : ""), value);
}
if(NULL != keybuf) free(keybuf);
}
void json_float(int padding, int whitespace, char *key, double value) {
char *keybuf = NULL;
if( NULL == key) {
indentf(padding, whitespace, "%.2f", value);
}
else {
keybuf = json_escape_string(key, &string_escapes);
indentf(padding, whitespace, "\"%s\":%s%.2f", keybuf,
(( whitespace > 0) ? " " : ""), value);
}
if(NULL != keybuf) free(keybuf);
}
void json_time(int padding, int whitespace, char *key, unsigned long value) {
char *keybuf = NULL;
unsigned hours;
unsigned minutes;
unsigned seconds;
hours = (unsigned)(value / 3600);
value -= hours * 3600;
minutes = (unsigned)(value / 60);
value -= minutes * 60;
seconds = value;
if( NULL == key) {
indentf(padding, whitespace, "\"%02u:%02u:%02u\"", hours, minutes,
seconds);
}
else {
keybuf = json_escape_string(key, &string_escapes);
indentf(padding, whitespace, "\"%s\":%s\"%02u:%02u:%02u\"", keybuf,
(( whitespace > 0) ? " " : ""), hours, minutes,
seconds);
}
if(NULL != keybuf) free(keybuf);
}
void json_time_t(int padding, int whitespace, char *key, time_t value,
char *format) {
char *keybuf = NULL;
char buf[1024];
struct tm *tmp_tm;
if(NULL == format) {
snprintf(buf, sizeof(buf)-1, "%llu%s", (unsigned long long)value,
((unsigned long long)value > 0 ? "000" : ""));
}
else {
tmp_tm = localtime(&value);
buf[ 0] = '"';
strftime(buf+1, sizeof(buf)-3, format, tmp_tm);
strcat(buf, "\"");
}
if(NULL == key) {
indentf(padding, whitespace, "%s", buf);
}
else {
keybuf = json_escape_string(key, &string_escapes);
indentf(padding, whitespace, "\"%s\":%s%s", keybuf,
(( whitespace > 0) ? " " : ""), buf);
}
if(NULL != keybuf) free(keybuf);
}
void json_duration(int padding, int whitespace, char *key, unsigned long value,
int format_duration) {
char *keybuf = NULL;
char buf[1024];
int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
if(0 == format_duration) {
snprintf(buf, sizeof(buf)-1, "%lu", (unsigned long)value);
}
else {
days = (unsigned)(value / 86400);
value -= days * 86400;
hours = (unsigned)(value / 3600);
value -= hours * 3600;
minutes = (unsigned)(value / 60);
value -= minutes * 60;
seconds = value;
snprintf(buf, sizeof(buf)-1, "%ud %uh %um %us", days, hours, minutes,
seconds);
}
if( NULL == key) {
indentf(padding, whitespace, "%s", buf);
}
else {
keybuf = json_escape_string(key, &string_escapes);
indentf(padding, whitespace, "\"%s\":%s%s%s%s", keybuf,
(( whitespace > 0) ? " " : ""), (format_duration ? "\"" : ""),
buf, (format_duration ? "\"" : ""));
}
if(NULL != keybuf) free(keybuf);
}
void json_enumeration(json_object *json_parent, unsigned format_options,
char *key, int value, const string_value_mapping *map) {
string_value_mapping *svmp;
if(format_options & JSON_FORMAT_ENUMERATE) {
for(svmp = (string_value_mapping *)map; NULL != svmp->string; svmp++) {
if( value == svmp->value) {
json_object_append_string(json_parent, key, &percent_escapes,
svmp->string);
break;
}
}
if( NULL == svmp->string) {
json_object_append_string(json_parent, key, NULL,
"Unknown value %d", svmp->value);
}
}
else {
json_object_append_integer(json_parent, key, value);
}
}
void json_bitmask(json_object *json_parent, unsigned format_options, char *key,
int value, const string_value_mapping *map) {
json_array *json_bitmask_array;
string_value_mapping *svmp;
if(format_options & JSON_FORMAT_BITMASK) {
json_bitmask_array = json_new_array();
for(svmp = (string_value_mapping *)map; NULL != svmp->string; svmp++) {
if( value & svmp->value) {
json_array_append_string(json_bitmask_array, &percent_escapes,
svmp->string);
}
}
json_object_append_array(json_parent, key, json_bitmask_array);
}
else {
json_object_append_integer(json_parent, key, value);
}
}
int parse_bitmask_cgivar(char *cgi, char *query, int query_status,
json_object *json_parent, time_t query_time, authdata *authinfo,
char *key, char *value, const string_value_mapping *svm,
unsigned *var) {
int result = RESULT_SUCCESS;
char *option;
char *saveptr;
string_value_mapping *svmp;
if(value == NULL) {
json_object_append_object(json_parent, "result",
json_result(query_time, cgi, query, query_status,
(time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING,
"No value specified for %s option.", key));
return RESULT_OPTION_VALUE_MISSING;
}
option = strtok_r(value, " ", &saveptr);
while(NULL != option) {
for(svmp = (string_value_mapping *)svm; NULL != svmp->string; svmp++) {
if( !strcmp( svmp->string, option)) {
*var |= svmp->value;
break;
}
}
if( NULL == svmp->string) {
json_object_append_object(json_parent, "result",
json_result(query_time, cgi, query, query_status,
(time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID,
"The %s option value '%s' is invalid.", key, option));
result = RESULT_OPTION_VALUE_INVALID;
break;
}
option = strtok_r(NULL, " ", &saveptr);
}
return result;
}
int parse_enumeration_cgivar(char *cgi, char *query, int query_status,
json_object *json_parent, time_t query_time, authdata *authinfo,
char *key, char *value, const string_value_mapping *svm, int *var) {
string_value_mapping *svmp;
if(value == NULL) {
json_object_append_object(json_parent, "result",
json_result(query_time, cgi, query, query_status,
(time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING,
"No value specified for %s option.", key));
return RESULT_OPTION_VALUE_MISSING;
}
for(svmp = (string_value_mapping *)svm; NULL != svmp->string; svmp++) {
if( !strcmp( svmp->string, value)) {
*var = svmp->value;
break;
}
}
if( NULL == svmp->string) {
json_object_append_object(json_parent, "result",
json_result(query_time, cgi, query, query_status,
(time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID,
"The %s option value '%s' is invalid.", key, value));
return RESULT_OPTION_VALUE_INVALID;
}
return RESULT_SUCCESS;
}
int parse_string_cgivar(char *cgi, char *query, int query_status,
json_object *json_parent, time_t query_time, authdata *authinfo,
char *key, char *value, char **var) {
if(value == NULL) {
json_object_append_object(json_parent, "result",
json_result(query_time, cgi, query, query_status,
(time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING,
"No value specified for %s option.", key));
return RESULT_OPTION_VALUE_MISSING;
}
if(NULL == (*var = strdup( value))) {
json_object_append_object(json_parent, "result",
json_result(query_time, cgi, query, query_status,
(time_t)-1, authinfo, RESULT_MEMORY_ALLOCATION_ERROR,
"Unable to allocate memory for %s option.", key));
return RESULT_MEMORY_ALLOCATION_ERROR;
}
return RESULT_SUCCESS;
}
int parse_time_cgivar(char *cgi, char *query, int query_status,
json_object *json_parent, time_t query_time, authdata *authinfo,
char *key, char *value, time_t *var) {
long long templl;
if(value == NULL) {
json_object_append_object(json_parent, "result",
json_result(query_time, cgi, query, query_status,
(time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING,
"No value specified for %s option.", key));
return RESULT_OPTION_VALUE_MISSING;
}
if('+' == value[0]) {
templl = strtoll(&(value[1]), NULL, 10);
*var = (time_t)((long long)query_time + templl);
}
else if('-' == value[0]) {
templl = strtoll(&(value[1]), NULL, 10);
*var = (time_t)((long long)query_time - templl);
}
else {
templl = strtoll(value, NULL, 10);
*var = (time_t)templl;
}
return RESULT_SUCCESS;
}
int parse_boolean_cgivar(char *cgi, char *query, int query_status,
json_object *json_parent, time_t query_time, authdata *authinfo,
char *key, char *value, int *var) {
if(value == NULL) {
json_object_append_object(json_parent, "result",
json_result(query_time, cgi, query, query_status,
(time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING,
"No value specified for %s option.", key));
return ERROR;
}
if(!strcmp(value, "true")) {
*var = 1;
}
else if(!strcmp(value, "false")) {
*var = 0;
}
else {
json_object_append_object(json_parent, "result",
json_result(query_time, cgi, query, query_status,
(time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID,
"Value for %s option must be 'true' or 'false'.", key));
return RESULT_OPTION_VALUE_INVALID;
}
return RESULT_SUCCESS;
}
int parse_int_cgivar(char *cgi, char *query, int query_status,
json_object *json_parent, time_t query_time, authdata *authinfo,
char *key, char *value, int *var) {
if(value == NULL) {
json_object_append_object(json_parent, "result",
json_result(query_time, cgi, query, query_status,
(time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING,
"No value specified for %s option.", key));
return RESULT_OPTION_VALUE_MISSING;
}
*var = atoi(value);
return RESULT_SUCCESS;
}
int get_query_status(const int statuses[][2], int query) {
int x;
for(x = 0; -1 != statuses[x][0]; x++) {
if(statuses[x][0] == query) return statuses[x][1];
}
return -1;
}
char *svm_get_string_from_value(int value, const string_value_mapping *svm) {
string_value_mapping *svmp;
for(svmp = (string_value_mapping *)svm; NULL != svmp->string; svmp++) {
if(svmp->value == value) return svmp->string;
}
return NULL;
}
char *svm_get_description_from_value(int value, const string_value_mapping *svm) {
string_value_mapping *svmp;
for(svmp = (string_value_mapping *)svm; NULL != svmp->string; svmp++) {
if(svmp->value == value) return svmp->description;
}
return NULL;
}
/* Thanks to Jerry Coffin for posting the basis of this function on Stack
Overflow */
time_t compile_time(const char *date, const char *time) {
char buf[5];
int year;
int month;
int day;
int hour;
int minute;
int second;
struct tm t;
const char *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
sscanf(date, "%s %d %d", buf, &day, &year);
sscanf(time, "%d:%d:%d", &hour, &minute, &second);
month = (strstr(months, buf) - months) / 3;
t.tm_year = year - 1900;
t.tm_mon = month;
t.tm_mday = day;
t.tm_hour = hour;
t.tm_min = minute;
t.tm_sec = second;
t.tm_isdst = -1;
return mktime(&t);
}
/* Escape a string based on the values in the escapes parameter */
char *json_escape_string(const char *src, const json_escape *escapes) {
wchar_t *wdest; /* wide character version of the output string */
size_t wdest_size; /* number of available wchars in wdest */
size_t wdest_len; /* number of wchars in wdest */
int x;
json_escape_pair *escp; /* pointer to current escape pair */
size_t from_len;
size_t to_len;
wchar_t *fromp; /* pointer to a found "from" string */
long offset; /* offset from beginning of wdest to a "from" string */
size_t wchars; /* number of wide characters to move */
size_t dest_len; /* length of output string "dest" */
char *dest; /* buffer containing the escaped version of src */
/* Make sure we're passed valid parameters */
if((NULL == src) || (NULL == escapes)) {
return NULL;
}
/* Make a wide string copy of src */
wdest_len = mbstowcs(NULL, src, 0);
if(wdest_len <= 0) return NULL;
if((wdest = calloc(wdest_len + 1, sizeof(wchar_t))) == NULL) {
return NULL;
}
if(mbstowcs(wdest, src, wdest_len) != wdest_len) {
free(wdest);
return NULL;
}
wdest_size = wdest_len;
/* Process each escape pair */
for(x = 0, escp = (json_escape_pair *)escapes->pairs; x < escapes->count;
x++, escp++) {
from_len = wcslen(escp->from);
to_len = wcslen(escp->to);
fromp = wdest;
while((fromp = wcsstr(fromp, escp->from)) != NULL) {
offset = fromp - wdest;
if(from_len < to_len) {
if((wdest_size - wdest_len) < (to_len - from_len)) {
/* If more room is needed, realloc and update variables */
wdest_size += (to_len - from_len) * BUF_REALLOC_MULTIPLIER;
wdest = realloc(wdest, (wdest_size + 1) * sizeof(wchar_t));
if(NULL == wdest) return NULL;
fromp = wdest + offset;
}
wchars = wdest_len - offset - from_len + 1;
wmemmove(fromp + to_len, fromp + from_len, wchars);
wcsncpy(fromp, escp->to, to_len);
wdest_len += (to_len - from_len);
fromp += to_len;
}
else {
wchars = wdest_len - offset - to_len;
memmove(fromp + to_len, fromp + from_len,
wchars * sizeof(wchar_t));
wcsncpy(fromp, escp->to, to_len);
fromp += (from_len - to_len);
wdest_len -= (from_len - to_len);
}
}
}
/* Covert the wide string back to a multibyte string */
dest_len = wcstombs(NULL, wdest, 0);
if(0 == dest_len) return NULL;
if((dest = calloc(dest_len + 1, sizeof(char))) == NULL) {
return NULL;
}
if(wcstombs(dest, wdest, dest_len) != dest_len) {
free(dest);
return NULL;
}
return dest;
}
nagios-4.4.6/cgi/notifications.c 0000664 0000000 0000000 00000062563 13652113235 0016601 0 ustar 00root root 0000000 0000000 /************************************************************************
*
* NOTIFICATIONS.C - Nagios Notifications CGI
*
*
* 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];
#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) {
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();
cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, 0);
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_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("
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
", (log_archive == 0) ? "the current" : "this archived");
}
free(input);
if(use_lifo == TRUE)
free_lifo_memory();
else
mmap_fclose(thefile);
return;
}
nagios-4.4.6/cgi/objectjson.c 0000664 0000000 0000000 00000626666 13652113235 0016102 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* OBJECTJSON.C - Nagios CGI for returning JSON-formatted object data
*
* Copyright (c) 2013 Nagios Enterprises, LLC
* Last Modified: 04-13-2013
*
* 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.
*************************************************************************/
/*
TODO:
Add code to display customvariables
Add sort criteria for *list queries
Add core3 flag for backward compatible display of flags that were
combined into a single variable in core4
Implement internationalized day of week, month names, and formats
for timeperiod details
Implement raw numbers for day of week, month for timeperiod details
*/
#include "../include/config.h"
#include "../include/common.h"
#include "../include/objects.h"
#include "../include/statusdata.h"
#include "../include/cgiutils.h"
#include "../include/getcgi.h"
#include "../include/cgiauth.h"
#include "../include/jsonutils.h"
#include "../include/objectjson.h"
#define THISCGI "objectjson.cgi"
extern char main_config_file[MAX_FILENAME_LENGTH];
extern char *status_file;
extern host *host_list;
extern hostgroup *hostgroup_list;
extern service *service_list;
extern servicegroup *servicegroup_list;
extern contact *contact_list;
extern contactgroup *contactgroup_list;
extern timeperiod *timeperiod_list;
extern command *command_list;
extern servicedependency *servicedependency_list;
extern serviceescalation *serviceescalation_list;
extern hostdependency *hostdependency_list;
extern hostescalation *hostescalation_list;
void document_header(int);
void document_footer(void);
void init_cgi_data(object_json_cgi_data *);
int process_cgivars(json_object *, object_json_cgi_data *, time_t);
void free_cgi_data(object_json_cgi_data *);
int validate_arguments(json_object *, object_json_cgi_data *, time_t);
authdata current_authdata;
const string_value_mapping valid_queries[] = {
{ "hostcount", OBJECT_QUERY_HOSTCOUNT,
"Return the number of hosts" },
{ "hostlist", OBJECT_QUERY_HOSTLIST,
"Return a list of hosts" },
{ "host", OBJECT_QUERY_HOST,
"Return the configuration for a single host" },
{ "hostgroupcount", OBJECT_QUERY_HOSTGROUPCOUNT,
"Return the number of host groups" },
{ "hostgrouplist", OBJECT_QUERY_HOSTGROUPLIST,
"Return a list of host groups" },
{ "hostgroup", OBJECT_QUERY_HOSTGROUP,
"Return the configuration for a single hostgroup" },
{ "servicecount", OBJECT_QUERY_SERVICECOUNT,
"Return a list of services" },
{ "servicelist", OBJECT_QUERY_SERVICELIST,
"Return a list of services" },
{ "service", OBJECT_QUERY_SERVICE,
"Return the configuration for a single service" },
{ "servicegroupcount", OBJECT_QUERY_SERVICEGROUPCOUNT,
"Return the number of service groups" },
{ "servicegrouplist", OBJECT_QUERY_SERVICEGROUPLIST,
"Return a list of service groups" },
{ "servicegroup", OBJECT_QUERY_SERVICEGROUP,
"Return the configuration for a single servicegroup" },
{ "contactcount", OBJECT_QUERY_CONTACTCOUNT,
"Return the number of contacts" },
{ "contactlist", OBJECT_QUERY_CONTACTLIST,
"Return a list of contacts" },
{ "contact", OBJECT_QUERY_CONTACT,
"Return the configuration for a single contact" },
{ "contactgroupcount", OBJECT_QUERY_CONTACTGROUPCOUNT,
"Return the number of contact groups" },
{ "contactgrouplist", OBJECT_QUERY_CONTACTGROUPLIST,
"Return a list of contact groups" },
{ "contactgroup", OBJECT_QUERY_CONTACTGROUP,
"Return the configuration for a single contactgroup" },
{ "timeperiodcount", OBJECT_QUERY_TIMEPERIODCOUNT,
"Return the number of time periods" },
{ "timeperiodlist", OBJECT_QUERY_TIMEPERIODLIST,
"Return a list of time periods" },
{ "timeperiod", OBJECT_QUERY_TIMEPERIOD,
"Return the configuration for a single timeperiod" },
{ "commandcount", OBJECT_QUERY_COMMANDCOUNT,
"Return the number of commands" },
{ "commandlist", OBJECT_QUERY_COMMANDLIST,
"Return a list of commands" },
{ "command", OBJECT_QUERY_COMMAND,
"Return the configuration for a single command" },
{ "servicedependencycount", OBJECT_QUERY_SERVICEDEPENDENCYCOUNT,
"Return the number of service dependencies" },
{ "servicedependencylist", OBJECT_QUERY_SERVICEDEPENDENCYLIST,
"Return a list of service dependencies" },
{ "serviceescalationcount", OBJECT_QUERY_SERVICEESCALATIONCOUNT,
"Return the number of service escalations" },
{ "serviceescalationlist", OBJECT_QUERY_SERVICEESCALATIONLIST,
"Return a list of service escalations" },
{ "hostdependencycount", OBJECT_QUERY_HOSTDEPENDENCYCOUNT,
"Return the number of host dependencies" },
{ "hostdependencylist", OBJECT_QUERY_HOSTDEPENDENCYLIST,
"Return a list of host dependencies" },
{ "hostescalationcount", OBJECT_QUERY_HOSTESCALATIONCOUNT,
"Return the number of host escalations" },
{ "hostescalationlist", OBJECT_QUERY_HOSTESCALATIONLIST,
"Return a list of host escalations" },
{ "help", OBJECT_QUERY_HELP,
"Display help for this CGI" },
{ NULL, -1, NULL },
};
static const int query_status[][2] = {
{ OBJECT_QUERY_HOSTCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_HOSTLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_HOST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_HOSTGROUPCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_HOSTGROUPLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_HOSTGROUP, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_SERVICECOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_SERVICELIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_SERVICE, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_SERVICEGROUPCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_SERVICEGROUPLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_SERVICEGROUP, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_CONTACTCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_CONTACTLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_CONTACT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_CONTACTGROUPCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_CONTACTGROUPLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_CONTACTGROUP, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_TIMEPERIODCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_TIMEPERIODLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_TIMEPERIOD, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_COMMANDCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_COMMANDLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_COMMAND, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_SERVICEDEPENDENCYCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_SERVICEDEPENDENCYLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_SERVICEESCALATIONCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_SERVICEESCALATIONLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_HOSTDEPENDENCYCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_HOSTDEPENDENCYLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_HOSTESCALATIONCOUNT, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_HOSTESCALATIONLIST, QUERY_STATUS_RELEASED },
{ OBJECT_QUERY_HELP, QUERY_STATUS_RELEASED },
{ -1, -1 },
};
option_help object_json_help[] = {
{
"query",
"Query",
"enumeration",
{ "all", NULL },
{ NULL },
NULL,
"Specifies the type of query to be executed.",
valid_queries
},
{
"formatoptions",
"Format Options",
"list",
{ NULL },
{ "all", NULL },
NULL,
"Specifies the formatting options to be used when displaying the results. Multiple options are allowed and are separated by a plus (+) sign..",
svm_format_options
},
{
"start",
"Start",
"integer",
{ NULL },
{ "hostlist", "hostgrouplist", "servicelist", "servicegrouplist", "contactlist", "contactgrouplist", "timeperiodlist", "commandlist", "servicedependencylist", "serviceescalationlist", "hostdependencylist", "hostescalationlist", NULL },
NULL,
"Specifies the index (zero-based) of the first object in the list to be returned.",
NULL
},
{
"count",
"Count",
"integer",
{ NULL },
{ "hostlist", "hostgrouplist", "servicelist", "servicegrouplist", "contactlist", "contactgrouplist", "timeperiodlist", "commandlist", "servicedependencylist", "serviceescalationlist", "hostdependencylist", "hostescalationlist", NULL },
NULL,
"Specifies the number of objects in the list to be returned.",
NULL
},
{
"dateformat",
"Date Format",
"string",
{ NULL },
{ "all", NULL },
NULL,
"strftime format string for values of type time_t. In the absence of a format, the Javascript default format of the number of milliseconds since the beginning of the Unix epoch is used. Because of URL encoding, percent signs must be encoded as %25 and a space must be encoded as a plus (+) sign.",
NULL
},
{
"parenthost",
"Parent Host",
"nagios:objectjson/hostlist",
{ NULL },
{ "hostcount", "hostlist", "servicecount", "servicelist", NULL },
NULL,
"Limits the hosts or services returned to those whose host parent is specified. A value of 'none' returns all hosts or services reachable directly by the Nagios core host.",
parent_host_extras
},
{
"childhost",
"Child Host",
"nagios:objectjson/hostlist",
{ NULL },
{ "hostcount", "hostlist", "servicecount", "servicelist", NULL },
NULL,
"Limits the hosts or services returned to those whose having the host specified as a child host. A value of 'none' returns all hosts or services with no child hosts.",
child_host_extras
},
{
"details",
"Show Details",
"boolean",
{ NULL },
{ "hostlist", "hostgrouplist", "servicelist", "servicegrouplist", "contactlist", "contactgrouplist", "timeperiodlist", "commandlist", NULL },
NULL,
"If true, return the details for all entities in the list.",
NULL
},
{
"hostname",
"Host Name",
"nagios:objectjson/hostlist",
{ "host", "service", NULL },
{ "servicecount", "servicelist", "hostescalationlist", "serviceescalationlist", NULL },
NULL,
"Name for the host requested.",
NULL
},
{
"hostgroupmember",
"Host Group Member",
"nagios:objectjson/hostlist",
{ NULL },
{ "hostgroupcount", "hostgrouplist", NULL },
NULL,
"Limits the hostgroups returned to those containing the hostgroupmember.",
NULL
},
{
"hostgroup",
"Host Group",
"nagios:objectjson/hostgrouplist",
{ "hostgroup", NULL },
{ "hostcount", "hostlist", "servicecount", "servicelist", "hostescalationcount", "hostescalationlist", "serviceescalationcount", "serviceescalationlist", NULL },
NULL,
"Returns information applicable to the hostgroup or the hosts in the hostgroup depending on the query.",
NULL
},
{
"servicegroup",
"Service Group",
"nagios:objectjson/servicegrouplist",
{ "servicegroup", NULL },
{ "servicecount", "servicelist", "serviceescalationcount", "serviceescalationlist", NULL },
NULL,
"Returns information applicable to the servicegroup or the services in the servicegroup depending on the query.",
NULL
},
{
"parentservice",
"Parent Service",
"nagios:objectjson/servicelist",
{ NULL },
{ "servicecount", "servicelist", NULL },
NULL,
"Limits the services returned to those whose service parent has the name specified. A value of 'none' returns all services with no service parent.",
parent_service_extras
},
{
"childservice",
"Child Service",
"nagios:objectjson/servicelist",
{ NULL },
{ "servicecount", "servicelist", NULL },
NULL,
"Limits the services returned to those whose having the named service as a child service. A value of 'none' returns all services with no child services.",
child_service_extras
},
{
"contactgroup",
"Contact Group",
"nagios:objectjson/contactgrouplist",
{ "contactgroup", NULL },
{ "hostcount", "hostlist", "servicecount", "servicelist", "contactcount", "contactlist", "serviceescalationcount", "serviceescalationlist", "hostescalationcount", "hostescalationlist", NULL },
NULL,
"Returns information applicable to the contactgroup or the contacts in the contactgroup depending on the query.",
NULL
},
{
"servicedescription",
"Service Description",
"nagios:objectjson/servicelist",
{ "service", NULL },
{ "servicecount", "servicelist", "serviceescalationcount", "serviceescalationlist", NULL },
"hostname",
"Description for the service requested.",
NULL
},
{
"servicegroupmemberhost",
"Service Group Member Host",
"nagios:objectjson/hostlist",
{ NULL },
{ "servicegroupcount", "servicegrouplist", NULL },
NULL,
"Limits the servicegroups returned to those containing the servicegroupmemberhost (and servicegroupmemberservice).",
NULL
},
{
"servicegroupmemberservice",
"Service Group Member Service",
"nagios:objectjson/servicelist",
{ NULL },
{ "servicegroupcount", "servicegrouplist", NULL },
"servicegroupmemberhost",
"Limits the servicegroups returned to those containing the servicegroupmemberservice (and servicegroupmemberhost).",
NULL
},
{
"contactname",
"Contact Name",
"nagios:objectjson/contactlist",
{ "contact", NULL },
{ "hostcount", "hostlist", "servicecount", "servicelist", "serviceescalationcount", "serviceescalationlist", "hostescalationcount", "hostescalationlist", NULL },
NULL,
"Name for the contact requested.",
NULL
},
{
"contactgroupmember",
"Contact Group Member",
"nagios:objectjson/contactlist",
{ NULL },
{ "contactgroupcount", "contactgrouplist", NULL },
NULL,
"Limits the contactgroups returned to those containing the contactgroupmember.",
NULL
},
{
"timeperiod",
"Timeperiod Name",
"nagios:objectjson/timeperiodlist",
{ "timeperiod", NULL },
{ NULL },
NULL,
"Name for the timeperiod requested.",
NULL
},
{
"checktimeperiod",
"Check Timeperiod Name",
"nagios:objectjson/timeperiodlist",
{ NULL },
{ "hostcount","hostlist", "servicecount", "servicelist", NULL },
NULL,
"Name of a check timeperiod to be used as selection criteria.",
NULL
},
{
"hostnotificationtimeperiod",
"Host Notification Timeperiod Name",
"nagios:objectjson/timeperiodlist",
{ NULL },
{ "hostcount","hostlist", "contactcount", "contactlist", NULL },
NULL,
"Name of a host notification timeperiod to be used as selection criteria.",
NULL
},
{
"servicenotificationtimeperiod",
"Service Notification Timeperiod Name",
"nagios:objectjson/timeperiodlist",
{ NULL },
{ "servicecount", "servicelist", "contactcount", "contactlist", NULL },
NULL,
"Name of a service notification timeperiod to be used as selection criteria.",
NULL
},
{
"command",
"Command Name",
"nagios:objectjson/commandlist",
{ "command", NULL },
{ NULL },
NULL,
"Name for the command requested.",
NULL
},
{
"checkcommand",
"Check Command Name",
"nagios:objectjson/commandlist",
{ NULL },
{ "hostcount", "hostlist", "servicecount", "servicelist", NULL },
NULL,
"Name of a check command to be be used as a selector.",
NULL
},
{
"eventhandler",
"Event Handler Name",
"nagios:objectjson/commandlist",
{ NULL },
{ "hostcount", "hostlist", "servicecount", "servicelist", NULL },
NULL,
"Name of an event handler to be be used as a selector.",
NULL
},
{
"masterhostname",
"Master Host Name",
"nagios:objectjson/hostlist",
{ NULL },
{ "hostdependencycount", "hostdependencylist", "servicedependencycount", "servicedependencylist", NULL },
NULL,
"Name for a master host to be used as a selector.",
NULL
},
{
"masterhostgroupname",
"Master Hostgroup Name",
"nagios:objectjson/hostgrouplist",
{ NULL },
{ "hostdependencycount", "hostdependencylist", "servicedependencycount", "servicedependencylist", NULL },
NULL,
"Name for a master hostgroup to be used as a selector.",
NULL
},
{
"masterservicedescription",
"Master Service Description",
"nagios:objectjson/servicelist",
{ NULL },
{ "servicedependencycount", "servicedependencylist", NULL },
"masterhostname",
"Description for a master service to be used as a selector.",
NULL
},
{
"masterservicegroupname",
"Master Servicegroup Name",
"nagios:objectjson/servicegrouplist",
{ NULL },
{ "servicedependencycount", "servicedependencylist", NULL },
NULL,
"Name for a master servicegroup to be used as a selector.",
NULL
},
{
"dependenthostname",
"Dependent Host Name",
"nagios:objectjson/hostlist",
{ NULL },
{ "hostdependencycount", "hostdependencylist", "servicedependencycount", "servicedependencylist", NULL },
NULL,
"Name for a dependent host to be used as a selector.",
NULL
},
{
"dependenthostgroupname",
"Dependent Hostgroup Name",
"nagios:objectjson/hostgrouplist",
{ NULL },
{ "hostdependencycount", "hostdependencylist", "servicedependencycount", "servicedependencylist", NULL },
NULL,
"Name for a dependent hostgroup to be used as a selector.",
NULL
},
{
"dependentservicedescription",
"Dependent Service Description",
"nagios:objectjson/servicelist",
{ NULL },
{ "servicedependencycount", "servicedependencylist", NULL },
"dependenthostname",
"Description for a dependent service to be used as a selector.",
NULL
},
{
"dependentservicegroupname",
"Dependent Servicegroup Name",
"nagios:objectjson/servicegrouplist",
{ NULL },
{ "servicedependencycount", "servicedependencylist", NULL },
NULL,
"Name for a dependent servicegroup to be used as a selector.",
NULL
},
{ /* The last entry must contain all NULL entries */
NULL,
NULL,
NULL,
{ NULL },
{ NULL },
NULL,
NULL,
NULL
},
};
extern const json_escape percent_escapes;
int json_object_host_passes_selection(host *, int, host *, int, host *,
hostgroup *, contact *, contactgroup *, timeperiod *, timeperiod *,
command *, command *);
json_object *json_object_host_selectors(int, int, int, host *, int, host *,
hostgroup *, contact *, contactgroup *, timeperiod *, timeperiod *,
command *, command *);
int json_object_hostgroup_passes_selection(hostgroup *, host *);
json_object *json_object_hostgroup_selectors(int, int, host *);
int json_object_service_passes_host_selection(host *, int, host *, int, host *,
hostgroup *, host *);
int json_object_service_passes_service_selection(service *, servicegroup *,
contact *, char *, char *, char *, contactgroup *, timeperiod *,
timeperiod *, command *, command *);
json_object *json_object_service_selectors(int, int, int, host *, int, host *,
hostgroup *, host *, servicegroup *, contact *, char *, char *, char *,
contactgroup *, timeperiod *, timeperiod *, command *, command *);
int json_object_servicegroup_passes_selection(servicegroup *, service *);
json_object *json_object_servicegroup_display_selectors(int, int, service *);
int json_object_contact_passes_selection(contact *, contactgroup *,
timeperiod *, timeperiod *);
json_object *json_object_contact_selectors(int, int, contactgroup *,
timeperiod *, timeperiod *);
int json_object_contactgroup_passes_selection(contactgroup *, contact *);
json_object *json_object_contactgroup_display_selectors(int, int, contact *);
json_object *json_object_timeperiod_selectors(int, int);
json_object *json_object_command_selectors(int, int);
int json_object_servicedependency_passes_selection(servicedependency *, host *,
hostgroup *, char *, servicegroup *, host *, hostgroup *, char *,
servicegroup *);
json_object *json_object_servicedependency_selectors(int, int, host *,
hostgroup *, char *, servicegroup *, host *, hostgroup *, char *,
servicegroup *);
int json_object_serviceescalation_passes_selection(serviceescalation *, host *,
char *, hostgroup *, servicegroup *, contact *, contactgroup *);
json_object *json_object_serviceescalation_selectors(int, int, host *, char *,
hostgroup *, servicegroup *, contact *, contactgroup *);
int json_object_hostdependency_passes_selection(hostdependency *, host *,
hostgroup *, host *, hostgroup *);
json_object *json_object_hostdependency_selectors(int, int, host *,
hostgroup *, host *, hostgroup *);
int json_object_hostescalation_passes_selection(hostescalation *, host *,
hostgroup *, contact *, contactgroup *);
json_object *json_object_hostescalation_selectors(int, int, host *,
hostgroup *, contact *, contactgroup *);
int main(void) {
int result = OK;
time_t query_time;
object_json_cgi_data cgi_data;
json_object *json_root;
struct stat ocstat;
time_t last_object_cache_update = (time_t)0;
/* The official time of the query */
time(&query_time);
json_root = json_new_object();
if(NULL == json_root) {
printf( "Failed to create new json object\n");
exit( 1);
}
json_object_append_integer(json_root, "format_version",
OUTPUT_FORMAT_VERSION);
/* Initialize shared configuration variables */
init_shared_cfg_vars(1);
init_cgi_data(&cgi_data);
document_header(cgi_data.format_options & JSON_FORMAT_WHITESPACE);
/* get the arguments passed in the URL */
result = process_cgivars(json_root, &cgi_data, query_time);
if(result != RESULT_SUCCESS) {
json_object_append_object(json_root, "data",
json_help(object_json_help));
json_object_print(json_root, 0, 1, cgi_data.strftime_format,
cgi_data.format_options);
document_footer();
return result;
}
/* reset internal variables */
reset_cgi_vars();
/* read the CGI configuration file */
result = read_cgi_config_file(get_cgi_config_location(), NULL);
if(result == ERROR) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR,
"Error: Could not open CGI configuration file '%s' for reading!",
get_cgi_config_location()));
json_object_append_object(json_root, "data", json_help(object_json_help));
json_object_print(json_root, 0, 1, cgi_data.strftime_format,
cgi_data.format_options);
document_footer();
return ERROR;
}
/* read the main configuration file */
result = read_main_config_file(main_config_file);
if(result == ERROR) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR,
"Error: Could not open main configuration file '%s' for reading!",
main_config_file));
json_object_append_object(json_root, "data", json_help(object_json_help));
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) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR,
"Error: Could not read some or all object configuration data!"));
json_object_append_object(json_root, "data", json_help(object_json_help));
document_footer();
return ERROR;
}
/* Get the update time on the object cache file */
if(stat(object_cache_file, &ocstat) < 0) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR,
"Error: Could not obtain object cache file status: %s!",
strerror(errno)));
json_object_append_object(json_root, "data", json_help(object_json_help));
document_footer();
return ERROR;
}
last_object_cache_update = ocstat.st_mtime;
/* read all status data */
result = read_all_status_data(status_file, READ_ALL_STATUS_DATA);
if(result == ERROR) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR,
"Error: Could not read host and service status information!"));
json_object_append_object(json_root, "data", json_help(object_json_help));
document_footer();
return ERROR;
}
/* validate arguments in URL */
result = validate_arguments(json_root, &cgi_data, query_time);
if(result != RESULT_SUCCESS) {
json_object_append_object(json_root, "data", json_help(object_json_help));
json_object_print(json_root, 0, 1, cgi_data.strftime_format,
cgi_data.format_options);
document_footer();
return ERROR;
}
/* get authentication information */
get_authentication_information(¤t_authdata);
/* For most locales, floats get output with a comma instead of a
* decimal point, which messes up the JSON data structure. */
setlocale(LC_NUMERIC, "C");
/* Return something to the user */
switch( cgi_data.query) {
case OBJECT_QUERY_HOSTCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_hostcount(cgi_data.use_parent_host,
cgi_data.parent_host, cgi_data.use_child_host,
cgi_data.child_host, cgi_data.hostgroup, cgi_data.contact,
cgi_data.contactgroup, cgi_data.check_timeperiod,
cgi_data.host_notification_timeperiod, cgi_data.check_command,
cgi_data.event_handler));
break;
case OBJECT_QUERY_HOSTLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_hostlist(cgi_data.format_options, cgi_data.start,
cgi_data.count, cgi_data.details, cgi_data.use_parent_host,
cgi_data.parent_host, cgi_data.use_child_host,
cgi_data.child_host, cgi_data.hostgroup, cgi_data.contact,
cgi_data.contactgroup, cgi_data.check_timeperiod,
cgi_data.host_notification_timeperiod, cgi_data.check_command,
cgi_data.event_handler));
break;
case OBJECT_QUERY_HOST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_host(cgi_data.format_options, cgi_data.host));
break;
case OBJECT_QUERY_HOSTGROUPCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_hostgroupcount(cgi_data.format_options,
cgi_data.hostgroup_member));
break;
case OBJECT_QUERY_HOSTGROUPLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_hostgrouplist(cgi_data.format_options,
cgi_data.start, cgi_data.count, cgi_data.details,
cgi_data.hostgroup_member));
break;
case OBJECT_QUERY_HOSTGROUP:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_hostgroup(cgi_data.format_options,
cgi_data.hostgroup));
break;
case OBJECT_QUERY_SERVICECOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_servicecount(cgi_data.host,
cgi_data.use_parent_host, cgi_data.parent_host,
cgi_data.use_child_host, cgi_data.child_host,
cgi_data.hostgroup, cgi_data.servicegroup, cgi_data.contact,
cgi_data.service_description, cgi_data.parent_service_name,
cgi_data.child_service_name, cgi_data.contactgroup,
cgi_data.check_timeperiod,
cgi_data.service_notification_timeperiod,
cgi_data.check_command, cgi_data.event_handler));
break;
case OBJECT_QUERY_SERVICELIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_servicelist(cgi_data.format_options, cgi_data.start,
cgi_data.count, cgi_data.details, cgi_data.host,
cgi_data.use_parent_host, cgi_data.parent_host,
cgi_data.use_child_host, cgi_data.child_host,
cgi_data.hostgroup, cgi_data.servicegroup, cgi_data.contact,
cgi_data.service_description, cgi_data.parent_service_name,
cgi_data.child_service_name, cgi_data.contactgroup,
cgi_data.check_timeperiod,
cgi_data.service_notification_timeperiod,
cgi_data.check_command, cgi_data.event_handler));
break;
case OBJECT_QUERY_SERVICE:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_service(cgi_data.format_options, cgi_data.service));
break;
case OBJECT_QUERY_SERVICEGROUPCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_servicegroupcount(cgi_data.servicegroup_member));
break;
case OBJECT_QUERY_SERVICEGROUPLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_servicegrouplist(cgi_data.format_options,
cgi_data.start, cgi_data.count, cgi_data.details,
cgi_data.servicegroup_member));
break;
case OBJECT_QUERY_SERVICEGROUP:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_servicegroup(cgi_data.format_options,
cgi_data.servicegroup));
break;
case OBJECT_QUERY_CONTACTCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_contactcount(cgi_data.contactgroup,
cgi_data.host_notification_timeperiod,
cgi_data.service_notification_timeperiod));
break;
case OBJECT_QUERY_CONTACTLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_contactlist(cgi_data.format_options, cgi_data.start,
cgi_data.count, cgi_data.details, cgi_data.contactgroup,
cgi_data.host_notification_timeperiod,
cgi_data.service_notification_timeperiod));
break;
case OBJECT_QUERY_CONTACT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_contact(cgi_data.format_options, cgi_data.contact));
break;
case OBJECT_QUERY_CONTACTGROUPCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_contactgroupcount(cgi_data.contactgroup_member));
break;
case OBJECT_QUERY_CONTACTGROUPLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_contactgrouplist(cgi_data.format_options,
cgi_data.start, cgi_data.count, cgi_data.details,
cgi_data.contactgroup_member));
break;
case OBJECT_QUERY_CONTACTGROUP:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_contactgroup(cgi_data.format_options,
cgi_data.contactgroup));
break;
case OBJECT_QUERY_TIMEPERIODCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_timeperiodcount());
break;
case OBJECT_QUERY_TIMEPERIODLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_timeperiodlist(cgi_data.format_options,
cgi_data.start, cgi_data.count, cgi_data.details));
break;
case OBJECT_QUERY_TIMEPERIOD:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_timeperiod(cgi_data.format_options,
cgi_data.timeperiod));
break;
case OBJECT_QUERY_COMMANDCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data", json_object_commandcount());
break;
case OBJECT_QUERY_COMMANDLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_commandlist(cgi_data.format_options, cgi_data.start,
cgi_data.count, cgi_data.details));
break;
case OBJECT_QUERY_COMMAND:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_command(cgi_data.format_options, cgi_data.command));
break;
case OBJECT_QUERY_SERVICEDEPENDENCYCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_servicedependencycount(cgi_data.master_host,
cgi_data.master_hostgroup, cgi_data.master_service_description,
cgi_data.master_servicegroup, cgi_data.dependent_host,
cgi_data.dependent_hostgroup,
cgi_data.dependent_service_description,
cgi_data.dependent_servicegroup));
break;
case OBJECT_QUERY_SERVICEDEPENDENCYLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_servicedependencylist(cgi_data.format_options,
cgi_data.start, cgi_data.count, cgi_data.master_host,
cgi_data.master_hostgroup, cgi_data.master_service_description,
cgi_data.master_servicegroup, cgi_data.dependent_host,
cgi_data.dependent_hostgroup,
cgi_data.dependent_service_description,
cgi_data.dependent_servicegroup));
break;
case OBJECT_QUERY_SERVICEESCALATIONCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_serviceescalationcount(cgi_data.host,
cgi_data.service_description, cgi_data.hostgroup,
cgi_data.servicegroup, cgi_data.contact,
cgi_data.contactgroup));
break;
case OBJECT_QUERY_SERVICEESCALATIONLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_serviceescalationlist(cgi_data.format_options,
cgi_data.start, cgi_data.count, cgi_data.host,
cgi_data.service_description, cgi_data.hostgroup,
cgi_data.servicegroup, cgi_data.contact,
cgi_data.contactgroup));
break;
case OBJECT_QUERY_HOSTDEPENDENCYCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_hostdependencycount(cgi_data.master_host,
cgi_data.master_hostgroup, cgi_data.dependent_host,
cgi_data.dependent_hostgroup));
break;
case OBJECT_QUERY_HOSTDEPENDENCYLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_hostdependencylist(cgi_data.format_options,
cgi_data.start, cgi_data.count, cgi_data.master_host,
cgi_data.master_hostgroup, cgi_data.dependent_host,
cgi_data.dependent_hostgroup));
break;
case OBJECT_QUERY_HOSTESCALATIONCOUNT:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_hostescalationcount(cgi_data.host,
cgi_data.hostgroup, cgi_data.contact, cgi_data.contactgroup));
break;
case OBJECT_QUERY_HOSTESCALATIONLIST:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
last_object_cache_update, ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data",
json_object_hostescalationlist(cgi_data.format_options,
cgi_data.start, cgi_data.count, cgi_data.host,
cgi_data.hostgroup, cgi_data.contact, cgi_data.contactgroup));
break;
case OBJECT_QUERY_HELP:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
compile_time(__DATE__, __TIME__), ¤t_authdata,
RESULT_SUCCESS, ""));
json_object_append_object(json_root, "data", json_help(object_json_help));
break;
default:
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data.query, valid_queries),
get_query_status(query_status, cgi_data.query),
(time_t)-1, ¤t_authdata, RESULT_OPTION_MISSING,
"Error: Object Type not specified. See data for help."));
json_object_append_object(json_root, "data", json_help(object_json_help));
break;
}
json_object_print(json_root, 0, 1, cgi_data.strftime_format,
cgi_data.format_options);
document_footer();
/* free all allocated memory */
free_cgi_data( &cgi_data);
json_free_object(json_root, 1);
free_memory();
return OK;
}
void document_header(int whitespace) {
char date_time[MAX_DATETIME_LENGTH];
time_t expire_time;
time_t current_time;
time(¤t_time);
printf("Cache-Control: no-store\r\n");
printf("Pragma: no-cache\r\n");
get_time_string(¤t_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: application/json; charset=utf-8\r\n\r\n");
return;
}
void document_footer(void) {
printf( "\n");
return;
}
void init_cgi_data(object_json_cgi_data *cgi_data) {
cgi_data->format_options = 0;
cgi_data->query = OBJECT_QUERY_INVALID;
cgi_data->start = 0;
cgi_data->count = 0;
cgi_data->details = 0;
cgi_data->strftime_format = NULL;
cgi_data->parent_host_name = NULL;
cgi_data->use_parent_host = 0;
cgi_data->parent_host = NULL;
cgi_data->child_host_name = NULL;
cgi_data->use_child_host = 0;
cgi_data->child_host = NULL;
cgi_data->host_name = NULL;
cgi_data->host = NULL;
cgi_data->hostgroup_member_name = NULL;
cgi_data->hostgroup_member = NULL;
cgi_data->hostgroup_name = NULL;
cgi_data->hostgroup = NULL;
cgi_data->servicegroup_name = NULL;
cgi_data->servicegroup = NULL;
cgi_data->service_description = NULL;
cgi_data->service = NULL;
cgi_data->servicegroup_member_host_name = NULL;
cgi_data->servicegroup_member_service_description = NULL;
cgi_data->servicegroup_member = NULL;
cgi_data->parent_service_name = NULL;
cgi_data->child_service_name = NULL;
cgi_data->contactgroup_name = NULL;
cgi_data->contactgroup = NULL;
cgi_data->contact_name = NULL;
cgi_data->contact = NULL;
cgi_data->contactgroup_member_name = NULL;
cgi_data->contactgroup_member = NULL;
cgi_data->timeperiod_name = NULL;
cgi_data->timeperiod = NULL;
cgi_data->check_timeperiod_name = NULL;
cgi_data->check_timeperiod = NULL;
cgi_data->host_notification_timeperiod_name = NULL;
cgi_data->host_notification_timeperiod = NULL;
cgi_data->service_notification_timeperiod_name = NULL;
cgi_data->service_notification_timeperiod = NULL;
cgi_data->command_name = NULL;
cgi_data->command = NULL;
cgi_data->check_command_name = NULL;
cgi_data->check_command = NULL;
cgi_data->event_handler_name = NULL;
cgi_data->event_handler = NULL;
cgi_data->master_host_name = NULL;
cgi_data->master_host = NULL;
cgi_data->master_hostgroup_name = NULL;
cgi_data->master_hostgroup = NULL;
cgi_data->master_service_description = NULL;
cgi_data->master_service = NULL;
cgi_data->master_servicegroup_name = NULL;
cgi_data->master_servicegroup = NULL;
cgi_data->dependent_host_name = NULL;
cgi_data->dependent_host = NULL;
cgi_data->dependent_hostgroup_name = NULL;
cgi_data->dependent_hostgroup = NULL;
cgi_data->dependent_service_description = NULL;
cgi_data->dependent_service = NULL;
cgi_data->dependent_servicegroup_name = NULL;
cgi_data->dependent_servicegroup = NULL;
}
void free_cgi_data( object_json_cgi_data *cgi_data) {
if( NULL != cgi_data->strftime_format) free( cgi_data->strftime_format);
if( NULL != cgi_data->parent_host_name) free( cgi_data->parent_host_name);
if( NULL != cgi_data->child_host_name) free( cgi_data->child_host_name);
if( NULL != cgi_data->host_name) free( cgi_data->host_name);
if( NULL != cgi_data->hostgroup_member_name) free( cgi_data->hostgroup_member_name);
if( NULL != cgi_data->hostgroup_name) free( cgi_data->hostgroup_name);
if( NULL != cgi_data->servicegroup_name) free(cgi_data->servicegroup_name);
if( NULL != cgi_data->service_description) free(cgi_data->service_description);
if( NULL != cgi_data->servicegroup_member_host_name) free(cgi_data->servicegroup_member_host_name);
if( NULL != cgi_data->servicegroup_member_service_description) free(cgi_data->servicegroup_member_service_description);
if( NULL != cgi_data->parent_service_name) free( cgi_data->parent_service_name);
if( NULL != cgi_data->child_service_name) free( cgi_data->child_service_name);
if( NULL != cgi_data->contactgroup_name) free(cgi_data->contactgroup_name);
if( NULL != cgi_data->contact_name) free(cgi_data->contact_name);
if( NULL != cgi_data->contactgroup_member_name) free(cgi_data->contactgroup_member_name);
if( NULL != cgi_data->timeperiod_name) free(cgi_data->timeperiod_name);
if( NULL != cgi_data->check_timeperiod_name) free(cgi_data->check_timeperiod_name);
if( NULL != cgi_data->host_notification_timeperiod_name) free(cgi_data->host_notification_timeperiod_name);
if( NULL != cgi_data->service_notification_timeperiod_name) free(cgi_data->service_notification_timeperiod_name);
if( NULL != cgi_data->command_name) free(cgi_data->command_name);
if( NULL != cgi_data->check_command_name) free(cgi_data->check_command_name);
if( NULL != cgi_data->event_handler_name) free(cgi_data->event_handler_name);
if( NULL != cgi_data->master_host_name) free(cgi_data->master_host_name);
if( NULL != cgi_data->master_hostgroup_name) free(cgi_data->master_hostgroup_name);
if( NULL != cgi_data->master_service_description) free(cgi_data->master_service_description);
if( NULL != cgi_data->master_servicegroup_name) free(cgi_data->master_servicegroup_name);
if( NULL != cgi_data->dependent_host_name) free(cgi_data->dependent_host_name);
if( NULL != cgi_data->dependent_hostgroup_name) free(cgi_data->dependent_hostgroup_name);
if( NULL != cgi_data->dependent_service_description) free(cgi_data->dependent_service_description);
if( NULL != cgi_data->dependent_servicegroup_name) free(cgi_data->dependent_servicegroup_name);
}
int process_cgivars(json_object *json_root, object_json_cgi_data *cgi_data,
time_t query_time) {
char **variables;
int result = RESULT_SUCCESS;
int x;
authdata *authinfo = NULL; /* Currently always NULL because
get_authentication_information() hasn't
been called yet, but in case we want to
use it in the future... */
variables = getcgivars();
for(x = 0; variables[x]; x++) {
/* We set these each iteration because they could change with each
iteration */
if(!strcmp(variables[x], "query")) {
if((result = parse_enumeration_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], valid_queries, &(cgi_data->query)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "formatoptions")) {
cgi_data->format_options = 0;
if((result = parse_bitmask_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], svm_format_options,
&(cgi_data->format_options))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "start")) {
if((result = parse_int_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->start))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "count")) {
if((result = parse_int_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->count))) != RESULT_SUCCESS) {
break;
}
if(cgi_data->count == 0) {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query,
valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID,
"The count option value is invalid. "
"It must be an integer greater than zero"));
result = RESULT_OPTION_VALUE_INVALID;
break;
}
x++;
}
else if(!strcmp(variables[x], "parenthost")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->parent_host_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "childhost")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->child_host_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "hostname")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->host_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "hostgroupmember")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->hostgroup_member_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "hostgroup")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->hostgroup_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "servicegroup")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->servicegroup_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "parentservice")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->parent_service_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "childservice")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->child_service_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "contactgroup")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->contactgroup_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "servicedescription")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->service_description)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "servicegroupmemberhost")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->servicegroup_member_host_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "servicegroupmemberservice")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1],
&(cgi_data->servicegroup_member_service_description)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "contactname")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->contact_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "contactgroupmember")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->contactgroup_member_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "timeperiod")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->timeperiod_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "checktimeperiod")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->check_timeperiod_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "hostnotificationtimeperiod")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1],
&(cgi_data->host_notification_timeperiod_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "servicenotificationtimeperiod")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1],
&(cgi_data->service_notification_timeperiod_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "command")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->command_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "checkcommand")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->check_command_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "eventhandler")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->event_handler_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "masterhostname")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->master_host_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "masterhostgroupname")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->master_hostgroup_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "masterservicedescription")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->master_service_description)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "masterservicegroupname")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->master_servicegroup_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "dependenthostname")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->dependent_host_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "dependenthostgroupname")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->dependent_hostgroup_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "dependentservicedescription")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->dependent_service_description)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "dependentservicegroupname")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->dependent_servicegroup_name)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "details")) {
if((result = parse_boolean_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->details))) != RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "dateformat")) {
if((result = parse_string_cgivar(THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
json_root, query_time, authinfo, variables[x],
variables[x+1], &(cgi_data->strftime_format)))
!= RESULT_SUCCESS) {
break;
}
x++;
}
else if(!strcmp(variables[x], "NagFormId"))
++x;
else if(!strcmp(variables[x], ""));
else {
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, RESULT_OPTION_INVALID,
"Invalid option: '%s'.", variables[x]));
result = RESULT_OPTION_INVALID;
break;
}
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return result;
}
int validate_arguments(json_object *json_root, object_json_cgi_data *cgi_data,
time_t query_time) {
int result = RESULT_SUCCESS;
host *temp_host = NULL;
hostgroup *temp_hostgroup = NULL;
servicegroup *temp_servicegroup = NULL;
service *temp_service = NULL;
contactgroup *temp_contactgroup = NULL;
contact *temp_contact = NULL;
timeperiod *temp_timeperiod = NULL;
command *temp_command = NULL;
authdata *authinfo = NULL; /* Currently always NULL because
get_authentication_information() hasn't
been called yet, but in case we want to
use it in the future... */
/* Validate that required parameters were supplied */
switch(cgi_data->query) {
case OBJECT_QUERY_HOSTCOUNT:
break;
case OBJECT_QUERY_HOSTLIST:
break;
case OBJECT_QUERY_HOST:
if( NULL == cgi_data->host_name) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Host information requested, but no host name specified."));
}
break;
case OBJECT_QUERY_HOSTGROUPCOUNT:
break;
case OBJECT_QUERY_HOSTGROUPLIST:
break;
case OBJECT_QUERY_HOSTGROUP:
if( NULL == cgi_data->hostgroup_name) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Hostgroup information requested, but no hostgroup name specified."));
}
break;
case OBJECT_QUERY_SERVICECOUNT:
break;
case OBJECT_QUERY_SERVICELIST:
break;
case OBJECT_QUERY_SERVICE:
if( NULL == cgi_data->host_name) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Service information requested, but no host name specified."));
}
if( NULL == cgi_data->service_description) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Service information requested, but no service description specified."));
}
break;
case OBJECT_QUERY_SERVICEGROUPCOUNT:
break;
case OBJECT_QUERY_SERVICEGROUPLIST:
break;
case OBJECT_QUERY_SERVICEGROUP:
if( NULL == cgi_data->servicegroup_name) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Service group information requested, but no service group name specified."));
}
break;
case OBJECT_QUERY_CONTACTCOUNT:
break;
case OBJECT_QUERY_CONTACTLIST:
break;
case OBJECT_QUERY_CONTACT:
if( NULL == cgi_data->contact_name) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Contact information requested, but no contact name specified."));
}
break;
case OBJECT_QUERY_CONTACTGROUPCOUNT:
break;
case OBJECT_QUERY_CONTACTGROUPLIST:
break;
case OBJECT_QUERY_CONTACTGROUP:
if( NULL == cgi_data->contactgroup_name) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Contactgroup information requested, but no contactgroup name specified."));
}
break;
case OBJECT_QUERY_TIMEPERIODCOUNT:
break;
case OBJECT_QUERY_TIMEPERIODLIST:
break;
case OBJECT_QUERY_TIMEPERIOD:
if( NULL == cgi_data->timeperiod_name) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Timeperiod information requested, but no timeperiod name specified."));
}
break;
case OBJECT_QUERY_COMMANDCOUNT:
break;
case OBJECT_QUERY_COMMANDLIST:
break;
case OBJECT_QUERY_COMMAND:
if( NULL == cgi_data->command_name) {
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Command information requested, but no command name specified."));
}
break;
case OBJECT_QUERY_SERVICEDEPENDENCYCOUNT:
break;
case OBJECT_QUERY_SERVICEDEPENDENCYLIST:
break;
case OBJECT_QUERY_SERVICEESCALATIONCOUNT:
break;
case OBJECT_QUERY_SERVICEESCALATIONLIST:
break;
case OBJECT_QUERY_HOSTDEPENDENCYCOUNT:
break;
case OBJECT_QUERY_HOSTDEPENDENCYLIST:
break;
case OBJECT_QUERY_HOSTESCALATIONCOUNT:
break;
case OBJECT_QUERY_HOSTESCALATIONLIST:
break;
case OBJECT_QUERY_HELP:
break;
default:
result = RESULT_OPTION_MISSING;
json_object_append_object(json_root, "result", json_result(query_time,
THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"Missing validation for object type %u.", cgi_data->query));
break;
}
/* Validate the requested parent host */
if( NULL != cgi_data->parent_host_name) {
cgi_data->use_parent_host = 1;
cgi_data->parent_host = NULL;
if(strcmp(cgi_data->parent_host_name, "none")) {
temp_host = find_host(cgi_data->parent_host_name);
if( NULL == temp_host) {
cgi_data->use_parent_host = 0;
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query,
valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The parenthost '%s' could not be found.",
cgi_data->parent_host_name));
}
else {
cgi_data->parent_host = temp_host;
}
}
}
/* Validate the requested child host */
if( NULL != cgi_data->child_host_name) {
cgi_data->use_child_host = 1;
cgi_data->child_host = NULL;
if(strcmp(cgi_data->child_host_name, "none")) {
temp_host = find_host(cgi_data->child_host_name);
if( NULL == temp_host) {
cgi_data->use_child_host = 0;
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query,
valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The childhost '%s' could not be found.",
cgi_data->child_host_name));
}
else {
cgi_data->child_host = temp_host;
}
}
}
/* Validate the requested host */
if( NULL != cgi_data->host_name) {
temp_host = find_host(cgi_data->host_name);
if( NULL == temp_host) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The host '%s' could not be found.", cgi_data->host_name));
}
else {
cgi_data->host = temp_host;
}
}
/* Validate the requested hostgroup member */
if( NULL != cgi_data->hostgroup_member_name) {
temp_host = find_host(cgi_data->hostgroup_member_name);
if( NULL == temp_host) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The hostgroup member '%s' could not be found.",
cgi_data->hostgroup_member_name));
}
else {
cgi_data->hostgroup_member = temp_host;
}
}
/* Validate the requested hostgroup */
if( NULL != cgi_data->hostgroup_name) {
temp_hostgroup = find_hostgroup(cgi_data->hostgroup_name);
if( NULL == temp_hostgroup) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The hostgroup '%s' could not be found.",
cgi_data->hostgroup_name));
}
else {
cgi_data->hostgroup = temp_hostgroup;
}
}
/* Validate the requested servicegroup */
if( NULL != cgi_data->servicegroup_name) {
temp_servicegroup = find_servicegroup(cgi_data->servicegroup_name);
if( NULL == temp_servicegroup) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The servicegroup '%s' could not be found.",
cgi_data->servicegroup_name));
}
else {
cgi_data->servicegroup = temp_servicegroup;
}
}
/* Validate the requested contactgroup */
if( NULL != cgi_data->contactgroup_name) {
temp_contactgroup = find_contactgroup(cgi_data->contactgroup_name);
if( NULL == temp_contactgroup) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The contactgroup '%s' could not be found.",
cgi_data->contactgroup_name));
}
else {
cgi_data->contactgroup = temp_contactgroup;
}
}
/* Validate the requested service. Note that the host name is not a
required parameter for all queries and so it may not make sense to
try to obtain the service associated with a service description */
if((NULL != cgi_data->service_description) &&
(NULL != cgi_data->host_name)) {
temp_service = find_service(cgi_data->host_name,
cgi_data->service_description);
if( NULL == temp_service) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The service '%s' on host '%s' could not be found.",
cgi_data->service_description, cgi_data->host_name));
}
else {
cgi_data->service = temp_service;
}
}
/* Validate the requested servicegroup member host name and service
description */
if( NULL != cgi_data->servicegroup_member_host_name ||
NULL != cgi_data->servicegroup_member_service_description) {
if( NULL == cgi_data->servicegroup_member_host_name ||
NULL == cgi_data->servicegroup_member_service_description) {
result = RESULT_OPTION_VALUE_MISSING;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"If either the servicegroupmemberhost or servicegroupmemberservice is specified, both must be specified."));
}
else {
temp_service = find_service( cgi_data->servicegroup_member_host_name,
cgi_data->servicegroup_member_service_description);
if( NULL == temp_service) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query,
valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The servicegroup member service '%s' on host '%s' could not be found.",
cgi_data->servicegroup_member_service_description,
cgi_data->servicegroup_member_host_name));
}
else {
cgi_data->servicegroup_member = temp_service;
}
}
}
/* Validate the requested contact */
if( NULL != cgi_data->contact_name) {
temp_contact = find_contact(cgi_data->contact_name);
if( NULL == temp_contact) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The contact '%s' could not be found.",
cgi_data->contact_name));
}
else {
cgi_data->contact = temp_contact;
}
}
/* Validate the requested contactgroup member */
if( NULL != cgi_data->contactgroup_member_name) {
temp_contact = find_contact(cgi_data->contactgroup_member_name);
if( NULL == temp_contact) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The contactgroup member '%s' could not be found.",
cgi_data->contactgroup_member_name));
}
else {
cgi_data->contactgroup_member = temp_contact;
}
}
/* Validate the requested timeperiod */
if( NULL != cgi_data->timeperiod_name) {
temp_timeperiod = find_timeperiod(cgi_data->timeperiod_name);
if( NULL == temp_timeperiod) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The timeperiod '%s' could not be found.",
cgi_data->timeperiod_name));
}
else {
cgi_data->timeperiod = temp_timeperiod;
}
}
/* Validate the requested check timeperiod */
if( NULL != cgi_data->check_timeperiod_name) {
temp_timeperiod = find_timeperiod(cgi_data->check_timeperiod_name);
if( NULL == temp_timeperiod) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The check timeperiod '%s' could not be found.",
cgi_data->check_timeperiod_name));
}
else {
cgi_data->check_timeperiod = temp_timeperiod;
}
}
/* Validate the requested host notification timeperiod */
if( NULL != cgi_data->host_notification_timeperiod_name) {
temp_timeperiod =
find_timeperiod(cgi_data->host_notification_timeperiod_name);
if( NULL == temp_timeperiod) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The host notification timeperiod '%s' could not be found.",
cgi_data->host_notification_timeperiod_name));
}
else {
cgi_data->host_notification_timeperiod = temp_timeperiod;
}
}
/* Validate the requested service notification timeperiod */
if( NULL != cgi_data->service_notification_timeperiod_name) {
temp_timeperiod =
find_timeperiod(cgi_data->service_notification_timeperiod_name);
if( NULL == temp_timeperiod) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The service notification timeperiod '%s' could not be found.",
cgi_data->service_notification_timeperiod_name));
}
else {
cgi_data->service_notification_timeperiod = temp_timeperiod;
}
}
/* Validate the requested command */
if( NULL != cgi_data->command_name) {
temp_command = find_command(cgi_data->command_name);
if( NULL == temp_command) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result, "The command '%s' could not be found.",
cgi_data->command_name));
}
else {
cgi_data->command = temp_command;
}
}
/* Validate the requested check command */
if( NULL != cgi_data->check_command_name) {
temp_command = find_command(cgi_data->check_command_name);
if( NULL == temp_command) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The check command '%s' could not be found.",
cgi_data->check_command_name));
}
else {
cgi_data->check_command = temp_command;
}
}
/* Validate the requested event handler */
if( NULL != cgi_data->event_handler_name) {
temp_command = find_command(cgi_data->event_handler_name);
if( NULL == temp_command) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The event handler '%s' could not be found.",
cgi_data->event_handler_name));
}
else {
cgi_data->event_handler = temp_command;
}
}
/* Validate the requested master host */
if( NULL != cgi_data->master_host_name) {
temp_host = find_host(cgi_data->master_host_name);
if( NULL == temp_host) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The master host '%s' could not be found.",
cgi_data->master_host_name));
}
else {
cgi_data->master_host = temp_host;
}
}
/* Validate the requested master hostgroup */
if( NULL != cgi_data->master_hostgroup_name) {
temp_hostgroup = find_hostgroup(cgi_data->master_hostgroup_name);
if( NULL == temp_hostgroup) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The master hostgroup '%s' could not be found.",
cgi_data->master_hostgroup_name));
}
else {
cgi_data->master_hostgroup = temp_hostgroup;
}
}
/* Validate the requested master servicegroup */
if( NULL != cgi_data->master_servicegroup_name) {
temp_servicegroup =
find_servicegroup(cgi_data->master_servicegroup_name);
if( NULL == temp_servicegroup) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The master servicegroup '%s' could not be found.",
cgi_data->master_servicegroup_name));
}
else {
cgi_data->master_servicegroup = temp_servicegroup;
}
}
/* Validate the requested dependent host */
if( NULL != cgi_data->dependent_host_name) {
temp_host = find_host(cgi_data->dependent_host_name);
if( NULL == temp_host) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The dependent host '%s' could not be found.",
cgi_data->dependent_host_name));
}
else {
cgi_data->dependent_host = temp_host;
}
}
/* Validate the requested dependent hostgroup */
if( NULL != cgi_data->dependent_hostgroup_name) {
temp_hostgroup = find_hostgroup(cgi_data->dependent_hostgroup_name);
if( NULL == temp_hostgroup) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The dependent hostgroup '%s' could not be found.",
cgi_data->dependent_hostgroup_name));
}
else {
cgi_data->dependent_hostgroup = temp_hostgroup;
}
}
/* Validate the requested dependent servicegroup */
if( NULL != cgi_data->dependent_servicegroup_name) {
temp_servicegroup =
find_servicegroup(cgi_data->dependent_servicegroup_name);
if( NULL == temp_servicegroup) {
result = RESULT_OPTION_VALUE_INVALID;
json_object_append_object(json_root, "result",
json_result(query_time, THISCGI,
svm_get_string_from_value(cgi_data->query, valid_queries),
get_query_status(query_status, cgi_data->query),
(time_t)-1, authinfo, result,
"The dependent servicegroup '%s' could not be found.",
cgi_data->dependent_servicegroup_name));
}
else {
cgi_data->dependent_servicegroup = temp_servicegroup;
}
}
return result;
}
json_object * json_object_custom_variables(struct customvariablesmember *custom_variables) {
json_object *json_custom_variables;
customvariablesmember *temp_custom_variablesmember;
json_custom_variables = json_new_object();
for(temp_custom_variablesmember = custom_variables;
temp_custom_variablesmember != NULL;
temp_custom_variablesmember = temp_custom_variablesmember->next) {
json_object_append_string(json_custom_variables,
temp_custom_variablesmember->variable_name, &percent_escapes,
temp_custom_variablesmember->variable_value);
}
return json_custom_variables;
}
int json_object_host_passes_selection(host *temp_host, int use_parent_host,
host *parent_host, int use_child_host, host *child_host,
hostgroup *temp_hostgroup, contact *temp_contact,
contactgroup *temp_contactgroup, timeperiod *check_timeperiod,
timeperiod *notification_timeperiod, command *check_command,
command *event_handler) {
host *temp_host2;
/* Skip if user is not authorized for this host */
if(FALSE == is_authorized_for_host(temp_host, ¤t_authdata)) {
return 0;
}
/* If the host parent was specified, skip this host if it's parent is
not the parent host specified */
if( 1 == use_parent_host &&
FALSE == is_host_immediate_child_of_host(parent_host, temp_host)) {
return 0;
}
/* If the hostgroup was specified, skip this host if it is not a member
of the hostgroup specified */
if( NULL != temp_hostgroup &&
( FALSE == is_host_member_of_hostgroup(temp_hostgroup,
temp_host))) {
return 0;
}
/* If the contact was specified, skip this host if it does not have
the contact specified */
if( NULL != temp_contact &&
( FALSE == is_contact_for_host(temp_host, temp_contact))) {
return 0;
}
/* If a contactgroup was specified, skip this host if it does not have
the contactgroup specified */
if(NULL != temp_contactgroup &&
(FALSE == is_contactgroup_for_host(temp_host, temp_contactgroup))) {
return 0;
}
/* If a check timeperiod was specified, skip this host if it does not have
the check timeperiod specified */
if(NULL != check_timeperiod &&
(check_timeperiod != temp_host->check_period_ptr)) {
return 0;
}
/* If a notification timeperiod was specified, skip this host if it
does not have the notification timeperiod specified */
if(NULL != notification_timeperiod &&
(notification_timeperiod != temp_host->notification_period_ptr)) {
return 0;
}
/* If a check command was specified, skip this host if it does not
have the check command specified */
if(NULL != check_command &&
(check_command != temp_host->check_command_ptr)) {
return 0;
}
/* If an event handler was specified, skip this host if it does not
have the event handler specified */
if(NULL != event_handler &&
(event_handler != temp_host->event_handler_ptr)) {
return 0;
}
/* If a child host was specified... */
if(1 == use_child_host) {
/* If the child host is "none", skip this host if it has children */
if(NULL == child_host) {
for(temp_host2 = host_list; temp_host2 != NULL;
temp_host2 = temp_host2->next) {
if(TRUE == is_host_immediate_child_of_host(temp_host,
temp_host2)) {
return 0;
}
}
}
/* Otherwise, skip this host if it does not have the specified host
as a child */
else if(FALSE == is_host_immediate_child_of_host(temp_host, child_host)) {
return 0;
}
}
return 1;
}
json_object * json_object_host_selectors(int start, int count,
int use_parent_host, host *parent_host, int use_child_host,
host *child_host, hostgroup *temp_hostgroup, contact *temp_contact,
contactgroup *temp_contactgroup, timeperiod *check_timeperiod,
timeperiod *notification_timeperiod, command *check_command,
command *event_handler) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if( 1 == use_parent_host) {
json_object_append_string(json_selectors, "parenthost",
&percent_escapes,
( NULL == parent_host ? "none" : parent_host->name));
}
if( 1 == use_child_host) {
json_object_append_string(json_selectors, "childhost", &percent_escapes,
( NULL == child_host ? "none" : child_host->name));
}
if( NULL != temp_hostgroup) {
json_object_append_string(json_selectors, "hostgroup", &percent_escapes,
temp_hostgroup->group_name);
}
if( NULL != temp_contact) {
json_object_append_string(json_selectors, "contact", &percent_escapes,
temp_contact->name);
}
if( NULL != temp_contactgroup) {
json_object_append_string(json_selectors, "contactgroup",
&percent_escapes, temp_contactgroup->group_name);
}
if( NULL != check_timeperiod) {
json_object_append_string(json_selectors, "checktimeperiod",
&percent_escapes, check_timeperiod->name);
}
if( NULL != notification_timeperiod) {
json_object_append_string(json_selectors, "hostnotificationtimeperiod",
&percent_escapes, notification_timeperiod->name);
}
if( NULL != check_command) {
json_object_append_string(json_selectors, "checkcommand",
&percent_escapes, check_command->name);
}
if( NULL != event_handler) {
json_object_append_string(json_selectors, "eventhandler",
&percent_escapes, event_handler->name);
}
return json_selectors;
}
json_object * json_object_hostcount(int use_parent_host, host *parent_host,
int use_child_host, host *child_host, hostgroup *temp_hostgroup,
contact *temp_contact, contactgroup *temp_contactgroup,
timeperiod *check_timeperiod, timeperiod *notification_timeperiod,
command *check_command, command *event_handler) {
json_object *json_data;
host *temp_host;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_host_selectors(0, 0, use_parent_host, parent_host,
use_child_host, child_host, temp_hostgroup, temp_contact,
temp_contactgroup, check_timeperiod, notification_timeperiod,
check_command, event_handler));
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(json_object_host_passes_selection(temp_host, use_parent_host,
parent_host, use_child_host, child_host, temp_hostgroup,
temp_contact, temp_contactgroup, check_timeperiod,
notification_timeperiod, check_command, event_handler) == 0) {
continue;
}
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object * json_object_hostlist(unsigned format_options, int start,
int count, int details, int use_parent_host, host *parent_host,
int use_child_host, host *child_host, hostgroup *temp_hostgroup,
contact *temp_contact, contactgroup *temp_contactgroup,
timeperiod *check_timeperiod, timeperiod *notification_timeperiod,
command *check_command, command *event_handler) {
json_object *json_data;
json_object *json_hostlist_object = NULL;
json_array *json_hostlist_array = NULL;
json_object *json_host_details;
host *temp_host;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_host_selectors(start, count, use_parent_host,
parent_host, use_child_host, child_host, temp_hostgroup,
temp_contact, temp_contactgroup, check_timeperiod,
notification_timeperiod, check_command, event_handler));
if(details > 0) {
json_hostlist_object = json_new_object();
}
else {
json_hostlist_array = json_new_array();
}
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(json_object_host_passes_selection(temp_host, use_parent_host,
parent_host, use_child_host, child_host, temp_hostgroup,
temp_contact, temp_contactgroup, check_timeperiod,
notification_timeperiod, check_command, event_handler) == 0) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
if( details > 0) {
json_host_details = json_new_object();
json_object_host_details(json_host_details, format_options,
temp_host);
json_object_append_object(json_hostlist_object, temp_host->name,
json_host_details);
}
else {
json_array_append_string(json_hostlist_array, &percent_escapes,
temp_host->name);
}
counted++;
}
current++;
}
if(details > 0) {
json_object_append_object(json_data, "hostlist", json_hostlist_object);
}
else {
json_object_append_array(json_data, "hostlist", json_hostlist_array);
}
return json_data;
}
json_object *json_object_host(unsigned format_options, host *temp_host) {
json_object *json_host = json_new_object();
json_object *json_details = json_new_object();
json_object_append_string(json_details, "name", &percent_escapes,
temp_host->name);
json_object_host_details(json_details, format_options, temp_host);
json_object_append_object(json_host, "host", json_details);
return json_host;
}
void json_object_host_details(json_object *json_details, unsigned format_options,
host *temp_host) {
json_array *json_parent_hosts;
json_array *json_child_hosts;
json_array *json_services;
json_array *json_contactgroups;
json_array *json_contacts;
hostsmember *temp_hostsmember;
servicesmember *temp_servicesmember;
contactgroupsmember *temp_contact_groupsmember;
#ifdef NSCORE
contactsmember *temp_contactsmember;
#else
contact *temp_contact;
#endif
json_object_append_string(json_details, "name", &percent_escapes,
temp_host->name);
json_object_append_string(json_details, "display_name", &percent_escapes,
temp_host->display_name);
json_object_append_string(json_details, "alias", &percent_escapes,
temp_host->alias);
json_object_append_string(json_details, "address", &percent_escapes,
temp_host->address);
json_parent_hosts = json_new_array();
for(temp_hostsmember = temp_host->parent_hosts; temp_hostsmember != NULL;
temp_hostsmember = temp_hostsmember->next) {
json_array_append_string(json_parent_hosts, &percent_escapes,
temp_hostsmember->host_name);
}
json_object_append_array(json_details, "parent_hosts", json_parent_hosts);
json_child_hosts = json_new_array();
for(temp_hostsmember = temp_host->child_hosts; temp_hostsmember != NULL;
temp_hostsmember = temp_hostsmember->next) {
json_array_append_string(json_child_hosts, &percent_escapes,
temp_hostsmember->host_name);
}
json_object_append_array(json_details, "child_hosts", json_child_hosts);
json_services = json_new_array();
for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL;
temp_servicesmember = temp_servicesmember->next) {
json_array_append_string(json_services, &percent_escapes,
temp_servicesmember->service_description);
}
json_object_append_array(json_details, "services", json_services);
#ifdef JSON_NAGIOS_4X
json_object_append_string(json_details, "check_command", &percent_escapes,
temp_host->check_command);
#else
json_object_append_string(json_details, "host_check_command",
&percent_escapes, temp_host->host_check_command);
#endif
json_enumeration(json_details, format_options, "initial_state",
temp_host->initial_state, svm_host_states);
json_object_append_real(json_details, "check_interval",
temp_host->check_interval);
json_object_append_real(json_details, "retry_interval",
temp_host->retry_interval);
json_object_append_integer(json_details, "max_attempts",
temp_host->max_attempts);
json_object_append_string(json_details, "event_handler", &percent_escapes,
temp_host->event_handler);
json_contactgroups = json_new_array();
for(temp_contact_groupsmember = temp_host->contact_groups;
temp_contact_groupsmember != NULL;
temp_contact_groupsmember = temp_contact_groupsmember->next) {
json_array_append_string(json_contactgroups, &percent_escapes,
temp_contact_groupsmember->group_name);
}
json_object_append_array(json_details, "contact_groups", json_contactgroups);
json_contacts = json_new_array();
#ifdef NSCORE
for(temp_contactsmember = temp_host->contacts;
temp_contactsmember != NULL;
temp_contactsmember = temp_contactsmember->next) {
json_array_append_string(json_contacts, &percent_escapes,
temp_contactsmember->contact_name);
}
#else
for(temp_contact = contact_list; temp_contact != NULL;
temp_contact = temp_contact->next) {
if(TRUE == is_contact_for_host(temp_host, temp_contact)) {
json_array_append_string(json_contacts, &percent_escapes,
temp_contact->name);
}
}
#endif
json_object_append_array(json_details, "contacts", json_contacts);
json_object_append_real(json_details, "notification_interval",
temp_host->notification_interval);
json_object_append_real(json_details, "first_notification_delay",
temp_host->first_notification_delay);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "notify_on_down",
flag_isset(temp_host->notification_options, OPT_DOWN));
json_object_append_boolean(json_details, "notify_on_unreachable",
flag_isset(temp_host->notification_options, OPT_UNREACHABLE));
json_object_append_boolean(json_details, "notify_on_recovery",
flag_isset(temp_host->notification_options, OPT_RECOVERY));
json_object_append_boolean(json_details, "notify_on_flapping",
flag_isset(temp_host->notification_options, OPT_FLAPPING));
json_object_append_boolean(json_details, "notify_on_downtime",
flag_isset(temp_host->notification_options, OPT_DOWNTIME));
}
else {
#endif
json_bitmask(json_details, format_options, "notifications_options",
temp_host->notification_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "notify_on_down",
temp_host->notify_on_down);
json_object_append_boolean(json_details, "notify_on_unreachable",
temp_host->notify_on_unreachable);
json_object_append_boolean(json_details, "notify_on_recovery",
temp_host->notify_on_recovery);
json_object_append_boolean(json_details, "notify_on_flapping",
temp_host->notify_on_flapping);
json_object_append_boolean(json_details, "notify_on_downtime",
temp_host->notify_on_downtime);
#endif
json_object_append_string(json_details, "notification_period",
&percent_escapes, temp_host->notification_period);
json_object_append_string(json_details, "check_period", &percent_escapes,
temp_host->check_period);
json_object_append_boolean(json_details, "flap_detection_enabled",
temp_host->flap_detection_enabled);
json_object_append_real(json_details, "low_flap_threshold",
temp_host->low_flap_threshold);
json_object_append_real(json_details, "high_flap_threshold",
temp_host->high_flap_threshold);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details "flap_detection_on_up",
flag_isset(temp_host->flap_detection_options, OPT_UP));
json_object_append_boolean(json_details "flap_detection_on_down",
flag_isset(temp_host->flap_detection_options, OPT_DOWN));
json_object_append_boolean(json_details "flap_detection_on_unreachable",
flag_isset(temp_host->flap_detection_options, OPT_UNREACHABLE));
}
else {
#endif
json_bitmask(json_details, format_options, "flap_detection_options",
temp_host->flap_detection_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "flap_detection_on_up",
temp_host->flap_detection_on_up);
json_object_append_boolean(json_details, "flap_detection_on_down",
temp_host->flap_detection_on_down);
json_object_append_boolean(json_details, "flap_detection_on_unreachable",
temp_host->flap_detection_on_unreachable);
#endif
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "stalk_on_up",
flag_isset(temp_host->stalking_options, OPT_UP));
json_object_append_boolean(json_details, "stalk_on_down",
flag_isset(temp_host->stalking_options, OPT_DOWN));
json_object_append_boolean(json_details, "stalk_on_unreachable",
flag_isset(temp_host->stalking_options, OPT_UNREACHABLE));
}
else {
#endif
json_bitmask(json_details, format_options, "stalking_options",
temp_host->stalking_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "stalk_on_up",
temp_host->stalk_on_up);
json_object_append_boolean(json_details, "stalk_on_down",
temp_host->stalk_on_down);
json_object_append_boolean(json_details, "stalk_on_unreachable",
temp_host->stalk_on_unreachable);
#endif
json_object_append_boolean(json_details, "check_freshness",
temp_host->check_freshness);
json_object_append_integer(json_details, "freshness_threshold",
temp_host->freshness_threshold);
json_object_append_boolean(json_details, "process_performance_data",
temp_host->process_performance_data);
json_object_append_boolean(json_details, "checks_enabled",
temp_host->checks_enabled);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "accept_passive_host_checks",
temp_host->accept_passive_checks);
}
else {
#endif
json_object_append_boolean(json_details, "accept_passive_checks",
temp_host->accept_passive_checks);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "accept_passive_host_checks",
temp_host->accept_passive_host_checks);
#endif
json_object_append_boolean(json_details, "event_handler_enabled",
temp_host->event_handler_enabled);
json_object_append_boolean(json_details, "retain_status_information",
temp_host->retain_status_information);
json_object_append_boolean(json_details, "retain_nonstatus_information",
temp_host->retain_nonstatus_information);
#ifndef JSON_NAGIOS_4X
json_object_append_boolean(json_details, "failure_prediction_enabled",
temp_host->failure_prediction_enabled);
json_object_append_string(json_details, "failure_prediction_options",
NULL, temp_host->failure_prediction_options);
#endif
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "obsess_over_host",
temp_host->obsess);
}
else {
#endif
json_object_append_boolean(json_details, "obsess", temp_host->obsess);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "obsess_over_host",
temp_host->obsess_over_host);
#endif
#ifdef JSON_NAGIOS_4X
json_object_append_integer(json_details, "hourly_value",
temp_host->hourly_value);
#endif
json_object_append_string(json_details, "notes", &percent_escapes,
temp_host->notes);
json_object_append_string(json_details, "notes_url", &percent_escapes,
temp_host->notes_url);
json_object_append_string(json_details, "action_url", &percent_escapes,
temp_host->action_url);
json_object_append_string(json_details, "icon_image", &percent_escapes,
temp_host->icon_image);
json_object_append_string(json_details, "icon_image_alt", &percent_escapes,
temp_host->icon_image_alt);
json_object_append_string(json_details, "vrml_image", &percent_escapes,
temp_host->vrml_image);
json_object_append_string(json_details, "statusmap_image", &percent_escapes,
temp_host->statusmap_image);
json_object_append_boolean(json_details, "have_2d_coords",
temp_host->have_2d_coords);
json_object_append_integer(json_details, "x_2d", temp_host->x_2d);
json_object_append_integer(json_details, "y_2d", temp_host->y_2d);
json_object_append_boolean(json_details, "have_3d_coords",
temp_host->have_3d_coords);
json_object_append_real(json_details, "x_3d", temp_host->x_3d);
json_object_append_real(json_details, "y_3d", temp_host->y_3d);
json_object_append_real(json_details, "z_3d", temp_host->z_3d);
json_object_append_boolean(json_details, "should_be_drawn",
temp_host->should_be_drawn);
json_object_append_object(json_details, "custom_variables",
json_object_custom_variables(temp_host->custom_variables));
}
int json_object_hostgroup_passes_selection(hostgroup *temp_hostgroup,
host *temp_hostgroup_member) {
/* Skip if user is not authorized for this hostgroup */
if(FALSE == is_authorized_for_hostgroup(temp_hostgroup,
¤t_authdata)) {
return 0;
}
/* Skip if a hostgroup member is specified and the hostgroup member
host is not a member of the hostgroup */
if( NULL != temp_hostgroup_member &&
( FALSE == is_host_member_of_hostgroup(temp_hostgroup,
temp_hostgroup_member))) {
return 0;
}
return 1;
}
json_object *json_object_hostgroup_selectors(int start, int count,
host *temp_hostgroup_member) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if( NULL != temp_hostgroup_member) {
json_object_append_string(json_selectors, "hostgroupmember",
&percent_escapes, temp_hostgroup_member->name);
}
return json_selectors;
}
json_object *json_object_hostgroupcount(unsigned format_options,
host *temp_hostgroup_member) {
json_object *json_data;
hostgroup *temp_hostgroup;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_hostgroup_selectors(0, 0, temp_hostgroup_member));
for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL;
temp_hostgroup = temp_hostgroup->next) {
if(json_object_hostgroup_passes_selection(temp_hostgroup,
temp_hostgroup_member) == 0) {
continue;
}
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_hostgrouplist(unsigned format_options, int start,
int count, int details, host *temp_hostgroup_member) {
json_object *json_data;
json_object *json_hostgrouplist_object = NULL;
json_array *json_hostgrouplist_array = NULL;
json_object *json_hostgroup_details;
hostgroup *temp_hostgroup;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_hostgroup_selectors(start, count,
temp_hostgroup_member));
if(details > 0) {
json_hostgrouplist_object = json_new_object();
}
else {
json_hostgrouplist_array = json_new_array();
}
for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL;
temp_hostgroup = temp_hostgroup->next) {
if(json_object_hostgroup_passes_selection(temp_hostgroup,
temp_hostgroup_member) == 0) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
if( details > 0) {
json_hostgroup_details = json_new_object();
json_object_hostgroup_details(json_hostgroup_details,
format_options, temp_hostgroup);
json_object_append_object(json_hostgrouplist_object,
temp_hostgroup->group_name, json_hostgroup_details);
}
else {
json_array_append_string(json_hostgrouplist_array,
&percent_escapes, temp_hostgroup->group_name);
}
counted++;
}
current++;
}
if(details > 0) {
json_object_append_object(json_data, "hostgrouplist",
json_hostgrouplist_object);
}
else {
json_object_append_array(json_data, "hostgrouplist",
json_hostgrouplist_array);
}
return json_data;
}
json_object *json_object_hostgroup(unsigned format_options,
hostgroup *temp_hostgroup) {
json_object *json_hostgroup = json_new_object();
json_object *json_details = json_new_object();
json_object_append_string(json_details, "group_name", &percent_escapes,
temp_hostgroup->group_name);
json_object_hostgroup_details(json_details, format_options, temp_hostgroup);
json_object_append_object(json_hostgroup, "hostgroup", json_details);
return json_hostgroup;
}
void json_object_hostgroup_details(json_object *json_details,
unsigned format_options, hostgroup *temp_hostgroup) {
json_array *json_members;
hostsmember *temp_member;
json_object_append_string(json_details, "group_name", &percent_escapes,
temp_hostgroup->group_name);
json_object_append_string(json_details, "alias", &percent_escapes,
temp_hostgroup->alias);
json_members = json_new_array();
for(temp_member = temp_hostgroup->members; temp_member != NULL;
temp_member = temp_member->next) {
json_array_append_string(json_members, &percent_escapes,
temp_member->host_name);
}
json_object_append_array(json_details, "members", json_members);
json_object_append_string(json_details, "notes", &percent_escapes,
temp_hostgroup->notes);
json_object_append_string(json_details, "notes_url", &percent_escapes,
temp_hostgroup->notes_url);
json_object_append_string(json_details, "action_url", &percent_escapes,
temp_hostgroup->action_url);
}
int json_object_service_passes_host_selection(host *temp_host,
int use_parent_host, host *parent_host, int use_child_host,
host *child_host, hostgroup *temp_hostgroup, host *match_host) {
host *temp_host2;
/* Skip if user is not authorized for this host */
if(FALSE == is_authorized_for_host(temp_host, ¤t_authdata)) {
return 0;
}
/* If the host parent was specified, skip the services whose host is
not a child of the parent host specified */
if( 1 == use_parent_host && NULL != temp_host &&
FALSE == is_host_immediate_child_of_host(parent_host, temp_host)) {
return 0;
}
/* If the hostgroup was specified, skip the services on hosts that
are not members of the hostgroup specified */
if( NULL != temp_hostgroup && NULL != temp_host &&
( FALSE == is_host_member_of_hostgroup(temp_hostgroup,
temp_host))) {
return 0;
}
/* If the host was specified, skip the services not on the host
specified */
if( NULL != match_host && NULL != temp_host && temp_host != match_host) {
return 0;
}
/* If a child host was specified... */
if(1 == use_child_host) {
/* If the child host is "none", skip this host if it has children */
if(NULL == child_host) {
for(temp_host2 = host_list; temp_host2 != NULL;
temp_host2 = temp_host2->next) {
if(TRUE == is_host_immediate_child_of_host(temp_host,
temp_host2)) {
return 0;
}
}
}
/* Otherwise, skip this host if it does not have the specified host
as a child */
else if(FALSE == is_host_immediate_child_of_host(temp_host, child_host)) {
return 0;
}
}
return 1;
}
int json_object_service_passes_service_selection(service *temp_service,
servicegroup *temp_servicegroup, contact *temp_contact,
char *service_description, char *parent_service_name,
char *child_service_name, contactgroup *temp_contactgroup,
timeperiod *check_timeperiod, timeperiod *notification_timeperiod,
command *check_command, command *event_handler) {
servicesmember *temp_servicesmember;
/* Skip if user is not authorized for this service */
if(FALSE == is_authorized_for_service(temp_service, ¤t_authdata)) {
return 0;
}
/* If the servicegroup was specified, skip the services that are not
members of the servicegroup specified */
if( NULL != temp_servicegroup &&
( FALSE == is_service_member_of_servicegroup(temp_servicegroup,
temp_service))) {
return 0;
}
/* If the contact was specified, skip the services that do not have
the contact specified */
if( NULL != temp_contact &&
( FALSE == is_contact_for_service(temp_service, temp_contact))) {
return 0;
}
/* If a contactgroup was specified, skip the services that do not have
the contactgroup specified */
if(NULL != temp_contactgroup &&
(FALSE == is_contactgroup_for_service(temp_service,
temp_contactgroup))) {
return 0;
}
/* If the service description was supplied, skip the services that do not
have this service description */
if((NULL != service_description) &&
strcmp(temp_service->description, service_description)) {
return 0;
}
/* If a check timeperiod was specified, skip this service if it does
not have the check timeperiod specified */
if(NULL != check_timeperiod &&
(check_timeperiod != temp_service->check_period_ptr)) {
return 0;
}
/* If a notification timeperiod was specified, skip this service if it does
not have the notification timeperiod specified */
if(NULL != notification_timeperiod && (notification_timeperiod !=
temp_service->notification_period_ptr)) {
return 0;
}
/* If a check command was specified, skip this service if it does not
have the check command specified */
if(NULL != check_command &&
(check_command != temp_service->check_command_ptr)) {
return 0;
}
/* If an event handler was specified, skip this service if it does not
have the event handler specified */
if(NULL != event_handler &&
(event_handler != temp_service->event_handler_ptr)) {
return 0;
}
/* If a parent service was specified... */
if(NULL != parent_service_name) {
/* If the parent service is "none", skip this service if it has
parentren */
if(!strcmp(parent_service_name,"none")) {
if(NULL != temp_service->parents) {
return 0;
}
}
/* Otherwise, skip this service if it does not have the specified
service as a parent */
else {
int found = 0;
for(temp_servicesmember = temp_service->parents;
temp_servicesmember != NULL;
temp_servicesmember = temp_servicesmember->next) {
if(!strcmp(temp_servicesmember->service_description,
parent_service_name)) {
found = 1;
}
}
if(0 == found) {
return 0;
}
}
}
/* If a child service was specified... */
if(NULL != child_service_name) {
/* If the child service is "none", skip this service if it has
children */
if(!strcmp(child_service_name,"none")) {
if(NULL != temp_service->children) {
return 0;
}
}
/* Otherwise, skip this service if it does not have the specified
service as a child */
else {
int found = 0;
for(temp_servicesmember = temp_service->children;
temp_servicesmember != NULL;
temp_servicesmember = temp_servicesmember->next) {
if(!strcmp(temp_servicesmember->service_description,
child_service_name)) {
found = 1;
}
}
if(0 == found) {
return 0;
}
}
}
return 1;
}
json_object *json_object_service_selectors(int start, int count,
int use_parent_host, host *parent_host, int use_child_host,
host *child_host, hostgroup *temp_hostgroup, host *match_host,
servicegroup *temp_servicegroup, contact *temp_contact,
char *service_description, char *parent_service_name,
char *child_service_name, contactgroup *temp_contactgroup,
timeperiod *check_timeperiod, timeperiod *notification_timeperiod,
command *check_command, command *event_handler) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if( NULL != match_host) {
json_object_append_string(json_selectors, "host", &percent_escapes,
match_host->name);
}
if( 1 == use_parent_host) {
json_object_append_string(json_selectors, "parenthost",
&percent_escapes,
( NULL == parent_host ? "none" : parent_host->name));
}
if( 1 == use_child_host) {
json_object_append_string(json_selectors, "childhost", &percent_escapes,
( NULL == child_host ? "none" : child_host->name));
}
if( NULL != temp_hostgroup) {
json_object_append_string(json_selectors, "hostgroup", &percent_escapes,
temp_hostgroup->group_name);
}
if( NULL != temp_servicegroup) {
json_object_append_string(json_selectors, "servicegroup", &percent_escapes,
temp_servicegroup->group_name);
}
if(NULL != temp_contact) {
json_object_append_string(json_selectors, "contact",&percent_escapes,
temp_contact->name);
}
if(NULL != temp_contactgroup) {
json_object_append_string(json_selectors, "contactgroup",
&percent_escapes, temp_contactgroup->group_name);
}
if( NULL != service_description) {
json_object_append_string(json_selectors, "servicedescription",
&percent_escapes, service_description);
}
if( NULL != parent_service_name) {
json_object_append_string(json_selectors, "parentservice",
&percent_escapes, parent_service_name);
}
if( NULL != child_service_name) {
json_object_append_string(json_selectors, "childservice",
&percent_escapes, child_service_name);
}
if( NULL != check_timeperiod) {
json_object_append_string(json_selectors, "checktimeperiod",
&percent_escapes, check_timeperiod->name);
}
if( NULL != notification_timeperiod) {
json_object_append_string(json_selectors,
"servicenotificationtimeperiod", &percent_escapes,
notification_timeperiod->name);
}
if( NULL != check_command) {
json_object_append_string(json_selectors, "checkcommand",
&percent_escapes, check_command->name);
}
if( NULL != event_handler) {
json_object_append_string(json_selectors, "eventhandler",
&percent_escapes, event_handler->name);
}
return json_selectors;
}
json_object *json_object_servicecount(host *match_host, int use_parent_host,
host *parent_host, int use_child_host, host *child_host,
hostgroup *temp_hostgroup, servicegroup *temp_servicegroup,
contact *temp_contact, char *service_description,
char *parent_service_name, char *child_service_name,
contactgroup *temp_contactgroup, timeperiod *check_timeperiod,
timeperiod *notification_timeperiod, command *check_command,
command *event_handler) {
json_object *json_data;
host *temp_host;
service *temp_service;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_service_selectors(0, 0, use_parent_host, parent_host,
use_child_host, child_host, temp_hostgroup, match_host,
temp_servicegroup, temp_contact, service_description,
parent_service_name, child_service_name, temp_contactgroup,
check_timeperiod, notification_timeperiod, check_command,
event_handler));
for(temp_service = service_list; temp_service != NULL;
temp_service = temp_service->next) {
temp_host = find_host(temp_service->host_name);
if(NULL == temp_host) {
continue;
}
if(json_object_service_passes_host_selection(temp_host,
use_parent_host, parent_host, use_child_host, child_host,
temp_hostgroup, match_host) == 0) {
continue;
}
if(json_object_service_passes_service_selection(temp_service,
temp_servicegroup, temp_contact, service_description,
parent_service_name, child_service_name,
temp_contactgroup, check_timeperiod,
notification_timeperiod, check_command, event_handler) == 0) {
continue;
}
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_servicelist(unsigned format_options, int start,
int count, int details, host *match_host, int use_parent_host,
host *parent_host, int use_child_host, host *child_host,
hostgroup *temp_hostgroup, servicegroup *temp_servicegroup,
contact *temp_contact, char *service_description,
char *parent_service_name, char *child_service_name,
contactgroup *temp_contactgroup, timeperiod *check_timeperiod,
timeperiod *notification_timeperiod, command *check_command,
command *event_handler) {
json_object *json_data;
json_object *json_hostlist;
json_object *json_servicelist_object = NULL;
json_array *json_servicelist_array = NULL;
json_object *json_service_details;
host *temp_host;
service *temp_service;
int current = 0;
int counted = 0;
int service_count;
char *buf;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_service_selectors(start, count, use_parent_host,
parent_host, use_child_host, child_host, temp_hostgroup, match_host,
temp_servicegroup, temp_contact, service_description,
parent_service_name, child_service_name, temp_contactgroup,
check_timeperiod, notification_timeperiod, check_command,
event_handler));
json_hostlist = json_new_object();
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(json_object_service_passes_host_selection(temp_host, use_parent_host,
parent_host, use_child_host, child_host, temp_hostgroup,
match_host) == 0) {
continue;
}
service_count = 0;
if(details > 0) {
json_servicelist_object = json_new_object();
}
else {
json_servicelist_array = json_new_array();
}
for(temp_service = service_list; temp_service != NULL;
temp_service = temp_service->next) {
if(json_object_service_passes_service_selection(temp_service,
temp_servicegroup, temp_contact,
service_description, parent_service_name,
child_service_name, temp_contactgroup,
check_timeperiod, notification_timeperiod,
check_command, event_handler) == 0) {
continue;
}
/* If this service isn't on the host we're currently working with,
skip it */
if( strcmp( temp_host->name, temp_service->host_name)) continue;
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
if( details > 0) {
json_service_details = json_new_object();
json_object_service_details(json_service_details,
format_options, temp_service);
asprintf(&buf, "%s",
temp_service->description);
json_object_append_object(json_servicelist_object, buf,
json_service_details);
}
else {
json_array_append_string(json_servicelist_array,
&percent_escapes, temp_service->description);
}
counted++;
service_count++;
}
current++;
}
if(service_count > 0) {
if(details > 0) {
json_object_append_object(json_hostlist, temp_host->name,
json_servicelist_object);
}
else {
json_object_append_array(json_hostlist, temp_host->name,
json_servicelist_array);
}
}
}
json_object_append_object(json_data, "servicelist", json_hostlist);
return json_data;
}
json_object *json_object_service(unsigned format_options, service *temp_service) {
json_object *json_service = json_new_object();
json_object *json_details = json_new_object();
/* host_name and description are included when json_object_service_details()
is called, so we don't need them here */
/*
json_object_append_string(json_details, "host_name", &percent_escapes,
temp_service->host_name);
json_object_append_string(json_details, "description", &percent_escapes,
temp_service->description);
*/
json_object_service_details(json_details, format_options, temp_service);
json_object_append_object(json_service, "service", json_details);
return json_service;
}
void json_object_service_details(json_object *json_details,
unsigned format_options, service *temp_service) {
json_array *json_contactgroups;
json_array *json_contacts;
contactgroupsmember *temp_contact_groupsmember;
#ifdef NSCORE
contactsmember *temp_contactsmember;
#else
contact *temp_contact;
#endif
#ifdef JSON_NAGIOS_4X
servicesmember *temp_servicesmember;
json_object *json_parent_service;
json_array *json_parent_services;
json_object *json_child_service;
json_array *json_child_services;
#endif
json_object_append_string(json_details, "host_name", &percent_escapes,
temp_service->host_name);
json_object_append_string(json_details, "description", &percent_escapes,
temp_service->description);
json_object_append_string(json_details, "display_name", &percent_escapes,
temp_service->display_name);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_string(json_details, "service_check_command",
&percent_escapes, temp_service->check_command);
}
else {
#endif
json_object_append_string(json_details, "check_command",
&percent_escapes, temp_service->check_command);
#if 0
}
#endif
#else
json_object_append_string(json_details, "service_check_command",
&percent_escapes, temp_service->service_check_command);
#endif
json_object_append_string(json_details, "event_handler", &percent_escapes,
temp_service->event_handler);
json_enumeration(json_details, format_options, "initial_state",
temp_service->initial_state, svm_service_states);
json_object_append_real(json_details, "check_interval",
temp_service->check_interval);
json_object_append_real(json_details, "retry_interval",
temp_service->retry_interval);
json_object_append_integer(json_details, "max_attempts",
temp_service->max_attempts);
json_object_append_boolean(json_details, "parallelize",
temp_service->parallelize);
json_contactgroups = json_new_array();
for(temp_contact_groupsmember = temp_service->contact_groups;
temp_contact_groupsmember != NULL;
temp_contact_groupsmember = temp_contact_groupsmember->next) {
json_array_append_string(json_contactgroups, &percent_escapes,
temp_contact_groupsmember->group_name);
}
json_object_append_array(json_details, "contact_groups", json_contactgroups);
json_contacts = json_new_array();
#ifdef NSCORE
for(temp_contactsmember = temp_service->contacts;
temp_contactsmember != NULL;
temp_contactsmember = temp_contactsmember->next) {
json_array_append_string(json_contacts, &percent_escapes,
temp_contactsmember->contact_name);
}
#else
for(temp_contact = contact_list; temp_contact != NULL;
temp_contact = temp_contact->next) {
if(TRUE == is_contact_for_service(temp_service, temp_contact)) {
json_array_append_string(json_contacts, &percent_escapes,
temp_contact->name);
}
}
#endif
json_object_append_array(json_details, "contacts", json_contacts);
json_object_append_real(json_details, "notification_interval",
temp_service->notification_interval);
json_object_append_real(json_details, "first_notification_delay",
temp_service->first_notification_delay);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "notify_on_unknown",
flag_isset(temp_service->notification_options, OPT_UNKNOWN));
json_object_append_boolean(json_details, "notify_on_warning",
flag_isset(temp_service->notification_options, OPT_WARNING));
json_object_append_boolean(json_details, "notify_on_critical",
flag_isset(temp_service->notification_options, OPT_CRITICAL));
json_object_append_boolean(json_details, "notify_on_recovery",
flag_isset(temp_service->notification_options, OPT_RECOVERY));
json_object_append_boolean(json_details, "notify_on_flapping",
flag_isset(temp_service->notification_options, OPT_FLAPPING));
json_object_append_boolean(json_details, "notify_on_downtime",
flag_isset(temp_service->notification_options, OPT_DOWNTIME));
}
else {
#endif
json_bitmask(json_details, format_options, "notifications_options",
temp_service->notification_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "notify_on_unknown",
temp_service->notify_on_unknown);
json_object_append_boolean(json_details, "notify_on_warning",
temp_service->notify_on_warning);
json_object_append_boolean(json_details, "notify_on_critical",
temp_service->notify_on_critical);
json_object_append_boolean(json_details, "notify_on_recovery",
temp_service->notify_on_recovery);
json_object_append_boolean(json_details, "notify_on_flapping",
temp_service->notify_on_flapping);
json_object_append_boolean(json_details, "notify_on_downtime",
temp_service->notify_on_downtime);
#endif
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "stalk_on_ok",
flag_isset(temp_service->stalking_options, OPT_OK));
json_object_append_boolean(json_details, "stalk_on_warning",
flag_isset(temp_service->stalking_options, OPT_WARNING));
json_object_append_boolean(json_details, "stalk_on_unknown",
flag_isset(temp_service->stalking_options, OPT_UNKNOWN));
json_object_append_boolean(json_details, "stalk_on_critical",
flag_isset(temp_service->stalking_options, OPT_CRITICAL));
}
else {
#endif
json_bitmask(json_details, format_options, "stalking_options",
temp_service->stalking_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "stalk_on_ok",
temp_service->stalk_on_ok);
json_object_append_boolean(json_details, "stalk_on_warning",
temp_service->stalk_on_warning);
json_object_append_boolean(json_details, "stalk_on_unknown",
temp_service->stalk_on_unknown);
json_object_append_boolean(json_details, "stalk_on_critical",
temp_service->stalk_on_critical);
#endif
json_object_append_boolean(json_details, "is_volatile",
temp_service->is_volatile);
json_object_append_string(json_details, "notification_period",
&percent_escapes, temp_service->notification_period);
json_object_append_string(json_details, "check_period", &percent_escapes,
temp_service->check_period);
json_object_append_boolean(json_details, "flap_detection_enabled",
temp_service->flap_detection_enabled);
json_object_append_real(json_details, "low_flap_threshold",
temp_service->low_flap_threshold);
json_object_append_real(json_details, "high_flap_threshold",
temp_service->high_flap_threshold);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "flap_detection_on_ok",
flag_isset(temp_service->flap_detection_options, OPT_OK));
json_object_append_boolean(json_details, "flap_detection_on_warning",
flag_isset(temp_service->flap_detection_options, OPT_WARNING));
json_object_append_boolean(json_details, "flap_detection_on_unknown",
flag_isset(temp_service->flap_detection_options, OPT_UNKNOWN));
json_object_append_boolean(json_details, "flap_detection_on_critical",
flag_isset(temp_service->flap_detection_options, OPT_CRITICAL));
}
else {
#endif
json_bitmask(json_details, format_options, "flap_detection_options",
temp_service->flap_detection_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "flap_detection_on_ok",
temp_service->flap_detection_on_ok);
json_object_append_boolean(json_details, "flap_detection_on_warning",
temp_service->flap_detection_on_warning);
json_object_append_boolean(json_details, "flap_detection_on_unknown",
temp_service->flap_detection_on_unknown);
json_object_append_boolean(json_details, "flap_detection_on_critical",
temp_service->flap_detection_on_critical);
#endif
json_object_append_boolean(json_details, "process_performance_data",
temp_service->process_performance_data);
json_object_append_boolean(json_details, "check_freshness",
temp_service->check_freshness);
json_object_append_integer(json_details, "freshness_threshold",
temp_service->freshness_threshold);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details,
"accept_passive_service_checks",
temp_service->accept_passive_checks);
}
else {
#endif
json_object_append_boolean(json_details, "accept_passive_checks",
temp_service->accept_passive_checks);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "accept_passive_service_checks",
temp_service->accept_passive_service_checks);
#endif
json_object_append_boolean(json_details, "event_handler_enabled",
temp_service->event_handler_enabled);
json_object_append_boolean(json_details, "checks_enabled",
temp_service->checks_enabled);
json_object_append_boolean(json_details, "retain_status_information",
temp_service->retain_status_information);
json_object_append_boolean(json_details, "retain_nonstatus_information",
temp_service->retain_nonstatus_information);
json_object_append_boolean(json_details, "notifications_enabled",
temp_service->notifications_enabled);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "obsess_over_service",
temp_service->obsess);
}
else {
#endif
json_object_append_boolean(json_details, "obsess", temp_service->obsess);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "obsess_over_service",
temp_service->obsess_over_service);
#endif
#ifndef JSON_NAGIOS_4X
json_object_append_boolean(json_details, "failure_prediction_enabled",
temp_service->failure_prediction_enabled);
json_object_append_string(json_details, "failure_prediction_options",
NULL, temp_service->failure_prediction_options);
#endif
#ifdef JSON_NAGIOS_4X
json_object_append_integer(json_details, "hourly_value",
temp_service->hourly_value);
#endif
#ifdef JSON_NAGIOS_4X
json_parent_services = json_new_array();
for(temp_servicesmember = temp_service->parents;
temp_servicesmember != NULL;
temp_servicesmember = temp_servicesmember->next) {
json_parent_service = json_new_object();
json_object_append_string(json_parent_service, "host_name",
&percent_escapes, temp_servicesmember->host_name);
json_object_append_string(json_parent_service, "service_description",
&percent_escapes, temp_servicesmember->service_description);
json_array_append_object(json_parent_services, json_parent_service);
}
json_object_append_array(json_details, "parents", json_parent_services);
json_child_services = json_new_array();
for(temp_servicesmember = temp_service->children;
temp_servicesmember != NULL;
temp_servicesmember = temp_servicesmember->next) {
json_child_service = json_new_object();
json_object_append_string(json_child_service, "host_name",
&percent_escapes, temp_servicesmember->host_name);
json_object_append_string(json_child_service, "service_description",
&percent_escapes, temp_servicesmember->service_description);
json_array_append_object(json_child_services, json_child_service);
}
json_object_append_array(json_details, "children", json_child_services);
#endif
json_object_append_string(json_details, "notes", &percent_escapes,
temp_service->notes);
json_object_append_string(json_details, "notes_url", &percent_escapes,
temp_service->notes_url);
json_object_append_string(json_details, "action_url", &percent_escapes,
temp_service->action_url);
json_object_append_string(json_details, "icon_image", &percent_escapes,
temp_service->icon_image);
json_object_append_string(json_details, "icon_image_alt", &percent_escapes,
temp_service->icon_image_alt);
json_object_append_object(json_details, "custom_variables",
json_object_custom_variables(temp_service->custom_variables));
}
int json_object_servicegroup_passes_selection(servicegroup *temp_servicegroup,
service *temp_servicegroup_member) {
/* Skip if user is not authorized for this hostgroup */
if(FALSE == is_authorized_for_servicegroup(temp_servicegroup,
¤t_authdata)) {
return 0;
}
/* Skip if a servicegroup member is specified and the servicegroup
member service is not a member of the servicegroup */
if( NULL != temp_servicegroup_member &&
( FALSE == is_service_member_of_servicegroup(temp_servicegroup,
temp_servicegroup_member))) {
return 0;
}
return 1;
}
json_object * json_object_servicegroup_selectors(int start, int count,
service *temp_servicegroup_member) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if( NULL != temp_servicegroup_member) {
json_object_append_string(json_selectors, "servicegroupmemberhost",
&percent_escapes, temp_servicegroup_member->host_name);
json_object_append_string(json_selectors, "servicegroupmemberservice",
&percent_escapes, temp_servicegroup_member->description);
}
return json_selectors;
}
json_object *json_object_servicegroupcount(service *temp_servicegroup_member) {
json_object *json_data;
servicegroup *temp_servicegroup;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_servicegroup_selectors(0, 0,
temp_servicegroup_member));
for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL;
temp_servicegroup = temp_servicegroup->next) {
if(json_object_servicegroup_passes_selection(temp_servicegroup,
temp_servicegroup_member) == 0) {
continue;
}
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_servicegrouplist(unsigned format_options, int start,
int count, int details, service *temp_servicegroup_member) {
json_object *json_data;
json_object *json_servicegrouplist_object = NULL;
json_array *json_servicegrouplist_array = NULL;
json_object *json_servicegroup_details;
servicegroup *temp_servicegroup;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_servicegroup_selectors(start, count,
temp_servicegroup_member));
if(details > 0) {
json_servicegrouplist_object = json_new_object();
}
else {
json_servicegrouplist_array = json_new_array();
}
for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL;
temp_servicegroup = temp_servicegroup->next) {
if(json_object_servicegroup_passes_selection(temp_servicegroup,
temp_servicegroup_member) == 0) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
if( details > 0) {
json_servicegroup_details = json_new_object();
json_object_servicegroup_details(json_servicegroup_details,
format_options, temp_servicegroup);
json_object_append_object(json_servicegrouplist_object,
temp_servicegroup->group_name,
json_servicegroup_details);
}
else {
json_object_append_string(json_servicegrouplist_array, NULL,
&percent_escapes, temp_servicegroup->group_name);
}
counted++;
}
current++;
}
if(details > 0) {
json_object_append_object(json_data, "servicegrouplist",
json_servicegrouplist_object);
}
else {
json_object_append_array(json_data, "servicegrouplist",
json_servicegrouplist_array);
}
return json_data;
}
json_object * json_object_servicegroup(unsigned format_options,
servicegroup *temp_servicegroup) {
json_object *json_servicegroup = json_new_object();
json_object *json_details = json_new_object();
json_object_append_string(json_details, "group_name",
&percent_escapes, temp_servicegroup->group_name);
json_object_servicegroup_details(json_details, format_options,
temp_servicegroup);
json_object_append_object(json_servicegroup, "servicegroup", json_details);
return json_servicegroup;
}
void json_object_servicegroup_details(json_object *json_details,
unsigned format_options, servicegroup *temp_servicegroup) {
json_array *json_members;
servicesmember *temp_member;
json_object *json_member;
json_object_append_string(json_details, "group_name", &percent_escapes,
temp_servicegroup->group_name);
json_object_append_string(json_details, "alias", &percent_escapes,
temp_servicegroup->alias);
json_members = json_new_array();
for(temp_member = temp_servicegroup->members; temp_member != NULL;
temp_member = temp_member->next) {
json_member = json_new_object();
json_object_append_string(json_member, "host_name", &percent_escapes,
temp_member->host_name);
json_object_append_string(json_member, "service_description",
&percent_escapes, temp_member->service_description);
json_array_append_object(json_members, json_member);
}
json_object_append_array(json_details, "members", json_members);
json_object_append_string(json_details, "notes", &percent_escapes,
temp_servicegroup->notes);
json_object_append_string(json_details, "notes_url", &percent_escapes,
temp_servicegroup->notes_url);
json_object_append_string(json_details, "action_url", &percent_escapes,
temp_servicegroup->action_url);
}
int json_object_contact_passes_selection(contact *temp_contact,
contactgroup *temp_contactgroup,
timeperiod *host_notification_timeperiod,
timeperiod *service_notification_timeperiod) {
/* If the contactgroup was specified, skip the contacts that are not
members of the contactgroup specified */
if( NULL != temp_contactgroup &&
( FALSE == is_contact_member_of_contactgroup(temp_contactgroup,
temp_contact))) {
return 0;
}
/* If a host notification timeperiod was specified, skip this contact
if it does not have the host notification timeperiod specified */
if(NULL != host_notification_timeperiod && (host_notification_timeperiod !=
temp_contact->host_notification_period_ptr)) {
return 0;
}
/* If a service notification timeperiod was specified, skip this contact
if it does not have the service notification timeperiod specified */
if(NULL != service_notification_timeperiod &&
(service_notification_timeperiod !=
temp_contact->service_notification_period_ptr)) {
return 0;
}
return 1;
}
json_object *json_object_contact_display_selectors(int start, int count,
contactgroup *temp_contactgroup,
timeperiod *host_notification_timeperiod,
timeperiod *service_notification_timeperiod) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if( NULL != temp_contactgroup) {
json_object_append_string(json_selectors, "contactgroup",
&percent_escapes, temp_contactgroup->group_name);
}
if( NULL != host_notification_timeperiod) {
json_object_append_string(json_selectors, "hostnotificationtimeperiod",
&percent_escapes, host_notification_timeperiod->name);
}
if( NULL != service_notification_timeperiod) {
json_object_append_string(json_selectors,
"servicenotificationtimeperiod", &percent_escapes,
service_notification_timeperiod->name);
}
return json_selectors;
}
json_object *json_object_contactcount(contactgroup *temp_contactgroup,
timeperiod *host_notification_timeperiod,
timeperiod *service_notification_timeperiod) {
json_object *json_data;
contact *temp_contact;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_contact_display_selectors(0, 0, temp_contactgroup,
host_notification_timeperiod, service_notification_timeperiod));
for(temp_contact = contact_list; temp_contact != NULL;
temp_contact = temp_contact->next) {
if(json_object_contact_passes_selection(temp_contact,
temp_contactgroup, host_notification_timeperiod,
service_notification_timeperiod) == 0) {
continue;
}
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_contactlist(unsigned format_options, int start,
int count, int details, contactgroup *temp_contactgroup,
timeperiod *host_notification_timeperiod,
timeperiod *service_notification_timeperiod) {
json_object *json_data;
json_object *json_contactlist_object = NULL;
json_array *json_contactlist_array = NULL;
json_object *json_contact_details;
contact *temp_contact;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_contact_display_selectors(start, count,
temp_contactgroup, host_notification_timeperiod,
service_notification_timeperiod));
if(details > 0) {
json_contactlist_object = json_new_object();
}
else {
json_contactlist_array = json_new_array();
}
for(temp_contact = contact_list; temp_contact != NULL;
temp_contact = temp_contact->next) {
if(json_object_contact_passes_selection(temp_contact,
temp_contactgroup, host_notification_timeperiod,
service_notification_timeperiod) == 0) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
if( details > 0) {
json_contact_details = json_new_object();
json_object_contact_details(json_contact_details,
format_options, temp_contact);
json_object_append_object(json_contactlist_object,
temp_contact->name, json_contact_details);
}
else {
json_array_append_string(json_contactlist_array,
&percent_escapes, temp_contact->name);
}
counted++;
}
current++;
}
if(details > 0) {
json_object_append_object(json_data, "contactlist",
json_contactlist_object);
}
else {
json_object_append_array(json_data, "contactlist",
json_contactlist_array);
}
return json_data;
}
json_object *json_object_contact(unsigned format_options, contact *temp_contact) {
json_object *json_contact = json_new_object();
json_object *json_details = json_new_object();
json_object_append_string(json_details, "name", &percent_escapes,
temp_contact->name);
json_object_contact_details(json_details, format_options, temp_contact);
json_object_append_object(json_contact, "contact", json_details);
return json_contact;
}
void json_object_contact_details(json_object *json_details,
unsigned format_options, contact *temp_contact) {
json_array *json_addresses;
json_array *json_host_commands;
json_array *json_service_commands;
int x;
commandsmember *temp_commandsmember;
json_object_append_string(json_details, "name", &percent_escapes,
temp_contact->name);
json_object_append_string(json_details, "alias", &percent_escapes,
temp_contact->alias);
json_object_append_string(json_details, "email", &percent_escapes,
temp_contact->email);
json_object_append_string(json_details, "pager", &percent_escapes,
temp_contact->pager);
json_addresses = json_new_array();
for( x = 0; x < MAX_CONTACT_ADDRESSES; x++) {
if( NULL != temp_contact->address[ x]) {
json_array_append_string(json_addresses, &percent_escapes,
temp_contact->address[ x]);
}
}
json_object_append_array(json_details, "addresses", json_addresses);
json_host_commands = json_new_array();
for(temp_commandsmember = temp_contact->host_notification_commands;
temp_commandsmember != NULL;
temp_commandsmember = temp_commandsmember->next) {
json_array_append_string(json_host_commands, &percent_escapes,
temp_commandsmember->command);
}
json_object_append_array(json_details, "host_notification_commands",
json_host_commands);
json_service_commands = json_new_array();
for(temp_commandsmember = temp_contact->service_notification_commands;
temp_commandsmember != NULL;
temp_commandsmember = temp_commandsmember->next) {
json_array_append_string(json_service_commands, &percent_escapes,
temp_commandsmember->command);
}
json_object_append_array(json_details, "service_notification_commands",
json_service_commands);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "notify_on_service_unknown",
flag_isset(temp_contact->service_notification_options,
OPT_UNKNOWN));
json_object_append_boolean(json_details, "notify_on_service_warning",
flag_isset(temp_contact->service_notification_options,
OPT_WARNING));
json_object_append_boolean(json_details, "notify_on_service_critical",
flag_isset(temp_contact->service_notification_options,
OPT_CRITICAL));
json_object_append_boolean(json_details, "notify_on_service_recovery",
flag_isset(temp_contact->service_notification_options,
OPT_RECOVERY));
json_object_append_boolean(json_details, "notify_on_service_flapping",
flag_isset(temp_contact->service_notification_options,
OPT_FLAPPING));
json_object_append_boolean(json_details, "notify_on_service_downtime",
flag_isset(temp_contact->service_notification_options,
OPT_DOWNTIME));
}
else {
#endif
json_bitmask(json_details, format_options,
"service_notification_options",
temp_contact->service_notification_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "notify_on_service_unknown",
temp_contact->notify_on_service_unknown);
json_object_append_boolean(json_details, "notify_on_service_warning",
temp_contact->notify_on_service_warning);
json_object_append_boolean(json_details, "notify_on_service_critical",
temp_contact->notify_on_service_critical);
json_object_append_boolean(json_details, "notify_on_service_recovery",
temp_contact->notify_on_service_recovery);
json_object_append_boolean(json_details, "notify_on_service_flapping",
temp_contact->notify_on_service_flapping);
json_object_append_boolean(json_details, "notify_on_service_downtime",
temp_contact->notify_on_service_downtime);
#endif
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "notify_on_host_down",
flag_isset(temp_contact->host_notification_options, OPT_DOWN));
json_object_append_boolean(json_details, "notify_on_host_unreachable",
flag_isset(temp_contact->host_notification_options,
OPT_UNREACHABLE));
json_object_append_boolean(json_details, "notify_on_host_recovery",
flag_isset(temp_contact->host_notification_options,
OPT_RECOVERY));
json_object_append_boolean(json_details, "notify_on_host_flapping",
flag_isset(temp_contact->host_notification_options,
OPT_FLAPPING));
json_object_append_boolean(json_details, "notify_on_host_downtime",
flag_isset(temp_contact->host_notification_options,
OPT_DOWNTIME));
}
else {
#endif
json_bitmask(json_details, format_options, "host_notification_options",
temp_contact->host_notification_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "notify_on_host_down",
temp_contact->notify_on_host_down);
json_object_append_boolean(json_details, "notify_on_host_unreachable",
temp_contact->notify_on_host_unreachable);
json_object_append_boolean(json_details, "notify_on_host_recovery",
temp_contact->notify_on_host_recovery);
json_object_append_boolean(json_details, "notify_on_host_flapping",
temp_contact->notify_on_host_flapping);
json_object_append_boolean(json_details, "notify_on_host_downtime",
temp_contact->notify_on_host_downtime);
#endif
json_object_append_string(json_details, "host_notification_period",
&percent_escapes, temp_contact->host_notification_period);
json_object_append_string(json_details, "service_notification_period",
&percent_escapes, temp_contact->service_notification_period);
json_object_append_boolean(json_details, "host_notifications_enabled",
temp_contact->host_notifications_enabled);
json_object_append_boolean(json_details, "service_notifications_enabled",
temp_contact->service_notifications_enabled);
json_object_append_boolean(json_details, "can_submit_commands",
temp_contact->can_submit_commands);
json_object_append_boolean(json_details, "retain_status_information",
temp_contact->retain_status_information);
json_object_append_boolean(json_details, "retain_nonstatus_information",
temp_contact->retain_nonstatus_information);
#ifdef JSON_NAGIOS_4X
json_object_append_integer(json_details, "minimum_value",
temp_contact->minimum_value);
#endif
json_object_append_object(json_details, "custom_variables",
json_object_custom_variables(temp_contact->custom_variables));
}
int json_object_contactgroup_passes_selection(contactgroup *temp_contactgroup,
contact *temp_contactgroup_member) {
/* Skip if a contactgroup member is specified and the contactgroup
member contact is not a member of the contactgroup */
if( NULL != temp_contactgroup_member &&
( FALSE == is_contact_member_of_contactgroup(temp_contactgroup,
temp_contactgroup_member))) {
return 0;
}
return 1;
}
json_object *json_object_contactgroup_display_selectors( int start, int count,
contact *temp_contactgroup_member) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if( NULL != temp_contactgroup_member) {
json_object_append_string(json_selectors, "contactgroupmember",
&percent_escapes, temp_contactgroup_member->name);
}
return json_selectors;
}
json_object *json_object_contactgroupcount(contact * temp_contactgroup_member) {
json_object *json_data;
contactgroup *temp_contactgroup;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_contactgroup_display_selectors(0, 0,
temp_contactgroup_member));
for(temp_contactgroup = contactgroup_list; temp_contactgroup != NULL;
temp_contactgroup = temp_contactgroup->next) {
if(json_object_contactgroup_passes_selection(temp_contactgroup,
temp_contactgroup_member) == 0) {
continue;
}
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_contactgrouplist(unsigned format_options, int start,
int count, int details, contact * temp_contactgroup_member) {
json_object *json_data;
json_object *json_contactgrouplist_object = NULL;
json_array *json_contactgrouplist_array = NULL;
json_object *json_contactgroup_details;
contactgroup *temp_contactgroup;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_contactgroup_display_selectors(start, count,
temp_contactgroup_member));
if(details > 0) {
json_contactgrouplist_object = json_new_object();
}
else {
json_contactgrouplist_array = json_new_array();
}
for(temp_contactgroup = contactgroup_list; temp_contactgroup != NULL;
temp_contactgroup = temp_contactgroup->next) {
if(json_object_contactgroup_passes_selection(temp_contactgroup,
temp_contactgroup_member) == 0) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
if( details > 0) {
json_contactgroup_details = json_new_object();
json_object_contactgroup_details(json_contactgroup_details,
format_options, temp_contactgroup);
json_object_append_object(json_contactgrouplist_object,
temp_contactgroup->group_name, json_contactgroup_details);
}
else {
json_array_append_string(json_contactgrouplist_array,
&percent_escapes, temp_contactgroup->group_name);
}
counted++;
}
current++;
}
if(details > 0) {
json_object_append_object(json_data, "contactgrouplist",
json_contactgrouplist_object);
}
else {
json_object_append_array(json_data, "contactgrouplist",
json_contactgrouplist_array);
}
return json_data;
}
json_object *json_object_contactgroup(unsigned format_options,
contactgroup *temp_contactgroup) {
json_object *json_contactgroup = json_new_object();
json_object *json_details = json_new_object();
json_object_append_string(json_details, "group_name", &percent_escapes,
temp_contactgroup->group_name);
json_object_contactgroup_details(json_details, format_options,
temp_contactgroup);
json_object_append_object(json_contactgroup, "contactgroup", json_details);
return json_contactgroup;
}
void json_object_contactgroup_details(json_object *json_details,
unsigned format_options, contactgroup *temp_contactgroup) {
json_array *json_members;
contactsmember *temp_member;
json_object_append_string(json_details, "group_name", &percent_escapes,
temp_contactgroup->group_name);
json_object_append_string(json_details, "alias", &percent_escapes,
temp_contactgroup->alias);
json_members = json_new_array();
for(temp_member = temp_contactgroup->members; temp_member != NULL;
temp_member = temp_member->next) {
json_array_append_string(json_members, &percent_escapes,
temp_member->contact_name);
}
json_object_append_array(json_details, "members", json_members);
}
json_object *json_object_timeperiod_selectors(int start, int count) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
return json_selectors;
}
json_object *json_object_timeperiodcount(void) {
json_object *json_data;
timeperiod *temp_timeperiod;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_timeperiod_selectors(0, 0));
for(temp_timeperiod = timeperiod_list; temp_timeperiod != NULL;
temp_timeperiod = temp_timeperiod->next) {
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_timeperiodlist(unsigned format_options, int start,
int count, int details) {
json_object *json_data;
json_object *json_timeperiodlist_object = NULL;
json_array *json_timeperiodlist_array = NULL;
json_object *json_timeperiod_details;
timeperiod *temp_timeperiod;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_timeperiod_selectors(start, count));
if(details > 0) {
json_timeperiodlist_object = json_new_object();
}
else {
json_timeperiodlist_array = json_new_array();
}
for(temp_timeperiod = timeperiod_list; temp_timeperiod != NULL;
temp_timeperiod = temp_timeperiod->next) {
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
if( details > 0) {
json_timeperiod_details = json_new_object();
json_object_timeperiod_details(json_timeperiod_details,
format_options, temp_timeperiod);
json_object_append_object(json_timeperiodlist_object,
temp_timeperiod->name, json_timeperiod_details);
}
else {
json_array_append_string(json_timeperiodlist_array,
&percent_escapes, temp_timeperiod->name);
}
counted++;
}
current++;
}
if(details > 0) {
json_object_append_object(json_data, "timeperiodlist",
json_timeperiodlist_object);
}
else {
json_object_append_array(json_data, "timeperiodlist",
json_timeperiodlist_array);
}
return json_data;
}
json_object *json_object_timeperiod(unsigned format_options,
timeperiod *temp_timeperiod) {
json_object *json_timeperiod = json_new_object();
json_object *json_details = json_new_object();
json_object_append_string(json_details, "name", &percent_escapes,
temp_timeperiod->name);
json_object_timeperiod_details(json_details, format_options, temp_timeperiod);
json_object_append_object(json_timeperiod, "timeperiod", json_details);
return json_timeperiod;
}
void json_object_timeperiod_details(json_object *json_details,
unsigned format_options, timeperiod *temp_timeperiod) {
json_object *json_days;
int x;
json_array *json_timeranges;
json_array *json_exceptions;
json_array *json_exclusions;
daterange *temp_daterange;
timeperiodexclusion *temp_timeperiodexclusion;
json_object_append_string(json_details, "name", &percent_escapes,
temp_timeperiod->name);
json_object_append_string(json_details, "alias", &percent_escapes,
temp_timeperiod->alias);
json_days = json_new_object();
for(x = 0; x < sizeof(temp_timeperiod->days) / sizeof(temp_timeperiod->days[0]); x++) {
if( NULL != temp_timeperiod->days[x]) {
json_timeranges = json_new_array();
json_object_timerange(json_timeranges, format_options,
temp_timeperiod->days[x]);
json_object_append_array(json_days, (char *)dayofweek[x],
json_timeranges);
}
}
json_object_append_object(json_details, "days", json_days);
json_exceptions = json_new_array();
for(x = 0; x < DATERANGE_TYPES; x++) {
for(temp_daterange = temp_timeperiod->exceptions[x];
temp_daterange != NULL; temp_daterange = temp_daterange->next) {
json_array_append_object(json_exceptions,
json_object_daterange(format_options, temp_daterange, x));
}
}
json_object_append_array(json_details, "exceptions", json_exceptions);
json_exclusions = json_new_array();
for(temp_timeperiodexclusion = temp_timeperiod->exclusions;
temp_timeperiodexclusion != NULL;
temp_timeperiodexclusion = temp_timeperiodexclusion->next) {
json_array_append_string(json_exclusions, &percent_escapes,
temp_timeperiodexclusion->timeperiod_name);
}
json_object_append_array(json_details, "exclusions", json_exclusions);
}
json_object * json_object_daterange(unsigned format_options,
daterange *temp_daterange, int daterange_type) {
json_object *json_daterange;
json_array *json_timeranges;
json_daterange = json_new_object();
switch(daterange_type) {
case DATERANGE_CALENDAR_DATE:
json_object_append_string(json_daterange, "type", NULL,
"DATERANGE_CALENDAR_DATE");
if(temp_daterange->syear == temp_daterange->eyear &&
temp_daterange->smon == temp_daterange->emon &&
temp_daterange->smday == temp_daterange->emday) {
json_object_append_string(json_daterange, "date", NULL,
"%4d-%02d-%02d", temp_daterange->syear,
temp_daterange->smon+1, temp_daterange->smday);
}
else {
json_object_append_string(json_daterange, "startdate", NULL,
"%4d-%02d-%02d", temp_daterange->syear,
temp_daterange->smon+1, temp_daterange->smday);
json_object_append_string(json_daterange, "enddate", NULL,
"%4d-%02d-%02d", temp_daterange->eyear,
temp_daterange->emon+1, temp_daterange->emday);
}
if( temp_daterange->skip_interval > 0) {
json_object_append_integer(json_daterange, "skip_interval",
temp_daterange->skip_interval);
}
json_timeranges = json_new_array();
json_object_timerange(json_timeranges, format_options,
temp_daterange->times);
json_object_append_array(json_daterange, "times", json_timeranges);
break;
case DATERANGE_MONTH_DATE:
json_object_append_string(json_daterange, "type", NULL,
"DATERANGE_MONTH_DATE");
if(temp_daterange->smon == temp_daterange->emon &&
temp_daterange->smday == temp_daterange->emday) {
json_object_append_string(json_daterange, "month", &percent_escapes,
(char *)month[temp_daterange->smon]);
json_object_append_integer(json_daterange, "day",
temp_daterange->smday);
}
else {
json_object_append_string(json_daterange, "startmonth",
&percent_escapes, (char *)month[temp_daterange->smon]);
json_object_append_integer(json_daterange, "startday",
temp_daterange->smday);
json_object_append_string(json_daterange, "endmonth",
&percent_escapes, (char *)month[temp_daterange->emon]);
json_object_append_integer(json_daterange, "endday",
temp_daterange->emday);
}
if( temp_daterange->skip_interval > 0) {
json_object_append_integer(json_daterange, "skip_interval",
temp_daterange->skip_interval);
}
json_timeranges = json_new_array();
json_object_timerange(json_timeranges, format_options,
temp_daterange->times);
json_object_append_array(json_daterange, "times", json_timeranges);
break;
case DATERANGE_MONTH_DAY:
json_object_append_string(json_daterange, "type", NULL,
"DATERANGE_MONTH_DAY");
if(temp_daterange->smday == temp_daterange->emday) {
json_object_append_integer(json_daterange, "day",
temp_daterange->smday);
}
else {
json_object_append_integer(json_daterange, "startday",
temp_daterange->smday);
json_object_append_integer(json_daterange, "endday",
temp_daterange->emday);
}
if( temp_daterange->skip_interval > 0) {
json_object_append_integer(json_daterange, "skip_interval",
temp_daterange->skip_interval);
}
json_timeranges = json_new_array();
json_object_timerange(json_timeranges, format_options,
temp_daterange->times);
json_object_append_array(json_daterange, "times", json_timeranges);
break;
case DATERANGE_MONTH_WEEK_DAY:
json_object_append_string(json_daterange, "type", NULL,
"DATERANGE_MONTH_WEEK_DAY");
if(temp_daterange->smon == temp_daterange->emon &&
temp_daterange->swday == temp_daterange->ewday &&
temp_daterange->swday_offset == temp_daterange->ewday_offset) {
json_object_append_string(json_daterange, "month", &percent_escapes,
(char *)month[temp_daterange->smon]);
json_object_append_string(json_daterange, "weekday",
&percent_escapes, (char *)dayofweek[temp_daterange->swday]);
json_object_append_integer(json_daterange, "weekdayoffset",
temp_daterange->swday_offset);
}
else {
json_object_append_string(json_daterange, "startmonth",
&percent_escapes, (char *)month[temp_daterange->smon]);
json_object_append_string(json_daterange, "startweekday",
&percent_escapes, (char *)dayofweek[temp_daterange->swday]);
json_object_append_integer(json_daterange, "startweekdayoffset",
temp_daterange->swday_offset);
json_object_append_string(json_daterange, "endmonth",
&percent_escapes, (char *)month[temp_daterange->emon]);
json_object_append_string(json_daterange, "endweekday",
&percent_escapes, (char *)dayofweek[temp_daterange->ewday]);
json_object_append_integer(json_daterange, "endweekdayoffset",
temp_daterange->ewday_offset);
}
if( temp_daterange->skip_interval > 0) {
json_object_append_integer(json_daterange, "skip_interval",
temp_daterange->skip_interval);
}
json_timeranges = json_new_array();
json_object_timerange(json_timeranges, format_options,
temp_daterange->times);
json_object_append_array(json_daterange, "times", json_timeranges);
break;
case DATERANGE_WEEK_DAY:
json_object_append_string(json_daterange, "type", NULL,
"DATERANGE_WEEK_DAY");
if(temp_daterange->swday == temp_daterange->ewday &&
temp_daterange->swday_offset == temp_daterange->ewday_offset) {
json_object_append_string(json_daterange, "weekday",
&percent_escapes, (char *)dayofweek[temp_daterange->swday]);
json_object_append_integer(json_daterange, "weekdayoffset",
temp_daterange->swday_offset);
}
else {
json_object_append_string(json_daterange, "startweekday",
&percent_escapes, (char *)dayofweek[temp_daterange->swday]);
json_object_append_integer(json_daterange, "startweekdayoffset",
temp_daterange->swday_offset);
json_object_append_string(json_daterange, "endweekday",
&percent_escapes, (char *)dayofweek[temp_daterange->ewday]);
json_object_append_integer(json_daterange, "endweekdayoffset",
temp_daterange->ewday_offset);
}
if( temp_daterange->skip_interval > 0) {
json_object_append_integer(json_daterange, "skip_interval",
temp_daterange->skip_interval);
}
json_timeranges = json_new_array();
json_object_timerange(json_timeranges, format_options,
temp_daterange->times);
json_object_append_array(json_daterange, "times", json_timeranges);
break;
default:
json_object_append_string(json_daterange, "type", NULL,
"Unknown daterange type: %u", daterange_type);
break;
}
return json_daterange;
}
void json_object_timerange(json_array *json_parent, unsigned format_options,
timerange *temp_timerange) {
json_object *json_timerange;
for(; temp_timerange != NULL; temp_timerange = temp_timerange->next) {
json_timerange = json_new_object();
json_object_append_time(json_timerange, "range_start",
temp_timerange->range_start);
json_object_append_time(json_timerange, "range_end",
temp_timerange->range_end);
json_array_append_object(json_parent, json_timerange);
}
}
json_object *json_object_command_selectors(int start, int count) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
return json_selectors;
}
json_object *json_object_commandcount(void) {
json_object *json_data;
command *temp_command;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_command_selectors(0, 0));
for(temp_command = command_list; temp_command != NULL;
temp_command = temp_command->next) {
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_commandlist(unsigned format_options, int start,
int count, int details) {
json_object *json_data;
json_object *json_commandlist_object = NULL;
json_array *json_commandlist_array = NULL;
json_object *json_command_details;
command *temp_command;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_command_selectors(start, count));
if(details > 0) {
json_commandlist_object = json_new_object();
}
else {
json_commandlist_array = json_new_array();
}
for(temp_command = command_list; temp_command != NULL;
temp_command = temp_command->next) {
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
if( details > 0) {
json_command_details = json_new_object();
json_object_command_details(json_command_details, format_options,
temp_command);
json_object_append_object(json_commandlist_object,
temp_command->name, json_command_details);
}
else {
json_array_append_string(json_commandlist_array,
&percent_escapes, temp_command->name);
}
counted++;
}
current++;
}
if(details > 0) {
json_object_append_object(json_data, "commandlist",
json_commandlist_object);
}
else {
json_object_append_array(json_data, "commandlist",
json_commandlist_array);
}
return json_data;
}
json_object *json_object_command(unsigned format_options, command *temp_command) {
json_object *json_command = json_new_object();
json_object *json_details = json_new_object();
json_object_append_string(json_details, "name", &percent_escapes,
temp_command->name);
json_object_command_details(json_details, format_options, temp_command);
json_object_append_object(json_command, "command", json_details);
return json_command;
}
void json_object_command_details(json_object *json_details,
unsigned format_options, command *temp_command) {
json_object_append_string(json_details, "name", &percent_escapes,
temp_command->name);
json_object_append_string(json_details, "command_line", &percent_escapes,
temp_command->command_line);
}
int json_object_servicedependency_passes_selection(
servicedependency *temp_servicedependency, host *master_host,
hostgroup *master_hostgroup, char *master_service_description,
servicegroup *master_servicegroup, host *dependent_host,
hostgroup *dependent_hostgroup, char * dependent_service_description,
servicegroup *dependent_servicegroup) {
host *temp_host = NULL;
service *temp_service = NULL;
/* Skip if the servicedependency does not have the specified master host */
if(NULL != master_host &&
strcmp(temp_servicedependency->host_name, master_host->name)) {
return 0;
}
/* Skip if the servicedependency does not have a master host in the
specified hostgroup */
if(NULL != master_hostgroup) {
temp_host = find_host(temp_servicedependency->host_name);
if((NULL != temp_host) && (FALSE ==
is_host_member_of_hostgroup(master_hostgroup, temp_host))) {
return 0;
}
}
/* Skip if the servicedependency does not have the specified master
service */
if(NULL != master_service_description &&
strcmp(temp_servicedependency->service_description,
master_service_description)) {
return 0;
}
/* Skip if the servicedependency does not have a master service in the
specified servicegroup */
if(NULL != master_servicegroup) {
temp_service = find_service(temp_servicedependency->host_name,
temp_servicedependency->service_description);
if((NULL != temp_service) && (FALSE ==
is_service_member_of_servicegroup(master_servicegroup,
temp_service))) {
return 0;
}
}
/* Skip if the servicedependency does not have the specified dependent
host */
if(NULL != dependent_host &&
strcmp(temp_servicedependency->dependent_host_name,
dependent_host->name)) {
return 0;
}
/* Skip if the servicedependency does not have a dependent host in the
specified hostgroup */
if(NULL != dependent_hostgroup) {
temp_host = find_host(temp_servicedependency->dependent_host_name);
if((NULL != temp_host) && (FALSE ==
is_host_member_of_hostgroup(dependent_hostgroup, temp_host))) {
return 0;
}
}
/* Skip if the servicedependency does not have the specified dependent
service */
if(NULL != dependent_service_description &&
strcmp(temp_servicedependency->dependent_service_description,
dependent_service_description)) {
return 0;
}
/* Skip if the servicedependency does not have a dependent service in the
specified servicegroup */
if(NULL != dependent_servicegroup) {
temp_service = find_service(temp_servicedependency->dependent_host_name,
temp_servicedependency->dependent_service_description);
if((NULL != temp_service) && (FALSE ==
is_service_member_of_servicegroup(dependent_servicegroup,
temp_service))) {
return 0;
}
}
return 1;
}
json_object *json_object_servicedependency_selectors(int start, int count,
host *master_host, hostgroup *master_hostgroup,
char *master_service_description, servicegroup *master_servicegroup,
host *dependent_host, hostgroup *dependent_hostgroup,
char * dependent_service_description,
servicegroup *dependent_servicegroup) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if(NULL != master_host) {
json_object_append_string(json_selectors, "masterhostname",
&percent_escapes, master_host->name);
}
if(NULL != master_hostgroup) {
json_object_append_string(json_selectors, "masterhostgroupname",
&percent_escapes, master_hostgroup->group_name);
}
if(NULL != master_service_description) {
json_object_append_string(json_selectors, "masterservicedescription",
&percent_escapes, master_service_description);
}
if(NULL != master_servicegroup) {
json_object_append_string(json_selectors, "masterservicegroupname",
&percent_escapes, master_servicegroup->group_name);
}
if(NULL != dependent_host) {
json_object_append_string(json_selectors, "dependenthostname",
&percent_escapes, dependent_host->name);
}
if(NULL != dependent_hostgroup) {
json_object_append_string(json_selectors, "dependenthostgroupname",
&percent_escapes, dependent_hostgroup->group_name);
}
if(NULL != dependent_service_description) {
json_object_append_string(json_selectors, "dependentservicedescription",
&percent_escapes, dependent_service_description);
}
if(NULL != dependent_servicegroup) {
json_object_append_string(json_selectors, "dependentservicegroupname",
&percent_escapes, dependent_servicegroup->group_name);
}
return json_selectors;
}
json_object *json_object_servicedependencycount(host *master_host,
hostgroup *master_hostgroup, char *master_service_description,
servicegroup *master_servicegroup, host *dependent_host,
hostgroup *dependent_hostgroup, char * dependent_service_description,
servicegroup *dependent_servicegroup) {
json_object *json_data;
#ifdef JSON_NAGIOS_4X
int x;
#endif
servicedependency *temp_servicedependency;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_servicedependency_selectors(0, 0, master_host,
master_hostgroup, master_service_description, master_servicegroup,
dependent_host, dependent_hostgroup, dependent_service_description,
dependent_servicegroup));
#ifdef JSON_NAGIOS_4X
for(x = 0; x < num_objects.servicedependencies; x++) {
temp_servicedependency = servicedependency_ary[ x];
#else
for(temp_servicedependency = servicedependency_list;
temp_servicedependency != NULL;
temp_servicedependency = temp_servicedependency->next) {
#endif
if(json_object_servicedependency_passes_selection(temp_servicedependency,
master_host, master_hostgroup, master_service_description,
master_servicegroup, dependent_host, dependent_hostgroup,
dependent_service_description, dependent_servicegroup)) {
count++;
}
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_servicedependencylist(unsigned format_options,
int start, int count, host *master_host, hostgroup *master_hostgroup,
char *master_service_description, servicegroup *master_servicegroup,
host *dependent_host, hostgroup *dependent_hostgroup,
char * dependent_service_description,
servicegroup *dependent_servicegroup) {
json_object *json_data;
json_array *json_servicedependencylist;
json_object *json_servicedependency_details;
#ifdef JSON_NAGIOS_4X
int x;
#endif
servicedependency *temp_servicedependency;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_servicedependency_selectors(start, count,
master_host, master_hostgroup, master_service_description,
master_servicegroup, dependent_host, dependent_hostgroup,
dependent_service_description, dependent_servicegroup));
json_servicedependencylist = json_new_array();
#ifdef JSON_NAGIOS_4X
for(x = 0; x < num_objects.servicedependencies; x++) {
temp_servicedependency = servicedependency_ary[ x];
#else
for(temp_servicedependency = servicedependency_list;
temp_servicedependency != NULL;
temp_servicedependency = temp_servicedependency->next) {
#endif
if(!json_object_servicedependency_passes_selection(temp_servicedependency,
master_host, master_hostgroup, master_service_description,
master_servicegroup, dependent_host, dependent_hostgroup,
dependent_service_description, dependent_servicegroup)) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count,
current, counted)) {
json_servicedependency_details = json_new_object();
json_object_servicedependency_details(json_servicedependency_details,
format_options, temp_servicedependency);
json_array_append_object(json_servicedependencylist,
json_servicedependency_details);
}
counted++;
current++;
}
json_object_append_array(json_data, "servicedependencylist",
json_servicedependencylist);
return json_data;
}
void json_object_servicedependency_details(json_object *json_details,
unsigned format_options, servicedependency *temp_servicedependency) {
json_object_append_integer(json_details, "dependency_type",
temp_servicedependency->dependency_type);
json_object_append_string(json_details, "dependent_host_name",
&percent_escapes, temp_servicedependency->dependent_host_name);
json_object_append_string(json_details, "dependent_service_description",
&percent_escapes,
temp_servicedependency->dependent_service_description);
json_object_append_string(json_details, "host_name",
&percent_escapes, temp_servicedependency->host_name);
json_object_append_string(json_details, "service_description",
&percent_escapes, temp_servicedependency->service_description);
json_object_append_string(json_details, "dependency_period",
&percent_escapes, temp_servicedependency->dependency_period);
json_object_append_boolean(json_details, "inherits_parent",
temp_servicedependency->inherits_parent);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "fail_on_ok",
flag_isset(temp_servicedependency->failure_options, OPT_OK));
json_object_append_boolean(json_details, "fail_on_warning",
flag_isset(temp_servicedependency->failure_options,
OPT_WARNING));
json_object_append_boolean(json_details, "fail_on_unknown",
flag_isset(temp_servicedependency->failure_options,
OPT_UNKNOWN));
json_object_append_boolean(json_details, "fail_on_critical",
flag_isset(temp_servicedependency->failure_options,
OPT_CRITICAL));
json_object_append_boolean(json_details, "fail_on_pending",
flag_isset(temp_servicedependency->failure_options,
OPT_PENDING));
}
else {
#endif
json_bitmask(json_details, format_options, "failure_options",
temp_servicedependency->failure_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "fail_on_ok",
temp_servicedependency->fail_on_ok);
json_object_append_boolean(json_details, "fail_on_warning",
temp_servicedependency->fail_on_warning);
json_object_append_boolean(json_details, "fail_on_unknown",
temp_servicedependency->fail_on_unknown);
json_object_append_boolean(json_details, "fail_on_critical",
temp_servicedependency->fail_on_critical);
json_object_append_boolean(json_details, "fail_on_pending",
temp_servicedependency->fail_on_pending);
#endif
}
int json_object_serviceescalation_passes_selection(serviceescalation *temp_serviceescalation,
host *match_host, char *service_description,
hostgroup *match_hostgroup, servicegroup *match_servicegroup,
contact *match_contact, contactgroup *match_contactgroup) {
int found;
hostsmember *temp_hostsmember;
servicesmember *temp_servicesmember;
/* Skip if the serviceescalation is not for the specified host */
if( NULL != match_host &&
strcmp( temp_serviceescalation->host_name, match_host->name)) {
return 0;
}
if((NULL != service_description) &&
strcmp(temp_serviceescalation->description, service_description)) {
return 0;
}
if(NULL != match_hostgroup) {
found = 0;
for(temp_hostsmember = match_hostgroup->members;
temp_hostsmember != NULL;
temp_hostsmember = temp_hostsmember->next) {
if(!strcmp(temp_hostsmember->host_name,
temp_serviceescalation->host_name)) {
found = 1;
break;
}
}
if(0 == found) {
return 0;
}
}
if(NULL != match_servicegroup) {
found = 0;
for(temp_servicesmember = match_servicegroup->members;
temp_servicesmember != NULL;
temp_servicesmember = temp_servicesmember->next) {
if(!strcmp(temp_servicesmember->host_name,
temp_serviceescalation->host_name) &&
!strcmp(temp_servicesmember->service_description,
temp_serviceescalation->description)) {
found = 1;
break;
}
}
if(0 == found) {
return 0;
}
}
/* If a contact was specified, skip this service escalation if it does
not have the contact specified */
if( NULL != match_contact &&
( FALSE == is_contact_for_service_escalation(temp_serviceescalation,
match_contact))) {
return 0;
}
/* If a contactgroup was specified, skip this service escalation if
it does not have the contactgroup specified */
if(NULL != match_contactgroup && (FALSE ==
is_contactgroup_for_service_escalation(temp_serviceescalation,
match_contactgroup))) {
return 0;
}
return 1;
}
json_object *json_object_serviceescalation_selectors(int start, int count,
host *match_host, char *service_description,
hostgroup *match_hostgroup, servicegroup *match_servicegroup,
contact *match_contact, contactgroup *match_contactgroup) {
json_object *json_selectors;
json_selectors = json_new_object();
if(start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if(count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if(NULL != match_host) {
json_object_append_string(json_selectors, "hostname", &percent_escapes,
match_host->name);
}
if(NULL != service_description) {
json_object_append_string(json_selectors, "servicedescription",
&percent_escapes, service_description);
}
if(NULL != match_hostgroup) {
json_object_append_string(json_selectors, "hostgroup",
&percent_escapes, match_hostgroup->group_name);
}
if(NULL != match_servicegroup) {
json_object_append_string(json_selectors, "servicegroup",
&percent_escapes, match_servicegroup->group_name);
}
if( NULL != match_contact) {
json_object_append_string(json_selectors, "contact",
&percent_escapes, match_contact->name);
}
if( NULL != match_contactgroup) {
json_object_append_string(json_selectors, "contactgroup",
&percent_escapes, match_contactgroup->group_name);
}
return json_selectors;
}
json_object *json_object_serviceescalationcount(host *match_host,
char *service_description, hostgroup *match_hostgroup,
servicegroup *match_servicegroup, contact *match_contact,
contactgroup *match_contactgroup) {
json_object *json_data;
#ifdef JSON_NAGIOS_4X
int x;
#endif
serviceescalation *temp_serviceescalation;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_serviceescalation_selectors(0, 0, match_host,
service_description, match_hostgroup, match_servicegroup,
match_contact, match_contactgroup));
#ifdef JSON_NAGIOS_4X
for(x = 0; x < num_objects.serviceescalations; x++) {
temp_serviceescalation=serviceescalation_ary[ x];
#else
for(temp_serviceescalation = serviceescalation_list;
temp_serviceescalation != NULL;
temp_serviceescalation = temp_serviceescalation->next) {
#endif
if(json_object_serviceescalation_passes_selection(temp_serviceescalation,
match_host, service_description, match_hostgroup,
match_servicegroup, match_contact, match_contactgroup) == 0) {
continue;
}
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_serviceescalationlist(unsigned format_options,
int start, int count, host *match_host, char *service_description,
hostgroup *match_hostgroup, servicegroup *match_servicegroup,
contact *match_contact, contactgroup *match_contactgroup) {
json_object *json_data;
json_array *json_serviceescalationlist;
json_object *json_serviceescalation_details;
#ifdef JSON_NAGIOS_4X
int x;
#endif
serviceescalation *temp_serviceescalation;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_serviceescalation_selectors(start, count, match_host,
service_description, match_hostgroup, match_servicegroup,
match_contact, match_contactgroup));
json_serviceescalationlist = json_new_array();
#ifdef JSON_NAGIOS_4X
for(x = 0; x < num_objects.serviceescalations; x++) {
temp_serviceescalation=serviceescalation_ary[ x];
#else
for(temp_serviceescalation = serviceescalation_list;
temp_serviceescalation != NULL;
temp_serviceescalation = temp_serviceescalation->next) {
#endif
if(json_object_serviceescalation_passes_selection(temp_serviceescalation,
match_host, service_description, match_hostgroup,
match_servicegroup, match_contact, match_contactgroup) == 0) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
json_serviceescalation_details = json_new_object();
json_object_serviceescalation_details(json_serviceescalation_details,
format_options, temp_serviceescalation);
json_array_append_object(json_serviceescalationlist,
json_serviceescalation_details);
}
counted++;
current++;
}
json_object_append_array(json_data, "serviceescalationlist",
json_serviceescalationlist);
return json_data;
}
void json_object_serviceescalation_details(json_object *json_details,
unsigned format_options, serviceescalation *temp_serviceescalation) {
json_array *json_contactgroups;
json_array *json_contacts;
contactgroupsmember *temp_contact_groupsmember;
contactsmember *temp_contactsmember;
json_object_append_string(json_details, "host_name", &percent_escapes,
temp_serviceescalation->host_name);
json_object_append_string(json_details, "description", &percent_escapes,
temp_serviceescalation->description);
json_object_append_integer(json_details, "first_notification",
temp_serviceescalation->first_notification);
json_object_append_integer(json_details, "last_notification",
temp_serviceescalation->last_notification);
json_object_append_real(json_details, "notification_interval",
temp_serviceescalation->notification_interval);
json_object_append_string(json_details, "escalation_period",
&percent_escapes, temp_serviceescalation->escalation_period);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "escalate_on_recovery",
flag_isset(temp_serviceescalation->escalation_options,
OPT_RECOVERY));
json_object_append_boolean(json_details, "escalate_on_warning",
flag_isset(temp_serviceescalation->escalation_options,
OPT_WARNING));
json_object_append_boolean(json_details, "escalate_on_unknown",
flag_isset(temp_serviceescalation->escalation_options,
OPT_UNKNOWN)));
json_object_append_boolean(json_details, "escalate_on_critical",
flag_isset(temp_serviceescalation->escalation_options,
OPT_CRITICAL));
}
else {
#endif
json_bitmask(json_details, format_options, "escalation_options",
temp_serviceescalation->escalation_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "escalate_on_recovery",
temp_serviceescalation->escalate_on_recovery);
json_object_append_boolean(json_details, "escalate_on_warning",
temp_serviceescalation->escalate_on_warning);
json_object_append_boolean(json_details, "escalate_on_unknown",
temp_serviceescalation->escalate_on_unknown);
json_object_append_boolean(json_details, "escalate_on_critical",
temp_serviceescalation->escalate_on_critical);
#endif
json_contactgroups = json_new_object();
for(temp_contact_groupsmember = temp_serviceescalation->contact_groups;
temp_contact_groupsmember != NULL;
temp_contact_groupsmember = temp_contact_groupsmember->next) {
json_array_append_string(json_contactgroups, &percent_escapes,
temp_contact_groupsmember->group_name);
}
json_object_append_array(json_details, "contact_groups", json_contactgroups);
json_contacts = json_new_object();
for(temp_contactsmember = temp_serviceescalation->contacts;
temp_contactsmember != NULL;
temp_contactsmember = temp_contactsmember->next) {
json_array_append_string(json_contacts, &percent_escapes,
temp_contactsmember->contact_name);
}
json_object_append_array(json_details, "contacts", json_contacts);
}
int json_object_hostdependency_passes_selection(
hostdependency *temp_hostdependency, host *master_host,
hostgroup *master_hostgroup, host *dependent_host,
hostgroup *dependent_hostgroup) {
host *temp_host = NULL;
/* Skip if the hostdependency does not have the specified master host */
if(NULL != master_host &&
strcmp(temp_hostdependency->host_name, master_host->name)) {
return 0;
}
/* Skip if the hostdependency does not have a master host in the
specified hostgroup*/
if(NULL != master_hostgroup) {
temp_host = find_host(temp_hostdependency->host_name);
if((NULL != temp_host) && (FALSE ==
is_host_member_of_hostgroup(master_hostgroup, temp_host))) {
return 0;
}
}
/* Skip if the hostdependency does not have the specified dependent host */
if(NULL != dependent_host &&
strcmp(temp_hostdependency->dependent_host_name,
dependent_host->name)) {
return 0;
}
/* Skip if the hostdependency does not have a dependent host in the
specified hostgroup*/
if(NULL != dependent_hostgroup) {
temp_host = find_host(temp_hostdependency->dependent_host_name);
if((NULL != temp_host) && (FALSE ==
is_host_member_of_hostgroup(dependent_hostgroup, temp_host))) {
return 0;
}
}
return 1;
}
json_object *json_object_hostdependency_selectors(int start, int count,
host *master_host, hostgroup *master_hostgroup, host *dependent_host,
hostgroup *dependent_hostgroup) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if(NULL != master_host) {
json_object_append_string(json_selectors, "masterhostname",
&percent_escapes, master_host->name);
}
if(NULL != master_hostgroup) {
json_object_append_string(json_selectors, "masterhostgroupname",
&percent_escapes, master_hostgroup->group_name);
}
if(NULL != dependent_host) {
json_object_append_string(json_selectors, "dependenthostname",
&percent_escapes, dependent_host->name);
}
if(NULL != dependent_hostgroup) {
json_object_append_string(json_selectors, "dependenthostgroupname",
&percent_escapes, dependent_hostgroup->group_name);
}
return json_selectors;
}
json_object *json_object_hostdependencycount(host *master_host,
hostgroup *master_hostgroup, host *dependent_host,
hostgroup *dependent_hostgroup) {
json_object *json_data;
#ifdef JSON_NAGIOS_4X
int x;
#endif
hostdependency *temp_hostdependency;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_hostdependency_selectors(0, 0, master_host,
master_hostgroup, dependent_host, dependent_hostgroup));
#ifdef JSON_NAGIOS_4X
for(x = 0; x < num_objects.hostdependencies; x++) {
temp_hostdependency = hostdependency_ary[ x];
#else
for(temp_hostdependency = hostdependency_list;
temp_hostdependency != NULL;
temp_hostdependency = temp_hostdependency->next) {
#endif
if(json_object_hostdependency_passes_selection(
temp_hostdependency, master_host, master_hostgroup,
dependent_host, dependent_hostgroup)) {
count++;
}
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_hostdependencylist(unsigned format_options, int start,
int count, host *master_host, hostgroup *master_hostgroup,
host *dependent_host, hostgroup *dependent_hostgroup) {
json_object *json_data;
json_array *json_hostdependencylist;
#ifdef JSON_NAGIOS_4X
int x;
#endif
json_object *json_hostdependency_details;
hostdependency *temp_hostdependency;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_hostdependency_selectors(start, count,
master_host, master_hostgroup, dependent_host,
dependent_hostgroup));
json_hostdependencylist = json_new_array();
#ifdef JSON_NAGIOS_4X
for(x = 0; x < num_objects.hostdependencies; x++) {
temp_hostdependency = hostdependency_ary[ x];
#else
for(temp_hostdependency = hostdependency_list;
temp_hostdependency != NULL;
temp_hostdependency = temp_hostdependency->next) {
#endif
if(!json_object_hostdependency_passes_selection(
temp_hostdependency, master_host, master_hostgroup,
dependent_host, dependent_hostgroup)) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
json_hostdependency_details = json_new_object();
json_object_hostdependency_details(json_hostdependency_details,
format_options, temp_hostdependency);
json_array_append_object(json_hostdependencylist,
json_hostdependency_details);
}
counted++;
current++;
}
json_object_append_array(json_data, "hostdependencylist",
json_hostdependencylist);
return json_data;
}
void json_object_hostdependency_details(json_object *json_details,
unsigned format_options, hostdependency *temp_hostdependency) {
json_object_append_integer(json_details, "dependency_type",
temp_hostdependency->dependency_type);
json_object_append_string(json_details, "dependent_host_name",
&percent_escapes, temp_hostdependency->dependent_host_name);
json_object_append_string(json_details, "host_name",
&percent_escapes, temp_hostdependency->host_name);
json_object_append_string(json_details, "dependency_period",
&percent_escapes, temp_hostdependency->dependency_period);
json_object_append_boolean(json_details, "inherits_parent",
temp_hostdependency->inherits_parent);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "fail_on_up",
flag_isset(temp_hostdependency->failure_options, OPT_UP));
json_object_append_boolean(json_details, "fail_on_down",
flag_isset(temp_hostdependency->failure_options, OPT_DOWN));
json_object_append_boolean(json_details, "fail_on_unreachable",
flag_isset(temp_hostdependency->failure_options,
OPT_UNREACHABLE));
json_object_append_boolean(json_details, "fail_on_pending",
flag_isset(temp_hostdependency->failure_options, OPT_PENDING));
}
else {
#endif
json_bitmask(json_details, format_options, "failure_options",
temp_hostdependency->failure_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "fail_on_up",
temp_hostdependency->fail_on_up);
json_object_append_boolean(json_details, "fail_on_down",
temp_hostdependency->fail_on_down);
json_object_append_boolean(json_details, "fail_on_unreachable",
temp_hostdependency->fail_on_unreachable);
json_object_append_boolean(json_details, "fail_on_pending",
temp_hostdependency->fail_on_pending);
#endif
}
int json_object_hostescalation_passes_selection(hostescalation *temp_hostescalation,
host *match_host, hostgroup *match_hostgroup, contact *match_contact,
contactgroup *match_contactgroup) {
int found;
hostsmember *temp_hostsmember;
/* Skip if the hostescalation is not for the specified host */
if( NULL != match_host &&
strcmp( temp_hostescalation->host_name, match_host->name)) {
return 0;
}
if(NULL != match_hostgroup) {
found = 0;
for(temp_hostsmember = match_hostgroup->members;
temp_hostsmember != NULL;
temp_hostsmember = temp_hostsmember->next) {
if(!strcmp(temp_hostsmember->host_name,
temp_hostescalation->host_name)) {
found = 1;
break;
}
}
if(0 == found) {
return 0;
}
}
/* If a contact was specified, skip this host escalation if it does
not have the contact specified */
if( NULL != match_contact &&
( FALSE == is_contact_for_host_escalation(temp_hostescalation,
match_contact))) {
return 0;
}
/* If a contactgroup was specified, skip this host escalation if
it does not have the contactgroup specified */
if(NULL != match_contactgroup && (FALSE ==
is_contactgroup_for_host_escalation(temp_hostescalation,
match_contactgroup))) {
return 0;
}
return 1;
}
json_object *json_object_hostescalation_selectors(int start, int count,
host *match_host, hostgroup *match_hostgroup, contact *match_contact,
contactgroup *match_contactgroup) {
json_object *json_selectors;
json_selectors = json_new_object();
if( start > 0) {
json_object_append_integer(json_selectors, "start", start);
}
if( count > 0) {
json_object_append_integer(json_selectors, "count", count);
}
if( NULL != match_host) {
json_object_append_string(json_selectors, "hostname", &percent_escapes,
match_host->name);
}
if(NULL != match_hostgroup) {
json_object_append_string(json_selectors, "hostgroup",
&percent_escapes, match_hostgroup->group_name);
}
if( NULL != match_contact) {
json_object_append_string(json_selectors, "contact",
&percent_escapes, match_contact->name);
}
if( NULL != match_contactgroup) {
json_object_append_string(json_selectors, "contactgroup",
&percent_escapes, match_contactgroup->group_name);
}
return json_selectors;
}
json_object *json_object_hostescalationcount(host *match_host,
hostgroup *match_hostgroup, contact *match_contact,
contactgroup *match_contactgroup) {
json_object *json_data;
#ifdef JSON_NAGIOS_4X
int x;
#endif
hostescalation *temp_hostescalation;
int count = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_hostescalation_selectors(0, 0, match_host,
match_hostgroup, match_contact, match_contactgroup));
#ifdef JSON_NAGIOS_4X
for(x = 0; x < num_objects.hostescalations; x++) {
temp_hostescalation = hostescalation_ary[ x];
#else
for(temp_hostescalation = hostescalation_list;
temp_hostescalation != NULL;
temp_hostescalation = temp_hostescalation->next) {
#endif
if(json_object_hostescalation_passes_selection(temp_hostescalation,
match_host, match_hostgroup, match_contact,
match_contactgroup) == 0) {
continue;
}
count++;
}
json_object_append_integer(json_data, "count", count);
return json_data;
}
json_object *json_object_hostescalationlist(unsigned format_options, int start,
int count, host *match_host, hostgroup *match_hostgroup,
contact *match_contact, contactgroup *match_contactgroup) {
json_object *json_data;
json_array *json_hostescalationlist;
json_object *json_hostescalation_details;
#ifdef JSON_NAGIOS_4X
int x;
#endif
hostescalation *temp_hostescalation;
int current = 0;
int counted = 0;
json_data = json_new_object();
json_object_append_object(json_data, "selectors",
json_object_hostescalation_selectors(start, count, match_host,
match_hostgroup, match_contact, match_contactgroup));
json_hostescalationlist = json_new_array();
#ifdef JSON_NAGIOS_4X
for(x = 0; x < num_objects.hostescalations; x++) {
temp_hostescalation = hostescalation_ary[ x];
#else
for(temp_hostescalation = hostescalation_list;
temp_hostescalation != NULL;
temp_hostescalation = temp_hostescalation->next) {
#endif
if(json_object_hostescalation_passes_selection(temp_hostescalation,
match_host, match_hostgroup, match_contact,
match_contactgroup) == 0) {
continue;
}
/* If the current item passes the start and limit tests, display it */
if( passes_start_and_count_limits(start, count, current, counted)) {
json_hostescalation_details = json_new_object();
json_object_hostescalation_details(json_hostescalation_details,
format_options, temp_hostescalation);
json_array_append_object(json_hostescalationlist,
json_hostescalation_details);
}
counted++;
current++;
}
json_object_append_array(json_data, "hostescalationlist",
json_hostescalationlist);
return json_data;
}
void json_object_hostescalation_details(json_object *json_details,
unsigned format_options, hostescalation *temp_hostescalation) {
json_array *json_contactgroups;
json_array *json_contacts;
contactgroupsmember *temp_contact_groupsmember;
contactsmember *temp_contactsmember;
json_object_append_string(json_details, "host_name", &percent_escapes,
temp_hostescalation->host_name);
json_object_append_integer(json_details, "first_notification",
temp_hostescalation->first_notification);
json_object_append_integer(json_details, "last_notification",
temp_hostescalation->last_notification);
json_object_append_real(json_details, "notification_interval",
temp_hostescalation->notification_interval);
json_object_append_string(json_details, "escalation_period",
&percent_escapes, temp_hostescalation->escalation_period);
#ifdef JSON_NAGIOS_4X
#if 0
if( CORE3_COMPATIBLE) {
json_object_append_boolean(json_details, "escalate_on_recovery",
flag_isset(temp_hostescalation->escalation_options,
OPT_RECOVERY));
json_object_append_boolean(json_details, "escalate_on_down",
flag_isset(temp_hostescalation->escalation_options, OPT_DOWN));
json_object_append_boolean(json_details, "escalate_on_unreachable",
flag_isset(temp_hostescalation->escalation_options,
OPT_UNREACHABLE));
}
else {
#endif
json_bitmask(json_details, format_options, "escalation_options",
temp_hostescalation->escalation_options, svm_option_types);
#if 0
}
#endif
#else
json_object_append_boolean(json_details, "escalate_on_recovery",
temp_hostescalation->escalate_on_recovery);
json_object_append_boolean(json_details, "escalate_on_down",
temp_hostescalation->escalate_on_down);
json_object_append_boolean(json_details, "escalate_on_unreachable",
temp_hostescalation->escalate_on_unreachable);
#endif
json_contactgroups = json_new_array();
for(temp_contact_groupsmember = temp_hostescalation->contact_groups;
temp_contact_groupsmember != NULL;
temp_contact_groupsmember = temp_contact_groupsmember->next) {
json_array_append_string(json_contactgroups, &percent_escapes,
temp_contact_groupsmember->group_name);
}
json_object_append_array(json_details, "contact_groups", json_contactgroups);
json_contacts = json_new_array();
for(temp_contactsmember = temp_hostescalation->contacts;
temp_contactsmember != NULL;
temp_contactsmember = temp_contactsmember->next) {
json_array_append_string(json_contacts, &percent_escapes,
temp_contactsmember->contact_name);
}
json_object_append_array(json_details, "contacts", json_contacts);
}
nagios-4.4.6/cgi/outages.c 0000664 0000000 0000000 00000046250 13652113235 0015372 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* OUTAGES.C - Nagios Network Outages CGI
*
*
* 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 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];
/* 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) {
/* get the arguments passed in the URL */
process_cgivars();
/* reset internal variables */
reset_cgi_vars();
cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, READ_ALL_STATUS_DATA);
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_authdata);
if(display_header == TRUE) {
/* begin top table */
printf("
\n");
/* display context-sensitive help */
display_context_help(CONTEXTHELP_OUTAGES);
printf("
\n");
/* end of top table */
printf("
\n");
printf("
\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(¤t_time);
get_time_string(¤t_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; charset=utf-8\r\n\r\n");
if(embedded == TRUE)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Network Outages\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("", url_stylesheets_path, COMMON_CSS);
printf("", url_stylesheets_path, OUTAGES_CSS);
}
printf("\n");
printf("\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("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
for(x = 0; variables[x]; 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 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;
const char *bg_class = "";
const 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(¤t_authdata) == FALSE) {
printf("
It appears as though you do not have permission to view information you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\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("
\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 != SD_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 (!is_authorized_for_host(temp_host, ¤t_authdata))
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 == SD_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;
}
nagios-4.4.6/cgi/showlog.c 0000664 0000000 0000000 00000036611 13652113235 0015405 0 ustar 00root root 0000000 0000000 /***********************************************************************
*
* SHOWLOG.C - Nagios Log File CGI
*
*
* 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 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) {
char temp_buffer[MAX_INPUT_BUFFER];
/* get the CGI variables passed in the URL */
process_cgivars();
/* reset internal variables */
reset_cgi_vars();
cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, 0);
document_header(TRUE);
/* get authentication information */
get_authentication_information(¤t_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("
\n");
printf("
\n");
/* left column of top table - info box */
printf("
\n");
printf("\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(¤t_time);
get_time_string(¤t_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; charset=utf-8\r\n\r\n");
if(embedded == TRUE)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Nagios Log File\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, SHOWLOG_CSS);
}
printf("\n");
printf("\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("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
for(x = 0; variables[x]; 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(¤t_authdata) == FALSE) {
printf("\n");
printf("
It appears as though you do not have permission to view the log file...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI and check the authorization options in your CGI configuration file.
\n");
if(display_type == DISPLAY_HOSTS) {
printf("View History For %s \n", HISTORY_CGI, (show_all_hosts == TRUE) ? "all" : url_encode(host_name), (show_all_hosts == TRUE) ? "all hosts" : "This Host");
printf("View Notifications For %s\n", NOTIFICATIONS_CGI, (show_all_hosts == TRUE) ? "all" : url_encode(host_name), (show_all_hosts == TRUE) ? "All Hosts" : "This Host");
if(show_all_hosts == FALSE)
printf(" View Service Status Detail For All Hosts\n", STATUS_CGI);
else
printf(" View Host Status Detail For All Hosts\n", STATUS_CGI);
}
else if(display_type == DISPLAY_SERVICEGROUPS) {
if(show_all_servicegroups == FALSE) {
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_GRID || group_style_type == STYLE_SUMMARY)
printf("View Service Status Detail For This Service Group \n", STATUS_CGI, url_encode(servicegroup_name));
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_GRID || group_style_type == STYLE_SUMMARY)
printf("View Status Overview For This Service Group \n", STATUS_CGI, url_encode(servicegroup_name));
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_GRID)
printf("View Status Summary For This Service Group \n", STATUS_CGI, url_encode(servicegroup_name));
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_SUMMARY)
printf("View Service Status Grid For This Service Group \n", STATUS_CGI, url_encode(servicegroup_name));
if(group_style_type == STYLE_DETAIL)
printf("View Service Status Detail For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW)
printf("View Status Overview For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_SUMMARY)
printf("View Status Summary For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_GRID)
printf("View Service Status Grid For All Service Groups \n", STATUS_CGI);
}
else {
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_GRID || group_style_type == STYLE_SUMMARY)
printf("View Service Status Detail For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_GRID || group_style_type == STYLE_SUMMARY)
printf("View Status Overview For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_GRID)
printf("View Status Summary For All Service Groups \n", STATUS_CGI);
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_SUMMARY)
printf("View Service Status Grid For All Service Groups \n", STATUS_CGI);
}
}
else {
if(show_all_hostgroups == FALSE) {
if(group_style_type == STYLE_DETAIL)
printf("View Service Status Detail For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_HOST_DETAIL)
printf("View Host Status Detail For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW)
printf("View Status Overview For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_SUMMARY)
printf("View Status Summary For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_GRID)
printf("View Status Grid For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Service Status Detail For This Host Group \n", STATUS_CGI, url_encode(hostgroup_name));
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID)
printf("View Host Status Detail For This Host Group \n", STATUS_CGI, url_encode(hostgroup_name));
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Overview For This Host Group \n", STATUS_CGI, url_encode(hostgroup_name));
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Summary For This Host Group \n", STATUS_CGI, url_encode(hostgroup_name));
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Grid For This Host Group \n", STATUS_CGI, url_encode(hostgroup_name));
}
else {
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Service Status Detail For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID)
printf("View Host Status Detail For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Overview For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_GRID || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Summary For All Host Groups \n", STATUS_CGI);
if(group_style_type == STYLE_OVERVIEW || group_style_type == STYLE_DETAIL || group_style_type == STYLE_SUMMARY || group_style_type == STYLE_HOST_DETAIL)
printf("View Status Grid For All Host Groups \n", STATUS_CGI);
}
}
printf("
\n");
printf("
\n");
printf("
\n");
/* middle column of top row */
printf("
\n");
show_host_status_totals();
printf("
\n");
/* right hand column of top row */
printf("
\n");
show_service_status_totals();
printf("
\n");
/* display context-sensitive help */
printf("
", EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(temp_status->host_name), url_images_path, ACKNOWLEDGEMENT_ICON, STATUS_ICON_WIDTH, STATUS_ICON_HEIGHT);
}
/* only show comments if this is a non-read-only user */
if(is_authorized_for_read_only(¤t_authdata) == FALSE) {
if(total_comments > 0)
printf("
\n");
total_comments = number_of_service_comments(temp_service->host_name, temp_service->description);
/* only show comments if this is a non-read-only user */
if(is_authorized_for_read_only(¤t_authdata) == FALSE) {
if(total_comments > 0) {
printf("
\n");
/* mod to account for paging */
if(visible_entries != 0)
last_host = temp_status->host_name;
}
}
printf("
\n");
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE) {
if(servicestatus_list != NULL) {
printf("
It appears as though you do not have permission to view information for any of the services you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
}
else {
printf("
There doesn't appear to be any service status information in the status log...
\n");
printf("Make sure that Nagios is running and that you have specified the location of you status log correctly in the configuration files.
\n");
}
}
else {
/* do page numbers if applicable */
create_pagenumbers(total_entries,temp_url,TRUE);
}
return;
}
/* display a detailed listing of the status of all hosts... */
void show_host_detail(void) {
time_t t;
char date_time[MAX_DATETIME_LENGTH];
char state_duration[48];
char status[MAX_INPUT_BUFFER];
char temp_buffer[MAX_INPUT_BUFFER];
char temp_url[MAX_INPUT_BUFFER];
char *processed_string = NULL;
const char *status_class = "";
const char *status_bg_class = "";
hoststatus *temp_status = NULL;
hostgroup *temp_hostgroup = NULL;
host *temp_host = NULL;
hostsort *temp_hostsort = NULL;
int odd = 0;
int total_comments = 0;
int user_has_seen_something = FALSE;
int use_sort = FALSE;
int result = OK;
int first_entry = TRUE;
int days;
int hours;
int minutes;
int seconds;
int duration_error = FALSE;
int total_entries = 0;
int visible_entries = 0;
regex_t preg_hostname;
// int show_host = FALSE;
if(host_filter != NULL)
regcomp(&preg_hostname, host_filter, REG_ICASE);
/* sort the host list if necessary */
if(sort_type != SORT_NONE) {
result = sort_hosts(sort_type, sort_option);
if(result == ERROR)
use_sort = FALSE;
else
use_sort = TRUE;
}
else
use_sort = FALSE;
// printf("
\n");
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE) {
if(hoststatus_list != NULL) {
printf("
It appears as though you do not have permission to view information for any of the hosts you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
}
else {
printf("
There doesn't appear to be any host status information in the status log...
\n");
printf("Make sure that Nagios is running and that you have specified the location of you status log correctly in the configuration files.
\n");
}
}
else {
/* do page numbers if applicable */
create_pagenumbers(total_entries,temp_url,FALSE);
}
return;
}
/* show an overview of servicegroup(s)... */
void show_servicegroup_overviews(void) {
servicegroup *temp_servicegroup = NULL;
int current_column;
int user_has_seen_something = FALSE;
int servicegroup_error = FALSE;
//printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Service Overview For ");
if(show_all_servicegroups == TRUE)
printf("All Service Groups");
else
printf("Service Group '%s'", servicegroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
//printf("\n");
/* display status overviews for all servicegroups */
if(show_all_servicegroups == TRUE) {
printf("
\n");
printf("
\n");
current_column = 1;
/* loop through all servicegroups... */
for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next) {
/* make sure the user is authorized to view at least one host in this servicegroup */
if(is_authorized_for_servicegroup(temp_servicegroup, ¤t_authdata) == FALSE)
continue;
if(current_column == 1)
printf("
Sorry, but service group '%s' doesn't seem to exist...
", servicegroup_name);
servicegroup_error = TRUE;
}
}
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && servicegroup_error == FALSE) {
//printf("
\n");
printf("
\n");
if(servicegroup_list != NULL) {
printf("
It appears as though you do not have permission to view information for any of the hosts you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
}
else {
printf("
There are no service groups defined.
\n");
}
printf("
\n");
//printf("\n");
}
return;
}
/* shows an overview of a specific servicegroup... */
void show_servicegroup_overview(servicegroup *temp_servicegroup) {
servicesmember *temp_member;
host *temp_host;
host *last_host;
hoststatus *temp_hoststatus = NULL;
int odd = 0;
printf("
\n");
/* find all hosts that have services that are members of the servicegroup */
last_host = NULL;
for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
/* find the host */
temp_host = find_host(temp_member->host_name);
if(temp_host == NULL)
continue;
/* make sure user has rights to view this host */
if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE)
continue;
/* skip this if it isn't a new host... */
if(temp_host == last_host)
continue;
/* find the host status */
temp_hoststatus = find_hoststatus(temp_host->name);
if(temp_hoststatus == NULL)
continue;
/* make sure we only display hosts of the specified status levels */
if(!(host_status_types & temp_hoststatus->status))
continue;
/* make sure we only display hosts that have the desired properties */
if(passes_host_properties_filter(temp_hoststatus) == FALSE)
continue;
if(odd)
odd = 0;
else
odd = 1;
show_servicegroup_hostgroup_member_overview(temp_hoststatus, odd, temp_servicegroup);
last_host = temp_host;
}
printf("
\n");
printf("
\n");
return;
}
/* show a summary of servicegroup(s)... */
void show_servicegroup_summaries(void) {
servicegroup *temp_servicegroup = NULL;
int user_has_seen_something = FALSE;
int servicegroup_error = FALSE;
int odd = 0;
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Status Summary For ");
if(show_all_servicegroups == TRUE)
printf("All Service Groups");
else
printf("Service Group '%s'", servicegroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Service Group
Host Status Summary
Service Status Summary
\n");
printf("
\n");
/* display status summary for all servicegroups */
if(show_all_servicegroups == TRUE) {
/* loop through all servicegroups... */
for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next) {
/* make sure the user is authorized to view at least one host in this servicegroup */
if(is_authorized_for_servicegroup(temp_servicegroup, ¤t_authdata) == FALSE)
continue;
if(odd == 0)
odd = 1;
else
odd = 0;
/* show summary for this servicegroup */
show_servicegroup_summary(temp_servicegroup, odd);
user_has_seen_something = TRUE;
}
}
/* else just show summary for a specific servicegroup */
else {
temp_servicegroup = find_servicegroup(servicegroup_name);
if(temp_servicegroup == NULL)
servicegroup_error = TRUE;
else {
show_servicegroup_summary(temp_servicegroup, 1);
user_has_seen_something = TRUE;
}
}
printf("
\n");
printf("
\n");
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && servicegroup_error == FALSE) {
printf("
\n");
if(servicegroup_list != NULL) {
printf("
It appears as though you do not have permission to view information for any of the hosts you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
}
else {
printf("
There are no service groups defined.
\n");
}
printf("
\n");
}
/* we couldn't find the servicegroup */
else if(servicegroup_error == TRUE) {
printf("
\n");
printf("
Sorry, but servicegroup '%s' doesn't seem to exist...
\n", servicegroup_name);
printf("
\n");
}
return;
}
/* displays status summary information for a specific servicegroup */
void show_servicegroup_summary(servicegroup *temp_servicegroup, int odd) {
const char *status_bg_class = "";
if(odd == 1)
status_bg_class = "Even";
else
status_bg_class = "Odd";
printf("
\n");
return;
}
/* shows host total summary information for a specific servicegroup */
void show_servicegroup_host_totals_summary(servicegroup *temp_servicegroup) {
servicesmember *temp_member;
int hosts_up = 0;
int hosts_down = 0;
int hosts_unreachable = 0;
int hosts_pending = 0;
int hosts_down_scheduled = 0;
int hosts_down_acknowledged = 0;
int hosts_down_disabled = 0;
int hosts_down_unacknowledged = 0;
int hosts_unreachable_scheduled = 0;
int hosts_unreachable_acknowledged = 0;
int hosts_unreachable_disabled = 0;
int hosts_unreachable_unacknowledged = 0;
hoststatus *temp_hoststatus = NULL;
host *temp_host = NULL;
host *last_host = NULL;
int problem = FALSE;
/* find all the hosts that belong to the servicegroup */
for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
/* find the host... */
temp_host = find_host(temp_member->host_name);
if(temp_host == NULL)
continue;
/* make sure user has rights to view this host */
if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE)
continue;
/* skip this if it isn't a new host... */
if(temp_host == last_host)
continue;
/* find the host status */
temp_hoststatus = find_hoststatus(temp_host->name);
if(temp_hoststatus == NULL)
continue;
/* make sure we only display hosts of the specified status levels */
if(!(host_status_types & temp_hoststatus->status))
continue;
/* make sure we only display hosts that have the desired properties */
if(passes_host_properties_filter(temp_hoststatus) == FALSE)
continue;
problem = TRUE;
if(temp_hoststatus->status == SD_HOST_UP)
hosts_up++;
else if(temp_hoststatus->status == SD_HOST_DOWN) {
if(temp_hoststatus->scheduled_downtime_depth > 0) {
hosts_down_scheduled++;
problem = FALSE;
}
if(temp_hoststatus->problem_has_been_acknowledged == TRUE) {
hosts_down_acknowledged++;
problem = FALSE;
}
if(temp_hoststatus->checks_enabled == FALSE) {
hosts_down_disabled++;
problem = FALSE;
}
if(problem == TRUE)
hosts_down_unacknowledged++;
hosts_down++;
}
else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) {
if(temp_hoststatus->scheduled_downtime_depth > 0) {
hosts_unreachable_scheduled++;
problem = FALSE;
}
if(temp_hoststatus->problem_has_been_acknowledged == TRUE) {
hosts_unreachable_acknowledged++;
problem = FALSE;
}
if(temp_hoststatus->checks_enabled == FALSE) {
hosts_unreachable_disabled++;
problem = FALSE;
}
if(problem == TRUE)
hosts_unreachable_unacknowledged++;
hosts_unreachable++;
}
else
hosts_pending++;
last_host = temp_host;
}
printf("
\n");
if((services_ok + services_warning + services_unknown + services_critical + services_pending) == 0)
printf("No matching services");
return;
}
/* show a grid layout of servicegroup(s)... */
void show_servicegroup_grids(void) {
servicegroup *temp_servicegroup = NULL;
int user_has_seen_something = FALSE;
int servicegroup_error = FALSE;
int odd = 0;
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Status Grid For ");
if(show_all_servicegroups == TRUE)
printf("All Service Groups");
else
printf("Service Group '%s'", servicegroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
/* display status grids for all servicegroups */
if(show_all_servicegroups == TRUE) {
/* loop through all servicegroups... */
for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next) {
/* make sure the user is authorized to view at least one host in this servicegroup */
if(is_authorized_for_servicegroup(temp_servicegroup, ¤t_authdata) == FALSE)
continue;
if(odd == 0)
odd = 1;
else
odd = 0;
/* show grid for this servicegroup */
show_servicegroup_grid(temp_servicegroup);
user_has_seen_something = TRUE;
}
}
/* else just show grid for a specific servicegroup */
else {
temp_servicegroup = find_servicegroup(servicegroup_name);
if(temp_servicegroup == NULL)
servicegroup_error = TRUE;
else {
show_servicegroup_grid(temp_servicegroup);
user_has_seen_something = TRUE;
}
}
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && servicegroup_error == FALSE) {
printf("
\n");
if(servicegroup_list != NULL) {
printf("
It appears as though you do not have permission to view information for any of the hosts you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
}
else {
printf("
There are no service groups defined.
\n");
}
printf("
\n");
}
/* we couldn't find the servicegroup */
else if(servicegroup_error == TRUE) {
printf("
\n");
printf("
Sorry, but servicegroup '%s' doesn't seem to exist...
\n", servicegroup_name);
printf("
\n");
}
return;
}
/* displays status grid for a specific servicegroup */
void show_servicegroup_grid(servicegroup *temp_servicegroup) {
const char *status_bg_class = "";
const char *host_status_class = "";
const char *service_status_class = "";
char *processed_string = NULL;
servicesmember *temp_member;
servicesmember *temp_member2;
host *temp_host;
host *last_host;
hoststatus *temp_hoststatus;
servicestatus *temp_servicestatus;
int odd = 0;
int current_item;
printf("
\n");
/* find all hosts that have services that are members of the servicegroup */
last_host = NULL;
for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) {
/* find the host */
temp_host = find_host(temp_member->host_name);
if(temp_host == NULL)
continue;
/* make sure user has rights to view this host */
if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE)
continue;
/* get the status of the host */
temp_hoststatus = find_hoststatus(temp_host->name);
if(temp_hoststatus == NULL)
continue;
/* skip this if it isn't a new host... */
if(temp_host == last_host)
continue;
if(odd == 1) {
status_bg_class = "Even";
odd = 0;
}
else {
status_bg_class = "Odd";
odd = 1;
}
printf("
\n");
printf("\n");
return;
}
/* show an overview of hostgroup(s)... */
void show_hostgroup_overviews(void) {
hostgroup *temp_hostgroup = NULL;
int current_column;
int user_has_seen_something = FALSE;
int hostgroup_error = FALSE;
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Service Overview For ");
if(show_all_hostgroups == TRUE)
printf("All Host Groups");
else
printf("Host Group '%s'", hostgroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
/* display status overviews for all hostgroups */
if(show_all_hostgroups == TRUE) {
printf("
\n");
printf("
\n");
current_column = 1;
/* loop through all hostgroups... */
for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next) {
/* make sure the user is authorized to view this hostgroup */
if(is_authorized_for_hostgroup(temp_hostgroup, ¤t_authdata) == FALSE)
continue;
if(current_column == 1)
printf("
Sorry, but host group '%s' doesn't seem to exist...
", hostgroup_name);
hostgroup_error = TRUE;
}
}
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && hostgroup_error == FALSE) {
printf("
\n");
printf("
\n");
if(hostgroup_list != NULL) {
printf("
It appears as though you do not have permission to view information for any of the hosts you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
}
else {
printf("
There are no host groups defined.
\n");
}
printf("
\n");
printf("\n");
}
return;
}
/* shows an overview of a specific hostgroup... */
void show_hostgroup_overview(hostgroup *hstgrp) {
hostsmember *temp_member = NULL;
host *temp_host = NULL;
hoststatus *temp_hoststatus = NULL;
int odd = 0;
/* make sure the user is authorized to view this hostgroup */
if(is_authorized_for_hostgroup(hstgrp, ¤t_authdata) == FALSE)
return;
printf("
\n");
/* find all the hosts that belong to the hostgroup */
for(temp_member = hstgrp->members; temp_member != NULL; temp_member = temp_member->next) {
/* find the host... */
temp_host = find_host(temp_member->host_name);
if(temp_host == NULL)
continue;
/* make sure user has rights to view this host */
if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE)
continue;
/* find the host status */
temp_hoststatus = find_hoststatus(temp_host->name);
if(temp_hoststatus == NULL)
continue;
/* make sure we only display hosts of the specified status levels */
if(!(host_status_types & temp_hoststatus->status))
continue;
/* make sure we only display hosts that have the desired properties */
if(passes_host_properties_filter(temp_hoststatus) == FALSE)
continue;
if(odd)
odd = 0;
else
odd = 1;
show_servicegroup_hostgroup_member_overview(temp_hoststatus, odd, NULL);
}
printf("
\n");
if((total_ok + total_warning + total_unknown + total_critical + total_pending) == 0)
printf("No matching services");
return;
}
/* show a summary of hostgroup(s)... */
void show_hostgroup_summaries(void) {
hostgroup *temp_hostgroup = NULL;
int user_has_seen_something = FALSE;
int hostgroup_error = FALSE;
int odd = 0;
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Status Summary For ");
if(show_all_hostgroups == TRUE)
printf("All Host Groups");
else
printf("Host Group '%s'", hostgroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
Host Group
Host Status Summary
Service Status Summary
\n");
printf("
\n");
/* display status summary for all hostgroups */
if(show_all_hostgroups == TRUE) {
/* loop through all hostgroups... */
for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next) {
/* make sure the user is authorized to view this hostgroup */
if(is_authorized_for_hostgroup(temp_hostgroup, ¤t_authdata) == FALSE)
continue;
if(odd == 0)
odd = 1;
else
odd = 0;
/* show summary for this hostgroup */
show_hostgroup_summary(temp_hostgroup, odd);
user_has_seen_something = TRUE;
}
}
/* else just show summary for a specific hostgroup */
else {
temp_hostgroup = find_hostgroup(hostgroup_name);
if(temp_hostgroup == NULL)
hostgroup_error = TRUE;
else {
show_hostgroup_summary(temp_hostgroup, 1);
user_has_seen_something = TRUE;
}
}
printf("
\n");
printf("
\n");
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && hostgroup_error == FALSE) {
printf("
\n");
if(hoststatus_list != NULL) {
printf("
It appears as though you do not have permission to view information for any of the hosts you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
}
else {
printf("
There doesn't appear to be any host status information in the status log...
\n");
printf("Make sure that Nagios is running and that you have specified the location of you status log correctly in the configuration files.
\n");
}
printf("
\n");
}
/* we couldn't find the hostgroup */
else if(hostgroup_error == TRUE) {
printf("
\n");
printf("
Sorry, but hostgroup '%s' doesn't seem to exist...
\n", hostgroup_name);
printf("
\n");
}
return;
}
/* displays status summary information for a specific hostgroup */
void show_hostgroup_summary(hostgroup *temp_hostgroup, int odd) {
const char *status_bg_class = "";
if(odd == 1)
status_bg_class = "Even";
else
status_bg_class = "Odd";
printf("
\n");
return;
}
/* shows host total summary information for a specific hostgroup */
void show_hostgroup_host_totals_summary(hostgroup *temp_hostgroup) {
hostsmember *temp_member;
int hosts_up = 0;
int hosts_down = 0;
int hosts_unreachable = 0;
int hosts_pending = 0;
int hosts_down_scheduled = 0;
int hosts_down_acknowledged = 0;
int hosts_down_disabled = 0;
int hosts_down_unacknowledged = 0;
int hosts_unreachable_scheduled = 0;
int hosts_unreachable_acknowledged = 0;
int hosts_unreachable_disabled = 0;
int hosts_unreachable_unacknowledged = 0;
hoststatus *temp_hoststatus;
host *temp_host;
int problem = FALSE;
/* find all the hosts that belong to the hostgroup */
for(temp_member = temp_hostgroup->members; temp_member != NULL; temp_member = temp_member->next) {
/* find the host... */
temp_host = find_host(temp_member->host_name);
if(temp_host == NULL)
continue;
/* make sure user has rights to view this host */
if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE)
continue;
/* find the host status */
temp_hoststatus = find_hoststatus(temp_host->name);
if(temp_hoststatus == NULL)
continue;
/* make sure we only display hosts of the specified status levels */
if(!(host_status_types & temp_hoststatus->status))
continue;
/* make sure we only display hosts that have the desired properties */
if(passes_host_properties_filter(temp_hoststatus) == FALSE)
continue;
problem = TRUE;
if(temp_hoststatus->status == SD_HOST_UP)
hosts_up++;
else if(temp_hoststatus->status == SD_HOST_DOWN) {
if(temp_hoststatus->scheduled_downtime_depth > 0) {
hosts_down_scheduled++;
problem = FALSE;
}
if(temp_hoststatus->problem_has_been_acknowledged == TRUE) {
hosts_down_acknowledged++;
problem = FALSE;
}
if(temp_hoststatus->checks_enabled == FALSE) {
hosts_down_disabled++;
problem = FALSE;
}
if(problem == TRUE)
hosts_down_unacknowledged++;
hosts_down++;
}
else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) {
if(temp_hoststatus->scheduled_downtime_depth > 0) {
hosts_unreachable_scheduled++;
problem = FALSE;
}
if(temp_hoststatus->problem_has_been_acknowledged == TRUE) {
hosts_unreachable_acknowledged++;
problem = FALSE;
}
if(temp_hoststatus->checks_enabled == FALSE) {
hosts_unreachable_disabled++;
problem = FALSE;
}
if(problem == TRUE)
hosts_unreachable_unacknowledged++;
hosts_unreachable++;
}
else
hosts_pending++;
}
printf("
\n");
if((services_ok + services_warning + services_unknown + services_critical + services_pending) == 0)
printf("No matching services");
return;
}
/* show a grid layout of hostgroup(s)... */
void show_hostgroup_grids(void) {
hostgroup *temp_hostgroup = NULL;
int user_has_seen_something = FALSE;
int hostgroup_error = FALSE;
int odd = 0;
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
show_filters();
printf("
");
printf("
\n");
printf("
Status Grid For ");
if(show_all_hostgroups == TRUE)
printf("All Host Groups");
else
printf("Host Group '%s'", hostgroup_name);
printf("
\n");
printf(" ");
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
printf("\n");
/* display status grids for all hostgroups */
if(show_all_hostgroups == TRUE) {
/* loop through all hostgroups... */
for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next) {
/* make sure the user is authorized to view this hostgroup */
if(is_authorized_for_hostgroup(temp_hostgroup, ¤t_authdata) == FALSE)
continue;
if(odd == 0)
odd = 1;
else
odd = 0;
/* show grid for this hostgroup */
show_hostgroup_grid(temp_hostgroup);
user_has_seen_something = TRUE;
}
}
/* else just show grid for a specific hostgroup */
else {
temp_hostgroup = find_hostgroup(hostgroup_name);
if(temp_hostgroup == NULL)
hostgroup_error = TRUE;
else {
show_hostgroup_grid(temp_hostgroup);
user_has_seen_something = TRUE;
}
}
/* if user couldn't see anything, print out some helpful info... */
if(user_has_seen_something == FALSE && hostgroup_error == FALSE) {
printf("
\n");
if(hoststatus_list != NULL) {
printf("
It appears as though you do not have permission to view information for any of the hosts you requested...
\n");
printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI ");
printf("and check the authorization options in your CGI configuration file.
\n");
}
else {
printf("
There doesn't appear to be any host status information in the status log...
\n");
printf("Make sure that Nagios is running and that you have specified the location of you status log correctly in the configuration files.
\n");
}
printf("
\n");
}
/* we couldn't find the hostgroup */
else if(hostgroup_error == TRUE) {
printf("
\n");
printf("
Sorry, but hostgroup '%s' doesn't seem to exist...
\n", hostgroup_name);
printf("
\n");
}
return;
}
/* displays status grid for a specific hostgroup */
void show_hostgroup_grid(hostgroup *temp_hostgroup) {
hostsmember *temp_member;
const char *status_bg_class = "";
const char *host_status_class = "";
const char *service_status_class = "";
host *temp_host;
service *temp_service;
hoststatus *temp_hoststatus;
servicestatus *temp_servicestatus;
char *processed_string = NULL;
int odd = 0;
int current_item;
printf("
");
printf(" Services: ");
service_totals = get_servicestatus_count(hst->name, SERVICE_OK);
if(service_totals > 0)
printf("- %d ok ", service_totals);
service_totals = get_servicestatus_count(hst->name, SERVICE_CRITICAL);
if(service_totals > 0)
printf("- %d critical ", service_totals);
service_totals = get_servicestatus_count(hst->name, SERVICE_WARNING);
if(service_totals > 0)
printf("- %d warning ", service_totals);
service_totals = get_servicestatus_count(hst->name, SERVICE_UNKNOWN);
if(service_totals > 0)
printf("- %d unknown ", service_totals);
service_totals = get_servicestatus_count(hst->name, SERVICE_PENDING);
if(service_totals > 0)
printf("- %d pending ", service_totals);
return;
}
/* draws a solid line */
void draw_line(int x1, int y1, int x2, int y2, int color) {
if(create_type == CREATE_HTML)
return;
gdImageLine(map_image, x1, y1, x2, y2, color);
return;
}
/* draws a dotted line */
void draw_dotted_line(int x1, int y1, int x2, int y2, int color) {
int styleDotted[12];
styleDotted[0] = color;
styleDotted[1] = gdTransparent;
styleDotted[2] = gdTransparent;
styleDotted[3] = gdTransparent;
styleDotted[4] = gdTransparent;
styleDotted[5] = gdTransparent;
styleDotted[6] = color;
styleDotted[7] = gdTransparent;
styleDotted[8] = gdTransparent;
styleDotted[9] = gdTransparent;
styleDotted[10] = gdTransparent;
styleDotted[11] = gdTransparent;
/* sets current style to a dashed line */
gdImageSetStyle(map_image, styleDotted, 12);
/* draws a line (dotted) */
gdImageLine(map_image, x1, y1, x2, y2, gdStyled);
return;
}
/* draws a dashed line */
void draw_dashed_line(int x1, int y1, int x2, int y2, int color) {
int styleDashed[12];
styleDashed[0] = color;
styleDashed[1] = color;
styleDashed[2] = color;
styleDashed[3] = color;
styleDashed[4] = gdTransparent;
styleDashed[5] = gdTransparent;
styleDashed[6] = color;
styleDashed[7] = color;
styleDashed[8] = color;
styleDashed[9] = color;
styleDashed[10] = gdTransparent;
styleDashed[11] = gdTransparent;
/* sets current style to a dashed line */
gdImageSetStyle(map_image, styleDashed, 12);
/* draws a line (dashed) */
gdImageLine(map_image, x1, y1, x2, y2, gdStyled);
return;
}
/******************************************************************/
/*********************** GRAPHICS FUNCTIONS ***********************/
/******************************************************************/
/* initialize graphics */
int initialize_graphics(void) {
char image_input_file[MAX_INPUT_BUFFER];
if(create_type == CREATE_HTML)
return ERROR;
/* allocate buffer for storing image */
#ifndef HAVE_GDIMAGECREATETRUECOLOR
map_image = gdImageCreate(canvas_width, canvas_height);
#else
map_image = gdImageCreateTrueColor(canvas_width, canvas_height);
#endif
if(map_image == NULL)
return ERROR;
/* allocate colors used for drawing */
color_white = gdImageColorAllocate(map_image, 255, 255, 255);
color_black = gdImageColorAllocate(map_image, 0, 0, 0);
color_grey = gdImageColorAllocate(map_image, 128, 128, 128);
color_lightgrey = gdImageColorAllocate(map_image, 210, 210, 210);
color_red = gdImageColorAllocate(map_image, 255, 0, 0);
color_lightred = gdImageColorAllocate(map_image, 215, 175, 175);
color_green = gdImageColorAllocate(map_image, 0, 175, 0);
color_lightgreen = gdImageColorAllocate(map_image, 210, 255, 215);
color_blue = gdImageColorAllocate(map_image, 0, 0, 255);
color_yellow = gdImageColorAllocate(map_image, 255, 255, 0);
color_orange = gdImageColorAllocate(map_image, 255, 100, 25);
color_transparency_index = gdImageColorAllocate(map_image, color_transparency_index_r, color_transparency_index_g, color_transparency_index_b);
/* set transparency index */
#ifndef HAVE_GDIMAGECREATETRUECOLOR
gdImageColorTransparent(map_image, color_white);
#else
gdImageColorTransparent(map_image, color_transparency_index);
/* set background */
gdImageFill(map_image, 0, 0, color_transparency_index);
#endif
/* make sure the graphic is interlaced */
gdImageInterlace(map_image, 1);
/* get the path where we will be reading logo images from (GD2 format)... */
snprintf(physical_logo_images_path, sizeof(physical_logo_images_path) - 1, "%slogos/", physical_images_path);
physical_logo_images_path[sizeof(physical_logo_images_path) - 1] = '\x0';
/* load the unknown icon to use for hosts that don't have pretty images associated with them... */
snprintf(image_input_file, sizeof(image_input_file) - 1, "%s%s", physical_logo_images_path, UNKNOWN_GD2_ICON);
image_input_file[sizeof(image_input_file) - 1] = '\x0';
unknown_logo_image = load_image_from_file(image_input_file);
return OK;
}
/* loads a graphic image (GD2, JPG or PNG) from file into memory */
gdImagePtr load_image_from_file(char *filename) {
FILE *fp;
gdImagePtr im = NULL;
char *ext;
/* make sure we were passed a file name */
if(filename == NULL)
return NULL;
/* find the file extension */
if((ext = rindex(filename, '.')) == NULL)
return NULL;
/* open the file for reading (binary mode) */
fp = fopen(filename, "rb");
if(fp == NULL)
return NULL;
/* attempt to read files in various formats */
if(!strcasecmp(ext, ".png"))
im = gdImageCreateFromPng(fp);
else if(!strcasecmp(ext, ".jpg") || !strcasecmp(ext, ".jpeg"))
im = gdImageCreateFromJpeg(fp);
else if(!strcasecmp(ext, ".xbm"))
im = gdImageCreateFromXbm(fp);
else if(!strcasecmp(ext, ".gd2"))
im = gdImageCreateFromGd2(fp);
else if(!strcasecmp(ext, ".gd"))
im = gdImageCreateFromGd(fp);
/* fall back to GD2 image format */
else
im = gdImageCreateFromGd2(fp);
/* close the file */
fclose(fp);
return im;
}
/* draw graphics */
void write_graphics(void) {
FILE *image_output_file = NULL;
if(create_type == CREATE_HTML)
return;
/* use STDOUT for writing the image data... */
image_output_file = stdout;
/* write the image out in PNG format */
gdImagePng(map_image, image_output_file);
/* or we could write the image out in JPG format... */
/*gdImageJpeg(map_image,image_output_file,99);*/
return;
}
/* cleanup graphics resources */
void cleanup_graphics(void) {
if(create_type == CREATE_HTML)
return;
/* free memory allocated to image */
gdImageDestroy(map_image);
return;
}
/******************************************************************/
/************************* MISC FUNCTIONS *************************/
/******************************************************************/
/* write JavaScript code an layer for popup window */
void write_popup_code(void) {
char *border_color = "#000000";
char *background_color = "#ffffcc";
int border = 1;
int padding = 3;
int x_offset = 3;
int y_offset = 3;
printf("\n");
return;
}
/* adds a layer to the list in memory */
int add_layer(char *group_name) {
struct layer *new_layer;
if(group_name == NULL)
return ERROR;
/* allocate memory for a new layer */
new_layer = (struct layer *)malloc(sizeof(struct layer));
if(new_layer == NULL)
return ERROR;
new_layer->layer_name = (char *)malloc(strlen(group_name) + 1);
if(new_layer->layer_name == NULL) {
free(new_layer);
return ERROR;
}
strcpy(new_layer->layer_name, group_name);
/* add new layer to head of layer list */
new_layer->next = layer_list;
layer_list = new_layer;
return OK;
}
/* frees memory allocated to the layer list */
void free_layer_list(void) {
struct layer *this_layer, *next_layer;
return;
for(this_layer = layer_list; layer_list != NULL; this_layer = next_layer) {
next_layer = this_layer->next;
free(this_layer->layer_name);
free(this_layer);
}
return;
}
/* checks to see if a host is in the layer list */
int is_host_in_layer_list(host *hst) {
hostgroup *temp_hostgroup;
struct layer *temp_layer;
if(hst == NULL)
return FALSE;
/* check each layer... */
for(temp_layer = layer_list; temp_layer != NULL; temp_layer = temp_layer->next) {
/* find the hostgroup */
temp_hostgroup = find_hostgroup(temp_layer->layer_name);
if(temp_hostgroup == NULL)
continue;
/* is the requested host a member of the hostgroup/layer? */
if(is_host_member_of_hostgroup(temp_hostgroup, hst) == TRUE)
return TRUE;
}
return FALSE;
}
/* print layer url info */
void print_layer_url(int get_method) {
struct layer *temp_layer;
for(temp_layer = layer_list; temp_layer != NULL; temp_layer = temp_layer->next) {
if(get_method == TRUE)
printf("&layer=%s", escape_string(temp_layer->layer_name));
else
printf("\n", escape_string(temp_layer->layer_name));
}
if(get_method == TRUE)
printf("&layermode=%s", (exclude_layers == TRUE) ? "exclude" : "include");
else
printf("\n", (exclude_layers == TRUE) ? "exclude" : "include");
return;
}
/******************************************************************/
/************************ UTILITY FUNCTIONS ***********************/
/******************************************************************/
/* calculates how many "layers" separate parent and child - used by collapsed tree layout method */
int host_child_depth_separation(host *parent, host *child) {
int this_depth = 0;
int min_depth = 0;
int have_min_depth = FALSE;
host *temp_host;
if(child == NULL)
return -1;
if(parent == child)
return 0;
if(is_host_immediate_child_of_host(parent, child) == TRUE)
return 1;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_host_immediate_child_of_host(parent, temp_host) == TRUE) {
this_depth = host_child_depth_separation(temp_host, child);
if(this_depth >= 0 && (have_min_depth == FALSE || (have_min_depth == TRUE && (this_depth < min_depth)))) {
have_min_depth = TRUE;
min_depth = this_depth;
}
}
}
if(have_min_depth == FALSE)
return -1;
else
return min_depth + 1;
}
/* calculates how many hosts reside on a specific "layer" - used by collapsed tree layout method */
int number_of_host_layer_members(host *parent, int layer) {
int current_layer;
int layer_members = 0;
host *temp_host;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
current_layer = host_child_depth_separation(parent, temp_host);
if(current_layer == layer)
layer_members++;
}
return layer_members;
}
/* calculate max number of members on all "layers" beneath and including parent host - used by collapsed tree layout method */
int max_child_host_layer_members(host *parent) {
int current_layer;
int max_members = 1;
int current_members = 0;
for(current_layer = 1;; current_layer++) {
current_members = number_of_host_layer_members(parent, current_layer);
if(current_members <= 0)
break;
if(current_members > max_members)
max_members = current_members;
}
return max_members;
}
/* calculate max drawing width for host and children - used by balanced tree layout method */
int max_child_host_drawing_width(host *parent) {
host *temp_host;
int child_width = 0;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_host_immediate_child_of_host(parent, temp_host) == TRUE)
child_width += max_child_host_drawing_width(temp_host);
}
/* no children, so set width to 1 for this host */
if(child_width == 0)
return 1;
else
return child_width;
}
/* calculates number of services associated with a particular service */
int number_of_host_services(host *hst) {
service *temp_service;
int total_services = 0;
if(hst == NULL)
return 0;
/* check all the 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;
}
/******************************************************************/
/***************** COORDINATE CALCULATION FUNCTIONS ***************/
/******************************************************************/
/* calculates coords of a host's children - used by balanced tree layout method */
void calculate_balanced_tree_coords(host *parent, int x, int y) {
int parent_drawing_width;
int start_drawing_x;
int current_drawing_x;
int this_drawing_width;
host *temp_host;
/* calculate total drawing width of parent host */
parent_drawing_width = max_child_host_drawing_width(parent);
/* calculate starting x coord */
start_drawing_x = x - (((DEFAULT_NODE_WIDTH * parent_drawing_width) + (DEFAULT_NODE_HSPACING * (parent_drawing_width - 1))) / 2);
current_drawing_x = start_drawing_x;
/* calculate coords for children */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_host_immediate_child_of_host(parent, temp_host) == TRUE) {
/* get drawing width of child host */
this_drawing_width = max_child_host_drawing_width(temp_host);
temp_host->x_2d = current_drawing_x + (((DEFAULT_NODE_WIDTH * this_drawing_width) + (DEFAULT_NODE_HSPACING * (this_drawing_width - 1))) / 2);
temp_host->y_2d = y + DEFAULT_NODE_HEIGHT + DEFAULT_NODE_VSPACING;
temp_host->have_2d_coords = TRUE;
temp_host->should_be_drawn = TRUE;
current_drawing_x += (this_drawing_width * DEFAULT_NODE_WIDTH) + ((this_drawing_width - 1) * DEFAULT_NODE_HSPACING) + DEFAULT_NODE_HSPACING;
/* recurse into child host ... */
calculate_balanced_tree_coords(temp_host, temp_host->x_2d, temp_host->y_2d);
}
}
return;
}
/* calculate coords of all hosts in circular layout method */
void calculate_circular_coords(void) {
int min_x = 0;
int min_y = 0;
int have_min_x = FALSE;
int have_min_y = FALSE;
host *temp_host;
/* calculate all host coords, starting with first layer */
calculate_circular_layer_coords(NULL, 0.0, 360.0, 1, CIRCULAR_DRAWING_RADIUS);
/* adjust all calculated coords so none are negative in x or y axis... */
/* calculate min x, y coords */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(have_min_x == FALSE || temp_host->x_2d < min_x) {
have_min_x = TRUE;
min_x = temp_host->x_2d;
}
if(have_min_y == FALSE || temp_host->y_2d < min_y) {
have_min_y = TRUE;
min_y = temp_host->y_2d;
}
}
/* offset all drawing coords by the min x,y coords we found */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(min_x < 0)
temp_host->x_2d -= min_x;
if(min_y < 0)
temp_host->y_2d -= min_y;
}
if(min_x < 0)
nagios_icon_x -= min_x;
if(min_y < 0)
nagios_icon_y -= min_y;
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
temp_host->x_2d += (DEFAULT_NODE_WIDTH / 2);
temp_host->y_2d += (DEFAULT_NODE_HEIGHT / 2);
}
nagios_icon_x += (DEFAULT_NODE_WIDTH / 2);
nagios_icon_y += (DEFAULT_NODE_HEIGHT / 2);
return;
}
/* calculates coords of all hosts in a particular "layer" in circular layout method */
void calculate_circular_layer_coords(host *parent, double start_angle, double useable_angle, int layer, int radius) {
int parent_drawing_width = 0;
int this_drawing_width = 0;
int immediate_children = 0;
double current_drawing_angle = 0.0;
double this_drawing_angle = 0.0;
double available_angle = 0.0;
double clipped_available_angle = 0.0;
double x_coord = 0.0;
double y_coord = 0.0;
host *temp_host;
/* get the total number of immediate children to this host */
immediate_children = number_of_immediate_child_hosts(parent);
/* bail out if we're done */
if(immediate_children == 0)
return;
/* calculate total drawing "width" of parent host */
parent_drawing_width = max_child_host_drawing_width(parent);
/* calculate initial drawing angle */
current_drawing_angle = start_angle;
/* calculate coords for children */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_host_immediate_child_of_host(parent, temp_host) == TRUE) {
/* get drawing width of child host */
this_drawing_width = max_child_host_drawing_width(temp_host);
/* calculate angle this host gets for drawing */
available_angle = useable_angle * ((double)this_drawing_width / (double)parent_drawing_width);
/* clip available angle if necessary */
/* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */
clipped_available_angle = 360.0 / layer;
if(available_angle < clipped_available_angle)
clipped_available_angle = available_angle;
/* calculate the exact angle at which we should draw this child */
this_drawing_angle = current_drawing_angle + (available_angle / 2.0);
/* compensate for angle overflow */
while(this_drawing_angle >= 360.0)
this_drawing_angle -= 360.0;
while(this_drawing_angle < 0.0)
this_drawing_angle += 360.0;
/* calculate drawing coords of this host using good ol' geometry... */
x_coord = -(sin(-this_drawing_angle * (M_PI / 180.0)) * radius);
y_coord = -(sin((90 + this_drawing_angle) * (M_PI / 180.0)) * radius);
temp_host->x_2d = (int)x_coord;
temp_host->y_2d = (int)y_coord;
temp_host->have_2d_coords = TRUE;
temp_host->should_be_drawn = TRUE;
/* recurse into child host ... */
calculate_circular_layer_coords(temp_host, current_drawing_angle + ((available_angle - clipped_available_angle) / 2), clipped_available_angle, layer + 1, radius + CIRCULAR_DRAWING_RADIUS);
/* increment current drawing angle */
current_drawing_angle += available_angle;
}
}
return;
}
/* draws background "extras" for all hosts in circular markup layout */
void draw_circular_markup(void) {
/* calculate all host sections, starting with first layer */
draw_circular_layer_markup(NULL, 0.0, 360.0, 1, CIRCULAR_DRAWING_RADIUS);
return;
}
/* draws background "extras" for all hosts in a particular "layer" in circular markup layout */
void draw_circular_layer_markup(host *parent, double start_angle, double useable_angle, int layer, int radius) {
int parent_drawing_width = 0;
int this_drawing_width = 0;
int immediate_children = 0;
double current_drawing_angle = 0.0;
double available_angle = 0.0;
double clipped_available_angle = 0.0;
double x_coord[4] = {0.0, 0.0, 0.0, 0.0};
double y_coord[4] = {0.0, 0.0, 0.0, 0.0};
hoststatus *temp_hoststatus;
host *temp_host;
int x_offset = 0;
int y_offset = 0;
int center_x = 0;
int center_y = 0;
int bgcolor = 0;
double arc_start_angle = 0.0;
double arc_end_angle = 0.0;
int translated_x = 0;
int translated_y = 0;
/* get the total number of immediate children to this host */
immediate_children = number_of_immediate_child_hosts(parent);
/* bail out if we're done */
if(immediate_children == 0)
return;
/* calculate total drawing "width" of parent host */
parent_drawing_width = max_child_host_drawing_width(parent);
/* calculate initial drawing angle */
current_drawing_angle = start_angle;
/* calculate coords for children */
for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
if(is_host_immediate_child_of_host(parent, temp_host) == TRUE) {
/* get drawing width of child host */
this_drawing_width = max_child_host_drawing_width(temp_host);
/* calculate angle this host gets for drawing */
available_angle = useable_angle * ((double)this_drawing_width / (double)parent_drawing_width);
/* clip available angle if necessary */
/* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */
clipped_available_angle = 360.0 / layer;
if(available_angle < clipped_available_angle)
clipped_available_angle = available_angle;
/* calculate drawing coords of "leftmost" divider using good ol' geometry... */
x_coord[0] = -(sin(-current_drawing_angle * (M_PI / 180.0)) * (radius - (CIRCULAR_DRAWING_RADIUS / 2)));
y_coord[0] = -(sin((90 + current_drawing_angle) * (M_PI / 180.0)) * (radius - (CIRCULAR_DRAWING_RADIUS / 2)));
x_coord[1] = -(sin(-current_drawing_angle * (M_PI / 180.0)) * (radius + (CIRCULAR_DRAWING_RADIUS / 2)));
y_coord[1] = -(sin((90 + current_drawing_angle) * (M_PI / 180.0)) * (radius + (CIRCULAR_DRAWING_RADIUS / 2)));
/* calculate drawing coords of "rightmost" divider using good ol' geometry... */
x_coord[2] = -(sin((-(current_drawing_angle + available_angle)) * (M_PI / 180.0)) * (radius - (CIRCULAR_DRAWING_RADIUS / 2)));
y_coord[2] = -(sin((90 + current_drawing_angle + available_angle) * (M_PI / 180.0)) * (radius - (CIRCULAR_DRAWING_RADIUS / 2)));
x_coord[3] = -(sin((-(current_drawing_angle + available_angle)) * (M_PI / 180.0)) * (radius + (CIRCULAR_DRAWING_RADIUS / 2)));
y_coord[3] = -(sin((90 + current_drawing_angle + available_angle) * (M_PI / 180.0)) * (radius + (CIRCULAR_DRAWING_RADIUS / 2)));
x_offset = nagios_icon_x + (DEFAULT_NODE_WIDTH / 2) - canvas_x;
y_offset = nagios_icon_y + (DEFAULT_NODE_HEIGHT / 2) - canvas_y;
/* draw "slice" dividers */
if(immediate_children > 1 || layer > 1) {
/* draw "leftmost" divider */
gdImageLine(map_image, (int)x_coord[0] + x_offset, (int)y_coord[0] + y_offset, (int)x_coord[1] + x_offset, (int)y_coord[1] + y_offset, color_lightgrey);
/* draw "rightmost" divider */
gdImageLine(map_image, (int)x_coord[2] + x_offset, (int)y_coord[2] + y_offset, (int)x_coord[3] + x_offset, (int)y_coord[3] + y_offset, color_lightgrey);
}
/* determine arc drawing angles */
arc_start_angle = current_drawing_angle - 90.0;
while(arc_start_angle < 0.0)
arc_start_angle += 360.0;
arc_end_angle = arc_start_angle + available_angle;
/* draw inner arc */
gdImageArc(map_image, x_offset, y_offset, (radius - (CIRCULAR_DRAWING_RADIUS / 2)) * 2, (radius - (CIRCULAR_DRAWING_RADIUS / 2)) * 2, floor(arc_start_angle), ceil(arc_end_angle), color_lightgrey);
/* draw outer arc */
gdImageArc(map_image, x_offset, y_offset, (radius + (CIRCULAR_DRAWING_RADIUS / 2)) * 2, (radius + (CIRCULAR_DRAWING_RADIUS / 2)) * 2, floor(arc_start_angle), ceil(arc_end_angle), color_lightgrey);
/* determine center of "slice" and fill with appropriate color */
center_x = -(sin(-(current_drawing_angle + (available_angle / 2.0)) * (M_PI / 180.0)) * (radius));
center_y = -(sin((90 + current_drawing_angle + (available_angle / 2.0)) * (M_PI / 180.0)) * (radius));
translated_x = center_x + x_offset;
translated_y = center_y + y_offset;
/* determine background color */
temp_hoststatus = find_hoststatus(temp_host->name);
if(temp_hoststatus == NULL)
bgcolor = color_lightgrey;
else if(temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)
bgcolor = color_lightred;
else
bgcolor = color_lightgreen;
/* fill slice with background color */
/* the fill function only works with coordinates that are in bounds of the actual image */
if(translated_x > 0 && translated_y > 0 && translated_x < canvas_width && translated_y < canvas_height)
gdImageFillToBorder(map_image, translated_x, translated_y, color_lightgrey, bgcolor);
/* recurse into child host ... */
draw_circular_layer_markup(temp_host, current_drawing_angle + ((available_angle - clipped_available_angle) / 2), clipped_available_angle, layer + 1, radius + CIRCULAR_DRAWING_RADIUS);
/* increment current drawing angle */
current_drawing_angle += available_angle;
}
}
return;
}
nagios-4.4.6/cgi/statuswml.c 0000664 0000000 0000000 00000141751 13652113235 0015770 0 ustar 00root root 0000000 0000000 /**************************************************************************
*
* STATUSWML.C - Nagios Status CGI for WAP-enabled devices
*
*
* 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/statusdata.h"
#include "../include/cgiutils.h"
#include "../include/getcgi.h"
#include "../include/cgiauth.h"
extern char main_config_file[MAX_FILENAME_LENGTH];
extern char *status_file;
extern hoststatus *hoststatus_list;
extern servicestatus *servicestatus_list;
extern int use_ssl_authentication;
extern int nagios_process_state;
extern char *ping_syntax;
#define DISPLAY_HOST 0
#define DISPLAY_SERVICE 1
#define DISPLAY_HOSTGROUP 2
#define DISPLAY_INDEX 3
#define DISPLAY_PING 4
#define DISPLAY_TRACEROUTE 5
#define DISPLAY_QUICKSTATS 6
#define DISPLAY_PROCESS 7
#define DISPLAY_ALL_PROBLEMS 8
#define DISPLAY_UNHANDLED_PROBLEMS 9
#define DISPLAY_HOSTGROUP_SUMMARY 0
#define DISPLAY_HOSTGROUP_OVERVIEW 1
#define DISPLAY_HOST_SUMMARY 0
#define DISPLAY_HOST_SERVICES 1
void document_header(void);
void document_footer(void);
int process_cgivars(void);
int validate_arguments(void);
int is_valid_hostip(char *hostip);
int display_type = DISPLAY_INDEX;
int hostgroup_style = DISPLAY_HOSTGROUP_SUMMARY;
int host_style = DISPLAY_HOST_SUMMARY;
void display_index(void);
void display_host(void);
void display_host_services(void);
void display_service(void);
void display_hostgroup_summary(void);
void display_hostgroup_overview(void);
void display_ping(void);
void display_traceroute(void);
void display_quick_stats(void);
void display_process(void);
void display_problems(void);
char *host_name = "";
char *hostgroup_name = "";
char *service_desc = "";
char *ping_address = "";
char *traceroute_address = "";
int show_all_hostgroups = TRUE;
authdata current_authdata;
int main(void) {
int result = OK;
/* get the arguments passed in the URL */
process_cgivars();
/* reset internal variables */
reset_cgi_vars();
/* Initialize shared configuration variables */
init_shared_cfg_vars(1);
document_header();
/* validate arguments in URL */
result = validate_arguments();
if(result == ERROR) {
document_footer();
return ERROR;
}
/* read the CGI configuration file */
result = read_cgi_config_file(get_cgi_config_location(), NULL);
if(result == ERROR) {
printf("
Error: Could not open CGI configuration file '%s' for reading!
\n", get_cgi_config_location());
document_footer();
return ERROR;
}
/* read the main configuration file */
result = read_main_config_file(main_config_file);
if(result == ERROR) {
printf("
Error: Could not open main configuration file '%s' for reading!
\n", 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) {
printf("
Error: Could not read some or all object configuration data!
\n");
document_footer();
return ERROR;
}
/* read all status data */
result = read_all_status_data(status_file, READ_ALL_STATUS_DATA);
if(result == ERROR) {
printf("
Error: Could not read host and service status information!
\n");
printf("\n");
printf("\n");
return;
}
/* displays service status */
void display_service(void) {
service *temp_service;
servicestatus *temp_servicestatus;
char last_check[MAX_DATETIME_LENGTH];
int days;
int hours;
int minutes;
int seconds;
time_t current_time;
time_t t;
char state_duration[48];
int found;
/**** MAIN SCREEN (CARD 1) ****/
printf("\n");
printf("
\n");
printf("Service '%s' on host '%s' \n", service_desc, host_name);
/* find the service */
temp_service = find_service(host_name, service_desc);
temp_servicestatus = find_servicestatus(host_name, service_desc);
if(temp_service == NULL || temp_servicestatus == NULL) {
printf("Error: Could not find service!\n");
printf("
\n");
return;
}
nagios-4.4.6/cgi/tac.c 0000664 0000000 0000000 00000163000 13652113235 0014463 0 ustar 00root root 0000000 0000000 /***********************************************************************
*
* TAC.C - Nagios Tactical Monitoring Overview CGI
*
*
* 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/statusdata.h"
#include "../include/getcgi.h"
#include "../include/cgiutils.h"
#include "../include/cgiauth.h"
#define HEALTH_WARNING_PERCENTAGE 90
#define HEALTH_CRITICAL_PERCENTAGE 75
/* HOSTOUTAGE structure */
typedef struct hostoutage_struct {
host *hst;
int affected_child_hosts;
struct hostoutage_struct *next;
} hostoutage;
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 char url_media_path[MAX_FILENAME_LENGTH];
extern char url_js_path[MAX_FILENAME_LENGTH];
extern int refresh_rate;
extern int tac_cgi_hard_only;
extern char *service_critical_sound;
extern char *service_warning_sound;
extern char *service_unknown_sound;
extern char *host_down_sound;
extern char *host_unreachable_sound;
extern char *normal_sound;
extern hoststatus *hoststatus_list;
extern servicestatus *servicestatus_list;
extern int nagios_process_state;
extern int enable_page_tour;
void analyze_status_data(void);
void display_tac_overview(void);
void find_hosts_causing_outages(void);
void calculate_outage_effect_of_host(host *, int *);
int is_route_to_host_blocked(host *);
int number_of_host_services(host *);
void add_hostoutage(host *);
void free_hostoutage_list(void);
void document_header(int);
void document_footer(void);
int process_cgivars(void);
authdata current_authdata;
int embedded = FALSE;
int display_header = TRUE;
hostoutage *hostoutage_list = NULL;
int total_blocking_outages = 0;
int total_nonblocking_outages = 0;
int total_service_health = 0;
int total_host_health = 0;
int potential_service_health = 0;
int potential_host_health = 0;
double percent_service_health = 0.0;
double percent_host_health = 0.0;
int total_hosts = 0;
int total_services = 0;
int total_active_service_checks = 0;
int total_active_host_checks = 0;
int total_passive_service_checks = 0;
int total_passive_host_checks = 0;
double min_service_execution_time = -1.0;
double max_service_execution_time = -1.0;
double total_service_execution_time = 0.0;
double average_service_execution_time = -1.0;
double min_host_execution_time = -1.0;
double max_host_execution_time = -1.0;
double total_host_execution_time = 0.0;
double average_host_execution_time = -1.0;
double min_service_latency = -1.0;
double max_service_latency = -1.0;
double total_service_latency = 0.0;
double average_service_latency = -1.0;
double min_host_latency = -1.0;
double max_host_latency = -1.0;
double total_host_latency = 0.0;
double average_host_latency = -1.0;
int flapping_services = 0;
int flapping_hosts = 0;
int flap_disabled_services = 0;
int flap_disabled_hosts = 0;
int notification_disabled_services = 0;
int notification_disabled_hosts = 0;
int event_handler_disabled_services = 0;
int event_handler_disabled_hosts = 0;
int active_checks_disabled_services = 0;
int active_checks_disabled_hosts = 0;
int passive_checks_disabled_services = 0;
int passive_checks_disabled_hosts = 0;
int hosts_pending = 0;
int hosts_pending_disabled = 0;
int hosts_up_disabled = 0;
int hosts_up_unacknowledged = 0;
int hosts_up = 0;
int hosts_down_scheduled = 0;
int hosts_down_acknowledged = 0;
int hosts_down_disabled = 0;
int hosts_down_unacknowledged = 0;
int hosts_down = 0;
int hosts_unreachable_scheduled = 0;
int hosts_unreachable_acknowledged = 0;
int hosts_unreachable_disabled = 0;
int hosts_unreachable_unacknowledged = 0;
int hosts_unreachable = 0;
int services_pending = 0;
int services_pending_disabled = 0;
int services_ok_disabled = 0;
int services_ok_unacknowledged = 0;
int services_ok = 0;
int services_warning_host_problem = 0;
int services_warning_scheduled = 0;
int services_warning_acknowledged = 0;
int services_warning_disabled = 0;
int services_warning_unacknowledged = 0;
int services_warning = 0;
int services_unknown_host_problem = 0;
int services_unknown_scheduled = 0;
int services_unknown_acknowledged = 0;
int services_unknown_disabled = 0;
int services_unknown_unacknowledged = 0;
int services_unknown = 0;
int services_critical_host_problem = 0;
int services_critical_scheduled = 0;
int services_critical_acknowledged = 0;
int services_critical_disabled = 0;
int services_critical_unacknowledged = 0;
int services_critical = 0;
/*efine DEBUG 1*/
int main(void) {
char *sound = NULL;
/* get the CGI variables passed in the URL */
process_cgivars();
/* reset internal variables */
reset_cgi_vars();
cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, READ_ALL_STATUS_DATA);
/* get authentication information */
get_authentication_information(¤t_authdata);
document_header(TRUE);
if(display_header == TRUE) {
/* begin top table */
printf("
\n");
printf("
\n");
/* left column of top table - info box */
printf("
\n");
display_info_table("Tactical Status Overview", TRUE, ¤t_authdata);
printf("
\n");
/* middle column of top table - log file navigation options */
printf("
\n");
printf("
\n");
/* right hand column of top row */
printf("
\n");
printf("
\n");
/* end of top table */
printf("
\n");
printf("
\n");
printf("\n");
}
/* analyze current host and service status data for tac overview */
analyze_status_data();
/* find all hosts that are causing network outages */
find_hosts_causing_outages();
/* embed sound tag if necessary... */
if(hosts_unreachable_unacknowledged > 0 && host_unreachable_sound != NULL)
sound = host_unreachable_sound;
else if(hosts_down_unacknowledged > 0 && host_down_sound != NULL)
sound = host_down_sound;
else if(services_critical_unacknowledged > 0 && service_critical_sound != NULL)
sound = service_critical_sound;
else if(services_warning_unacknowledged > 0 && service_warning_sound != NULL)
sound = service_warning_sound;
else if(services_unknown_unacknowledged == 0 && services_warning_unacknowledged == 0 && services_critical_unacknowledged == 0 && hosts_down_unacknowledged == 0 && hosts_unreachable_unacknowledged == 0 && normal_sound != NULL)
sound = normal_sound;
if(sound != NULL) {
printf("");
}
/**** display main tac screen ****/
display_tac_overview();
document_footer();
/* free memory allocated to the host outage list */
free_hostoutage_list();
/* 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");
printf("Refresh: %d\r\n", refresh_rate);
time(¤t_time);
get_time_string(¤t_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; charset=utf-8\r\n\r\n");
if(embedded == TRUE)
return;
printf("\n");
printf("\n");
printf("\n", url_images_path);
printf("\n");
printf("Nagios Tactical Monitoring Overview\n");
printf("\n");
if(use_stylesheet == TRUE) {
printf("\n", url_stylesheets_path, COMMON_CSS);
printf("\n", url_stylesheets_path, TAC_CSS);
printf("\n", url_stylesheets_path, NAGFUNCS_CSS);
}
printf("\n", url_js_path, JQUERY_JS);
if (enable_page_tour == TRUE) {
printf("\n", url_js_path, NAGFUNCS_JS);
printf("\n");
}
printf("\n");
printf("\n");
/* include user SSI header */
include_ssi_files(TAC_CGI, SSI_HEADER);
return;
}
void document_footer(void) {
if(embedded == TRUE)
return;
/* include user SSI footer */
include_ssi_files(TAC_CGI, SSI_FOOTER);
printf("\n");
printf("\n");
return;
}
int process_cgivars(void) {
char **variables;
int error = FALSE;
int x;
variables = getcgivars();
for(x = 0; variables[x]; 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 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 received an invalid argument */
else
error = TRUE;
}
/* free memory allocated to the CGI variables */
free_cgivars(variables);
return error;
}
void analyze_status_data(void) {
servicestatus *temp_servicestatus;
service *temp_service;
hoststatus *temp_hoststatus;
host *temp_host;
int problem = TRUE;
/* check all services */
for(temp_servicestatus = servicestatus_list; temp_servicestatus != NULL; temp_servicestatus = temp_servicestatus->next) {
/* see if user is authorized to view this service */
temp_service = find_service(temp_servicestatus->host_name, temp_servicestatus->description);
if(is_authorized_for_service(temp_service, ¤t_authdata) == FALSE)
continue;
/******** CHECK FEATURES *******/
/* check flapping */
if(temp_servicestatus->flap_detection_enabled == FALSE)
flap_disabled_services++;
else if(temp_servicestatus->is_flapping == TRUE)
flapping_services++;
/* check notifications */
if(temp_servicestatus->notifications_enabled == FALSE)
notification_disabled_services++;
/* check event handler */
if(temp_servicestatus->event_handler_enabled == FALSE)
event_handler_disabled_services++;
/* active check execution */
if(temp_servicestatus->checks_enabled == FALSE)
active_checks_disabled_services++;
/* passive check acceptance */
if(temp_servicestatus->accept_passive_checks == FALSE)
passive_checks_disabled_services++;
/********* CHECK STATUS ********/
problem = TRUE;
if(temp_servicestatus->status == SERVICE_OK) {
if(temp_servicestatus->checks_enabled == FALSE)
services_ok_disabled++;
else
services_ok_unacknowledged++;
services_ok++;
}
else if(temp_servicestatus->status == SERVICE_WARNING) {
temp_hoststatus = find_hoststatus(temp_servicestatus->host_name);
if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) {
services_warning_host_problem++;
problem = FALSE;
}
if(temp_servicestatus->scheduled_downtime_depth > 0) {
services_warning_scheduled++;
problem = FALSE;
}
if(temp_servicestatus->problem_has_been_acknowledged == TRUE) {
services_warning_acknowledged++;
problem = FALSE;
}
if(temp_servicestatus->checks_enabled == FALSE) {
services_warning_disabled++;
problem = FALSE;
}
if(problem == TRUE) {
if (temp_servicestatus->state_type == HARD_STATE || tac_cgi_hard_only == FALSE)
services_warning_unacknowledged++;
}
services_warning++;
}
else if(temp_servicestatus->status == SERVICE_UNKNOWN) {
temp_hoststatus = find_hoststatus(temp_servicestatus->host_name);
if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) {
services_unknown_host_problem++;
problem = FALSE;
}
if(temp_servicestatus->scheduled_downtime_depth > 0) {
services_unknown_scheduled++;
problem = FALSE;
}
if(temp_servicestatus->problem_has_been_acknowledged == TRUE) {
services_unknown_acknowledged++;
problem = FALSE;
}
if(temp_servicestatus->checks_enabled == FALSE) {
services_unknown_disabled++;
problem = FALSE;
}
if(problem == TRUE) {
if (temp_servicestatus->state_type == HARD_STATE || tac_cgi_hard_only == FALSE)
services_unknown_unacknowledged++;
}
services_unknown++;
}
else if(temp_servicestatus->status == SERVICE_CRITICAL) {
temp_hoststatus = find_hoststatus(temp_servicestatus->host_name);
if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) {
services_critical_host_problem++;
problem = FALSE;
}
if(temp_servicestatus->scheduled_downtime_depth > 0) {
services_critical_scheduled++;
problem = FALSE;
}
if(temp_servicestatus->problem_has_been_acknowledged == TRUE) {
services_critical_acknowledged++;
problem = FALSE;
}
if(temp_servicestatus->checks_enabled == FALSE) {
services_critical_disabled++;
problem = FALSE;
}
if(problem == TRUE) {
if (temp_servicestatus->state_type == HARD_STATE || tac_cgi_hard_only == FALSE)
services_critical_unacknowledged++;
}
services_critical++;
}
else if(temp_servicestatus->status == SERVICE_PENDING) {
if(temp_servicestatus->checks_enabled == FALSE)
services_pending_disabled++;
services_pending++;
}
/* get health stats */
if(temp_servicestatus->status == SERVICE_OK)
total_service_health += 2;
else if(temp_servicestatus->status == SERVICE_WARNING || temp_servicestatus->status == SERVICE_UNKNOWN)
total_service_health++;
if(temp_servicestatus->status != SERVICE_PENDING)
potential_service_health += 2;
/* calculate execution time and latency stats */
if(temp_servicestatus->check_type == CHECK_TYPE_ACTIVE) {
total_active_service_checks++;
if(min_service_latency == -1.0 || temp_servicestatus->latency < min_service_latency)
min_service_latency = temp_servicestatus->latency;
if(max_service_latency == -1.0 || temp_servicestatus->latency > max_service_latency)
max_service_latency = temp_servicestatus->latency;
if(min_service_execution_time == -1.0 || temp_servicestatus->execution_time < min_service_execution_time)
min_service_execution_time = temp_servicestatus->execution_time;
if(max_service_execution_time == -1.0 || temp_servicestatus->execution_time > max_service_execution_time)
max_service_execution_time = temp_servicestatus->execution_time;
total_service_latency += temp_servicestatus->latency;
total_service_execution_time += temp_servicestatus->execution_time;
}
else
total_passive_service_checks++;
total_services++;
}
/* check all hosts */
for(temp_hoststatus = hoststatus_list; temp_hoststatus != NULL; temp_hoststatus = temp_hoststatus->next) {
/* see if user is authorized to view this host */
temp_host = find_host(temp_hoststatus->host_name);
if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE)
continue;
/******** CHECK FEATURES *******/
/* check flapping */
if(temp_hoststatus->flap_detection_enabled == FALSE)
flap_disabled_hosts++;
else if(temp_hoststatus->is_flapping == TRUE)
flapping_hosts++;
/* check notifications */
if(temp_hoststatus->notifications_enabled == FALSE)
notification_disabled_hosts++;
/* check event handler */
if(temp_hoststatus->event_handler_enabled == FALSE)
event_handler_disabled_hosts++;
/* active check execution */
if(temp_hoststatus->checks_enabled == FALSE)
active_checks_disabled_hosts++;
/* passive check acceptance */
if(temp_hoststatus->accept_passive_checks == FALSE)
passive_checks_disabled_hosts++;
/********* CHECK STATUS ********/
problem = TRUE;
if(temp_hoststatus->status == SD_HOST_UP) {
if(temp_hoststatus->checks_enabled == FALSE)
hosts_up_disabled++;
else
hosts_up_unacknowledged++;
hosts_up++;
}
else if(temp_hoststatus->status == SD_HOST_DOWN) {
if(temp_hoststatus->scheduled_downtime_depth > 0) {
hosts_down_scheduled++;
problem = FALSE;
}
if(temp_hoststatus->problem_has_been_acknowledged == TRUE) {
hosts_down_acknowledged++;
problem = FALSE;
}
if(temp_hoststatus->checks_enabled == FALSE) {
hosts_down_disabled++;
problem = FALSE;
}
if(problem == TRUE) {
if (temp_hoststatus->state_type == HARD_STATE || tac_cgi_hard_only == FALSE)
hosts_down_unacknowledged++;
}
hosts_down++;
}
else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) {
if(temp_hoststatus->scheduled_downtime_depth > 0) {
hosts_unreachable_scheduled++;
problem = FALSE;
}
if(temp_hoststatus->problem_has_been_acknowledged == TRUE) {
hosts_unreachable_acknowledged++;
problem = FALSE;
}
if(temp_hoststatus->checks_enabled == FALSE) {
hosts_unreachable_disabled++;
problem = FALSE;
}
if(problem == TRUE) {
if (temp_hoststatus->state_type == HARD_STATE || tac_cgi_hard_only == FALSE)
hosts_unreachable_unacknowledged++;
}
hosts_unreachable++;
}
else if(temp_hoststatus->status == HOST_PENDING) {
if(temp_hoststatus->checks_enabled == FALSE)
hosts_pending_disabled++;
hosts_pending++;
}
/* get health stats */
if(temp_hoststatus->status == SD_HOST_UP)
total_host_health++;
if(temp_hoststatus->status != HOST_PENDING)
potential_host_health++;
/* check type stats */
if(temp_hoststatus->check_type == CHECK_TYPE_ACTIVE) {
total_active_host_checks++;
if(min_host_latency == -1.0 || temp_hoststatus->latency < min_host_latency)
min_host_latency = temp_hoststatus->latency;
if(max_host_latency == -1.0 || temp_hoststatus->latency > max_host_latency)
max_host_latency = temp_hoststatus->latency;
if(min_host_execution_time == -1.0 || temp_hoststatus->execution_time < min_host_execution_time)
min_host_execution_time = temp_hoststatus->execution_time;
if(max_host_execution_time == -1.0 || temp_hoststatus->execution_time > max_host_execution_time)
max_host_execution_time = temp_hoststatus->execution_time;
total_host_latency += temp_hoststatus->latency;
total_host_execution_time += temp_hoststatus->execution_time;
}
else
total_passive_host_checks++;
total_hosts++;
}
/* calculate service health */
if(potential_service_health == 0)
percent_service_health = 0.0;
else
percent_service_health = ((double)total_service_health / (double)potential_service_health) * 100.0;
/* calculate host health */
if(potential_host_health == 0)
percent_host_health = 0.0;
else
percent_host_health = ((double)total_host_health / (double)potential_host_health) * 100.0;
/* calculate service latency */
if(total_service_latency == 0L)
average_service_latency = 0.0;
else
average_service_latency = ((double)total_service_latency / (double)total_active_service_checks);
/* calculate host latency */
if(total_host_latency == 0L)
average_host_latency = 0.0;
else
average_host_latency = ((double)total_host_latency / (double)total_active_host_checks);
/* calculate service execution time */
if(total_service_execution_time == 0.0)
average_service_execution_time = 0.0;
else
average_service_execution_time = ((double)total_service_execution_time / (double)total_active_service_checks);
/* calculate host execution time */
if(total_host_execution_time == 0.0)
average_host_execution_time = 0.0;
else
average_host_execution_time = ((double)total_host_execution_time / (double)total_active_host_checks);
return;
}
/* determine what hosts are causing network outages */
void find_hosts_causing_outages(void) {
hoststatus *temp_hoststatus;
hostoutage *temp_hostoutage;
host *temp_host;
/* user must be authorized for all hosts in order to see outages */
if(is_authorized_for_all_hosts(¤t_authdata) == FALSE)
return;
/* 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 != SD_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);
}
}
/* check all hosts that are causing problems and calculate the extent of the problem */
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);
if(temp_hostoutage->affected_child_hosts > 1)
total_blocking_outages++;
else
total_nonblocking_outages++;
}
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->affected_child_hosts = 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;
for(this_hostoutage = hostoutage_list; this_hostoutage != NULL; this_hostoutage = next_hostoutage) {
next_hostoutage = this_hostoutage->next;
free(this_hostoutage);
}
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 total_child_hosts_affected = 0;
int temp_child_hosts_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);
/* keep a running total of outage effects */
total_child_hosts_affected += temp_child_hosts_affected;
}
*affected_hosts = total_child_hosts_affected + 1;
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 == SD_HOST_UP || temp_hoststatus->status == HOST_PENDING)
return FALSE;
}
return TRUE;
}
void display_tac_overview(void) {
char host_health_image[16];
char service_health_image[16];
printf("
\n");
printf("
\n");
printf("
\n");
/* left column */
printf("
\n");
printf("
\n");
/* right column */
printf("
\n");
printf("
\n");
printf("
\n");
printf("
\n");
/* display context-sensitive help */
display_context_help(CONTEXTHELP_TAC);
printf("
\n");
printf("Note: Choosing the 'suppress image map' option will make the report run approximately twice as fast as it would otherwise, but it will prevent you from being able to zoom in on specific time periods.\n");
printf("
\n");
*/
}
/* as the user whether they want a graph for a host or service */
else {
printf("