1package App::Netdisco::SSHCollector::Platform::Linux; 2 3=head1 NAME 4 5App::Netdisco::SSHCollector::Platform::Linux 6 7=head1 DESCRIPTION 8 9Collect ARP entries from Linux routers 10 11This collector uses "C<arp>" as the command for the arp utility on your 12system. If you wish to specify an absolute path, then add an C<arp_command> 13item to your configuration: 14 15 device_auth: 16 - tag: sshlinux 17 driver: cli 18 platform: Linux 19 only: '192.0.2.1' 20 username: oliver 21 password: letmein 22 arp_command: '/usr/sbin/arp' 23 24=cut 25 26use strict; 27use warnings; 28 29use Dancer ':script'; 30use Expect; 31use Moo; 32 33=head1 PUBLIC METHODS 34 35=over 4 36 37=item B<arpnip($host, $ssh)> 38 39Retrieve ARP entries from device. C<$host> is the hostname or IP address 40of the device. C<$ssh> is a Net::OpenSSH connection to the device. 41 42Returns a list of hashrefs in the format C<{ mac =E<gt> MACADDR, ip =E<gt> IPADDR }>. 43 44=back 45 46=cut 47 48sub arpnip { 49 my ($self, $hostlabel, $ssh, $args) = @_; 50 51 debug "$hostlabel $$ arpnip()"; 52 53 my ($pty, $pid) = $ssh->open2pty; 54 unless ($pty) { 55 debug "unable to run remote command [$hostlabel] " . $ssh->error; 56 return (); 57 } 58 my $expect = Expect->init($pty); 59 60 my ($pos, $error, $match, $before, $after); 61 my $prompt = qr/\$/; 62 63 ($pos, $error, $match, $before, $after) = $expect->expect(10, -re, $prompt); 64 65 my $command = ($args->{arp_command} || 'arp'); 66 $expect->send("$command -n | tail -n +2\n"); 67 ($pos, $error, $match, $before, $after) = $expect->expect(5, -re, $prompt); 68 69 my @arpentries = (); 70 my @lines = split(m/\n/, $before); 71 72 # 192.168.1.1 ether 00:b6:aa:f5:bb:6e C eth1 73 my $linereg = qr/([0-9\.]+)\s+ether\s+([a-fA-F0-9:]+)/; 74 75 foreach my $line (@lines) { 76 if ($line =~ $linereg) { 77 my ($ip, $mac) = ($1, $2); 78 push @arpentries, { mac => $mac, ip => $ip }; 79 } 80 } 81 82 $expect->send("exit\n"); 83 $expect->soft_close(); 84 85 return @arpentries; 86} 87 881; 89