<?
//-- Port browser for Cisco switches
//   v0.1
//   Holger Marzen (holger@marzen.de), 2003
//   
//   This work is released under the GPL,
//   see http://www.gnu.org/licenses/gpl.html for details.
//   Use this code at your own risk. NO WARRANTY.
//
//   See http://www.cisco.com/warp/public/477/SNMP/cam_snmp.html
//   for their perverted way to store port/vlan info.
//   
//   See http://www.cisco.com/pcgi-bin/Support/Mibbrowser/unity.pl
//   for online MIB browsing.
//
//   This application can log changes to a PostgreSQL database,
//   see http://www.postgresql.org for details.
//   See switch.sql for DDL to create the table.
//

//-- icons
$pic_green = "<img border=\"0\" src=\"green.gif\" alt=\"up\">";
$pic_clear = "<img border=\"0\" src=\"clear.gif\" alt=\"down\">";
$pic_red   = "<img border=\"0\" src=\"red.gif\"   alt=\"down\">";

//-- devices
//         name               ip-addr   read     write
$switches["SWITCH1"] = array("2.3.4.1","public","secret");
$switches["SWITCH2"] = array("2.3.4.2","public","secret");
$switches["SWITCH3"] = array("2.3.4.3","public","secret");

//-- args
$arg_device   = $_REQUEST["arg_device"];
$arg_device   = strtoupper($arg_device);
$arg_action   = $_REQUEST["arg_action"];
$arg_ifindex  = $_REQUEST["arg_ifindex"];
$arg_alias    = $_REQUEST["arg_alias"];

//-- vars
$db = "";     // set to db name for logging
$ixcom = 0;   // 1=use informations that can only be read
              //   with indexed communities (like public@123),
              //   e.g. VLAN info, MAC info.
	      //   Some Ciscos hang at some communities.

$userid = $_SERVER["REMOTE_USER"];
$PHP_SELF = $_SERVER["PHP_SELF"];
$do_enteralias = 1;
$do_changealias = 2;
$do_adminstatusup = 3;
$do_adminstatusdown = 4;
$do_ifportduplexhalf = 5;
$do_ifportduplexfull = 6;

?>


<html>
<head>
  <title>Tool für Cisco Switche - 
    <? print $arg_device; ?> -
    UserID <? print $userid ?>
  </title>
  <link rel="stylesheet" href="switch.css">
</head>
<body>
<a href="/">[Zurück]</a>

<h1>Tool für Cisco Switche</h1>
<form method="post" action="<? print $PHP_SELF; ?>">

Switch/Router:
<select name="arg_device" size="1">
<?
for (reset($switches); $ddevice = key($switches); next($switches))
  {
  if ($arg_device == $ddevice)
    {
    echo "<option selected>$ddevice</option>\n";
    }
  else
    {
    echo "<option>$ddevice</option>\n";
    }
  }
?>
</select>
<input type="submit" value="Anzeigen"  >
</form>

<?
if ($db <> "")
  $dblink = pg_connect("dbname=$db") or die ("Connect to database $db failed");


if ($arg_device)
  {
  $deviceip = $switches["$arg_device"][0];
  $readpw   = $switches["$arg_device"][1];
  $writepw  = $switches["$arg_device"][2];

  //-- Only "short" values
  snmp_set_quick_print(1);

  //-- Actions ---------------------------------------------
  if ($arg_action)
    {
    if ($arg_action == $do_changealias)
      {
      $arg_alias = validsnmpchars($arg_alias);
      $oid="ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifAlias.$arg_ifindex";
      snmpset($deviceip, $writepw, $oid, "s", $arg_alias);
      if ($db <> "")
        if ($arg_alias == "")
          logaction($userid, "${arg_device}[${arg_ifindex}]: Kommentarfeld gelöscht");
        else
          logaction($userid, "${arg_device}[${arg_ifindex}]: Kommentarfeld zu $arg_alias");
      }

    if ($arg_action == $do_adminstatusup)
      {
      $oid="interfaces.ifTable.ifEntry.ifAdminStatus.$arg_ifindex";
      snmpset($deviceip, $writepw, $oid, "i", 1);
      if ($db <> "")
        logaction($userid, "${arg_device}[${arg_ifindex}]: Admin Status up");
      }

    if ($arg_action == $do_adminstatusdown)
      {
      $oid="interfaces.ifTable.ifEntry.ifAdminStatus.$arg_ifindex";
      snmpset($deviceip, $writepw, $oid, "i", 2);
      if ($db <> "")
        logaction($userid, "${arg_device}[${arg_ifindex}]: Admin Status down");
      }

    if ($arg_action == $do_ifportduplexhalf)
      {
      $oid=".1.3.6.1.4.1.9.5.1.4.1.1.10.1.$arg_ifindex";
      snmpset($deviceip, $writepw, $oid, "i", 1);
      if ($db <> "")
        logaction($userid, "${arg_device}[${arg_ifindex}]: Duplex half");
      }

    if ($arg_action == $do_ifportduplexfull)
      {
      $oid=".1.3.6.1.4.1.9.5.1.4.1.1.10.1.$arg_ifindex";
      snmpset($deviceip, $writepw, $oid, "i", 2);
      if ($db <> "")
        logaction($userid, "${arg_device}[${arg_ifindex}]: Duplex full");
      }
    }


  //-- Anzeige ---------------------------------------------
  $sysnameloc = snmpgetsysnameloc($deviceip, $readpw);
  if (!$sysnameloc)
    {
    echo "<h2>Keine Antwort von $deviceip.</h2>\n";
    }
  else
    {
    $sysdescr = snmpgetsysdescr($deviceip, $readpw);
    $sysdescr = eregi_replace("Copyright.*$","",$sysdescr);

    echo "<h2>$sysnameloc</h2>\n";
    echo "$sysdescr\n";
    echo "<p>";
  
    echo "<table border=\"1\">\n";
  
    echo "<th>Nr.</th>";
    echo "<th>VLAN</th>";
    echo "<th>Beschreibung/Kommentar</th>";
//  echo "<th>MBit/s</th>";
    echo "<th>Duplex</th>";
    echo "<th>Admin Status</th>";
    echo "<th>Status</th>";
//  echo "<th>Statusänderung</th>";
    echo "<th>Bytes In</th>";
    echo "<th>Bytes Out</th>";
    echo "<th>MAC Adresse</th>";
  

    //-------------------------------------
    //-- VLAN index/status ----------------
    //-------------------------------------
    if ($ixcom == 1)
      {
      $startoid = ".1.3.6.1.4.1.9.9.46.1.3.1.1.2";
      $vs = snmprealwalk($deviceip, $readpw, $startoid);
      for (reset($vs); $vlan = key($vs); next($vs))
        {
        $numvlan = $output = eregi_replace("^.*\.","",$vlan);
        if ($numvlan < 1000)
          if ($vs[$vlan] == 1)
            {
            //-- $numvlan is number of an active vlan

            //-- mac addr to interface --------------------------------------
            //   Get MAC address table
            $startoid = ".1.3.6.1.2.1.17.4.3.1.1";
            $filteroid = "17\.4\.3\.1\.1\.";
            $macs = snmprealwalk($deviceip, $readpw . "@" . $numvlan, $startoid);
            for (reset($macs); $macid = key($macs); next($macs))
              {
              $macaddr = $macs[$macid];
              $macaddr = eregi_replace("\"","",$macaddr);
              $macaddr = eregi_replace(" *$","",$macaddr);
              $macaddr = eregi_replace(" ",":",$macaddr);

              $macoidpart = eregi_replace("^$filteroid","",$macid);
              $oid = ".1.3.6.1.2.1.17.4.3.1.2.$macoidpart";

              // Get bridge port
              $bridgeport = @snmpget($deviceip, $readpw . "@" . $numvlan, $oid);

              // Get interface index
              $ifindex = snmpgetifindexfrombridgeport($deviceip, $readpw, $bridgeport);
              $ifindexmacs[$ifindex][] = $macaddr;
              }

            //---------------------------------------------------------------

            //-- interface to vlan ------------------------------------------
            //   Get bridge port numbers with indexed community.
            $startoid = ".1.3.6.1.2.1.17.4.3.1.2";
            $bp = snmpwalk($deviceip, $readpw . "@" . $numvlan, $startoid);

            //-- only unique bridge ports
            $bp = array_values(array_unique($bp));

            //-- now get the ifindex from bridge port
            for ($ma = 0; $ma < count($bp); $ma++)
              {
              $bridgeport = $bp[$ma];
              $ifindex = snmpgetifindexfrombridgeport($deviceip, $readpw, $bridgeport);
              $ifindexvlan[$ifindex][] = $numvlan;
              }
            //---------------------------------------------------------------
            }
        }
      }


    //-- Hauptschleife ----------------------------------------
    $numifs = snmpgetnumifs($deviceip, $readpw);
    for ($if=1;$if <= $numifs;$if++)
      {
      $ifindex = snmpgetifindexfromifno($deviceip, $readpw, $if);
  
      $ifalias = snmpgetifalias($deviceip, $readpw, $ifindex);
      $iftype = snmpgetiftype($deviceip, $readpw, $ifindex);
      if (substr($iftype,0,8) == "ethernet")
        {
        echo "\n<tr>";
        //$ifspeed = snmpgetifspeed($deviceip, $readpw, $ifindex);
        $ifportduplex = snmpgetifportduplex($deviceip, $readpw, $ifindex);

        $ifadminstatus = snmpgetifadminstatus($deviceip, $readpw, $ifindex);
	if ($ifadminstatus == "up")
	  $d_ifadminstatus = $pic_green;
	else
	  $d_ifadminstatus = $pic_red;

        $ifoperstatus = snmpgetifoperstatus($deviceip, $readpw, $ifindex);
	if ($ifoperstatus == "up")
	  $d_ifoperstatus = $pic_green;
	else
	  $d_ifoperstatus = $pic_clear;

        //$iflastchange = snmpgetiflastchange($deviceip, $readpw, $ifindex);
        $ifinoctets = snmpgetifinoctets($deviceip, $readpw, $ifindex);
        $ifoutoctets = snmpgetifoutoctets($deviceip, $readpw, $ifindex);

	$ifvlan = $ifindexvlan[$ifindex];

	$ifmacs = $ifindexmacs[$ifindex];
  
        echo "\n";
        echo "<td class=tdfixed align=\"right\">$if</td>";

        echo "<td class=tdfixed align=\"right\">";
	if (count($ifvlan) <= 1)
	  {
          echo $ifvlan[0];
	  }
	else
	  {
          echo "<form method=\"post\" action=\"$PHP_SELF\">";
          echo "<select class=tdfixed name=\"vlan\" size=\"1\">\n";
	  for ($m=0; $m<count($ifvlan); $m++)
	    {
	    echo "<option>$ifvlan[$m]</option>";
	    }
          echo "</select>\n";
          echo "</form>";
	  }
	echo "</td>";


        //-- Anzeige/Eingabe Kommentar (Alias) ----------
        echo "<td align=\"right\">";
	if ($ifalias == "")
	  $d_ifalias = "...";
	else
	  $d_ifalias = $ifalias;
	$d_ifalias = htmlspecialchars($d_ifalias);

	$href="$PHP_SELF" . "?arg_device=$arg_device&arg_ifindex=$ifindex";
        if ($arg_action == $do_enteralias)
	  if ($arg_ifindex == $ifindex)
	    {
            echo "<form method=\"post\" action=\"$PHP_SELF\">";
	    echo "<input type=\"input\" maxlength=\"40\" name=\"arg_alias\" value=\"$ifalias\">";
	    echo "<input type=\"hidden\" name=\"arg_action\" value=\"$do_changealias\">";
	    echo "<input type=\"hidden\" name=\"arg_device\" value=\"$arg_device\">";
	    echo "<input type=\"hidden\" name=\"arg_ifindex\" value=\"$ifindex\">";
	    echo "<input type=\"submit\" value=\"OK\">";
            echo "</form>\n";
	    }
	  else
	    {
	    $href = $href . "&arg_action=$do_enteralias";
            echo "<a href=\"$href\">$d_ifalias</a>";
	    }
	else
	  {
	  $href = $href . "&arg_action=$do_enteralias";
          echo "<a href=\"$href\">$d_ifalias</a>";
	  }
        echo "</td>";
	//-----------------------------------------------

        //echo "<td class=tdfixed align=\"right\">$ifspeed</td>";

	$href="$PHP_SELF" . "?arg_device=$arg_device&arg_ifindex=$ifindex";
        if ($ifportduplex == "half")
	  {
	  $href = $href . "&arg_action=$do_ifportduplexfull";
	  }
	else
	  {
	  $href = $href . "&arg_action=$do_ifportduplexhalf";
	  }
        //echo "<td align=\"center\"><a href=\"$href\">$ifportduplex</a></td>";
        echo "<td class=tdfixed align=\"right\">$ifportduplex</td>";


	$href="$PHP_SELF" . "?arg_device=$arg_device&arg_ifindex=$ifindex";
        if ($ifadminstatus == "up")
	  {
	  $href = $href . "&arg_action=$do_adminstatusdown";
	  }
	else
	  {
	  $href = $href . "&arg_action=$do_adminstatusup";
	  }
        echo "<td align=\"center\"><a href=\"$href\">$d_ifadminstatus</a></td>";


        echo "<td align=\"center\">$d_ifoperstatus</td>";
//      echo "<td align=\"right\">$iflastchange</td>";
        echo "<td class=tdfixed align=\"right\">$ifinoctets</td>";
        echo "<td class=tdfixed align=\"right\">$ifoutoctets</td>";

        echo "<td class=tdfixed align=\"center\">";
	if (count($ifmacs) <= 1)
	  {
          echo $ifmacs[0];
	  }
	else
	  {
          echo "<form method=\"post\" action=\"$PHP_SELF\">";
          echo "<select class=tdfixed name=\"macaddr\" size=\"1\">\n";
	  for ($m=0; $m<count($ifmacs); $m++)
	    {
	    echo "<option>$ifmacs[$m]</option>";
	    }
          echo "</select>\n";
          echo "</form>";
	  }
	echo "</td>";
  
        echo "</tr>\n";
        }
      }
    echo "</table>\n";
    }
  }
?>

<?
echo "<p>";

//-- Log-Tabelle anzeigen
if ($db <> "")
  {
  $limit = 20;
  $result = pg_exec("select to_char(timestamp,'DD.MM.YYYY HH24:MI:SS'), " .
                    "userid, action from switch_log " .
                    "order by timestamp desc limit $limit")
            or die ("Select from db $db failed");
  $num = pg_numrows($result);
  
  echo "\n<table border=\"1\">\n";
  echo "\n<tr>";
  echo "<th colspan=\"3\">Letzte $limit Änderungen</td>";
  echo "</tr>";
  echo "\n<tr>";
  echo "<th>Datum/Uhrzeit</td>";
  echo "<th>UserID</td>";
  echo "<th>Aktion</td>";
  echo "</tr>";
  
  for ($i=0; $i<$num; $i++)
    {
    echo "\n<tr>";
    $row = pg_fetch_row($result, $i);
    $d_timestamp = $row[0];
    $d_userid    = $row[1];
    $d_action    = htmlspecialchars($row[2]);
  
    echo "<td class=\"tdfixed\">$d_timestamp</td>";
    echo "<td align=\"right\">$d_userid</td>";
    echo "<td>$d_action</td>";
    echo "</tr>";
    }
  echo "</table>\n";
  
  pg_close($dblink);
  }
?>

</body>
</html>


<?
function snmpgetifportduplex($deviceip,$readpw,$ifindex){
    $oid=".1.3.6.1.4.1.9.5.1.4.1.1.10.1.$ifindex";
    $output = @snmpget($deviceip, $readpw, $oid);
    if ($output == 1) return ("half");
    if ($output == 2) return ("full");
    if ($output == 3) return ("disagree");
    if ($output == 4) return ("auto");
    return "?";
}

function snmpgetifoutoctets($deviceip,$readpw,$ifindex){
    $oid="interfaces.ifTable.ifEntry.ifOutOctets.$ifindex";
    $output = snmpget($deviceip, $readpw, $oid);
    return $output;
}

function snmpgetifinoctets($deviceip,$readpw,$ifindex){
    $oid="interfaces.ifTable.ifEntry.ifInOctets.$ifindex";
    $output = snmpget($deviceip, $readpw, $oid);
    return $output;
}

function snmpgetiflastchange($deviceip,$readpw,$ifindex){
    $quickprint = snmp_get_quick_print();
    $oid="interfaces.ifTable.ifEntry.ifLastChange.$ifindex";
    snmp_set_quick_print(0);
    $output = snmpget($deviceip, $readpw, $oid);
    snmp_set_quick_print($quickprint);
    $output = eregi_replace("\(.*\)","",$output);
    $output = eregi_replace("^[^:]*:","",$output);
    return $output;
}

function snmpgetifoperstatus($deviceip,$readpw,$ifindex){
    $oid="interfaces.ifTable.ifEntry.ifOperStatus.$ifindex";
    $output = snmpget($deviceip, $readpw, $oid);
    return $output;
}

function snmpgetifadminstatus($deviceip,$readpw,$ifindex){
    $oid="interfaces.ifTable.ifEntry.ifAdminStatus.$ifindex";
    $output = snmpget($deviceip, $readpw, $oid);
    return $output;
}

function snmpgetifspeed($deviceip,$readpw,$ifindex){
    $oid="interfaces.ifTable.ifEntry.ifSpeed.$ifindex";
    $output = snmpget($deviceip, $readpw, $oid);
    $output = $output / 1000000;
    return $output;
}

function snmpgetiftype($deviceip,$readpw,$ifindex){
    $oid="interfaces.ifTable.ifEntry.ifType.$ifindex";
    $output = snmpget($deviceip, $readpw, $oid);
    return $output;
}

function snmpgetifdescr($deviceip,$readpw,$ifindex){
    $oid="interfaces.ifTable.ifEntry.ifDescr.$ifindex";
    $output = snmpget($deviceip, $readpw, $oid);
    return $output;
}

function snmpgetifalias($deviceip,$readpw,$ifindex){
    $oid="ifMIB.ifMIBObjects.ifXTable.ifXEntry.ifAlias.$ifindex";
    $output = snmpget($deviceip, $readpw, $oid);
    return stripslashes($output);
}

function snmpgetifindexfromifno($deviceip,$readpw,$ifno){
    $oid="interfaces.ifTable.ifEntry.ifIndex.$ifno";
    $output = snmpget($deviceip, $readpw, $oid);
    return $output;
}

function snmpgetifindexfrombridgeport($deviceip,$readpw,$bridgeport){
    $oid=".1.3.6.1.2.1.2.2.1.1.$bridgeport";
    $output = @snmpget($deviceip, $readpw, $oid);
    return $output;
}

function snmpgetnumifs($deviceip,$readpw){
    $oid="interfaces.ifNumber.0";
    $output = snmpget($deviceip, $readpw, $oid);
    return $output;
}

function snmpgetsysnameloc($deviceip,$readpw){
    $oid="system.sysName.0";
    $output = snmpget($deviceip, $readpw, $oid);
    if (!$output)
      {
      return $output;
      }
    $oid="system.sysLocation.0";
    $output = $output . " - $deviceip - " . snmpget($deviceip, $readpw, $oid);
    return $output;
}

function snmpgetsysdescr($deviceip,$readpw){
    $oid="system.sysDescr.0";
    $output = snmpget($deviceip, $readpw, $oid);
    return $output;
}

function validsnmpchars($string){
    $output = eregi_replace("[^0-9a-z+\-_,.;:()'/ %]","",$string);
    return $output;
}

function logaction($userid, $action){
$result = pg_exec("insert into switch_log(userid, action)" .
                  "values('$userid', '$action')")
  or die ("Select from db $db failed");
$result = pg_exec("delete from switch_log " .
                  "where age(current_timestamp, timestamp) > '6 months'")
  or die ("Delete from db $db failed");
return;
}

?>
