diff options
Diffstat (limited to 'plugins')
83 files changed, 20385 insertions, 0 deletions
diff --git a/plugins/.cvsignore b/plugins/.cvsignore new file mode 100644 index 0000000..58f14fe --- /dev/null +++ b/plugins/.cvsignore | |||
@@ -0,0 +1,43 @@ | |||
1 | check_disk | ||
2 | check_dns | ||
3 | check_dummy | ||
4 | check_ftp | ||
5 | check_http | ||
6 | check_imap | ||
7 | check_load | ||
8 | check_mrtg | ||
9 | check_mrtgtraf | ||
10 | check_nagios | ||
11 | check_nntp | ||
12 | check_nwstat | ||
13 | check_overcr | ||
14 | check_ping | ||
15 | check_pop | ||
16 | check_procs | ||
17 | check_real | ||
18 | check_reply | ||
19 | check_smtp | ||
20 | check_ssh | ||
21 | check_tcp | ||
22 | check_time | ||
23 | check_udp | ||
24 | check_ups | ||
25 | check_users | ||
26 | check_vsz | ||
27 | check_by_ssh | ||
28 | urlize | ||
29 | check_pgsql | ||
30 | check_radius | ||
31 | check_ldap | ||
32 | check_mysql | ||
33 | check_netsaint | ||
34 | check_hpjd | ||
35 | check_snmp | ||
36 | check_by_ssh | ||
37 | check_swap | ||
38 | stamp-h* | ||
39 | *.h | ||
40 | Makefile | ||
41 | Makefile.in | ||
42 | config.h.in | ||
43 | .deps | ||
diff --git a/plugins/Makefile.am b/plugins/Makefile.am new file mode 100644 index 0000000..64b14bf --- /dev/null +++ b/plugins/Makefile.am | |||
@@ -0,0 +1,139 @@ | |||
1 | ## Process this file with automake to produce Makefile.in | ||
2 | |||
3 | VPATH = $(top_srcdir) $(top_srcdir)/plugins $(top_srcdir)/plugins/t | ||
4 | |||
5 | INCLUDES = @LDAPINCLUDE@ @PGINCLUDE@ @SSLINCLUDE@ | ||
6 | |||
7 | libexec_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 | |||
15 | EXTRA_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 | |||
19 | EXTRA_DIST = t utils.c netutils.c popen.c getopt.h getopt.c getopt1.c snprintf.c | ||
20 | |||
21 | PLUGINHDRS = common.h config.h | ||
22 | |||
23 | BASEOBJS = utils.o | ||
24 | NETOBJS = netutils.o $(BASEOBJS) | ||
25 | NETLIBS = $(NETOBJS) $(SOCKETLIBS) | ||
26 | |||
27 | TESTS_ENVIRONMENT = perl -I $(top_builddir) -I $(top_srcdir) | ||
28 | |||
29 | TESTS = @PLUGIN_TEST@ | ||
30 | |||
31 | test: | ||
32 | perl -I $(top_builddir) -I $(top_srcdir) ../test.pl | ||
33 | |||
34 | AM_INSTALL_PROGRAM_FLAGS = @INSTALL_OPTS@ | ||
35 | |||
36 | ############################################################################## | ||
37 | # the actual targets | ||
38 | |||
39 | check_dig_LDADD = $(BASEOBJS) popen.o | ||
40 | check_disk_LDADD = $(BASEOBJS) popen.o | ||
41 | check_dns_LDADD = $(BASEOBJS) popen.o | ||
42 | check_dummy_LDADD = $(BASEOBJS) | ||
43 | check_fping_LDADD = $(BASEOBJS) popen.o | ||
44 | check_ftp_LDADD = $(NETLIBS) | ||
45 | check_game_LDADD = $(BASEOBJS) | ||
46 | check_http_LDADD = $(NETLIBS) $(SSLLIBS) | ||
47 | check_hpjd_LDADD = $(BASEOBJS) popen.o | ||
48 | check_imap_LDADD = $(NETLIBS) | ||
49 | check_ldap_LDADD = $(NETLIBS) $(LDAPLIBS) | ||
50 | check_load_LDADD = $(BASEOBJS) popen.o | ||
51 | check_mrtg_LDADD = $(BASEOBJS) | ||
52 | check_mrtgtraf_LDADD = $(BASEOBJS) | ||
53 | check_mysql_LDADD = $(BASEOBJS) $(MYSQLLIBS) | ||
54 | check_nagios_LDADD = $(BASEOBJS) popen.o | ||
55 | check_nntp_LDADD = $(NETLIBS) | ||
56 | check_nt_LDADD = $(NETLIBS) | ||
57 | check_nwstat_LDADD = $(NETLIBS) | ||
58 | check_overcr_LDADD = $(NETLIBS) | ||
59 | check_pgsql_LDADD = $(BASEOBJS) $(PGLIBS) | ||
60 | check_ping_LDADD = $(BASEOBJS) popen.o | ||
61 | check_pop_LDADD = $(NETLIBS) | ||
62 | check_procs_LDADD = $(BASEOBJS) popen.o | ||
63 | check_radius_LDADD = $(BASEOBJS) $(RADIUSLIBS) | ||
64 | check_real_LDADD = $(NETLIBS) | ||
65 | check_snmp_LDADD = $(BASEOBJS) popen.o | ||
66 | check_smtp_LDADD = $(NETLIBS) | ||
67 | check_ssh_LDADD = $(NETLIBS) | ||
68 | check_swap_LDADD = $(BASEOBJS) popen.o | ||
69 | check_tcp_LDADD = $(NETLIBS) $(SSLLIBS) | ||
70 | check_time_LDADD = $(NETLIBS) | ||
71 | check_udp_LDADD = $(NETLIBS) | ||
72 | check_ups_LDADD = $(NETLIBS) | ||
73 | check_users_LDADD = $(BASEOBJS) popen.o | ||
74 | check_vsz_LDADD = $(BASEOBJS) popen.o | ||
75 | check_by_ssh_LDADD = $(BASEOBJS) popen.o | ||
76 | urlize_LDADD = $(BASEOBJS) popen.o | ||
77 | |||
78 | check_dig_DEPENDENCIES = check_dig.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
79 | check_disk_DEPENDENCIES = check_disk.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
80 | check_dns_DEPENDENCIES = check_dns.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
81 | check_dummy_DEPENDENCIES = check_dummy.c $(DEPLIBS) | ||
82 | check_fping_DEPENDENCIES = check_fping.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
83 | check_ftp_DEPENDENCIES = check_ftp.c $(NETOBJS) $(DEPLIBS) | ||
84 | check_game_DEPENDENCIES = check_game.c $(DEPLIBS) | ||
85 | check_http_DEPENDENCIES = check_http.c $(NETOBJS) $(DEPLIBS) | ||
86 | check_hpjd_DEPENDENCIES = check_hpjd.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
87 | check_imap_DEPENDENCIES = check_imap.c $(NETOBJS) $(DEPLIBS) | ||
88 | check_ldap_DEPENDENCIES = check_ldap.c $(NETOBJS) $(DEPLIBS) | ||
89 | check_load_DEPENDENCIES = check_load.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
90 | check_mrtg_DEPENDENCIES = check_mrtg.c $(DEPLIBS) | ||
91 | check_mrtgtraf_DEPENDENCIES = check_mrtgtraf.c $(DEPLIBS) | ||
92 | check_mysql_DEPENDENCIES = check_mysql.c $(DEPLIBS) | ||
93 | check_nagios_DEPENDENCIES = check_nagios.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
94 | check_nntp_DEPENDENCIES = check_nntp.c $(NETOBJS) $(DEPLIBS) | ||
95 | check_nt_DEPENDENCIES = check_nt.c $(NETOBJS) $(DEPLIBS) | ||
96 | check_nwstat_DEPENDENCIES = check_nwstat.c $(NETOBJS) $(DEPLIBS) | ||
97 | check_overcr_DEPENDENCIES = check_overcr.c $(NETOBJS) $(DEPLIBS) | ||
98 | check_pgsql_DEPENDENCIES = check_pgsql.c $(DEPLIBS) | ||
99 | check_ping_DEPENDENCIES = check_ping.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
100 | check_pop_DEPENDENCIES = check_pop.c $(NETOBJS) $(DEPLIBS) | ||
101 | check_procs_DEPENDENCIES = check_procs.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
102 | check_radius_DEPENDENCIES = check_radius.c $(DEPLIBS) | ||
103 | check_real_DEPENDENCIES = check_real.c $(NETOBJS) $(DEPLIBS) | ||
104 | check_snmp_DEPENDENCIES = check_snmp.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
105 | check_smtp_DEPENDENCIES = check_smtp.c $(NETOBJS) $(DEPLIBS) | ||
106 | check_ssh_DEPENDENCIES = check_ssh.c $(NETOBJS) $(DEPLIBS) | ||
107 | check_swap_DEPENDENCIES = check_swap.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
108 | check_tcp_DEPENDENCIES = check_tcp.c $(NETOBJS) $(DEPLIBS) | ||
109 | check_time_DEPENDENCIES = check_time.c $(NETOBJS) $(DEPLIBS) | ||
110 | check_udp_DEPENDENCIES = check_udp.c $(NETOBJS) $(DEPLIBS) | ||
111 | check_ups_DEPENDENCIES = check_ups.c $(NETOBJS) $(DEPLIBS) | ||
112 | check_users_DEPENDENCIES = check_users.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
113 | check_vsz_DEPENDENCIES = check_vsz.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
114 | check_by_ssh_DEPENDENCIES = check_by_ssh.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
115 | urlize_DEPENDENCIES = urlize.c $(BASEOBJS) popen.o $(DEPLIBS) | ||
116 | |||
117 | ############################################################################## | ||
118 | # secondary dependencies | ||
119 | |||
120 | popen.o: popen.c popen.h $(PLUGINHDRS) | ||
121 | |||
122 | utils.o: utils.c utils.h $(PLUGINHDRS) | ||
123 | |||
124 | netutils.o: netutils.c netutils.h $(PLUGINHDRS) | ||
125 | |||
126 | getopt.o: getopt.c getopt.h | ||
127 | $(COMPILE) -c $(srcdir)/getopt.c -o $@ | ||
128 | |||
129 | getopt1.o: getopt1.c getopt.h | ||
130 | $(COMPILE) -c $(srcdir)/getopt1.c -o $@ | ||
131 | |||
132 | snprintf.o: snprintf.c | ||
133 | $(COMPILE) @NEED_VA_LIST@ -c $? -o $@ | ||
134 | |||
135 | libgetopt.a: getopt.o getopt1.o | ||
136 | $(AR) -r $@ getopt.o getopt1.o | ||
137 | |||
138 | libsnprintf.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 0000000..a81b333 --- /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 | |||
39 | int process_arguments (int, char **); | ||
40 | int call_getopt (int, char **); | ||
41 | int validate_arguments (void); | ||
42 | void print_help (char *command_name); | ||
43 | void print_usage (void); | ||
44 | |||
45 | |||
46 | int commands; | ||
47 | char *remotecmd = NULL; | ||
48 | char *comm = NULL; | ||
49 | char *hostname = NULL; | ||
50 | char *outputfile = NULL; | ||
51 | char *host_shortname = NULL; | ||
52 | char *servicelist = NULL; | ||
53 | int passive = FALSE; | ||
54 | int verbose = FALSE; | ||
55 | |||
56 | |||
57 | int | ||
58 | main (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 */ | ||
176 | int | ||
177 | process_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 */ | ||
229 | int | ||
230 | call_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 | |||
343 | int | ||
344 | validate_arguments (void) | ||
345 | { | ||
346 | if (remotecmd == NULL || hostname == NULL) | ||
347 | return ERROR; | ||
348 | return OK; | ||
349 | } | ||
350 | |||
351 | |||
352 | |||
353 | |||
354 | |||
355 | void | ||
356 | print_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 | |||
403 | void | ||
404 | print_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 0000000..57609ac --- /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 | |||
20 | int process_arguments (int, char **); | ||
21 | int call_getopt (int, char **); | ||
22 | int validate_arguments (void); | ||
23 | int check_disk (int usp, int free_disk); | ||
24 | void print_help (void); | ||
25 | void print_usage (void); | ||
26 | |||
27 | char *query_address = NULL; | ||
28 | char *dns_server = NULL; | ||
29 | int verbose = FALSE; | ||
30 | |||
31 | int | ||
32 | main (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 */ | ||
138 | int | ||
139 | process_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 | |||
174 | int | ||
175 | call_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 | |||
250 | int | ||
251 | validate_arguments (void) | ||
252 | { | ||
253 | return OK; | ||
254 | } | ||
255 | |||
256 | |||
257 | |||
258 | |||
259 | |||
260 | void | ||
261 | print_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 | |||
289 | void | ||
290 | print_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 0000000..d7aad07 --- /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 | |||
41 | int process_arguments (int, char **); | ||
42 | int call_getopt (int, char **); | ||
43 | int validate_arguments (void); | ||
44 | int check_disk (int usp, int free_disk); | ||
45 | void print_help (void); | ||
46 | void print_usage (void); | ||
47 | |||
48 | int w_df = -1; | ||
49 | int c_df = -1; | ||
50 | float w_dfp = -1.0; | ||
51 | float c_dfp = -1.0; | ||
52 | char *path = NULL; | ||
53 | int verbose = FALSE; | ||
54 | |||
55 | int | ||
56 | main (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 */ | ||
135 | int | ||
136 | process_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 | |||
170 | int | ||
171 | call_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 | |||
272 | int | ||
273 | validate_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 | |||
298 | int | ||
299 | check_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 | |||
316 | void | ||
317 | print_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 | |||
346 | void | ||
347 | print_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 0000000..eaff437 --- /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 | |||
50 | int process_arguments (int, char **); | ||
51 | int call_getopt (int, char **); | ||
52 | int validate_arguments (void); | ||
53 | void print_usage (char *); | ||
54 | void print_help (char *); | ||
55 | int error_scan (char *); | ||
56 | |||
57 | #define ADDRESS_LENGTH 256 | ||
58 | char query_address[ADDRESS_LENGTH] = ""; | ||
59 | char dns_server[ADDRESS_LENGTH] = ""; | ||
60 | char ptr_server[ADDRESS_LENGTH] = ""; | ||
61 | int verbose = FALSE; | ||
62 | |||
63 | int | ||
64 | main (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 | |||
186 | int | ||
187 | error_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 */ | ||
245 | int | ||
246 | process_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 | |||
285 | int | ||
286 | call_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 | |||
376 | int | ||
377 | validate_arguments () | ||
378 | { | ||
379 | if (query_address[0] == 0) | ||
380 | return ERROR; | ||
381 | else | ||
382 | return OK; | ||
383 | } | ||
384 | |||
385 | void | ||
386 | print_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 | |||
392 | void | ||
393 | print_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 0000000..c2a5b7e --- /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 | |||
40 | void print_help (char *); | ||
41 | void print_usage (char *); | ||
42 | |||
43 | int | ||
44 | main (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 | |||
84 | void | ||
85 | print_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 | |||
96 | void | ||
97 | print_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 0000000..f6531a5 --- /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 | |||
44 | int textscan (char *buf); | ||
45 | int process_arguments (int, char **); | ||
46 | int get_threshold (char *arg, char *rv[2]); | ||
47 | void print_usage (void); | ||
48 | void print_help (void); | ||
49 | |||
50 | char *server_name = NULL; | ||
51 | int cpl = UNKNOWN_PACKET_LOSS; | ||
52 | int wpl = UNKNOWN_PACKET_LOSS; | ||
53 | double crta = UNKNOWN_TRIP_TIME; | ||
54 | double wrta = UNKNOWN_TRIP_TIME; | ||
55 | int packet_size = PACKET_SIZE; | ||
56 | int packet_count = PACKET_COUNT; | ||
57 | int verbose = FALSE; | ||
58 | |||
59 | int | ||
60 | main (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 | |||
120 | int | ||
121 | textscan (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 */ | ||
180 | int | ||
181 | process_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 | |||
295 | int | ||
296 | get_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 | |||
339 | void | ||
340 | print_usage (void) | ||
341 | { | ||
342 | printf ("Usage: %s <host_address>\n", PROGNAME); | ||
343 | } | ||
344 | |||
345 | |||
346 | |||
347 | |||
348 | |||
349 | void | ||
350 | print_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 0000000..1c65d64 --- /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 | |||
48 | int process_arguments (int, char **); | ||
49 | int call_getopt (int, char **); | ||
50 | void print_usage (void); | ||
51 | void print_help (void); | ||
52 | |||
53 | time_t start_time, end_time; | ||
54 | int server_port = FTP_PORT; | ||
55 | char *server_address = NULL; | ||
56 | char *server_expect = NULL; | ||
57 | int warning_time = 0; | ||
58 | int check_warning_time = FALSE; | ||
59 | int critical_time = 0; | ||
60 | int check_critical_time = FALSE; | ||
61 | int verbose = FALSE; | ||
62 | |||
63 | |||
64 | int | ||
65 | main (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 */ | ||
152 | int | ||
153 | process_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 | |||
197 | int | ||
198 | call_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 | |||
295 | void | ||
296 | print_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 | |||
307 | void | ||
308 | print_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 0000000..63d1be6 --- /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 | |||
71 | int 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 | |||
80 | char server_ip[MAX_HOST_ADDRESS_LENGTH]; | ||
81 | char game_type[MAX_INPUT_BUFFER]; | ||
82 | char port[MAX_INPUT_BUFFER]; | ||
83 | |||
84 | int qstat_game_field = 2; | ||
85 | int qstat_map_field = 3; | ||
86 | int qstat_ping_field = 5; | ||
87 | |||
88 | |||
89 | int | ||
90 | main (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 | |||
214 | int | ||
215 | process_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 0000000..8234abd --- /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 | |||
86 | int process_arguments (int, char **); | ||
87 | int call_getopt (int, char **); | ||
88 | int validate_arguments (void); | ||
89 | void print_help (void); | ||
90 | void print_usage (void); | ||
91 | |||
92 | char *community = NULL; | ||
93 | char *address = NULL; | ||
94 | |||
95 | int | ||
96 | main (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 */ | ||
384 | int | ||
385 | process_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 | |||
433 | int | ||
434 | call_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 | |||
500 | int | ||
501 | validate_arguments (void) | ||
502 | { | ||
503 | return OK; | ||
504 | } | ||
505 | |||
506 | |||
507 | |||
508 | |||
509 | |||
510 | void | ||
511 | print_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 | |||
535 | void | ||
536 | print_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 0000000..db5d50d --- /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 "\ | ||
39 | This plugin tests the HTTP service on the specified host. It can test\n\ | ||
40 | normal (http) and secure (https) servers, follow redirects, search for\n\ | ||
41 | strings and regular expressions, check connection times, and report on\n\ | ||
42 | certificate 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 "\ | ||
97 | This plugin will attempt to open an HTTP connection with the host. Successul\n\ | ||
98 | connects return STATE_OK, refusals and timeouts return STATE_CRITICAL, other\n\ | ||
99 | errors return STATE_UNKNOWN. Successful connects, but incorrect reponse\n\ | ||
100 | messages from the host result in STATE_WARNING return values. If you are\n\ | ||
101 | checking 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 "\ | ||
105 | This plugin can also check whether an SSL enabled web server is able to\n\ | ||
106 | serve content (optionally within a specified time) or whether the X509 \n\ | ||
107 | certificate is still valid for the specified number of days.\n\n\ | ||
108 | CHECK CONTENT: check_http -w 5 -c 10 --ssl www.verisign.com\n\n\ | ||
109 | When the 'www.verisign.com' server returns its content within 5 seconds, a\n\ | ||
110 | STATE_OK will be returned. When the server returns its content but exceeds\n\ | ||
111 | the 5-second threshold, a STATE_WARNING will be returned. When an error occurs,\n\ | ||
112 | a STATE_CRITICAL will be returned.\n\n\ | ||
113 | CHECK CERTIFICATE: check_http www.verisign.com -C 14\n\n\ | ||
114 | When the certificate of 'www.verisign.com' is valid for more than 14 days, a\n\ | ||
115 | STATE_OK is returned. When the certificate is still valid, but for less than\n\ | ||
116 | 14 days, a STATE_WARNING is returned. A STATE_CRITICAL will be returned when\n\ | ||
117 | the 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 | ||
140 | int check_cert = FALSE; | ||
141 | int days_till_exp; | ||
142 | unsigned char *randbuff; | ||
143 | SSL_CTX *ctx; | ||
144 | SSL *ssl; | ||
145 | X509 *server_cert; | ||
146 | int connect_SSL (void); | ||
147 | int 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> | ||
154 | regex_t preg; | ||
155 | regmatch_t pmatch[REGS]; | ||
156 | char regexp[MAX_RE_SIZE]; | ||
157 | char errbuf[MAX_INPUT_BUFFER]; | ||
158 | int cflags = REG_NOSUB | REG_EXTENDED | REG_NEWLINE; | ||
159 | int 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 | |||
179 | time_t start_time, end_time; | ||
180 | char timestamp[10] = ""; | ||
181 | int specify_port = FALSE; | ||
182 | int server_port = HTTP_PORT; | ||
183 | char server_port_text[6] = ""; | ||
184 | char server_type[6] = "http"; | ||
185 | char *server_address = NULL; | ||
186 | char *host_name = NULL; | ||
187 | char *server_url = NULL; | ||
188 | int server_url_length = 0; | ||
189 | char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT; | ||
190 | char string_expect[MAX_INPUT_BUFFER] = ""; | ||
191 | int warning_time = 0; | ||
192 | int check_warning_time = FALSE; | ||
193 | int critical_time = 0; | ||
194 | int check_critical_time = FALSE; | ||
195 | char user_auth[MAX_INPUT_BUFFER] = ""; | ||
196 | int display_html = FALSE; | ||
197 | int onredirect = STATE_OK; | ||
198 | int use_ssl = FALSE; | ||
199 | int verbose = FALSE; | ||
200 | int sd; | ||
201 | char *http_method = NULL; | ||
202 | char *http_post_data = NULL; | ||
203 | char buffer[MAX_INPUT_BUFFER]; | ||
204 | |||
205 | void print_usage (void); | ||
206 | void print_help (void); | ||
207 | int process_arguments (int, char **); | ||
208 | int call_getopt (int, char **); | ||
209 | static char *base64 (char *bin, int len); | ||
210 | int check_http (void); | ||
211 | int my_recv (void); | ||
212 | int my_close (void); | ||
213 | |||
214 | int | ||
215 | main (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 */ | ||
268 | int | ||
269 | process_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 */ | ||
477 | static char * | ||
478 | base64 (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 | |||
520 | int | ||
521 | check_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 | ||
872 | int | ||
873 | connect_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 | ||
921 | int | ||
922 | check_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 | |||
1000 | int | ||
1001 | my_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 | |||
1018 | int | ||
1019 | my_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 | |||
1038 | void | ||
1039 | print_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 | |||
1055 | void | ||
1056 | print_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 0000000..869f7dc --- /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; | ||
67 | typedef 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; | ||
76 | typedef struct value_s | ||
77 | { | ||
78 | __u8 id; | ||
79 | __u16 status; | ||
80 | __u8 value; | ||
81 | __u8 vendor[8]; | ||
82 | } | ||
83 | __attribute__ ((packed)) value_t; | ||
84 | typedef 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; | ||
99 | struct | ||
100 | { | ||
101 | __u8 value; | ||
102 | char *text; | ||
103 | } | ||
104 | offline_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 | }; | ||
119 | struct | ||
120 | { | ||
121 | __u8 value; | ||
122 | char *text; | ||
123 | } | ||
124 | smart_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 */ | ||
138 | enum SmartCommand | ||
139 | { SMART_CMD_ENABLE, SMART_CMD_DISABLE, SMART_CMD_IMMEDIATE_OFFLINE, | ||
140 | SMART_CMD_AUTO_OFFLINE | ||
141 | }; | ||
142 | char * | ||
143 | get_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 | } | ||
153 | int | ||
154 | smart_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 | } | ||
166 | int | ||
167 | values_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 | } | ||
188 | int | ||
189 | net_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 | } | ||
243 | void | ||
244 | print_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 | } | ||
251 | void | ||
252 | print_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 | } | ||
275 | void | ||
276 | print_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 | } | ||
290 | int | ||
291 | smart_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 | } | ||
305 | int | ||
306 | smart_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 | } | ||
318 | void | ||
319 | show_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 | } | ||
325 | void | ||
326 | show_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 | } | ||
337 | int | ||
338 | main (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 0000000..5ec0439 --- /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 | |||
40 | int process_arguments (int, char **); | ||
41 | int call_getopt (int, char **); | ||
42 | int validate_arguments (void); | ||
43 | int check_disk (int usp, int free_disk); | ||
44 | void print_help (void); | ||
45 | void print_usage (void); | ||
46 | |||
47 | int server_port = PORT; | ||
48 | char *server_address = NULL; | ||
49 | char *server_expect = NULL; | ||
50 | int warning_time = 0; | ||
51 | int check_warning_time = FALSE; | ||
52 | int critical_time = 0; | ||
53 | int check_critical_time = FALSE; | ||
54 | int verbose = FALSE; | ||
55 | |||
56 | int | ||
57 | main (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 */ | ||
127 | int | ||
128 | process_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 | |||
176 | int | ||
177 | call_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 | |||
286 | int | ||
287 | validate_arguments (void) | ||
288 | { | ||
289 | return OK; | ||
290 | } | ||
291 | |||
292 | |||
293 | |||
294 | |||
295 | |||
296 | void | ||
297 | print_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 | |||
332 | void | ||
333 | print_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 0000000..d3f0615 --- /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 | |||
36 | int process_arguments (int, char **); | ||
37 | int call_getopt (int, char **); | ||
38 | int validate_arguments (void); | ||
39 | static void print_help (void); | ||
40 | static void print_usage (void); | ||
41 | |||
42 | char ld_defattr[] = "(objectclass=*)"; | ||
43 | char *ld_attr = ld_defattr; | ||
44 | char *ld_host = NULL, *ld_base = NULL, *ld_passwd = NULL, *ld_binddn = NULL; | ||
45 | unsigned int ld_port = 389; | ||
46 | int warn_time = UNKNOWN, crit_time = UNKNOWN; | ||
47 | |||
48 | int | ||
49 | main (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 */ | ||
122 | int | ||
123 | process_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 | |||
148 | int | ||
149 | call_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 | |||
245 | int | ||
246 | validate_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 */ | ||
261 | static void | ||
262 | print_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 | |||
284 | static void | ||
285 | print_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 0000000..6673b1d --- /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 | |||
49 | int process_arguments (int argc, char **argv); | ||
50 | int call_getopt (int argc, char **argv); | ||
51 | int validate_arguments (void); | ||
52 | void print_usage (void); | ||
53 | void print_help (void); | ||
54 | |||
55 | float wload1 = -1, wload5 = -1, wload15 = -1; | ||
56 | float cload1 = -1, cload5 = -1, cload15 = -1; | ||
57 | |||
58 | int | ||
59 | main (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 */ | ||
152 | int | ||
153 | process_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 | |||
186 | int | ||
187 | call_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 | |||
272 | int | ||
273 | validate_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 | |||
288 | void | ||
289 | print_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 | |||
300 | void | ||
301 | print_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 0000000..b86686d --- /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 "\ | ||
31 | This plugin will check either the average or maximum value of one of the\n\ | ||
32 | two 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 "\ | ||
64 | If the value exceeds the <vwl> threshold, a WARNING status is returned. If\n\ | ||
65 | the value exceeds the <vcl> threshold, a CRITICAL status is returned. If\n\ | ||
66 | the data in the log file is older than <expire_minutes> old, a WARNING\n\ | ||
67 | status is returned and a warning message is printed.\n\ | ||
68 | \n\ | ||
69 | This plugin is useful for monitoring MRTG data that does not correspond to\n\ | ||
70 | bandwidth usage. (Use the check_mrtgtraf plugin for monitoring bandwidth).\n\ | ||
71 | It can be used to monitor any kind of data that MRTG is monitoring - errors,\n\ | ||
72 | packets/sec, etc. I use MRTG in conjuction with the Novell NLM that allows\n\ | ||
73 | me to track processor utilization, user connections, drive space, etc and\n\ | ||
74 | this plugin works well for monitoring that kind of data as well.\n\ | ||
75 | \n\ | ||
76 | Notes:\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 | |||
88 | int process_arguments (int, char **); | ||
89 | int call_getopt (int, char **); | ||
90 | int validate_arguments (void); | ||
91 | void print_help (void); | ||
92 | void print_usage (void); | ||
93 | |||
94 | char *log_file = NULL; | ||
95 | int expire_minutes = 0; | ||
96 | int use_average = TRUE; | ||
97 | int variable_number = -1; | ||
98 | unsigned long value_warning_threshold = 0L; | ||
99 | unsigned long value_critical_threshold = 0L; | ||
100 | char *value_label = NULL; | ||
101 | char *units_label = NULL; | ||
102 | |||
103 | int | ||
104 | main (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 (¤t_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 */ | ||
213 | int | ||
214 | process_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 | |||
290 | int | ||
291 | call_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 | |||
382 | int | ||
383 | validate_arguments (void) | ||
384 | { | ||
385 | if (variable_number == -1) | ||
386 | usage ("You must supply the variable number\n"); | ||
387 | |||
388 | return OK; | ||
389 | } | ||
390 | |||
391 | void | ||
392 | print_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 | |||
401 | void | ||
402 | print_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 0000000..11f5146 --- /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 | |||
57 | int process_arguments (int, char **); | ||
58 | int call_getopt (int, char **); | ||
59 | int validate_arguments (void); | ||
60 | void print_help (void); | ||
61 | void print_usage (void); | ||
62 | |||
63 | char *log_file = NULL; | ||
64 | int expire_minutes = -1; | ||
65 | int use_average = TRUE; | ||
66 | unsigned long incoming_warning_threshold = 0L; | ||
67 | unsigned long incoming_critical_threshold = 0L; | ||
68 | unsigned long outgoing_warning_threshold = 0L; | ||
69 | unsigned long outgoing_critical_threshold = 0L; | ||
70 | |||
71 | int | ||
72 | main (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 (¤t_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 */ | ||
231 | int | ||
232 | process_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 | |||
290 | int | ||
291 | call_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 | |||
371 | int | ||
372 | validate_arguments (void) | ||
373 | { | ||
374 | return OK; | ||
375 | } | ||
376 | |||
377 | |||
378 | |||
379 | |||
380 | |||
381 | void | ||
382 | print_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 | |||
411 | void | ||
412 | print_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 0000000..50836f9 --- /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 | |||
25 | char *db_user = NULL; | ||
26 | char *db_host = NULL; | ||
27 | char *db_pass = NULL; | ||
28 | char *db = NULL; | ||
29 | unsigned int db_port = MYSQL_PORT; | ||
30 | |||
31 | int process_arguments (int, char **); | ||
32 | int call_getopt (int, char **); | ||
33 | int validate_arguments (void); | ||
34 | int check_disk (int usp, int free_disk); | ||
35 | void print_help (void); | ||
36 | void print_usage (void); | ||
37 | |||
38 | int | ||
39 | main (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 */ | ||
124 | int | ||
125 | process_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 | |||
166 | int | ||
167 | call_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 | |||
246 | int | ||
247 | validate_arguments (void) | ||
248 | { | ||
249 | return OK; | ||
250 | } | ||
251 | |||
252 | |||
253 | |||
254 | |||
255 | |||
256 | void | ||
257 | print_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 | |||
290 | void | ||
291 | print_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 0000000..0425835 --- /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 | |||
35 | int process_arguments (int, char **); | ||
36 | void print_usage (void); | ||
37 | void print_help (void); | ||
38 | |||
39 | char *status_log = NULL; | ||
40 | char *process_string = NULL; | ||
41 | int expire_minutes = 0; | ||
42 | |||
43 | int | ||
44 | main (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 (¤t_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 */ | ||
142 | int | ||
143 | process_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 | |||
229 | void | ||
230 | print_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 | |||
241 | void | ||
242 | print_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 0000000..4bdc83a --- /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 | |||
52 | int process_arguments (int, char **); | ||
53 | int call_getopt (int, char **); | ||
54 | int validate_arguments (void); | ||
55 | int check_disk (int usp, int free_disk); | ||
56 | void print_help (void); | ||
57 | void print_usage (void); | ||
58 | |||
59 | int server_port = PORT; | ||
60 | char *server_expect = NULL; | ||
61 | char *server_address = NULL; | ||
62 | char *newsgroup = NULL; | ||
63 | int check_newsgroup = FALSE; | ||
64 | int send_modereader = FALSE; | ||
65 | int warning_time = 0; | ||
66 | int check_warning_time = FALSE; | ||
67 | int critical_time = 0; | ||
68 | int check_critical_time = FALSE; | ||
69 | int verbose = FALSE; | ||
70 | |||
71 | |||
72 | int | ||
73 | main (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 */ | ||
193 | int | ||
194 | process_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 | |||
242 | int | ||
243 | call_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 | |||
360 | int | ||
361 | validate_arguments (void) | ||
362 | { | ||
363 | return OK; | ||
364 | } | ||
365 | |||
366 | |||
367 | |||
368 | |||
369 | |||
370 | void | ||
371 | print_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 | |||
410 | void | ||
411 | print_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 0000000..ed0dc98 --- /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 | |||
50 | char *server_address=NULL; | ||
51 | char *volume_name=NULL; | ||
52 | int server_port=PORT; | ||
53 | char *value_list=NULL; | ||
54 | char *req_password=NULL; | ||
55 | unsigned long lvalue_list[MAX_VALUE_LIST]; | ||
56 | unsigned long warning_value=0L; | ||
57 | unsigned long critical_value=0L; | ||
58 | int check_value_list=FALSE; | ||
59 | int check_warning_value=FALSE; | ||
60 | int check_critical_value=FALSE; | ||
61 | int vars_to_check=CHECK_NONE; | ||
62 | int show_all=FALSE; | ||
63 | |||
64 | #define PROGNAME "check_nt" | ||
65 | |||
66 | int process_arguments(int, char **); | ||
67 | void print_usage(void); | ||
68 | void print_help(void); | ||
69 | void preparelist(char *string); | ||
70 | |||
71 | int 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 */ | ||
342 | int 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 | |||
465 | void 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 | |||
471 | void 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 | |||
520 | int 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 | |||
539 | void 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 0000000..e142670 --- /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 "\ | ||
31 | This plugin attempts to contact the MRTGEXT NLM running on a Novell server\n\ | ||
32 | to 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 "\ | ||
82 | Notes:\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 | |||
120 | char *server_address=NULL; | ||
121 | char *volume_name=NULL; | ||
122 | int server_port=PORT; | ||
123 | unsigned long warning_value=0L; | ||
124 | unsigned long critical_value=0L; | ||
125 | int check_warning_value=FALSE; | ||
126 | int check_critical_value=FALSE; | ||
127 | int check_netware_version=FALSE; | ||
128 | unsigned long vars_to_check=CHECK_NONE; | ||
129 | int sap_number=-1; | ||
130 | |||
131 | #define PROGNAME "check_nwstat" | ||
132 | |||
133 | int process_arguments(int, char **); | ||
134 | void print_usage(void); | ||
135 | void print_help(void); | ||
136 | |||
137 | int 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 */ | ||
624 | int 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 | |||
797 | void 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 | |||
812 | void 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 0000000..305a824 --- /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 | |||
63 | char *server_address = NULL; | ||
64 | int server_port = PORT; | ||
65 | double warning_value = 0L; | ||
66 | double critical_value = 0L; | ||
67 | int check_warning_value = FALSE; | ||
68 | int check_critical_value = FALSE; | ||
69 | int vars_to_check = CHECK_NONE; | ||
70 | int cmd_timeout = 1; | ||
71 | |||
72 | int netstat_port = 0; | ||
73 | char *disk_name = NULL; | ||
74 | char *process_name = NULL; | ||
75 | |||
76 | int process_arguments (int, char **); | ||
77 | void print_usage (void); | ||
78 | void print_help (void); | ||
79 | |||
80 | int | ||
81 | main (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 */ | ||
315 | int | ||
316 | process_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 | |||
436 | void | ||
437 | print_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 | |||
448 | void | ||
449 | print_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 0000000..03614ab --- /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\ | ||
57 | This plugin tests a PostgreSQL DBMS to determine whether it is active and\n\ | ||
58 | accepting queries. In its current operation, it simply connects to the\n\ | ||
59 | specified database, and then disconnects. If no database is specified, it\n\ | ||
60 | connects to the template1 database, which is present in every functioning \n\ | ||
61 | PostgreSQL DBMS.\n\ | ||
62 | \n\ | ||
63 | The plugin will connect to a local postmaster if no host is specified. To\n\ | ||
64 | connect to a remote host, be sure that the remote postmaster accepts TCP/IP\n\ | ||
65 | connections (start the postmaster with the -i option).\n\ | ||
66 | \n\ | ||
67 | Typically, the nagios user (unless the --logname option is used) should be\n\ | ||
68 | able to connect to the database without a password. The plugin can also send\n\ | ||
69 | a 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 | |||
84 | int process_arguments (int, char **); | ||
85 | int validate_arguments (void); | ||
86 | void print_usage (void); | ||
87 | void print_help (void); | ||
88 | int is_pg_dbname (char *); | ||
89 | int is_pg_logname (char *); | ||
90 | |||
91 | char *pghost = NULL; /* host name of the backend server */ | ||
92 | char *pgport = NULL; /* port of the backend server */ | ||
93 | char default_port[4] = DEFAULT_PORT; | ||
94 | char *pgoptions = NULL; | ||
95 | char *pgtty = NULL; | ||
96 | char dbName[NAMEDATALEN] = DEFAULT_DB; | ||
97 | char *pguser = NULL; | ||
98 | char *pgpasswd = NULL; | ||
99 | int twarn = DEFAULT_WARN; | ||
100 | int tcrit = DEFAULT_CRIT; | ||
101 | |||
102 | PGconn *conn; | ||
103 | /*PGresult *res;*/ | ||
104 | |||
105 | |||
106 | /****************************************************************************** | ||
107 | |||
108 | The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@ | ||
109 | tags in the comments. With in the tags, the XML is assembled sequentially. | ||
110 | You can define entities in tags. You also have all the #defines available as | ||
111 | entities. | ||
112 | |||
113 | Please 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 | |||
160 | int | ||
161 | main (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 | |||
218 | void | ||
219 | print_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 | |||
232 | void | ||
233 | print_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 */ | ||
249 | int | ||
250 | process_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 | ||
347 | is a valid PostgreSQL database name, and returns false if it is | ||
348 | not.</para> | ||
349 | |||
350 | <para>Valid PostgreSQL database names are less than &NAMEDATALEN; | ||
351 | characters long and consist of letters, numbers, and underscores. The | ||
352 | first character cannot be a number, however.</para> | ||
353 | |||
354 | </sect3> | ||
355 | -@@ | ||
356 | ******************************************************************************/ | ||
357 | |||
358 | int | ||
359 | validate_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 | ||
375 | is a valid PostgreSQL database name, and returns false if it is | ||
376 | not.</para> | ||
377 | |||
378 | <para>Valid PostgreSQL database names are less than &NAMEDATALEN; | ||
379 | characters long and consist of letters, numbers, and underscores. The | ||
380 | first character cannot be a number, however.</para> | ||
381 | |||
382 | </sect3> | ||
383 | -@@ | ||
384 | ******************************************************************************/ | ||
385 | |||
386 | int | ||
387 | is_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 | |||
404 | the tango program should eventually create an entity here based on the | ||
405 | function 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 | ||
414 | valid PostgreSQL username, and returns false if it is not. Valid PostgreSQL | ||
415 | usernames are less than &NAMEDATALEN; characters long and consist of | ||
416 | letters, numbers, dashes, and underscores, plus possibly some other | ||
417 | characters.</para> | ||
418 | |||
419 | <para>Currently this function only checks string length. Additional checks | ||
420 | should be added.</para> | ||
421 | |||
422 | </sect3> | ||
423 | -@@ | ||
424 | ******************************************************************************/ | ||
425 | |||
426 | int | ||
427 | is_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 0000000..b61b41b --- /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\ | ||
37 | THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel\n\ | ||
38 | time (ms) which triggers a WARNING or CRITICAL state, and <pl> is the\n\ | ||
39 | percentage of packet loss to trigger an alarm state.\n" | ||
40 | |||
41 | #define DESCRIPTION "\ | ||
42 | This 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\ | ||
44 | linking to a traceroute CGI contributed by Ian Cass. The CGI can be found in\n\ | ||
45 | the 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 | |||
58 | int process_arguments (int, char **); | ||
59 | int call_getopt (int, char **); | ||
60 | int get_threshold (char *, float *, int *); | ||
61 | int validate_arguments (void); | ||
62 | int run_ping (char *); | ||
63 | void print_usage (void); | ||
64 | void print_help (void); | ||
65 | |||
66 | int display_html = FALSE; | ||
67 | int wpl = UNKNOWN_PACKET_LOSS; | ||
68 | int cpl = UNKNOWN_PACKET_LOSS; | ||
69 | float wrta = UNKNOWN_TRIP_TIME; | ||
70 | float crta = UNKNOWN_TRIP_TIME; | ||
71 | char *server_address = NULL; | ||
72 | int max_packets = -1; | ||
73 | int verbose = FALSE; | ||
74 | |||
75 | float rta = UNKNOWN_TRIP_TIME; | ||
76 | int pl = UNKNOWN_PACKET_LOSS; | ||
77 | |||
78 | char *warn_text = NULL; | ||
79 | |||
80 | int | ||
81 | main (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 */ | ||
146 | int | ||
147 | process_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 | |||
218 | int | ||
219 | call_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 | |||
307 | int | ||
308 | get_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 | |||
321 | int | ||
322 | validate_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 | |||
362 | int | ||
363 | run_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 | |||
466 | void | ||
467 | print_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 | |||
480 | void | ||
481 | print_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 0000000..9fcfaec --- /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 | |||
48 | int process_arguments (int, char **); | ||
49 | int call_getopt (int, char **); | ||
50 | int validate_arguments (void); | ||
51 | int check_disk (int usp, int free_disk); | ||
52 | void print_help (void); | ||
53 | void print_usage (void); | ||
54 | |||
55 | int server_port = POP_PORT; | ||
56 | char *server_address = NULL; | ||
57 | char *server_expect = NULL; | ||
58 | int warning_time = 0; | ||
59 | int check_warning_time = FALSE; | ||
60 | int critical_time = 0; | ||
61 | int check_critical_time = FALSE; | ||
62 | int verbose = FALSE; | ||
63 | |||
64 | int | ||
65 | main (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 */ | ||
152 | int | ||
153 | process_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 | |||
201 | int | ||
202 | call_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 | |||
311 | int | ||
312 | validate_arguments (void) | ||
313 | { | ||
314 | return OK; | ||
315 | } | ||
316 | |||
317 | |||
318 | |||
319 | |||
320 | |||
321 | void | ||
322 | print_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 | |||
357 | void | ||
358 | print_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 0000000..c66d33d --- /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 | |||
43 | int process_arguments (int, char **); | ||
44 | int call_getopt (int, char **); | ||
45 | int validate_arguments (void); | ||
46 | void print_usage (void); | ||
47 | void print_help (char *); | ||
48 | |||
49 | int wmax = -1; | ||
50 | int cmax = -1; | ||
51 | int wmin = -1; | ||
52 | int cmin = -1; | ||
53 | |||
54 | int 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 | |||
62 | int verbose = FALSE; | ||
63 | int uid; | ||
64 | int ppid; | ||
65 | char *statopts = NULL; | ||
66 | char *prog = NULL; | ||
67 | char *args = NULL; | ||
68 | char *format = NULL; | ||
69 | char tmp[MAX_INPUT_BUFFER]; | ||
70 | |||
71 | int | ||
72 | main (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 */ | ||
214 | int | ||
215 | process_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 | |||
247 | int | ||
248 | call_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 | |||
428 | int | ||
429 | validate_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 | |||
465 | void | ||
466 | print_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 | |||
502 | void | ||
503 | print_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 0000000..614d467 --- /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 "\ | ||
63 | The password option presents a substantial security issue because the | ||
64 | password can be determined by careful watching of the command line in | ||
65 | a process listing. This risk is exacerbated because nagios will | ||
66 | run the plugin at regular prdictable intervals. Please be sure that | ||
67 | the password used does not allow access to sensitive system resources, | ||
68 | otherwise compormise could occur.\n" | ||
69 | |||
70 | #include "config.h" | ||
71 | #include "common.h" | ||
72 | #include "utils.h" | ||
73 | #include <radiusclient.h> | ||
74 | |||
75 | int process_arguments (int, char **); | ||
76 | void print_usage (void); | ||
77 | void print_help (void); | ||
78 | |||
79 | char *server = NULL; | ||
80 | int port = PW_AUTH_UDP_PORT; | ||
81 | char *username = NULL; | ||
82 | char *password = NULL; | ||
83 | char *expect = NULL; | ||
84 | char *config_file = NULL; | ||
85 | int retries = 1; | ||
86 | int verbose = FALSE; | ||
87 | |||
88 | ENV *env = NULL; | ||
89 | |||
90 | /****************************************************************************** | ||
91 | |||
92 | The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@ | ||
93 | tags in the comments. With in the tags, the XML is assembled sequentially. | ||
94 | You can define entities in tags. You also have all the #defines available as | ||
95 | entities. | ||
96 | |||
97 | Please 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 | |||
143 | int | ||
144 | main (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 */ | ||
200 | int | ||
201 | process_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 | |||
318 | void | ||
319 | print_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 | |||
333 | void | ||
334 | print_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 0000000..ba746b8 --- /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 | |||
57 | int process_arguments (int, char **); | ||
58 | int call_getopt (int, char **); | ||
59 | int validate_arguments (void); | ||
60 | int check_disk (int usp, int free_disk); | ||
61 | void print_help (void); | ||
62 | void print_usage (void); | ||
63 | |||
64 | int server_port = PORT; | ||
65 | char *server_address = NULL; | ||
66 | char *host_name = NULL; | ||
67 | char *server_url = NULL; | ||
68 | char *server_expect = NULL; | ||
69 | int warning_time = 0; | ||
70 | int check_warning_time = FALSE; | ||
71 | int critical_time = 0; | ||
72 | int check_critical_time = FALSE; | ||
73 | int verbose = FALSE; | ||
74 | |||
75 | int | ||
76 | main (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 */ | ||
273 | int | ||
274 | process_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 | |||
319 | int | ||
320 | call_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 | |||
445 | int | ||
446 | validate_arguments (void) | ||
447 | { | ||
448 | return OK; | ||
449 | } | ||
450 | |||
451 | |||
452 | |||
453 | |||
454 | |||
455 | void | ||
456 | print_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 | |||
495 | void | ||
496 | print_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 | ||
510 | int | ||
511 | process_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 0000000..d57b784 --- /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 | |||
48 | int process_arguments (int, char **); | ||
49 | int call_getopt (int, char **); | ||
50 | int validate_arguments (void); | ||
51 | int check_disk (int usp, int free_disk); | ||
52 | void print_help (void); | ||
53 | void print_usage (void); | ||
54 | |||
55 | int server_port = SMTP_PORT; | ||
56 | char *server_address = NULL; | ||
57 | char *server_expect = NULL; | ||
58 | int warning_time = 0; | ||
59 | int check_warning_time = FALSE; | ||
60 | int critical_time = 0; | ||
61 | int check_critical_time = FALSE; | ||
62 | int verbose = FALSE; | ||
63 | |||
64 | int | ||
65 | main (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 */ | ||
150 | int | ||
151 | process_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 | |||
199 | int | ||
200 | call_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 | |||
309 | int | ||
310 | validate_arguments (void) | ||
311 | { | ||
312 | return OK; | ||
313 | } | ||
314 | |||
315 | |||
316 | |||
317 | |||
318 | |||
319 | void | ||
320 | print_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 | |||
355 | void | ||
356 | print_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 0000000..2f970b3 --- /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 | |||
71 | void print_usage (void); | ||
72 | void print_help (char *); | ||
73 | int process_arguments (int, char **); | ||
74 | int call_getopt (int, char **); | ||
75 | int check_num (int); | ||
76 | char *clarify_message (char *); | ||
77 | int lu_getll (unsigned long *, char *); | ||
78 | int lu_getul (unsigned long *, char *); | ||
79 | char *thisarg (char *str); | ||
80 | char *nextarg (char *str); | ||
81 | |||
82 | #ifdef HAVE_REGEX_H | ||
83 | #include <regex.h> | ||
84 | char regex_expect[MAX_INPUT_BUFFER] = ""; | ||
85 | regex_t preg; | ||
86 | regmatch_t pmatch[10]; | ||
87 | char timestamp[10] = ""; | ||
88 | char regex[MAX_INPUT_BUFFER]; | ||
89 | char errbuf[MAX_INPUT_BUFFER]; | ||
90 | int cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE; | ||
91 | int eflags = 0; | ||
92 | int errcode, excode; | ||
93 | #endif | ||
94 | |||
95 | char *server_address = NULL; | ||
96 | char *community = NULL; | ||
97 | char oid[MAX_INPUT_BUFFER] = ""; | ||
98 | char *label = NULL; | ||
99 | char *units = NULL; | ||
100 | char string_value[MAX_INPUT_BUFFER] = ""; | ||
101 | char **labels = NULL; | ||
102 | char **unitv = NULL; | ||
103 | int nlabels = 0; | ||
104 | int labels_size = 8; | ||
105 | int nunits = 0; | ||
106 | int unitv_size = 8; | ||
107 | unsigned long lower_warn_lim[MAX_OIDS]; | ||
108 | unsigned long upper_warn_lim[MAX_OIDS]; | ||
109 | unsigned long lower_crit_lim[MAX_OIDS]; | ||
110 | unsigned long upper_crit_lim[MAX_OIDS]; | ||
111 | unsigned long response_value[MAX_OIDS]; | ||
112 | int check_warning_value = FALSE; | ||
113 | int check_critical_value = FALSE; | ||
114 | int eval_method[MAX_OIDS]; | ||
115 | char *delimiter = NULL; | ||
116 | char *output_delim = NULL; | ||
117 | |||
118 | |||
119 | int | ||
120 | main (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 */ | ||
311 | int | ||
312 | process_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 | |||
354 | int | ||
355 | call_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 | |||
576 | void | ||
577 | print_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 | |||
586 | void | ||
587 | print_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 | |||
647 | char * | ||
648 | clarify_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 | |||
683 | int | ||
684 | check_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 | |||
726 | int | ||
727 | lu_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 | |||
739 | int | ||
740 | lu_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 | |||
760 | char * | ||
761 | thisarg (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 | |||
776 | char * | ||
777 | nextarg (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 0000000..d78189f --- /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 | |||
27 | short port = -1; | ||
28 | char *server_name = NULL; | ||
29 | int verbose = FALSE; | ||
30 | |||
31 | int process_arguments (int, char **); | ||
32 | int call_getopt (int, char **); | ||
33 | int validate_arguments (void); | ||
34 | void print_help (void); | ||
35 | void print_usage (void); | ||
36 | |||
37 | char *ssh_resolve (char *hostname); | ||
38 | int ssh_connect (char *haddr, short hport); | ||
39 | |||
40 | int | ||
41 | main (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 */ | ||
61 | int | ||
62 | process_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 | |||
101 | int | ||
102 | call_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 | |||
170 | int | ||
171 | validate_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 | |||
187 | char * | ||
188 | ssh_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 | |||
207 | int | ||
208 | ssh_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 | |||
266 | void | ||
267 | print_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 | |||
275 | void | ||
276 | print_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 0000000..d225e1d --- /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 | |||
19 | int process_arguments (int argc, char **argv); | ||
20 | int call_getopt (int argc, char **argv); | ||
21 | int validate_arguments (void); | ||
22 | void print_usage (void); | ||
23 | void print_help (void); | ||
24 | |||
25 | int warn_percent = 200, crit_percent = 200, warn_size = -1, crit_size = -1; | ||
26 | |||
27 | int | ||
28 | main (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 */ | ||
150 | int | ||
151 | process_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 | |||
180 | int | ||
181 | call_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 | |||
267 | int | ||
268 | validate_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 | |||
289 | void | ||
290 | print_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 | |||
302 | void | ||
303 | print_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 0000000..bef0e75 --- /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 | ||
55 | SSL_CTX *ctx; | ||
56 | SSL *ssl; | ||
57 | int connect_SSL (void); | ||
58 | #endif | ||
59 | |||
60 | #define TCP_PROTOCOL 1 | ||
61 | #define UDP_PROTOCOL 2 | ||
62 | |||
63 | int process_arguments (int, char **); | ||
64 | void print_usage (void); | ||
65 | void print_help (void); | ||
66 | |||
67 | char *PROGNAME = NULL; | ||
68 | char *SERVICE = NULL; | ||
69 | char *SEND = NULL; | ||
70 | char *EXPECT = NULL; | ||
71 | char *QUIT = NULL; | ||
72 | int PROTOCOL = 0; | ||
73 | int PORT = 0; | ||
74 | |||
75 | int server_port = 0; | ||
76 | char *server_address = NULL; | ||
77 | char *server_send = NULL; | ||
78 | char *server_quit = NULL; | ||
79 | char **server_expect = NULL; | ||
80 | int server_expect_count = 0; | ||
81 | char **warn_codes = NULL; | ||
82 | int warn_codes_count = 0; | ||
83 | char **crit_codes = NULL; | ||
84 | int crit_codes_count = 0; | ||
85 | int delay = 0; | ||
86 | int warning_time = 0; | ||
87 | int check_warning_time = FALSE; | ||
88 | int critical_time = 0; | ||
89 | int check_critical_time = FALSE; | ||
90 | int verbose = FALSE; | ||
91 | int use_ssl = FALSE; | ||
92 | int sd; | ||
93 | |||
94 | int | ||
95 | main (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 */ | ||
317 | int | ||
318 | process_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 | |||
465 | void | ||
466 | print_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 | |||
477 | void | ||
478 | print_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 | ||
515 | int | ||
516 | connect_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 0000000..86c414e --- /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 | |||
47 | unsigned long server_time, raw_server_time; | ||
48 | time_t diff_time; | ||
49 | int warning_time = 0; | ||
50 | int check_warning_time = FALSE; | ||
51 | int critical_time = 0; | ||
52 | int check_critical_time = FALSE; | ||
53 | unsigned long warning_diff = 0; | ||
54 | int check_warning_diff = FALSE; | ||
55 | unsigned long critical_diff = 0; | ||
56 | int check_critical_diff = FALSE; | ||
57 | int server_port = TIME_PORT; | ||
58 | char *server_address = NULL; | ||
59 | |||
60 | |||
61 | int process_arguments (int, char **); | ||
62 | int call_getopt (int, char **); | ||
63 | void print_usage (void); | ||
64 | void print_help (void); | ||
65 | |||
66 | |||
67 | int | ||
68 | main (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 */ | ||
152 | int | ||
153 | process_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 | |||
198 | int | ||
199 | call_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 | |||
328 | void | ||
329 | print_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 | |||
340 | void | ||
341 | print_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 0000000..d00ce9c --- /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 | |||
46 | int warning_time = 0; | ||
47 | int check_warning_time = FALSE; | ||
48 | int critical_time = 0; | ||
49 | int check_critical_time = FALSE; | ||
50 | |||
51 | int process_arguments (int, char **); | ||
52 | int call_getopt (int, char **); | ||
53 | void print_usage (void); | ||
54 | void print_help (void); | ||
55 | |||
56 | int verbose = FALSE; | ||
57 | int server_port = 0; | ||
58 | char *server_address = NULL; | ||
59 | char *server_expect = NULL; | ||
60 | char *server_send = NULL; | ||
61 | |||
62 | int | ||
63 | main (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 */ | ||
124 | int | ||
125 | process_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 | |||
169 | int | ||
170 | call_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 | |||
272 | void | ||
273 | print_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 | |||
284 | void | ||
285 | print_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 0000000..4632bdc --- /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 | |||
80 | int server_port = PORT; | ||
81 | char *server_address = NULL; | ||
82 | char *ups_name = NULL; | ||
83 | double warning_value = 0.0L; | ||
84 | double critical_value = 0.0L; | ||
85 | int check_warning_value = FALSE; | ||
86 | int check_critical_value = FALSE; | ||
87 | int check_variable = UPS_NONE; | ||
88 | int supported_options = UPS_NONE; | ||
89 | int status = UPSSTATUS_NONE; | ||
90 | |||
91 | double ups_utility_voltage = 0.0L; | ||
92 | double ups_battery_percent = 0.0L; | ||
93 | double ups_load_percent = 0.0L; | ||
94 | double ups_temperature = 0.0L; | ||
95 | char ups_status[MAX_INPUT_BUFFER] = "N/A"; | ||
96 | |||
97 | int determine_status (void); | ||
98 | int determine_supported_vars (void); | ||
99 | int get_ups_variable (const char *, char *, int); | ||
100 | |||
101 | int process_arguments (int, char **); | ||
102 | int call_getopt (int, char **); | ||
103 | int validate_arguments (void); | ||
104 | void print_help (void); | ||
105 | void print_usage (void); | ||
106 | |||
107 | int | ||
108 | main (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 */ | ||
285 | int | ||
286 | determine_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 */ | ||
322 | int | ||
323 | determine_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 */ | ||
371 | int | ||
372 | get_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 */ | ||
431 | int | ||
432 | process_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 | |||
475 | int | ||
476 | call_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 | |||
596 | int | ||
597 | validate_arguments (void) | ||
598 | { | ||
599 | return OK; | ||
600 | } | ||
601 | |||
602 | |||
603 | |||
604 | |||
605 | |||
606 | void | ||
607 | print_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 | |||
641 | void | ||
642 | print_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 0000000..2b8fa15 --- /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 | |||
55 | int process_arguments (int, char **); | ||
56 | int call_getopt (int, char **); | ||
57 | void print_usage (void); | ||
58 | void print_help (void); | ||
59 | |||
60 | int wusers = -1; | ||
61 | int cusers = -1; | ||
62 | |||
63 | int | ||
64 | main (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 */ | ||
131 | int | ||
132 | process_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 | |||
165 | int | ||
166 | call_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 | |||
229 | void | ||
230 | print_usage (void) | ||
231 | { | ||
232 | printf ("Usage: %s -w <users> -c <users>\n", PROGNAME); | ||
233 | } | ||
234 | |||
235 | |||
236 | |||
237 | |||
238 | |||
239 | void | ||
240 | print_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 0000000..c8ca82b --- /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 | |||
40 | int process_arguments (int argc, char **argv); | ||
41 | int call_getopt (int argc, char **argv); | ||
42 | void print_help (char *cmd); | ||
43 | void print_usage (char *cmd); | ||
44 | |||
45 | int warn = -1; | ||
46 | int crit = -1; | ||
47 | char *proc = NULL; | ||
48 | |||
49 | int | ||
50 | main (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 | |||
144 | int | ||
145 | process_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 | |||
185 | int | ||
186 | call_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 | |||
260 | void | ||
261 | print_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 | |||
267 | void | ||
268 | print_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 0000000..9cb4bcb --- /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 | /* | ||
117 | int snprintf (char *str, size_t n, const char *fmt, ...); | ||
118 | int 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 0000000..364a145 --- /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 | |||
95 | char *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. */ | ||
110 | int 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 | |||
119 | static char *nextchar; | ||
120 | |||
121 | /* Callers store zero here to inhibit the error message | ||
122 | for unrecognized options. */ | ||
123 | |||
124 | int 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 | |||
130 | int 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 | |||
161 | static enum | ||
162 | { | ||
163 | REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER | ||
164 | } | ||
165 | ordering; | ||
166 | |||
167 | /* Value of POSIXLY_CORRECT environment variable. */ | ||
168 | static 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 | |||
182 | char *getenv (); | ||
183 | |||
184 | static char * | ||
185 | my_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. */ | ||
205 | extern 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 | |||
217 | static int first_nonopt; | ||
218 | static 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 | |||
229 | static void | ||
230 | exchange (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 | |||
282 | static 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 | |||
370 | int | ||
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 | |||
645 | int | ||
646 | getopt (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 | |||
662 | int | ||
663 | main (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 0000000..bbac373 --- /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 | ||
51 | char *getenv (); | ||
52 | #endif | ||
53 | |||
54 | #ifndef NULL | ||
55 | #define NULL 0 | ||
56 | #endif | ||
57 | |||
58 | int | ||
59 | getopt_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 | |||
74 | int | ||
75 | getopt_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 | |||
92 | int | ||
93 | main (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 0000000..e5d3528 --- /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 | |||
39 | extern int socket_timeout; | ||
40 | RETSIGTYPE socket_timeout_alarm_handler (int); | ||
41 | |||
42 | int process_tcp_request2 (char *, int, char *, char *, int); | ||
43 | int process_tcp_request (char *, int, char *, char *, int); | ||
44 | int process_udp_request (char *, int, char *, char *, int); | ||
45 | int process_request (char *, int, char *, char *, char *, int); | ||
46 | |||
47 | int my_tcp_connect (char *, int, int *); | ||
48 | int my_udp_connect (char *, int, int *); | ||
49 | int my_connect (char *, int, int *, char *); | ||
50 | |||
51 | int my_inet_aton (register const char *, struct in_addr *); | ||
52 | |||
53 | /* handles socket timeouts */ | ||
54 | void | ||
55 | socket_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 */ | ||
66 | int | ||
67 | process_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 */ | ||
84 | int | ||
85 | process_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 */ | ||
104 | int | ||
105 | process_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 */ | ||
177 | int | ||
178 | process_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 */ | ||
239 | int | ||
240 | my_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 */ | ||
252 | int | ||
253 | my_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 */ | ||
265 | int | ||
266 | my_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. */ | ||
333 | int | ||
334 | my_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 0000000..be4ae24 --- /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 | |||
42 | void socket_timeout_alarm_handler (int); | ||
43 | |||
44 | int process_tcp_request2 (char *address, int port, char *sbuffer, | ||
45 | char *rbuffer, int rsize); | ||
46 | int process_tcp_request (char *address, int port, char *sbuffer, | ||
47 | char *rbuffer, int rsize); | ||
48 | int process_udp_request (char *address, int port, char *sbuffer, | ||
49 | char *rbuffer, int rsize); | ||
50 | int process_request (char *address, int port, char *proto, char *sbuffer, | ||
51 | char *rbuffer, int rsize); | ||
52 | |||
53 | int my_tcp_connect (char *address, int port, int *sd); | ||
54 | int my_udp_connect (char *address, int port, int *sd); | ||
55 | int my_connect (char *address, int port, int *sd, char *proto); | ||
56 | |||
57 | int 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 | ||
63 | int socket_timeout = DEFAULT_SOCKET_TIMEOUT; | ||
diff --git a/plugins/popen.c b/plugins/popen.c new file mode 100644 index 0000000..cde3c76 --- /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 | |||
8 | FILE * spopen(const char *); | ||
9 | int 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 */ | ||
25 | extern int timeout_interval; | ||
26 | extern pid_t *childpid; | ||
27 | extern int *child_stderr_array; | ||
28 | extern FILE *child_process; | ||
29 | |||
30 | FILE *spopen (const char *); | ||
31 | int spclose (FILE *); | ||
32 | RETSIGTYPE 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)) | ||
59 | int open_max (void); /* {Prog openmax} */ | ||
60 | void err_sys (const char *, ...); | ||
61 | char *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 */ | ||
65 | static int maxfd; /* from our open_max(), {Prog openmax} */ | ||
66 | |||
67 | FILE * | ||
68 | spopen (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 | |||
199 | int | ||
200 | spclose (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 | ||
227 | static int openmax = OPEN_MAX; | ||
228 | #else | ||
229 | static int openmax = 0; | ||
230 | #endif | ||
231 | |||
232 | #define OPEN_MAX_GUESS 256 /* if OPEN_MAX is indeterminate */ | ||
233 | /* no guarantee this is adequate */ | ||
234 | |||
235 | void | ||
236 | popen_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 | |||
246 | int | ||
247 | open_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 | |||
262 | static void err_doit (int, const char *, va_list); | ||
263 | |||
264 | char *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 | |||
269 | void | ||
270 | err_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 | ||
284 | static void | ||
285 | err_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 | |||
301 | char * | ||
302 | rtrim (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 0000000..adae2ec --- /dev/null +++ b/plugins/popen.h.in | |||
@@ -0,0 +1,9 @@ | |||
1 | FILE *spopen (const char *); | ||
2 | int spclose (FILE *); | ||
3 | RETSIGTYPE popen_timeout_alarm_handler (int); | ||
4 | |||
5 | int timeout_interval; | ||
6 | pid_t *childpid; | ||
7 | int *child_stderr_array; | ||
8 | FILE *child_process; | ||
9 | FILE *child_stderr; | ||
diff --git a/plugins/snprintf.c b/plugins/snprintf.c new file mode 100644 index 0000000..1474b63 --- /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 | ||
41 | static 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$";*/ | ||
94 | static void dopr(); | ||
95 | static char *end; | ||
96 | #ifndef _SCO_DS | ||
97 | /* VARARGS3 */ | ||
98 | int | ||
99 | # ifdef __STDC__ | ||
100 | snprintf(char *str, size_t count, const char *fmt, ...) | ||
101 | # else | ||
102 | snprintf(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 | ||
120 | int | ||
121 | # ifdef __STDC__ | ||
122 | vsnprintf(char *str, size_t count, const char *fmt, va_list args) | ||
123 | #else | ||
124 | vsnprintf(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 | |||
143 | static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth)); | ||
144 | static void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad)); | ||
145 | static void dostr __P(( char * , int )); | ||
146 | static char *output; | ||
147 | static void dopr_outch __P(( int c )); | ||
148 | |||
149 | static void | ||
150 | # ifdef __STDC__ | ||
151 | dopr(char * buffer, const char * format, va_list args ) | ||
152 | #else | ||
153 | dopr( 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 | |||
261 | static void | ||
262 | fmtstr( 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 | |||
288 | static void | ||
289 | fmtnum( 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 | |||
348 | static void | ||
349 | dostr( 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 | |||
360 | static void | ||
361 | dopr_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 0000000..f1e436d --- /dev/null +++ b/plugins/t/check_disk.t | |||
@@ -0,0 +1,31 @@ | |||
1 | use strict; | ||
2 | use Test; | ||
3 | use vars qw($tests); | ||
4 | |||
5 | BEGIN {$tests = 6; plan tests => $tests} | ||
6 | |||
7 | my $null = ''; | ||
8 | my $cmd; | ||
9 | my $str; | ||
10 | my $t; | ||
11 | |||
12 | $cmd = "./check_disk 100 100 /"; | ||
13 | $str = `$cmd`; | ||
14 | $t += ok $?>>8,0; | ||
15 | print "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; | ||
21 | print "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; | ||
27 | print "Test was: $cmd\n" unless ($?); | ||
28 | $t += ok $str, '/^(Only +[\.0-9]+|DISK CRITICAL - )/'; | ||
29 | |||
30 | exit(0) if defined($Test::Harness::VERSION); | ||
31 | exit($tests - $t); | ||
diff --git a/plugins/t/check_dns.t b/plugins/t/check_dns.t new file mode 100644 index 0000000..a85e2e7 --- /dev/null +++ b/plugins/t/check_dns.t | |||
@@ -0,0 +1,29 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 3; plan tests => $tests} | ||
9 | |||
10 | #`nslookup localhost > /dev/null 2>&1` || exit(77); | ||
11 | |||
12 | my $null = ''; | ||
13 | my $cmd; | ||
14 | my $str; | ||
15 | my $t; | ||
16 | |||
17 | $cmd = "./check_dns 127.0.0.1 -to 5"; | ||
18 | $str = `$cmd`; | ||
19 | $t += ok $?>>8,0; | ||
20 | print "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; | ||
26 | print "Test was: $cmd\n" unless ($?); | ||
27 | |||
28 | exit(0) if defined($Test::Harness::VERSION); | ||
29 | exit($tests - $t); | ||
diff --git a/plugins/t/check_fping.t b/plugins/t/check_fping.t new file mode 100644 index 0000000..629ee35 --- /dev/null +++ b/plugins/t/check_fping.t | |||
@@ -0,0 +1,37 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | # $Id$ | ||
3 | |||
4 | use strict; | ||
5 | use Cache; | ||
6 | use Test; | ||
7 | use vars qw($tests); | ||
8 | |||
9 | BEGIN {$tests = 3; plan tests => $tests} | ||
10 | |||
11 | exit(0) unless (-x "./check_fping"); | ||
12 | |||
13 | #`fping 127.0.0.1 > /dev/null 2>&1` || exit(77); | ||
14 | |||
15 | my $null = ''; | ||
16 | my $cmd; | ||
17 | my $str; | ||
18 | my $t; | ||
19 | my $stat; | ||
20 | |||
21 | |||
22 | $cmd = "./check_fping 127.0.0.1"; | ||
23 | $str = `$cmd`; | ||
24 | $t += ok $?>>8,0; | ||
25 | print "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`; | ||
30 | if ($?>>8 == 1 or $?>>8 == 2) { | ||
31 | $stat = 2; | ||
32 | } | ||
33 | $t += ok $stat,2; | ||
34 | print "Test was: $cmd\n" if (($?>>8) < 1); | ||
35 | |||
36 | exit(0) if defined($Test::Harness::VERSION); | ||
37 | exit($tests - $t); | ||
diff --git a/plugins/t/check_ftp.t b/plugins/t/check_ftp.t new file mode 100644 index 0000000..c3f74d9 --- /dev/null +++ b/plugins/t/check_ftp.t | |||
@@ -0,0 +1,32 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | #use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 3; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $cmd; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | |||
15 | $cmd = "./check_ftp $Cache::hostname -wt 300 -ct 600"; | ||
16 | $str = `$cmd`; | ||
17 | $t += ok $?>>8,0; | ||
18 | print "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; | ||
29 | print "Test was: $cmd\n" unless ($?); | ||
30 | |||
31 | exit(0) if defined($Test::Harness::VERSION); | ||
32 | exit($tests - $t); | ||
diff --git a/plugins/t/check_hpjd.t b/plugins/t/check_hpjd.t new file mode 100644 index 0000000..b4e198d --- /dev/null +++ b/plugins/t/check_hpjd.t | |||
@@ -0,0 +1,32 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Helper; | ||
5 | use Cache; | ||
6 | use Test; | ||
7 | use vars qw($tests); | ||
8 | |||
9 | BEGIN {$tests = 4; plan tests => $tests} | ||
10 | |||
11 | exit(0) unless (-x "./check_hpjd"); | ||
12 | |||
13 | my $null = ''; | ||
14 | my $cmd; | ||
15 | my $str; | ||
16 | my $t; | ||
17 | my $printer = get_option("hpjd_printer","HP Jet-Direct card address"); | ||
18 | |||
19 | $cmd = "./check_hpjd $printer"; | ||
20 | $str = `$cmd`; | ||
21 | $t += ok $?>>8,0; | ||
22 | print "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; | ||
28 | print "Test was: $cmd\n" unless ($?); | ||
29 | $t += ok $str, '/Timeout: No response from /'; | ||
30 | |||
31 | exit(0) if defined($Test::Harness::VERSION); | ||
32 | exit($tests - $t); | ||
diff --git a/plugins/t/check_http.t b/plugins/t/check_http.t new file mode 100644 index 0000000..2782fcd --- /dev/null +++ b/plugins/t/check_http.t | |||
@@ -0,0 +1,22 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 3; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $str; | ||
12 | my $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 | |||
21 | exit(0) if defined($Test::Harness::VERSION); | ||
22 | exit($tests - $t); | ||
diff --git a/plugins/t/check_imap.t b/plugins/t/check_imap.t new file mode 100644 index 0000000..47494e5 --- /dev/null +++ b/plugins/t/check_imap.t | |||
@@ -0,0 +1,34 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | #use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 3; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $cmd; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | |||
15 | $cmd = "./check_imap $Cache::mailhost"; | ||
16 | $str = `$cmd`; | ||
17 | $t += ok $?>>8,0; | ||
18 | print "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; | ||
23 | print "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; | ||
30 | print "Test was: $cmd\n" if ($?); | ||
31 | |||
32 | exit(0) if defined($Test::Harness::VERSION); | ||
33 | exit($tests - $t); | ||
34 | |||
diff --git a/plugins/t/check_load.t b/plugins/t/check_load.t new file mode 100644 index 0000000..ac14620 --- /dev/null +++ b/plugins/t/check_load.t | |||
@@ -0,0 +1,27 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Test; | ||
5 | use vars qw($tests); | ||
6 | |||
7 | BEGIN {$tests = 4; plan tests => $tests} | ||
8 | |||
9 | my $null = ''; | ||
10 | my $cmd; | ||
11 | my $str; | ||
12 | my $t; | ||
13 | |||
14 | $cmd = "./check_load 100 100 100 100 100 100"; | ||
15 | $str = `$cmd`; | ||
16 | $t += ok $?>>8,0; | ||
17 | print "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; | ||
23 | print "Test was: $cmd\n" unless ($?); | ||
24 | $t += ok $str, '/^load average: +[\.0-9]+, +[\.0-9]+, +[\.0-9]+ CRITICAL$/'; | ||
25 | |||
26 | exit(0) if defined($Test::Harness::VERSION); | ||
27 | exit($tests - $t); | ||
diff --git a/plugins/t/check_mysql.t b/plugins/t/check_mysql.t new file mode 100644 index 0000000..ae2a008 --- /dev/null +++ b/plugins/t/check_mysql.t | |||
@@ -0,0 +1,23 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 1; plan tests => $tests} | ||
9 | |||
10 | exit(0) unless (-x "./check_mysql"); | ||
11 | |||
12 | my $null = ''; | ||
13 | my $cmd; | ||
14 | my $str; | ||
15 | my $t; | ||
16 | |||
17 | $cmd = "./check_mysql -H 127.0.0.1 -P 3306"; | ||
18 | $str = `$cmd`; | ||
19 | $t += ok $?>>8,0; | ||
20 | print "Test was: $cmd\n" if ($?); | ||
21 | |||
22 | exit(0) if defined($Test::Harness::VERSION); | ||
23 | exit($tests - $t); | ||
diff --git a/plugins/t/check_ping.t b/plugins/t/check_ping.t new file mode 100644 index 0000000..97bc660 --- /dev/null +++ b/plugins/t/check_ping.t | |||
@@ -0,0 +1,33 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 5; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $cmd; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | |||
15 | $cmd = "./check_ping 127.0.0.1 100 100 1000 1000 -p 1"; | ||
16 | $str = `$cmd`; | ||
17 | $t += ok $?>>8,0; | ||
18 | print "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; | ||
24 | print "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; | ||
30 | print "Test was: $cmd\n" unless ($?); | ||
31 | |||
32 | exit(0) if defined($Test::Harness::VERSION); | ||
33 | exit($tests - $t); | ||
diff --git a/plugins/t/check_pop.t b/plugins/t/check_pop.t new file mode 100644 index 0000000..60b5a4e --- /dev/null +++ b/plugins/t/check_pop.t | |||
@@ -0,0 +1,31 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | #use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 3; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $cmd; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | |||
15 | $cmd = "./check_pop $Cache::mailhost"; | ||
16 | $str = `$cmd`; | ||
17 | $t += ok $?>>8,0; | ||
18 | print "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; | ||
23 | print "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; | ||
28 | print "Test was: $cmd\n" if ($?); | ||
29 | |||
30 | exit(0) if defined($Test::Harness::VERSION); | ||
31 | exit($tests - $t); | ||
diff --git a/plugins/t/check_procs.t b/plugins/t/check_procs.t new file mode 100644 index 0000000..9c2330f --- /dev/null +++ b/plugins/t/check_procs.t | |||
@@ -0,0 +1,51 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 10; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $cmd; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | |||
15 | # Reverse Compatibility | ||
16 | $cmd = "./check_procs 100000 100000"; | ||
17 | $str = `$cmd`; | ||
18 | $t += ok $?>>8,0; | ||
19 | print "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; | ||
26 | print "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; | ||
33 | print "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; | ||
40 | print "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; | ||
47 | print "Test was: $cmd\n" unless ($?); | ||
48 | $t += ok $str, '/^CRITICAL - [0-9]+ processes running with /'; | ||
49 | |||
50 | exit(0) if defined($Test::Harness::VERSION); | ||
51 | exit($tests - $t); | ||
diff --git a/plugins/t/check_smtp.t b/plugins/t/check_smtp.t new file mode 100644 index 0000000..2a82b87 --- /dev/null +++ b/plugins/t/check_smtp.t | |||
@@ -0,0 +1,31 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | #use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 3; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $cmd; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | |||
15 | $cmd = "./check_smtp $Cache::mailhost"; | ||
16 | $str = `$cmd`; | ||
17 | $t += ok $?>>8,0; | ||
18 | print "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; | ||
23 | print "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; | ||
28 | print "Test was: $cmd\n" if ($?); | ||
29 | |||
30 | exit(0) if defined($Test::Harness::VERSION); | ||
31 | exit($tests - $t); | ||
diff --git a/plugins/t/check_snmp.t b/plugins/t/check_snmp.t new file mode 100644 index 0000000..162b0b9 --- /dev/null +++ b/plugins/t/check_snmp.t | |||
@@ -0,0 +1,52 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Helper; | ||
5 | use Cache; | ||
6 | use Test; | ||
7 | use vars qw($tests); | ||
8 | |||
9 | BEGIN {$tests = 8; plan tests => $tests} | ||
10 | |||
11 | my $null = ''; | ||
12 | my $cmd; | ||
13 | my $str; | ||
14 | my $t; | ||
15 | my $community=get_option("snmp_community","SNMP community name"); | ||
16 | |||
17 | exit(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; | ||
22 | print "Test was: $cmd\n" if ($?); | ||
23 | chomp $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; | ||
29 | print "Test was: $cmd\n" if ($?); | ||
30 | chomp $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; | ||
36 | print "Test was: $cmd\n" unless ($?); | ||
37 | chomp $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; | ||
43 | print "Test was: $cmd\n" unless ($?); | ||
44 | chomp $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 | |||
51 | exit(0) if defined($Test::Harness::VERSION); | ||
52 | exit($tests - $t); | ||
diff --git a/plugins/t/check_swap.t b/plugins/t/check_swap.t new file mode 100644 index 0000000..5b702f0 --- /dev/null +++ b/plugins/t/check_swap.t | |||
@@ -0,0 +1,34 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 6; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $cmd; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | |||
15 | $cmd = "./check_swap 100 100"; | ||
16 | $str = `$cmd`; | ||
17 | $t += ok $?>>8,0; | ||
18 | print "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; | ||
24 | print "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; | ||
30 | print "Test was: $cmd\n" unless ($?); | ||
31 | $t += ok $str, '/^CRITICAL - Swap used\: +[0-9]{1,2}\% \([0-9]+ bytes out of [0-9]+\)$/'; | ||
32 | |||
33 | exit(0) if defined($Test::Harness::VERSION); | ||
34 | exit($tests - $t); | ||
diff --git a/plugins/t/check_tcp.t b/plugins/t/check_tcp.t new file mode 100644 index 0000000..1abec76 --- /dev/null +++ b/plugins/t/check_tcp.t | |||
@@ -0,0 +1,27 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | #use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 3; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $cmd; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | |||
15 | $cmd = "./check_tcp $Cache::hostname -p 80 -wt 300 -ct 600"; | ||
16 | $str = `$cmd`; | ||
17 | $t += ok $?>>8,0; | ||
18 | print "$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; | ||
24 | print "$cmd\n" unless ($?); | ||
25 | |||
26 | exit(0) if defined($Test::Harness::VERSION); | ||
27 | exit($tests - $t); | ||
diff --git a/plugins/t/check_time.t b/plugins/t/check_time.t new file mode 100644 index 0000000..4d8c5c2 --- /dev/null +++ b/plugins/t/check_time.t | |||
@@ -0,0 +1,52 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Cache; | ||
5 | use Helper; | ||
6 | use Test; | ||
7 | use vars qw($tests); | ||
8 | |||
9 | BEGIN {$tests = 6; plan tests => $tests} | ||
10 | |||
11 | my $null = ''; | ||
12 | my $cmd; | ||
13 | my $str; | ||
14 | my $t; | ||
15 | my $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; | ||
22 | print "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; | ||
28 | print "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; | ||
36 | print "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 | |||
51 | exit(0) if defined($Test::Harness::VERSION); | ||
52 | exit($tests - $t); | ||
diff --git a/plugins/t/check_udp.t b/plugins/t/check_udp.t new file mode 100644 index 0000000..abbf5e4 --- /dev/null +++ b/plugins/t/check_udp.t | |||
@@ -0,0 +1,24 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | #use strict; | ||
4 | use Cache; | ||
5 | use Helper; | ||
6 | use Test; | ||
7 | use vars qw($tests); | ||
8 | |||
9 | BEGIN {$tests = 3; plan tests => $tests} | ||
10 | |||
11 | my $null = ''; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | my $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 | |||
23 | exit(0) if defined($Test::Harness::VERSION); | ||
24 | exit($tests - $t); | ||
diff --git a/plugins/t/check_users.t b/plugins/t/check_users.t new file mode 100644 index 0000000..593f173 --- /dev/null +++ b/plugins/t/check_users.t | |||
@@ -0,0 +1,28 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 4; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $cmd; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | |||
15 | $cmd = "./check_users 1000 1000"; | ||
16 | $str = `$cmd`; | ||
17 | $t += ok $?>>8,0; | ||
18 | print "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; | ||
24 | print "Test was: $cmd\n" unless ($?); | ||
25 | $t += ok $str, '/^USERS CRITICAL - [0-9]+ +users currently logged in$/'; | ||
26 | |||
27 | exit(0) if defined($Test::Harness::VERSION); | ||
28 | exit($tests - $t); | ||
diff --git a/plugins/t/check_vsz.t b/plugins/t/check_vsz.t new file mode 100644 index 0000000..9597261 --- /dev/null +++ b/plugins/t/check_vsz.t | |||
@@ -0,0 +1,28 @@ | |||
1 | #! /usr/bin/perl -w | ||
2 | |||
3 | use strict; | ||
4 | use Cache; | ||
5 | use Test; | ||
6 | use vars qw($tests); | ||
7 | |||
8 | BEGIN {$tests = 4; plan tests => $tests} | ||
9 | |||
10 | my $null = ''; | ||
11 | my $cmd; | ||
12 | my $str; | ||
13 | my $t; | ||
14 | |||
15 | $cmd = "./check_vsz 100000 1000000 init"; | ||
16 | $str = `$cmd`; | ||
17 | $t += ok $?>>8,0; | ||
18 | print "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; | ||
24 | print "Test was: $cmd\n" unless ($?); | ||
25 | $t += ok $str, '/^CRITICAL \(VSZ\>[0-9]+\)/'; | ||
26 | |||
27 | exit(0) if defined($Test::Harness::VERSION); | ||
28 | exit($tests - $t); | ||
diff --git a/plugins/tests/check_disk b/plugins/tests/check_disk new file mode 100644 index 0000000..c4323e0 --- /dev/null +++ b/plugins/tests/check_disk | |||
@@ -0,0 +1,9 @@ | |||
1 | check_disk | ||
2 | |||
3 | [normal] | ||
4 | 100 100 / | ||
5 | ^Disk ok - +[\.0-9]+ | ||
6 | |||
7 | [critical] | ||
8 | 0 0 / | ||
9 | ^Only +[\.0-9]+ | ||
diff --git a/plugins/tests/check_dns b/plugins/tests/check_dns new file mode 100644 index 0000000..2e9b9a0 --- /dev/null +++ b/plugins/tests/check_dns | |||
@@ -0,0 +1,9 @@ | |||
1 | check_dns | ||
2 | |||
3 | [normal] | ||
4 | 127.0.0.1 | ||
5 | DNS ok - +[\.0-9]+ seconds response time, Address\(es\) is\/are 127\.0\.0\.1 | ||
6 | |||
7 | [critical] | ||
8 | $nullhost | ||
9 | DNS (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 0000000..4266ebd --- /dev/null +++ b/plugins/tests/check_ftp | |||
@@ -0,0 +1,9 @@ | |||
1 | check_ftp | ||
2 | |||
3 | [normal] | ||
4 | $hostname -wt 300 -ct 600 | ||
5 | FTP 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 0000000..df35996 --- /dev/null +++ b/plugins/tests/check_hpjd | |||
@@ -0,0 +1,9 @@ | |||
1 | check_hpjd | ||
2 | |||
3 | [normal] | ||
4 | $printer | ||
5 | ^Printer ok - | ||
6 | |||
7 | [critical] | ||
8 | $noserver | ||
9 | Timeout: No response from ns | ||
diff --git a/plugins/tests/check_http b/plugins/tests/check_http new file mode 100644 index 0000000..e09f6ff --- /dev/null +++ b/plugins/tests/check_http | |||
@@ -0,0 +1,9 @@ | |||
1 | check_http | ||
2 | |||
3 | [normal] | ||
4 | www.infoplease.com -wt 300 -ct 600 | ||
5 | HTTP/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 0000000..5e4be3a --- /dev/null +++ b/plugins/tests/check_load | |||
@@ -0,0 +1,9 @@ | |||
1 | check_load | ||
2 | |||
3 | [normal] | ||
4 | 100 100 100 100 100 100 | ||
5 | ^load average: +[\.0-9]+, +[\.0-9]+, +[\.0-9]+$ | ||
6 | |||
7 | [critical] | ||
8 | 0 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 0000000..115cbaa --- /dev/null +++ b/plugins/tests/check_ping | |||
@@ -0,0 +1,13 @@ | |||
1 | check_ping | ||
2 | |||
3 | [normal] | ||
4 | 127.0.0.1 100 100 1000 1000 -p 1 | ||
5 | PING ok - Packet loss = +[0-9]{1,2}\%, +RTA = [\.0-9]+ ms | ||
6 | |||
7 | [critical] | ||
8 | 127.0.0.1 0 0 0 0 -p 1 | ||
9 | Packet loss = +[0-9]{1,2}\%, +RTA = [\.0-9]+ ms | ||
10 | |||
11 | [critical] | ||
12 | $nullhost 0 0 0 0 -p 1 -to 1 | ||
13 | CRITICAL - Plugin timed out after 1 seconds | ||
diff --git a/plugins/tests/check_procs b/plugins/tests/check_procs new file mode 100644 index 0000000..f7c6522 --- /dev/null +++ b/plugins/tests/check_procs | |||
@@ -0,0 +1,23 @@ | |||
1 | check_procs | ||
2 | |||
3 | # this is a comment | ||
4 | |||
5 | [normal] | ||
6 | 100000 100000 | ||
7 | ^OK - [0-9]+ processes running$ | ||
8 | |||
9 | [normal] | ||
10 | 100000 100000 Z | ||
11 | ^OK - [0-9]+ processes with Z status$ | ||
12 | |||
13 | [warning] | ||
14 | 0 10000000 | ||
15 | ^WARNING - [0-9]+ processes running$ | ||
16 | |||
17 | [critical] | ||
18 | 0 0 | ||
19 | ^CRITICAL - [0-9]+ processes running$ | ||
20 | |||
21 | [critical] | ||
22 | 0 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 0000000..b6cbb42 --- /dev/null +++ b/plugins/tests/check_swap | |||
@@ -0,0 +1,13 @@ | |||
1 | check_swap | ||
2 | |||
3 | [normal] | ||
4 | 100 100 | ||
5 | ^Swap ok - Swap used\: +[0-9]{1,2}\% \([0-9]+ bytes out of [0-9]+\)$ | ||
6 | |||
7 | [critical] | ||
8 | 0 0 | ||
9 | ^CRITICAL - Swap used\: +[0-9]{1,2}\% \([0-9]+ bytes out of [0-9]+\)$ | ||
10 | |||
11 | [critical] | ||
12 | 100 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 0000000..5a7959a --- /dev/null +++ b/plugins/tests/check_users | |||
@@ -0,0 +1,9 @@ | |||
1 | check_users | ||
2 | |||
3 | [normal] | ||
4 | 1000 1000 | ||
5 | ^Users ok - +[0-9]+ users logged in$ | ||
6 | |||
7 | [critical] | ||
8 | 0 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 0000000..4fdec93 --- /dev/null +++ b/plugins/tests/check_vsz | |||
@@ -0,0 +1,9 @@ | |||
1 | check_vsz | ||
2 | |||
3 | [normal] | ||
4 | 100000 1000000 init | ||
5 | ^ok \(all VSZ\<[0-9]+\) | ||
6 | |||
7 | [critical] | ||
8 | 0 0 | ||
9 | ^CRITICAL \(VSZ\>[0-9]+\) | ||
diff --git a/plugins/urlize.c b/plugins/urlize.c new file mode 100644 index 0000000..83c37da --- /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 | |||
44 | void print_usage (char *); | ||
45 | void print_help (char *); | ||
46 | |||
47 | int | ||
48 | main (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 | |||
122 | void | ||
123 | print_usage (char *cmd) | ||
124 | { | ||
125 | printf ("Usage:\n %s <url> <plugin> <arg1> ... <argN>\n", | ||
126 | my_basename (cmd)); | ||
127 | } | ||
128 | |||
129 | void | ||
130 | print_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 0000000..49e4d3d --- /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 | |||
20 | extern int timeout_interval; | ||
21 | |||
22 | char *my_basename (char *); | ||
23 | void support (void); | ||
24 | char *clean_revstring (const char *); | ||
25 | void print_revision (char *, const char *); | ||
26 | void terminate (int, const char *fmt, ...); | ||
27 | RETSIGTYPE timeout_alarm_handler (int); | ||
28 | |||
29 | int is_host (char *); | ||
30 | int is_dotted_quad (char *); | ||
31 | int is_hostname (char *); | ||
32 | |||
33 | int is_integer (char *); | ||
34 | int is_intpos (char *); | ||
35 | int is_intneg (char *); | ||
36 | int is_intnonneg (char *); | ||
37 | int is_intpercent (char *); | ||
38 | |||
39 | int is_numeric (char *); | ||
40 | int is_positive (char *); | ||
41 | int is_negative (char *); | ||
42 | int is_nonnegative (char *); | ||
43 | int is_percentage (char *); | ||
44 | |||
45 | int is_option (char *str); | ||
46 | |||
47 | void strip (char *); | ||
48 | char *strscpy (char *dest, const char *src); | ||
49 | char *strscat (char *dest, const char *src); | ||
50 | char *strnl (char *str); | ||
51 | char *ssprintf (char *str, const char *fmt, ...); | ||
52 | char *strpcpy (char *dest, const char *src, const char *str); | ||
53 | char *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 | |||
61 | char * | ||
62 | my_basename (char *path) | ||
63 | { | ||
64 | if (!strstr (path, "/")) | ||
65 | return path; | ||
66 | else | ||
67 | return 1 + strrchr (path, '/'); | ||
68 | } | ||
69 | |||
70 | |||
71 | void | ||
72 | support (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 | |||
81 | char * | ||
82 | clean_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 | |||
91 | void | ||
92 | print_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 | |||
108 | void | ||
109 | terminate (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 | |||
118 | void | ||
119 | timeout_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 | |||
128 | int | ||
129 | is_host (char *address) | ||
130 | { | ||
131 | if (is_dotted_quad (address) || is_hostname (address)) | ||
132 | return (TRUE); | ||
133 | return (FALSE); | ||
134 | } | ||
135 | |||
136 | int | ||
137 | is_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 | |||
159 | int | ||
160 | is_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 | |||
180 | int | ||
181 | is_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 | |||
190 | int | ||
191 | is_positive (char *number) | ||
192 | { | ||
193 | if (is_numeric (number) && atof (number) > 0.0) | ||
194 | return (TRUE); | ||
195 | return (FALSE); | ||
196 | } | ||
197 | |||
198 | int | ||
199 | is_negative (char *number) | ||
200 | { | ||
201 | if (is_numeric (number) && atof (number) < 0.0) | ||
202 | return (TRUE); | ||
203 | return (FALSE); | ||
204 | } | ||
205 | |||
206 | int | ||
207 | is_nonnegative (char *number) | ||
208 | { | ||
209 | if (is_numeric (number) && atof (number) >= 0.0) | ||
210 | return (TRUE); | ||
211 | return (FALSE); | ||
212 | } | ||
213 | |||
214 | int | ||
215 | is_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 | |||
223 | int | ||
224 | is_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 | |||
237 | int | ||
238 | is_intpos (char *number) | ||
239 | { | ||
240 | if (is_integer (number) && atoi (number) > 0) | ||
241 | return (TRUE); | ||
242 | return (FALSE); | ||
243 | } | ||
244 | |||
245 | int | ||
246 | is_intneg (char *number) | ||
247 | { | ||
248 | if (is_integer (number) && atoi (number) < 0) | ||
249 | return (TRUE); | ||
250 | return (FALSE); | ||
251 | } | ||
252 | |||
253 | int | ||
254 | is_intnonneg (char *number) | ||
255 | { | ||
256 | if (is_integer (number) && atoi (number) >= 0) | ||
257 | return (TRUE); | ||
258 | return (FALSE); | ||
259 | } | ||
260 | |||
261 | int | ||
262 | is_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 | |||
270 | int | ||
271 | is_option (char *str) | ||
272 | { | ||
273 | if (strspn (str, "-") == 1 || strspn (str, "-") == 2) | ||
274 | return TRUE; | ||
275 | return FALSE; | ||
276 | } | ||
277 | |||
278 | |||
279 | |||
280 | |||
281 | |||
282 | void | ||
283 | strip (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 | |||
321 | char * | ||
322 | strscpy (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 | |||
364 | char * | ||
365 | strscat (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 | |||
443 | char * | ||
444 | strnl (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 | |||
481 | char * | ||
482 | ssprintf (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 | |||
547 | char * | ||
548 | strpcpy (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 | |||
585 | char * | ||
586 | strpcat (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 0000000..a21d63d --- /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 | ||
6 | functions that might otherwise be vulnerable to hacking. This | ||
7 | currently includes a standard suite of validation routines to be sure | ||
8 | that an string argument acually converts to its intended type and a | ||
9 | suite of string handling routine that do their own memory management | ||
10 | in order to resist overflow attacks. In addition, a few functions are | ||
11 | provided to standardize version and error reporting accross the entire | ||
12 | suite of plugins. */ | ||
13 | |||
14 | /* Standardize version information, termination */ | ||
15 | |||
16 | char *my_basename (char *); | ||
17 | void support (void); | ||
18 | char *clean_revstring (const char *revstring); | ||
19 | void print_revision (char *, const char *); | ||
20 | void terminate (int result, char *msg, ...); | ||
21 | extern RETSIGTYPE timeout_alarm_handler (int); | ||
22 | |||
23 | /* Handle timeouts */ | ||
24 | |||
25 | time_t start_time, end_time; | ||
26 | int timeout_interval = DEFAULT_SOCKET_TIMEOUT; | ||
27 | |||
28 | /* Test input types */ | ||
29 | |||
30 | int is_host (char *); | ||
31 | int is_dotted_quad (char *); | ||
32 | int is_hostname (char *); | ||
33 | |||
34 | int is_integer (char *); | ||
35 | int is_intpos (char *); | ||
36 | int is_intneg (char *); | ||
37 | int is_intnonneg (char *); | ||
38 | int is_intpercent (char *); | ||
39 | |||
40 | int is_numeric (char *); | ||
41 | int is_positive (char *); | ||
42 | int is_negative (char *); | ||
43 | int is_nonnegative (char *); | ||
44 | int is_percentage (char *); | ||
45 | |||
46 | int is_option (char *); | ||
47 | |||
48 | /* Handle strings safely */ | ||
49 | |||
50 | void strip (char *buffer); | ||
51 | char *strscpy (char *dest, char *src); | ||
52 | char *strscat (char *dest, char *src); | ||
53 | char *strnl (char *str); | ||
54 | char *ssprintf (char *str, const char *fmt, ...); | ||
55 | char *strpcpy (char *dest, const char *src, const char *str); | ||
56 | char *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();\ | ||
63 | exit(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 0000000..e41aaee --- /dev/null +++ b/plugins/version.h.in | |||
@@ -0,0 +1,2 @@ | |||
1 | #define PACKAGE_VERSION "1.3.0-alpha1" | ||
2 | #define CVS_DATE "$Date$" | ||