diff options
Diffstat (limited to 'contrib/check_wins.pl')
| -rwxr-xr-x | contrib/check_wins.pl | 248 |
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 @@ | |||
| 1 | #!/usr/bin/perl -w | ||
| 2 | |||
| 3 | # $Id$ | ||
| 4 | |||
| 5 | # $Log$ | ||
| 6 | # Revision 1.1 2003/02/09 14:16:28 sghosh | ||
| 7 | # more contribs | ||
| 8 | # | ||
| 9 | |||
| 10 | use strict ; | ||
| 11 | |||
| 12 | use Getopt::Long ; | ||
| 13 | use vars qw($opt_H $opt_D $opt_W $opt_T $debug @my_dcs); | ||
| 14 | |||
| 15 | use lib '/usr/local/netsaint/libexec/' ; | ||
| 16 | use utils qw($TIMEOUT %ERRORS &print_revision &support &usage); | ||
| 17 | |||
| 18 | my $PROGNAME = 'check_wins' ; | ||
| 19 | |||
| 20 | use constant SAMBA_DEBUG_LVL => 2 ; | ||
| 21 | use constant MY_DCS => ('dc1','dc2') ; | ||
| 22 | # use constant MY_DCS => qw(ipa01 ipa02 ipa03) ; | ||
| 23 | |||
| 24 | my $NMBLOOKUP_PATH = '/usr/bin/nmblookup' ; | ||
| 25 | my $NMBLOOKUP = sub { return `$NMBLOOKUP_PATH $_[2] -R -U $_[0] $_[1]` } ; | ||
| 26 | my $NMBLOOKUP_CMD = $NMBLOOKUP_PATH . ' -R -U' ; | ||
| 27 | |||
| 28 | sub print_help (); | ||
| 29 | sub print_usage (); | ||
| 30 | sub help (); | ||
| 31 | sub version (); | ||
| 32 | |||
| 33 | delete @ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; | ||
| 34 | |||
| 35 | $SIG{"ALRM"} = sub { die "Alarm clock restart" } ; | ||
| 36 | |||
| 37 | Getopt::Long::Configure('bundling', 'no_ignore_case'); | ||
| 38 | GetOptions | ||
| 39 | ("V|version" => \&version, | ||
| 40 | "h|help" => \&help, | ||
| 41 | "d|debug" => \$debug, | ||
| 42 | "C|controllers:s" => \@my_dcs, | ||
| 43 | "T|timeout:i" => \$opt_T, | ||
| 44 | "W|wins=s" => \$opt_W, | ||
| 45 | "D|domain=s" => \$opt_D); | ||
| 46 | |||
| 47 | |||
| 48 | ($opt_D) || usage("MS Domain name not specified\n"); | ||
| 49 | my $domain = $1 if $opt_D =~ m#(\w+)# ; # NetBIOS names allow __any__ characters (more than \w) | ||
| 50 | ($domain) || usage("Invalid MS D name: $opt_D\n"); | ||
| 51 | |||
| 52 | ($opt_W) || usage("WINS hostname or address not specified\n"); | ||
| 53 | my $wins = $1 if $opt_W =~ m#((?:^\w+$)|(?:\d+(?:\.\d+){3,3}$))# ; | ||
| 54 | ($wins) || usage("Invalid WINS hostname or address: $opt_W\n"); | ||
| 55 | |||
| 56 | 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") | ||
| 57 | unless (@my_dcs or MY_DCS) ; | ||
| 58 | |||
| 59 | @my_dcs = MY_DCS unless defined $my_dcs[0] ; | ||
| 60 | $TIMEOUT = $opt_T if defined $opt_T ; | ||
| 61 | |||
| 62 | my ($netbios_name, @dcs_of_domain, @dc_addresses) ; | ||
| 63 | my (@addr_dcs_of_domain, @found_dcs, %address2dc) ; | ||
| 64 | my (@dc_query) ; | ||
| 65 | |||
| 66 | # tsitc> /usr/local/samba/bin/nmblookup -R -U wins ipa01 | ||
| 67 | # Sending queries to 10.0.100.29 | ||
| 68 | # 10.0.100.16 ipa01<00> | ||
| 69 | |||
| 70 | eval { | ||
| 71 | alarm($TIMEOUT) ; | ||
| 72 | @dc_query = $debug ? map { $NMBLOOKUP->($wins, "$_#20", '-d ' . SAMBA_DEBUG_LVL) } @my_dcs : | ||
| 73 | map { ( $NMBLOOKUP->($wins, "$_#20", '') )[1] } @my_dcs ; | ||
| 74 | alarm(0) ; | ||
| 75 | } ; | ||
| 76 | |||
| 77 | if ($@ and $@ =~ /Alarm clock restart/) { | ||
| 78 | print qq(Failed. Timeout while waiting for response from (one of) "$NMBLOOKUP_CMD $wins @my_dcs"\n) ; | ||
| 79 | exit $ERRORS{"CRITICAL"} ; | ||
| 80 | } | ||
| 81 | |||
| 82 | if ($@ and $@ !~ /Alarm clock restart/) { | ||
| 83 | print qq(Failed. "$@" in response to "NMBLOOKUP_CMD $wins @my_dcs"\n) ; | ||
| 84 | exit $ERRORS{"UNKNOWN"} ; | ||
| 85 | } | ||
| 86 | |||
| 87 | chomp @dc_query ; | ||
| 88 | if ( scalar grep(/name_query failed/, @dc_query) ) { | ||
| 89 | 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) ; | ||
| 90 | exit $ERRORS{"CRITICAL"} ; | ||
| 91 | } | ||
| 92 | |||
| 93 | # the results of looking up the DCs (by their name) in the WINS | ||
| 94 | |||
| 95 | # 10.0.100.16 ipa01<20> | ||
| 96 | # 10.0.100.1 ipa02<20> | ||
| 97 | # 10.0.100.104 ipa03<20> | ||
| 98 | |||
| 99 | @dc_addresses = () ; | ||
| 100 | foreach (@dc_query) { | ||
| 101 | next unless /^(\S+)\s+(\S+?)<\S+?>$/ ; | ||
| 102 | $address2dc{$1} = $2 ; | ||
| 103 | push @dc_addresses, $1 ; | ||
| 104 | } | ||
| 105 | |||
| 106 | $netbios_name = "$domain#1C" ; | ||
| 107 | |||
| 108 | eval { | ||
| 109 | alarm($TIMEOUT) ; | ||
| 110 | @dcs_of_domain = $NMBLOOKUP->($wins, $netbios_name, defined $debug ? '-d ' . SAMBA_DEBUG_LVL : '') ; | ||
| 111 | alarm(0) ; | ||
| 112 | |||
| 113 | } ; | ||
| 114 | |||
| 115 | if ($@ and $@ =~ /Alarm clock restart/) { | ||
| 116 | print qq(Failed. Timeout while waiting for response from "$NMBLOOKUP_CMD $wins $netbios_name"\n) ; | ||
| 117 | exit $ERRORS{"CRITICAL"} ; | ||
| 118 | } | ||
| 119 | |||
| 120 | if ($@ and $@ !~ /Alarm clock restart/) { | ||
| 121 | print qq(Failed. "$@" in response to "$NMBLOOKUP_CMD $wins $netbios_name"\n) ; | ||
| 122 | exit $ERRORS{"UNKNOWN"} ; | ||
| 123 | } | ||
| 124 | |||
| 125 | shift @dcs_of_domain ; | ||
| 126 | chomp @dcs_of_domain ; | ||
| 127 | @addr_dcs_of_domain = map /^(\S+)/, @dcs_of_domain ; | ||
| 128 | |||
| 129 | # tsitc> /usr/local/samba/bin/nmblookup -R -U wins ipaustralia#1c | ||
| 130 | # Sending queries to 10.0.100.29 | ||
| 131 | # 10.0.100.114 ipaustralia<1c> | ||
| 132 | # 168.168.102.129 ipaustralia<1c> | ||
| 133 | # 192.168.101.221 ipaustralia<1c> | ||
| 134 | # 10.0.100.61 ipaustralia<1c> | ||
| 135 | # 192.168.108.129 ipaustralia<1c> | ||
| 136 | # 192.168.102.128 ipaustralia<1c> | ||
| 137 | # 10.0.4.126 ipaustralia<1c> | ||
| 138 | # 192.168.106.214 ipaustralia<1c> | ||
| 139 | # 10.0.3.165 ipaustralia<1c> | ||
| 140 | # 192.168.105.214 ipaustralia<1c> | ||
| 141 | # 10.0.6.145 ipaustralia<1c> | ||
| 142 | # 192.168.104.128 ipaustralia<1c> | ||
| 143 | # 10.0.4.59 ipaustralia<1c> | ||
| 144 | # 10.9.99.99 ipaustralia<1c> | ||
| 145 | # 10.99.99.99 ipaustralia<1c> | ||
| 146 | # 10.9.99.254 ipaustralia<1c> | ||
| 147 | # 10.0.3.15 ipaustralia<1c> | ||
| 148 | # 192.168.102.129 ipaustralia<1c> | ||
| 149 | # 192.168.103.129 ipaustralia<1c> | ||
| 150 | # 192.168.105.129 ipaustralia<1c> | ||
| 151 | # 192.168.106.129 ipaustralia<1c> | ||
| 152 | # 192.168.101.129 ipaustralia<1c> | ||
| 153 | # 192.168.104.129 ipaustralia<1c> | ||
| 154 | # 10.0.3.123 ipaustralia<1c> | ||
| 155 | # 10.0.100.67 ipaustralia<1c> | ||
| 156 | # tsitc> | ||
| 157 | |||
| 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 | ||
| 164 | |||
| 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"} ; | ||
| 175 | } | ||
| 176 | |||
| 177 | sub set_eq { | ||
| 178 | |||
| 179 | return 0 unless scalar @{$_[0]} == scalar @{$_[1]} ; | ||
| 180 | foreach my $a ( @{$_[0]} ) { | ||
| 181 | return 0 unless scalar grep { $a eq $_ } @{$_[1]} ; | ||
| 182 | } | ||
| 183 | return 1 ; | ||
| 184 | |||
| 185 | } | ||
| 186 | |||
| 187 | |||
| 188 | sub print_usage () { | ||
| 189 | print "Usage: $PROGNAME -W <wins> -D <domain>\n"; | ||
| 190 | } | ||
| 191 | |||
| 192 | sub print_help () { | ||
| 193 | print_revision($PROGNAME,'$Revision$ '); | ||
| 194 | print "Copyright (c) 2001 Karl DeBisschop/S Hopcroft | ||
| 195 | |||
| 196 | Perl Check WINS plugin for NetSaint. | ||
| 197 | |||
| 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' | ||
| 199 | |||
| 200 | Why would you want to do this ? | ||
| 201 | |||
| 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. | ||
| 209 | |||
| 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 | ||
| 217 | |||
| 218 | "; | ||
| 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. | ||
| 234 | |||
| 235 | '; | ||
| 236 | support(); | ||
| 237 | } | ||
| 238 | |||
| 239 | sub version () { | ||
| 240 | print_revision($PROGNAME,'$Revision$ '); | ||
| 241 | exit $ERRORS{'OK'}; | ||
| 242 | } | ||
| 243 | |||
| 244 | sub help () { | ||
| 245 | print_help(); | ||
| 246 | exit $ERRORS{'OK'}; | ||
| 247 | } | ||
| 248 | |||
