ACC SHELL
#!/usr/bin/perl -w
# Copyright (c) 2003-2004 SuSE Linux AG, Nuernberg, Germany.
# All rights reserved.
#
# $Id: nmbstatus,v 1.11 2003/07/29 14:11:44 lmuelle Exp $
#
# Author: Lars Mueller <lmuelle@suse.de>
# Günther Deschner <gd@suse.de> (minor fixes)
use strict;
use warnings;
use Getopt::Long;
use Pod::Usage;
use File::Basename;
my $basename = basename( $0);
my $nmblookup = '/usr/bin/nmblookup';
my $opts = '-d0 2> /dev/null';
my $workgroup = '';
my ($winsServer,$allworkgroups,$seperator,$quiet,$help,$man);
# set defaults
my ($pdc,$bdc,$dmb,$lmb,$members) = ( 0, 0, 0, 0, 0);
my $debuglevel = 3;
GetOptions (
'winsserver|U=s' => \$winsServer,
'workgroup|w=s' => \$workgroup,
'pdc|p' => \$pdc,
'bdc' => \$bdc,
'dmb|d' => \$dmb,
'lmb' => \$lmb,
'members' => \$members,
'allworkgroups' => \$allworkgroups,
'print0' => \$seperator,
'quiet' => \$quiet,
'debuglevel=i' => \$debuglevel,
'help' => \$help,
'man' => \$man,
) or pod2usage(2);
pod2usage(1) if $help;
pod2usage(-exitstatus => 0, -verbose => 2) if $man;
sub debug {
if ($debuglevel >= $_[0]) {
print STDERR "$_[1]";
return( 1);
}
return( 0);
}
# check syntax
if ( $quiet) {
unless ( $workgroup) {
debug( 3, "$basename: Syntax error. You must set a workgroup.\n");
exit 3;
}
my $count = $pdc + $bdc + $lmb + $dmb + $members;
# more than one option choosen
if ( $count > 1) {
debug( 3, "$basename: Syntax error. Only one option is valid.\n");
debug( 3, "You must choose one between pdc, bdc, dmb, lmb, and members.\n");
exit 3;
}
# none option choosen
if ( $count == 0) {
debug( 3, "$basename: Syntax error. Option missing for quiet mode.\n");
debug( 3, "You must choose one between pdc, bdc, dmb, lmb, and members.\n");
exit 3;
}
}
# always upper case the workgroup name
$workgroup = uc( $workgroup);
my %ipAddrsList;
my %workGroups;
my %workGroupsPDC;
my %workGroupsBDC;
my %workGroupsDMB;
my %workGroupsLMB;
my %workGroupsMEM;
open ( NMBLOOKUP, "$nmblookup '*' $opts | ") || die "Can't run $nmblookup '*'\n";
%ipAddrsList = map {$_, 1} grep(s/ \*<00>.*$//s,<NMBLOOKUP>);
close( NMBLOOKUP);
# check if we're root
my $nmblookupOpt = '';
$nmblookupOpt .= ' -r' if ( !$<);
# did we know a WINS server
$nmblookupOpt .= " -U $winsServer -R" if ( $winsServer);
# set output seperator
if ( $seperator) {
$seperator = "\0";
} else {
$seperator = "\t";
}
print STDERR "Found " . keys( %ipAddrsList) . " hosts. Collecting additional information. Please wait.\n" unless ( $quiet);
my $progress = 0;
foreach my $ipAddrs ( keys %ipAddrsList) {
debug( 15, "$basename: ipAddrs<$ipAddrs>\n");
print STDERR "." unless ( $quiet);
my $primaryHostName = undef;
my $currWorkgroup = undef;
my $domainController = undef;
my $domainMaster = undef;
my $localMaster = undef;
my @hostNames = ();
open ( NMBLOOKUP, "$nmblookup $nmblookupOpt -A '$ipAddrs' $opts | ") || die "Can't run $nmblookup -A\n";
while (<NMBLOOKUP>) {
next unless my ($name, $state, $group) = /^\t(.{15}) <([0-9a-z]{2})> - .(.{5})/;
$name =~ s/\s*$//;
next if $name eq "..__MSBROWSE__." || $name eq "INet~Services" || $name =~ /^IS~/;
debug( 20, "$basename: name<$name> state<$state> group<$group>\n");
if ($name && ($group ne 'GROUP' && $state eq '00')) {
# store the first host name we get
$primaryHostName = $name unless ( $primaryHostName);
debug( 20, "$basename: computer found name<$name>\n");
# store a hostname in a list
push( @hostNames, $name);
next;
}
if ($name && ($group eq 'GROUP' || $state eq '1b' || $state eq '1d')) {
last if ( $workgroup ne '' && $name ne $workgroup);
$currWorkgroup = $name unless ( $currWorkgroup);
debug( 20, "$basename: currWorkgroup<$currWorkgroup>\n");
}
next unless defined($currWorkgroup);
if ( $state eq '1c') {
# this is a DC
$domainController = 1;
debug( 15, "$basename: DC found for workgroup <$currWorkgroup>\n");
} elsif ( $state eq '1b') {
# this is a DMB
$domainMaster = 1;
debug( 15, "$basename: DMB found for workgroup <$currWorkgroup>\n");
} elsif ( $state eq '1d') {
# this is a LMB
$localMaster = 1;
debug( 15, "$basename: LMB found for workgroup <$currWorkgroup>\n");
}
}
close( NMBLOOKUP);
unless ($primaryHostName) {
my ($name, $aliases, $type, $length, @addresses) = gethostbyaddr(pack('C4',split('\.',$ipAddrs)),2);
$name ||= "unknown";
$primaryHostName = $name || "unknown";
push @hostNames, $name;
debug( 5, "$basename: nis name $name\n");
}
open(SMB,"smbclient -L '$primaryHostName' -I '$ipAddrs' -N --debuglevel=1 2>&1 |")
|| die("Can't do smbclient command.\n");
my @smb = grep {s/^Domain=\[(.*)] OS=\[.*$/$1/s} <SMB>;
close SMB;
if (@smb) {
$currWorkgroup = $smb[0];
} else {
next;
}
debug( 15, "$basename: currWorkgroup<$currWorkgroup> primaryHostName<$primaryHostName>\n");
$workGroups{$currWorkgroup} = 1;
if ( $domainController && $domainMaster) {
# it's a PDC
$workGroupsPDC{$currWorkgroup} .= $seperator if ( $workGroupsPDC{$currWorkgroup});
$workGroupsPDC{$currWorkgroup} .= $primaryHostName;
} elsif ( $domainController) {
# it's a BDC
$workGroupsBDC{$currWorkgroup} .= $seperator if ( $workGroupsBDC{$currWorkgroup});
$workGroupsBDC{$currWorkgroup} .= $primaryHostName;
}
if ($domainMaster) {
# this is a DMB
$workGroupsDMB{$currWorkgroup} .= $seperator if ( $workGroupsLMB{$currWorkgroup});
$workGroupsDMB{$currWorkgroup} .= $primaryHostName if ( $primaryHostName );
}
if ($localMaster) {
# this is a LMB
$workGroupsLMB{$currWorkgroup} .= $seperator if ( $workGroupsLMB{$currWorkgroup});
$workGroupsLMB{$currWorkgroup} .= $primaryHostName if ( $primaryHostName );
}
if ( @hostNames) {
$workGroupsMEM{$currWorkgroup} .= $seperator if ( $workGroupsMEM{$currWorkgroup});
$workGroupsMEM{$currWorkgroup} .= join( "$seperator", @hostNames);
}
}
print STDERR "\n" unless ( $quiet);
# undef workgroup if empty
$workgroup = undef if ( $workgroup eq '');
# show all data we found or only one workgroup
my @displayWorkgroups = ();
if ( $quiet || defined($workgroup)) {
@displayWorkgroups = $workgroup;
} else {
@displayWorkgroups = keys %workGroups;
}
if ( $pdc + $bdc + $dmb + $lmb + $members == 0 && !defined( $allworkgroups)) {
$pdc = 1;
$bdc = 1;
$dmb = 1;
$lmb = 1;
$members = 1;
}
sub printWorkgroup {
my ($localWorkgroup, $shown) = @_;
return if ( $shown && ${$shown});
# only display the workgroup name if not set on the command line
print "WORKGROUP$seperator" if ( !defined $workgroup && !defined $allworkgroups);
print "$localWorkgroup\n" unless ( $workgroup);
${$shown} = 1;
}
if ( $quiet) {
exit 0 if ( $pdc > 0 && $workGroupsPDC{$workgroup});
exit 0 if ( $bdc > 0 && $workGroupsBDC{$workgroup});
exit 0 if ( $dmb > 0 && $workGroupsDMB{$workgroup});
exit 0 if ( $lmb > 0 && $workGroupsLMB{$workgroup});
exit 0 if ( $members >0 && $workGroupsMEM{$workgroup});
exit 1;
} else {
my $newLine = undef;
foreach my $currWorkgroup ( sort @displayWorkgroups) {
my $workgroupShown = undef;
my $count = $pdc + $bdc + $dmb + $lmb + $members;
print "\n" if ( $newLine);
$newLine = undef;
if ( $allworkgroups) {
printWorkgroup( $currWorkgroup);
next;
}
if ( $pdc > 0) {
$count--;
if ( $workGroupsPDC{$currWorkgroup}) {
printWorkgroup( $currWorkgroup, \$workgroupShown);
print "PDC$seperator$workGroupsPDC{$currWorkgroup}\n";
$newLine = 1;
} elsif ( $workgroup && $count < 1) {
exit 1;
}
}
if ( $bdc > 0) {
$count--;
if ( $workGroupsBDC{$currWorkgroup}) {
printWorkgroup( $currWorkgroup, \$workgroupShown);
print "BDC$seperator$workGroupsBDC{$currWorkgroup}\n";
$newLine = 1;
} elsif ( $workgroup && $count < 1) {
exit 1;
}
}
if ( $dmb > 0) {
$count--;
if ( $workGroupsDMB{$currWorkgroup}) {
printWorkgroup( $currWorkgroup, \$workgroupShown);
print "DMB$seperator$workGroupsDMB{$currWorkgroup}\n";
$newLine = 1;
} elsif ( $workgroup && $count < 1) {
exit 1;
}
}
if ( $lmb > 0) {
$count--;
if ( $workGroupsLMB{$currWorkgroup}) {
printWorkgroup( $currWorkgroup, \$workgroupShown);
print "LMB$seperator$workGroupsLMB{$currWorkgroup}\n";
$newLine = 1;
} elsif ( $workgroup && $count < 1) {
exit 1;
}
}
if ( $members > 0) {
$count--;
if ( $workGroupsMEM{$currWorkgroup}) {
printWorkgroup( $currWorkgroup, \$workgroupShown);
print "MEMBERS$seperator$workGroupsMEM{$currWorkgroup}\n" ;
$newLine = 1;
} elsif ( $workgroup && $count < 1) {
exit 1;
}
}
}
}
__END__
=head1 NAME
B<nmbstatus> - Lists NMB node status of a UDP network
=head1 SYNOPSIS
nmbstatus [options]
Options:
--workgroup
--pdc
--bdc
--lmb
--dmb
--members
--quiet
--allworkgroups
--winsserver
--print0
--debug
--help
--man
=head1 GENERAL OPTIONS
=over 8
=item B<--help>
Print a brief help message and exits.Prints a help message.
=item B<--man>
Print the manual page and exit.
=item B<--print0>
Use '\0' instead of a tab stop as seperator between the output.
=item B<--debug>
Use an debuglevel. No debuglevel available yet.
=head1 GENERAL ARGUMENTS
=item B<--workgroup>
Perform all actions on this workgroup name. If no workgroup is set the
information off all available groups is shown.
=item B<--pdc>
If not called in conjunction with B<--quiet> print a line starting with the
acronym PDC followed by the seperator and the netbios name of the PDC if one is
available. If not print nothing and return with 1.
=item B<--bdc>
If not called in conjunction with B<--quiet> print a line starting with the
acronym BDC followed by the seperator and the netbios name of the BDC if one is
available. If not print nothing and return with 1.
=item B<--dmb>
If not called in conjunction with B<--quiet> print a line starting with the
acronym DMB followed by the seperator and the netbios name of the DMB if one is
available. If not print nothing and return with 1.
=item B<--lmb>
If not called in conjunction with B<--quiet> print a line starting with the
acronym LMB followed by the seperator and the netbios name of the LMB if one is
available. If not print nothing and return with 1.
=item B<--members>
If not called in conjunction with B<--quiet> print a line starting with the
word MEMBERS followed by the seperator and the netbios names of the workgroup
members. If not print nothing and return with 1.
=item B<--quiet>
Don't print any information. Just return with 0 if a type - pdc, lmb, dmb, or
members was found. Else return 1.
=item B<--allworkgroups>
List all available workgroups.
=item B<--winsserver>
Use this WINS server to gather the information.
=back
=head1 DESCRIPTION
B<nmbstatus> will detect workgroups, PDCs, BDCs, DMBs, LMBs, and Members of
workgroups in your network.
If more than one type is specizied but only one result found, B<nmbstatus>
nevertheless returns 0.
=head1 AUTHOR
Lars Mueller <lmuelle@suse.de>
If you find any errors in the code please let me know.
=head1 COPYRIGHT
Copyright (c) 2003-2004 SuSE Linux AG. All rights reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
=cut
ACC SHELL 2018