diff options
Diffstat (limited to 'plugins/check_ide-smart.c')
-rw-r--r-- | plugins/check_ide-smart.c | 523 |
1 files changed, 0 insertions, 523 deletions
diff --git a/plugins/check_ide-smart.c b/plugins/check_ide-smart.c deleted file mode 100644 index 1c0af310..00000000 --- a/plugins/check_ide-smart.c +++ /dev/null | |||
@@ -1,523 +0,0 @@ | |||
1 | /* | ||
2 | * check_ide-smart v.1 - hacked version of ide-smart for Nagios | ||
3 | * Copyright (C) 2000 Robert Dale <rdale@digital-mission.com> | ||
4 | * | ||
5 | * Nagios - http://www.nagios.org | ||
6 | * | ||
7 | * Notes: | ||
8 | * ide-smart has the same functionality as before. Some return | ||
9 | * values were changed, otherwise the --net-saint option was added. | ||
10 | * | ||
11 | * Run with: check_ide-smart --net-saint [-d] <DRIVE> | ||
12 | * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc | ||
13 | * | ||
14 | * - Returns 0 on no errors | ||
15 | * - Returns 1 on advisories | ||
16 | * - Returns 2 on prefailure | ||
17 | * - Returns -1 not too often | ||
18 | * | ||
19 | * ide-smart 1.3 - IDE S.M.A.R.T. checking tool | ||
20 | * Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org> | ||
21 | * 1998 Gadi Oxman <gadio@netvision.net.il> | ||
22 | * | ||
23 | * This program is free software; you can redistribute it and/or modify | ||
24 | * it under the terms of the GNU General Public License as published by | ||
25 | * the Free Software Foundation; either version 2 of the License, or | ||
26 | * (at your option) any later version. | ||
27 | * | ||
28 | * This program is distributed in the hope that it will be useful, | ||
29 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
31 | * GNU General Public License for more details. | ||
32 | * | ||
33 | * You should have received a copy of the GNU General Public License | ||
34 | * along with this program; if not, write to the Free Software | ||
35 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
36 | * | ||
37 | * $Id$ | ||
38 | */ | ||
39 | |||
40 | const char *progname = "check_ide_smart"; | ||
41 | const char *revision = "$Revision$"; | ||
42 | const char *copyright = "2000-2004"; | ||
43 | const char *email = "nagiosplug-devel@lists.sourceforge.net"; | ||
44 | |||
45 | #include "common.h" | ||
46 | #include "utils.h" | ||
47 | |||
48 | #include <sys/stat.h> | ||
49 | #include <sys/ioctl.h> | ||
50 | #include <fcntl.h> | ||
51 | #include <linux/hdreg.h> | ||
52 | #include <linux/types.h> | ||
53 | #include <errno.h> | ||
54 | |||
55 | #define NR_ATTRIBUTES 30 | ||
56 | |||
57 | #ifndef TRUE | ||
58 | #define TRUE 1 | ||
59 | #endif /* */ | ||
60 | |||
61 | #define PREFAILURE 2 | ||
62 | #define ADVISORY 1 | ||
63 | #define OPERATIONAL 0 | ||
64 | #define UNKNOWN -1 | ||
65 | |||
66 | typedef struct threshold_s | ||
67 | { | ||
68 | __u8 id; | ||
69 | __u8 threshold; | ||
70 | __u8 reserved[10]; | ||
71 | } | ||
72 | __attribute__ ((packed)) threshold_t; | ||
73 | |||
74 | typedef struct thresholds_s | ||
75 | { | ||
76 | __u16 revision; | ||
77 | threshold_t thresholds[NR_ATTRIBUTES]; | ||
78 | __u8 reserved[18]; | ||
79 | __u8 vendor[131]; | ||
80 | __u8 checksum; | ||
81 | } | ||
82 | __attribute__ ((packed)) thresholds_t; | ||
83 | |||
84 | typedef struct value_s | ||
85 | { | ||
86 | __u8 id; | ||
87 | __u16 status; | ||
88 | __u8 value; | ||
89 | __u8 vendor[8]; | ||
90 | } | ||
91 | __attribute__ ((packed)) value_t; | ||
92 | |||
93 | typedef struct values_s | ||
94 | { | ||
95 | __u16 revision; | ||
96 | value_t values[NR_ATTRIBUTES]; | ||
97 | __u8 offline_status; | ||
98 | __u8 vendor1; | ||
99 | __u16 offline_timeout; | ||
100 | __u8 vendor2; | ||
101 | __u8 offline_capability; | ||
102 | __u16 smart_capability; | ||
103 | __u8 reserved[16]; | ||
104 | __u8 vendor[125]; | ||
105 | __u8 checksum; | ||
106 | } | ||
107 | __attribute__ ((packed)) values_t; | ||
108 | |||
109 | struct | ||
110 | { | ||
111 | __u8 value; | ||
112 | char *text; | ||
113 | } | ||
114 | |||
115 | offline_status_text[] = | ||
116 | { | ||
117 | {0x00, "NeverStarted"}, | ||
118 | {0x02, "Completed"}, | ||
119 | {0x04, "Suspended"}, | ||
120 | {0x05, "Aborted"}, | ||
121 | {0x06, "Failed"}, | ||
122 | {0, 0} | ||
123 | }; | ||
124 | |||
125 | struct | ||
126 | { | ||
127 | __u8 value; | ||
128 | char *text; | ||
129 | } | ||
130 | |||
131 | smart_command[] = | ||
132 | { | ||
133 | {SMART_ENABLE, "SMART_ENABLE"}, | ||
134 | {SMART_DISABLE, "SMART_DISABLE"}, | ||
135 | {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"}, | ||
136 | {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"} | ||
137 | }; | ||
138 | |||
139 | |||
140 | /* Index to smart_command table, keep in order */ | ||
141 | enum SmartCommand | ||
142 | { SMART_CMD_ENABLE, | ||
143 | SMART_CMD_DISABLE, | ||
144 | SMART_CMD_IMMEDIATE_OFFLINE, | ||
145 | SMART_CMD_AUTO_OFFLINE | ||
146 | }; | ||
147 | |||
148 | |||
149 | int | ||
150 | main (int argc, char *argv[]) | ||
151 | { | ||
152 | char *device = NULL; | ||
153 | int command = -1; | ||
154 | int o, longindex; | ||
155 | int retval = 0; | ||
156 | |||
157 | thresholds_t thresholds; | ||
158 | values_t values; | ||
159 | int fd; | ||
160 | |||
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 | {"net-saint", no_argument, 0, 'n'}, | ||
168 | {"help", no_argument, 0, 'h'}, | ||
169 | {"version", no_argument, 0, 'V'}, {0, 0, 0, 0} | ||
170 | }; | ||
171 | |||
172 | setlocale (LC_ALL, ""); | ||
173 | bindtextdomain (PACKAGE, LOCALEDIR); | ||
174 | textdomain (PACKAGE); | ||
175 | |||
176 | while (1) { | ||
177 | |||
178 | o = getopt_long (argc, argv, "+d:iq10nhV", longopts, &longindex); | ||
179 | |||
180 | if (o == -1 || o == EOF) | ||
181 | break; | ||
182 | |||
183 | switch (o) { | ||
184 | case 'd': | ||
185 | device = optarg; | ||
186 | break; | ||
187 | case 'q': | ||
188 | command = 3; | ||
189 | break; | ||
190 | case 'i': | ||
191 | command = 2; | ||
192 | break; | ||
193 | case '1': | ||
194 | command = 1; | ||
195 | break; | ||
196 | case '0': | ||
197 | command = 0; | ||
198 | break; | ||
199 | case 'n': | ||
200 | command = 4; | ||
201 | break; | ||
202 | case 'h': | ||
203 | print_help (); | ||
204 | return STATE_OK; | ||
205 | case 'V': | ||
206 | print_revision (progname, revision); | ||
207 | return STATE_OK; | ||
208 | default: | ||
209 | printf (_("%s: Unknown argument: %s\n\n"), progname, optarg); | ||
210 | print_usage (); | ||
211 | exit (STATE_UNKNOWN); | ||
212 | } | ||
213 | |||
214 | if (optind < argc) { | ||
215 | device = argv[optind]; | ||
216 | } | ||
217 | |||
218 | if (!device) { | ||
219 | show_help (); | ||
220 | show_version (); | ||
221 | return -1; | ||
222 | } | ||
223 | |||
224 | fd = open (device, O_RDONLY); | ||
225 | |||
226 | if (fd < 0) { | ||
227 | printf (_("CRITICAL - Couldn't open device: %s\n"), strerror (errno)); | ||
228 | return 2; | ||
229 | } | ||
230 | |||
231 | if (smart_cmd_simple (fd, SMART_CMD_ENABLE, 0, TRUE)) { | ||
232 | printf (_("CRITICAL - SMART_CMD_ENABLE\n")); | ||
233 | return 2; | ||
234 | } | ||
235 | |||
236 | switch (command) { | ||
237 | case 0: | ||
238 | retval = smart_cmd_simple (fd, SMART_CMD_AUTO_OFFLINE, 0, TRUE); | ||
239 | break; | ||
240 | case 1: | ||
241 | retval = smart_cmd_simple (fd, SMART_CMD_AUTO_OFFLINE, 0xF8, TRUE); | ||
242 | break; | ||
243 | case 2: | ||
244 | retval = smart_cmd_simple (fd, SMART_CMD_IMMEDIATE_OFFLINE, 0, TRUE); | ||
245 | break; | ||
246 | case 3: | ||
247 | smart_read_values (fd, &values); | ||
248 | smart_read_thresholds (fd, &thresholds); | ||
249 | retval = values_not_passed (&values, &thresholds); | ||
250 | break; | ||
251 | case 4: | ||
252 | smart_read_values (fd, &values); | ||
253 | smart_read_thresholds (fd, &thresholds); | ||
254 | retval = net_saint (&values, &thresholds); | ||
255 | break; | ||
256 | default: | ||
257 | smart_read_values (fd, &values); | ||
258 | smart_read_thresholds (fd, &thresholds); | ||
259 | print_values (&values, &thresholds); | ||
260 | break; | ||
261 | } | ||
262 | close (fd); | ||
263 | } | ||
264 | return retval; | ||
265 | } | ||
266 | |||
267 | |||
268 | |||
269 | char * | ||
270 | get_offline_text (int status) | ||
271 | { | ||
272 | int i; | ||
273 | for (i = 0; offline_status_text[i].text; i++) { | ||
274 | if (offline_status_text[i].value == status) { | ||
275 | return offline_status_text[i].text; | ||
276 | } | ||
277 | } | ||
278 | return "UNKNOW"; | ||
279 | } | ||
280 | |||
281 | |||
282 | |||
283 | int | ||
284 | smart_read_values (int fd, values_t * values) | ||
285 | { | ||
286 | int e; | ||
287 | __u8 args[4 + 512]; | ||
288 | args[0] = WIN_SMART; | ||
289 | args[1] = 0; | ||
290 | args[2] = SMART_READ_VALUES; | ||
291 | args[3] = 1; | ||
292 | if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { | ||
293 | e = errno; | ||
294 | printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno)); | ||
295 | return e; | ||
296 | } | ||
297 | memcpy (values, args + 4, 512); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | |||
302 | |||
303 | int | ||
304 | values_not_passed (values_t * p, thresholds_t * t) | ||
305 | { | ||
306 | value_t * value = p->values; | ||
307 | threshold_t * threshold = t->thresholds; | ||
308 | int failed = 0; | ||
309 | int passed = 0; | ||
310 | int i; | ||
311 | for (i = 0; i < NR_ATTRIBUTES; i++) { | ||
312 | if (value->id && threshold->id && value->id == threshold->id) { | ||
313 | if (value->value <= threshold->threshold) { | ||
314 | ++failed; | ||
315 | } | ||
316 | else { | ||
317 | ++passed; | ||
318 | } | ||
319 | } | ||
320 | ++value; | ||
321 | ++threshold; | ||
322 | } | ||
323 | return (passed ? -failed : 2); | ||
324 | } | ||
325 | |||
326 | |||
327 | |||
328 | int | ||
329 | net_saint (values_t * p, thresholds_t * t) | ||
330 | { | ||
331 | value_t * value = p->values; | ||
332 | threshold_t * threshold = t->thresholds; | ||
333 | int status = OPERATIONAL; | ||
334 | int prefailure = 0; | ||
335 | int advisory = 0; | ||
336 | int failed = 0; | ||
337 | int passed = 0; | ||
338 | int total = 0; | ||
339 | int i; | ||
340 | for (i = 0; i < NR_ATTRIBUTES; i++) { | ||
341 | if (value->id && threshold->id && value->id == threshold->id) { | ||
342 | if (value->value <= threshold->threshold) { | ||
343 | ++failed; | ||
344 | if (value->status & 1) { | ||
345 | status = PREFAILURE; | ||
346 | ++prefailure; | ||
347 | } | ||
348 | else { | ||
349 | status = ADVISORY; | ||
350 | ++advisory; | ||
351 | } | ||
352 | } | ||
353 | else { | ||
354 | ++passed; | ||
355 | } | ||
356 | ++total; | ||
357 | } | ||
358 | ++value; | ||
359 | ++threshold; | ||
360 | } | ||
361 | switch (status) { | ||
362 | case PREFAILURE: | ||
363 | printf (_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"), | ||
364 | prefailure, | ||
365 | prefailure > 1 ? 's' : ' ', | ||
366 | failed, | ||
367 | total); | ||
368 | break; | ||
369 | case ADVISORY: | ||
370 | printf (_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"), | ||
371 | advisory, | ||
372 | advisory > 1 ? "ies" : "y", | ||
373 | failed, | ||
374 | total); | ||
375 | break; | ||
376 | case OPERATIONAL: | ||
377 | printf (_("OK - Operational (%d/%d tests passed)\n"), passed, total); | ||
378 | break; | ||
379 | default: | ||
380 | printf (_("ERROR - Status '%d' uknown. %d/%d tests passed\n"), status, | ||
381 | passed, total); | ||
382 | status = -1; | ||
383 | break; | ||
384 | } | ||
385 | return status; | ||
386 | } | ||
387 | |||
388 | |||
389 | |||
390 | void | ||
391 | print_value (value_t * p, threshold_t * t) | ||
392 | { | ||
393 | printf ("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n", | ||
394 | p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory ", | ||
395 | p->status & 2 ? "OnLine " : "OffLine", p->value, t->threshold, | ||
396 | p->value > t->threshold ? "Passed" : "Failed"); | ||
397 | } | ||
398 | |||
399 | |||
400 | |||
401 | void | ||
402 | print_values (values_t * p, thresholds_t * t) | ||
403 | { | ||
404 | value_t * value = p->values; | ||
405 | threshold_t * threshold = t->thresholds; | ||
406 | int i; | ||
407 | for (i = 0; i < NR_ATTRIBUTES; i++) { | ||
408 | if (value->id && threshold->id && value->id == threshold->id) { | ||
409 | print_value (value++, threshold++); | ||
410 | } | ||
411 | } | ||
412 | printf | ||
413 | (_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"), | ||
414 | p->offline_status, | ||
415 | get_offline_text (p->offline_status & 0x7f), | ||
416 | (p->offline_status & 0x80 ? "Yes" : "No"), | ||
417 | p->offline_timeout / 60); | ||
418 | printf | ||
419 | (_("OffLineCapability=%d {%s %s %s}\n"), | ||
420 | p->offline_capability, | ||
421 | p->offline_capability & 1 ? "Immediate" : "", | ||
422 | p->offline_capability & 2 ? "Auto" : "", | ||
423 | p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd"); | ||
424 | printf | ||
425 | (_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"), | ||
426 | p->revision, | ||
427 | p->checksum, | ||
428 | p->smart_capability, | ||
429 | p->smart_capability & 1 ? "SaveOnStandBy" : "", | ||
430 | p->smart_capability & 2 ? "AutoSave" : ""); | ||
431 | } | ||
432 | |||
433 | |||
434 | |||
435 | void | ||
436 | print_thresholds (thresholds_t * p) | ||
437 | { | ||
438 | threshold_t * threshold = p->thresholds; | ||
439 | int i; | ||
440 | printf ("\n"); | ||
441 | printf ("SmartRevision=%d\n", p->revision); | ||
442 | for (i = 0; i < NR_ATTRIBUTES; i++) { | ||
443 | if (threshold->id) { | ||
444 | printf ("Id=%3d, Threshold=%3d\n", threshold->id, | ||
445 | threshold->threshold); } | ||
446 | ++threshold; | ||
447 | } | ||
448 | printf ("CheckSum=%d\n", p->checksum); | ||
449 | } | ||
450 | |||
451 | int | ||
452 | smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, | ||
453 | char show_error) | ||
454 | { | ||
455 | int e = 0; | ||
456 | __u8 args[4]; | ||
457 | args[0] = WIN_SMART; | ||
458 | args[1] = val0; | ||
459 | args[2] = smart_command[command].value; | ||
460 | args[3] = 0; | ||
461 | if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { | ||
462 | e = errno; | ||
463 | if (show_error) { | ||
464 | printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno)); | ||
465 | } | ||
466 | } | ||
467 | return e; | ||
468 | } | ||
469 | |||
470 | |||
471 | |||
472 | int | ||
473 | smart_read_thresholds (int fd, thresholds_t * thresholds) | ||
474 | { | ||
475 | int e; | ||
476 | __u8 args[4 + 512]; | ||
477 | args[0] = WIN_SMART; | ||
478 | args[1] = 0; | ||
479 | args[2] = SMART_READ_THRESHOLDS; | ||
480 | args[3] = 1; | ||
481 | if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { | ||
482 | e = errno; | ||
483 | printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno)); | ||
484 | return e; | ||
485 | } | ||
486 | memcpy (thresholds, args + 4, 512); | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | |||
491 | |||
492 | void | ||
493 | print_help () | ||
494 | { | ||
495 | print_revision (progname, revision); | ||
496 | |||
497 | printf ("Nagios feature - 1999 Robert Dale <rdale@digital-mission.com>\n"); | ||
498 | printf ("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n"); | ||
499 | printf (COPYRIGHT, copyright, email); | ||
500 | |||
501 | printf (_("\ | ||
502 | Usage: %s [DEVICE] [OPTION]\n\ | ||
503 | -d, --device=DEVICE\n\ | ||
504 | Select device DEVICE\n\ | ||
505 | -i, --immediate\n\ | ||
506 | Perform immediately offline tests\n\ | ||
507 | -q, --quiet-check\n\ | ||
508 | Returns the number of failed tests\n\ | ||
509 | -1, --auto-on\n\ | ||
510 | Turn on automatic offline tests\n\ | ||
511 | -0, --auto-off\n\ | ||
512 | Turn off automatic offline tests\n\ | ||
513 | -n, --net-saint\n\ | ||
514 | Output suitable for Net Saint\n", progname); | ||
515 | } | ||
516 | |||
517 | |||
518 | |||
519 | void | ||
520 | print_usage (void) | ||
521 | { | ||
522 | printf ("Usage: %s \n"), progname); | ||
523 | } | ||