<?php

/**
 * netstat-kiss.php - Show online status of hosts and services
 *
 * This script is intended to provide a simplified, easily comprehensible
 * and aesthetically pleasing overview of the online status of hosts and
 * services. Checks are done in real-time but they only check whether
 * a port is open (which might be sufficient if your hosts are monitored
 * by full-blown monitoring tools anyway and all you want is a simple
 * interface for e.g. users or clients).
 *
 * This file is the KISS version of the original netstat.php.
 * netstat-kiss.php tries to follow the KISS principle even more
 * (cf. https://en.wikipedia.org/wiki/KISS_principle )
 *
 * Requirements: fsockopen(), for ICMP pings also exec()
 *
 * (License + History: see also end of file)
 *
 * @author     Andreas Schamanek <https://andreas.schamanek.net>
 * @license    GPL <https://www.gnu.org/licenses/gpl.html>
 * @copyright  (c) 2012 Andreas Schamanek
 *
 */
$version '<a href="https://wox.at/as/sysadmin/netstat/">netstat-kiss.php</a> by <a href="https://wox.at/as/">Andreas Schamanek</a> ~ v0.02 ~ 2019-01-28 ~ <a href="https://www.gnu.org/licenses/gpl.html">GPL licensed</a>';

/* --- Settings --- */
//
// Either change settings here, or, better, copy them to a file called
// netstat.conf.php and make sure the file is readable for the web server
// (e.g. chmod 644 netstat.conf.php)

// $checks (use pipes (|) with care ;)
//   syntax: ' host or IP to check | port | description '
//     if $port = 'ping' an ICMP ping will be executed
//     if $port = 'headline' $host is printed as a headline
$checks = array(
 
'Examples testing localhost |headline',
    
'localhost | ping| ICMP ping (ping)',
    
'localhost |  80 | WWW server (port 80)',
    
'127.0.0.2 | 443 | WWW server (SSL, port 443)',
    
'127.0.0.1 |  22 | SSH server (port 22)',
    
'127.0.0.3 |  21 | FTP server (port 21)',
);

$configfile 'netstat.conf.php';
$title 'Our Network Status';
$headline $title;
error_reporting(0);
$alertfile='netstat.txt'// will be shown ahead if readable
$ping_command 'ping -c3 -w1 -q'// maybe try 'ping -l3 -c3 -w1 -q'
$ping6_command 'ping6 -c3 -w1 -q';
$timeout 6// fsockopen timeout, leave it as it is :)
$online 'Online';
$offline 'Offline';
$datetime 'l, F j, Y, H:i:s T';

// HTML/page header
$htmlheader = <<<EOH
<!doctype html><html>
<head>
<title>
$title</title>
<meta charset="utf-8">
<meta http-equiv="Refresh" content="399">
<meta name="description" content="Online status of hosts and services provided by netstat.php" />
<meta name="viewport" content="width=device-width; initial-scale=1.0">
<style type="text/css"><!--
body { font-family: Verdana, "Lucida Sans", Arial, Helvetica, sans-serif; font-size: 87%; }
html>body { font-size: 14px; /* for FF */ }
div#container { width: 37em; margin: 0 auto; position: relative; }
.datetime { font-size: 87%; font-weight: bolder; text-align: center; margin-bottom: 2em; }
.version { font-size: 73%; text-align: center; color: black; background: white; }
.version a { font-weight: bolder; color: black; text-decoration: none; }
h1 { color: #500000; border-bottom: 1px solid #999999; text-align: center; margin-bottom: 1em; margin-top: 2em; }
div#alert { border: 1px solid red; padding: 0.2em 1.5em; margin: 1em 0; }
.status_table { border: 1px solid #333333; border-collapse: collapse; width: 100%; }
.status_table td { color: #333333; border: 1px solid #444444; padding: 0.3em; }
.status_table td.headline { font-weight: bolder; background-color: #CFCCCC; padding: 0.4em 0.4em 0.3em 1.5em; }
.hidden { display: none !important; }
.
$online { background-color: #D9FFB3; padding-left: 0.8em !important; }
.
$offline { background-color: #FFB6B6; padding-left: 0.8em !important; }
--></style>
</head>
<body>
<div id="container">
EOH;

// HTML/page footer
$htmlfooter "</div>\n</body>\n</html>";

/* That's it */

// ------------------------------------------------- main part of script

// including $configfile if available
if (file_exists($configfile) && is_readable($configfile)) @include($configfile);

// output HTML/page header
echo $htmlheader;

// headline, date and time and start of table
echo "<h1>$headline</h1>\n";
if (
$datetime) echo '<p class="datetime">as of ' date($datetime) . "</p>\n";

// show the contents of $alertfile if it is readable and larger than 7 bytes
if (file_exists($alertfile))
{
    
clearstatcache(true$alertfile);
    if ((
is_readable($alertfile) && (filesize($alertfile) > 7)))
    {
        echo 
"<div id=\"alert\">\n";
        @include(
$alertfile);
        echo 
"</div>\n";
    }
}

// flush output buffers (if any)/send content to browser
@ob_flush(); @flush();

echo 
'<table class="status_table">' "\n";

// main loop of checks
foreach ($checks as $check)
{
    
$status $offline;  // default state
    
$diagnostics '';   // mouse-over for tooltips
    
$output true;      // print a line or print no line
    
list($host,$port,$description) = explode('|',"$check||"); // the 2 extra '|'s are to avoid notices about undefined offsets
    
$host trim($host);
    
$port trim($port);

    switch (
$port)
    {
        case 
''// ignore lines with empty or no "ports", and ignore ...
        
case (substr($port,0,1)=='-'): // negative ports, '-ping', and
            // any "port" starting with '-' is considered a disabled check
            
$output false; break;
        case 
'headline'// print a headline within the status table
            // we enclose it with invisible <br>== == for nicer text output
            
echo '<tr><td class="headline" colspan="2">'
                
'<span class="hidden">&nbsp;<br />==&nbsp;</span>'
                
$host
                
'<span class="hidden">&nbsp;==</span>'
                
"</td></tr>\n";
            
$output false; break;
        case 
'ping'// do an ICMP ping
            
$ping=exec("$ping_command $host",$pingoutput,$pingreturn);
            
// Continues on into ping6 as they share all but the command.
        
case 'ping6'// do an ICMP IPv6 ping
            
if (!isset($ping))
            {
                
$ping=exec("$ping6_command $host",$pingoutput,$pingreturn);
            }
            if(
strlen($ping)>10)
            {
                
// strlen($ping)>10 works around a bug in Debian ping (", pipe 3")
                // https://bugs.debian.org/456192
                
$status $online$diagnostics "$ping :: $pingreturn";
            }
            else 
$diagnostics "$ping :: $pingreturn";
            unset(
$ping);
            break;
        default: 
// look if a TCP connection to port can be opened
            
$time_start microtime(true);
            
$fp = @fsockopen($host$port$errno$errstr$timeout);
            
$time_end microtime(true);
            
$time number_format(($time_end $time_start)*1000,1);

            if (
$fp)
            {
                
// fsockopen worked, service is online
                
$status $online;
                
$diagnostics "$time ms";
                
fclose($fp);
            }
            else if (
$errno<0) { $diagnostics "errno=$errno; Host unknown?"; }
            else { 
$diagnostics $errstr; }
    }

    
// output results
    
if ($output)
    echo 
"<tr><td>$description</td><td class=\"$status\" title=\"$diagnostics\">$status</td></tr>\n";

    
// flush output buffers (if any)/send content to browser
    
@ob_flush(); @flush();
}

echo 
"</table>\n";

// output $version and HTML/page footer
if (!empty($version)) echo "<p class=\"version\">$version</p>\n";
echo 
"$htmlfooter\n";

/*
 * License
 *
 * This script is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This script is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this script; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA

 * History
 *
 * 0.01 * 2012-08-05  KISSified netstat-kiss.php based on netstat.php v0.15
 * 0.02 * 2019-01-28  merged minor tweaks from netstat.php v0.16
 *
 */