summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorEthan Galstad <egalstad@users.sourceforge.net>2002-02-28 06:42:51 +0000
committerEthan Galstad <egalstad@users.sourceforge.net>2002-02-28 06:42:51 +0000
commit44a321cb8a42d6c0ea2d96a1086a17f2134c89cc (patch)
treea1a4d9f7b92412a17ab08f34f04eec45433048b7 /plugins
parent54fd5d7022ff2d6a59bc52b8869182f3fc77a058 (diff)
downloadmonitoring-plugins-44a321cb8a42d6c0ea2d96a1086a17f2134c89cc.tar.gz
Initial revision
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@2 f882894a-f735-0410-b71e-b25c423dba1c
Diffstat (limited to 'plugins')
-rw-r--r--plugins/.cvsignore43
-rw-r--r--plugins/Makefile.am139
-rw-r--r--plugins/check_by_ssh.c412
-rw-r--r--plugins/check_dig.c296
-rw-r--r--plugins/check_disk.c353
-rw-r--r--plugins/check_dns.c415
-rw-r--r--plugins/check_dummy.c100
-rw-r--r--plugins/check_fping.c386
-rw-r--r--plugins/check_ftp.c337
-rw-r--r--plugins/check_game.c287
-rw-r--r--plugins/check_hpjd.c571
-rw-r--r--plugins/check_http.c1067
-rw-r--r--plugins/check_ide-smart.c448
-rw-r--r--plugins/check_imap.c340
-rw-r--r--plugins/check_ldap.c291
-rw-r--r--plugins/check_load.c321
-rw-r--r--plugins/check_mrtg.c413
-rw-r--r--plugins/check_mrtgtraf.c419
-rw-r--r--plugins/check_mysql.c297
-rw-r--r--plugins/check_nagios.c267
-rw-r--r--plugins/check_nntp.c418
-rw-r--r--plugins/check_nt.c548
-rw-r--r--plugins/check_nwstat.c821
-rw-r--r--plugins/check_overcr.c489
-rw-r--r--plugins/check_pgsql.c440
-rw-r--r--plugins/check_ping.c492
-rw-r--r--plugins/check_pop.c364
-rw-r--r--plugins/check_procs.c510
-rw-r--r--plugins/check_radius.c345
-rw-r--r--plugins/check_real.c661
-rw-r--r--plugins/check_smtp.c362
-rw-r--r--plugins/check_snmp.c805
-rw-r--r--plugins/check_ssh.c285
-rw-r--r--plugins/check_swap.c325
-rw-r--r--plugins/check_tcp.c563
-rw-r--r--plugins/check_time.c370
-rw-r--r--plugins/check_udp.c315
-rw-r--r--plugins/check_ups.c649
-rw-r--r--plugins/check_users.c257
-rw-r--r--plugins/check_vsz.c287
-rw-r--r--plugins/common.h.in159
-rw-r--r--plugins/getopt.c724
-rw-r--r--plugins/getopt1.c176
-rw-r--r--plugins/netutils.c431
-rw-r--r--plugins/netutils.h.in63
-rw-r--r--plugins/popen.c314
-rw-r--r--plugins/popen.h.in9
-rw-r--r--plugins/snprintf.c377
-rw-r--r--plugins/t/check_disk.t31
-rw-r--r--plugins/t/check_dns.t29
-rw-r--r--plugins/t/check_fping.t37
-rw-r--r--plugins/t/check_ftp.t32
-rw-r--r--plugins/t/check_hpjd.t32
-rw-r--r--plugins/t/check_http.t22
-rw-r--r--plugins/t/check_imap.t34
-rw-r--r--plugins/t/check_load.t27
-rw-r--r--plugins/t/check_mysql.t23
-rw-r--r--plugins/t/check_ping.t33
-rw-r--r--plugins/t/check_pop.t31
-rw-r--r--plugins/t/check_procs.t51
-rw-r--r--plugins/t/check_smtp.t31
-rw-r--r--plugins/t/check_snmp.t52
-rw-r--r--plugins/t/check_swap.t34
-rw-r--r--plugins/t/check_tcp.t27
-rw-r--r--plugins/t/check_time.t52
-rw-r--r--plugins/t/check_udp.t24
-rw-r--r--plugins/t/check_users.t28
-rw-r--r--plugins/t/check_vsz.t28
-rw-r--r--plugins/tests/check_disk9
-rw-r--r--plugins/tests/check_dns9
-rw-r--r--plugins/tests/check_ftp9
-rw-r--r--plugins/tests/check_hpjd9
-rw-r--r--plugins/tests/check_http9
-rw-r--r--plugins/tests/check_load9
-rw-r--r--plugins/tests/check_ping13
-rw-r--r--plugins/tests/check_procs23
-rw-r--r--plugins/tests/check_swap13
-rw-r--r--plugins/tests/check_users9
-rw-r--r--plugins/tests/check_vsz9
-rw-r--r--plugins/urlize.c141
-rw-r--r--plugins/utils.c610
-rw-r--r--plugins/utils.h.in92
-rw-r--r--plugins/version.h.in2
83 files changed, 20385 insertions, 0 deletions
diff --git a/plugins/.cvsignore b/plugins/.cvsignore
new file mode 100644
index 00000000..58f14fe8
--- /dev/null
+++ b/plugins/.cvsignore
@@ -0,0 +1,43 @@
1check_disk
2check_dns
3check_dummy
4check_ftp
5check_http
6check_imap
7check_load
8check_mrtg
9check_mrtgtraf
10check_nagios
11check_nntp
12check_nwstat
13check_overcr
14check_ping
15check_pop
16check_procs
17check_real
18check_reply
19check_smtp
20check_ssh
21check_tcp
22check_time
23check_udp
24check_ups
25check_users
26check_vsz
27check_by_ssh
28urlize
29check_pgsql
30check_radius
31check_ldap
32check_mysql
33check_netsaint
34check_hpjd
35check_snmp
36check_by_ssh
37check_swap
38stamp-h*
39*.h
40Makefile
41Makefile.in
42config.h.in
43.deps
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
new file mode 100644
index 00000000..64b14bfb
--- /dev/null
+++ b/plugins/Makefile.am
@@ -0,0 +1,139 @@
1## Process this file with automake to produce Makefile.in
2
3VPATH = $(top_srcdir) $(top_srcdir)/plugins $(top_srcdir)/plugins/t
4
5INCLUDES = @LDAPINCLUDE@ @PGINCLUDE@ @SSLINCLUDE@
6
7libexec_PROGRAMS = check_disk check_dummy check_ftp check_http \
8 check_imap check_load check_mrtg check_mrtgtraf \
9 check_nntp check_nwstat check_overcr \
10 check_ping check_pop check_procs check_real \
11 check_smtp check_ssh check_tcp check_time check_udp \
12 check_ups check_users check_vsz urlize \
13 @EXTRAS@
14
15EXTRA_PROGRAMS = check_mysql check_radius check_pgsql check_snmp check_hpjd \
16 check_swap check_fping check_ldap check_game check_dig \
17 check_nagios check_by_ssh check_dns check_nt
18
19EXTRA_DIST = t utils.c netutils.c popen.c getopt.h getopt.c getopt1.c snprintf.c
20
21PLUGINHDRS = common.h config.h
22
23BASEOBJS = utils.o
24NETOBJS = netutils.o $(BASEOBJS)
25NETLIBS = $(NETOBJS) $(SOCKETLIBS)
26
27TESTS_ENVIRONMENT = perl -I $(top_builddir) -I $(top_srcdir)
28
29TESTS = @PLUGIN_TEST@
30
31test:
32 perl -I $(top_builddir) -I $(top_srcdir) ../test.pl
33
34AM_INSTALL_PROGRAM_FLAGS = @INSTALL_OPTS@
35
36##############################################################################
37# the actual targets
38
39check_dig_LDADD = $(BASEOBJS) popen.o
40check_disk_LDADD = $(BASEOBJS) popen.o
41check_dns_LDADD = $(BASEOBJS) popen.o
42check_dummy_LDADD = $(BASEOBJS)
43check_fping_LDADD = $(BASEOBJS) popen.o
44check_ftp_LDADD = $(NETLIBS)
45check_game_LDADD = $(BASEOBJS)
46check_http_LDADD = $(NETLIBS) $(SSLLIBS)
47check_hpjd_LDADD = $(BASEOBJS) popen.o
48check_imap_LDADD = $(NETLIBS)
49check_ldap_LDADD = $(NETLIBS) $(LDAPLIBS)
50check_load_LDADD = $(BASEOBJS) popen.o
51check_mrtg_LDADD = $(BASEOBJS)
52check_mrtgtraf_LDADD = $(BASEOBJS)
53check_mysql_LDADD = $(BASEOBJS) $(MYSQLLIBS)
54check_nagios_LDADD = $(BASEOBJS) popen.o
55check_nntp_LDADD = $(NETLIBS)
56check_nt_LDADD = $(NETLIBS)
57check_nwstat_LDADD = $(NETLIBS)
58check_overcr_LDADD = $(NETLIBS)
59check_pgsql_LDADD = $(BASEOBJS) $(PGLIBS)
60check_ping_LDADD = $(BASEOBJS) popen.o
61check_pop_LDADD = $(NETLIBS)
62check_procs_LDADD = $(BASEOBJS) popen.o
63check_radius_LDADD = $(BASEOBJS) $(RADIUSLIBS)
64check_real_LDADD = $(NETLIBS)
65check_snmp_LDADD = $(BASEOBJS) popen.o
66check_smtp_LDADD = $(NETLIBS)
67check_ssh_LDADD = $(NETLIBS)
68check_swap_LDADD = $(BASEOBJS) popen.o
69check_tcp_LDADD = $(NETLIBS) $(SSLLIBS)
70check_time_LDADD = $(NETLIBS)
71check_udp_LDADD = $(NETLIBS)
72check_ups_LDADD = $(NETLIBS)
73check_users_LDADD = $(BASEOBJS) popen.o
74check_vsz_LDADD = $(BASEOBJS) popen.o
75check_by_ssh_LDADD = $(BASEOBJS) popen.o
76urlize_LDADD = $(BASEOBJS) popen.o
77
78check_dig_DEPENDENCIES = check_dig.c $(BASEOBJS) popen.o $(DEPLIBS)
79check_disk_DEPENDENCIES = check_disk.c $(BASEOBJS) popen.o $(DEPLIBS)
80check_dns_DEPENDENCIES = check_dns.c $(BASEOBJS) popen.o $(DEPLIBS)
81check_dummy_DEPENDENCIES = check_dummy.c $(DEPLIBS)
82check_fping_DEPENDENCIES = check_fping.c $(BASEOBJS) popen.o $(DEPLIBS)
83check_ftp_DEPENDENCIES = check_ftp.c $(NETOBJS) $(DEPLIBS)
84check_game_DEPENDENCIES = check_game.c $(DEPLIBS)
85check_http_DEPENDENCIES = check_http.c $(NETOBJS) $(DEPLIBS)
86check_hpjd_DEPENDENCIES = check_hpjd.c $(BASEOBJS) popen.o $(DEPLIBS)
87check_imap_DEPENDENCIES = check_imap.c $(NETOBJS) $(DEPLIBS)
88check_ldap_DEPENDENCIES = check_ldap.c $(NETOBJS) $(DEPLIBS)
89check_load_DEPENDENCIES = check_load.c $(BASEOBJS) popen.o $(DEPLIBS)
90check_mrtg_DEPENDENCIES = check_mrtg.c $(DEPLIBS)
91check_mrtgtraf_DEPENDENCIES = check_mrtgtraf.c $(DEPLIBS)
92check_mysql_DEPENDENCIES = check_mysql.c $(DEPLIBS)
93check_nagios_DEPENDENCIES = check_nagios.c $(BASEOBJS) popen.o $(DEPLIBS)
94check_nntp_DEPENDENCIES = check_nntp.c $(NETOBJS) $(DEPLIBS)
95check_nt_DEPENDENCIES = check_nt.c $(NETOBJS) $(DEPLIBS)
96check_nwstat_DEPENDENCIES = check_nwstat.c $(NETOBJS) $(DEPLIBS)
97check_overcr_DEPENDENCIES = check_overcr.c $(NETOBJS) $(DEPLIBS)
98check_pgsql_DEPENDENCIES = check_pgsql.c $(DEPLIBS)
99check_ping_DEPENDENCIES = check_ping.c $(BASEOBJS) popen.o $(DEPLIBS)
100check_pop_DEPENDENCIES = check_pop.c $(NETOBJS) $(DEPLIBS)
101check_procs_DEPENDENCIES = check_procs.c $(BASEOBJS) popen.o $(DEPLIBS)
102check_radius_DEPENDENCIES = check_radius.c $(DEPLIBS)
103check_real_DEPENDENCIES = check_real.c $(NETOBJS) $(DEPLIBS)
104check_snmp_DEPENDENCIES = check_snmp.c $(BASEOBJS) popen.o $(DEPLIBS)
105check_smtp_DEPENDENCIES = check_smtp.c $(NETOBJS) $(DEPLIBS)
106check_ssh_DEPENDENCIES = check_ssh.c $(NETOBJS) $(DEPLIBS)
107check_swap_DEPENDENCIES = check_swap.c $(BASEOBJS) popen.o $(DEPLIBS)
108check_tcp_DEPENDENCIES = check_tcp.c $(NETOBJS) $(DEPLIBS)
109check_time_DEPENDENCIES = check_time.c $(NETOBJS) $(DEPLIBS)
110check_udp_DEPENDENCIES = check_udp.c $(NETOBJS) $(DEPLIBS)
111check_ups_DEPENDENCIES = check_ups.c $(NETOBJS) $(DEPLIBS)
112check_users_DEPENDENCIES = check_users.c $(BASEOBJS) popen.o $(DEPLIBS)
113check_vsz_DEPENDENCIES = check_vsz.c $(BASEOBJS) popen.o $(DEPLIBS)
114check_by_ssh_DEPENDENCIES = check_by_ssh.c $(BASEOBJS) popen.o $(DEPLIBS)
115urlize_DEPENDENCIES = urlize.c $(BASEOBJS) popen.o $(DEPLIBS)
116
117##############################################################################
118# secondary dependencies
119
120popen.o: popen.c popen.h $(PLUGINHDRS)
121
122utils.o: utils.c utils.h $(PLUGINHDRS)
123
124netutils.o: netutils.c netutils.h $(PLUGINHDRS)
125
126getopt.o: getopt.c getopt.h
127 $(COMPILE) -c $(srcdir)/getopt.c -o $@
128
129getopt1.o: getopt1.c getopt.h
130 $(COMPILE) -c $(srcdir)/getopt1.c -o $@
131
132snprintf.o: snprintf.c
133 $(COMPILE) @NEED_VA_LIST@ -c $? -o $@
134
135libgetopt.a: getopt.o getopt1.o
136 $(AR) -r $@ getopt.o getopt1.o
137
138libsnprintf.a: snprintf.o
139 $(AR) -r $@ snprintf.o
diff --git a/plugins/check_by_ssh.c b/plugins/check_by_ssh.c
new file mode 100644
index 00000000..a81b333f
--- /dev/null
+++ b/plugins/check_by_ssh.c
@@ -0,0 +1,412 @@
1/******************************************************************************
2 *
3 * This file is part of the Nagios Plugins.
4 *
5 * Copyright (c) 1999, 2000, 2001 Karl DeBisschop <karl@debisschop.net>
6 *
7 * The Nagios Plugins are free software; you can redistribute them
8 * and/or modify them under the terms of the GNU General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * $Id$
22 *
23 *****************************************************************************/
24
25#define PROGRAM check_by_ssh
26#define DESCRIPTION "Run checks on a remote system using ssh, wrapping the proper timeout around the ssh invocation."
27#define AUTHOR "Karl DeBisschop"
28#define EMAIL "karl@debisschop.net"
29#define COPYRIGHTDATE "1999, 2000, 2001"
30
31#include "config.h"
32#include "common.h"
33#include "popen.h"
34#include "utils.h"
35#include <time.h>
36
37#define PROGNAME "check_by_ssh"
38
39int process_arguments (int, char **);
40int call_getopt (int, char **);
41int validate_arguments (void);
42void print_help (char *command_name);
43void print_usage (void);
44
45
46int commands;
47char *remotecmd = NULL;
48char *comm = NULL;
49char *hostname = NULL;
50char *outputfile = NULL;
51char *host_shortname = NULL;
52char *servicelist = NULL;
53int passive = FALSE;
54int verbose = FALSE;
55
56
57int
58main (int argc, char **argv)
59{
60
61 char input_buffer[MAX_INPUT_BUFFER] = "";
62 char *result_text = NULL;
63 char *status_text;
64 char *output = NULL;
65 char *eol = NULL;
66 char *srvc_desc = NULL;
67 int cresult;
68 int result = STATE_UNKNOWN;
69 time_t local_time;
70 FILE *fp = NULL;
71
72
73 /* process arguments */
74 if (process_arguments (argc, argv) == ERROR)
75 usage ("Could not parse arguments\n");
76
77
78 /* Set signal handling and alarm timeout */
79 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
80 printf ("Cannot catch SIGALRM");
81 return STATE_UNKNOWN;
82 }
83 alarm (timeout_interval);
84
85
86 /* run the command */
87
88 if (verbose)
89 printf ("%s\n", comm);
90
91 child_process = spopen (comm);
92
93 if (child_process == NULL) {
94 printf ("Unable to open pipe: %s", comm);
95 return STATE_UNKNOWN;
96 }
97
98
99 /* open STDERR for spopen */
100 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
101 if (child_stderr == NULL) {
102 printf ("Could not open stderr for %s\n", SSH_COMMAND);
103 }
104
105
106 /* get results from remote command */
107 result_text = realloc (result_text, 1);
108 result_text[0] = 0;
109 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
110 result_text = strscat (result_text, input_buffer);
111
112
113 /* WARNING if output found on stderr */
114 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
115 printf ("%s\n", input_buffer);
116 return STATE_WARNING;
117 }
118 (void) fclose (child_stderr);
119
120
121 /* close the pipe */
122 result = spclose (child_process);
123
124
125 /* process output */
126 if (passive) {
127
128 if (!(fp = fopen (outputfile, "a"))) {
129 printf ("SSH WARNING: could not open %s\n", outputfile);
130 exit (STATE_UNKNOWN);
131 }
132
133 time (&local_time);
134 srvc_desc = strtok (servicelist, ":");
135 while (result_text != NULL) {
136 status_text = (strstr (result_text, "STATUS CODE: "));
137 if (status_text == NULL) {
138 printf ("%s", result_text);
139 return result;
140 }
141 output = result_text;
142 result_text = strnl (status_text);
143 eol = strpbrk (output, "\r\n");
144 if (eol != NULL)
145 eol[0] = 0;
146 if (srvc_desc && status_text
147 && sscanf (status_text, "STATUS CODE: %d", &cresult) == 1) {
148 fprintf (fp, "%d PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
149 (int) local_time, host_shortname, srvc_desc, cresult,
150 output);
151 srvc_desc = strtok (NULL, ":");
152 }
153 }
154
155 }
156
157 /* print the first line from the remote command */
158 else {
159 eol = strpbrk (result_text, "\r\n");
160 if (eol)
161 eol[0] = 0;
162 printf ("%s\n", result_text);
163
164 }
165
166
167 /* return error status from remote command */
168 return result;
169}
170
171
172
173
174
175/* process command-line arguments */
176int
177process_arguments (int argc, char **argv)
178{
179 int c;
180
181 if (argc < 2)
182 return ERROR;
183
184 remotecmd = realloc (remotecmd, 1);
185 remotecmd[0] = 0;
186
187 for (c = 1; c < argc; c++)
188 if (strcmp ("-to", argv[c]) == 0)
189 strcpy (argv[c], "-t");
190
191 comm = strscpy (comm, SSH_COMMAND);
192
193 c = 0;
194 while (c += (call_getopt (argc - c, &argv[c]))) {
195
196 if (argc <= c)
197 break;
198
199 if (hostname == NULL) {
200 if (!is_host (argv[c]))
201 terminate (STATE_UNKNOWN, "%s: Invalid host name %s\n", PROGNAME,
202 argv[c]);
203 hostname = argv[c];
204 }
205 else if (remotecmd == NULL) {
206 remotecmd = strscpy (remotecmd, argv[c++]);
207 for (; c < argc; c++)
208 remotecmd = ssprintf (remotecmd, "%s %s", remotecmd, argv[c]);
209 }
210
211 }
212
213 if (commands > 1)
214 remotecmd = strscat (remotecmd, ";echo STATUS CODE: $?;");
215
216 if (remotecmd == NULL || strlen (remotecmd) <= 1)
217 usage ("No remotecmd\n");
218
219 comm = ssprintf (comm, "%s %s '%s'", comm, hostname, remotecmd);
220
221 return validate_arguments ();
222}
223
224
225
226
227
228/* Call getopt */
229int
230call_getopt (int argc, char **argv)
231{
232 int c, i = 1;
233
234#ifdef HAVE_GETOPT_H
235 int option_index = 0;
236 static struct option long_options[] = {
237 {"version", no_argument, 0, 'V'},
238 {"help", no_argument, 0, 'h'},
239 {"verbose", no_argument, 0, 'v'},
240 {"fork", no_argument, 0, 'f'},
241 {"timeout", required_argument, 0, 't'},
242 {"host", required_argument, 0, 'H'},
243 {"port", required_argument,0,'P'},
244 {"output", required_argument, 0, 'O'},
245 {"name", required_argument, 0, 'n'},
246 {"services", required_argument, 0, 's'},
247 {"identity", required_argument, 0, 'i'},
248 {"user", required_argument, 0, 'u'},
249 {"logname", required_argument, 0, 'l'},
250 {"command", required_argument, 0, 'C'},
251 {0, 0, 0, 0}
252 };
253#endif
254
255 while (1) {
256#ifdef HAVE_GETOPT_H
257 c =
258 getopt_long (argc, argv, "+?Vvhft:H:O:P:p:i:u:l:C:n:s:", long_options,
259 &option_index);
260#else
261 c = getopt (argc, argv, "+?Vvhft:H:O:P:p:i:u:l:C:n:s:");
262#endif
263
264 if (c == -1 || c == EOF)
265 break;
266
267 i++;
268 switch (c) {
269 case 't':
270 case 'H':
271 case 'O':
272 case 'p':
273 case 'i':
274 case 'u':
275 case 'l':
276 case 'n':
277 case 's':
278 i++;
279 }
280
281 switch (c) {
282 case '?': /* help */
283 print_usage ();
284 exit (STATE_UNKNOWN);
285 case 'V': /* version */
286 print_revision (PROGNAME, "$Revision$");
287 exit (STATE_OK);
288 case 'h': /* help */
289 print_help (PROGNAME);
290 exit (STATE_OK);
291 case 'v': /* help */
292 verbose = TRUE;
293 break;
294 case 'f': /* fork to background */
295 comm = ssprintf (comm, "%s -f", comm);
296 break;
297 case 't': /* timeout period */
298 if (!is_integer (optarg))
299 usage2 ("timeout interval must be an integer", optarg);
300 timeout_interval = atoi (optarg);
301 break;
302 case 'H': /* host */
303 if (!is_host (optarg))
304 usage2 ("invalid host name", optarg);
305 hostname = optarg;
306 break;
307 case 'P': /* port number */
308 case 'p': /* port number */
309 if (!is_integer (optarg))
310 usage2 ("port must be an integer", optarg);
311 comm = ssprintf (comm,"%s -p %s", comm, optarg);
312 break;
313 case 'O': /* output file */
314 outputfile = optarg;
315 passive = TRUE;
316 break;
317 case 's': /* description of service to check */
318 servicelist = optarg;
319 break;
320 case 'n': /* short name of host in nagios configuration */
321 host_shortname = optarg;
322 break;
323 case 'u':
324 c = 'l';
325 case 'l': /* login name */
326 case 'i': /* identity */
327 comm = ssprintf (comm, "%s -%c %s", comm, c, optarg);
328 break;
329 case 'C': /* Command for remote machine */
330 commands++;
331 if (commands > 1)
332 remotecmd = strscat (remotecmd, ";echo STATUS CODE: $?;");
333 remotecmd = strscat (remotecmd, optarg);
334 }
335 }
336 return i;
337}
338
339
340
341
342
343int
344validate_arguments (void)
345{
346 if (remotecmd == NULL || hostname == NULL)
347 return ERROR;
348 return OK;
349}
350
351
352
353
354
355void
356print_help (char *cmd)
357{
358 print_revision (cmd, "$Revision$");
359
360 printf
361 ("Copyright (c) 1999 Karl DeBisschop (kdebisschop@alum.mit.edu)\n\n"
362 "This plugin will execute a command on a remote host using SSH\n\n");
363
364 print_usage ();
365
366 printf
367 ("\nOptions:\n"
368 "-H, --hostname=HOST\n"
369 " name or IP address of remote host\n"
370 "-C, --command='COMMAND STRING'\n"
371 " command to execute on the remote machine\n"
372 "-f tells ssh to fork rather than create a tty\n"
373 "-t, --timeout=INTEGER\n"
374 " specify timeout (default: %d seconds) [optional]\n"
375 "-l, --logname=USERNAME\n"
376 " SSH user name on remote host [optional]\n"
377 "-i, --identity=KEYFILE\n"
378 " identity of an authorized key [optional]\n"
379 "-O, --output=FILE\n"
380 " external command file for nagios [optional]\n"
381 "-s, --services=LIST\n"
382 " list of nagios service names, separated by ':' [optional]\n"
383 "-n, --name=NAME\n"
384 " short name of host in nagios configuration [optional]\n"
385 "\n"
386 "The most common mode of use is to refer to a local identity file with\n"
387 "the '-i' option. In this mode, the identity pair should have a null\n"
388 "passphrase and the public key should be listed in the authorized_keys\n"
389 "file of the remote host. Usually the key will be restricted to running\n"
390 "only one command on the remote server. If the remote SSH server tracks\n"
391 "invocation agruments, the one remote program may be an agent that can\n"
392 "execute additional commands as proxy\n"
393 "\n"
394 "To use passive mode, provide multiple '-C' options, and provide\n"
395 "all of -O, -s, and -n options (servicelist order must match '-C'\n"
396 "options)\n", DEFAULT_SOCKET_TIMEOUT);
397}
398
399
400
401
402
403void
404print_usage (void)
405{
406 printf
407 ("Usage:\n"
408 "check_by_ssh [-f] [-t timeout] [-i identity] [-l user] -H <host> <command>\n"
409 " [-n name] [-s servicelist] [-O outputfile] [-P port]\n"
410 "check_by_ssh -V prints version info\n"
411 "check_by_ssh -h prints more detailed help\n");
412}
diff --git a/plugins/check_dig.c b/plugins/check_dig.c
new file mode 100644
index 00000000..57609acd
--- /dev/null
+++ b/plugins/check_dig.c
@@ -0,0 +1,296 @@
1/******************************************************************************
2*
3* check_dig.c
4*
5* Program: dig plugin for Nagios
6* License: GPL
7* Copyright (c) 2000
8*
9* $Id$
10*
11*****************************************************************************/
12
13#include "config.h"
14#include "common.h"
15#include "utils.h"
16#include "popen.h"
17
18#define PROGNAME "check_dig"
19
20int process_arguments (int, char **);
21int call_getopt (int, char **);
22int validate_arguments (void);
23int check_disk (int usp, int free_disk);
24void print_help (void);
25void print_usage (void);
26
27char *query_address = NULL;
28char *dns_server = NULL;
29int verbose = FALSE;
30
31int
32main (int argc, char **argv)
33{
34 char input_buffer[MAX_INPUT_BUFFER];
35 char *command_line = NULL;
36 char *output = NULL;
37 int result = STATE_UNKNOWN;
38
39 /* Set signal handling and alarm */
40 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR)
41 usage ("Cannot catch SIGALRM\n");
42
43 if (process_arguments (argc, argv) != OK)
44 usage ("Could not parse arguments\n");
45
46 /* get the command to run */
47 command_line =
48 ssprintf (command_line, "%s @%s %s", PATH_TO_DIG, dns_server,
49 query_address);
50
51 alarm (timeout_interval);
52 time (&start_time);
53
54 if (verbose)
55 printf ("%s\n", command_line);
56 /* run the command */
57 child_process = spopen (command_line);
58 if (child_process == NULL) {
59 printf ("Could not open pipe: %s\n", command_line);
60 return STATE_UNKNOWN;
61 }
62
63 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
64 if (child_stderr == NULL)
65 printf ("Could not open stderr for %s\n", command_line);
66
67 output = strscpy (output, "");
68
69 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
70
71 /* the server is responding, we just got the host name... */
72 if (strstr (input_buffer, ";; ANSWER SECTION:")) {
73
74 /* get the host address */
75 if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
76 break;
77
78 if (strpbrk (input_buffer, "\r\n"))
79 input_buffer[strcspn (input_buffer, "\r\n")] = '\0';
80
81 if (strstr (input_buffer, query_address) == input_buffer) {
82 output = strscpy (output, input_buffer);
83 result = STATE_OK;
84 }
85 else {
86 strcpy (output, "Server not found in ANSWER SECTION");
87 result = STATE_WARNING;
88 }
89
90 continue;
91 }
92
93 }
94
95 if (result != STATE_OK) {
96 strcpy (output, "No ANSWER SECTION found");
97 }
98
99 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
100 /* If we get anything on STDERR, at least set warning */
101 result = max (result, STATE_WARNING);
102 printf ("%s", input_buffer);
103 if (!strcmp (output, ""))
104 strcpy (output, 1 + index (input_buffer, ':'));
105 }
106
107 (void) fclose (child_stderr);
108
109 /* close the pipe */
110 if (spclose (child_process)) {
111 result = max (result, STATE_WARNING);
112 if (!strcmp (output, ""))
113 strcpy (output, "nslookup returned error status");
114 }
115
116 (void) time (&end_time);
117
118 if (result == STATE_OK)
119 printf ("DNS ok - %d seconds response time (%s)\n",
120 (int) (end_time - start_time), output);
121 else if (result == STATE_WARNING)
122 printf ("DNS WARNING - %s\n",
123 !strcmp (output,
124 "") ? " Probably a non-existent host/domain" : output);
125 else if (result == STATE_CRITICAL)
126 printf ("DNS CRITICAL - %s\n",
127 !strcmp (output,
128 "") ? " Probably a non-existent host/domain" : output);
129 else
130 printf ("DNS problem - %s\n",
131 !strcmp (output,
132 "") ? " Probably a non-existent host/domain" : output);
133
134 return result;
135}
136
137/* process command-line arguments */
138int
139process_arguments (int argc, char **argv)
140{
141 int c;
142
143 if (argc < 2)
144 return ERROR;
145
146
147 c = 0;
148 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
149
150 if (is_option (argv[c]))
151 continue;
152
153 if (dns_server == NULL) {
154 if (is_host (argv[c])) {
155 dns_server = argv[c];
156 }
157 else {
158 usage ("Invalid host name");
159 }
160 }
161 }
162
163 if (dns_server == NULL)
164 dns_server = strscpy (NULL, "127.0.0.1");
165
166 return validate_arguments ();
167}
168
169
170
171
172
173
174int
175call_getopt (int argc, char **argv)
176{
177 int c, i = 0;
178
179#ifdef HAVE_GETOPT_H
180 int option_index = 0;
181 static struct option long_options[] = {
182 {"hostname", required_argument, 0, 'H'},
183 {"query_address", required_argument, 0, 'e'},
184 {"verbose", no_argument, 0, 'v'},
185 {"version", no_argument, 0, 'V'},
186 {"help", no_argument, 0, 'h'},
187 {0, 0, 0, 0}
188 };
189#endif
190
191 while (1) {
192#ifdef HAVE_GETOPT_H
193 c = getopt_long (argc, argv, "+hVvt:l:H:", long_options, &option_index);
194#else
195 c = getopt (argc, argv, "+?hVvt:l:H:");
196#endif
197
198 i++;
199
200 if (c == -1 || c == EOF || c == 1)
201 break;
202
203 switch (c) {
204 case 't':
205 case 'l':
206 case 'H':
207 i++;
208 }
209
210 switch (c) {
211 case 'H': /* hostname */
212 if (is_host (optarg)) {
213 dns_server = optarg;
214 }
215 else {
216 usage ("Invalid host name\n");
217 }
218 break;
219 case 'l': /* username */
220 query_address = optarg;
221 break;
222 case 'v': /* verbose */
223 verbose = TRUE;
224 break;
225 case 't': /* timeout */
226 if (is_intnonneg (optarg)) {
227 timeout_interval = atoi (optarg);
228 }
229 else {
230 usage ("Time interval must be a nonnegative integer\n");
231 }
232 break;
233 case 'V': /* version */
234 print_revision (PROGNAME, "$Revision$");
235 exit (STATE_OK);
236 case 'h': /* help */
237 print_help ();
238 exit (STATE_OK);
239 case '?': /* help */
240 usage ("Invalid argument\n");
241 }
242 }
243 return i;
244}
245
246
247
248
249
250int
251validate_arguments (void)
252{
253 return OK;
254}
255
256
257
258
259
260void
261print_help (void)
262{
263 print_revision (PROGNAME, "$Revision$");
264 printf
265 ("Copyright (c) 2000 Karl DeBisschop\n\n"
266 "This plugin use dig to test the DNS service on the specified host.\n\n");
267 print_usage ();
268 printf
269 ("\nOptions:\n"
270 " -H, --hostname=STRING or IPADDRESS\n"
271 " Check server on the indicated host\n"
272 " -l, --lookup=STRING\n"
273 " machine name to lookup\n"
274 " -t, --timeout=INTEGER\n"
275 " Seconds before connection attempt times out (default: %d)\n"
276 " -v, --verbose\n"
277 " Print extra information (command-line use only)\n"
278 " -h, --help\n"
279 " Print detailed help screen\n"
280 " -V, --version\n"
281 " Print version information\n\n", DEFAULT_SOCKET_TIMEOUT);
282 support ();
283}
284
285
286
287
288
289void
290print_usage (void)
291{
292 printf
293 ("Usage: %s -H host -l lookup [-t timeout] [-v]\n"
294 " %s --help\n"
295 " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
296}
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
new file mode 100644
index 00000000..d7aad072
--- /dev/null
+++ b/plugins/check_disk.c
@@ -0,0 +1,353 @@
1/******************************************************************************
2 *
3 * CHECK_DISK.C
4 *
5 * Program: Disk space plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 * Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
9 *
10 * $Id$
11 *
12 * Description:
13 *
14 * This plugin will use the /bin/df command to check the free space on
15 * currently mounted filesystems. If the percent used disk space is
16 * above <c_dfp>, a STATE_CRITICAL is returned. If the percent used
17 * disk space is above <w_dfp>, a STATE_WARNING is returned. If the
18 * speicified filesystem cannot be read, a STATE_CRITICAL is returned,
19 * other errors with reading the output result in a STATE_UNKNOWN
20 * error.
21 *
22 * Notes:
23 * - IRIX support added by Charlie Cook 4-16-1999
24 * - Modifications by Karl DeBisschop 1999-11-24
25 * reformat code to 80 char screen width
26 * set STATE_WARNING if stderr is written or spclose status set
27 * set default result to STAT_UNKNOWN
28 * initailize usp to -1, eliminate 'found' variable
29 * accept any filename/filesystem
30 * use sscanf, drop while loop
31 *
32 *****************************************************************************/
33
34#include "common.h"
35#include "popen.h"
36#include "utils.h"
37#include <stdarg.h>
38
39#define PROGNAME "check_disk"
40
41int process_arguments (int, char **);
42int call_getopt (int, char **);
43int validate_arguments (void);
44int check_disk (int usp, int free_disk);
45void print_help (void);
46void print_usage (void);
47
48int w_df = -1;
49int c_df = -1;
50float w_dfp = -1.0;
51float c_dfp = -1.0;
52char *path = NULL;
53int verbose = FALSE;
54
55int
56main (int argc, char **argv)
57{
58 int len;
59 int usp = -1;
60 int total_disk = -1;
61 int used_disk = -1;
62 int free_disk = -1;
63 int result = STATE_UNKNOWN;
64 char *command_line = NULL;
65 char input_buffer[MAX_INPUT_BUFFER] = "";
66 char file_system[MAX_INPUT_BUFFER] = "";
67 char outbuf[MAX_INPUT_BUFFER] = "";
68 char *output = NULL;
69
70 if (process_arguments (argc, argv) != OK)
71 usage ("Could not parse arguments\n");
72
73 command_line = ssprintf (command_line, "%s %s", DF_COMMAND, path);
74
75 if (verbose)
76 printf ("%s ==> ", command_line);
77
78 child_process = spopen (command_line);
79 if (child_process == NULL) {
80 printf ("Could not open pipe: %s\n", command_line);
81 return STATE_UNKNOWN;
82 }
83
84 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
85 if (child_stderr == NULL) {
86 printf ("Could not open stderr for %s\n", command_line);
87 }
88
89 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
90
91 if (!index (input_buffer, '/'))
92 continue;
93
94 if (sscanf
95 (input_buffer, "%s %d %d %d %d%%", file_system, &total_disk,
96 &used_disk, &free_disk, &usp) == 5
97 || sscanf (input_buffer, "%s %*s %d %d %d %d%%", file_system,
98 &total_disk, &used_disk, &free_disk, &usp) == 5) {
99 result = max (result, check_disk (usp, free_disk));
100 len =
101 snprintf (outbuf, MAX_INPUT_BUFFER - 1,
102 " [%d kB (%d%%) free on %s]", free_disk, 100 - usp,
103 file_system);
104 outbuf[len] = 0;
105 output = strscat (output, outbuf);
106 }
107 else {
108 printf ("Unable to read output:\n%s\n%s\n", command_line, input_buffer);
109 return result;
110 }
111 }
112
113 /* If we get anything on stderr, at least set warning */
114 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
115 result = max (result, STATE_WARNING);
116
117 /* close stderr */
118 (void) fclose (child_stderr);
119
120 /* close the pipe */
121 if (spclose (child_process))
122 result = max (result, STATE_WARNING);
123
124 else if (usp < 0)
125 printf ("Disk %s not mounted or nonexistant\n", argv[3]);
126 else if (result == STATE_UNKNOWN)
127 printf ("Unable to read output\n%s\n%s\n", command_line, input_buffer);
128 else
129 printf ("DISK %s -%s\n", state_text (result), output);
130
131 return result;
132}
133
134/* process command-line arguments */
135int
136process_arguments (int argc, char **argv)
137{
138 int c;
139
140 if (argc < 2)
141 return ERROR;
142
143 for (c = 1; c < argc; c++) {
144 if (strcmp ("-to", argv[c]) == 0) {
145 strcpy (argv[c], "-t");
146 }
147 }
148
149 c = 0;
150 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
151
152 if (w_dfp == -1 && is_intnonneg (argv[c]))
153 w_dfp = (100.0 - atof (argv[c]));
154 else if (c_dfp == -1 && is_intnonneg (argv[c]))
155 c_dfp = (100.0 - atof (argv[c]));
156 else if (path == NULL || path[0] == 0)
157 path = strscpy (path, argv[c]);
158 }
159
160 if (path == NULL) {
161 path = malloc (1);
162 if (path == NULL)
163 terminate (STATE_UNKNOWN, "Could not malloc empty path\n");
164 path[0] = 0;
165 }
166
167 return validate_arguments ();
168}
169
170int
171call_getopt (int argc, char **argv)
172{
173 int c, i = 0;
174
175#ifdef HAVE_GETOPT_H
176 int option_index = 0;
177 static struct option long_options[] = {
178 {"warning", required_argument, 0, 'w'},
179 {"critical", required_argument, 0, 'c'},
180 {"timeout", required_argument, 0, 't'},
181 {"path", required_argument, 0, 'p'},
182 {"partition", required_argument, 0, 'p'},
183 {"verbose", no_argument, 0, 'v'},
184 {"version", no_argument, 0, 'V'},
185 {"help", no_argument, 0, 'h'},
186 {0, 0, 0, 0}
187 };
188#endif
189
190 while (1) {
191#ifdef HAVE_GETOPT_H
192 c =
193 getopt_long (argc, argv, "+?Vhvt:c:w:p:", long_options, &option_index);
194#else
195 c = getopt (argc, argv, "+?Vhvt:c:w:p:");
196#endif
197
198 i++;
199
200 if (c == -1 || c == EOF || c == 1)
201 break;
202
203 switch (c) {
204 case 't':
205 case 'c':
206 case 'w':
207 case 'p':
208 i++;
209 }
210
211 switch (c) {
212 case 'w': /* warning time threshold */
213 if (is_intnonneg (optarg)) {
214 w_df = atoi (optarg);
215 break;
216 }
217 else if (strpbrk (optarg, ",:") &&
218 strstr (optarg, "%") &&
219 sscanf (optarg, "%d%*[:,]%f%%", &w_df, &w_dfp) == 2) {
220 break;
221 }
222 else if (strstr (optarg, "%") && sscanf (optarg, "%f%%", &w_dfp) == 1) {
223 break;
224 }
225 else {
226 usage ("Warning threshold must be integer or percentage!\n");
227 }
228 case 'c': /* critical time threshold */
229 if (is_intnonneg (optarg)) {
230 c_df = atoi (optarg);
231 break;
232 }
233 else if (strpbrk (optarg, ",:") &&
234 strstr (optarg, "%") &&
235 sscanf (optarg, "%d%*[,:]%f%%", &c_df, &c_dfp) == 2) {
236 break;
237 }
238 else if (strstr (optarg, "%") && sscanf (optarg, "%f%%", &c_dfp) == 1) {
239 break;
240 }
241 else {
242 usage ("Critical threshold must be integer or percentage!\n");
243 }
244 case 't': /* timeout period */
245 if (is_integer (optarg)) {
246 timeout_interval = atoi (optarg);
247 break;
248 }
249 else {
250 usage ("Timeout Interval must be an integer!\n");
251 }
252 case 'p': /* path or partition */
253 path = optarg;
254 break;
255 case 'v': /* verbose */
256 verbose = TRUE;
257 break;
258 case 'V': /* version */
259 print_revision (my_basename (argv[0]), "$Revision$");
260 exit (STATE_OK);
261 case 'h': /* help */
262 print_help ();
263 exit (STATE_OK);
264 case '?': /* help */
265 usage ("check_disk: unrecognized option\n");
266 break;
267 }
268 }
269 return i;
270}
271
272int
273validate_arguments ()
274{
275 if (w_df < 0 && c_df < 0 && w_dfp < 0 && c_dfp < 0) {
276 printf ("INPUT ERROR: Unable to parse command line\n");
277 return ERROR;
278 }
279 else if ((w_dfp >= 0 || c_dfp >= 0)
280 && (w_dfp < 0 || c_dfp < 0 || w_dfp > 100 || c_dfp > 100
281 || c_dfp > w_dfp)) {
282 printf
283 ("INPUT ERROR: C_DFP (%f) should be less than W_DFP (%f) and both should be between zero and 100 percent, inclusive\n",
284 c_dfp, w_dfp);
285 return ERROR;
286 }
287 else if ((w_df > 0 || c_df > 0) && (w_df < 0 || c_df < 0 || c_df > w_df)) {
288 printf
289 ("INPUT ERROR: C_DF (%d) should be less than W_DF (%d) and both should be greater than zero\n",
290 c_df, w_df);
291 return ERROR;
292 }
293 else {
294 return OK;
295 }
296}
297
298int
299check_disk (usp, free_disk)
300{
301 int result = STATE_UNKNOWN;
302 /* check the percent used space against thresholds */
303 if (usp >= 0 && usp >= (100.0 - c_dfp))
304 result = STATE_CRITICAL;
305 else if (c_df >= 0 && free_disk <= c_df)
306 result = STATE_CRITICAL;
307 else if (usp >= 0 && usp >= (100.0 - w_dfp))
308 result = STATE_WARNING;
309 else if (w_df >= 0 && free_disk <= w_df)
310 result = STATE_WARNING;
311 else if (usp >= 0.0)
312 result = STATE_OK;
313 return result;
314}
315
316void
317print_help (void)
318{
319 print_revision (PROGNAME, "$Revision$");
320 printf
321 ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
322 "This plugin will check the percent of used disk space on a mounted\n"
323 "file system and generate an alert if percentage is above one of the\n"
324 "threshold values.\n\n");
325 print_usage ();
326 printf
327 ("\nOptions:\n"
328 " -w, --warning=INTEGER\n"
329 " Exit with WARNING status if less than INTEGER kilobytes of disk are free\n"
330 " -w, --warning=PERCENT%%\n"
331 " Exit with WARNING status if more than PERCENT of disk space is free\n"
332 " -c, --critical=INTEGER\n"
333 " Exit with CRITICAL status if less than INTEGER kilobytes of disk are free\n"
334 " -c, --critical=PERCENT%%\n"
335 " Exit with CRITCAL status if more than PERCENT of disk space is free\n"
336 " -p, --path=PATH, --partition=PARTTION\n"
337 " Path or partition (checks all mounted partitions if unspecified)\n"
338 " -v, --verbose\n"
339 " Show details for command-line debugging (do not use with nagios server)\n"
340 " -h, --help\n"
341 " Print detailed help screen\n"
342 " -V, --version\n" " Print version information\n\n");
343 support ();
344}
345
346void
347print_usage (void)
348{
349 printf
350 ("Usage: %s -w limit -c limit [-p path] [-t timeout] [--verbose]\n"
351 " %s (-h|--help)\n"
352 " %s (-V|--version)\n", PROGNAME, PROGNAME, PROGNAME);
353}
diff --git a/plugins/check_dns.c b/plugins/check_dns.c
new file mode 100644
index 00000000..eaff4372
--- /dev/null
+++ b/plugins/check_dns.c
@@ -0,0 +1,415 @@
1/******************************************************************************
2 *
3 * CHECK_DNS.C
4 *
5 * Program: DNS plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 *
9 * Last Modified: $Date$
10 *
11 * Notes:
12 * - Safe popen added by Karl DeBisschop 9-11-99
13 *
14 * Command line: CHECK_DNS <query_address> [dns_server]
15 *
16 * Description:
17 *
18 * This program will use the nslookup program to obtain the IP address
19 * for a given host name. A optional DNS server may be specified. If
20 * no DNS server is specified, the default server(s) for the system
21 * are used.
22 *
23 * Return Values:
24 * OK The DNS query was successful (host IP address was returned).
25 * WARNING The DNS server responded, but could not fulfill the request.
26 * CRITICAL The DNS server is not responding or encountered an error.
27 *
28 * License Information:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
43 *
44 *****************************************************************************/
45
46#include "common.h"
47#include "popen.h"
48#include "utils.h"
49
50int process_arguments (int, char **);
51int call_getopt (int, char **);
52int validate_arguments (void);
53void print_usage (char *);
54void print_help (char *);
55int error_scan (char *);
56
57#define ADDRESS_LENGTH 256
58char query_address[ADDRESS_LENGTH] = "";
59char dns_server[ADDRESS_LENGTH] = "";
60char ptr_server[ADDRESS_LENGTH] = "";
61int verbose = FALSE;
62
63int
64main (int argc, char **argv)
65{
66 char *command_line = NULL;
67 char input_buffer[MAX_INPUT_BUFFER];
68 char *output = NULL;
69 char *address = NULL;
70 char *temp_buffer = NULL;
71 int result = STATE_UNKNOWN;
72
73 /* Set signal handling and alarm */
74 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
75 printf ("Cannot catch SIGALRM");
76 return STATE_UNKNOWN;
77 }
78
79 if (process_arguments (argc, argv) != OK) {
80 print_usage (my_basename (argv[0]));
81 return STATE_UNKNOWN;
82 }
83
84 /* get the command to run */
85 command_line = ssprintf (command_line, "%s %s %s", NSLOOKUP_COMMAND,
86 query_address, dns_server);
87
88 alarm (timeout_interval);
89 time (&start_time);
90
91 if (verbose)
92 printf ("%s\n", command_line);
93 /* run the command */
94 child_process = spopen (command_line);
95 if (child_process == NULL) {
96 printf ("Could not open pipe: %s\n", command_line);
97 return STATE_UNKNOWN;
98 }
99
100 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
101 if (child_stderr == NULL)
102 printf ("Could not open stderr for %s\n", command_line);
103
104 /* scan stdout */
105 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
106
107 if (verbose)
108 printf ("%s\n", input_buffer);
109
110 if (strstr (input_buffer, ".in-addr.arpa")) {
111 if ((temp_buffer = strstr (input_buffer, "name = ")))
112 address = strscpy (address, temp_buffer + 7);
113 else {
114 output = strscpy (output, "Unknown error (plugin)");
115 result = STATE_WARNING;
116 }
117 }
118
119 /* the server is responding, we just got the host name... */
120 if (strstr (input_buffer, "Name:")) {
121
122 /* get the host address */
123 if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
124 break;
125
126 if (verbose)
127 printf ("%s\n", input_buffer);
128
129 if ((temp_buffer = index (input_buffer, ':'))) {
130 address = strscpy (address, temp_buffer + 2);
131 strip (address);
132 result = STATE_OK;
133 }
134 else {
135 output = strscpy (output, "Unknown error (plugin)");
136 result = STATE_WARNING;
137 }
138
139 break;
140 }
141
142 result = error_scan (input_buffer);
143 if (result != STATE_OK) {
144 output = strscpy (output, 1 + index (input_buffer, ':'));
145 break;
146 }
147
148 }
149
150 /* scan stderr */
151 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
152 if (error_scan (input_buffer) != STATE_OK) {
153 result = max (result, error_scan (input_buffer));
154 output = strscpy (output, 1 + index (input_buffer, ':'));
155 }
156 }
157
158 /* close stderr */
159 (void) fclose (child_stderr);
160
161 /* close stdout */
162 if (spclose (child_process)) {
163 result = max (result, STATE_WARNING);
164 if (!strcmp (output, ""))
165 output = strscpy (output, "nslookup returned error status");
166 }
167
168 (void) time (&end_time);
169
170 if (result == STATE_OK)
171 printf ("DNS ok - %d seconds response time, Address(es) is/are %s\n",
172 (int) (end_time - start_time), address);
173 else if (result == STATE_WARNING)
174 printf ("DNS WARNING - %s\n",
175 !strcmp (output, "") ? " Probably a non-existent host/domain" : output);
176 else if (result == STATE_CRITICAL)
177 printf ("DNS CRITICAL - %s\n",
178 !strcmp (output, "") ? " Probably a non-existent host/domain" : output);
179 else
180 printf ("DNS problem - %s\n",
181 !strcmp (output, "") ? " Probably a non-existent host/domain" : output);
182
183 return result;
184}
185
186int
187error_scan (char *input_buffer)
188{
189
190 /* the DNS lookup timed out */
191 if (strstr (input_buffer,
192 "Note: nslookup is deprecated and may be removed from future releases.")
193 || strstr (input_buffer,
194 "Consider using the `dig' or `host' programs instead. Run nslookup with")
195 || strstr (input_buffer,
196 "the `-sil[ent]' option to prevent this message from appearing."))
197 return STATE_OK;
198
199 /* the DNS lookup timed out */
200 else if (strstr (input_buffer, "Timed out"))
201 return STATE_WARNING;
202
203 /* DNS server is not running... */
204 else if (strstr (input_buffer, "No response from server"))
205 return STATE_CRITICAL;
206
207 /* Host name is valid, but server doesn't have records... */
208 else if (strstr (input_buffer, "No records"))
209 return STATE_WARNING;
210
211 /* Host or domain name does not exist */
212 else if (strstr (input_buffer, "Non-existent"))
213 return STATE_CRITICAL;
214 else if (strstr (input_buffer, "** server can't find"))
215 return STATE_CRITICAL;
216 else if(strstr(input_buffer,"NXDOMAIN")) /* 9.x */
217 return STATE_CRITICAL;
218
219 /* Connection was refused */
220 else if (strstr (input_buffer, "Connection refused"))
221 return STATE_CRITICAL;
222
223 /* Network is unreachable */
224 else if (strstr (input_buffer, "Network is unreachable"))
225 return STATE_CRITICAL;
226
227 /* Internal server failure */
228 else if (strstr (input_buffer, "Server failure"))
229 return STATE_CRITICAL;
230
231 /* DNS server refused to service request */
232 else if (strstr (input_buffer, "Refused"))
233 return STATE_CRITICAL;
234
235 /* Request error */
236 else if (strstr (input_buffer, "Format error"))
237 return STATE_WARNING;
238
239 else
240 return STATE_OK;
241
242}
243
244/* process command-line arguments */
245int
246process_arguments (int argc, char **argv)
247{
248 int c;
249
250 if (argc < 2)
251 return ERROR;
252
253 for (c = 1; c < argc; c++)
254 if (strcmp ("-to", argv[c]) == 0)
255 strcpy (argv[c], "-t");
256
257 c = 0;
258 while (c += (call_getopt (argc - c, &argv[c]))) {
259 if (argc <= c)
260 break;
261 if (query_address[0] == 0) {
262 if (is_host (argv[c]) == FALSE) {
263 printf ("Invalid name/address: %s\n\n", argv[c]);
264 return ERROR;
265 }
266 if (strlen (argv[c]) >= ADDRESS_LENGTH)
267 terminate (STATE_UNKNOWN, "Input buffer overflow\n");
268 strcpy (query_address, argv[c]);
269 }
270 else if (dns_server[0] == 0) {
271 if (is_host (argv[c]) == FALSE) {
272 printf ("Invalid name/address: %s\n\n", argv[c]);
273 return ERROR;
274 }
275 if (strlen (argv[c]) >= ADDRESS_LENGTH)
276 terminate (STATE_UNKNOWN, "Input buffer overflow\n");
277 strcpy (dns_server, argv[c]);
278 }
279 }
280
281 return validate_arguments ();
282
283}
284
285int
286call_getopt (int argc, char **argv)
287{
288 int c, i = 1;
289
290#ifdef HAVE_GETOPT_H
291 int opt_index = 0;
292 static struct option long_opts[] = {
293 {"help", no_argument, 0, 'h'},
294 {"version", no_argument, 0, 'V'},
295 {"verbose", no_argument, 0, 'v'},
296 {"timeout", required_argument, 0, 't'},
297 {"hostname", required_argument, 0, 'H'},
298 {"server", required_argument, 0, 's'},
299 {"reverse-server", required_argument, 0, 'r'},
300 {0, 0, 0, 0}
301 };
302#endif
303
304
305 while (1) {
306#ifdef HAVE_GETOPT_H
307 c = getopt_long (argc, argv, "+?hVvt:H:s:r:", long_opts, &opt_index);
308#else
309 c = getopt (argc, argv, "+?hVvt:H:s:r:");
310#endif
311
312 if (c == -1 || c == EOF)
313 break;
314
315 i++;
316 switch (c) {
317 case 't':
318 case 'H':
319 case 's':
320 case 'r':
321 i++;
322 }
323
324 switch (c) {
325 case '?': /* args not parsable */
326 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
327 print_usage (my_basename (argv[0]));
328 exit (STATE_UNKNOWN);
329 case 'h': /* help */
330 print_help (my_basename (argv[0]));
331 exit (STATE_OK);
332 case 'V': /* version */
333 print_revision (my_basename (argv[0]), "$Revision$");
334 exit (STATE_OK);
335 case 'v': /* version */
336 verbose = TRUE;
337 break;
338 case 't': /* timeout period */
339 timeout_interval = atoi (optarg);
340 break;
341 case 'H': /* hostname */
342 if (is_host (optarg) == FALSE) {
343 printf ("Invalid host name/address\n\n");
344 print_usage (my_basename (argv[0]));
345 exit (STATE_UNKNOWN);
346 }
347 if (strlen (optarg) >= ADDRESS_LENGTH)
348 terminate (STATE_UNKNOWN, "Input buffer overflow\n");
349 strcpy (query_address, optarg);
350 break;
351 case 's': /* server name */
352 if (is_host (optarg) == FALSE) {
353 printf ("Invalid server name/address\n\n");
354 print_usage (my_basename (argv[0]));
355 exit (STATE_UNKNOWN);
356 }
357 if (strlen (optarg) >= ADDRESS_LENGTH)
358 terminate (STATE_UNKNOWN, "Input buffer overflow\n");
359 strcpy (dns_server, optarg);
360 break;
361 case 'r': /* reverse server name */
362 if (is_host (optarg) == FALSE) {
363 printf ("Invalid host name/address\n\n");
364 print_usage (my_basename (argv[0]));
365 exit (STATE_UNKNOWN);
366 }
367 if (strlen (optarg) >= ADDRESS_LENGTH)
368 terminate (STATE_UNKNOWN, "Input buffer overflow\n");
369 strcpy (ptr_server, optarg);
370 break;
371 }
372 }
373 return i;
374}
375
376int
377validate_arguments ()
378{
379 if (query_address[0] == 0)
380 return ERROR;
381 else
382 return OK;
383}
384
385void
386print_usage (char *cmd)
387{
388 printf ("Usage: %s -H host [-s server] [-t timeout]\n" " %s --help\n"
389 " %s --version\n", cmd, cmd, cmd);
390}
391
392void
393print_help (char *cmd)
394{
395 print_revision (cmd, "$Revision$");
396 printf ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n\n");
397 print_usage (cmd);
398 printf ("\n");
399 printf
400 ("-H, --hostname=HOST\n"
401 " The name or address you want to query\n"
402 "-s, --server=HOST\n"
403 " Optional DNS server you want to use for the lookup\n"
404 "-t, --timeout=INTEGER\n"
405 " Seconds before connection times out (default: %d)\n"
406 "-h, --help\n"
407 " Print detailed help\n"
408 "-V, --version\n"
409 " Print version numbers and license information\n"
410 "\n"
411 "This plugin uses the nslookup program to obtain the IP address\n"
412 "for the given host/domain query. A optional DNS server to use may\n"
413 "be specified. If no DNS server is specified, the default server(s)\n"
414 "specified in /etc/resolv.conf will be used.\n", DEFAULT_SOCKET_TIMEOUT);
415}
diff --git a/plugins/check_dummy.c b/plugins/check_dummy.c
new file mode 100644
index 00000000..c2a5b7eb
--- /dev/null
+++ b/plugins/check_dummy.c
@@ -0,0 +1,100 @@
1/*************************************************************
2 *
3 * CHECK_DUMMY.C
4 *
5 * Program: Dummy plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 *
9 * Last Modified: $Date$
10 *
11 * Command line: CHECK_DUMMY <state>
12 *
13 * Description:
14 *
15 * This plugin will simply return the state corresponding to the
16 * numerical value of the <state> argument.
17 *
18 * License Information:
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 *
34 **************************************************************/
35
36#include "config.h"
37#include "common.h"
38#include "utils.h"
39
40void print_help (char *);
41void print_usage (char *);
42
43int
44main (int argc, char **argv)
45{
46 int result;
47
48 if (argc != 2) {
49 printf ("Incorrect number of arguments supplied\n");
50 exit (STATE_UNKNOWN);
51 }
52 else if (strcmp (argv[1], "-V") == 0 || strcmp (argv[1], "--version") == 0) {
53 print_revision (argv[0], "$Revision$");
54 exit (STATE_OK);
55 }
56 else if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) {
57 print_help (argv[0]);
58 exit (STATE_OK);
59 }
60 else if (!is_integer (argv[1])) {
61 print_usage (argv[0]);
62 exit (STATE_UNKNOWN);
63 }
64 result = atoi (argv[1]);
65
66 switch (result) {
67 case STATE_OK:
68 printf ("Status is OK\n");
69 break;
70 case STATE_WARNING:
71 printf ("Status is at WARNING level\n");
72 break;
73 case STATE_CRITICAL:
74 printf ("Status is CRITICAL\n");
75 break;
76 default:
77 printf ("Status is UNKNOWN\n");
78 result = STATE_UNKNOWN;
79 }
80
81 return result;
82}
83
84void
85print_help (char *cmd)
86{
87 print_revision (cmd, "$Revision$");
88 printf ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n"
89 "License: GPL\n\n");
90 print_usage (cmd);
91 printf
92 ("\nThis plugin will simply return the state corresponding to the numeric value\n"
93 "of the <state> argument.\n");
94}
95
96void
97print_usage (char *cmd)
98{
99 printf ("Usage: %s <integer state>\n", cmd);
100}
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
new file mode 100644
index 00000000..f6531a54
--- /dev/null
+++ b/plugins/check_fping.c
@@ -0,0 +1,386 @@
1/******************************************************************************
2*
3* CHECK_FPING.C
4*
5* Program: Fping plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
8* $Id$
9*
10* Modifications:
11*
12* 08-24-1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
13* Intial Coding
14* 09-11-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
15* Change to spopen
16* Fix so that state unknown is returned by default
17* (formerly would give state ok if no fping specified)
18* Add server_name to output
19* Reformat to 80-character standard screen
20* 11-18-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
21* set STATE_WARNING of stderr written or nonzero status returned
22*
23* Description:
24*
25* This plugin will use the /bin/fping command (form saint) to ping
26* the specified host for a fast check if the host is alive. Note that
27* it is necessary to set the suid flag on fping.
28******************************************************************************/
29
30#include "config.h"
31#include "common.h"
32#include "popen.h"
33#include "utils.h"
34
35#define PROGNAME "check_fping"
36#define PACKET_COUNT 1
37#define PACKET_SIZE 56
38#define UNKNOWN_PACKET_LOSS 200 /* 200% */
39#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
40
41#define PL 0
42#define RTA 1
43
44int textscan (char *buf);
45int process_arguments (int, char **);
46int get_threshold (char *arg, char *rv[2]);
47void print_usage (void);
48void print_help (void);
49
50char *server_name = NULL;
51int cpl = UNKNOWN_PACKET_LOSS;
52int wpl = UNKNOWN_PACKET_LOSS;
53double crta = UNKNOWN_TRIP_TIME;
54double wrta = UNKNOWN_TRIP_TIME;
55int packet_size = PACKET_SIZE;
56int packet_count = PACKET_COUNT;
57int verbose = FALSE;
58
59int
60main (int argc, char **argv)
61{
62 int status = STATE_UNKNOWN;
63 char *server = NULL;
64 char *command_line = NULL;
65 char *input_buffer = NULL;
66 input_buffer = malloc (MAX_INPUT_BUFFER);
67
68 if (process_arguments (argc, argv) == ERROR)
69 usage ("Could not parse arguments\n");
70
71 server = strscpy (server, server_name);
72
73 /* compose the command */
74 command_line = ssprintf
75 (command_line, "%s -b %d -c %d %s",
76 PATH_TO_FPING, packet_size, packet_count, server);
77
78 if (verbose)
79 printf ("%s\n", command_line);
80
81 /* run the command */
82 child_process = spopen (command_line);
83 if (child_process == NULL) {
84 printf ("Unable to open pipe: %s\n", command_line);
85 return STATE_UNKNOWN;
86 }
87
88 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
89 if (child_stderr == NULL) {
90 printf ("Could not open stderr for %s\n", command_line);
91 }
92
93 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
94 if (verbose)
95 printf ("%s", input_buffer);
96 status = max (status, textscan (input_buffer));
97 }
98
99 /* If we get anything on STDERR, at least set warning */
100 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
101 status = max (status, STATE_WARNING);
102 if (verbose)
103 printf ("%s", input_buffer);
104 status = max (status, textscan (input_buffer));
105 }
106 (void) fclose (child_stderr);
107
108 /* close the pipe */
109 if (spclose (child_process))
110 status = max (status, STATE_WARNING);
111
112 printf ("FPING %s - %s\n", state_text (status), server_name);
113
114 return status;
115}
116
117
118
119
120int
121textscan (char *buf)
122{
123 char *rtastr = NULL;
124 char *losstr = NULL;
125 double loss;
126 double rta;
127 int status = STATE_UNKNOWN;
128
129 if (strstr (buf, "not found")) {
130 terminate (STATE_CRITICAL, "FPING unknown - %s not found\n", server_name);
131
132 }
133 else if (strstr (buf, "is unreachable") || strstr (buf, "Unreachable")) {
134 terminate (STATE_CRITICAL, "FPING critical - %s is unreachable\n",
135 "host");
136
137 }
138 else if (strstr (buf, "is down")) {
139 terminate (STATE_CRITICAL, "FPING critical - %s is down\n", server_name);
140
141 }
142 else if (strstr (buf, "is alive")) {
143 status = STATE_OK;
144
145 }
146 else if (strstr (buf, "xmt/rcv/%loss") && strstr (buf, "min/avg/max")) {
147 losstr = strstr (buf, "=");
148 losstr = 1 + strstr (losstr, "/");
149 losstr = 1 + strstr (losstr, "/");
150 rtastr = strstr (buf, "min/avg/max");
151 rtastr = strstr (rtastr, "=");
152 rtastr = 1 + index (rtastr, '/');
153 loss = strtod (losstr, NULL);
154 rta = strtod (rtastr, NULL);
155 if (cpl != UNKNOWN_PACKET_LOSS && loss > cpl)
156 status = STATE_CRITICAL;
157 else if (crta != UNKNOWN_TRIP_TIME && rta > crta)
158 status = STATE_CRITICAL;
159 else if (wpl != UNKNOWN_PACKET_LOSS && loss > wpl)
160 status = STATE_WARNING;
161 else if (wrta != UNKNOWN_TRIP_TIME && rta > wrta)
162 status = STATE_WARNING;
163 else
164 status = STATE_OK;
165 terminate (status, "FPING %s - %s (loss=%f%%, rta=%f ms)\n",
166 state_text (status), server_name, loss, rta);
167
168 }
169 else {
170 status = max (status, STATE_WARNING);
171 }
172
173 return status;
174}
175
176
177
178
179/* process command-line arguments */
180int
181process_arguments (int argc, char **argv)
182{
183 int c;
184 char *rv[2];
185
186#ifdef HAVE_GETOPT_H
187 int option_index = 0;
188 static struct option long_options[] = {
189 {"hostname", required_argument, 0, 'H'},
190 {"critical", required_argument, 0, 'c'},
191 {"warning", required_argument, 0, 'w'},
192 {"bytes", required_argument, 0, 'b'},
193 {"number", required_argument, 0, 'n'},
194 {"verbose", no_argument, 0, 'v'},
195 {"version", no_argument, 0, 'V'},
196 {"help", no_argument, 0, 'h'},
197 {0, 0, 0, 0}
198 };
199#endif
200
201 rv[PL] = NULL;
202 rv[RTA] = NULL;
203
204 if (argc < 2)
205 return ERROR;
206
207 if (!is_option (argv[1])) {
208 server_name = argv[1];
209 argv[1] = argv[0];
210 argv = &argv[1];
211 argc--;
212 }
213
214 while (1) {
215#ifdef HAVE_GETOPT_H
216 c =
217 getopt_long (argc, argv, "+hVvH:c:w:b:n:", long_options, &option_index);
218#else
219 c = getopt (argc, argv, "+hVvH:c:w:b:n:");
220#endif
221
222 if (c == -1 || c == EOF || c == 1)
223 break;
224
225 switch (c) {
226 case '?': /* print short usage statement if args not parsable */
227 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
228 print_usage ();
229 exit (STATE_UNKNOWN);
230 case 'h': /* help */
231 print_help ();
232 exit (STATE_OK);
233 case 'V': /* version */
234 print_revision (my_basename (argv[0]), "$Revision$");
235 exit (STATE_OK);
236 case 'v': /* verbose mode */
237 verbose = TRUE;
238 break;
239 case 'H': /* hostname */
240 if (is_host (optarg) == FALSE) {
241 printf ("Invalid host name/address\n\n");
242 print_usage ();
243 exit (STATE_UNKNOWN);
244 }
245 server_name = strscpy (server_name, optarg);
246 break;
247 case 'c':
248 get_threshold (optarg, rv);
249 if (rv[RTA]) {
250 crta = strtod (rv[RTA], NULL);
251 rv[RTA] = NULL;
252 }
253 if (rv[PL]) {
254 cpl = atoi (rv[PL]);
255 rv[PL] = NULL;
256 }
257 break;
258 case 'w':
259 get_threshold (optarg, rv);
260 if (rv[RTA]) {
261 wrta = strtod (rv[RTA], NULL);
262 rv[RTA] = NULL;
263 }
264 if (rv[PL]) {
265 wpl = atoi (rv[PL]);
266 rv[PL] = NULL;
267 }
268 break;
269 case 'b': /* bytes per packet */
270 if (is_intpos (optarg))
271 packet_size = atoi (optarg);
272 else
273 usage ("Packet size must be a positive integer");
274 break;
275 case 'n': /* number of packets */
276 if (is_intpos (optarg))
277 packet_count = atoi (optarg);
278 else
279 usage ("Packet count must be a positive integer");
280 break;
281 }
282 }
283
284
285 if (server_name == NULL)
286 usage ("Host name was not supplied\n\n");
287
288 return OK;
289}
290
291
292
293
294
295int
296get_threshold (char *arg, char *rv[2])
297{
298 char *arg1 = NULL;
299 char *arg2 = NULL;
300
301 arg1 = strscpy (arg1, arg);
302 if (strpbrk (arg1, ",:"))
303 arg2 = 1 + strpbrk (arg1, ",:");
304
305 if (arg2) {
306 arg1[strcspn (arg1, ",:")] = 0;
307 if (strstr (arg1, "%") && strstr (arg2, "%"))
308 terminate (STATE_UNKNOWN,
309 "%s: Only one threshold may be packet loss (%s)\n", PROGNAME,
310 arg);
311 if (!strstr (arg1, "%") && !strstr (arg2, "%"))
312 terminate (STATE_UNKNOWN,
313 "%s: Only one threshold must be packet loss (%s)\n",
314 PROGNAME, arg);
315 }
316
317 if (arg2 && strstr (arg2, "%")) {
318 rv[PL] = arg2;
319 rv[RTA] = arg1;
320 }
321 else if (arg2) {
322 rv[PL] = arg1;
323 rv[RTA] = arg2;
324 }
325 else if (strstr (arg1, "%")) {
326 rv[PL] = arg1;
327 }
328 else {
329 rv[RTA] = arg1;
330 }
331
332 return OK;
333}
334
335
336
337
338
339void
340print_usage (void)
341{
342 printf ("Usage: %s <host_address>\n", PROGNAME);
343}
344
345
346
347
348
349void
350print_help (void)
351{
352
353 print_revision (PROGNAME, "$Revision$");
354
355 printf
356 ("Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)\n\n"
357 "This plugin will use the /bin/fping command (from saint) to ping the\n"
358 "specified host for a fast check if the host is alive. Note that it is\n"
359 "necessary to set the suid flag on fping.\n\n");
360
361 print_usage ();
362
363 printf
364 ("\nOptions:\n"
365 "-H, --hostname=HOST\n"
366 " Name or IP Address of host to ping (IP Address bypasses name lookup,\n"
367 " reducing system load)\n"
368 "-w, --warning=THRESHOLD\n"
369 " warning threshold pair\n"
370 "-c, --critical=THRESHOLD\n"
371 " critical threshold pair\n"
372 "-b, --bytes=INTEGER\n"
373 " Size of ICMP packet (default: %d)\n"
374 "-n, --number=INTEGER\n"
375 " Number of ICMP packets to send (default: %d)\n"
376 "-v, --verbose\n"
377 " Show details for command-line debugging (do not use with nagios server)\n"
378 "-h, --help\n"
379 " Print this help screen\n"
380 "-V, --version\n"
381 " Print version information\n"
382 "THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel\n"
383 "time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the\n"
384 "percentage of packet loss to trigger an alarm state.\n",
385 PACKET_SIZE, PACKET_COUNT);
386}
diff --git a/plugins/check_ftp.c b/plugins/check_ftp.c
new file mode 100644
index 00000000..1c65d642
--- /dev/null
+++ b/plugins/check_ftp.c
@@ -0,0 +1,337 @@
1/******************************************************************************
2 *
3 * CHECK_FTP.C
4 *
5 * Program: FTP plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 *
9 * $Id$
10 *
11 * Description:
12 *
13 * This plugin will attempt to open an FTP connection with the host.
14 * Successul connects return STATE_OK, refusals and timeouts return
15 * STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful
16 * connects, but incorrect reponse messages from the host result in
17 * STATE_WARNING return values.
18 *
19 * License Information:
20 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 *
35 *****************************************************************************/
36
37#include "config.h"
38#include "common.h"
39#include "netutils.h"
40#include "utils.h"
41
42#define PROGNAME "check_ftp"
43
44#define FTP_PORT 21
45#define FTP_EXPECT "220"
46#define FTP_QUIT "QUIT\n"
47
48int process_arguments (int, char **);
49int call_getopt (int, char **);
50void print_usage (void);
51void print_help (void);
52
53time_t start_time, end_time;
54int server_port = FTP_PORT;
55char *server_address = NULL;
56char *server_expect = NULL;
57int warning_time = 0;
58int check_warning_time = FALSE;
59int critical_time = 0;
60int check_critical_time = FALSE;
61int verbose = FALSE;
62
63
64int
65main (int argc, char **argv)
66{
67 int sd;
68 int result;
69 char buffer[MAX_INPUT_BUFFER];
70
71 if (process_arguments (argc, argv) == ERROR)
72 usage ("Could not parse arguments\n");
73
74 /* initialize alarm signal handling */
75 signal (SIGALRM, socket_timeout_alarm_handler);
76
77 /* set socket timeout */
78 alarm (socket_timeout);
79
80 /* try to connect to the host at the given port number */
81 time (&start_time);
82 result = my_tcp_connect (server_address, server_port, &sd);
83
84 /* we connected, so close connection before exiting */
85 if (result == STATE_OK) {
86
87 /* watch for the FTP connection string */
88 result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
89
90 /* strip the buffer of carriage returns */
91 strip (buffer);
92
93 /* return a WARNING status if we couldn't read any data */
94 if (result == -1) {
95 printf ("recv() failed\n");
96 result = STATE_WARNING;
97 }
98
99 else {
100
101 /* make sure we find the response we are looking for */
102 if (!strstr (buffer, server_expect)) {
103
104 if (server_port == FTP_PORT)
105 printf ("Invalid FTP response received from host\n");
106 else
107 printf ("Invalid FTP response received from host on port %d\n",
108 server_port);
109 result = STATE_WARNING;
110 }
111
112 else {
113 time (&end_time);
114
115 result = STATE_OK;
116
117 if (check_critical_time == TRUE
118 && (end_time - start_time) > critical_time) result =
119 STATE_CRITICAL;
120 else if (check_warning_time == TRUE
121 && (end_time - start_time) > warning_time) result =
122 STATE_WARNING;
123
124 if (verbose == TRUE)
125 printf ("FTP %s - %d sec. response time, %s\n",
126 (result == STATE_OK) ? "ok" : "problem",
127 (int) (end_time - start_time), buffer);
128 else
129 printf ("FTP %s - %d second response time\n",
130 (result == STATE_OK) ? "ok" : "problem",
131 (int) (end_time - start_time));
132 }
133 }
134
135 /* close the connection */
136 send (sd, FTP_QUIT, strlen (FTP_QUIT), 0);
137 close (sd);
138 }
139
140 /* reset the alarm */
141 alarm (0);
142
143 return result;
144}
145
146
147
148
149
150
151/* process command-line arguments */
152int
153process_arguments (int argc, char **argv)
154{
155 int c;
156
157 if (argc < 2)
158 usage ("\n");
159
160 for (c = 1; c < argc; c++) {
161 if (strcmp ("-to", argv[c]) == 0)
162 strcpy (argv[c], "-t");
163 else if (strcmp ("-wt", argv[c]) == 0)
164 strcpy (argv[c], "-w");
165 else if (strcmp ("-ct", argv[c]) == 0)
166 strcpy (argv[c], "-c");
167 }
168
169 c = 0;
170 while ((c += call_getopt (argc - c, &argv[c])) < argc) {
171
172 if (is_option (argv[c]))
173 continue;
174
175 if (server_address == NULL) {
176 if (argc > c) {
177 if (is_host (argv[c]) == FALSE)
178 usage ("Invalid host name/address\n");
179 server_address = argv[c];
180 }
181 else {
182 usage ("Host name was not supplied\n");
183 }
184 }
185 }
186
187 if (server_expect == NULL)
188 server_expect = strscpy (NULL, FTP_EXPECT);
189
190 return OK;
191}
192
193
194
195
196
197int
198call_getopt (int argc, char **argv)
199{
200 int c, i = 0;
201
202#ifdef HAVE_GETOPT_H
203 int option_index = 0;
204 static struct option long_options[] = {
205 {"hostname", required_argument, 0, 'H'},
206 {"expect", required_argument, 0, 'e'},
207 {"critical", required_argument, 0, 'c'},
208 {"warning", required_argument, 0, 'w'},
209 {"timeout", required_argument, 0, 'w'},
210 {"port", required_argument, 0, 'p'},
211 {"verbose", no_argument, 0, 'v'},
212 {"version", no_argument, 0, 'V'},
213 {"help", no_argument, 0, 'h'},
214 {0, 0, 0, 0}
215 };
216#endif
217
218 while (1) {
219#ifdef HAVE_GETOPT_H
220 c =
221 getopt_long (argc, argv, "+hVvH:e:c:w:t:p:", long_options,
222 &option_index);
223#else
224 c = getopt (argc, argv, "+hVvH:e:c:w:t:p:");
225#endif
226
227 i++;
228
229 if (c == -1 || c == EOF || c == 1)
230 break;
231
232 switch (c) {
233 case 'H':
234 case 'e':
235 case 'c':
236 case 'w':
237 case 't':
238 case 'p':
239 i++;
240 }
241
242 switch (c) {
243 case '?': /* print short usage statement if args not parsable */
244 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
245 print_usage ();
246 exit (STATE_UNKNOWN);
247 case 'h': /* help */
248 print_help ();
249 exit (STATE_OK);
250 case 'V': /* version */
251 print_revision (my_basename (argv[0]), "$Revision$");
252 exit (STATE_OK);
253 case 'v': /* verbose mode */
254 verbose = TRUE;
255 break;
256 case 'H': /* hostname */
257 if (is_host (optarg) == FALSE)
258 usage ("Invalid host name/address\n");
259 server_address = optarg;
260 break;
261 case 'e': /* expect */
262 server_expect = optarg;
263 break;
264 case 'c': /* critical */
265 if (!is_intnonneg (optarg))
266 usage ("Critical threshold must be a nonnegative integer\n");
267 critical_time = atoi (optarg);
268 check_critical_time = TRUE;
269 break;
270 case 'w': /* warning */
271 if (!is_intnonneg (optarg))
272 usage ("Warning threshold must be a nonnegative integer\n");
273 warning_time = atoi (optarg);
274 check_warning_time = TRUE;
275 break;
276 case 't': /* timeout */
277 if (!is_intnonneg (optarg))
278 usage ("Timeout interval must be a nonnegative integer\n");
279 socket_timeout = atoi (optarg);
280 break;
281 case 'p': /* port */
282 if (!is_intnonneg (optarg))
283 usage ("Serevr port must be a nonnegative integer\n");
284 server_port = atoi (optarg);
285 break;
286 }
287 }
288 return i;
289}
290
291
292
293
294
295void
296print_usage (void)
297{
298 printf
299 ("Usage: %s -H <host_address> [-e expect] [-p port] [-w warn_time]\n"
300 " [-c crit_time] [-t to_sec] [-v]\n", PROGNAME);
301}
302
303
304
305
306
307void
308print_help (void)
309{
310 print_revision (PROGNAME, "$Revision$");
311 printf
312 ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n\n"
313 "This plugin tests an FTP connection with the specified host.\n\n");
314 print_usage ();
315 printf
316 ("Options:\n"
317 " -H, --hostname=ADDRESS\n"
318 " Host name argument for servers using host headers (use numeric\n"
319 " address if possible to bypass DNS lookup).\n"
320 " -e, --expect=STRING\n"
321 " String to expect in first line of server response (default: %s)\n"
322 " -p, --port=INTEGER\n"
323 " Port number (default: %d)\n"
324 " -w, --warning=INTEGER\n"
325 " Response time to result in warning status (seconds)\n"
326 " -c, --critical=INTEGER\n"
327 " Response time to result in critical status (seconds)\n"
328 " -t, --timeout=INTEGER\n"
329 " Seconds before connection times out (default: %d)\n"
330 " -v"
331 " Show details for command-line debugging (do not use with nagios server)\n"
332 " -h, --help\n"
333 " Print detailed help screen\n"
334 " -V, --version\n"
335 " Print version information\n",
336 FTP_EXPECT, FTP_PORT, DEFAULT_SOCKET_TIMEOUT);
337}
diff --git a/plugins/check_game.c b/plugins/check_game.c
new file mode 100644
index 00000000..63d1be62
--- /dev/null
+++ b/plugins/check_game.c
@@ -0,0 +1,287 @@
1/******************************************************************************
2 *
3 * CHECK_GAME.C
4 *
5 * Program: GAME plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ian Cass (ian@knowledge.com)
8 *
9 * Last Modified: $Date$
10 *
11 * Mod History
12 *
13 * 25-8-99 Ethan Galstad <nagios@nagios.org>
14 * Integrated with common plugin code, minor cleanup stuff
15 *
16 * 17-8-99 version 1.1b
17 *
18 * 17-8-99 make port a separate argument so we can use something like
19 * check_game q2s!27910 with the probe set up as
20 * check_game $ARG1$ $HOSTADDRESS$ $ARG2$
21 *
22 * 17-8-99 Put in sanity check for ppl who enter the wrong server type
23 *
24 * 17-8-99 Release version 1.0b
25 *
26 * Command line: CHECK_GAME <server type> <ip_address> [port]
27 *
28 * server type = a server type that qstat understands (type qstat & look at the -default line)
29 * ip_address = either a dotted address or a FQD name
30 * port = defaults game default port
31 *
32 *
33 * Description:
34 *
35 * Needed to explore writing my own probes for nagios. It looked
36 * pretty simple so I thought I'd write one for monitoring the status
37 * of game servers. It uses qstat to do the actual monitoring and
38 * analyses the result. Doing it this way means I can support all the
39 * servers that qstat does and will do in the future.
40 *
41 *
42 * Dependencies:
43 *
44 * This plugin uses the 'qstat' command If you don't
45 * have the package installed you will need to download it from
46 * http://www.activesw.com/people/steve/qstat.html or any popular files archive
47 * before you can use this plugin.
48 *
49 * License Information:
50 *
51 * This program is free software; you can redistribute it and/or modify
52 * it under the terms of the GNU General Public License as published by
53 * the Free Software Foundation; either version 2 of the License, or
54 * (at your option) any later version.
55 *
56 * This program is distributed in the hope that it will be useful,
57 * but WITHOUT ANY WARRANTY; without even the implied warranty of
58 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59 * GNU General Public License for more details.
60 *
61 * You should have received a copy of the GNU General Public License
62 * along with this program; if not, write to the Free Software
63 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
64 *
65 *****************************************************************************/
66
67#include "config.h"
68#include "common.h"
69#include "utils.h"
70
71int process_arguments (int, char **);
72
73#define QSTAT_DATA_DELIMITER ","
74
75#define QSTAT_HOST_ERROR "ERROR"
76#define QSTAT_HOST_DOWN "DOWN"
77#define QSTAT_HOST_TIMEOUT "TIMEOUT"
78#define QSTAT_MAX_RETURN_ARGS 12
79
80char server_ip[MAX_HOST_ADDRESS_LENGTH];
81char game_type[MAX_INPUT_BUFFER];
82char port[MAX_INPUT_BUFFER];
83
84int qstat_game_field = 2;
85int qstat_map_field = 3;
86int qstat_ping_field = 5;
87
88
89int
90main (int argc, char **argv)
91{
92 char command_line[MAX_INPUT_BUFFER];
93 int result;
94 FILE *fp;
95 char input_buffer[MAX_INPUT_BUFFER];
96 char response[MAX_INPUT_BUFFER];
97 char *temp_ptr;
98 int found;
99 char *p, *ret[QSTAT_MAX_RETURN_ARGS];
100 int i;
101
102 result = process_arguments (argc, argv);
103
104 if (result != OK) {
105 printf ("Incorrect arguments supplied\n");
106 printf ("\n");
107 print_revision (argv[0], "$Revision$");
108 printf ("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n");
109 printf ("License: GPL\n");
110 printf ("\n");
111 printf
112 ("Usage: %s <game> <ip_address> [-p port] [-gf game_field] [-mf map_field] [-pf ping_field]\n",
113 argv[0]);
114 printf ("\n");
115 printf ("Options:\n");
116 printf
117 (" <game> = Game type that is recognised by qstat (without the leading dash)\n");
118 printf
119 (" <ip_address> = The IP address of the device you wish to query\n");
120 printf (" [port] = Optional port of which to connect\n");
121 printf
122 (" [game_field] = Field number in raw qstat output that contains game name\n");
123 printf
124 (" [map_field] = Field number in raw qstat output that contains map name\n");
125 printf
126 (" [ping_field] = Field number in raw qstat output that contains ping time\n");
127 printf ("\n");
128 printf ("Notes:\n");
129 printf
130 ("- This plugin uses the 'qstat' command, the popular game server status query tool .\n");
131 printf
132 (" If you don't have the package installed, you will need to download it from\n");
133 printf
134 (" http://www.activesw.com/people/steve/qstat.html before you can use this plugin.\n");
135 printf ("\n");
136 return STATE_UNKNOWN;
137 }
138
139 result = STATE_OK;
140
141 /* create the command line to execute */
142 snprintf (command_line, sizeof (command_line) - 1, "%s -raw %s -%s %s%s",
143 PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip, port);
144 command_line[sizeof (command_line) - 1] = 0;
145
146 /* run the command */
147 fp = popen (command_line, "r");
148 if (fp == NULL) {
149 printf ("Error - Could not open pipe: %s\n", command_line);
150 return STATE_UNKNOWN;
151 }
152
153 found = 0;
154 fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp); /* Only interested in the first line */
155
156 /* strip the newline character from the end of the input */
157 input_buffer[strlen (input_buffer) - 1] = 0;
158
159 /* sanity check */
160 /* was thinking about running qstat without any options, capturing the
161 -default line, parsing it & making an array of all know server types
162 but thought this would be too much hassle considering this is a tool
163 for intelligent sysadmins (ha). Could put a static array of known
164 server types in a header file but then we'd be limiting ourselves
165
166 In the end, I figured I'd simply let an error occur & then trap it
167 */
168
169 if (!strncmp (input_buffer, "unknown option", 14)) {
170 printf ("ERROR: Host type parameter incorrect!\n");
171 result = STATE_CRITICAL;
172 return result;
173 }
174
175 /* initialize the returned data buffer */
176 for (i = 0; i < QSTAT_MAX_RETURN_ARGS; i++)
177 ret[i] = "";
178
179 i = 0;
180 p = (char *) strtok (input_buffer, QSTAT_DATA_DELIMITER);
181 while (p != NULL) {
182 ret[i] = p;
183 p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER);
184 i++;
185 if (i >= QSTAT_MAX_RETURN_ARGS)
186 break;
187 }
188
189 if (strstr (ret[2], QSTAT_HOST_ERROR)) {
190 printf ("ERROR: Host not found\n");
191 result = STATE_CRITICAL;
192 }
193 else if (strstr (ret[2], QSTAT_HOST_DOWN)) {
194 printf ("ERROR: Game server down or unavailable\n");
195 result = STATE_CRITICAL;
196 }
197 else if (strstr (ret[2], QSTAT_HOST_TIMEOUT)) {
198 printf ("ERROR: Game server timeout\n");
199 result = STATE_CRITICAL;
200 }
201 else {
202 printf ("OK: %s (%s), Ping: %s ms\n", ret[qstat_game_field],
203 ret[qstat_map_field], ret[qstat_ping_field]);
204 }
205
206 /* close the pipe */
207 pclose (fp);
208
209 return result;
210}
211
212
213
214int
215process_arguments (int argc, char **argv)
216{
217 int x;
218
219 /* not enough options were supplied */
220 if (argc < 3)
221 return ERROR;
222
223 /* first option is always the game type */
224 strncpy (game_type, argv[1], sizeof (game_type) - 1);
225 game_type[sizeof (game_type) - 1] = 0;
226
227 /* Second option is always the server name */
228 strncpy (server_ip, argv[2], sizeof (server_ip) - 1);
229 server_ip[sizeof (server_ip) - 1] = 0;
230
231 /* process all remaining arguments */
232 for (x = 4; x <= argc; x++) {
233
234 /* we got the port number to connect to */
235 if (!strcmp (argv[x - 1], "-p")) {
236 if (x < argc) {
237 snprintf (port, sizeof (port) - 2, ":%s", argv[x]);
238 port[sizeof (port) - 1] = 0;
239 x++;
240 }
241 else
242 return ERROR;
243 }
244
245 /* we got the game field */
246 else if (!strcmp (argv[x - 1], "-gf")) {
247 if (x < argc) {
248 qstat_game_field = atoi (argv[x]);
249 if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS)
250 return ERROR;
251 x++;
252 }
253 else
254 return ERROR;
255 }
256
257 /* we got the map field */
258 else if (!strcmp (argv[x - 1], "-mf")) {
259 if (x < argc) {
260 qstat_map_field = atoi (argv[x]);
261 if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS)
262 return ERROR;
263 x++;
264 }
265 else
266 return ERROR;
267 }
268
269 /* we got the ping field */
270 else if (!strcmp (argv[x - 1], "-pf")) {
271 if (x < argc) {
272 qstat_ping_field = atoi (argv[x]);
273 if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS)
274 return ERROR;
275 x++;
276 }
277 else
278 return ERROR;
279 }
280
281 /* else we got something else... */
282 else
283 return ERROR;
284 }
285
286 return OK;
287}
diff --git a/plugins/check_hpjd.c b/plugins/check_hpjd.c
new file mode 100644
index 00000000..8234abdf
--- /dev/null
+++ b/plugins/check_hpjd.c
@@ -0,0 +1,571 @@
1/******************************************************************************
2*
3* CHECK_HPJD.C
4*
5* Program: HP printer plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8*
9* Last Modified: $Date$
10*
11* Command line: CHECK_HPJD <ip_address> [community]
12*
13* Description:
14*
15* This plugin will attempt to check the status of an HP printer. The
16* printer must have a JetDirect card installed and TCP/IP protocol
17* stack enabled. This plugin has only been tested on a few printers
18* and may not work well on all models of JetDirect cards. Multiple
19* port JetDirect devices must have an IP address assigned to each
20* port in order to be monitored.
21*
22* Dependencies:
23*
24* This plugin used the 'snmpget' command included with the UCD-SNMP
25* package. If you don't have the package installed you will need to
26* download it from http://ucd-snmp.ucdavis.edu before you can use
27* this plugin.
28*
29* Return Values:
30*
31* UNKNOWN = The plugin could not read/process the output from the printer
32* OK = Printer looks normal
33* WARNING = Low toner, paper jam, intervention required, paper out, etc.
34* CRITICAL = The printer could not be reached (it's probably turned off)
35*
36* Acknowledgements:
37*
38* The idea for the plugin (as well as some code) were taken from Jim
39* Trocki's pinter alert script in his "mon" utility, found at
40* http://www.kernel.org/software/mon
41*
42* Notes:
43* 'JetDirect' is copyrighted by Hewlett-Packard.
44* HP, please don't sue me... :-)
45*
46* License Information:
47*
48* This program is free software; you can redistribute it and/or modify
49* it under the terms of the GNU General Public License as published by
50* the Free Software Foundation; either version 2 of the License, or
51* (at your option) any later version.
52*
53* This program is distributed in the hope that it will be useful,
54* but WITHOUT ANY WARRANTY; without even the implied warranty of
55* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
56* GNU General Public License for more details.
57*
58* You should have received a copy of the GNU General Public License
59* along with this program; if not, write to the Free Software
60* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
61*
62*****************************************************************************/
63
64#include "common.h"
65#include "popen.h"
66#include "utils.h"
67
68#define PROGNAME "check_hpjd"
69
70#define HPJD_LINE_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.1"
71#define HPJD_PAPER_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.2"
72#define HPJD_INTERVENTION_REQUIRED ".1.3.6.1.4.1.11.2.3.9.1.1.2.3"
73#define HPJD_GD_PERIPHERAL_ERROR ".1.3.6.1.4.1.11.2.3.9.1.1.2.6"
74#define HPJD_GD_PAPER_JAM ".1.3.6.1.4.1.11.2.3.9.1.1.2.8"
75#define HPJD_GD_PAPER_OUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.9"
76#define HPJD_GD_TONER_LOW ".1.3.6.1.4.1.11.2.3.9.1.1.2.10"
77#define HPJD_GD_PAGE_PUNT ".1.3.6.1.4.1.11.2.3.9.1.1.2.11"
78#define HPJD_GD_MEMORY_OUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.12"
79#define HPJD_GD_DOOR_OPEN ".1.3.6.1.4.1.11.2.3.9.1.1.2.17"
80#define HPJD_GD_PAPER_OUTPUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.19"
81#define HPJD_GD_STATUS_DISPLAY ".1.3.6.1.4.1.11.2.3.9.1.1.3"
82
83#define ONLINE 0
84#define OFFLINE 1
85
86int process_arguments (int, char **);
87int call_getopt (int, char **);
88int validate_arguments (void);
89void print_help (void);
90void print_usage (void);
91
92char *community = NULL;
93char *address = NULL;
94
95int
96main (int argc, char **argv)
97{
98 char command_line[1024];
99 int result;
100 int line;
101 char input_buffer[MAX_INPUT_BUFFER];
102 char query_string[512];
103 char error_message[MAX_INPUT_BUFFER];
104 char *temp_buffer;
105 int line_status = ONLINE;
106 int paper_status = 0;
107 int intervention_required = 0;
108 int peripheral_error = 0;
109 int paper_jam = 0;
110 int paper_out = 0;
111 int toner_low = 0;
112 int page_punt = 0;
113 int memory_out = 0;
114 int door_open = 0;
115 int paper_output = 0;
116 char display_message[MAX_INPUT_BUFFER];
117
118 if (process_arguments (argc, argv) != OK)
119 usage ("Invalid command arguments supplied\n");
120
121 /* removed ' 2>1' at end of command 10/27/1999 - EG */
122 /* create the query string */
123 sprintf
124 (query_string,
125 "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0",
126 HPJD_LINE_STATUS,
127 HPJD_PAPER_STATUS,
128 HPJD_INTERVENTION_REQUIRED,
129 HPJD_GD_PERIPHERAL_ERROR,
130 HPJD_GD_PAPER_JAM,
131 HPJD_GD_PAPER_OUT,
132 HPJD_GD_TONER_LOW,
133 HPJD_GD_PAGE_PUNT,
134 HPJD_GD_MEMORY_OUT,
135 HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY);
136
137 /* get the command to run */
138 sprintf (command_line, "%s -v 1 %s %s %s", PATH_TO_SNMPGET, address,
139 community, query_string);
140
141 /* run the command */
142 child_process = spopen (command_line);
143 if (child_process == NULL) {
144 printf ("Could not open pipe: %s\n", command_line);
145 return STATE_UNKNOWN;
146 }
147
148 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
149 if (child_stderr == NULL) {
150 printf ("Could not open stderr for %s\n", command_line);
151 }
152
153 result = STATE_OK;
154
155 line = 0;
156 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
157
158 /* strip the newline character from the end of the input */
159 if (input_buffer[strlen (input_buffer) - 1] == '\n')
160 input_buffer[strlen (input_buffer) - 1] = 0;
161
162 line++;
163
164 temp_buffer = strtok (input_buffer, "=");
165 temp_buffer = strtok (NULL, "=");
166
167 switch (line) {
168
169 case 1: /* 1st line should contain the line status */
170 if (temp_buffer != NULL)
171 line_status = atoi (temp_buffer);
172 else {
173 result = STATE_UNKNOWN;
174 strcpy (error_message, input_buffer);
175 }
176 break;
177
178 case 2: /* 2nd line should contain the paper status */
179 if (temp_buffer != NULL)
180 paper_status = atoi (temp_buffer);
181 else {
182 result = STATE_UNKNOWN;
183 strcpy (error_message, input_buffer);
184 }
185 break;
186
187 case 3: /* 3rd line should be intervention required */
188 if (temp_buffer != NULL)
189 intervention_required = atoi (temp_buffer);
190 else {
191 result = STATE_UNKNOWN;
192 strcpy (error_message, input_buffer);
193 }
194 break;
195
196 case 4: /* 4th line should be peripheral error */
197 if (temp_buffer != NULL)
198 peripheral_error = atoi (temp_buffer);
199 else {
200 result = STATE_UNKNOWN;
201 strcpy (error_message, input_buffer);
202 }
203 break;
204
205 case 5: /* 5th line should contain the paper jam status */
206 if (temp_buffer != NULL)
207 paper_jam = atoi (temp_buffer);
208 else {
209 result = STATE_UNKNOWN;
210 strcpy (error_message, input_buffer);
211 }
212 break;
213
214 case 6: /* 6th line should contain the paper out status */
215 if (temp_buffer != NULL)
216 paper_out = atoi (temp_buffer);
217 else {
218 result = STATE_UNKNOWN;
219 strcpy (error_message, input_buffer);
220 }
221 break;
222
223 case 7: /* 7th line should contain the toner low status */
224 if (temp_buffer != NULL)
225 toner_low = atoi (temp_buffer);
226 else {
227 result = STATE_UNKNOWN;
228 strcpy (error_message, input_buffer);
229 }
230 break;
231
232 case 8: /* did data come too slow for engine */
233 if (temp_buffer != NULL)
234 page_punt = atoi (temp_buffer);
235 else {
236 result = STATE_UNKNOWN;
237 strcpy (error_message, input_buffer);
238 }
239 break;
240
241 case 9: /* did we run out of memory */
242 if (temp_buffer != NULL)
243 memory_out = atoi (temp_buffer);
244 else {
245 result = STATE_UNKNOWN;
246 strcpy (error_message, input_buffer);
247 }
248 break;
249
250 case 10: /* is there a door open */
251 if (temp_buffer != NULL)
252 door_open = atoi (temp_buffer);
253 else {
254 result = STATE_UNKNOWN;
255 strcpy (error_message, input_buffer);
256 }
257 break;
258
259 case 11: /* is output tray full */
260 if (temp_buffer != NULL)
261 paper_output = atoi (temp_buffer);
262 else {
263 result = STATE_UNKNOWN;
264 strcpy (error_message, input_buffer);
265 }
266 break;
267
268 case 12: /* display panel message */
269 if (temp_buffer != NULL)
270 strcpy (display_message, temp_buffer + 1);
271 else {
272 result = STATE_UNKNOWN;
273 strcpy (error_message, input_buffer);
274 }
275 break;
276
277 default:
278 break;
279 }
280
281 /* break out of the read loop if we encounter an error */
282 if (result != STATE_OK)
283 break;
284 }
285
286 /* WARNING if output found on stderr */
287 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
288 result = max (result, STATE_WARNING);
289
290 /* close stderr */
291 (void) fclose (child_stderr);
292
293 /* close the pipe */
294 if (spclose (child_process))
295 result = max (result, STATE_WARNING);
296
297 /* if there wasn't any output, display an error */
298 if (line == 0) {
299
300 /*
301 result=STATE_UNKNOWN;
302 strcpy(error_message,"Error: Could not read plugin output\n");
303 */
304
305 /* might not be the problem, but most likely is.. */
306 result = STATE_UNKNOWN;
307 sprintf (error_message, "Timeout: No response from %s\n", address);
308 }
309
310 /* if we had no read errors, check the printer status results... */
311 if (result == STATE_OK) {
312
313 if (paper_jam) {
314 result = STATE_WARNING;
315 strcpy (error_message, "Paper Jam");
316 }
317 else if (paper_out) {
318 result = STATE_WARNING;
319 strcpy (error_message, "Out of Paper");
320 }
321 else if (line_status == OFFLINE) {
322 if (strcmp (error_message, "POWERSAVE ON") != 0) {
323 result = STATE_WARNING;
324 strcpy (error_message, "Printer Offline");
325 }
326 }
327 else if (peripheral_error) {
328 result = STATE_WARNING;
329 strcpy (error_message, "Peripheral Error");
330 }
331 else if (intervention_required) {
332 result = STATE_WARNING;
333 strcpy (error_message, "Intervention Required");
334 }
335 else if (toner_low) {
336 result = STATE_WARNING;
337 strcpy (error_message, "Toner Low");
338 }
339 else if (memory_out) {
340 result = STATE_WARNING;
341 strcpy (error_message, "Insufficient Memory");
342 }
343 else if (door_open) {
344 result = STATE_WARNING;
345 strcpy (error_message, "A Door is Open");
346 }
347 else if (paper_output) {
348 result = STATE_WARNING;
349 strcpy (error_message, "Output Tray is Full");
350 }
351 else if (page_punt) {
352 result = STATE_WARNING;
353 strcpy (error_message, "Data too Slow for Engine");
354 }
355 else if (paper_status) {
356 result = STATE_WARNING;
357 strcpy (error_message, "Unknown Paper Error");
358 }
359 }
360
361 if (result == STATE_OK)
362 printf ("Printer ok - (%s)\n", display_message);
363
364 else if (result == STATE_UNKNOWN) {
365
366 printf ("%s\n", error_message);
367
368 /* if printer could not be reached, escalate to critical */
369 if (strstr (error_message, "Timeout"))
370 result = STATE_CRITICAL;
371 }
372
373 else if (result == STATE_WARNING)
374 printf ("%s (%s)\n", error_message, display_message);
375
376 return result;
377}
378
379
380
381
382
383/* process command-line arguments */
384int
385process_arguments (int argc, char **argv)
386{
387 int c;
388
389 if (argc < 2)
390 return ERROR;
391
392 for (c = 1; c < argc; c++) {
393 if (strcmp ("-to", argv[c]) == 0)
394 strcpy (argv[c], "-t");
395 else if (strcmp ("-wt", argv[c]) == 0)
396 strcpy (argv[c], "-w");
397 else if (strcmp ("-ct", argv[c]) == 0)
398 strcpy (argv[c], "-c");
399 }
400
401
402
403 c = 0;
404 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
405
406 if (is_option (argv[c]))
407 continue;
408
409 if (address == NULL) {
410 if (is_host (argv[c])) {
411 address = argv[c];
412 }
413 else {
414 usage ("Invalid host name");
415 }
416 }
417 else if (community == NULL) {
418 community = argv[c];
419 }
420 }
421
422 if (address == NULL)
423 address = strscpy (NULL, "127.0.0.1");
424
425 return validate_arguments ();
426}
427
428
429
430
431
432
433int
434call_getopt (int argc, char **argv)
435{
436 int c, i = 0;
437
438#ifdef HAVE_GETOPT_H
439 int option_index = 0;
440 static struct option long_options[] = {
441 {"hostname", required_argument, 0, 'H'},
442 {"expect", required_argument, 0, 'e'},
443/* {"critical", required_argument,0,'c'}, */
444/* {"warning", required_argument,0,'w'}, */
445/* {"port", required_argument,0,'P'}, */
446 {"verbose", no_argument, 0, 'v'},
447 {"version", no_argument, 0, 'V'},
448 {"help", no_argument, 0, 'h'},
449 {0, 0, 0, 0}
450 };
451#endif
452
453 while (1) {
454#ifdef HAVE_GETOPT_H
455 c = getopt_long (argc, argv, "+hVH:C:", long_options, &option_index);
456#else
457 c = getopt (argc, argv, "+?hVH:C:");
458#endif
459
460 i++;
461
462 if (c == -1 || c == EOF || c == 1)
463 break;
464
465 switch (c) {
466 case 'H':
467 case 'C':
468 i++;
469 }
470
471 switch (c) {
472 case 'H': /* hostname */
473 if (is_host (optarg)) {
474 address = optarg;
475 }
476 else {
477 usage ("Invalid host name\n");
478 }
479 break;
480 case 'C': /* community */
481 community = optarg;
482 break;
483 case 'V': /* version */
484 print_revision (PROGNAME, "$Revision$");
485 exit (STATE_OK);
486 case 'h': /* help */
487 print_help ();
488 exit (STATE_OK);
489 case '?': /* help */
490 usage ("Invalid argument\n");
491 }
492 }
493 return i;
494}
495
496
497
498
499
500int
501validate_arguments (void)
502{
503 return OK;
504}
505
506
507
508
509
510void
511print_help (void)
512{
513 print_revision (PROGNAME, "$Revision$");
514 printf
515 ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
516 "This plugin tests the STATUS of an HP printer with a JetDirect card.\n"
517 "Ucd-snmp must be installed on the computer running the plugin.\n\n");
518 print_usage ();
519 printf
520 ("\nOptions:\n"
521 " -H, --hostname=STRING or IPADDRESS\n"
522 " Check server on the indicated host\n"
523 " -C, --community=STRING\n"
524 " The SNMP community name\n"
525 " -h, --help\n"
526 " Print detailed help screen\n"
527 " -V, --version\n" " Print version information\n\n");
528 support ();
529}
530
531
532
533
534
535void
536print_usage (void)
537{
538 printf
539 ("Usage: %s -H host [-C community]\n"
540 " %s --help\n"
541 " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
542}
543
544
545/*
546 if(argc<2||argc>3){
547 printf("Incorrect number of arguments supplied\n");
548 printf("\n");
549 print_revision(argv[0],"$Revision$");
550 printf("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n");
551 printf("License: GPL\n");
552 printf("\n");
553 printf("Usage: %s <ip_address> [community]\n",argv[0]);
554 printf("\n");
555 printf("Note:\n");
556 printf(" <ip_address> = The IP address of the JetDirect card\n");
557 printf(" [community] = An optional community string used for SNMP communication\n");
558 printf(" with the JetDirect card. The default is 'public'.\n");
559 printf("\n");
560 return STATE_UNKNOWN;
561 }
562
563 // get the IP address of the JetDirect device
564 strcpy(address,argv[1]);
565
566 // get the community name to use for SNMP communication
567 if(argc>=3)
568 strcpy(community,argv[2]);
569 else
570 strcpy(community,"public");
571*/
diff --git a/plugins/check_http.c b/plugins/check_http.c
new file mode 100644
index 00000000..db5d50dd
--- /dev/null
+++ b/plugins/check_http.c
@@ -0,0 +1,1067 @@
1/****************************************************************************
2 *
3 * Program: HTTP plugin for Nagios
4 * License: GPL
5 *
6 * License Information:
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * $Id$
23 *
24 *****************************************************************************/
25
26#define PROGNAME "check_http"
27#define REVISION "$Revision$"
28#define COPYRIGHT "1999-2001"
29#define AUTHORS "Ethan Galstad/Karl DeBisschop"
30#define EMAIL "kdebisschop@users.sourceforge.net"
31
32#include "config.h"
33#include "common.h"
34#include "version.h"
35#include "netutils.h"
36#include "utils.h"
37
38#define SUMMARY "\
39This plugin tests the HTTP service on the specified host. It can test\n\
40normal (http) and secure (https) servers, follow redirects, search for\n\
41strings and regular expressions, check connection times, and report on\n\
42certificate expiration times.\n"
43
44#define OPTIONS "\
45\(-H <vhost> | -I <IP-address>) [-u <uri>] [-p <port>]\n\
46 [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L]\n\
47 [-a auth] [-f <ok | warn | critcal | follow>] [-e <expect>]\n\
48 [-s string] [-r <regex> | -R <case-insensitive regex>]\n\
49 [-P string]"
50
51#define LONGOPTIONS "\
52 -H, --hostname=ADDRESS\n\
53 Host name argument for servers using host headers (virtual host)\n\
54 -I, --IP-address=ADDRESS\n\
55 IP address or name (use numeric address if possible to bypass DNS lookup).\n\
56 -e, --expect=STRING\n\
57 String to expect in first line of server response (default: %s)\n\
58 -s, --string=STRING\n\
59 String to expect in the content\n\
60 -u, --url=PATH\n\
61 URL to GET or POST (default: /)\n\
62 -p, --port=INTEGER\n\
63 Port number (default: %d)\n\
64 -P, --post=STRING\n\
65 URL encoded http POST data\n\
66 -w, --warning=INTEGER\n\
67 Response time to result in warning status (seconds)\n\
68 -c, --critical=INTEGER\n\
69 Response time to result in critical status (seconds)\n\
70 -t, --timeout=INTEGER\n\
71 Seconds before connection times out (default: %d)\n\
72 -a, --authorization=AUTH_PAIR\n\
73 Username:password on sites with basic authentication\n\
74 -L, --link=URL\n\
75 Wrap output in HTML link (obsoleted by urlize)\n\
76 -f, --onredirect=<ok|warning|critical|follow>\n\
77 How to handle redirected pages\n%s\
78 -v, --verbose\n\
79 Show details for command-line debugging (do not use with nagios server)\n\
80 -h, --help\n\
81 Print detailed help screen\n\
82 -V, --version\n\
83 Print version information\n"
84
85#ifdef HAVE_SSL
86#define SSLOPTIONS "\
87 -S, --ssl\n\
88 Connect via SSL\n\
89 -C, --certificate=INTEGER\n\
90 Minimum number of days a certificate has to be valid.\n\
91 (when this option is used the url is not checked.)\n"
92#else
93#define SSLOPTIONS ""
94#endif
95
96#define DESCRIPTION "\
97This plugin will attempt to open an HTTP connection with the host. Successul\n\
98connects return STATE_OK, refusals and timeouts return STATE_CRITICAL, other\n\
99errors return STATE_UNKNOWN. Successful connects, but incorrect reponse\n\
100messages from the host result in STATE_WARNING return values. If you are\n\
101checking a virtual server that uses \"host headers\" you must supply the FQDN\n\
102\(fully qualified domain name) as the [host_name] argument.\n"
103
104#define SSLDESCRIPTION "\
105This plugin can also check whether an SSL enabled web server is able to\n\
106serve content (optionally within a specified time) or whether the X509 \n\
107certificate is still valid for the specified number of days.\n\n\
108CHECK CONTENT: check_http -w 5 -c 10 --ssl www.verisign.com\n\n\
109When the 'www.verisign.com' server returns its content within 5 seconds, a\n\
110STATE_OK will be returned. When the server returns its content but exceeds\n\
111the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,\n\
112a STATE_CRITICAL will be returned.\n\n\
113CHECK CERTIFICATE: check_http www.verisign.com -C 14\n\n\
114When the certificate of 'www.verisign.com' is valid for more than 14 days, a\n\
115STATE_OK is returned. When the certificate is still valid, but for less than\n\
11614 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when\n\
117the certificate is expired.\n"
118
119#ifdef HAVE_SSL_H
120#include <rsa.h>
121#include <crypto.h>
122#include <x509.h>
123#include <pem.h>
124#include <ssl.h>
125#include <err.h>
126#include <rand.h>
127#endif
128
129#ifdef HAVE_OPENSSL_SSL_H
130#include <openssl/rsa.h>
131#include <openssl/crypto.h>
132#include <openssl/x509.h>
133#include <openssl/pem.h>
134#include <openssl/ssl.h>
135#include <openssl/err.h>
136#include <openssl/rand.h>
137#endif
138
139#ifdef HAVE_SSL
140int check_cert = FALSE;
141int days_till_exp;
142unsigned char *randbuff;
143SSL_CTX *ctx;
144SSL *ssl;
145X509 *server_cert;
146int connect_SSL (void);
147int check_certificate (X509 **);
148#endif
149
150#ifdef HAVE_REGEX_H
151#define REGS 2
152#define MAX_RE_SIZE 256
153#include <regex.h>
154regex_t preg;
155regmatch_t pmatch[REGS];
156char regexp[MAX_RE_SIZE];
157char errbuf[MAX_INPUT_BUFFER];
158int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE;
159int errcode;
160#endif
161
162#define server_type_check(server_type) \
163(strcmp (server_type, "https") ? FALSE : TRUE)
164
165#define server_port_check(use_ssl) (use_ssl ? HTTPS_PORT : HTTP_PORT)
166
167#define MAX_IPV4_HOSTLENGTH 64
168#define HDR_LOCATION "%*[Ll]%*[Oo]%*[Cc]%*[Aa]%*[Tt]%*[Ii]%*[Oo]%*[Nn]: "
169#define URI_HTTP "%[HTPShtps]://"
170#define URI_HOST "%[a-zA-Z0-9.-]"
171#define URI_PORT ":%[0-9]"
172#define URI_PATH "%[/a-zA-Z0-9._-=@,]"
173
174#define HTTP_PORT 80
175#define HTTPS_PORT 443
176#define HTTP_EXPECT "HTTP/1."
177#define HTTP_URL "/"
178
179time_t start_time, end_time;
180char timestamp[10] = "";
181int specify_port = FALSE;
182int server_port = HTTP_PORT;
183char server_port_text[6] = "";
184char server_type[6] = "http";
185char *server_address = NULL;
186char *host_name = NULL;
187char *server_url = NULL;
188int server_url_length = 0;
189char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT;
190char string_expect[MAX_INPUT_BUFFER] = "";
191int warning_time = 0;
192int check_warning_time = FALSE;
193int critical_time = 0;
194int check_critical_time = FALSE;
195char user_auth[MAX_INPUT_BUFFER] = "";
196int display_html = FALSE;
197int onredirect = STATE_OK;
198int use_ssl = FALSE;
199int verbose = FALSE;
200int sd;
201char *http_method = NULL;
202char *http_post_data = NULL;
203char buffer[MAX_INPUT_BUFFER];
204
205void print_usage (void);
206void print_help (void);
207int process_arguments (int, char **);
208int call_getopt (int, char **);
209static char *base64 (char *bin, int len);
210int check_http (void);
211int my_recv (void);
212int my_close (void);
213
214int
215main (int argc, char **argv)
216{
217 int result = STATE_UNKNOWN;
218
219 if (process_arguments (argc, argv) == ERROR)
220 usage ("check_http: could not parse arguments\n");
221
222 if (strstr (timestamp, ":")) {
223 if (strstr (server_url, "?"))
224 sprintf (server_url, "%s&%s", server_url, timestamp);
225 else
226 sprintf (server_url, "%s?%s", server_url, timestamp);
227 }
228
229 if (display_html == TRUE)
230 printf ("<A HREF=\"http://%s:%d%s\" target=\"_blank\">",
231 host_name, server_port, server_url);
232
233 /* initialize alarm signal handling, set socket timeout, start timer */
234 signal (SIGALRM, socket_timeout_alarm_handler);
235 alarm (socket_timeout);
236 time (&start_time);
237
238#ifdef HAVE_SSL
239 if (use_ssl && check_cert == TRUE) {
240 if (connect_SSL () != OK)
241 terminate (STATE_CRITICAL,
242 "HTTP CRITICAL - Could not make SSL connection\n");
243 if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) {
244 result = check_certificate (&server_cert);
245 X509_free (server_cert);
246 }
247 else {
248 printf ("ERROR: Cannot retrieve server certificate.\n");
249 result = STATE_CRITICAL;
250 }
251 SSL_shutdown (ssl);
252 SSL_free (ssl);
253 SSL_CTX_free (ctx);
254 close (sd);
255 }
256 else {
257 result = check_http ();
258 }
259#else
260 result = check_http ();
261#endif
262 return result;
263}
264
265
266
267/* process command-line arguments */
268int
269process_arguments (int argc, char **argv)
270{
271 int c, i = 1;
272 char optchars[MAX_INPUT_BUFFER];
273
274#ifdef HAVE_GETOPT_H
275 int option_index = 0;
276 static struct option long_options[] = {
277 STD_OPTS_LONG,
278 {"link", no_argument, 0, 'L'},
279 {"nohtml", no_argument, 0, 'n'},
280 {"ssl", no_argument, 0, 'S'},
281 {"verbose", no_argument, 0, 'v'},
282 {"post", required_argument, 0, 'P'},
283 {"IP-address", required_argument, 0, 'I'},
284 {"string", required_argument, 0, 's'},
285 {"regex", required_argument, 0, 'r'},
286 {"ereg", required_argument, 0, 'r'},
287 {"eregi", required_argument, 0, 'R'},
288 {"onredirect", required_argument, 0, 'f'},
289 {"certificate", required_argument, 0, 'C'},
290 {0, 0, 0, 0}
291 };
292#endif
293
294 if (argc < 2)
295 return ERROR;
296
297 for (c = 1; c < argc; c++) {
298 if (strcmp ("-to", argv[c]) == 0)
299 strcpy (argv[c], "-t");
300 if (strcmp ("-hn", argv[c]) == 0)
301 strcpy (argv[c], "-H");
302 if (strcmp ("-wt", argv[c]) == 0)
303 strcpy (argv[c], "-w");
304 if (strcmp ("-ct", argv[c]) == 0)
305 strcpy (argv[c], "-c");
306 if (strcmp ("-nohtml", argv[c]) == 0)
307 strcpy (argv[c], "-n");
308 }
309
310 snprintf (optchars, MAX_INPUT_BUFFER, "%s%s", STD_OPTS,
311 "P:I:a:e:p:s:R:r:u:f:C:nLS");
312
313 while (1) {
314#ifdef HAVE_GETOPT_H
315 c = getopt_long (argc, argv, optchars, long_options, &option_index);
316#else
317 c = getopt (argc, argv, optchars);
318#endif
319 if (c == -1 || c == EOF)
320 break;
321
322 switch (c) {
323 case '?': /* usage */
324 usage2 ("unknown argument", optarg);
325 break;
326 case 'h': /* help */
327 print_help ();
328 exit (STATE_OK);
329 break;
330 case 'V': /* version */
331 print_revision (PROGNAME, REVISION);
332 exit (STATE_OK);
333 break;
334 case 't': /* timeout period */
335 if (!is_intnonneg (optarg))
336 usage2 ("timeout interval must be a non-negative integer", optarg);
337 socket_timeout = atoi (optarg);
338 break;
339 case 'c': /* critical time threshold */
340 if (!is_intnonneg (optarg))
341 usage2 ("invalid critical threshold", optarg);
342 critical_time = atoi (optarg);
343 check_critical_time = TRUE;
344 break;
345 case 'w': /* warning time threshold */
346 if (!is_intnonneg (optarg))
347 usage2 ("invalid warning threshold", optarg);
348 warning_time = atoi (optarg);
349 check_warning_time = TRUE;
350 break;
351 case 'L': /* show html link */
352 display_html = TRUE;
353 break;
354 case 'n': /* do not show html link */
355 display_html = FALSE;
356 break;
357 case 'S': /* use SSL */
358#ifndef HAVE_SSL
359 usage ("check_http: invalid option - SSL is not available\n");
360#endif
361 use_ssl = TRUE;
362 if (specify_port == FALSE)
363 server_port = HTTPS_PORT;
364 break;
365 case 'C': /* warning time threshold */
366#ifdef HAVE_SSL
367 if (!is_intnonneg (optarg))
368 usage2 ("invalid certificate expiration period", optarg);
369 days_till_exp = atoi (optarg);
370 check_cert = TRUE;
371#else
372 usage ("check_http: invalid option - SSL is not available\n");
373#endif
374 break;
375 case 'f': /* onredirect */
376 if (!strcmp (optarg, "follow"))
377 onredirect = STATE_DEPENDENT;
378 if (!strcmp (optarg, "unknown"))
379 onredirect = STATE_UNKNOWN;
380 if (!strcmp (optarg, "ok"))
381 onredirect = STATE_OK;
382 if (!strcmp (optarg, "warning"))
383 onredirect = STATE_WARNING;
384 if (!strcmp (optarg, "critical"))
385 onredirect = STATE_CRITICAL;
386 break;
387 /* Note: H, I, and u must be malloc'd or will fail on redirects */
388 case 'H': /* Host Name (virtual host) */
389 host_name = strscpy (host_name, optarg);
390 break;
391 case 'I': /* Server IP-address */
392 server_address = strscpy (server_address, optarg);
393 break;
394 case 'u': /* Host or server */
395 server_url = strscpy (server_url, optarg);
396 server_url_length = strlen (optarg);
397 break;
398 case 'p': /* Host or server */
399 if (!is_intnonneg (optarg))
400 usage2 ("invalid port number", optarg);
401 server_port = atoi (optarg);
402 specify_port = TRUE;
403 break;
404 case 'a': /* authorization info */
405 strncpy (user_auth, optarg, MAX_INPUT_BUFFER - 1);
406 user_auth[MAX_INPUT_BUFFER - 1] = 0;
407 break;
408 case 'P': /* HTTP POST data in URL encoded format */
409 http_method = strscpy (http_method, "POST");
410 http_post_data = strscpy (http_post_data, optarg);
411 break;
412 case 's': /* string or substring */
413 strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1);
414 string_expect[MAX_INPUT_BUFFER - 1] = 0;
415 break;
416 case 'e': /* string or substring */
417 strncpy (server_expect, optarg, MAX_INPUT_BUFFER - 1);
418 server_expect[MAX_INPUT_BUFFER - 1] = 0;
419 break;
420 case 'R': /* regex */
421#ifdef HAVE_REGEX_H
422 cflags = REG_ICASE;
423#else
424 usage ("check_http: call for regex which was not a compiled option\n");
425#endif
426 case 'r': /* regex */
427#ifdef HAVE_REGEX_H
428 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
429 strncpy (regexp, optarg, MAX_INPUT_BUFFER - 1);
430 regexp[MAX_INPUT_BUFFER - 1] = 0;
431 errcode = regcomp (&preg, regexp, cflags);
432 if (errcode != 0) {
433 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
434 printf ("Could Not Compile Regular Expression: %s", errbuf);
435 return ERROR;
436 }
437#else
438 usage ("check_http: call for regex which was not a compiled option\n");
439#endif
440 break;
441 case 'v': /* verbose */
442 verbose = TRUE;
443 break;
444 }
445 }
446
447 c = optind;
448
449 if (server_address == NULL && host_name == NULL) {
450 server_address = strscpy (NULL, argv[c]);
451 host_name = strscpy (NULL, argv[c++]);
452 }
453
454 if (server_address == NULL && host_name == NULL)
455 usage ("check_http: you must specify a host name\n");
456
457 if (server_address == NULL)
458 server_address = strscpy (NULL, host_name);
459
460 if (host_name == NULL)
461 host_name = strscpy (NULL, server_address);
462
463 if (http_method == NULL)
464 http_method = strscpy (http_method, "GET");
465
466 if (server_url == NULL) {
467 server_url = strscpy (NULL, "/");
468 server_url_length = strlen(HTTP_URL);
469 }
470
471 return TRUE;
472}
473
474
475
476/* written by lauri alanko */
477static char *
478base64 (char *bin, int len)
479{
480
481 char *buf = (char *) malloc ((len + 2) / 3 * 4 + 1);
482 int i = 0, j = 0;
483
484 char BASE64_END = '=';
485 char base64_table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
486 "abcdefghijklmnopqrstuvwxyz"
487 "0123456789+/";
488
489 while (j < len - 2) {
490 buf[i++] = base64_table[bin[j] >> 2];
491 buf[i++] = base64_table[((bin[j] & 3) << 4) | (bin[j + 1] >> 4)];
492 buf[i++] = base64_table[((bin[j + 1] & 15) << 2) | (bin[j + 2] >> 6)];
493 buf[i++] = base64_table[bin[j + 2] & 63];
494 j += 3;
495 }
496
497 switch (len - j) {
498 case 1:
499 buf[i++] = base64_table[bin[j] >> 2];
500 buf[i++] = base64_table[(bin[j] & 3) << 4];
501 buf[i++] = BASE64_END;
502 buf[i++] = BASE64_END;
503 break;
504 case 2:
505 buf[i++] = base64_table[bin[j] >> 2];
506 buf[i++] = base64_table[((bin[j] & 3) << 4) | (bin[j + 1] >> 4)];
507 buf[i++] = base64_table[(bin[j + 1] & 15) << 2];
508 buf[i++] = BASE64_END;
509 break;
510 case 0:
511 break;
512 }
513
514 buf[i] = '\0';
515 return buf;
516}
517
518
519
520int
521check_http (void)
522{
523 char *msg = NULL;
524 char *status_line = NULL;
525 char *header = NULL;
526 char *page = NULL;
527 char *auth = NULL;
528 int i = 0;
529 size_t pagesize = 0;
530 char *full_page = NULL;
531 char *pos = NULL;
532
533 /* try to connect to the host at the given port number */
534#ifdef HAVE_SSL
535 if (use_ssl == TRUE) {
536
537 if (connect_SSL () != OK) {
538 msg = ssprintf (msg, "Unable to open TCP socket");
539 terminate (STATE_CRITICAL, msg);
540 }
541
542 if ((server_cert = SSL_get_peer_certificate (ssl)) != NULL) {
543 X509_free (server_cert);
544 }
545 else {
546 printf ("ERROR: Cannot retrieve server certificate.\n");
547 return STATE_CRITICAL;
548 }
549
550 sprintf (buffer, "%s %s HTTP/1.0\r\n", http_method, server_url);
551 if (SSL_write (ssl, buffer, strlen (buffer)) == -1) {
552 ERR_print_errors_fp (stderr);
553 return STATE_CRITICAL;
554 }
555
556 /* optionally send the host header info (not clear if it's usable) */
557 if (strcmp (host_name, "")) {
558 sprintf (buffer, "Host: %s\r\n", host_name);
559 if (SSL_write (ssl, buffer, strlen (buffer)) == -1) {
560 ERR_print_errors_fp (stderr);
561 return STATE_CRITICAL;
562 }
563 }
564
565 /* send user agent */
566 sprintf (buffer, "User-Agent: check_http/%s (nagios-plugins %s)\r\n",
567 clean_revstring (REVISION), PACKAGE_VERSION);
568 if (SSL_write (ssl, buffer, strlen (buffer)) == -1) {
569 ERR_print_errors_fp (stderr);
570 return STATE_CRITICAL;
571 }
572
573 /* optionally send the authentication info */
574 if (strcmp (user_auth, "")) {
575 auth = base64 (user_auth, strlen (user_auth));
576 sprintf (buffer, "Authorization: Basic %s\r\n", auth);
577 if (SSL_write (ssl, buffer, strlen (buffer)) == -1) {
578 ERR_print_errors_fp (stderr);
579 return STATE_CRITICAL;
580 }
581 }
582
583 /* optionally send http POST data */
584 if (http_post_data) {
585 sprintf (buffer, "Content-Type: application/x-www-form-urlencoded\r\n");
586 if (SSL_write (ssl, buffer, strlen (buffer)) == -1) {
587 ERR_print_errors_fp (stderr);
588 return STATE_CRITICAL;
589 }
590 sprintf (buffer, "Content-Length: %i\r\n\r\n", strlen (http_post_data));
591 if (SSL_write (ssl, buffer, strlen (buffer)) == -1) {
592 ERR_print_errors_fp (stderr);
593 return STATE_CRITICAL;
594 }
595 http_post_data = strscat (http_post_data, "\r\n");
596 if (SSL_write (ssl, http_post_data, strlen (http_post_data)) == -1) {
597 ERR_print_errors_fp (stderr);
598 return STATE_CRITICAL;
599 }
600 }
601
602 /* send a newline so the server knows we're done with the request */
603 sprintf (buffer, "\r\n\r\n");
604 if (SSL_write (ssl, buffer, strlen (buffer)) == -1) {
605 ERR_print_errors_fp (stderr);
606 return STATE_CRITICAL;
607 }
608
609 }
610 else {
611#endif
612 if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) {
613 msg = ssprintf (msg, "Unable to open TCP socket");
614 terminate (STATE_CRITICAL, msg);
615 }
616 sprintf (buffer, "%s %s HTTP/1.0\r\n", http_method, server_url);
617 send (sd, buffer, strlen (buffer), 0);
618
619 /* optionally send the host header info */
620 if (strcmp (host_name, "")) {
621 sprintf (buffer, "Host: %s\r\n", host_name);
622 send (sd, buffer, strlen (buffer), 0);
623 }
624
625 /* send user agent */
626 sprintf (buffer,
627 "User-Agent: check_http/%s (nagios-plugins %s)\r\n",
628 clean_revstring (REVISION), PACKAGE_VERSION);
629 send (sd, buffer, strlen (buffer), 0);
630
631 /* optionally send the authentication info */
632 if (strcmp (user_auth, "")) {
633 auth = base64 (user_auth, strlen (user_auth));
634 sprintf (buffer, "Authorization: Basic %s\r\n", auth);
635 send (sd, buffer, strlen (buffer), 0);
636 }
637
638 /* optionally send http POST data */
639 /* written by Chris Henesy <lurker@shadowtech.org> */
640 if (http_post_data) {
641 sprintf (buffer, "Content-Type: application/x-www-form-urlencoded\r\n");
642 send (sd, buffer, strlen (buffer), 0);
643 sprintf (buffer, "Content-Length: %i\r\n\r\n", strlen (http_post_data));
644 send (sd, buffer, strlen (buffer), 0);
645 http_post_data = strscat (http_post_data, "\r\n");
646 send (sd, http_post_data, strlen (http_post_data), 0);
647 }
648
649 /* send a newline so the server knows we're done with the request */
650 sprintf (buffer, "\r\n\r\n");
651 send (sd, buffer, strlen (buffer), 0);
652#ifdef HAVE_SSL
653 }
654#endif
655
656 /* fetch the page */
657 pagesize = (size_t) 0;
658 while ((i = my_recv ()) > 0) {
659 full_page = strscat (full_page, buffer);
660 pagesize += i;
661 }
662
663 if (i < 0)
664 terminate (STATE_CRITICAL, "Error in recv()");
665
666 /* return a CRITICAL status if we couldn't read any data */
667 if (pagesize == (size_t) 0)
668 terminate (STATE_CRITICAL, "No data received %s", timestamp);
669
670 /* close the connection */
671 my_close ();
672
673 /* reset the alarm */
674 alarm (0);
675
676 /* leave full_page untouched so we can free it later */
677 page = full_page;
678
679 if (verbose)
680 printf ("Page is %d characters\n", pagesize);
681
682 /* find status line and null-terminate it */
683 status_line = page;
684 page += (size_t) strcspn (page, "\r\n");
685 pos = page;
686 page += (size_t) strspn (page, "\r\n");
687 status_line[pos - status_line] = 0;
688 strip (status_line);
689 if (verbose)
690 printf ("STATUS: %s\n", status_line);
691
692 /* find header info and null terminate it */
693 header = page;
694 while (strcspn (page, "\r\n") > 0) {
695 page += (size_t) strcspn (page, "\r\n");
696 pos = page;
697 if ((strspn (page, "\r") == 1 && strspn (page, "\r\n") >= 2) ||
698 (strspn (page, "\n") == 1 && strspn (page, "\r\n") >= 2))
699 page += (size_t) 2;
700 else
701 page += (size_t) 1;
702 }
703 page += (size_t) strspn (page, "\r\n");
704 header[pos - header] = 0;
705 if (verbose)
706 printf ("**** HEADER ****\n%s\n**** CONTENT ****\n%s\n", header, page);
707
708 /* make sure the status line matches the response we are looking for */
709 if (!strstr (status_line, server_expect)) {
710 if (server_port == HTTP_PORT)
711 msg = ssprintf (msg, "Invalid HTTP response received from host\n");
712 else
713 msg = ssprintf (msg,
714 "Invalid HTTP response received from host on port %d\n",
715 server_port);
716 terminate (STATE_CRITICAL, msg);
717 }
718
719 /* check the return code */
720 /* server errors result in a critical state */
721 if (strstr (status_line, "500") ||
722 strstr (status_line, "501") ||
723 strstr (status_line, "502") ||
724 strstr (status_line, "503")) {
725 msg = ssprintf (msg, "HTTP CRITICAL: %s\n", status_line);
726 terminate (STATE_CRITICAL, msg);
727 }
728
729 /* client errors result in a warning state */
730 if (strstr (status_line, "400") ||
731 strstr (status_line, "401") ||
732 strstr (status_line, "402") ||
733 strstr (status_line, "403") ||
734 strstr (status_line, "404")) {
735 msg = ssprintf (msg, "HTTP WARNING: %s\n", status_line);
736 terminate (STATE_WARNING, msg);
737 }
738
739 /* check redirected page if specified */
740 if (strstr (status_line, "300") ||
741 strstr (status_line, "301") ||
742 strstr (status_line, "302") ||
743 strstr (status_line, "303") ||
744 strstr (status_line, "304")) {
745 if (onredirect == STATE_DEPENDENT) {
746
747 pos = header;
748 while (pos) {
749 server_address = realloc (server_address, MAX_IPV4_HOSTLENGTH);
750 if (server_address == NULL)
751 terminate (STATE_UNKNOWN,
752 "HTTP UNKNOWN: could not allocate server_address");
753 if (strspn (pos, "\r\n") > server_url_length) {
754 server_url = realloc (server_url, strspn (pos, "\r\n"));
755 if (server_url == NULL)
756 terminate (STATE_UNKNOWN,
757 "HTTP UNKNOWN: could not allocate server_url");
758 server_url_length = strspn (pos, "\r\n");
759 }
760 if (sscanf (pos, HDR_LOCATION URI_HTTP URI_HOST URI_PORT URI_PATH, server_type, server_address, server_port_text, server_url) == 4) {
761 host_name = strscpy (host_name, server_address);
762 use_ssl = server_type_check (server_type);
763 server_port = atoi (server_port_text);
764 check_http ();
765 }
766 else if (sscanf (pos, HDR_LOCATION URI_HTTP URI_HOST URI_PATH, server_type, server_address, server_url) == 3) {
767 host_name = strscpy (host_name, server_address);
768 use_ssl = server_type_check (server_type);
769 server_port = server_port_check (use_ssl);
770 check_http ();
771 }
772 else if (sscanf (pos, HDR_LOCATION URI_HTTP URI_HOST URI_PORT, server_type, server_address, server_port_text) == 3) {
773 host_name = strscpy (host_name, server_address);
774 strcpy (server_url, "/");
775 use_ssl = server_type_check (server_type);
776 server_port = atoi (server_port_text);
777 check_http ();
778 }
779 else if (sscanf (pos, HDR_LOCATION URI_HTTP URI_HOST, server_type, server_address) == 2) {
780 host_name = strscpy (host_name, server_address);
781 strcpy (server_url, "/");
782 use_ssl = server_type_check (server_type);
783 server_port = server_port_check (use_ssl);
784 check_http ();
785 }
786 else if (sscanf (pos, HDR_LOCATION URI_PATH, server_url) == 1) {
787 check_http ();
788 }
789 pos += (size_t) strcspn (pos, "\r\n");
790 pos += (size_t) strspn (pos, "\r\n");
791 } /* end while (pos) */
792 printf ("HTTP UNKNOWN: Could not find redirect location - %s%s",
793 status_line, (display_html ? "</A>" : ""));
794 exit (STATE_UNKNOWN);
795 } /* end if (onredirect == STATE_DEPENDENT) */
796 else if (onredirect == STATE_UNKNOWN)
797 printf ("HTTP UNKNOWN");
798 else if (onredirect == STATE_OK)
799 printf ("HTTP ok");
800 else if (onredirect == STATE_WARNING)
801 printf ("HTTP WARNING");
802 else if (onredirect == STATE_CRITICAL)
803 printf ("HTTP CRITICAL");
804 time (&end_time);
805 msg = ssprintf (msg, ": %s - %d second response time %s%s\n",
806 status_line, (int) (end_time - start_time),
807 timestamp, (display_html ? "</A>" : ""));
808 terminate (onredirect, msg);
809 } /* end if (strstr (status_line, "30[0-4]") */
810
811 /* check elapsed time */
812 time (&end_time);
813 msg = ssprintf (msg, "HTTP problem: %s - %d second response time %s%s\n",
814 status_line, (int) (end_time - start_time),
815 timestamp, (display_html ? "</A>" : ""));
816 if (check_critical_time == TRUE && (end_time - start_time) > critical_time)
817 terminate (STATE_CRITICAL, msg);
818 if (check_warning_time == TRUE && (end_time - start_time) > warning_time)
819 terminate (STATE_WARNING, msg);
820
821 /* Page and Header content checks go here */
822 /* these checks should be last */
823
824 if (strlen (string_expect)) {
825 if (strstr (page, string_expect)) {
826 printf ("HTTP ok: %s - %d second response time %s%s\n",
827 status_line, (int) (end_time - start_time),
828 timestamp, (display_html ? "</A>" : ""));
829 exit (STATE_OK);
830 }
831 else {
832 printf ("HTTP CRITICAL: string not found%s\n",
833 (display_html ? "</A>" : ""));
834 exit (STATE_CRITICAL);
835 }
836 }
837#ifdef HAVE_REGEX_H
838 if (strlen (regexp)) {
839 errcode = regexec (&preg, page, REGS, pmatch, 0);
840 if (errcode == 0) {
841 printf ("HTTP ok: %s - %d second response time %s%s\n",
842 status_line, (int) (end_time - start_time),
843 timestamp, (display_html ? "</A>" : ""));
844 exit (STATE_OK);
845 }
846 else {
847 if (errcode == REG_NOMATCH) {
848 printf ("HTTP CRITICAL: pattern not found%s\n",
849 (display_html ? "</A>" : ""));
850 exit (STATE_CRITICAL);
851 }
852 else {
853 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
854 printf ("Execute Error: %s\n", errbuf);
855 exit (STATE_CRITICAL);
856 }
857 }
858 }
859#endif
860
861 /* We only get here if all tests have been passed */
862 msg = ssprintf (msg, "HTTP ok: %s - %d second response time %s%s\n",
863 status_line, (int) (end_time - start_time),
864 timestamp, (display_html ? "</A>" : ""));
865 terminate (STATE_OK, msg);
866 return STATE_UNKNOWN;
867}
868
869
870
871#ifdef HAVE_SSL
872int
873connect_SSL (void)
874{
875 SSL_METHOD *meth;
876
877 randbuff = strscpy (NULL, "qwertyuiopasdfghjkl");
878 RAND_seed (randbuff, strlen (randbuff));
879 /* Initialize SSL context */
880 SSLeay_add_ssl_algorithms ();
881 meth = SSLv23_client_method ();
882 SSL_load_error_strings ();
883 if ((ctx = SSL_CTX_new (meth)) == NULL) {
884 printf ("ERROR: Cannot create SSL context.\n");
885 return STATE_CRITICAL;
886 }
887
888 /* Initialize alarm signal handling */
889 signal (SIGALRM, socket_timeout_alarm_handler);
890
891 /* Set socket timeout */
892 alarm (socket_timeout);
893
894 /* Save start time */
895 time (&start_time);
896
897 /* Make TCP connection */
898 if (my_tcp_connect (server_address, server_port, &sd) == STATE_OK) {
899 /* Do the SSL handshake */
900 if ((ssl = SSL_new (ctx)) != NULL) {
901 SSL_set_cipher_list(ssl, "ALL");
902 SSL_set_fd (ssl, sd);
903 if (SSL_connect (ssl) != -1)
904 return OK;
905 ERR_print_errors_fp (stderr);
906 }
907 else {
908 printf ("ERROR: Cannot initiate SSL handshake.\n");
909 }
910 SSL_free (ssl);
911 }
912
913 SSL_CTX_free (ctx);
914 close (sd);
915
916 return STATE_CRITICAL;
917}
918#endif
919
920#ifdef HAVE_SSL
921int
922check_certificate (X509 ** certificate)
923{
924 ASN1_STRING *tm;
925 int offset;
926 struct tm stamp;
927 int days_left;
928 /* int result = STATE_OK; */
929 /* char timestamp[14]; */
930
931
932 /* Retrieve timestamp of certificate */
933 tm = X509_get_notAfter (*certificate);
934
935 /* Generate tm structure to process timestamp */
936 if (tm->type == V_ASN1_UTCTIME) {
937 if (tm->length < 10) {
938 printf ("ERROR: Wrong time format in certificate.\n");
939 return STATE_CRITICAL;
940 }
941 else {
942 stamp.tm_year = (tm->data[0] - '0') * 10 + (tm->data[1] - '0');
943 if (stamp.tm_year < 50)
944 stamp.tm_year += 100;
945 offset = 0;
946 }
947 }
948 else {
949 if (tm->length < 12) {
950 printf ("ERROR: Wrong time format in certificate.\n");
951 return STATE_CRITICAL;
952 }
953 else {
954 stamp.tm_year =
955 (tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 +
956 (tm->data[2] - '0') * 10 + (tm->data[3] - '0');
957 stamp.tm_year -= 1900;
958 offset = 2;
959 }
960 }
961 stamp.tm_mon =
962 (tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1;
963 stamp.tm_mday =
964 (tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0');
965 stamp.tm_hour =
966 (tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
967 stamp.tm_min =
968 (tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
969 stamp.tm_sec = 0;
970 stamp.tm_isdst = -1;
971
972 days_left = (mktime (&stamp) - time (NULL)) / 86400;
973 sprintf
974 (timestamp, "%02d/%02d/%04d %02d:%02d",
975 stamp.tm_mon + 1,
976 stamp.tm_mday, stamp.tm_year + 1900, stamp.tm_hour, stamp.tm_min);
977
978 if (days_left > 0 && days_left <= days_till_exp) {
979 printf ("Certificate expires in %d day(s) (%s).\n", days_left, timestamp);
980 return STATE_WARNING;
981 }
982 if (days_left < 0) {
983 printf ("Certificate expired on %s.\n", timestamp);
984 return STATE_CRITICAL;
985 }
986
987 if (days_left == 0) {
988 printf ("Certificate expires today (%s).\n", timestamp);
989 return STATE_WARNING;
990 }
991
992 printf ("Certificate will expire on %s.\n", timestamp);
993
994 return STATE_OK;
995}
996#endif
997
998
999
1000int
1001my_recv (void)
1002{
1003 int i;
1004#ifdef HAVE_SSL
1005 if (use_ssl) {
1006 i = SSL_read (ssl, buffer, MAX_INPUT_BUFFER - 1);
1007 }
1008 else {
1009 i = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
1010 }
1011#else
1012 i = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
1013#endif
1014 return i;
1015}
1016
1017
1018int
1019my_close (void)
1020{
1021#ifdef HAVE_SSL
1022 if (use_ssl == TRUE) {
1023 SSL_shutdown (ssl);
1024 SSL_free (ssl);
1025 SSL_CTX_free (ctx);
1026 return 0;
1027 }
1028 else {
1029#endif
1030 return close (sd);
1031#ifdef HAVE_SSL
1032 }
1033#endif
1034}
1035
1036
1037
1038void
1039print_help (void)
1040{
1041 print_revision (PROGNAME, REVISION);
1042 printf
1043 ("Copyright (c) %s %s <%s>\n\n%s\n",
1044 COPYRIGHT, AUTHORS, EMAIL, SUMMARY);
1045 print_usage ();
1046 printf ("NOTE: One or both of -H and -I must be specified\n");
1047 printf ("\nOptions:\n" LONGOPTIONS "\n", HTTP_EXPECT, HTTP_PORT,
1048 DEFAULT_SOCKET_TIMEOUT, SSLOPTIONS);
1049#ifdef HAVE_SSL
1050 printf (SSLDESCRIPTION);
1051#endif
1052}
1053
1054
1055void
1056print_usage (void)
1057{
1058 printf ("Usage:\n" " %s %s\n"
1059#ifdef HAVE_GETOPT_H
1060 " %s (-h | --help) for detailed help\n"
1061 " %s (-V | --version) for version information\n",
1062#else
1063 " %s -h for detailed help\n"
1064 " %s -V for version information\n",
1065#endif
1066 PROGNAME, OPTIONS, PROGNAME, PROGNAME);
1067}
diff --git a/plugins/check_ide-smart.c b/plugins/check_ide-smart.c
new file mode 100644
index 00000000..869f7dc0
--- /dev/null
+++ b/plugins/check_ide-smart.c
@@ -0,0 +1,448 @@
1/*
2 * check_ide-smart v.1 - hacked version of ide-smart for Nagios
3 * Copyright (C) 2000 Robert Dale <rdale@digital-mission.com>
4 *
5 * Net Saint - http://www.nagios.org
6 *
7 * Notes:
8 * ide-smart has the same functionality as before. Some return
9 * values were changed, otherwise the --net-saint option was added.
10 *
11 * Run with: check_ide-smart --net-saint [-d] <DRIVE>
12 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc
13 *
14 * - Returns 0 on no errors
15 * - Returns 1 on advisories
16 * - Returns 2 on prefailure
17 * - Returns -1 not too often
18 *
19 * ide-smart 1.3 - IDE S.M.A.R.T. cheking tool
20 * Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>
21 * 1998 Gadi Oxman <gadio@netvision.net.il>
22 *
23 * This program is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2 of the License, or
26 * (at your option) any later version.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36 */
37
38#include <stdio.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <sys/ioctl.h>
42#include <fcntl.h>
43#include <string.h>
44#include <unistd.h>
45#include <linux/hdreg.h>
46#include <linux/types.h>
47#include <getopt.h>
48#include <errno.h>
49
50#define NR_ATTRIBUTES 30
51
52#ifndef TRUE
53#define TRUE 1
54#endif /* */
55
56#define PREFAILURE 2
57#define ADVISORY 1
58#define OPERATIONAL 0
59#define UNKNOWN -1
60 typedef struct threshold_s
61{
62 __u8 id;
63 __u8 threshold;
64 __u8 reserved[10];
65}
66__attribute__ ((packed)) threshold_t;
67typedef struct thresholds_s
68{
69 __u16 revision;
70 threshold_t thresholds[NR_ATTRIBUTES];
71 __u8 reserved[18];
72 __u8 vendor[131];
73 __u8 checksum;
74}
75__attribute__ ((packed)) thresholds_t;
76typedef struct value_s
77{
78 __u8 id;
79 __u16 status;
80 __u8 value;
81 __u8 vendor[8];
82}
83__attribute__ ((packed)) value_t;
84typedef struct values_s
85{
86 __u16 revision;
87 value_t values[NR_ATTRIBUTES];
88 __u8 offline_status;
89 __u8 vendor1;
90 __u16 offline_timeout;
91 __u8 vendor2;
92 __u8 offline_capability;
93 __u16 smart_capability;
94 __u8 reserved[16];
95 __u8 vendor[125];
96 __u8 checksum;
97}
98__attribute__ ((packed)) values_t;
99struct
100{
101 __u8 value;
102 char *text;
103 }
104offline_status_text[] =
105{
106 {
107 0x00, "NeverStarted"}
108 , {
109 0x02, "Completed"}
110 , {
111 0x04, "Suspended"}
112 , {
113 0x05, "Aborted"}
114 , {
115 0x06, "Failed"}
116 , {
117 0, 0}
118};
119struct
120{
121 __u8 value;
122 char *text;
123 }
124smart_command[] =
125{
126 {
127 SMART_ENABLE, "SMART_ENABLE"}
128 , {
129 SMART_DISABLE, "SMART_DISABLE"}
130 , {
131 SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"}
132 , {
133 SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"}
134, };
135
136
137/* Index to smart_command table, keep in order */
138enum SmartCommand
139{ SMART_CMD_ENABLE, SMART_CMD_DISABLE, SMART_CMD_IMMEDIATE_OFFLINE,
140 SMART_CMD_AUTO_OFFLINE
141};
142char *
143get_offline_text (int status)
144{
145 int i;
146 for (i = 0; offline_status_text[i].text; i++) {
147 if (offline_status_text[i].value == status) {
148 return offline_status_text[i].text;
149 }
150 }
151 return "unknown";
152}
153int
154smart_read_values (int fd, values_t * values)
155{
156 __u8 args[4 + 512] = {
157 WIN_SMART, 0, SMART_READ_VALUES, 1,};
158 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
159 int e = errno;
160 printf ("Critical: SMART_READ_VALUES: %s\n", strerror (errno));
161 return e;
162 }
163 memcpy (values, args + 4, 512);
164 return 0;
165}
166int
167values_not_passed (values_t * p, thresholds_t * t)
168{
169 value_t * value = p->values;
170 threshold_t * threshold = t->thresholds;
171 int failed = 0;
172 int passed = 0;
173 int i;
174 for (i = 0; i < NR_ATTRIBUTES; i++) {
175 if (value->id && threshold->id && value->id == threshold->id) {
176 if (value->value <= threshold->threshold) {
177 ++failed;
178 }
179 else {
180 ++passed;
181 }
182 }
183 ++value;
184 ++threshold;
185 }
186 return (passed ? -failed : 2);
187}
188int
189net_saint (values_t * p, thresholds_t * t)
190{
191 value_t * value = p->values;
192 threshold_t * threshold = t->thresholds;
193 int status = OPERATIONAL;
194 int prefailure = 0;
195 int advisory = 0;
196 int failed = 0;
197 int passed = 0;
198 int total = 0;
199 int i;
200 for (i = 0; i < NR_ATTRIBUTES; i++) {
201 if (value->id && threshold->id && value->id == threshold->id) {
202 if (value->value <= threshold->threshold) {
203 ++failed;
204 if (value->status & 1) {
205 status = PREFAILURE;
206 ++prefailure;
207 }
208 else {
209 status = ADVISORY;
210 ++advisory;
211 }
212 }
213 else {
214 ++passed;
215 }
216 ++total;
217 }
218 ++value;
219 ++threshold;
220 }
221 switch (status) {
222 case PREFAILURE:
223 printf ("Critical: %d Harddrive PreFailure%cDetected! "
224 "%d/%d tests failed.\n", prefailure, prefailure > 1 ? 's' : ' ',
225 failed, total);
226 break;
227 case ADVISORY:
228 printf ("Warning: %d Harddrive Advisor%s Detected. "
229 "%d/%d tests failed.\n", advisory, advisory > 1 ? "ies" : "y",
230 failed, total);
231 break;
232 case OPERATIONAL:
233 printf ("Status: Operational (%d/%d tests passed)\n", passed, total);
234 break;
235 default:
236 printf ("Error: Status '%d' uknown. %d/%d tests passed\n", status,
237 passed, total);
238 status = -1;
239 break;
240 }
241 return status;
242}
243void
244print_value (value_t * p, threshold_t * t)
245{
246 printf ("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n",
247 p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory ",
248 p->status & 2 ? "OnLine " : "OffLine", p->value, t->threshold,
249 p->value > t->threshold ? "Passed" : "Failed");
250}
251void
252print_values (values_t * p, thresholds_t * t)
253{
254 value_t * value = p->values;
255 threshold_t * threshold = t->thresholds;
256 int i;
257 for (i = 0; i < NR_ATTRIBUTES; i++) {
258 if (value->id && threshold->id && value->id == threshold->id) {
259 print_value (value++, threshold++);
260 }
261 }
262 printf
263 ("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n",
264 p->offline_status, get_offline_text (p->offline_status & 0x7f),
265 (p->offline_status & 0x80 ? "Yes" : "No"), p->offline_timeout / 60);
266 printf ("OffLineCapability=%d {%s %s %s}\n", p->offline_capability,
267 p->offline_capability & 1 ? "Immediate" : "",
268 p->offline_capability & 2 ? "Auto" : "",
269 p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
270 printf ("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n",
271 p->revision, p->checksum, p->smart_capability,
272 p->smart_capability & 1 ? "SaveOnStandBy" : "",
273 p->smart_capability & 2 ? "AutoSave" : "");
274}
275void
276print_thresholds (thresholds_t * p)
277{
278 threshold_t * threshold = p->thresholds;
279 int i;
280 printf ("\n");
281 printf ("SmartRevision=%d\n", p->revision);
282 for (i = 0; i < NR_ATTRIBUTES; i++) {
283 if (threshold->id) {
284 printf ("Id=%3d, Threshold=%3d\n", threshold->id,
285 threshold->threshold); }
286 ++threshold;
287 }
288 printf ("CheckSum=%d\n", p->checksum);
289}
290int
291smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0,
292 char show_error)
293{
294 __u8 args[4] = {
295 WIN_SMART, val0, smart_command[command].value, 0};
296 int e = 0;
297 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
298 e = errno;
299 if (show_error) {
300 printf ("Critical: %s: %s\n", smart_command[command].text,
301 strerror (errno)); }
302 }
303 return e;
304}
305int
306smart_read_thresholds (int fd, thresholds_t * thresholds)
307{
308 __u8 args[4 + 512] = {
309 WIN_SMART, 0, SMART_READ_THRESHOLDS, 1,};
310 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
311 int e = errno;
312 printf ("Critical: SMART_READ_THRESHOLDS: %s\n", strerror (errno));
313 return e;
314 }
315 memcpy (thresholds, args + 4, 512);
316 return 0;
317}
318void
319show_version ()
320{
321 printf ("check_ide-smart v.1 - FREE Software with NO WARRANTY\n");
322 printf ("Nagios feature - Robert Dale <rdale@digital-mission.com>\n");
323 printf ("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n");
324}
325void
326show_help ()
327{
328 printf ("Usage: check_ide-smart [DEVICE] [OPTION]\n"
329 " -d, --device=DEVICE Select device DEVICE\n"
330 " -i, --immediate Perform immediately offline tests\n"
331 " -q, --quiet-check Returns the number of failed tests\n"
332 " -1, --auto-on Turn on automatic offline tests\n"
333 " -0, --auto-off Turn off automatic offline tests\n"
334 " -n, --net-saint Output suitable for Net Saint\n"
335 " -h, --help\n" " -V, --version\n");
336}
337int
338main (int argc, char *argv[])
339{
340 char *device = NULL;
341 int command = -1;
342 int o, longindex;
343 int retval = 0;
344
345#ifdef HAVE_GETOPT_H
346 const struct option longopts[] = {
347 {"device", required_argument, 0, 'd'},
348 {"immediate", no_argument, 0, 'i'},
349 {"quiet-check", no_argument, 0, 'q'},
350 {"auto-on", no_argument, 0, '1'},
351 {"auto-off", no_argument, 0, '0'},
352 {"net-saint", no_argument, 0, 'n'},
353 {"help", no_argument, 0, 'h'},
354 {"version", no_argument, 0, 'V'}, {0, 0, 0, 0}
355 };
356
357#endif /* */
358 while (1) {
359
360#ifdef HAVE_GETOPT_H
361 o = getopt_long (argc, argv, "+d:iq10nhV", longopts, &longindex);
362
363#else /* */
364 o = getopt (argc, argv, "+d:iq10nhV");
365
366#endif /* */
367 if (o == -1 || o == EOF)
368 break;
369 switch (o) {
370 case 'd':
371 device = optarg;
372 break;
373 case 'q':
374 command = 3;
375 break;
376 case 'i':
377 command = 2;
378 break;
379 case '1':
380 command = 1;
381 break;
382 case '0':
383 command = 0;
384 break;
385 case 'n':
386 command = 4;
387 break;
388 case 'h':
389 show_help ();
390 return 0;
391 case 'V':
392 show_version ();
393 return 0;
394 default:
395 printf ("Try `%s --help' for more information.\n", argv[0]);
396 return 1;
397 }
398 if (optind < argc) {
399 device = argv[optind];
400 }
401 if (!device) {
402 show_help ();
403 show_version ();
404 return -1;
405 }
406 if (1) {
407 thresholds_t thresholds;
408 values_t values;
409 int fd = open (device, O_RDONLY);
410 if (fd < 0) {
411 printf ("Critical: Couldn't open device: %s\n", strerror (errno));
412 return 2;
413 }
414 if (smart_cmd_simple (fd, SMART_CMD_ENABLE, 0, TRUE)) {
415 printf ("Critical: SMART_CMD_ENABLE\n");
416 return 2;
417 }
418 switch (command) {
419 case 0:
420 retval = smart_cmd_simple (fd, SMART_CMD_AUTO_OFFLINE, 0, TRUE);
421 break;
422 case 1:
423 retval = smart_cmd_simple (fd, SMART_CMD_AUTO_OFFLINE, 0xF8, TRUE);
424 break;
425 case 2:
426 retval = smart_cmd_simple (fd, SMART_CMD_IMMEDIATE_OFFLINE, 0, TRUE);
427 break;
428 case 3:
429 smart_read_values (fd, &values);
430 smart_read_thresholds (fd, &thresholds);
431 retval = values_not_passed (&values, &thresholds);
432 break;
433 case 4:
434 smart_read_values (fd, &values);
435 smart_read_thresholds (fd, &thresholds);
436 retval = net_saint (&values, &thresholds);
437 break;
438 default:
439 smart_read_values (fd, &values);
440 smart_read_thresholds (fd, &thresholds);
441 print_values (&values, &thresholds);
442 break;
443 }
444 close (fd);
445 }
446 return retval;
447 }
448
diff --git a/plugins/check_imap.c b/plugins/check_imap.c
new file mode 100644
index 00000000..5ec0439b
--- /dev/null
+++ b/plugins/check_imap.c
@@ -0,0 +1,340 @@
1/******************************************************************************
2*
3* CHECK_IMAP.C
4*
5* Program: IMAP4 plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Tom Shields (tom.shields@basswood.com)
8*
9* $Id$
10*
11* Description:
12*
13* This plugin will attempt to open an IMAP connection with the host.
14* Successul connects return STATE_OK, refusals and timeouts return
15* STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful
16* connects, but incorrect reponse messages from the host result in
17* STATE_WARNING return values.
18*
19* Modifications:
20* 04-13-1999 Tom Shields
21* Initial code
22* 08-18-1999 Ethan Galstad <nagios@nagios.org>
23* Modified code to work with common plugin functions, added socket
24* timeout, string * length checking
25* 09-19-1999 Ethan Galstad <nagios@nagios.org>
26* Changed expect string from "+OK" to "* OK" and default port to 143
27*****************************************************************************/
28
29#include "config.h"
30#include "common.h"
31#include "netutils.h"
32#include "utils.h"
33
34#define PROGNAME "check_imap"
35
36#define PORT 143
37#define EXPECT "* OK"
38#define QUIT "a1 LOGOUT\n"
39
40int process_arguments (int, char **);
41int call_getopt (int, char **);
42int validate_arguments (void);
43int check_disk (int usp, int free_disk);
44void print_help (void);
45void print_usage (void);
46
47int server_port = PORT;
48char *server_address = NULL;
49char *server_expect = NULL;
50int warning_time = 0;
51int check_warning_time = FALSE;
52int critical_time = 0;
53int check_critical_time = FALSE;
54int verbose = FALSE;
55
56int
57main (int argc, char **argv)
58{
59 int sd;
60 int result;
61 char buffer[MAX_INPUT_BUFFER];
62
63 if (process_arguments (argc, argv) != OK)
64 usage ("Invalid command arguments supplied\n");
65
66 /* initialize alarm signal handling */
67 signal (SIGALRM, socket_timeout_alarm_handler);
68
69 /* set socket timeout */
70 alarm (socket_timeout);
71
72 /* try to connect to the host at the given port number */
73 time (&start_time);
74 result = my_tcp_connect (server_address, server_port, &sd);
75
76 /* we connected, so close connection before exiting */
77 if (result == STATE_OK) {
78
79 /* watch for the IMAP connection string */
80 result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
81
82 /* strip carriange returns */
83 strip (buffer);
84
85 /* return a WARNING status if we couldn't read any data */
86 if (result == -1) {
87 printf ("recv() failed\n");
88 result = STATE_WARNING;
89 }
90
91 else {
92
93 /* make sure we find the response we are looking for */
94 if (!strstr (buffer, server_expect)) {
95 if (server_port == server_port)
96 printf ("Invalid IMAP response received from host\n");
97 else
98 printf ("Invalid IMAP response received from host on port %d\n",
99 server_port);
100 result = STATE_WARNING;
101 }
102
103 else {
104 time (&end_time);
105 printf ("IMAP ok - %d second response time\n",
106 (int) (end_time - start_time));
107 result = STATE_OK;
108 }
109 }
110
111 /* close the connection */
112 send (sd, QUIT, strlen (QUIT), 0);
113 close (sd);
114 }
115
116 /* reset the alarm handler */
117 alarm (0);
118
119 return result;
120}
121
122
123
124
125
126/* process command-line arguments */
127int
128process_arguments (int argc, char **argv)
129{
130 int c;
131
132 if (argc < 2)
133 return ERROR;
134
135 for (c = 1; c < argc; c++) {
136 if (strcmp ("-to", argv[c]) == 0)
137 strcpy (argv[c], "-t");
138 else if (strcmp ("-wt", argv[c]) == 0)
139 strcpy (argv[c], "-w");
140 else if (strcmp ("-ct", argv[c]) == 0)
141 strcpy (argv[c], "-c");
142 }
143
144
145
146 c = 0;
147 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
148
149 if (is_option (argv[c]))
150 continue;
151
152 if (server_address == NULL) {
153 if (is_host (argv[c])) {
154 server_address = argv[c];
155 }
156 else {
157 usage ("Invalid host name");
158 }
159 }
160 }
161
162 if (server_address == NULL)
163 server_address = strscpy (NULL, "127.0.0.1");
164
165 if (server_expect == NULL)
166 server_expect = strscpy (NULL, EXPECT);
167
168 return validate_arguments ();
169}
170
171
172
173
174
175
176int
177call_getopt (int argc, char **argv)
178{
179 int c, i = 0;
180
181#ifdef HAVE_GETOPT_H
182 int option_index = 0;
183 static struct option long_options[] = {
184 {"hostname", required_argument, 0, 'H'},
185 {"expect", required_argument, 0, 'e'},
186 {"critical", required_argument, 0, 'c'},
187 {"warning", required_argument, 0, 'w'},
188 {"port", required_argument, 0, 'P'},
189 {"verbose", no_argument, 0, 'v'},
190 {"version", no_argument, 0, 'V'},
191 {"help", no_argument, 0, 'h'},
192 {0, 0, 0, 0}
193 };
194#endif
195
196 while (1) {
197#ifdef HAVE_GETOPT_H
198 c =
199 getopt_long (argc, argv, "+hVvt:p:e:c:w:H:", long_options,
200 &option_index);
201#else
202 c = getopt (argc, argv, "+?hVvt:p:e:c:w:H:");
203#endif
204
205 i++;
206
207 if (c == -1 || c == EOF || c == 1)
208 break;
209
210 switch (c) {
211 case 't':
212 case 'p':
213 case 'e':
214 case 'c':
215 case 'w':
216 case 'H':
217 i++;
218 }
219
220 switch (c) {
221 case 'H': /* hostname */
222 if (is_host (optarg)) {
223 server_address = optarg;
224 }
225 else {
226 usage ("Invalid host name\n");
227 }
228 break;
229 case 'p': /* port */
230 if (is_intpos (optarg)) {
231 server_port = atoi (optarg);
232 }
233 else {
234 usage ("Server port must be a positive integer\n");
235 }
236 break;
237 case 'e': /* username */
238 server_expect = optarg;
239 break;
240 case 'c': /* critical time threshold */
241 if (is_intnonneg (optarg)) {
242 critical_time = atoi (optarg);
243 check_critical_time = TRUE;
244 }
245 else {
246 usage ("Critical time must be a nonnegative integer\n");
247 }
248 break;
249 case 'w': /* warning time threshold */
250 if (is_intnonneg (optarg)) {
251 warning_time = atoi (optarg);
252 check_warning_time = TRUE;
253 }
254 else {
255 usage ("Warning time must be a nonnegative integer\n");
256 }
257 break;
258 case 'v': /* verbose */
259 verbose = TRUE;
260 break;
261 case 't': /* timeout */
262 if (is_intnonneg (optarg)) {
263 socket_timeout = atoi (optarg);
264 }
265 else {
266 usage ("Time interval must be a nonnegative integer\n");
267 }
268 break;
269 case 'V': /* version */
270 print_revision (PROGNAME, "$Revision$");
271 exit (STATE_OK);
272 case 'h': /* help */
273 print_help ();
274 exit (STATE_OK);
275 case '?': /* help */
276 usage ("Invalid argument\n");
277 }
278 }
279 return i;
280}
281
282
283
284
285
286int
287validate_arguments (void)
288{
289 return OK;
290}
291
292
293
294
295
296void
297print_help (void)
298{
299 print_revision (PROGNAME, "$Revision$");
300 printf
301 ("Copyright (c) 2000 Tom Shields/Karl DeBisschop\n\n"
302 "This plugin tests the IMAP4 service on the specified host.\n\n");
303 print_usage ();
304 printf
305 ("\nOptions:\n"
306 " -H, --hostname=STRING or IPADDRESS\n"
307 " Check server on the indicated host\n"
308 " -p, --port=INTEGER\n"
309 " Make connection on the indicated port (default: %d)\n"
310 " -e, --expect=STRING\n"
311 " String to expect in first line of server response (default: %s)\n"
312 " -w, --warning=INTEGER\n"
313 " Seconds necessary to result in a warning status\n"
314 " -c, --critical=INTEGER\n"
315 " Seconds necessary to result in a critical status\n"
316 " -t, --timeout=INTEGER\n"
317 " Seconds before connection attempt times out (default: %d)\n"
318 " -v, --verbose\n"
319 " Print extra information (command-line use only)\n"
320 " -h, --help\n"
321 " Print detailed help screen\n"
322 " -V, --version\n"
323 " Print version information\n\n",
324 PORT, EXPECT, DEFAULT_SOCKET_TIMEOUT);
325 support ();
326}
327
328
329
330
331
332void
333print_usage (void)
334{
335 printf
336 ("Usage: %s -H host [-e expect] [-p port] [-w warn] [-c crit]\n"
337 " [-t timeout] [-v]\n"
338 " %s --help\n"
339 " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
340}
diff --git a/plugins/check_ldap.c b/plugins/check_ldap.c
new file mode 100644
index 00000000..d3f06158
--- /dev/null
+++ b/plugins/check_ldap.c
@@ -0,0 +1,291 @@
1/***************************************************************************** *
2 * CHECK_LDAP.C
3 *
4 * Program: Ldap plugin for Nagios
5 * License: GPL
6 * Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
7 *
8 * Last Modified: $Date$
9 *
10 * Command line: check_ldap -h <host> -b <base_dn> -p <port> -w <warn_time> -w <crit_time>
11 *
12 * Description:
13 *
14 * This plugin is for testing a ldap server.
15 *
16 * Modifications:
17 *
18 * 08-25-1999 Ethan Galstad (nagios@nagios.org)
19 * Modified to use common plugin include file
20 *
21 *****************************************************************************/
22
23#define PROGNAME "check_ldap"
24#define REVISION "$Revision$"
25
26#include "config.h"
27#include "common.h"
28#include "netutils.h"
29#include "utils.h"
30
31#include <lber.h>
32#include <ldap.h>
33
34#define UNKNOWN -1
35
36int process_arguments (int, char **);
37int call_getopt (int, char **);
38int validate_arguments (void);
39static void print_help (void);
40static void print_usage (void);
41
42char ld_defattr[] = "(objectclass=*)";
43char *ld_attr = ld_defattr;
44char *ld_host = NULL, *ld_base = NULL, *ld_passwd = NULL, *ld_binddn = NULL;
45unsigned int ld_port = 389;
46int warn_time = UNKNOWN, crit_time = UNKNOWN;
47
48int
49main (int argc, char *argv[])
50{
51
52 LDAP *ld;
53 LDAPMessage *result;
54
55 int t_diff;
56 time_t time0, time1;
57
58 if (process_arguments (argc, argv) == ERROR)
59 usage ("check_ldap: could not parse arguments\n");
60
61 /* initialize alarm signal handling */
62 signal (SIGALRM, socket_timeout_alarm_handler);
63
64 /* set socket timeout */
65 alarm (socket_timeout);
66
67 /* get the start time */
68 time (&time0);
69
70 /* initialize ldap */
71 if (!(ld = ldap_open (ld_host, ld_port))) {
72 /*ldap_perror(ld, "ldap_open"); */
73 printf ("Could not connect to the server at port %i\n", ld_port);
74 return STATE_CRITICAL;
75 }
76
77 /* bind to the ldap server */
78 if (ldap_bind_s (ld, ld_binddn, ld_passwd, LDAP_AUTH_SIMPLE) !=
79 LDAP_SUCCESS) {
80 /*ldap_perror(ld, "ldap_bind"); */
81 printf ("Could not bind to the ldap-server\n");
82 return STATE_CRITICAL;
83 }
84
85 /* do a search of all objectclasses in the base dn */
86 if (ldap_search_s (ld, ld_base, LDAP_SCOPE_BASE, ld_attr, NULL, 0, &result)
87 != LDAP_SUCCESS) {
88 /*ldap_perror(ld, "ldap_search"); */
89 printf ("Could not search/find objectclasses in %s\n", ld_base);
90 return STATE_CRITICAL;
91 }
92
93 /* unbind from the ldap server */
94 ldap_unbind (ld);
95
96 /* reset the alarm handler */
97 alarm (0);
98
99 /* get the finish time */
100 time (&time1);
101
102 /* calcutate the elapsed time */
103 t_diff = time1 - time0;
104
105 /* check if warn_time or crit_time was exceeded */
106 if ((t_diff >= warn_time) && (t_diff < crit_time)) {
107 printf ("LDAP warning - %i seconds response time\n", t_diff);
108 return STATE_WARNING;
109 }
110 if (t_diff >= crit_time) {
111 printf ("LDAP critical - %i seconds response time\n", t_diff);
112 return STATE_CRITICAL;
113 }
114
115 /* print out the result */
116 printf ("LDAP ok - %i seconds response time\n", t_diff);
117
118 return STATE_OK;
119}
120
121/* process command-line arguments */
122int
123process_arguments (int argc, char **argv)
124{
125 int c;
126
127 if (argc < 2)
128 return ERROR;
129
130 for (c = 1; c < argc; c++) {
131 if (strcmp ("-to", argv[c]) == 0)
132 strcpy (argv[c], "-t");
133 }
134
135 c = 0;
136 while (c += (call_getopt (argc - c, &argv[c]))) {
137 if (argc <= c)
138 break;
139 if (ld_host[0] == 0) {
140 strncpy (ld_host, argv[c], sizeof (ld_host) - 1);
141 ld_host[sizeof (ld_host) - 1] = 0;
142 }
143 }
144
145 return c;
146}
147
148int
149call_getopt (int argc, char **argv)
150{
151 int c, i = 1;
152#ifdef HAVE_GETOPT_H
153 int option_index = 0;
154 /* initialize the long option struct */
155 static struct option long_options[] = {
156 {"help", no_argument, 0, 'h'},
157 {"version", no_argument, 0, 'V'},
158 {"timeout", required_argument, 0, 't'},
159 {"host", required_argument, 0, 'H'},
160 {"base", required_argument, 0, 'b'},
161 {"attr", required_argument, 0, 'a'},
162 {"bind", required_argument, 0, 'D'},
163 {"pass", required_argument, 0, 'P'},
164 {"port", required_argument, 0, 'p'},
165 {"warn", required_argument, 0, 'w'},
166 {"crit", required_argument, 0, 'c'},
167 {0, 0, 0, 0}
168 };
169#endif
170
171 for (c = 1; c < argc; c++)
172 if (strcmp ("-to", argv[c]) == 0)
173 strcpy (argv[c], "-t");
174
175 while (1) {
176#ifdef HAVE_GETOPT_H
177 c =
178 getopt_long (argc, argv, "+hVt:c:w:H:b:p:a:D:P:", long_options,
179 &option_index);
180#else
181 c = getopt (argc, argv, "+?hVt:c:w:H:b:p:a:D:P:");
182#endif
183
184 if (c == -1 || c == EOF)
185 break;
186
187 i++;
188 switch (c) {
189 case 't':
190 case 'c':
191 case 'w':
192 case 'H':
193 case 'b':
194 case 'p':
195 case 'a':
196 case 'D':
197 case 'P':
198 i++;
199 }
200
201 switch (c) {
202 case 'h': /* help */
203 print_help ();
204 exit (STATE_OK);
205 case 'V': /* version */
206 print_revision (PROGNAME, REVISION);
207 exit (STATE_OK);
208 case 't': /* timeout period */
209 if (!is_intnonneg (optarg))
210 usage2 ("timeout interval must be an integer", optarg);
211 socket_timeout = atoi (optarg);
212 break;
213 case 'H':
214 ld_host = optarg;
215 break;
216 case 'b':
217 ld_base = optarg;
218 break;
219 case 'p':
220 ld_port = atoi (optarg);
221 break;
222 case 'a':
223 ld_attr = optarg;
224 break;
225 case 'D':
226 ld_binddn = optarg;
227 break;
228 case 'P':
229 ld_passwd = optarg;
230 break;
231 case 'w':
232 warn_time = atoi (optarg);
233 break;
234 case 'c':
235 crit_time = atoi (optarg);
236 break;
237 default:
238 usage ("check_ldap: could not parse arguments\n");
239 break;
240 }
241 }
242 return i;
243}
244
245int
246validate_arguments ()
247{
248 if (ld_host[0] == 0 ||
249 ld_base[0] == 0 ||
250 ld_port == UNKNOWN || warn_time == UNKNOWN || crit_time == UNKNOWN) {
251 return ERROR;
252 }
253 else {
254 return OK;
255 }
256}
257
258
259
260/* function print_help */
261static void
262print_help ()
263{
264 print_revision (PROGNAME, REVISION);
265 printf
266 ("Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)\n"
267 "License: GPL\n" "\n");
268 print_usage ();
269 printf
270 ("\n"
271 "Options:\n"
272 "\t-H [--host] ... host\n"
273 "\t-a [--attr] ... ldap attribute to search (default: \"(objectclass=*)\"\n"
274 "\t-b [--base] ... ldap base (eg. ou=my unit, o=my org, c=at)\n"
275 "\t-D [--bind] ... ldap bind DN (if required)\n"
276 "\t-P [--pass] ... ldap password (if required)\n"
277 "\t-p [--port] ... ldap port (normaly 389)\n"
278 "\t-w [--warn] ... time in secs. - if the exceeds <warn> the STATE_WARNING will be returned\n"
279 "\t-c [--crit] ... time in secs. - if the exceeds <crit> the STATE_CRITICAL will be returned\n"
280 "\n");
281}
282
283
284static void
285print_usage ()
286{
287 printf
288 ("Usage: %s -H <host> -b <base_dn> -p <port> [-a <attr>] [-D <binddn>]\n"
289 " [-P <password>] [-w <warn_time>] [-c <crit_time>] [-t timeout]\n"
290 "(Note: all times are in seconds.)\n", PROGNAME);
291}
diff --git a/plugins/check_load.c b/plugins/check_load.c
new file mode 100644
index 00000000..6673b1dc
--- /dev/null
+++ b/plugins/check_load.c
@@ -0,0 +1,321 @@
1/******************************************************************************
2 *
3 * CHECK_LOAD.C
4 *
5 * Written by Felipe Gustavo de Almeida <galmeida@linux.ime.usp.br>
6 * License: GPL
7 * Command line: CHECK_LOAD <wload1> <cload1> <wload5> <cload5> <wload15> <cload15>
8 * First Written: 04/17/99
9 *
10 * Modifications:
11 *
12 * 05/18/1999 - Modified to work getloadavg where available, and use uptime
13 * where neither proc or getloadavg are found. Also use autoconf.
14 * mods by Karl DeBisschop (kdebiss@alum.mit.edu)
15 * 07/01/1999 - Added some #DEFINEs to allow compilation under NetBSD, as
16 * suggested by Andy Doran.
17 * mods by Ethan Galstad (nagios@nagios.org)
18 * 07/17/1999 - Initialized la[] array to prevent NetBSD from complaining
19 * mods by Ethan Galstad (nagios@nagios.org)
20 * 08/18/1999 - Integrated some code with common plugin utilities
21 * mods by Ethan Galstad (nagios@nagios.org)
22 * $Date$
23 * Note: The load format is the same used by "uptime" and "w"
24 *
25 *****************************************************************************/
26
27#include "config.h"
28#include "common.h"
29#include "utils.h"
30
31#ifdef HAVE_SYS_LOADAVG_H
32#include <sys/loadavg.h>
33#endif
34
35/* needed for compilation under NetBSD, as suggested by Andy Doran */
36#ifndef LOADAVG_1MIN
37#define LOADAVG_1MIN 0
38#define LOADAVG_5MIN 1
39#define LOADAVG_15MIN 2
40#endif /* !defined LOADAVG_1MIN */
41
42#include "popen.h"
43#ifdef HAVE_PROC_LOADAVG
44
45#endif
46
47#define PROGNAME "check_load"
48
49int process_arguments (int argc, char **argv);
50int call_getopt (int argc, char **argv);
51int validate_arguments (void);
52void print_usage (void);
53void print_help (void);
54
55float wload1 = -1, wload5 = -1, wload15 = -1;
56float cload1 = -1, cload5 = -1, cload15 = -1;
57
58int
59main (int argc, char **argv)
60{
61#if HAVE_GETLOADAVG==1
62 int result;
63 double la[3] = { 0.0, 0.0, 0.0 }; /* NetBSD complains about unitialized arrays */
64#elif HAVE_PROC_LOADAVG==1
65 FILE *fp;
66 char input_buffer[MAX_INPUT_BUFFER];
67 char *tmp_ptr;
68#else
69 int result;
70 char input_buffer[MAX_INPUT_BUFFER];
71#endif
72
73 float la1, la5, la15;
74
75 if (process_arguments (argc, argv) == ERROR)
76 usage ("\n");
77
78#if HAVE_GETLOADAVG==1
79 result = getloadavg (la, 3);
80 if (result == -1)
81 return STATE_UNKNOWN;
82 la1 = la[LOADAVG_1MIN];
83 la5 = la[LOADAVG_5MIN];
84 la15 = la[LOADAVG_15MIN];
85#elif HAVE_PROC_LOADAVG==1
86 fp = fopen (PROC_LOADAVG, "r");
87 if (fp == NULL) {
88 printf ("Error opening %s\n", PROC_LOADAVG);
89 return STATE_UNKNOWN;
90 }
91
92 la1 = la5 = la15 = -1;
93
94 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
95 tmp_ptr = strtok (input_buffer, " ");
96 la1 = atof (tmp_ptr);
97 tmp_ptr = strtok (NULL, " ");
98 la5 = atof (tmp_ptr);
99 tmp_ptr = strtok (NULL, " ");
100 la15 = atof (tmp_ptr);
101 }
102
103 fclose (fp);
104#else
105 child_process = spopen (PATH_TO_UPTIME);
106 if (child_process == NULL) {
107 printf ("Error opening %s\n", PATH_TO_UPTIME);
108 return STATE_UNKNOWN;
109 }
110 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
111 if (child_stderr == NULL) {
112 printf ("Could not open stderr for %s\n", PATH_TO_UPTIME);
113 }
114 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
115 sscanf (input_buffer, "%*[^l]load average: %f, %f, %f", &la1, &la5, &la15);
116
117 result = spclose (child_process);
118 if (result) {
119 printf ("Error code %d returned in %s\n", result, PATH_TO_UPTIME);
120 return STATE_UNKNOWN;
121 }
122#endif
123
124 if ((la1 == -1) || (la5 == -1) || (la15 == -1)) {
125#if HAVE_GETLOADAVG==1
126 printf ("Error in getloadavg()\n");
127#elif HAVE_PROC_LOADAVG==1
128 printf ("Error processing %s\n", PROC_LOADAVG);
129#else
130 printf ("Error processing %s\n", PATH_TO_UPTIME);
131#endif
132 return STATE_UNKNOWN;
133 }
134 printf ("load average: %.2f, %.2f, %.2f", la1, la5, la15);
135 if ((la1 >= cload1) || (la5 >= cload5) || (la15 >= cload15)) {
136 printf (" CRITICAL\n");
137 return STATE_CRITICAL;
138 }
139 if ((la1 >= wload1) || (la5 >= wload5) || (la15 >= wload15)) {
140 printf (" WARNING\n");
141 return STATE_WARNING;
142 }
143 printf ("\n");
144 return STATE_OK;
145}
146
147
148
149
150
151/* process command-line arguments */
152int
153process_arguments (int argc, char **argv)
154{
155 int c;
156
157 if (argc < 2)
158 return ERROR;
159
160 c = 0;
161 while (c += (call_getopt (argc - c, &argv[c]))) {
162 if (argc <= c)
163 break;
164
165 if (wload1 < 0 && is_nonnegative (argv[c]))
166 wload1 = atof (argv[c]);
167 else if (cload1 < 0 && is_nonnegative (argv[c]))
168 cload1 = atof (argv[c]);
169 else if (wload5 < 0 && is_nonnegative (argv[c]))
170 wload5 = atof (argv[c]);
171 else if (cload5 < 0 && is_nonnegative (argv[c]))
172 cload5 = atof (argv[c]);
173 else if (wload15 < 0 && is_nonnegative (argv[c]))
174 wload15 = atof (argv[c]);
175 else if (cload15 < 0 && is_nonnegative (argv[c]))
176 cload15 = atof (argv[c]);
177 }
178
179 return validate_arguments ();
180}
181
182
183
184
185
186int
187call_getopt (int argc, char **argv)
188{
189 int c, i = 0;
190
191#ifdef HAVE_GETOPT_H
192 int option_index = 0;
193 static struct option long_options[] = {
194 {"warning", required_argument, 0, 'w'},
195 {"critical", required_argument, 0, 'c'},
196 {"version", no_argument, 0, 'V'},
197 {"help", no_argument, 0, 'h'},
198 {0, 0, 0, 0}
199 };
200#endif
201
202 while (1) {
203#ifdef HAVE_GETOPT_H
204 c = getopt_long (argc, argv, "+?Vhc:w:", long_options, &option_index);
205#else
206 c = getopt (argc, argv, "+?Vhc:w:");
207#endif
208
209 i++;
210
211 if (c == -1 || c == EOF)
212 break;
213
214 switch (c) {
215 case 'c':
216 case 'w':
217 i++;
218 }
219
220 switch (c) {
221 case 'w': /* warning time threshold */
222 if (is_intnonneg (optarg)) {
223 if (wload1 < 0 && is_nonnegative (argv[c]))
224 wload1 = atof (argv[c]);
225 else if (wload5 < 0 && is_nonnegative (argv[c]))
226 wload5 = atof (argv[c]);
227 else if (wload15 < 0 && is_nonnegative (argv[c]))
228 wload15 = atof (argv[c]);
229 break;
230 }
231 else if (strstr (optarg, ",") &&
232 sscanf (optarg, "%f,%f,%f", &wload1, &wload5, &wload15) == 3) {
233 break;
234 }
235 else {
236 usage ("Warning threshold must be float or float triplet!\n");
237 }
238 case 'c': /* critical time threshold */
239 if (is_intnonneg (optarg)) {
240 if (cload1 < 0 && is_nonnegative (argv[c]))
241 cload1 = atof (argv[c]);
242 else if (cload5 < 0 && is_nonnegative (argv[c]))
243 cload5 = atof (argv[c]);
244 else if (cload15 < 0 && is_nonnegative (argv[c]))
245 cload15 = atof (argv[c]);
246 break;
247 }
248 else if (strstr (optarg, ",") &&
249 sscanf (optarg, "%f,%f,%f", &cload1, &cload5, &cload15) == 3) {
250 break;
251 }
252 else {
253 usage ("Critical threshold must be float or float triplet!\n");
254 }
255 case 'V': /* version */
256 print_revision (my_basename (argv[0]), "$Revision$");
257 exit (STATE_OK);
258 case 'h': /* help */
259 print_help ();
260 exit (STATE_OK);
261 case '?': /* help */
262 usage ("Invalid argument\n");
263 }
264 }
265 return i;
266}
267
268
269
270
271
272int
273validate_arguments (void)
274{
275 if ((wload1 > cload1) || (wload5 > cload5) || (wload15 > cload15)) {
276 printf
277 ("Inconsistence in parameters: \"warning load\" greater than \"critical load\".\n");
278 return STATE_UNKNOWN;
279 }
280
281 return OK;
282}
283
284
285
286
287
288void
289print_usage (void)
290{
291 printf
292 ("Usage: check_load -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n"
293 " check_load --version\n" " check_load --help\n");
294}
295
296
297
298
299
300void
301print_help (void)
302{
303 print_revision (PROGNAME, "$Revision$");
304 printf
305 ("Copyright (c) 1999 Felipe Gustavo de Almeida <galmeida@linux.ime.usp.br>\n"
306 "Copyright (c) 2000 Karl DeBisschop\n\n"
307 "This plugin tests the current system load average.\n\n");
308 print_usage ();
309 printf
310 ("\nOptions:\n"
311 " -w, --warning=WLOAD1,WLOAD5,WLOAD15\n"
312 " Exit with WARNING status if load average exceeds WLOADn\n"
313 " -c, --critical=CLOAD1,CLOAD5,CLOAD15\n"
314 " Exit with CRITICAL status if load average exceed CLOADn\n"
315 " -h, --help\n"
316 " Print detailed help screen\n"
317 " -V, --version\n"
318 " Print version information\n\n"
319 "the load average format is the same used by \"uptime\" and \"w\"\n\n");
320 support ();
321}
diff --git a/plugins/check_mrtg.c b/plugins/check_mrtg.c
new file mode 100644
index 00000000..b86686d7
--- /dev/null
+++ b/plugins/check_mrtg.c
@@ -0,0 +1,413 @@
1/******************************************************************************
2 *
3 * Program: MRTG (Multi-Router Traffic Grapher) generic plugin for Nagios
4 * License: GPL
5 *
6 * License Information:
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * $Id$
23 *
24 *****************************************************************************/
25
26#define PROGNAME "check_mrtg"
27#define REVISION "$Revision$"
28#define COPYRIGHT "Copyright (c) 1999-2001 Ethan Galstad"
29
30#define SUMMARY "\
31This plugin will check either the average or maximum value of one of the\n\
32two variables recorded in an MRTG log file.\n"
33
34/* old command line:
35 <log_file> <expire_minutes> <AVG|MAX> <variable> <vwl> <vcl> <label> [units] */
36#define OPTIONS "\
37-F log_file -a <AVG | MAX> -v variable -w warning -c critical\n\
38 [-l label] [-u units] [-e expire_minutes] [-t timeout] [-v]"
39
40#define LONGOPTIONS "\
41 -F, --logfile=FILE\n\
42 The MRTG log file containing the data you want to monitor\n\
43 -e, --expires=MINUTES\n\
44 Minutes before MRTG data is considered to be too old\n\
45 -a, --aggregation=AVG|MAX\n\
46 Should we check average or maximum values?\n\
47 -v, --variable=INTEGER\n\
48 Which variable set should we inspect? 1 or 2?\n\
49 -w, --warning=INTEGER\n\
50 Threshold value for data to result in WARNING status\n\
51 -c, --critical=INTEGER\n\
52 Threshold value for data to result in CRITICAL status\n\
53 -l, --label=STRING\n\
54 Type label for data (Examples: Conns, \"Processor Load\", In, Out)\n\
55 -u, --units=STRING\n\
56 Option units label for data (Example: Packets/Sec, Errors/Sec, \n\
57 \"Bytes Per Second\", \"%% Utilization\")\n\
58 -h, --help\n\
59 Print detailed help screen\n\
60 -V, --version\n\
61 Print version information\n"
62
63#define DESCRIPTION "\
64If the value exceeds the <vwl> threshold, a WARNING status is returned. If\n\
65the value exceeds the <vcl> threshold, a CRITICAL status is returned. If\n\
66the data in the log file is older than <expire_minutes> old, a WARNING\n\
67status is returned and a warning message is printed.\n\
68\n\
69This plugin is useful for monitoring MRTG data that does not correspond to\n\
70bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth).\n\
71It can be used to monitor any kind of data that MRTG is monitoring - errors,\n\
72packets/sec, etc. I use MRTG in conjuction with the Novell NLM that allows\n\
73me to track processor utilization, user connections, drive space, etc and\n\
74this plugin works well for monitoring that kind of data as well.\n\
75\n\
76Notes:\n\
77- This plugin only monitors one of the two variables stored in the MRTG log\n\
78 file. If you want to monitor both values you will have to define two\n\
79 commands with different values for the <variable> argument. Of course,\n\
80 you can always hack the code to make this plugin work for you...\n\
81- MRTG stands for the Multi Router Traffic Grapher. It can be downloaded from\n\
82 http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html\n"
83
84#include "config.h"
85#include "common.h"
86#include "utils.h"
87
88int process_arguments (int, char **);
89int call_getopt (int, char **);
90int validate_arguments (void);
91void print_help (void);
92void print_usage (void);
93
94char *log_file = NULL;
95int expire_minutes = 0;
96int use_average = TRUE;
97int variable_number = -1;
98unsigned long value_warning_threshold = 0L;
99unsigned long value_critical_threshold = 0L;
100char *value_label = NULL;
101char *units_label = NULL;
102
103int
104main (int argc, char **argv)
105{
106 int result = STATE_OK;
107 FILE *fp;
108 int line;
109 char input_buffer[MAX_INPUT_BUFFER];
110 char *temp_buffer;
111 time_t current_time;
112 char error_message[MAX_INPUT_BUFFER];
113 time_t timestamp = 0L;
114 unsigned long average_value_rate = 0L;
115 unsigned long maximum_value_rate = 0L;
116 unsigned long value_rate = 0L;
117
118 if (process_arguments (argc, argv) != OK)
119 usage ("Invalid command arguments supplied\n");
120
121 /* open the MRTG log file for reading */
122 fp = fopen (log_file, "r");
123 if (fp == NULL) {
124 printf ("Unable to open MRTG log file\n");
125 return STATE_UNKNOWN;
126 }
127
128 line = 0;
129 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
130
131 line++;
132
133 /* skip the first line of the log file */
134 if (line == 1)
135 continue;
136
137 /* break out of read loop if we've passed the number of entries we want to read */
138 if (line > 2)
139 break;
140
141 /* grab the timestamp */
142 temp_buffer = strtok (input_buffer, " ");
143 timestamp = strtoul (temp_buffer, NULL, 10);
144
145 /* grab the average value 1 rate */
146 temp_buffer = strtok (NULL, " ");
147 if (variable_number == 1)
148 average_value_rate = strtoul (temp_buffer, NULL, 10);
149
150 /* grab the average value 2 rate */
151 temp_buffer = strtok (NULL, " ");
152 if (variable_number == 2)
153 average_value_rate = strtoul (temp_buffer, NULL, 10);
154
155 /* grab the maximum value 1 rate */
156 temp_buffer = strtok (NULL, " ");
157 if (variable_number == 1)
158 maximum_value_rate = strtoul (temp_buffer, NULL, 10);
159
160 /* grab the maximum value 2 rate */
161 temp_buffer = strtok (NULL, " ");
162 if (variable_number == 2)
163 maximum_value_rate = strtoul (temp_buffer, NULL, 10);
164 }
165
166 /* close the log file */
167 fclose (fp);
168
169 /* if we couldn't read enough data, return an unknown error */
170 if (line <= 2) {
171 result = STATE_UNKNOWN;
172 sprintf (error_message, "Unable to process MRTG log file\n");
173 }
174
175 /* make sure the MRTG data isn't too old */
176 if (result == STATE_OK) {
177 time (&current_time);
178 if (expire_minutes > 0
179 && (current_time - timestamp) > (expire_minutes * 60)) {
180 result = STATE_WARNING;
181 sprintf (error_message, "MRTG data has expired (%d minutes old)\n",
182 (int) ((current_time - timestamp) / 60));
183 }
184 }
185
186 /* else check the incoming/outgoing rates */
187 if (result == STATE_OK) {
188
189 if (use_average == TRUE)
190 value_rate = average_value_rate;
191 else
192 value_rate = maximum_value_rate;
193
194 if (value_rate > value_critical_threshold)
195 result = STATE_CRITICAL;
196 else if (value_rate > value_warning_threshold)
197 result = STATE_WARNING;
198 }
199
200 sprintf (error_message, "%s. %s = %lu %s",
201 (use_average == TRUE) ? "Ave" : "Max", value_label, value_rate,
202 units_label);
203 printf ("%s\n", error_message);
204
205 return result;
206}
207
208
209
210
211
212/* process command-line arguments */
213int
214process_arguments (int argc, char **argv)
215{
216 int c;
217
218 if (argc < 2)
219 return ERROR;
220
221 for (c = 1; c < argc; c++) {
222 if (strcmp ("-to", argv[c]) == 0)
223 strcpy (argv[c], "-t");
224 else if (strcmp ("-wt", argv[c]) == 0)
225 strcpy (argv[c], "-w");
226 else if (strcmp ("-ct", argv[c]) == 0)
227 strcpy (argv[c], "-c");
228 }
229
230
231
232 c = 0;
233 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
234
235 if (is_option (argv[c]))
236 continue;
237
238 if (log_file == NULL) {
239 log_file = argv[c];
240 }
241 else if (expire_minutes <= 0) {
242 if (is_intpos (argv[c]))
243 expire_minutes = atoi (argv[c]);
244 else
245 terminate (STATE_UNKNOWN,
246 "%s is not a valid expiration time\nUse '%s -h' for additional help\n",
247 argv[c], PROGNAME);
248 }
249 else if (strcmp (argv[c], "MAX") == 0) {
250 use_average = FALSE;
251 }
252 else if (strcmp (argv[c], "AVG") == 0) {
253 use_average = TRUE;
254 }
255 else if (variable_number == -1) {
256 variable_number = atoi (argv[c]);
257 if (variable_number < 1 || variable_number > 2) {
258 printf ("%s :", argv[c]);
259 usage ("Invalid variable number\n");
260 }
261 }
262 else if (value_warning_threshold == 0) {
263 value_warning_threshold = strtoul (argv[c], NULL, 10);
264 }
265 else if (value_critical_threshold == 0) {
266 value_critical_threshold = strtoul (argv[c], NULL, 10);
267 }
268 else if (value_label == NULL) {
269 value_label = argv[c];
270 }
271 else if (units_label == NULL) {
272 units_label = argv[c];
273 }
274 }
275
276 if (value_label == NULL)
277 value_label = strscpy (NULL, "");
278
279 if (units_label == NULL)
280 units_label = strscpy (NULL, "");
281
282 return validate_arguments ();
283}
284
285
286
287
288
289
290int
291call_getopt (int argc, char **argv)
292{
293 int c, i = 0;
294
295#ifdef HAVE_GETOPT_H
296 int option_index = 0;
297 static struct option long_options[] = {
298 {"logfile", required_argument, 0, 'F'},
299 {"expires", required_argument, 0, 'e'},
300 {"aggregation", required_argument, 0, 'a'},
301 {"variable", required_argument, 0, 'v'},
302 {"critical", required_argument, 0, 'c'},
303 {"warning", required_argument, 0, 'w'},
304 {"label", required_argument, 0, 'l'},
305 {"units", required_argument, 0, 'u'},
306 {"verbose", no_argument, 0, 'v'},
307 {"version", no_argument, 0, 'V'},
308 {"help", no_argument, 0, 'h'},
309 {0, 0, 0, 0}
310 };
311#endif
312
313 while (1) {
314#ifdef HAVE_GETOPT_H
315 c =
316 getopt_long (argc, argv, "+hVF:e:a:v:c:w:l:u:", long_options,
317 &option_index);
318#else
319 c = getopt (argc, argv, "+?hVF:e:a:v:c:w:l:u:");
320#endif
321
322 i++;
323
324 if (c == -1 || c == EOF || c == 1)
325 break;
326
327 switch (c) {
328 case 'F':
329 case 'e':
330 case 'a':
331 case 'v':
332 case 'c':
333 case 'w':
334 case 'l':
335 case 'u':
336 i++;
337 }
338
339 switch (c) {
340 case 'F': /* input file */
341 log_file = optarg;
342 break;
343 case 'e': /* ups name */
344 expire_minutes = atoi (optarg);
345 break;
346 case 'a': /* port */
347 if (!strcmp (optarg, "MAX"))
348 use_average = FALSE;
349 else
350 use_average = TRUE;
351 break;
352 case 'v':
353 variable_number = atoi (optarg);
354 if (variable_number < 1 || variable_number > 2)
355 usage ("Invalid variable number\n");
356 break;
357 case 'w': /* critical time threshold */
358 value_warning_threshold = strtoul (optarg, NULL, 10);
359 break;
360 case 'c': /* warning time threshold */
361 value_critical_threshold = strtoul (optarg, NULL, 10);
362 break;
363 case 'l': /* label */
364 value_label = optarg;
365 break;
366 case 'u': /* timeout */
367 units_label = optarg;
368 break;
369 case 'V': /* version */
370 print_revision (PROGNAME, "$Revision$");
371 exit (STATE_OK);
372 case 'h': /* help */
373 print_help ();
374 exit (STATE_OK);
375 case '?': /* help */
376 usage ("Invalid argument\n");
377 }
378 }
379 return i;
380}
381
382int
383validate_arguments (void)
384{
385 if (variable_number == -1)
386 usage ("You must supply the variable number\n");
387
388 return OK;
389}
390
391void
392print_help (void)
393{
394 print_revision (PROGNAME, REVISION);
395 printf ("%s\n\n%s\n", COPYRIGHT, SUMMARY);
396 print_usage ();
397 printf ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n");
398 support ();
399}
400
401void
402print_usage (void)
403{
404 printf ("Usage:\n" " %s %s\n"
405#ifdef HAVE_GETOPT_H
406 " %s (-h | --help) for detailed help\n"
407 " %s (-V | --version) for version information\n",
408#else
409 " %s -h for detailed help\n"
410 " %s -V for version information\n",
411#endif
412 PROGNAME, OPTIONS, PROGNAME, PROGNAME);
413}
diff --git a/plugins/check_mrtgtraf.c b/plugins/check_mrtgtraf.c
new file mode 100644
index 00000000..11f5146b
--- /dev/null
+++ b/plugins/check_mrtgtraf.c
@@ -0,0 +1,419 @@
1/******************************************************************************
2 *
3 * CHECK_MRTGTRAF.C
4 *
5 * Program: MRTG (Multi-Router Traffic Grapher) traffic plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 *
9 * Last Modified: $Date$
10 *
11 * Command line: CHECK_MRTGTRAF <log_file> <expire_minutes> <AVG|MAX> <iwl> <icl> <owl> <ocl>
12 *
13 * Description:
14 *
15 * This plugin will check the incoming/outgoing transfer rates of a
16 * router, switch, etc recorded in an MRTG log. If the newest log
17 * entry is older than <expire_minutes>, a WARNING status is returned.
18 * If either the incoming or outgoing rates exceed the <icl> or <ocl>
19 * thresholds (in Bytes/sec), a CRITICAL status results. If either of
20 * the rates exceed the <iwl> or <owl> thresholds (in Bytes/sec), a
21 * WARNING status results.
22 *
23 * Notes:
24 * - MRTG stands for the Multi Router Traffic Grapher. It can be
25 * downloaded from
26 * http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html
27 * - While MRTG can monitor things other than traffic rates, this
28 * plugin probably won't work with much else without modification.
29 * - The calculated i/o rates are a little off from what MRTG actually
30 * reports. I'm not sure why this is right now, but will look into it
31 * for future enhancements of this plugin.
32 *
33 * License Information:
34 *
35 * This program is free software; you can redistribute it and/or modify
36 * it under the terms of the GNU General Public License as published by
37 * the Free Software Foundation; either version 2 of the License, or
38 * (at your option) any later version.
39 *
40 * This program is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
44 *
45 * You should have received a copy of the GNU General Public License
46 * along with this program; if not, write to the Free Software
47 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
48 *
49 *****************************************************************************/
50
51#include "config.h"
52#include "common.h"
53#include "utils.h"
54
55#define PROGNAME "check_mrtgtraf"
56
57int process_arguments (int, char **);
58int call_getopt (int, char **);
59int validate_arguments (void);
60void print_help (void);
61void print_usage (void);
62
63char *log_file = NULL;
64int expire_minutes = -1;
65int use_average = TRUE;
66unsigned long incoming_warning_threshold = 0L;
67unsigned long incoming_critical_threshold = 0L;
68unsigned long outgoing_warning_threshold = 0L;
69unsigned long outgoing_critical_threshold = 0L;
70
71int
72main (int argc, char **argv)
73{
74 int result = STATE_OK;
75 FILE *fp;
76 int line;
77 char input_buffer[MAX_INPUT_BUFFER];
78 char *temp_buffer;
79 time_t current_time;
80 char error_message[MAX_INPUT_BUFFER];
81 time_t timestamp = 0L;
82 unsigned long average_incoming_rate = 0L;
83 unsigned long average_outgoing_rate = 0L;
84 unsigned long maximum_incoming_rate = 0L;
85 unsigned long maximum_outgoing_rate = 0L;
86 unsigned long incoming_rate = 0L;
87 unsigned long outgoing_rate = 0L;
88 double adjusted_incoming_rate = 0.0;
89 double adjusted_outgoing_rate = 0.0;
90 char incoming_speed_rating[8];
91 char outgoing_speed_rating[8];
92
93 if (process_arguments (argc, argv) != OK)
94 usage ("Invalid command arguments supplied\n");
95
96 /* open the MRTG log file for reading */
97 fp = fopen (log_file, "r");
98 if (fp == NULL)
99 usage ("Unable to open MRTG log file\n");
100
101 line = 0;
102 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
103
104 line++;
105
106 /* skip the first line of the log file */
107 if (line == 1)
108 continue;
109
110 /* break out of read loop */
111 /* if we've passed the number of entries we want to read */
112 if (line > 2)
113 break;
114
115 /* grab the timestamp */
116 temp_buffer = strtok (input_buffer, " ");
117 timestamp = strtoul (temp_buffer, NULL, 10);
118
119 /* grab the average incoming transfer rate */
120 temp_buffer = strtok (NULL, " ");
121 average_incoming_rate = strtoul (temp_buffer, NULL, 10);
122
123 /* grab the average outgoing transfer rate */
124 temp_buffer = strtok (NULL, " ");
125 average_outgoing_rate = strtoul (temp_buffer, NULL, 10);
126
127 /* grab the maximum incoming transfer rate */
128 temp_buffer = strtok (NULL, " ");
129 maximum_incoming_rate = strtoul (temp_buffer, NULL, 10);
130
131 /* grab the maximum outgoing transfer rate */
132 temp_buffer = strtok (NULL, " ");
133 maximum_outgoing_rate = strtoul (temp_buffer, NULL, 10);
134 }
135
136 /* close the log file */
137 fclose (fp);
138
139 /* if we couldn't read enough data, return an unknown error */
140 if (line <= 2)
141 usage ("Unable to process MRTG log file\n");
142
143 /* make sure the MRTG data isn't too old */
144 time (&current_time);
145 if (expire_minutes > 0
146 && (current_time - timestamp) >
147 (expire_minutes * 60)) terminate (STATE_WARNING,
148 "MRTG data has expired (%d minutes old)\n",
149 (int) ((current_time - timestamp) /
150 60));
151
152 /* else check the incoming/outgoing rates */
153 if (use_average == TRUE) {
154 incoming_rate = average_incoming_rate;
155 outgoing_rate = average_outgoing_rate;
156 }
157 else {
158 incoming_rate = maximum_incoming_rate;
159 outgoing_rate = maximum_outgoing_rate;
160 }
161
162 /* report incoming traffic in Bytes/sec */
163 if (incoming_rate < 1024) {
164 strcpy (incoming_speed_rating, "B/s");
165 adjusted_incoming_rate = (double) incoming_rate;
166 }
167
168 /* report incoming traffic in KBytes/sec */
169 else if (incoming_rate < (1024 * 1024)) {
170 strcpy (incoming_speed_rating, "KB/s");
171 adjusted_incoming_rate = (double) (incoming_rate / 1024.0);
172 }
173
174 /* report incoming traffic in MBytes/sec */
175 else {
176 strcpy (incoming_speed_rating, "MB/s");
177 adjusted_incoming_rate = (double) (incoming_rate / 1024.0 / 1024.0);
178 }
179
180 /* report outgoing traffic in Bytes/sec */
181 if (outgoing_rate < 1024) {
182 strcpy (outgoing_speed_rating, "B/s");
183 adjusted_outgoing_rate = (double) outgoing_rate;
184 }
185
186 /* report outgoing traffic in KBytes/sec */
187 else if (outgoing_rate < (1024 * 1024)) {
188 strcpy (outgoing_speed_rating, "KB/s");
189 adjusted_outgoing_rate = (double) (outgoing_rate / 1024.0);
190 }
191
192 /* report outgoing traffic in MBytes/sec */
193 else {
194 strcpy (outgoing_speed_rating, "MB/s");
195 adjusted_outgoing_rate = (double) (outgoing_rate / 1024.0 / 1024.0);
196 }
197
198 if (incoming_rate > incoming_critical_threshold
199 || outgoing_rate > outgoing_critical_threshold) {
200 result = STATE_CRITICAL;
201 sprintf (error_message, "%s. In = %0.1f %s, %s. Out = %0.1f %s",
202 (use_average == TRUE) ? "Ave" : "Max", adjusted_incoming_rate,
203 incoming_speed_rating, (use_average == TRUE) ? "Ave" : "Max",
204 adjusted_outgoing_rate, outgoing_speed_rating);
205 }
206 else if (incoming_rate > incoming_warning_threshold
207 || outgoing_rate > outgoing_warning_threshold) {
208 result = STATE_WARNING;
209 sprintf (error_message, "%s. In = %0.1f %s, %s. Out = %0.1f %s",
210 (use_average == TRUE) ? "Ave" : "Max", adjusted_incoming_rate,
211 incoming_speed_rating, (use_average == TRUE) ? "Ave" : "Max",
212 adjusted_outgoing_rate, outgoing_speed_rating);
213 }
214
215 if (result == STATE_OK)
216 printf ("Traffic ok - %s. In = %0.1f %s, %s. Out = %0.1f %s\n",
217 (use_average == TRUE) ? "Ave" : "Max", adjusted_incoming_rate,
218 incoming_speed_rating, (use_average == TRUE) ? "Ave" : "Max",
219 adjusted_outgoing_rate, outgoing_speed_rating);
220 else
221 printf ("%s\n", error_message);
222
223 return result;
224}
225
226
227
228
229
230/* process command-line arguments */
231int
232process_arguments (int argc, char **argv)
233{
234 int c;
235
236 if (argc < 2)
237 return ERROR;
238
239 for (c = 1; c < argc; c++) {
240 if (strcmp ("-to", argv[c]) == 0)
241 strcpy (argv[c], "-t");
242 else if (strcmp ("-wt", argv[c]) == 0)
243 strcpy (argv[c], "-w");
244 else if (strcmp ("-ct", argv[c]) == 0)
245 strcpy (argv[c], "-c");
246 }
247
248
249
250 c = 0;
251 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
252
253 if (is_option (argv[c]))
254 continue;
255
256 if (log_file == NULL) {
257 log_file = argv[c];
258 }
259 else if (expire_minutes == -1) {
260 expire_minutes = atoi (optarg);
261 }
262 else if (strcmp (argv[c], "MAX") == 0) {
263 use_average = FALSE;
264 }
265 else if (strcmp (argv[c], "AVG") == 0) {
266 use_average = TRUE;
267 }
268 else if (incoming_warning_threshold == 0) {
269 incoming_warning_threshold = strtoul (argv[c], NULL, 10);
270 }
271 else if (incoming_critical_threshold == 0) {
272 incoming_critical_threshold = strtoul (argv[c], NULL, 10);
273 }
274 else if (outgoing_warning_threshold == 0) {
275 outgoing_warning_threshold = strtoul (argv[c], NULL, 10);
276 }
277 else if (outgoing_critical_threshold == 0) {
278 outgoing_critical_threshold = strtoul (argv[c], NULL, 10);
279 }
280 }
281
282 return validate_arguments ();
283}
284
285
286
287
288
289
290int
291call_getopt (int argc, char **argv)
292{
293 int c, i = 0;
294
295#ifdef HAVE_GETOPT_H
296 int option_index = 0;
297 static struct option long_options[] = {
298 {"logfile", required_argument, 0, 'F'},
299 {"expires", required_argument, 0, 'e'},
300 {"aggregation", required_argument, 0, 'a'},
301 {"variable", required_argument, 0, 'v'},
302 {"critical", required_argument, 0, 'c'},
303 {"warning", required_argument, 0, 'w'},
304 {"verbose", no_argument, 0, 'v'},
305 {"version", no_argument, 0, 'V'},
306 {"help", no_argument, 0, 'h'},
307 {0, 0, 0, 0}
308 };
309#endif
310
311 while (1) {
312#ifdef HAVE_GETOPT_H
313 c =
314 getopt_long (argc, argv, "+hVF:e:a:c:w:", long_options, &option_index);
315#else
316 c = getopt (argc, argv, "+hVF:e:a:c:w:");
317#endif
318
319 i++;
320
321 if (c == -1 || c == EOF || c == 1)
322 break;
323
324 switch (c) {
325 case 'F':
326 case 'e':
327 case 'a':
328 case 'c':
329 case 'w':
330 i++;
331 }
332
333 switch (c) {
334 case 'F': /* input file */
335 log_file = optarg;
336 break;
337 case 'e': /* expiration time */
338 expire_minutes = atoi (optarg);
339 break;
340 case 'a': /* aggregation (AVE or MAX) */
341 if (!strcmp (optarg, "MAX"))
342 use_average = FALSE;
343 else
344 use_average = TRUE;
345 break;
346 case 'c': /* warning threshold */
347 sscanf (optarg, "%lu,%lu", &incoming_critical_threshold,
348 &outgoing_critical_threshold);
349 break;
350 case 'w': /* critical threshold */
351 sscanf (optarg, "%lu,%lu", &incoming_warning_threshold,
352 &outgoing_warning_threshold);
353 break;
354 case 'V': /* version */
355 print_revision (PROGNAME, "$Revision$");
356 exit (STATE_OK);
357 case 'h': /* help */
358 print_help ();
359 exit (STATE_OK);
360 case '?': /* help */
361 usage ("Invalid argument\n");
362 }
363 }
364 return i;
365}
366
367
368
369
370
371int
372validate_arguments (void)
373{
374 return OK;
375}
376
377
378
379
380
381void
382print_help (void)
383{
384 print_revision (PROGNAME, "$Revision$");
385 printf
386 ("Copyright (c) 2000 Tom Shields/Karl DeBisschop\n\n"
387 "This plugin tests the UPS service on the specified host.\n\n");
388 print_usage ();
389 printf
390 ("\nOptions:\n"
391 " -F, --filename=STRING\n"
392 " File to read log from\n"
393 " -e, --expires=INTEGER\n"
394 " Minutes after which log expires\n"
395 " -a, --aggregation=(AVG|MAX)\n"
396 " Test average or maximum"
397 " -w, --warning\n"
398 " Warning threshold pair \"<incoming>,<outgoing>\"\n"
399 " -c, --critical\n"
400 " Critical threshold pair \"<incoming>,<outgoing>\"\n"
401 " -h, --help\n"
402 " Print detailed help screen\n"
403 " -V, --version\n" " Print version information\n\n");
404 support ();
405}
406
407
408
409
410
411void
412print_usage (void)
413{
414 printf
415 ("Usage: %s -F <log_file> -a <AVG | MAX> -v <variable> -w <warning_pair> -c <critical_pair>\n"
416 " [-e expire_minutes] [-t timeout] [-v]\n"
417 " %s --help\n"
418 " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
419}
diff --git a/plugins/check_mysql.c b/plugins/check_mysql.c
new file mode 100644
index 00000000..50836f91
--- /dev/null
+++ b/plugins/check_mysql.c
@@ -0,0 +1,297 @@
1/******************************************************************************
2*
3* CHECK_MYSQL.C
4*
5* Program: Mysql plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Didi Rieder (adrieder@sbox.tu-graz.ac.at)
8* portions (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
9*
10* $Id$
11*
12* Description:
13*
14* This plugin is for testing a mysql server.
15******************************************************************************/
16
17#define PROGNAME "check_mysql"
18
19#include "common.h"
20#include "utils.h"
21
22#include <mysql/mysql.h>
23#include <mysql/errmsg.h>
24
25char *db_user = NULL;
26char *db_host = NULL;
27char *db_pass = NULL;
28char *db = NULL;
29unsigned int db_port = MYSQL_PORT;
30
31int process_arguments (int, char **);
32int call_getopt (int, char **);
33int validate_arguments (void);
34int check_disk (int usp, int free_disk);
35void print_help (void);
36void print_usage (void);
37
38int
39main (int argc, char **argv)
40{
41
42 MYSQL mysql;
43 char result[1024];
44
45 if (process_arguments (argc, argv) != OK)
46 usage ("Invalid command arguments supplied\n");
47
48 /* initialize mysql */
49 mysql_init (&mysql);
50
51 /* establish a connection to the server and error checking */
52 if (!mysql_real_connect
53 (&mysql, db_host, db_user, db_pass, db, db_port, NULL, 0)) {
54
55 if (mysql_errno (&mysql) == CR_UNKNOWN_HOST) {
56 printf ("%s\n", mysql_error (&mysql));
57 return STATE_WARNING;
58
59 }
60 else if (mysql_errno (&mysql) == CR_VERSION_ERROR) {
61 printf ("%s\n", mysql_error (&mysql));
62 return STATE_WARNING;
63
64 }
65 else if (mysql_errno (&mysql) == CR_OUT_OF_MEMORY) {
66 printf ("%s\n", mysql_error (&mysql));
67 return STATE_WARNING;
68
69 }
70 else if (mysql_errno (&mysql) == CR_IPSOCK_ERROR) {
71 printf ("%s\n", mysql_error (&mysql));
72 return STATE_WARNING;
73
74 }
75 else if (mysql_errno (&mysql) == CR_SOCKET_CREATE_ERROR) {
76 printf ("%s\n", mysql_error (&mysql));
77 return STATE_WARNING;
78
79 }
80 else {
81 printf ("%s\n", mysql_error (&mysql));
82 return STATE_CRITICAL;
83 }
84
85 }
86
87 /* get the server stats */
88 sprintf (result, mysql_stat (&mysql));
89
90 /* error checking once more */
91 if (mysql_error (&mysql)) {
92
93 if (mysql_errno (&mysql) == CR_SERVER_GONE_ERROR) {
94 printf ("%s\n", mysql_error (&mysql));
95 return STATE_CRITICAL;
96
97 }
98 else if (mysql_errno (&mysql) == CR_SERVER_LOST) {
99 printf ("%s\n", mysql_error (&mysql));
100 return STATE_CRITICAL;
101
102 }
103 else if (mysql_errno (&mysql) == CR_UNKNOWN_ERROR) {
104 printf ("%s\n", mysql_error (&mysql));
105 return STATE_UNKNOWN;
106 }
107
108 }
109
110 /* close the connection */
111 mysql_close (&mysql);
112
113 /* print out the result of stats */
114 printf ("%s\n", result);
115
116 return STATE_OK;
117}
118
119
120
121
122
123/* process command-line arguments */
124int
125process_arguments (int argc, char **argv)
126{
127 int c;
128
129 if (argc < 1)
130 return ERROR;
131
132 c = 0;
133 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
134
135 if (is_option (argv[c]))
136 continue;
137
138 if (db_host == NULL)
139 if (is_host (argv[c])) {
140 db_host = argv[c];
141 }
142 else {
143 usage ("Invalid host name");
144 }
145 else if (db_user == NULL)
146 db_user = argv[c];
147 else if (db_pass == NULL)
148 db_pass = argv[c];
149 else if (db == NULL)
150 db = argv[c];
151 else if (is_intnonneg (argv[c]))
152 db_port = atoi (argv[c]);
153 }
154
155 if (db_host == NULL)
156 db_host = strscpy (db_host, "127.0.0.1");
157
158 return validate_arguments ();
159}
160
161
162
163
164
165
166int
167call_getopt (int argc, char **argv)
168{
169 int c, i = 0;
170
171#ifdef HAVE_GETOPT_H
172 int option_index = 0;
173 static struct option long_options[] = {
174 {"hostname", required_argument, 0, 'H'},
175 {"database", required_argument, 0, 'd'},
176 {"username", required_argument, 0, 'u'},
177 {"password", required_argument, 0, 'p'},
178 {"port", required_argument, 0, 'P'},
179 {"verbose", no_argument, 0, 'v'},
180 {"version", no_argument, 0, 'V'},
181 {"help", no_argument, 0, 'h'},
182 {0, 0, 0, 0}
183 };
184#endif
185
186 while (1) {
187#ifdef HAVE_GETOPT_H
188 c =
189 getopt_long (argc, argv, "+hVP:p:u:d:H:", long_options, &option_index);
190#else
191 c = getopt (argc, argv, "+?hVP:p:u:d:H:");
192#endif
193
194 i++;
195
196 if (c == -1 || c == EOF || c == 1)
197 break;
198
199 switch (c) {
200 case 'P':
201 case 'p':
202 case 'u':
203 case 'd':
204 case 'H':
205 i++;
206 }
207
208 switch (c) {
209 case 'H': /* hostname */
210 if (is_host (optarg)) {
211 db_host = optarg;
212 }
213 else {
214 usage ("Invalid host name\n");
215 }
216 break;
217 case 'd': /* hostname */
218 db = optarg;
219 break;
220 case 'u': /* username */
221 db_user = optarg;
222 break;
223 case 'p': /* authentication information: password */
224 db_pass = optarg;
225 break;
226 case 'P': /* critical time threshold */
227 db_port = atoi (optarg);
228 break;
229 case 'V': /* version */
230 print_revision (my_basename (argv[0]), "$Revision$");
231 exit (STATE_OK);
232 case 'h': /* help */
233 print_help ();
234 exit (STATE_OK);
235 case '?': /* help */
236 usage ("Invalid argument\n");
237 }
238 }
239 return i;
240}
241
242
243
244
245
246int
247validate_arguments (void)
248{
249 return OK;
250}
251
252
253
254
255
256void
257print_help (void)
258{
259 print_revision (PROGNAME, "$Revision$");
260 printf
261 ("Copyright (c) 2000 Didi Rieder/Karl DeBisschop\n\n"
262 "This plugin is for testing a mysql server.\n");
263 print_usage ();
264 printf
265 ("\nThere are no required arguments. By default, the local database with\n"
266 "a server listening on MySQL standard port %d will be checked\n\n"
267 "Options:\n"
268 " -d, --database=STRING\n"
269 " Check database with indicated name\n"
270 " -H, --hostname=STRING or IPADDRESS\n"
271 " Check server on the indicated host\n"
272 " -P, --port=INTEGER\n"
273 " Make connection on the indicated port\n"
274 " -u, --username=STRING\n"
275 " Connect using the indicated username\n"
276 " -p, --password=STRING\n"
277 " Use the indicated password to authenticate the connection\n"
278 " ==> IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!! <==\n"
279 " Your clear-text password will be visible as a process table entry\n"
280 " -h, --help\n"
281 " Print detailed help screen\n"
282 " -V, --version\n" " Print version information\n\n", MYSQL_PORT);
283 support ();
284}
285
286
287
288
289
290void
291print_usage (void)
292{
293 printf
294 ("Usage: %s [-d database] [-H host] [-P port] [-u user] [-p password]\n"
295 " %s --help\n"
296 " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
297}
diff --git a/plugins/check_nagios.c b/plugins/check_nagios.c
new file mode 100644
index 00000000..04258354
--- /dev/null
+++ b/plugins/check_nagios.c
@@ -0,0 +1,267 @@
1/******************************************************************************
2 *
3 * CHECK_NAGIOS.C
4 *
5 * Program: Nagios process plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 *
9 * $Id$
10 *
11 * License Information:
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 *****************************************************************************/
28
29#include "common.h"
30#include "popen.h"
31#include "utils.h"
32
33#define PROGNAME "check_nagios"
34
35int process_arguments (int, char **);
36void print_usage (void);
37void print_help (void);
38
39char *status_log = NULL;
40char *process_string = NULL;
41int expire_minutes = 0;
42
43int
44main (int argc, char **argv)
45{
46 int result = STATE_UNKNOWN;
47 char input_buffer[MAX_INPUT_BUFFER];
48 unsigned long latest_entry_time = 0L;
49 unsigned long temp_entry_time = 0L;
50 int proc_entries = 0;
51 time_t current_time;
52 char *temp_ptr;
53 FILE *fp;
54
55 if (process_arguments (argc, argv) == ERROR)
56 usage ("Could not parse arguments\n");
57
58 /* Set signal handling and alarm */
59 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
60 printf ("Cannot catch SIGALRM");
61 return STATE_UNKNOWN;
62 }
63
64 /* handle timeouts gracefully... */
65 alarm (timeout_interval);
66
67 /* open the status log */
68 fp = fopen (status_log, "r");
69 if (fp == NULL) {
70 printf ("Error: Cannot open status log for reading!\n");
71 return STATE_CRITICAL;
72 }
73
74 /* get the date/time of the last item updated in the log */
75 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
76 temp_ptr = strtok (input_buffer, "]");
77 temp_entry_time =
78 (temp_ptr == NULL) ? 0L : strtoul (temp_ptr + 1, NULL, 10);
79 if (temp_entry_time > latest_entry_time)
80 latest_entry_time = temp_entry_time;
81 }
82 fclose (fp);
83
84 /* run the command to check for the Nagios process.. */
85 child_process = spopen (PS_RAW_COMMAND);
86 if (child_process == NULL) {
87 printf ("Could not open pipe: %s\n", PS_RAW_COMMAND);
88 return STATE_UNKNOWN;
89 }
90
91 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
92 if (child_stderr == NULL) {
93 printf ("Could not open stderr for %s\n", PS_RAW_COMMAND);
94 }
95
96 /* cound the number of matching Nagios processes... */
97 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
98 if (strstr (input_buffer, process_string))
99 proc_entries++;
100 }
101
102 /* If we get anything on stderr, at least set warning */
103 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
104 result = max (result, STATE_WARNING);
105
106 /* close stderr */
107 (void) fclose (child_stderr);
108
109 /* close the pipe */
110 if (spclose (child_process))
111 result = max (result, STATE_WARNING);
112
113 /* reset the alarm handler */
114 alarm (0);
115
116 if (proc_entries == 0) {
117 printf ("Could not locate a running Nagios process!\n");
118 return STATE_CRITICAL;
119 }
120
121 result = STATE_OK;
122
123 time (&current_time);
124 if ((current_time - latest_entry_time) > (expire_minutes * 60))
125 result = STATE_WARNING;
126
127 printf
128 ("Nagios %s: located %d process%s, status log updated %d second%s ago\n",
129 (result == STATE_OK) ? "ok" : "problem", proc_entries,
130 (proc_entries == 1) ? "" : "es",
131 (int) (current_time - latest_entry_time),
132 ((int) (current_time - latest_entry_time) == 1) ? "" : "s");
133
134 return result;
135}
136
137
138
139
140
141/* process command-line arguments */
142int
143process_arguments (int argc, char **argv)
144{
145 int c;
146
147#ifdef HAVE_GETOPT_H
148 int option_index = 0;
149 static struct option long_options[] = {
150 {"filename", required_argument, 0, 'F'},
151 {"expires", required_argument, 0, 'e'},
152 {"command", required_argument, 0, 'C'},
153 {"version", no_argument, 0, 'V'},
154 {"help", no_argument, 0, 'h'},
155 {0, 0, 0, 0}
156 };
157#endif
158
159 if (argc < 2)
160 return ERROR;
161
162 if (!is_option (argv[1])) {
163 status_log = argv[1];
164 if (is_intnonneg (argv[2]))
165 expire_minutes = atoi (argv[2]);
166 else
167 terminate (STATE_UNKNOWN,
168 "Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n",
169 PROGNAME);
170 process_string = argv[3];
171 return OK;
172 }
173
174 while (1) {
175#ifdef HAVE_GETOPT_H
176 c = getopt_long (argc, argv, "+hVF:C:e:", long_options, &option_index);
177#else
178 c = getopt (argc, argv, "+hVF:C:e:");
179#endif
180
181 if (c == -1 || c == EOF || c == 1)
182 break;
183
184 switch (c) {
185 case '?': /* print short usage statement if args not parsable */
186 printf ("%s: Unknown argument: %c\n\n", my_basename (argv[0]), optopt);
187 print_usage ();
188 exit (STATE_UNKNOWN);
189 case 'h': /* help */
190 print_help ();
191 exit (STATE_OK);
192 case 'V': /* version */
193 print_revision (my_basename (argv[0]), "$Revision$");
194 exit (STATE_OK);
195 case 'F': /* hostname */
196 status_log = optarg;
197 break;
198 case 'C': /* hostname */
199 process_string = optarg;
200 break;
201 case 'e': /* hostname */
202 if (is_intnonneg (optarg))
203 expire_minutes = atoi (optarg);
204 else
205 terminate (STATE_UNKNOWN,
206 "Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n",
207 PROGNAME);
208 break;
209 }
210 }
211
212
213 if (status_log == NULL)
214 terminate (STATE_UNKNOWN,
215 "You must provide the status_log\nType '%s -h' for additional help\n",
216 PROGNAME);
217 else if (process_string == NULL)
218 terminate (STATE_UNKNOWN,
219 "You must provide a process string\nType '%s -h' for additional help\n",
220 PROGNAME);
221
222 return OK;
223}
224
225
226
227
228
229void
230print_usage (void)
231{
232 printf
233 ("Usage: %s -F <status log file> -e <expire_minutes> -C <process_string>\n",
234 PROGNAME);
235}
236
237
238
239
240
241void
242print_help (void)
243{
244 print_revision (PROGNAME, "$Revision$");
245 printf
246 ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
247 "This plugin attempts to check the status of the Nagios process on the local\n"
248 "machine. The plugin will check to make sure the Nagios status log is no older\n"
249 "than the number of minutes specified by the <expire_minutes> option. It also\n"
250 "uses the /bin/ps command to check for a process matching whatever you specify\n"
251 "by the <process_string> argument.\n");
252 print_usage ();
253 printf
254 ("\nOptions:\n"
255 "-F, --filename=FILE\n"
256 " Name of the log file to check\n"
257 "-e, --expires=INTEGER\n"
258 " Seconds aging afterwhich logfile is condsidered stale\n"
259 "-C, --command=STRING\n"
260 " Command to search for in process table\n"
261 "-h, --help\n"
262 " Print this help screen\n"
263 "-V, --version\n"
264 " Print version information\n\n"
265 "Example:\n"
266 " ./check_nagios -H /usr/local/nagios/var/status.log -e 5 -C /usr/local/nagios/bin/nagios\n");
267}
diff --git a/plugins/check_nntp.c b/plugins/check_nntp.c
new file mode 100644
index 00000000..4bdc83ab
--- /dev/null
+++ b/plugins/check_nntp.c
@@ -0,0 +1,418 @@
1/******************************************************************************
2 *
3 * CHECK_NNTP.C
4 *
5 * Program: NNTP plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 *
9 * $Id$
10 *
11 * Description:
12 *
13 * This plugin will attempt to open an NNTP connection with the host.
14 * Successul connects return STATE_OK, refusals and timeouts return
15 * STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful
16 * connects, but incorrect reponse messages from the host result in
17 * STATE_WARNING return values. An invalid newsgroup (if the -g
18 * option is used) results in a STATE_WARNING value.
19 *
20 * License Information:
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *
36 *****************************************************************************/
37
38#include "config.h"
39#include "common.h"
40#include "netutils.h"
41#include "utils.h"
42
43#define PROGNAME "check_nntp"
44
45#define PORT 119
46#define EXPECT1A "200" /* posting allowed */
47#define EXPECT1B "201" /* posting not allowed */
48#define EXPECT "NNTP"
49#define QUIT "QUIT\r\n"
50#define MODEREADER "MODE READER\r\n"
51
52int process_arguments (int, char **);
53int call_getopt (int, char **);
54int validate_arguments (void);
55int check_disk (int usp, int free_disk);
56void print_help (void);
57void print_usage (void);
58
59int server_port = PORT;
60char *server_expect = NULL;
61char *server_address = NULL;
62char *newsgroup = NULL;
63int check_newsgroup = FALSE;
64int send_modereader = FALSE;
65int warning_time = 0;
66int check_warning_time = FALSE;
67int critical_time = 0;
68int check_critical_time = FALSE;
69int verbose = FALSE;
70
71
72int
73main (int argc, char **argv)
74{
75 char buffer[MAX_INPUT_BUFFER] = "";
76 int sd;
77 int result;
78 int recv_result;
79
80 if (process_arguments (argc, argv) != OK)
81 usage ("Invalid command arguments supplied\n");
82
83 /* initialize alarm signal handling */
84 signal (SIGALRM, socket_timeout_alarm_handler);
85
86 /* set socket timeout */
87 alarm (socket_timeout);
88
89 /* try to connect to the host at the given port number */
90 time (&start_time);
91 result = my_tcp_connect (server_address, server_port, &sd);
92
93 /* we connected */
94 if (result == STATE_OK) {
95
96 /* watch for the NNTP connection string */
97 recv_result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
98
99 /* return a WARNING status if we couldn't read any data */
100 if (recv_result == -1) {
101
102 printf ("recv() failed\n");
103 result = STATE_WARNING;
104
105 }
106 else {
107
108 /* strip carriage returns from buffer */
109 strip (buffer);
110
111 /* make sure we find the response we are looking for */
112 if (strstr (buffer, EXPECT1A) != buffer
113 && strstr (buffer, EXPECT1B) != buffer) {
114 printf ("Invalid NNTP response received from host: %s\n", buffer);
115 result = STATE_WARNING;
116 }
117
118 /* optionally send mode reader */
119 /* added 2000-09-18 by Andreas M. Kirchwitz <amk@krell.snafu.de> including some other minor fixes */
120 if (send_modereader == TRUE) {
121 send (sd, MODEREADER, strlen (MODEREADER), 0);
122 recv_result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
123 if (recv_result == -1)
124 strcpy (buffer, "");
125 else
126 buffer[recv_result] = 0;
127 strip (buffer);
128 if ((strstr (buffer, EXPECT1A) != buffer)
129 && (strstr (buffer, EXPECT1B) != buffer)) {
130 printf ("Unexpected NNTP response received from host");
131 result = STATE_WARNING;
132 }
133 }
134
135 if (server_expect && !strstr (buffer, server_expect)) {
136 printf ("Invalid NNTP header received from host: %s\n", buffer);
137 result = STATE_WARNING;
138 }
139
140 if (check_newsgroup == TRUE) {
141 sprintf (buffer, "GROUP %s\r\n", newsgroup);
142 send (sd, buffer, strlen (buffer), 0);
143 recv_result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
144 if (recv_result == -1)
145 strcpy (buffer, "");
146 else
147 buffer[recv_result] = 0;
148 strip (buffer);
149 if (strstr (buffer, "211") != buffer) {
150 printf ("NNTP problem - newsgroup '%s' not found\n", newsgroup);
151 result = STATE_WARNING;
152 }
153 }
154
155 if (result == STATE_OK) {
156 time (&end_time);
157 if (check_critical_time == TRUE
158 && (end_time - start_time) > critical_time) result =
159 STATE_CRITICAL;
160 else if (check_warning_time == TRUE
161 && (end_time - start_time) > warning_time) result =
162 STATE_WARNING;
163 if (verbose)
164 printf ("NNTP %s - %d sec. response time, %s\n",
165 (result == STATE_OK) ? "ok" : "problem",
166 (int) (end_time - start_time), buffer);
167 else
168 printf ("NNTP %s - %d second response time\n",
169 (result == STATE_OK) ? "ok" : "problem",
170 (int) (end_time - start_time));
171 }
172
173 }
174
175 /* close the connection */
176 send (sd, QUIT, strlen (QUIT), 0);
177 close (sd);
178
179 }
180
181 /* reset the alarm timeout */
182 alarm (0);
183
184 return result;
185}
186
187
188
189
190
191
192/* process command-line arguments */
193int
194process_arguments (int argc, char **argv)
195{
196 int c;
197
198 if (argc < 2)
199 return ERROR;
200
201 for (c = 1; c < argc; c++) {
202 if (strcmp ("-to", argv[c]) == 0)
203 strcpy (argv[c], "-t");
204 else if (strcmp ("-wt", argv[c]) == 0)
205 strcpy (argv[c], "-w");
206 else if (strcmp ("-ct", argv[c]) == 0)
207 strcpy (argv[c], "-c");
208 }
209
210
211
212 c = 0;
213 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
214
215 if (is_option (argv[c]))
216 continue;
217
218 if (server_address == NULL) {
219 if (is_host (argv[c])) {
220 server_address = argv[c];
221 }
222 else {
223 usage ("Invalid host name");
224 }
225 }
226 }
227
228 if (server_address == NULL)
229 server_address = strscpy (NULL, "127.0.0.1");
230
231/* if (server_expect==NULL) */
232/* server_expect=strscpy(NULL,EXPECT); */
233
234 return validate_arguments ();
235}
236
237
238
239
240
241
242int
243call_getopt (int argc, char **argv)
244{
245 int c, i = 0;
246
247#ifdef HAVE_GETOPT_H
248 int option_index = 0;
249 static struct option long_options[] = {
250 {"hostname", required_argument, 0, 'H'},
251 {"expect", required_argument, 0, 'e'},
252 {"critical", required_argument, 0, 'c'},
253 {"warning", required_argument, 0, 'w'},
254 {"port", required_argument, 0, 'P'},
255 {"modereader", required_argument, 0, 'M'},
256 {"verbose", no_argument, 0, 'v'},
257 {"version", no_argument, 0, 'V'},
258 {"help", no_argument, 0, 'h'},
259 {0, 0, 0, 0}
260 };
261#endif
262
263 while (1) {
264#ifdef HAVE_GETOPT_H
265 c =
266 getopt_long (argc, argv, "+hVMvt:p:e:c:w:H:", long_options,
267 &option_index);
268#else
269 c = getopt (argc, argv, "+?hVMvt:p:e:c:w:H:");
270#endif
271
272 i++;
273
274 if (c == -1 || c == EOF || c == 1)
275 break;
276
277 switch (c) {
278 case 't':
279 case 'p':
280 case 'e':
281 case 'c':
282 case 'w':
283 case 'H':
284 i++;
285 }
286
287 switch (c) {
288 case 'H': /* hostname */
289 if (is_host (optarg)) {
290 server_address = optarg;
291 }
292 else {
293 usage ("Invalid host name\n");
294 }
295 break;
296 case 'p': /* port */
297 if (is_intpos (optarg)) {
298 server_port = atoi (optarg);
299 }
300 else {
301 usage ("Server port must be a positive integer\n");
302 }
303 break;
304 case 'M': /* mode reader */
305 send_modereader = TRUE;
306 break;
307 case 'e': /* expect */
308 server_expect = optarg;
309 break;
310 case 'g': /* newsgroup */
311 newsgroup = optarg;
312 check_newsgroup = TRUE;
313 break;
314 case 'c': /* critical time threshold */
315 if (is_intnonneg (optarg)) {
316 critical_time = atoi (optarg);
317 check_critical_time = TRUE;
318 }
319 else {
320 usage ("Critical time must be a nonnegative integer\n");
321 }
322 break;
323 case 'w': /* warning time threshold */
324 if (is_intnonneg (optarg)) {
325 warning_time = atoi (optarg);
326 check_warning_time = TRUE;
327 }
328 else {
329 usage ("Warning time must be a nonnegative integer\n");
330 }
331 break;
332 case 'v': /* verbose */
333 verbose = TRUE;
334 break;
335 case 't': /* timeout */
336 if (is_intnonneg (optarg)) {
337 socket_timeout = atoi (optarg);
338 }
339 else {
340 usage ("Time interval must be a nonnegative integer\n");
341 }
342 break;
343 case 'V': /* version */
344 print_revision (PROGNAME, "$Revision$");
345 exit (STATE_OK);
346 case 'h': /* help */
347 print_help ();
348 exit (STATE_OK);
349 case '?': /* help */
350 usage ("Invalid argument\n");
351 }
352 }
353 return i;
354}
355
356
357
358
359
360int
361validate_arguments (void)
362{
363 return OK;
364}
365
366
367
368
369
370void
371print_help (void)
372{
373 print_revision (PROGNAME, "$Revision$");
374 printf
375 ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
376 "This plugin tests the NNTP service on the specified host.\n\n");
377 print_usage ();
378 printf
379 ("\nOptions:\n"
380 " -H, --hostname=STRING or IPADDRESS\n"
381 " Check server on the indicated host\n"
382 " -p, --port=INTEGER\n"
383 " Make connection on the indicated port (default: %d)\n"
384 " -e, --expect=STRING\n"
385 " String to expect in first line of server response (default: %s)\n"
386 " -g, --group=STRING\n"
387 " Newsgroup to poll\n"
388 " -w, --warning=INTEGER\n"
389 " Seconds necessary to result in a warning status\n"
390 " -c, --critical=INTEGER\n"
391 " Seconds necessary to result in a critical status\n"
392 " -t, --timeout=INTEGER\n"
393 " Seconds before connection attempt times out (default: %d)\n"
394 " -M\n"
395 " Send \"MODE READER\" after initial connect.\n"
396 " -v, --verbose\n"
397 " Print extra information (command-line use only)\n"
398 " -h, --help\n"
399 " Print detailed help screen\n"
400 " -V, --version\n"
401 " Print version information\n\n",
402 PORT, EXPECT, DEFAULT_SOCKET_TIMEOUT);
403 support ();
404}
405
406
407
408
409
410void
411print_usage (void)
412{
413 printf
414 ("Usage: %s -H host [-e expect] [-g group] [-p port] [-w warn] [-c crit]\n"
415 " [-t timeout] [-v]\n"
416 " %s --help\n"
417 " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
418}
diff --git a/plugins/check_nt.c b/plugins/check_nt.c
new file mode 100644
index 00000000..ed0dc98b
--- /dev/null
+++ b/plugins/check_nt.c
@@ -0,0 +1,548 @@
1/******************************************************************************
2 *
3 * This file is part of the Nagios Plugins.
4 *
5 * Copyright (c) 2000 Yves Rubin <rubiyz@yahoo.com>
6 *
7 * The Nagios Plugins are free software; you can redistribute them
8 * and/or modify them under the terms of the GNU General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * $Id$
22 *
23 *****************************************************************************/
24
25#define PROGRAM check_nt
26#define DESCRIPTION "Windows NT plugin for Nagios"
27#define AUTHOR "Yves Rubin"
28#define EMAIL "rubiyz@yahoo.com"
29#define COPYRIGHTDATE "2000"
30
31//#include "stdlib.h"
32#include "config.h"
33#include "common.h"
34#include "netutils.h"
35#include "utils.h"
36
37#define CHECK_NONE 0
38#define CHECK_CLIENTVERSION 1
39#define CHECK_CPULOAD 2
40#define CHECK_UPTIME 3
41#define CHECK_USEDDISKSPACE 4
42#define CHECK_SERVICESTATE 5
43#define CHECK_PROCSTATE 6
44#define CHECK_MEMUSE 7
45#define CHECK_COUNTER 8
46#define MAX_VALUE_LIST 30
47
48#define PORT 1248
49
50char *server_address=NULL;
51char *volume_name=NULL;
52int server_port=PORT;
53char *value_list=NULL;
54char *req_password=NULL;
55unsigned long lvalue_list[MAX_VALUE_LIST];
56unsigned long warning_value=0L;
57unsigned long critical_value=0L;
58int check_value_list=FALSE;
59int check_warning_value=FALSE;
60int check_critical_value=FALSE;
61int vars_to_check=CHECK_NONE;
62int show_all=FALSE;
63
64#define PROGNAME "check_nt"
65
66int process_arguments(int, char **);
67void print_usage(void);
68void print_help(void);
69void preparelist(char *string);
70
71int main(int argc, char **argv){
72 int result;
73 int return_code;
74 char *send_buffer=NULL;
75 char recv_buffer[MAX_INPUT_BUFFER];
76 char *output_message=NULL;
77 char *temp_buffer=NULL;
78 char *temp_string=NULL;
79 char *sep_string=NULL;
80 char *description=NULL;
81
82 double total_disk_space=0;
83 double free_disk_space=0;
84 double percent_used_space=0;
85 double mem_commitLimit=0;
86 double mem_commitByte=0;
87 unsigned long current_connections=0;
88 unsigned long utilization;
89 unsigned long uptime;
90 unsigned long cache_hits;
91 unsigned long cache_buffers;
92 unsigned long lru_time;
93 double counter_value;
94 int offset=0;
95 int updays=0;
96 int uphours=0;
97 int upminutes=0;
98 req_password=strscpy(req_password,"None");
99
100 if(process_arguments(argc,argv)==ERROR)
101 usage("Could not parse arguments\n");
102
103 /* initialize alarm signal handling */
104 signal(SIGALRM,socket_timeout_alarm_handler);
105
106 /* set socket timeout */
107 alarm(socket_timeout);
108
109 if (vars_to_check==CHECK_CLIENTVERSION) {
110
111 send_buffer = strscpy(send_buffer,strcat(req_password,"&1"));
112 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
113 if(result!=STATE_OK)
114 return result;
115 output_message = strscpy(output_message,recv_buffer);
116 return_code=STATE_OK;
117 }
118 else if(vars_to_check==CHECK_CPULOAD){
119
120 if (check_value_list==TRUE) {
121 if (strtolarray(&lvalue_list,value_list,",")==TRUE) {
122 // -l parameters is present with only integers
123 return_code=STATE_OK;
124 temp_string = strscpy(temp_string,"CPU Load");
125 while (lvalue_list[0+offset]>0 && lvalue_list[0+offset]<=17280 &&
126 lvalue_list[1+offset]>=0 && lvalue_list[1+offset]<=100 &&
127 lvalue_list[2+offset]>=0 && lvalue_list[2+offset]<=100) {
128 // loop until one of the parameters is wrong or not present
129
130 // Send request and retrieve data
131 send_buffer = ssprintf(send_buffer,"%s&2&%lu",req_password,lvalue_list[0+offset]);
132 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
133 if(result!=STATE_OK)
134 return result;
135
136 if (!strncmp(recv_buffer,"ERROR",5)) {
137 printf("NSClient - %s\n",recv_buffer);
138 exit(STATE_UNKNOWN);
139 }
140
141 utilization=strtoul(recv_buffer,NULL,10);
142
143 // Check if any of the request is in a warning or critical state
144 if(utilization >= lvalue_list[2+offset])
145 return_code=STATE_CRITICAL;
146 else if(utilization >= lvalue_list[1+offset] && return_code<STATE_WARNING)
147 return_code=STATE_WARNING;
148
149 output_message = ssprintf(output_message," (%lu min. %lu%)",lvalue_list[0+offset], utilization);
150 temp_string = strscat(temp_string,output_message);
151 offset+=3; //move accross the array
152 }
153 if (strlen(temp_string)>10) {
154 // we had at least on loop
155 output_message = ssprintf(output_message,"%s",temp_string);
156 }
157 else
158 output_message = strscpy(output_message,"not enough values for -l parameters");
159
160 } else
161 output_message = strscpy(output_message,"wrong -l parameter.");
162
163 } else
164 output_message = strscpy(output_message,"missing -l parameters");
165 }
166
167 else if(vars_to_check==CHECK_UPTIME){
168
169 send_buffer = strscpy(send_buffer,strcat(req_password,"&3"));
170 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
171 if(result!=STATE_OK)
172 return result;
173
174 if (!strncmp(recv_buffer,"ERROR",5)) {
175 printf("NSClient - %s\n",recv_buffer);
176 exit(STATE_UNKNOWN);
177 }
178
179 uptime=strtoul(recv_buffer,NULL,10);
180 updays = uptime / 86400;
181 uphours = (uptime % 86400) / 3600;
182 upminutes = ((uptime % 86400) % 3600) / 60;
183 output_message = ssprintf(output_message,"System Uptime : %u day(s) %u hour(s) %u minute(s)",updays,uphours, upminutes);
184 return_code=STATE_OK;
185 }
186
187 else if(vars_to_check==CHECK_USEDDISKSPACE){
188
189 return_code=STATE_UNKNOWN;
190 if (check_value_list==TRUE) {
191 if (strlen(value_list)==1) {
192 send_buffer = ssprintf(send_buffer,"%s&4&%s", req_password, value_list);
193 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
194 if(result!=STATE_OK)
195 return result;
196
197 if (!strncmp(recv_buffer,"ERROR",5)) {
198 printf("NSClient - %s\n",recv_buffer);
199 exit(STATE_UNKNOWN);
200 }
201
202 free_disk_space=atof(strtok(recv_buffer,"&"));
203 total_disk_space=atof(strtok(NULL,"&"));
204 percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100;
205
206 if (free_disk_space>=0) {
207 temp_string = ssprintf(temp_string,"%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)",
208 value_list, total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824, percent_used_space,
209 free_disk_space / 1073741824, (free_disk_space / total_disk_space)*100);
210
211
212 if(check_critical_value==TRUE && percent_used_space >= critical_value)
213 return_code=STATE_CRITICAL;
214 else if (check_warning_value==TRUE && percent_used_space >= warning_value)
215 return_code=STATE_WARNING;
216 else
217 return_code=STATE_OK;
218
219 output_message = ssprintf(output_message,"%s",temp_string);
220
221 }
222 else {
223 output_message = ssprintf(output_message,"Free disk space : Invalid drive ");
224 return_code=STATE_UNKNOWN;
225 }
226 }
227 else
228 output_message = strscpy(output_message,"wrong -l argument");
229 } else
230 output_message = strscpy(output_message,"missing -l parameters");
231
232 }
233
234 else if(vars_to_check==CHECK_SERVICESTATE || vars_to_check==CHECK_PROCSTATE){
235
236 if (check_value_list==TRUE) {
237 preparelist(value_list); // replace , between services with & to send the request
238 send_buffer = ssprintf(send_buffer,"%s&%u&%s&%s", req_password,(vars_to_check==CHECK_SERVICESTATE)?5:6,
239 (show_all==TRUE)?"ShowAll":"ShowFail",value_list);
240 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
241 if(result!=STATE_OK)
242 return result;
243
244 if (!strncmp(recv_buffer,"ERROR",5)) {
245 printf("NSClient - %s\n",recv_buffer);
246 exit(STATE_UNKNOWN);
247 }
248 return_code=atoi(strtok(recv_buffer,"&"));
249 temp_string=strtok(NULL,"&");
250 output_message = ssprintf(output_message, "%s",temp_string);
251 }
252 else
253 output_message = strscpy(output_message,"No service/process specified");
254 }
255
256 else if(vars_to_check==CHECK_MEMUSE) {
257
258 send_buffer = ssprintf(send_buffer,"%s&7", req_password);
259 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
260 if (result!=STATE_OK)
261 return result;
262
263 if (!strncmp(recv_buffer,"ERROR",5)) {
264 printf("NSClient - %s\n",recv_buffer);
265 exit(STATE_UNKNOWN);
266 }
267
268 mem_commitLimit=atof(strtok(recv_buffer,"&"));
269 mem_commitByte=atof(strtok(NULL,"&"));
270 percent_used_space = (mem_commitByte / mem_commitLimit) * 100;
271 output_message = ssprintf(output_message,"Memory usage: total:%.2f Mb - used: %.2f Mb (%.0f%%) - free: %.2f Mb (%.0f%%)",
272 mem_commitLimit / 1048576, mem_commitByte / 1048567, percent_used_space,
273 (mem_commitLimit - mem_commitByte) / 1048576, (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100);
274
275 if(check_critical_value==TRUE && percent_used_space >= critical_value)
276 return_code=STATE_CRITICAL;
277 else if (check_warning_value==TRUE && percent_used_space >= warning_value)
278 return_code=STATE_WARNING;
279 else
280 return_code=STATE_OK;
281
282 }
283
284 else if(vars_to_check==CHECK_COUNTER) {
285
286 if (check_value_list==TRUE) {
287 preparelist(value_list); // replace , between services with & to send the request
288 send_buffer = ssprintf(send_buffer,"%s&8&%s", req_password,value_list);
289 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
290 if (result!=STATE_OK)
291 return result;
292
293 if (!strncmp(recv_buffer,"ERROR",5)) {
294 printf("NSClient - %s\n",recv_buffer);
295 exit(STATE_UNKNOWN);
296 }
297
298 strtok(value_list,"&"); // burn the first parameters
299 description = strtok(NULL,"&");
300 counter_value = atof(recv_buffer);
301 if (description == NULL)
302 output_message = ssprintf(output_message, "%.f", counter_value);
303 else
304 output_message = ssprintf(output_message, description, counter_value);
305
306 if (critical_value > warning_value) {
307 // Normal thresholds
308 if(check_critical_value==TRUE && counter_value >= critical_value)
309 return_code=STATE_CRITICAL;
310 else if (check_warning_value==TRUE && counter_value >= warning_value)
311 return_code=STATE_WARNING;
312 else
313 return_code=STATE_OK;
314 }
315 else {
316 // inverse thresholds
317 if(check_critical_value==TRUE && counter_value <= critical_value)
318 return_code=STATE_CRITICAL;
319 else if (check_warning_value==TRUE && counter_value <= warning_value)
320 return_code=STATE_WARNING;
321 else
322 return_code=STATE_OK;
323 }
324
325 }
326 else {
327 output_message = strscpy(output_message,"No counter specified");
328 result=STATE_UNKNOWN;
329 }
330 }
331
332 /* reset timeout */
333 alarm(0);
334
335 printf("%s\n",output_message);
336
337 return return_code;
338}
339
340
341/* process command-line arguments */
342int process_arguments(int argc, char **argv){
343 int c;
344
345#ifdef HAVE_GETOPT_H
346 int option_index = 0;
347 static struct option long_options[] =
348 {
349 {"port", required_argument,0,'p'},
350 {"timeout", required_argument,0,'t'},
351 {"critical", required_argument,0,'c'},
352 {"warning", required_argument,0,'w'},
353 {"variable", required_argument,0,'v'},
354 {"hostname", required_argument,0,'H'},
355 {"version", no_argument, 0,'V'},
356 {"help", no_argument, 0,'h'},
357 {0,0,0,0}
358 };
359#endif
360
361 /* no options were supplied */
362 if(argc<2) return ERROR;
363
364 /* backwards compatibility */
365 if (! is_option(argv[1])) {
366 server_address=argv[1];
367 argv[1]=argv[0];
368 argv=&argv[1];
369 argc--;
370 }
371
372 for (c=1;c<argc;c++) {
373 if(strcmp("-to",argv[c])==0)
374 strcpy(argv[c],"-t");
375 else if (strcmp("-wv",argv[c])==0)
376 strcpy(argv[c],"-w");
377 else if (strcmp("-cv",argv[c])==0)
378 strcpy(argv[c],"-c");
379 }
380
381 while (1){
382#ifdef HAVE_GETOPT_H
383 c = getopt_long(argc,argv,"+hVH:t:c:w:p:v:l:s:d:",long_options,&option_index);
384#else
385 c = getopt(argc,argv,"+hVH:t:c:w:p:v:l:s:d:");
386#endif
387
388 if (c==-1||c==EOF||c==1)
389 break;
390
391 switch (c)
392 {
393 case '?': /* print short usage statement if args not parsable */
394 printf("%s: Unknown argument: %s\n\n",my_basename(argv[0]),optarg);
395 print_usage();
396 exit(STATE_UNKNOWN);
397 case 'h': /* help */
398 print_help();
399 exit(STATE_OK);
400 case 'V': /* version */
401 print_revision(my_basename(argv[0]),"$Revision$");
402 exit(STATE_OK);
403 case 'H': /* hostname */
404 server_address=optarg;
405 break;
406 case 's': /* password */
407 req_password=strscpy(req_password,optarg);
408 break;
409 case 'p': /* port */
410 if (is_intnonneg(optarg))
411 server_port=atoi(optarg);
412 else
413 terminate(STATE_UNKNOWN,"Server port an integer (seconds)\nType '%s -h' for additional help\n",PROGNAME);
414 break;
415 case 'v':
416 if(strlen(optarg)<4)
417 return ERROR;
418 if(!strcmp(optarg,"CLIENTVERSION"))
419 vars_to_check=CHECK_CLIENTVERSION;
420 else if(!strcmp(optarg,"CPULOAD"))
421 vars_to_check=CHECK_CPULOAD;
422 else if(!strcmp(optarg,"UPTIME"))
423 vars_to_check=CHECK_UPTIME;
424 else if(!strcmp(optarg,"USEDDISKSPACE"))
425 vars_to_check=CHECK_USEDDISKSPACE;
426 else if(!strcmp(optarg,"SERVICESTATE"))
427 vars_to_check=CHECK_SERVICESTATE;
428 else if(!strcmp(optarg,"PROCSTATE"))
429 vars_to_check=CHECK_PROCSTATE;
430 else if(!strcmp(optarg,"MEMUSE"))
431 vars_to_check=CHECK_MEMUSE;
432 else if(!strcmp(optarg,"COUNTER"))
433 vars_to_check=CHECK_COUNTER;
434 else
435 return ERROR;
436 break;
437 case 'l': /* value list */
438 value_list=strscpy(value_list,optarg);
439 check_value_list=TRUE;
440 break;
441 case 'w': /* warning threshold */
442 warning_value=strtoul(optarg,NULL,10);
443 check_warning_value=TRUE;
444 break;
445 case 'c': /* critical threshold */
446 critical_value=strtoul(optarg,NULL,10);
447 check_critical_value=TRUE;
448 break;
449 case 'd': /* Display select for services */
450 if (!strcmp(optarg,"SHOWALL"))
451 show_all = TRUE;
452 break;
453 case 't': /* timeout */
454 socket_timeout=atoi(optarg);
455 if(socket_timeout<=0)
456 return ERROR;
457 }
458
459 }
460
461 return OK;
462}
463
464
465void print_usage(void)
466{
467 printf("Usage: %s -H host [-p port] [-v variable] [-w warning] [-c critical] [-l params] [-d SHOWALL] [-t timeout]\n",PROGNAME);
468}
469
470
471void print_help(void)
472{
473 print_revision(PROGNAME,"$Revision$");
474 printf
475 ("Copyright (c) 2000 Yves Rubin (rubiyz@yahoo.com)\n\n"
476 "This plugin attempts to contact the NSClient service running on a Windows NT or Windows 2000 server to\n"
477 "gather the requested system information.\n\n");
478 print_usage();
479 printf
480 ("\nOptions:\n"
481 "-H, --hostname=HOST\n"
482 " Name of the host to check\n"
483 "-p, --port=INTEGER\n"
484 " Optional port number (default: %d)\n"
485 "-s <password>\n"
486 " Password needed for the request\n"
487 "-v, --variable=STRING\n"
488 " Variable to check. Valid variables are:\n"
489 " CLIENTVERSION = Get the NSClient version\n"
490 " CPULOAD = Average CPU load on last x minutes. Request a -l parameter with the following syntax:\n"
491 " -l <minutes range>,<warning threshold>,<critical threshold>. <minute range> should be less than 24*60.\n"
492 " Thresholds are percentage and up to 10 requests can be done in one shot. ie: -l 60,90,95,120,90,95\n"
493 " UPTIME = Get the uptime of the machine. No specific parameters. No warning or critical threshold\n"
494 " USEDDISKSPACE = Size and percentage of disk use. Request a -l parameter containing the drive letter only.\n"
495 " Warning and critical thresholds can be specified with -w and -c.\n"
496 " MEMUSE = Memory use. Warning and critical thresholds can be specified with -w and -c.\n"
497 " SERVICESTATE = Check the state of one or several services. Request a -l parameters with the following syntax:\n"
498 " -l <service1>,<service2>,<service3>,... You can specify -d SHOWALL in case you want to see working services\n"
499 " in the returned string.\n"
500 " PROCSTATE = Check if one or several process are running. Same syntax as SERVICESTATE.\n"
501 " COUNTER = Check any performance counter of Windows NT/2000. Request a -l parameters with the following syntax:\n"
502 " -l \"\\\\<performance object>\\\\counter\",\"<description>\" The <description> parameter is optional and \n"
503 " is given to a printf output command which require a float parameters. Some examples:\n"
504 " \"Paging file usage is %%.2f %%%%\" or \"%%.f %%%% paging file used.\"\n"
505 " -w, --warning=INTEGER\n"
506 " Threshold which will result in a warning status\n"
507 " -c, --critical=INTEGER\n"
508 " Threshold which will result in a critical status\n"
509 " -t, --timeout=INTEGER\n"
510 " Seconds before connection attempt times out (default: %d)\n"
511 "-h, --help\n"
512 " Print this help screen\n"
513 "-V, --version\n"
514 " Print version information\n\n"
515 "Notes:\n"
516 " - The NSClient service should be running on the server to get any information.\n"
517 " - Critical thresholds should be lower than warning thresholds\n", PORT, DEFAULT_SOCKET_TIMEOUT);
518}
519
520int strtolarray(unsigned long *array, char *string, char *delim) {
521 // split a <delim> delimited string into a long array
522 int idx=0;
523 char *t1;
524
525 for (idx=0;idx<MAX_VALUE_LIST;idx++)
526 array[idx]=-1;
527
528 idx=0;
529 for(t1 = strtok(string,delim);t1 != NULL; t1 = strtok(NULL, delim)) {
530 if (is_numeric(t1) && idx<MAX_VALUE_LIST) {
531 array[idx]=strtoul(t1,NULL,10);
532 idx++;
533 } else
534 return FALSE;
535 }
536 return TRUE;
537}
538
539void preparelist(char *string) {
540 // Replace all , with & which is the delimiter for the request
541 int i;
542
543 for (i = 0; i < strlen(string); i++)
544 if (string[i] == ',') {
545 string[i]='&';
546 }
547}
548
diff --git a/plugins/check_nwstat.c b/plugins/check_nwstat.c
new file mode 100644
index 00000000..e1426702
--- /dev/null
+++ b/plugins/check_nwstat.c
@@ -0,0 +1,821 @@
1/******************************************************************************
2 *
3 * Program: NetWare statistics plugin for Nagios
4 * License: GPL
5 *
6 * License Information:
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * $Id$
23 *
24 *****************************************************************************/
25
26#define PROGNAME "check_nwstat"
27#define REVISION "$Revision$"
28#define COPYRIGHT "Copyright (c) 1999-2001 Ethan Galstad"
29
30#define SUMMARY "\
31This plugin attempts to contact the MRTGEXT NLM running on a Novell server\n\
32to gather the requested system information.\n"
33
34#define OPTIONS "\
35-H host [-v variable] [-w warning] [-c critical]\n\
36 [-p port] [-t timeout]"
37
38#define LONGOPTIONS "\
39-H, --hostname=HOST\n\
40 Name of the host to check\n\
41-v, --variable=STRING\n\
42 Variable to check. Valid variables include:\n\
43 LOAD1 = 1 minute average CPU load\n\
44 LOAD5 = 5 minute average CPU load\n\
45 LOAD15 = 15 minute average CPU load\n\
46 CONNS = number of currently licensed connections\n\
47 VPF<vol> = percent free space on volume <vol>\n\
48 VKF<vol> = KB of free space on volume <vol>\n\
49 LTCH = percent long term cache hits\n\
50 CBUFF = current number of cache buffers\n\
51 CDBUFF = current number of dirty cache buffers\n\
52 LRUM = LRU sitting time in minutes\n\
53 DSDB = check to see if DS Database is open\n\
54 LOGINS = check to see if logins are enabled\n\
55 UPRB = used packet receive buffers\n\
56 PUPRB = percent (of max) used packet receive buffers\n\
57 SAPENTRIES = number of entries in the SAP table\n\
58 SAPENTRIES<n> = number of entries in the SAP table for SAP type <n>\n\
59 OFILES = number of open files\n\
60 VPP<vol> = percent purgeable space on volume <vol>\n\
61 VKP<vol> = KB of purgeable space on volume <vol>\n\
62 VPNP<vol> = percent not yet purgeable space on volume <vol>\n\
63 VKNP<vol> = KB of not yet purgeable space on volume <vol>\n\
64 ABENDS = number of abended threads (NW 5.x only)\n\
65 CSPROCS = number of current service processes (NW 5.x only)\n\
66-w, --warning=INTEGER\n\
67 Threshold which will result in a warning status\n\
68-c, --critical=INTEGER\n\
69 Threshold which will result in a critical status\n\
70-p, --port=INTEGER\n\
71 Optional port number (default: %d)\n\
72-t, --timeout=INTEGER\n\
73 Seconds before connection attempt times out (default: %d)\n\
74-o, --osversion\n\
75 Include server version string in results\n\
76-h, --help\n\
77 Print this help screen\n\
78-V, --version\n\
79 Print version information\n"
80
81#define DESCRIPTION "\
82Notes:\n\
83- This plugin requres that the MRTGEXT.NLM file from James Drews' MRTG\n\
84 extension for NetWare be loaded on the Novell servers you wish to check.\n\
85 (available from http://www.engr.wisc.edu/~drews/mrtg/)\n\
86- Values for critical thresholds should be lower than warning thresholds\n\
87 when the following variables are checked: VPF, VKF, LTCH, CBUFF, and LRUM.\n"
88
89#include "config.h"
90#include "common.h"
91#include "netutils.h"
92#include "utils.h"
93
94#define CHECK_NONE 0
95#define CHECK_LOAD1 1 /* check 1 minute CPU load */
96#define CHECK_LOAD5 2 /* check 5 minute CPU load */
97#define CHECK_LOAD15 3 /* check 15 minute CPU load */
98#define CHECK_CONNS 4 /* check number of connections */
99#define CHECK_VPF 5 /* check % free space on volume */
100#define CHECK_VKF 6 /* check KB free space on volume */
101#define CHECK_LTCH 7 /* check long-term cache hit percentage */
102#define CHECK_CBUFF 8 /* check total cache buffers */
103#define CHECK_CDBUFF 9 /* check dirty cache buffers */
104#define CHECK_LRUM 10 /* check LRU sitting time in minutes */
105#define CHECK_DSDB 11 /* check to see if DS Database is open */
106#define CHECK_LOGINS 12 /* check to see if logins are enabled */
107#define CHECK_PUPRB 13 /* check % of used packet receive buffers */
108#define CHECK_UPRB 14 /* check used packet receive buffers */
109#define CHECK_SAPENTRIES 15 /* check SAP entries */
110#define CHECK_OFILES 16 /* check number of open files */
111#define CHECK_VKP 17 /* check KB purgeable space on volume */
112#define CHECK_VPP 18 /* check % purgeable space on volume */
113#define CHECK_VKNP 19 /* check KB not yet purgeable space on volume */
114#define CHECK_VPNP 20 /* check % not yet purgeable space on volume */
115#define CHECK_ABENDS 21 /* check abended thread count */
116#define CHECK_CSPROCS 22 /* check number of current service processes */
117
118#define PORT 9999
119
120char *server_address=NULL;
121char *volume_name=NULL;
122int server_port=PORT;
123unsigned long warning_value=0L;
124unsigned long critical_value=0L;
125int check_warning_value=FALSE;
126int check_critical_value=FALSE;
127int check_netware_version=FALSE;
128unsigned long vars_to_check=CHECK_NONE;
129int sap_number=-1;
130
131#define PROGNAME "check_nwstat"
132
133int process_arguments(int, char **);
134void print_usage(void);
135void print_help(void);
136
137int main(int argc, char **argv){
138 int result;
139 char *send_buffer=NULL;
140 char recv_buffer[MAX_INPUT_BUFFER];
141 char *output_message=NULL;
142 char *temp_buffer=NULL;
143 char *netware_version=NULL;
144
145 int open_files=0;
146 int abended_threads=0;
147 int max_service_processes=0;
148 int current_service_processes=0;
149 unsigned long free_disk_space=0L;
150 unsigned long total_disk_space=0L;
151 unsigned long purgeable_disk_space=0L;
152 unsigned long non_purgeable_disk_space=0L;
153 int percent_free_space=0;
154 int percent_purgeable_space=0;
155 int percent_non_purgeable_space=0;
156 unsigned long current_connections=0L;
157 unsigned long utilization=0L;
158 int cache_hits=0;
159 unsigned long cache_buffers=0L;
160 unsigned long lru_time=0L;
161 char uptime[MAX_INPUT_BUFFER];
162 int max_packet_receive_buffers=0;
163 int used_packet_receive_buffers=0;
164 unsigned long percent_used_packet_receive_buffers=0L;
165 int sap_entries=0;
166
167 if(process_arguments(argc,argv)==ERROR)
168 usage("Could not parse arguments\n");
169
170 /* initialize alarm signal handling */
171 signal(SIGALRM,socket_timeout_alarm_handler);
172
173 /* set socket timeout */
174 alarm(socket_timeout);
175
176 /* get OS version string */
177 if (check_netware_version==TRUE) {
178 send_buffer = strscpy(send_buffer,"S19\r\n");
179 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
180 if(result!=STATE_OK)
181 return result;
182 if(!strcmp(recv_buffer,"-1\n"))
183 netware_version = ssprintf(netware_version,"");
184 else {
185 recv_buffer[strlen(recv_buffer)-1]=0;
186 netware_version = ssprintf(netware_version,"NetWare %s: ",recv_buffer);
187 }
188 } else
189 netware_version = ssprintf(netware_version,"");
190
191
192 /* check CPU load */
193 if (vars_to_check==CHECK_LOAD1 || vars_to_check==CHECK_LOAD5 || vars_to_check==CHECK_LOAD15) {
194
195 switch(vars_to_check){
196 case CHECK_LOAD1:
197 temp_buffer = strscpy(temp_buffer,"1");
198 break;
199 case CHECK_LOAD5:
200 temp_buffer = strscpy(temp_buffer,"5");
201 break;
202 default:
203 temp_buffer = strscpy(temp_buffer,"15");
204 break;
205 }
206
207 send_buffer = ssprintf(send_buffer,"UTIL%s\r\n",temp_buffer);
208 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
209 if(result!=STATE_OK)
210 return result;
211 utilization=strtoul(recv_buffer,NULL,10);
212 send_buffer = strscpy(send_buffer,"UPTIME\r\n");
213 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
214 if(result!=STATE_OK)
215 return result;
216 recv_buffer[strlen(recv_buffer)-1]=0;
217 sprintf(uptime,"Up %s,",recv_buffer);
218
219 if(check_critical_value==TRUE && utilization >= critical_value)
220 result=STATE_CRITICAL;
221 else if(check_warning_value==TRUE && utilization >= warning_value)
222 result=STATE_WARNING;
223
224 output_message = ssprintf(output_message,"Load %s - %s %s-min load average = %lu%%",(result==STATE_OK)?"ok":"problem",uptime,temp_buffer,utilization);
225
226 /* check number of user connections */
227 } else if (vars_to_check==CHECK_CONNS) {
228
229 send_buffer = strscpy(send_buffer,"CONNECT\r\n");
230 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
231 if(result!=STATE_OK)
232 return result;
233 current_connections=strtoul(recv_buffer,NULL,10);
234
235 if(check_critical_value==TRUE && current_connections >= critical_value)
236 result=STATE_CRITICAL;
237 else if(check_warning_value==TRUE && current_connections >= warning_value)
238 result=STATE_WARNING;
239 output_message = ssprintf(output_message,"Conns %s - %lu current connections",(result==STATE_OK)?"ok":"problem",current_connections);
240
241 /* check % long term cache hits */
242 } else if (vars_to_check==CHECK_LTCH) {
243
244 send_buffer = strscpy(send_buffer,"S1\r\n");
245 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
246 if(result!=STATE_OK)
247 return result;
248 cache_hits=atoi(recv_buffer);
249
250 if(check_critical_value==TRUE && cache_hits <= critical_value)
251 result=STATE_CRITICAL;
252 else if(check_warning_value==TRUE && cache_hits <= warning_value)
253 result=STATE_WARNING;
254 output_message = ssprintf(output_message,"Long term cache hits = %d%%",cache_hits);
255
256 /* check cache buffers */
257 } else if (vars_to_check==CHECK_CBUFF) {
258
259 send_buffer = strscpy(send_buffer,"S2\r\n");
260 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
261 if(result!=STATE_OK)
262 return result;
263 cache_buffers=strtoul(recv_buffer,NULL,10);
264
265 if(check_critical_value==TRUE && cache_buffers <= critical_value)
266 result=STATE_CRITICAL;
267 else if(check_warning_value==TRUE && cache_buffers <= warning_value)
268 result=STATE_WARNING;
269 output_message = ssprintf(output_message,"Total cache buffers = %lu",cache_buffers);
270
271 /* check dirty cache buffers */
272 } else if (vars_to_check==CHECK_CDBUFF) {
273
274 send_buffer = strscpy(send_buffer,"S3\r\n");
275 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
276 if(result!=STATE_OK)
277 return result;
278 cache_buffers=strtoul(recv_buffer,NULL,10);
279
280 if(check_critical_value==TRUE && cache_buffers >= critical_value)
281 result=STATE_CRITICAL;
282 else if(check_warning_value==TRUE && cache_buffers >= warning_value)
283 result=STATE_WARNING;
284 output_message = ssprintf(output_message,"Dirty cache buffers = %lu",cache_buffers);
285
286 /* check LRU sitting time in minutes */
287 } else if (vars_to_check==CHECK_LRUM) {
288
289 send_buffer = strscpy(send_buffer,"S5\r\n");
290 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
291 if(result!=STATE_OK)
292 return result;
293 lru_time=strtoul(recv_buffer,NULL,10);
294
295 if(check_critical_value==TRUE && lru_time <= critical_value)
296 result=STATE_CRITICAL;
297 else if(check_warning_value==TRUE && lru_time <= warning_value)
298 result=STATE_WARNING;
299 output_message = ssprintf(output_message,"LRU sitting time = %lu minutes",lru_time);
300
301
302 /* check KB free space on volume */
303 } else if (vars_to_check==CHECK_VKF) {
304
305 send_buffer = ssprintf(send_buffer,"VKF%s\r\n",volume_name);
306 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
307 if(result!=STATE_OK)
308 return result;
309
310 if (!strcmp(recv_buffer,"-1\n")) {
311 output_message = ssprintf(output_message,"Error: Volume '%s' does not exist!",volume_name);
312 result=STATE_CRITICAL;
313 } else {
314 free_disk_space=strtoul(recv_buffer,NULL,10);
315 if(check_critical_value==TRUE && free_disk_space <= critical_value)
316 result=STATE_CRITICAL;
317 else if(check_warning_value==TRUE && free_disk_space <= warning_value)
318 result=STATE_WARNING;
319 output_message = ssprintf(output_message,"%s%lu KB free on volume %s",(result==STATE_OK)?"":"Only ",free_disk_space,volume_name);
320 }
321
322 /* check % free space on volume */
323 } else if (vars_to_check==CHECK_VPF) {
324
325 send_buffer = ssprintf(send_buffer,"VKF%s\r\n",volume_name);
326 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
327 if(result!=STATE_OK)
328 return result;
329
330 if(!strcmp(recv_buffer,"-1\n")){
331
332 output_message = ssprintf(output_message,"Error: Volume '%s' does not exist!",volume_name);
333 result=STATE_CRITICAL;
334
335 } else {
336
337 free_disk_space=strtoul(recv_buffer,NULL,10);
338
339 send_buffer = ssprintf(send_buffer,"VKS%s\r\n",volume_name);
340 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
341 if(result!=STATE_OK)
342 return result;
343 total_disk_space=strtoul(recv_buffer,NULL,10);
344
345 percent_free_space=(int)(((double)free_disk_space/(double)total_disk_space)*100.0);
346
347 if(check_critical_value==TRUE && percent_free_space <= critical_value)
348 result=STATE_CRITICAL;
349 else if(check_warning_value==TRUE && percent_free_space <= warning_value)
350 result=STATE_WARNING;
351 free_disk_space/=1024;
352 output_message = ssprintf(output_message,"%lu MB (%d%%) free on volume %s",free_disk_space,percent_free_space,volume_name);
353 }
354
355 /* check to see if DS Database is open or closed */
356 } else if(vars_to_check==CHECK_DSDB) {
357
358 send_buffer = strscpy(send_buffer,"S11\r\n");
359 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
360 if(result!=STATE_OK)
361 return result;
362 if(atoi(recv_buffer)==1)
363 result=STATE_OK;
364 else
365 result=STATE_WARNING;
366
367 send_buffer = strscpy(send_buffer,"S13\r\n");
368 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
369 temp_buffer=strtok(recv_buffer,"\r\n");
370
371 output_message = ssprintf(output_message,"Directory Services Database is %s (DS version %s)",(result==STATE_OK)?"open":"closed",temp_buffer);
372
373 /* check to see if logins are enabled */
374 } else if (vars_to_check==CHECK_LOGINS) {
375
376 send_buffer = strscpy(send_buffer,"S12\r\n");
377 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
378 if(result!=STATE_OK)
379 return result;
380 if(atoi(recv_buffer)==1)
381 result=STATE_OK;
382 else
383 result=STATE_WARNING;
384
385 output_message = ssprintf(output_message,"Logins are %s",(result==STATE_OK)?"enabled":"disabled");
386
387 /* check packet receive buffers */
388 } else if (vars_to_check==CHECK_UPRB || vars_to_check==CHECK_PUPRB) {
389
390 send_buffer = ssprintf(send_buffer,"S15\r\n",volume_name);
391 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
392 if(result!=STATE_OK)
393 return result;
394
395 used_packet_receive_buffers=atoi(recv_buffer);
396
397 send_buffer = ssprintf(send_buffer,"S16\r\n",volume_name);
398 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
399 if(result!=STATE_OK)
400 return result;
401
402 max_packet_receive_buffers=atoi(recv_buffer);
403
404 percent_used_packet_receive_buffers=(unsigned long)(((double)used_packet_receive_buffers/(double)max_packet_receive_buffers)*100.0);
405
406 if(vars_to_check==CHECK_UPRB){
407 if(check_critical_value==TRUE && used_packet_receive_buffers >= critical_value)
408 result=STATE_CRITICAL;
409 else if(check_warning_value==TRUE && used_packet_receive_buffers >= warning_value)
410 result=STATE_WARNING;
411 } else {
412 if(check_critical_value==TRUE && percent_used_packet_receive_buffers >= critical_value)
413 result=STATE_CRITICAL;
414 else if(check_warning_value==TRUE && percent_used_packet_receive_buffers >= warning_value)
415 result=STATE_WARNING;
416 }
417
418 output_message = ssprintf(output_message,"%d of %d (%lu%%) packet receive buffers used",used_packet_receive_buffers,max_packet_receive_buffers,percent_used_packet_receive_buffers);
419
420 /* check SAP table entries */
421 } else if (vars_to_check==CHECK_SAPENTRIES) {
422
423 if(sap_number==-1)
424 send_buffer = ssprintf(send_buffer,"S9\r\n");
425 else
426 send_buffer = ssprintf(send_buffer,"S9.%d\r\n",sap_number);
427 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
428 if(result!=STATE_OK)
429 return result;
430
431 sap_entries=atoi(recv_buffer);
432
433 if(check_critical_value==TRUE && sap_entries >= critical_value)
434 result=STATE_CRITICAL;
435 else if(check_warning_value==TRUE && sap_entries >= warning_value)
436 result=STATE_WARNING;
437
438 if(sap_number==-1)
439 output_message = ssprintf(output_message,"%d entries in SAP table",sap_entries);
440 else
441 output_message = ssprintf(output_message,"%d entries in SAP table for SAP type %d",sap_entries,sap_number);
442
443 /* check KB purgeable space on volume */
444 } else if (vars_to_check==CHECK_VKP) {
445
446 send_buffer = ssprintf(send_buffer,"VKP%s\r\n",volume_name);
447 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
448 if(result!=STATE_OK)
449 return result;
450
451 if (!strcmp(recv_buffer,"-1\n")) {
452 output_message = ssprintf(output_message,"Error: Volume '%s' does not exist!",volume_name);
453 result=STATE_CRITICAL;
454 } else {
455 purgeable_disk_space=strtoul(recv_buffer,NULL,10);
456 if(check_critical_value==TRUE && purgeable_disk_space >= critical_value)
457 result=STATE_CRITICAL;
458 else if(check_warning_value==TRUE && purgeable_disk_space >= warning_value)
459 result=STATE_WARNING;
460 output_message = ssprintf(output_message,"%s%lu KB purgeable on volume %s",(result==STATE_OK)?"":"Only ",purgeable_disk_space,volume_name);
461 }
462
463 /* check % purgeable space on volume */
464 } else if (vars_to_check==CHECK_VPP) {
465
466 send_buffer = ssprintf(send_buffer,"VKP%s\r\n",volume_name);
467 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
468 if(result!=STATE_OK)
469 return result;
470
471 if(!strcmp(recv_buffer,"-1\n")){
472
473 output_message = ssprintf(output_message,"Error: Volume '%s' does not exist!",volume_name);
474 result=STATE_CRITICAL;
475
476 } else {
477
478 purgeable_disk_space=strtoul(recv_buffer,NULL,10);
479
480 send_buffer = ssprintf(send_buffer,"VKS%s\r\n",volume_name);
481 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
482 if(result!=STATE_OK)
483 return result;
484 total_disk_space=strtoul(recv_buffer,NULL,10);
485
486 percent_purgeable_space=(int)(((double)purgeable_disk_space/(double)total_disk_space)*100.0);
487
488 if(check_critical_value==TRUE && percent_purgeable_space >= critical_value)
489 result=STATE_CRITICAL;
490 else if(check_warning_value==TRUE && percent_purgeable_space >= warning_value)
491 result=STATE_WARNING;
492 purgeable_disk_space/=1024;
493 output_message = ssprintf(output_message,"%lu MB (%d%%) purgeable on volume %s",purgeable_disk_space,percent_purgeable_space,volume_name);
494 }
495
496 /* check KB not yet purgeable space on volume */
497 } else if (vars_to_check==CHECK_VKNP) {
498
499 send_buffer = ssprintf(send_buffer,"VKNP%s\r\n",volume_name);
500 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
501 if(result!=STATE_OK)
502 return result;
503
504 if (!strcmp(recv_buffer,"-1\n")) {
505 output_message = ssprintf(output_message,"Error: Volume '%s' does not exist!",volume_name);
506 result=STATE_CRITICAL;
507 } else {
508 non_purgeable_disk_space=strtoul(recv_buffer,NULL,10);
509 if(check_critical_value==TRUE && non_purgeable_disk_space >= critical_value)
510 result=STATE_CRITICAL;
511 else if(check_warning_value==TRUE && non_purgeable_disk_space >= warning_value)
512 result=STATE_WARNING;
513 output_message = ssprintf(output_message,"%s%lu KB not yet purgeable on volume %s",(result==STATE_OK)?"":"Only ",non_purgeable_disk_space,volume_name);
514 }
515
516 /* check % not yet purgeable space on volume */
517 } else if (vars_to_check==CHECK_VPNP) {
518
519 send_buffer = ssprintf(send_buffer,"VKNP%s\r\n",volume_name);
520 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
521 if(result!=STATE_OK)
522 return result;
523
524 if(!strcmp(recv_buffer,"-1\n")){
525
526 output_message = ssprintf(output_message,"Error: Volume '%s' does not exist!",volume_name);
527 result=STATE_CRITICAL;
528
529 } else {
530
531 non_purgeable_disk_space=strtoul(recv_buffer,NULL,10);
532
533 send_buffer = ssprintf(send_buffer,"VKS%s\r\n",volume_name);
534 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
535 if(result!=STATE_OK)
536 return result;
537 total_disk_space=strtoul(recv_buffer,NULL,10);
538
539 percent_non_purgeable_space=(int)(((double)non_purgeable_disk_space/(double)total_disk_space)*100.0);
540
541 if(check_critical_value==TRUE && percent_non_purgeable_space >= critical_value)
542 result=STATE_CRITICAL;
543 else if(check_warning_value==TRUE && percent_non_purgeable_space >= warning_value)
544 result=STATE_WARNING;
545 purgeable_disk_space/=1024;
546 output_message = ssprintf(output_message,"%lu MB (%d%%) not yet purgeable on volume %s",non_purgeable_disk_space,percent_non_purgeable_space,volume_name);
547 }
548
549 /* check # of open files */
550 } else if (vars_to_check==CHECK_OFILES) {
551
552 send_buffer = ssprintf(send_buffer,"S18\r\n");
553 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
554 if(result!=STATE_OK)
555 return result;
556
557 open_files=atoi(recv_buffer);
558
559 if(check_critical_value==TRUE && open_files >= critical_value)
560 result=STATE_CRITICAL;
561 else if(check_warning_value==TRUE && open_files >= warning_value)
562 result=STATE_WARNING;
563
564 output_message = ssprintf(output_message,"%d open files",open_files);
565
566 /* check # of abended threads (Netware 5.x only) */
567 } else if (vars_to_check==CHECK_ABENDS) {
568
569 send_buffer = ssprintf(send_buffer,"S17\r\n");
570 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
571 if(result!=STATE_OK)
572 return result;
573
574 abended_threads=atoi(recv_buffer);
575
576 if(check_critical_value==TRUE && abended_threads >= critical_value)
577 result=STATE_CRITICAL;
578 else if(check_warning_value==TRUE && abended_threads >= warning_value)
579 result=STATE_WARNING;
580
581 output_message = ssprintf(output_message,"%d abended threads",abended_threads);
582
583 /* check # of current service processes (Netware 5.x only) */
584 } else if (vars_to_check==CHECK_CSPROCS) {
585
586 send_buffer = ssprintf(send_buffer,"S20\r\n");
587 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
588 if(result!=STATE_OK)
589 return result;
590
591 max_service_processes=atoi(recv_buffer);
592
593 send_buffer = ssprintf(send_buffer,"S21\r\n");
594 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
595 if(result!=STATE_OK)
596 return result;
597
598 current_service_processes=atoi(recv_buffer);
599
600 if(check_critical_value==TRUE && current_service_processes >= critical_value)
601 result=STATE_CRITICAL;
602 else if(check_warning_value==TRUE && current_service_processes >= warning_value)
603 result=STATE_WARNING;
604
605 output_message = ssprintf(output_message,"%d current service processes (%d max)",current_service_processes,max_service_processes);
606
607 } else {
608
609 output_message = strscpy(output_message,"Nothing to check!\n");
610 result=STATE_UNKNOWN;
611
612 }
613
614 /* reset timeout */
615 alarm(0);
616
617 printf("%s%s\n",netware_version,output_message);
618
619 return result;
620}
621
622
623/* process command-line arguments */
624int process_arguments(int argc, char **argv){
625 int c;
626
627#ifdef HAVE_GETOPT_H
628 int option_index = 0;
629 static struct option long_options[] =
630 {
631 {"port", required_argument,0,'p'},
632 {"timeout", required_argument,0,'t'},
633 {"critical", required_argument,0,'c'},
634 {"warning", required_argument,0,'w'},
635 {"variable", required_argument,0,'v'},
636 {"hostname", required_argument,0,'H'},
637 {"osversion",no_argument, 0,'o'},
638 {"version", no_argument, 0,'V'},
639 {"help", no_argument, 0,'h'},
640 {0,0,0,0}
641 };
642#endif
643
644 /* no options were supplied */
645 if(argc<2) return ERROR;
646
647 /* backwards compatibility */
648 if (! is_option(argv[1])) {
649 server_address=argv[1];
650 argv[1]=argv[0];
651 argv=&argv[1];
652 argc--;
653 }
654
655 for (c=1;c<argc;c++) {
656 if(strcmp("-to",argv[c])==0)
657 strcpy(argv[c],"-t");
658 else if (strcmp("-wv",argv[c])==0)
659 strcpy(argv[c],"-w");
660 else if (strcmp("-cv",argv[c])==0)
661 strcpy(argv[c],"-c");
662 }
663
664 while (1){
665#ifdef HAVE_GETOPT_H
666 c = getopt_long(argc,argv,"+hoVH:t:c:w:p:v:",long_options,&option_index);
667#else
668 c = getopt(argc,argv,"+hoVH:t:c:w:p:v:");
669#endif
670
671 if (c==-1||c==EOF||c==1)
672 break;
673
674 switch (c)
675 {
676 case '?': /* print short usage statement if args not parsable */
677 printf("%s: Unknown argument: %s\n\n",my_basename(argv[0]),optarg);
678 print_usage();
679 exit(STATE_UNKNOWN);
680 case 'h': /* help */
681 print_help();
682 exit(STATE_OK);
683 case 'V': /* version */
684 print_revision(my_basename(argv[0]),"$Revision$");
685 exit(STATE_OK);
686 case 'H': /* hostname */
687 server_address=optarg;
688 break;
689 case 'o': /* display nos version */
690 check_netware_version=TRUE;
691 break;
692 case 'p': /* port */
693 if (is_intnonneg(optarg))
694 server_port=atoi(optarg);
695 else
696 terminate(STATE_UNKNOWN,"Server port an integer (seconds)\nType '%s -h' for additional help\n",PROGNAME);
697 break;
698 case 'v':
699 if(strlen(optarg)<3)
700 return ERROR;
701 if(!strcmp(optarg,"LOAD1"))
702 vars_to_check=CHECK_LOAD1;
703 else if(!strcmp(optarg,"LOAD5"))
704 vars_to_check=CHECK_LOAD5;
705 else if(!strcmp(optarg,"LOAD15"))
706 vars_to_check=CHECK_LOAD15;
707 else if(!strcmp(optarg,"CONNS"))
708 vars_to_check=CHECK_CONNS;
709 else if(!strcmp(optarg,"LTCH"))
710 vars_to_check=CHECK_LTCH;
711 else if(!strcmp(optarg,"CBUFF"))
712 vars_to_check=CHECK_CBUFF;
713 else if(!strcmp(optarg,"CDBUFF"))
714 vars_to_check=CHECK_CDBUFF;
715 else if(!strcmp(optarg,"LRUM"))
716 vars_to_check=CHECK_LRUM;
717 else if(strncmp(optarg,"VPF",3)==0){
718 vars_to_check=CHECK_VPF;
719 volume_name = strscpy(volume_name,optarg+3);
720 if(!strcmp(volume_name,""))
721 volume_name = strscpy(volume_name,"SYS");
722 }
723 else if(strncmp(optarg,"VKF",3)==0){
724 vars_to_check=CHECK_VKF;
725 volume_name = strscpy(volume_name,optarg+3);
726 if(!strcmp(volume_name,""))
727 volume_name = strscpy(volume_name,"SYS");
728 }
729 else if(!strcmp(optarg,"DSDB"))
730 vars_to_check=CHECK_DSDB;
731 else if(!strcmp(optarg,"LOGINS"))
732 vars_to_check=CHECK_LOGINS;
733 else if(!strcmp(optarg,"UPRB"))
734 vars_to_check=CHECK_UPRB;
735 else if(!strcmp(optarg,"PUPRB"))
736 vars_to_check=CHECK_PUPRB;
737 else if(!strncmp(optarg,"SAPENTRIES",10)){
738 vars_to_check=CHECK_SAPENTRIES;
739 if(strlen(optarg)>10)
740 sap_number=atoi(optarg+10);
741 else
742 sap_number=-1;
743 }
744 else if(!strcmp(optarg,"OFILES"))
745 vars_to_check=CHECK_OFILES;
746 else if(strncmp(optarg,"VKP",3)==0){
747 vars_to_check=CHECK_VKP;
748 volume_name = strscpy(volume_name,optarg+3);
749 if(!strcmp(volume_name,""))
750 volume_name = strscpy(volume_name,"SYS");
751 }
752 else if(strncmp(optarg,"VPP",3)==0){
753 vars_to_check=CHECK_VPP;
754 volume_name = strscpy(volume_name,optarg+3);
755 if(!strcmp(volume_name,""))
756 volume_name = strscpy(volume_name,"SYS");
757 }
758 else if(strncmp(optarg,"VKNP",4)==0){
759 vars_to_check=CHECK_VKNP;
760 volume_name = strscpy(volume_name,optarg+4);
761 if(!strcmp(volume_name,""))
762 volume_name = strscpy(volume_name,"SYS");
763 }
764 else if(strncmp(optarg,"VPNP",4)==0){
765 vars_to_check=CHECK_VPNP;
766 volume_name = strscpy(volume_name,optarg+4);
767 if(!strcmp(volume_name,""))
768 volume_name = strscpy(volume_name,"SYS");
769 }
770 else if(!strcmp(optarg,"ABENDS"))
771 vars_to_check=CHECK_ABENDS;
772 else if(!strcmp(optarg,"CSPROCS"))
773 vars_to_check=CHECK_CSPROCS;
774 else
775 return ERROR;
776 break;
777 case 'w': /* warning threshold */
778 warning_value=strtoul(optarg,NULL,10);
779 check_warning_value=TRUE;
780 break;
781 case 'c': /* critical threshold */
782 critical_value=strtoul(optarg,NULL,10);
783 check_critical_value=TRUE;
784 break;
785 case 't': /* timeout */
786 socket_timeout=atoi(optarg);
787 if(socket_timeout<=0)
788 return ERROR;
789 }
790
791 }
792
793 return OK;
794}
795
796
797void print_usage(void)
798{
799 printf
800 ("Usage:\n"
801 " %s %s\n"
802#ifdef HAVE_GETOPT_H
803 " %s (-h | --help) for detailed help\n"
804 " %s (-V | --version) for version information\n",
805#else
806 " %s -h for detailed help\n"
807 " %s -V for version information\n",
808#endif
809 PROGNAME, OPTIONS, PROGNAME, PROGNAME);
810}
811
812void print_help(void)
813{
814 print_revision (PROGNAME, REVISION);
815 printf ("%s\n\n%s\n", COPYRIGHT, SUMMARY);
816 print_usage();
817 printf
818 ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n",
819 PORT, DEFAULT_SOCKET_TIMEOUT);
820 support ();
821}
diff --git a/plugins/check_overcr.c b/plugins/check_overcr.c
new file mode 100644
index 00000000..305a8242
--- /dev/null
+++ b/plugins/check_overcr.c
@@ -0,0 +1,489 @@
1/******************************************************************************
2*
3* CHECK_OVERCR.C
4*
5* Program: Over-CR collector plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8*
9* $Id$
10*
11* Description:
12*
13* Notes:
14* - This plugin requires that Eric Molitors' Over-CR collector daemon
15* be running on any UNIX boxes you want to monitor. Over-CR
16* is available from * http://www.molitor.org/overcr/
17*
18* Modifications:
19*
20* 08-11-999 Jacob Lundqvist <jaclu@grm.se>
21* Load was presented as a one digit percentage - changed to two digit
22* value * before load of 11.2 was presented as "1.2%" (not very
23* high). Warning and Critical params were int's, not very good
24* for load, changed to doubles, so we can trap loadlimits like
25* 1.5. Also added more informative LOAD error messages.
26*
27* License Information:
28*
29* This program is free software; you can redistribute it and/or modify
30* it under the terms of the GNU General Public License as published by
31* the Free Software Foundation; either version 2 of the License, or
32* (at your option) any later version.
33*
34* This program is distributed in the hope that it will be useful,
35* but WITHOUT ANY WARRANTY; without even the implied warranty of
36* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37* GNU General Public License for more details.
38*
39* You should have received a copy of the GNU General Public License
40* along with this program; if not, write to the Free Software
41* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
42*
43*****************************************************************************/
44
45#include "config.h"
46#include "common.h"
47#include "netutils.h"
48#include "utils.h"
49
50#define CHECK_NONE 0
51#define CHECK_LOAD1 1
52#define CHECK_LOAD5 2
53#define CHECK_LOAD15 4
54#define CHECK_DPU 8
55#define CHECK_PROCS 16
56#define CHECK_NETSTAT 32
57#define CHECK_UPTIME 64
58
59#define PORT 2000
60
61#define PROGNAME "check_overcr"
62
63char *server_address = NULL;
64int server_port = PORT;
65double warning_value = 0L;
66double critical_value = 0L;
67int check_warning_value = FALSE;
68int check_critical_value = FALSE;
69int vars_to_check = CHECK_NONE;
70int cmd_timeout = 1;
71
72int netstat_port = 0;
73char *disk_name = NULL;
74char *process_name = NULL;
75
76int process_arguments (int, char **);
77void print_usage (void);
78void print_help (void);
79
80int
81main (int argc, char **argv)
82{
83 int result;
84 char send_buffer[MAX_INPUT_BUFFER];
85 char recv_buffer[MAX_INPUT_BUFFER];
86 char output_message[MAX_INPUT_BUFFER];
87 char temp_buffer[MAX_INPUT_BUFFER];
88 char *temp_ptr = NULL;
89 int found_disk = FALSE;
90 unsigned long percent_used_disk_space = 100;
91 double load;
92 double load_1min;
93 double load_5min;
94 double load_15min;
95 int port_connections = 0;
96 int processes = 0;
97 double uptime_raw_hours;
98 int uptime_raw_minutes = 0;
99 int uptime_days = 0;
100 int uptime_hours = 0;
101 int uptime_minutes = 0;
102
103 if (process_arguments (argc, argv) == ERROR)
104 usage ("Could not parse arguments\n");
105
106 /* initialize alarm signal handling */
107 signal (SIGALRM, socket_timeout_alarm_handler);
108
109 /* set socket timeout */
110 alarm (socket_timeout);
111
112 result = STATE_OK;
113
114 if (vars_to_check == CHECK_LOAD1 || vars_to_check == CHECK_LOAD5
115 || vars_to_check == CHECK_LOAD15) {
116
117 strcpy (send_buffer, "LOAD\r\nQUIT\r\n");
118 result =
119 process_tcp_request2 (server_address, server_port, send_buffer,
120 recv_buffer, sizeof (recv_buffer));
121 if (result != STATE_OK)
122 return result;
123
124 temp_ptr = (char *) strtok (recv_buffer, "\r\n");
125 if (temp_ptr == NULL) {
126 printf ("Invalid response from server - no load information\n");
127 return STATE_CRITICAL;
128 }
129 load_1min = strtod (temp_ptr, NULL);
130 temp_ptr = (char *) strtok (NULL, "\r\n");
131 if (temp_ptr == NULL) {
132 printf ("Invalid response from server after load 1\n");
133 return STATE_CRITICAL;
134 }
135 load_5min = strtod (temp_ptr, NULL);
136 temp_ptr = (char *) strtok (NULL, "\r\n");
137 if (temp_ptr == NULL) {
138 printf ("Invalid response from server after load 5\n");
139 return STATE_CRITICAL;
140 }
141 load_15min = strtod (temp_ptr, NULL);
142
143
144 switch (vars_to_check) {
145 case CHECK_LOAD1:
146 strcpy (temp_buffer, "1");
147 load = load_1min;
148 break;
149 case CHECK_LOAD5:
150 strcpy (temp_buffer, "5");
151 load = load_5min;
152 break;
153 default:
154 strcpy (temp_buffer, "15");
155 load = load_15min;
156 break;
157 }
158
159 if (check_critical_value == TRUE && (load >= critical_value))
160 result = STATE_CRITICAL;
161 else if (check_warning_value == TRUE && (load >= warning_value))
162 result = STATE_WARNING;
163 sprintf (output_message, "Load %s - %s-min load average = %0.2f",
164 (result == STATE_OK) ? "ok" : "problem", temp_buffer, load);
165 }
166
167
168 else if (vars_to_check == CHECK_DPU) {
169
170 sprintf (send_buffer, "DISKSPACE\r\n");
171 result =
172 process_tcp_request2 (server_address, server_port, send_buffer,
173 recv_buffer, sizeof (recv_buffer));
174 if (result != STATE_OK)
175 return result;
176
177 for (temp_ptr = (char *) strtok (recv_buffer, " "); temp_ptr != NULL;
178 temp_ptr = (char *) strtok (NULL, " ")) {
179
180 if (!strcmp (temp_ptr, disk_name)) {
181 found_disk = TRUE;
182 temp_ptr = (char *) strtok (NULL, "%");
183 if (temp_ptr == NULL) {
184 printf ("Invalid response from server\n");
185 return STATE_CRITICAL;
186 }
187 percent_used_disk_space = strtoul (temp_ptr, NULL, 10);
188 break;
189 }
190
191 temp_ptr = (char *) strtok (NULL, "\r\n");
192 }
193
194 /* error if we couldn't find the info for the disk */
195 if (found_disk == FALSE) {
196 sprintf (output_message, "Error: Disk '%s' non-existent or not mounted",
197 disk_name);
198 result = STATE_CRITICAL;
199 }
200
201 /* else check the disk space used */
202 else {
203
204 if (check_critical_value == TRUE
205 && (percent_used_disk_space >= critical_value)) result =
206 STATE_CRITICAL;
207 else if (check_warning_value == TRUE
208 && (percent_used_disk_space >= warning_value)) result =
209 STATE_WARNING;
210
211 sprintf (output_message, "Disk %s - %lu%% used on %s",
212 (result == STATE_OK) ? "ok" : "problem",
213 percent_used_disk_space, disk_name);
214 }
215 }
216
217 else if (vars_to_check == CHECK_NETSTAT) {
218
219 sprintf (send_buffer, "NETSTAT %d\r\n", netstat_port);
220 result =
221 process_tcp_request2 (server_address, server_port, send_buffer,
222 recv_buffer, sizeof (recv_buffer));
223 if (result != STATE_OK)
224 return result;
225
226 port_connections = strtod (recv_buffer, NULL);
227
228 if (check_critical_value == TRUE && (port_connections >= critical_value))
229 result = STATE_CRITICAL;
230 else if (check_warning_value == TRUE
231 && (port_connections >= warning_value)) result = STATE_WARNING;
232
233 sprintf (output_message, "Net %s - %d connection%s on port %d",
234 (result == STATE_OK) ? "ok" : "problem", port_connections,
235 (port_connections == 1) ? "" : "s", netstat_port);
236 }
237
238 else if (vars_to_check == CHECK_PROCS) {
239
240 sprintf (send_buffer, "PROCESS %s\r\n", process_name);
241 result =
242 process_tcp_request2 (server_address, server_port, send_buffer,
243 recv_buffer, sizeof (recv_buffer));
244 if (result != STATE_OK)
245 return result;
246
247 temp_ptr = (char *) strtok (recv_buffer, "(");
248 if (temp_ptr == NULL) {
249 printf ("Invalid response from server\n");
250 return STATE_CRITICAL;
251 }
252 temp_ptr = (char *) strtok (NULL, ")");
253 if (temp_ptr == NULL) {
254 printf ("Invalid response from server\n");
255 return STATE_CRITICAL;
256 }
257 processes = strtod (temp_ptr, NULL);
258
259 if (check_critical_value == TRUE && (processes >= critical_value))
260 result = STATE_CRITICAL;
261 else if (check_warning_value == TRUE && (processes >= warning_value))
262 result = STATE_WARNING;
263
264 sprintf (output_message, "Process %s - %d instance%s of %s running",
265 (result == STATE_OK) ? "ok" : "problem", processes,
266 (processes == 1) ? "" : "s", process_name);
267 }
268
269 else if (vars_to_check == CHECK_UPTIME) {
270
271 sprintf (send_buffer, "UPTIME\r\n");
272 result =
273 process_tcp_request2 (server_address, server_port, send_buffer,
274 recv_buffer, sizeof (recv_buffer));
275 if (result != STATE_OK)
276 return result;
277
278 uptime_raw_hours = strtod (recv_buffer, NULL);
279 uptime_raw_minutes = (unsigned long) (uptime_raw_hours * 60.0);
280
281 if (check_critical_value == TRUE
282 && (uptime_raw_minutes <= critical_value)) result = STATE_CRITICAL;
283 else if (check_warning_value == TRUE
284 && (uptime_raw_minutes <= warning_value)) result = STATE_WARNING;
285
286 uptime_days = uptime_raw_minutes / 1440;
287 uptime_raw_minutes %= 1440;
288 uptime_hours = uptime_raw_minutes / 60;
289 uptime_raw_minutes %= 60;
290 uptime_minutes = uptime_raw_minutes;
291
292 sprintf (output_message, "Uptime %s - Up %d days %d hours %d minutes",
293 (result == STATE_OK) ? "ok" : "problem", uptime_days,
294 uptime_hours, uptime_minutes);
295 }
296
297 else {
298 strcpy (output_message, "Nothing to check!\n");
299 result = STATE_UNKNOWN;
300 }
301
302 /* reset timeout */
303 alarm (0);
304
305 printf ("%s\n", output_message);
306
307 return result;
308}
309
310
311
312
313
314/* process command-line arguments */
315int
316process_arguments (int argc, char **argv)
317{
318 int c;
319
320#ifdef HAVE_GETOPT_H
321 int option_index = 0;
322 static struct option long_options[] = {
323 {"port", required_argument, 0, 'p'},
324 {"timeout", required_argument, 0, 't'},
325 {"critical", required_argument, 0, 'c'},
326 {"warning", required_argument, 0, 'w'},
327 {"variable", required_argument, 0, 'v'},
328 {"hostname", required_argument, 0, 'H'},
329 {"version", no_argument, 0, 'V'},
330 {"help", no_argument, 0, 'h'},
331 {0, 0, 0, 0}
332 };
333#endif
334
335 /* no options were supplied */
336 if (argc < 2)
337 return ERROR;
338
339 /* backwards compatibility */
340 if (!is_option (argv[1])) {
341 server_address = argv[1];
342 argv[1] = argv[0];
343 argv = &argv[1];
344 argc--;
345 }
346
347 for (c = 1; c < argc; c++) {
348 if (strcmp ("-to", argv[c]) == 0)
349 strcpy (argv[c], "-t");
350 else if (strcmp ("-wv", argv[c]) == 0)
351 strcpy (argv[c], "-w");
352 else if (strcmp ("-cv", argv[c]) == 0)
353 strcpy (argv[c], "-c");
354 }
355
356 while (1) {
357#ifdef HAVE_GETOPT_H
358 c =
359 getopt_long (argc, argv, "+hVH:t:c:w:p:v:", long_options,
360 &option_index);
361#else
362 c = getopt (argc, argv, "+hVH:t:c:w:p:v:");
363#endif
364
365 if (c == -1 || c == EOF || c == 1)
366 break;
367
368 switch (c) {
369 case '?': /* print short usage statement if args not parsable */
370 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
371 print_usage ();
372 exit (STATE_UNKNOWN);
373 case 'h': /* help */
374 print_help ();
375 exit (STATE_OK);
376 case 'V': /* version */
377 print_revision (my_basename (argv[0]), "$Revision$");
378 exit (STATE_OK);
379 case 'H': /* hostname */
380 server_address = optarg;
381 break;
382 case 'p': /* port */
383 if (is_intnonneg (optarg))
384 server_port = atoi (optarg);
385 else
386 terminate (STATE_UNKNOWN,
387 "Server port an integer (seconds)\nType '%s -h' for additional help\n",
388 PROGNAME);
389 break;
390 case 'v': /* variable */
391 if (strcmp (optarg, "LOAD1") == 0)
392 vars_to_check = CHECK_LOAD1;
393 else if (strcmp (optarg, "LOAD5") == 0)
394 vars_to_check = CHECK_LOAD5;
395 else if (strcmp (optarg, "LOAD15") == 0)
396 vars_to_check = CHECK_LOAD15;
397 else if (strcmp (optarg, "UPTIME") == 0)
398 vars_to_check = CHECK_UPTIME;
399 else if (strstr (optarg, "PROC") == optarg) {
400 vars_to_check = CHECK_PROCS;
401 process_name = strscpy (process_name, optarg + 4);
402 }
403 else if (strstr (optarg, "NET") == optarg) {
404 vars_to_check = CHECK_NETSTAT;
405 netstat_port = atoi (optarg + 3);
406 }
407 else if (strstr (optarg, "DPU") == optarg) {
408 vars_to_check = CHECK_DPU;
409 disk_name = strscpy (disk_name, optarg + 3);
410 }
411 else
412 return ERROR;
413 break;
414 case 'w': /* warning threshold */
415 warning_value = strtoul (optarg, NULL, 10);
416 check_warning_value = TRUE;
417 break;
418 case 'c': /* critical threshold */
419 critical_value = strtoul (optarg, NULL, 10);
420 check_critical_value = TRUE;
421 break;
422 case 't': /* timeout */
423 socket_timeout = atoi (optarg);
424 if (socket_timeout <= 0)
425 return ERROR;
426 }
427
428 }
429 return OK;
430}
431
432
433
434
435
436void
437print_usage (void)
438{
439 printf
440 ("Usage: %s -H host [-p port] [-v variable] [-w warning] [-c critical] [-t timeout]\n",
441 PROGNAME);
442}
443
444
445
446
447
448void
449print_help (void)
450{
451 print_revision (PROGNAME, "$Revision$");
452 printf
453 ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
454 "This plugin attempts to contact the Over-CR collector daemon running on the\n"
455 "remote UNIX server in order to gather the requested system information. This\n"
456 "plugin requres that Eric Molitors' Over-CR collector daemon be running on the\n"
457 "remote server. Over-CR can be downloaded from http://www.molitor.org/overcr\n"
458 "(This plugin was tested with version 0.99.53 of the Over-CR collector)\n\n");
459 print_usage ();
460 printf
461 ("\nOptions:\n"
462 "-H, --hostname=HOST\n"
463 " Name of the host to check\n"
464 "-p, --port=INTEGER\n"
465 " Optional port number (default: %d)\n"
466 "-v, --variable=STRING\n"
467 " Variable to check. Valid variables include:\n"
468 " LOAD1 = 1 minute average CPU load\n"
469 " LOAD5 = 5 minute average CPU load\n"
470 " LOAD15 = 15 minute average CPU load\n"
471 " DPU<filesys> = percent used disk space on filesystem <filesys>\n"
472 " PROC<process> = number of running processes with name <process>\n"
473 " NET<port> = number of active connections on TCP port <port>\n"
474 " UPTIME = system uptime in seconds\n"
475 " -w, --warning=INTEGER\n"
476 " Threshold which will result in a warning status\n"
477 " -c, --critical=INTEGER\n"
478 " Threshold which will result in a critical status\n"
479 " -t, --timeout=INTEGER\n"
480 " Seconds before connection attempt times out (default: %d)\n"
481 "-h, --help\n"
482 " Print this help screen\n"
483 "-V, --version\n"
484 " Print version information\n\n"
485 "Notes:\n"
486 " - For the available options, the critical threshold value should always be\n"
487 " higher than the warning threshold value, EXCEPT with the uptime variable\n"
488 " (i.e. lower uptimes are worse).\n", PORT, DEFAULT_SOCKET_TIMEOUT);
489}
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
new file mode 100644
index 00000000..03614ab1
--- /dev/null
+++ b/plugins/check_pgsql.c
@@ -0,0 +1,440 @@
1/******************************************************************************
2 *
3 * Program: PostgreSQL plugin for Nagios
4 * License: GPL
5 *
6 * License Information:
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * $Id$
23 *
24 *****************************************************************************/
25
26#define PROGNAME "check_pgsql"
27#define REVISION "$Revision$"
28#define COPYRIGHT "1999-2001"
29#define AUTHOR "Karl DeBisschop"
30#define EMAIL "kdebisschop@users.sourceforge.net"
31#define SUMMARY "Tests to see if a PostgreSQL DBMS is accepting connections.\n"
32
33#define OPTIONS "\
34\[-c critical_time] [-w warning_time] [-t timeout] [-H host]\n\
35 [-P port] [-d database] [-l logname] [-p password]"
36
37#define LONGOPTIONS "\
38 -c, --critical=INTEGER\n\
39 Exit STATE_CRITICAL if connection time exceeds threshold (default: %d)\n\
40 -w, --warning=INTEGER\n\
41 Exit STATE_WARNING if connection time exceeds threshold (default: %d)\n\
42 -t, --timeout=INTEGER\n\
43 Terminate test if timeout limit is exceeded (default: %d)\n\
44 -H, --hostname=STRING\n\
45 Name or numeric IP address of machine running backend\n\
46 -P, --port=INTEGER\n\
47 Port running backend (default: %s)\n\
48 -d, --database=STRING\n\
49 Database to check (default: %s)\n\
50 -l, --logname = STRING\n\
51 Login name of user\n\
52 -p, --password = STRING\n\
53 Password (BIG SECURITY ISSUE)\n"
54
55#define DESCRIPTION "All parameters are optional.\n\
56\n\
57This plugin tests a PostgreSQL DBMS to determine whether it is active and\n\
58accepting queries. In its current operation, it simply connects to the\n\
59specified database, and then disconnects. If no database is specified, it\n\
60connects to the template1 database, which is present in every functioning \n\
61PostgreSQL DBMS.\n\
62\n\
63The plugin will connect to a local postmaster if no host is specified. To\n\
64connect to a remote host, be sure that the remote postmaster accepts TCP/IP\n\
65connections (start the postmaster with the -i option).\n\
66\n\
67Typically, the nagios user (unless the --logname option is used) should be\n\
68able to connect to the database without a password. The plugin can also send\n\
69a password, but no effort is made to obsure or encrypt the password.\n"
70
71#define DEFAULT_DB "template1"
72#define DEFAULT_HOST "127.0.0.1"
73#define DEFAULT_PORT "5432"
74#define DEFAULT_WARN 2
75#define DEFAULT_CRIT 8
76#define DEFAULT_TIMEOUT 30
77
78#include "config.h"
79#include "common.h"
80#include "utils.h"
81#include <netdb.h>
82#include <libpq-fe.h>
83
84int process_arguments (int, char **);
85int validate_arguments (void);
86void print_usage (void);
87void print_help (void);
88int is_pg_dbname (char *);
89int is_pg_logname (char *);
90
91char *pghost = NULL; /* host name of the backend server */
92char *pgport = NULL; /* port of the backend server */
93char default_port[4] = DEFAULT_PORT;
94char *pgoptions = NULL;
95char *pgtty = NULL;
96char dbName[NAMEDATALEN] = DEFAULT_DB;
97char *pguser = NULL;
98char *pgpasswd = NULL;
99int twarn = DEFAULT_WARN;
100int tcrit = DEFAULT_CRIT;
101
102PGconn *conn;
103/*PGresult *res;*/
104
105
106/******************************************************************************
107
108The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
109tags in the comments. With in the tags, the XML is assembled sequentially.
110You can define entities in tags. You also have all the #defines available as
111entities.
112
113Please note that all tags must be lowercase to use the DocBook XML DTD.
114
115@@-<article>
116
117<sect1>
118<title>Quick Reference</title>
119<!-- The refentry forms a manpage -->
120<refentry>
121<refmeta>
122<manvolnum>5<manvolnum>
123</refmeta>
124<refnamdiv>
125<refname>&PROGNAME;</refname>
126<refpurpose>&SUMMARY;</refpurpose>
127</refnamdiv>
128</refentry>
129</sect1>
130
131<sect1>
132<title>FAQ</title>
133</sect1>
134
135<sect1>
136<title>Theory, Installation, and Operation</title>
137
138<sect2>
139<title>General Description</title>
140<para>
141&DESCRIPTION;
142</para>
143</sect2>
144
145<sect2>
146<title>Future Enhancements</title>
147<para>ToDo List</para>
148<itemizedlist>
149<listitem>Add option to get password from a secured file rather than the command line</listitem>
150<listitem>Add option to specify the query to execute</listitem>
151</itemizedlist>
152</sect2>
153
154
155<sect2>
156<title>Functions</title>
157-@@
158******************************************************************************/
159
160int
161main (int argc, char **argv)
162{
163 int elapsed_time;
164
165 /* begin, by setting the parameters for a backend connection if the
166 * parameters are null, then the system will try to use reasonable
167 * defaults by looking up environment variables or, failing that,
168 * using hardwired constants */
169
170 pgoptions = NULL; /* special options to start up the backend server */
171 pgtty = NULL; /* debugging tty for the backend server */
172
173 if (process_arguments (argc, argv) == ERROR)
174 usage ("Could not parse arguments");
175
176 /* Set signal handling and alarm */
177 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
178 printf ("Cannot catch SIGALRM");
179 return STATE_UNKNOWN;
180 }
181 alarm (timeout_interval);
182
183 /* make a connection to the database */
184 time (&start_time);
185 conn =
186 PQsetdbLogin (pghost, pgport, pgoptions, pgtty, dbName, pguser, pgpasswd);
187 time (&end_time);
188 elapsed_time = (int) (end_time - start_time);
189
190 /* check to see that the backend connection was successfully made */
191 if (PQstatus (conn) == CONNECTION_BAD) {
192 printf ("PGSQL: CRITICAL - no connection to '%s' (%s).\n", dbName,
193 PQerrorMessage (conn));
194 PQfinish (conn);
195 return STATE_CRITICAL;
196 }
197 else if (elapsed_time > tcrit) {
198 PQfinish (conn);
199 printf ("PGSQL: CRITICAL - database %s (%d sec.)\n", dbName,
200 elapsed_time);
201 return STATE_CRITICAL;
202 }
203 else if (elapsed_time > twarn) {
204 PQfinish (conn);
205 printf ("PGSQL: WARNING - database %s (%d sec.)\n", dbName, elapsed_time);
206 return STATE_WARNING;
207 }
208 else {
209 PQfinish (conn);
210 printf ("PGSQL: ok - database %s (%d sec.)\n", dbName, elapsed_time);
211 return STATE_OK;
212 }
213}
214
215
216
217
218void
219print_help (void)
220{
221 print_revision (PROGNAME, REVISION);
222 printf
223 ("Copyright (c) %s %s <%s>\n\n%s\n",
224 COPYRIGHT, AUTHOR, EMAIL, SUMMARY);
225 print_usage ();
226 printf
227 ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n",
228 DEFAULT_WARN, DEFAULT_CRIT, DEFAULT_TIMEOUT, DEFAULT_PORT, DEFAULT_DB);
229 support ();
230}
231
232void
233print_usage (void)
234{
235 printf ("Usage:\n" " %s %s\n"
236#ifdef HAVE_GETOPT_H
237 " %s (-h | --help) for detailed help\n"
238 " %s (-V | --version) for version information\n",
239#else
240 " %s -h for detailed help\n"
241 " %s -V for version information\n",
242#endif
243 PROGNAME, OPTIONS, PROGNAME, PROGNAME);
244}
245
246
247
248/* process command-line arguments */
249int
250process_arguments (int argc, char **argv)
251{
252 int c;
253
254#ifdef HAVE_GETOPT_H
255 int option_index = 0;
256 static struct option long_options[] = {
257 {"help", no_argument, 0, 'h'},
258 {"version", no_argument, 0, 'V'},
259 {"timeout", required_argument, 0, 't'},
260 {"critical", required_argument, 0, 'c'},
261 {"warning", required_argument, 0, 'w'},
262 {"hostname", required_argument, 0, 'H'},
263 {"logname", required_argument, 0, 'l'},
264 {"password", required_argument, 0, 'p'},
265 {"authorization", required_argument, 0, 'a'},
266 {"port", required_argument, 0, 'P'},
267 {"database", required_argument, 0, 'd'},
268 {0, 0, 0, 0}
269 };
270#endif
271
272 while (1) {
273#ifdef HAVE_GETOPT_H
274 c = getopt_long (argc, argv, "+?hVt:c:w:H:P:d:l:p:a:",
275 long_options, &option_index);
276#else
277 c = getopt (argc, argv, "+?hVt:c:w:H:P:d:l:p:a:");
278#endif
279 if (c == EOF)
280 break;
281
282 switch (c) {
283 case '?': /* help */
284 usage2 ("Unknown argument", optarg);
285 case 'h': /* help */
286 print_help ();
287 exit (STATE_OK);
288 case 'V': /* version */
289 print_revision (PROGNAME, REVISION);
290 exit (STATE_OK);
291 case 't': /* timeout period */
292 if (!is_integer (optarg))
293 usage2 ("Timeout Interval must be an integer", optarg);
294 timeout_interval = atoi (optarg);
295 break;
296 case 'c': /* critical time threshold */
297 if (!is_integer (optarg))
298 usage2 ("Invalid critical threshold", optarg);
299 tcrit = atoi (optarg);
300 break;
301 case 'w': /* warning time threshold */
302 if (!is_integer (optarg))
303 usage2 ("Invalid critical threshold", optarg);
304 twarn = atoi (optarg);
305 break;
306 case 'H': /* host */
307 if (!is_host (optarg))
308 usage2 ("You gave an invalid host name", optarg);
309 pghost = optarg;
310 break;
311 case 'P': /* port */
312 if (!is_integer (optarg))
313 usage2 ("Port must be an integer", optarg);
314 pgport = optarg;
315 break;
316 case 'd': /* database name */
317 if (!is_pg_dbname (optarg))
318 usage2 ("Database name is not valid", optarg);
319 strncpy (dbName, optarg, NAMEDATALEN - 1);
320 dbName[NAMEDATALEN - 1] = 0;
321 break;
322 case 'l': /* login name */
323 if (!is_pg_logname (optarg))
324 usage2 ("user name is not valid", optarg);
325 pguser = optarg;
326 break;
327 case 'p': /* authentication password */
328 case 'a':
329 pgpasswd = optarg;
330 break;
331 }
332 }
333
334 return validate_arguments ();
335}
336
337
338/******************************************************************************
339
340@@-
341<sect3>
342<title>validate_arguments</title>
343
344<para>&PROTO_validate_arguments;</para>
345
346<para>Given a database name, this function returns TRUE if the string
347is a valid PostgreSQL database name, and returns false if it is
348not.</para>
349
350<para>Valid PostgreSQL database names are less than &NAMEDATALEN;
351characters long and consist of letters, numbers, and underscores. The
352first character cannot be a number, however.</para>
353
354</sect3>
355-@@
356******************************************************************************/
357
358int
359validate_arguments ()
360{
361 return OK;
362}
363
364
365
366/******************************************************************************
367
368@@-
369<sect3>
370<title>is_pg_dbname</title>
371
372<para>&PROTO_is_pg_dbname;</para>
373
374<para>Given a database name, this function returns TRUE if the string
375is a valid PostgreSQL database name, and returns false if it is
376not.</para>
377
378<para>Valid PostgreSQL database names are less than &NAMEDATALEN;
379characters long and consist of letters, numbers, and underscores. The
380first character cannot be a number, however.</para>
381
382</sect3>
383-@@
384******************************************************************************/
385
386int
387is_pg_dbname (char *dbname)
388{
389 char txt[NAMEDATALEN];
390 char tmp[NAMEDATALEN];
391 if (strlen (dbname) > NAMEDATALEN - 1)
392 return (FALSE);
393 strncpy (txt, dbname, NAMEDATALEN - 1);
394 txt[NAMEDATALEN - 1] = 0;
395 if (sscanf (txt, "%[_a-zA-Z]%[^_a-zA-Z0-9]", tmp, tmp) == 1)
396 return (TRUE);
397 if (sscanf (txt, "%[_a-zA-Z]%[_a-zA-Z0-9]%[^_a-zA-Z0-9]", tmp, tmp, tmp) ==
398 2) return (TRUE);
399 return (FALSE);
400}
401
402/**
403
404the tango program should eventually create an entity here based on the
405function prototype
406
407@@-
408<sect3>
409<title>is_pg_logname</title>
410
411<para>&PROTO_is_pg_logname;</para>
412
413<para>Given a username, this function returns TRUE if the string is a
414valid PostgreSQL username, and returns false if it is not. Valid PostgreSQL
415usernames are less than &NAMEDATALEN; characters long and consist of
416letters, numbers, dashes, and underscores, plus possibly some other
417characters.</para>
418
419<para>Currently this function only checks string length. Additional checks
420should be added.</para>
421
422</sect3>
423-@@
424******************************************************************************/
425
426int
427is_pg_logname (char *username)
428{
429 if (strlen (username) > NAMEDATALEN - 1)
430 return (FALSE);
431 return (TRUE);
432}
433
434/******************************************************************************
435@@-
436</sect2>
437</sect1>
438</article>
439-@@
440******************************************************************************/
diff --git a/plugins/check_ping.c b/plugins/check_ping.c
new file mode 100644
index 00000000..b61b41b5
--- /dev/null
+++ b/plugins/check_ping.c
@@ -0,0 +1,492 @@
1/*****************************************************************************
2*
3* CHECK_PING.C
4*
5* Program: Ping plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8*
9* $Id$
10*
11*****************************************************************************/
12
13#define PROGNAME "check_pgsql"
14#define REVISION "$Revision$"
15#define COPYRIGHT "1999-2001"
16#define AUTHOR "Ethan Galstad/Karl DeBisschop"
17#define EMAIL "kdebisschop@users.sourceforge.net"
18#define SUMMARY "Use ping to check connection statistics for a remote host.\n"
19
20#define OPTIONS "\
21-H <host_address> -w <wrta>,<wpl>%% -c <crta>,<cpl>%%\n\
22 [-p packets] [-t timeout] [-L]\n"
23
24#define LONGOPTIONS "\
25-H, --hostname=HOST\n\
26 host to ping\n\
27-w, --warning=THRESHOLD\n\
28 warning threshold pair\n\
29-c, --critical=THRESHOLD\n\
30 critical threshold pair\n\
31-p, --packets=INTEGER\n\
32 number of ICMP ECHO packets to send (Default: %d)\n\
33-t, --timeout=INTEGER\n\
34 optional specified timeout in second (Default: %d)\n\
35-L, --link\n\
36 show HTML in the plugin output (obsoleted by urlize)\n\
37THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel\n\
38time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the\n\
39percentage of packet loss to trigger an alarm state.\n"
40
41#define DESCRIPTION "\
42This plugin uses the ping command to probe the specified host for packet loss\n\
43(percentage) and round trip average (milliseconds). It can produce HTML output\n\
44linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in\n\
45the contrib area of the downloads section at http://www.nagios.org\n\n"
46
47#include "config.h"
48#include "common.h"
49#include "popen.h"
50#include "utils.h"
51
52#define UNKNOWN_PACKET_LOSS 200 /* 200% */
53#define UNKNOWN_TRIP_TIME -1.0 /* -1 seconds */
54#define DEFAULT_MAX_PACKETS 5 /* default no. of ICMP ECHO packets */
55
56#define WARN_DUPLICATES "DUPLICATES FOUND! "
57
58int process_arguments (int, char **);
59int call_getopt (int, char **);
60int get_threshold (char *, float *, int *);
61int validate_arguments (void);
62int run_ping (char *);
63void print_usage (void);
64void print_help (void);
65
66int display_html = FALSE;
67int wpl = UNKNOWN_PACKET_LOSS;
68int cpl = UNKNOWN_PACKET_LOSS;
69float wrta = UNKNOWN_TRIP_TIME;
70float crta = UNKNOWN_TRIP_TIME;
71char *server_address = NULL;
72int max_packets = -1;
73int verbose = FALSE;
74
75float rta = UNKNOWN_TRIP_TIME;
76int pl = UNKNOWN_PACKET_LOSS;
77
78char *warn_text = NULL;
79
80int
81main (int argc, char **argv)
82{
83 char *command_line = NULL;
84 int result = STATE_UNKNOWN;
85
86 if (process_arguments (argc, argv) == ERROR)
87 usage ("Could not parse arguments");
88
89 /* does the host address of number of packets argument come first? */
90#ifdef PING_PACKETS_FIRST
91 command_line =
92 ssprintf (command_line, PING_COMMAND, max_packets, server_address);
93#else
94 command_line =
95 ssprintf (command_line, PING_COMMAND, server_address, max_packets);
96#endif
97
98 /* Set signal handling and alarm */
99 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
100 printf ("Cannot catch SIGALRM");
101 return STATE_UNKNOWN;
102 }
103
104 /* handle timeouts gracefully */
105 alarm (timeout_interval);
106
107 if (verbose)
108 printf ("%s ==> ", command_line);
109
110 /* run the command */
111 run_ping (command_line);
112
113 if (pl == UNKNOWN_PACKET_LOSS || rta == UNKNOWN_TRIP_TIME) {
114 printf ("%s\n", command_line);
115 terminate (STATE_UNKNOWN,
116 "Error: Could not interpret output from ping command\n");
117 }
118
119 if (pl >= cpl || rta >= crta || rta < 0)
120 result = STATE_CRITICAL;
121 else if (pl >= wpl || rta >= wrta)
122 result = STATE_WARNING;
123 else if (pl < wpl && rta < wrta && pl >= 0 && rta >= 0)
124 result = max (result, STATE_OK);
125
126 if (display_html == TRUE)
127 printf ("<A HREF='%s/traceroute.cgi?%s'>", CGIURL, server_address);
128 if (pl == 100)
129 printf ("PING %s - %sPacket loss = %d%%", state_text (result), warn_text,
130 pl);
131 else
132 printf ("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms",
133 state_text (result), warn_text, pl, rta);
134 if (display_html == TRUE)
135 printf ("</A>");
136 printf ("\n");
137
138 if (verbose)
139 printf ("%f:%d%% %f:%d%%\n", wrta, wpl, crta, cpl);
140
141 return result;
142}
143
144
145/* process command-line arguments */
146int
147process_arguments (int argc, char **argv)
148{
149 int c;
150
151 if (argc < 2)
152 return ERROR;
153
154 for (c = 1; c < argc; c++) {
155 if (strcmp ("-to", argv[c]) == 0)
156 strcpy (argv[c], "-t");
157 if (strcmp ("-nohtml", argv[c]) == 0)
158 strcpy (argv[c], "-n");
159 }
160
161 c = 0;
162 while ((c += call_getopt (argc - c, &argv[c])) < argc) {
163
164 if (is_option (argv[c]))
165 continue;
166
167 if (server_address == NULL) {
168 if (is_host (argv[c]) == FALSE) {
169 printf ("Invalid host name/address: %s\n\n", argv[c]);
170 return ERROR;
171 }
172 server_address = argv[c];
173 }
174 else if (wpl == UNKNOWN_PACKET_LOSS) {
175 if (is_intpercent (argv[c]) == FALSE) {
176 printf ("<wpl> (%s) must be an integer percentage\n", argv[c]);
177 return ERROR;
178 }
179 wpl = atoi (argv[c]);
180 }
181 else if (cpl == UNKNOWN_PACKET_LOSS) {
182 if (is_intpercent (argv[c]) == FALSE) {
183 printf ("<cpl> (%s) must be an integer percentage\n", argv[c]);
184 return ERROR;
185 }
186 cpl = atoi (argv[c]);
187 }
188 else if (wrta == UNKNOWN_TRIP_TIME) {
189 if (is_negative (argv[c])) {
190 printf ("<wrta> (%s) must be a non-negative number\n", argv[c]);
191 return ERROR;
192 }
193 wrta = atof (argv[c]);
194 }
195 else if (crta == UNKNOWN_TRIP_TIME) {
196 if (is_negative (argv[c])) {
197 printf ("<crta> (%s) must be a non-negative number\n", argv[c]);
198 return ERROR;
199 }
200 crta = atof (argv[c]);
201 }
202 else if (max_packets == -1) {
203 if (is_intnonneg (argv[c])) {
204 max_packets = atoi (argv[c]);
205 }
206 else {
207 printf ("<max_packets> (%s) must be a non-negative number\n",
208 argv[c]);
209 return ERROR;
210 }
211 }
212
213 }
214
215 return validate_arguments ();
216}
217
218int
219call_getopt (int argc, char **argv)
220{
221 int c, i = 0;
222
223#ifdef HAVE_GETOPT_H
224 int option_index = 0;
225 static struct option long_options[] = {
226 {"help", no_argument, 0, 'h'},
227 {"version", no_argument, 0, 'V'},
228 {"verbose", no_argument, 0, 'v'},
229 {"nohtml", no_argument, 0, 'n'},
230 {"link", no_argument, 0, 'L'},
231 {"timeout", required_argument, 0, 't'},
232 {"critical", required_argument, 0, 'c'},
233 {"warning", required_argument, 0, 'w'},
234 {"hostname", required_argument, 0, 'H'},
235 {"packets", required_argument, 0, 'p'},
236 {0, 0, 0, 0}
237 };
238#endif
239
240 while (1) {
241#ifdef HAVE_GETOPT_H
242 c =
243 getopt_long (argc, argv, "+hVvt:c:w:H:p:nL", long_options,
244 &option_index);
245#else
246 c = getopt (argc, argv, "+hVvt:c:w:H:p:nL");
247#endif
248
249 i++;
250
251 if (c == -1 || c == EOF || c == 1)
252 break;
253
254 switch (c) {
255 case 't':
256 case 'c':
257 case 'w':
258 case 'H':
259 case 'p':
260 i++;
261 }
262
263 switch (c) {
264 case '?': /* print short usage statement if args not parsable */
265 usage2 ("Unknown argument", optarg);
266 case 'h': /* help */
267 print_help ();
268 exit (STATE_OK);
269 case 'V': /* version */
270 print_revision (PROGNAME, REVISION);
271 exit (STATE_OK);
272 case 't': /* timeout period */
273 timeout_interval = atoi (optarg);
274 break;
275 case 'v': /* verbose mode */
276 verbose = TRUE;
277 break;
278 case 'H': /* hostname */
279 if (is_host (optarg) == FALSE)
280 usage2 ("Invalid host name/address", optarg);
281 server_address = optarg;
282 break;
283 case 'p': /* number of packets to send */
284 if (is_intnonneg (optarg))
285 max_packets = atoi (optarg);
286 else
287 usage2 ("<max_packets> (%s) must be a non-negative number\n", optarg);
288 break;
289 case 'n': /* no HTML */
290 display_html = FALSE;
291 break;
292 case 'L': /* show HTML */
293 display_html = TRUE;
294 break;
295 case 'c':
296 get_threshold (optarg, &crta, &cpl);
297 break;
298 case 'w':
299 get_threshold (optarg, &wrta, &wpl);
300 break;
301 }
302 }
303
304 return i;
305}
306
307int
308get_threshold (char *arg, float *trta, int *tpl)
309{
310 if (is_intnonneg (arg) && sscanf (arg, "%f", trta) == 1)
311 return OK;
312 else if (strpbrk (arg, ",:") && strstr (arg, "%") && sscanf (arg, "%f%*[:,]%d%%", trta, tpl) == 2)
313 return OK;
314 else if (strstr (arg, "%") && sscanf (arg, "%d%%", tpl) == 1)
315 return OK;
316 else
317 usage2 ("%s: Warning threshold must be integer or percentage!\n\n", arg);
318
319}
320
321int
322validate_arguments ()
323{
324 float max_seconds;
325
326 if (wrta == UNKNOWN_TRIP_TIME) {
327 printf ("<wrta> was not set\n");
328 return ERROR;
329 }
330 else if (crta == UNKNOWN_TRIP_TIME) {
331 printf ("<crta> was not set\n");
332 return ERROR;
333 }
334 else if (wpl == UNKNOWN_PACKET_LOSS) {
335 printf ("<wpl> was not set\n");
336 return ERROR;
337 }
338 else if (cpl == UNKNOWN_PACKET_LOSS) {
339 printf ("<cpl> was not set\n");
340 return ERROR;
341 }
342 else if (wrta > crta) {
343 printf ("<wrta> (%f) cannot be larger than <crta> (%f)\n", wrta, crta);
344 return ERROR;
345 }
346 else if (wpl > cpl) {
347 printf ("<wpl> (%d) cannot be larger than <cpl> (%d)\n", wpl, cpl);
348 return ERROR;
349 }
350
351 if (max_packets == -1)
352 max_packets = DEFAULT_MAX_PACKETS;
353
354 max_seconds = crta / 1000.0 * max_packets + max_packets;
355 if (max_seconds > timeout_interval)
356 timeout_interval = (int)max_seconds;
357
358 return OK;
359}
360
361
362int
363run_ping (char *command_line)
364{
365 char input_buffer[MAX_INPUT_BUFFER];
366 int result = STATE_UNKNOWN;
367
368 warn_text = malloc (1);
369 if (warn_text == NULL)
370 terminate (STATE_UNKNOWN, "unable to malloc warn_text");
371 warn_text[0] = 0;
372
373 if ((child_process = spopen (command_line)) == NULL) {
374 printf ("Cannot open pipe: ");
375 terminate (STATE_UNKNOWN, command_line);
376 }
377 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
378 if (child_stderr == NULL)
379 printf ("Cannot open stderr for %s\n", command_line);
380
381 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
382
383 if (strstr (input_buffer, "(DUP!)")) {
384 result = max (result, STATE_WARNING);
385 warn_text = realloc (warn_text, strlen (WARN_DUPLICATES) + 1);
386 if (warn_text == NULL)
387 terminate (STATE_UNKNOWN, "unable to realloc warn_text");
388 strcpy (warn_text, WARN_DUPLICATES);
389 }
390
391 /* get the percent loss statistics */
392 if (sscanf
393 (input_buffer,
394 "%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss",
395 &pl) == 1
396 || sscanf (input_buffer,
397 "%*d packets transmitted, %*d packets received, %d%% packet loss",
398 &pl) == 1)
399 continue;
400
401 /* get the round trip average */
402 else
403 if (sscanf (input_buffer, "round-trip min/avg/max = %*f/%f/%*f", &rta)
404 == 1
405 || sscanf (input_buffer,
406 "round-trip min/avg/max/mdev = %*f/%f/%*f/%*f",
407 &rta) == 1
408 || sscanf (input_buffer,
409 "round-trip min/avg/max/sdev = %*f/%f/%*f/%*f",
410 &rta) == 1
411 || sscanf (input_buffer,
412 "round-trip min/avg/max/stddev = %*f/%f/%*f/%*f",
413 &rta) == 1
414 || sscanf (input_buffer,
415 "round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f",
416 &rta) == 1
417 || sscanf (input_buffer, "round-trip (ms) min/avg/max = %*f/%f/%*f",
418 &rta) == 1)
419 continue;
420 }
421
422 /* this is needed because there is no rta if all packets are lost */
423 if (pl == 100)
424 rta = crta;
425
426
427 /* check stderr */
428 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
429 if (strstr
430 (input_buffer,
431 "Warning: no SO_TIMESTAMP support, falling back to SIOCGSTAMP"))
432 continue;
433
434 if (strstr (input_buffer, "Network is unreachable"))
435 terminate (STATE_CRITICAL, "PING CRITICAL - Network unreachable (%s)",
436 server_address);
437 else if (strstr (input_buffer, "Destination Host Unreachable"))
438 terminate (STATE_CRITICAL, "PING CRITICAL - Host Unreachable (%s)",
439 server_address);
440
441 warn_text =
442 realloc (warn_text, strlen (warn_text) + strlen (input_buffer) + 2);
443 if (warn_text == NULL)
444 terminate (STATE_UNKNOWN, "unable to realloc warn_text");
445 if (strlen (warn_text) == 0)
446 strcpy (warn_text, input_buffer);
447 else
448 sprintf (warn_text, "%s %s", warn_text, input_buffer);
449
450 if (strstr (input_buffer, "DUPLICATES FOUND"))
451 result = max (result, STATE_WARNING);
452 else
453 result = max (result, STATE_CRITICAL);
454 }
455 (void) fclose (child_stderr);
456
457
458 /* close the pipe - WARNING if status is set */
459 if (spclose (child_process))
460 result = max (result, STATE_WARNING);
461
462 return result;
463}
464
465
466void
467print_usage (void)
468{
469 printf ("Usage:\n" " %s %s\n"
470#ifdef HAVE_GETOPT_H
471 " %s (-h | --help) for detailed help\n"
472 " %s (-V | --version) for version information\n",
473#else
474 " %s -h for detailed help\n"
475 " %s -V for version information\n",
476#endif
477 PROGNAME, OPTIONS, PROGNAME, PROGNAME);
478}
479
480void
481print_help (void)
482{
483 print_revision (PROGNAME, REVISION);
484 printf
485 ("Copyright (c) %s %s <%s>\n\n%s\n",
486 COPYRIGHT, AUTHOR, EMAIL, SUMMARY);
487 print_usage ();
488 printf
489 ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n",
490 DEFAULT_MAX_PACKETS, DEFAULT_SOCKET_TIMEOUT);
491 support ();
492}
diff --git a/plugins/check_pop.c b/plugins/check_pop.c
new file mode 100644
index 00000000..9fcfaec6
--- /dev/null
+++ b/plugins/check_pop.c
@@ -0,0 +1,364 @@
1/******************************************************************************
2 *
3 * CHECK_POP.C
4 *
5 * Program: POP3 plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 *
9 * $Id$
10 *
11 * Description:
12 *
13 * This plugin will attempt to open an POP connection with the host.
14 * Successul connects return STATE_OK, refusals and timeouts return
15 * STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful
16 * connects, but incorrect reponse messages from the host result in
17 * STATE_WARNING return values.
18 *
19 * License Information:
20 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
25 *
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
30 *
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 *
35 *****************************************************************************/
36
37#include "config.h"
38#include "common.h"
39#include "netutils.h"
40#include "utils.h"
41
42#define PROGNAME "check_pop"
43
44#define POP_PORT 110
45#define POP_EXPECT "+OK"
46#define POP_QUIT "QUIT\n"
47
48int process_arguments (int, char **);
49int call_getopt (int, char **);
50int validate_arguments (void);
51int check_disk (int usp, int free_disk);
52void print_help (void);
53void print_usage (void);
54
55int server_port = POP_PORT;
56char *server_address = NULL;
57char *server_expect = NULL;
58int warning_time = 0;
59int check_warning_time = FALSE;
60int critical_time = 0;
61int check_critical_time = FALSE;
62int verbose = FALSE;
63
64int
65main (int argc, char **argv)
66{
67 int sd;
68 int result;
69 char buffer[MAX_INPUT_BUFFER];
70
71 if (process_arguments (argc, argv) != OK)
72 usage ("Invalid command arguments supplied\n");
73
74 /* initialize alarm signal handling */
75 signal (SIGALRM, socket_timeout_alarm_handler);
76
77 /* set socket timeout */
78 alarm (socket_timeout);
79
80 /* try to connect to the host at the given port number */
81 time (&start_time);
82 result = my_tcp_connect (server_address, server_port, &sd);
83
84 /* we connected, so close connection before exiting */
85 if (result == STATE_OK) {
86
87 /* watch for the SMTP connection string */
88 result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
89
90 /* strip the buffer of carriage returns */
91 strip (buffer);
92
93 /* return a WARNING status if we couldn't read any data */
94 if (result == -1) {
95 printf ("recv() failed\n");
96 result = STATE_WARNING;
97 }
98
99 else {
100
101 /* make sure we find the response we are looking for */
102 if (!strstr (buffer, server_expect)) {
103 if (server_port == POP_PORT)
104 printf ("Invalid POP response received from host\n");
105 else
106 printf ("Invalid POP response received from host on port %d\n",
107 server_port);
108 result = STATE_WARNING;
109 }
110
111 else {
112 time (&end_time);
113
114 result = STATE_OK;
115
116 if (check_critical_time == TRUE
117 && (end_time - start_time) > critical_time) result =
118 STATE_CRITICAL;
119 else if (check_warning_time == TRUE
120 && (end_time - start_time) > warning_time) result =
121 STATE_WARNING;
122
123 if (verbose == TRUE)
124 printf ("POP %s - %d sec. response time, %s\n",
125 (result == STATE_OK) ? "ok" : "problem",
126 (int) (end_time - start_time), buffer);
127 else
128 printf ("POP %s - %d second response time\n",
129 (result == STATE_OK) ? "ok" : "problem",
130 (int) (end_time - start_time));
131 }
132 }
133
134 /* close the connection */
135 send (sd, POP_QUIT, strlen (POP_QUIT), 0);
136 close (sd);
137 }
138
139 /* reset the alarm */
140 alarm (0);
141
142 return result;
143}
144
145
146
147
148
149
150
151/* process command-line arguments */
152int
153process_arguments (int argc, char **argv)
154{
155 int c;
156
157 if (argc < 2)
158 return ERROR;
159
160 for (c = 1; c < argc; c++) {
161 if (strcmp ("-to", argv[c]) == 0)
162 strcpy (argv[c], "-t");
163 else if (strcmp ("-wt", argv[c]) == 0)
164 strcpy (argv[c], "-w");
165 else if (strcmp ("-ct", argv[c]) == 0)
166 strcpy (argv[c], "-c");
167 }
168
169
170
171 c = 0;
172 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
173
174 if (is_option (argv[c]))
175 continue;
176
177 if (server_address == NULL) {
178 if (is_host (argv[c])) {
179 server_address = argv[c];
180 }
181 else {
182 usage ("Invalid host name");
183 }
184 }
185 }
186
187 if (server_address == NULL)
188 server_address = strscpy (NULL, "127.0.0.1");
189
190 if (server_expect == NULL)
191 server_expect = strscpy (NULL, POP_EXPECT);
192
193 return validate_arguments ();
194}
195
196
197
198
199
200
201int
202call_getopt (int argc, char **argv)
203{
204 int c, i = 0;
205
206#ifdef HAVE_GETOPT_H
207 int option_index = 0;
208 static struct option long_options[] = {
209 {"hostname", required_argument, 0, 'H'},
210 {"expect", required_argument, 0, 'e'},
211 {"critical", required_argument, 0, 'c'},
212 {"warning", required_argument, 0, 'w'},
213 {"port", required_argument, 0, 'P'},
214 {"verbose", no_argument, 0, 'v'},
215 {"version", no_argument, 0, 'V'},
216 {"help", no_argument, 0, 'h'},
217 {0, 0, 0, 0}
218 };
219#endif
220
221 while (1) {
222#ifdef HAVE_GETOPT_H
223 c =
224 getopt_long (argc, argv, "+hVvt:p:e:c:w:H:", long_options,
225 &option_index);
226#else
227 c = getopt (argc, argv, "+?hVvt:p:e:c:w:H:");
228#endif
229
230 i++;
231
232 if (c == -1 || c == EOF || c == 1)
233 break;
234
235 switch (c) {
236 case 't':
237 case 'p':
238 case 'e':
239 case 'c':
240 case 'w':
241 case 'H':
242 i++;
243 }
244
245 switch (c) {
246 case 'H': /* hostname */
247 if (is_host (optarg)) {
248 server_address = optarg;
249 }
250 else {
251 usage ("Invalid host name\n");
252 }
253 break;
254 case 'p': /* port */
255 if (is_intpos (optarg)) {
256 server_port = atoi (optarg);
257 }
258 else {
259 usage ("Server port must be a positive integer\n");
260 }
261 break;
262 case 'e': /* username */
263 server_expect = optarg;
264 break;
265 case 'c': /* critical time threshold */
266 if (is_intnonneg (optarg)) {
267 critical_time = atoi (optarg);
268 check_critical_time = TRUE;
269 }
270 else {
271 usage ("Critical time must be a nonnegative integer\n");
272 }
273 break;
274 case 'w': /* warning time threshold */
275 if (is_intnonneg (optarg)) {
276 warning_time = atoi (optarg);
277 check_warning_time = TRUE;
278 }
279 else {
280 usage ("Warning time must be a nonnegative integer\n");
281 }
282 break;
283 case 'v': /* verbose */
284 verbose = TRUE;
285 break;
286 case 't': /* timeout */
287 if (is_intnonneg (optarg)) {
288 socket_timeout = atoi (optarg);
289 }
290 else {
291 usage ("Time interval must be a nonnegative integer\n");
292 }
293 break;
294 case 'V': /* version */
295 print_revision (PROGNAME, "$Revision$");
296 exit (STATE_OK);
297 case 'h': /* help */
298 print_help ();
299 exit (STATE_OK);
300 case '?': /* help */
301 usage ("Invalid argument\n");
302 }
303 }
304 return i;
305}
306
307
308
309
310
311int
312validate_arguments (void)
313{
314 return OK;
315}
316
317
318
319
320
321void
322print_help (void)
323{
324 print_revision (PROGNAME, "$Revision$");
325 printf
326 ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
327 "This plugin tests the POP service on the specified host.\n\n");
328 print_usage ();
329 printf
330 ("\nOptions:\n"
331 " -H, --hostname=STRING or IPADDRESS\n"
332 " Check server on the indicated host\n"
333 " -p, --port=INTEGER\n"
334 " Make connection on the indicated port (default: %d)\n"
335 " -e, --expect=STRING\n"
336 " String to expect in first line of server response (default: %s)\n"
337 " -w, --warning=INTEGER\n"
338 " Seconds necessary to result in a warning status\n"
339 " -c, --critical=INTEGER\n"
340 " Seconds necessary to result in a critical status\n"
341 " -t, --timeout=INTEGER\n"
342 " Seconds before connection attempt times out (default: %d)\n"
343 " -v, --verbose\n"
344 " Print extra information (command-line use only)\n"
345 " -h, --help\n"
346 " Print detailed help screen\n"
347 " -V, --version\n"
348 " Print version information\n\n",
349 POP_PORT, POP_EXPECT, DEFAULT_SOCKET_TIMEOUT);
350 support ();
351}
352
353
354
355
356
357void
358print_usage (void)
359{
360 printf
361 ("Usage: %s -H host [-e expect] [-p port] [-w warn] [-c crit] [-t timeout] [-v]\n"
362 " %s --help\n"
363 " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
364}
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
new file mode 100644
index 00000000..c66d33de
--- /dev/null
+++ b/plugins/check_procs.c
@@ -0,0 +1,510 @@
1/******************************************************************************
2*
3* CHECK_PROCS.C
4*
5* Program: Process plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8*
9* $Id$
10*
11* Description:
12*
13* This plugin checks the number of currently running processes and
14* generates WARNING or CRITICAL states if the process count is outside
15* the specified threshold ranges. The process count can be filtered by
16* process owner, parent process PID, current state (e.g., 'Z'), or may
17* be the total number of running processes
18*
19* License Information:
20*
21* This program is free software; you can redistribute it and/or modify
22* it under the terms of the GNU General Public License as published by
23* the Free Software Foundation; either version 2 of the License, or
24* (at your option) any later version.
25*
26* This program is distributed in the hope that it will be useful, but
27* WITHOUT ANY WARRANTY; without even the implied warranty of
28* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29* General Public License for more details.
30*
31* You should have received a copy of the GNU General Public License
32* along with this program; if not, write to the Free Software
33* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34*
35******************************************************************************/
36
37#include "config.h"
38#include <pwd.h>
39#include "common.h"
40#include "popen.h"
41#include "utils.h"
42
43int process_arguments (int, char **);
44int call_getopt (int, char **);
45int validate_arguments (void);
46void print_usage (void);
47void print_help (char *);
48
49int wmax = -1;
50int cmax = -1;
51int wmin = -1;
52int cmin = -1;
53
54int options = 0;
55#define ALL 1
56#define STAT 2
57#define PPID 4
58#define USER 8
59#define PROG 16
60#define ARGS 32
61
62int verbose = FALSE;
63int uid;
64int ppid;
65char *statopts = NULL;
66char *prog = NULL;
67char *args = NULL;
68char *format = NULL;
69char tmp[MAX_INPUT_BUFFER];
70
71int
72main (int argc, char **argv)
73{
74 char input_buffer[MAX_INPUT_BUFFER];
75
76 int procuid = 0;
77 int procppid = 0;
78 char procstat[8];
79 char procprog[MAX_INPUT_BUFFER];
80 char *procargs;
81
82 int resultsum = 0;
83 int found = 0;
84 int procs = 0;
85 int pos;
86
87 int result = STATE_UNKNOWN;
88
89 procargs = malloc (MAX_INPUT_BUFFER);
90
91 if (process_arguments (argc, argv) == ERROR)
92 usage ("Unable to parse command line\n");
93
94 /* run the command */
95 if (verbose)
96 printf ("%s\n", PS_COMMAND);
97 child_process = spopen (PS_COMMAND);
98 if (child_process == NULL) {
99 printf ("Could not open pipe: %s\n", PS_COMMAND);
100 return STATE_UNKNOWN;
101 }
102
103 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
104 if (child_stderr == NULL)
105 printf ("Could not open stderr for %s\n", PS_COMMAND);
106
107 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
108
109 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
110 if (
111#ifdef USE_PS_VARS
112 sscanf (input_buffer, PS_FORMAT, PS_VARLIST) >= 4
113#else
114 sscanf (input_buffer, PS_FORMAT, procstat, &procuid, &procppid, &pos,
115 procprog) >= 4
116#endif
117 ) {
118 found++;
119 resultsum = 0;
120 procargs = strcpy (procargs, &input_buffer[pos]);
121 strip (procargs);
122 if ((options & STAT) && (strstr (statopts, procstat)))
123 resultsum |= STAT;
124 if ((options & ARGS) && (strstr (procargs, args) == procargs))
125 resultsum |= ARGS;
126 if ((options & PROG) && (strcmp (prog, procprog) == 0))
127 resultsum |= PROG;
128 if ((options & PPID) && (procppid == ppid))
129 resultsum |= PPID;
130 if ((options & USER) && (procuid == uid))
131 resultsum |= USER;
132#ifdef DEBUG1
133 if (procargs == NULL)
134 printf ("%d %d %d %s %s\n", procs, procuid, procppid, procstat,
135 procprog);
136 else
137 printf ("%d %d %d %s %s %s\n", procs, procuid, procppid, procstat,
138 procprog, procargs);
139#endif
140 if (options == resultsum)
141 procs++;
142 }
143 }
144
145 /* If we get anything on STDERR, at least set warning */
146 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
147 if (verbose)
148 printf ("%s", input_buffer);
149 result = max (result, STATE_WARNING);
150 }
151 if (result > STATE_OK)
152 printf ("System call sent warnings to stderr\n");
153
154 (void) fclose (child_stderr);
155
156 /* close the pipe */
157 if (spclose (child_process)) {
158 printf ("System call returned nonzero status\n");
159 return max (result, STATE_WARNING);
160 }
161
162 if (options == ALL)
163 procs = found;
164
165 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
166 printf ("Unable to read output\n");
167 return max (result, STATE_UNKNOWN);
168 }
169
170 if (verbose && (options & STAT))
171 printf ("%s ", statopts);
172 if (verbose && (options & PROG))
173 printf ("%s ", prog);
174 if (verbose && (options & PPID))
175 printf ("%d ", ppid);
176 if (verbose && (options & USER))
177 printf ("%d ", uid);
178
179 if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
180 if (procs > cmax && procs < cmin) {
181 printf (format, "CRITICAL", procs);
182 return STATE_CRITICAL;
183 }
184 }
185 else if (cmax >= 0 && procs > cmax) {
186 printf (format, "CRITICAL", procs);
187 return STATE_CRITICAL;
188 }
189 else if (cmin >= 0 && procs < cmin) {
190 printf (format, "CRITICAL", procs);
191 return STATE_CRITICAL;
192 }
193
194 if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
195 if (procs > wmax && procs < wmin) {
196 printf (format, "CRITICAL", procs);
197 return STATE_CRITICAL;
198 }
199 }
200 else if (wmax >= 0 && procs > wmax) {
201 printf (format, "WARNING", procs);
202 return max (result, STATE_WARNING);
203 }
204 else if (wmin >= 0 && procs < wmin) {
205 printf (format, "WARNING", procs);
206 return max (result, STATE_WARNING);
207 }
208
209 printf (format, "OK", procs);
210 return max (result, STATE_OK);
211}
212
213/* process command-line arguments */
214int
215process_arguments (int argc, char **argv)
216{
217 int c;
218
219 if (argc < 2)
220 return ERROR;
221
222 for (c = 1; c < argc; c++)
223 if (strcmp ("-to", argv[c]) == 0)
224 strcpy (argv[c], "-t");
225
226 c = 0;
227 while (c += (call_getopt (argc - c, &argv[c]))) {
228 if (argc <= c)
229 break;
230 if (wmax == -1)
231 wmax = atoi (argv[c]);
232 else if (cmax == -1)
233 cmax = atoi (argv[c]);
234 else if (statopts == NULL) {
235 statopts = strscpy (statopts, argv[c]);
236 format =
237 strscat (format,
238 ssprintf (NULL, "%sSTATE = %s", (options ? ", " : ""),
239 statopts));
240 options |= STAT;
241 }
242 }
243
244 return validate_arguments ();
245}
246
247int
248call_getopt (int argc, char **argv)
249{
250 int c, i = 1;
251 char *user;
252 struct passwd *pw;
253#ifdef HAVE_GETOPT_H
254 int option_index = 0;
255 static struct option long_options[] = {
256 {"warning", required_argument, 0, 'w'},
257 {"critical", required_argument, 0, 'c'},
258 {"timeout", required_argument, 0, 't'},
259 {"status", required_argument, 0, 's'},
260 {"ppid", required_argument, 0, 'p'},
261 {"command", required_argument, 0, 'C'},
262 {"argument-array", required_argument, 0, 'a'},
263 {"help", no_argument, 0, 'h'},
264 {"version", no_argument, 0, 'V'},
265 {"verbose", no_argument, 0, 'v'},
266 {0, 0, 0, 0}
267 };
268#endif
269
270 while (1) {
271#ifdef HAVE_GETOPT_H
272 c =
273 getopt_long (argc, argv, "+Vvht:c:w:p:s:u:C:a:", long_options,
274 &option_index);
275#else
276 c = getopt (argc, argv, "+Vvht:c:w:p:s:u:C:a:");
277#endif
278
279 if (c == EOF)
280 break;
281
282 i++;
283 switch (c) {
284 case 't':
285 case 'c':
286 case 'w':
287 case 'p':
288 case 's':
289 case 'a':
290 case 'u':
291 case 'C':
292 i++;
293 }
294
295 switch (c) {
296 case '?': /* help */
297 print_usage ();
298 exit (STATE_UNKNOWN);
299 case 'h': /* help */
300 print_help (my_basename (argv[0]));
301 exit (STATE_OK);
302 case 'V': /* version */
303 print_revision (my_basename (argv[0]), "$Revision$");
304 exit (STATE_OK);
305 case 't': /* timeout period */
306 if (!is_integer (optarg)) {
307 printf ("%s: Timeout Interval must be an integer!\n\n",
308 my_basename (argv[0]));
309 print_usage ();
310 exit (STATE_UNKNOWN);
311 }
312 timeout_interval = atoi (optarg);
313 break;
314 case 'c': /* critical threshold */
315 if (is_integer (optarg)) {
316 cmax = atoi (optarg);
317 break;
318 }
319 else if (sscanf (optarg, ":%d", &cmax) == 1) {
320 break;
321 }
322 else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2) {
323 break;
324 }
325 else if (sscanf (optarg, "%d:", &cmin) == 1) {
326 break;
327 }
328 else {
329 printf ("%s: Critical Process Count must be an integer!\n\n",
330 my_basename (argv[0]));
331 print_usage ();
332 exit (STATE_UNKNOWN);
333 }
334 case 'w': /* warning time threshold */
335 if (is_integer (optarg)) {
336 wmax = atoi (optarg);
337 break;
338 }
339 else if (sscanf (optarg, ":%d", &wmax) == 1) {
340 break;
341 }
342 else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2) {
343 break;
344 }
345 else if (sscanf (optarg, "%d:", &wmin) == 1) {
346 break;
347 }
348 else {
349 printf ("%s: Warning Process Count must be an integer!\n\n",
350 my_basename (argv[0]));
351 print_usage ();
352 exit (STATE_UNKNOWN);
353 }
354 case 'p': /* process id */
355 if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
356 format =
357 strscat (format,
358 ssprintf (NULL, "%sPPID = %d", (options ? ", " : ""),
359 ppid));
360 options |= PPID;
361 break;
362 }
363 printf ("%s: Parent Process ID must be an integer!\n\n",
364 my_basename (argv[0]));
365 print_usage ();
366 exit (STATE_UNKNOWN);
367 case 's': /* status */
368 statopts = strscpy (statopts, optarg);
369 format =
370 strscat (format,
371 ssprintf (NULL, "%sSTATE = %s", (options ? ", " : ""),
372 statopts));
373 options |= STAT;
374 break;
375 case 'u': /* user or user id */
376 if (is_integer (optarg)) {
377 uid = atoi (optarg);
378 pw = getpwuid ((uid_t) uid);
379 /* check to be sure user exists */
380 if (pw == NULL) {
381 printf ("UID %d was not found\n", uid);
382 print_usage ();
383 exit (STATE_UNKNOWN);
384 }
385 }
386 else {
387 pw = getpwnam (optarg);
388 /* check to be sure user exists */
389 if (pw == NULL) {
390 printf ("User name %s was not found\n", optarg);
391 print_usage ();
392 exit (STATE_UNKNOWN);
393 }
394 /* then get uid */
395 uid = pw->pw_uid;
396 }
397 user = pw->pw_name;
398 format =
399 strscat (format,
400 ssprintf (NULL, "%sUID = %d (%s)", (options ? ", " : ""),
401 uid, user));
402 options |= USER;
403 break;
404 case 'C': /* command */
405 prog = strscpy (prog, optarg);
406 format =
407 strscat (format,
408 ssprintf (NULL, "%scommand name %s", (options ? ", " : ""),
409 prog));
410 options |= PROG;
411 break;
412 case 'a': /* args (full path name with args) */
413 args = strscpy (args, optarg);
414 format =
415 strscat (format,
416 ssprintf (NULL, "%sargs %s", (options ? ", " : ""), args));
417 options |= ARGS;
418 break;
419 case 'v': /* command */
420 verbose = TRUE;
421 break;
422 }
423 }
424 return i;
425}
426
427
428int
429validate_arguments ()
430{
431
432 if (wmax >= 0 && wmin == -1)
433 wmin = 0;
434 if (cmax >= 0 && cmin == -1)
435 cmin = 0;
436 if (wmax >= wmin && cmax >= cmin) { /* standard ranges */
437 if (wmax > cmax && cmax != -1) {
438 printf ("wmax (%d) cannot be greater than cmax (%d)\n", wmax, cmax);
439 return ERROR;
440 }
441 if (cmin > wmin && wmin != -1) {
442 printf ("wmin (%d) cannot be less than cmin (%d)\n", wmin, cmin);
443 return ERROR;
444 }
445 }
446
447 if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
448 printf ("At least one threshold must be set\n");
449 return ERROR;
450 }
451
452 if (options == 0) {
453 options = 1;
454 format = ssprintf (format, "%%s - %%d processes running\n");
455 }
456 else {
457 format =
458 ssprintf (format, "%%s - %%d processes running with %s\n", format);
459 }
460
461 return options;
462}
463
464
465void
466print_help (char *cmd)
467{
468 print_revision (cmd, "$Revision$");
469 printf
470 ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n\n"
471 "This plugin checks the number of currently running processes and\n"
472 "generates WARNING or CRITICAL states if the process count is outside\n"
473 "the specified threshold ranges. The process count can be filtered by\n"
474 "process owner, parent process PID, current state (e.g., 'Z'), or may\n"
475 "be the total number of running processes\n\n");
476 print_usage ();
477 printf
478 ("\nRequired Arguments:\n"
479 " -w, --warning=RANGE\n"
480 " generate warning state if process count is outside this range\n"
481 " -c, --critical=RANGE\n"
482 " generate critical state if process count is outside this range\n\n"
483 "Optional Filters:\n"
484 " -s, --state=STATUSFLAGS\n"
485 " Only scan for processes that have, in the output of `ps`, one or\n"
486 " more of the status flags you specify (for example R, Z, S, RS,\n"
487 " RSZDT, plus others based on the output of your 'ps' command).\n"
488 " -p, --ppid=PPID\n"
489 " Only scan for children of the parent process ID indicated.\n"
490 " -u, --user=USER\n"
491 " Only scan for proceses with user name or ID indicated.\n"
492 " -a, --argument-array=STRING\n"
493 " Only scan for ARGS that match up to the length of the given STRING\n"
494 " -C, --command=COMMAND\n"
495 " Only scan for exact matches to the named COMMAND.\n\n"
496 "RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n"
497 "specified 'max:min', a warning status will be generated if the\n"
498
499 "count is inside the specified range\n");}
500
501
502void
503print_usage (void)
504{
505 printf
506 ("Usage:\n"
507 " check_procs -w <range> -c <range> [-s state] [-p ppid] [-u user]\n"
508 " [-a argument-array] [-C command]\n"
509 " check_procs --version\n" " check_procs --help\n");
510}
diff --git a/plugins/check_radius.c b/plugins/check_radius.c
new file mode 100644
index 00000000..614d467b
--- /dev/null
+++ b/plugins/check_radius.c
@@ -0,0 +1,345 @@
1/******************************************************************************
2 *
3 * Program: radius server check plugin for Nagios
4 * License: GPL
5 *
6 * License Information:
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * $Id$
23 *
24 *****************************************************************************/
25
26#define PROGNAME "check_radius"
27#define REVISION "$Revision$"
28#define COPYRIGHT "1999-2001"
29#define AUTHORS "Robert August Vincent II/Karl DeBisschop"
30#define EMAIL "kdebisschop@users.sourceforge.net"
31#define SUMMARY "Tests to see if a radius server is accepting connections.\n"
32
33#define OPTIONS "\
34-H host -F config_file -u username -p password\'\
35 [-P port] [-t timeout] [-r retries] [-e expect]"
36
37#define LONGOPTIONS "\
38 -H, --hostname=HOST\n\
39 Host name argument for servers using host headers (use numeric\n\
40 address if possible to bypass DNS lookup).\n\
41 -P, --port=INTEGER\n\
42 Port number (default: %d)\n\
43 -u, --username=STRING\n\
44 The user to authenticate\n\
45 -p, --password=STRING\n\
46 Password for autentication (SECURITY RISK)\n\
47 -F, --filename=STRING\n\
48 Configuration file\n\
49 -e, --expect=STRING\n\
50 Response string to expect from the server\n\
51 -r, --retries=INTEGER\n\
52 Number of times to retry a failed connection\n\
53 -t, --timeout=INTEGER\n\
54 Seconds before connection times out (default: %d)\n\
55 -v\n\
56 Show details for command-line debugging (do not use with nagios server)\n\
57 -h, --help\n\
58 Print detailed help screen\n\
59 -V, --version\n\
60 Print version information\n"
61
62#define DESCRIPTION "\
63The password option presents a substantial security issue because the
64password can be determined by careful watching of the command line in
65a process listing. This risk is exacerbated because nagios will
66run the plugin at regular prdictable intervals. Please be sure that
67the password used does not allow access to sensitive system resources,
68otherwise compormise could occur.\n"
69
70#include "config.h"
71#include "common.h"
72#include "utils.h"
73#include <radiusclient.h>
74
75int process_arguments (int, char **);
76void print_usage (void);
77void print_help (void);
78
79char *server = NULL;
80int port = PW_AUTH_UDP_PORT;
81char *username = NULL;
82char *password = NULL;
83char *expect = NULL;
84char *config_file = NULL;
85int retries = 1;
86int verbose = FALSE;
87
88ENV *env = NULL;
89
90/******************************************************************************
91
92The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
93tags in the comments. With in the tags, the XML is assembled sequentially.
94You can define entities in tags. You also have all the #defines available as
95entities.
96
97Please note that all tags must be lowercase to use the DocBook XML DTD.
98
99@@-<article>
100
101<sect1>
102<title>Quick Reference</title>
103<!-- The refentry forms a manpage -->
104<refentry>
105<refmeta>
106<manvolnum>5<manvolnum>
107</refmeta>
108<refnamdiv>
109<refname>&PROGNAME;</refname>
110<refpurpose>&SUMMARY;</refpurpose>
111</refnamdiv>
112</refentry>
113</sect1>
114
115<sect1>
116<title>FAQ</title>
117</sect1>
118
119<sect1>
120<title>Theory, Installation, and Operation</title>
121
122<sect2>
123<title>General Description</title>
124<para>
125&DESCRIPTION;
126</para>
127</sect2>
128
129<sect2>
130<title>Future Enhancements</title>
131<para>ToDo List</para>
132<itemizedlist>
133<listitem>Add option to get password from a secured file rather than the command line</listitem>
134</itemizedlist>
135</sect2>
136
137
138<sect2>
139<title>Functions</title>
140-@@
141******************************************************************************/
142
143int
144main (int argc, char **argv)
145{
146 UINT4 service;
147 char msg[BUFFER_LEN];
148 SEND_DATA data = { 0 };
149 int result;
150 UINT4 client_id;
151
152 if (process_arguments (argc, argv) == ERROR)
153 usage ("Could not parse arguments\n");
154
155 if ((config_file && rc_read_config (config_file)) ||
156 rc_read_dictionary (rc_conf_str ("dictionary")))
157 terminate (STATE_UNKNOWN, "Config file error");
158
159 service = PW_AUTHENTICATE_ONLY;
160
161 if (!(rc_avpair_add (&data.send_pairs, PW_SERVICE_TYPE, &service, 0) &&
162 rc_avpair_add (&data.send_pairs, PW_USER_NAME, username, 0) &&
163 rc_avpair_add (&data.send_pairs, PW_USER_PASSWORD, password, 0)))
164 terminate (STATE_UNKNOWN, "Out of Memory?");
165
166 /*
167 * Fill in NAS-IP-Address
168 */
169
170 if ((client_id = rc_own_ipaddress ()) == 0)
171 return (ERROR_RC);
172
173 if (rc_avpair_add (&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0) ==
174 NULL) return (ERROR_RC);
175
176 rc_buildreq (&data, PW_ACCESS_REQUEST, server, port, timeout_interval,
177 retries);
178
179 result = rc_send_server (&data, msg);
180 rc_avpair_free (data.send_pairs);
181 if (data.receive_pairs)
182 rc_avpair_free (data.receive_pairs);
183
184 if (result == TIMEOUT_RC)
185 terminate (STATE_CRITICAL, "Timeout");
186 if (result == ERROR_RC)
187 terminate (STATE_CRITICAL, "Auth Error");
188 if (result == BADRESP_RC)
189 terminate (STATE_WARNING, "Auth Failed");
190 if (expect && !strstr (msg, expect))
191 terminate (STATE_WARNING, msg);
192 if (result == OK_RC)
193 terminate (STATE_OK, "Auth OK");
194 return (0);
195}
196
197
198
199/* process command-line arguments */
200int
201process_arguments (int argc, char **argv)
202{
203 int c;
204
205#ifdef HAVE_GETOPT_H
206 int option_index = 0;
207 static struct option long_options[] = {
208 {"hostname", required_argument, 0, 'H'},
209 {"port", required_argument, 0, 'P'},
210 {"username", required_argument, 0, 'u'},
211 {"password", required_argument, 0, 'p'},
212 {"filename", required_argument, 0, 'F'},
213 {"expect", required_argument, 0, 'e'},
214 {"retries", required_argument, 0, 'r'},
215 {"timeout", required_argument, 0, 't'},
216 {"verbose", no_argument, 0, 'v'},
217 {"version", no_argument, 0, 'V'},
218 {"help", no_argument, 0, 'h'},
219 {0, 0, 0, 0}
220 };
221#endif
222
223 if (argc < 2)
224 return ERROR;
225
226 if (argc == 9) {
227 config_file = argv[1];
228 username = argv[2];
229 password = argv[3];
230 if (is_intpos (argv[4]))
231 timeout_interval = atoi (argv[4]);
232 else
233 usage ("Timeout interval must be a positive integer");
234 if (is_intpos (argv[5]))
235 retries = atoi (argv[5]);
236 else
237 usage ("Number of retries must be a positive integer");
238 server = argv[6];
239 if (is_intpos (argv[7]))
240 port = atoi (argv[7]);
241 else
242 usage ("Server port must be a positive integer");
243 expect = argv[8];
244 return OK;
245 }
246
247 while (1) {
248#ifdef HAVE_GETOPT_H
249 c =
250 getopt_long (argc, argv, "+hVvH:P:F:u:p:t:r:e:", long_options,
251 &option_index);
252#else
253 c = getopt (argc, argv, "+hVvH:P:F:u:p:t:r:e:");
254#endif
255
256 if (c == -1 || c == EOF || c == 1)
257 break;
258
259 switch (c) {
260 case '?': /* print short usage statement if args not parsable */
261 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
262 print_usage ();
263 exit (STATE_UNKNOWN);
264 case 'h': /* help */
265 print_help ();
266 exit (OK);
267 case 'V': /* version */
268 print_revision (my_basename (argv[0]), "$Revision$");
269 exit (OK);
270 case 'v': /* verbose mode */
271 verbose = TRUE;
272 break;
273 case 'H': /* hostname */
274 if (is_host (optarg) == FALSE) {
275 printf ("Invalid host name/address\n\n");
276 print_usage ();
277 exit (STATE_UNKNOWN);
278 }
279 server = optarg;
280 break;
281 case 'P': /* port */
282 if (is_intnonneg (optarg))
283 port = atoi (optarg);
284 else
285 usage ("Server port must be a positive integer");
286 break;
287 case 'u': /* username */
288 username = optarg;
289 break;
290 case 'p': /* password */
291 password = optarg;
292 break;
293 case 'F': /* configuration file */
294 config_file = optarg;
295 break;
296 case 'e': /* expect */
297 expect = optarg;
298 break;
299 case 'r': /* retries */
300 if (is_intpos (optarg))
301 retries = atoi (optarg);
302 else
303 usage ("Number of retries must be a positive integer");
304 break;
305 case 't': /* timeout */
306 if (is_intpos (optarg))
307 timeout_interval = atoi (optarg);
308 else
309 usage ("Timeout interval must be a positive integer");
310 break;
311 }
312 }
313 return OK;
314}
315
316
317
318void
319print_help (void)
320{
321 print_revision (PROGNAME, REVISION);
322 printf
323 ("Copyright (c) %s %s <%s>\n\n%s\n",
324 COPYRIGHT, AUTHORS, EMAIL, SUMMARY);
325 print_usage ();
326 printf
327 ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n",
328 port, timeout_interval);
329 support ();
330}
331
332
333void
334print_usage (void)
335{
336 printf ("Usage:\n" " %s %s\n"
337#ifdef HAVE_GETOPT_H
338 " %s (-h | --help) for detailed help\n"
339 " %s (-V | --version) for version information\n",
340#else
341 " %s -h for detailed help\n"
342 " %s -V for version information\n",
343#endif
344 PROGNAME, OPTIONS, PROGNAME, PROGNAME);
345}
diff --git a/plugins/check_real.c b/plugins/check_real.c
new file mode 100644
index 00000000..ba746b81
--- /dev/null
+++ b/plugins/check_real.c
@@ -0,0 +1,661 @@
1/*****************************************************************************
2*
3* CHECK_REAL.C
4*
5* Program: RealMedia plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Pedro Leite (leite@cic.ua.pt)
8*
9* Based on CHECK_HTTP.C
10* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
11*
12* Last Modified: $Date$
13*
14* Command line: CHECK_REAL <host_address> [-e expect] [-u url] [-p port]
15* [-hn host_name] [-wt warn_time] [-ct crit_time]
16* [-to to_sec]
17*
18* Description:
19*
20* This plugin will attempt to open an RTSP connection with the host.
21* Successul connects return STATE_OK, refusals and timeouts return
22* STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful connects,
23* but incorrect reponse messages from the host result in STATE_WARNING return
24* values. If you are checking a virtual server that uses "host headers"you
25* must supply the FQDN (fully qualified domain name) as the [host_name]
26* argument.
27*
28* License Information:
29*
30* This program is free software; you can redistribute it and/or modify
31* it under the terms of the GNU General Public License as published by
32* the Free Software Foundation; either version 2 of the License, or
33* (at your option) any later version.
34*
35* This program is distributed in the hope that it will be useful,
36* but WITHOUT ANY WARRANTY; without even the implied warranty of
37* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38* GNU General Public License for more details.
39*
40* You should have received a copy of the GNU General Public License
41* along with this program; if not, write to the Free Software
42* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
43*
44****************************************************************************/
45
46#include "config.h"
47#include "common.h"
48#include "netutils.h"
49#include "utils.h"
50
51#define PROGNAME "check_real"
52
53#define PORT 554
54#define EXPECT "RTSP/1."
55#define URL ""
56
57int process_arguments (int, char **);
58int call_getopt (int, char **);
59int validate_arguments (void);
60int check_disk (int usp, int free_disk);
61void print_help (void);
62void print_usage (void);
63
64int server_port = PORT;
65char *server_address = NULL;
66char *host_name = NULL;
67char *server_url = NULL;
68char *server_expect = NULL;
69int warning_time = 0;
70int check_warning_time = FALSE;
71int critical_time = 0;
72int check_critical_time = FALSE;
73int verbose = FALSE;
74
75int
76main (int argc, char **argv)
77{
78 int sd;
79 int result;
80 char buffer[MAX_INPUT_BUFFER];
81 char *status_line = NULL;
82
83 if (process_arguments (argc, argv) != OK)
84 usage ("Invalid command arguments supplied\n");
85
86 /* initialize alarm signal handling */
87 signal (SIGALRM, socket_timeout_alarm_handler);
88
89 /* set socket timeout */
90 alarm (socket_timeout);
91 time (&start_time);
92
93 /* try to connect to the host at the given port number */
94 if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK)
95 terminate (STATE_CRITICAL, "Unable to connect to %s on port %d\n",
96 server_address, server_port);
97
98 /* Part I - Server Check */
99
100 /* send the OPTIONS request */
101 sprintf (buffer, "OPTIONS rtsp://%s:%d RTSP/1.0\n", host_name, server_port);
102 result = send (sd, buffer, strlen (buffer), 0);
103
104 /* send the header sync */
105 sprintf (buffer, "CSeq: 1\n");
106 result = send (sd, buffer, strlen (buffer), 0);
107
108 /* send a newline so the server knows we're done with the request */
109 sprintf (buffer, "\n");
110 result = send (sd, buffer, strlen (buffer), 0);
111
112 /* watch for the REAL connection string */
113 result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
114
115 /* return a CRITICAL status if we couldn't read any data */
116 if (result == -1)
117 terminate (STATE_CRITICAL, "No data received from %s\n", host_name);
118
119 /* make sure we find the response we are looking for */
120 if (!strstr (buffer, EXPECT)) {
121 if (server_port == PORT)
122 printf ("Invalid REAL response received from host\n");
123 else
124 printf ("Invalid REAL response received from host on port %d\n",
125 server_port);
126 }
127 else {
128 /* else we got the REAL string, so check the return code */
129
130 time (&end_time);
131
132 result = STATE_OK;
133
134 status_line = (char *) strtok (buffer, "\n");
135
136 if (strstr (status_line, "200"))
137 result = STATE_OK;
138
139 /* client errors result in a warning state */
140 else if (strstr (status_line, "400"))
141 result = STATE_WARNING;
142 else if (strstr (status_line, "401"))
143 result = STATE_WARNING;
144 else if (strstr (status_line, "402"))
145 result = STATE_WARNING;
146 else if (strstr (status_line, "403"))
147 result = STATE_WARNING;
148 else if (strstr (status_line, "404"))
149 result = STATE_WARNING;
150
151 /* server errors result in a critical state */
152 else if (strstr (status_line, "500"))
153 result = STATE_CRITICAL;
154 else if (strstr (status_line, "501"))
155 result = STATE_CRITICAL;
156 else if (strstr (status_line, "502"))
157 result = STATE_CRITICAL;
158 else if (strstr (status_line, "503"))
159 result = STATE_CRITICAL;
160
161 else
162 result = STATE_UNKNOWN;
163 }
164
165 /* Part II - Check stream exists and is ok */
166 if ((result == STATE_OK) && (server_url != NULL)) {
167
168 /* Part I - Server Check */
169
170 /* send the OPTIONS request */
171 sprintf (buffer, "DESCRIBE rtsp://%s:%d%s RTSP/1.0\n", host_name,
172 server_port, server_url);
173 result = send (sd, buffer, strlen (buffer), 0);
174
175 /* send the header sync */
176 sprintf (buffer, "CSeq: 2\n");
177 result = send (sd, buffer, strlen (buffer), 0);
178
179 /* send a newline so the server knows we're done with the request */
180 sprintf (buffer, "\n");
181 result = send (sd, buffer, strlen (buffer), 0);
182
183 /* watch for the REAL connection string */
184 result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
185
186 /* return a CRITICAL status if we couldn't read any data */
187 if (result == -1) {
188 printf ("No data received from host\n");
189 result = STATE_CRITICAL;
190 }
191 else {
192 /* make sure we find the response we are looking for */
193 if (!strstr (buffer, EXPECT)) {
194 if (server_port == PORT)
195 printf ("Invalid REAL response received from host\n");
196 else
197 printf ("Invalid REAL response received from host on port %d\n",
198 server_port);
199 }
200 else {
201
202 /* else we got the REAL string, so check the return code */
203
204 time (&end_time);
205
206 result = STATE_OK;
207
208 status_line = (char *) strtok (buffer, "\n");
209
210 if (strstr (status_line, "200"))
211 result = STATE_OK;
212
213 /* client errors result in a warning state */
214 else if (strstr (status_line, "400"))
215 result = STATE_WARNING;
216 else if (strstr (status_line, "401"))
217 result = STATE_WARNING;
218 else if (strstr (status_line, "402"))
219 result = STATE_WARNING;
220 else if (strstr (status_line, "403"))
221 result = STATE_WARNING;
222 else if (strstr (status_line, "404"))
223 result = STATE_WARNING;
224
225 /* server errors result in a critical state */
226 else if (strstr (status_line, "500"))
227 result = STATE_CRITICAL;
228 else if (strstr (status_line, "501"))
229 result = STATE_CRITICAL;
230 else if (strstr (status_line, "502"))
231 result = STATE_CRITICAL;
232 else if (strstr (status_line, "503"))
233 result = STATE_CRITICAL;
234
235 else
236 result = STATE_UNKNOWN;
237 }
238 }
239 }
240
241 /* Return results */
242 if (result == STATE_OK) {
243
244 if (check_critical_time == TRUE
245 && (end_time - start_time) > critical_time) result = STATE_CRITICAL;
246 else if (check_warning_time == TRUE
247 && (end_time - start_time) > warning_time) result =
248 STATE_WARNING;
249
250 /* Put some HTML in here to create a dynamic link */
251 printf ("REAL %s - %d second response time\n",
252 (result == STATE_OK) ? "ok" : "problem",
253 (int) (end_time - start_time));
254 }
255 else
256 printf ("%s\n", status_line);
257
258 /* close the connection */
259 close (sd);
260
261 /* reset the alarm */
262 alarm (0);
263
264 return result;
265}
266
267
268
269
270
271
272/* process command-line arguments */
273int
274process_arguments (int argc, char **argv)
275{
276 int c;
277
278 if (argc < 2)
279 return ERROR;
280
281 for (c = 1; c < argc; c++) {
282 if (strcmp ("-to", argv[c]) == 0)
283 strcpy (argv[c], "-t");
284 else if (strcmp ("-wt", argv[c]) == 0)
285 strcpy (argv[c], "-w");
286 else if (strcmp ("-ct", argv[c]) == 0)
287 strcpy (argv[c], "-c");
288 }
289
290
291
292 c = 0;
293 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
294
295 if (is_option (argv[c]))
296 continue;
297
298 if (server_address == NULL) {
299 if (is_host (argv[c])) {
300 server_address = argv[c];
301 }
302 else {
303 usage ("Invalid host name");
304 }
305 }
306 }
307
308 if (server_expect == NULL)
309 server_expect = strscpy (NULL, EXPECT);
310
311 return validate_arguments ();
312}
313
314
315
316
317
318
319int
320call_getopt (int argc, char **argv)
321{
322 int c, i = 0;
323
324#ifdef HAVE_GETOPT_H
325 int option_index = 0;
326 static struct option long_options[] = {
327 {"hostname", required_argument, 0, 'H'},
328 {"IPaddress", required_argument, 0, 'I'},
329 {"expect", required_argument, 0, 'e'},
330 {"url", required_argument, 0, 'u'},
331 {"port", required_argument, 0, 'p'},
332 {"critical", required_argument, 0, 'c'},
333 {"warning", required_argument, 0, 'w'},
334 {"timeout", required_argument, 0, 't'},
335 {"verbose", no_argument, 0, 'v'},
336 {"version", no_argument, 0, 'V'},
337 {"help", no_argument, 0, 'h'},
338 {0, 0, 0, 0}
339 };
340#endif
341
342 while (1) {
343#ifdef HAVE_GETOPT_H
344 c =
345 getopt_long (argc, argv, "+hVI:H:e:u:p:w:c:t:", long_options,
346 &option_index);
347#else
348 c = getopt (argc, argv, "+?hVI:H:e:u:p:w:c:t");
349#endif
350
351 i++;
352
353 if (c == -1 || c == EOF || c == 1)
354 break;
355
356 switch (c) {
357 case 'I':
358 case 'H':
359 case 'e':
360 case 'u':
361 case 'p':
362 case 'w':
363 case 'c':
364 case 't':
365 i++;
366 }
367
368 switch (c) {
369 case 'I': /* hostname */
370 if (is_host (optarg)) {
371 server_address = optarg;
372 }
373 else {
374 usage ("Invalid host name\n");
375 }
376 break;
377 case 'H': /* hostname */
378 if (is_host (optarg)) {
379 server_address = optarg;
380 }
381 else {
382 usage ("Invalid host name\n");
383 }
384 break;
385 case 'e': /* string to expect in response header */
386 server_expect = optarg;
387 break;
388 case 'u': /* string to expect in response header */
389 server_url = optarg;
390 break;
391 case 'p': /* port */
392 if (is_intpos (optarg)) {
393 server_port = atoi (optarg);
394 }
395 else {
396 usage ("Server port must be a positive integer\n");
397 }
398 break;
399 case 'w': /* warning time threshold */
400 if (is_intnonneg (optarg)) {
401 warning_time = atoi (optarg);
402 check_warning_time = TRUE;
403 }
404 else {
405 usage ("Warning time must be a nonnegative integer\n");
406 }
407 break;
408 case 'c': /* critical time threshold */
409 if (is_intnonneg (optarg)) {
410 critical_time = atoi (optarg);
411 check_critical_time = TRUE;
412 }
413 else {
414 usage ("Critical time must be a nonnegative integer\n");
415 }
416 break;
417 case 'v': /* verbose */
418 verbose = TRUE;
419 break;
420 case 't': /* timeout */
421 if (is_intnonneg (optarg)) {
422 socket_timeout = atoi (optarg);
423 }
424 else {
425 usage ("Time interval must be a nonnegative integer\n");
426 }
427 break;
428 case 'V': /* version */
429 print_revision (PROGNAME, "$Revision$");
430 exit (STATE_OK);
431 case 'h': /* help */
432 print_help ();
433 exit (STATE_OK);
434 case '?': /* help */
435 usage ("Invalid argument\n");
436 }
437 }
438 return i;
439}
440
441
442
443
444
445int
446validate_arguments (void)
447{
448 return OK;
449}
450
451
452
453
454
455void
456print_help (void)
457{
458 print_revision (PROGNAME, "$Revision$");
459 printf
460 ("Copyright (c) 2000 Pedro Leite (leite@cic.ua.pt)/Karl DeBisschop\n\n"
461 "This plugin tests the REAL service on the specified host.\n\n");
462 print_usage ();
463 printf
464 ("\nOptions:\n"
465 " -H, --hostname=STRING or IPADDRESS\n"
466 " Check this server on the indicated host\n"
467 " -I, --IPaddress=STRING or IPADDRESS\n"
468 " Check server at this host address\n"
469 " -p, --port=INTEGER\n"
470 " Make connection on the indicated port (default: %d)\n"
471 " -u, --url=STRING\n"
472 " Connect to this url\n"
473 " -e, --expect=STRING\n"
474 " String to expect in first line of server response (default: %s)\n"
475 " -w, --warning=INTEGER\n"
476 " Seconds necessary to result in a warning status\n"
477 " -c, --critical=INTEGER\n"
478 " Seconds necessary to result in a critical status\n"
479 " -t, --timeout=INTEGER\n"
480 " Seconds before connection attempt times out (default: %d)\n"
481 " -v, --verbose\n"
482 " Print extra information (command-line use only)\n"
483 " -h, --help\n"
484 " Print detailed help screen\n"
485 " -V, --version\n"
486 " Print version information\n\n",
487 PORT, EXPECT, DEFAULT_SOCKET_TIMEOUT);
488 support ();
489}
490
491
492
493
494
495void
496print_usage (void)
497{
498 printf
499 ("Usage: %s -H host [-e expect] [-p port] [-w warn] [-c crit]\n"
500 " [-t timeout] [-v]\n"
501 " %s --help\n"
502 " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
503}
504
505
506
507
508/*
509// process command-line arguments
510int
511process_arguments (int argc, char **argv)
512{
513 int x;
514
515 // no options were supplied
516 if (argc < 2)
517 return ERROR;
518
519 // first option is always the server name/address
520 strncpy (server_address, argv[1], sizeof (server_address) - 1);
521 server_address[sizeof (server_address) - 1] = 0;
522
523 // set the host name to the server address (until its overridden)
524 strcpy (host_name, server_address);
525
526 // process all remaining arguments
527 for (x = 3; x <= argc; x++)
528 {
529
530 // we got the string to expect from the server
531 if (!strcmp (argv[x - 1], "-e"))
532 {
533 if (x < argc)
534 {
535 strncpy (server_expect, argv[x], sizeof (server_expect) - 1);
536 server_expect[sizeof (server_expect) - 1] = 0;
537 x++;
538 }
539 else
540 return ERROR;
541 }
542
543 // we got the URL to check
544 else if (!strcmp (argv[x - 1], "-u"))
545 {
546 if (x < argc)
547 {
548 strncpy (server_url, argv[x], sizeof (server_url) - 1);
549 server_url[sizeof (server_url) - 1] = 0;
550 x++;
551 }
552 else
553 return ERROR;
554 }
555
556 // we go the host name to use in the host header
557 else if (!strcmp (argv[x - 1], "-hn"))
558 {
559 if (x < argc)
560 {
561 strncpy (host_name, argv[x], sizeof (host_name) - 1);
562 host_name[sizeof (host_name) - 1] = 0;
563 x++;
564 }
565 else
566 return ERROR;
567 }
568
569 // we got the port number to use
570 else if (!strcmp (argv[x - 1], "-p"))
571 {
572 if (x < argc)
573 {
574 server_port = atoi (argv[x]);
575 x++;
576 }
577 else
578 return ERROR;
579 }
580
581 // we got the socket timeout
582 else if (!strcmp (argv[x - 1], "-to"))
583 {
584 if (x < argc)
585 {
586 socket_timeout = atoi (argv[x]);
587 if (socket_timeout <= 0)
588 return ERROR;
589 x++;
590 }
591 else
592 return ERROR;
593 }
594
595 // we got the warning threshold time
596 else if (!strcmp (argv[x - 1], "-wt"))
597 {
598 if (x < argc)
599 {
600 warning_time = atoi (argv[x]);
601 check_warning_time = TRUE;
602 x++;
603 }
604 else
605 return ERROR;
606 }
607
608 // we got the critical threshold time
609 else if (!strcmp (argv[x - 1], "-ct"))
610 {
611 if (x < argc)
612 {
613 critical_time = atoi (argv[x]);
614 check_critical_time = TRUE;
615 x++;
616 }
617 else
618 return ERROR;
619 }
620
621 // else we got something else...
622 else
623 return ERROR;
624 }
625
626 return OK;
627}
628
629 result = process_arguments (argc, argv);
630
631 if (result != OK)
632 {
633
634 printf ("Incorrect number of arguments supplied\n");
635 printf ("\n");
636 print_revision(argv[0],"$Revision$");
637 printf ("Copyright (c) 1999 Pedro Leite (leite@cic.ua.pt)\n");
638 printf ("Last Modified: 30-10-1999\n");
639 printf ("License: GPL\n");
640 printf ("\n");
641 printf ("Usage: %s <host_address> [-e expect] [-u url] [-p port] [-hn host_name] [-wt warn_time]\n",argv[0]);
642 printf(" [-ct crit_time] [-to to_sec] [-a auth]\n");
643 printf ("\n");
644 printf ("Options:\n");
645 printf (" [expect] = String to expect in first line of server response - default is \"%s\"\n", EXPECT);
646 printf (" [url] = Optional URL to GET - default is root document\n");
647 printf (" [port] = Optional port number to use - default is %d\n", PORT);
648 printf (" [host_name] = Optional host name argument to GET command - used for servers using host headers\n");
649 printf (" [warn_time] = Response time in seconds necessary to result in a warning status\n");
650 printf (" [crit_time] = Response time in seconds necessary to result in a critical status\n");
651 printf (" [to_sec] = Number of seconds before connection attempt times out - default is %d seconds\n", DEFAULT_SOCKET_TIMEOUT);
652 printf (" [auth] = Optional username:password for sites requiring basic authentication\n");
653 printf ("\n");
654 printf ("This plugin attempts to contact the REAL service on the specified host.\n");
655 printf ("If possible, supply an IP address for the host address, as this will bypass the DNS lookup.\n");
656 printf ("\n");
657
658 return STATE_UNKNOWN;
659 }
660
661*/
diff --git a/plugins/check_smtp.c b/plugins/check_smtp.c
new file mode 100644
index 00000000..d57b7841
--- /dev/null
+++ b/plugins/check_smtp.c
@@ -0,0 +1,362 @@
1/******************************************************************************
2*
3* CHECK_SMTP.C
4*
5* Program: SMTP plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8*
9* $Id$
10*
11* Description:
12*
13* This plugin will attempt to open an SMTP connection with the host.
14* Successul connects return STATE_OK, refusals and timeouts return
15* STATE_CRITICAL, other errors return STATE_UNKNOWN. Successful
16* connects, but incorrect reponse messages from the host result in
17* STATE_WARNING return values.
18*
19* License Information:
20*
21* This program is free software; you can redistribute it and/or modify
22* it under the terms of the GNU General Public License as published by
23* the Free Software Foundation; either version 2 of the License, or
24* (at your option) any later version.
25*
26* This program is distributed in the hope that it will be useful,
27* but WITHOUT ANY WARRANTY; without even the implied warranty of
28* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29* GNU General Public License for more details.
30*
31* You should have received a copy of the GNU General Public License
32* along with this program; if not, write to the Free Software
33* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34*
35*****************************************************************************/
36
37#include "config.h"
38#include "common.h"
39#include "netutils.h"
40#include "utils.h"
41
42#define PROGNAME "check_smtp"
43
44#define SMTP_PORT 25
45#define SMTP_EXPECT "220"
46#define SMTP_QUIT "QUIT\n"
47
48int process_arguments (int, char **);
49int call_getopt (int, char **);
50int validate_arguments (void);
51int check_disk (int usp, int free_disk);
52void print_help (void);
53void print_usage (void);
54
55int server_port = SMTP_PORT;
56char *server_address = NULL;
57char *server_expect = NULL;
58int warning_time = 0;
59int check_warning_time = FALSE;
60int critical_time = 0;
61int check_critical_time = FALSE;
62int verbose = FALSE;
63
64int
65main (int argc, char **argv)
66{
67 int sd;
68 int result;
69 char buffer[MAX_INPUT_BUFFER] = "";
70
71 if (process_arguments (argc, argv) != OK)
72 usage ("Invalid command arguments supplied\n");
73
74 /* initialize alarm signal handling */
75 signal (SIGALRM, socket_timeout_alarm_handler);
76
77 /* set socket timeout */
78 alarm (socket_timeout);
79
80 /* try to connect to the host at the given port number */
81 time (&start_time);
82 result = my_tcp_connect (server_address, server_port, &sd);
83
84 /* we connected, so close connection before exiting */
85 if (result == STATE_OK) {
86
87 /* watch for the SMTP connection string */
88 result = recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0);
89
90 /* strip the buffer of carriage returns */
91 strip (buffer);
92
93 /* return a WARNING status if we couldn't read any data */
94 if (result == -1) {
95 printf ("recv() failed\n");
96 result = STATE_WARNING;
97 }
98
99 else {
100
101 /* make sure we find the response we are looking for */
102 if (!strstr (buffer, server_expect)) {
103 if (server_port == SMTP_PORT)
104 printf ("Invalid SMTP response received from host\n");
105 else
106 printf ("Invalid SMTP response received from host on port %d\n",
107 server_port);
108 result = STATE_WARNING;
109 }
110
111 else {
112
113 time (&end_time);
114
115 result = STATE_OK;
116
117 if (check_critical_time == TRUE
118 && (end_time - start_time) > critical_time) result =
119 STATE_CRITICAL;
120 else if (check_warning_time == TRUE
121 && (end_time - start_time) > warning_time) result =
122 STATE_WARNING;
123
124 if (verbose == TRUE)
125 printf ("SMTP %s - %d sec. response time, %s\n",
126 state_text (result), (int) (end_time - start_time), buffer);
127 else
128 printf ("SMTP %s - %d second response time\n", state_text (result),
129 (int) (end_time - start_time));
130 }
131 }
132
133 /* close the connection */
134 send (sd, SMTP_QUIT, strlen (SMTP_QUIT), 0);
135 close (sd);
136 }
137
138 /* reset the alarm */
139 alarm (0);
140
141 return result;
142}
143
144
145
146
147
148
149/* process command-line arguments */
150int
151process_arguments (int argc, char **argv)
152{
153 int c;
154
155 if (argc < 2)
156 return ERROR;
157
158 for (c = 1; c < argc; c++) {
159 if (strcmp ("-to", argv[c]) == 0)
160 strcpy (argv[c], "-t");
161 else if (strcmp ("-wt", argv[c]) == 0)
162 strcpy (argv[c], "-w");
163 else if (strcmp ("-ct", argv[c]) == 0)
164 strcpy (argv[c], "-c");
165 }
166
167
168
169 c = 0;
170 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
171
172 if (is_option (argv[c]))
173 continue;
174
175 if (server_address == NULL) {
176 if (is_host (argv[c])) {
177 server_address = argv[c];
178 }
179 else {
180 usage ("Invalid host name");
181 }
182 }
183 }
184
185 if (server_address == NULL)
186 server_address = strscpy (NULL, "127.0.0.1");
187
188 if (server_expect == NULL)
189 server_expect = strscpy (NULL, SMTP_EXPECT);
190
191 return validate_arguments ();
192}
193
194
195
196
197
198
199int
200call_getopt (int argc, char **argv)
201{
202 int c, i = 0;
203
204#ifdef HAVE_GETOPT_H
205 int option_index = 0;
206 static struct option long_options[] = {
207 {"hostname", required_argument, 0, 'H'},
208 {"expect", required_argument, 0, 'e'},
209 {"critical", required_argument, 0, 'c'},
210 {"warning", required_argument, 0, 'w'},
211 {"port", required_argument, 0, 'P'},
212 {"verbose", no_argument, 0, 'v'},
213 {"version", no_argument, 0, 'V'},
214 {"help", no_argument, 0, 'h'},
215 {0, 0, 0, 0}
216 };
217#endif
218
219 while (1) {
220#ifdef HAVE_GETOPT_H
221 c =
222 getopt_long (argc, argv, "+hVvt:p:e:c:w:H:", long_options,
223 &option_index);
224#else
225 c = getopt (argc, argv, "+?hVvt:p:e:c:w:H:");
226#endif
227
228 i++;
229
230 if (c == -1 || c == EOF || c == 1)
231 break;
232
233 switch (c) {
234 case 't':
235 case 'p':
236 case 'e':
237 case 'c':
238 case 'w':
239 case 'H':
240 i++;
241 }
242
243 switch (c) {
244 case 'H': /* hostname */
245 if (is_host (optarg)) {
246 server_address = optarg;
247 }
248 else {
249 usage ("Invalid host name\n");
250 }
251 break;
252 case 'p': /* port */
253 if (is_intpos (optarg)) {
254 server_port = atoi (optarg);
255 }
256 else {
257 usage ("Server port must be a positive integer\n");
258 }
259 break;
260 case 'e': /* username */
261 server_expect = optarg;
262 break;
263 case 'c': /* critical time threshold */
264 if (is_intnonneg (optarg)) {
265 critical_time = atoi (optarg);
266 check_critical_time = TRUE;
267 }
268 else {
269 usage ("Critical time must be a nonnegative integer\n");
270 }
271 break;
272 case 'w': /* warning time threshold */
273 if (is_intnonneg (optarg)) {
274 warning_time = atoi (optarg);
275 check_warning_time = TRUE;
276 }
277 else {
278 usage ("Warning time must be a nonnegative integer\n");
279 }
280 break;
281 case 'v': /* verbose */
282 verbose = TRUE;
283 break;
284 case 't': /* timeout */
285 if (is_intnonneg (optarg)) {
286 socket_timeout = atoi (optarg);
287 }
288 else {
289 usage ("Time interval must be a nonnegative integer\n");
290 }
291 break;
292 case 'V': /* version */
293 print_revision (PROGNAME, "$Revision$");
294 exit (STATE_OK);
295 case 'h': /* help */
296 print_help ();
297 exit (STATE_OK);
298 case '?': /* help */
299 usage ("Invalid argument\n");
300 }
301 }
302 return i;
303}
304
305
306
307
308
309int
310validate_arguments (void)
311{
312 return OK;
313}
314
315
316
317
318
319void
320print_help (void)
321{
322 print_revision (PROGNAME, "$Revision$");
323 printf
324 ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
325 "This plugin test the SMTP service on the specified host.\n\n");
326 print_usage ();
327 printf
328 ("\nOptions:\n"
329 " -H, --hostname=STRING or IPADDRESS\n"
330 " Check server on the indicated host\n"
331 " -p, --port=INTEGER\n"
332 " Make connection on the indicated port (default: %d)\n"
333 " -e, --expect=STRING\n"
334 " String to expect in first line of server response (default: %s)\n"
335 " -w, --warning=INTEGER\n"
336 " Seconds necessary to result in a warning status\n"
337 " -c, --critical=INTEGER\n"
338 " Seconds necessary to result in a critical status\n"
339 " -t, --timeout=INTEGER\n"
340 " Seconds before connection attempt times out (default: %d)\n"
341 " -v, --verbose\n"
342 " Print extra information (command-line use only)\n"
343 " -h, --help\n"
344 " Print detailed help screen\n"
345 " -V, --version\n"
346 " Print version information\n\n",
347 SMTP_PORT, SMTP_EXPECT, DEFAULT_SOCKET_TIMEOUT);
348 support ();
349}
350
351
352
353
354
355void
356print_usage (void)
357{
358 printf
359 ("Usage: %s -H host [-e expect] [-p port] [-w warn] [-c crit] [-t timeout] [-v]\n"
360 " %s --help\n"
361 " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
362}
diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c
new file mode 100644
index 00000000..2f970b3d
--- /dev/null
+++ b/plugins/check_snmp.c
@@ -0,0 +1,805 @@
1/******************************************************************************
2 *
3 * CHECK_SNMP.C
4 *
5 * Program: SNMP plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 *
9 * Last Modified: $Date$
10 *
11 * Description:
12 *
13 * This plugin uses the 'snmpget' command included with the UCD-SNMP
14 * package. If you don't have the package installed you will need to
15 * download it from http://ucd-snmp.ucdavis.edu before you can use
16 * this plugin.
17 *
18 * License Information:
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 *./plugins/check_snmp 127.0.0.1 -c public -o .1.3.6.1.4.1.2021.9.1.2.1
34 *****************************************************************************/
35
36#include "common.h"
37#include "utils.h"
38#include "popen.h"
39
40#define PROGNAME check_snmp
41
42#define mark(a) ((a)!=0?"*":"")
43
44#define CHECK_UNDEF 0
45#define CRIT_PRESENT 1
46#define CRIT_STRING 2
47#define CRIT_REGEX 4
48#define CRIT_GT 8
49#define CRIT_LT 16
50#define CRIT_GE 32
51#define CRIT_LE 64
52#define CRIT_EQ 128
53#define CRIT_NE 256
54#define CRIT_RANGE 512
55#define WARN_PRESENT 1024
56#define WARN_STRING 2048
57#define WARN_REGEX 4096
58#define WARN_GT 8192
59#define WARN_LT 16384
60#define WARN_GE 32768
61#define WARN_LE 65536
62#define WARN_EQ 131072
63#define WARN_NE 262144
64#define WARN_RANGE 524288
65
66#define MAX_OIDS 8
67#define MAX_DELIM_LENGTH 8
68#define DEFAULT_DELIMITER "="
69#define DEFAULT_OUTPUT_DELIMITER " "
70
71void print_usage (void);
72void print_help (char *);
73int process_arguments (int, char **);
74int call_getopt (int, char **);
75int check_num (int);
76char *clarify_message (char *);
77int lu_getll (unsigned long *, char *);
78int lu_getul (unsigned long *, char *);
79char *thisarg (char *str);
80char *nextarg (char *str);
81
82#ifdef HAVE_REGEX_H
83#include <regex.h>
84char regex_expect[MAX_INPUT_BUFFER] = "";
85regex_t preg;
86regmatch_t pmatch[10];
87char timestamp[10] = "";
88char regex[MAX_INPUT_BUFFER];
89char errbuf[MAX_INPUT_BUFFER];
90int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
91int eflags = 0;
92int errcode, excode;
93#endif
94
95char *server_address = NULL;
96char *community = NULL;
97char oid[MAX_INPUT_BUFFER] = "";
98char *label = NULL;
99char *units = NULL;
100char string_value[MAX_INPUT_BUFFER] = "";
101char **labels = NULL;
102char **unitv = NULL;
103int nlabels = 0;
104int labels_size = 8;
105int nunits = 0;
106int unitv_size = 8;
107unsigned long lower_warn_lim[MAX_OIDS];
108unsigned long upper_warn_lim[MAX_OIDS];
109unsigned long lower_crit_lim[MAX_OIDS];
110unsigned long upper_crit_lim[MAX_OIDS];
111unsigned long response_value[MAX_OIDS];
112int check_warning_value = FALSE;
113int check_critical_value = FALSE;
114int eval_method[MAX_OIDS];
115char *delimiter = NULL;
116char *output_delim = NULL;
117
118
119int
120main (int argc, char **argv)
121{
122 int i = 0;
123 int iresult = STATE_UNKNOWN;
124 int found = 0;
125 int result = STATE_DEPENDENT;
126 char input_buffer[MAX_INPUT_BUFFER];
127 char *command_line = NULL;
128 char *response = NULL;
129 char *outbuff = NULL;
130 char *output = NULL;
131 char *ptr = NULL;
132 char *p2 = NULL;
133 char *show = NULL;
134
135 labels = malloc (labels_size);
136 unitv = malloc (unitv_size);
137 outbuff = strscpy (outbuff, "");
138 for (i = 0; i < MAX_OIDS; i++)
139 eval_method[i] = CHECK_UNDEF;
140 i = 0;
141
142 if (process_arguments (argc, argv) == ERROR)
143 usage ("Incorrect arguments supplied\n");
144
145 /* create the command line to execute */
146 command_line = ssprintf
147 (command_line,
148 "%s -m ALL -v 1 %s %s %s",
149 PATH_TO_SNMPGET, server_address, community, oid);
150
151 /* run the command */
152 child_process = spopen (command_line);
153 if (child_process == NULL) {
154 printf ("Could not open pipe: %s\n", command_line);
155 exit (STATE_UNKNOWN);
156 }
157
158 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
159 if (child_stderr == NULL) {
160 printf ("Could not open stderr for %s\n", command_line);
161 }
162
163 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
164 output = strscat (output, input_buffer);
165
166 ptr = output;
167
168 while (ptr) {
169
170 ptr = strstr (ptr, delimiter);
171 if (ptr == NULL)
172 break;
173
174 ptr += strlen (delimiter);
175 ptr += strspn (ptr, " ");
176
177 found++;
178
179 if (ptr[0] == '"') {
180 ptr++;
181 response = strpcpy (response, ptr, "\"");
182 ptr = strpbrk (ptr, "\"");
183 ptr += strspn (ptr, "\"\n");
184 }
185 else {
186 response = strpcpy (response, ptr, "\n");
187 ptr = strpbrk (ptr, "\n");
188 ptr += strspn (ptr, "\n");
189 while
190 (strstr (ptr, delimiter) &&
191 strstr (ptr, "\n") && strstr (ptr, "\n") < strstr (ptr, delimiter)) {
192 response = strpcat (response, ptr, "\n");
193 ptr = strpbrk (ptr, "\n");
194 }
195 if (ptr && strstr (ptr, delimiter) == NULL) {
196 response = strscat (response, ptr);
197 ptr = NULL;
198 }
199 }
200
201 if (strstr (response, "Gauge: "))
202 show = strstr (response, "Gauge: ") + 7;
203 else if (strstr (response, "Gauge32: "))
204 show = strstr (response, "Gauge32: ") + 9;
205 else
206 show = response;
207 p2 = show;
208
209 if (eval_method[i] & CRIT_GT ||
210 eval_method[i] & CRIT_LT ||
211 eval_method[i] & CRIT_GE ||
212 eval_method[i] & CRIT_LE ||
213 eval_method[i] & CRIT_EQ ||
214 eval_method[i] & CRIT_NE ||
215 eval_method[i] & WARN_GT ||
216 eval_method[i] & WARN_LT ||
217 eval_method[i] & WARN_GE ||
218 eval_method[i] & WARN_LE ||
219 eval_method[i] & WARN_EQ || eval_method[i] & WARN_NE) {
220 p2 = strpbrk (p2, "0123456789");
221 response_value[i] = strtoul (p2, NULL, 10);
222 iresult = check_num (i);
223 show = ssprintf (show, "%d", response_value[i]);
224 }
225
226 else if (eval_method[i] & CRIT_STRING) {
227 if (strcmp (response, string_value))
228 iresult = STATE_CRITICAL;
229 else
230 iresult = STATE_OK;
231 }
232
233 else if (eval_method[i] & CRIT_REGEX) {
234#ifdef HAVE_REGEX_H
235 excode = regexec (&preg, response, 10, pmatch, eflags);
236 if (excode == 0) {
237 iresult = STATE_OK;
238 }
239 else if (excode != REG_NOMATCH) {
240 regerror (excode, &preg, errbuf, MAX_INPUT_BUFFER);
241 printf ("Execute Error: %s\n", errbuf);
242 exit (STATE_CRITICAL);
243 }
244 else {
245 iresult = STATE_CRITICAL;
246 }
247#else
248 printf ("SNMP UNKNOWN: call for regex which was not a compiled option");
249 exit (STATE_UNKNOWN);
250#endif
251 }
252
253 else {
254 if (response)
255 iresult = STATE_OK;
256 else if (eval_method[i] & CRIT_PRESENT)
257 iresult = STATE_CRITICAL;
258 else
259 iresult = STATE_WARNING;
260 }
261
262 result = max (result, iresult);
263
264 if (nlabels > 1 && i < nlabels && labels[i] != NULL)
265 outbuff = ssprintf
266 (outbuff,
267 "%s%s%s %s%s%s",
268 outbuff,
269 (i == 0) ? " " : output_delim,
270 labels[i], mark (iresult), show, mark (iresult));
271 else
272 outbuff = ssprintf
273 (outbuff,
274 "%s%s%s%s%s",
275 outbuff,
276 (i == 0) ? " " : output_delim, mark (iresult), show, mark (iresult));
277
278 if (nunits > 0 && i < nunits)
279 outbuff = ssprintf (outbuff, "%s %s", outbuff, unitv[i]);
280
281 i++;
282
283 } /* end while */
284
285 if (found == 0)
286 terminate
287 (STATE_UNKNOWN,
288 "%s problem - No data recieved from host\nCMD: %s\n",
289 label, command_line);
290
291 /* WARNING if output found on stderr */
292 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
293 result = max (result, STATE_WARNING);
294
295 /* close stderr */
296 (void) fclose (child_stderr);
297
298 /* close the pipe */
299 if (spclose (child_process))
300 result = max (result, STATE_WARNING);
301
302 if (nunits > 0)
303 printf ("%s %s -%s\n", label, state_text (result), outbuff);
304 else
305 printf ("%s %s -%s %s\n", label, state_text (result), outbuff, units);
306
307 return result;
308}
309
310/* process command-line arguments */
311int
312process_arguments (int argc, char **argv)
313{
314 int c;
315
316 if (argc < 2)
317 return ERROR;
318
319 for (c = 1; c < argc; c++) {
320 if (strcmp ("-to", argv[c]) == 0)
321 strcpy (argv[c], "-t");
322 if (strcmp ("-wv", argv[c]) == 0)
323 strcpy (argv[c], "-w");
324 if (strcmp ("-cv", argv[c]) == 0)
325 strcpy (argv[c], "-c");
326 }
327
328 c = 0;
329 while (c += (call_getopt (argc - c, &argv[c]))) {
330 if (argc <= c)
331 break;
332 if (server_address == NULL)
333 server_address = strscpy (NULL, argv[c]);
334 }
335
336 if (community == NULL)
337 community = strscpy (NULL, "public");
338
339 if (delimiter == NULL)
340 delimiter = strscpy (NULL, DEFAULT_DELIMITER);
341
342 if (output_delim == NULL)
343 output_delim = strscpy (NULL, DEFAULT_OUTPUT_DELIMITER);
344
345 if (label == NULL)
346 label = strscpy (NULL, "SNMP");
347
348 if (units == NULL)
349 units = strscpy (NULL, "");
350
351 return c;
352}
353
354int
355call_getopt (int argc, char **argv)
356{
357 char *ptr;
358 int c, i = 1;
359 int j = 0, jj = 0;
360
361#ifdef HAVE_GETOPT_H
362 int option_index = 0;
363 static struct option long_options[] = {
364 {"help", no_argument, 0, 'h'},
365 {"version", no_argument, 0, 'V'},
366 {"timeout", required_argument, 0, 't'},
367 {"critical", required_argument, 0, 'c'},
368 {"warning", required_argument, 0, 'w'},
369 {"hostname", required_argument, 0, 'H'},
370 {"community", required_argument, 0, 'C'},
371 {"oid", required_argument, 0, 'o'},
372 {"object", required_argument, 0, 'o'},
373 {"delimiter", required_argument, 0, 'd'},
374 {"output-delimiter", required_argument, 0, 'D'},
375 {"string", required_argument, 0, 's'},
376 {"regex", required_argument, 0, 'r'},
377 {"ereg", required_argument, 0, 'r'},
378 {"eregi", required_argument, 0, 'R'},
379 {"label", required_argument, 0, 'l'},
380 {"units", required_argument, 0, 'u'},
381 {0, 0, 0, 0}
382 };
383#endif
384
385 while (1) {
386#ifdef HAVE_GETOPT_H
387 c =
388 getopt_long (argc, argv, "+?hVt:c:w:H:C:o:d:D:s:R:r:l:u:",
389 long_options, &option_index);
390#else
391 c = getopt (argc, argv, "+?hVt:c:w:H:C:o:d:D:s:R:r:l:u:");
392#endif
393
394 if (c == -1 || c == EOF)
395 break;
396
397 i++;
398 switch (c) {
399 case 't':
400 case 'c':
401 case 'w':
402 case 'H':
403 case 'C':
404 case 'o':
405 case 'd':
406 case 'D':
407 case 's':
408 case 'R':
409 case 'r':
410 case 'l':
411 case 'u':
412 i++;
413 }
414
415 switch (c) {
416 case '?': /* help */
417 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
418 print_usage ();
419 exit (STATE_UNKNOWN);
420 case 'h': /* help */
421 print_help (my_basename (argv[0]));
422 exit (STATE_OK);
423 case 'V': /* version */
424 print_revision (my_basename (argv[0]), "$Revision$");
425 exit (STATE_OK);
426 case 't': /* timeout period */
427 if (!is_integer (optarg)) {
428 printf ("%s: Timeout Interval must be an integer!\n\n",
429 my_basename (argv[0]));
430 print_usage ();
431 exit (STATE_UNKNOWN);
432 }
433 timeout_interval = atoi (optarg);
434 break;
435 case 'c': /* critical time threshold */
436 if (strspn (optarg, "0123456789:,") < strlen (optarg)) {
437 printf ("Invalid critical threshold: %s\n", optarg);
438 print_usage ();
439 exit (STATE_UNKNOWN);
440 }
441 for (ptr = optarg, jj = 0; ptr && jj < MAX_OIDS; jj++) {
442 if (lu_getll (&lower_crit_lim[jj], ptr) == 1)
443 eval_method[jj] |= CRIT_LT;
444 if (lu_getul (&upper_crit_lim[jj], ptr) == 1)
445 eval_method[jj] |= CRIT_GT;
446 (ptr = index (ptr, ',')) ? ptr++ : ptr;
447 }
448 break;
449 case 'w': /* warning time threshold */
450 if (strspn (optarg, "0123456789:,") < strlen (optarg)) {
451 printf ("Invalid warning threshold: %s\n", optarg);
452 print_usage ();
453 exit (STATE_UNKNOWN);
454 }
455 for (ptr = optarg, jj = 0; ptr && jj < MAX_OIDS; jj++) {
456 if (lu_getll (&lower_warn_lim[jj], ptr) == 1)
457 eval_method[jj] |= WARN_LT;
458 if (lu_getul (&upper_warn_lim[jj], ptr) == 1)
459 eval_method[jj] |= WARN_GT;
460 (ptr = index (ptr, ',')) ? ptr++ : ptr;
461 }
462 break;
463 case 'H': /* Host or server */
464 server_address = strscpy (server_address, optarg);
465 break;
466 case 'C': /* group or community */
467 community = strscpy (community, optarg);
468 break;
469 case 'o': /* object identifier */
470 for (ptr = optarg; (ptr = index (ptr, ',')); ptr++)
471 ptr[0] = ' ';
472 strncpy (oid, optarg, sizeof (oid) - 1);
473 oid[sizeof (oid) - 1] = 0;
474 for (ptr = optarg, j = 1; (ptr = index (ptr, ' ')); ptr++)
475 j++;
476 break;
477 case 'd': /* delimiter */
478 delimiter = strscpy (delimiter, optarg);
479 break;
480 case 'D': /* output-delimiter */
481 output_delim = strscpy (output_delim, optarg);
482 break;
483 case 's': /* string or substring */
484 strncpy (string_value, optarg, sizeof (string_value) - 1);
485 string_value[sizeof (string_value) - 1] = 0;
486 eval_method[jj++] = CRIT_STRING;
487 break;
488 case 'R': /* regex */
489#ifdef HAVE_REGEX_H
490 cflags = REG_ICASE;
491#endif
492 case 'r': /* regex */
493#ifdef HAVE_REGEX_H
494 cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
495 strncpy (regex_expect, optarg, sizeof (regex_expect) - 1);
496 regex_expect[sizeof (regex_expect) - 1] = 0;
497 errcode = regcomp (&preg, regex_expect, cflags);
498 if (errcode != 0) {
499 regerror (errcode, &preg, errbuf, MAX_INPUT_BUFFER);
500 printf ("Could Not Compile Regular Expression");
501 return ERROR;
502 }
503 eval_method[jj++] = CRIT_REGEX;
504#else
505 printf ("SNMP UNKNOWN: call for regex which was not a compiled option");
506 exit (STATE_UNKNOWN);
507#endif
508 break;
509 case 'l': /* label */
510 label = optarg;
511 nlabels++;
512 if (nlabels >= labels_size) {
513 labels_size += 8;
514 labels = realloc (labels, labels_size);
515 if (labels == NULL)
516 terminate (STATE_UNKNOWN,
517 "Could not realloc() labels[%d]", nlabels);
518 }
519 labels[nlabels - 1] = optarg;
520 ptr = thisarg (optarg);
521 if (strstr (ptr, "'") == ptr)
522 labels[nlabels - 1] = ptr + 1;
523 else
524 labels[nlabels - 1] = ptr;
525 while (ptr && (ptr = nextarg (ptr))) {
526 if (nlabels >= labels_size) {
527 labels_size += 8;
528 labels = realloc (labels, labels_size);
529 if (labels == NULL)
530 terminate (STATE_UNKNOWN, "Could not realloc() labels\n");
531 }
532 labels++;
533 ptr = thisarg (ptr);
534 if (strstr (ptr, "'") == ptr)
535 labels[nlabels - 1] = ptr + 1;
536 else
537 labels[nlabels - 1] = ptr;
538 }
539 break;
540 case 'u': /* units */
541 units = optarg;
542 nunits++;
543 if (nunits >= unitv_size) {
544 unitv_size += 8;
545 unitv = realloc (unitv, unitv_size);
546 if (unitv == NULL)
547 terminate (STATE_UNKNOWN,
548 "Could not realloc() units [%d]\n", nunits);
549 }
550 unitv[nunits - 1] = optarg;
551 ptr = thisarg (optarg);
552 if (strstr (ptr, "'") == ptr)
553 unitv[nunits - 1] = ptr + 1;
554 else
555 unitv[nunits - 1] = ptr;
556 while (ptr && (ptr = nextarg (ptr))) {
557 if (nunits >= unitv_size) {
558 unitv_size += 8;
559 unitv = realloc (unitv, unitv_size);
560 if (units == NULL)
561 terminate (STATE_UNKNOWN, "Could not realloc() units\n");
562 }
563 nunits++;
564 ptr = thisarg (ptr);
565 if (strstr (ptr, "'") == ptr)
566 unitv[nunits - 1] = ptr + 1;
567 else
568 unitv[nunits - 1] = ptr;
569 }
570 break;
571 }
572 }
573 return i;
574}
575
576void
577print_usage (void)
578{
579 printf
580 ("Usage: check_snmp -H <ip_address> -o <OID> [-w warn_range] [-c crit_range] \n"
581 " [-C community] [-s string] [-r regex] [-R regexi] [-t timeout]\n"
582 " [-l label] [-u units] [-d delimiter] [-D output-delimiter]\n"
583 " check_snmp --help\n" " check_snmp --version\n");
584}
585
586void
587print_help (char *cmd)
588{
589 printf ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n"
590 "License: GPL\n\n");
591 print_usage ();
592 printf
593 ("\nOptions:\n"
594 " -h, --help\n"
595 " Print detailed help screen\n"
596 " -V, --version\n"
597 " Print version information\n"
598 " -H, --hostname=HOST\n"
599 " Name or IP address of the device you wish to query\n"
600 " -o, --oid=OID(s)\n"
601 " Object identifier(s) whose value you wish to query\n"
602 " -w, --warning=INTEGER_RANGE(s)\n"
603 " Range(s) which will not result in a WARNING status\n"
604 " -c, --critical=INTEGER_RANGE(s)\n"
605 " Range(s) which will not result in a CRITICAL status\n"
606 " -C, --community=STRING\n"
607 " Optional community string for SNMP communication\n"
608 " (default is \"public\")\n"
609 " -u, --units=STRING\n"
610 " Units label(s) for output data (e.g., 'sec.').\n"
611 " -d, --delimiter=STRING\n"
612 " Delimiter to use when parsing returned data. Default is \"%s\"\n"
613 " Any data on the right hand side of the delimiter is considered\n"
614 " to be the data that should be used in the evaluation.\n"
615 " -t, --timeout=INTEGER\n"
616 " Seconds to wait before plugin times out (see also nagios server timeout)\n"
617 " -D, --output-delimiter=STRING\n"
618 " Separates output on multiple OID requests\n"
619 " -s, --string=STRING\n"
620 " Return OK state (for that OID) if STRING is an exact match\n"
621 " -r, --ereg=REGEX\n"
622 " Return OK state (for that OID) if extended regular expression REGEX matches\n"
623 " -R, --eregi=REGEX\n"
624 " Return OK state (for that OID) if case-insensitive extended REGEX matches\n"
625 " -l, --label=STRING\n"
626 " Prefix label for output from plugin (default -s 'SNMP')\n\n"
627 "- This plugin uses the 'snmpget' command included with the UCD-SNMP package.\n"
628 " If you don't have the package installed, you will need to download it from\n"
629 " http://ucd-snmp.ucdavis.edu before you can use this plugin.\n"
630 "- Multiple OIDs may be indicated by a comma- or space-delimited list (lists with\n"
631 " internal spaces must be quoted)\n"
632 "- Ranges are inclusive and are indicated with colons. When specified as\n"
633 " 'min:max' a STATE_OK will be returned if the result is within the indicated\n"
634 " range or is equal to the upper or lower bound. A non-OK state will be\n"
635 " returned if the result is outside the specified range.\n"
636 "- If spcified in the order 'max:min' a non-OK state will be returned if the\n"
637 " result is within the (inclusive) range.\n"
638 "- Upper or lower bounds may be omitted to skip checking the respective limit.\n"
639 "- Bare integers are interpreted as upper limits.\n"
640 "- When checking multiple OIDs, separate ranges by commas like '-w 1:10,1:,:20'\n"
641 "- Note that only one string and one regex may be checked at present\n"
642 "- All evaluation methods other than PR, STR, and SUBSTR expect that the value\n"
643 " returned from the SNMP query is an unsigned integer.\n\n",
644 DEFAULT_DELIMITER);
645}
646
647char *
648clarify_message (char *msg)
649{
650 int i = 0;
651 int foo;
652 char tmpmsg_c[MAX_INPUT_BUFFER];
653 char *tmpmsg = (char *) &tmpmsg_c;
654 tmpmsg = strcpy (tmpmsg, msg);
655 if (!strncmp (tmpmsg, " Hex:", 5)) {
656 tmpmsg = strtok (tmpmsg, ":");
657 while ((tmpmsg = strtok (NULL, " "))) {
658 foo = strtol (tmpmsg, NULL, 16);
659 /* Translate chars that are not the same value in the printers
660 * character set.
661 */
662 switch (foo) {
663 case 208:
664 {
665 foo = 197;
666 break;
667 }
668 case 216:
669 {
670 foo = 196;
671 break;
672 }
673 }
674 msg[i] = foo;
675 i++;
676 }
677 msg[i] = 0;
678 }
679 return (msg);
680}
681
682
683int
684check_num (int i)
685{
686 int result;
687 result = STATE_OK;
688 if (eval_method[i] & WARN_GT && eval_method[i] & WARN_LT &&
689 lower_warn_lim[i] > upper_warn_lim[i]) {
690 if (response_value[i] <= lower_warn_lim[i] &&
691 response_value[i] >= upper_warn_lim[i]) {
692 result = STATE_WARNING;
693 }
694 }
695 else if
696 ((eval_method[i] & WARN_GT && response_value[i] > upper_warn_lim[i]) ||
697 (eval_method[i] & WARN_GE && response_value[i] >= upper_warn_lim[i]) ||
698 (eval_method[i] & WARN_LT && response_value[i] < lower_warn_lim[i]) ||
699 (eval_method[i] & WARN_LE && response_value[i] <= lower_warn_lim[i]) ||
700 (eval_method[i] & WARN_EQ && response_value[i] == upper_warn_lim[i]) ||
701 (eval_method[i] & WARN_NE && response_value[i] != upper_warn_lim[i])) {
702 result = STATE_WARNING;
703 }
704
705 if (eval_method[i] & CRIT_GT && eval_method[i] & CRIT_LT &&
706 lower_warn_lim[i] > upper_warn_lim[i]) {
707 if (response_value[i] <= lower_crit_lim[i] &&
708 response_value[i] >= upper_crit_lim[i]) {
709 result = STATE_CRITICAL;
710 }
711 }
712 else if
713 ((eval_method[i] & CRIT_GT && response_value[i] > upper_crit_lim[i]) ||
714 (eval_method[i] & CRIT_GE && response_value[i] >= upper_crit_lim[i]) ||
715 (eval_method[i] & CRIT_LT && response_value[i] < lower_crit_lim[i]) ||
716 (eval_method[i] & CRIT_LE && response_value[i] <= lower_crit_lim[i]) ||
717 (eval_method[i] & CRIT_EQ && response_value[i] == upper_crit_lim[i]) ||
718 (eval_method[i] & CRIT_NE && response_value[i] != upper_crit_lim[i])) {
719 result = STATE_CRITICAL;
720 }
721
722 return result;
723}
724
725
726int
727lu_getll (unsigned long *ll, char *str)
728{
729 char tmp[100];
730 if (strchr (str, ':') == NULL)
731 return 0;
732 if (strchr (str, ',') != NULL && (strchr (str, ',') < strchr (str, ':')))
733 return 0;
734 if (sscanf (str, "%lu%[:]", ll, tmp) == 2)
735 return 1;
736 return 0;
737}
738
739int
740lu_getul (unsigned long *ul, char *str)
741{
742 char tmp[100];
743 if (sscanf (str, "%lu%[^,]", ul, tmp) == 1)
744 return 1;
745 if (sscanf (str, ":%lu%[^,]", ul, tmp) == 1)
746 return 1;
747 if (sscanf (str, "%*u:%lu%[^,]", ul, tmp) == 1)
748 return 1;
749 return 0;
750}
751
752
753
754
755
756
757/* trim leading whitespace
758 if there is a leading quote, make sure it balances */
759
760char *
761thisarg (char *str)
762{
763 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
764 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
765 if (strlen (str) == 1 || !strstr (str + 1, "'"))
766 terminate (STATE_UNKNOWN, "Unbalanced quotes\n");
767 }
768 return str;
769}
770
771
772/* if there's a leading quote, advance to the trailing quote
773 set the trailing quote to '\x0'
774 if the string continues, advance beyond the comma */
775
776char *
777nextarg (char *str)
778{
779 if (strstr (str, "'") == str) {
780 if (strlen (str) > 1) {
781 str = strstr (str + 1, "'");
782 str[0] = 0;
783 return (++str);
784 }
785 else {
786 str[0] = 0;
787 return NULL;
788 }
789 }
790 if (strstr (str, ",") == str) {
791 if (strlen (str) > 1) {
792 str[0] = 0;
793 return (++str);
794 }
795 else {
796 str[0] = 0;
797 return NULL;
798 }
799 }
800 if ((str = strstr (str, ",")) && strlen (str) > 1) {
801 str[0] = 0;
802 return (++str);
803 }
804 return NULL;
805}
diff --git a/plugins/check_ssh.c b/plugins/check_ssh.c
new file mode 100644
index 00000000..d78189fc
--- /dev/null
+++ b/plugins/check_ssh.c
@@ -0,0 +1,285 @@
1/*
2* check_ssh.c
3*
4* Made by (Remi PAULMIER)
5* Login <remi@sinfomic.fr>
6*
7* Started on Fri Jul 9 09:18:23 1999 Remi PAULMIER
8* Update Thu Jul 22 12:50:04 1999 remi paulmier
9* $Id$
10*
11*/
12
13#include "config.h"
14#include "common.h"
15#include "netutils.h"
16#include "utils.h"
17
18#define PROGNAME "check_ssh"
19
20#ifndef MSG_DONTWAIT
21#define MSG_DONTWAIT 0
22#endif
23
24#define SSH_DFL_PORT 22
25#define BUFF_SZ 256
26
27short port = -1;
28char *server_name = NULL;
29int verbose = FALSE;
30
31int process_arguments (int, char **);
32int call_getopt (int, char **);
33int validate_arguments (void);
34void print_help (void);
35void print_usage (void);
36
37char *ssh_resolve (char *hostname);
38int ssh_connect (char *haddr, short hport);
39
40int
41main (int argc, char **argv)
42{
43
44 if (process_arguments (argc, argv) == ERROR)
45 usage ("Could not parse arguments\n");
46
47 /* initialize alarm signal handling */
48 signal (SIGALRM, socket_timeout_alarm_handler);
49 alarm (socket_timeout);
50
51 /* ssh_connect exits if error is found */
52 ssh_connect (ssh_resolve (server_name), port);
53
54 alarm (0);
55
56 return (STATE_OK);
57}
58
59
60/* process command-line arguments */
61int
62process_arguments (int argc, char **argv)
63{
64 int c;
65
66 if (argc < 2)
67 return ERROR;
68
69 for (c = 1; c < argc; c++)
70 if (strcmp ("-to", argv[c]) == 0)
71 strcpy (argv[c], "-t");
72
73 c = 0;
74 while (c += (call_getopt (argc - c, &argv[c]))) {
75 if (argc <= c)
76 break;
77 if (server_name == NULL) {
78 server_name = argv[c];
79 }
80 else if (port == -1) {
81 if (is_intpos (argv[c])) {
82 port = atoi (argv[c]);
83 }
84 else {
85 print_usage ();
86 exit (STATE_UNKNOWN);
87 }
88 }
89 }
90
91 return validate_arguments ();
92}
93
94
95/************************************************************************
96*
97* Run the getopt until we encounter a non-option entry in the arglist
98*
99*-----------------------------------------------------------------------*/
100
101int
102call_getopt (int argc, char **argv)
103{
104 int c, i = 1;
105
106#ifdef HAVE_GETOPT_H
107 int option_index = 0;
108 static struct option long_options[] = {
109 {"version", no_argument, 0, 'V'},
110 {"help", no_argument, 0, 'h'},
111 {"verbose", no_argument, 0, 'v'},
112 {"timeout", required_argument, 0, 't'},
113 {"host", required_argument, 0, 'H'},
114 {0, 0, 0, 0}
115 };
116#endif
117
118 while (1) {
119#ifdef HAVE_GETOPT_H
120 c = getopt_long (argc, argv, "+Vhvt:H:p:", long_options, &option_index);
121#else
122 c = getopt (argc, argv, "+Vhvt:H:p:");
123#endif
124
125 if (c == -1 || c == EOF)
126 break;
127
128 i++;
129 switch (c) {
130 case 't':
131 case 'H':
132 case 'p':
133 i++;
134 }
135
136 switch (c) {
137 case '?': /* help */
138 usage ("");
139 case 'V': /* version */
140 print_revision (my_basename (argv[0]), "$Revision$");
141 exit (STATE_OK);
142 case 'h': /* help */
143 print_help ();
144 exit (STATE_OK);
145 case 'v': /* verose */
146 verbose = TRUE;
147 break;
148 case 't': /* timeout period */
149 if (!is_integer (optarg))
150 usage ("Timeout Interval must be an integer!\n\n");
151 socket_timeout = atoi (optarg);
152 break;
153 case 'H': /* host */
154 server_name = optarg;
155 break;
156 case 'p': /* port */
157 if (is_intpos (optarg)) {
158 port = atoi (optarg);
159 }
160 else {
161 printf ("Port number nust be a positive integer: %s\n", optarg);
162 usage ("");
163 }
164 }
165
166 }
167 return i;
168}
169
170int
171validate_arguments (void)
172{
173 if (server_name == NULL)
174 return ERROR;
175 if (port == -1) /* funky, but allows -p to override stray integer in args */
176 port = SSH_DFL_PORT;
177 return OK;
178}
179
180
181/************************************************************************
182*
183* Resolve hostname into IP address
184*
185*-----------------------------------------------------------------------*/
186
187char *
188ssh_resolve (char *hostname)
189{
190 struct hostent *host;
191
192 host = gethostbyname (hostname);
193 if (!host) {
194 herror (hostname);
195 exit (STATE_CRITICAL);
196 }
197 return (host->h_addr);
198}
199
200
201/************************************************************************
202*
203* Try to connect to SSH server at specified server and port
204*
205*-----------------------------------------------------------------------*/
206
207int
208ssh_connect (char *haddr, short hport)
209{
210 int s;
211 struct sockaddr_in addr;
212 int addrlen;
213 int len;
214 char *output = NULL;
215 char *buffer = NULL;
216 char *ssh_proto = NULL;
217 char *ssh_server = NULL;
218 char revision[20];
219
220 sscanf ("$Revision$", "$Revision: %[0123456789.]", revision);
221
222 addrlen = sizeof (addr);
223 memset (&addr, 0, addrlen);
224 addr.sin_port = htons (hport);
225 addr.sin_family = AF_INET;
226 bcopy (haddr, (void *) &addr.sin_addr.s_addr, 4);
227
228 s = socket (AF_INET, SOCK_STREAM, 0);
229 if (!s) {
230 printf ("socket(): %s for %s:%d\n", strerror (errno), server_name, hport);
231 exit (STATE_CRITICAL);
232 }
233
234 if (connect (s, (struct sockaddr *) &addr, addrlen)) {
235 printf ("connect(): %s for %s:%d\n", strerror (errno), server_name,
236 hport);
237 exit (STATE_CRITICAL);
238 }
239
240 output = (char *) malloc (BUFF_SZ + 1);
241 memset (output, 0, BUFF_SZ + 1);
242 recv (s, output, BUFF_SZ, 0);
243 if (strncmp (output, "SSH", 3)) {
244 printf ("Server answer: %s", output);
245 exit (STATE_CRITICAL);
246 }
247 else {
248 strip (output);
249 if (verbose)
250 printf ("%s\n", output);
251 ssh_proto = output + 4;
252 ssh_server = ssh_proto + strspn (ssh_proto, "0123456789-. ");
253 ssh_proto[strspn (ssh_proto, "0123456789-. ")] = 0;
254 printf
255 ("SSH ok - protocol version %s - server version %s\n",
256 ssh_proto, ssh_server);
257 buffer =
258 ssprintf (buffer, "SSH-%s-check_ssh_%s\r\n", ssh_proto, revision);
259 send (s, buffer, strlen (buffer), MSG_DONTWAIT);
260 if (verbose)
261 printf ("%s\n", buffer);
262 exit (STATE_OK);
263 }
264}
265
266void
267print_help (void)
268{
269 print_revision (PROGNAME, "$Revision$");
270 printf ("Copyright (c) 1999 Remi Paulmier (remi@sinfomic.fr)\n\n");
271 print_usage ();
272 printf ("by default, port is %d\n", SSH_DFL_PORT);
273}
274
275void
276print_usage (void)
277{
278 printf
279 ("Usage:\n"
280 " %s -t [timeout] -p [port] <host>\n"
281 " %s -V prints version info\n"
282 " %s -h prints more detailed help\n", PROGNAME, PROGNAME, PROGNAME);
283}
284
285/* end of check_ssh.c */
diff --git a/plugins/check_swap.c b/plugins/check_swap.c
new file mode 100644
index 00000000..d225e1dc
--- /dev/null
+++ b/plugins/check_swap.c
@@ -0,0 +1,325 @@
1/******************************************************************************
2*
3* CHECK_SWAP.C
4*
5* Program: Process plugin for Nagios
6* License: GPL
7* Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
8*
9* $Id$
10*
11******************************************************************************/
12
13#include "common.h"
14#include "popen.h"
15#include "utils.h"
16
17#define PROGNAME "check_swap"
18
19int process_arguments (int argc, char **argv);
20int call_getopt (int argc, char **argv);
21int validate_arguments (void);
22void print_usage (void);
23void print_help (void);
24
25int warn_percent = 200, crit_percent = 200, warn_size = -1, crit_size = -1;
26
27int
28main (int argc, char **argv)
29{
30 int total_swap, used_swap, free_swap, percent_used;
31 int result = STATE_OK;
32 char input_buffer[MAX_INPUT_BUFFER];
33#ifdef HAVE_SWAP
34 char *temp_buffer;
35#endif
36#ifdef HAVE_PROC_MEMINFO
37 FILE *fp;
38#endif
39 char str[32];
40 char *status = NULL;
41
42 if (process_arguments (argc, argv) != OK)
43 usage ("Invalid command arguments supplied\n");
44
45#ifdef HAVE_PROC_MEMINFO
46 fp = fopen (PROC_MEMINFO, "r");
47 status = ssprintf (status, "%s", "Swap used:");
48 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
49 sscanf (input_buffer, " %s %d %d %d", str, &total_swap, &used_swap,
50 &free_swap);
51 if (strstr (str, "Swap")) {
52 percent_used = 100 * (((float) used_swap) / ((float) total_swap));
53 status = ssprintf
54 (status,
55 "%s %2d%% (%d bytes out of %d)",
56 status, percent_used, used_swap, total_swap);
57 if (percent_used >= crit_percent || free_swap <= crit_size)
58 result = STATE_CRITICAL;
59 else if (percent_used >= warn_percent || free_swap <= warn_size)
60 result = STATE_WARNING;
61 break;
62 }
63 }
64 fclose (fp);
65#else
66#ifdef HAVE_SWAP
67 child_process = spopen (SWAP_COMMAND);
68 if (child_process == NULL) {
69 printf ("Could not open pipe: %s\n", SWAP_COMMAND);
70 return STATE_UNKNOWN;
71 }
72
73 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
74 if (child_stderr == NULL)
75 printf ("Could not open stderr for %s\n", SWAP_COMMAND);
76
77 sprintf (str, "%s", "");
78 /* read 1st line */
79 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
80 if (strcmp (SWAP_FORMAT, "") == 0) {
81 temp_buffer = strtok (input_buffer, " \n");
82 while (temp_buffer) {
83 if (strstr (temp_buffer, "blocks"))
84 sprintf (str, "%s %s", str, "%f");
85 else if (strstr (temp_buffer, "free"))
86 sprintf (str, "%s %s", str, "%f");
87 else
88 sprintf (str, "%s %s", str, "%*s");
89 temp_buffer = strtok (NULL, " \n");
90 }
91 }
92
93 status = ssprintf (status, "%s", "Swap used:");
94 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
95 sscanf (input_buffer, SWAP_FORMAT, &total_swap, &free_swap);
96 used_swap = total_swap - free_swap;
97 percent_used = 100 * ((float) used_swap) / ((float) total_swap);
98 status = ssprintf
99 (status,
100 "%s %2d%% (%d bytes out of %d)",
101 status, percent_used, used_swap, total_swap);
102 if (percent_used >= crit_percent || free_swap <= crit_size)
103 result = STATE_CRITICAL;
104 else if (percent_used >= warn_percent || free_swap <= warn_size)
105 result = STATE_WARNING;
106 }
107
108 /* If we get anything on STDERR, at least set warning */
109 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
110 result = max (result, STATE_WARNING);
111
112 /* close stderr */
113 (void) fclose (child_stderr);
114
115 /* close the pipe */
116 if (spclose (child_process))
117 result = max (result, STATE_WARNING);
118#endif
119#endif
120
121#ifndef SWAP_COMMAND
122#ifndef SWAP_FILE
123#ifndef HAVE_PROC_MEMINFO
124 return STATE_UNKNOWN;
125#endif
126#endif
127#endif
128
129 if (result == STATE_OK)
130 printf ("Swap ok - %s\n", status);
131 else if (result == STATE_CRITICAL)
132 printf ("CRITICAL - %s\n", status);
133 else if (result == STATE_WARNING)
134 printf ("WARNING - %s\n", status);
135 else if (result == STATE_UNKNOWN)
136 printf ("Unable to read output\n");
137 else {
138 result = STATE_UNKNOWN;
139 printf ("UNKNOWN - %s\n", status);
140 }
141
142 return result;
143}
144
145
146
147
148
149/* process command-line arguments */
150int
151process_arguments (int argc, char **argv)
152{
153 int c;
154
155 if (argc < 2)
156 return ERROR;
157
158 c = 0;
159 while (c += (call_getopt (argc - c, &argv[c]))) {
160 if (argc <= c)
161 break;
162
163 if (warn_percent > 100 && is_intnonneg (argv[c]))
164 warn_percent = atoi (argv[c]);
165 else if (crit_percent > 100 && is_intnonneg (argv[c]))
166 crit_percent = atoi (argv[c]);
167 else if (warn_size < 0 && is_intnonneg (argv[c]))
168 warn_size = atoi (argv[c]);
169 else if (crit_size < 0 && is_intnonneg (argv[c]))
170 crit_size = atoi (argv[c]);
171 }
172
173 return validate_arguments ();
174}
175
176
177
178
179
180int
181call_getopt (int argc, char **argv)
182{
183 int c, i = 0;
184
185#ifdef HAVE_GETOPT_H
186 int option_index = 0;
187 static struct option long_options[] = {
188 {"warning", required_argument, 0, 'w'},
189 {"critical", required_argument, 0, 'c'},
190 {"verbose", no_argument, 0, 'v'},
191 {"version", no_argument, 0, 'V'},
192 {"help", no_argument, 0, 'h'},
193 {0, 0, 0, 0}
194 };
195#endif
196
197 while (1) {
198#ifdef HAVE_GETOPT_H
199 c = getopt_long (argc, argv, "+?Vhc:w:", long_options, &option_index);
200#else
201 c = getopt (argc, argv, "+?Vhc:w:");
202#endif
203
204 i++;
205
206 if (c == -1 || c == EOF)
207 break;
208
209 switch (c) {
210 case 'c':
211 case 'w':
212 i++;
213 }
214
215 switch (c) {
216 case 'w': /* warning time threshold */
217 if (is_intnonneg (optarg)) {
218 warn_size = atoi (optarg);
219 break;
220 }
221 else if (strstr (optarg, ",") &&
222 strstr (optarg, "%") &&
223 sscanf (optarg, "%d,%d%%", &warn_size, &warn_percent) == 2) {
224 break;
225 }
226 else if (strstr (optarg, "%") &&
227 sscanf (optarg, "%d%%", &warn_percent) == 1) {
228 break;
229 }
230 else {
231 usage ("Warning threshold must be integer or percentage!\n");
232 }
233 case 'c': /* critical time threshold */
234 if (is_intnonneg (optarg)) {
235 crit_size = atoi (optarg);
236 break;
237 }
238 else if (strstr (optarg, ",") &&
239 strstr (optarg, "%") &&
240 sscanf (optarg, "%d,%d%%", &crit_size, &crit_percent) == 2) {
241 break;
242 }
243 else if (strstr (optarg, "%") &&
244 sscanf (optarg, "%d%%", &crit_percent) == 1) {
245 break;
246 }
247 else {
248 usage ("Critical threshold must be integer or percentage!\n");
249 }
250 case 'V': /* version */
251 print_revision (my_basename (argv[0]), "$Revision$");
252 exit (STATE_OK);
253 case 'h': /* help */
254 print_help ();
255 exit (STATE_OK);
256 case '?': /* help */
257 usage ("Invalid argument\n");
258 }
259 }
260 return i;
261}
262
263
264
265
266
267int
268validate_arguments (void)
269{
270 if (warn_percent > 100 && crit_percent > 100 && warn_size < 0
271 && crit_size < 0) {
272 return ERROR;
273 }
274 else if (warn_percent > crit_percent) {
275 usage
276 ("Warning percentage should not be less than critical percentage\n");
277 }
278 else if (warn_size < crit_size) {
279 usage
280 ("Warning free space should not be more than critical free space\n");
281 }
282 return OK;
283}
284
285
286
287
288
289void
290print_usage (void)
291{
292 printf
293 ("Usage: check_swap -w <used_percentage>%% -c <used_percentage>%%\n"
294 " check_swap -w <bytes_free> -c <bytes_free>\n"
295 " check_swap (-V|--version)\n" " check_swap (-h|--help)\n");
296}
297
298
299
300
301
302void
303print_help (void)
304{
305 print_revision (PROGNAME, "$Revision$");
306 printf
307 ("Copyright (c) 2000 Karl DeBisschop\n\n"
308 "This plugin will check all of the swap partitions and return an\n"
309 "error if the the avalable swap space is less than specified.\n\n");
310 print_usage ();
311 printf
312 ("\nOptions:\n"
313 " -w, --warning=INTEGER\n"
314 " Exit with WARNING status if less than INTEGER bytes of swap space are free\n"
315 " -w, --warning=PERCENT%%\n"
316 " Exit with WARNING status if more than PERCENT of swap space has been used\n"
317 " -c, --critical=INTEGER\n"
318 " Exit with CRITICAL status if less than INTEGER bytes of swap space are free\n"
319 " -c, --critical=PERCENT%%\n"
320 " Exit with CRITCAL status if more than PERCENT of swap space has been used\n"
321 " -h, --help\n"
322 " Print detailed help screen\n"
323 " -V, --version\n" " Print version information\n\n");
324 support ();
325}
diff --git a/plugins/check_tcp.c b/plugins/check_tcp.c
new file mode 100644
index 00000000..bef0e752
--- /dev/null
+++ b/plugins/check_tcp.c
@@ -0,0 +1,563 @@
1/******************************************************************************
2 *
3 * This file is part of the Nagios Plugins.
4 *
5 * Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>
6 *
7 * The Nagios Plugins are free software; you can redistribute them
8 * and/or modify them under the terms of the GNU General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * $Id$
22 *
23 *****************************************************************************/
24
25#define PROGRAM check_tcp
26#define DESCRIPTION "Check a TCP port"
27#define AUTHOR "Ethan Galstad"
28#define EMAIL "nagios@nagios.org"
29#define COPYRIGHTDATE "1999"
30
31#include "config.h"
32#include "common.h"
33#include "netutils.h"
34#include "utils.h"
35
36#ifdef HAVE_SSL_H
37#include <rsa.h>
38#include <crypto.h>
39#include <x509.h>
40#include <pem.h>
41#include <ssl.h>
42#include <err.h>
43#endif
44
45#ifdef HAVE_OPENSSL_SSL_H
46#include <openssl/rsa.h>
47#include <openssl/crypto.h>
48#include <openssl/x509.h>
49#include <openssl/pem.h>
50#include <openssl/ssl.h>
51#include <openssl/err.h>
52#endif
53
54#ifdef HAVE_SSL
55SSL_CTX *ctx;
56SSL *ssl;
57int connect_SSL (void);
58#endif
59
60#define TCP_PROTOCOL 1
61#define UDP_PROTOCOL 2
62
63int process_arguments (int, char **);
64void print_usage (void);
65void print_help (void);
66
67char *PROGNAME = NULL;
68char *SERVICE = NULL;
69char *SEND = NULL;
70char *EXPECT = NULL;
71char *QUIT = NULL;
72int PROTOCOL = 0;
73int PORT = 0;
74
75int server_port = 0;
76char *server_address = NULL;
77char *server_send = NULL;
78char *server_quit = NULL;
79char **server_expect = NULL;
80int server_expect_count = 0;
81char **warn_codes = NULL;
82int warn_codes_count = 0;
83char **crit_codes = NULL;
84int crit_codes_count = 0;
85int delay = 0;
86int warning_time = 0;
87int check_warning_time = FALSE;
88int critical_time = 0;
89int check_critical_time = FALSE;
90int verbose = FALSE;
91int use_ssl = FALSE;
92int sd;
93
94int
95main (int argc, char **argv)
96{
97 int result;
98 int i;
99 char buffer[MAX_INPUT_BUFFER] = "";
100 char *status = NULL;
101 char *output = NULL;
102 char *ptr = NULL;
103
104 if (strstr (argv[0], "check_udp")) {
105 PROGNAME = strscpy (PROGNAME, "check_udp");
106 SERVICE = strscpy (SERVICE, "UDP");
107 SEND = NULL;
108 EXPECT = NULL;
109 QUIT = NULL;
110 PROTOCOL = UDP_PROTOCOL;
111 PORT = 0;
112 }
113 else if (strstr (argv[0], "check_tcp")) {
114 PROGNAME = strscpy (PROGNAME, "check_tcp");
115 SERVICE = strscpy (SERVICE, "TCP");
116 SEND = NULL;
117 EXPECT = NULL;
118 QUIT = NULL;
119 PROTOCOL = TCP_PROTOCOL;
120 PORT = 0;
121 }
122 else if (strstr (argv[0], "check_ftp")) {
123 PROGNAME = strscpy (PROGNAME, "check_ftp");
124 SERVICE = strscpy (SERVICE, "FTP");
125 SEND = NULL;
126 EXPECT = strscpy (EXPECT, "220");
127 QUIT = strscpy (QUIT, "QUIT\r\n");
128 PROTOCOL = TCP_PROTOCOL;
129 PORT = 21;
130 }
131 else if (strstr (argv[0], "check_smtp")) {
132 PROGNAME = strscpy (PROGNAME, "check_smtp");
133 SERVICE = strscpy (SERVICE, "SMTP");
134 SEND = NULL;
135 EXPECT = strscpy (EXPECT, "220");
136 QUIT = strscpy (QUIT, "QUIT\r\n");
137 PROTOCOL = TCP_PROTOCOL;
138 PORT = 25;
139 }
140 else if (strstr (argv[0], "check_pop")) {
141 PROGNAME = strscpy (PROGNAME, "check_pop");
142 SERVICE = strscpy (SERVICE, "POP");
143 SEND = NULL;
144 EXPECT = strscpy (EXPECT, "110");
145 QUIT = strscpy (QUIT, "QUIT\r\n");
146 PROTOCOL = TCP_PROTOCOL;
147 PORT = 110;
148 }
149 else if (strstr (argv[0], "check_imap")) {
150 PROGNAME = strscpy (PROGNAME, "check_imap");
151 SERVICE = strscpy (SERVICE, "IMAP");
152 SEND = NULL;
153 EXPECT = strscpy (EXPECT, "* OK");
154 QUIT = strscpy (QUIT, "a1 LOGOUT\r\n");
155 PROTOCOL = TCP_PROTOCOL;
156 PORT = 143;
157 }
158#ifdef HAVE_SSL
159 else if (strstr(argv[0],"check_simap")) {
160 PROGNAME=strscpy(PROGNAME,"check_simap");
161 SERVICE=strscpy(SERVICE,"SIMAP");
162 SEND=NULL;
163 EXPECT=strscpy(EXPECT,"* OK");
164 QUIT=strscpy(QUIT,"a1 LOGOUT\n");
165 PROTOCOL=TCP_PROTOCOL;
166 use_ssl=TRUE;
167 PORT=993;
168 }
169#endif
170 else if (strstr (argv[0], "check_nntp")) {
171 PROGNAME = strscpy (PROGNAME, "check_nntp");
172 SERVICE = strscpy (SERVICE, "NNTP");
173 SEND = NULL;
174 EXPECT = NULL;
175 server_expect = realloc (server_expect, ++server_expect_count);
176 server_expect[server_expect_count - 1] = strscpy (EXPECT, "200");
177 server_expect = realloc (server_expect, ++server_expect_count);
178 server_expect[server_expect_count - 1] = strscpy (NULL, "201");
179 QUIT = strscpy (QUIT, "QUIT\r\n");
180 PROTOCOL = TCP_PROTOCOL;
181 PORT = 119;
182 }
183 else {
184 usage ("ERROR: Generic check_tcp called with unknown service\n");
185 }
186
187 server_address = strscpy (NULL, "127.0.0.1");
188 server_port = PORT;
189 server_send = SEND;
190 server_quit = QUIT;
191
192 if (process_arguments (argc, argv) == ERROR)
193 usage ("Could not parse arguments\n");
194
195 /* use default expect if none listed in process_arguments() */
196 if (EXPECT && server_expect_count == 0) {
197 server_expect = malloc (1);
198 server_expect[server_expect_count - 1] = EXPECT;
199 }
200
201 /* initialize alarm signal handling */
202 signal (SIGALRM, socket_timeout_alarm_handler);
203
204 /* set socket timeout */
205 alarm (socket_timeout);
206
207 /* try to connect to the host at the given port number */
208 time (&start_time);
209#ifdef HAVE_SSL
210 if (use_ssl)
211 result = connect_SSL ();
212 else
213#endif
214 {
215 if (PROTOCOL == UDP_PROTOCOL)
216 result = my_udp_connect (server_address, server_port, &sd);
217 else /* default is TCP */
218 result = my_tcp_connect (server_address, server_port, &sd);
219 }
220
221 if (result == STATE_CRITICAL)
222 return STATE_CRITICAL;
223
224 if (server_send != NULL) { /* Something to send? */
225 snprintf (buffer, MAX_INPUT_BUFFER - 1, "%s\r\n", server_send);
226 buffer[MAX_INPUT_BUFFER - 1] = 0;
227#ifdef HAVE_SSL
228 if (use_ssl)
229 SSL_write(ssl,buffer,strlen(buffer));
230 else
231#endif
232 send (sd, buffer, strlen (buffer), 0);
233 }
234
235 if (delay > 0) {
236 start_time = start_time + delay;
237 sleep (delay);
238 }
239
240 if (server_send || server_expect_count > 0) {
241
242 /* watch for the expect string */
243#ifdef HAVE_SSL
244 if (use_ssl && SSL_read (ssl, buffer, MAX_INPUT_BUFFER - 1)>=0)
245 status = strscat(status,buffer);
246 else
247#endif
248 {
249 if (recv (sd, buffer, MAX_INPUT_BUFFER - 1, 0) >= 0)
250 status = strscat (status, buffer);
251 }
252 strip (status);
253
254 /* return a CRITICAL status if we couldn't read any data */
255 if (status == NULL)
256 terminate (STATE_CRITICAL, "No data received from host\n");
257
258 if (status && verbose)
259 printf ("%s\n", status);
260
261 if (server_expect_count > 0) {
262 for (i = 0;; i++) {
263 printf ("%d %d\n", i, server_expect_count);
264 if (i >= server_expect_count)
265 terminate (STATE_WARNING, "Invalid response from host\n");
266 if (strstr (status, server_expect[i]))
267 break;
268 }
269 }
270 }
271
272 if (server_quit)
273#ifdef HAVE_SSL
274 if (use_ssl) {
275 SSL_write (ssl, QUIT, strlen (QUIT));
276 SSL_shutdown (ssl);
277 SSL_free (ssl);
278 SSL_CTX_free (ctx);
279 }
280 else
281#endif
282 send (sd, server_quit, strlen (server_quit), 0);
283
284 /* close the connection */
285 close (sd);
286
287 time (&end_time);
288
289 if (check_critical_time == TRUE && (end_time - start_time) > critical_time)
290 result = STATE_CRITICAL;
291 else if (check_warning_time == TRUE
292 && (end_time - start_time) > warning_time) result = STATE_WARNING;
293
294 /* reset the alarm */
295 alarm (0);
296
297 printf
298 ("%s %s - %d second response time on port %d",
299 SERVICE,
300 state_text (result), (int) (end_time - start_time), server_port);
301
302 if (status)
303 printf (" [%s]\n", status);
304 else
305 printf ("\n");
306
307 return result;
308}
309
310
311
312
313
314
315
316/* process command-line arguments */
317int
318process_arguments (int argc, char **argv)
319{
320 int c;
321
322#ifdef HAVE_GETOPT_H
323 int option_index = 0;
324 static struct option long_options[] = {
325 {"hostname", required_argument, 0, 'H'},
326 {"critical-time", required_argument, 0, 'c'},
327 {"warning-time", required_argument, 0, 'w'},
328 {"critical-codes", required_argument, 0, 'C'},
329 {"warning-codes", required_argument, 0, 'W'},
330 {"timeout", required_argument, 0, 't'},
331 {"protocol", required_argument, 0, 'P'},
332 {"port", required_argument, 0, 'p'},
333 {"send", required_argument, 0, 's'},
334 {"expect", required_argument, 0, 'e'},
335 {"quit", required_argument, 0, 'q'},
336 {"delay", required_argument, 0, 'd'},
337 {"verbose", no_argument, 0, 'v'},
338 {"version", no_argument, 0, 'V'},
339 {"help", no_argument, 0, 'h'},
340 {0, 0, 0, 0}
341 };
342#endif
343
344 if (argc < 2)
345 usage ("No arguments found\n");
346
347 /* backwards compatibility */
348 for (c = 1; c < argc; c++) {
349 if (strcmp ("-to", argv[c]) == 0)
350 strcpy (argv[c], "-t");
351 else if (strcmp ("-wt", argv[c]) == 0)
352 strcpy (argv[c], "-w");
353 else if (strcmp ("-ct", argv[c]) == 0)
354 strcpy (argv[c], "-c");
355 }
356
357 if (!is_option (argv[1])) {
358 server_address = argv[1];
359 argv[1] = argv[0];
360 argv = &argv[1];
361 argc--;
362 }
363
364 while (1) {
365#ifdef HAVE_GETOPT_H
366 c =
367 getopt_long (argc, argv, "+hVvH:s:e:q:c:w:t:p:C:W:d:S", long_options,
368 &option_index);
369#else
370 c = getopt (argc, argv, "+hVvH:s:e:q:c:w:t:p:C:W:d:S");
371#endif
372
373 if (c == -1 || c == EOF || c == 1)
374 break;
375
376 switch (c) {
377 case '?': /* print short usage statement if args not parsable */
378 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
379 print_usage ();
380 exit (STATE_UNKNOWN);
381 case 'h': /* help */
382 print_help ();
383 exit (STATE_OK);
384 case 'V': /* version */
385 print_revision (PROGNAME, "$Revision$");
386 exit (STATE_OK);
387 case 'v': /* verbose mode */
388 verbose = TRUE;
389 break;
390 case 'H': /* hostname */
391 if (is_host (optarg) == FALSE)
392 usage ("Invalid host name/address\n");
393 server_address = optarg;
394 break;
395 case 'c': /* critical */
396 if (!is_intnonneg (optarg))
397 usage ("Critical threshold must be a nonnegative integer\n");
398 critical_time = atoi (optarg);
399 check_critical_time = TRUE;
400 break;
401 case 'w': /* warning */
402 if (!is_intnonneg (optarg))
403 usage ("Warning threshold must be a nonnegative integer\n");
404 warning_time = atoi (optarg);
405 check_warning_time = TRUE;
406 break;
407 case 'C':
408 crit_codes = realloc (crit_codes, ++crit_codes_count);
409 crit_codes[crit_codes_count - 1] = optarg;
410 break;
411 case 'W':
412 warn_codes = realloc (warn_codes, ++warn_codes_count);
413 warn_codes[warn_codes_count - 1] = optarg;
414 break;
415 case 't': /* timeout */
416 if (!is_intpos (optarg))
417 usage ("Timeout interval must be a positive integer\n");
418 socket_timeout = atoi (optarg);
419 break;
420 case 'p': /* port */
421 if (!is_intpos (optarg))
422 usage ("Server port must be a positive integer\n");
423 server_port = atoi (optarg);
424 break;
425 case 's':
426 server_send = optarg;
427 break;
428 case 'e':
429 EXPECT = NULL;
430 if (server_expect_count == 0)
431 server_expect = malloc (++server_expect_count);
432 else
433 server_expect = realloc (server_expect, ++server_expect_count);
434 server_expect[server_expect_count - 1] = optarg;
435 break;
436 case 'q':
437 server_quit = optarg;
438 break;
439 case 'd':
440 if (is_intpos (optarg))
441 delay = atoi (optarg);
442 else
443 usage ("Delay must be a positive integer\n");
444 break;
445 case 'S':
446#ifndef HAVE_SSL
447 terminate (STATE_UNKNOWN,
448 "SSL support not available. Install OpenSSL and recompile.");
449#endif
450 use_ssl = TRUE;
451 break;
452 }
453 }
454
455 if (server_address == NULL)
456 usage ("You must provide a server address\n");
457
458 return OK;
459}
460
461
462
463
464
465void
466print_usage (void)
467{
468 printf
469 ("Usage: %s -H host -p port [-w warn_time] [-c crit_time] [-s send]\n"
470 " [-e expect] [-W wait] [-t to_sec] [-v]\n", PROGNAME);
471}
472
473
474
475
476
477void
478print_help (void)
479{
480 print_revision (PROGNAME, "$Revision$");
481 printf
482 ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n\n"
483 "This plugin tests %s connections with the specified host.\n\n",
484 SERVICE);
485 print_usage ();
486 printf
487 ("Options:\n"
488 " -H, --hostname=ADDRESS\n"
489 " Host name argument for servers using host headers (use numeric\n"
490 " address if possible to bypass DNS lookup).\n"
491 " -p, --port=INTEGER\n"
492 " Port number\n"
493 " -s, --send=STRING\n"
494 " String to send to the server\n"
495 " -e, --expect=STRING\n"
496 " String to expect in server response"
497 " -W, --wait=INTEGER\n"
498 " Seconds to wait between sending string and polling for response\n"
499 " -w, --warning=INTEGER\n"
500 " Response time to result in warning status (seconds)\n"
501 " -c, --critical=INTEGER\n"
502 " Response time to result in critical status (seconds)\n"
503 " -t, --timeout=INTEGER\n"
504 " Seconds before connection times out (default: %d)\n"
505 " -v"
506 " Show details for command-line debugging (do not use with nagios server)\n"
507 " -h, --help\n"
508 " Print detailed help screen\n"
509 " -V, --version\n"
510 " Print version information\n", DEFAULT_SOCKET_TIMEOUT);
511}
512
513
514#ifdef HAVE_SSL
515int
516connect_SSL (void)
517{
518 SSL_METHOD *meth;
519
520 /* Initialize SSL context */
521 SSLeay_add_ssl_algorithms ();
522 meth = SSLv2_client_method ();
523 SSL_load_error_strings ();
524 if ((ctx = SSL_CTX_new (meth)) == NULL)
525 {
526 printf ("ERROR: Cannot create SSL context.\n");
527 return STATE_CRITICAL;
528 }
529
530 /* Initialize alarm signal handling */
531 signal (SIGALRM, socket_timeout_alarm_handler);
532
533 /* Set socket timeout */
534 alarm (socket_timeout);
535
536 /* Save start time */
537 time (&start_time);
538
539 /* Make TCP connection */
540 if (my_tcp_connect (server_address, server_port, &sd) == STATE_OK)
541 {
542 /* Do the SSL handshake */
543 if ((ssl = SSL_new (ctx)) != NULL)
544 {
545 SSL_set_fd (ssl, sd);
546 if (SSL_connect (ssl) != -1)
547 return OK;
548 ERR_print_errors_fp (stderr);
549 }
550 else
551 {
552 printf ("ERROR: Cannot initiate SSL handshake.\n");
553 }
554 SSL_free (ssl);
555 }
556
557 SSL_CTX_free (ctx);
558 close (sd);
559
560 return STATE_CRITICAL;
561}
562#endif
563
diff --git a/plugins/check_time.c b/plugins/check_time.c
new file mode 100644
index 00000000..86c414e2
--- /dev/null
+++ b/plugins/check_time.c
@@ -0,0 +1,370 @@
1/******************************************************************************
2*
3* CHECK_TIME.C
4*
5* Program: Network time server plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8* Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
9*
10* $Id$
11*
12* Description:
13*
14* This plugin will attempt to connect to the specified port
15* on the host. Successul connects return STATE_OK, refusals
16* and timeouts return STATE_CRITICAL, other errors return
17* STATE_UNKNOWN.
18*
19* License Information:
20*
21* This program is free software; you can redistribute it and/or modify
22* it under the terms of the GNU General Public License as published by
23* the Free Software Foundation; either version 2 of the License, or
24* (at your option) any later version.
25*
26* This program is distributed in the hope that it will be useful,
27* but WITHOUT ANY WARRANTY; without even the implied warranty of
28* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29* GNU General Public License for more details.
30*
31* You should have received a copy of the GNU General Public License
32* along with this program; if not, write to the Free Software
33* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34*
35*****************************************************************************/
36
37#include "config.h"
38#include "common.h"
39#include "netutils.h"
40#include "utils.h"
41
42#define PROGNAME "check_time"
43
44#define TIME_PORT 37
45#define UNIX_EPOCH 2208988800UL
46
47unsigned long server_time, raw_server_time;
48time_t diff_time;
49int warning_time = 0;
50int check_warning_time = FALSE;
51int critical_time = 0;
52int check_critical_time = FALSE;
53unsigned long warning_diff = 0;
54int check_warning_diff = FALSE;
55unsigned long critical_diff = 0;
56int check_critical_diff = FALSE;
57int server_port = TIME_PORT;
58char *server_address = NULL;
59
60
61int process_arguments (int, char **);
62int call_getopt (int, char **);
63void print_usage (void);
64void print_help (void);
65
66
67int
68main (int argc, char **argv)
69{
70 int sd;
71 int result;
72
73 if (process_arguments (argc, argv) != OK)
74 usage ("Invalid command arguments supplied\n");
75
76 /* initialize alarm signal handling */
77 signal (SIGALRM, socket_timeout_alarm_handler);
78
79 /* set socket timeout */
80 alarm (socket_timeout);
81 time (&start_time);
82
83 /* try to connect to the host at the given port number */
84 if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) {
85 if (check_critical_time == TRUE)
86 result = STATE_CRITICAL;
87 else if (check_warning_time == TRUE)
88 result = STATE_WARNING;
89 else
90 result = STATE_UNKNOWN;
91 terminate (result,
92 "TIME UNKNOWN - could not connect to server %s, port %d\n",
93 server_address, server_port);
94 }
95
96 /* watch for the FTP connection string */
97 result = recv (sd, &raw_server_time, sizeof (raw_server_time), 0);
98
99 /* close the connection */
100 close (sd);
101
102 /* reset the alarm */
103 time (&end_time);
104 alarm (0);
105
106 /* return a WARNING status if we couldn't read any data */
107 if (result <= 0) {
108 if (check_critical_time == TRUE)
109 result = STATE_CRITICAL;
110 else if (check_warning_time == TRUE)
111 result = STATE_WARNING;
112 else
113 result = STATE_UNKNOWN;
114 terminate (result,
115 "TIME UNKNOWN - no data on recv() from server %s, port %d\n",
116 server_address, server_port);
117 }
118
119 result = STATE_OK;
120
121 if (check_critical_time == TRUE && (end_time - start_time) > critical_time)
122 result = STATE_CRITICAL;
123 else if (check_warning_time == TRUE
124 && (end_time - start_time) > warning_time) result = STATE_WARNING;
125
126 if (result != STATE_OK)
127 terminate (result, "TIME %s - %d second response time\n",
128 state_text (result), (int) (end_time - start_time));
129
130 server_time = ntohl (raw_server_time) - UNIX_EPOCH;
131 if (server_time > end_time)
132 diff_time = server_time - end_time;
133 else
134 diff_time = end_time - server_time;
135
136 if (check_critical_diff == TRUE && diff_time > critical_diff)
137 result = STATE_CRITICAL;
138 else if (check_warning_diff == TRUE && diff_time > warning_diff)
139 result = STATE_WARNING;
140
141 printf ("TIME %s - %lu second time difference\n", state_text (result),
142 diff_time);
143 return result;
144}
145
146
147
148
149
150
151/* process command-line arguments */
152int
153process_arguments (int argc, char **argv)
154{
155 int c;
156
157 if (argc < 2)
158 usage ("\n");
159
160 for (c = 1; c < argc; c++) {
161 if (strcmp ("-to", argv[c]) == 0)
162 strcpy (argv[c], "-t");
163 else if (strcmp ("-wd", argv[c]) == 0)
164 strcpy (argv[c], "-w");
165 else if (strcmp ("-cd", argv[c]) == 0)
166 strcpy (argv[c], "-c");
167 else if (strcmp ("-wt", argv[c]) == 0)
168 strcpy (argv[c], "-W");
169 else if (strcmp ("-ct", argv[c]) == 0)
170 strcpy (argv[c], "-C");
171 }
172
173 c = 0;
174 while ((c += call_getopt (argc - c, &argv[c])) < argc) {
175
176 if (is_option (argv[c]))
177 continue;
178
179 if (server_address == NULL) {
180 if (argc > c) {
181 if (is_host (argv[c]) == FALSE)
182 usage ("Invalid host name/address\n");
183 server_address = argv[c];
184 }
185 else {
186 usage ("Host name was not supplied\n");
187 }
188 }
189 }
190
191 return OK;
192}
193
194
195
196
197
198int
199call_getopt (int argc, char **argv)
200{
201 int c, i = 0;
202
203#ifdef HAVE_GETOPT_H
204 int option_index = 0;
205 static struct option long_options[] = {
206 {"hostname", required_argument, 0, 'H'},
207 {"warning-variance", required_argument, 0, 'w'},
208 {"critical-variance", required_argument, 0, 'c'},
209 {"warning-connect", required_argument, 0, 'W'},
210 {"critical-connect", required_argument, 0, 'C'},
211 {"port", required_argument, 0, 'p'},
212 {"timeout", required_argument, 0, 't'},
213 {"version", no_argument, 0, 'V'},
214 {"help", no_argument, 0, 'h'},
215 {0, 0, 0, 0}
216 };
217#endif
218
219 while (1) {
220#ifdef HAVE_GETOPT_H
221 c =
222 getopt_long (argc, argv, "+hVH:w:c:W:C:p:t:", long_options,
223 &option_index);
224#else
225 c = getopt (argc, argv, "+hVH:w:c:W:C:p:t:");
226#endif
227
228 i++;
229
230 if (c == -1 || c == EOF || c == 1)
231 break;
232
233 switch (c) {
234 case 'H':
235 case 'w':
236 case 'c':
237 case 'W':
238 case 'C':
239 case 'p':
240 case 't':
241 i++;
242 }
243
244 switch (c) {
245 case '?': /* print short usage statement if args not parsable */
246 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
247 print_usage ();
248 exit (STATE_UNKNOWN);
249 case 'h': /* help */
250 print_help ();
251 exit (STATE_OK);
252 case 'V': /* version */
253 print_revision (my_basename (argv[0]), "$Revision$");
254 exit (STATE_OK);
255 case 'H': /* hostname */
256 if (is_host (optarg) == FALSE)
257 usage ("Invalid host name/address\n");
258 server_address = optarg;
259 break;
260 case 'w': /* warning-variance */
261 if (is_intnonneg (optarg)) {
262 warning_diff = strtoul (optarg, NULL, 10);
263 check_warning_diff = TRUE;
264 }
265 else if (strspn (optarg, "0123456789:,") > 0) {
266 if (sscanf (optarg, "%lu%*[:,]%d", &warning_diff, &warning_time) == 2) {
267 check_warning_diff = TRUE;
268 check_warning_time = TRUE;
269 }
270 else {
271 usage ("Warning thresholds must be a nonnegative integer\n");
272 }
273 }
274 else {
275 usage ("Warning threshold must be a nonnegative integer\n");
276 }
277 break;
278 case 'c': /* critical-variance */
279 if (is_intnonneg (optarg)) {
280 critical_diff = strtoul (optarg, NULL, 10);
281 check_critical_diff = TRUE;
282 }
283 else if (strspn (optarg, "0123456789:,") > 0) {
284 if (sscanf (optarg, "%lu%*[:,]%d", &critical_diff, &critical_time) ==
285 2) {
286 check_critical_diff = TRUE;
287 check_critical_time = TRUE;
288 }
289 else {
290 usage ("Critical thresholds must be a nonnegative integer\n");
291 }
292 }
293 else {
294 usage ("Critical threshold must be a nonnegative integer\n");
295 }
296 break;
297 case 'W': /* warning-connect */
298 if (!is_intnonneg (optarg))
299 usage ("Warning threshold must be a nonnegative integer\n");
300 warning_time = atoi (optarg);
301 check_warning_time = TRUE;
302 break;
303 case 'C': /* critical-connect */
304 if (!is_intnonneg (optarg))
305 usage ("Critical threshold must be a nonnegative integer\n");
306 critical_time = atoi (optarg);
307 check_critical_time = TRUE;
308 break;
309 case 'p': /* port */
310 if (!is_intnonneg (optarg))
311 usage ("Serevr port must be a nonnegative integer\n");
312 server_port = atoi (optarg);
313 break;
314 case 't': /* timeout */
315 if (!is_intnonneg (optarg))
316 usage ("Timeout interval must be a nonnegative integer\n");
317 socket_timeout = atoi (optarg);
318 break;
319 }
320 }
321 return i;
322}
323
324
325
326
327
328void
329print_usage (void)
330{
331 printf
332 ("Usage: check_time -H <host_address> [-p port] [-w variance] [-c variance]\n"
333 " [-W connect_time] [-C connect_time] [-t timeout]\n");
334}
335
336
337
338
339
340void
341print_help (void)
342{
343 print_revision (PROGNAME, "$Revision$");
344 printf
345 ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
346 "This plugin connects to a time port on the specified host.\n\n");
347 print_usage ();
348 printf
349 ("Options:\n"
350 " -H, --hostname=ADDRESS\n"
351 " Host name argument for servers using host headers (use numeric\n"
352 " address if possible to bypass DNS lookup).\n"
353 " -w, --warning-variance=INTEGER\n"
354 " Time difference (sec.) necessary to result in a warning status\n"
355 " -c, --critical-variance=INTEGER\n"
356 " Time difference (sec.) necessary to result in a critical status\n"
357 " -W, --warning-connect=INTEGER\n"
358 " Response time (sec.) necessary to result in warning status\n"
359 " -C, --critical-connect=INTEGER\n"
360 " Response time (sec.) necessary to result in critical status\n"
361 " -t, --timeout=INTEGER\n"
362 " Seconds before connection times out (default: %d)\n"
363 " -p, --port=INTEGER\n"
364 " Port number (default: %d)\n"
365 " -h, --help\n"
366 " Print detailed help screen\n"
367 " -V, --version\n"
368 " Print version information\n\n", DEFAULT_SOCKET_TIMEOUT, TIME_PORT);
369 support ();
370}
diff --git a/plugins/check_udp.c b/plugins/check_udp.c
new file mode 100644
index 00000000..d00ce9c3
--- /dev/null
+++ b/plugins/check_udp.c
@@ -0,0 +1,315 @@
1/******************************************************************************
2*
3* CHECK_UDP.C
4*
5* Program: UDP port plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8*
9* Last Modified: $Date$
10*
11* Command line: CHECK_UDP <host_address> [-p port] [-s send] [-e expect] \
12* [-wt warn_time] [-ct crit_time] [-to to_sec]
13*
14* Description:
15*
16* This plugin will attempt to connect to the specified port
17* on the host. Successul connects return STATE_OK, refusals
18* and timeouts return STATE_CRITICAL, other errors return
19* STATE_UNKNOWN.
20*
21* License Information:
22*
23* This program is free software; you can redistribute it and/or modify
24* it under the terms of the GNU General Public License as published by
25* the Free Software Foundation; either version 2 of the License, or
26* (at your option) any later version.
27*
28* This program is distributed in the hope that it will be useful,
29* but WITHOUT ANY WARRANTY; without even the implied warranty of
30* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31* GNU General Public License for more details.
32*
33* You should have received a copy of the GNU General Public License
34* along with this program; if not, write to the Free Software
35* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
36*
37*****************************************************************************/
38
39#include "config.h"
40#include "common.h"
41#include "netutils.h"
42#include "utils.h"
43
44#define PROGNAME "check_udp"
45
46int warning_time = 0;
47int check_warning_time = FALSE;
48int critical_time = 0;
49int check_critical_time = FALSE;
50
51int process_arguments (int, char **);
52int call_getopt (int, char **);
53void print_usage (void);
54void print_help (void);
55
56int verbose = FALSE;
57int server_port = 0;
58char *server_address = NULL;
59char *server_expect = NULL;
60char *server_send = NULL;
61
62int
63main (int argc, char **argv)
64{
65 int result;
66 char recv_buffer[MAX_INPUT_BUFFER];
67
68 if (process_arguments (argc, argv) == ERROR)
69 usage ("\n");
70
71 /* initialize alarm signal handling */
72 signal (SIGALRM, socket_timeout_alarm_handler);
73
74 /* set socket timeout */
75 alarm (socket_timeout);
76
77 time (&start_time);
78 result =
79 process_udp_request (server_address, server_port, server_send,
80 recv_buffer, MAX_INPUT_BUFFER - 1);
81 time (&end_time);
82
83 if (result != STATE_OK) {
84 printf ("No response from host on port %d\n", server_port);
85 result = STATE_CRITICAL;
86 }
87
88 else {
89
90 /* check to see if we got the response we wanted */
91 if (server_expect) {
92 if (!strstr (recv_buffer, server_expect)) {
93 printf ("Invalid response received from host on port %d\n",
94 server_port);
95 result = STATE_CRITICAL;
96 }
97 }
98 }
99
100 /* we connected, so close connection before exiting */
101 if (result == STATE_OK) {
102
103 if (check_critical_time == TRUE
104 && (end_time - start_time) > critical_time) result = STATE_CRITICAL;
105 else if (check_warning_time == TRUE
106 && (end_time - start_time) > warning_time) result =
107 STATE_WARNING;
108
109 printf ("Connection %s on port %d - %d second response time\n",
110 (result == STATE_OK) ? "accepted" : "problem", server_port,
111 (int) (end_time - start_time));
112 }
113
114 /* reset the alarm */
115 alarm (0);
116
117 return result;
118}
119
120
121
122
123/* process command-line arguments */
124int
125process_arguments (int argc, char **argv)
126{
127 int c;
128
129 if (argc < 2)
130 usage ("\n");
131
132 for (c = 1; c < argc; c++) {
133 if (strcmp ("-to", argv[c]) == 0)
134 strcpy (argv[c], "-t");
135 else if (strcmp ("-wt", argv[c]) == 0)
136 strcpy (argv[c], "-w");
137 else if (strcmp ("-ct", argv[c]) == 0)
138 strcpy (argv[c], "-c");
139 }
140
141 c = 0;
142 while ((c += call_getopt (argc - c, &argv[c])) < argc) {
143
144 if (is_option (argv[c]))
145 continue;
146
147 if (server_address == NULL) {
148 if (argc > c) {
149 if (is_host (argv[c]) == FALSE)
150 usage ("Invalid host name/address\n");
151 server_address = argv[c];
152 }
153 else {
154 usage ("Host name was not supplied\n");
155 }
156 }
157 }
158
159 if (server_send == NULL)
160 server_send = strscpy (server_send, "");
161
162 return OK;
163}
164
165
166
167
168
169int
170call_getopt (int argc, char **argv)
171{
172 int c, i = 0;
173
174#ifdef HAVE_GETOPT_H
175 int option_index = 0;
176 static struct option long_options[] = {
177 {"hostname", required_argument, 0, 'H'},
178 {"critical", required_argument, 0, 'c'},
179 {"warning", required_argument, 0, 'w'},
180 {"timeout", required_argument, 0, 't'},
181 {"port", required_argument, 0, 'p'},
182 {"expect", required_argument, 0, 'e'},
183 {"send", required_argument, 0, 's'},
184 {"verbose", no_argument, 0, 'v'},
185 {"version", no_argument, 0, 'V'},
186 {"help", no_argument, 0, 'h'},
187 {0, 0, 0, 0}
188 };
189#endif
190
191 while (1) {
192#ifdef HAVE_GETOPT_H
193 c =
194 getopt_long (argc, argv, "+hVvH:e:s:c:w:t:p:", long_options,
195 &option_index);
196#else
197 c = getopt (argc, argv, "+hVvH:e:s:c:w:t:p:");
198#endif
199
200 i++;
201
202 if (c == -1 || c == EOF || c == 1)
203 break;
204
205 switch (c) {
206 case 'H':
207 case 'c':
208 case 'w':
209 case 't':
210 case 'p':
211 case 'e':
212 case 's':
213 i++;
214 }
215
216 switch (c) {
217 case '?': /* print short usage statement if args not parsable */
218 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
219 print_usage ();
220 exit (STATE_UNKNOWN);
221 case 'h': /* help */
222 print_help ();
223 exit (STATE_OK);
224 case 'V': /* version */
225 print_revision (my_basename (argv[0]), "$Revision$");
226 exit (STATE_OK);
227 case 'v': /* verbose mode */
228 verbose = TRUE;
229 break;
230 case 'H': /* hostname */
231 if (is_host (optarg) == FALSE)
232 usage ("Invalid host name/address\n");
233 server_address = optarg;
234 break;
235 case 'c': /* critical */
236 if (!is_intnonneg (optarg))
237 usage ("Critical threshold must be a nonnegative integer\n");
238 critical_time = atoi (optarg);
239 check_critical_time = TRUE;
240 break;
241 case 'w': /* warning */
242 if (!is_intnonneg (optarg))
243 usage ("Warning threshold must be a nonnegative integer\n");
244 warning_time = atoi (optarg);
245 check_warning_time = TRUE;
246 break;
247 case 't': /* timeout */
248 if (!is_intnonneg (optarg))
249 usage ("Timeout interval must be a nonnegative integer\n");
250 socket_timeout = atoi (optarg);
251 break;
252 case 'p': /* port */
253 if (!is_intnonneg (optarg))
254 usage ("Serevr port must be a nonnegative integer\n");
255 server_port = atoi (optarg);
256 break;
257 case 'e': /* expect */
258 server_expect = optarg;
259 break;
260 case 's': /* send */
261 server_send = optarg;
262 break;
263 }
264 }
265 return i;
266}
267
268
269
270
271
272void
273print_usage (void)
274{
275 printf
276 ("Usage: %s -H <host_address> [-p port] [-w warn_time] [-c crit_time]\n"
277 " [-e expect] [-s send] [-t to_sec] [-v]\n", PROGNAME);
278}
279
280
281
282
283
284void
285print_help (void)
286{
287 print_revision (PROGNAME, "$Revision$");
288 printf
289 ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n\n"
290 "This plugin tests an UDP connection with the specified host.\n\n");
291 print_usage ();
292 printf
293 ("Options:\n"
294 " -H, --hostname=ADDRESS\n"
295 " Host name argument for servers using host headers (use numeric\n"
296 " address if possible to bypass DNS lookup).\n"
297 " -p, --port=INTEGER\n"
298 " Port number\n"
299 " -e, --expect=STRING <optional>\n"
300 " String to expect in first line of server response\n"
301 " -s, --send=STRING <optional>\n"
302 " String to send to the server when initiating the connection\n"
303 " -w, --warning=INTEGER <optional>\n"
304 " Response time to result in warning status (seconds)\n"
305 " -c, --critical=INTEGER <optional>\n"
306 " Response time to result in critical status (seconds)\n"
307 " -t, --timeout=INTEGER <optional>\n"
308 " Seconds before connection times out (default: %d)\n"
309 " -v, --verbose <optional>\n"
310 " Show details for command-line debugging (do not use with nagios server)\n"
311 " -h, --help\n"
312 " Print detailed help screen and exit\n"
313 " -V, --version\n"
314 " Print version information and exit\n", DEFAULT_SOCKET_TIMEOUT);
315}
diff --git a/plugins/check_ups.c b/plugins/check_ups.c
new file mode 100644
index 00000000..4632bdc0
--- /dev/null
+++ b/plugins/check_ups.c
@@ -0,0 +1,649 @@
1/******************************************************************************
2*
3* CHECK_UPS.C
4*
5* Program: UPS monitor plugin for Nagios
6* License: GPL
7* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8*
9* Last Modified: $Date$
10*
11* Command line: CHECK_UPS <host_address> [-u ups] [-p port] [-v variable] \
12* [-wv warn_value] [-cv crit_value] [-to to_sec]
13*
14* Description:
15*
16
17* This plugin attempts to determine the status of an UPS
18* (Uninterruptible Power Supply) on a remote host (or the local host)
19* that is being monitored with Russel Kroll's "Smarty UPS Tools"
20* package. If the UPS is online or calibrating, the plugin will
21* return an OK state. If the battery is on it will return a WARNING
22* state. If the UPS is off or has a low battery the plugin will
23* return a CRITICAL state. You may also specify a variable to check
24* (such as temperature, utility voltage, battery load, etc.) as well
25* as warning and critical thresholds for the value of that variable.
26* If the remote host has multiple UPS that are being monitored you
27* will have to use the [ups] option to specify which UPS to check.
28*
29* Notes:
30*
31* This plugin requires that the UPSD daemon distributed with Russel
32* Kroll's "Smart UPS Tools" be installed on the remote host. If you
33* don't have the package installed on your system, you can download
34* it from http://www.exploits.org/~rkroll/smartupstools
35*
36* License Information:
37*
38* This program is free software; you can redistribute it and/or modify
39* it under the terms of the GNU General Public License as published by
40* the Free Software Foundation; either version 2 of the License, or
41* (at your option) any later version.
42*
43* This program is distributed in the hope that it will be useful,
44* but WITHOUT ANY WARRANTY; without even the implied warranty of
45* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46* GNU General Public License for more details.
47*
48* You should have received a copy of the GNU General Public License
49* along with this program; if not, write to the Free Software
50* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
51*
52******************************************************************************/
53
54#include "config.h"
55#include "common.h"
56#include "netutils.h"
57#include "utils.h"
58
59#define PROGNAME "check_ups"
60
61#define CHECK_NONE 0
62
63#define PORT 3305
64
65#define UPS_NONE 0 /* no supported options */
66#define UPS_UTILITY 1 /* supports utility line voltage */
67#define UPS_BATTPCT 2 /* supports percent battery remaining */
68#define UPS_STATUS 4 /* supports UPS status */
69#define UPS_TEMP 8 /* supports UPS temperature */
70#define UPS_LOADPCT 16 /* supports load percent */
71
72#define UPSSTATUS_NONE 0
73#define UPSSTATUS_OFF 1
74#define UPSSTATUS_OL 2
75#define UPSSTATUS_OB 4
76#define UPSSTATUS_LB 8
77#define UPSSTATUS_CAL 16
78#define UPSSTATUS_UNKOWN 32
79
80int server_port = PORT;
81char *server_address = NULL;
82char *ups_name = NULL;
83double warning_value = 0.0L;
84double critical_value = 0.0L;
85int check_warning_value = FALSE;
86int check_critical_value = FALSE;
87int check_variable = UPS_NONE;
88int supported_options = UPS_NONE;
89int status = UPSSTATUS_NONE;
90
91double ups_utility_voltage = 0.0L;
92double ups_battery_percent = 0.0L;
93double ups_load_percent = 0.0L;
94double ups_temperature = 0.0L;
95char ups_status[MAX_INPUT_BUFFER] = "N/A";
96
97int determine_status (void);
98int determine_supported_vars (void);
99int get_ups_variable (const char *, char *, int);
100
101int process_arguments (int, char **);
102int call_getopt (int, char **);
103int validate_arguments (void);
104void print_help (void);
105void print_usage (void);
106
107int
108main (int argc, char **argv)
109{
110 int result = STATE_OK;
111 char output_message[MAX_INPUT_BUFFER];
112 char temp_buffer[MAX_INPUT_BUFFER];
113
114 double ups_utility_deviation = 0.0L;
115
116 if (process_arguments (argc, argv) != OK)
117 usage ("Invalid command arguments supplied\n");
118
119 /* initialize alarm signal handling */
120 signal (SIGALRM, socket_timeout_alarm_handler);
121
122 /* set socket timeout */
123 alarm (socket_timeout);
124
125 /* determine what variables the UPS supports */
126 if (determine_supported_vars () != OK)
127 return STATE_CRITICAL;
128
129 /* get the ups status if possible */
130 if (supported_options & UPS_STATUS) {
131
132 if (determine_status () != OK)
133 return STATE_CRITICAL;
134 ups_status[0] = 0;
135 result = STATE_OK;
136
137 if (status & UPSSTATUS_OFF) {
138 strcpy (ups_status, "Off");
139 result = STATE_CRITICAL;
140 }
141 else if ((status & (UPSSTATUS_OB | UPSSTATUS_LB)) ==
142 (UPSSTATUS_OB | UPSSTATUS_LB)) {
143 strcpy (ups_status, "On Battery, Low Battery");
144 result = STATE_CRITICAL;
145 }
146 else {
147 if (status & UPSSTATUS_OL) {
148 strcat (ups_status, "Online");
149 }
150 if (status & UPSSTATUS_OB) {
151 strcat (ups_status, "On Battery");
152 result = STATE_WARNING;
153 }
154 if (status & UPSSTATUS_LB) {
155 strcat (ups_status, ", Low Battery");
156 result = STATE_WARNING;
157 }
158 if (status & UPSSTATUS_CAL) {
159 strcat (ups_status, ", Calibrating");
160 }
161 if (status & UPSSTATUS_UNKOWN) {
162 strcat (ups_status, ", Unknown");
163 }
164 }
165 }
166
167 /* get the ups utility voltage if possible */
168 if (supported_options & UPS_UTILITY) {
169
170 if (get_ups_variable ("UTILITY", temp_buffer, sizeof (temp_buffer)) != OK)
171 return STATE_CRITICAL;
172
173 ups_utility_voltage = atof (temp_buffer);
174
175 if (ups_utility_voltage > 120.0)
176 ups_utility_deviation = 120.0 - ups_utility_voltage;
177 else
178 ups_utility_deviation = ups_utility_voltage - 120.0;
179
180 if (check_variable == UPS_UTILITY) {
181 if (check_critical_value == TRUE
182 && ups_utility_deviation >= critical_value) result = STATE_CRITICAL;
183 else if (check_warning_value == TRUE
184 && ups_utility_deviation >= warning_value
185 && result < STATE_WARNING) result = STATE_WARNING;
186 }
187 }
188
189 /* get the ups battery percent if possible */
190 if (supported_options & UPS_BATTPCT) {
191
192 if (get_ups_variable ("BATTPCT", temp_buffer, sizeof (temp_buffer)) != OK)
193 return STATE_CRITICAL;
194
195 ups_battery_percent = atof (temp_buffer);
196
197 if (check_variable == UPS_BATTPCT) {
198 if (check_critical_value == TRUE
199 && ups_battery_percent <= critical_value) result = STATE_CRITICAL;
200 else if (check_warning_value == TRUE
201 && ups_battery_percent <= warning_value
202 && result < STATE_WARNING) result = STATE_WARNING;
203 }
204 }
205
206 /* get the ups load percent if possible */
207 if (supported_options & UPS_LOADPCT) {
208
209 if (get_ups_variable ("LOADPCT", temp_buffer, sizeof (temp_buffer)) != OK)
210 return STATE_CRITICAL;
211
212 ups_load_percent = atof (temp_buffer);
213
214 if (check_variable == UPS_LOADPCT) {
215 if (check_critical_value == TRUE && ups_load_percent >= critical_value)
216 result = STATE_CRITICAL;
217 else if (check_warning_value == TRUE
218 && ups_load_percent >= warning_value && result < STATE_WARNING)
219 result = STATE_WARNING;
220 }
221 }
222
223 /* get the ups temperature if possible */
224 if (supported_options & UPS_TEMP) {
225
226 if (get_ups_variable ("UPSTEMP", temp_buffer, sizeof (temp_buffer)) != OK)
227 return STATE_CRITICAL;
228
229 ups_temperature = (atof (temp_buffer) * 1.8) + 32;
230
231 if (check_variable == UPS_TEMP) {
232 if (check_critical_value == TRUE && ups_temperature >= critical_value)
233 result = STATE_CRITICAL;
234 else if (check_warning_value == TRUE && ups_temperature >= warning_value
235 && result < STATE_WARNING)
236 result = STATE_WARNING;
237 }
238 }
239
240 /* if the UPS does not support any options we are looking for, report an error */
241 if (supported_options == UPS_NONE)
242 result = STATE_CRITICAL;
243
244 /* reset timeout */
245 alarm (0);
246
247
248 sprintf (output_message, "UPS %s - ",
249 (result == STATE_OK) ? "ok" : "problem");
250
251 if (supported_options & UPS_STATUS) {
252 sprintf (temp_buffer, "Status=%s ", ups_status);
253 strcat (output_message, temp_buffer);
254 }
255 if (supported_options & UPS_UTILITY) {
256 sprintf (temp_buffer, "Utility=%3.1fV ", ups_utility_voltage);
257 strcat (output_message, temp_buffer);
258 }
259 if (supported_options & UPS_BATTPCT) {
260 sprintf (temp_buffer, "Batt=%3.1f%% ", ups_battery_percent);
261 strcat (output_message, temp_buffer);
262 }
263 if (supported_options & UPS_LOADPCT) {
264 sprintf (temp_buffer, "Load=%3.1f%% ", ups_load_percent);
265 strcat (output_message, temp_buffer);
266 }
267 if (supported_options & UPS_TEMP) {
268 sprintf (temp_buffer, "Temp=%3.1fF", ups_temperature);
269 strcat (output_message, temp_buffer);
270 }
271 if (supported_options == UPS_NONE) {
272 sprintf (temp_buffer,
273 "UPS does not appear to support any available options\n");
274 strcat (output_message, temp_buffer);
275 }
276
277 printf ("%s\n", output_message);
278
279 return result;
280}
281
282
283
284/* determines what options are supported by the UPS */
285int
286determine_status (void)
287{
288 char recv_buffer[MAX_INPUT_BUFFER];
289 char temp_buffer[MAX_INPUT_BUFFER];
290 char *ptr;
291
292 if (get_ups_variable ("STATUS", recv_buffer, sizeof (recv_buffer)) !=
293 STATE_OK) {
294 printf ("Invalid response received from hostn");
295 return ERROR;
296 }
297
298 recv_buffer[strlen (recv_buffer) - 1] = 0;
299
300 strcpy (temp_buffer, recv_buffer);
301 for (ptr = (char *) strtok (temp_buffer, " "); ptr != NULL;
302 ptr = (char *) strtok (NULL, " ")) {
303 if (!strcmp (ptr, "OFF"))
304 status |= UPSSTATUS_OFF;
305 else if (!strcmp (ptr, "OL"))
306 status |= UPSSTATUS_OL;
307 else if (!strcmp (ptr, "OB"))
308 status |= UPSSTATUS_OB;
309 else if (!strcmp (ptr, "LB"))
310 status |= UPSSTATUS_LB;
311 else if (!strcmp (ptr, "CAL"))
312 status |= UPSSTATUS_CAL;
313 else
314 status |= UPSSTATUS_UNKOWN;
315 }
316
317 return OK;
318}
319
320
321/* determines what options are supported by the UPS */
322int
323determine_supported_vars (void)
324{
325 char send_buffer[MAX_INPUT_BUFFER];
326 char recv_buffer[MAX_INPUT_BUFFER];
327 char temp_buffer[MAX_INPUT_BUFFER];
328 char *ptr;
329
330
331 /* get the list of variables that this UPS supports */
332 if (ups_name)
333 sprintf (send_buffer, "LISTVARS %s\r\n", ups_name);
334 else
335 sprintf (send_buffer, "LISTVARS\r\n");
336 if (process_tcp_request
337 (server_address, server_port, send_buffer, recv_buffer,
338 sizeof (recv_buffer)) != STATE_OK) {
339 printf ("Invalid response received from host\n");
340 return ERROR;
341 }
342
343 recv_buffer[strlen (recv_buffer) - 1] = 0;
344
345 if (ups_name)
346 ptr = recv_buffer + 5 + strlen (ups_name) + 2;
347 else
348 ptr = recv_buffer + 5;
349
350 strcpy (temp_buffer, recv_buffer);
351
352 for (ptr = (char *) strtok (temp_buffer, " "); ptr != NULL;
353 ptr = (char *) strtok (NULL, " ")) {
354 if (!strcmp (ptr, "UTILITY"))
355 supported_options |= UPS_UTILITY;
356 else if (!strcmp (ptr, "BATTPCT"))
357 supported_options |= UPS_BATTPCT;
358 else if (!strcmp (ptr, "LOADPCT"))
359 supported_options |= UPS_LOADPCT;
360 else if (!strcmp (ptr, "STATUS"))
361 supported_options |= UPS_STATUS;
362 else if (!strcmp (ptr, "UPSTEMP"))
363 supported_options |= UPS_TEMP;
364 }
365
366 return OK;
367}
368
369
370/* gets a variable value for a specific UPS */
371int
372get_ups_variable (const char *varname, char *buf, int buflen)
373{
374 /* char command[MAX_INPUT_BUFFER]; */
375 char temp_buffer[MAX_INPUT_BUFFER];
376 char send_buffer[MAX_INPUT_BUFFER];
377 char *ptr;
378
379 /* create the command string to send to the UPS daemon */
380 if (ups_name)
381 sprintf (send_buffer, "REQ %s@%s\n", varname, ups_name);
382 else
383 sprintf (send_buffer, "REQ %s\n", varname);
384
385 /* send the command to the daemon and get a response back */
386 if (process_tcp_request
387 (server_address, server_port, send_buffer, temp_buffer,
388 sizeof (temp_buffer)) != STATE_OK) {
389 printf ("Invalid response received from host\n");
390 return ERROR;
391 }
392
393 if (ups_name)
394 ptr = temp_buffer + strlen (varname) + 5 + strlen (ups_name) + 1;
395 else
396 ptr = temp_buffer + strlen (varname) + 5;
397
398 if (!strcmp (ptr, "NOT-SUPPORTED")) {
399 printf ("Error: Variable '%s' is not supported\n", varname);
400 return ERROR;
401 }
402
403 if (!strcmp (ptr, "DATA-STALE")) {
404 printf ("Error: UPS data is stale\n");
405 return ERROR;
406 }
407
408 if (!strcmp (ptr, "UNKNOWN-UPS")) {
409 if (ups_name)
410 printf ("Error: UPS '%s' is unknown\n", ups_name);
411 else
412 printf ("Error: UPS is unknown\n");
413 return ERROR;
414 }
415
416 strncpy (buf, ptr, buflen - 1);
417 buf[buflen - 1] = 0;
418
419 return OK;
420}
421
422
423
424
425
426/* Command line: CHECK_UPS <host_address> [-u ups] [-p port] [-v variable]
427 [-wv warn_value] [-cv crit_value] [-to to_sec] */
428
429
430/* process command-line arguments */
431int
432process_arguments (int argc, char **argv)
433{
434 int c;
435
436 if (argc < 2)
437 return ERROR;
438
439 for (c = 1; c < argc; c++) {
440 if (strcmp ("-to", argv[c]) == 0)
441 strcpy (argv[c], "-t");
442 else if (strcmp ("-wt", argv[c]) == 0)
443 strcpy (argv[c], "-w");
444 else if (strcmp ("-ct", argv[c]) == 0)
445 strcpy (argv[c], "-c");
446 }
447
448 c = 0;
449 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
450
451 if (is_option (argv[c]))
452 continue;
453
454 if (server_address == NULL) {
455 if (is_host (argv[c])) {
456 server_address = argv[c];
457 }
458 else {
459 usage ("Invalid host name");
460 }
461 }
462 }
463
464 if (server_address == NULL)
465 server_address = strscpy (NULL, "127.0.0.1");
466
467 return validate_arguments ();
468}
469
470
471
472
473
474
475int
476call_getopt (int argc, char **argv)
477{
478 int c, i = 0;
479
480#ifdef HAVE_GETOPT_H
481 int option_index = 0;
482 static struct option long_options[] = {
483 {"hostname", required_argument, 0, 'H'},
484 {"ups", required_argument, 0, 'u'},
485 {"port", required_argument, 0, 'p'},
486 {"critical", required_argument, 0, 'c'},
487 {"warning", required_argument, 0, 'w'},
488 {"timeout", required_argument, 0, 't'},
489 {"variable", required_argument, 0, 'v'},
490 {"version", no_argument, 0, 'V'},
491 {"help", no_argument, 0, 'h'},
492 {0, 0, 0, 0}
493 };
494#endif
495
496 while (1) {
497#ifdef HAVE_GETOPT_H
498 c =
499 getopt_long (argc, argv, "+hVH:u:p:v:c:w:t:", long_options,
500 &option_index);
501#else
502 c = getopt (argc, argv, "+?hVH:u:p:v:c:w:t:");
503#endif
504
505 i++;
506
507 if (c == -1 || c == EOF || c == 1)
508 break;
509
510 switch (c) {
511 case 'H':
512 case 'u':
513 case 'p':
514 case 'v':
515 case 'c':
516 case 'w':
517 case 't':
518 i++;
519 }
520
521 switch (c) {
522 case '?': /* help */
523 usage ("Invalid argument\n");
524 case 'H': /* hostname */
525 if (is_host (optarg)) {
526 server_address = optarg;
527 }
528 else {
529 usage ("Invalid host name\n");
530 }
531 break;
532 case 'u': /* ups name */
533 ups_name = optarg;
534 break;
535 case 'p': /* port */
536 if (is_intpos (optarg)) {
537 server_port = atoi (optarg);
538 }
539 else {
540 usage ("Server port must be a positive integer\n");
541 }
542 break;
543 case 'c': /* critical time threshold */
544 if (is_intnonneg (optarg)) {
545 critical_value = atoi (optarg);
546 check_critical_value = TRUE;
547 }
548 else {
549 usage ("Critical time must be a nonnegative integer\n");
550 }
551 break;
552 case 'w': /* warning time threshold */
553 if (is_intnonneg (optarg)) {
554 warning_value = atoi (optarg);
555 check_warning_value = TRUE;
556 }
557 else {
558 usage ("Warning time must be a nonnegative integer\n");
559 }
560 break;
561 case 'v': /* variable */
562 if (!strcmp (optarg, "LINE"))
563 check_variable = UPS_UTILITY;
564 else if (!strcmp (optarg, "TEMP"))
565 check_variable = UPS_TEMP;
566 else if (!strcmp (optarg, "BATTPCT"))
567 check_variable = UPS_BATTPCT;
568 else if (!strcmp (optarg, "LOADPCT"))
569 check_variable = UPS_LOADPCT;
570 else
571 usage ("Unrecognized UPS variable\n");
572 break;
573 case 't': /* timeout */
574 if (is_intnonneg (optarg)) {
575 socket_timeout = atoi (optarg);
576 }
577 else {
578 usage ("Time interval must be a nonnegative integer\n");
579 }
580 break;
581 case 'V': /* version */
582 print_revision (PROGNAME, "$Revision$");
583 exit (STATE_OK);
584 case 'h': /* help */
585 print_help ();
586 exit (STATE_OK);
587 }
588 }
589 return i;
590}
591
592
593
594
595
596int
597validate_arguments (void)
598{
599 return OK;
600}
601
602
603
604
605
606void
607print_help (void)
608{
609 print_revision (PROGNAME, "$Revision$");
610 printf
611 ("Copyright (c) 2000 Tom Shields/Karl DeBisschop\n\n"
612 "This plugin tests the UPS service on the specified host.\n\n");
613 print_usage ();
614 printf
615 ("\nOptions:\n"
616 " -H, --hostname=STRING or IPADDRESS\n"
617 " Check server on the indicated host\n"
618 " -p, --port=INTEGER\n"
619 " Make connection on the indicated port (default: %d)\n"
620 " -u, --ups=STRING\n"
621 " Name of UPS\n"
622 " -w, --warning=INTEGER\n"
623 " Seconds necessary to result in a warning status\n"
624 " -c, --critical=INTEGER\n"
625 " Seconds necessary to result in a critical status\n"
626 " -t, --timeout=INTEGER\n"
627 " Seconds before connection attempt times out (default: %d)\n"
628 " -v, --verbose\n"
629 " Print extra information (command-line use only)\n"
630 " -h, --help\n"
631 " Print detailed help screen\n"
632 " -V, --version\n"
633 " Print version information\n\n", PORT, DEFAULT_SOCKET_TIMEOUT);
634 support ();
635}
636
637
638
639
640
641void
642print_usage (void)
643{
644 printf
645 ("Usage: %s -H host [-e expect] [-p port] [-w warn] [-c crit]\n"
646 " [-t timeout] [-v]\n"
647 " %s --help\n"
648 " %s --version\n", PROGNAME, PROGNAME, PROGNAME);
649}
diff --git a/plugins/check_users.c b/plugins/check_users.c
new file mode 100644
index 00000000..2b8fa15b
--- /dev/null
+++ b/plugins/check_users.c
@@ -0,0 +1,257 @@
1/******************************************************************************
2 *
3 * CHECK_USERS.C
4 *
5 * Program: Current users plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 *
9 * Last Modified: $Date$
10 * Modifications:
11 *
12 * 1999-11-17 Karl DeBisschop
13 * - check stderr and status from spoen/spclose
14 * - reformat commenst to fit 80-cahr screen
15 * - set default result to STATE_UNKNOWN
16 * - initialize users at -1, eliminate 'found' variable
17 *
18 * Command line: CHECK_USERS <wusers> <cusers>
19 *
20 * Description:
21 *
22 * This plugin will use the /usr/bin/who command to check the number
23 * of users currently logged into the system. If number of logged in
24 * user exceeds the number specified by the <cusers> option, a
25 * STATE_CRITICAL is return. It it exceeds <wusers>, a STATE_WARNING
26 * is returned. Errors reading the output from the who command result
27 * in a STATE_UNKNOWN error.
28 *
29 * License Information:
30 *
31 * This program is free software; you can redistribute it and/or modify
32 * it under the terms of the GNU General Public License as published by
33 * the Free Software Foundation; either version 2 of the License, or
34 * (at your option) any later version.
35 *
36 * This program is distributed in the hope that it will be useful,
37 * but WITHOUT ANY WARRANTY; without even the implied warranty of
38 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 * GNU General Public License for more details.
40 *
41 * You should have received a copy of the GNU General Public License
42 * along with this program; if not, write to the Free Software
43 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
44 *
45 *****************************************************************************/
46
47#include "common.h"
48#include "popen.h"
49#include "utils.h"
50
51#define PROGNAME "check_users"
52
53#define possibly_set(a,b) ((a) == 0 ? (b) : 0)
54
55int process_arguments (int, char **);
56int call_getopt (int, char **);
57void print_usage (void);
58void print_help (void);
59
60int wusers = -1;
61int cusers = -1;
62
63int
64main (int argc, char **argv)
65{
66 int users = -1;
67 int result = STATE_OK;
68 char input_buffer[MAX_INPUT_BUFFER];
69
70 if (process_arguments (argc, argv) == ERROR)
71 usage ("Could not parse arguments\n");
72
73 /* run the command */
74 child_process = spopen (WHO_COMMAND);
75 if (child_process == NULL) {
76 printf ("Could not open pipe: %s\n", WHO_COMMAND);
77 return STATE_UNKNOWN;
78 }
79
80 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
81 if (child_stderr == NULL)
82 printf ("Could not open stderr for %s\n", WHO_COMMAND);
83
84 users = 0;
85
86 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
87
88 /* increment 'users' on all lines except total user count */
89 if (input_buffer[0] != '#') {
90 users++;
91 continue;
92 }
93
94 /* get total logged in users */
95 if (sscanf (input_buffer, "# users=%d", &users) == 1)
96 break;
97
98 }
99
100 /* check STDERR */
101 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
102 result = possibly_set (result, STATE_UNKNOWN);
103 (void) fclose (child_stderr);
104
105 /* close the pipe */
106 if (spclose (child_process))
107 result = possibly_set (result, STATE_UNKNOWN);
108
109 /* else check the user count against warning and critical thresholds */
110 if (users >= cusers)
111 result = STATE_CRITICAL;
112 else if (users >= wusers)
113 result = STATE_WARNING;
114 else if (users >= 0)
115 result = STATE_OK;
116
117 if (result == STATE_UNKNOWN)
118 printf ("Unable to read output\n");
119 else
120 printf ("USERS %s - %d users currently logged in\n", state_text (result),
121 users);
122
123 return result;
124}
125
126
127
128
129
130/* process command-line arguments */
131int
132process_arguments (int argc, char **argv)
133{
134 int c;
135
136 if (argc < 2)
137 usage ("\n");
138
139 c = 0;
140 while ((c += call_getopt (argc - c, &argv[c])) < argc) {
141
142 if (is_option (argv[c]))
143 continue;
144
145 if (wusers == -1 && argc > c) {
146 if (is_intnonneg (argv[c]) == FALSE)
147 usage ("Warning threshold must be a nonnegative integer\n");
148 wusers = atoi (argv[c]);
149
150 }
151 else if (cusers == -1 && argc > c) {
152 if (is_intnonneg (argv[c]) == FALSE)
153 usage ("Warning threshold must be a nonnegative integer\n");
154 cusers = atoi (argv[c]);
155 }
156 }
157
158 return OK;
159}
160
161
162
163
164
165int
166call_getopt (int argc, char **argv)
167{
168 int c, i = 0;
169
170#ifdef HAVE_GETOPT_H
171 int option_index = 0;
172 static struct option long_options[] = {
173 {"critical", required_argument, 0, 'c'},
174 {"warning", required_argument, 0, 'w'},
175 {"version", no_argument, 0, 'V'},
176 {"help", no_argument, 0, 'h'},
177 {0, 0, 0, 0}
178 };
179#endif
180
181 while (1) {
182#ifdef HAVE_GETOPT_H
183 c = getopt_long (argc, argv, "+hVvc:w:", long_options, &option_index);
184#else
185 c = getopt (argc, argv, "+hVvc:w:");
186#endif
187
188 i++;
189
190 if (c == -1 || c == EOF || c == 1)
191 break;
192
193 switch (c) {
194 case 'c':
195 case 'w':
196 i++;
197 }
198
199 switch (c) {
200 case '?': /* print short usage statement if args not parsable */
201 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
202 print_usage ();
203 exit (STATE_UNKNOWN);
204 case 'h': /* help */
205 print_help ();
206 exit (STATE_OK);
207 case 'V': /* version */
208 print_revision (my_basename (argv[0]), "$Revision$");
209 exit (STATE_OK);
210 case 'c': /* critical */
211 if (!is_intnonneg (optarg))
212 usage ("Critical threshold must be a nonnegative integer\n");
213 cusers = atoi (optarg);
214 break;
215 case 'w': /* warning */
216 if (!is_intnonneg (optarg))
217 usage ("Warning threshold must be a nonnegative integer\n");
218 wusers = atoi (optarg);
219 break;
220 }
221 }
222 return i;
223}
224
225
226
227
228
229void
230print_usage (void)
231{
232 printf ("Usage: %s -w <users> -c <users>\n", PROGNAME);
233}
234
235
236
237
238
239void
240print_help (void)
241{
242 print_revision (PROGNAME, "$Revision$");
243 printf
244 ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n\n"
245 "This plugin checks the number of users currently logged in on the local\n"
246 "system and generates an error if the number exceeds the thresholds specified.\n");
247 print_usage ();
248 printf
249 ("Options:\n"
250 " -w, --warning=INTEGER\n"
251 " Set WARNING status if more than INTEGER users are logged in\n"
252 " -c, --critical=INTEGER\n"
253 " Set CRITICAL status if more than INTEGER users are logged in\n"
254 " -h, --help\n"
255 " Print detailed help screen\n"
256 " -V, --version\n" " Print version information\n");
257}
diff --git a/plugins/check_vsz.c b/plugins/check_vsz.c
new file mode 100644
index 00000000..c8ca82bd
--- /dev/null
+++ b/plugins/check_vsz.c
@@ -0,0 +1,287 @@
1/******************************************************************************
2 *
3 * CHECK_VSZ.C
4 *
5 * Program: Process plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999,2000 Karl DeBisschop <kdebiss@alum.mit.edu>
8 *
9 * Last Modified: $Date$
10 *
11 * Description:
12 *
13 * This plugin will check for processes whose total image size exceeds
14 * the warning or critical thresholds given on the command line. With
15 * no command_name, everything that shows up on ps is evaluated.
16 * Otherwise, only jobs with the command_name given are examined.
17 * This program is particularly useful if you have to run a piece of
18 * commercial software that has a memory leak. With it you can shut
19 * down and restart the processes whenever the program threatens to
20 * take over your system.
21 *
22 * Modifications:
23 *
24 * 11-18-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
25 * change to getopt, use print_help
26 * 08-18-1999 Ethan Galstad (nagios@nagios.org)
27 * Changed code to use common include file
28 * Changed fclose() to pclose()
29 * 09-09-1999 Ethan Galstad (nagios@nagios.org)
30 * Changed popen()/pclose() to spopen()/spclose()
31 * 11-18-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
32 * set STATE_WARNING of stderr written or nonzero status returned
33 *
34 *****************************************************************************/
35
36#include "common.h"
37#include "popen.h"
38#include "utils.h"
39
40int process_arguments (int argc, char **argv);
41int call_getopt (int argc, char **argv);
42void print_help (char *cmd);
43void print_usage (char *cmd);
44
45int warn = -1;
46int crit = -1;
47char *proc = NULL;
48
49int
50main (int argc, char **argv)
51{
52 int len;
53 int result = STATE_OK;
54 int line = 0;
55 int proc_size = -1;
56 char input_buffer[MAX_INPUT_BUFFER];
57 char proc_name[MAX_INPUT_BUFFER];
58 char *message = NULL;
59
60 if (!process_arguments (argc, argv)) {
61 printf ("%s: failure parsing arguments\n", my_basename (argv[0]));
62 print_help (my_basename (argv[0]));
63 return STATE_UNKNOWN;
64 }
65
66 /* run the command */
67 child_process = spopen (VSZ_COMMAND);
68 if (child_process == NULL) {
69 printf ("Unable to open pipe: %s\n", VSZ_COMMAND);
70 return STATE_UNKNOWN;
71 }
72
73 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
74 if (child_stderr == NULL)
75 printf ("Could not open stderr for %s\n", VSZ_COMMAND);
76
77 message = malloc ((size_t) 1);
78 message[0] = 0;
79 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
80
81 line++;
82
83 /* skip the first line */
84 if (line == 1)
85 continue;
86
87 if (sscanf (input_buffer, VSZ_FORMAT, &proc_size, proc_name) == 2) {
88 if (proc == NULL) {
89 if (proc_size > warn) {
90 len = strlen (message) + strlen (proc_name) + 23;
91 message = realloc (message, len);
92 if (message == NULL)
93 terminate (STATE_UNKNOWN,
94 "check_vsz: could not malloc message (1)");
95 sprintf (message, "%s %s(%d)", message, proc_name, proc_size);
96 result = max (result, STATE_WARNING);
97 }
98 if (proc_size > crit) {
99 result = STATE_CRITICAL;
100 }
101 }
102 else if (strstr (proc_name, proc)) {
103 len = strlen (message) + 21;
104 message = realloc (message, len);
105 if (message == NULL)
106 terminate (STATE_UNKNOWN,
107 "check_vsz: could not malloc message (2)");
108 sprintf (message, "%s %d", message, proc_size);
109 if (proc_size > warn) {
110 result = max (result, STATE_WARNING);
111 }
112 if (proc_size > crit) {
113 result = STATE_CRITICAL;
114 }
115 }
116 }
117 }
118
119 /* If we get anything on STDERR, at least set warning */
120 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
121 result = max (result, STATE_WARNING);
122
123 (void) fclose (child_stderr);
124
125 /* close the pipe */
126 if (spclose (child_process))
127 result = max (result, STATE_WARNING);
128
129 if (result == STATE_OK)
130 printf ("ok (all VSZ<%d): %s\n", warn, message);
131 else if (result == STATE_UNKNOWN)
132 printf ("Unable to read output\n");
133 else if (result == STATE_WARNING)
134 printf ("WARNING (VSZ>%d):%s\n", warn, message);
135 else
136 printf ("CRITICAL (VSZ>%d):%s\n", crit, message);
137
138 return result;
139}
140
141
142
143
144int
145process_arguments (int argc, char **argv)
146{
147 int c;
148
149 if (argc < 2)
150 return ERROR;
151
152 c = 0;
153 while (c += (call_getopt (argc - c, &argv[c]))) {
154 if (argc <= c)
155 break;
156 if (warn == -1) {
157 if (!is_intnonneg (argv[c])) {
158 printf ("%s: critical threshold must be an integer: %s\n",
159 my_basename (argv[0]), argv[c]);
160 print_usage (my_basename (argv[0]));
161 exit (STATE_UNKNOWN);
162 }
163 warn = atoi (argv[c]);
164 }
165 else if (crit == -1) {
166 if (!is_intnonneg (argv[c])) {
167 printf ("%s: critical threshold must be an integer: %s\n",
168 my_basename (argv[0]), argv[c]);
169 print_usage (my_basename (argv[0]));
170 exit (STATE_UNKNOWN);
171 }
172 crit = atoi (argv[c]);
173 }
174 else if (proc == NULL) {
175 proc = malloc (strlen (argv[c]) + 1);
176 if (proc == NULL)
177 terminate (STATE_UNKNOWN,
178 "check_vsz: failed malloc of proc in process_arguments");
179 strcpy (proc, argv[c]);
180 }
181 }
182 return c;
183}
184
185int
186call_getopt (int argc, char **argv)
187{
188 int c, i = 1;
189
190#ifdef HAVE_GETOPT_H
191 int option_index = 0;
192 static struct option long_options[] = {
193 {"help", no_argument, 0, 'h'},
194 {"version", no_argument, 0, 'V'},
195 {"critical", required_argument, 0, 'c'},
196 {"warning", required_argument, 0, 'w'},
197 {"command", required_argument, 0, 'C'},
198 {0, 0, 0, 0}
199 };
200#endif
201
202 while (1) {
203#ifdef HAVE_GETOPT_H
204 c = getopt_long (argc, argv, "+hVc:w:C:", long_options, &option_index);
205#else
206 c = getopt (argc, argv, "+hVc:w:C:");
207#endif
208 if (c == EOF)
209 break;
210
211 i++;
212 switch (c) {
213 case 'c':
214 case 'w':
215 case 'C':
216 i++;
217 }
218
219 switch (c) {
220 case '?': /* help */
221 printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
222 print_usage (my_basename (argv[0]));
223 exit (STATE_UNKNOWN);
224 case 'h': /* help */
225 print_help (my_basename (argv[0]));
226 exit (STATE_OK);
227 case 'V': /* version */
228 print_revision (my_basename (argv[0]), "$Revision$");
229 exit (STATE_OK);
230 case 'c': /* critical threshold */
231 if (!is_intnonneg (optarg)) {
232 printf ("%s: critical threshold must be an integer: %s\n",
233 my_basename (argv[0]), optarg);
234 print_usage (my_basename (argv[0]));
235 exit (STATE_UNKNOWN);
236 }
237 crit = atoi (optarg);
238 break;
239 case 'w': /* warning threshold */
240 if (!is_intnonneg (optarg)) {
241 printf ("%s: warning threshold must be an integer: %s\n",
242 my_basename (argv[0]), optarg);
243 print_usage (my_basename (argv[0]));
244 exit (STATE_UNKNOWN);
245 }
246 warn = atoi (optarg);
247 break;
248 case 'C': /* command name */
249 proc = malloc (strlen (optarg) + 1);
250 if (proc == NULL)
251 terminate (STATE_UNKNOWN,
252 "check_vsz: failed malloc of proc in process_arguments");
253 strcpy (proc, optarg);
254 break;
255 }
256 }
257 return i;
258}
259
260void
261print_usage (char *cmd)
262{
263 printf ("Usage: %s -w <wsize> -c <csize> [-C command]\n"
264 " %s --help\n" " %s --version\n", cmd, cmd, cmd);
265}
266
267void
268print_help (char *cmd)
269{
270 print_revision ("check_vsz", "$Revision$");
271 printf
272 ("Copyright (c) 2000 Karl DeBisschop <kdebiss@alum.mit.edu>\n\n"
273 "This plugin checks the image size of a running program and returns an\n"
274 "error if the number is above either of the thresholds given.\n\n");
275 print_usage (cmd);
276 printf
277 ("\nOptions:\n"
278 " -h, --help\n"
279 " Print detailed help\n"
280 " -V, --version\n"
281 " Print version numbers and license information\n"
282 " -w, --warning=INTEGER\n"
283 " Program image size necessary to cause a WARNING state\n"
284 " -c, --critical=INTEGER\n"
285 " Program image size necessary to cause a CRITICAL state\n"
286 " -C, --command=STRING\n" " Program to search for [optional]\n");
287}
diff --git a/plugins/common.h.in b/plugins/common.h.in
new file mode 100644
index 00000000..9cb4bcbb
--- /dev/null
+++ b/plugins/common.h.in
@@ -0,0 +1,159 @@
1/******************************************************************************
2 *
3 * Nagios plugins common include file
4 *
5 * License: GPL
6 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
7 *
8 * Last Modified: 11-05-1999
9 *
10 * Description:
11 *
12 * This file contains common include files and defines used in many of
13 * the plugins.
14 *
15 * License Information:
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 *
31 *****************************************************************************/
32
33#include <stdio.h> /* obligatory includes */
34#include <stdlib.h>
35#include <errno.h>
36
37#include "config.h"
38
39#ifdef HAVE_STRINGS_H
40#include <strings.h>
41#endif
42#ifdef HAVE_STRING_H
43#include <string.h>
44#endif
45
46#ifdef HAVE_UNISTD_H
47#include <unistd.h>
48#endif
49
50#ifdef TIME_WITH_SYS_TIME
51# include <sys/time.h>
52# include <time.h>
53#else
54# ifdef HAVE_SYS_TIME_H
55# include <sys/time.h>
56# else
57# include <time.h>
58# endif
59#endif
60
61#ifdef HAVE_SYS_TYPES_H
62#include <sys/types.h>
63#endif
64
65#ifdef HAVE_SIGNAL_H
66#include <signal.h>
67#endif
68
69/* #ifdef HAVE_GETOPT_H */
70#include <getopt.h>
71/* #endif */
72
73#include <ctype.h>
74
75
76/*
77 *
78 * Missing Functions
79 *
80 */
81
82#ifndef HAVE_STRTOL
83# define strtol(a,b,c) atol((a))
84#endif
85
86#ifndef HAVE_STRTOUL
87# define strtoul(a,b,c) (unsigned long)atol((a))
88#endif
89
90/*
91 *
92 * Standard Values
93 *
94 */
95
96#define OK 0
97#define ERROR -1
98
99#define TRUE 1
100#define FALSE 0
101
102#define STATE_CRITICAL 2 /* service state return codes */
103#define STATE_WARNING 1
104#define STATE_OK 0
105#define STATE_UNKNOWN -1
106#define STATE_DEPENDENT -2
107
108#define DEFAULT_SOCKET_TIMEOUT 10 /* timeout after 10 seconds */
109
110#define MAX_INPUT_BUFFER 1024 /* max size of most buffers we use */
111
112#define MAX_HOST_ADDRESS_LENGTH 256 /* max size of a host address */
113
114
115#ifndef HAVE_SNPRINTF
116/*
117int snprintf (char *str, size_t n, const char *fmt, ...);
118int snprintf (char *str, size_t n, const char *fmt, ...)
119{
120 char *buf;
121 int i;
122 int j=0;
123 va_list ap;
124 int d;
125 char c, *p, *s;
126
127 if((buf=malloc(n))==NULL){
128 puts("could not malloc snprintf buffer\n");
129 exit(-1);
130 }
131 va_start(ap,fmt);
132 i=strlen(fmt);
133 while((jj=index(&fmt[j],'%'))){
134 j+=jj+1;
135 switch fmt[j]
136 {
137 case 's':
138 s = va_arg(ap, char *);
139 i+=strlen(s);
140 break;
141 case 'd':
142 d = va_arg(ap, int);
143 i++;
144 if (d<0) i++;
145 while((d=d/10)>0) i++;
146 break;
147 case 'c':
148 c = va_arg(ap, char);
149 i++;
150 break;
151 }
152 }
153 va_end(ap);
154 vsprintf(buf,fmt,ap);
155 strcpy(str,buf[1:n-1]);
156 exit(result);
157}
158*/
159#endif
diff --git a/plugins/getopt.c b/plugins/getopt.c
new file mode 100644
index 00000000..364a1459
--- /dev/null
+++ b/plugins/getopt.c
@@ -0,0 +1,724 @@
1/* Getopt for GNU.
2 NOTE: getopt is now part of the C library, so if you don't know what
3 "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
4 before changing it!
5
6 Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95
7 Free Software Foundation, Inc.
8
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
24 Ditto for AIX 3.2 and <stdlib.h>. */
25#ifndef _NO_PROTO
26#define _NO_PROTO
27#endif
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32
33#if !defined (__STDC__) || !__STDC__
34/* This is a separate conditional since some stdc systems
35 reject `defined (const)'. */
36#ifndef const
37#define const
38#endif
39#endif
40
41#include <stdio.h>
42
43/* Comment out all this code if we are using the GNU C Library, and are not
44 actually compiling the library itself. This code is part of the GNU C
45 Library, but also included in many other GNU distributions. Compiling
46 and linking in this code is a waste when using the GNU C library
47 (especially if it is a shared library). Rather than having every GNU
48 program understand `configure --with-gnu-libc' and omit the object files,
49 it is simpler to just do this in the source for each such file. */
50
51#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
52
53
54/* This needs to come after some library #include
55 to get __GNU_LIBRARY__ defined. */
56#ifdef __GNU_LIBRARY__
57/* Don't include stdlib.h for non-GNU C libraries because some of them
58 contain conflicting prototypes for getopt. */
59#include <stdlib.h>
60#endif /* GNU C library. */
61
62#ifndef _
63/* This is for other GNU distributions with internationalized messages.
64 When compiling libc, the _ macro is predefined. */
65#ifdef HAVE_LIBINTL_H
66# include <libintl.h>
67# define _(msgid) gettext (msgid)
68#else
69# define _(msgid) (msgid)
70#endif
71#endif
72
73/* This version of `getopt' appears to the caller like standard Unix `getopt'
74 but it behaves differently for the user, since it allows the user
75 to intersperse the options with the other arguments.
76
77 As `getopt' works, it permutes the elements of ARGV so that,
78 when it is done, all the options precede everything else. Thus
79 all application programs are extended to handle flexible argument order.
80
81 Setting the environment variable POSIXLY_CORRECT disables permutation.
82 Then the behavior is completely standard.
83
84 GNU application programs can use a third alternative mode in which
85 they can distinguish the relative order of options and other arguments. */
86
87#include "getopt.h"
88
89/* For communication from `getopt' to the caller.
90 When `getopt' finds an option that takes an argument,
91 the argument value is returned here.
92 Also, when `ordering' is RETURN_IN_ORDER,
93 each non-option ARGV-element is returned here. */
94
95char *optarg = NULL;
96
97/* Index in ARGV of the next element to be scanned.
98 This is used for communication to and from the caller
99 and for communication between successive calls to `getopt'.
100
101 On entry to `getopt', zero means this is the first call; initialize.
102
103 When `getopt' returns EOF, this is the index of the first of the
104 non-option elements that the caller should itself scan.
105
106 Otherwise, `optind' communicates from one call to the next
107 how much of ARGV has been scanned so far. */
108
109/* XXX 1003.2 says this must be 1 before any call. */
110int optind = 0;
111
112/* The next char to be scanned in the option-element
113 in which the last option character we returned was found.
114 This allows us to pick up the scan where we left off.
115
116 If this is zero, or a null string, it means resume the scan
117 by advancing to the next ARGV-element. */
118
119static char *nextchar;
120
121/* Callers store zero here to inhibit the error message
122 for unrecognized options. */
123
124int opterr = 1;
125
126/* Set to an option character which was unrecognized.
127 This must be initialized on some systems to avoid linking in the
128 system's own getopt implementation. */
129
130int optopt = '?';
131
132/* Describe how to deal with options that follow non-option ARGV-elements.
133
134 If the caller did not specify anything,
135 the default is REQUIRE_ORDER if the environment variable
136 POSIXLY_CORRECT is defined, PERMUTE otherwise.
137
138 REQUIRE_ORDER means don't recognize them as options;
139 stop option processing when the first non-option is seen.
140 This is what Unix does.
141 This mode of operation is selected by either setting the environment
142 variable POSIXLY_CORRECT, or using `+' as the first character
143 of the list of option characters.
144
145 PERMUTE is the default. We permute the contents of ARGV as we scan,
146 so that eventually all the non-options are at the end. This allows options
147 to be given in any order, even with programs that were not written to
148 expect this.
149
150 RETURN_IN_ORDER is an option available to programs that were written
151 to expect options and other ARGV-elements in any order and that care about
152 the ordering of the two. We describe each non-option ARGV-element
153 as if it were the argument of an option with character code 1.
154 Using `-' as the first character of the list of option characters
155 selects this mode of operation.
156
157 The special argument `--' forces an end of option-scanning regardless
158 of the value of `ordering'. In the case of RETURN_IN_ORDER, only
159 `--' can cause `getopt' to return EOF with `optind' != ARGC. */
160
161static enum
162{
163 REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
164}
165ordering;
166
167/* Value of POSIXLY_CORRECT environment variable. */
168static char *posixly_correct;
169
170#ifdef __GNU_LIBRARY__
171/* We want to avoid inclusion of string.h with non-GNU libraries
172 because there are many ways it can cause trouble.
173 On some systems, it contains special magic macros that don't work
174 in GCC. */
175#include <string.h>
176#define my_index strchr
177#else
178
179/* Avoid depending on library functions or files
180 whose names are inconsistent. */
181
182char *getenv ();
183
184static char *
185my_index (str, chr)
186 const char *str;
187 int chr;
188{
189 while (*str) {
190 if (*str == chr)
191 return (char *) str;
192 str++;
193 }
194 return 0;
195}
196
197/* If using GCC, we can safely declare strlen this way.
198 If not using GCC, it is ok not to declare it. */
199#ifdef __GNUC__
200/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
201 That was relevant to code that was here before. */
202#if !defined (__STDC__) || !__STDC__
203/* gcc with -traditional declares the built-in strlen to return int,
204 and has done so at least since version 2.4.5. -- rms. */
205extern int strlen (const char *);
206#endif /* not __STDC__ */
207#endif /* __GNUC__ */
208
209#endif /* not __GNU_LIBRARY__ */
210
211/* Handle permutation of arguments. */
212
213/* Describe the part of ARGV that contains non-options that have
214 been skipped. `first_nonopt' is the index in ARGV of the first of them;
215 `last_nonopt' is the index after the last of them. */
216
217static int first_nonopt;
218static int last_nonopt;
219
220/* Exchange two adjacent subsequences of ARGV.
221 One subsequence is elements [first_nonopt,last_nonopt)
222 which contains all the non-options that have been skipped so far.
223 The other is elements [last_nonopt,optind), which contains all
224 the options processed since those non-options were skipped.
225
226 `first_nonopt' and `last_nonopt' are relocated so that they describe
227 the new indices of the non-options in ARGV after they are moved. */
228
229static void
230exchange (argv)
231 char **argv;
232{
233 int bottom = first_nonopt;
234 int middle = last_nonopt;
235 int top = optind;
236 char *tem;
237
238 /* Exchange the shorter segment with the far end of the longer segment.
239 That puts the shorter segment into the right place.
240 It leaves the longer segment in the right place overall,
241 but it consists of two parts that need to be swapped next. */
242
243 while (top > middle && middle > bottom) {
244 if (top - middle > middle - bottom) {
245 /* Bottom segment is the short one. */
246 int len = middle - bottom;
247 register int i;
248
249 /* Swap it with the top part of the top segment. */
250 for (i = 0; i < len; i++) {
251 tem = argv[bottom + i];
252 argv[bottom + i] = argv[top - (middle - bottom) + i];
253 argv[top - (middle - bottom) + i] = tem;
254 }
255 /* Exclude the moved bottom segment from further swapping. */
256 top -= len;
257 }
258 else {
259 /* Top segment is the short one. */
260 int len = top - middle;
261 register int i;
262
263 /* Swap it with the bottom part of the bottom segment. */
264 for (i = 0; i < len; i++) {
265 tem = argv[bottom + i];
266 argv[bottom + i] = argv[middle + i];
267 argv[middle + i] = tem;
268 }
269 /* Exclude the moved top segment from further swapping. */
270 bottom += len;
271 }
272 }
273
274 /* Update records for the slots the non-options now occupy. */
275
276 first_nonopt += (optind - last_nonopt);
277 last_nonopt = optind;
278}
279
280/* Initialize the internal data when the first call is made. */
281
282static const char *
283_getopt_initialize (optstring)
284 const char *optstring;
285{
286 /* Start processing options with ARGV-element 1 (since ARGV-element 0
287 is the program name); the sequence of previously skipped
288 non-option ARGV-elements is empty. */
289
290 first_nonopt = last_nonopt = optind = 1;
291
292 nextchar = NULL;
293
294 posixly_correct = getenv ("POSIXLY_CORRECT");
295
296 /* Determine how to handle the ordering of options and nonoptions. */
297
298 if (optstring[0] == '-') {
299 ordering = RETURN_IN_ORDER;
300 ++optstring;
301 }
302 else if (optstring[0] == '+') {
303 ordering = REQUIRE_ORDER;
304 ++optstring;
305 }
306 else if (posixly_correct != NULL)
307 ordering = REQUIRE_ORDER;
308 else
309 ordering = PERMUTE;
310
311 return optstring;
312}
313
314/* Scan elements of ARGV (whose length is ARGC) for option characters
315 given in OPTSTRING.
316
317 If an element of ARGV starts with '-', and is not exactly "-" or "--",
318 then it is an option element. The characters of this element
319 (aside from the initial '-') are option characters. If `getopt'
320 is called repeatedly, it returns successively each of the option characters
321 from each of the option elements.
322
323 If `getopt' finds another option character, it returns that character,
324 updating `optind' and `nextchar' so that the next call to `getopt' can
325 resume the scan with the following option character or ARGV-element.
326
327 If there are no more option characters, `getopt' returns `EOF'.
328 Then `optind' is the index in ARGV of the first ARGV-element
329 that is not an option. (The ARGV-elements have been permuted
330 so that those that are not options now come last.)
331
332 OPTSTRING is a string containing the legitimate option characters.
333 If an option character is seen that is not listed in OPTSTRING,
334 return '?' after printing an error message. If you set `opterr' to
335 zero, the error message is suppressed but we still return '?'.
336
337 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
338 so the following text in the same ARGV-element, or the text of the following
339 ARGV-element, is returned in `optarg'. Two colons mean an option that
340 wants an optional arg; if there is text in the current ARGV-element,
341 it is returned in `optarg', otherwise `optarg' is set to zero.
342
343 If OPTSTRING starts with `-' or `+', it requests different methods of
344 handling the non-option ARGV-elements.
345 See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
346
347 Long-named options begin with `--' instead of `-'.
348 Their names may be abbreviated as long as the abbreviation is unique
349 or is an exact match for some defined option. If they have an
350 argument, it follows the option name in the same ARGV-element, separated
351 from the option name by a `=', or else the in next ARGV-element.
352 When `getopt' finds a long-named option, it returns 0 if that option's
353 `flag' field is nonzero, the value of the option's `val' field
354 if the `flag' field is zero.
355
356 The elements of ARGV aren't really const, because we permute them.
357 But we pretend they're const in the prototype to be compatible
358 with other systems.
359
360 LONGOPTS is a vector of `struct option' terminated by an
361 element containing a name which is zero.
362
363 LONGIND returns the index in LONGOPT of the long-named option found.
364 It is only valid when a long-named option has been found by the most
365 recent call.
366
367 If LONG_ONLY is nonzero, '-' as well as '--' can introduce
368 long-named options. */
369
370int
371_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
372 int argc;
373 char *const *argv;
374 const char *optstring;
375 const struct option *longopts;
376 int *longind;
377 int long_only;
378{
379 optarg = NULL;
380
381 if (optind == 0) {
382 optstring = _getopt_initialize (optstring);
383 optind = 1; /* Don't scan ARGV[0], the program name. */
384 }
385
386 if (nextchar == NULL || *nextchar == '\0') {
387 /* Advance to the next ARGV-element. */
388
389 if (ordering == PERMUTE) {
390 /* If we have just processed some options following some non-options,
391 exchange them so that the options come first. */
392
393 if (first_nonopt != last_nonopt && last_nonopt != optind)
394 exchange ((char **) argv);
395 else if (last_nonopt != optind)
396 first_nonopt = optind;
397
398 /* Skip any additional non-options
399 and extend the range of non-options previously skipped. */
400
401 while (optind < argc
402 && (argv[optind][0] != '-' || argv[optind][1] == '\0')) optind++;
403 last_nonopt = optind;
404 }
405
406 /* The special ARGV-element `--' means premature end of options.
407 Skip it like a null option,
408 then exchange with previous non-options as if it were an option,
409 then skip everything else like a non-option. */
410
411 if (optind != argc && !strcmp (argv[optind], "--")) {
412 optind++;
413
414 if (first_nonopt != last_nonopt && last_nonopt != optind)
415 exchange ((char **) argv);
416 else if (first_nonopt == last_nonopt)
417 first_nonopt = optind;
418 last_nonopt = argc;
419
420 optind = argc;
421 }
422
423 /* If we have done all the ARGV-elements, stop the scan
424 and back over any non-options that we skipped and permuted. */
425
426 if (optind == argc) {
427 /* Set the next-arg-index to point at the non-options
428 that we previously skipped, so the caller will digest them. */
429 if (first_nonopt != last_nonopt)
430 optind = first_nonopt;
431 return EOF;
432 }
433
434 /* If we have come to a non-option and did not permute it,
435 either stop the scan or describe it to the caller and pass it by. */
436
437 if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) {
438 if (ordering == REQUIRE_ORDER)
439 return EOF;
440 optarg = argv[optind++];
441 return 1;
442 }
443
444 /* We have found another option-ARGV-element.
445 Skip the initial punctuation. */
446
447 nextchar = (argv[optind] + 1
448 + (longopts != NULL && argv[optind][1] == '-'));
449 }
450
451 /* Decode the current option-ARGV-element. */
452
453 /* Check whether the ARGV-element is a long option.
454
455 If long_only and the ARGV-element has the form "-f", where f is
456 a valid short option, don't consider it an abbreviated form of
457 a long option that starts with f. Otherwise there would be no
458 way to give the -f short option.
459
460 On the other hand, if there's a long option "fubar" and
461 the ARGV-element is "-fu", do consider that an abbreviation of
462 the long option, just like "--fu", and not "-f" with arg "u".
463
464 This distinction seems to be the most useful approach. */
465
466 if (longopts != NULL
467 && (argv[optind][1] == '-'
468 || (long_only
469 && (argv[optind][2]
470 || !my_index (optstring, argv[optind][1]))))) {
471 char *nameend;
472 const struct option *p;
473 const struct option *pfound = NULL;
474 int exact = 0;
475 int ambig = 0;
476 int indfound;
477 int option_index;
478
479 for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
480 /* Do nothing. */ ;
481
482 /* Test all long options for either exact match
483 or abbreviated matches. */
484 for (p = longopts, option_index = 0; p->name; p++, option_index++)
485 if (!strncmp (p->name, nextchar, nameend - nextchar)) {
486 if (nameend - nextchar == strlen (p->name)) {
487 /* Exact match found. */
488 pfound = p;
489 indfound = option_index;
490 exact = 1;
491 break;
492 }
493 else if (pfound == NULL) {
494 /* First nonexact match found. */
495 pfound = p;
496 indfound = option_index;
497 }
498 else
499 /* Second or later nonexact match found. */
500 ambig = 1;
501 }
502
503 if (ambig && !exact) {
504 if (opterr)
505 fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
506 argv[0], argv[optind]);
507 nextchar += strlen (nextchar);
508 optind++;
509 return '?';
510 }
511
512 if (pfound != NULL) {
513 option_index = indfound;
514 optind++;
515 if (*nameend) {
516 /* Don't test has_arg with >, because some C compilers don't
517 allow it to be used on enums. */
518 if (pfound->has_arg)
519 optarg = nameend + 1;
520 else {
521 if (opterr)
522 if (argv[optind - 1][1] == '-')
523 /* --option */
524 fprintf (stderr,
525 _("%s: option `--%s' doesn't allow an argument\n"),
526 argv[0], pfound->name);
527 else
528 /* +option or -option */
529 fprintf (stderr,
530 _("%s: option `%c%s' doesn't allow an argument\n"),
531 argv[0], argv[optind - 1][0], pfound->name);
532
533 nextchar += strlen (nextchar);
534 return '?';
535 }
536 }
537 else if (pfound->has_arg == 1) {
538 if (optind < argc)
539 optarg = argv[optind++];
540 else {
541 if (opterr)
542 fprintf (stderr,
543 _("%s: option `%s' requires an argument\n"),
544 argv[0], argv[optind - 1]);
545 nextchar += strlen (nextchar);
546 return optstring[0] == ':' ? ':' : '?';
547 }
548 }
549 nextchar += strlen (nextchar);
550 if (longind != NULL)
551 *longind = option_index;
552 if (pfound->flag) {
553 *(pfound->flag) = pfound->val;
554 return 0;
555 }
556 return pfound->val;
557 }
558
559 /* Can't find it as a long option. If this is not getopt_long_only,
560 or the option starts with '--' or is not a valid short
561 option, then it's an error.
562 Otherwise interpret it as a short option. */
563 if (!long_only || argv[optind][1] == '-'
564 || my_index (optstring, *nextchar) == NULL) {
565 if (opterr) {
566 if (argv[optind][1] == '-')
567 /* --option */
568 fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
569 argv[0], nextchar);
570 else
571 /* +option or -option */
572 fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
573 argv[0], argv[optind][0], nextchar);
574 }
575 nextchar = (char *) "";
576 optind++;
577 return '?';
578 }
579 }
580
581 /* Look at and handle the next short option-character. */
582
583 {
584 char c = *nextchar++;
585 char *temp = my_index (optstring, c);
586
587 /* Increment `optind' when we start to process its last character. */
588 if (*nextchar == '\0')
589 ++optind;
590
591 if (temp == NULL || c == ':') {
592 if (opterr) {
593 if (posixly_correct)
594 /* 1003.2 specifies the format of this message. */
595 fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
596 else
597 fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
598 }
599 optopt = c;
600 return '?';
601 }
602 if (temp[1] == ':') {
603 if (temp[2] == ':') {
604 /* This is an option that accepts an argument optionally. */
605 if (*nextchar != '\0') {
606 optarg = nextchar;
607 optind++;
608 }
609 else
610 optarg = NULL;
611 nextchar = NULL;
612 }
613 else {
614 /* This is an option that requires an argument. */
615 if (*nextchar != '\0') {
616 optarg = nextchar;
617 /* If we end this ARGV-element by taking the rest as an arg,
618 we must advance to the next element now. */
619 optind++;
620 }
621 else if (optind == argc) {
622 if (opterr) {
623 /* 1003.2 specifies the format of this message. */
624 fprintf (stderr,
625 _("%s: option requires an argument -- %c\n"),
626 argv[0], c);
627 }
628 optopt = c;
629 if (optstring[0] == ':')
630 c = ':';
631 else
632 c = '?';
633 }
634 else
635 /* We already incremented `optind' once;
636 increment it again when taking next ARGV-elt as argument. */
637 optarg = argv[optind++];
638 nextchar = NULL;
639 }
640 }
641 return c;
642 }
643}
644
645int
646getopt (argc, argv, optstring)
647 int argc;
648 char *const *argv;
649 const char *optstring;
650{
651 return _getopt_internal (argc, argv, optstring,
652 (const struct option *) 0, (int *) 0, 0);
653}
654
655#endif /* _LIBC or not __GNU_LIBRARY__. */
656
657#ifdef TEST
658
659/* Compile with -DTEST to make an executable for use in testing
660 the above definition of `getopt'. */
661
662int
663main (argc, argv)
664 int argc;
665 char **argv;
666{
667 int c;
668 int digit_optind = 0;
669
670 while (1) {
671 int this_option_optind = optind ? optind : 1;
672
673 c = getopt (argc, argv, "abc:d:0123456789");
674 if (c == EOF)
675 break;
676
677 switch (c) {
678 case '0':
679 case '1':
680 case '2':
681 case '3':
682 case '4':
683 case '5':
684 case '6':
685 case '7':
686 case '8':
687 case '9':
688 if (digit_optind != 0 && digit_optind != this_option_optind)
689 printf ("digits occur in two different argv-elements.\n");
690 digit_optind = this_option_optind;
691 printf ("option %c\n", c);
692 break;
693
694 case 'a':
695 printf ("option a\n");
696 break;
697
698 case 'b':
699 printf ("option b\n");
700 break;
701
702 case 'c':
703 printf ("option c with value `%s'\n", optarg);
704 break;
705
706 case '?':
707 break;
708
709 default:
710 printf ("?? getopt returned character code 0%o ??\n", c);
711 }
712 }
713
714 if (optind < argc) {
715 printf ("non-option ARGV-elements: ");
716 while (optind < argc)
717 printf ("%s ", argv[optind++]);
718 printf ("\n");
719 }
720
721 exit (0);
722}
723
724#endif /* TEST */
diff --git a/plugins/getopt1.c b/plugins/getopt1.c
new file mode 100644
index 00000000..bbac373b
--- /dev/null
+++ b/plugins/getopt1.c
@@ -0,0 +1,176 @@
1/* getopt_long and getopt_long_only entry points for GNU getopt.
2 Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994
3 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18
19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
23#include "getopt.h"
24
25#if !defined (__STDC__) || !__STDC__
26/* This is a separate conditional since some stdc systems
27 reject `defined (const)'. */
28#ifndef const
29#define const
30#endif
31#endif
32
33#include <stdio.h>
34
35/* Comment out all this code if we are using the GNU C Library, and are not
36 actually compiling the library itself. This code is part of the GNU C
37 Library, but also included in many other GNU distributions. Compiling
38 and linking in this code is a waste when using the GNU C library
39 (especially if it is a shared library). Rather than having every GNU
40 program understand `configure --with-gnu-libc' and omit the object files,
41 it is simpler to just do this in the source for each such file. */
42
43#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
44
45
46/* This needs to come after some library #include
47 to get __GNU_LIBRARY__ defined. */
48#ifdef __GNU_LIBRARY__
49#include <stdlib.h>
50#else
51char *getenv ();
52#endif
53
54#ifndef NULL
55#define NULL 0
56#endif
57
58int
59getopt_long (argc, argv, options, long_options, opt_index)
60 int argc;
61 char *const *argv;
62 const char *options;
63 const struct option *long_options;
64 int *opt_index;
65{
66 return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
67}
68
69/* Like getopt_long, but '-' as well as '--' can indicate a long option.
70 If an option that starts with '-' (not '--') doesn't match a long option,
71 but does match a short option, it is parsed as a short option
72 instead. */
73
74int
75getopt_long_only (argc, argv, options, long_options, opt_index)
76 int argc;
77 char *const *argv;
78 const char *options;
79 const struct option *long_options;
80 int *opt_index;
81{
82 return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
83}
84
85
86#endif /* _LIBC or not __GNU_LIBRARY__. */
87
88#ifdef TEST
89
90#include <stdio.h>
91
92int
93main (argc, argv)
94 int argc;
95 char **argv;
96{
97 int c;
98 int digit_optind = 0;
99
100 while (1) {
101 int this_option_optind = optind ? optind : 1;
102 int option_index = 0;
103 static struct option long_options[] = {
104 {"add", 1, 0, 0},
105 {"append", 0, 0, 0},
106 {"delete", 1, 0, 0},
107 {"verbose", 0, 0, 0},
108 {"create", 0, 0, 0},
109 {"file", 1, 0, 0},
110 {0, 0, 0, 0}
111 };
112
113 c = getopt_long (argc, argv, "abc:d:0123456789",
114 long_options, &option_index);
115 if (c == EOF)
116 break;
117
118 switch (c) {
119 case 0:
120 printf ("option %s", long_options[option_index].name);
121 if (optarg)
122 printf (" with arg %s", optarg);
123 printf ("\n");
124 break;
125
126 case '0':
127 case '1':
128 case '2':
129 case '3':
130 case '4':
131 case '5':
132 case '6':
133 case '7':
134 case '8':
135 case '9':
136 if (digit_optind != 0 && digit_optind != this_option_optind)
137 printf ("digits occur in two different argv-elements.\n");
138 digit_optind = this_option_optind;
139 printf ("option %c\n", c);
140 break;
141
142 case 'a':
143 printf ("option a\n");
144 break;
145
146 case 'b':
147 printf ("option b\n");
148 break;
149
150 case 'c':
151 printf ("option c with value `%s'\n", optarg);
152 break;
153
154 case 'd':
155 printf ("option d with value `%s'\n", optarg);
156 break;
157
158 case '?':
159 break;
160
161 default:
162 printf ("?? getopt returned character code 0%o ??\n", c);
163 }
164 }
165
166 if (optind < argc) {
167 printf ("non-option ARGV-elements: ");
168 while (optind < argc)
169 printf ("%s ", argv[optind++]);
170 printf ("\n");
171 }
172
173 exit (0);
174}
175
176#endif /* TEST */
diff --git a/plugins/netutils.c b/plugins/netutils.c
new file mode 100644
index 00000000..e5d35281
--- /dev/null
+++ b/plugins/netutils.c
@@ -0,0 +1,431 @@
1/****************************************************************************
2*
3* Nagios plugins network utilities
4*
5* License: GPL
6* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
7*
8* Last Modified: $Date$
9*
10* Description:
11*
12* This file contains commons functions used in many of the plugins.
13*
14* License Information:
15*
16* This program is free software; you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by
18* the Free Software Foundation; either version 2 of the License, or
19* (at your option) any later version.
20*
21* This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details.
25*
26* You should have received a copy of the GNU General Public License
27* along with this program; if not, write to the Free Software
28* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29*
30****************************************************************************/
31
32#include "config.h"
33#include "common.h"
34#include <sys/socket.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37#include <netdb.h>
38
39extern int socket_timeout;
40RETSIGTYPE socket_timeout_alarm_handler (int);
41
42int process_tcp_request2 (char *, int, char *, char *, int);
43int process_tcp_request (char *, int, char *, char *, int);
44int process_udp_request (char *, int, char *, char *, int);
45int process_request (char *, int, char *, char *, char *, int);
46
47int my_tcp_connect (char *, int, int *);
48int my_udp_connect (char *, int, int *);
49int my_connect (char *, int, int *, char *);
50
51int my_inet_aton (register const char *, struct in_addr *);
52
53/* handles socket timeouts */
54void
55socket_timeout_alarm_handler (int sig)
56{
57
58 printf ("Socket timeout after %d seconds\n", socket_timeout);
59
60 exit (STATE_CRITICAL);
61}
62
63
64/* connects to a host on a specified TCP port, sends a string,
65 and gets a response */
66int
67process_tcp_request (char *server_address,
68 int server_port,
69 char *send_buffer, char *recv_buffer, int recv_size)
70{
71 int result;
72 char proto[4] = "tcp";
73
74 result = process_request (server_address,
75 server_port,
76 proto, send_buffer, recv_buffer, recv_size);
77
78 return result;
79}
80
81
82/* connects to a host on a specified UDP port, sends a string, and gets a
83 response */
84int
85process_udp_request (char *server_address,
86 int server_port,
87 char *send_buffer, char *recv_buffer, int recv_size)
88{
89 int result;
90 char proto[4] = "udp";
91
92 result = process_request (server_address,
93 server_port,
94 proto, send_buffer, recv_buffer, recv_size);
95
96 return result;
97}
98
99
100
101/* connects to a host on a specified tcp port, sends a string, and gets a
102 response. loops on select-recv until timeout or eof to get all of a
103 multi-packet answer */
104int
105process_tcp_request2 (char *server_address,
106 int server_port,
107 char *send_buffer, char *recv_buffer, int recv_size)
108{
109
110 int result;
111 int send_result;
112 int recv_result;
113 int sd;
114 struct timeval tv;
115 fd_set readfds;
116 int recv_length = 0;
117
118 result = my_connect (server_address, server_port, &sd, "tcp");
119 if (result != STATE_OK)
120 return STATE_CRITICAL;
121
122 send_result = send (sd, send_buffer, strlen (send_buffer), 0);
123 if (send_result != strlen (send_buffer)) {
124 printf ("send() failed\n");
125 result = STATE_WARNING;
126 }
127
128 while (1) {
129 /* wait up to the number of seconds for socket timeout
130 minus one for data from the host */
131 tv.tv_sec = socket_timeout - 1;
132 tv.tv_usec = 0;
133 FD_ZERO (&readfds);
134 FD_SET (sd, &readfds);
135 select (sd + 1, &readfds, NULL, NULL, &tv);
136
137 /* make sure some data has arrived */
138 if (!FD_ISSET (sd, &readfds)) { /* it hasn't */
139 if (!recv_length) {
140 strcpy (recv_buffer, "");
141 printf ("No data was recieved from host!\n");
142 result = STATE_WARNING;
143 }
144 else { /* this one failed, but previous ones worked */
145 recv_buffer[recv_length] = 0;
146 }
147 break;
148 }
149 else { /* it has */
150 recv_result =
151 recv (sd, recv_buffer + recv_length, recv_size - recv_length - 1, 0);
152 if (recv_result == -1) { /* recv failed, bail out */
153 strcpy (recv_buffer + recv_length, "");
154 result = STATE_WARNING;
155 break;
156 }
157 else if (recv_result == 0) { /* end of file ? */
158 recv_buffer[recv_length] = 0;
159 break;
160 }
161 else { /* we got data! */
162 recv_length += recv_result;
163 if (recv_length >= recv_size - 1) { /* buffer full, we're done */
164 recv_buffer[recv_size - 1] = 0;
165 break;
166 }
167 }
168 } /* end if(!FD_ISSET(sd,&readfds)) */
169 } /* end while(1) */
170
171 close (sd);
172 return result;
173}
174
175/* connects to a host on a specified port, sends a string, and gets a
176 response */
177int
178process_request (char *server_address,
179 int server_port,
180 char *proto,
181 char *send_buffer, char *recv_buffer, int recv_size)
182{
183 int result;
184 int send_result;
185 int recv_result;
186 int sd;
187 struct timeval tv;
188 fd_set readfds;
189
190 result = STATE_OK;
191
192 result = my_connect (server_address, server_port, &sd, proto);
193 if (result != STATE_OK)
194 return STATE_CRITICAL;
195
196 send_result = send (sd, send_buffer, strlen (send_buffer), 0);
197 if (send_result != strlen (send_buffer)) {
198 printf ("send() failed\n");
199 result = STATE_WARNING;
200 }
201
202 /* wait up to the number of seconds for socket timeout minus one
203 for data from the host */
204 tv.tv_sec = socket_timeout - 1;
205 tv.tv_usec = 0;
206 FD_ZERO (&readfds);
207 FD_SET (sd, &readfds);
208 select (sd + 1, &readfds, NULL, NULL, &tv);
209
210 /* make sure some data has arrived */
211 if (!FD_ISSET (sd, &readfds)) {
212 strcpy (recv_buffer, "");
213 printf ("No data was recieved from host!\n");
214 result = STATE_WARNING;
215 }
216
217 else {
218 recv_result = recv (sd, recv_buffer, recv_size - 1, 0);
219 if (recv_result == -1) {
220 strcpy (recv_buffer, "");
221 if (!strcmp (proto, "tcp"))
222 printf ("recv() failed\n");
223 result = STATE_WARNING;
224 }
225 else
226 recv_buffer[recv_result] = 0;
227
228 /* terminate returned string */
229 recv_buffer[recv_size - 1] = 0;
230 }
231
232 close (sd);
233
234 return result;
235}
236
237
238/* opens a connection to a remote host/tcp port */
239int
240my_tcp_connect (char *host_name, int port, int *sd)
241{
242 int result;
243 char proto[4] = "tcp";
244
245 result = my_connect (host_name, port, sd, proto);
246
247 return result;
248}
249
250
251/* opens a connection to a remote host/udp port */
252int
253my_udp_connect (char *host_name, int port, int *sd)
254{
255 int result;
256 char proto[4] = "udp";
257
258 result = my_connect (host_name, port, sd, proto);
259
260 return result;
261}
262
263
264/* opens a tcp or udp connection to a remote host */
265int
266my_connect (char *host_name, int port, int *sd, char *proto)
267{
268 struct sockaddr_in servaddr;
269 struct hostent *hp;
270 struct protoent *ptrp;
271 int result;
272
273 bzero ((char *) &servaddr, sizeof (servaddr));
274 servaddr.sin_family = AF_INET;
275 servaddr.sin_port = htons (port);
276
277 /* try to bypass using a DNS lookup if this is just an IP address */
278 if (!my_inet_aton (host_name, &servaddr.sin_addr)) {
279
280 /* else do a DNS lookup */
281 hp = gethostbyname ((const char *) host_name);
282 if (hp == NULL) {
283 printf ("Invalid host name '%s'\n", host_name);
284 return STATE_UNKNOWN;
285 }
286
287 memcpy (&servaddr.sin_addr, hp->h_addr, hp->h_length);
288 }
289
290 /* map transport protocol name to protocol number */
291 if ((ptrp = getprotobyname (proto)) == NULL) {
292 printf ("Cannot map \"%s\" to protocol number\n", proto);
293 return STATE_UNKNOWN;
294 }
295
296 /* create a socket */
297 *sd =
298 socket (PF_INET, (!strcmp (proto, "udp")) ? SOCK_DGRAM : SOCK_STREAM,
299 ptrp->p_proto);
300 if (*sd < 0) {
301 printf ("Socket creation failed\n");
302 return STATE_UNKNOWN;
303 }
304
305 /* open a connection */
306 result = connect (*sd, (struct sockaddr *) &servaddr, sizeof (servaddr));
307 if (result < 0) {
308 switch (errno) {
309 case ECONNREFUSED:
310 printf ("Connection refused by host\n");
311 break;
312 case ETIMEDOUT:
313 printf ("Timeout while attempting connection\n");
314 break;
315 case ENETUNREACH:
316 printf ("Network is unreachable\n");
317 break;
318 default:
319 printf ("Connection refused or timed out\n");
320 }
321
322 return STATE_CRITICAL;
323 }
324
325 return STATE_OK;
326}
327
328
329
330/* This code was taken from Fyodor's nmap utility, which was originally
331 taken from the GLIBC 2.0.6 libraries because Solaris doesn't contain
332 the inet_aton() funtion. */
333int
334my_inet_aton (register const char *cp, struct in_addr *addr)
335{
336 register unsigned int val; /* changed from u_long --david */
337 register int base, n;
338 register char c;
339 u_int parts[4];
340 register u_int *pp = parts;
341
342 c = *cp;
343
344 for (;;) {
345
346 /*
347 * Collect number up to ``.''.
348 * Values are specified as for C:
349 * 0x=hex, 0=octal, isdigit=decimal.
350 */
351 if (!isdigit ((int) c))
352 return (0);
353 val = 0;
354 base = 10;
355
356 if (c == '0') {
357 c = *++cp;
358 if (c == 'x' || c == 'X')
359 base = 16, c = *++cp;
360 else
361 base = 8;
362 }
363
364 for (;;) {
365 if (isascii ((int) c) && isdigit ((int) c)) {
366 val = (val * base) + (c - '0');
367 c = *++cp;
368 }
369 else if (base == 16 && isascii ((int) c) && isxdigit ((int) c)) {
370 val = (val << 4) | (c + 10 - (islower ((int) c) ? 'a' : 'A'));
371 c = *++cp;
372 }
373 else
374 break;
375 }
376
377 if (c == '.') {
378
379 /*
380 * Internet format:
381 * a.b.c.d
382 * a.b.c (with c treated as 16 bits)
383 * a.b (with b treated as 24 bits)
384 */
385 if (pp >= parts + 3)
386 return (0);
387 *pp++ = val;
388 c = *++cp;
389 }
390 else
391 break;
392 }
393
394 /* Check for trailing characters */
395 if (c != '\0' && (!isascii ((int) c) || !isspace ((int) c)))
396 return (0);
397
398 /* Concoct the address according to the number of parts specified */
399 n = pp - parts + 1;
400 switch (n) {
401
402 case 0:
403 return (0); /* initial nondigit */
404
405 case 1: /* a -- 32 bits */
406 break;
407
408 case 2: /* a.b -- 8.24 bits */
409 if (val > 0xffffff)
410 return (0);
411 val |= parts[0] << 24;
412 break;
413
414 case 3: /* a.b.c -- 8.8.16 bits */
415 if (val > 0xffff)
416 return (0);
417 val |= (parts[0] << 24) | (parts[1] << 16);
418 break;
419
420 case 4: /* a.b.c.d -- 8.8.8.8 bits */
421 if (val > 0xff)
422 return (0);
423 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
424 break;
425 }
426
427 if (addr)
428 addr->s_addr = htonl (val);
429
430 return (1);
431}
diff --git a/plugins/netutils.h.in b/plugins/netutils.h.in
new file mode 100644
index 00000000..be4ae241
--- /dev/null
+++ b/plugins/netutils.h.in
@@ -0,0 +1,63 @@
1/******************************************************************************
2*
3* Nagios plugins net utilities include file
4*
5* License: GPL
6* Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
7*
8* Last Modified: $Date$
9*
10* Description:
11*
12* This file contains common include files and function definitions
13* used in many of the plugins.
14*
15* License Information:
16*
17* This program is free software; you can redistribute it and/or modify
18* it under the terms of the GNU General Public License as published by
19* the Free Software Foundation; either version 2 of the License, or
20* (at your option) any later version.
21*
22* This program is distributed in the hope that it will be useful,
23* but WITHOUT ANY WARRANTY; without even the implied warranty of
24* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25* GNU General Public License for more details.
26*
27* You should have received a copy of the GNU General Public License
28* along with this program; if not, write to the Free Software
29* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30*
31******************************************************************************/
32
33#undef STDC_HEADERS
34#undef HAVE_STRINGS_H
35#undef HAVE_STRING_H
36
37#include <sys/socket.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
40#include <netdb.h>
41
42void socket_timeout_alarm_handler (int);
43
44int process_tcp_request2 (char *address, int port, char *sbuffer,
45 char *rbuffer, int rsize);
46int process_tcp_request (char *address, int port, char *sbuffer,
47 char *rbuffer, int rsize);
48int process_udp_request (char *address, int port, char *sbuffer,
49 char *rbuffer, int rsize);
50int process_request (char *address, int port, char *proto, char *sbuffer,
51 char *rbuffer, int rsize);
52
53int my_tcp_connect (char *address, int port, int *sd);
54int my_udp_connect (char *address, int port, int *sd);
55int my_connect (char *address, int port, int *sd, char *proto);
56
57int my_inet_aton (register const char *cp, struct in_addr *addr);
58
59#ifndef DEFAULT_SOCKET_TIMEOUT
60#include "config.h"
61#include "common.h"
62#endif
63int socket_timeout = DEFAULT_SOCKET_TIMEOUT;
diff --git a/plugins/popen.c b/plugins/popen.c
new file mode 100644
index 00000000..cde3c764
--- /dev/null
+++ b/plugins/popen.c
@@ -0,0 +1,314 @@
1/******************************************************************************
2 * popen.c
3 *
4 * A safe alternative to popen
5 *
6 * Provides spopen and spclose
7
8FILE * spopen(const char *);
9int spclose(FILE *);
10
11 *
12 * Code taken with liitle modification from "Advanced Programming for the Unix
13 * Environment" by W. Richard Stevens
14 *
15 * This is considered safe in that no shell is spawned, and the environment and
16 * path passed to the exec'd program are esstially empty. (popen create a shell
17 * and passes the environment to it).
18 *
19 ******************************************************************************/
20
21#include <config.h>
22#include <common.h>
23
24/* extern so plugin has pid to kill exec'd process on timeouts */
25extern int timeout_interval;
26extern pid_t *childpid;
27extern int *child_stderr_array;
28extern FILE *child_process;
29
30FILE *spopen (const char *);
31int spclose (FILE *);
32RETSIGTYPE popen_timeout_alarm_handler (int);
33
34#include <stdarg.h> /* ANSI C header file */
35#include <fcntl.h>
36
37#include <limits.h>
38#include <sys/resource.h>
39
40#ifdef HAVE_SYS_WAIT_H
41#include <sys/wait.h>
42#endif
43
44#ifndef WEXITSTATUS
45# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
46#endif
47
48#ifndef WIFEXITED
49# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
50#endif
51
52/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
53#if defined(SIG_IGN) && !defined(SIG_ERR)
54#define SIG_ERR ((Sigfunc *)-1)
55#endif
56
57#define min(a,b) ((a) < (b) ? (a) : (b))
58#define max(a,b) ((a) > (b) ? (a) : (b))
59int open_max (void); /* {Prog openmax} */
60void err_sys (const char *, ...);
61char *rtrim (char *, const char *);
62
63/*int *childerr = NULL;*//* ptr to array allocated at run-time */
64/*extern pid_t *childpid = NULL; *//* ptr to array allocated at run-time */
65static int maxfd; /* from our open_max(), {Prog openmax} */
66
67FILE *
68spopen (const char *cmdstring)
69{
70 char *environ[] = { NULL };
71 char *cmd = NULL;
72 char **argv = NULL;
73 char *str;
74 int argc;
75
76 int i = 0, pfd[2], pfderr[2];
77 pid_t pid;
78
79#ifdef RLIMIT_CORE
80 /* do not leave core files */
81 struct rlimit limit;
82 getrlimit (RLIMIT_CORE, &limit);
83 limit.rlim_cur = 0;
84 setrlimit (RLIMIT_CORE, &limit);
85#endif
86
87 /* if no command was passed, return with no error */
88 if (cmdstring == NULL)
89 return (NULL);
90
91 /* make copy of command string so strtok() doesn't silently modify it */
92 /* (the calling program may want to access it later) */
93 cmd = malloc (strlen (cmdstring) + 1);
94 if (cmd == NULL)
95 return NULL;
96 strcpy (cmd, cmdstring);
97
98 /* This is not a shell, so we don't handle "???" */
99 if (strstr (cmdstring, "\""))
100 return NULL;
101
102 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
103 if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''"))
104 return NULL;
105
106 /* there cannot be more args than characters */
107 argc = strlen (cmdstring) + 1; /* add 1 for NULL termination */
108 argv = malloc (sizeof(char*)*argc);
109 if (argv == NULL) {
110 printf ("Could not malloc argv array in popen()\n");
111 return NULL;
112 }
113
114 /* loop to get arguments to command */
115 while (cmd) {
116 str = cmd;
117 str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
118
119 if (i >= argc - 2) {
120 printf ("You've got a big problem buddy! You need more args!!!\n");
121 return (NULL);
122 }
123
124 if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */
125 str++;
126 if (!strstr (str, "'"))
127 return NULL; /* balanced? */
128 cmd = 1 + strstr (str, "'");
129 str[strcspn (str, "'")] = 0;
130 }
131 else {
132 if (strpbrk (str, " \t\r\n")) {
133 cmd = 1 + strpbrk (str, " \t\r\n");
134 str[strcspn (str, " \t\r\n")] = 0;
135 }
136 else {
137 cmd = NULL;
138 }
139 }
140
141 if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n"))
142 cmd = NULL;
143
144 argv[i++] = str;
145
146 }
147 argv[i] = NULL;
148
149 if (childpid == NULL) { /* first time through */
150 maxfd = open_max (); /* allocate zeroed out array for child pids */
151 if ((childpid = calloc (maxfd, sizeof (pid_t))) == NULL)
152 return (NULL);
153 }
154
155 if (child_stderr_array == NULL) { /* first time through */
156 maxfd = open_max (); /* allocate zeroed out array for child pids */
157 if ((child_stderr_array = calloc (maxfd, sizeof (int))) == NULL)
158 return (NULL);
159 }
160
161 if (pipe (pfd) < 0)
162 return (NULL); /* errno set by pipe() */
163
164 if (pipe (pfderr) < 0)
165 return (NULL); /* errno set by pipe() */
166
167 if ((pid = fork ()) < 0)
168 return (NULL); /* errno set by fork() */
169 else if (pid == 0) { /* child */
170 close (pfd[0]);
171 if (pfd[1] != STDOUT_FILENO) {
172 dup2 (pfd[1], STDOUT_FILENO);
173 close (pfd[1]);
174 }
175 close (pfderr[0]);
176 if (pfderr[1] != STDERR_FILENO) {
177 dup2 (pfderr[1], STDERR_FILENO);
178 close (pfderr[1]);
179 }
180 /* close all descriptors in childpid[] */
181 for (i = 0; i < maxfd; i++)
182 if (childpid[i] > 0)
183 close (i);
184
185 execve (argv[0], argv, environ);
186 _exit (0);
187 }
188
189 close (pfd[1]); /* parent */
190 if ((child_process = fdopen (pfd[0], "r")) == NULL)
191 return (NULL);
192 close (pfderr[1]);
193
194 childpid[fileno (child_process)] = pid; /* remember child pid for this fd */
195 child_stderr_array[fileno (child_process)] = pfderr[0]; /* remember STDERR */
196 return (child_process);
197}
198
199int
200spclose (FILE * fp)
201{
202 int fd, stat;
203 pid_t pid;
204
205 if (childpid == NULL)
206 return (-1); /* popen() has never been called */
207
208 fd = fileno (fp);
209 if ((pid = childpid[fd]) == 0)
210 return (-1); /* fp wasn't opened by popen() */
211
212 childpid[fd] = 0;
213 if (fclose (fp) == EOF)
214 return (-1);
215
216 while (waitpid (pid, &stat, 0) < 0)
217 if (errno != EINTR)
218 return (-1); /* error other than EINTR from waitpid() */
219
220 if (WIFEXITED (stat))
221 return (WEXITSTATUS (stat)); /* return child's termination status */
222
223 return (STATE_UNKNOWN);
224}
225
226#ifdef OPEN_MAX
227static int openmax = OPEN_MAX;
228#else
229static int openmax = 0;
230#endif
231
232#define OPEN_MAX_GUESS 256 /* if OPEN_MAX is indeterminate */
233 /* no guarantee this is adequate */
234
235void
236popen_timeout_alarm_handler (int signo)
237{
238 if (signo == SIGALRM) {
239 kill (childpid[fileno (child_process)], SIGKILL);
240 printf ("CRITICAL - Plugin timed out after %d seconds\n",
241 timeout_interval);
242 exit (STATE_CRITICAL);
243 }
244}
245
246int
247open_max (void)
248{
249 if (openmax == 0) { /* first time through */
250 errno = 0;
251 if ((openmax = sysconf (_SC_OPEN_MAX)) < 0) {
252 if (errno == 0)
253 openmax = OPEN_MAX_GUESS; /* it's indeterminate */
254 else
255 err_sys ("sysconf error for _SC_OPEN_MAX");
256 }
257 }
258 return (openmax);
259}
260
261
262static void err_doit (int, const char *, va_list);
263
264char *pname = NULL; /* caller can set this from argv[0] */
265
266/* Fatal error related to a system call.
267 * Print a message and terminate. */
268
269void
270err_sys (const char *fmt, ...)
271{
272 va_list ap;
273
274 va_start (ap, fmt);
275 err_doit (1, fmt, ap);
276 va_end (ap);
277 exit (1);
278}
279
280/* Print a message and return to caller.
281 * Caller specifies "errnoflag". */
282
283#define MAXLINE 2048
284static void
285err_doit (int errnoflag, const char *fmt, va_list ap)
286{
287 int errno_save;
288 char buf[MAXLINE];
289
290 errno_save = errno; /* value caller might want printed */
291 vsprintf (buf, fmt, ap);
292 if (errnoflag)
293 sprintf (buf + strlen (buf), ": %s", strerror (errno_save));
294 strcat (buf, "\n");
295 fflush (stdout); /* in case stdout and stderr are the same */
296 fputs (buf, stderr);
297 fflush (NULL); /* flushes all stdio output streams */
298 return;
299}
300
301char *
302rtrim (char *str, const char *tok)
303{
304 int i = 0;
305
306 while (str != NULL) {
307 if (*(str + i) == *tok) {
308 sprintf (str + i, "%s", "\0");
309 return str;
310 }
311 i++;
312 }
313 return str;
314}
diff --git a/plugins/popen.h.in b/plugins/popen.h.in
new file mode 100644
index 00000000..adae2ecf
--- /dev/null
+++ b/plugins/popen.h.in
@@ -0,0 +1,9 @@
1FILE *spopen (const char *);
2int spclose (FILE *);
3RETSIGTYPE popen_timeout_alarm_handler (int);
4
5int timeout_interval;
6pid_t *childpid;
7int *child_stderr_array;
8FILE *child_process;
9FILE *child_stderr;
diff --git a/plugins/snprintf.c b/plugins/snprintf.c
new file mode 100644
index 00000000..1474b639
--- /dev/null
+++ b/plugins/snprintf.c
@@ -0,0 +1,377 @@
1/*
2 * Copyright (c) 1983, 1995, 1996 Eric P. Allman
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/* Some changes made by bbraun@synack.net for use with xinetd */
36
37#if !defined(HAVE_SNPRINTF)
38
39/* Extracted from sendmail 8.8.5 */
40#ifndef lint
41static char sccsid[] = "@(#)$Id$ excerpted from conf.c 8.333 (Berkeley) 1/21/97";
42#endif /* not lint */
43# ifdef __STDC__
44#include <stdio.h>
45#include <stdlib.h>
46
47#ifndef __P
48#define __P(p) p
49#endif
50
51#include <stdarg.h>
52#define VA_LOCAL_DECL va_list ap;
53#define VA_START(f) va_start(ap, f)
54#define VA_END va_end(ap)
55
56#else
57
58#include <sys/types.h>
59#include <stdio.h>
60
61#ifndef __P
62#define __P(p) ()
63#endif
64
65#include <varargs.h>
66#define VA_LOCAL_DECL va_list ap;
67#define VA_START(f) va_start(ap)
68#define VA_END va_end(ap)
69
70#endif
71/*
72** SNPRINTF, VSNPRINT -- counted versions of printf
73**
74** These versions have been grabbed off the net. They have been
75** cleaned up to compile properly and support for .precision and
76** %lx has been added.
77*/
78
79/**************************************************************
80 * Original:
81 * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
82 * A bombproof version of doprnt (dopr) included.
83 * Sigh. This sort of thing is always nasty do deal with. Note that
84 * the version here does not include floating point...
85 *
86 * snprintf() is used instead of sprintf() as it does limit checks
87 * for string length. This covers a nasty loophole.
88 *
89 * The other functions are there to prevent NULL pointers from
90 * causing nast effects.
91 **************************************************************/
92
93/*static char _id[] = "$Id$";*/
94static void dopr();
95static char *end;
96#ifndef _SCO_DS
97/* VARARGS3 */
98int
99# ifdef __STDC__
100snprintf(char *str, size_t count, const char *fmt, ...)
101# else
102snprintf(str, count, fmt, va_alist)
103 char *str;
104 size_t count;
105 char *fmt;
106 va_dcl
107#endif
108{
109 int len;
110 VA_LOCAL_DECL
111
112 VA_START(fmt);
113 len = vsnprintf(str, count, fmt, ap);
114 VA_END;
115 return len;
116}
117#endif
118
119# ifndef luna2
120int
121# ifdef __STDC__
122vsnprintf(char *str, size_t count, const char *fmt, va_list args)
123#else
124vsnprintf(str, count, fmt, args)
125 char *str;
126 int count;
127 char *fmt;
128 va_list args;
129#endif
130{
131 str[0] = 0;
132 end = str + count - 1;
133 dopr( str, fmt, args );
134 if (count > 0)
135 end[0] = 0;
136 return strlen(str);
137}
138
139/*
140 * dopr(): poor man's version of doprintf
141 */
142
143static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth));
144static void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad));
145static void dostr __P(( char * , int ));
146static char *output;
147static void dopr_outch __P(( int c ));
148
149static void
150# ifdef __STDC__
151dopr(char * buffer, const char * format, va_list args )
152#else
153dopr( buffer, format, args )
154 char *buffer;
155 char *format;
156 va_list args;
157#endif
158{
159 int ch;
160 long value;
161 int longflag = 0;
162 int pointflag = 0;
163 int maxwidth = 0;
164 char *strvalue;
165 int ljust;
166 int len;
167 int zpad;
168
169 output = buffer;
170 while( (ch = *format++) ){
171 switch( ch ){
172 case '%':
173 ljust = len = zpad = maxwidth = 0;
174 longflag = pointflag = 0;
175 nextch:
176 ch = *format++;
177 switch( ch ){
178 case 0:
179 dostr( "**end of format**" , 0);
180 return;
181 case '-': ljust = 1; goto nextch;
182 case '0': /* set zero padding if len not set */
183 if(len==0 && !pointflag) zpad = '0';
184 case '1': case '2': case '3':
185 case '4': case '5': case '6':
186 case '7': case '8': case '9':
187 if (pointflag)
188 maxwidth = maxwidth*10 + ch - '0';
189 else
190 len = len*10 + ch - '0';
191 goto nextch;
192 case '*':
193 if (pointflag)
194 maxwidth = va_arg( args, int );
195 else
196 len = va_arg( args, int );
197 goto nextch;
198 case '.': pointflag = 1; goto nextch;
199 case 'l': longflag = 1; goto nextch;
200 case 'u': case 'U':
201 /*fmtnum(value,base,dosign,ljust,len,zpad) */
202 if( longflag ){
203 value = va_arg( args, long );
204 } else {
205 value = va_arg( args, int );
206 }
207 fmtnum( value, 10,0, ljust, len, zpad ); break;
208 case 'o': case 'O':
209 /*fmtnum(value,base,dosign,ljust,len,zpad) */
210 if( longflag ){
211 value = va_arg( args, long );
212 } else {
213 value = va_arg( args, int );
214 }
215 fmtnum( value, 8,0, ljust, len, zpad ); break;
216 case 'd': case 'D':
217 if( longflag ){
218 value = va_arg( args, long );
219 } else {
220 value = va_arg( args, int );
221 }
222 fmtnum( value, 10,1, ljust, len, zpad ); break;
223 case 'x':
224 if( longflag ){
225 value = va_arg( args, long );
226 } else {
227 value = va_arg( args, int );
228 }
229 fmtnum( value, 16,0, ljust, len, zpad ); break;
230 case 'X':
231 if( longflag ){
232 value = va_arg( args, long );
233 } else {
234 value = va_arg( args, int );
235 }
236 fmtnum( value,-16,0, ljust, len, zpad ); break;
237 case 's':
238 strvalue = va_arg( args, char *);
239 if (maxwidth > 0 || !pointflag) {
240 if (pointflag && len > maxwidth)
241 len = maxwidth; /* Adjust padding */
242 fmtstr( strvalue,ljust,len,zpad, maxwidth);
243 }
244 break;
245 case 'c':
246 ch = va_arg( args, int );
247 dopr_outch( ch ); break;
248 case '%': dopr_outch( ch ); continue;
249 default:
250 dostr( "???????" , 0);
251 }
252 break;
253 default:
254 dopr_outch( ch );
255 break;
256 }
257 }
258 *output = 0;
259}
260
261static void
262fmtstr( value, ljust, len, zpad, maxwidth )
263 char *value;
264 int ljust, len, zpad, maxwidth;
265{
266 int padlen, strlen; /* amount to pad */
267
268 if( value == 0 ){
269 value = "<NULL>";
270 }
271 for( strlen = 0; value[strlen]; ++ strlen ); /* strlen */
272 if (strlen > maxwidth && maxwidth)
273 strlen = maxwidth;
274 padlen = len - strlen;
275 if( padlen < 0 ) padlen = 0;
276 if( ljust ) padlen = -padlen;
277 while( padlen > 0 ) {
278 dopr_outch( ' ' );
279 --padlen;
280 }
281 dostr( value, maxwidth );
282 while( padlen < 0 ) {
283 dopr_outch( ' ' );
284 ++padlen;
285 }
286}
287
288static void
289fmtnum( value, base, dosign, ljust, len, zpad )
290 long value;
291 int base, dosign, ljust, len, zpad;
292{
293 int signvalue = 0;
294 unsigned long uvalue;
295 char convert[20];
296 int place = 0;
297 int padlen = 0; /* amount to pad */
298 int caps = 0;
299
300 /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
301 value, base, dosign, ljust, len, zpad )); */
302 uvalue = value;
303 if( dosign ){
304 if( value < 0 ) {
305 signvalue = '-';
306 uvalue = -value;
307 }
308 }
309 if( base < 0 ){
310 caps = 1;
311 base = -base;
312 }
313 do{
314 convert[place++] =
315 (caps? "0123456789ABCDEF":"0123456789abcdef")
316 [uvalue % (unsigned)base ];
317 uvalue = (uvalue / (unsigned)base );
318 }while(uvalue);
319 convert[place] = 0;
320 padlen = len - place;
321 if( padlen < 0 ) padlen = 0;
322 if( ljust ) padlen = -padlen;
323 /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
324 convert,place,signvalue,padlen)); */
325 if( zpad && padlen > 0 ){
326 if( signvalue ){
327 dopr_outch( signvalue );
328 --padlen;
329 signvalue = 0;
330 }
331 while( padlen > 0 ){
332 dopr_outch( zpad );
333 --padlen;
334 }
335 }
336 while( padlen > 0 ) {
337 dopr_outch( ' ' );
338 --padlen;
339 }
340 if( signvalue ) dopr_outch( signvalue );
341 while( place > 0 ) dopr_outch( convert[--place] );
342 while( padlen < 0 ){
343 dopr_outch( ' ' );
344 ++padlen;
345 }
346}
347
348static void
349dostr( str , cut)
350 char *str;
351 int cut;
352{
353 if (cut) {
354 while(*str && cut-- > 0) dopr_outch(*str++);
355 } else {
356 while(*str) dopr_outch(*str++);
357 }
358}
359
360static void
361dopr_outch( c )
362 int c;
363{
364#if 0
365 if( iscntrl(c) && c != '\n' && c != '\t' ){
366 c = '@' + (c & 0x1F);
367 if( end == 0 || output < end )
368 *output++ = '^';
369 }
370#endif
371 if( end == 0 || output < end )
372 *output++ = c;
373}
374
375# endif /* !luna2 */
376
377#endif /* HAVE_SNPRINTF */
diff --git a/plugins/t/check_disk.t b/plugins/t/check_disk.t
new file mode 100644
index 00000000..f1e436dc
--- /dev/null
+++ b/plugins/t/check_disk.t
@@ -0,0 +1,31 @@
1use strict;
2use Test;
3use vars qw($tests);
4
5BEGIN {$tests = 6; plan tests => $tests}
6
7my $null = '';
8my $cmd;
9my $str;
10my $t;
11
12$cmd = "./check_disk 100 100 /";
13$str = `$cmd`;
14$t += ok $?>>8,0;
15print "Test was: $cmd\n" if ($?);
16$t += ok $str, '/^(Disk ok - +[\.0-9]+|DISK OK - )/';
17
18$cmd = "./check_disk -w 0 -c 0 /";
19$str = `$cmd`;
20$t += ok $?>>8,0;
21print "Test was: $cmd\n" if ($?);
22$t += ok $str, '/^(Disk ok - +[\.0-9]+|DISK OK - )/';
23
24$cmd = "./check_disk 0 0 /";
25$str = `$cmd`;
26$t += ok $?>>8,2;
27print "Test was: $cmd\n" unless ($?);
28$t += ok $str, '/^(Only +[\.0-9]+|DISK CRITICAL - )/';
29
30exit(0) if defined($Test::Harness::VERSION);
31exit($tests - $t);
diff --git a/plugins/t/check_dns.t b/plugins/t/check_dns.t
new file mode 100644
index 00000000..a85e2e76
--- /dev/null
+++ b/plugins/t/check_dns.t
@@ -0,0 +1,29 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 3; plan tests => $tests}
9
10#`nslookup localhost > /dev/null 2>&1` || exit(77);
11
12my $null = '';
13my $cmd;
14my $str;
15my $t;
16
17$cmd = "./check_dns 127.0.0.1 -to 5";
18$str = `$cmd`;
19$t += ok $?>>8,0;
20print "Test was: $cmd\n" if ($?);
21$t += ok $str, '/DNS ok - +[\.0-9]+ seconds response time, Address\(es\) is\/are /';
22
23$cmd = "./check_dns $Cache::nullhost -to 1";
24$str = `$cmd`;
25$t += ok $?>>8,2;
26print "Test was: $cmd\n" unless ($?);
27
28exit(0) if defined($Test::Harness::VERSION);
29exit($tests - $t);
diff --git a/plugins/t/check_fping.t b/plugins/t/check_fping.t
new file mode 100644
index 00000000..629ee35f
--- /dev/null
+++ b/plugins/t/check_fping.t
@@ -0,0 +1,37 @@
1#! /usr/bin/perl -w
2# $Id$
3
4use strict;
5use Cache;
6use Test;
7use vars qw($tests);
8
9BEGIN {$tests = 3; plan tests => $tests}
10
11exit(0) unless (-x "./check_fping");
12
13#`fping 127.0.0.1 > /dev/null 2>&1` || exit(77);
14
15my $null = '';
16my $cmd;
17my $str;
18my $t;
19my $stat;
20
21
22$cmd = "./check_fping 127.0.0.1";
23$str = `$cmd`;
24$t += ok $?>>8,0;
25print "Test was: $cmd\n" if ($?);
26$t += ok $str, '/^FPING OK - 127.0.0.1/';
27
28$cmd = "./check_fping $Cache::nullhost";
29$str = `$cmd`;
30if ($?>>8 == 1 or $?>>8 == 2) {
31 $stat = 2;
32}
33$t += ok $stat,2;
34print "Test was: $cmd\n" if (($?>>8) < 1);
35
36exit(0) if defined($Test::Harness::VERSION);
37exit($tests - $t);
diff --git a/plugins/t/check_ftp.t b/plugins/t/check_ftp.t
new file mode 100644
index 00000000..c3f74d92
--- /dev/null
+++ b/plugins/t/check_ftp.t
@@ -0,0 +1,32 @@
1#! /usr/bin/perl -w
2
3#use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 3; plan tests => $tests}
9
10my $null = '';
11my $cmd;
12my $str;
13my $t;
14
15$cmd = "./check_ftp $Cache::hostname -wt 300 -ct 600";
16$str = `$cmd`;
17$t += ok $?>>8,0;
18print "Test was: $cmd\n" if ($?);
19$t += ok $str, '/FTP ok - [0-9]+ second response time/';
20
21#$cmd = "./check_ftp $Cache::noserver -wt 0 -ct 0";
22#$str = `$cmd`;
23#$t += ok $?>>8,2;
24#print "Test was: $cmd\n" unless ($?);
25
26$cmd = "./check_ftp $Cache::nullhost -wt 0 -ct 0 -to 1";
27$str = `$cmd`;
28$t += ok $?>>8,2;
29print "Test was: $cmd\n" unless ($?);
30
31exit(0) if defined($Test::Harness::VERSION);
32exit($tests - $t);
diff --git a/plugins/t/check_hpjd.t b/plugins/t/check_hpjd.t
new file mode 100644
index 00000000..b4e198d2
--- /dev/null
+++ b/plugins/t/check_hpjd.t
@@ -0,0 +1,32 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Helper;
5use Cache;
6use Test;
7use vars qw($tests);
8
9BEGIN {$tests = 4; plan tests => $tests}
10
11exit(0) unless (-x "./check_hpjd");
12
13my $null = '';
14my $cmd;
15my $str;
16my $t;
17my $printer = get_option("hpjd_printer","HP Jet-Direct card address");
18
19$cmd = "./check_hpjd $printer";
20$str = `$cmd`;
21$t += ok $?>>8,0;
22print "Test was: $cmd\n" if ($?);
23$t += ok $str, '/^Printer ok - /';
24
25$cmd = "./check_hpjd $Cache::noserver";
26$str = `$cmd`;
27$t += ok $?>>8,2;
28print "Test was: $cmd\n" unless ($?);
29$t += ok $str, '/Timeout: No response from /';
30
31exit(0) if defined($Test::Harness::VERSION);
32exit($tests - $t);
diff --git a/plugins/t/check_http.t b/plugins/t/check_http.t
new file mode 100644
index 00000000..2782fcd5
--- /dev/null
+++ b/plugins/t/check_http.t
@@ -0,0 +1,22 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 3; plan tests => $tests}
9
10my $null = '';
11my $str;
12my $t;
13
14$str = `./check_http $Cache::hostname -wt 300 -ct 600`;
15$t += ok $?>>8,0;
16$t += ok $str, '/HTTP\/1.1 [0-9]{3} (OK|Found) - [0-9]+ second response time/';
17
18$str = `./check_http $Cache::nullhost -wt 1 -ct 2`;
19$t += ok $?>>8,2;
20
21exit(0) if defined($Test::Harness::VERSION);
22exit($tests - $t);
diff --git a/plugins/t/check_imap.t b/plugins/t/check_imap.t
new file mode 100644
index 00000000..47494e59
--- /dev/null
+++ b/plugins/t/check_imap.t
@@ -0,0 +1,34 @@
1#! /usr/bin/perl -w
2
3#use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 3; plan tests => $tests}
9
10my $null = '';
11my $cmd;
12my $str;
13my $t;
14
15$cmd = "./check_imap $Cache::mailhost";
16$str = `$cmd`;
17$t += ok $?>>8,0;
18print "Test was: $cmd\n" if ($?);
19
20$cmd = "./check_imap -H $Cache::mailhost -p 143 -w 9 -c 9 -t 10 -e '* OK'";
21$str = `$cmd`;
22$t += ok $?>>8,0;
23print "Test was: $cmd\n" if ($?);
24
25
26# Reverse compatibility
27$cmd = "./check_imap $Cache::mailhost -p 143 -wt 9 -ct 9 -to 10 -e '* OK'";
28$str = `$cmd`;
29$t += ok $?>>8,0;
30print "Test was: $cmd\n" if ($?);
31
32exit(0) if defined($Test::Harness::VERSION);
33exit($tests - $t);
34
diff --git a/plugins/t/check_load.t b/plugins/t/check_load.t
new file mode 100644
index 00000000..ac14620f
--- /dev/null
+++ b/plugins/t/check_load.t
@@ -0,0 +1,27 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Test;
5use vars qw($tests);
6
7BEGIN {$tests = 4; plan tests => $tests}
8
9my $null = '';
10my $cmd;
11my $str;
12my $t;
13
14$cmd = "./check_load 100 100 100 100 100 100";
15$str = `$cmd`;
16$t += ok $?>>8,0;
17print "Test was: $cmd\n" if ($?);
18$t += ok $str, '/^load average: +[\.0-9]+, +[\.0-9]+, +[\.0-9]+$/';
19
20$cmd = "./check_load 0 0 0 0 0 0";
21$str = `$cmd`;
22$t += ok $?>>8,2;
23print "Test was: $cmd\n" unless ($?);
24$t += ok $str, '/^load average: +[\.0-9]+, +[\.0-9]+, +[\.0-9]+ CRITICAL$/';
25
26exit(0) if defined($Test::Harness::VERSION);
27exit($tests - $t);
diff --git a/plugins/t/check_mysql.t b/plugins/t/check_mysql.t
new file mode 100644
index 00000000..ae2a0087
--- /dev/null
+++ b/plugins/t/check_mysql.t
@@ -0,0 +1,23 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 1; plan tests => $tests}
9
10exit(0) unless (-x "./check_mysql");
11
12my $null = '';
13my $cmd;
14my $str;
15my $t;
16
17$cmd = "./check_mysql -H 127.0.0.1 -P 3306";
18$str = `$cmd`;
19$t += ok $?>>8,0;
20print "Test was: $cmd\n" if ($?);
21
22exit(0) if defined($Test::Harness::VERSION);
23exit($tests - $t);
diff --git a/plugins/t/check_ping.t b/plugins/t/check_ping.t
new file mode 100644
index 00000000..97bc660e
--- /dev/null
+++ b/plugins/t/check_ping.t
@@ -0,0 +1,33 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 5; plan tests => $tests}
9
10my $null = '';
11my $cmd;
12my $str;
13my $t;
14
15$cmd = "./check_ping 127.0.0.1 100 100 1000 1000 -p 1";
16$str = `$cmd`;
17$t += ok $?>>8,0;
18print "Test was: $cmd\n" if ($?);
19$t += ok $str, '/PING (ok|OK) - Packet loss = +[0-9]{1,2}\%, +RTA = [\.0-9]+ ms/';
20
21$cmd = "./check_ping 127.0.0.1 0 0 0 0 -p 1";
22$str = `$cmd`;
23$t += ok $?>>8,2;
24print "Test was: $cmd\n" unless ($?);
25$t += ok $str, '/Packet loss = +[0-9]{1,2}\%, +RTA = [\.0-9]+ ms/';
26
27$cmd = "./check_ping $Cache::nullhost 0 0 0 0 -p 1 -to 1";
28$str = `$cmd`;
29$t += ok $?>>8,2;
30print "Test was: $cmd\n" unless ($?);
31
32exit(0) if defined($Test::Harness::VERSION);
33exit($tests - $t);
diff --git a/plugins/t/check_pop.t b/plugins/t/check_pop.t
new file mode 100644
index 00000000..60b5a4ef
--- /dev/null
+++ b/plugins/t/check_pop.t
@@ -0,0 +1,31 @@
1#! /usr/bin/perl -w
2
3#use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 3; plan tests => $tests}
9
10my $null = '';
11my $cmd;
12my $str;
13my $t;
14
15$cmd = "./check_pop $Cache::mailhost";
16$str = `$cmd`;
17$t += ok $?>>8,0;
18print "Test was: $cmd\n" if ($?);
19
20$cmd = "./check_pop -H $Cache::mailhost -p 110 -w 9 -c 9 -t 10 -e '+OK'";
21$str = `$cmd`;
22$t += ok $?>>8,0;
23print "Test was: $cmd\n" if ($?);
24
25$cmd = "./check_pop $Cache::mailhost -p 110 -wt 9 -ct 9 -to 10 -e '+OK'";
26$str = `$cmd`;
27$t += ok $?>>8,0;
28print "Test was: $cmd\n" if ($?);
29
30exit(0) if defined($Test::Harness::VERSION);
31exit($tests - $t);
diff --git a/plugins/t/check_procs.t b/plugins/t/check_procs.t
new file mode 100644
index 00000000..9c2330f9
--- /dev/null
+++ b/plugins/t/check_procs.t
@@ -0,0 +1,51 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 10; plan tests => $tests}
9
10my $null = '';
11my $cmd;
12my $str;
13my $t;
14
15# Reverse Compatibility
16$cmd = "./check_procs 100000 100000";
17$str = `$cmd`;
18$t += ok $?>>8,0;
19print "Test was: $cmd\n" if ($?);
20$t += ok $str, '/^OK - [0-9]+ processes running$/';
21
22# Reverse Compatibility
23$cmd = "./check_procs 100000 100000 Z";
24$str = `$cmd`;
25$t += ok $?>>8,0;
26print "Test was: $cmd\n" if ($?);
27$t += ok $str, '/^OK - [0-9]+ processes running with /';
28
29# Reverse Compatibility
30$cmd = "./check_procs 0 10000000";
31$str = `$cmd`;
32$t += ok $?>>8,1;
33print "Test was: $cmd\n" unless ($?);
34$t += ok $str, '/^WARNING - [0-9]+ processes running$/';
35
36# Reverse Compatibility
37$cmd = "./check_procs 0 0";
38$str = `$cmd`;
39$t += ok $?>>8,2;
40print "Test was: $cmd\n" unless ($?);
41$t += ok $str, '/^CRITICAL - [0-9]+ processes running$/';
42
43# Reverse Compatibility
44$cmd = "./check_procs 0 0 S";
45$str = `$cmd`;
46$t += ok $?>>8,2;
47print "Test was: $cmd\n" unless ($?);
48$t += ok $str, '/^CRITICAL - [0-9]+ processes running with /';
49
50exit(0) if defined($Test::Harness::VERSION);
51exit($tests - $t);
diff --git a/plugins/t/check_smtp.t b/plugins/t/check_smtp.t
new file mode 100644
index 00000000..2a82b877
--- /dev/null
+++ b/plugins/t/check_smtp.t
@@ -0,0 +1,31 @@
1#! /usr/bin/perl -w
2
3#use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 3; plan tests => $tests}
9
10my $null = '';
11my $cmd;
12my $str;
13my $t;
14
15$cmd = "./check_smtp $Cache::mailhost";
16$str = `$cmd`;
17$t += ok $?>>8,0;
18print "Test was: $cmd\n" if ($?);
19
20$cmd = "./check_smtp -H $Cache::mailhost -p 25 -t 1 -w 9 -c 9 -t 10 -e 220";
21$str = `$cmd`;
22$t += ok $?>>8,0;
23print "Test was: $cmd\n" if ($?);
24
25$cmd = "./check_smtp -H $Cache::mailhost -p 25 -wt 9 -ct 9 -to 10 -e 220";
26$str = `$cmd`;
27$t += ok $?>>8,0;
28print "Test was: $cmd\n" if ($?);
29
30exit(0) if defined($Test::Harness::VERSION);
31exit($tests - $t);
diff --git a/plugins/t/check_snmp.t b/plugins/t/check_snmp.t
new file mode 100644
index 00000000..162b0b9b
--- /dev/null
+++ b/plugins/t/check_snmp.t
@@ -0,0 +1,52 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Helper;
5use Cache;
6use Test;
7use vars qw($tests);
8
9BEGIN {$tests = 8; plan tests => $tests}
10
11my $null = '';
12my $cmd;
13my $str;
14my $t;
15my $community=get_option("snmp_community","SNMP community name");
16
17exit(0) unless (-x "./check_snmp");
18
19$cmd = "./check_snmp -H 127.0.0.1 -C $community -o system.sysUpTime.0 -w 1: -c 1:";
20$str = `$cmd`;
21$t += ok $?>>8,0;
22print "Test was: $cmd\n" if ($?);
23chomp $str;
24$t += ok $str, '/^SNMP OK - \d+/';
25
26$cmd = "./check_snmp -H 127.0.0.1 -C $community -o host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w 1:1 -c 1:1";
27$str = `$cmd`;
28$t += ok $?>>8,0;
29print "Test was: $cmd\n" if ($?);
30chomp $str;
31$t += ok $str, '/^SNMP OK - 1\s*$/';
32
33$cmd = "./check_snmp -H 127.0.0.1 -C $community -o host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w 0 -c 1:";
34$str = `$cmd`;
35$t += ok $?>>8,1;
36print "Test was: $cmd\n" unless ($?);
37chomp $str;
38$t += ok $str, '/^SNMP WARNING - \*1\*\s*$/';
39
40$cmd = "./check_snmp -H 127.0.0.1 -C $community -o host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w :0 -c 0";
41$str = `$cmd`;
42$t += ok $?>>8,2;
43print "Test was: $cmd\n" unless ($?);
44chomp $str;
45$t += ok $str, '/^SNMP CRITICAL - \*1\*\s*$/';
46
47#host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 = 1
48#enterprises.ucdavis.memory.memAvailSwap.0
49#./check_snmp 127.0.0.1 -C staff -o enterprises.ucdavis.diskTable.dskEntry.dskAvail.1,enterprises.ucdavis.diskTable.dskEntry.dskPercent.1 -w 100000: -c 50000: -l Space on root -u 'bytes free (','% used)'
50
51exit(0) if defined($Test::Harness::VERSION);
52exit($tests - $t);
diff --git a/plugins/t/check_swap.t b/plugins/t/check_swap.t
new file mode 100644
index 00000000..5b702f00
--- /dev/null
+++ b/plugins/t/check_swap.t
@@ -0,0 +1,34 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 6; plan tests => $tests}
9
10my $null = '';
11my $cmd;
12my $str;
13my $t;
14
15$cmd = "./check_swap 100 100";
16$str = `$cmd`;
17$t += ok $?>>8,0;
18print "Test was: $cmd\n" if ($?);
19$t += ok $str, '/^Swap ok - Swap used\: +[0-9]{1,2}\% \([0-9]+ bytes out of [0-9]+\)$/';
20
21$cmd = "./check_swap 0 0";
22$str = `$cmd`;
23$t += ok $?>>8,2;
24print "Test was: $cmd\n" unless ($?);
25$t += ok $str, '/^CRITICAL - Swap used\: +[0-9]{1,2}\% \([0-9]+ bytes out of [0-9]+\)$/';
26
27$cmd = "./check_swap 100 100 1000000000 1000000000";
28$str = `$cmd`;
29$t += ok $?>>8,2;
30print "Test was: $cmd\n" unless ($?);
31$t += ok $str, '/^CRITICAL - Swap used\: +[0-9]{1,2}\% \([0-9]+ bytes out of [0-9]+\)$/';
32
33exit(0) if defined($Test::Harness::VERSION);
34exit($tests - $t);
diff --git a/plugins/t/check_tcp.t b/plugins/t/check_tcp.t
new file mode 100644
index 00000000..1abec769
--- /dev/null
+++ b/plugins/t/check_tcp.t
@@ -0,0 +1,27 @@
1#! /usr/bin/perl -w
2
3#use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 3; plan tests => $tests}
9
10my $null = '';
11my $cmd;
12my $str;
13my $t;
14
15$cmd = "./check_tcp $Cache::hostname -p 80 -wt 300 -ct 600";
16$str = `$cmd`;
17$t += ok $?>>8,0;
18print "$cmd\n" if ($?);
19$t += ok $str, '/^TCP OK - [0-9]+ second response time on port 80/';
20
21$cmd = "./check_tcp $Cache::nullhost -p 81 -wt 0 -ct 0 -to 1";
22$str = `$cmd`;
23$t += ok $?>>8,2;
24print "$cmd\n" unless ($?);
25
26exit(0) if defined($Test::Harness::VERSION);
27exit($tests - $t);
diff --git a/plugins/t/check_time.t b/plugins/t/check_time.t
new file mode 100644
index 00000000..4d8c5c2b
--- /dev/null
+++ b/plugins/t/check_time.t
@@ -0,0 +1,52 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Cache;
5use Helper;
6use Test;
7use vars qw($tests);
8
9BEGIN {$tests = 6; plan tests => $tests}
10
11my $null = '';
12my $cmd;
13my $str;
14my $t;
15my $udp_hostname=get_option("udp_hostname","UDP host name");
16
17# standard mode
18
19$cmd = "./check_time -H $udp_hostname -w 999999,59 -c 999999,59 -t 60";
20$str = `$cmd`;
21$t += ok $?>>8,0;
22print "Test was: $cmd\n" if ($?);
23$t += ok $str, '/^TIME OK - [0-9]+ second time difference$/';
24
25$cmd = "./check_time -H $udp_hostname -w 999999 -W 59 -c 999999 -C 59 -t 60";
26$str = `$cmd`;
27$t += ok $?>>8,0;
28print "Test was: $cmd\n" if ($?);
29$t += ok $str, '/^TIME OK - [0-9]+ second time difference$/';
30
31# reverse compatibility mode
32
33$cmd = "./check_time $udp_hostname -wt 59 -ct 59 -cd 999999 -wd 999999 -to 60";
34$str = `$cmd`;
35$t += ok $?>>8,0;
36print "Test was: $cmd\n" if ($?);
37$t += ok $str, '/^TIME OK - [0-9]+ second time difference$/';
38
39# failure mode
40
41#$cmd = "./check_time -H $Cache::nullhost -t 1";
42#$str = `$cmd`;
43#$t += ok $?>>8,255;
44#print "Test was: $cmd\n" unless ($?);
45
46#$cmd = "./check_time -H $Cache::noserver -t 1";
47#$str = `$cmd`;
48#$t += ok $?>>8,255;
49#print "$cmd\n" unless ($?);
50
51exit(0) if defined($Test::Harness::VERSION);
52exit($tests - $t);
diff --git a/plugins/t/check_udp.t b/plugins/t/check_udp.t
new file mode 100644
index 00000000..abbf5e49
--- /dev/null
+++ b/plugins/t/check_udp.t
@@ -0,0 +1,24 @@
1#! /usr/bin/perl -w
2
3#use strict;
4use Cache;
5use Helper;
6use Test;
7use vars qw($tests);
8
9BEGIN {$tests = 3; plan tests => $tests}
10
11my $null = '';
12my $str;
13my $t;
14my $hostname=get_option("udp_hostname","UDP host name");
15
16$str = `./check_udp $hostname -p 37 -wt 300 -ct 600`;
17$t += ok $?>>8,0;
18$t += ok $str, '/^Connection accepted on port 37 - [0-9]+ second response time$/';
19
20$str = `./check_udp $Cache::nullhost -p 80 -wt 0 -ct 0 -to 1`;
21$t += ok $?>>8,2;
22
23exit(0) if defined($Test::Harness::VERSION);
24exit($tests - $t);
diff --git a/plugins/t/check_users.t b/plugins/t/check_users.t
new file mode 100644
index 00000000..593f1737
--- /dev/null
+++ b/plugins/t/check_users.t
@@ -0,0 +1,28 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 4; plan tests => $tests}
9
10my $null = '';
11my $cmd;
12my $str;
13my $t;
14
15$cmd = "./check_users 1000 1000";
16$str = `$cmd`;
17$t += ok $?>>8,0;
18print "Test was: $cmd\n" if ($?);
19$t += ok $str, '/^USERS OK - +[0-9]+ users currently logged in$/';
20
21$cmd = "./check_users 0 0";
22$str = `$cmd`;
23$t += ok $?>>8,2;
24print "Test was: $cmd\n" unless ($?);
25$t += ok $str, '/^USERS CRITICAL - [0-9]+ +users currently logged in$/';
26
27exit(0) if defined($Test::Harness::VERSION);
28exit($tests - $t);
diff --git a/plugins/t/check_vsz.t b/plugins/t/check_vsz.t
new file mode 100644
index 00000000..95972619
--- /dev/null
+++ b/plugins/t/check_vsz.t
@@ -0,0 +1,28 @@
1#! /usr/bin/perl -w
2
3use strict;
4use Cache;
5use Test;
6use vars qw($tests);
7
8BEGIN {$tests = 4; plan tests => $tests}
9
10my $null = '';
11my $cmd;
12my $str;
13my $t;
14
15$cmd = "./check_vsz 100000 1000000 init";
16$str = `$cmd`;
17$t += ok $?>>8,0;
18print "Test was: $cmd\n" if ($?);
19$t += ok $str, '/^ok \(all VSZ\<[0-9]+\)/';
20
21$cmd = "./check_vsz 0 0";
22$str = `$cmd`;
23$t += ok $?>>8,2;
24print "Test was: $cmd\n" unless ($?);
25$t += ok $str, '/^CRITICAL \(VSZ\>[0-9]+\)/';
26
27exit(0) if defined($Test::Harness::VERSION);
28exit($tests - $t);
diff --git a/plugins/tests/check_disk b/plugins/tests/check_disk
new file mode 100644
index 00000000..c4323e0b
--- /dev/null
+++ b/plugins/tests/check_disk
@@ -0,0 +1,9 @@
1check_disk
2
3[normal]
4100 100 /
5^Disk ok - +[\.0-9]+
6
7[critical]
80 0 /
9^Only +[\.0-9]+
diff --git a/plugins/tests/check_dns b/plugins/tests/check_dns
new file mode 100644
index 00000000..2e9b9a09
--- /dev/null
+++ b/plugins/tests/check_dns
@@ -0,0 +1,9 @@
1check_dns
2
3[normal]
4127.0.0.1
5DNS ok - +[\.0-9]+ seconds response time, Address\(es\) is\/are 127\.0\.0\.1
6
7[critical]
8$nullhost
9DNS (problem - Probably a non-existent host/domain|CRITICAL - Non-existent host/domain|CRITICAL - Connection timed out after [0-9]+ seconds)
diff --git a/plugins/tests/check_ftp b/plugins/tests/check_ftp
new file mode 100644
index 00000000..4266ebdc
--- /dev/null
+++ b/plugins/tests/check_ftp
@@ -0,0 +1,9 @@
1check_ftp
2
3[normal]
4$hostname -wt 300 -ct 600
5FTP ok - [0-9]+ second response time
6
7[critical]
8$noserver -wt 0 -ct 0
9(Invalid FTP response received from host|Connection refused by host)
diff --git a/plugins/tests/check_hpjd b/plugins/tests/check_hpjd
new file mode 100644
index 00000000..df35996f
--- /dev/null
+++ b/plugins/tests/check_hpjd
@@ -0,0 +1,9 @@
1check_hpjd
2
3[normal]
4$printer
5^Printer ok -
6
7[critical]
8$noserver
9Timeout: No response from ns
diff --git a/plugins/tests/check_http b/plugins/tests/check_http
new file mode 100644
index 00000000..e09f6ff7
--- /dev/null
+++ b/plugins/tests/check_http
@@ -0,0 +1,9 @@
1check_http
2
3[normal]
4www.infoplease.com -wt 300 -ct 600
5HTTP/1.1 200 OK - [0-9]+ second response time
6
7[critical]
8$nullhost -wt 1 -ct 2
9(Connection refused by host|Network is unreachable|Connection refused or timed out|Socket timeout after [0-9]+ seconds)$
diff --git a/plugins/tests/check_load b/plugins/tests/check_load
new file mode 100644
index 00000000..5e4be3a4
--- /dev/null
+++ b/plugins/tests/check_load
@@ -0,0 +1,9 @@
1check_load
2
3[normal]
4100 100 100 100 100 100
5^load average: +[\.0-9]+, +[\.0-9]+, +[\.0-9]+$
6
7[critical]
80 0 0 0 0 0
9^load average: +[\.0-9]+, +[\.0-9]+, +[\.0-9]+ CRITICAL$
diff --git a/plugins/tests/check_ping b/plugins/tests/check_ping
new file mode 100644
index 00000000..115cbaa3
--- /dev/null
+++ b/plugins/tests/check_ping
@@ -0,0 +1,13 @@
1check_ping
2
3[normal]
4127.0.0.1 100 100 1000 1000 -p 1
5PING ok - Packet loss = +[0-9]{1,2}\%, +RTA = [\.0-9]+ ms
6
7[critical]
8127.0.0.1 0 0 0 0 -p 1
9Packet loss = +[0-9]{1,2}\%, +RTA = [\.0-9]+ ms
10
11[critical]
12$nullhost 0 0 0 0 -p 1 -to 1
13CRITICAL - Plugin timed out after 1 seconds
diff --git a/plugins/tests/check_procs b/plugins/tests/check_procs
new file mode 100644
index 00000000..f7c65222
--- /dev/null
+++ b/plugins/tests/check_procs
@@ -0,0 +1,23 @@
1check_procs
2
3# this is a comment
4
5[normal]
6100000 100000
7^OK - [0-9]+ processes running$
8
9[normal]
10100000 100000 Z
11^OK - [0-9]+ processes with Z status$
12
13[warning]
140 10000000
15^WARNING - [0-9]+ processes running$
16
17[critical]
180 0
19^CRITICAL - [0-9]+ processes running$
20
21[critical]
220 0 S
23^CRITICAL - [0-9]+ processes with S status$
diff --git a/plugins/tests/check_swap b/plugins/tests/check_swap
new file mode 100644
index 00000000..b6cbb42f
--- /dev/null
+++ b/plugins/tests/check_swap
@@ -0,0 +1,13 @@
1check_swap
2
3[normal]
4100 100
5^Swap ok - Swap used\: +[0-9]{1,2}\% \([0-9]+ bytes out of [0-9]+\)$
6
7[critical]
80 0
9^CRITICAL - Swap used\: +[0-9]{1,2}\% \([0-9]+ bytes out of [0-9]+\)$
10
11[critical]
12100 100 1000000000 10000000000
13^CRITICAL - Swap used\: +[0-9]{1,2}\% \([0-9]+ bytes out of [0-9]+\)$
diff --git a/plugins/tests/check_users b/plugins/tests/check_users
new file mode 100644
index 00000000..5a7959a5
--- /dev/null
+++ b/plugins/tests/check_users
@@ -0,0 +1,9 @@
1check_users
2
3[normal]
41000 1000
5^Users ok - +[0-9]+ users logged in$
6
7[critical]
80 0
9^[0-9]+ +users currently logged in$
diff --git a/plugins/tests/check_vsz b/plugins/tests/check_vsz
new file mode 100644
index 00000000..4fdec936
--- /dev/null
+++ b/plugins/tests/check_vsz
@@ -0,0 +1,9 @@
1check_vsz
2
3[normal]
4100000 1000000 init
5^ok \(all VSZ\<[0-9]+\)
6
7[critical]
80 0
9^CRITICAL \(VSZ\>[0-9]+\)
diff --git a/plugins/urlize.c b/plugins/urlize.c
new file mode 100644
index 00000000..83c37dac
--- /dev/null
+++ b/plugins/urlize.c
@@ -0,0 +1,141 @@
1/******************************************************************************
2 *
3 * urlize.c
4 *
5 * Program: plugin wrapper for Nagios
6 * License: GPL
7 * Copyright (c) 2000 Karl DeBisschop (kdebiss@alum.mit.edu)
8 *
9 * Last Modified: $Date$
10 * 2000-06-01 Karl DeBisschop <karl@debisschop.net>
11 * Written based of concept in urlize.pl
12 *
13 * Usage: urlize <url> <plugin> <arg1> ... <argN>
14 *
15 * Description:
16 *
17 * This plugin wraps the text output of another command (plugin) in HTML
18 * <A> tags, thus displaying the plugin output in as a clickable link in
19 * the Nagios status screen. The return status is the same as the plugin
20 * invoked by urlize
21 *
22 * License Information:
23 *
24 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation; either version 2 of the License, or
27 * (at your option) any later version.
28 *
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
33 *
34 * You should have received a copy of the GNU General Public License
35 * along with this program; if not, write to the Free Software
36 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37 *
38 *****************************************************************************/
39
40#include "common.h"
41#include "utils.h"
42#include "popen.h"
43
44void print_usage (char *);
45void print_help (char *);
46
47int
48main (int argc, char **argv)
49{
50 int i = 0, found = 0, result = STATE_UNKNOWN;
51 char command_line[MAX_INPUT_BUFFER] = "";
52 char input_buffer[MAX_INPUT_BUFFER];
53
54 if (argc < 2) {
55 print_usage (my_basename (argv[0]));
56 exit (STATE_UNKNOWN);
57 }
58
59 if (!strcmp (argv[1], "-h") || !strcmp (argv[1], "--help")) {
60 print_help (argv[0]);
61 exit (STATE_OK);
62 }
63
64 if (!strcmp (argv[1], "-V") || !strcmp (argv[1], "--version")) {
65 print_revision (my_basename (argv[0]), "$Revision$");
66 exit (STATE_OK);
67 }
68
69 if (argc < 2) {
70 print_usage (my_basename (argv[0]));
71 exit (STATE_UNKNOWN);
72 }
73
74 sprintf (command_line, "%s", argv[2]);
75 for (i = 3; i < argc; i++) {
76 sprintf (command_line, "%s %s", command_line, argv[i]);
77 }
78
79 child_process = spopen (command_line);
80 if (child_process == NULL) {
81 printf ("Could not open pipe: %s\n", command_line);
82 exit (STATE_UNKNOWN);
83 }
84
85 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
86 if (child_stderr == NULL) {
87 printf ("Could not open stderr for %s\n", command_line);
88 }
89
90 printf ("<A href=\"%s\">", argv[1]);
91 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
92 found++;
93 if (index (input_buffer, '\n')) {
94 input_buffer[strcspn (input_buffer, "\n")] = 0;
95 printf ("%s", input_buffer);
96 }
97 else {
98 printf ("%s", input_buffer);
99 }
100 }
101
102 if (!found) {
103 printf ("%s problem - No data recieved from host\nCMD: %s\n", argv[0],
104 command_line);
105 exit (STATE_UNKNOWN);
106 }
107
108 /* close the pipe */
109 result = spclose (child_process);
110
111 /* WARNING if output found on stderr */
112 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
113 result = max (result, STATE_WARNING);
114
115 /* close stderr */
116 (void) fclose (child_stderr);
117
118 printf ("</A>\n");
119 return result;
120}
121
122void
123print_usage (char *cmd)
124{
125 printf ("Usage:\n %s <url> <plugin> <arg1> ... <argN>\n",
126 my_basename (cmd));
127}
128
129void
130print_help (char *cmd)
131{
132 print_revision ("urlize", "$Revision$");
133 printf
134 ("Copyright (c) 2000 Karl DeBisschop (kdebiss@alum.mit.edu)\n\n"
135 "\nThis plugin wraps the text output of another command (plugin) in HTML\n"
136 "<A> tags, thus displaying the plugin output in as a clickable link in\n"
137 "the Nagios status screen. The return status is the same as the invoked\n"
138 "plugin.\n\n");
139 print_usage (cmd);
140 exit (STATE_OK);
141}
diff --git a/plugins/utils.c b/plugins/utils.c
new file mode 100644
index 00000000..49e4d3d7
--- /dev/null
+++ b/plugins/utils.c
@@ -0,0 +1,610 @@
1/*****************************************************************************
2 *
3 * utils.c
4 *
5 * Library of useful functions for plugins
6 *
7 * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
8 * License: GPL
9 *
10 * $Revision$
11 * $Date$
12 ****************************************************************************/
13
14#include "config.h"
15#include "common.h"
16#include "version.h"
17#include <stdarg.h>
18#include <limits.h>
19
20extern int timeout_interval;
21
22char *my_basename (char *);
23void support (void);
24char *clean_revstring (const char *);
25void print_revision (char *, const char *);
26void terminate (int, const char *fmt, ...);
27RETSIGTYPE timeout_alarm_handler (int);
28
29int is_host (char *);
30int is_dotted_quad (char *);
31int is_hostname (char *);
32
33int is_integer (char *);
34int is_intpos (char *);
35int is_intneg (char *);
36int is_intnonneg (char *);
37int is_intpercent (char *);
38
39int is_numeric (char *);
40int is_positive (char *);
41int is_negative (char *);
42int is_nonnegative (char *);
43int is_percentage (char *);
44
45int is_option (char *str);
46
47void strip (char *);
48char *strscpy (char *dest, const char *src);
49char *strscat (char *dest, const char *src);
50char *strnl (char *str);
51char *ssprintf (char *str, const char *fmt, ...);
52char *strpcpy (char *dest, const char *src, const char *str);
53char *strpcat (char *dest, const char *src, const char *str);
54
55#define LABELLEN 63
56#define STRLEN 64
57#define TXTBLK 128
58
59#define max(a,b) ((a)>(b))?(a):(b)
60
61char *
62my_basename (char *path)
63{
64 if (!strstr (path, "/"))
65 return path;
66 else
67 return 1 + strrchr (path, '/');
68}
69
70
71void
72support (void)
73{
74 printf
75 ("Send email to nagios-users@lists.sourceforge.net if you have questions\n"
76 "regarding use of this software. To submit patches or suggest improvements,\n"
77 "send email to nagiosplug-devel@lists.sourceforge.net\n");
78}
79
80
81char *
82clean_revstring (const char *revstring)
83{
84 char plugin_revision[STRLEN];
85 if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
86 return strscpy (NULL, plugin_revision);
87 else
88 return strscpy (NULL, "N/A");
89}
90
91void
92print_revision (char *command_name, const char *revision_string)
93{
94 char plugin_revision[STRLEN];
95
96 if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
97 strncpy (plugin_revision, "N/A", STRLEN);
98 printf ("%s (nagios-plugins %s) %s\n",
99 my_basename (command_name), VERSION, plugin_revision);
100 printf
101 ("The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n"
102 "copies of the plugins under the terms of the GNU General Public License.\n"
103 "For more information about these matters, see the file named COPYING.\n");
104
105}
106
107
108void
109terminate (int result, const char *fmt, ...)
110{
111 va_list ap;
112 va_start (ap, fmt);
113 vprintf (fmt, ap);
114 va_end (ap);
115 exit (result);
116}
117
118void
119timeout_alarm_handler (int signo)
120{
121 if (signo == SIGALRM) {
122 printf ("CRITICAL - Plugin timed out after %d seconds\n",
123 timeout_interval);
124 exit (STATE_CRITICAL);
125 }
126}
127
128int
129is_host (char *address)
130{
131 if (is_dotted_quad (address) || is_hostname (address))
132 return (TRUE);
133 return (FALSE);
134}
135
136int
137is_dotted_quad (char *address)
138{
139 int o1, o2, o3, o4;
140 char c[1];
141
142 if (sscanf (address, "%d.%d.%d.%d%c", &o1, &o2, &o3, &o4, c) != 4)
143 return FALSE;
144 else if (o1 > 255 || o2 > 255 || o3 > 255 || o4 > 255)
145 return FALSE;
146 else if (o1 < 0 || o2 < 0 || o3 < 0 || o4 < 0)
147 return FALSE;
148 else
149 return TRUE;
150}
151
152/* from RFC-1035
153 *
154 * The labels must follow the rules for ARPANET host names. They must
155 * start with a letter, end with a letter or digit, and have as interior
156 * characters only letters, digits, and hyphen. There are also some
157 * restrictions on the length. Labels must be 63 characters or less. */
158
159int
160is_hostname (char *s1)
161{
162 if (strlen (s1) > 63)
163 return FALSE;
164 if (strcspn
165 (s1,
166 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUWVXYZ0123456789-.") !=
167 0) return FALSE;
168 if (strspn (s1, "0123456789-.") == 1)
169 return FALSE;
170 while ((s1 = index (s1, '.'))) {
171 s1++;
172 if (strspn (s1, "0123456789-.") == 1) {
173 printf ("%s\n", s1);
174 return FALSE;
175 }
176 }
177 return TRUE;
178}
179
180int
181is_numeric (char *number)
182{
183 char tmp[1];
184 float x;
185 if (sscanf (number, "%f%c", &x, tmp) == 1)
186 return (TRUE);
187 return (FALSE);
188}
189
190int
191is_positive (char *number)
192{
193 if (is_numeric (number) && atof (number) > 0.0)
194 return (TRUE);
195 return (FALSE);
196}
197
198int
199is_negative (char *number)
200{
201 if (is_numeric (number) && atof (number) < 0.0)
202 return (TRUE);
203 return (FALSE);
204}
205
206int
207is_nonnegative (char *number)
208{
209 if (is_numeric (number) && atof (number) >= 0.0)
210 return (TRUE);
211 return (FALSE);
212}
213
214int
215is_percentage (char *number)
216{
217 int x;
218 if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
219 return (TRUE);
220 return (FALSE);
221}
222
223int
224is_integer (char *number)
225{
226 long int n;
227
228 if (strspn (number, "-0123456789 ") != strlen (number))
229 return (FALSE);
230
231 n = strtol (number, NULL, 10);
232 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
233 return (TRUE);
234 return (FALSE);
235}
236
237int
238is_intpos (char *number)
239{
240 if (is_integer (number) && atoi (number) > 0)
241 return (TRUE);
242 return (FALSE);
243}
244
245int
246is_intneg (char *number)
247{
248 if (is_integer (number) && atoi (number) < 0)
249 return (TRUE);
250 return (FALSE);
251}
252
253int
254is_intnonneg (char *number)
255{
256 if (is_integer (number) && atoi (number) >= 0)
257 return (TRUE);
258 return (FALSE);
259}
260
261int
262is_intpercent (char *number)
263{
264 int i;
265 if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
266 return (TRUE);
267 return (FALSE);
268}
269
270int
271is_option (char *str)
272{
273 if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
274 return TRUE;
275 return FALSE;
276}
277
278
279
280
281
282void
283strip (char *buffer)
284{
285 size_t x;
286 int i;
287
288 for (x = strlen (buffer); x >= 1; x--) {
289 i = x - 1;
290 if (buffer[i] == ' ' ||
291 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
292 buffer[i] = '\0';
293 else
294 break;
295 }
296 return;
297}
298
299
300
301
302
303/******************************************************************************
304 *
305 * Copies one string to another
306 *
307 * Given a pointer destination string, which may or may not already
308 * hold some text, and a source string with additional text (possibly
309 * NULL or empty), returns a pointer to a a copy of the source
310 * string. Uses realloc to free memory held by the dest argument if
311 * new storage space is required, and any previously existing data in
312 * the destination string is lost.
313 *
314 * Example:
315 *
316 * char *str=NULL;
317 * str = strscpy("This is a line of text with no trailing newline");
318 *
319 *****************************************************************************/
320
321char *
322strscpy (char *dest, const char *src)
323{
324 size_t len;
325
326 if (src == NULL)
327 return dest;
328
329 len = strlen (src) + 1;
330 if (dest == NULL)
331 dest = malloc (len);
332 else if (strlen (dest) < len)
333 dest = realloc (dest, len);
334 if (dest == NULL)
335 terminate (STATE_UNKNOWN, "failed realloc in strscpy\n");
336
337 strncpy (dest, src, len);
338
339 return dest;
340}
341
342
343
344
345
346/******************************************************************************
347 *
348 * Concatenates one string to the end of another
349 *
350 * Given a pointer destination string, which may or may not already
351 * hold some text, and a source string with additional text (possibly
352 * NULL or empty), returns a pointer to a string that is the first
353 * string with the second concatenated to it. Uses realloc to free
354 * memory held by the dest argument if new storage space is required.
355 *
356 * Example:
357 *
358 * char *str=NULL;
359 * str = strscpy("This is a line of text with no trailing newline");
360 * str = strscat(str,"\n");
361 *
362 *****************************************************************************/
363
364char *
365strscat (char *dest, const char *src)
366{
367 size_t len, l2;
368
369 if (src)
370 l2 = strlen (src);
371 else
372 return dest;
373
374 if (dest)
375 len = strlen (dest);
376 else
377 len = 0;
378
379 dest = realloc (dest, len + l2 + 1);
380 if (dest == NULL)
381 terminate (STATE_UNKNOWN, "failed malloc in strscat\n");
382
383 strncpy (dest + len, src, l2);
384 dest[len + l2] = '\0';
385
386 return dest;
387}
388
389
390
391
392
393/******************************************************************************
394 *
395 * Returns a pointer to the next line of a multiline string buffer
396 *
397 * Given a pointer string, find the text following the next sequence
398 * of \r and \n characters. This has the effect of skipping blank
399 * lines as well
400 *
401 * Example:
402 *
403 * Given text as follows:
404 *
405 * ==============================
406 * This
407 * is
408 * a
409 *
410 * multiline string buffer
411 * ==============================
412 *
413 * int i=0;
414 * char *str=NULL;
415 * char *ptr=NULL;
416 * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
417 * ptr = str;
418 * while (ptr) {
419 * printf("%d %s",i++,firstword(ptr));
420 * ptr = strnl(ptr);
421 * }
422 *
423 * Produces the following:
424 *
425 * 1 This
426 * 2 is
427 * 3 a
428 * 4 multiline
429 *
430 * NOTE: The 'firstword()' function is conceptual only and does not
431 * exist in this package.
432 *
433 * NOTE: Although the second 'ptr' variable is not strictly needed in
434 * this example, it is good practice with these utilities. Once
435 * the * pointer is advance in this manner, it may no longer be
436 * handled with * realloc(). So at the end of the code fragment
437 * above, * strscpy(str,"foo") work perfectly fine, but
438 * strscpy(ptr,"foo") will * cause the the program to crash with
439 * a segmentation fault.
440 *
441 *****************************************************************************/
442
443char *
444strnl (char *str)
445{
446 size_t len;
447 if (str == NULL)
448 return NULL;
449 str = strpbrk (str, "\r\n");
450 if (str == NULL)
451 return NULL;
452 len = strspn (str, "\r\n");
453 if (str[len] == '\0')
454 return NULL;
455 str += len;
456 if (strlen (str) == 0)
457 return NULL;
458 return str;
459}
460
461
462
463
464
465/******************************************************************************
466 *
467 * Does a formatted print to a string variable
468 *
469 * Given a pointer destination string, which may or may not already
470 * hold some text, and a source string with additional text (possibly
471 * NULL or empty), returns a pointer to a string that cntains the
472 * results of the specified formatted print
473 *
474 * Example:
475 *
476 * char *str=NULL;
477 * str = ssprintf(str,"%d %s",1,"string");
478 *
479 *****************************************************************************/
480
481char *
482ssprintf (char *ptr, const char *fmt, ...)
483{
484 va_list ap;
485 int nchars;
486 size_t size;
487 char *str = NULL;
488
489 if (str == NULL) {
490 str = malloc (TXTBLK);
491 if (str == NULL)
492 terminate (STATE_UNKNOWN, "malloc failed in ssprintf");
493 size = TXTBLK;
494 }
495 else
496 size = max (strlen (str), TXTBLK);
497
498 va_start (ap, fmt);
499
500 while (1) {
501
502 nchars = vsnprintf (str, size, fmt, ap);
503
504 if (nchars > -1)
505 if (nchars < (int) size) {
506 va_end (ap);
507 str[nchars] = '\0';
508 if (ptr)
509 free (ptr);
510 return str;
511 }
512 else {
513 size = (size_t) (nchars + 1);
514 }
515
516 else
517 size *= 2;
518
519 str = realloc (str, size);
520
521 if (str == NULL)
522 terminate (STATE_UNKNOWN, "realloc failed in ssprintf");
523 }
524
525}
526
527
528
529
530
531/******************************************************************************
532 *
533 * Like strscpy, except only the portion of the source string up to
534 * the provided delimiter is copied.
535 *
536 * Example:
537 *
538 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
539 * printf("%s\n",str);
540 *
541 * Produces:
542 *
543 *This is a line of te
544 *
545 *****************************************************************************/
546
547char *
548strpcpy (char *dest, const char *src, const char *str)
549{
550 size_t len;
551
552 if (src)
553 len = strcspn (src, str);
554 else
555 return NULL;
556
557 if (dest == NULL || strlen (dest) < len)
558 dest = realloc (dest, len + 1);
559 if (dest == NULL)
560 terminate (STATE_UNKNOWN, "failed realloc in strpcpy\n");
561
562 strncpy (dest, src, len);
563 dest[len] = '\0';
564
565 return dest;
566}
567
568
569
570
571
572/******************************************************************************
573 *
574 * Like strscat, except only the portion of the source string up to
575 * the provided delimiter is copied.
576 *
577 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
578 * str = strpcat(str,"This is a line of text with no trailing newline","x");
579 * printf("%s\n",str);
580 *
581 *This is a line of texThis is a line of tex
582 *
583 *****************************************************************************/
584
585char *
586strpcat (char *dest, const char *src, const char *str)
587{
588 size_t len, l2;
589
590 if (dest)
591 len = strlen (dest);
592 else
593 len = 0;
594
595 if (src) {
596 l2 = strcspn (src, str);
597 }
598 else {
599 return dest;
600 }
601
602 dest = realloc (dest, len + l2 + 1);
603 if (dest == NULL)
604 terminate (STATE_UNKNOWN, "failed malloc in strscat\n");
605
606 strncpy (dest + len, src, l2);
607 dest[len + l2] = '\0';
608
609 return dest;
610}
diff --git a/plugins/utils.h.in b/plugins/utils.h.in
new file mode 100644
index 00000000..a21d63d6
--- /dev/null
+++ b/plugins/utils.h.in
@@ -0,0 +1,92 @@
1/* header file for nagios plugins uitls.c */
2
3/* this file should be included in all plugins */
4
5/* The purpose of this package is to provide safer alternantives to C
6functions that might otherwise be vulnerable to hacking. This
7currently includes a standard suite of validation routines to be sure
8that an string argument acually converts to its intended type and a
9suite of string handling routine that do their own memory management
10in order to resist overflow attacks. In addition, a few functions are
11provided to standardize version and error reporting accross the entire
12suite of plugins. */
13
14/* Standardize version information, termination */
15
16char *my_basename (char *);
17void support (void);
18char *clean_revstring (const char *revstring);
19void print_revision (char *, const char *);
20void terminate (int result, char *msg, ...);
21extern RETSIGTYPE timeout_alarm_handler (int);
22
23/* Handle timeouts */
24
25time_t start_time, end_time;
26int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
27
28/* Test input types */
29
30int is_host (char *);
31int is_dotted_quad (char *);
32int is_hostname (char *);
33
34int is_integer (char *);
35int is_intpos (char *);
36int is_intneg (char *);
37int is_intnonneg (char *);
38int is_intpercent (char *);
39
40int is_numeric (char *);
41int is_positive (char *);
42int is_negative (char *);
43int is_nonnegative (char *);
44int is_percentage (char *);
45
46int is_option (char *);
47
48/* Handle strings safely */
49
50void strip (char *buffer);
51char *strscpy (char *dest, char *src);
52char *strscat (char *dest, char *src);
53char *strnl (char *str);
54char *ssprintf (char *str, const char *fmt, ...);
55char *strpcpy (char *dest, const char *src, const char *str);
56char *strpcat (char *dest, const char *src, const char *str);
57
58#define max(a,b) ((a)>(b))?(a):(b)
59
60#define usage(msg) {\
61 printf(msg);\
62 print_usage();\
63exit(STATE_UNKNOWN);\
64}
65
66#define usage2(msg,arg) {\
67 printf("%s: %s - %s\n",PROGNAME,msg,arg);\
68 print_usage();\
69 exit(STATE_UNKNOWN);\
70}
71
72#define state_text(a) \
73(a)==0?"OK":\
74(a)==1?"WARNING":\
75(a)==2?"CRITICAL":\
76(a)==-2?"DEPENDENT":\
77"UNKNOWN"
78
79/* The idea here is that, although not every plugin will use all of these,
80 most will or should. Therefore, for consistency, these very common
81 options should have only these meanings throughout the overall suite */
82
83#define STD_OPTS "Vvht:c:w:H:F:"
84#define STD_OPTS_LONG \
85{"version",no_argument,0,'V'},\
86{"verbose",no_argument,0,'v'},\
87{"help",no_argument,0,'h'},\
88{"timeout",required_argument,0,'t'},\
89{"critical",required_argument,0,'c'},\
90{"warning",required_argument,0,'w'},\
91{"hostname",required_argument,0,'H'},\
92{"file",required_argument,0,'F'}
diff --git a/plugins/version.h.in b/plugins/version.h.in
new file mode 100644
index 00000000..e41aaee0
--- /dev/null
+++ b/plugins/version.h.in
@@ -0,0 +1,2 @@
1#define PACKAGE_VERSION "1.3.0-alpha1"
2#define CVS_DATE "$Date$"