Addition to help to state that -f will always return OK if ssh command
[monitoring-plugins.git] / plugins / check_ide_smart.c
blob02f07c012d3140dab0395b6129559d65ec114cc0
1 /*****************************************************************************
2 *
3 * Nagios check_ide_smart plugin
4 * ide-smart 1.3 - IDE S.M.A.R.T. checking tool
5 *
6 * License: GPL
7 * Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>
8 * 1998 Gadi Oxman <gadio@netvision.net.il>
9 * Copyright (c) 2000 Robert Dale <rdale@digital-mission.com>
10 * Copyright (c) 2000-2007 Nagios Plugins Development Team
12 * Last Modified: $Date$
14 * Description:
16 * This file contains the check_ide_smart plugin
18 * This plugin checks a local hard drive with the (Linux specific) SMART
19 * interface
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 3 of the License, or
25 * (at your option) any later version.
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.
32 * You should have received a copy of the GNU General Public License
33 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35 * $Id$
37 *****************************************************************************/
39 const char *progname = "check_ide_smart";
40 const char *revision = "$Revision$";
41 const char *copyright = "1998-2007";
42 const char *email = "nagiosplug-devel@lists.sourceforge.net";
44 #include "common.h"
45 #include "utils.h"
47 void print_help (void);
48 void print_usage (void);
50 #include <sys/stat.h>
51 #include <sys/ioctl.h>
52 #include <fcntl.h>
53 #include <linux/hdreg.h>
54 #include <linux/types.h>
55 #include <errno.h>
57 #define NR_ATTRIBUTES 30
59 #ifndef TRUE
60 #define TRUE 1
61 #endif /* */
63 #define PREFAILURE 2
64 #define ADVISORY 1
65 #define OPERATIONAL 0
66 #define UNKNOWN -1
68 typedef struct threshold_s
70 __u8 id;
71 __u8 threshold;
72 __u8 reserved[10];
74 __attribute__ ((packed)) threshold_t;
76 typedef struct thresholds_s
78 __u16 revision;
79 threshold_t thresholds[NR_ATTRIBUTES];
80 __u8 reserved[18];
81 __u8 vendor[131];
82 __u8 checksum;
84 __attribute__ ((packed)) thresholds_t;
86 typedef struct value_s
88 __u8 id;
89 __u16 status;
90 __u8 value;
91 __u8 vendor[8];
93 __attribute__ ((packed)) value_t;
95 typedef struct values_s
97 __u16 revision;
98 value_t values[NR_ATTRIBUTES];
99 __u8 offline_status;
100 __u8 vendor1;
101 __u16 offline_timeout;
102 __u8 vendor2;
103 __u8 offline_capability;
104 __u16 smart_capability;
105 __u8 reserved[16];
106 __u8 vendor[125];
107 __u8 checksum;
109 __attribute__ ((packed)) values_t;
111 struct
113 __u8 value;
114 char *text;
117 offline_status_text[] =
119 {0x00, "NeverStarted"},
120 {0x02, "Completed"},
121 {0x04, "Suspended"},
122 {0x05, "Aborted"},
123 {0x06, "Failed"},
124 {0, 0}
127 struct
129 __u8 value;
130 char *text;
133 smart_command[] =
135 {SMART_ENABLE, "SMART_ENABLE"},
136 {SMART_DISABLE, "SMART_DISABLE"},
137 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"},
138 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"}
142 /* Index to smart_command table, keep in order */
143 enum SmartCommand
144 { SMART_CMD_ENABLE,
145 SMART_CMD_DISABLE,
146 SMART_CMD_IMMEDIATE_OFFLINE,
147 SMART_CMD_AUTO_OFFLINE
150 void print_values (values_t * p, thresholds_t * t);
151 int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, char show_error);
154 main (int argc, char *argv[])
156 char *device = NULL;
157 int command = -1;
158 int o, longindex;
159 int retval = 0;
161 thresholds_t thresholds;
162 values_t values;
163 int fd;
165 /* Parse extra opts if any */
166 argv=np_extra_opts (&argc, argv, progname);
168 static struct option longopts[] = {
169 {"device", required_argument, 0, 'd'},
170 {"immediate", no_argument, 0, 'i'},
171 {"quiet-check", no_argument, 0, 'q'},
172 {"auto-on", no_argument, 0, '1'},
173 {"auto-off", no_argument, 0, '0'},
174 {"nagios", no_argument, 0, 'n'},
175 {"help", no_argument, 0, 'h'},
176 {"version", no_argument, 0, 'V'}, {0, 0, 0, 0}
179 setlocale (LC_ALL, "");
180 bindtextdomain (PACKAGE, LOCALEDIR);
181 textdomain (PACKAGE);
183 while (1) {
185 o = getopt_long (argc, argv, "+d:iq10nhV", longopts, &longindex);
187 if (o == -1 || o == EOF || o == 1)
188 break;
190 switch (o) {
191 case 'd':
192 device = optarg;
193 break;
194 case 'q':
195 command = 3;
196 break;
197 case 'i':
198 command = 2;
199 break;
200 case '1':
201 command = 1;
202 break;
203 case '0':
204 command = 0;
205 break;
206 case 'n':
207 command = 4;
208 break;
209 case 'h':
210 print_help ();
211 return STATE_OK;
212 case 'V':
213 print_revision (progname, revision);
214 return STATE_OK;
215 default:
216 usage5 ();
220 if (optind < argc) {
221 device = argv[optind];
224 if (!device) {
225 print_help ();
226 return STATE_OK;
229 fd = open (device, O_RDONLY);
231 if (fd < 0) {
232 printf (_("CRITICAL - Couldn't open device %s: %s\n"), device, strerror (errno));
233 return STATE_CRITICAL;
236 if (smart_cmd_simple (fd, SMART_CMD_ENABLE, 0, TRUE)) {
237 printf (_("CRITICAL - SMART_CMD_ENABLE\n"));
238 return STATE_CRITICAL;
241 switch (command) {
242 case 0:
243 retval = smart_cmd_simple (fd, SMART_CMD_AUTO_OFFLINE, 0, TRUE);
244 break;
245 case 1:
246 retval = smart_cmd_simple (fd, SMART_CMD_AUTO_OFFLINE, 0xF8, TRUE);
247 break;
248 case 2:
249 retval = smart_cmd_simple (fd, SMART_CMD_IMMEDIATE_OFFLINE, 0, TRUE);
250 break;
251 case 3:
252 smart_read_values (fd, &values);
253 smart_read_thresholds (fd, &thresholds);
254 retval = values_not_passed (&values, &thresholds);
255 break;
256 case 4:
257 smart_read_values (fd, &values);
258 smart_read_thresholds (fd, &thresholds);
259 retval = nagios (&values, &thresholds);
260 break;
261 default:
262 smart_read_values (fd, &values);
263 smart_read_thresholds (fd, &thresholds);
264 print_values (&values, &thresholds);
265 break;
267 close (fd);
268 return retval;
273 char *
274 get_offline_text (int status)
276 int i;
277 for (i = 0; offline_status_text[i].text; i++) {
278 if (offline_status_text[i].value == status) {
279 return offline_status_text[i].text;
282 return "UNKNOW";
288 smart_read_values (int fd, values_t * values)
290 int e;
291 __u8 args[4 + 512];
292 args[0] = WIN_SMART;
293 args[1] = 0;
294 args[2] = SMART_READ_VALUES;
295 args[3] = 1;
296 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
297 e = errno;
298 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno));
299 return e;
301 memcpy (values, args + 4, 512);
302 return 0;
308 values_not_passed (values_t * p, thresholds_t * t)
310 value_t * value = p->values;
311 threshold_t * threshold = t->thresholds;
312 int failed = 0;
313 int passed = 0;
314 int i;
315 for (i = 0; i < NR_ATTRIBUTES; i++) {
316 if (value->id && threshold->id && value->id == threshold->id) {
317 if (value->value <= threshold->threshold) {
318 ++failed;
320 else {
321 ++passed;
324 ++value;
325 ++threshold;
327 return (passed ? -failed : 2);
333 nagios (values_t * p, thresholds_t * t)
335 value_t * value = p->values;
336 threshold_t * threshold = t->thresholds;
337 int status = OPERATIONAL;
338 int prefailure = 0;
339 int advisory = 0;
340 int failed = 0;
341 int passed = 0;
342 int total = 0;
343 int i;
344 for (i = 0; i < NR_ATTRIBUTES; i++) {
345 if (value->id && threshold->id && value->id == threshold->id) {
346 if (value->value <= threshold->threshold) {
347 ++failed;
348 if (value->status & 1) {
349 status = PREFAILURE;
350 ++prefailure;
352 else {
353 status = ADVISORY;
354 ++advisory;
357 else {
358 ++passed;
360 ++total;
362 ++value;
363 ++threshold;
365 switch (status) {
366 case PREFAILURE:
367 printf (_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"),
368 prefailure,
369 prefailure > 1 ? 's' : ' ',
370 failed,
371 total);
372 status=STATE_CRITICAL;
373 break;
374 case ADVISORY:
375 printf (_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"),
376 advisory,
377 advisory > 1 ? "ies" : "y",
378 failed,
379 total);
380 status=STATE_WARNING;
381 break;
382 case OPERATIONAL:
383 printf (_("OK - Operational (%d/%d tests passed)\n"), passed, total);
384 status=STATE_OK;
385 break;
386 default:
387 printf (_("ERROR - Status '%d' unkown. %d/%d tests passed\n"), status,
388 passed, total);
389 status = STATE_UNKNOWN;
390 break;
392 return status;
397 void
398 print_value (value_t * p, threshold_t * t)
400 printf ("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n",
401 p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory ",
402 p->status & 2 ? "OnLine " : "OffLine", p->value, t->threshold,
403 p->value > t->threshold ? "Passed" : "Failed");
408 void
409 print_values (values_t * p, thresholds_t * t)
411 value_t * value = p->values;
412 threshold_t * threshold = t->thresholds;
413 int i;
414 for (i = 0; i < NR_ATTRIBUTES; i++) {
415 if (value->id && threshold->id && value->id == threshold->id) {
416 print_value (value++, threshold++);
419 printf
420 (_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"),
421 p->offline_status,
422 get_offline_text (p->offline_status & 0x7f),
423 (p->offline_status & 0x80 ? "Yes" : "No"),
424 p->offline_timeout / 60);
425 printf
426 (_("OffLineCapability=%d {%s %s %s}\n"),
427 p->offline_capability,
428 p->offline_capability & 1 ? "Immediate" : "",
429 p->offline_capability & 2 ? "Auto" : "",
430 p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
431 printf
432 (_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"),
433 p->revision,
434 p->checksum,
435 p->smart_capability,
436 p->smart_capability & 1 ? "SaveOnStandBy" : "",
437 p->smart_capability & 2 ? "AutoSave" : "");
442 smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, char show_error)
444 int e = 0;
445 __u8 args[4];
446 args[0] = WIN_SMART;
447 args[1] = val0;
448 args[2] = smart_command[command].value;
449 args[3] = 0;
450 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
451 e = errno;
452 if (show_error) {
453 printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno));
456 return e;
462 smart_read_thresholds (int fd, thresholds_t * thresholds)
464 int e;
465 __u8 args[4 + 512];
466 args[0] = WIN_SMART;
467 args[1] = 0;
468 args[2] = SMART_READ_THRESHOLDS;
469 args[3] = 1;
470 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
471 e = errno;
472 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno));
473 return e;
475 memcpy (thresholds, args + 4, 512);
476 return 0;
480 void
481 print_help (void)
483 print_revision (progname, revision);
485 printf ("Nagios feature - 1999 Robert Dale <rdale@digital-mission.com>\n");
486 printf ("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n");
487 printf (COPYRIGHT, copyright, email);
489 printf (_("This plugin checks a local hard drive with the (Linux specific) SMART interface [http://smartlinux.sourceforge.net/smart/index.php]."));
491 printf ("\n\n");
493 print_usage ();
495 printf (_(UT_HELP_VRSN));
496 printf (_(UT_EXTRA_OPTS));
498 printf (" %s\n", "-d, --device=DEVICE");
499 printf (" %s\n", _("Select device DEVICE"));
500 printf (" %s\n", _("Note: if the device is selected with this option, _no_ other options are accepted"));
501 printf (" %s\n", "-i, --immediate");
502 printf (" %s\n", _("Perform immediately offline tests"));
503 printf (" %s\n", "-q, --quiet-check");
504 printf (" %s\n", _("Returns the number of failed tests"));
505 printf (" %s\n", "-1, --auto-on");
506 printf (" %s\n", _("Turn on automatic offline tests"));
507 printf (" %s\n", "-0, --auto-off");
508 printf (" %s\n", _("Turn off automatic offline tests"));
509 printf (" %s\n", "-n, --nagios");
510 printf (" %s\n", _("Output suitable for Nagios"));
512 #ifdef NP_EXTRA_OPTS
513 printf ("\n");
514 printf ("%s\n", _("Notes:"));
515 printf (_(UT_EXTRA_OPTS_NOTES));
516 #endif
518 printf (_(UT_SUPPORT));
521 /* todo : add to the long nanual as example
523 * Run with: check_ide-smart --nagios [-d] <DRIVE>
524 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc
526 * - Returns 0 on no errors
527 * - Returns 1 on advisories
528 * - Returns 2 on prefailure
529 * - Returns -1 not too often
533 void
534 print_usage (void)
536 printf (_("Usage:"));
537 printf ("%s [-d <device>] [-i <immediate>] [-q quiet] [-1 <auto-on>]",progname);
538 printf (" [-O <auto-off>] [-n <nagios>]\n");