diff --git a/Netdisco/Changes b/Netdisco/Changes index e0cb297f..5df8415f 100644 --- a/Netdisco/Changes +++ b/Netdisco/Changes @@ -2,8 +2,9 @@ [ENHANCEMENTS] - * Add systemd guide - * Add environment variable for https reverse proxy (B. Marshall) + * systemd deployment guide + * document env var for https reverse proxy (B. Marshall) + * FreeBSD sshcollector support (H. Teulahti) [BUG FIXES] diff --git a/Netdisco/bin/netdisco-sshcollector b/Netdisco/bin/netdisco-sshcollector index e958cc70..d57b66fb 100755 --- a/Netdisco/bin/netdisco-sshcollector +++ b/Netdisco/bin/netdisco-sshcollector @@ -184,6 +184,8 @@ Currently, ARP tables can be retrieved from the following device classes: =item * L - F5 Networks BigIP +=item * L - FreeBSD + =item * L - Cisco IOS =item * L - Cisco IOS XR diff --git a/Netdisco/lib/App/Netdisco/SSHCollector/Platform/FreeBSD.pm b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/FreeBSD.pm new file mode 100644 index 00000000..bf7cf255 --- /dev/null +++ b/Netdisco/lib/App/Netdisco/SSHCollector/Platform/FreeBSD.pm @@ -0,0 +1,80 @@ +package App::Netdisco::SSHCollector::Platform::FreeBSD; + +=head1 NAME + +App::Netdisco::SSHCollector::Platform::FreeBSD + +=head1 DESCRIPTION + +Collect ARP entries from FreeBSD routers. + +This collector uses "C" as the command for the arp utility on your +system. If you wish to specify an absolute path, then add an C +item to your configuration: + + sshcollector: + - ip: '192.0.2.1' + user: oliver + password: letmein + platform: FreeBSD + arp_command: '/usr/sbin/arp' + +=cut + +use strict; +use warnings; + +use Dancer ':script'; +use Expect; +use Moo; + +=head1 PUBLIC METHODS + +=over 4 + +=item B + +Retrieve ARP entries from device. C<$host> is the hostname or IP address +of the device. C<$ssh> is a Net::OpenSSH connection to the device. + +Returns a list of hashrefs in the format C<{ mac => MACADDR, ip => IPADDR }>. + +=cut + +sub arpnip { + my ($self, $hostlabel, $ssh, $args) = @_; + + debug "$hostlabel $$ arpnip()"; + + my ($pty, $pid) = $ssh->open2pty or die "unable to run remote command"; + my $expect = Expect->init($pty); + + my ($pos, $error, $match, $before, $after); + my $prompt = qr/\$/; + + ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt); + + my $command = ($args->{arp_command} || 'arp'); + $expect->send("$command -n -a\n"); + ($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt); + + my @arpentries = (); + my @lines = split(m/\n/, $before); + + # ? (192.0.2.1) at fe:ed:de:ad:be:ef on igb0_vlan2 expires in 658 seconds [vlan] + my $linereg = qr/\s+\((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\)\s+at\s+([a-fA-F0-9:]{17})\s+on/; + + foreach my $line (@lines) { + if ($line =~ $linereg) { + my ($ip, $mac) = ($1, $2); + push @arpentries, { mac => $mac, ip => $ip }; + } + } + + $expect->send("exit\n"); + $expect->soft_close(); + + return @arpentries; +} + +1;