1 /******************************************************************************
2 *
3 * Nagios check_time plugin
4 *
5 * License: GPL
6 * Copyright (c) 1999-2006 nagios-plugins team
7 *
8 * Last Modified: $Date$
9 *
10 * Description:
11 *
12 * This file contains the check_time plugin
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 * $Id$
32 *
33 ******************************************************************************/
35 const char *progname = "check_time";
36 const char *revision = "$Revision$";
37 const char *copyright = "1999-2006";
38 const char *email = "nagiosplug-devel@lists.sourceforge.net";
40 #include "common.h"
41 #include "netutils.h"
42 #include "utils.h"
44 enum {
45 TIME_PORT = 37
46 };
48 #define UNIX_EPOCH 2208988800UL
50 uint32_t server_time, raw_server_time;
51 time_t diff_time;
52 int warning_time = 0;
53 int check_warning_time = FALSE;
54 int critical_time = 0;
55 int check_critical_time = FALSE;
56 unsigned long warning_diff = 0;
57 int check_warning_diff = FALSE;
58 unsigned long critical_diff = 0;
59 int check_critical_diff = FALSE;
60 int server_port = TIME_PORT;
61 char *server_address = NULL;
62 int use_udp = FALSE;
64 int process_arguments (int, char **);
65 void print_help (void);
66 void print_usage (void);
68 int
69 main (int argc, char **argv)
70 {
71 int sd;
72 int result = STATE_UNKNOWN;
73 time_t conntime;
75 setlocale (LC_ALL, "");
76 bindtextdomain (PACKAGE, LOCALEDIR);
77 textdomain (PACKAGE);
79 if (process_arguments (argc, argv) == ERROR)
80 usage4 (_("Could not parse arguments"));
82 /* initialize alarm signal handling */
83 signal (SIGALRM, socket_timeout_alarm_handler);
85 /* set socket timeout */
86 alarm (socket_timeout);
87 time (&start_time);
89 /* try to connect to the host at the given port number */
90 if (use_udp) {
91 result = my_udp_connect (server_address, server_port, &sd);
92 } else {
93 result = my_tcp_connect (server_address, server_port, &sd);
94 }
96 if (result != STATE_OK) {
97 if (check_critical_time == TRUE)
98 result = STATE_CRITICAL;
99 else if (check_warning_time == TRUE)
100 result = STATE_WARNING;
101 else
102 result = STATE_UNKNOWN;
103 die (result,
104 _("TIME UNKNOWN - could not connect to server %s, port %d\n"),
105 server_address, server_port);
106 }
108 if (use_udp) {
109 if (send (sd, "", 0, 0) < 0) {
110 if (check_critical_time == TRUE)
111 result = STATE_CRITICAL;
112 else if (check_warning_time == TRUE)
113 result = STATE_WARNING;
114 else
115 result = STATE_UNKNOWN;
116 die (result,
117 _("TIME UNKNOWN - could not send UDP request to server %s, port %d\n"),
118 server_address, server_port);
119 }
120 }
122 /* watch for the connection string */
123 result = recv (sd, (void *)&raw_server_time, sizeof (raw_server_time), 0);
125 /* close the connection */
126 close (sd);
128 /* reset the alarm */
129 time (&end_time);
130 alarm (0);
132 /* return a WARNING status if we couldn't read any data */
133 if (result <= 0) {
134 if (check_critical_time == TRUE)
135 result = STATE_CRITICAL;
136 else if (check_warning_time == TRUE)
137 result = STATE_WARNING;
138 else
139 result = STATE_UNKNOWN;
140 die (result,
141 _("TIME UNKNOWN - no data received from server %s, port %d\n"),
142 server_address, server_port);
143 }
145 result = STATE_OK;
147 conntime = (end_time - start_time);
148 if (check_critical_time == TRUE && conntime > critical_time)
149 result = STATE_CRITICAL;
150 else if (check_warning_time == TRUE && conntime > warning_time)
151 result = STATE_WARNING;
153 if (result != STATE_OK)
154 die (result, _("TIME %s - %d second response time|%s\n"),
155 state_text (result), (int)conntime,
156 perfdata ("time", (long)conntime, "s",
157 check_warning_time, (long)warning_time,
158 check_critical_time, (long)critical_time,
159 TRUE, 0, FALSE, 0));
161 server_time = ntohl (raw_server_time) - UNIX_EPOCH;
162 if (server_time > (unsigned long)end_time)
163 diff_time = server_time - (unsigned long)end_time;
164 else
165 diff_time = (unsigned long)end_time - server_time;
167 if (check_critical_diff == TRUE && diff_time > (time_t)critical_diff)
168 result = STATE_CRITICAL;
169 else if (check_warning_diff == TRUE && diff_time > (time_t)warning_diff)
170 result = STATE_WARNING;
172 printf (_("TIME %s - %lu second time difference|%s %s\n"),
173 state_text (result), diff_time,
174 perfdata ("time", (long)conntime, "s",
175 check_warning_time, (long)warning_time,
176 check_critical_time, (long)critical_time,
177 TRUE, 0, FALSE, 0),
178 perfdata ("offset", (long)diff_time, "s",
179 check_warning_diff, (long)warning_diff,
180 check_critical_diff, (long)critical_diff,
181 TRUE, 0, FALSE, 0));
182 return result;
183 }
187 /* process command-line arguments */
188 int
189 process_arguments (int argc, char **argv)
190 {
191 int c;
193 int option = 0;
194 static struct option longopts[] = {
195 {"hostname", required_argument, 0, 'H'},
196 {"warning-variance", required_argument, 0, 'w'},
197 {"critical-variance", required_argument, 0, 'c'},
198 {"warning-connect", required_argument, 0, 'W'},
199 {"critical-connect", required_argument, 0, 'C'},
200 {"port", required_argument, 0, 'p'},
201 {"udp", no_argument, 0, 'u'},
202 {"timeout", required_argument, 0, 't'},
203 {"version", no_argument, 0, 'V'},
204 {"help", no_argument, 0, 'h'},
205 {0, 0, 0, 0}
206 };
208 if (argc < 2)
209 usage ("\n");
211 for (c = 1; c < argc; c++) {
212 if (strcmp ("-to", argv[c]) == 0)
213 strcpy (argv[c], "-t");
214 else if (strcmp ("-wd", argv[c]) == 0)
215 strcpy (argv[c], "-w");
216 else if (strcmp ("-cd", argv[c]) == 0)
217 strcpy (argv[c], "-c");
218 else if (strcmp ("-wt", argv[c]) == 0)
219 strcpy (argv[c], "-W");
220 else if (strcmp ("-ct", argv[c]) == 0)
221 strcpy (argv[c], "-C");
222 }
224 while (1) {
225 c = getopt_long (argc, argv, "hVH:w:c:W:C:p:t:u", longopts,
226 &option);
228 if (c == -1 || c == EOF)
229 break;
231 switch (c) {
232 case '?': /* print short usage statement if args not parsable */
233 usage2 (_("Unknown argument"), optarg);
234 case 'h': /* help */
235 print_help ();
236 exit (STATE_OK);
237 case 'V': /* version */
238 print_revision (progname, revision);
239 exit (STATE_OK);
240 case 'H': /* hostname */
241 if (is_host (optarg) == FALSE)
242 usage2 (_("Invalid hostname/address"), optarg);
243 server_address = optarg;
244 break;
245 case 'w': /* warning-variance */
246 if (is_intnonneg (optarg)) {
247 warning_diff = strtoul (optarg, NULL, 10);
248 check_warning_diff = TRUE;
249 }
250 else if (strspn (optarg, "0123456789:,") > 0) {
251 if (sscanf (optarg, "%lu%*[:,]%d", &warning_diff, &warning_time) == 2) {
252 check_warning_diff = TRUE;
253 check_warning_time = TRUE;
254 }
255 else {
256 usage4 (_("Warning thresholds must be a positive integer"));
257 }
258 }
259 else {
260 usage4 (_("Warning threshold must be a positive integer"));
261 }
262 break;
263 case 'c': /* critical-variance */
264 if (is_intnonneg (optarg)) {
265 critical_diff = strtoul (optarg, NULL, 10);
266 check_critical_diff = TRUE;
267 }
268 else if (strspn (optarg, "0123456789:,") > 0) {
269 if (sscanf (optarg, "%lu%*[:,]%d", &critical_diff, &critical_time) ==
270 2) {
271 check_critical_diff = TRUE;
272 check_critical_time = TRUE;
273 }
274 else {
275 usage4 (_("Critical thresholds must be a positive integer"));
276 }
277 }
278 else {
279 usage4 (_("Critical threshold must be a positive integer"));
280 }
281 break;
282 case 'W': /* warning-connect */
283 if (!is_intnonneg (optarg))
284 usage4 (_("Warning threshold must be a positive integer"));
285 else
286 warning_time = atoi (optarg);
287 check_warning_time = TRUE;
288 break;
289 case 'C': /* critical-connect */
290 if (!is_intnonneg (optarg))
291 usage4 (_("Critical threshold must be a positive integer"));
292 else
293 critical_time = atoi (optarg);
294 check_critical_time = TRUE;
295 break;
296 case 'p': /* port */
297 if (!is_intnonneg (optarg))
298 usage4 (_("Port must be a positive integer"));
299 else
300 server_port = atoi (optarg);
301 break;
302 case 't': /* timeout */
303 if (!is_intnonneg (optarg))
304 usage2 (_("Timeout interval must be a positive integer"), optarg);
305 else
306 socket_timeout = atoi (optarg);
307 break;
308 case 'u': /* udp */
309 use_udp = TRUE;
310 }
311 }
313 c = optind;
314 if (server_address == NULL) {
315 if (argc > c) {
316 if (is_host (argv[c]) == FALSE)
317 usage2 (_("Invalid hostname/address"), optarg);
318 server_address = argv[c];
319 }
320 else {
321 usage4 (_("Hostname was not supplied"));
322 }
323 }
325 return OK;
326 }
330 void
331 print_help (void)
332 {
333 char *myport;
334 asprintf (&myport, "%d", TIME_PORT);
336 print_revision (progname, revision);
338 printf ("Copyright (c) 1999 Ethan Galstad\n");
339 printf (COPYRIGHT, copyright, email);
341 printf ("%s\n", _("This plugin will check the time on the specified host."));
343 printf ("\n\n");
345 print_usage ();
347 printf (_(UT_HELP_VRSN));
349 printf (_(UT_HOST_PORT), 'p', myport);
351 printf (" %s\n", "-u, --udp");
352 printf (" %s\n", _("Use UDP to connect, not TCP"));
353 printf (" %s\n", "-w, --warning-variance=INTEGER");
354 printf (" %s\n", _("Time difference (sec.) necessary to result in a warning status"));
355 printf (" %s\n", "-c, --critical-variance=INTEGER");
356 printf (" %s\n", _("Time difference (sec.) necessary to result in a critical status"));
357 printf (" %s\n", "-W, --warning-connect=INTEGER");
358 printf (" %s\n", _("Response time (sec.) necessary to result in warning status"));
359 printf (" %s\n", "-C, --critical-connect=INTEGER");
360 printf (" %s\n", _("Response time (sec.) necessary to result in critical status"));
362 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
363 printf (_(UT_SUPPORT));
364 }
368 void
369 print_usage (void)
370 {
371 printf (_("Usage:"));
372 printf ("%s -H <host_address> [-p port] [-u] [-w variance] [-c variance]\n",progname);
373 printf (" [-W connect_time] [-C connect_time] [-t timeout]\n");
374 }