Location: PHPKode > scripts > Minotaur - a layer 2 trace route for cisco switches > minotaur-a-layer-2-trace-route-for-cisco-switches/mactrace005.php
<?
//****************************************************************************
// Minotaur - a PHP layer-2 traceroute script
// MAC address traceroute script ver o.oo5 09/03/2003
//    by Min-Hsao Chen hide@address.com
//    http://www.mintrix.net/projects/
//
// The purpose of this script is to trace through a switch network and find 
// the port where a specific mac address is connect.
//     Go to http://www.mintrix.net/projects/ for more details
//
// Requirements:
//     - This script requires the network switches to be cisco based switches.
//        - NEW !!! WORKS on 2948G-L3
//        - will work on other IOS based or CATos based switches
//     - The cisco switches must have TACACS+ support ... no TACACS version might be coming
//     
// Disclaimer
//    This script is open source … if you are going to use this script please have the 
//    courtesy and send me an email and say hi.  This is script is under the GNU general 
//    public license. This script is provided "AS IS".  I will not be responsible 
//    for anything that happens because of this script.  
//    If there are any questions please email me. 
//    I will try to answer your question as soon as I can.  Thank you very much 
//    and have fun tracing.
//    
//****************************************************************************

// user edit area

$snmppublicstr="public"; // public snmp string 
$consolepw="cisco";
$enablepw="cisco123";
//

// edit with caution from this point on
?>
<!-- Main HTML -->
<div align="left">
  <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="72%" id="AutoNumber1">
    <tr>
      <td width="23%">
      <img border="0" src="minotaurlogoB.jpg" width="108" height="131"></td>
      <td width="77%" align="left"><b><font size="5" face="Verdana">MINOTAUR</font></b><small><br>
      a layer-2 traceroute script <br>
ver. o.oo5 ... <br>
09/03/2003<br>
<a href="mailto:hide@address.com">hide@address.com</a>
</small>

      </td>
    </tr>
  </table>
</div>
<form method="post" action="mactrace005.php">

Username:
<input type="text" name="username" value="<? echo "$username";?>" size="20"  size="13"><br>

Password:
<input type="password" name="password" value="<? echo "$password";?>" size="20" size="13"><br>

MAC or IP ADDRESS :
<input type="text" name="address" value="<? echo "$address";?>" size="20" size="16"><br>

<i>Seed switch IP (optional)</i> :
<input type="text" name="seedip" value="<? echo "$seedip"; ?>"size="20"  size="16"><br>

<input type="submit" value="Go get it"  >
</form>


<?
// main program

if ($username)
{
 echo "please wait... <br>\n ";
 flush();		
	
// Sets start time.
$timeparts = explode(" ",microtime());
$starttime = $timeparts[1].substr($timeparts[0],1);


// get the gateway if needed
if (isitip($address)){
  $localrouter=findgateway($address);
  if (!$localrouter) {       // default router
      $adevice=explode(".",$address); // finding router ip
      $temp=array_pop($adevice);
      array_push($adevice,"20");   // default router 4th octect
      $localrouter=implode(".",$adevice);
  }
  echo "gateway IP : $localrouter<br>";
  $mac=getmacfromtelnet($localrouter,$username,$password,$ostype,$address);
  
}else{
  $mac=$address;
  echo "MAC: $mac <br>";
}// got mac
flush();

// get seed device if needed
if (!$seedip){
    //echo "getting seed device... from $localrouter <br>";
    $seedip=getseedip($localrouter,$username,$password,$ostype,$address);
}
$nextip=$seedip; // device IP is the next ip
// got seed


$mac=str_replace("-","",$mac);  // strip out the dashes 
$mac=str_replace(".","",$mac);  // strip out the dots
$mac=str_replace(":","",$mac);  // strip out the colons 
$mac=strtolower($mac);

  


  echo "Seed device : $seedip <br>";
  flush();
  $count=-1;
  echo "<pre>";	
  echo "<b>OS TYPE		FROM IP			PORT				TO </b><br>";
  flush();
  while ($nextip){	
  	
  	$typeofos= getostypebysnmp($nextip,$snmppublicstr);
  	$nextip=rtrim($nextip);
 	echo "$typeofos		 <a href=\"telnet:\\\\$nextip\">$nextip</a>		";// telnet option
  	$nextip=locatethismac($username,$password,$nextip,$typeofos,$mac);
  	if ($nextip){
  	     echo "			$nextip";
  	   }else{
  	     echo "			$mac";
  	   }
  	$count+=1;
        echo "<br>";
      
  	flush();

  }// end while
  echo "</pre>";
  echo "<br> $count hop(s) from the seed device<br>";
  
  //total time taken
  $timeparts = explode(" ",microtime());
  $total_time = ($timeparts[1].substr($timeparts[0],1)) - $starttime;
  echo "<br><font size=\"0\"><i>Total time: ".substr($total_time,0,4)." secs.</i></font><br>";
}else {
  echo "Please user your TACACS UserID and Password <br>";
}

//functions

function getseedip($routerip,$username,$password,$ostype,$address){
// this function finds the seedip from the default gateway.
       $command="show ip arp $address";
       $data=getdatafromdevice($routerip,$username,$password,$command,$typeofos); // get the info
       // $ndata=str_replace("\n","<br>",$data);
       // echo "$ndata <br>";
       $data=cleandata($data,$command,$ostype);
       $list=explode("\n",$data);
       $line= implode ("",preg_grep ("/$address /", $list));
       $parts=preg_split( "/ +/", $line ); // perl expression splitf
       $port=rtrim($parts[5]); // pick out the interface from ip arp
       // echo "$port <br>";
       $seedswitch=get_cdp_neighbor($username,$password,$routerip,$typeofos,$port);
       // echo "seedip = $seedswitch <br>";
       return $seedswitch;
}

function isitip($address){
   $dotcount=substr_count($address,".");
   if ($dotcount=="3"){
         return true;
    }else{
         return false;
    }
} // end of isitip


// find the ip's local router functions
function findgateway($device){
// this function finds the default gateway of the device
   $tracearray=traceroute($device);   	
   $numberofdevices=count($tracearray);
   //var_dump($tracearray);
   $routerip=preg_split("/ +/",$tracearray[$numberofdevices-2]);
   //echo "gateway IP : $routerip[2] <br>";
   return $routerip[2];
}


Function traceroute ($destip) {
    // traceroute function that does a ICMP traceroute.	
    // not the best way to do it .. bit it will do for now
    exec("traceroute -I $destip",$tracearray);
    return $tracearray;  
}

// end of finding gateway functions


function getmacfromtelnet($routerip,$username,$password,$ostype,$ipaddress){
// this function gets the arptable by telneting into the router and do 
// a "show ip arp ip address" then return the mac address
// this might be able to be speed up	
	$command="show ip arp ".$ipaddress;
	$data=getdatafromdevice($routerip,$username,$password,$command,$ostype);
	$data=cleandata($data,$command,$ostype);
	$rawtablearray=explode("\n",$data); // breaks the string to array units per line
	$title=array_shift($rawtablearray); // take out the title
	
	   $line=$rawtablearray[0];
	   $parts=preg_split( "/ +/", $line ); // perl expression split
	   $mac=str_replace(".","",$parts[3]);
	   echo "MAC: $mac = IP: $ipaddress <br>";	
		
        return $mac; // returns mac address
}

function str_split($chaine, $length=1)
{ $retour= FALSE;
  $incrmt= (int)$length;
  if (0 < $incrmt)
  { $retour= array();
    $offset= 0;
    $limite= strlen($chaine);
    while ($offset < $limite)
    { $retour[]= substr($chaine, $offset, $incrmt);
      $offset += $incrmt;
    }
  }// if (0 < $incrmt)
  return ($retour);
}

function convertmac ($mac, $typeofos){
// converts xxxxxxxxxxxx to 
//   xx-xx-xx-xx-xx-xx for catos
// or
//   xxxx.xxxx.xxxx for ios

  if ($typeofos=="catos"){
      $macarray=str_split($mac, 2);
      $output=implode ("-",$macarray);
  }else{
      $macarray=str_split($mac, 4);
      $output=implode (".",$macarray);
  }
  
  return $output; // converted mac address	
}


function locatethismac ($username,$password,$device,$typeofos,$mac){
// This function locate the mac address and returns an array of the port and ip
 
  $mac = convertmac ($mac,$typeofos); 
  if ($typeofos=="catos"){
       $command="show cam $mac";
       $data=getdatafromdevice($device,$username,$password,$command,$typeofos); // get the info
       // $ndata=str_replace("\n","<br>",$data);
       // echo "$ndata <br>";
       $data=cleandata($data,$command,$ostype);
       $list=explode("\n",$data);
       $line= implode ("",preg_grep ("/$mac /", $list));
       $parts=preg_split( "/ +/", $line ); // perl expression split
       $port=$parts[2];
  }elseif ($typeofos=="L3IOS"){
       $command="show bridge $mac";
       $data=getdatafromdevice($device,$username,$password,$command,$typeofos); // get the info
       // $ndata=str_replace("\n","<br>",$data);
       // echo "$ndata <br>";
       $data=cleandata($data,$command,$ostype);
       $list=explode("\n",$data);
       $line= implode ("",preg_grep ("/$mac /", $list));
       $parts=preg_split( "/ +/", $line ); // perl expression split
       $port=$parts[2];
  }elseif ($typeofos=="2950/3550"){   
       $command="show mac-address-table";
       $data=getdatafromdevice($device,$username,$password,$command,$typeofos); // get the info
       $data=cleandata($data,$command,$ostype);
       $list=explode("\n",$data);
       $line= implode ("",preg_grep ("/$mac /", $list));
       $parts=preg_split( "/ +/", $line ); // perl expression split
       $port=rtrim($parts[4]);
  }elseif ($typeofos=="C1900"){   
       $command="show mac address $mac";
       $data=getdatafromdevice($device,$username,$password,$command,$typeofos); // get the info
       $data=cleandata($data,$command,$ostype);
       $mac=strtoupper($mac);
       $list=explode("\n",$data);
       $line= implode ("",preg_grep ("/$mac /", $list));
       $parts=preg_split( "/ +/", $line ); // perl expression split
       $port=$parts[1].$parts[2];
  }else {
       $command="show mac address $mac";
       $data=getdatafromdevice($device,$username,$password,$command,$typeofos); // get the info
       // $ndata=str_replace("\n","<br>",$data);
       // echo "$ndata <br>";
       $data=cleandata($data,$command,$ostype);
       $list=explode("\n",$data);
       $line= implode ("",preg_grep ("/$mac /", $list));
       $parts=preg_split( "/ +/", $line ); // perl expression splitf
       $port=rtrim($parts[3]);
       
  }
  
  if ($port=="") {
      echo "<font color=\"#FF0000\"><b>Can not find MAC address in $device</b></font> <br>";
      exit ("Try another Seed Device<br><br>");
  }else { 
    $oneport=explode("-",$port); // ignore trunking in catos ex. 2/1-2 will only be 2/1
    $nextip=get_cdp_neighbor($username,$password,$device,$typeofos,$oneport[0]);
    echo "$port	";  // display port on the switch
  }
  	
  
  return $nextip;
}


function get_cdp_neighbor($username,$password,$device,$typeofos,$port){
       
       
       if (strstr($port,"BVI")){
         return $device;
       }elseif (strstr($port,"Vlan")){
       	    $port="";
       }
       $command="show cdp neighbor $port detail";
       $data=getdatafromdevice($device,$username,$password,$command,$typeofos); // get the info
       $data=cleandata($data,$command,$ostype);
       $list=explode("\n",$data);
       $line= preg_grep ("/IP Address: | IP address: /", $list);
       $line=implode("",$line);
       $parts=preg_split( "/ +/", $line ); // perl expression split
       $nextip=$parts[3];
       return $nextip;
}

function getostypebysnmp($deviceip,$cstring){
// This function uses snmp to get the switch type
// default switch type is IOS
   
    $ostypeoid=".1.3.6.1.2.1.1.1.0";
    $rawosdata=snmpget($deviceip, $cstring,$ostypeoid);
    if (strstr($rawosdata,"L3")){
       $output="L3IOS";
    }elseif(strstr($rawosdata,"1900")){
       $output="C1900";	
    }elseif(strstr($rawosdata,"Catalyst")){
       $output="catos";
    }elseif(strstr($rawosdata,"2950")||strstr($rawosdata,"3550")){
       $output="2950/3550";
    }elseif(strstr($rawosdata,"3500")||strstr($rawosdata,"2900")){
       $output="ios";
    }else {
       $output="ios";
       echo " <font color=\"#FF0000\"><b>UNKnown Switch type </b></font><br>";
       echo " email me the text below <br>";
       echo " $rawosdata <br>";
    }
    
    return $output;
}

function getostype($username,$password,$device,$ostype){
// old method of getting os type
    $command="xxx";
    $data=getdatafromdevice($device,$username,$password,$command,$ostype);
    $data=cleandata($data,$command,"1");
    $array=explode("\n",$data);
    $ostype=array_pop($array);
    return $ostype;
}

function cleandata($incoming,$cmd,$os) {
// remove all header for clean data section
  $in_array=explode("\n",$incoming);
  $out=array();
  $found="";
  $typeofos="";
  foreach ($in_array as $in){
     if (!$found){
        $parts=explode("#",$in);
        $cmd=rtrim($cmd);
	$part=rtrim($parts[1]);
        if ($part==$cmd){
	  $found="1";
	  $typeofos="ios";
	  }else{
	   $parts=explode("(enable)",$in);
           $part=trim(rtrim($parts[1]));
           if ($part==$cmd){
	   $found="1";
	   $typeofos="catos";
	   }
	  }
	}else{
	   array_push($out,$in);
	}
  }

  if (!$found) {
       echo "ERROR : BAD LOGIN OR PASSWORD";
       $incoming=preg_replace("/\n/","<br>",$incoming);
       echo "<br> ERROR DEBUG <br>";
       echo " if this is the first time you get this message hit GO GET IT AGAIN <br>";
       echo " if you continue to get is message plese email me the text below so <br>";
       echo " I can debug the script <br>";
       echo "<b>Please email me this error so I can fix the issue</b> <br>";
       echo $incoming; // print $res
       echo "<br> END OF ERROR DEBUG <br>";
       var_dump($res);
       exit("Cant find enable maybe timed out due to slow response from the device <br> \n");
  }
  if ($os) {
     array_push($out,$typeofos);
  }
  $output=implode("\n",$out);
  return $output; // clean data list
} //end cleandata



function getdatafromdevice($device,$username,$password,$command,$ostype){
// This function gets the data from the device via port 23 aka telnet

  $enablepw=$GLOBALS["enablepw"];
  if ($device != ""){
      $fp = fsockopen($device, 23,$errno, $errstr, 1);
      
     }

  if(!$fp){    
  	echo "Impossible to connect because : <br> $errstr <br>\n"; //can't connect
        exit ("Please Enter a Valid IP ADDRESS <br> \n");         
  } else {
      // logging in get info
      if ($ostype=="C1900"){  // special case c1900s
      	 socket_set_timeout($fp, 30);
      	 sleep(20);
      	 fputs ($fp, "k \n");
         fputs ($fp, "enable \n");
         fputs ($fp, $enablepw);
         //fputs ($fp, "\n");
         //fputs ($fp, "\n");
         //fputs ($fp, $consolepw);
         fputs ($fp, "\n");
      }else {
       socket_set_timeout($fp, 10);
       fputs ($fp, "\n");
       fputs ($fp, "\n");
       fputs ($fp, "\n");
       fputs ($fp, "\n");
       fputs ($fp, "\n");
       fputs ($fp, "\n");
       fputs ($fp, $username);
       fputs ($fp,"\n");
       fputs ($fp, $password);
       fputs ($fp,"\n");
      
       sleep(1);  // may need it if it don't work right
       if ($ostype=="catos") {
         fputs ($fp, "set length 0 \n");
  	 } else {
            fputs ($fp, "terminal length 0\n");
         }
       fputs ($fp, "\n");
       fputs ($fp, " enable \n");
       fputs ($fp, $password);
       fputs ($fp,"\n");
      }
      fputs ($fp, $command);
      fputs ($fp,"\n");
      fputs ($fp, " exit\n");
      $res = fread($fp, 100000);
      fclose($fp);
      }
   return $res;
 }



?>
Return current item: Minotaur - a layer 2 trace route for cisco switches