Code

Fix translations when extra-opts aren't enabled
[nagiosplug.git] / plugins / check_ide_smart.c
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
11
12 * Description:
13
14 * This file contains the check_ide_smart plugin
15
16 * This plugin checks a local hard drive with the (Linux specific) SMART
17 * interface
18
19
20 * This program is free software: you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation, either version 3 of the License, or
23 * (at your option) any later version.
24
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28 * GNU General Public License for more details.
29
30 * You should have received a copy of the GNU General Public License
31 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
32
33
34 *****************************************************************************/
36 const char *progname = "check_ide_smart";
37 const char *copyright = "1998-2007";
38 const char *email = "nagiosplug-devel@lists.sourceforge.net";
39         
40 #include "common.h"
41 #include "utils.h"
43 void print_help (void);
44 void print_usage (void);
46 #include <sys/stat.h>
47 #include <sys/ioctl.h>
48 #include <fcntl.h>
49 #include <linux/hdreg.h>
50 #include <linux/types.h>
51 #include <errno.h>
52         
53 #define NR_ATTRIBUTES   30
54         
55 #ifndef TRUE
56 #define TRUE 1
57 #endif  /*  */
58         
59 #define PREFAILURE 2
60 #define ADVISORY 1
61 #define OPERATIONAL 0
62 #define UNKNOWN -1
64 typedef struct threshold_s
65 {
66         __u8 id;
67         __u8 threshold;
68         __u8 reserved[10];
69 }
70 __attribute__ ((packed)) threshold_t;
72 typedef struct thresholds_s
73 {
74         __u16 revision;
75         threshold_t thresholds[NR_ATTRIBUTES];
76         __u8 reserved[18];
77         __u8 vendor[131];
78         __u8 checksum;
79 }
80 __attribute__ ((packed)) thresholds_t;
82 typedef struct value_s
83 {
84         __u8 id;
85         __u16 status;
86         __u8 value;
87         __u8 vendor[8];
88 }
89 __attribute__ ((packed)) value_t;
91 typedef struct values_s
92 {
93         __u16 revision;
94         value_t values[NR_ATTRIBUTES];
95         __u8 offline_status;
96         __u8 vendor1;
97         __u16 offline_timeout;
98         __u8 vendor2;
99         __u8 offline_capability;
100         __u16 smart_capability;
101         __u8 reserved[16];
102         __u8 vendor[125];
103         __u8 checksum;
105 __attribute__ ((packed)) values_t;
107 struct
109         __u8 value;
110         char *text;
113 offline_status_text[] =
114         {
115                 {0x00, "NeverStarted"},
116                 {0x02, "Completed"},
117                 {0x04, "Suspended"},
118                 {0x05, "Aborted"},
119                 {0x06, "Failed"},
120                 {0, 0}
121         };
123 struct
125         __u8 value;
126         char *text;
129 smart_command[] =
130         {
131                 {SMART_ENABLE, "SMART_ENABLE"},
132                 {SMART_DISABLE, "SMART_DISABLE"},
133                 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"},
134                 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"}
135         };
138 /* Index to smart_command table, keep in order */ 
139 enum SmartCommand 
140         { SMART_CMD_ENABLE,
141                 SMART_CMD_DISABLE,
142                 SMART_CMD_IMMEDIATE_OFFLINE,
143                 SMART_CMD_AUTO_OFFLINE 
144         };
146 void print_values (values_t * p, thresholds_t * t);
147 int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, char show_error); 
149 int
150 main (int argc, char *argv[]) 
152         char *device = NULL;
153         int command = -1;
154         int o, longindex;
155         int retval = 0;
157         thresholds_t thresholds;
158         values_t values;
159         int fd;
161         static struct option longopts[] = { 
162                 {"device", required_argument, 0, 'd'}, 
163                 {"immediate", no_argument, 0, 'i'}, 
164                 {"quiet-check", no_argument, 0, 'q'}, 
165                 {"auto-on", no_argument, 0, '1'}, 
166                 {"auto-off", no_argument, 0, '0'}, 
167                 {"nagios", no_argument, 0, 'n'}, 
168                 {"help", no_argument, 0, 'h'}, 
169                 {"version", no_argument, 0, 'V'},
170                 {0, 0, 0, 0}
171         };
173         /* Parse extra opts if any */
174         argv=np_extra_opts (&argc, argv, progname);
176         setlocale (LC_ALL, "");
177         bindtextdomain (PACKAGE, LOCALEDIR);
178         textdomain (PACKAGE);
180         while (1) {
181                 
182                 o = getopt_long (argc, argv, "+d:iq10nhV", longopts, &longindex);
184                 if (o == -1 || o == EOF || o == 1)
185                         break;
187                 switch (o) {
188                 case 'd':
189                         device = optarg;
190                         break;
191                 case 'q':
192                         command = 3;
193                         break;
194                 case 'i':
195                         command = 2;
196                         break;
197                 case '1':
198                         command = 1;
199                         break;
200                 case '0':
201                         command = 0;
202                         break;
203                 case 'n':
204                         command = 4;
205                         break;
206                 case 'h':
207                         print_help ();
208                         return STATE_OK;
209                 case 'V':
210                         print_revision (progname, NP_VERSION);
211                         return STATE_OK;
212                 default:
213                         usage5 ();
214                 }
215         }
217         if (optind < argc) {
218                 device = argv[optind];
219         }
221         if (!device) {
222                 print_help ();
223                 return STATE_OK;
224         }
226         fd = open (device, O_RDONLY);
228         if (fd < 0) {
229                 printf (_("CRITICAL - Couldn't open device %s: %s\n"), device, strerror (errno));
230                 return STATE_CRITICAL;
231         }
233         if (smart_cmd_simple (fd, SMART_CMD_ENABLE, 0, TRUE)) {
234                 printf (_("CRITICAL - SMART_CMD_ENABLE\n"));
235                 return STATE_CRITICAL;
236         }
238         switch (command) {
239         case 0:
240                 retval = smart_cmd_simple (fd, SMART_CMD_AUTO_OFFLINE, 0, TRUE);
241                 break;
242         case 1:
243                 retval = smart_cmd_simple (fd, SMART_CMD_AUTO_OFFLINE, 0xF8, TRUE);
244                 break;
245         case 2:
246                 retval = smart_cmd_simple (fd, SMART_CMD_IMMEDIATE_OFFLINE, 0, TRUE);
247                 break;
248         case 3:
249                 smart_read_values (fd, &values);
250                 smart_read_thresholds (fd, &thresholds);
251                 retval = values_not_passed (&values, &thresholds);
252                 break;
253         case 4:
254                 smart_read_values (fd, &values);
255                 smart_read_thresholds (fd, &thresholds);
256                 retval = nagios (&values, &thresholds);
257                 break;
258         default:
259                 smart_read_values (fd, &values);
260                 smart_read_thresholds (fd, &thresholds);
261                 print_values (&values, &thresholds);
262                 break;
263         }
264         close (fd);
265         return retval;
270 char *
271 get_offline_text (int status) 
273         int i;
274         for (i = 0; offline_status_text[i].text; i++) {
275                 if (offline_status_text[i].value == status) {
276                         return offline_status_text[i].text;
277                 }
278         }
279         return "UNKNOW";
284 int
285 smart_read_values (int fd, values_t * values) 
287         int e;
288         __u8 args[4 + 512];
289         args[0] = WIN_SMART;
290         args[1] = 0;
291         args[2] = SMART_READ_VALUES;
292         args[3] = 1;
293         if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
294                 e = errno;
295                 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno));
296                 return e;
297         }
298         memcpy (values, args + 4, 512);
299         return 0;
304 int
305 values_not_passed (values_t * p, thresholds_t * t) 
307         value_t * value = p->values;
308         threshold_t * threshold = t->thresholds;
309         int failed = 0;
310         int passed = 0;
311         int i;
312         for (i = 0; i < NR_ATTRIBUTES; i++) {
313                 if (value->id && threshold->id && value->id == threshold->id) {
314                         if (value->value <= threshold->threshold) {
315                                 ++failed;
316                         }
317                         else {
318                                 ++passed;
319                         }
320                 }
321                 ++value;
322                 ++threshold;
323         }
324         return (passed ? -failed : 2);
329 int
330 nagios (values_t * p, thresholds_t * t) 
332         value_t * value = p->values;
333         threshold_t * threshold = t->thresholds;
334         int status = OPERATIONAL;
335         int prefailure = 0;
336         int advisory = 0;
337         int failed = 0;
338         int passed = 0;
339         int total = 0;
340         int i;
341         for (i = 0; i < NR_ATTRIBUTES; i++) {
342                 if (value->id && threshold->id && value->id == threshold->id) {
343                         if (value->value <= threshold->threshold) {
344                                 ++failed;
345                                 if (value->status & 1) {
346                                         status = PREFAILURE;
347                                         ++prefailure;
348                                 }
349                                 else {
350                                         status = ADVISORY;
351                                         ++advisory;
352                                 }
353                         }
354                         else {
355                                 ++passed;
356                         }
357                         ++total;
358                 }
359                 ++value;
360                 ++threshold;
361         }
362         switch (status) {
363         case PREFAILURE:
364                 printf (_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"),
365                         prefailure,
366                         prefailure > 1 ? 's' : ' ',
367                         failed,
368                   total);
369                 status=STATE_CRITICAL;
370                 break;
371         case ADVISORY:
372                 printf (_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"),
373                         advisory,
374                         advisory > 1 ? "ies" : "y",
375                         failed,
376                         total);
377                 status=STATE_WARNING;
378                 break;
379         case OPERATIONAL:
380                 printf (_("OK - Operational (%d/%d tests passed)\n"), passed, total);
381                 status=STATE_OK;
382                 break;
383         default:
384                 printf (_("ERROR - Status '%d' unkown. %d/%d tests passed\n"), status,
385                                                 passed, total);
386                 status = STATE_UNKNOWN;
387                 break;
388         }
389         return status;
394 void
395 print_value (value_t * p, threshold_t * t) 
397         printf ("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n",
398                                         p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory   ",
399                                         p->status & 2 ? "OnLine " : "OffLine", p->value, t->threshold,
400                                         p->value > t->threshold ? "Passed" : "Failed");
405 void
406 print_values (values_t * p, thresholds_t * t)
408         value_t * value = p->values;
409         threshold_t * threshold = t->thresholds;
410         int i;
411         for (i = 0; i < NR_ATTRIBUTES; i++) {
412                 if (value->id && threshold->id && value->id == threshold->id) {
413                         print_value (value++, threshold++);
414                 }
415         }
416         printf
417                 (_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"),
418                  p->offline_status,
419                  get_offline_text (p->offline_status & 0x7f),
420                  (p->offline_status & 0x80 ? "Yes" : "No"),
421                  p->offline_timeout / 60);
422         printf
423                 (_("OffLineCapability=%d {%s %s %s}\n"),
424                  p->offline_capability,
425                  p->offline_capability & 1 ? "Immediate" : "",
426                  p->offline_capability & 2 ? "Auto" : "",
427                  p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
428         printf
429                 (_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"),
430                  p->revision,
431                  p->checksum,
432                  p->smart_capability,
433                  p->smart_capability & 1 ? "SaveOnStandBy" : "",
434                  p->smart_capability & 2 ? "AutoSave" : "");
438 int
439 smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, char show_error) 
441         int e = 0;
442         __u8 args[4];
443         args[0] = WIN_SMART;
444         args[1] = val0;
445         args[2] = smart_command[command].value;
446         args[3] = 0;
447         if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
448                 e = errno;
449                 if (show_error) {
450                         printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno));
451                 }
452         }
453         return e;
458 int
459 smart_read_thresholds (int fd, thresholds_t * thresholds) 
461         int e;
462         __u8 args[4 + 512];
463         args[0] = WIN_SMART;
464   args[1] = 0;
465   args[2] = SMART_READ_THRESHOLDS;
466   args[3] = 1;
467         if (ioctl (fd, HDIO_DRIVE_CMD, &args)) {
468                 e = errno;
469                 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno));
470                 return e;
471         }
472         memcpy (thresholds, args + 4, 512);
473         return 0;
477 void
478 print_help (void)
480         print_revision (progname, NP_VERSION);
482         printf ("Nagios feature - 1999 Robert Dale <rdale@digital-mission.com>\n");
483         printf ("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n");
484         printf (COPYRIGHT, copyright, email);
486         printf (_("This plugin checks a local hard drive with the (Linux specific) SMART interface [http://smartlinux.sourceforge.net/smart/index.php]."));
488   printf ("\n\n");
490   print_usage ();
492   printf (UT_HELP_VRSN);
493   printf (UT_EXTRA_OPTS);
495   printf (" %s\n", "-d, --device=DEVICE");
496   printf ("    %s\n", _("Select device DEVICE"));
497   printf ("    %s\n", _("Note: if the device is selected with this option, _no_ other options are accepted"));
498   printf (" %s\n", "-i, --immediate");
499   printf ("    %s\n", _("Perform immediately offline tests"));
500   printf (" %s\n", "-q, --quiet-check");
501   printf ("    %s\n", _("Returns the number of failed tests"));
502   printf (" %s\n", "-1, --auto-on");
503   printf ("    %s\n", _("Turn on automatic offline tests"));
504   printf (" %s\n", "-0, --auto-off");
505   printf ("    %s\n", _("Turn off automatic offline tests"));
506   printf (" %s\n", "-n, --nagios");
507   printf ("    %s\n", _("Output suitable for Nagios"));
509 #ifdef NP_EXTRA_OPTS
510   printf ("\n");
511   printf ("%s\n", _("Notes:"));
512   printf (UT_EXTRA_OPTS_NOTES);
513 #endif
515   printf (UT_SUPPORT);
518  /* todo : add to the long nanual as example
519  *
520  *     Run with:  check_ide-smart --nagios [-d] <DRIVE>
521  *     Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc
522  *
523  *       - Returns 0 on no errors
524  *       - Returns 1 on advisories
525  *       - Returns 2 on prefailure
526  *       - Returns -1 not too often
527  */
530 void
531 print_usage (void)
533   printf (_("Usage:"));
534   printf ("%s [-d <device>] [-i <immediate>] [-q quiet] [-1 <auto-on>]",progname);
535   printf (" [-O <auto-off>] [-n <nagios>]\n");