#!/usr/bin/php
<?php

/*
 * Nagios Plugin:
 * - Retrieves SNMP Table.
 * - Write table as performance data output
 * - One row (entry) per line.
 */

$params['host'] = '127.0.0.1';
$params['verbose'] = 0;
$params['snmp_version'] = '1';
$params['snmp_comname'] = 'public';
$params['snmp_options'] = '';
$params['snmp_table'] = 'IF-MIB::ifTable';
$params['output_perf'] = true;
$params['output_columns'] = array();
$params['output_indexes'] = array(0);
$params['output_indexes_sep'] = '_';
$params['output_columns_sep'] = '|';
$params['output_format'] = 'serialized';
$params['output_file'] = '';
$params['output_dir'] = '/var/tmp';


function show_help($prog)
{
  echo "$prog [-H <hostname/ip>][-v <1|2c>][-c <com_name>][-T <table_name>'][-cols <0-n comma sep>][-indexes <0-n comma sep>]\n" .
       "[-indexes_sep <c>][-cols_sep <c>][-oformat <serialized|json|rrdgraph|gnuplot>][-odir <output_dir>][-ofile <output_file>][-P][-h][-v]\n\n";
  echo "    Examples: \n";
  echo "    1. Retrieve IWC-VISHNU-MIB::topDomainsTable table. Output table as performance data. First column as row index.\n";
  echo "       Concatenated columns as row value using '|' as delimiter. Finally, serialize (PHP) table (all) and store into '/var/tmp/snmp_table.serialized'.\n\n";
  echo "       $prog -H 10.1.1.10 -T IWC-VISHNU-MIB::topDomainsTable\n\n";
  echo "       SNMP OK |1=1|0.10.in-addr.arpa|2461850 2=2|cebu.infoweapons.com|398873 3=3|www.google.com|95652 4=4|soliddns1.infoweapons.com|91460 5=5|\n";
  echo "       soliddns2.infoweapons.com|69187 6=6|0.2.ip6.arpa|55596 7=7|com.infoweapons.com|39537 8=8|infoweapons.com|34414 9=9|api.ip2info.org|33557 10=10|\n";
  echo "       1.10.in-addr.arpa|29938 11=11|ws2.infoweapons.com|29443 12=12|ak.fbcdn.net|29347 13=13|mail.google.com|24958 14=14|dns21.infoweapons.com|22655 15=15|\n";
  echo "       _msdcs.infoweapons.com|17474\n\n";
  echo "    2. Retrieve IWC-VISHNU-MIB::topDomainsTable table. Output table as performance data. Second column as row index.\n";
  echo "       Third column as row value. Finally, JSONized table (all) and store into '/var/tmp/snmp_table.json'.\n\n";
  echo "       $prog -H 10.1.1.10 -T IWC-VISHNU-MIB::topDomainsTable -indexes 1 -cols 2 -oformat json\n\n";
  echo "       SNMP OK |0.10.in-addr.arpa=2464045 cebu.infoweapons.com=399022 www.google.com=95656 soliddns1.infoweapons.com=91464 soliddns2.infoweapons.com=69187 \n";
  echo "       0.2.ip6.arpa=55614 com.infoweapons.com=39551 infoweapons.com=34428 api.ip2info.org=33588 1.10.in-addr.arpa=29949 ws2.infoweapons.com=29448 ak.fbcdn.net=29348 \n";
  echo "       mail.google.com=24990 dns21.infoweapons.com=22669 _msdcs.infoweapons.com=17480\n\n";
}

function get_args()
{
  global $params;
  global $argv;

  $argc = count($argv);
  for ($i = 1; $i < $argc; $i++)
  {
    $opt = trim($argv[$i]);
    switch ($opt)
    {
      case '-H':
        $i++;
        if (empty($argv[$i]))
        {
          echo "IP addresss/hostname missing.\n";
          exit(3);
        }

        $params['host'] = $argv[$i];
        break;

      case '-v':
        $i++;
        if (empty($argv[$i]))
        {
          echo "SNMP version missing.\n";
          exit(3);
        }

        if (($argv[$i] != '1') && ($argv[$i] != '2c'))
        {
          echo "Invalid/Unsupported SNMP version.\n";
          exit(3);
        }

        $params['snmp_version'] = $argv[$i];
        break;

      case '-c':
        $i++;
        if (empty($argv[$i]))
        {
          echo "SNMP community name missing.\n";
          exit(3);
        }

        $params['snmp_comname'] = $argv[$i];
        break;

      case '-T':
        $i++;
        if (empty($argv[$i]))
        {
          echo "SNMP Table name missing.\n";
          exit(3);
        }

        $params['snmp_table'] = $argv[$i];
        break;

      case '-cols':
        $i++;
        if (empty($argv[$i]))
        {
          echo "Output column indexes missing.\n";
          exit(3);
        }

        $params['output_columns'] = explode(':', $argv[$i]);
        break;

      case '-indexes':
        $i++;
        if (empty($argv[$i]))
        {
          echo "Output row indexes missing.\n";
          exit(3);
        }

        $params['output_indexes'] = explode(':', $argv[$i]);
        break;

      case '-oformat':
        $i++;
        if (empty($argv[$i]))
        {
          echo "Output format value missing.\n";
          exit(3);
        }

        if (($argv[$i] != 'serialized') && ($argv[$i] != 'json') && ($argv[$i] != 'rrdgraph') && ($argv[$i] != 'gnuplot'))
        {
          echo "Unsupported Output format.\n";
          exit(3);
        }

        $params['output_format'] = $argv[$i];
        break;

      case '-odir':
        $i++;
        if (empty($argv[$i]))
        {
          echo "Output directory missing.\n";
          exit(3);
        }

        $params['output_dir'] = $argv[$i];
        break;

      case '-ofile':
        $i++;
        if (empty($argv[$i]))
        {
          echo "Output file missing.\n";
          exit(3);
        }

        $params['output_file'] = $argv[$i];
        break;

      case '-P':
        $params['output_perf'] = false;
        break;

      case '-v':
        $params['verbose']++;
        break;

      case '-h':
        show_help($argv[0]);
        exit(0);

      default:
        echo "Invalid parameter(s) - [$opt].\n";
        exit(3);
    }
  }
}

/* get args */
get_args();

$cmd = 'snmptable -v' . $params['snmp_version']. ' -c ' . $params['snmp_comname'];
if (!empty($params['snmp_options']))
{
  $cmd .= " $params[snmp_options]";
}

$cmd .= " $params[host] $params[snmp_table]";
$output = array();
$last = exec($cmd, $output, $result);
if ($result != 0)
{
  echo "Error retrieving statistics - [$last].\n";
  exit(2);
}

$data = array();

$n_output = count($output);
if ($n_output > 3)
{
  for ($i = 3; $i < $n_output; $i++)
  {
    $line = trim($output[$i]);
    $toks = preg_split('%[\s]+%', $line);

    $data[$toks[0]] = $toks;
  }
}

// var_dump($data);

echo "SNMP OK |";
if (($params['output_perf']) && !empty($data))
{
  foreach ($data as $entry)
  {
    /* format index */
    $first = true;
    $idx_str = '';
    foreach ($params['output_indexes'] as $idx)
    {
      if ($first)
      {
        $idx_str .= $entry[$idx];
        $first = false;
      }
      else
      {
        $idx_str .= $params['output_indexes_sep'] . $entry[$idx];
      }
    }

    /* format value */
    $val_str = '';
    if (empty($params['output_columns']))
    {
      $val_str = implode($params['output_columns_sep'], $entry);
    }
    else
    {
      $first = true;
      foreach ($params['output_columns'] as $idx)
      {
        if ($first)
        {
          $val_str .= $entry[$idx];
          $first = false;
        }
        else
        {
          $val_str .= $params['output_columns_sep'] . $entry[$idx];
        }
      }
    }

    echo "$idx_str=$val_str ";
  }

  echo "\n";
}
else
{
  echo "\n";
}

/* store output to a file for later processing */
$jdata['timestamp'] = time();
$jdata['table_name'] = $params['snmp_table'];
$jdata['num_rows'] = count($data);
$jdata['rows'] = $data;

if (is_dir($params['output_dir']) === false)
{
  mkdir($params['output_dir']);
}

switch ($params['output_format'])
{
  case 'serialized':
    $file = (empty($params['output_file'])) ? '/snmp_table.serialized' : $params['output_file'];
    file_put_contents($params['output_dir'] . '/' . $file, serialize($jdata));
    break;

  case 'json':
    $file = (empty($params['output_file'])) ? '/snmp_table.json' : $params['output_file'];
    file_put_contents($params['output_dir'] . '/' . $file, json_encode($jdata));
    break;
}

exit(0);
?>
