summaryrefslogtreecommitdiffstats
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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