Source for file funcs.inc.php

Documentation is available at funcs.inc.php

  1. <?php
  2. /**
  3.  * /opt/nac/bin/funcs.inc.php
  4.  *
  5.  * common PHP functions used by several scripts
  6.  *
  7.  * PHP version 5
  8.  *
  9.  * LICENSE: This program is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU General Public License as published
  11.  * by the Free Software Foundation.
  12.  *
  13.  * @package            FreeNAC
  14.  * @author            Sean Boran (FreeNAC Core Team)
  15.  * @copyright        2007 FreeNAC
  16.  * @license            http://www.gnu.org/copyleft/gpl.html   GNU Public License Version 2
  17.  * @version            SVN: $Id$
  18.  * @link                http://www.freenac.net
  19.  *
  20.  */
  21.  
  22.  
  23. /**
  24. * Common PHP functions used by several scripts
  25. */
  26.  
  27. chdir(dirname(__FILE__));
  28. set_include_path("./:../lib/:../");
  29.  
  30. /**
  31. * Load automagically a file containing the class specified by classname
  32. @param object $classname    Class to load
  33. */
  34. function __autoload($classname)
  35. {
  36.    if (is_readable("../lib/$classname.php"))
  37.       require_once "../lib/$classname.php";
  38.    else if (is_readable("../enterprise/$classname.php"))
  39.       require_once "../enterprise/$classname.php";
  40. }
  41.  
  42. /**
  43. * Get configuration variables from config file
  44. */
  45. require_once 'etc/config.inc';
  46.  
  47. /**
  48. @global object $conf        Contains configuration parameters from the config table
  49. @global object $logger    Provides for logging facilities
  50. */
  51. $logger=Logger::getInstance();
  52.  
  53. /**
  54. * Tell if an IPv4 address is valid (well-formed)
  55. @param string $ip    IP address to test
  56. *  return boolean    True if IP address is valid, false otherwise
  57. */
  58. function valid_ip($ip)
  59. {
  60.    $tmp explode("."$ip);
  61.    if (count($tmp!= 4)
  62.    {
  63.       return false;
  64.    }
  65.    else
  66.    {
  67.       foreach($tmp AS $sub)
  68.       {
  69.          if (!preg_match("/^([0-9]{1,3})$/"$sub))
  70.          {
  71.             return false;
  72.          }
  73.          if (($sub 1|| ($sub 255))
  74.          {
  75.             return false;
  76.          }
  77.       }
  78.    }
  79.    return true;
  80. }
  81.  
  82. /**
  83. * Get WINS Name from IP Address
  84. * Original contribution from johnboy68
  85. @param string $ip   Ip Address
  86. @return string      WINS Name
  87. */
  88. function getwinsfromip($ip)
  89. {
  90.    #Try to avoid command injection
  91.    $ip ereg_replace("[|&;`]"""$ip);
  92.    if (valid_ip($ip))
  93.    {
  94.       return false;
  95.    }
  96.    /*
  97.    Successful query
  98.    
  99.    added interface ip=192.168.201.216 bcast=192.168.201.255 nmask=255.255.255.0
  100.    Socket opened.
  101.    Looking up status of 192.168.202.222
  102.         HOST59          <00> -         M <ACTIVE>
  103.         WORK            <00> - <GROUP> M <ACTIVE>
  104.         HOST59          <20> -         M <ACTIVE>
  105.         WORK            <1e> - <GROUP> M <ACTIVE>
  106.         WORK            <1d> -         M <ACTIVE>
  107.         ..__MSBROWSE__. <01> - <GROUP> M <ACTIVE>
  108.  
  109.         MAC Address = CC-00-FF-EE-EE-EE
  110.    */
  111.  
  112.    /*
  113.    Failed query
  114.    
  115.    added interface ip=192.168.201.216 bcast=192.168.201.255 nmask=255.255.255.0
  116.    Socket opened.
  117.    Looking up status of 192.168.202.223
  118.    No reply from 192.168.202.223
  119.    */
  120.  
  121.    /*
  122.    Case where we are trying to lookup the hostname of the server running this script
  123.  
  124.    added interface ip=192.168.201.216 bcast=192.168.201.255 nmask=255.255.255.0
  125.    Socket opened.
  126.    Looking up status of 192.168.202.216
  127.    No reply from 192.168.202.216   
  128.    */
  129.  
  130.    #Call nmblookup for this ip address
  131.    $command "nmblookup -A $ip";
  132.    $output shell_exec($command);
  133.    $foutput explode("$ip",$output)// all after the IP
  134.    $foutput explode(" ",$foutput[1]);    // fields sep. by spaces
  135.    $foutput trim($foutput[0]);           // get first filed, i.e. STNS59 above
  136.    # Check if we have a result;
  137.    if ($foutput=="No")
  138.    {
  139.       #No result, return IP address
  140.       return mysql_escape_string($ip);
  141.    }
  142.    else if (strpos($ip,"bcast="))
  143.    {
  144.       return mysql_escape_string($ip);
  145.    }
  146.    else
  147.    {
  148.       #Return the hostname we've just learnt
  149.       return mysql_escape_string($foutput);
  150.    }
  151. }
  152.  
  153. /**
  154. * Converts a vlan id to a vlan name
  155. @param integer $vlanID     Vlan ID
  156. @return mixed         Vlan name
  157. */
  158. function vlanId2Name($vlanID{
  159.    // Todo: Proper Error Handling, and use better Database abstraction
  160.    $vlan_name NULL;
  161.    if (is_integer($vlanID))
  162.    {
  163.       $vlan_name=v_sql_1_select("select default_name from vlan where id='$vlanID' limit 1");
  164.       if ($vlan_name !== false)
  165.       {
  166.          return $vlan_name;
  167.       }
  168.       else
  169.       {
  170.          return false;
  171.       }
  172.    }
  173.    else
  174.    {
  175.       return false;
  176.    }
  177. }
  178.  
  179. /**
  180. * Get the last number of an SNMP OID
  181. * The OID is separated by dots and we use them as a separator.
  182. * Example: OID=1.2.3.4.5.6.7.8
  183. *       Returns: 8
  184. @param mixed $oid        OID of interest
  185. @return mixed            Last part of the OID.
  186. */
  187. function get_last_index($oid)                                                  
  188. {
  189.    if $oid )
  190.       return false;
  191.    $temp=explode('.',$oid);
  192.    return $temp[count($temp)-1];
  193. }
  194.  
  195. /**
  196. * Returns the difference between 2 dates in secs
  197. @param mixed $date1            Date to substract from
  198. @param mixed $date2            Date
  199. @return mixed                Difference in second between those 2 dates
  200. */
  201. function time_diff($date1,$date2)
  202. {
  203.    if ($date1 && $date2)
  204.    {
  205.       $temp=explode(' ',$date1);
  206.       //Return false if there are no spaces in $date1
  207.       if (count($temp== 1)
  208.          return false;
  209.       $time_info_1=explode(':',$temp[1]);
  210.       //Return false because the date format is not what we expected
  211.       if strcmp($time_info_1[0],$temp[1]===)
  212.          return false;
  213.       $date_info_1=explode('-',$temp[0]);
  214.       //Return false because the date format is not what we expected
  215.       if strcmp($date_info_1[0]$temp[0]=== )
  216.          return false;
  217.       $temp=explode(' ',$date2);
  218.       //Return false if there are no spaces in $date2
  219.       if (count($temp== 1)
  220.          return false;
  221.       $time_info_2=explode(':',$temp[1]);
  222.       //Return false because the date format is not what we expected
  223.       if strcmp($time_info_2[0],$temp[1]===)
  224.          return false;
  225.       $date_info_2=explode('-',$temp[0]);
  226.       //Return false because the date format is not what we expected
  227.       if strcmp($date_info_2[0]$temp[0]=== )
  228.          return false;
  229.       $time1=mktime((int)$time_info_1[0],(int)$time_info_1[1],(int)$time_info_1[2],(int)$date_info_1[1],(int)$date_info_1[2],(int)$date_info_1[0]);
  230.       $time2=mktime((int)$time_info_2[0],(int)$time_info_2[1],(int)$time_info_2[2],(int)$date_info_2[1],(int)$date_info_2[2],(int)$date_info_2[0]);
  231.       if ( ($time1 !== false&& ($time2 !== false) )
  232.       {
  233.          $time=$time2-$time1;
  234.          return $time;
  235.       }
  236.       else
  237.       {
  238.          //Invalid arguments
  239.          return false;
  240.       }
  241.    }
  242.    else
  243.    {
  244.       //No dates were specified
  245.       return false;
  246.    }
  247. }
  248.  
  249. /**
  250. * Wrapper around the debug method part of the logger object.
  251. * Logs to debug level 1
  252. * It will be soon depreciated. Present only for backwards compatibility.
  253. @param mixed $msg Message to log
  254. */
  255. function debug($msg{
  256.    global $logger;
  257.    $msg=rtrim($msg);
  258.    if (strlen($msg)>0{
  259.       $logger->debug($msg);
  260.    }
  261.  
  262. /**
  263. * Wrapper around the debug method part of the logger object.
  264. * Logs to debug level 1
  265. * It will be soon depreciated. Present only for backwards compatibility.
  266. @param mixed $msg    Message to log
  267. */
  268. function debug1($msg{
  269.   global $logger;
  270.   $msg=rtrim($msg);
  271.   if (strlen($msg)>0{
  272.      $logger->debug($msg);
  273.   }
  274. }
  275.  
  276. /**
  277. * Wrapper around the debug method part of the logger object.
  278. * Logs to debug level 2
  279. * It will be soon depreciated. Present only for backwards compatibility.
  280. @param mixed $msg     Message to log
  281. */
  282. function debug2($msg{
  283.   global $logger;
  284.   $msg=rtrim($msg);
  285.   if (strlen($msg)>0{
  286.      $logger->debug($msg,2);
  287.   }
  288. }
  289.  
  290. /**
  291. * Wrapper around the logit method part of the logger object.
  292. * It will be soon depreciated. Present only for backwards compatibility.
  293. @param mixed $msg     Message to log
  294. */
  295. function logit($msg{
  296.   global $logger;
  297.   $msg=rtrim($msg);
  298.   $logger->logit($msg);
  299. }
  300.  
  301. /**
  302. * Write key events to naclog which is visible from the GUI
  303. * This should NOT be called from a secondary server, i.e.
  304. * avoid it in vmpsd_external
  305. @param mixed $level    Level of severity of the message
  306. @param mixed $msg    Message to log
  307. */
  308. function log2db($level$msg)
  309. {
  310.   if $level && $msg )
  311.   {
  312.      global $connect,$logger;
  313.      $msg=rtrim($msg);
  314.      if (strlen($msg)>{
  315.        db_connect();                 // just in case its not connected
  316.        #$query="INSERT DELAYED INTO naclog "
  317.        if (isset($_SERVER['HOSTNAME']))
  318.           $host=$_SERVER['HOSTNAME'];
  319.        else
  320.           $host='';
  321.        $query="insert into naclog set what='".mysql_real_escape_string($msg)."', host='$host', priority='".$level."'";
  322.        #$query="INSERT INTO naclog "
  323.        #  . "SET what='" . mysql_real_escape_string($msg )  . "', "
  324.        #  . "host='"     . mysql_real_escape_string($_SERVER["HOSTNAME"]) . "', "
  325.        #  . "priority='$level' ";
  326.        #$logger->logit("$query\n");
  327.        $res mysql_query($query$connect);
  328.        if (!$res
  329.        
  330.           $logger->logit('Cannot write to vmplog table: ' mysql_error()LOG_ERR)
  331.           return false;
  332.        }
  333.        return true;
  334.      }
  335.      else
  336.         return false;
  337.    }
  338.    else
  339.       return false;
  340.   // To view recent entries:
  341.   // select * from naclog ORDER BY datetime DESC LIMIT 5;
  342. }
  343.  
  344.  
  345. ## log2db3: write to naclog if debug level=3 
  346. function log2db3($msg)
  347. {
  348.   if ($msg)
  349.   {
  350.      global $connect$logger;
  351.      $level='debug';
  352.      $msg=rtrim($msg);
  353.      if (($logger->getDebugLevel()==3&& (strlen($msg)>0) ) {
  354.         db_connect();                 // just in case its not connected
  355.         #$query="INSERT INTO naclog "
  356.         $query="INSERT DELAYED INTO naclog "
  357.           . "SET what='" $msg   "', "
  358.           . "priority='" $level "' ";
  359.         #$logger->logit("$query\n");
  360.         $res mysql_query($query$connect);
  361.         if (!$res
  362.         
  363.            $logger->logit('Cannot write to vmplog table: ' mysql_error()LOG_ERR)
  364.            return false;
  365.         }
  366.         return true;
  367.       }
  368.       else
  369.          return false;
  370.    }
  371.    else
  372.       return false;
  373. }
  374.  
  375. /**
  376. * Creates a connection to the MySQL database with the parameters defined in config.inc
  377. */
  378. function db_connect()
  379. {
  380.    global $connect$dbhost$dbuser$dbpass$dbname$logger;
  381.  
  382.    if $connect=@mysql_connect($dbhost$dbuser$dbpass))
  383.    {
  384.       $logger->logit("Could not connect to mysql: " mysql_error()LOG_ERR);
  385.       exit(1);
  386.    }
  387.    if @mysql_select_db($dbname$connect))
  388.    {
  389.       $logger->logit("Could not select database: ".mysql_error()LOG_ERR);
  390.       exit(1);
  391.    }
  392. }
  393.  
  394. /**
  395.  * Abstract calling of unix commands.
  396.  * Problem: popen does not pass back command success
  397.  * so syscall cannot say if the command works.
  398.  * @param mixed $command    Command to be executed
  399.  * @return mixed        Result from that command
  400.  */
  401. function syscall($command){
  402.    if ($command)
  403.    {
  404.       $result='';
  405.       #if ( $proc = popen("($command) ","r") ) {
  406.       if $proc popen("($command) 2>&1","r") ) {
  407.           while (!feof($proc))
  408.             $result .= fgets($proc1000);
  409.           pclose($proc);
  410.           #debug2("syscall(): executed $command, RETURN=$result");
  411.           return $result;
  412.       #} else {       # will never be reaches, popen does not pass back command success
  413.       #  logit("syscall error ", $proc);
  414.       #  return undef;
  415.       }
  416.       else
  417.          return false;
  418.    }
  419.    else return false;
  420. }
  421.  
  422. function ping_mac($mac)
  423. # Return: true=Ping successful
  424. {
  425.   db_connect();
  426.   global $connect$logger;
  427.   
  428.   $query="SELECT r_ip from systems "
  429.         . " WHERE mac='" $mac "'";
  430.         #$logger->logit("$query\n");
  431.         $resmysql_query($query$connect);
  432.         if (!$res
  433.         
  434.            $logger->logit('Invalid query: ' mysql_error(),LOG_ERR)
  435.            exit(1);
  436.         }
  437.  
  438.    $rowcount=mysql_num_rows($res);
  439.  
  440.    if ($rowcount==1{
  441.      list($ip)=mysql_fetch_array($resMYSQL_NUM);
  442.      if (strlen($ip)<8{
  443.        debug2("Invalid IP - $ip for mac $mac");
  444.        return(false)
  445.      }
  446.      #debug2("ping $ip - $mac");
  447.      logit("ping $ip - $mac");
  448.  
  449.      // ping for max 1 sec, make sure it does not sty running/hung
  450.      #$answer=syscall("ping -c 1 -w 1 $ip");
  451.      $answer=syscall("ping -c 3 -w 1 $ip");
  452.      syscall("killall ping");
  453.      if preg_match("/0 received,/m"$answer) ) {
  454.        #$logger->logit "Ping Error: $answer\n";
  455.        logit("Ping Error no answer: $answer");
  456.        return false;
  457.  
  458.      else if preg_match("/\d+ received,/m"$answer) ) {
  459.        #$logger->logit "Ping OK\n";
  460.        logit("Ping OK: $answer");
  461.        #logit("Ping OK");
  462.        return true;
  463.  
  464.      else {
  465.        #$logger->logit "Ping Error: $answer\n";
  466.        logit("Ping Error: $answer");
  467.        return false;
  468.      }
  469.    else {   #
  470.      logit("No IP found for $mac");
  471.      return false;
  472.    }
  473. }
  474.  
  475. /**
  476. * Perform a case insensitive search for a given value in an array and return its key
  477. @param mixed $str    Value to look for
  478. @param array $array    Array to look in
  479. @return mixed        Key for that value, or false otherwise
  480. */
  481. function array_isearch($str,$array)                    
  482. {
  483.    if ($str && $array)
  484.    {
  485.       if is_array($array))
  486.          return false;
  487.       foreach($array as $k => $v)
  488.       {
  489.          if (strcasecmp($v,$str)==0)
  490.          {
  491.             return $k;
  492.          }
  493.       }
  494.       return false;
  495.    }
  496.    else
  497.       return false;
  498. }
  499.  
  500. /**
  501. * Perform a case insensitive search for a given value in a bi-dimensional array and return its key
  502. @param mixed $str     Value to look for
  503. @param array $array   Array to look in
  504. @return mixed         Key for that value, or false otherwise
  505. */
  506. function array_multi_isearch($str,$array)
  507. {
  508.    if ($str && $array)
  509.    {
  510.       if is_array($array))
  511.          return false;
  512.       foreach($array as $k)
  513.       {
  514.          if (array_isearch($str,$k))
  515.             return $k;
  516.       }
  517.       return false;
  518.    }
  519.    else
  520.       return false;
  521. }
  522.  
  523. /**
  524. * Search the array for a given key and return its value, but using tokenizers
  525. @param mixed $str             String to look for
  526. @param array $array           Array where we should look in
  527. @param mixed $token           Token to use as a separator
  528. @param integer $number        The number of parts we want to return
  529. @return mixed                 Desired value or false otherwise
  530. */
  531. function array_find_key($str,$array,$token,$number)   
  532. {
  533.    if ($str && $array && $token && $number)
  534.    {
  535.       if is_array($array))
  536.          return false;
  537.       #What if we have a string without tokens? 
  538.       #Add the token to the beginning of the string
  539.       #so we cover that case without affecting the strings
  540.       #containing the token 
  541.       $str "$token$str";
  542.       foreach($array as $k => $v)
  543.       {
  544.          if (strcasecmp(str_get_last($k,$token,$number),str_get_last($str,$token,$number))==0)
  545.          {
  546.             return $v;
  547.          }
  548.       }
  549.       return false;
  550.    }
  551.    else
  552.       return false;
  553. }
  554.  
  555. /**
  556. * Search the array for a given value and return it, but using tokenizers
  557. @param mixed $str        String to look for
  558. @param array $array        Array where we should look in
  559. @param mixed $token        Token to use as a separator
  560. @param integer $number    The number of parts we want to return
  561. @return mixed            Desired value or false otherwise
  562. */
  563. function array_find_value($str,$array,$token,$number)   
  564. {
  565.    if ($str && $array && $token && $number)
  566.    {
  567.       if is_array($array))
  568.          return false;
  569.       foreach($array as $k => $v)
  570.       {
  571.          if (strcasecmp(str_get_last($v,$token,$number),str_get_last($str,$token,$number))==0)
  572.          {
  573.             return $v;
  574.          }
  575.       }
  576.       return false;
  577.    }
  578.    else
  579.       return false;
  580. }
  581.  
  582. /**
  583. * Return the last parts of a tokenized string
  584. @param $string    String to split
  585. @param $token        Token to use to split the string
  586. @param $number    How many parts we want to return
  587. @return mixed        Desired string
  588. */
  589. function str_get_last($string,$token,$number)          
  590. {
  591.    $final='';
  592.    if