parse_ini now reads the default section if the request one can't be found.
[monitoring-plugins.git] / contrib / check_wins.pl
blob0d11737f3054efdd9d03c74a98530760d18538ca
1 #!/usr/bin/perl -w
3 # $Id$
5 # $Log$
6 # Revision 1.3 2004/11/25 04:46:16 stanleyhopcroft
7 # Non functional tidy ups to check_wins
9 # Revision 1.2 2003/08/20 08:31:49 tonvoon
10 # Changed netsaint to nagios in use lib
12 # Revision 1.1 2003/02/09 14:16:28 sghosh
13 # more contribs
16 use strict ;
18 use Getopt::Long ;
19 use vars qw($opt_H $opt_D $opt_W $opt_T $debug @my_dcs);
21 use lib '/usr/local/nagios/libexec/' ;
22 use utils qw($TIMEOUT %ERRORS &print_revision &support &usage);
24 my $PROGNAME = 'check_wins' ;
26 use constant SAMBA_DEBUG_LVL => 2 ;
27 use constant MY_DCS => ('dc1','dc2') ;
29 my $NMBLOOKUP_PATH = '/usr/bin/nmblookup' ;
30 my $NMBLOOKUP = sub { return `$NMBLOOKUP_PATH $_[2] -R -U $_[0] $_[1]` } ;
31 my $NMBLOOKUP_CMD = $NMBLOOKUP_PATH . ' -R -U' ;
33 sub print_help ();
34 sub print_usage ();
35 sub help ();
36 sub version ();
38 delete @ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
40 $SIG{"ALRM"} = sub { die "Alarm clock restart" } ;
42 Getopt::Long::Configure('bundling', 'no_ignore_case');
43 GetOptions
44 ("V|version" => \&version,
45 "h|help" => \&help,
46 "d|debug" => \$debug,
47 "C|controllers:s" => \@my_dcs,
48 "T|timeout:i" => \$opt_T,
49 "W|wins=s" => \$opt_W,
50 "D|domain=s" => \$opt_D);
53 ($opt_D) || usage("MS Domain name not specified\n");
54 my $domain = $1 if $opt_D =~ m#(\w+)# ; # NetBIOS names allow __any__ characters (more than \w)
55 ($domain) || usage("Invalid MS D name: $opt_D\n");
57 ($opt_W) || usage("WINS hostname or address not specified\n");
58 my $wins = $1 if $opt_W =~ m#((?:^\w+$)|(?:\d+(?:\.\d+){3,3}$))# ;
59 ($wins) || usage("Invalid WINS hostname or address: $opt_W\n");
61 usage("You must provide the names of your domain controllers by updating MY_DCS in the text or use -C dc_name1 -C dc_name2 ..\n")
62 unless (@my_dcs or MY_DCS) ;
64 @my_dcs = MY_DCS unless defined $my_dcs[0] ;
65 $TIMEOUT = $opt_T if defined $opt_T ;
67 my ($netbios_name, @dcs_of_domain, @dc_addresses) ;
68 my (@addr_dcs_of_domain, @found_dcs, %address2dc) ;
69 my (@dc_query) ;
71 # tsitc> /usr/local/samba/bin/nmblookup -R -U wins ipa01
72 # Sending queries to 192.168.1.29
73 # 192.168.1.16 ipa01<00>
75 eval {
76 alarm($TIMEOUT) ;
77 @dc_query = $debug ? map { $NMBLOOKUP->($wins, "$_#20", '-d ' . SAMBA_DEBUG_LVL) } @my_dcs :
78 map { ( $NMBLOOKUP->($wins, "$_#20", '') )[1] } @my_dcs ;
79 alarm(0) ;
80 } ;
82 if ($@ and $@ =~ /Alarm clock restart/) {
83 print qq(Failed. Timeout while waiting for response from (one of) "$NMBLOOKUP_CMD $wins @my_dcs"\n) ;
84 exit $ERRORS{"CRITICAL"} ;
87 if ($@ and $@ !~ /Alarm clock restart/) {
88 print qq(Failed. "$@" in response to "NMBLOOKUP_CMD $wins @my_dcs"\n) ;
89 exit $ERRORS{"UNKNOWN"} ;
92 chomp @dc_query ;
93 if ( scalar grep(/name_query failed/, @dc_query) ) {
94 print qq(Failed. WINS "$wins" failed to resolve), scalar @my_dcs > 1 ? ' at least one of ' : ' ', qq("@my_dcs", the domain controller(s) of "$domain". Got "@dc_query"\n) ;
95 exit $ERRORS{"CRITICAL"} ;
98 =begin comment
100 the results of looking up the DCs (by their name) in the WINS
102 192.168.1.16 ipa01<20>
103 192.168.1.1 ipa02<20>
104 192.168.1.104 ipa03<20>
106 =end comment
108 =cut
110 @dc_addresses = () ;
111 foreach (@dc_query) {
112 next unless /^(\S+)\s+(\S+?)<\S+?>$/ ;
113 $address2dc{$1} = $2 ;
114 push @dc_addresses, $1 ;
117 $netbios_name = "$domain#1C" ;
119 eval {
120 alarm($TIMEOUT) ;
121 @dcs_of_domain = $NMBLOOKUP->($wins, $netbios_name, defined $debug ? '-d ' . SAMBA_DEBUG_LVL : '') ;
122 alarm(0) ;
126 if ($@ and $@ =~ /Alarm clock restart/) {
127 print qq(Failed. Timeout while waiting for response from "$NMBLOOKUP_CMD $wins $netbios_name"\n) ;
128 exit $ERRORS{"CRITICAL"} ;
131 if ($@ and $@ !~ /Alarm clock restart/) {
132 print qq(Failed. "$@" in response to "$NMBLOOKUP_CMD $wins $netbios_name"\n) ;
133 exit $ERRORS{"UNKNOWN"} ;
136 shift @dcs_of_domain ;
137 chomp @dcs_of_domain ;
138 @addr_dcs_of_domain = map /^(\S+)/, @dcs_of_domain ;
140 =begin comment
142 tsitc> /usr/local/samba/bin/nmblookup -R -U wins ipaustralia#1c
143 Sending queries to 192.168.1.29
144 192.168.1.114 ipaustralia<1c>
145 192.168.1.221 ipaustralia<1c>
146 192.168.1.61 ipaustralia<1c>
147 192.168.1.129 ipaustralia<1c>
148 192.168.1.128 ipaustralia<1c>
149 192.168.1.214 ipaustralia<1c>
150 192.168.1.67 ipaustralia<1c>
151 tsitc>
153 =end comment
155 =cut
158 my %x ;
159 @found_dcs = grep { ! $x{$_}++ } @address2dc{ grep exists $address2dc{$_}, @addr_dcs_of_domain} ;
160 # @found_dcs = grep { defined $_} @address2dc{ grep exists $address2dc{$_}, @addr_dcs_of_domain} ;
161 # Gotcha.
162 # 'exists' is necessary to prevent autovivificatiton
163 # of keys in %address2dc
165 if ( &set_eq( \@found_dcs, [ values %address2dc ] ) ) {
166 print $debug ? qq(Ok. WINS named "$wins" resolved addresses of "@my_dcs" as "@dc_query" and controllers of domain "$domain" as "@dcs_of_domain"\n) :
167 qq(Ok. Found controllers named "@my_dcs" in response to "$domain#1C" name query from WINS named "$wins".\n) ;
168 exit $ERRORS{"OK"} ;
169 } elsif ( scalar @found_dcs == 0 ) {
170 print qq(Failed. Found __no__ controllers named "@my_dcs" in response to "$domain#1C" query from WINS named "$wins". Got "@dcs_of_domain"\n) ;
171 exit $ERRORS{"CRITICAL"} ;
172 } elsif ( scalar @found_dcs < scalar keys %address2dc ) {
173 print qq(Warning. Not all domain controllers found in response to "$domain#1C" query from WINS named "$wins". Expected "@my_dcs", got "@found_dcs"\n) ;
174 exit $ERRORS{"WARNING"} ;
177 sub set_eq {
179 return 0 unless scalar @{$_[0]} == scalar @{$_[1]} ;
180 foreach my $a ( @{$_[0]} ) {
181 return 0 unless scalar grep { $a eq $_ } @{$_[1]} ;
183 return 1 ;
188 sub print_usage () {
189 print "Usage: $PROGNAME -W <wins> -D <domain>\n";
192 sub print_help () {
193 print_revision($PROGNAME,'$Revision$ ');
194 print "Copyright (c) 2001 Karl DeBisschop/S Hopcroft
196 Perl Check WINS plugin for NetSaint.
198 Returns OK if the addresses of domain controllers are found in the list of domain controllers returned in the WINS response to a 'domain controllers query'
200 Why would you want to do this ?
202 MS File server clients insist on connecting to file servers using NetBIOS names.
203 If they __don't__ resolve NetBIOS names with a WINS (NBNS) then they'll either fail to logon and connect to shares or they will
204 broadcast requsts for names.
205 Both problems are eliminated by a healthy WINS.
206 Also, you may have a MS domain spanning a number of WAN connected sites, with domain controllers far away from powerful local
207 domain controllers.
208 In this case, you want your local clients to have their logon requests validated by the local controllers.
210 The plugin works by
211 asking the WINS to resolve the addresses of the domain controllers (supplied by -C or from the constant MY_DCS)
212 asking the WINS to return the list of addresses of the domain controllers able to validate requests for the domain
213 whose name is given by -D
214 returning Ok if all controller addresses are in that list (of addresses of domain controllers) or
215 returning WARNING if not all the controller addresses are in the list or
216 returning CRITICAL if there is no reply from the WINS or the list contains none of the contoller addresses
219 print_usage();
220 print '
221 -W, --wins=STRING
222 Hostname or address of the WINS (Either Samba/nmbd or MS product)
223 -D, --domain=STRING
224 MS Domain name to find the Domain controllers of.
225 -C, --controllers:STRING
226 Optional __name(s)__ of domain controller that __must__ be found in the response to a domain controller name query.
227 If not defined, then use the constant value MY_DCS. You must use either -C or make sure that MY_DCS contains the names
228 of __your__ domain controllers.
229 -T, --timeout:INTEGER
230 -d, --debug
231 Debugging output.
232 -h, --help
233 This stuff.
236 support();
239 sub version () {
240 print_revision($PROGNAME,'$Revision$ ');
241 exit $ERRORS{'OK'};
244 sub help () {
245 print_help();
246 exit $ERRORS{'OK'};