aboutsummaryrefslogtreecommitdiffstats
path: root/config/ifbwstats/ifbwstats_daemon.php
diff options
context:
space:
mode:
Diffstat (limited to 'config/ifbwstats/ifbwstats_daemon.php')
-rw-r--r--config/ifbwstats/ifbwstats_daemon.php352
1 files changed, 352 insertions, 0 deletions
diff --git a/config/ifbwstats/ifbwstats_daemon.php b/config/ifbwstats/ifbwstats_daemon.php
new file mode 100644
index 00000000..17026fba
--- /dev/null
+++ b/config/ifbwstats/ifbwstats_daemon.php
@@ -0,0 +1,352 @@
+<?php
+/*
+ /usr/local/www/ifbwstats_daemon.php
+
+ Contributed - 2010 - Zorac
+
+ interface read code using netstat as identifed below from
+ /usr/local/www/ifstats.php
+ Copyright (C) 2005-2006 Scott Ullrich (sullrich@gmail.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ command to run
+ /usr/local/bin/php -q /usr/local/www/ifbwstats_daemon.php &
+
+ command to interupt
+ kill -INT pid
+ kill -INT `cat /var/run/ifbwstats.lock`
+
+ command to force interface read without quitting daemon
+ kill -USR1 pid
+ kill -USR1 `cat /var/run/ifbwstats.lock`
+*/
+
+//required for SIGINT and SIGUSR1
+declare(ticks = 1);
+
+//allow php to run as a daemon and not time out
+set_time_limit(0);
+
+require_once("config.inc");
+define( 'LOCK_FILE', "/var/run/ifbwstats.lock" );
+
+function isLocked()
+{
+ # If lock file exists, check if stale. If exists and is not stale, return TRUE
+ # Else, create lock file and return FALSE.
+
+ if( file_exists( LOCK_FILE ) )
+ {
+ # check if it's stale
+ $lockingPID = trim( file_get_contents( LOCK_FILE ) );
+
+ # Get all active PIDs.
+ $pids = explode( "\n", trim( `ps | awk '{print $1}'` ) );
+
+ # If PID is still active, return true
+ if( in_array( $lockingPID, $pids ) )
+ {
+ return true;
+ }
+
+ # Lock-file is stale, so kill it. Then move on to re-creating it.
+ unlink( LOCK_FILE );
+ }
+ file_put_contents( LOCK_FILE, getmypid() . "\n" );
+ return false;
+}
+
+function sig_handler($signo)
+{
+ global $logfile;
+ switch ($signo)
+ {
+ case SIGTERM:
+ if (isset($logfile)) fwrite($logfile, date('Y-m-d H:i:s')." SIGTERM ".getmypid()." \n");
+ break;
+ case SIGINT:
+ global $_MYDAEMON_SHOULD_STOP;
+ $_MYDAEMON_SHOULD_STOP = true;
+ if (isset($logfile)) fwrite($logfile, date('Y-m-d H:i:s')." SIGINT ".getmypid()." \n");
+ break;
+ case SIGUSR1:
+ global $_MYDAEMON_SHOULD_QUERY;
+ $_MYDAEMON_SHOULD_QUERY = true;
+ if (isset($logfile)) fwrite($logfile, date('Y-m-d H:i:s')." SIGUSR1 ".getmypid()." \n");
+ break;
+ }
+}
+
+function interface_query($if)
+{
+ global $config;
+ global $g;
+
+ //set data files for appropriate interface
+ $wandatalastfile = '/tmp/ifbwstats-'.$if.'.last';
+ $wandataallfile = '/tmp/ifbwstats-'.$if.'.data';
+ $wandatabackupfile = '/cf/conf/ifbwstats-'.$if.'.data';
+
+ //assume max is 4GB because of the 32bit counter wrap
+ $maxbytesin = 4294967296;
+ $maxbytesout = 4294967296;
+
+ //create (or clear if already used) variables
+ $wandatacurrent = array();
+ $wandatalast = array();
+ $wandataall = array();
+
+ //----------start modified code insert from ifstats.php----------
+ $ifinfo = array();
+
+ $ifinfo['hwif'] = $config['interfaces'][$if]['if'];
+ if(!$ifinfo['hwif'])
+ $ifinfo['hwif'] = $if;
+
+ $ifinfo['if'] = $ifinfo['hwif'];
+
+ /* run netstat to determine link info */
+ $linkinfo = "";
+ unset($linkinfo);
+ exec("/usr/bin/netstat -I " . $ifinfo['hwif'] . " -nWb -f link", $linkinfo);
+ $linkinfo = preg_split("/\s+/", $linkinfo[1]);
+ if (preg_match("/\*$/", $linkinfo[0])) {
+ $ifinfo['status'] = "down";
+ } else {
+ $ifinfo['status'] = "up";
+ }
+
+ if(preg_match("/^enc|^tun/i", $ifinfo['if'])) {
+ $ifinfo['inbytes'] = $linkinfo[5];
+ $ifinfo['outbytes'] = $linkinfo[8];
+ } else {
+ $ifinfo['inbytes'] = $linkinfo[6];
+ $ifinfo['outbytes'] = $linkinfo[9];
+ }
+ //----------end modified code insert from ifstats.php----------
+
+ //check for errors
+ if ((file_exists($wandatalastfile)) && ($ifinfo['inbytes'] == 0) && ($ifinfo['outbytes'] == 0))
+ {
+ $ifinfo['status'] = "down";
+ }
+
+ if (is_NaN($ifinfo['inbytes']) || is_NaN($outinfo['inbytes']))
+ {
+ $ifinfo['status'] = "down";
+ }
+
+ if ($ifinfo['status'] == "up")
+ {
+ $wandatacurrent[0] = $ifinfo['inbytes'];
+ $wandatacurrent[1] = $ifinfo['outbytes'];
+
+ if (file_exists($wandatalastfile))
+ {
+ //read last read file
+ $wandatalast = explode("|", file_get_contents($wandatalastfile));
+ }
+ else
+ {
+ $wandatalast = $wandatacurrent;
+ }
+
+ if (!is_numeric($wandatalast[0]) || is_NaN($wandatalast[1]))
+ {
+ $wandatalast = $wandatacurrent;
+ }
+
+ $fp = fopen($wandatalastfile,"w") or die("Error Reading File");
+ fwrite($fp, $wandatacurrent[0].'|'.$wandatacurrent[1]);
+ fclose($fp);
+
+ //account for 4gig counter reset
+ if ($wandatacurrent[0] < $wandatalast[0]) $inbytes = ((4294967296 - $wandatalast[0]) + $wandatacurrent[0]);
+ else $inbytes = $wandatacurrent[0] - $wandatalast[0];
+ if ($wandatacurrent[1] < $wandatalast[1]) $outbytes = ((4294967296 - $wandatalast[1]) + $wandatacurrent[1]);
+ else $outbytes = $wandatacurrent[1] - $wandatalast[1];
+
+ //check to make sure inbytes and outbytes are possible, if not, 0 both and erase last data as it may be corrupt
+ if (($inbytes < 0) || ($inbytes > $maxbytesin) || ($outbytes < 0) || ($outbytes > $maxbytesout))
+ {
+ $inbytes = 0;
+ $outbytes = 0;
+ if (file_exists($wandatalastfile)) unlink ($wandatalastfile);
+ }
+
+ $foundfile = 'null';
+ if (file_exists($wandataallfile)) $foundfile = $wandataallfile;
+ else
+ {
+ if (file_exists($wandatabackupfile)) $foundfile = $wandatabackupfile;
+ }
+
+ //if no file is found, create new data, else read file and add to existing data
+ if ($foundfile == 'null')
+ {
+ $wanwritedata = date("Y-m-d").'|'.$inbytes.'|'.$outbytes;
+ }
+ else
+ {
+ //read data file
+ $wandataall = explode("\n", file_get_contents($foundfile));
+ $n = count($wandataall);
+
+ //if last line of data date matchs current date, add to totals, else add new line
+ $dataset = explode("|", $wandataall[$n-1]);
+ if ($dataset[0] == date("Y-m-d"))
+ {
+ $dataset[1]=$dataset[1]+$inbytes;
+ $dataset[2]=$dataset[2]+$outbytes;
+ $wandataall[$n-1]=$dataset[0].'|'.$dataset[1].'|'.$dataset[2];
+ }
+ else
+ {
+ $wandataall[$n] = date("Y-m-d").'|'.$inbytes.'|'.$outbytes;
+ }
+
+ //number of data entries (days)
+ $n = count($wandataall);
+
+ //if more than three years worth of data, trim data to 4 years (1460 days)
+ $start = 0;
+ if ($n > 1460) $start = $n - 1460;
+
+ //generate file data to write
+ for ($i=$start ; $i < ($n-1) ; $i++ ) $wanwritedata = $wanwritedata.$wandataall[$i]."\n";
+ $wanwritedata = $wanwritedata.$wandataall[$n-1];
+ }
+
+ //write data file
+ $fp = fopen($wandataallfile,"w") or die("Error Reading File");
+ fwrite($fp, $wanwritedata);
+ fclose($fp);
+ }
+ else
+ {
+ if (file_exists($wandatalastfile)) unlink ($wandatalastfile);
+ }
+}
+
+pcntl_signal(SIGTERM, 'sig_handler');
+pcntl_signal(SIGINT, 'sig_handler');
+pcntl_signal(SIGUSR1, 'sig_handler');
+
+global $config;
+global $g;
+global $_MYDAEMON_SHOULD_STOP;
+global $_MYDAEMON_SHOULD_QUERY;
+
+//logging -> yes or no
+$logging = $config['installedpackages']['ifbwstats']['config'][0]['logging'];
+
+if ($logging == 'yes')
+{
+ global $logfile;
+ $logfile = fopen("/tmp/ifbwstats-daemon.log","a") or die("Error Reading File");
+ $parentpid = getmypid();
+ fwrite($logfile, date('Y-m-d H:i:s')." Startup - Parent PID is: ".$parentpid."\n");
+}
+
+if ($g['platform'] == 'cdrom')
+{
+ fwrite($logfile, date('Y-m-d H:i:s')." Daemon will not run on CD Rom platform, exiting... \n");
+ fclose ($logfile);
+ exit ();
+}
+if (isLocked())
+{
+ if ($logging == 'yes') fwrite($logfile, date('Y-m-d H:i:s')." Daemon is already running, exiting second instance (".getmypid().") \n");
+ fclose ($logfile);
+ exit ();
+}
+
+// endless loop
+while (1)
+{
+ if (isset($_MYDAEMON_SHOULD_STOP) AND $_MYDAEMON_SHOULD_STOP) break;
+ $pidA = pcntl_fork();
+ if($pidA)
+ {
+ // parent process runs here
+ // wait until the child has finished processing then end the script
+ pcntl_waitpid($pid, $status, WUNTRACED);
+ //calc seconds to midnight
+ $sleeptime = (mktime(23, 59, 55, date ('m, d, Y'))) - time();
+ //use whichever is less, seconds to midnight or interval, running script just prior to midnight insure accurate daily reporting as standard timing interval could be as great at 50min
+ if (($sleeptime > $config['installedpackages']['ifbwstats']['config'][0]['intervalrun']) || ($sleeptime < 5)) $sleeptime = $config['installedpackages']['ifbwstats']['config'][0]['intervalrun'];
+ if ($logging == 'yes') fwrite($logfile, date('Y-m-d H:i:s')." Parent (".$parentpid.") Sleep for: ".$sleeptime."\n");
+ for ($i=0; $i<$sleeptime; $i++)
+ {
+ if ((isset($_MYDAEMON_SHOULD_QUERY) AND $_MYDAEMON_SHOULD_QUERY) || (isset($_MYDAEMON_SHOULD_STOP) AND $_MYDAEMON_SHOULD_STOP))
+ {
+ $_MYDAEMON_SHOULD_QUERY = false;
+ break;
+ }
+ else sleep (1);
+ }
+ }
+ else
+ {
+ //child process runs here
+ if ($logging == 'yes') fwrite($logfile, date('Y-m-d H:i:s')." Child Process ". getmypid(). " Reading Interfaces... (Parent: ".$parentpid.")\n");
+ if ($config['installedpackages']['ifbwstats']['config'][0]['ifmon'] != 'all') interface_query($config['installedpackages']['ifbwstats']['config'][0]['ifmon']);
+ else
+ {
+ foreach ($config[interfaces] as $if => $value)
+ {
+ interface_query($if);
+ }
+ }
+ exit (0);
+ }
+}
+
+//run query one last time
+if ($logging == 'yes') fwrite($logfile, date('Y-m-d H:i:s')." Parent Process ". getmypid(). " Reading Interfaces One Last Time... \n");
+if ($config['installedpackages']['ifbwstats']['config'][0]['ifmon'] != 'all') interface_query($config['installedpackages']['ifbwstats']['config'][0]['ifmon']);
+else
+{
+ foreach ($config[interfaces] as $if => $value)
+ {
+ interface_query($if);
+ }
+}
+// backup data files to conf dir on exit
+if ($g['platform'] != 'pfSense') exec ('/etc/rc.conf_mount_rw');
+exec('cp /tmp/ifbwstats-*.data /cf/conf/');
+if ($g['platform'] != 'pfSense') exec ('/etc/rc.conf_mount_ro');
+
+if ($logging == 'yes')
+{
+ fwrite($logfile, date('Y-m-d H:i:s')." Shutdown Parent ".$parentpid." \n");
+ fclose ($logfile);
+}
+
+if( file_exists( LOCK_FILE ) ) unlink( LOCK_FILE );
+
+exit (0);
+
+?>
+