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::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 NetAddr::IP::Lite ':lower'; | ||||
| use Time::HiRes 'gettimeofday'; | ||||
| use Net::MAC; | ||||
|  | ||||
| use base 'Exporter'; | ||||
| 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); | ||||
|  | ||||
| =head1 NAME | ||||
| @@ -82,91 +82,13 @@ sub _get_arps { | ||||
|   while (my ($arp, $node) = each %$paddr) { | ||||
|       my $ip = $netaddr->{$arp}; | ||||
|       next unless defined $ip; | ||||
|       push @arps, [$node, $ip, hostname_from_ip($ip)] | ||||
|         if check_mac($device, $node, $port_macs); | ||||
|       next unless check_mac($device, $node, $port_macs); | ||||
|       push @arps, [$node, $ip, hostname_from_ip($ip)]; | ||||
|   } | ||||
|  | ||||
|   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? ) | ||||
|  | ||||
| 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::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 Time::HiRes 'gettimeofday'; | ||||
|  | ||||
| @@ -77,9 +78,9 @@ sub do_macsuck { | ||||
|   } | ||||
|  | ||||
|   # 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 $port (keys %{ $fwtable->{$vlan} }) { | ||||
|           if ($device_ports->{$port}->is_uplink) { | ||||
| @@ -270,6 +271,7 @@ sub _walk_fwtable { | ||||
|  | ||||
|   while (my ($idx, $mac) = each %$fw_mac) { | ||||
|       my $bp_id = $fw_port->{$idx}; | ||||
|       next unless check_mac($device, $mac, $port_macs); | ||||
|  | ||||
|       unless (defined $bp_id) { | ||||
|           debug sprintf | ||||
| @@ -361,15 +363,6 @@ sub _walk_fwtable { | ||||
|           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}; | ||||
|   } | ||||
|  | ||||
|   | ||||
							
								
								
									
										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