summaryrefslogtreecommitdiffstats
path: root/plugins/check_ide_smart.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_ide_smart.c')
-rw-r--r--plugins/check_ide_smart.c727
1 files changed, 338 insertions, 389 deletions
diff --git a/plugins/check_ide_smart.c b/plugins/check_ide_smart.c
index 3872e341..c1325cf9 100644
--- a/plugins/check_ide_smart.c
+++ b/plugins/check_ide_smart.c
@@ -1,307 +1,287 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_ide_smart plugin 3 * Monitoring check_ide_smart plugin
4* ide-smart 1.3 - IDE S.M.A.R.T. checking tool 4 * ide-smart 1.3 - IDE S.M.A.R.T. checking tool
5* 5 *
6* License: GPL 6 * License: GPL
7* Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org> 7 * Copyright (C) 1998-1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>
8* 1998 Gadi Oxman <gadio@netvision.net.il> 8 * 1998 Gadi Oxman <gadio@netvision.net.il>
9* Copyright (c) 2000 Robert Dale <rdale@digital-mission.com> 9 * Copyright (c) 2000 Robert Dale <rdale@digital-mission.com>
10* Copyright (c) 2000-2007 Monitoring Plugins Development Team 10 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
11* 11 *
12* Description: 12 * Description:
13* 13 *
14* This file contains the check_ide_smart plugin 14 * This file contains the check_ide_smart plugin
15* 15 *
16* This plugin checks a local hard drive with the (Linux specific) SMART 16 * This plugin checks a local hard drive with the (Linux specific) SMART
17* interface 17 * interface
18* 18 *
19* 19 *
20* This program is free software: you can redistribute it and/or modify 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 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 22 * the Free Software Foundation, either version 3 of the License, or
23* (at your option) any later version. 23 * (at your option) any later version.
24* 24 *
25* This program is distributed in the hope that it will be useful, 25 * This program is distributed in the hope that it will be useful,
26* but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28* GNU General Public License for more details. 28 * GNU General Public License for more details.
29* 29 *
30* You should have received a copy of the GNU General Public License 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/>. 31 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32* 32 *
33* 33 *
34*****************************************************************************/ 34 *****************************************************************************/
35 35
36const char *progname = "check_ide_smart"; 36const char *progname = "check_ide_smart";
37const char *copyright = "1998-2007"; 37const char *copyright = "1998-2024";
38const char *email = "devel@monitoring-plugins.org"; 38const char *email = "devel@monitoring-plugins.org";
39 39
40#include "common.h" 40#include "common.h"
41#include "utils.h" 41#include "utils.h"
42#include "check_ide_smart.d/config.h"
43#include "states.h"
42 44
43void print_help (void); 45static void print_help(void);
44void print_usage (void); 46void print_usage(void);
45 47
46#include <sys/stat.h> 48#include <sys/stat.h>
47#include <sys/ioctl.h> 49#include <sys/ioctl.h>
48#include <fcntl.h> 50#include <fcntl.h>
51
49#ifdef __linux__ 52#ifdef __linux__
50#include <linux/hdreg.h> 53# include <linux/hdreg.h>
51#include <linux/types.h> 54# include <linux/types.h>
52 55
53#define OPEN_MODE O_RDONLY 56# define OPEN_MODE O_RDONLY
54#endif /* __linux__ */ 57#endif /* __linux__ */
55#ifdef __NetBSD__ 58#ifdef __NetBSD__
56#include <sys/device.h> 59# include <sys/device.h>
57#include <sys/param.h> 60# include <sys/param.h>
58#include <sys/sysctl.h> 61# include <sys/sysctl.h>
59#include <sys/videoio.h> /* for __u8 and friends */ 62# include <sys/scsiio.h>
60#include <sys/scsiio.h> 63# include <sys/ataio.h>
61#include <sys/ataio.h> 64# include <dev/ata/atareg.h>
62#include <dev/ata/atareg.h> 65# include <dev/ic/wdcreg.h>
63#include <dev/ic/wdcreg.h> 66
64 67# define SMART_ENABLE WDSM_ENABLE_OPS
65#define SMART_ENABLE WDSM_ENABLE_OPS 68# define SMART_DISABLE WDSM_DISABLE_OPS
66#define SMART_DISABLE WDSM_DISABLE_OPS 69# define SMART_IMMEDIATE_OFFLINE WDSM_EXEC_OFFL_IMM
67#define SMART_IMMEDIATE_OFFLINE WDSM_EXEC_OFFL_IMM 70# define SMART_AUTO_OFFLINE 0xdb /* undefined in NetBSD headers */
68#define SMART_AUTO_OFFLINE 0xdb /* undefined in NetBSD headers */ 71
69 72# define OPEN_MODE O_RDWR
70#define OPEN_MODE O_RDWR
71#endif /* __NetBSD__ */ 73#endif /* __NetBSD__ */
72#include <errno.h> 74#include <errno.h>
73
74#define NR_ATTRIBUTES 30
75
76#define PREFAILURE 2
77#define ADVISORY 1
78#define OPERATIONAL 0
79#define UNKNOWN -1
80 75
81typedef struct threshold_s 76#define NR_ATTRIBUTES 30
82{
83 __u8 id;
84 __u8 threshold;
85 __u8 reserved[10];
86}
87__attribute__ ((packed)) threshold_t;
88
89typedef struct thresholds_s
90{
91 __u16 revision;
92 threshold_t thresholds[NR_ATTRIBUTES];
93 __u8 reserved[18];
94 __u8 vendor[131];
95 __u8 checksum;
96}
97__attribute__ ((packed)) thresholds_t;
98
99typedef struct value_s
100{
101 __u8 id;
102 __u16 status;
103 __u8 value;
104 __u8 vendor[8];
105}
106__attribute__ ((packed)) value_t;
107
108typedef struct values_s
109{
110 __u16 revision;
111 value_t values[NR_ATTRIBUTES];
112 __u8 offline_status;
113 __u8 vendor1;
114 __u16 offline_timeout;
115 __u8 vendor2;
116 __u8 offline_capability;
117 __u16 smart_capability;
118 __u8 reserved[16];
119 __u8 vendor[125];
120 __u8 checksum;
121}
122__attribute__ ((packed)) values_t;
123 77
124struct 78#define PREFAILURE 2
125{ 79#define ADVISORY 1
126 __u8 value; 80#define OPERATIONAL 0
81#define UNKNOWN -1
82
83typedef struct {
84 uint8_t id;
85 uint8_t threshold;
86 uint8_t reserved[10];
87} __attribute__((packed)) smart_threshold;
88
89typedef struct {
90 uint16_t revision;
91 smart_threshold thresholds[NR_ATTRIBUTES];
92 uint8_t reserved[18];
93 uint8_t vendor[131];
94 uint8_t checksum;
95} __attribute__((packed)) smart_thresholds;
96
97typedef struct {
98 uint8_t id;
99 uint16_t status;
100 uint8_t value;
101 uint8_t vendor[8];
102} __attribute__((packed)) smart_value;
103
104typedef struct {
105 uint16_t revision;
106 smart_value values[NR_ATTRIBUTES];
107 uint8_t offline_status;
108 uint8_t vendor1;
109 uint16_t offline_timeout;
110 uint8_t vendor2;
111 uint8_t offline_capability;
112 uint16_t smart_capability;
113 uint8_t reserved[16];
114 uint8_t vendor[125];
115 uint8_t checksum;
116} __attribute__((packed)) smart_values;
117
118static struct {
119 uint8_t value;
127 char *text; 120 char *text;
128} 121} offline_status_text[] = {{0x00, "NeverStarted"}, {0x02, "Completed"}, {0x04, "Suspended"}, {0x05, "Aborted"}, {0x06, "Failed"}, {0, 0}};
129
130offline_status_text[] =
131 {
132 {0x00, "NeverStarted"},
133 {0x02, "Completed"},
134 {0x04, "Suspended"},
135 {0x05, "Aborted"},
136 {0x06, "Failed"},
137 {0, 0}
138 };
139 122
140struct 123static struct {
141{ 124 uint8_t value;
142 __u8 value;
143 char *text; 125 char *text;
144} 126} smart_command[] = {{SMART_ENABLE, "SMART_ENABLE"},
145 127 {SMART_DISABLE, "SMART_DISABLE"},
146smart_command[] = 128 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"},
147 { 129 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"}};
148 {SMART_ENABLE, "SMART_ENABLE"}, 130
149 {SMART_DISABLE, "SMART_DISABLE"}, 131/* Index to smart_command table, keep in order */
150 {SMART_IMMEDIATE_OFFLINE, "SMART_IMMEDIATE_OFFLINE"}, 132enum SmartCommand {
151 {SMART_AUTO_OFFLINE, "SMART_AUTO_OFFLINE"} 133 SMART_CMD_ENABLE,
152 }; 134 SMART_CMD_DISABLE,
153 135 SMART_CMD_IMMEDIATE_OFFLINE,
154 136 SMART_CMD_AUTO_OFFLINE
155/* Index to smart_command table, keep in order */ 137};
156enum SmartCommand 138
157 { SMART_CMD_ENABLE, 139static char *get_offline_text(int /*status*/);
158 SMART_CMD_DISABLE, 140static int smart_read_values(int /*fd*/, smart_values * /*values*/);
159 SMART_CMD_IMMEDIATE_OFFLINE, 141static mp_state_enum compare_values_and_thresholds(smart_values * /*p*/, smart_thresholds * /*t*/);
160 SMART_CMD_AUTO_OFFLINE 142static void print_value(smart_value * /*p*/, smart_threshold * /*t*/);
143static void print_values(smart_values * /*p*/, smart_thresholds * /*t*/);
144static mp_state_enum smart_cmd_simple(int /*fd*/, enum SmartCommand /*command*/, uint8_t /*val0*/, bool /*show_error*/);
145static int smart_read_thresholds(int /*fd*/, smart_thresholds * /*thresholds*/);
146static int verbose = 0;
147
148typedef struct {
149 int errorcode;
150 check_ide_smart_config config;
151} check_ide_smart_config_wrapper;
152static check_ide_smart_config_wrapper process_arguments(int argc, char **argv) {
153 static struct option longopts[] = {{"device", required_argument, 0, 'd'},
154 {"immediate", no_argument, 0, 'i'},
155 {"quiet-check", no_argument, 0, 'q'},
156 {"auto-on", no_argument, 0, '1'},
157 {"auto-off", no_argument, 0, '0'},
158 {"nagios", no_argument, 0, 'n'}, /* DEPRECATED, but we still accept it */
159 {"help", no_argument, 0, 'h'},
160 {"version", no_argument, 0, 'V'},
161 {0, 0, 0, 0}};
162
163 check_ide_smart_config_wrapper result = {
164 .errorcode = OK,
165 .config = check_ide_smart_init(),
161 }; 166 };
162 167
163char *get_offline_text (int);
164int smart_read_values (int, values_t *);
165int nagios (values_t *, thresholds_t *);
166void print_value (value_t *, threshold_t *);
167void print_values (values_t *, thresholds_t *);
168int smart_cmd_simple (int, enum SmartCommand, __u8, bool);
169int smart_read_thresholds (int, thresholds_t *);
170bool verbose = false;
171
172int
173main (int argc, char *argv[])
174{
175 char *device = NULL;
176 int o, longindex;
177 int retval = 0;
178
179 thresholds_t thresholds;
180 values_t values;
181 int fd;
182
183 static struct option longopts[] = {
184 {"device", required_argument, 0, 'd'},
185 {"immediate", no_argument, 0, 'i'},
186 {"quiet-check", no_argument, 0, 'q'},
187 {"auto-on", no_argument, 0, '1'},
188 {"auto-off", no_argument, 0, '0'},
189 {"nagios", no_argument, 0, 'n'}, /* DEPRECATED, but we still accept it */
190 {"help", no_argument, 0, 'h'},
191 {"version", no_argument, 0, 'V'},
192 {0, 0, 0, 0}
193 };
194
195 /* Parse extra opts if any */
196 argv=np_extra_opts (&argc, argv, progname);
197
198 setlocale (LC_ALL, "");
199 bindtextdomain (PACKAGE, LOCALEDIR);
200 textdomain (PACKAGE);
201
202 while (true) { 168 while (true) {
203 169 int longindex = 0;
204 o = getopt_long (argc, argv, "+d:iq10nhVv", longopts, &longindex); 170 int option_index = getopt_long(argc, argv, "+d:iq10nhVv", longopts, &longindex);
205 171
206 if (o == -1 || o == EOF || o == 1) 172 if (option_index == -1 || option_index == EOF || option_index == 1) {
207 break; 173 break;
174 }
208 175
209 switch (o) { 176 switch (option_index) {
210 case 'd': 177 case 'd':
211 device = optarg; 178 result.config.device = optarg;
212 break; 179 break;
213 case 'q': 180 case 'q':
214 fprintf (stderr, "%s\n", _("DEPRECATION WARNING: the -q switch (quiet output) is no longer \"quiet\".")); 181 fprintf(stderr, "%s\n", _("DEPRECATION WARNING: the -q switch (quiet output) is no longer \"quiet\"."));
215 fprintf (stderr, "%s\n", _("Nagios-compatible output is now always returned.")); 182 fprintf(stderr, "%s\n", _("Nagios-compatible output is now always returned."));
216 break; 183 break;
217 case 'i': 184 case 'i':
218 case '1': 185 case '1':
219 case '0': 186 case '0':
220 printf ("%s\n", _("SMART commands are broken and have been disabled (See Notes in --help).")); 187 printf("%s\n", _("SMART commands are broken and have been disabled (See Notes in --help)."));
221 return STATE_CRITICAL; 188 result.errorcode = ERROR;
189 return result;
222 break; 190 break;
223 case 'n': 191 case 'n':
224 fprintf (stderr, "%s\n", _("DEPRECATION WARNING: the -n switch (Nagios-compatible output) is now the")); 192 fprintf(stderr, "%s\n", _("DEPRECATION WARNING: the -n switch (Nagios-compatible output) is now the"));
225 fprintf (stderr, "%s\n", _("default and will be removed from future releases.")); 193 fprintf(stderr, "%s\n", _("default and will be removed from future releases."));
226 break; 194 break;
227 case 'v': /* verbose */ 195 case 'v': /* verbose */
228 verbose = true; 196 verbose++;
229 break; 197 break;
230 case 'h': 198 case 'h':
231 print_help (); 199 print_help();
232 return STATE_UNKNOWN; 200 exit(STATE_UNKNOWN);
233 case 'V': 201 case 'V':
234 print_revision (progname, NP_VERSION); 202 print_revision(progname, NP_VERSION);
235 return STATE_UNKNOWN; 203 exit(STATE_UNKNOWN);
236 default: 204 default:
237 usage5 (); 205 usage5();
238 } 206 }
239 } 207 }
240 208
241 if (optind < argc) { 209 if (optind < argc) {
242 device = argv[optind]; 210 result.config.device = argv[optind];
243 } 211 }
244 212
245 if (!device) { 213 if (result.config.device == NULL) {
246 print_help (); 214 print_help();
247 return STATE_UNKNOWN; 215 exit(STATE_UNKNOWN);
248 } 216 }
249 217
250 fd = open (device, OPEN_MODE); 218 return result;
219}
220
221int main(int argc, char *argv[]) {
222 setlocale(LC_ALL, "");
223 bindtextdomain(PACKAGE, LOCALEDIR);
224 textdomain(PACKAGE);
225
226 /* Parse extra opts if any */
227 argv = np_extra_opts(&argc, argv, progname);
228
229 check_ide_smart_config_wrapper tmp_config = process_arguments(argc, argv);
251 230
252 if (fd < 0) { 231 if (tmp_config.errorcode != OK) {
253 printf (_("CRITICAL - Couldn't open device %s: %s\n"), device, strerror (errno)); 232 die(STATE_UNKNOWN, _("Failed to parse commandline"));
233 }
234
235 check_ide_smart_config config = tmp_config.config;
236
237 int device_file_descriptor = open(config.device, OPEN_MODE);
238
239 if (device_file_descriptor < 0) {
240 printf(_("CRITICAL - Couldn't open device %s: %s\n"), config.device, strerror(errno));
254 return STATE_CRITICAL; 241 return STATE_CRITICAL;
255 } 242 }
256 243
257 if (smart_cmd_simple (fd, SMART_CMD_ENABLE, 0, false)) { 244 if (smart_cmd_simple(device_file_descriptor, SMART_CMD_ENABLE, 0, false)) {
258 printf (_("CRITICAL - SMART_CMD_ENABLE\n")); 245 printf(_("CRITICAL - SMART_CMD_ENABLE\n"));
259 return STATE_CRITICAL; 246 return STATE_CRITICAL;
260 } 247 }
261 248
262 smart_read_values (fd, &values); 249 smart_values values;
263 smart_read_thresholds (fd, &thresholds); 250 smart_read_values(device_file_descriptor, &values);
264 retval = nagios (&values, &thresholds); 251 smart_thresholds thresholds;
265 if (verbose) print_values (&values, &thresholds); 252 smart_read_thresholds(device_file_descriptor, &thresholds);
253 mp_state_enum retval = compare_values_and_thresholds(&values, &thresholds);
254 if (verbose) {
255 print_values(&values, &thresholds);
256 }
266 257
267 close (fd); 258 close(device_file_descriptor);
268 return retval; 259 return retval;
269} 260}
270 261
271 262char *get_offline_text(int status) {
272 263 for (int index = 0; offline_status_text[index].text; index++) {
273char * 264 if (offline_status_text[index].value == status) {
274get_offline_text (int status) 265 return offline_status_text[index].text;
275{
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;
280 } 266 }
281 } 267 }
282 return "UNKNOWN"; 268 return "UNKNOWN";
283} 269}
284 270
285 271int smart_read_values(int file_descriptor, smart_values *values) {
286
287int
288smart_read_values (int fd, values_t * values)
289{
290#ifdef __linux__ 272#ifdef __linux__
291 int e; 273 uint8_t args[4 + 512];
292 __u8 args[4 + 512];
293 args[0] = WIN_SMART; 274 args[0] = WIN_SMART;
294 args[1] = 0; 275 args[1] = 0;
295 args[2] = SMART_READ_VALUES; 276 args[2] = SMART_READ_VALUES;
296 args[3] = 1; 277 args[3] = 1;
297 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 278 if (ioctl(file_descriptor, HDIO_DRIVE_CMD, &args)) {
298 e = errno; 279 int errno_storage = errno;
299 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno)); 280 printf(_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror(errno));
300 return e; 281 return errno_storage;
301 } 282 }
302 memcpy (values, args + 4, 512); 283 memcpy(values, args + 4, 512);
303#endif /* __linux__ */ 284#elif defined __NetBSD__
304#ifdef __NetBSD__
305 struct atareq req; 285 struct atareq req;
306 unsigned char inbuf[DEV_BSIZE]; 286 unsigned char inbuf[DEV_BSIZE];
307 287
@@ -316,50 +296,48 @@ smart_read_values (int fd, values_t * values)
316 req.datalen = sizeof(inbuf); 296 req.datalen = sizeof(inbuf);
317 req.cylinder = WDSMART_CYL; 297 req.cylinder = WDSMART_CYL;
318 298
319 if (ioctl(fd, ATAIOCCOMMAND, &req) == 0) { 299 if (ioctl(file_descriptor, ATAIOCCOMMAND, &req) == 0) {
320 if (req.retsts != ATACMD_OK) 300 if (req.retsts != ATACMD_OK) {
321 errno = ENODEV; 301 errno = ENODEV;
302 }
322 } 303 }
323 304
324 if (errno != 0) { 305 if (errno != 0) {
325 int e = errno; 306 int errno_storage = errno;
326 printf (_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror (errno)); 307 printf(_("CRITICAL - SMART_READ_VALUES: %s\n"), strerror(errno));
327 return e; 308 return errno_storage;
328 } 309 }
329 310
330 (void)memcpy(values, inbuf, 512); 311 (void)memcpy(values, inbuf, 512);
331#endif /* __NetBSD__ */ 312#else // __linux__ || __NetBSD__
313# error Not implemented for this OS
314#endif
315
332 return 0; 316 return 0;
333} 317}
334 318
319mp_state_enum compare_values_and_thresholds(smart_values *values, smart_thresholds *thresholds) {
320 smart_value *value = values->values;
321 smart_threshold *threshold = thresholds->thresholds;
335 322
336
337int
338nagios (values_t * p, thresholds_t * t)
339{
340 value_t * value = p->values;
341 threshold_t * threshold = t->thresholds;
342 int status = OPERATIONAL; 323 int status = OPERATIONAL;
343 int prefailure = 0; 324 int prefailure = 0;
344 int advisory = 0; 325 int advisory = 0;
345 int failed = 0; 326 int failed = 0;
346 int passed = 0; 327 int passed = 0;
347 int total = 0; 328 int total = 0;
348 int i; 329 for (int i = 0; i < NR_ATTRIBUTES; i++) {
349 for (i = 0; i < NR_ATTRIBUTES; i++) {
350 if (value->id && threshold->id && value->id == threshold->id) { 330 if (value->id && threshold->id && value->id == threshold->id) {
351 if (value->value < threshold->threshold) { 331 if (value->value < threshold->threshold) {
352 ++failed; 332 ++failed;
353 if (value->status & 1) { 333 if (value->status & 1) {
354 status = PREFAILURE; 334 status = PREFAILURE;
355 ++prefailure; 335 ++prefailure;
356 } 336 } else {
357 else {
358 status = ADVISORY; 337 status = ADVISORY;
359 ++advisory; 338 ++advisory;
360 } 339 }
361 } 340 } else {
362 else {
363 ++passed; 341 ++passed;
364 } 342 }
365 ++total; 343 ++total;
@@ -367,102 +345,74 @@ nagios (values_t * p, thresholds_t * t)
367 ++value; 345 ++value;
368 ++threshold; 346 ++threshold;
369 } 347 }
348
370 switch (status) { 349 switch (status) {
371 case PREFAILURE: 350 case PREFAILURE:
372 printf (_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"), 351 printf(_("CRITICAL - %d Harddrive PreFailure%cDetected! %d/%d tests failed.\n"), prefailure, prefailure > 1 ? 's' : ' ', failed,
373 prefailure, 352 total);
374 prefailure > 1 ? 's' : ' ', 353 status = STATE_CRITICAL;
375 failed,
376 total);
377 status=STATE_CRITICAL;
378 break; 354 break;
379 case ADVISORY: 355 case ADVISORY:
380 printf (_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"), 356 printf(_("WARNING - %d Harddrive Advisor%s Detected. %d/%d tests failed.\n"), advisory, advisory > 1 ? "ies" : "y", failed, total);
381 advisory, 357 status = STATE_WARNING;
382 advisory > 1 ? "ies" : "y",
383 failed,
384 total);
385 status=STATE_WARNING;
386 break; 358 break;
387 case OPERATIONAL: 359 case OPERATIONAL:
388 printf (_("OK - Operational (%d/%d tests passed)\n"), passed, total); 360 printf(_("OK - Operational (%d/%d tests passed)\n"), passed, total);
389 status=STATE_OK; 361 status = STATE_OK;
390 break; 362 break;
391 default: 363 default:
392 printf (_("ERROR - Status '%d' unknown. %d/%d tests passed\n"), status, 364 printf(_("ERROR - Status '%d' unknown. %d/%d tests passed\n"), status, passed, total);
393 passed, total);
394 status = STATE_UNKNOWN; 365 status = STATE_UNKNOWN;
395 break; 366 break;
396 } 367 }
397 return status; 368 return status;
398} 369}
399 370
400 371void print_value(smart_value *value_pointer, smart_threshold *threshold_pointer) {
401 372 printf("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n", value_pointer->id, value_pointer->status,
402void 373 value_pointer->status & 1 ? "PreFailure" : "Advisory ", value_pointer->status & 2 ? "OnLine " : "OffLine",
403print_value (value_t * p, threshold_t * t) 374 value_pointer->value, threshold_pointer->threshold, value_pointer->value >= threshold_pointer->threshold ? "Passed" : "Failed");
404{
405 printf ("Id=%3d, Status=%2d {%s , %s}, Value=%3d, Threshold=%3d, %s\n",
406 p->id, p->status, p->status & 1 ? "PreFailure" : "Advisory ",
407 p->status & 2 ? "OnLine " : "OffLine", p->value, t->threshold,
408 p->value >= t->threshold ? "Passed" : "Failed");
409} 375}
410 376
411 377void print_values(smart_values *values, smart_thresholds *thresholds) {
412 378 smart_value *value = values->values;
413void 379 smart_threshold *threshold = thresholds->thresholds;
414print_values (values_t * p, thresholds_t * t) 380 for (int i = 0; i < NR_ATTRIBUTES; i++) {
415{
416 value_t * value = p->values;
417 threshold_t * threshold = t->thresholds;
418 int i;
419 for (i = 0; i < NR_ATTRIBUTES; i++) {
420 if (value->id && threshold->id && value->id == threshold->id) { 381 if (value->id && threshold->id && value->id == threshold->id) {
421 print_value (value++, threshold++); 382 print_value(value++, threshold++);
422 } 383 }
423 } 384 }
424 printf 385 printf(_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"), values->offline_status,
425 (_("OffLineStatus=%d {%s}, AutoOffLine=%s, OffLineTimeout=%d minutes\n"), 386 get_offline_text(values->offline_status & 0x7f), (values->offline_status & 0x80 ? "Yes" : "No"), values->offline_timeout / 60);
426 p->offline_status, 387 printf(_("OffLineCapability=%d {%s %s %s}\n"), values->offline_capability, values->offline_capability & 1 ? "Immediate" : "",
427 get_offline_text (p->offline_status & 0x7f), 388 values->offline_capability & 2 ? "Auto" : "", values->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
428 (p->offline_status & 0x80 ? "Yes" : "No"), 389 printf(_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"), values->revision, values->checksum, values->smart_capability,
429 p->offline_timeout / 60); 390 values->smart_capability & 1 ? "SaveOnStandBy" : "", values->smart_capability & 2 ? "AutoSave" : "");
430 printf
431 (_("OffLineCapability=%d {%s %s %s}\n"),
432 p->offline_capability,
433 p->offline_capability & 1 ? "Immediate" : "",
434 p->offline_capability & 2 ? "Auto" : "",
435 p->offline_capability & 4 ? "AbortOnCmd" : "SuspendOnCmd");
436 printf
437 (_("SmartRevision=%d, CheckSum=%d, SmartCapability=%d {%s %s}\n"),
438 p->revision,
439 p->checksum,
440 p->smart_capability,
441 p->smart_capability & 1 ? "SaveOnStandBy" : "",
442 p->smart_capability & 2 ? "AutoSave" : "");
443} 391}
444 392
445 393mp_state_enum smart_cmd_simple(int file_descriptor, enum SmartCommand command, uint8_t val0, bool show_error) {
446int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, bool show_error) { 394 mp_state_enum result = STATE_UNKNOWN;
447 int e = STATE_UNKNOWN;
448#ifdef __linux__ 395#ifdef __linux__
449 __u8 args[4]; 396 uint8_t args[4] = {
450 args[0] = WIN_SMART; 397 WIN_SMART,
451 args[1] = val0; 398 val0,
452 args[2] = smart_command[command].value; 399 smart_command[command].value,
453 args[3] = 0; 400 0,
454 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 401 };
455 e = STATE_CRITICAL; 402
456 if (show_error) 403 if (ioctl(file_descriptor, HDIO_DRIVE_CMD, &args)) {
457 printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno)); 404 result = STATE_CRITICAL;
405 if (show_error) {
406 printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
407 }
458 } else { 408 } else {
459 e = STATE_OK; 409 result = STATE_OK;
460 if (show_error) 410 if (show_error) {
461 printf (_("OK - Command sent (%s)\n"), smart_command[command].text); 411 printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
412 }
462 } 413 }
463 414
464#endif /* __linux__ */ 415#elif defined __NetBSD__
465#ifdef __NetBSD__
466 struct atareq req; 416 struct atareq req;
467 417
468 memset(&req, 0, sizeof(req)); 418 memset(&req, 0, sizeof(req));
@@ -473,52 +423,52 @@ int smart_cmd_simple (int fd, enum SmartCommand command, __u8 val0, bool show_er
473 req.cylinder = WDSMART_CYL; 423 req.cylinder = WDSMART_CYL;
474 req.sec_count = val0; 424 req.sec_count = val0;
475 425
476 if (ioctl(fd, ATAIOCCOMMAND, &req) == 0) { 426 if (ioctl(file_descriptor, ATAIOCCOMMAND, &req) == 0) {
477 if (req.retsts != ATACMD_OK) 427 if (req.retsts != ATACMD_OK) {
478 errno = ENODEV; 428 errno = ENODEV;
479 if (req.cylinder != WDSMART_CYL) 429 }
430 if (req.cylinder != WDSMART_CYL) {
480 errno = ENODEV; 431 errno = ENODEV;
432 }
481 } 433 }
482 434
483 if (errno != 0) { 435 if (errno != 0) {
484 e = STATE_CRITICAL; 436 result = STATE_CRITICAL;
485 if (show_error) 437 if (show_error) {
486 printf (_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror (errno)); 438 printf(_("CRITICAL - %s: %s\n"), smart_command[command].text, strerror(errno));
439 }
487 } else { 440 } else {
488 e = STATE_OK; 441 result = STATE_OK;
489 if (show_error) 442 if (show_error) {
490 printf (_("OK - Command sent (%s)\n"), smart_command[command].text); 443 printf(_("OK - Command sent (%s)\n"), smart_command[command].text);
444 }
491 } 445 }
492 446#else
447# error Not implemented for this OS
493#endif /* __NetBSD__ */ 448#endif /* __NetBSD__ */
494 return e;
495}
496
497 449
450 return result;
451}
498 452
499int 453int smart_read_thresholds(int file_descriptor, smart_thresholds *thresholds) {
500smart_read_thresholds (int fd, thresholds_t * thresholds)
501{
502#ifdef __linux__ 454#ifdef __linux__
503 int e; 455 uint8_t args[4 + 512];
504 __u8 args[4 + 512];
505 args[0] = WIN_SMART; 456 args[0] = WIN_SMART;
506 args[1] = 0; 457 args[1] = 0;
507 args[2] = SMART_READ_THRESHOLDS; 458 args[2] = SMART_READ_THRESHOLDS;
508 args[3] = 1; 459 args[3] = 1;
509 if (ioctl (fd, HDIO_DRIVE_CMD, &args)) { 460 if (ioctl(file_descriptor, HDIO_DRIVE_CMD, &args)) {
510 e = errno; 461 int errno_storage = errno;
511 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno)); 462 printf(_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror(errno));
512 return e; 463 return errno_storage;
513 } 464 }
514 memcpy (thresholds, args + 4, 512); 465 memcpy(thresholds, args + 4, 512);
515#endif /* __linux__ */ 466#elif defined __NetBSD__
516#ifdef __NetBSD__
517 struct atareq req; 467 struct atareq req;
518 unsigned char inbuf[DEV_BSIZE];
519
520 memset(&req, 0, sizeof(req)); 468 memset(&req, 0, sizeof(req));
521 req.timeout = 1000; 469 req.timeout = 1000;
470
471 unsigned char inbuf[DEV_BSIZE];
522 memset(&inbuf, 0, sizeof(inbuf)); 472 memset(&inbuf, 0, sizeof(inbuf));
523 473
524 req.flags = ATACMD_READ; 474 req.flags = ATACMD_READ;
@@ -528,61 +478,63 @@ smart_read_thresholds (int fd, thresholds_t * thresholds)
528 req.datalen = sizeof(inbuf); 478 req.datalen = sizeof(inbuf);
529 req.cylinder = WDSMART_CYL; 479 req.cylinder = WDSMART_CYL;
530 480
531 if (ioctl(fd, ATAIOCCOMMAND, &req) == 0) { 481 if (ioctl(file_descriptor, ATAIOCCOMMAND, &req) == 0) {
532 if (req.retsts != ATACMD_OK) 482 if (req.retsts != ATACMD_OK) {
533 errno = ENODEV; 483 errno = ENODEV;
484 }
534 } 485 }
535 486
536 if (errno != 0) { 487 if (errno != 0) {
537 int e = errno; 488 int errno_storage = errno;
538 printf (_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror (errno)); 489 printf(_("CRITICAL - SMART_READ_THRESHOLDS: %s\n"), strerror(errno));
539 return e; 490 return errno_storage;
540 } 491 }
541 492
542 (void)memcpy(thresholds, inbuf, 512); 493 (void)memcpy(thresholds, inbuf, 512);
494#else
495# error Not implemented for this OS
543#endif /* __NetBSD__ */ 496#endif /* __NetBSD__ */
497
544 return 0; 498 return 0;
545} 499}
546 500
501void print_help(void) {
502 print_revision(progname, NP_VERSION);
547 503
548void 504 printf("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n");
549print_help (void) 505 printf("Plugin implementation - 1999 Robert Dale <rdale@digital-mission.com>\n");
550{ 506 printf(COPYRIGHT, copyright, email);
551 print_revision (progname, NP_VERSION);
552 507
553 printf ("(C) 1999 Ragnar Hojland Espinosa <ragnar@lightside.dhis.org>\n"); 508 printf(_("This plugin checks a local hard drive with the (Linux specific) SMART interface "
554 printf ("Plugin implementation - 1999 Robert Dale <rdale@digital-mission.com>\n"); 509 "[http://smartlinux.sourceforge.net/smart/index.php]."));
555 printf (COPYRIGHT, copyright, email);
556 510
557 printf (_("This plugin checks a local hard drive with the (Linux specific) SMART interface [http://smartlinux.sourceforge.net/smart/index.php].")); 511 printf("\n\n");
558 512
559 printf ("\n\n"); 513 print_usage();
560 514
561 print_usage (); 515 printf(UT_HELP_VRSN);
516 printf(UT_EXTRA_OPTS);
562 517
563 printf (UT_HELP_VRSN); 518 printf(" %s\n", "-d, --device=DEVICE");
564 printf (UT_EXTRA_OPTS); 519 printf(" %s\n", _("Select device DEVICE"));
520 printf(" %s\n", _("Note: if the device is specified without this option, any further option will"));
521 printf(" %s\n", _("be ignored."));
565 522
566 printf (" %s\n", "-d, --device=DEVICE"); 523 printf(UT_VERBOSE);
567 printf (" %s\n", _("Select device DEVICE"));
568 printf (" %s\n", _("Note: if the device is specified without this option, any further option will"));
569 printf (" %s\n", _("be ignored."));
570 524
571 printf (UT_VERBOSE); 525 printf("\n");
526 printf("%s\n", _("Notes:"));
527 printf(" %s\n", _("The SMART command modes (-i/--immediate, -0/--auto-off and -1/--auto-on) were"));
528 printf(" %s\n", _("broken in an underhand manner and have been disabled. You can use smartctl"));
529 printf(" %s\n", _("instead:"));
530 printf(" %s\n", _("-0/--auto-off: use \"smartctl --offlineauto=off\""));
531 printf(" %s\n", _("-1/--auto-on: use \"smartctl --offlineauto=on\""));
532 printf(" %s\n", _("-i/--immediate: use \"smartctl --test=offline\""));
572 533
573 printf ("\n"); 534 printf(UT_SUPPORT);
574 printf ("%s\n", _("Notes:"));
575 printf (" %s\n", _("The SMART command modes (-i/--immediate, -0/--auto-off and -1/--auto-on) were"));
576 printf (" %s\n", _("broken in an underhand manner and have been disabled. You can use smartctl"));
577 printf (" %s\n", _("instead:"));
578 printf (" %s\n", _("-0/--auto-off: use \"smartctl --offlineauto=off\""));
579 printf (" %s\n", _("-1/--auto-on: use \"smartctl --offlineauto=on\""));
580 printf (" %s\n", _("-i/--immediate: use \"smartctl --test=offline\""));
581
582 printf (UT_SUPPORT);
583} 535}
584 536
585 /* todo : add to the long nanual as example 537/* todo : add to the long nanual as example
586 * 538 *
587 * Run with: check_ide-smart --nagios [-d] <DRIVE> 539 * Run with: check_ide-smart --nagios [-d] <DRIVE>
588 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc 540 * Where DRIVE is an IDE drive, ie. /dev/hda, /dev/hdb, /dev/hdc
@@ -593,10 +545,7 @@ print_help (void)
593 * - Returns -1 not too often 545 * - Returns -1 not too often
594 */ 546 */
595 547
596 548void print_usage(void) {
597void 549 printf("%s\n", _("Usage:"));
598print_usage (void) 550 printf("%s [-d <device>] [-v]", progname);
599{
600 printf ("%s\n", _("Usage:"));
601 printf ("%s [-d <device>] [-v]", progname);
602} 551}