#!/usr/bin/perl -w # # Finds MAC-IP association for each tcpdump entry in a captured # interface and prints them. Will also print the vendor # information if a suitable Ethercodes file is found. # # (c) 2004 Javier Fernández-Sanguino Peña - Germinus XXI, S.A. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # # This software is distributed under the GPL license, please # read the license at http://www.gnu/org/licences/licenses.html#TOCGPL # Run with: # # /usr/sbin/tcpdump -enni ethX -c XXXX | find-mac.pl # # Where XXXX is the maximum number of packets you want to process. # # Sample tcpdump line: # 14:34:11.275823 0:e0:b6:4:xx:xx 0:4f:4e:a:xx:xx 0800 60: x.y.z.w.QQQQ > a.b.c.d.PPPP # TODO: # - If $MAXMAC limit is crossed, the MAC is reported # as "multiple" (possibly a router) # # Should be customizable # TODO: Not yet used # $MAXMAC = 10; $ETHERCODES="/usr/share/arpwatch/ethercodes.dat"; if ( ! -e $ETHERCODES ) { print STDERR "WARN: Ethercodes file '$ETHERCODES' not found, will not look for vendor"; } while ($line = ) { chomp $line; if ( $line =~ /(\w+:\w+:\w+:\w+:\w+:\w+)\s+(\w+:\w+:\w+:\w+:\w+:\w+)\s+.*?\s+(\d+\.\d+\.\d+\.\d+)\.\d+\s+>\s+(\d+\.\d+\.\d+\.\d+)\.\d+/ ) { $ether1=$1; $ether2=$2; $ip1=$3; $ip2=$4; add_ether ( $ether1, $ip1); add_ether ( $ether2, $ip2); } } foreach $ether ( keys %ethers ) { print "$ether\t$ethers{$ether}\t$vendor{$ether}\n"; } exit 0; sub add_ether { # Adds an Ethernet MAC my ($ether, $ip ) = @_; if ( ! defined ( $ethers{"$ether"} ) ) { $ethers{"$ether"}=$ip; # Get first three bytes $vendor = $ether; $vendor =~ s/:\w+:\w+:\w+$//; if ( $vendor ne "" ) { if ( -e $ETHERCODES ) { $vendorname=find_vendor($vendor); } else { $vendorname="?"; } $vendor{"$ether"}=$vendorname; $vendor{"$ether"}=~s/^\w+:\w+:\w+\s+//; } } else { $ethers{"$ether"}="multiple" if $ethers{"$ether"} ne $ip; } return 0; } sub find_vendor{ # Finds the vendor given a MAC # Note: will only work if you have an ethercodes file my ($vendor) = @_; $vendorname=`grep '^$vendor' /usr/share/arpwatch/ethercodes.dat |head -1`; chomp $vendorname; return $vendorname; }