1 /******************************************************************************
2 *
3 * CHECK_NT.C
4 *
5 * Program: Windows NT plugin for NetSaint
6 * License: GPL
7 * Copyright (c) 2000-2002 Yves Rubin (rubiyz@yahoo.com)
8 *
9 * Description:
10 *
11 * This requires NSClient software to run on NT (http://nsclient.ready2run.nl/)
12 *
13 * License Information:
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 *
29 *****************************************************************************/
31 #include "config.h"
32 #include "common.h"
33 #include "netutils.h"
34 #include "utils.h"
36 #define CHECK_NONE 0
37 #define CHECK_CLIENTVERSION 1
38 #define CHECK_CPULOAD 2
39 #define CHECK_UPTIME 3
40 #define CHECK_USEDDISKSPACE 4
41 #define CHECK_SERVICESTATE 5
42 #define CHECK_PROCSTATE 6
43 #define CHECK_MEMUSE 7
44 #define CHECK_COUNTER 8
45 #define CHECK_FILEAGE 9
46 #define MAX_VALUE_LIST 30
48 #define PORT 1248
50 char *server_address=NULL;
51 char *volume_name=NULL;
52 int server_port=PORT;
53 char *value_list=NULL;
54 char *req_password=NULL;
55 unsigned long lvalue_list[MAX_VALUE_LIST];
56 unsigned long warning_value=0L;
57 unsigned long critical_value=0L;
58 int check_value_list=FALSE;
59 int check_warning_value=FALSE;
60 int check_critical_value=FALSE;
61 int vars_to_check=CHECK_NONE;
62 int show_all=FALSE;
64 const char *progname = "check_nt";
66 int process_arguments(int, char **);
67 void preparelist(char *string);
68 int strtoularray(unsigned long *array, char *string, const char *delim);
69 void print_help(void);
70 void print_usage(void);
72 int main(int argc, char **argv){
73 int result;
74 int return_code = STATE_UNKNOWN;
75 char *send_buffer=NULL;
76 char recv_buffer[MAX_INPUT_BUFFER];
77 char *output_message=NULL;
78 char *temp_string=NULL;
79 char *description=NULL;
81 double total_disk_space=0;
82 double free_disk_space=0;
83 double percent_used_space=0;
84 double mem_commitLimit=0;
85 double mem_commitByte=0;
86 unsigned long utilization;
87 unsigned long uptime;
88 unsigned long age_in_minutes;
89 double counter_value;
90 int offset=0;
91 int updays=0;
92 int uphours=0;
93 int upminutes=0;
95 asprintf(&req_password, _("None"));
97 if(process_arguments(argc,argv)==ERROR)
98 usage(_("Could not parse arguments\n"));
100 /* initialize alarm signal handling */
101 signal(SIGALRM,socket_timeout_alarm_handler);
103 /* set socket timeout */
104 alarm(socket_timeout);
106 if (vars_to_check==CHECK_CLIENTVERSION) {
108 asprintf(&send_buffer,strcat(req_password,"&1"));
109 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
110 if(result!=STATE_OK)
111 return result;
112 asprintf(&output_message,recv_buffer);
113 return_code=STATE_OK;
115 }
117 else if(vars_to_check==CHECK_CPULOAD){
119 if (check_value_list==TRUE) {
120 if (strtoularray(lvalue_list,value_list,",")==TRUE) {
121 /* -l parameters is present with only integers */
122 return_code=STATE_OK;
123 asprintf(&temp_string,_("CPU Load"));
124 while (lvalue_list[0+offset]> (unsigned long)0 &&
125 lvalue_list[0+offset]<=(unsigned long)17280 &&
126 lvalue_list[1+offset]> (unsigned long)0 &&
127 lvalue_list[1+offset]<=(unsigned long)100 &&
128 lvalue_list[2+offset]> (unsigned long)0 &&
129 lvalue_list[2+offset]<=(unsigned long)100) {
130 /* loop until one of the parameters is wrong or not present */
132 /* Send request and retrieve data */
133 asprintf(&send_buffer,"%s&2&%lu",req_password,lvalue_list[0+offset]);
134 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
135 if(result!=STATE_OK)
136 return result;
138 if (!strncmp(recv_buffer,"ERROR",5)) {
139 printf("NSClient - %s\n",recv_buffer);
140 exit(STATE_UNKNOWN);
141 }
143 utilization=strtoul(recv_buffer,NULL,10);
145 /* Check if any of the request is in a warning or critical state */
146 if(utilization >= lvalue_list[2+offset])
147 return_code=STATE_CRITICAL;
148 else if(utilization >= lvalue_list[1+offset] && return_code<STATE_WARNING)
149 return_code=STATE_WARNING;
151 asprintf(&output_message,_(" %lu%% (%lu min average)"), utilization, lvalue_list[0+offset]);
152 asprintf(&temp_string,"%s%s",temp_string,output_message);
153 offset+=3; /* move across the array */
154 }
155 if (strlen(temp_string)>10) {
156 /* we had at least on loop */
157 asprintf(&output_message,"%s",temp_string);
158 }
159 else
160 asprintf(&output_message,"%s",_("not enough values for -l parameters"));
162 } else
163 asprintf(&output_message,_("wrong -l parameter."));
165 } else
166 asprintf(&output_message,_("missing -l parameters"));
167 }
169 else if(vars_to_check==CHECK_UPTIME){
171 asprintf(&send_buffer,strcat(req_password,"&3"));
172 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
173 if(result!=STATE_OK)
174 return result;
176 if (!strncmp(recv_buffer,"ERROR",5)) {
177 printf("NSClient - %s\n",recv_buffer);
178 exit(STATE_UNKNOWN);
179 }
181 uptime=strtoul(recv_buffer,NULL,10);
182 updays = uptime / 86400;
183 uphours = (uptime % 86400) / 3600;
184 upminutes = ((uptime % 86400) % 3600) / 60;
185 asprintf(&output_message,_("System Uptime : %u day(s) %u hour(s) %u minute(s)"),updays,uphours, upminutes);
186 return_code=STATE_OK;
187 }
189 else if(vars_to_check==CHECK_USEDDISKSPACE){
191 return_code=STATE_UNKNOWN;
192 if (check_value_list==TRUE) {
193 if (strlen(value_list)==1) {
194 asprintf(&send_buffer,"%s&4&%s", req_password, value_list);
195 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
196 if(result!=STATE_OK)
197 return result;
199 if (!strncmp(recv_buffer,"ERROR",5)) {
200 printf("NSClient - %s\n",recv_buffer);
201 exit(STATE_UNKNOWN);
202 }
204 free_disk_space=atof(strtok(recv_buffer,"&"));
205 total_disk_space=atof(strtok(NULL,"&"));
206 percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100;
208 if (free_disk_space>=0) {
209 asprintf(&temp_string,_("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"),
210 value_list, total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824, percent_used_space,
211 free_disk_space / 1073741824, (free_disk_space / total_disk_space)*100);
214 if(check_critical_value==TRUE && percent_used_space >= critical_value)
215 return_code=STATE_CRITICAL;
216 else if (check_warning_value==TRUE && percent_used_space >= warning_value)
217 return_code=STATE_WARNING;
218 else
219 return_code=STATE_OK;
221 asprintf(&output_message,"%s",temp_string);
223 }
224 else {
225 asprintf(&output_message,_("Free disk space : Invalid drive "));
226 return_code=STATE_UNKNOWN;
227 }
228 }
229 else
230 asprintf(&output_message,_("wrong -l argument"));
231 } else
232 asprintf(&output_message,_("missing -l parameters"));
234 }
236 else if(vars_to_check==CHECK_SERVICESTATE || vars_to_check==CHECK_PROCSTATE){
238 if (check_value_list==TRUE) {
239 preparelist(value_list); /* replace , between services with & to send the request */
240 asprintf(&send_buffer,"%s&%u&%s&%s", req_password,(vars_to_check==CHECK_SERVICESTATE)?5:6,
241 (show_all==TRUE)?_("ShowAll"):_("ShowFail"),value_list);
242 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
243 if(result!=STATE_OK)
244 return result;
246 if (!strncmp(recv_buffer,"ERROR",5)) {
247 printf("NSClient - %s\n",recv_buffer);
248 exit(STATE_UNKNOWN);
249 }
250 return_code=atoi(strtok(recv_buffer,"&"));
251 temp_string=strtok(NULL,"&");
252 asprintf(&output_message, "%s",temp_string);
253 }
254 else
255 asprintf(&output_message,_("No service/process specified"));
256 }
258 else if(vars_to_check==CHECK_MEMUSE) {
260 asprintf(&send_buffer,"%s&7", req_password);
261 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
262 if (result!=STATE_OK)
263 return result;
265 if (!strncmp(recv_buffer,"ERROR",5)) {
266 printf("NSClient - %s\n",recv_buffer);
267 exit(STATE_UNKNOWN);
268 }
270 mem_commitLimit=atof(strtok(recv_buffer,"&"));
271 mem_commitByte=atof(strtok(NULL,"&"));
272 percent_used_space = (mem_commitByte / mem_commitLimit) * 100;
273 asprintf(&output_message,_("Memory usage: total:%.2f Mb - used: %.2f Mb (%.0f%%) - free: %.2f Mb (%.0f%%)"),
274 mem_commitLimit / 1048576, mem_commitByte / 1048567, percent_used_space,
275 (mem_commitLimit - mem_commitByte) / 1048576, (mem_commitLimit - mem_commitByte) / mem_commitLimit * 100);
277 if(check_critical_value==TRUE && percent_used_space >= critical_value)
278 return_code=STATE_CRITICAL;
279 else if (check_warning_value==TRUE && percent_used_space >= warning_value)
280 return_code=STATE_WARNING;
281 else
282 return_code=STATE_OK;
284 }
286 else if(vars_to_check==CHECK_COUNTER) {
288 if (check_value_list==TRUE) {
289 preparelist(value_list); /* replace , between services with & to send the request */
290 asprintf(&send_buffer,"%s&8&%s", req_password,value_list);
291 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
292 if (result!=STATE_OK)
293 return result;
295 if (!strncmp(recv_buffer,"ERROR",5)) {
296 printf("NSClient - %s\n",recv_buffer);
297 exit(STATE_UNKNOWN);
298 }
300 strtok(value_list,"&"); /* burn the first parameters */
301 description = strtok(NULL,"&");
302 counter_value = atof(recv_buffer);
303 if (description == NULL)
304 asprintf(&output_message, "%.f", counter_value);
305 else
306 asprintf(&output_message, description, counter_value);
308 if (critical_value > warning_value) {
309 /* Normal thresholds */
310 if(check_critical_value==TRUE && counter_value >= critical_value)
311 return_code=STATE_CRITICAL;
312 else if (check_warning_value==TRUE && counter_value >= warning_value)
313 return_code=STATE_WARNING;
314 else
315 return_code=STATE_OK;
316 }
317 else {
318 /* inverse thresholds */
319 if(check_critical_value==TRUE && counter_value <= critical_value)
320 return_code=STATE_CRITICAL;
321 else if (check_warning_value==TRUE && counter_value <= warning_value)
322 return_code=STATE_WARNING;
323 else
324 return_code=STATE_OK;
325 }
327 }
328 else {
329 asprintf(&output_message,_("No counter specified"));
330 result=STATE_UNKNOWN;
331 }
332 }
333 else if(vars_to_check==CHECK_FILEAGE) {
335 if (check_value_list==TRUE) {
336 preparelist(value_list); /* replace , between services with & to send the request */
337 asprintf(&send_buffer,"%s&9&%s", req_password,value_list);
338 result=process_tcp_request(server_address,server_port,send_buffer,recv_buffer,sizeof(recv_buffer));
339 if (result!=STATE_OK)
340 return result;
342 if (!strncmp(recv_buffer,"ERROR",5)) {
343 printf("NSClient - %s\n",recv_buffer);
344 exit(STATE_UNKNOWN);
345 }
347 age_in_minutes = atoi(strtok(recv_buffer,"&"));
348 description = strtok(NULL,"&");
349 asprintf(&output_message, description);
351 if (critical_value > warning_value) {
352 /* Normal thresholds */
353 if(check_critical_value==TRUE && age_in_minutes >= critical_value)
354 return_code=STATE_CRITICAL;
355 else if (check_warning_value==TRUE && age_in_minutes >= warning_value)
356 return_code=STATE_WARNING;
357 else
358 return_code=STATE_OK;
359 }
360 else {
361 /* inverse thresholds */
362 if(check_critical_value==TRUE && age_in_minutes <= critical_value)
363 return_code=STATE_CRITICAL;
364 else if (check_warning_value==TRUE && age_in_minutes <= warning_value)
365 return_code=STATE_WARNING;
366 else
367 return_code=STATE_OK;
368 }
370 }
371 else {
372 asprintf(&output_message,_("No file specified"));
373 result=STATE_UNKNOWN;
374 }
375 }
377 /* reset timeout */
378 alarm(0);
380 printf("%s\n",output_message);
382 return return_code;
383 }
389 \f
390 /* process command-line arguments */
391 int process_arguments(int argc, char **argv){
392 int c;
394 int option_index = 0;
395 static struct option long_options[] =
396 {
397 {"port", required_argument,0,'p'},
398 {"timeout", required_argument,0,'t'},
399 {"critical", required_argument,0,'c'},
400 {"warning", required_argument,0,'w'},
401 {"variable", required_argument,0,'v'},
402 {"hostname", required_argument,0,'H'},
403 {"version", no_argument, 0,'V'},
404 {"help", no_argument, 0,'h'},
405 {0,0,0,0}
406 };
408 /* no options were supplied */
409 if(argc<2) return ERROR;
411 /* backwards compatibility */
412 if (! is_option(argv[1])) {
413 server_address=argv[1];
414 argv[1]=argv[0];
415 argv=&argv[1];
416 argc--;
417 }
419 for (c=1;c<argc;c++) {
420 if(strcmp("-to",argv[c])==0)
421 strcpy(argv[c],"-t");
422 else if (strcmp("-wv",argv[c])==0)
423 strcpy(argv[c],"-w");
424 else if (strcmp("-cv",argv[c])==0)
425 strcpy(argv[c],"-c");
426 }
428 while (1){
429 c = getopt_long(argc,argv,"+hVH:t:c:w:p:v:l:s:d:",long_options,&option_index);
431 if (c==-1||c==EOF||c==1)
432 break;
434 switch (c)
435 {
436 case '?': /* print short usage statement if args not parsable */
437 printf("%s: Unknown argument: %s\n\n",progname,optarg);
438 print_usage();
439 exit(STATE_UNKNOWN);
440 case 'h': /* help */
441 print_help();
442 exit(STATE_OK);
443 case 'V': /* version */
444 print_revision(progname,"$Revision$");
445 exit(STATE_OK);
446 case 'H': /* hostname */
447 server_address=optarg;
448 break;
449 case 's': /* password */
450 asprintf(&req_password,optarg);
451 break;
452 case 'p': /* port */
453 if (is_intnonneg(optarg))
454 server_port=atoi(optarg);
455 else
456 die(STATE_UNKNOWN,_("Server port an integer (seconds)\nType '%s -h' for additional help\n"),progname);
457 break;
458 case 'v':
459 if(strlen(optarg)<4)
460 return ERROR;
461 if(!strcmp(optarg,"CLIENTVERSION"))
462 vars_to_check=CHECK_CLIENTVERSION;
463 else if(!strcmp(optarg,"CPULOAD"))
464 vars_to_check=CHECK_CPULOAD;
465 else if(!strcmp(optarg,"UPTIME"))
466 vars_to_check=CHECK_UPTIME;
467 else if(!strcmp(optarg,"USEDDISKSPACE"))
468 vars_to_check=CHECK_USEDDISKSPACE;
469 else if(!strcmp(optarg,"SERVICESTATE"))
470 vars_to_check=CHECK_SERVICESTATE;
471 else if(!strcmp(optarg,"PROCSTATE"))
472 vars_to_check=CHECK_PROCSTATE;
473 else if(!strcmp(optarg,"MEMUSE"))
474 vars_to_check=CHECK_MEMUSE;
475 else if(!strcmp(optarg,"COUNTER"))
476 vars_to_check=CHECK_COUNTER;
477 else if(!strcmp(optarg,"FILEAGE"))
478 vars_to_check=CHECK_FILEAGE;
479 else
480 return ERROR;
481 break;
482 case 'l': /* value list */
483 asprintf(&value_list,"%s",optarg);
484 check_value_list=TRUE;
485 break;
486 case 'w': /* warning threshold */
487 warning_value=strtoul(optarg,NULL,10);
488 check_warning_value=TRUE;
489 break;
490 case 'c': /* critical threshold */
491 critical_value=strtoul(optarg,NULL,10);
492 check_critical_value=TRUE;
493 break;
494 case 'd': /* Display select for services */
495 if (!strcmp(optarg,"SHOWALL"))
496 show_all = TRUE;
497 break;
498 case 't': /* timeout */
499 socket_timeout=atoi(optarg);
500 if(socket_timeout<=0)
501 return ERROR;
502 }
504 }
506 if (vars_to_check==CHECK_NONE)
507 return ERROR;
509 return OK;
510 }
516 \f
517 int strtoularray(unsigned long *array, char *string, const char *delim) {
518 /* split a <delim> delimited string into a long array */
519 int idx=0;
520 char *t1;
522 for (idx=0;idx<MAX_VALUE_LIST;idx++)
523 array[idx]=0;
525 idx=0;
526 for(t1 = strtok(string,delim);t1 != NULL; t1 = strtok(NULL, delim)) {
527 if (is_numeric(t1) && idx<MAX_VALUE_LIST) {
528 array[idx]=strtoul(t1,NULL,10);
529 idx++;
530 } else
531 return FALSE;
532 }
533 return TRUE;
534 }
536 void preparelist(char *string) {
537 /* Replace all , with & which is the delimiter for the request */
538 int i;
540 for (i = 0; (size_t)i < strlen(string); i++)
541 if (string[i] == ',') {
542 string[i]='&';
543 }
544 }
550 \f
551 void print_help(void)
552 {
553 print_revision(progname,"$Revision$");
554 printf (_("\
555 Copyright (c) 2000 Yves Rubin (rubiyz@yahoo.com)\n\n\
556 This plugin collects data from the NSClient service running on a\n\
557 Windows NT/2000/XP server.\n\n"));
558 print_usage();
559 printf (_("\nOptions:\n\
560 -H, --hostname=HOST\n\
561 Name of the host to check\n\
562 -p, --port=INTEGER\n\
563 Optional port number (default: %d)\n\
564 -s <password>\n\
565 Password needed for the request\n\
566 -w, --warning=INTEGER\n\
567 Threshold which will result in a warning status\n\
568 -c, --critical=INTEGER\n\
569 Threshold which will result in a critical status\n\
570 -t, --timeout=INTEGER\n\
571 Seconds before connection attempt times out (default: %d)\n\
572 -h, --help\n\
573 Print this help screen\n\
574 -V, --version\n\
575 Print version information\n"),
576 PORT, DEFAULT_SOCKET_TIMEOUT);
577 printf (_("\
578 -v, --variable=STRING\n\
579 Variable to check. Valid variables are:\n"));
580 printf (_("\
581 CLIENTVERSION = Get the NSClient version\n"));
582 printf (_("\
583 CPULOAD = Average CPU load on last x minutes.\n\
584 Request a -l parameter with the following syntax:\n\
585 -l <minutes range>,<warning threshold>,<critical threshold>.\n\
586 <minute range> should be less than 24*60.\n\
587 Thresholds are percentage and up to 10 requests can be done in one shot.\n\
588 ie: -l 60,90,95,120,90,95\n"));
589 printf (_("\
590 UPTIME = Get the uptime of the machine.\n\
591 No specific parameters. No warning or critical threshold\n"));
592 printf (_("\
593 USEDDISKSPACE = Size and percentage of disk use.\n\
594 Request a -l parameter containing the drive letter only.\n\
595 Warning and critical thresholds can be specified with -w and -c.\n"));
596 printf (_("\
597 MEMUSE = Memory use.\n\
598 Warning and critical thresholds can be specified with -w and -c.\n"));
599 printf (_("\
600 SERVICESTATE = Check the state of one or several services.\n\
601 Request a -l parameters with the following syntax:\n\
602 -l <service1>,<service2>,<service3>,...\n\
603 You can specify -d SHOWALL in case you want to see working services\n\
604 in the returned string.\n"));
605 printf (_("\
606 PROCSTATE = Check if one or several process are running.\n\
607 Same syntax as SERVICESTATE.\n"));
608 printf (_("\
609 COUNTER = Check any performance counter of Windows NT/2000.\n\
610 Request a -l parameters with the following syntax:\n\
611 -l \"\\\\<performance object>\\\\counter\",\"<description>\n\
612 The <description> parameter is optional and \n\
613 is given to a printf output command which require a float parameters.\n\
614 Some examples:\n\
615 \"Paging file usage is %%.2f %%%%\"\n\
616 \"%%.f %%%% paging file used.\"\n"));
617 printf (_("Notes:\n\
618 - The NSClient service should be running on the server to get any information\n\
619 (http://nsclient.ready2run.nl).\n\
620 - Critical thresholds should be lower than warning thresholds\n"));
621 }
626 void print_usage(void)
627 {
628 printf(_("\
629 Usage: %s -H host -v variable [-p port] [-w warning] [-c critical]\n\
630 [-l params] [-d SHOWALL] [-t timeout]\n"), progname);
631 printf (_(UT_HLP_VRS), progname, progname);
632 }