remove check_mac to own module, use in macsuck too
This commit is contained in:
@@ -3,15 +3,15 @@ package App::Netdisco::Core::Arpnip;
|
|||||||
use Dancer qw/:syntax :script/;
|
use Dancer qw/:syntax :script/;
|
||||||
use Dancer::Plugin::DBIC 'schema';
|
use Dancer::Plugin::DBIC 'schema';
|
||||||
|
|
||||||
use App::Netdisco::Util::PortMAC ':all';
|
use App::Netdisco::Util::PortMAC 'get_port_macs';
|
||||||
|
use App::Netdisco::Util::SanityCheck 'check_mac';
|
||||||
use App::Netdisco::Util::DNS ':all';
|
use App::Netdisco::Util::DNS ':all';
|
||||||
use NetAddr::IP::Lite ':lower';
|
use NetAddr::IP::Lite ':lower';
|
||||||
use Time::HiRes 'gettimeofday';
|
use Time::HiRes 'gettimeofday';
|
||||||
use Net::MAC;
|
|
||||||
|
|
||||||
use base 'Exporter';
|
use base 'Exporter';
|
||||||
our @EXPORT = ();
|
our @EXPORT = ();
|
||||||
our @EXPORT_OK = qw/ do_arpnip check_mac store_arp /;
|
our @EXPORT_OK = qw/ do_arpnip store_arp /;
|
||||||
our %EXPORT_TAGS = (all => \@EXPORT_OK);
|
our %EXPORT_TAGS = (all => \@EXPORT_OK);
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
@@ -82,91 +82,13 @@ sub _get_arps {
|
|||||||
while (my ($arp, $node) = each %$paddr) {
|
while (my ($arp, $node) = each %$paddr) {
|
||||||
my $ip = $netaddr->{$arp};
|
my $ip = $netaddr->{$arp};
|
||||||
next unless defined $ip;
|
next unless defined $ip;
|
||||||
push @arps, [$node, $ip, hostname_from_ip($ip)]
|
next unless check_mac($device, $node, $port_macs);
|
||||||
if check_mac($device, $node, $port_macs);
|
push @arps, [$node, $ip, hostname_from_ip($ip)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return @arps;
|
return @arps;
|
||||||
}
|
}
|
||||||
|
|
||||||
=head2 check_mac( $device, $node, $port_macs? )
|
|
||||||
|
|
||||||
Given a Device database object and a MAC address, perform various sanity
|
|
||||||
checks which need to be done before writing an ARP/Neighbor entry to the
|
|
||||||
database storage.
|
|
||||||
|
|
||||||
Returns false, and logs a debug level message, if the checks fail.
|
|
||||||
|
|
||||||
Returns a true value if these checks pass:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
MAC address is not malformed
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
MAC address is not broadcast, CLIP, VRRP or HSRP
|
|
||||||
|
|
||||||
=item *
|
|
||||||
|
|
||||||
MAC address does not belong to an interface on C<$device>
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
Optionally pass a cached set of Device port MAC addresses as the fourth
|
|
||||||
argument, or else C<check_mac> will retrieve this for itself from the
|
|
||||||
database.
|
|
||||||
|
|
||||||
=cut
|
|
||||||
|
|
||||||
sub check_mac {
|
|
||||||
my ($device, $node, $port_macs) = @_;
|
|
||||||
$port_macs ||= get_port_macs($device);
|
|
||||||
my $mac = Net::MAC->new(mac => $node, 'die' => 0, verbose => 0);
|
|
||||||
|
|
||||||
# incomplete MAC addresses (BayRS frame relay DLCI, etc)
|
|
||||||
if ($mac->get_error) {
|
|
||||||
debug sprintf ' [%s] arpnip - mac [%s] malformed - skipping',
|
|
||||||
$device->ip, $node;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
# lower case, hex, colon delimited, 8-bit groups
|
|
||||||
$node = lc $mac->as_IEEE;
|
|
||||||
}
|
|
||||||
|
|
||||||
# broadcast MAC addresses
|
|
||||||
return 0 if $node eq 'ff:ff:ff:ff:ff:ff';
|
|
||||||
|
|
||||||
# CLIP
|
|
||||||
return 0 if $node eq '00:00:00:00:00:01';
|
|
||||||
|
|
||||||
# VRRP
|
|
||||||
if (index($node, '00:00:5e:00:01:') == 0) {
|
|
||||||
debug sprintf ' [%s] arpnip - VRRP mac [%s] - skipping',
|
|
||||||
$device->ip, $node;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# HSRP
|
|
||||||
if (index($node, '00:00:0c:07:ac:') == 0) {
|
|
||||||
debug sprintf ' [%s] arpnip - HSRP mac [%s] - skipping',
|
|
||||||
$device->ip, $node;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# device's own MACs
|
|
||||||
if (exists $port_macs->{$node}) {
|
|
||||||
debug sprintf ' [%s] arpnip - mac [%s] is device port - skipping',
|
|
||||||
$device->ip, $node;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
=head2 store_arp( $mac, $ip, $name, $now? )
|
=head2 store_arp( $mac, $ip, $name, $now? )
|
||||||
|
|
||||||
Stores a new entry to the C<node_ip> table with the given MAC, IP (v4 or v6)
|
Stores a new entry to the C<node_ip> table with the given MAC, IP (v4 or v6)
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ package App::Netdisco::Core::Macsuck;
|
|||||||
use Dancer qw/:syntax :script/;
|
use Dancer qw/:syntax :script/;
|
||||||
use Dancer::Plugin::DBIC 'schema';
|
use Dancer::Plugin::DBIC 'schema';
|
||||||
|
|
||||||
use App::Netdisco::Util::PortMAC ':all';
|
use App::Netdisco::Util::PortMAC 'get_port_macs';
|
||||||
|
use App::Netdisco::Util::SanityCheck 'check_mac';
|
||||||
use App::Netdisco::Util::SNMP 'snmp_comm_reindex';
|
use App::Netdisco::Util::SNMP 'snmp_comm_reindex';
|
||||||
use Time::HiRes 'gettimeofday';
|
use Time::HiRes 'gettimeofday';
|
||||||
|
|
||||||
@@ -77,9 +78,9 @@ sub do_macsuck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# now it's time to call store_node for every node discovered
|
# now it's time to call store_node for every node discovered
|
||||||
# on every port on every vlan on every device.
|
# on every port on every vlan on this device.
|
||||||
|
|
||||||
# reverse sort allows vlan 0 entries to be added as fallback
|
# reverse sort allows vlan 0 entries to be included only as fallback
|
||||||
foreach my $vlan (reverse sort keys %$fwtable) {
|
foreach my $vlan (reverse sort keys %$fwtable) {
|
||||||
foreach my $port (keys %{ $fwtable->{$vlan} }) {
|
foreach my $port (keys %{ $fwtable->{$vlan} }) {
|
||||||
if ($device_ports->{$port}->is_uplink) {
|
if ($device_ports->{$port}->is_uplink) {
|
||||||
@@ -270,6 +271,7 @@ sub _walk_fwtable {
|
|||||||
|
|
||||||
while (my ($idx, $mac) = each %$fw_mac) {
|
while (my ($idx, $mac) = each %$fw_mac) {
|
||||||
my $bp_id = $fw_port->{$idx};
|
my $bp_id = $fw_port->{$idx};
|
||||||
|
next unless check_mac($device, $mac, $port_macs);
|
||||||
|
|
||||||
unless (defined $bp_id) {
|
unless (defined $bp_id) {
|
||||||
debug sprintf
|
debug sprintf
|
||||||
@@ -361,15 +363,6 @@ sub _walk_fwtable {
|
|||||||
next unless setting('macsuck_bleed');
|
next unless setting('macsuck_bleed');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($mac =~ /^([0-9a-f]{2}):/i and ($1 =~ /.(1|3|5|7|9|b|d|f)/i)) {
|
|
||||||
debug sprintf ' [%s] macsuck %s is multicast - skipping.',
|
|
||||||
$device->ip, $mac;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
|
|
||||||
next if $mac eq '00:00:00:00:00:00';
|
|
||||||
next if lc($mac) eq 'ff:ff:ff:ff:ff:ff';
|
|
||||||
|
|
||||||
++$cache->{$port}->{$mac};
|
++$cache->{$port}->{$mac};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
115
Netdisco/lib/App/Netdisco/Util/SanityCheck.pm
Normal file
115
Netdisco/lib/App/Netdisco/Util/SanityCheck.pm
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package App::Netdisco::Util::SanityCheck;
|
||||||
|
|
||||||
|
use Dancer qw/:syntax :script/;
|
||||||
|
use Dancer::Plugin::DBIC 'schema';
|
||||||
|
|
||||||
|
use App::Netdisco::Util::PortMAC ':all';
|
||||||
|
use Net::MAC;
|
||||||
|
|
||||||
|
use base 'Exporter';
|
||||||
|
our @EXPORT = ();
|
||||||
|
our @EXPORT_OK = qw/ check_mac /;
|
||||||
|
our %EXPORT_TAGS = (all => \@EXPORT_OK);
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
App::Netdisco::Util::SanityCheck
|
||||||
|
|
||||||
|
=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 check_mac( $device, $node, $port_macs? )
|
||||||
|
|
||||||
|
Given a Device database object and a MAC address, perform various sanity
|
||||||
|
checks which need to be done before writing an ARP/Neighbor entry to the
|
||||||
|
database storage.
|
||||||
|
|
||||||
|
Returns false, and might log a debug level message, if the checks fail.
|
||||||
|
|
||||||
|
Returns a true value if these checks pass:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item *
|
||||||
|
|
||||||
|
MAC address is well-formed (according to common formats)
|
||||||
|
|
||||||
|
=item *
|
||||||
|
|
||||||
|
MAC address is not all-zero, broadcast, CLIP, VRRP or HSRP
|
||||||
|
|
||||||
|
=item *
|
||||||
|
|
||||||
|
MAC address does not belong to an interface on any known Device
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
Optionally pass a cached set of Device port MAC addresses as the third
|
||||||
|
argument, or else C<check_mac> will retrieve this for itself from the
|
||||||
|
database.
|
||||||
|
|
||||||
|
=cut
|
||||||
|
|
||||||
|
sub check_mac {
|
||||||
|
my ($device, $node, $port_macs) = @_;
|
||||||
|
$port_macs ||= get_port_macs($device);
|
||||||
|
my $mac = Net::MAC->new(mac => $node, 'die' => 0, verbose => 0);
|
||||||
|
|
||||||
|
# incomplete MAC addresses (BayRS frame relay DLCI, etc)
|
||||||
|
if ($mac->get_error) {
|
||||||
|
debug sprintf ' [%s] check_mac - mac [%s] malformed - skipping',
|
||||||
|
$device->ip, $node;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# lower case, hex, colon delimited, 8-bit groups
|
||||||
|
$node = lc $mac->as_IEEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
# broadcast MAC addresses
|
||||||
|
return 0 if $node eq 'ff:ff:ff:ff:ff:ff';
|
||||||
|
|
||||||
|
# all-zero MAC addresses
|
||||||
|
return 0 if $node eq '00:00:00:00:00:00';
|
||||||
|
|
||||||
|
# CLIP
|
||||||
|
return 0 if $node eq '00:00:00:00:00:01';
|
||||||
|
|
||||||
|
# multicast
|
||||||
|
if ($node =~ m/^[0-9a-f](?:1|3|5|7|9|b|d|f):/) {
|
||||||
|
debug sprintf ' [%s] check_mac - multicast mac [%s] - skipping',
|
||||||
|
$device->ip, $node;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# VRRP
|
||||||
|
if (index($node, '00:00:5e:00:01:') == 0) {
|
||||||
|
debug sprintf ' [%s] check_mac - VRRP mac [%s] - skipping',
|
||||||
|
$device->ip, $node;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# HSRP
|
||||||
|
if (index($node, '00:00:0c:07:ac:') == 0) {
|
||||||
|
debug sprintf ' [%s] check_mac - HSRP mac [%s] - skipping',
|
||||||
|
$device->ip, $node;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# device's own MACs
|
||||||
|
if (exists $port_macs->{$node}) {
|
||||||
|
debug sprintf ' [%s] check_mac - mac [%s] is device port - skipping',
|
||||||
|
$device->ip, $node;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
Reference in New Issue
Block a user