[#73] NetBIOS Poller - nbtstat and nbtwalk
This commit is contained in:
159
Netdisco/lib/App/Netdisco/Core/Nbtstat.pm
Normal file
159
Netdisco/lib/App/Netdisco/Core/Nbtstat.pm
Normal file
@@ -0,0 +1,159 @@
|
||||
package App::Netdisco::Core::Nbtstat;
|
||||
|
||||
use Dancer qw/:syntax :script/;
|
||||
use Dancer::Plugin::DBIC 'schema';
|
||||
|
||||
use App::Netdisco::Util::SanityCheck 'check_mac';
|
||||
use NetAddr::IP::Lite ':lower';
|
||||
use Time::HiRes 'gettimeofday';
|
||||
use Net::NBName;
|
||||
|
||||
use base 'Exporter';
|
||||
our @EXPORT = ();
|
||||
our @EXPORT_OK = qw/ do_nbtstat store_nbt /;
|
||||
our %EXPORT_TAGS = (all => \@EXPORT_OK);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
App::Netdisco::Core::Nbtstat
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Helper subroutines to support parts of the Netdisco application.
|
||||
|
||||
There are no default exports, however the C<:all> tag will export all
|
||||
subroutines.
|
||||
|
||||
=head1 EXPORT_OK
|
||||
|
||||
=head2 do_nbtstat( $node )
|
||||
|
||||
Connects to node and gets NetBIOS information. Then adds entries to
|
||||
node_nbt table.
|
||||
|
||||
Returns whether a node is answering netbios calls or not.
|
||||
|
||||
=cut
|
||||
|
||||
sub do_nbtstat {
|
||||
my $host = shift;
|
||||
|
||||
my $ip = NetAddr::IP::Lite->new($host) or return;
|
||||
|
||||
unless ( $ip->version() == 4 ) {
|
||||
debug ' nbtstat only supports IPv4, invalid ip %s', $ip->addr;
|
||||
return;
|
||||
}
|
||||
|
||||
my $nb = Net::NBName->new;
|
||||
|
||||
my $ns = $nb->node_status( $ip->addr );
|
||||
|
||||
# Check for NetBIOS Info
|
||||
return unless $ns;
|
||||
|
||||
my $nbname = _filter_nbname( $ip->addr, $ns );
|
||||
|
||||
if ($nbname) {
|
||||
store_nbt($nbname);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# filter nbt names / information
|
||||
sub _filter_nbname {
|
||||
my $ip = shift;
|
||||
my $node_status = shift;
|
||||
|
||||
my $server = 0;
|
||||
my $nbname = '';
|
||||
my $domain = '';
|
||||
my $nbuser = '';
|
||||
|
||||
for my $rr ( $node_status->names ) {
|
||||
my $suffix = defined $rr->suffix ? $rr->suffix : -1;
|
||||
my $G = defined $rr->G ? $rr->G : '';
|
||||
my $name = defined $rr->name ? $rr->name : '';
|
||||
|
||||
if ( $suffix == 0 and $G eq "GROUP" ) {
|
||||
$domain = $name;
|
||||
}
|
||||
if ( $suffix == 3 and $G eq "UNIQUE" ) {
|
||||
$nbuser = $name;
|
||||
}
|
||||
if ( $suffix == 0 and $G eq "UNIQUE" ) {
|
||||
$nbname = $name unless $name =~ /^IS~/;
|
||||
}
|
||||
if ( $suffix == 32 and $G eq "UNIQUE" ) {
|
||||
$server = 1;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($nbname) {
|
||||
debug ' nbtstat no computer name found for %s', $ip;
|
||||
return;
|
||||
}
|
||||
|
||||
my $mac = $node_status->mac_address || '';
|
||||
|
||||
unless ( check_mac( $ip, $mac ) ) {
|
||||
|
||||
# Just assume it's the last MAC we saw this IP at.
|
||||
my $node_ip = schema('netdisco')->resultset('NodeIp')
|
||||
->single( { ip => $ip, active => \'true' } );
|
||||
|
||||
if ( !defined $node_ip ) {
|
||||
debug ' no MAC for %s returned by nbtstat or in DB', $ip;
|
||||
return;
|
||||
}
|
||||
$mac = $node_ip->mac;
|
||||
}
|
||||
|
||||
return {
|
||||
ip => $ip,
|
||||
mac => $mac,
|
||||
nbname => $nbname,
|
||||
domain => $domain,
|
||||
server => $server,
|
||||
nbuser => $nbuser
|
||||
};
|
||||
}
|
||||
|
||||
=item store_nbt($nb_hash_ref, $now?)
|
||||
|
||||
Stores entries in C<node_nbt> table from the provided hash reference; MAC
|
||||
C<mac>, IP C<ip>, Unique NetBIOS Node Name C<nbname>, NetBIOS Domain or
|
||||
Workgroup C<domain>, whether the Server Service is running C<server>,
|
||||
and the current NetBIOS user C<nbuser>.
|
||||
|
||||
Adds new entry or time stamps matching one.
|
||||
|
||||
Optionally a literal string can be passed in the second argument for the
|
||||
C<time_last> timestamp, otherwise the current timestamp (C<now()>) is used.
|
||||
|
||||
=cut
|
||||
|
||||
sub store_nbt {
|
||||
my ( $hash_ref, $now ) = @_;
|
||||
$now ||= 'now()';
|
||||
|
||||
schema('netdisco')->resultset('NodeNbt')->update_or_create(
|
||||
{ mac => $hash_ref->{'mac'},
|
||||
ip => $hash_ref->{'ip'},
|
||||
nbname => $hash_ref->{'nbname'},
|
||||
domain => $hash_ref->{'domain'},
|
||||
server => $hash_ref->{'server'},
|
||||
nbuser => $hash_ref->{'nbuser'},
|
||||
active => \'true',
|
||||
time_last => \$now,
|
||||
},
|
||||
{ key => 'primary',
|
||||
for => 'update',
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user