Source for file snmp_defs.inc.php

Documentation is available at snmp_defs.inc.php

  1. <?php
  2. /**
  3.  * /opt/nac/contrib/snmp_defs.inc
  4.  *
  5.  * Long description for file:
  6.  * - Specific SNMP queries
  7.  * - Some functions for snmp scripts
  8.  *
  9.  * - tested on the following switches:
  10.  * - Cisco
  11.  *    - 3500xl
  12.  *     - 2950, 2940-8TT
  13.  *    - 3550
  14.  *    - 3750
  15.  *
  16.  * Further reading:
  17.  *    http://www.cisco.com/public/sw-center/netmgmt/cmtk/mibs.shtml
  18.  *    The "getif" tool for exploring MIBs.
  19.  *
  20.  * PHP version 5
  21.  *
  22.  * LICENSE: This program is free software; you can redistribute it and/or
  23.  * modify it under the terms of the GNU General Public License as published
  24.  * by the Free Software Foundation.
  25.  *
  26.  * @package                     FreeNAC
  27.  * @author                      Thomas Dagonnier - Sean Boran (FreeNAC Core Team)
  28.  * @copyright                   2006 FreeNAC
  29.  * @license                     http://www.gnu.org/copyleft/gpl.html   GNU Public License Version 2
  30.  * @version                     CVS: $Id:$
  31.  * @link                        http://www.freenac.net
  32.  *
  33.  */
  34.  
  35.  
  36. $snmp_sw['descr'=             '1.3.6.1.2.1.1.1';
  37. #$snmp_sw['soft_version'] =     '1.3.6.1.2.1.47.1.1.1.1.10';
  38. $snmp_sw['name'=              '1.3.6.1.2.1.1.5';
  39. $snmp_sw['location'=          '1.3.6.1.2.1.1.6';
  40. $snmp_sw['contact'=           '1.3.6.1.2.1.1.4';
  41. // $snmp_sw['cdp'] =        '1.3.6.1.4.1.9.9.23.1.2.1.1.8';        // get array with port index + CDP neigbours
  42.  
  43. $snmp_ifaces =                  '1.3.6.1.2.1.31.1.1.1.1';
  44. $snmp_mac =            '1.3.6.1.2.1.17.4.3.1.1';
  45. $snmp_bridge =            '1.3.6.1.2.1.17.4.3.1.2';
  46. $snmp_ports =            '1.3.6.1.2.1.17.1.4.1.2';
  47.  
  48. $snmp_cisco['hw'=             '1.3.6.1.2.1.47.1.1.1.1.13.1';
  49.  
  50. $snmp_if['name'=              '1.3.6.1.2.1.31.1.1.1.1';
  51. $snmp_if['highspeed'=         '1.3.6.1.2.1.31.1.1.1.15';              //      10 - 100 - 1000 
  52. $snmp_if['description'=       '1.3.6.1.2.1.31.1.1.1.18';
  53. $snmp_if['phys'=              '1.3.6.1.2.1.31.1.1.1.17';              // true - false
  54. $snmp_if['trunk'=             '1.3.6.1.4.1.9.9.46.1.6.1.1.14';        // 1 : on - 2 : off - 3 : desirable - 4 : auto - 5 : onNoNegotiate
  55. $snmp_if['vlan'=              '1.3.6.1.4.1.9.9.68.1.2.2.1.2';
  56. $snmp_if['type'=        '1.3.6.1.4.1.9.9.68.1.2.2.1.1';                 // 1 - static; 2 - dynamic; 3 - multivlan
  57.  
  58. #$snmp_vlan['id'] =        '1.3.6.1.4.1.9.9.46.1.3.1.1.1';            // not reliable ???
  59. $snmp_vlan['state'=        '1.3.6.1.4.1.9.9.46.1.3.1.1.2';
  60. $snmp_vlan['type'=        '1.3.6.1.4.1.9.9.46.1.3.1.1.3';            // 1 : ethernet - 2, 4 : fddi -3 tokenring - 5, trnet
  61. $snmp_vlan['name'=        '1.3.6.1.4.1.9.9.46.1.3.1.1.4';
  62.  
  63. $snmp_port['type'=         '1.3.6.1.4.1.9.9.68.1.2.2.1.1';            // 1 - static; 2 - dynamic; 3 - multivlan
  64. $snmp_port['trunk'=         '1.3.6.1.4.1.9.9.46.1.6.1.1.14';        // 1 - trunking; 2 - ot trunking
  65. #$snmp_port['stp'] =        '1.3.6.1.4.1.9.9.82.1.9.3.1.2';            // 1 - true; 2 - false
  66. #$snmp_port['802.1x'] =        '1.3.6.1.4.1.9.5.1.19.1.1.20';            // 1 - Port support for 802.1x; 2 - No support for 802.1x on this port
  67.  
  68. $snmp_port['ad_status'=     '1.3.6.1.2.1.2.2.1.7';    // 1 - up; 2 - down; 3 - testing;
  69. #$snmp_port['op_status'] =     '1.3.6.1.2.1.2.2.1.8';    // 1 - up; 2 - down; 3 - testing; 4 - unknown; 5 - dormant; 6 - notpresent; 7 - lowerLayerDown
  70. #$snmp_port['dot1x_control'] =    '1.1.8802.1.1.1.1.2.1.1.6';  // 1 - forceUnauthorized; 2 - auto; 3 - forceAuthorized
  71. #$snmp_port['dot1x_status'] =    '1.1.8802.1.1.1.1.2.1.1.5';  // 1 - authorized; 2 - unauthorized;
  72. #$snmp_port['dot1x_state'] =     '1.1.8802.1.1.1.1.2.1.1.1';      // 1 - initialize; 2 - disconnected; 3 - connecting;
  73.                                    // 4 - authenticating; 5 - authenticated; 6 - aborting;
  74.                                 // 7 - held; 8 - forceAuth; 9 - forceUnauth
  75. #$snmp_port['dot1x_eapolrx'] =     '1.1.8802.1.1.1.1.2.2.1.1';    //Number of valid EAPOL frames received
  76. #$snmp_port['dot1x_quietp'] =     '1.1.8802.1.1.1.1.2.1.1.7';
  77. #$snmp_port['dot1x_authtxp'] =    '1.1.8802.1.1.1.1.2.1.1.8';
  78. $vmps_reconfirm =         '1.3.6.1.4.1.9.9.68.1.1.4';    // 2 to reconfirm
  79. $write_command['old'=     '1.3.6.1.4.1.9.2.1.54';    //1 to write
  80. $write_command['source'=    '1.3.6.1.4.1.9.9.96.1.1.1.1.3';    //2 for running config
  81. $write_command['destination'=    '1.3.6.1.4.1.9.9.96.1.1.1.1.4';    //1 for startup config
  82. $write_command['execute'=    '1.3.6.1.4.1.9.9.96.1.1.1.1.14'//4 for create and go
  83. # 1.0.8802.1.1.1.1.2.1.1.1    //Current value of the Authenticator PAE state machine
  84. /** This function is called for any errors or
  85.  *  messages sent to stdout/err. The idea is to catch all
  86.  *  such messages and send them to syslog, this this is a daemon normally
  87.  *  detached from the console
  88.  */
  89. function callback($buffer)
  90. {
  91.   if (strlen($buffer1{
  92.     logit('callback:[' $buffer .']');
  93.   }
  94.   #return(true);
  95. }
  96.  
  97.  
  98. /**
  99. * Get the snmp port index
  100. @param mixed $port    Port name to look for.
  101. @param mixed $switch  Switch to ask
  102. @return mixed         Port index if found, false otherwise
  103. */
  104. function get_snmp_port_index($switch,$port)
  105. {
  106.    global $logger;
  107.    if ($switch && $port)
  108.    {
  109.       if $ports_on_switch ports_on_switch($switch) )              //Get the list of ports on the switch
  110.       {
  111.          return false;                                             # Error handling in ports_on_switch
  112.       }
  113.  
  114.       if $snmp_port_index get_snmp_index($port,$ports_on_switch))                   //Get port's index
  115.       {
  116.          $logger->logit("Port $port not found on switch $switch");
  117.          return false;
  118.       }
  119.       return $snmp_port_index;
  120.    }
  121.    else
  122.    {
  123.       return false;
  124.    }
  125. }
  126.  
  127. /**
  128. * Turn on a determined port identified by its index.
  129. @param mixed  $port_index             Port index according to SNMP
  130. @return boolean                       True if port was successfully switched on, false otherwise
  131. */
  132. function turn_on_port($switch,$port,$port_index=false)
  133. {
  134.    global $snmp_rw,$snmp_port,$logger;
  135.    if ($switch && $port)
  136.    {
  137.       $logger->debug("Turning on port $port on switch $switch",2);
  138.       if $port_index)
  139.       {
  140.          if $port_index get_snmp_port_index($switch$port))
  141.          {
  142.             return false;
  143.          }
  144.       }
  145.       #$oid=$snmp_port['ad_status'].'.'.$port_index;
  146.       $oid='1.3.6.1.2.1.2.2.1.7.'.$port_index;
  147.       $logger->debug("Setting $oid to 1 in $switch (Turning on)",3);
  148.       if (!snmpset($switch,$snmp_rw,$oid,'i',1))
  149.       {
  150.          $logger->logit("Could not turn on $switch port index $port_index");
  151.          return false;
  152.       }
  153.       else
  154.       {
  155.          return true;
  156.       }
  157.    }
  158.    else
  159.    {
  160.       return false;
  161.    }
  162. }
  163.  
  164.  
  165. /**
  166. * Turn off a determined port identified by its index.
  167. @param mixed  $port_index             Port index according to SNMP
  168. @return boolean                       True if port was successfully switched off, false otherwise
  169. */
  170. function turn_off_port($switch$port$port_index=false)
  171. {
  172.    global $snmp_rw,$snmp_port,$logger;
  173.    if ($switch && $port)
  174.    {
  175.       $logger->debug("Turning off port $port on switch $switch",2);
  176.       if $port_index)
  177.       {
  178.          if $port_index get_snmp_port_index($switch$port))
  179.          {
  180.             return false;
  181.          }
  182.       }
  183.       #$oid=$snmp_port['ad_status'].'.'.$port_index;
  184.       $oid='1.3.6.1.2.1.2.2.1.7.'.$port_index;
  185.       $logger->debug("Setting $oid to 2 in $switch (Turning off)",3);
  186.       if (!snmpset($switch,$snmp_rw,$oid,'i',2))
  187.       {
  188.          $logger->logit("Couldn't shut down port $port.");
  189.          return false;
  190.       }
  191.       else
  192.       {
  193.          return true;
  194.       }
  195.    }
  196.    else
  197.    {
  198.       return false;
  199.    }
  200. }
  201.  
  202. /**
  203. * Remove the type of one element and leave only the value.
  204. * This function is to be used when performing SNMP operations
  205. * Example: INTEGER:33
  206.            Returns: 33
  207. @param mixed $element         Element to remove type from
  208. @return mixed                 Value without type
  209. */
  210. function remove_type($element)
  211. {
  212.    if $element )
  213.       return false;
  214.    else
  215.       return trim(trim(substr($element,strpos($element,':')+1,strlen($element))),'"');
  216. }
  217.  
  218. /**
  219. * Ping a MAC address on a specific switch port
  220. @param mixed $mac     MAC address to ping
  221. @param mixed $switch  Switch we want to query
  222. @param mixed $port    switch port we want to query
  223. @param mixed $vlan    VLAN to use to perform the query
  224. @return boolean       True if MAC has been found on the switch port
  225. */
  226. function ping_mac2($mac,$switch,$port,$vlan)
  227. {
  228.    global $logger;
  229.    if (!$vlan)
  230.       return false;
  231.    $logger->debug("Querying if $mac is on port $port in switch $switch using vlan $vlan",2);
  232.    if (is_mac_on_port($mac,$switch,$port,$vlan))
  233.       return true;
  234.    else
  235.       return false;
  236. }
  237.  
  238. /**
  239. * Detect if a hub is attached to a certain port
  240. * If a hub is detected, suggest another vlan to avoid port flapping.
  241. * So far it is only an adaptation from the old algorithm
  242. * It hasn't been tested yet
  243. */
  244. function detect_hub ($REQUEST)
  245. {
  246.    global $logger$conf;
  247.    if ($conf->detect_hubs)
  248.    {
  249.       #Get vlan_groups
  250.       $query "SELECT vlan_group FROM vlan WHERE id='{$REQUEST->host->getNewVLAN_id()}';";
  251.       $logger->debug($query,3);
  252.       $new_vlan_group v_sql_1_select($query);
  253.  
  254.       $query "SELECT vlan_group FROM vlan WHERE id='{$REQUEST->host->getLastVLAN_id()}';";
  255.       $logger->debug($query,3);
  256.       $last_vlan_group v_sql_1_select($query);
  257.  
  258.       if (($new_vlan_group&& ($last_vlan_group == $new_vlan_group))
  259.       {
  260.          #Stay with the existing vlan, to preserve connectivity
  261.          $result $lvlan_id;
  262.       }
  263.       else
  264.       {
  265.          #Use the normal vlan for this device
  266.          $result $nvlan_id;
  267.       }
  268.  
  269.       $query=<<<EOF
  270. SELECT sid, AuthVlan, AuthLast FROM vmpsauth WHERE
  271.    TIME_TO_SEC(TIMEDIFF(NOW(), AuthLast)) < 7500 AND
  272.    sid!='{$REQUEST->host->getSid()}' AND
  273.    AuthVlan!='{$REQUEST->host->getNewVlan_id()}' AND
  274.    AuthPort='{$REQUEST->switch_port->getPort_id()}' ORDER BY AuthLast DESC;
  275. EOF;
  276.       $logger->debug($query,3);
  277.       $res mysql_query($query);
  278.       if (!$res)
  279.          return false;
  280.       if (mysql_num_rows($res0)
  281.       {
  282.          while (list($othersid$tempvlan$authlast)=mysql_fetch_array($res,MYSQL_NUM))
  283.          {
  284.             $query "SELECT mac FROM systems WHERE id='$othersid';";
  285.             $logger->debug($query,3);
  286.             $other_mac v_sql_1_select($query);
  287.  
  288.             $query "SELECT default_id FROM vlan WHERE id='$tempvlan';";
  289.             $logger->debug($query,3);
  290.             $other_vlan v_sql_1_select($query);
  291.  
  292.             if (ping_mac2($other_mac$REQUEST->switch_port->getSwitch_Name()$REQUEST->switch_port->getPort_Name(),$other_vlan))
  293.             {
  294.                $query "SELECT vlan_group FROM vlan WHERE id='$other_vlan';";
  295.                $logger->debug($query,3);
  296.                $other_vlan_group v_sql_1_select($query);
  297.                if (($other_vlan_group&& ($other_vlan_group == $new_vlan_group))
  298.                {
  299.                   $result $other_vlan;
  300.                   continue;
  301.                }
  302.                else
  303.                {
  304.                   $result=false;
  305.                }
  306.             }
  307.          }
  308.          return $result;
  309.       }
  310.    }
  311.    else
  312.    {
  313.       return false;
  314.    }
  315. }
  316.  
  317. /**
  318. * Wrapper around the restart_port script.
  319. * Restart a switch port
  320. @param mixed $port    Port name
  321. @param mixed $switch  Switch
  322. */
  323. function snmp_restart_port($port$switch{
  324.   global $lastseen_sms_restart,$logger;
  325.   #if ($lastseen_sms_restart)
  326.   {
  327.      /*$answer=syscall("./restart_port.php $port $switch");
  328.      debug1($answer);
  329.      logit("snmp_restart_port: $answer");*/
  330.      if (turn_off_port($switch$port&& turn_off_port($switch$port))
  331.         return turn_on_port($switch$port);
  332.      else
  333.         return false;
  334.   }
  335. }
  336.  
  337.  
  338. /**
  339. * Wrapper around snmp_restart_port
  340. @param integer $port_id       ID of the port we want to restart
  341. */
  342. function snmp_restart_port_id($port_id)
  343. {
  344.    global $logger;
  345.    if (is_numeric($port_id&& ($port_id>0))
  346.    {
  347.       $query="select p.name as port, s.ip as switch from port p inner join switch s on p.switch=s.id where p.id='$port_id' limit 1;";
  348.       $logger->debug($query,3);
  349.       $result=mysql_fetch_one($query);
  350.       if ($result)
  351.       {
  352.          $port=$result['port'];
  353.          $switch=$result['switch'];
  354.          return snmp_restart_port($port,$switch);
  355.       }
  356.       else
  357.          return false;
  358.    }
  359. }
  360.  
  361. /**
  362. * Tell whether a MAC address is on a certain port using SNMP
  363. @param mixed $mac     MAC to look for
  364. @param mixed $switch  Switch to look on
  365. @param mixed $port    Switch port to look on
  366. @param mixed $vlan    Vlan we'll use to look for that MAC address
  367. @return boolean       True if MAC found on that port, false otherwise
  368. */
  369. function is_mac_on_port($mac,$switch,$port,$vlan)
  370. {
  371.    global $snmp_ro,$logger;                                     //Read Only community
  372.    if (!$vlan)
  373.       return false;
  374.    $macs_on_vlan=@snmprealwalk($switch,"$snmp_ro@$vlan",'1.3.6.1.2.1.17.4.3.1.1');      //Obtain MAC address table
  375.    if (empty($macs_on_vlan))
  376.    {
  377.       $logger->logit("Couldn't establish communication with $switch using the SNMP_RO community.");
  378.       return false;
  379.    }
  380.    $macs_on_vlan=array_map("remove_type",$macs_on_vlan);
  381.    $macs_on_vlan=array_map("normalise_mac",$macs_on_vlan);
  382.    $mac_on=array_isearch($mac,$macs_on_vlan);                                           //Is this MAC in this switch?
  383.    if (empty($mac_on))
  384.       return false;                                                                     //No, return
  385.  
  386.    $bridge_port_number=@snmprealwalk($switch,"$snmp_ro@$vlan",'1.3.6.1.2.1.17.4.3.1.2')//Yes, get bridge port number for vlan
  387.    if (empty($bridge_port_number))
  388.       return false;
  389.    $bridge_port_number=array_map("remove_type",$bridge_port_number);
  390.    $bridge_port=array_find_key($mac_on,$bridge_port_number,'.',5);                      //Where is this MAC?
  391.    if (empty($bridge_port))
  392.       return false;
  393.  
  394.    $map_bridge_port=@snmprealwalk($switch,"$snmp_ro@$vlan","1.3.6.1.2.1.17.1.4.1.2");   //Map the bridge port to the ifIndex
  395.    if (empty($map_bridge_port))
  396.       return false;
  397.    $map_bridge_port=array_map("remove_type",$map_bridge_port);
  398.    $map_bridge=array_find_key($bridge_port,$map_bridge_port,'.',1);                   //Get the one that is of interest to us
  399.    if (empty($map_bridge))
  400.       return false;
  401.  
  402.    $port_names=@snmprealwalk($switch,"$snmp_ro@$vlan","1.3.6.1.2.1.31.1.1.1.1");        //Get the name of the interfaces
  403.    if (empty($port_names))
  404.       return false;
  405.    $port_names=array_map("remove_type",$port_names);
  406.    $port_learnt=array_find_key($map_bridge,$port_names,'.',1);                          //What is the port name of this interface?
  407.    if (strcmp($port_learnt,$port)==0)                                                   //Is this name equal to the one we provided??
  408.       return true;                                                                      //Yes, the MAC is on this port
  409.    else
  410.       return false;                                                                     //No, MAC is not using this port
  411. }
  412.  
  413. function ports_on_switch($switch)
  414. {
  415.    global $logger$snmp_rw$snmp_if$snmp_ifaces;
  416.    $oid '1.3.6.1.2.1.31.1.1.1.1';
  417.    if ($switch)
  418.    {
  419.       $logger->debug("Retrieving ports on $switch",2);
  420.       #$logger->debug("Sending {$snmp_if['name']} to $switch",3);
  421.       #$ports_on_switch=@snmprealwalk($switch,$snmp_rw,$snmp_if['name']);        //Get the list of ports on the switch
  422.  
  423.       $logger->debug("Sending $oid to $switch",3);
  424.       $ports_on_switch=@snmprealwalk($switch,$snmp_rw,$oid);        //Get the list of ports on the switch
  425.       if (empty($ports_on_switch))
  426.       {
  427.          $logger->logit("Couldn't establish communication with $switch with the defined parameters.");
  428.          return false;
  429.       }
  430.       $ports_on_switch=array_map("remove_type",$ports_on_switch);               //We are only interested in the value
  431.       $logger->debug(print_r($ports_on_switch,true),3);
  432.      return $ports_on_switch;
  433.    }
  434.    else
  435.    {
  436.       return false;
  437.    }
  438. }
  439.  
  440. function vm_type($switch)
  441. {
  442.    global $logger$snmp_rw$snmp_port;
  443.    if ($switch)
  444.    {
  445.       $logger->debug("Retrieving vlan membership types on $switch",2);
  446.       $logger->debug("Sending {$snmp_port['type']} to $switch",3);
  447.       $vm_type=@snmprealwalk($switch$snmp_rw$snmp_port['type']);
  448.       if (empty($vm_type))
  449.       {
  450.          $logger->logit"Couldn't establish communication with $switch with the defined parameters");
  451.          return false;
  452.       }
  453.       $vm_type=array_map("remove_type",$vm_type);
  454.       $logger->debug(print_r($vm_type,true),3);
  455.       return $vm_type;
  456.    }
  457.    else
  458.    {
  459.       return false;
  460.    }
  461. }
  462.  
  463. function vlans_on_switch($switch)
  464. {
  465.    global $logger$snmp_rw$snmp_vlan;
  466.    if ($switch)
  467.    {
  468.       $logger->debug("Retrieving vlans on $switch",2);
  469.       $logger->debug("Sending {$snmp_vlan['name']} to $switch",3);
  470.       $vlans_on_switch=@snmprealwalk($switch,$snmp_rw,$snmp_vlan['name']);         //Lookup of VLAN in the switch
  471.       if (empty($vlans_on_switch))
  472.       {
  473.          $logger->logit"Couldn't establish communication with $switch with the defined parameters");
  474.          return false;
  475.       }
  476.       $vlans_on_switch=array_map("remove_type",$vlans_on_switch);
  477.       $logger->debug(print_r($vlans_on_switch,true),3);
  478.       return $vlans_on_switch;
  479.    }
  480.    else
  481.    {
  482.       return false;
  483.    }
  484. }
  485.  
  486. function get_snmp_index($what$where)
  487. {
  488.    if $what || $where )
  489.       return false;
  490.    if is_array($where))
  491.       return false;
  492.    $what_oid=array_search($what,$where);                                //Is what we look for present in this array?
  493.    if (empty($what_oid))
  494.    {
  495.       return false;
  496.    }
  497.    $what_index=get_last_index($what_oid);
  498.    return $what_index;
  499. }
  500.  
  501. function set_port_as_dynamic($switch,$port$snmp_port_index=false)
  502. {
  503.    global $snmp_rw$snmp_port$logger;
  504.    $logger->debug("Setting port $port on switch $switch to dynamic",2);
  505.    if ($snmp_port_index)
  506.    {
  507.       if $snmp_port_index get_snmp_port_index($switch$port))                   //Get port's index
  508.       {
  509.          return false;
  510.       }
  511.    }
  512.  
  513.    if&nb