Asynchronous NBTstat
This commit is contained in:
@@ -5,11 +5,11 @@ use Dancer::Plugin::DBIC 'schema';
|
||||
|
||||
use App::Netdisco::Util::Node 'check_mac';
|
||||
use NetAddr::IP::Lite ':lower';
|
||||
use Net::NBName;
|
||||
use App::Netdisco::AnyEvent::Nbtstat;
|
||||
|
||||
use base 'Exporter';
|
||||
our @EXPORT = ();
|
||||
our @EXPORT_OK = qw/ do_nbtstat store_nbt /;
|
||||
our @EXPORT_OK = qw/ nbtstat_resolve_async store_nbt /;
|
||||
our %EXPORT_TAGS = (all => \@EXPORT_OK);
|
||||
|
||||
=head1 NAME
|
||||
@@ -25,42 +25,64 @@ subroutines.
|
||||
|
||||
=head1 EXPORT_OK
|
||||
|
||||
=head2 do_nbtstat( $node )
|
||||
=head2 nbtstat_resolve_async( $ips )
|
||||
|
||||
Connects to node and gets NetBIOS information. Then adds entries to
|
||||
node_nbt table.
|
||||
This method uses an asynchronous AnyEvent NetBIOS node status requester
|
||||
C<App::Netdisco::AnyEvent::Nbtstat>.
|
||||
|
||||
Returns whether a node is answering netbios calls or not.
|
||||
Given a reference to an array of hashes will connects to the C<IPv4> of a
|
||||
node and gets NetBIOS node status information.
|
||||
|
||||
Returns the supplied reference to an array of hashes with MAC address,
|
||||
NetBIOS name, NetBIOS domain/workgroup, NetBIOS user, and NetBIOS server
|
||||
service status for addresses which responded.
|
||||
|
||||
=cut
|
||||
|
||||
sub do_nbtstat {
|
||||
my ($host, $now) = @_;
|
||||
my $ip = NetAddr::IP::Lite->new($host) or return;
|
||||
sub nbtstat_resolve_async {
|
||||
my $ips = shift;
|
||||
|
||||
unless ( $ip->version() == 4 ) {
|
||||
debug ' nbtstat only supports IPv4, invalid ip %s', $ip->addr;
|
||||
return;
|
||||
my $timeout = setting('nbtstat_timeout') || 1;
|
||||
my $interval = setting('nbtstat_interval') || 0.02;
|
||||
|
||||
my $stater = App::Netdisco::AnyEvent::Nbtstat->new(
|
||||
timeout => $timeout,
|
||||
interval => $interval
|
||||
);
|
||||
|
||||
# Set up the condvar
|
||||
my $cv = AE::cv;
|
||||
$cv->begin( sub { shift->send } );
|
||||
|
||||
foreach my $hash_ref (@$ips) {
|
||||
my $ip = $hash_ref->{'ip'};
|
||||
$cv->begin;
|
||||
$stater->nbtstat(
|
||||
$ip,
|
||||
sub {
|
||||
my $res = shift;
|
||||
_filter_nbname( $ip, $hash_ref, $res );
|
||||
$cv->end;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
my $nb = Net::NBName->new;
|
||||
my $ns = $nb->node_status( $ip->addr );
|
||||
# Decrement the cv counter to cancel out the send declaration
|
||||
$cv->end;
|
||||
|
||||
# Check for NetBIOS Info
|
||||
return unless $ns;
|
||||
# Wait for the resolver to perform all resolutions
|
||||
$cv->recv;
|
||||
|
||||
my $nbname = _filter_nbname( $ip->addr, $ns );
|
||||
# Close sockets
|
||||
undef $stater;
|
||||
|
||||
if ($nbname) {
|
||||
store_nbt($nbname, $now);
|
||||
}
|
||||
|
||||
return 1;
|
||||
return $ips;
|
||||
}
|
||||
|
||||
# filter nbt names / information
|
||||
sub _filter_nbname {
|
||||
my $ip = shift;
|
||||
my $hash_ref = shift;
|
||||
my $node_status = shift;
|
||||
|
||||
my $server = 0;
|
||||
@@ -68,10 +90,10 @@ sub _filter_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 : '';
|
||||
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;
|
||||
@@ -88,11 +110,11 @@ sub _filter_nbname {
|
||||
}
|
||||
|
||||
unless ($nbname) {
|
||||
debug ' nbtstat no computer name found for %s', $ip;
|
||||
debug sprintf ' nbtstat no computer name found for %s', $ip;
|
||||
return;
|
||||
}
|
||||
|
||||
my $mac = $node_status->mac_address || '';
|
||||
my $mac = $node_status->{'mac_address'} || '';
|
||||
|
||||
unless ( check_mac( $ip, $mac ) ) {
|
||||
|
||||
@@ -101,23 +123,23 @@ sub _filter_nbname {
|
||||
->single( { ip => $ip, -bool => 'active' } );
|
||||
|
||||
if ( !defined $node_ip ) {
|
||||
debug ' no MAC for %s returned by nbtstat or in DB', $ip;
|
||||
debug sprintf ' 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
|
||||
};
|
||||
$hash_ref->{'ip'} = $ip;
|
||||
$hash_ref->{'mac'} = $mac;
|
||||
$hash_ref->{'nbname'} = $nbname;
|
||||
$hash_ref->{'domain'} = $domain;
|
||||
$hash_ref->{'server'} = $server;
|
||||
$hash_ref->{'nbuser'} = $nbuser;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
=head2 store_nbt($nb_hash_ref, $now?)
|
||||
=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
|
||||
|
||||
Reference in New Issue
Block a user