7e7b36a4b01882e3b429d148618b2679fd19934c
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 (at
6 your option) any later version.
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 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 const char *progname = "check_ups";
20 const char *revision = "$Revision$";
21 const char *copyright = "2000-2002";
22 const char *email = "nagiosplug-devel@lists.sourceforge.net";
24 #include "common.h"
25 #include "netutils.h"
26 #include "utils.h"
28 enum {
29 PORT = 3493
30 };
32 #define CHECK_NONE 0
34 #define UPS_NONE 0 /* no supported options */
35 #define UPS_UTILITY 1 /* supports utility line voltage */
36 #define UPS_BATTPCT 2 /* supports percent battery remaining */
37 #define UPS_STATUS 4 /* supports UPS status */
38 #define UPS_TEMP 8 /* supports UPS temperature */
39 #define UPS_LOADPCT 16 /* supports load percent */
41 #define UPSSTATUS_NONE 0
42 #define UPSSTATUS_OFF 1
43 #define UPSSTATUS_OL 2
44 #define UPSSTATUS_OB 4
45 #define UPSSTATUS_LB 8
46 #define UPSSTATUS_CAL 16
47 #define UPSSTATUS_RB 32 /*Replace Battery */
48 #define UPSSTATUS_UNKOWN 64
50 int server_port = PORT;
51 char *server_address;
52 char *ups_name = NULL;
53 double warning_value = 0.0;
54 double critical_value = 0.0;
55 int check_warning_value = FALSE;
56 int check_critical_value = FALSE;
57 int check_variable = UPS_NONE;
58 int supported_options = UPS_NONE;
59 int status = UPSSTATUS_NONE;
61 double ups_utility_voltage = 0.0;
62 double ups_battery_percent = 0.0;
63 double ups_load_percent = 0.0;
64 double ups_temperature = 0.0;
65 char *ups_status;
67 int determine_status (void);
68 int determine_supported_vars (void);
69 int get_ups_variable (const char *, char *, size_t);
71 int process_arguments (int, char **);
72 int validate_arguments (void);
73 void print_help (void);
74 void print_usage (void);
76 int
77 main (int argc, char **argv)
78 {
79 int result = STATE_OK;
80 char *message;
81 char temp_buffer[MAX_INPUT_BUFFER];
83 double ups_utility_deviation = 0.0;
84 ups_status = strdup ("N/A");
86 if (process_arguments (argc, argv) != OK)
87 usage ("Invalid command arguments supplied\n");
89 /* initialize alarm signal handling */
90 signal (SIGALRM, socket_timeout_alarm_handler);
92 /* set socket timeout */
93 alarm (socket_timeout);
95 /* determine what variables the UPS supports */
96 if (determine_supported_vars () != OK)
97 return STATE_CRITICAL;
99 /* get the ups status if possible */
100 if (supported_options & UPS_STATUS) {
102 if (determine_status () != OK)
103 return STATE_CRITICAL;
104 ups_status = strdup ("");
105 result = STATE_OK;
107 if (status & UPSSTATUS_OFF) {
108 asprintf (&ups_status, "Off");
109 result = STATE_CRITICAL;
110 }
111 else if ((status & (UPSSTATUS_OB | UPSSTATUS_LB)) ==
112 (UPSSTATUS_OB | UPSSTATUS_LB)) {
113 asprintf (&ups_status, "On Battery, Low Battery");
114 result = STATE_CRITICAL;
115 }
116 else {
117 if (status & UPSSTATUS_OL) {
118 asprintf (&ups_status, "%s%s", ups_status, "Online");
119 }
120 if (status & UPSSTATUS_OB) {
121 asprintf (&ups_status, "%s%s", ups_status, "On Battery");
122 result = STATE_WARNING;
123 }
124 if (status & UPSSTATUS_LB) {
125 asprintf (&ups_status, "%s%s", ups_status, ", Low Battery");
126 result = STATE_WARNING;
127 }
128 if (status & UPSSTATUS_CAL) {
129 asprintf (&ups_status, "%s%s", ups_status, ", Calibrating");
130 }
131 if (status & UPSSTATUS_RB) {
132 asprintf (&ups_status, "%s%s", ups_status, ", Replace Battery");
133 result = STATE_WARNING;
134 }
135 if (status & UPSSTATUS_UNKOWN) {
136 asprintf (&ups_status, "%s%s", ups_status, ", Unknown");
137 }
138 }
139 }
141 /* get the ups utility voltage if possible */
142 if (supported_options & UPS_UTILITY) {
144 if (get_ups_variable ("UTILITY", temp_buffer, sizeof (temp_buffer)) != OK)
145 return STATE_CRITICAL;
147 ups_utility_voltage = atof (temp_buffer);
149 if (ups_utility_voltage > 120.0)
150 ups_utility_deviation = 120.0 - ups_utility_voltage;
151 else
152 ups_utility_deviation = ups_utility_voltage - 120.0;
154 if (check_variable == UPS_UTILITY) {
155 if (check_critical_value == TRUE
156 && ups_utility_deviation >= critical_value) result = STATE_CRITICAL;
157 else if (check_warning_value == TRUE
158 && ups_utility_deviation >= warning_value
159 && result < STATE_WARNING) result = STATE_WARNING;
160 }
161 }
163 /* get the ups battery percent if possible */
164 if (supported_options & UPS_BATTPCT) {
166 if (get_ups_variable ("BATTPCT", temp_buffer, sizeof (temp_buffer)) != OK)
167 return STATE_CRITICAL;
169 ups_battery_percent = atof (temp_buffer);
171 if (check_variable == UPS_BATTPCT) {
172 if (check_critical_value == TRUE
173 && ups_battery_percent <= critical_value) result = STATE_CRITICAL;
174 else if (check_warning_value == TRUE
175 && ups_battery_percent <= warning_value
176 && result < STATE_WARNING) result = STATE_WARNING;
177 }
178 }
180 /* get the ups load percent if possible */
181 if (supported_options & UPS_LOADPCT) {
183 if (get_ups_variable ("LOADPCT", temp_buffer, sizeof (temp_buffer)) != OK)
184 return STATE_CRITICAL;
186 ups_load_percent = atof (temp_buffer);
188 if (check_variable == UPS_LOADPCT) {
189 if (check_critical_value == TRUE && ups_load_percent >= critical_value)
190 result = STATE_CRITICAL;
191 else if (check_warning_value == TRUE
192 && ups_load_percent >= warning_value && result < STATE_WARNING)
193 result = STATE_WARNING;
194 }
195 }
197 /* get the ups temperature if possible */
198 if (supported_options & UPS_TEMP) {
200 if (get_ups_variable ("UPSTEMP", temp_buffer, sizeof (temp_buffer)) != OK)
201 return STATE_CRITICAL;
203 ups_temperature = (atof (temp_buffer) * 1.8) + 32;
205 if (check_variable == UPS_TEMP) {
206 if (check_critical_value == TRUE && ups_temperature >= critical_value)
207 result = STATE_CRITICAL;
208 else if (check_warning_value == TRUE && ups_temperature >= warning_value
209 && result < STATE_WARNING)
210 result = STATE_WARNING;
211 }
212 }
214 /* if the UPS does not support any options we are looking for, report an error */
215 if (supported_options == UPS_NONE)
216 result = STATE_CRITICAL;
218 /* reset timeout */
219 alarm (0);
222 asprintf (&message, "UPS %s - ", (result == STATE_OK) ? "ok" : "problem");
224 if (supported_options & UPS_STATUS)
225 asprintf (&message, "%sStatus=%s ", message, ups_status);
227 if (supported_options & UPS_UTILITY)
228 asprintf (&message, "%sUtility=%3.1fV ", message, ups_utility_voltage);
230 if (supported_options & UPS_BATTPCT)
231 asprintf (&message, "%sBatt=%3.1f%% ", message, ups_battery_percent);
233 if (supported_options & UPS_LOADPCT)
234 asprintf (&message, "%sLoad=%3.1f%% ", message, ups_load_percent);
236 if (supported_options & UPS_TEMP)
237 asprintf (&message, "%sTemp=%3.1fF", message, ups_temperature);
239 if (supported_options == UPS_NONE)
240 asprintf (&message, "UPS does not support any available options\n");
242 printf ("%s\n", message);
244 return result;
245 }
249 /* determines what options are supported by the UPS */
250 int
251 determine_status (void)
252 {
253 char recv_buffer[MAX_INPUT_BUFFER];
254 char temp_buffer[MAX_INPUT_BUFFER];
255 char *ptr;
257 if (get_ups_variable ("STATUS", recv_buffer, sizeof (recv_buffer)) !=
258 STATE_OK) {
259 printf ("Invalid response received from hostn");
260 return ERROR;
261 }
263 recv_buffer[strlen (recv_buffer) - 1] = 0;
265 strcpy (temp_buffer, recv_buffer);
266 for (ptr = (char *) strtok (temp_buffer, " "); ptr != NULL;
267 ptr = (char *) strtok (NULL, " ")) {
268 if (!strcmp (ptr, "OFF"))
269 status |= UPSSTATUS_OFF;
270 else if (!strcmp (ptr, "OL"))
271 status |= UPSSTATUS_OL;
272 else if (!strcmp (ptr, "OB"))
273 status |= UPSSTATUS_OB;
274 else if (!strcmp (ptr, "LB"))
275 status |= UPSSTATUS_LB;
276 else if (!strcmp (ptr, "CAL"))
277 status |= UPSSTATUS_CAL;
278 else if (!strcmp (ptr, "RB"))
279 status |= UPSSTATUS_RB;
280 else
281 status |= UPSSTATUS_UNKOWN;
282 }
284 return OK;
285 }
288 /* determines what options are supported by the UPS */
289 int
290 determine_supported_vars (void)
291 {
292 char send_buffer[MAX_INPUT_BUFFER];
293 char recv_buffer[MAX_INPUT_BUFFER];
294 char temp_buffer[MAX_INPUT_BUFFER];
295 char *ptr;
298 /* get the list of variables that this UPS supports */
299 if (ups_name)
300 sprintf (send_buffer, "LISTVARS %s\r\n", ups_name);
301 else
302 sprintf (send_buffer, "LISTVARS\r\n");
303 if (process_tcp_request
304 (server_address, server_port, send_buffer, recv_buffer,
305 sizeof (recv_buffer)) != STATE_OK) {
306 printf ("Invalid response received from host\n");
307 return ERROR;
308 }
310 recv_buffer[strlen (recv_buffer) - 1] = 0;
312 if (ups_name)
313 ptr = recv_buffer + 5 + strlen (ups_name) + 2;
314 else
315 ptr = recv_buffer + 5;
317 strcpy (temp_buffer, recv_buffer);
319 for (ptr = (char *) strtok (temp_buffer, " "); ptr != NULL;
320 ptr = (char *) strtok (NULL, " ")) {
321 if (!strcmp (ptr, "UTILITY"))
322 supported_options |= UPS_UTILITY;
323 else if (!strcmp (ptr, "BATTPCT"))
324 supported_options |= UPS_BATTPCT;
325 else if (!strcmp (ptr, "LOADPCT"))
326 supported_options |= UPS_LOADPCT;
327 else if (!strcmp (ptr, "STATUS"))
328 supported_options |= UPS_STATUS;
329 else if (!strcmp (ptr, "UPSTEMP"))
330 supported_options |= UPS_TEMP;
331 }
333 return OK;
334 }
337 /* gets a variable value for a specific UPS */
338 int
339 get_ups_variable (const char *varname, char *buf, size_t buflen)
340 {
341 /* char command[MAX_INPUT_BUFFER]; */
342 char temp_buffer[MAX_INPUT_BUFFER];
343 char send_buffer[MAX_INPUT_BUFFER];
344 char *ptr;
346 /* create the command string to send to the UPS daemon */
347 if (ups_name)
348 sprintf (send_buffer, "REQ %s@%s\n", varname, ups_name);
349 else
350 sprintf (send_buffer, "REQ %s\n", varname);
352 /* send the command to the daemon and get a response back */
353 if (process_tcp_request
354 (server_address, server_port, send_buffer, temp_buffer,
355 sizeof (temp_buffer)) != STATE_OK) {
356 printf ("Invalid response received from host\n");
357 return ERROR;
358 }
360 if (ups_name)
361 ptr = temp_buffer + strlen (varname) + 5 + strlen (ups_name) + 1;
362 else
363 ptr = temp_buffer + strlen (varname) + 5;
365 if (!strcmp (ptr, "NOT-SUPPORTED")) {
366 printf ("Error: Variable '%s' is not supported\n", varname);
367 return ERROR;
368 }
370 if (!strcmp (ptr, "DATA-STALE")) {
371 printf ("Error: UPS data is stale\n");
372 return ERROR;
373 }
375 if (!strcmp (ptr, "UNKNOWN-UPS")) {
376 if (ups_name)
377 printf ("Error: UPS '%s' is unknown\n", ups_name);
378 else
379 printf ("Error: UPS is unknown\n");
380 return ERROR;
381 }
383 strncpy (buf, ptr, buflen - 1);
384 buf[buflen - 1] = 0;
386 return OK;
387 }
393 /* Command line: CHECK_UPS <host_address> [-u ups] [-p port] [-v variable]
394 [-wv warn_value] [-cv crit_value] [-to to_sec] */
397 /* process command-line arguments */
398 int
399 process_arguments (int argc, char **argv)
400 {
401 int c;
403 int option = 0;
404 static struct option longopts[] = {
405 {"hostname", required_argument, 0, 'H'},
406 {"ups", required_argument, 0, 'u'},
407 {"port", required_argument, 0, 'p'},
408 {"critical", required_argument, 0, 'c'},
409 {"warning", required_argument, 0, 'w'},
410 {"timeout", required_argument, 0, 't'},
411 {"variable", required_argument, 0, 'v'},
412 {"version", no_argument, 0, 'V'},
413 {"help", no_argument, 0, 'h'},
414 {0, 0, 0, 0}
415 };
417 if (argc < 2)
418 return ERROR;
420 for (c = 1; c < argc; c++) {
421 if (strcmp ("-to", argv[c]) == 0)
422 strcpy (argv[c], "-t");
423 else if (strcmp ("-wt", argv[c]) == 0)
424 strcpy (argv[c], "-w");
425 else if (strcmp ("-ct", argv[c]) == 0)
426 strcpy (argv[c], "-c");
427 }
429 while (1) {
430 c = getopt_long (argc, argv, "hVH:u:p:v:c:w:t:", longopts,
431 &option);
433 if (c == -1 || c == EOF)
434 break;
436 switch (c) {
437 case '?': /* help */
438 usage3 ("Unknown option", optopt);
439 case 'H': /* hostname */
440 if (is_host (optarg)) {
441 server_address = optarg;
442 }
443 else {
444 usage2 ("Invalid host name", optarg);
445 }
446 break;
447 case 'u': /* ups name */
448 ups_name = optarg;
449 break;
450 case 'p': /* port */
451 if (is_intpos (optarg)) {
452 server_port = atoi (optarg);
453 }
454 else {
455 usage2 ("Server port must be a positive integer", optarg);
456 }
457 break;
458 case 'c': /* critical time threshold */
459 if (is_intnonneg (optarg)) {
460 critical_value = atoi (optarg);
461 check_critical_value = TRUE;
462 }
463 else {
464 usage2 ("Critical time must be a nonnegative integer", optarg);
465 }
466 break;
467 case 'w': /* warning time threshold */
468 if (is_intnonneg (optarg)) {
469 warning_value = atoi (optarg);
470 check_warning_value = TRUE;
471 }
472 else {
473 usage2 ("Warning time must be a nonnegative integer", optarg);
474 }
475 break;
476 case 'v': /* variable */
477 if (!strcmp (optarg, "LINE"))
478 check_variable = UPS_UTILITY;
479 else if (!strcmp (optarg, "TEMP"))
480 check_variable = UPS_TEMP;
481 else if (!strcmp (optarg, "BATTPCT"))
482 check_variable = UPS_BATTPCT;
483 else if (!strcmp (optarg, "LOADPCT"))
484 check_variable = UPS_LOADPCT;
485 else
486 usage2 ("Unrecognized UPS variable", optarg);
487 break;
488 case 't': /* timeout */
489 if (is_intnonneg (optarg)) {
490 socket_timeout = atoi (optarg);
491 }
492 else {
493 usage ("Time interval must be a nonnegative integer\n");
494 }
495 break;
496 case 'V': /* version */
497 print_revision (progname, "$Revision$");
498 exit (STATE_OK);
499 case 'h': /* help */
500 print_help ();
501 exit (STATE_OK);
502 }
503 }
506 if (server_address == NULL && argc > optind) {
507 if (is_host (argv[optind]))
508 server_address = argv[optind++];
509 else
510 usage ("Invalid host name");
511 }
513 if (server_address == NULL)
514 server_address = strdup("127.0.0.1");
516 return validate_arguments();
517 }
523 int
524 validate_arguments (void)
525 {
526 return OK;
527 }
533 \f
534 void
535 print_help (void)
536 {
537 char *myport;
538 asprintf (&myport, "%d", PORT);
540 print_revision (progname, revision);
542 printf (_("Copyright (c) 2000 Tom Shields"));
543 printf (_(COPYRIGHT), copyright, email);
545 printf (_("This plugin tests the UPS service on the specified host.\n\
546 Network UPS Tools from www.exploits.org must be running for this plugin to\n\
547 work.\n\n"));
549 print_usage ();
551 printf (_(UT_HELP_VRSN));
553 printf (_(UT_HOST_PORT), 'p', myport);
555 printf (_("\
556 -u, --ups=STRING\n\
557 Name of UPS\n"));
559 printf (_(UT_WARN_CRIT));
561 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
563 printf (_(UT_VERBOSE));
565 printf (_("\
566 This plugin attempts to determine the status of a UPS (Uninterruptible Power\n\
567 Supply) on a local or remote host. If the UPS is online or calibrating, the\n\
568 plugin will return an OK state. If the battery is on it will return a WARNING\n\
569 state. If the UPS is off or has a low battery the plugin will return a CRITICAL\n\
570 state.\n\n"));
572 printf (_("\
573 You may also specify a variable to check [such as temperature, utility voltage,\n\
574 battery load, etc.] as well as warning and critical thresholds for the value of\n\
575 that variable. If the remote host has multiple UPS that are being monitored you\n\
576 will have to use the [ups] option to specify which UPS to check.\n\n"));
578 printf (_("Notes:\n\n\
579 This plugin requires that the UPSD daemon distributed with Russel Kroll's\n\
580 Smart UPS Tools be installed on the remote host. If you do not have the\n\
581 package installed on your system, you can download it from\n\
582 http://www.exploits.org/nut\n\n"));
584 printf (_(UT_SUPPORT));
585 }
590 void
591 print_usage (void)
592 {
593 printf (_("\
594 Usage: %s -H host [-e expect] [-p port] [-w warn] [-c crit]\n\
595 [-t timeout] [-v]\n"), progname);
596 printf (_(UT_HLP_VRS), progname, progname);
597 }