#!/usr/bin/perl # use Getopt::Long; use Net::Ping; use Net::Telnet::Cisco; &Main; sub Main { InitParameters(); ChkOptions(); PrintHeader(); ChkHost(); ChkMacAddr(); if (defined $AGGRESSIVE) { AllSwitch($coreswitch,$password,$enable); } else { FindMac($coreswitch,$password,$enable); } } sub InitParameters { %SWITCHOS=(); %CAP=(); $SHMAC{"CAT5OS"}="sh cam "; $SHMAC{"IOS"}="sh mac-address-table addr "; $SHCDP{"CAT5OS"}="sh cdp ne cap "; $SHCDP{"IOS"}="sh cdp ne "; $PINGPROT = "tcp"; # (tcp,udp,icmp) $password="123qwe"; $enable="123qwe"; $coreswitch="192.168.1.1"; } sub AllSwitch { my $DEVICE=$_[0]; my $PASSWORD=$_[1]; my $ENABLE=$_[2]; my $log=""; my $log1=""; my $HEADERCAT5OS; my $HEADERIOS; my $device_object; my $IP; my $t1; FindMac($DEVICE,$password,$enable); if (defined $DEBUG) { print "DEBUG - Unable to locate MAC on $DEVICE\n"; } # Establish Connection $device_object = Net::Telnet::Cisco->new( Host => $DEVICE ); $device_object->login( 'login', "$PASSWORD" ) || die "Can't login to $DEVICE\n$!\n"; $device_object->enable("$ENABLE"); ChkOS($device_object,$DEVICE); $HEADERCAT5OS=0; $HEADERIOS=0; $log .= join "", $device_object->cmd($SHCDP{$SWITCHOS{$DEVICE}}); while ($log =~ /^(.*)$/mg) { $t1 = $1; if ($HEADERCAT5OS) { @t1 = split(/\s+/,$t1); $log1 = join "", $device_object->cmd("sh cdp ne $t1[1] detail"); while ($log1 =~ /IP Address:(.*)$/img) { $IP = trim($1); $CAP{$IP} = ""; for ($i=4;$icmd("sh cdp ne $t1[0]$t1[1] detail"); while ($log1 =~ /IP Address:(.*)$/img) { $IP = trim($1); $CAP{$IP} = trim(substr($t1,47-17,10)); if (ChkClusterIP($IP,$DEVICE)) { last; } if (! defined $SWITCHOS{$IP} && $CAP{$IP} =~ /S/m ) { if (defined $DEBUG) { print "DEBUG - Searching on $IP\n"; } AllSwitch($IP,$PASSWORD,$ENABLE); } } } if ($t1 =~ /---/m && $SWITCHOS{$DEVICE}=~ /CAT5OS/m ) { $HEADERCAT5OS = 1; } if ($t1 =~ /Device ID/m && $SWITCHOS{$DEVICE}=~ /IOS/m ) { $HEADERIOS = 1; } } # Closing Connection $device_object->close; } sub FindMac { my $DEVICE=$_[0]; my $PASSWORD=$_[1]; my $ENABLE=$_[2]; my $log=""; my $log1=""; my $HEADERCAT5OS; my $HEADERIOS; my $device_object; my $IP; my $t1; my $SWITCHNAME; if (defined $DEBUG) { print "DEBUG - Logging in to $DEVICE\n"; } # Establish Connection $device_object = Net::Telnet::Cisco->new( Host => $DEVICE ); $device_object->login( 'login', "$PASSWORD" ) or die "Can't login to $DEVICE:\n$!\n"; $device_object->enable("$ENABLE"); ChkOS($device_object,$DEVICE); $HEADERCAT5OS=0; $HEADERIOS=0; # Execute Show Mac Command if ($SWITCHOS{$DEVICE} =~ /CAT5OS/m) { $log .= join "", $device_object->cmd($SHMAC{$SWITCHOS{$DEVICE}}." $MACADDR"); if (!($log =~ m/Total Matching CAM Entries Displayed.*\n/)) { if (! defined $AGGRESSIVE) { print "Unable to locate MAC Addr $MACADDR on $DEVICE!!\n"; } } $log =~ s/Total Matching CAM Entries Displayed.*\n//; } else { $log .= join "", $device_object->cmd($SHMAC{$SWITCHOS{$DEVICE}}." $MACADDR1"); if (($log =~ m/No matching entry found.*\n/)) { if (! defined $AGGRESSIVE) { print "Unable to locate MAC Addr $MACADDR on $DEVICE!!\n"; } } $log =~ s/------------------------------------------//; } # Checking the Output from Show Mac Command while ($log =~ /^(.*)$/mg) { $t1 = $1; if ($HEADERCAT5OS) { @t1 = split(/\s+/,$t1); if ($t1[2] =~ /-/) { if (defined $DEBUG) { print "DEBUG - ---> $t1[2] <--- This is an aggregated interface.\n"; } @t2 = split(/\-/,$t1[2]); $t1[2] = $t2[0]; } if (defined $DEBUG) { print "DEBUG - sh cdp ne $t1[2] detail\n"; } $log1 = join "", $device_object->cmd("sh cdp ne $t1[2] detail"); ($SWITCHNAME)=$device_object->last_prompt=~ /^(.*)\s?(?:\(config[^\)]*\))?\s?[\$#>]\s?(?:\(enable\))?\s*$/; if ($log1 =~ /Router/mi) { print "This is a router.\n"; ShowResult($MACADDR,$DEVICE,$t1[2],$SWITCHNAME); } while ($log1 =~ /IP Address:(.*)$/img) { $IP = trim($1); if (ChkClusterIP($IP,$DEVICE)) { last; } if (defined $PATHTRACE) { print "$SWITCHNAME ($DEVICE) port $t1[2] => ($IP)\n"; } if ($log1 =~ /Switch/mi) { FindMac($IP,$PASSWORD,$ENABLE); } } if ($log1 =~ /No entry found/m) { ShowResult($MACADDR,$DEVICE,$t1[2],$SWITCHNAME); } } if ($HEADERIOS) { @t1 = split(/\s+/,trim($t1)); if (defined $DEBUG) { print "DEBUG - sh cdp ne $t1[3] detail\n"; } $log1 = join "", $device_object->cmd("sh cdp ne $t1[3] detail"); ($SWITCHNAME)=$device_object->last_prompt=~ /^(.*)\s?(?:\(config[^\)]*\))?\s?[\$#>]\s?(?:\(enable\))?\s*$/; if ($log1 =~ /Router/mi) { print "This is a router.\n"; ShowResult($MACADDR,$DEVICE,$t1[3],$SWITCHNAME); } while ($log1 =~ /IP Address:(.*)$/img) { $IP = trim($1); if (ChkClusterIP($IP,$DEVICE)) { last; } if (defined $PATHTRACE) { print "$SWITCHNAME ($DEVICE) port $t1[3] => ($IP)\n"; } if ($log1 =~ /Switch/mi) { FindMac($IP,$PASSWORD,$ENABLE); } } if ($log1 =~ /^\s+$/m) { ShowResult($MACADDR,$DEVICE,$t1[3],$SWITCHNAME); } } if ($t1 =~ /---/m && $SWITCHOS{$DEVICE}=~ /CAT5OS/m ) { $HEADERCAT5OS = 1; } if ($t1 =~ /---/m && $SWITCHOS{$DEVICE}=~ /IOS/m ) { $HEADERIOS = 1; } } # Closing Connection $device_object->close; } sub ChkClusterIP { my $IP=$_[0]; my $DEVICE=$_[1]; if ($IP eq $DEVICE) { if (defined $DEBUG) { print "DEBUG - Ignore! Cluster Switch or GigaStack Connections ($IP)\n"; } return 1; } return 0; } sub trim { my @out = @_; for (@out) { s/^\s+//; s/\s+$//; } return wantarray?@out:$out[0]; } sub ChkOptions { GetOptions ('macaddr=s' => \$MACADDR, 'host=s' => \$HOST, 'aggressive:s' => \$AGGRESSIVE, 'id:s' => \$SHOWDEVICEID, 'pathtrace:s' => \$PATHTRACE, 'quiet:s' => \$QUIET, 'debug:s' => \$DEBUG ); unless ($MACADDR || $HOST) { print "$0\n"; print "\t--macaddr < MAC Address 00:00:00:00:00:00 >\n"; print "\t--host < hostname >\n"; print "\t--aggressive\n"; print "\t--id\n"; print "\t--pathtrace\n"; print "\t--quiet\n"; print "\t--debug\n"; exit(10); } } sub ChkMacAddr { my $MACCHECK; $MACCHECK = 0; $MACADDR1=$MACADDR; if ( $MACADDR =~ m/^(([0-9a-fA-f]){2}[-|:]){5}([0-9a-fA-f]){2}/) { $MACCHECK=1; } if ( $MACADDR =~ m/^(([0-9a-fA-f]){2}\.){5}([0-9a-fA-f]){2}/) { $MACCHECK=1; $MACADDR =~ s/\./-/g; } $MACADDR1 =~ s/^([0-9a-fA-f][0-9a-fA-f])[-|:]([0-9a-fA-f][0-9a-fA-f])[-|:]([0-9a-fA-f][0-9a-fA-f])[-|:]([0-9a-fA-f][0-9a-fA-f])[-|:]([0-9a-fA-f][0-9a-fA-f])[-|:]([0-9a-fA-f][0-9a-fA-f])/$1$2.$3$4.$5$6/; if (!$MACCHECK) { print "MAC Address format is incorrect!!\n\te.g. 00-00-00-00-00-00\n"; exit(11); } } sub ChkHost { my $p; my $ARP; unless (! defined $HOST ) { $p = Net::Ping->new($PINGPROT) or die "Can't create new ping object: $!\n"; if (defined $DEBUG) { print "DEBUG - ICMP PING Object Created\n"; } if ($p->ping($HOST)) { if (defined $DEBUG) { print "DEBUG - PING ($HOST) OK\n"; } $ARP = qx!/sbin/arp -a $HOST!; @ARP=split(/\s+/,$ARP); $MACADDR=$ARP[3]; print "$HOST MAC Address is $MACADDR\n"; } else { print "$HOST Not found!\n"; exit; } $p->close; } } sub PrintHeader { if (! defined $QUIET) { print "findmac.pl by Mike Lyon\n\n"; } } sub ShowResult { my $MACADDR=$_[0]; my $DEVICE=$_[1]; my $PORT=$_[2]; my $SWITCHNAME=$_[3]; if (defined($SHOWDEVICEID)) { print "$SWITCHNAME ($DEVICE)"; } else { print $DEVICE; } print " port $PORT => $MACADDR\n"; exit; } sub ChkOS { my $device_object=$_[0]; my $DEVICE=$_[1]; if (! defined $SWITCHOS{$DEVICE} ) { $t1 .= join "", $device_object->cmd("show version"); if ($t1 =~ /^(.*IOS.*)$/mg) { $SWITCHOS{$DEVICE} = "IOS"; if (defined $DEBUG) { print "DEBUG - $DEVICE is running IOS\n"; } } else { $SWITCHOS{$DEVICE} = "CAT5OS"; if (defined $DEBUG) { print "DEBUG - $DEVICE is running CAT5OS\n"; } } } }