1
|
<?php
|
2
|
/*
|
3
|
diag_dump_states.php
|
4
|
Copyright (C) 2005 Colin Smith
|
5
|
Copyright (C) 2005-2009 Scott Ullrich
|
6
|
Copyright (C) 2013-2015 Electric Sheep Fencing, LP
|
7
|
All rights reserved.
|
8
|
|
9
|
Redistribution and use in source and binary forms, with or without
|
10
|
modification, are permitted provided that the following conditions are met:
|
11
|
|
12
|
1. Redistributions of source code must retain the above copyright notice,
|
13
|
this list of conditions and the following disclaimer.
|
14
|
|
15
|
2. Redistributions in binary form must reproduce the above copyright
|
16
|
notice, this list of conditions and the following disclaimer in the
|
17
|
documentation and/or other materials provided with the distribution.
|
18
|
|
19
|
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
20
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
21
|
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
22
|
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
23
|
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
24
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
25
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
26
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
27
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
28
|
POSSIBILITY OF SUCH DAMAGE.
|
29
|
*/
|
30
|
|
31
|
/*
|
32
|
pfSense_BUILDER_BINARIES: /sbin/pfctl
|
33
|
pfSense_MODULE: filter
|
34
|
*/
|
35
|
|
36
|
##|+PRIV
|
37
|
##|*IDENT=page-diagnostics-showstates
|
38
|
##|*NAME=Diagnostics: Show States page
|
39
|
##|*DESCR=Allow access to the 'Diagnostics: Show States' page.
|
40
|
##|*MATCH=diag_dump_states.php*
|
41
|
##|-PRIV
|
42
|
|
43
|
require_once("guiconfig.inc");
|
44
|
require_once("interfaces.inc");
|
45
|
|
46
|
/* handle AJAX operations */
|
47
|
if(isset($_POST['action']) && $_POST['action'] == "remove") {
|
48
|
if (isset($_POST['srcip']) && isset($_POST['dstip']) && is_ipaddr($_POST['srcip']) && is_ipaddr($_POST['dstip'])) {
|
49
|
$retval = pfSense_kill_states($_POST['srcip'], $_POST['dstip']);
|
50
|
echo htmlentities("|{$_POST['srcip']}|{$_POST['dstip']}|0|");
|
51
|
} else {
|
52
|
echo gettext("invalid input");
|
53
|
}
|
54
|
return;
|
55
|
}
|
56
|
|
57
|
if (isset($_POST['filter']) && isset($_POST['killfilter'])) {
|
58
|
if (is_ipaddr($_POST['filter'])) {
|
59
|
$tokill = $_POST['filter'] . "/32";
|
60
|
} elseif (is_subnet($_POST['filter'])) {
|
61
|
$tokill = $_POST['filter'];
|
62
|
} else {
|
63
|
// Invalid filter
|
64
|
$tokill = "";
|
65
|
}
|
66
|
if (!empty($tokill)) {
|
67
|
$retval = pfSense_kill_states($tokill);
|
68
|
$retval = pfSense_kill_states("0.0.0.0/0", $tokill);
|
69
|
}
|
70
|
}
|
71
|
|
72
|
$pgtitle = array(gettext("Diagnostics"),gettext("Show States"));
|
73
|
include("head.inc");
|
74
|
?>
|
75
|
|
76
|
<script>
|
77
|
events.push(function(){
|
78
|
$('a[data-entry]').on('click', function(){
|
79
|
var el = $(this);
|
80
|
var data = $(this).data('entry').split('|');
|
81
|
|
82
|
$.ajax(
|
83
|
'/diag_dump_states.php',
|
84
|
{
|
85
|
type: 'post',
|
86
|
data: {
|
87
|
action: 'remove',
|
88
|
srcip: data[0],
|
89
|
dstip: data[1]
|
90
|
},
|
91
|
success: function(){
|
92
|
el.parents('tr').remove();
|
93
|
},
|
94
|
});
|
95
|
});
|
96
|
});
|
97
|
</script>
|
98
|
|
99
|
<?php
|
100
|
$tab_array = array();
|
101
|
$tab_array[] = array(gettext("States"), true, "diag_dump_states.php");
|
102
|
if (isset($config['system']['lb_use_sticky']))
|
103
|
$tab_array[] = array(gettext("Source Tracking"), false, "diag_dump_states_sources.php");
|
104
|
$tab_array[] = array(gettext("Reset States"), false, "diag_resetstate.php");
|
105
|
display_top_tabs($tab_array);
|
106
|
|
107
|
// Start of tab content
|
108
|
$current_statecount=`pfctl -si | grep "current entries" | awk '{ print $3 }'`;
|
109
|
|
110
|
require('classes/Form.class.php');
|
111
|
|
112
|
$form = new Form(false);
|
113
|
|
114
|
$section = new Form_Section('State filter');
|
115
|
|
116
|
$section->addInput(new Form_Input(
|
117
|
'filter',
|
118
|
'Filter expression',
|
119
|
'text',
|
120
|
$_POST['filter'],
|
121
|
['placeholder' => 'Simple filter such as 192.168, v6, icmp or ESTABLISHED']
|
122
|
));
|
123
|
|
124
|
$filterbtn = new Form_Button('filterbtn', 'Filter', null);
|
125
|
$filterbtn->removeClass('btn-primary')->addClass('btn-default btn-sm');
|
126
|
$section->addInput(new Form_StaticText(
|
127
|
'',
|
128
|
$filterbtn
|
129
|
));
|
130
|
|
131
|
if (isset($_POST['filter']) && (is_ipaddr($_POST['filter']) || is_subnet($_POST['filter']))) {
|
132
|
$killbtn = new Form_Button('killfilter', 'Kill States');
|
133
|
$killbtn->removeClass('btn-primary')->addClass('btn-danger btn-sm');
|
134
|
$section->addInput(new Form_StaticText(
|
135
|
'Kill filtered states',
|
136
|
$killbtn
|
137
|
))->setHelp('Remove all states to and from the filtered address');
|
138
|
}
|
139
|
|
140
|
$form->add($section);
|
141
|
print $form;
|
142
|
?>
|
143
|
<table class="table table-striped">
|
144
|
<thead>
|
145
|
<tr>
|
146
|
<th><?=gettext("Int")?></th>
|
147
|
<th><?=gettext("Proto")?></th>
|
148
|
<th><?=gettext("Source -> Router -> Destination")?></th>
|
149
|
<th><?=gettext("State")?></th>
|
150
|
<th></th> <!-- For the optional "Remove" button -->
|
151
|
</tr>
|
152
|
</thead>
|
153
|
<tbody>
|
154
|
<?php
|
155
|
$row = 0;
|
156
|
/* get our states */
|
157
|
$grepline = (isset($_POST['filter'])) ? "| /usr/bin/egrep " . escapeshellarg(htmlspecialchars($_POST['filter'])) : "";
|
158
|
$fd = popen("/sbin/pfctl -s state {$grepline}", "r" );
|
159
|
while ($line = chop(fgets($fd))) {
|
160
|
if($row >= 10000)
|
161
|
break;
|
162
|
|
163
|
$line_split = preg_split("/\s+/", $line);
|
164
|
|
165
|
$iface = array_shift($line_split);
|
166
|
$proto = array_shift($line_split);
|
167
|
$state = array_pop($line_split);
|
168
|
$info = implode(" ", $line_split);
|
169
|
|
170
|
// We may want to make this optional, with a large state table, this could get to be expensive.
|
171
|
$iface = convert_real_interface_to_friendly_descr($iface);
|
172
|
|
173
|
/* break up info and extract $srcip and $dstip */
|
174
|
$ends = preg_split("/\<?-\>?/", $info);
|
175
|
$parts = explode(":", $ends[0]);
|
176
|
$srcip = trim($parts[0]);
|
177
|
$parts = explode(":", $ends[count($ends) - 1]);
|
178
|
$dstip = trim($parts[0]);
|
179
|
?>
|
180
|
<tr>
|
181
|
<td><?= $iface ?></td>
|
182
|
<td><?= $proto ?></td>
|
183
|
<td><?= $info ?></td>
|
184
|
<td><?= $state ?></td>
|
185
|
|
186
|
<td>
|
187
|
<a class="btn btn-xs btn-danger" data-entry="<?=$srcip?>|<?=$dstip?>"
|
188
|
title="<?=sprintf(gettext('Remove all state entries from %s to %s'), $srcip, $dstip);?>">Remove</a>
|
189
|
</td>
|
190
|
</tr>
|
191
|
<?php $row++; } ?>
|
192
|
</tbody>
|
193
|
</table>
|
194
|
<?php
|
195
|
|
196
|
if ($row == 0) {
|
197
|
if (isset($_POST['filter']) && !empty($_POST['filter']))
|
198
|
$errmsg = gettext('No states were found that match the current filter');
|
199
|
else
|
200
|
$errmsg = gettext('No states were found');
|
201
|
|
202
|
print('<p class="alert alert-warning">' . $errmsg . '</p>');
|
203
|
}
|
204
|
|
205
|
include("foot.inc");
|