register_worker({
phase
=>
'main'
,
driver
=>
'snmp'
},
sub
{
my
(
$job
,
$workerconf
) =
@_
;
my
$device
=
$job
->device;
my
$snmp
= App::Netdisco::Transport::SNMP->reader_for(
$device
)
or
return
Status->defer(
"arpnip failed: could not SNMP connect to $device"
);
my
@subnets
= gather_subnets(
$device
);
my
$now
=
'to_timestamp('
. (
join
'.'
, gettimeofday) .
')::timestamp'
;
store_subnet(
$_
,
$now
)
for
@subnets
;
return
Status->info(
sprintf
' [%s] arpnip - processed %s Subnet entries'
,
$device
->ip,
scalar
@subnets
);
});
sub
gather_subnets {
my
$device
=
shift
;
my
@subnets
= ();
my
$snmp
= App::Netdisco::Transport::SNMP->reader_for(
$device
)
or
return
();
my
$ip_netmask
=
$snmp
->ip_netmask;
foreach
my
$entry
(
keys
%$ip_netmask
) {
my
$ip
= NetAddr::IP::Lite->new(
$entry
) or
next
;
my
$addr
=
$ip
->addr;
next
if
$addr
eq
'0.0.0.0'
;
next
if
acl_matches(
$ip
,
'group:__LOOPBACK_ADDRESSES__'
);
next
if
setting(
'ignore_private_nets'
) and
$ip
->is_rfc1918;
my
$netmask
=
$ip_netmask
->{
$addr
} ||
$ip
->bits();
next
if
$netmask
eq
'255.255.255.255'
or
$netmask
eq
'0.0.0.0'
;
my
$cidr
= NetAddr::IP::Lite->new(
$addr
,
$netmask
)->network->cidr;
debug
sprintf
' [%s] arpnip - found subnet %s'
,
$device
->ip,
$cidr
;
push
@subnets
,
$cidr
;
}
return
@subnets
;
}
sub
store_subnet {
my
(
$subnet
,
$now
) =
@_
;
schema(
'netdisco'
)->txn_do(
sub
{
schema(
'netdisco'
)->resultset(
'Subnet'
)->update_or_create(
{
net
=>
$subnet
,
last_discover
=> \
$now
,
},
{
for
=>
'update'
});
});
}
true;