summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNOYB <Al_Stu@Frontier.com>2015-12-02 14:47:32 -0800
committerStephen Beaver <sbeaver@netgate.com>2015-12-03 19:03:32 -0500
commite3efcb23fa0ab60dcfa032e12236fb433dea88d5 (patch)
tree0cd472f018f633a04f2ce80a186170304ca32d6a
parentc71d37a7f44e5987f39c1b497ad9808ae4ba3402 (diff)
downloadpfsense-e3efcb23fa0ab60dcfa032e12236fb433dea88d5.zip
pfsense-e3efcb23fa0ab60dcfa032e12236fb433dea88d5.tar.gz
Status - System Logs - Filter
Add advanced log filter form Break out log listing fields in to columns (Time, Process, PID, Message). Basic log filter form is still used in raw mode.
-rw-r--r--src/etc/inc/filter_log.inc139
-rwxr-xr-xsrc/usr/local/www/diag_logs.php242
2 files changed, 341 insertions, 40 deletions
diff --git a/src/etc/inc/filter_log.inc b/src/etc/inc/filter_log.inc
index ea45aa9..05f2b19 100644
--- a/src/etc/inc/filter_log.inc
+++ b/src/etc/inc/filter_log.inc
@@ -79,10 +79,60 @@ function conv_log_filter($logfile, $nentries, $tail = 50, $filtertext = "", $fil
/* Always do a reverse tail, to be sure we're grabbing the 'end' of the log. */
$logarr = "";
+ if ($logfile == "{$g['varlog_path']}/system.log") { $logfile_type = "system"; }
+ elseif ($logfile == "{$g['varlog_path']}/gateways.log") { $logfile_type = "system"; }
+ elseif ($logfile == "{$g['varlog_path']}/routing.log") { $logfile_type = "system"; }
+ elseif ($logfile == "{$g['varlog_path']}/resolver.log") { $logfile_type = "system"; }
+ elseif ($logfile == "{$g['varlog_path']}/wireless.log") { $logfile_type = "system"; }
+
+ elseif ($logfile == "{$g['varlog_path']}/filter.log") { $logfile_type = "firewall"; }
+ elseif ($logfile == "{$g['varlog_path']}/dhcpd.log") { $logfile_type = "system"; }
+ elseif ($logfile == "{$g['varlog_path']}/portalauth.log") { $logfile_type = "system"; }
+ elseif ($logfile == "{$g['varlog_path']}/ipsec.log") { $logfile_type = "system"; }
+ elseif ($logfile == "{$g['varlog_path']}/ppp.log") { $logfile_type = "system"; }
+
+ elseif ($logfile == "{$g['varlog_path']}/vpn.log") { $logfile_type = "tbd"; }
+ elseif ($logfile == "{$g['varlog_path']}/pptps.log") { $logfile_type = "tbd"; }
+ elseif ($logfile == "{$g['varlog_path']}/poes.log") { $logfile_type = "tbd"; }
+ elseif ($logfile == "{$g['varlog_path']}/l2tps.log") { $logfile_type = "tbd"; }
+
+ elseif ($logfile == "{$g['varlog_path']}/relayd.log") { $logfile_type = "system"; }
+ elseif ($logfile == "{$g['varlog_path']}/openvpn.log") { $logfile_type = "system"; }
+ elseif ($logfile == "{$g['varlog_path']}/ntpd.log") { $logfile_type = "system"; }
+
+ else { $logfile_type = "unknown"; }
+
+ if ($logfile_type == 'firewall') {
+ $pattern = "filterlog:";
+ }
+ elseif ($logfile_type == 'system') {
+
+ $month_pattern = "[a-zA-Z]{3}";
+ $day_pattern = "[0-9]{1,2}";
+ $time_pattern = "[0-9]{2}:[0-9]{2}:[0-9]{2}";
+
+ $date_pattern = "\(" . $month_pattern . "\ +" . $day_pattern . "\ +" . $time_pattern . "\)";
+
+ $process_pattern = "\(.*?\)";
+ $pid_pattern = "\(.*?\)\(?::\ +\)?\(?:\[[0-9:]*\]\)?:?";
+ $log_message_pattern = "\(.*\)";
+
+ $pattern = "^" . $date_pattern . "\ +" . $process_pattern . "\ +" . $pid_pattern . "\ +" . $log_message_pattern . "$";
+ }
+ elseif ($logfile_type == 'tbd') {
+ $pattern = "^\(.*\)$";
+ }
+ elseif ($logfile_type == 'unknown') {
+ $pattern = "^\(.*\)$";
+ }
+ else {
+ $pattern = "^\(.*\)$";
+ }
+
if (isset($config['system']['usefifolog'])) {
- exec("/usr/sbin/fifolog_reader " . escapeshellarg($logfile) . " | /usr/bin/grep 'filterlog:' | /usr/bin/tail -r -n {$tail}", $logarr);
+ exec("/usr/sbin/fifolog_reader " . escapeshellarg($logfile) . " | /usr/bin/grep -E $pattern | /usr/bin/tail -r -n {$tail}", $logarr);
} else {
- exec("/usr/local/sbin/clog " . escapeshellarg($logfile) . " | /usr/bin/grep -v \"CLOG\" | /usr/bin/grep -v \"\033\" | /usr/bin/grep 'filterlog:' | /usr/bin/tail -r -n {$tail}", $logarr);
+ exec("/usr/local/sbin/clog " . escapeshellarg($logfile) . " | /usr/bin/grep -v \"CLOG\" | /usr/bin/grep -v \"\033\" | /usr/bin/grep -E $pattern | /usr/bin/tail -r -n {$tail}", $logarr);
}
$filterlog = array();
@@ -94,7 +144,12 @@ function conv_log_filter($logfile, $nentries, $tail = 50, $filtertext = "", $fil
break;
}
- $flent = parse_filter_line($logent);
+ if ($logfile_type == 'firewall') { $flent = parse_firewall_log_line($logent); }
+ elseif ($logfile_type == 'system') { $flent = parse_system_log_line($logent); }
+ elseif ($logfile_type == 'tbd') { $flent = array(); }
+ elseif ($logfile_type == 'unknown') { $flent = parse_unknown_log_line($logent); }
+ else { $flent = array(); }
+
if (!$filterinterface || ($filterinterface == $flent['interface'])) {
if ((($flent != "") && (!is_array($filtertext)) && (match_filter_line($flent, $filtertext))) ||
(($flent != "") && (is_array($filtertext)) && (match_filter_field($flent, $filtertext)))) {
@@ -159,7 +214,83 @@ function in_arrayi($needle, $haystack) {
return in_array(strtolower($needle), array_map('strtolower', $haystack));
}
-function parse_filter_line($line) {
+function parse_unknown_log_line($line) {
+ global $config, $g;
+
+ $flent = array();
+ $log_split = "";
+
+ $month_pattern = "[a-zA-Z]{3}";
+ $day_pattern = "[0-9]{1,2}";
+ $time_pattern = "[0-9]{2}:[0-9]{2}:[0-9]{2}";
+
+ $date_pattern = "(" . $month_pattern . "\ +" . $day_pattern . "\ +" . $time_pattern . ")";
+
+ $log_message_pattern = "(.*)";
+
+ $pattern = "/^" . $date_pattern . "\ +" . $log_message_pattern . "$/";
+
+ if (!preg_match($pattern, $line, $log_split))
+ return "";
+
+ list($all, $flent['time'], $flent['message']) = $log_split;
+
+ if($g['debug']) {
+ log_error(sprintf(gettext("There was a error parsing: %s. Please report to mailing list or forum."), $flent['process']));
+ return "";
+ }
+
+ /* If there is time, and message, fields, then the line should be usable/good */
+ if (!( (trim($flent['time']) == "") && (trim($flent['message']) == "") )) {
+ return $flent;
+ } else {
+ if($g['debug']) {
+ log_error(sprintf(gettext("There was a error parsing log entry: %s. Please report to mailing list or forum."), $errline));
+ }
+ return "";
+ }
+}
+
+function parse_system_log_line($line) {
+ global $config, $g;
+
+ $flent = array();
+ $log_split = "";
+
+ $month_pattern = "[a-zA-Z]{3}";
+ $day_pattern = "[0-9]{1,2}";
+ $time_pattern = "[0-9]{2}:[0-9]{2}:[0-9]{2}";
+
+ $date_pattern = "(" . $month_pattern . "\ +" . $day_pattern . "\ +" . $time_pattern . ")";
+
+ $process_pattern = "(.*?)";
+ $pid_pattern = "(.*?)(?::\ +)?(?:\[([0-9:]*)\])?:?";
+ $log_message_pattern = "(.*)";
+
+ $pattern = "/^" . $date_pattern . "\ +" . $process_pattern . "\ +" . $pid_pattern . "\ +" . $log_message_pattern . "$/";
+
+ if (!preg_match($pattern, $line, $log_split))
+ return "";
+
+ list($all, $flent['time'], $flent['host'], $flent['process'], $flent['pid'], $flent['message']) = $log_split;
+
+ if($g['debug']) {
+ log_error(sprintf(gettext("There was a error parsing: %s. Please report to mailing list or forum."), $flent['process']));
+ return "";
+ }
+
+ /* If there is time, process, and message, fields, then the line should be usable/good */
+ if (!( (trim($flent['time']) == "") && (trim($flent['process']) == "") && (trim($flent['message']) == "") )) {
+ return $flent;
+ } else {
+ if($g['debug']) {
+ log_error(sprintf(gettext("There was a error parsing log entry: %s. Please report to mailing list or forum."), $errline));
+ }
+ return "";
+ }
+}
+
+function parse_firewall_log_line($line) {
global $config, $g;
$flent = array();
diff --git a/src/usr/local/www/diag_logs.php b/src/usr/local/www/diag_logs.php
index c668936..4e098e4 100755
--- a/src/usr/local/www/diag_logs.php
+++ b/src/usr/local/www/diag_logs.php
@@ -68,6 +68,7 @@
##|-PRIV
require("guiconfig.inc");
+require_once("filter_log.inc");
/*
Build a list of allowed log files so we can reject others to prevent the page
@@ -111,23 +112,51 @@ if (!$_GET['logfile']) {
}
}
+function getGETPOSTsettingvalue($settingname, $default) {
+ $settingvalue = $default;
+ if ($_GET[$settingname]) {
+ $settingvalue = $_GET[$settingname];
+ }
+ if ($_POST[$settingname]) {
+ $settingvalue = $_POST[$settingname];
+ }
+ return $settingvalue;
+}
+
+$filtersubmit = getGETPOSTsettingvalue('filtersubmit', null);
+
+if ($filtersubmit) {
+ $filtertext = getGETPOSTsettingvalue('filtertext', "");
+ $filterlogentries_qty = getGETPOSTsettingvalue('filterlogentries_qty', null);
+}
+
+$filterlogentries_submit = getGETPOSTsettingvalue('filterlogentries_submit', null);
+
+if ($filterlogentries_submit) {
+ $filterfieldsarray = array();
+
+ $filterfieldsarray['time'] = getGETPOSTsettingvalue('filterlogentries_time', null);
+ $filterfieldsarray['process'] = getGETPOSTsettingvalue('filterlogentries_process', null);
+ $filterfieldsarray['pid'] = getGETPOSTsettingvalue('filterlogentries_pid', null);
+ $filterfieldsarray['message'] = getGETPOSTsettingvalue('filterlogentries_message', null);
+ $filterlogentries_qty = getGETPOSTsettingvalue('filterlogentries_qty', null);
+}
+
$system_logfile = "{$g['varlog_path']}/" . basename($logfile) . ".log";
$nentries = $config['syslog']['nentries'];
-if (!$nentries) {
- $nentries = 50;
-}
-if ($_POST['clear']) {
- clear_log_file($system_logfile);
+# Override Display Quantity
+if ($filterlogentries_qty) {
+ $nentries = $filterlogentries_qty;
}
-if ($_GET['filtertext']) {
- $filtertext = htmlspecialchars($_GET['filtertext']);
+if (!$nentries || !is_numeric($nentries)) {
+ $nentries = 50;
}
-if ($_POST['filtertext']) {
- $filtertext = htmlspecialchars($_POST['filtertext']);
+if ($_POST['clear']) {
+ clear_log_file($system_logfile);
}
if ($filtertext) {
@@ -167,50 +196,157 @@ if (in_array($logfile, array('system', 'gateways', 'routing', 'resolver', 'wirel
display_top_tabs($tab_array, false, 'nav nav-tabs');
}
-$form = new Form(false);
+if (!isset($config['syslog']['rawfilter'])) { // Advanced log filter form
+ $form = new Form(false);
-$section = new Form_Section('Log file filter');
+ $section = new Form_Section('Advanced Log Filter', 'adv-filter-panel', true);
-$section->addInput(new Form_Input(
- 'filtertext',
- 'Filter',
- 'text',
- $filtertext,
- ['placeholder' => 'Filter text']
-));
+ $group = new Form_Group('');
+
+ $group->add(new Form_Input(
+ 'filterlogentries_time',
+ null,
+ 'text',
+ $filterfieldsarray['time']
+ ))->setHelp('Time');
+
+ $group->add(new Form_Input(
+ 'filterlogentries_process',
+ null,
+ 'text',
+ $filterfieldsarray['process']
+ ))->setHelp('Process');
+
+ $group->add(new Form_Input(
+ 'filterlogentries_pid',
+ null,
+ 'number',
+ $filterfieldsarray['pid']
+ ))->setHelp('PID');
+
+ $group->add(new Form_Input(
+ 'filterlogentries_qty',
+ null,
+ 'number',
+ $filterlogentries_qty,
+ ['placeholder' => $nentries]
+ ))->setHelp('Quantity');
+
+ $section->add($group);
+
+ $group = new Form_Group('');
+
+ $group->add(new Form_Input(
+ 'filterlogentries_message',
+ null,
+ 'text',
+ $filterfieldsarray['message']
+ ))->setHelp('Log Message');
+}
+else { // Simple log filter form
+ $form = new Form(false);
+
+ $section = new Form_Section('Log Filter', 'basic-filter-panel', true);
+
+ $group = new Form_Group('');
+
+ $group->add(new Form_Input(
+ 'filtertext',
+ null,
+ 'text',
+ $filtertext
+ ))->setHelp('Filter Expression');
+
+ $group->add(new Form_Input(
+ 'filterlogentries_qty',
+ null,
+ 'number',
+ $filterlogentries_qty,
+ ['placeholder' => $nentries]
+ ))->setHelp('Quantity');
+}
$btnsubmit = new Form_Button(
- 'filtersubmit',
- 'Filter',
+ 'filterlogentries_submit',
+ ' ' . 'Apply Filter',
null,
'fa-filter'
);
$btnsubmit->removeClass('btn-primary')->addClass('btn-success')->addClass('btn-sm');
-$btnclear = new Form_Button(
- 'clear',
- 'Clear log',
- null,
- 'fa-trash'
-);
-
-$btnclear->removeClass('btn-primary')->addClass('btn-danger')->addClass('btn-sm');
-
-$section->addInput(new Form_StaticText(
+$group->add(new Form_StaticText(
'',
- $btnsubmit . $btnclear
+ $btnsubmit
));
+$group->setHelp('<a target="_blank" href="http://www.php.net/manual/en/book.pcre.php">' . 'Regular expression reference</a> Precede with exclamation (!) to exclude match.');
+$section->add($group);
$form->add($section);
print $form;
-if ($logfile == 'dhcpd')
- print_info_box('Warning: Clearing the log file will restart the DHCP daemon.');
-
+// Now the forms are complete we can draw the log table and its controls
+if (!isset($config['syslog']['rawfilter'])) {
+ if ($filterlogentries_submit)
+ $filterlog = conv_log_filter($system_logfile, $nentries, $nentries + 100, $filterfieldsarray);
+ else
+ $filterlog = conv_log_filter($system_logfile, $nentries, $nentries + 100, $filtertext);
?>
<div class="panel panel-default">
+ <div class="panel-heading">
+ <h2 class="panel-title">
+<?php
+ if ((!$filtertext) && (!$filterfieldsarray))
+ printf(gettext("Last %d %s log entries."), count($filterlog), $logfile);
+ else
+ printf(gettext("%d matched %s log entries."), count($filterlog), $logfile);
+
+ printf(gettext(" (Maximum %d)"), $nentries);
+?>
+ </h2>
+ </div>
+ <div class="panel-body">
+ <div class="table-responsive">
+ <table class="table table-striped table-hover table-compact">
+ <tr>
+ <th><?=gettext("Time")?></th>
+ <th><?=gettext("Process")?></th>
+ <th><?=gettext("PID")?></th>
+ <th style="width:100%"><?=gettext("Log Message")?></th>
+ </tr>
+<?php
+ foreach ($filterlog as $filterent) {
+?>
+ <tr>
+ <td style="white-space:nowrap;">
+ <?=htmlspecialchars($filterent['time'])?>
+ </td>
+ <td style="white-space:nowrap;">
+ <?=htmlspecialchars($filterent['process'])?>
+ </td>
+ <td style="white-space:nowrap;">
+ <?=htmlspecialchars($filterent['pid'])?>
+ </td>
+ <td style="word-wrap:break-word; word-break:break-all; white-space:normal">
+ <?=htmlspecialchars($filterent['message'])?>
+ </td>
+ </tr>
+<?php
+ } // e-o-foreach
+?>
+ </table>
+ </div>
+ </div>
+</div>
+<?php
+ if (count($filterlog) == 0)
+ print_info_box('No logs to display');
+}
+else
+{
+?>
+<div class="panel panel-default">
<div class="panel-heading"><h2 class="panel-title"><?=gettext("Last ")?><?=$nentries?> <?=$logfile?><?=gettext(" log entries")?></h2></div>
<div class="table table-responsive">
<table class="table table-striped table-hover">
@@ -228,13 +364,47 @@ if ($logfile == 'dhcpd')
$inverse = null;
if ($filtertext)
- dump_clog($system_logfile, $nentries, true, array("$filtertext"), $inverse);
+ $rows = dump_clog($system_logfile, $nentries, true, array("$filtertext"), $inverse);
else
- dump_clog($system_logfile, $nentries, true, array(), $inverse);
+ $rows = dump_clog($system_logfile, $nentries, true, array(), $inverse);
?>
</tbody>
</table>
</div>
</div>
+<?php
+ if ($rows == 0)
+ print_info_box('No logs to display');
+}
+?>
+
+<?php
+$form = new Form(false);
+
+$section = new Form_Section('Manage Log', 'log-manager-panel', true);
+
+$group = new Form_Group('');
+
+$btnclear = new Form_Button(
+ 'clear',
+ ' ' . 'Clear log',
+ null,
+ 'fa-trash'
+);
+
+$btnclear->removeClass('btn-primary')->addClass('btn-danger')->addClass('btn-sm');
+
+if ($logfile == 'dhcpd')
+ print_info_box('Warning: Clearing the log file will restart the DHCP daemon.');
+
+$group->add(new Form_StaticText(
+ '',
+ $btnclear
+));
+
+$section->add($group);
+$form->add($section);
+print $form;
+?>
<?php include("foot.inc"); ?>
OpenPOWER on IntegriCloud