~ubuntu-branches/ubuntu/precise/nagios-snmp-plugins/precise

« back to all changes in this revision

Viewing changes to check_snmp_win.pl

  • Committer: Bazaar Package Importer
  • Author(s): Jan Wagner
  • Date: 2007-04-25 22:00:50 UTC
  • Revision ID: james.westby@ubuntu.com-20070425220050-tesozvdx9rwgo0j4
Tags: upstream-1.1.1
ImportĀ upstreamĀ versionĀ 1.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl -w
 
2
############################## check_snmp_win ##############
 
3
# Version : 0.6
 
4
# Date : Nov 29 2006 
 
5
# Author  : Patrick Proy (patrick at proy.org)
 
6
# Help : http://www.manubulon.com/nagios/
 
7
# Licence : GPL - http://www.fsf.org/licenses/gpl.txt
 
8
# TODO : 
 
9
###############################################################
 
10
#
 
11
# help : ./check_snmp_win.pl -h
 
12
 
 
13
use strict;
 
14
use Net::SNMP;
 
15
use Getopt::Long;
 
16
 
 
17
# Nagios specific
 
18
 
 
19
use lib "/usr/local/nagios/libexec";
 
20
use utils qw(%ERRORS $TIMEOUT);
 
21
#my $TIMEOUT = 5;
 
22
#my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4);
 
23
 
 
24
# SNMP Datas for processes (MIB II)
 
25
my $process_table= '1.3.6.1.2.1.25.4.2.1';
 
26
my $index_table = '1.3.6.1.2.1.25.4.2.1.1';
 
27
my $run_name_table = '1.3.6.1.2.1.25.4.2.1.2';
 
28
my $run_path_table = '1.3.6.1.2.1.25.4.2.1.4';
 
29
my $proc_mem_table = '1.3.6.1.2.1.25.5.1.1.2'; # Kbytes
 
30
my $proc_cpu_table = '1.3.6.1.2.1.25.5.1.1.1'; # Centi sec of CPU
 
31
my $proc_run_state = '1.3.6.1.2.1.25.4.2.1.7';
 
32
 
 
33
# Windows SNMP DATA
 
34
 
 
35
my $win_serv_table = '1.3.6.1.4.1.77.1.2.3.1'; # Windows services table
 
36
my $win_serv_name = '1.3.6.1.4.1.77.1.2.3.1.1'; # Name of the service
 
37
# Install state : uninstalled(1), install-pending(2), uninstall-pending(3), installed(4)
 
38
my $win_serv_inst = '1.3.6.1.4.1.77.1.2.3.1.2'; 
 
39
# Operating state : active(1),  continue-pending(2),  pause-pending(3),  paused(4)
 
40
my $win_serv_state = '1.3.6.1.4.1.77.1.2.3.1.3'; 
 
41
my %win_serv_state_label = ( 1 => 'active', 2=> 'continue-pending', 3=> 'pause-pending', 4=> 'paused');
 
42
# Can be uninstalled : cannot-be-uninstalled(1), can-be-uninstalled(2)
 
43
my $win_serv_uninst = '1.3.6.1.4.1.77.1.2.3.1.4'; 
 
44
 
 
45
# Globals
 
46
 
 
47
my $Version='0.6';
 
48
my $Name='check_snmp_win';
 
49
 
 
50
my $o_host =    undef;          # hostname 
 
51
my $o_community =undef;         # community 
 
52
my $o_port =    161;            # port
 
53
my $o_version2  = undef;        #use snmp v2c
 
54
my $o_descr =   undef;          # description filter 
 
55
my @o_descrL =  undef;          # Service descriprion list.
 
56
my $o_showall = undef;  # Show all services even if OK
 
57
my $o_type = "service"; # Check type (service, ...)
 
58
my $o_number = undef;  # Number of service for warn and crit levels
 
59
my $o_help=     undef;          # wan't some help ?
 
60
my $o_verb=     undef;          # verbose mode
 
61
my $o_version=   undef;         # print version
 
62
my $o_noreg=    undef;          # Do not use Regexp for name
 
63
my $o_timeout=  5;              # Default 5s Timeout
 
64
# SNMP V3 specific
 
65
my $o_login=    undef;          # snmp v3 login
 
66
my $o_passwd=   undef;          # snmp v3 passwd
 
67
 
 
68
# functions
 
69
 
 
70
sub p_version { print "$Name version : $Version\n"; }
 
71
 
 
72
sub print_usage {
 
73
    print "Usage: $Name [-v] -H <host> -C <snmp_community> [-2] | (-l login -x passwd) [-p <port>] -n <name>[,<name2] [-T=service] [-r] [-s] [-N=<n>] [-t <timeout>] [-V]\n";
 
74
}
 
75
 
 
76
sub isnotnum { # Return true if arg is not a number
 
77
  my $num = shift;
 
78
  if ( $num =~ /^-?(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;}
 
79
  return 1;
 
80
}
 
81
 
 
82
sub is_pattern_valid { # Test for things like "<I\s*[^>" or "+5-i"
 
83
 my $pat = shift;
 
84
 if (!defined($pat)) { $pat=" ";} # Just to get rid of compilation time warnings
 
85
 return eval { "" =~ /$pat/; 1 } || 0;
 
86
}
 
87
 
 
88
# Get the alarm signal (just in case snmp timout screws up)
 
89
$SIG{'ALRM'} = sub {
 
90
     print ("ERROR: Alarm signal (Nagios time-out)\n");
 
91
     exit $ERRORS{"UNKNOWN"};
 
92
};
 
93
 
 
94
sub help {
 
95
   print "\nSNMP Windows Monitor for Nagios version ",$Version,"\n";
 
96
   print "GPL licence, (c)2004-2005 Patrick Proy\n\n";
 
97
   print_usage();
 
98
   print <<EOT;
 
99
-v, --verbose
 
100
   print extra debugging information (and lists all services)
 
101
-h, --help
 
102
   print this help message
 
103
-H, --hostname=HOST
 
104
   name or IP address of host to check
 
105
-C, --community=COMMUNITY NAME
 
106
   community name for the host's SNMP agent (implies SNMP v1 or v2c with option)
 
107
-2, --v2c
 
108
   Use snmp v2c
 
109
-l, --login=LOGIN
 
110
   Login for snmpv3 authentication (implies v3 protocol with MD5)
 
111
-x, --passwd=PASSWD
 
112
   Password for snmpv3 authentication
 
113
-p, --port=PORT
 
114
   SNMP port (Default 161)
 
115
-T, --type=service
 
116
   Check type : 
 
117
     - service (default) checks service
 
118
-n, --name=NAME[,NAME2...]
 
119
   Comma separated names of services (perl regular expressions can be used for every one).
 
120
   By default, it is not case sensitive.
 
121
-N, --number=<n>
 
122
   Compare matching services with <n> instead of the number of names provided.
 
123
-s, --showall
 
124
   Show all services in the output, instead of only the non-active ones.
 
125
-r, --noregexp
 
126
   Do not use regexp to match NAME in service description.
 
127
-t, --timeout=INTEGER
 
128
   timeout for SNMP in seconds (Default: 5)
 
129
-V, --version
 
130
   prints version number
 
131
Note :   
 
132
  The script will return 
 
133
    OK if ALL services are in active state,
 
134
    WARNING if there is more than specified (ex 2 service specified, 3 active services matching), 
 
135
    CRITICAL if at least one of them is non active.
 
136
  The -n option will allows regexp in perl format 
 
137
  -n "service" will match 'service WINS' 'sevice DNS' etc...
 
138
  It is not case sensitive by default : WINS = wins
 
139
EOT
 
140
}
 
141
 
 
142
sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; }
 
143
 
 
144
sub decode_utf8 { # just replaces UFT8 caracters by "."
 
145
  my $utfstr=shift;
 
146
  if (substr($utfstr,0,2) ne "0x") { return $utfstr; }
 
147
  my @stringL=split(//,$utfstr);
 
148
  my $newstring="";
 
149
  for (my $i=2;$i<$#stringL;$i+=2) {
 
150
    if ( ($stringL[$i] . $stringL[$i+1]) eq "c3") {
 
151
          $i+=2;$newstring .= ".";
 
152
        } else {
 
153
          $newstring .= chr(hex($stringL[$i] . $stringL[$i+1]));
 
154
        }
 
155
  }
 
156
  return $newstring;
 
157
}
 
158
 
 
159
sub check_options {
 
160
    Getopt::Long::Configure ("bundling");
 
161
    GetOptions(
 
162
        'v'     => \$o_verb,            'verbose'       => \$o_verb,
 
163
        'h'     => \$o_help,            'help'          => \$o_help,
 
164
        'H:s'   => \$o_host,            'hostname:s'    => \$o_host,
 
165
        'p:i'   => \$o_port,            'port:i'        => \$o_port,
 
166
        'C:s'   => \$o_community,       'community:s'   => \$o_community,
 
167
        'l:s'   => \$o_login,           'login:s'       => \$o_login,
 
168
        'x:s'   => \$o_passwd,          'passwd:s'      => \$o_passwd,
 
169
        't:i'   => \$o_timeout,         'timeout:i'     => \$o_timeout,
 
170
        'n:s'   => \$o_descr,           'name:s'        => \$o_descr,
 
171
        'r'     => \$o_noreg,           'noregexp'      => \$o_noreg,
 
172
        'T:s'   => \$o_type,            'type:s'        => \$o_type,
 
173
        'N:i'   => \$o_number,          'number:i'      => \$o_number,
 
174
        '2'     => \$o_version2,        'v2c'           => \$o_version2,
 
175
        's'     => \$o_showall,         'showall'       => \$o_showall,  
 
176
        'V'     => \$o_version,         'version'       => \$o_version
 
177
    );
 
178
    if (defined ($o_help)) { help(); exit $ERRORS{"UNKNOWN"}};
 
179
    if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}};
 
180
    # check snmp information
 
181
    if ( !defined($o_community) && (!defined($o_login) || !defined($o_passwd)) )
 
182
        { print "Put snmp login info!\n"; print_usage(); exit $ERRORS{"UNKNOWN"}}
 
183
    # Check compulsory attributes
 
184
    if ( $o_type ne "service" ) {
 
185
      print "Invalid check type !\n"; print_usage(); exit $ERRORS{"UNKNOWN"} 
 
186
    }
 
187
    if ( ! defined($o_descr) ||  ! defined($o_host) ) { print_usage(); exit $ERRORS{"UNKNOWN"}};
 
188
    @o_descrL=split(/,/,$o_descr);      
 
189
    foreach my $List (@o_descrL) {
 
190
      if ( ! is_pattern_valid ($List) ) { print "Invalid pattern ! ";print_usage(); exit $ERRORS{"UNKNOWN"} }
 
191
    }
 
192
    if (defined ($o_number)) {
 
193
      if (isnotnum($o_number) || ($o_number<0) ) 
 
194
        { print "Invalid number of services!\n";print_usage(); exit $ERRORS{"UNKNOWN"}}
 
195
    }
 
196
 
 
197
}
 
198
 
 
199
########## MAIN #######
 
200
 
 
201
check_options();
 
202
 
 
203
# Check gobal timeout if snmp screws up
 
204
if (defined($TIMEOUT)) {
 
205
  verb("Alarm at $TIMEOUT");
 
206
  alarm($TIMEOUT);
 
207
} else {
 
208
  verb("no timeout defined : $o_timeout + 10");
 
209
  alarm ($o_timeout+10);
 
210
}
 
211
 
 
212
# Connect to host
 
213
my ($session,$error);
 
214
if ( defined($o_login) && defined($o_passwd)) {
 
215
  # SNMPv3 login
 
216
  verb("SNMPv3 login");
 
217
  ($session, $error) = Net::SNMP->session(
 
218
      -hostname         => $o_host,
 
219
      -version          => '3',
 
220
      -username         => $o_login,
 
221
      -authpassword     => $o_passwd,
 
222
      -authprotocol     => 'md5',
 
223
      -privpassword     => $o_passwd,
 
224
      -timeout          => $o_timeout
 
225
   );
 
226
} else {
 
227
  if (defined ($o_version2)) {
 
228
    # SNMPv2 Login
 
229
        ($session, $error) = Net::SNMP->session(
 
230
       -hostname  => $o_host,
 
231
           -version   => 2,
 
232
       -community => $o_community,
 
233
       -port      => $o_port,
 
234
       -timeout   => $o_timeout
 
235
    );
 
236
  } else {
 
237
  # SNMPV1 login
 
238
    ($session, $error) = Net::SNMP->session(
 
239
       -hostname  => $o_host,
 
240
       -community => $o_community,
 
241
       -port      => $o_port,
 
242
       -timeout   => $o_timeout
 
243
    );
 
244
  }
 
245
}
 
246
 
 
247
 
 
248
if (!defined($session)) {
 
249
   printf("ERROR: %s.\n", $error);
 
250
   exit $ERRORS{"UNKNOWN"};
 
251
}
 
252
 
 
253
$session->max_msg_size(5000);
 
254
verb($session->max_msg_size);
 
255
 
 
256
# Look for process in name or path name table
 
257
my $resultat=undef;
 
258
 
 
259
$resultat = (Net::SNMP->VERSION < 4) ? 
 
260
                $session->get_table($win_serv_name)
 
261
                : $session->get_table(Baseoid => $win_serv_name);
 
262
 
 
263
if (!defined($resultat)) {
 
264
   printf("ERROR: Process name table : %s.\n", $session->error);
 
265
   $session->close;
 
266
   exit $ERRORS{"UNKNOWN"};
 
267
}
 
268
 
 
269
my @tindex = undef;
 
270
my @oids = undef;
 
271
my @descr = undef;
 
272
my $num_int = 0;
 
273
my $count_oid = 0;
 
274
# Select storage by regexp of exact match
 
275
# and put the oid to query in an array
 
276
 
 
277
verb("Filter : $o_descr");
 
278
 
 
279
foreach my $key ( keys %$resultat) {
 
280
   my $descr_d=decode_utf8($$resultat{$key});
 
281
   verb("Desc : $descr_d");
 
282
   # test by regexp or exact match
 
283
   my $test=undef;
 
284
   foreach my $List (@o_descrL) {
 
285
     if (!($test)) {
 
286
            $test = defined($o_noreg)
 
287
                         ? $descr_d eq $List
 
288
                         : $descr_d =~ /$List/i;
 
289
     }
 
290
  }
 
291
  if ($test) {
 
292
      # get the full description
 
293
     $descr[$num_int]=$descr_d;
 
294
         # get the index number of the process
 
295
         $key =~ s/$win_serv_name\.//;
 
296
     $tindex[$num_int] = $key;
 
297
     # put the oid of running state in an array.
 
298
     $oids[$count_oid++]=$win_serv_state . "." . $tindex[$num_int];
 
299
     verb("Name : $descr[$num_int], Index : $tindex[$num_int]");
 
300
     $num_int++;
 
301
  }
 
302
}
 
303
 
 
304
if ( $num_int == 0) {
 
305
   if (defined ($o_number) && ($o_number ==0)) {
 
306
    print "No services ",(defined ($o_noreg)) ? "named \"" : "matching \"", $o_descr, "\" found : OK\n";
 
307
    exit $ERRORS{"OK"};
 
308
  } else  {
 
309
    print "No services ",(defined ($o_noreg)) ? "named \"" : "matching \"", $o_descr, "\" found : CRITICAL\n";
 
310
    exit $ERRORS{"CRITICAL"};
 
311
  }
 
312
}
 
313
 
 
314
my $result=undef;
 
315
my $num_int_ok=0;
 
316
 
 
317
$result = (Net::SNMP->VERSION < 4) ? 
 
318
    $session->get_request(@oids)
 
319
  : $session->get_request(Varbindlist => \@oids);
 
320
 
 
321
if (!defined($result)) { printf("ERROR: running table : %s.\n", $session->error); $session->close;
 
322
   exit $ERRORS{"UNKNOWN"};
 
323
}
 
324
 
 
325
$session->close;
 
326
 
 
327
my $output=undef;
 
328
#Check if service are in active state
 
329
for (my $i=0; $i< $num_int; $i++) {
 
330
   my $state=$$result{$win_serv_state . "." . $tindex[$i]};
 
331
   verb ("Process $tindex[$i] in state $state");
 
332
   if ($state == 1) {
 
333
     $num_int_ok++
 
334
   } else {
 
335
     $output .= ", " if defined($output);
 
336
     $output .= $descr[$i] . " : " . $win_serv_state_label{$state};
 
337
   }
 
338
}
 
339
 
 
340
my $force_critical=0;
 
341
 
 
342
# Show the services that are not present
 
343
# Or all of them with -s option
 
344
foreach my $List (@o_descrL) {
 
345
  my $test=0;
 
346
  for (my $i=0; $i< $num_int; $i++) {
 
347
    if ( $descr[$i] =~ /$List/i  ) { $test++; }
 
348
  }
 
349
  if ($test==0) {
 
350
    $output .= ", " if defined($output);
 
351
    $output .= "\"" . $List . "\" not active";
 
352
    # Force a critical state (could otherwise lead to false OK)
 
353
    $force_critical=1; 
 
354
  } elsif ( defined ($o_showall) ) {
 
355
    $output .= ", " if defined($output);
 
356
    $output .= "\"" . $List . "\" active";
 
357
    if ($test != 1) {
 
358
      $output .= "(" .$test . " services)";
 
359
    }
 
360
  }
 
361
}
 
362
 
 
363
if (defined ($output) ) {
 
364
  print $output, " : ";  
 
365
} else {
 
366
  print $num_int_ok, " services active (", (defined ($o_noreg)) ? "named \"" : "matching \"", $o_descr, "\") : ";
 
367
}
 
368
 
 
369
$o_number = $#o_descrL+1 if (!defined($o_number));
 
370
 
 
371
if (($num_int_ok < $o_number)||($force_critical == 1)) { 
 
372
        print "CRITICAL\n";
 
373
        exit $ERRORS{"CRITICAL"};
 
374
} elsif ($num_int_ok > $o_number) {
 
375
  print "WARNING\n";
 
376
  exit $ERRORS{"WARNING"};
 
377
}
 
378
print "OK\n";
 
379
exit $ERRORS{"OK"};
 
380
 
 
381