1 /******************************************************************************
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 ******************************************************************************/
19 #include "common.h"
20 #include "netutils.h"
21 #include "utils.h"
23 const char *progname = "check_time";
24 const char *revision = "$Revision$";
25 const char *copyright = "1999-2003";
26 const char *email = "nagiosplug-devel@lists.sourceforge.net";
28 enum {
29 TIME_PORT = 37
30 };
32 #define UNIX_EPOCH 2208988800UL
34 unsigned long server_time, raw_server_time;
35 time_t diff_time;
36 int warning_time = 0;
37 int check_warning_time = FALSE;
38 int critical_time = 0;
39 int check_critical_time = FALSE;
40 unsigned long warning_diff = 0;
41 int check_warning_diff = FALSE;
42 unsigned long critical_diff = 0;
43 int check_critical_diff = FALSE;
44 int server_port = TIME_PORT;
45 char *server_address = NULL;
47 int process_arguments (int, char **);
48 void print_help (void);
49 void print_usage (void);
51 int
52 main (int argc, char **argv)
53 {
54 int sd;
55 int result;
57 if (process_arguments (argc, argv) != OK)
58 usage (_("Invalid command arguments supplied\n"));
60 /* initialize alarm signal handling */
61 signal (SIGALRM, socket_timeout_alarm_handler);
63 /* set socket timeout */
64 alarm (socket_timeout);
65 time (&start_time);
67 /* try to connect to the host at the given port number */
68 if (my_tcp_connect (server_address, server_port, &sd) != STATE_OK) {
69 if (check_critical_time == TRUE)
70 result = STATE_CRITICAL;
71 else if (check_warning_time == TRUE)
72 result = STATE_WARNING;
73 else
74 result = STATE_UNKNOWN;
75 die (result,
76 _("TIME UNKNOWN - could not connect to server %s, port %d\n"),
77 server_address, server_port);
78 }
80 /* watch for the connection string */
81 result = recv (sd, (void *)&raw_server_time, sizeof (raw_server_time), 0);
83 /* close the connection */
84 close (sd);
86 /* reset the alarm */
87 time (&end_time);
88 alarm (0);
90 /* return a WARNING status if we couldn't read any data */
91 if (result <= 0) {
92 if (check_critical_time == TRUE)
93 result = STATE_CRITICAL;
94 else if (check_warning_time == TRUE)
95 result = STATE_WARNING;
96 else
97 result = STATE_UNKNOWN;
98 die (result,
99 _("TIME UNKNOWN - no data on recv() from server %s, port %d\n"),
100 server_address, server_port);
101 }
103 result = STATE_OK;
105 if (check_critical_time == TRUE && (end_time - start_time) > critical_time)
106 result = STATE_CRITICAL;
107 else if (check_warning_time == TRUE
108 && (end_time - start_time) > warning_time) result = STATE_WARNING;
110 if (result != STATE_OK)
111 die (result, _("TIME %s - %d second response time\n"),
112 state_text (result), (int) (end_time - start_time));
114 server_time = ntohl (raw_server_time) - UNIX_EPOCH;
115 if (server_time > (unsigned long)end_time)
116 diff_time = server_time - (unsigned long)end_time;
117 else
118 diff_time = (unsigned long)end_time - server_time;
120 if (check_critical_diff == TRUE && diff_time > (time_t)critical_diff)
121 result = STATE_CRITICAL;
122 else if (check_warning_diff == TRUE && diff_time > (time_t)warning_diff)
123 result = STATE_WARNING;
125 printf (_("TIME %s - %lu second time difference\n"), state_text (result),
126 diff_time);
127 return result;
128 }
135 /* process command-line arguments */
136 int
137 process_arguments (int argc, char **argv)
138 {
139 int c;
141 int option = 0;
142 static struct option longopts[] = {
143 {"hostname", required_argument, 0, 'H'},
144 {"warning-variance", required_argument, 0, 'w'},
145 {"critical-variance", required_argument, 0, 'c'},
146 {"warning-connect", required_argument, 0, 'W'},
147 {"critical-connect", required_argument, 0, 'C'},
148 {"port", required_argument, 0, 'p'},
149 {"timeout", required_argument, 0, 't'},
150 {"version", no_argument, 0, 'V'},
151 {"help", no_argument, 0, 'h'},
152 {0, 0, 0, 0}
153 };
155 if (argc < 2)
156 usage ("\n");
158 for (c = 1; c < argc; c++) {
159 if (strcmp ("-to", argv[c]) == 0)
160 strcpy (argv[c], "-t");
161 else if (strcmp ("-wd", argv[c]) == 0)
162 strcpy (argv[c], "-w");
163 else if (strcmp ("-cd", argv[c]) == 0)
164 strcpy (argv[c], "-c");
165 else if (strcmp ("-wt", argv[c]) == 0)
166 strcpy (argv[c], "-W");
167 else if (strcmp ("-ct", argv[c]) == 0)
168 strcpy (argv[c], "-C");
169 }
171 while (1) {
172 c = getopt_long (argc, argv, "hVH:w:c:W:C:p:t:", longopts,
173 &option);
175 if (c == -1 || c == EOF)
176 break;
178 switch (c) {
179 case '?': /* print short usage statement if args not parsable */
180 usage3 (_("Unknown argument"), optopt);
181 case 'h': /* help */
182 print_help ();
183 exit (STATE_OK);
184 case 'V': /* version */
185 print_revision (progname, revision);
186 exit (STATE_OK);
187 case 'H': /* hostname */
188 if (is_host (optarg) == FALSE)
189 usage (_("Invalid host name/address\n"));
190 server_address = optarg;
191 break;
192 case 'w': /* warning-variance */
193 if (is_intnonneg (optarg)) {
194 warning_diff = strtoul (optarg, NULL, 10);
195 check_warning_diff = TRUE;
196 }
197 else if (strspn (optarg, "0123456789:,") > 0) {
198 if (sscanf (optarg, "%lu%*[:,]%d", &warning_diff, &warning_time) == 2) {
199 check_warning_diff = TRUE;
200 check_warning_time = TRUE;
201 }
202 else {
203 usage (_("Warning thresholds must be a nonnegative integer\n"));
204 }
205 }
206 else {
207 usage (_("Warning threshold must be a nonnegative integer\n"));
208 }
209 break;
210 case 'c': /* critical-variance */
211 if (is_intnonneg (optarg)) {
212 critical_diff = strtoul (optarg, NULL, 10);
213 check_critical_diff = TRUE;
214 }
215 else if (strspn (optarg, "0123456789:,") > 0) {
216 if (sscanf (optarg, "%lu%*[:,]%d", &critical_diff, &critical_time) ==
217 2) {
218 check_critical_diff = TRUE;
219 check_critical_time = TRUE;
220 }
221 else {
222 usage (_("Critical thresholds must be a nonnegative integer\n"));
223 }
224 }
225 else {
226 usage (_("Critical threshold must be a nonnegative integer\n"));
227 }
228 break;
229 case 'W': /* warning-connect */
230 if (!is_intnonneg (optarg))
231 usage (_("Warning threshold must be a nonnegative integer\n"));
232 else
233 warning_time = atoi (optarg);
234 check_warning_time = TRUE;
235 break;
236 case 'C': /* critical-connect */
237 if (!is_intnonneg (optarg))
238 usage (_("Critical threshold must be a nonnegative integer\n"));
239 else
240 critical_time = atoi (optarg);
241 check_critical_time = TRUE;
242 break;
243 case 'p': /* port */
244 if (!is_intnonneg (optarg))
245 usage (_("Server port must be a nonnegative integer\n"));
246 else
247 server_port = atoi (optarg);
248 break;
249 case 't': /* timeout */
250 if (!is_intnonneg (optarg))
251 usage (_("Timeout interval must be a nonnegative integer\n"));
252 else
253 socket_timeout = atoi (optarg);
254 break;
255 }
256 }
258 c = optind;
259 if (server_address == NULL) {
260 if (argc > c) {
261 if (is_host (argv[c]) == FALSE)
262 usage (_("Invalid host name/address\n"));
263 server_address = argv[c];
264 }
265 else {
266 usage (_("Host name was not supplied\n"));
267 }
268 }
270 return OK;
271 }
277 \f
278 void
279 print_help (void)
280 {
281 char *myport;
282 asprintf (&myport, "%d", TIME_PORT);
284 print_revision (progname, revision);
286 printf (_("Copyright (c) 1999 Ethan Galstad\n"));
287 printf (_(COPYRIGHT), copyright, email);
289 printf (_("\
290 This plugin will check the time on the specified host.\n\n"));
292 print_usage ();
294 printf (_(UT_HELP_VRSN));
296 printf (_(UT_HOST_PORT), 'p', myport);
298 printf (_("\
299 -w, --warning-variance=INTEGER\n\
300 Time difference (sec.) necessary to result in a warning status\n\
301 -c, --critical-variance=INTEGER\n\
302 Time difference (sec.) necessary to result in a critical status\n\
303 -W, --warning-connect=INTEGER\n\
304 Response time (sec.) necessary to result in warning status\n\
305 -C, --critical-connect=INTEGER\n\
306 Response time (sec.) necessary to result in critical status\n"));
308 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
310 printf (_(UT_SUPPORT));
311 }
316 void
317 print_usage (void)
318 {
319 printf (_("\
320 Usage: %s -H <host_address> [-p port] [-w variance] [-c variance]\n\
321 [-W connect_time] [-C connect_time] [-t timeout]\n"), progname);
322 printf (_(UT_HLP_VRS), progname, progname);
323 }