Reverted commit 1879 where an invalid hostname returns UNKNOWN - back to CRITICAL
[monitoring-plugins.git] / plugins / check_ide_smart.c
blob5dcf7a3b7fa74d813c6e0d54f196e885e426884a
1 /******************************************************************************
2 * Nagios check_ide_smart plugin
4 * License: GPL
6 * ide-smart 1.3 - IDE S.M.A.R.T. checking tool
7 * Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>
8 * 1998 Gadi Oxman <gadio@netvision.net.il>
9 *
10 * Copyright (c) 2000 Robert Dale <rdale@digital-mission.com>
11 * Copyright (c) 2000-2006 nagios-plugins team
13 * Last Modified: $Date$
15 * Description:
17 * This file contains the check_ide_smart plugin
19 * This plugin checks a local hard drive with the (Linux specific) SMART interface
22 * License Information:
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.
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.
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.
38 * $Id$
41 const char *progname = "check_ide_smart";
42 const char *revision = "$Revision$";
43 const char *copyright = "2000-2006";
44 const char *email = "nagiosplug-devel@lists.sourceforge.net";
46 #include "common.h"
47 #include "utils.h"
49 void print_help (void);
50 void print_usage (void);
52 #include <sys/stat.h>
53 #include <sys/ioctl.h>
54 #include <fcntl.h>
55 #include <linux/hdreg.h>
56 #include <linux/types.h>
57 #include <errno.h>
59 #define NR_ATTRIBUTES 30
61 #ifndef TRUE
62 #define TRUE 1
63 #endif /* */
65 #define PREFAILURE 2
66 #define ADVISORY 1
67 #define OPERATIONAL 0
68 #define UNKNOWN -1
70 typedef struct threshold_s
72 __u8 id;
73 __u8 threshold;
74 __u8 reserved[10];
76 __attribute__ ((packed)) threshold_t;
78 typedef struct thresholds_s
80 __u16 revision;
81 threshold_t thresholds[NR_ATTRIBUTES];
82 __u8 reserved[18];
83 __u8 vendor[131];
84 __u8 checksum;
86 __attribute__ ((packed)) thresholds_t;
88 typedef struct value_s
90 __u8 id;
91 __u16 status;
92 __u8 value;
93 __u8 vendor[8];
95 __attribute__ ((packed)) value_t;
97 typedef struct values_s
99 __u16 revision;
100 value_t values[NR_ATTRIBUTES];
101 __u8 offline_status;
102 __u8 vendor1;
103 __u16 offline_timeout;
104 __u8 vendor2;
105 __u8 offline_capability;
106 __u16 smart_capability;
107 __u8 reserved[16];
108 __u8 vendor[125];
109 __u8 checksum;
111 __attribute__ ((packed)) values_t;
113 struct
115 __u8 value;
116 char *text;
119 offline_status_text[] =
121 {0x00, "NeverStarted"},
122 {0x02, "Completed"},
123 {0x04, "Suspended"},
124 {0x05, "Aborted"},
125 {0x06, "Failed"},
126 {0, 0}
129 struct
131 __u8 value;
132 char *text;
135 smart_command[] =
137 {SMART_ENABLE, "SMART_ENABLE"},
138 {SMART_DISABLE, "SMART_DISABLE"},
139 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"},
140 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"}
144 /* Index to smart_command table, keep in order */
145 enum SmartCommand
146 { SMART_CMD_ENABLE,
147 SMART_CMD_DISABLE,
148 SMART_CMD_IMMEDIATE_OFFLINE,
149 SMART_CMD_AUTO_OFFLINE
152 void print_values (values_t * p, thresholds_t * t);
153 int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, char show_error);
156 main (int argc, char *argv[])
158 char *device = NULL;
159 int command = -1;
160 int o, longindex;
161 int retval = 0;
163 thresholds_t thresholds;
164 values_t values;
165 int fd;
167 static struct option longopts[] = {
168 {"device", required_argument, 0, 'd'},
169 {"immediate", no_argument, 0, 'i'},
170 {"quiet-check", no_argument, 0, 'q'},
171 {"auto-on", no_argument, 0, '1'},
172 {"auto-off", no_argument, 0, '0'},
173 {"nagios", no_argument, 0, 'n'},
174 {"help", no_argument, 0, 'h'},
175 {"version", no_argument, 0, 'V'}, {0, 0, 0, 0}
178 setlocale (LC_ALL, "");
179 bindtextdomain (PACKAGE, LOCALEDIR);
180 textdomain (PACKAGE);
182 while (1) {
184 o = getopt_long (argc, argv, "+d:iq10nhV", longopts, &longindex);
186 if (o == -1 || o == EOF || o == 1)
187 break;
189 switch (o) {
190 case 'd':
191 device = optarg;
192 break;
193 case 'q':
194 command = 3;
195 break;
196 case 'i':
197 command = 2;
198 break;
199 case '1':
200 command = 1;
201 break;
202 case '0':
203 command = 0;
204 break;
205 case 'n':
206 command = 4;
207 break;
208 case 'h':
209 print_help ();
210 return STATE_OK;
211 case 'V':
212 print_revision (progname, revision);
213 return STATE_OK;
214 default:
215 usage5 ();
219 if (optind < argc) {
220 device = argv[optind];
223 if (!device) {
224 print_help ();
225 return STATE_OK;
228 fd = open (device, O_RDONLY);
230 if (fd < 0) {
231 printf (_("CRITICAL - Couldn't open device %s: %s\n"), device, strerror (errno));
232 return STATE_CRITICAL;
235 if (smart_cmd_simple (fd, SMART_CMD_ENABLE, 0, TRUE)) {
236 printf (_("CRITICAL - SMART_CMD_ENABLE\n"));
237 return STATE_CRITICAL;
240 switch (command) {
241 case 0:
242 retval = smart_cmd_simple (fd, SMART_CMD_AUTO_OFFLINE, 0, TRUE);
243 break;
244 case 1:
245 retval = smart_cmd_simple (fd, SMART_CMD_AUTO_OFFLINE, 0xF8, TRUE);
246 break;
247 case 2:
248 retval = smart_cmd_simple (fd, SMART_CMD_IMMEDIATE_OFFLINE, 0, TRUE);
249 break;
250 case 3:
251 smart_read_values (fd, &values);
252 smart_read_thresholds (fd, &thresholds);
253 retval = values_not_passed (&values, &thresholds);
254 break;
255 case 4:
256 smart_read_values (fd, &values);
257 smart_read_thresholds (fd, &thresholds);
258 retval = nagios (&values, &thresholds);
259 break;
260 default:
261 smart_read_values (fd, &values);
262 smart_read_thresholds (fd, &thresholds);
263 print_values (&values, &thresholds);
264 break;
266 close (fd);
267 return retval;
272 char *
273 get_offline_text (int status)
275 int i;
276 for (i = 0; offline_status_text[i].text; i++) {
277 if (offline_status_text[i].value == status) {
278 return offline_status_text[i].text;
281 return "UNKNOW";
287 smart_read_values (int fd, values_t * values)
289 int e;
290 __u8 args[4 + 512];
291 args[0] = WIN_SMART;
292 args[1] = 0;
293 args[2] = SMART_READ_VALUES;
294 args[3] = 1;
295 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
296 e = errno;
297 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno));
298 return e;
300 memcpy (values, args + 4, 512);
301 return 0;
307 values_not_passed (values_t * p, thresholds_t * t)
309 value_t * value = p->values;
310 threshold_t * threshold = t->thresholds;
311 int failed = 0;
312 int passed = 0;
313 int i;
314 for (i = 0; i < NR_ATTRIBUTES; i++) {
315 if (value->id && threshold->id && value->id == threshold->id) {
316 if (value->value <= threshold->threshold) {
317 ++failed;
319 else {
320 ++passed;
323 ++value;
324 ++threshold;
326 return (passed ? -failed : 2);
332 nagios (values_t * p, thresholds_t * t)
334 value_t * value = p->values;
335 threshold_t * threshold = t->thresholds;
336 int status = OPERATIONAL;
337 int prefailure = 0;
338 int advisory = 0;
339 int failed = 0;
340 int passed = 0;
341 int total = 0;
342 int i;
343 for (i = 0; i < NR_ATTRIBUTES; i++) {
344 if (value->id && threshold->id && value->id == threshold->id) {
345 if (value->value <= threshold->threshold) {
346 ++failed;
347 if (value->status & 1) {
348 status = PREFAILURE;
349 ++prefailure;
351 else {
352 status = ADVISORY;
353 ++advisory;
356 else {
357 ++passed;
359 ++total;
361 ++value;
362 ++threshold;
364 switch (status) {
365 case PREFAILURE:
366 printf (_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"),
367 prefailure,
368 prefailure > 1 ? 's' : ' ',
369 failed,
370 total);
371 status=STATE_CRITICAL;
372 break;
373 case ADVISORY:
374 printf (_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"),
375 advisory,
376 advisory > 1 ? "ies" : "y",
377 failed,
378 total);
379 status=STATE_WARNING;
380 break;
381 case OPERATIONAL:
382 printf (_("OK - Operational (%d/%d tests passed)\n"), passed, total);
383 status=STATE_OK;
384 break;
385 default:
386 printf (_("ERROR - Status '%d' unkown. %d/%d tests passed\n"), status,
387 passed, total);
388 status = STATE_UNKNOWN;
389 break;
391 return status;
396 void
397 print_value (value_t * p, threshold_t * t)
399 printf ("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n",
400 p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory ",
401 p->status & 2 ? "OnLine " : "OffLine", p->value, t->threshold,
402 p->value > t->threshold ? "Passed" : "Failed");
407 void
408 print_values (values_t * p, thresholds_t * t)
410 value_t * value = p->values;
411 threshold_t * threshold = t->thresholds;
412 int i;
413 for (i = 0; i < NR_ATTRIBUTES; i++) {
414 if (value->id && threshold->id && value->id == threshold->id) {
415 print_value (value++, threshold++);
418 printf
419 (_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"),
420 p->offline_status,
421 get_offline_text (p->offline_status & 0x7f),
422 (p->offline_status & 0x80 ? "Yes" : "No"),
423 p->offline_timeout / 60);
424 printf
425 (_("OffLineCapability=%d {%s %s %s}\n"),
426 p->offline_capability,
427 p->offline_capability & 1 ? "Immediate" : "",
428 p->offline_capability & 2 ? "Auto" : "",
429 p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
430 printf
431 (_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"),
432 p->revision,
433 p->checksum,
434 p->smart_capability,
435 p->smart_capability & 1 ? "SaveOnStandBy" : "",
436 p->smart_capability & 2 ? "AutoSave" : "");
441 smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, char show_error)
443 int e = 0;
444 __u8 args[4];
445 args[0] = WIN_SMART;
446 args[1] = val0;
447 args[2] = smart_command[command].value;
448 args[3] = 0;
449 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
450 e = errno;
451 if (show_error) {
452 printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno));
455 return e;
461 smart_read_thresholds (int fd, thresholds_t * thresholds)
463 int e;
464 __u8 args[4 + 512];
465 args[0] = WIN_SMART;
466 args[1] = 0;
467 args[2] = SMART_READ_THRESHOLDS;
468 args[3] = 1;
469 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
470 e = errno;
471 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno));
472 return e;
474 memcpy (thresholds, args + 4, 512);
475 return 0;
479 void
480 print_help (void)
482 print_revision (progname, revision);
484 printf ("Nagios feature - 1999 Robert Dale <rdale@digital-mission.com>\n");
485 printf ("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n");
486 printf (COPYRIGHT, copyright, email);
488 printf (_("This plugin checks a local hard drive with the (Linux specific) SMART interface [http://smartlinux.sourceforge.net/smart/index.php]."));
490 printf ("\n\n");
492 print_usage ();
494 printf (_(UT_HELP_VRSN));
496 printf (" %s\n", "-d, --device=DEVICE");
497 printf (" %s\n", _("Select device DEVICE"));
498 printf (" %s\n", _("Note: if the device is selected with this option, _no_ other options are accepted"));
499 printf (" %s\n", "-i, --immediate");
500 printf (" %s\n", _("Perform immediately offline tests"));
501 printf (" %s\n", "-q, --quiet-check");
502 printf (" %s\n", _("Returns the number of failed tests"));
503 printf (" %s\n", "-1, --auto-on");
504 printf (" %s\n", _("Turn on automatic offline tests"));
505 printf (" %s\n", "-0, --auto-off");
506 printf (" %s\n", _("Turn off automatic offline tests"));
507 printf (" %s\n", "-n, --nagios");
508 printf (" %s\n\n", _("Output suitable for Nagios"));
509 printf (_(UT_SUPPORT));
512 /* todo : add to the long nanual as example
514 * Run with: check_ide-smart --nagios [-d] <DRIVE>
515 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc
517 * - Returns 0 on no errors
518 * - Returns 1 on advisories
519 * - Returns 2 on prefailure
520 * - Returns -1 not too often
524 void
525 print_usage (void)
527 printf (_("Usage:"));
528 printf ("%s [-d <device>] [-i <immediate>] [-q quiet] [-1 <auto-on>]",progname);
529 printf (" [-O <auto-off>] [-n <nagios>]\n");