aboutsummaryrefslogtreecommitdiff
path: root/contrib/check_wins.pl
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/check_wins.pl')
-rwxr-xr-xcontrib/check_wins.pl248
1 files changed, 248 insertions, 0 deletions
diff --git a/contrib/check_wins.pl b/contrib/check_wins.pl
new file mode 100755
index 00000000..58a597aa
--- /dev/null
+++ b/contrib/check_wins.pl
@@ -0,0 +1,248 @@
+#!/usr/bin/perl -w
+
+# $Id$
+
+# $Log$
+# Revision 1.1 2003/02/09 14:16:28 sghosh
+# more contribs
+#
+
+use strict ;
+
+use Getopt::Long ;
+use vars qw($opt_H $opt_D $opt_W $opt_T $debug @my_dcs);
+
+use lib '/usr/local/netsaint/libexec/' ;
+use utils qw($TIMEOUT %ERRORS &print_revision &support &usage);
+
+my $PROGNAME = 'check_wins' ;
+
+use constant SAMBA_DEBUG_LVL => 2 ;
+use constant MY_DCS => ('dc1','dc2') ;
+# use constant MY_DCS => qw(ipa01 ipa02 ipa03) ;
+
+my $NMBLOOKUP_PATH = '/usr/bin/nmblookup' ;
+my $NMBLOOKUP = sub { return `$NMBLOOKUP_PATH $_[2] -R -U $_[0] $_[1]` } ;
+my $NMBLOOKUP_CMD = $NMBLOOKUP_PATH . ' -R -U' ;
+
+sub print_help ();
+sub print_usage ();
+sub help ();
+sub version ();
+
+delete @ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
+
+$SIG{"ALRM"} = sub { die "Alarm clock restart" } ;
+
+Getopt::Long::Configure('bundling', 'no_ignore_case');
+GetOptions
+ ("V|version" => \&version,
+ "h|help" => \&help,
+ "d|debug" => \$debug,
+ "C|controllers:s" => \@my_dcs,
+ "T|timeout:i" => \$opt_T,
+ "W|wins=s" => \$opt_W,
+ "D|domain=s" => \$opt_D);
+
+
+($opt_D) || usage("MS Domain name not specified\n");
+my $domain = $1 if $opt_D =~ m#(\w+)# ; # NetBIOS names allow __any__ characters (more than \w)
+($domain) || usage("Invalid MS D name: $opt_D\n");
+
+($opt_W) || usage("WINS hostname or address not specified\n");
+my $wins = $1 if $opt_W =~ m#((?:^\w+$)|(?:\d+(?:\.\d+){3,3}$))# ;
+($wins) || usage("Invalid WINS hostname or address: $opt_W\n");
+
+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")
+ unless (@my_dcs or MY_DCS) ;
+
+@my_dcs = MY_DCS unless defined $my_dcs[0] ;
+$TIMEOUT = $opt_T if defined $opt_T ;
+
+my ($netbios_name, @dcs_of_domain, @dc_addresses) ;
+my (@addr_dcs_of_domain, @found_dcs, %address2dc) ;
+my (@dc_query) ;
+
+# tsitc> /usr/local/samba/bin/nmblookup -R -U wins ipa01
+# Sending queries to 10.0.100.29
+# 10.0.100.16 ipa01<00>
+
+eval {
+ alarm($TIMEOUT) ;
+ @dc_query = $debug ? map { $NMBLOOKUP->($wins, "$_#20", '-d ' . SAMBA_DEBUG_LVL) } @my_dcs :
+ map { ( $NMBLOOKUP->($wins, "$_#20", '') )[1] } @my_dcs ;
+ alarm(0) ;
+} ;
+
+if ($@ and $@ =~ /Alarm clock restart/) {
+ print qq(Failed. Timeout while waiting for response from (one of) "$NMBLOOKUP_CMD $wins @my_dcs"\n) ;
+ exit $ERRORS{"CRITICAL"} ;
+}
+
+if ($@ and $@ !~ /Alarm clock restart/) {
+ print qq(Failed. "$@" in response to "NMBLOOKUP_CMD $wins @my_dcs"\n) ;
+ exit $ERRORS{"UNKNOWN"} ;
+}
+
+chomp @dc_query ;
+if ( scalar grep(/name_query failed/, @dc_query) ) {
+ 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) ;
+ exit $ERRORS{"CRITICAL"} ;
+}
+
+# the results of looking up the DCs (by their name) in the WINS
+
+# 10.0.100.16 ipa01<20>
+# 10.0.100.1 ipa02<20>
+# 10.0.100.104 ipa03<20>
+
+@dc_addresses = () ;
+foreach (@dc_query) {
+ next unless /^(\S+)\s+(\S+?)<\S+?>$/ ;
+ $address2dc{$1} = $2 ;
+ push @dc_addresses, $1 ;
+}
+
+$netbios_name = "$domain#1C" ;
+
+eval {
+ alarm($TIMEOUT) ;
+ @dcs_of_domain = $NMBLOOKUP->($wins, $netbios_name, defined $debug ? '-d ' . SAMBA_DEBUG_LVL : '') ;
+ alarm(0) ;
+
+} ;
+
+if ($@ and $@ =~ /Alarm clock restart/) {
+ print qq(Failed. Timeout while waiting for response from "$NMBLOOKUP_CMD $wins $netbios_name"\n) ;
+ exit $ERRORS{"CRITICAL"} ;
+}
+
+if ($@ and $@ !~ /Alarm clock restart/) {
+ print qq(Failed. "$@" in response to "$NMBLOOKUP_CMD $wins $netbios_name"\n) ;
+ exit $ERRORS{"UNKNOWN"} ;
+}
+
+shift @dcs_of_domain ;
+chomp @dcs_of_domain ;
+@addr_dcs_of_domain = map /^(\S+)/, @dcs_of_domain ;
+
+# tsitc> /usr/local/samba/bin/nmblookup -R -U wins ipaustralia#1c
+# Sending queries to 10.0.100.29
+# 10.0.100.114 ipaustralia<1c>
+# 168.168.102.129 ipaustralia<1c>
+# 192.168.101.221 ipaustralia<1c>
+# 10.0.100.61 ipaustralia<1c>
+# 192.168.108.129 ipaustralia<1c>
+# 192.168.102.128 ipaustralia<1c>
+# 10.0.4.126 ipaustralia<1c>
+# 192.168.106.214 ipaustralia<1c>
+# 10.0.3.165 ipaustralia<1c>
+# 192.168.105.214 ipaustralia<1c>
+# 10.0.6.145 ipaustralia<1c>
+# 192.168.104.128 ipaustralia<1c>
+# 10.0.4.59 ipaustralia<1c>
+# 10.9.99.99 ipaustralia<1c>
+# 10.99.99.99 ipaustralia<1c>
+# 10.9.99.254 ipaustralia<1c>
+# 10.0.3.15 ipaustralia<1c>
+# 192.168.102.129 ipaustralia<1c>
+# 192.168.103.129 ipaustralia<1c>
+# 192.168.105.129 ipaustralia<1c>
+# 192.168.106.129 ipaustralia<1c>
+# 192.168.101.129 ipaustralia<1c>
+# 192.168.104.129 ipaustralia<1c>
+# 10.0.3.123 ipaustralia<1c>
+# 10.0.100.67 ipaustralia<1c>
+# tsitc>
+
+my %x ;
+@found_dcs = grep { ! $x{$_}++ } @address2dc{ grep exists $address2dc{$_}, @addr_dcs_of_domain} ;
+# @found_dcs = grep { defined $_} @address2dc{ grep exists $address2dc{$_}, @addr_dcs_of_domain} ;
+ # Gotcha.
+ # 'exists' is necessary to prevent autovivificatiton
+ # of keys in %address2dc
+
+if ( &set_eq( \@found_dcs, [ values %address2dc ] ) ) {
+ 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) :
+ qq(Ok. Found controllers named "@my_dcs" in response to "$domain#1C" name query from WINS named "$wins".\n) ;
+ exit $ERRORS{"OK"} ;
+} elsif ( scalar @found_dcs == 0 ) {
+ print qq(Failed. Found __no__ controllers named "@my_dcs" in response to "$domain#1C" query from WINS named "$wins". Got "@dcs_of_domain"\n) ;
+ exit $ERRORS{"CRITICAL"} ;
+} elsif ( scalar @found_dcs < scalar keys %address2dc ) {
+ 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) ;
+ exit $ERRORS{"WARNING"} ;
+}
+
+sub set_eq {
+
+ return 0 unless scalar @{$_[0]} == scalar @{$_[1]} ;
+ foreach my $a ( @{$_[0]} ) {
+ return 0 unless scalar grep { $a eq $_ } @{$_[1]} ;
+ }
+ return 1 ;
+
+}
+
+
+sub print_usage () {
+ print "Usage: $PROGNAME -W <wins> -D <domain>\n";
+}
+
+sub print_help () {
+ print_revision($PROGNAME,'$Revision$ ');
+ print "Copyright (c) 2001 Karl DeBisschop/S Hopcroft
+
+Perl Check WINS plugin for NetSaint.
+
+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'
+
+Why would you want to do this ?
+
+MS File server clients insist on connecting to file servers using NetBIOS names.
+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
+broadcast requsts for names.
+Both problems are eliminated by a healthy WINS.
+Also, you may have a MS domain spanning a number of WAN connected sites, with domain controllers far away from powerful local
+domain controllers.
+In this case, you want your local clients to have their logon requests validated by the local controllers.
+
+The plugin works by
+ asking the WINS to resolve the addresses of the domain controllers (supplied by -C or from the constant MY_DCS)
+ asking the WINS to return the list of addresses of the domain controllers able to validate requests for the domain
+ whose name is given by -D
+ returning Ok if all controller addresses are in that list (of addresses of domain controllers) or
+ returning WARNING if not all the controller addresses are in the list or
+ returning CRITICAL if there is no reply from the WINS or the list contains none of the contoller addresses
+
+";
+ print_usage();
+ print '
+-W, --wins=STRING
+ Hostname or address of the WINS (Either Samba/nmbd or MS product)
+-D, --domain=STRING
+ MS Domain name to find the Domain controllers of.
+-C, --controllers:STRING
+ Optional __name(s)__ of domain controller that __must__ be found in the response to a domain controller name query.
+ If not defined, then use the constant value MY_DCS. You must use either -C or make sure that MY_DCS contains the names
+ of __your__ domain controllers.
+-T, --timeout:INTEGER
+-d, --debug
+ Debugging output.
+-h, --help
+ This stuff.
+
+';
+ support();
+}
+
+sub version () {
+ print_revision($PROGNAME,'$Revision$ ');
+ exit $ERRORS{'OK'};
+}
+
+sub help () {
+ print_help();
+ exit $ERRORS{'OK'};
+}
+