Project

General

Profile

Download (9.7 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * diag_arp.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2019 Rubicon Communications, LLC (Netgate)
9
 * All rights reserved.
10
 *
11
 * originally based on m0n0wall (http://m0n0.ch/wall)
12
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
13
 * All rights reserved.
14
 *
15
 * Licensed under the Apache License, Version 2.0 (the "License");
16
 * you may not use this file except in compliance with the License.
17
 * You may obtain a copy of the License at
18
 *
19
 * http://www.apache.org/licenses/LICENSE-2.0
20
 *
21
 * Unless required by applicable law or agreed to in writing, software
22
 * distributed under the License is distributed on an "AS IS" BASIS,
23
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
 * See the License for the specific language governing permissions and
25
 * limitations under the License.
26
 */
27

    
28
##|+PRIV
29
##|*IDENT=page-diagnostics-arptable
30
##|*NAME=Diagnostics: ARP Table
31
##|*DESCR=Allow access to the 'Diagnostics: ARP Table' page.
32
##|*MATCH=diag_arp.php*
33
##|-PRIV
34

    
35
@ini_set('zlib.output_compression', 0);
36
@ini_set('implicit_flush', 1);
37

    
38
require_once("guiconfig.inc");
39

    
40
// delete arp entry
41
if (isset($_POST['deleteentry'])) {
42
	$ip = $_POST['deleteentry'];
43
	if (is_ipaddrv4($ip)) {
44
		$ret = mwexec("arp -d " . $_POST['deleteentry'], true);
45
	} else {
46
		$ret = 1;
47
	}
48
	if ($ret) {
49
		$savemsg = sprintf(gettext("%s is not a valid IPv4 address or could not be deleted."), $ip);
50
		$savemsgtype = 'alert-warning';
51
	} else {
52
		$savemsg = sprintf(gettext("The ARP cache entry for %s has been deleted."), $ip);
53
		$savemsgtype = 'success';
54
	}
55
}
56

    
57
$leases = system_get_dhcpleases();
58

    
59
// Put this in an easy to use form
60
$dhcpmac = array();
61
$dhcpip = array();
62

    
63
foreach ($leases['lease'] as $value) {
64
	$dhcpmac[$value['mac']] = $value['hostname'];
65
	$dhcpip[$value['ip']] = $value['hostname'];
66
}
67

    
68
$arp_table = system_get_arp_table();
69

    
70
$i = 0;
71

    
72
/* if list */
73
$ifdescrs = get_configured_interface_with_descr();
74

    
75
foreach ($ifdescrs as $key => $interface) {
76
	$thisif = convert_friendly_interface_to_real_interface_name($key);
77
	if (!empty($thisif)) {
78
		$hwif[$thisif] = $interface;
79
	}
80
}
81

    
82
function _getHostName($mac, $ip) {
83
	global $dhcpmac, $dhcpip;
84

    
85
	if ($dhcpmac[$mac]) {
86
		return $dhcpmac[$mac];
87
	} else if ($dhcpip[$ip]) {
88
		return $dhcpip[$ip];
89
	} else {
90
		exec("host -W 1 " . escapeshellarg($ip), $output);
91
		if (preg_match('/.*pointer ([A-Za-z_0-9.-]+)\..*/', $output[0], $matches)) {
92
			if ($matches[1] <> $ip) {
93
				return $matches[1];
94
			}
95
		}
96
	}
97
	return "";
98
}
99

    
100
$pgtitle = array(gettext("Diagnostics"), gettext("ARP Table"));
101
include("head.inc");
102

    
103
// Handle save msg if defined
104
if ($savemsg) {
105
	print_info_box(htmlentities($savemsg), $savemsgtype);
106
}
107
?>
108

    
109
<!-- On modern hardware the table will load so fast you may never see this! -->
110
<div id="loading">
111
	<?= gettext(" Loading, please wait...")?>
112
</div>
113

    
114
<?php
115

    
116
// Flush buffers out to client so that they see Loading, please wait....
117
for ($i = 0; $i < ob_get_level(); $i++) {
118
	ob_end_flush();
119
}
120

    
121
ob_implicit_flush(1);
122

    
123
// Resolve hostnames and replace Z_ with "".  The intention
124
// is to sort the list by hostnames, alpha and then the non
125
// resolvable addresses will appear last in the list.
126
$dnsavailable=1;
127
$dns = trim(_getHostName("", "8.8.8.8"));
128
if ($dns == "") {
129
	$dns = trim(_getHostName("", "8.8.4.4"));
130
	if ($dns == "") {
131
		$dnsavailable = 0;
132
	}
133
}
134

    
135
foreach ($arp_table as &$entry) {
136
	if ($dnsavailable && !empty($entry['mac-address'])) {
137
		$dns = trim(_getHostName($entry['mac-address'],
138
		    $entry['ip-address']));
139
	} else {
140
		$dns="";
141
	}
142
	if (trim($dns)) {
143
		$entry['dnsresolve'] = "$dns";
144
	} else {
145
		$entry['dnsresolve'] = "Z_ ";
146
	}
147
}
148
unset($entry);
149

    
150
// Sort the data alpha first
151
$arp_table = msort($arp_table, "dnsresolve");
152

    
153
// Load MAC-Manufacturer table
154
$mac_man = load_mac_manufacturer_table();
155
?>
156
<div class="panel panel-default" id="search-panel">
157
	<div class="panel-heading">
158
		<h2 class="panel-title">
159
			<?=gettext('Search')?>
160
			<span class="widget-heading-icon pull-right">
161
				<a data-toggle="collapse" href="#search-panel_panel-body">
162
					<i class="fa fa-plus-circle"></i>
163
				</a>
164
			</span>
165
		</h2>
166
	</div>
167
	<div id="search-panel_panel-body" class="panel-body collapse in">
168
		<div class="form-group">
169
			<label class="col-sm-2 control-label">
170
				<?=gettext("Search term")?>
171
			</label>
172
			<div class="col-sm-5"><input class="form-control" name="searchstr" id="searchstr" type="text"/></div>
173
			<div class="col-sm-2">
174
				<select id="where" class="form-control">
175
					<option value="0"><?=gettext("Interface")?></option>
176
					<option value="1"><?=gettext("IP Address")?></option>
177
					<option value="2"><?=gettext("MAC Address")?></option>
178
					<option value="3"><?=gettext("Hostname")?></option>
179
					<option value="4"><?=gettext("Status")?></option>
180
					<option value="5"><?=gettext("Link Type")?></option>
181
					<option value="6" selected><?=gettext("All")?></option>
182
				</select>
183
			</div>
184
			<div class="col-sm-3">
185
				<a id="btnsearch" title="<?=gettext("Search")?>" class="btn btn-primary btn-sm"><i class="fa fa-search icon-embed-btn"></i><?=gettext("Search")?></a>
186
				<a id="btnclear" title="<?=gettext("Clear")?>" class="btn btn-info btn-sm"><i class="fa fa-undo icon-embed-btn"></i><?=gettext("Clear")?></a>
187
			</div>
188
			<div class="col-sm-10 col-sm-offset-2">
189
				<span class="help-block"><?=gettext('Enter a search string or *nix regular expression to filter entries.')?></span>
190
			</div>
191
		</div>
192
	</div>
193
</div>
194

    
195
<div class="panel panel-default">
196
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('ARP Table')?></h2></div>
197
	<div class="panel-body">
198

    
199
<div class="table-responsive">
200
	<table class="sortable-theme-bootstrap table table-striped table-hover" data-sortable>
201
		<thead>
202
			<tr>
203
				<th><?= gettext("Interface")?></th>
204
				<th><?= gettext("IP address")?></th>
205
				<th><?= gettext("MAC address")?></th>
206
				<th><?= gettext("Hostname")?></th>
207
				<th><?= gettext("Status")?></th>
208
				<th><?= gettext("Link Type")?></th>
209
				<th data-sortable="false"><?=gettext("Actions")?></th>
210
			</tr>
211
		</thead>
212
		<tbody>
213

    
214
<?php
215
		foreach ($arp_table as $entry): ?>
216
			<tr>
217
				<td><?=$hwif[$entry['interface']]?></td>
218
				<td><?=$entry['ip-address']?></td>
219
<?php
220
				if (empty($entry['mac-address'])) {
221
					$mac = '(' . gettext("Incomplete") .')';
222
					print "<td>{$mac}</td>";
223
				} else {
224
					$mac = trim($entry['mac-address']);
225
					print "<td>{$mac}";
226
					$mac_hi = strtoupper($mac[0] . $mac[1] .
227
					    $mac[3] . $mac[4] . $mac[6] .
228
					    $mac[7]);
229

    
230
					if (isset($mac_man[$mac_hi])) {
231
						print ' <small>('.
232
						    $mac_man[$mac_hi] .
233
						    ')</small>';
234
					}
235
				}
236

    
237
				$status = '';
238
				if (!empty($entry['expires'])) {
239
					$status = sprintf(gettext(
240
					    "Expires in %d seconds"),
241
					    $entry['expires']);
242
				} else if (!empty($entry['permanent'])) {
243
					$status = gettext("Permanent");
244
				}
245
?>
246
				</td>
247
				<td><?=trim(str_replace("Z_ ", "", $entry['dnsresolve']))?></td>
248
				<td><?=ucfirst($status)?></td>
249
				<td><?=$entry['type']?></td>
250
				<td>
251
					<a class="fa fa-trash" title="<?=gettext('Delete arp cache entry')?>"	href="diag_arp.php?deleteentry=<?=$entry['ip-address']?>" usepost></a>
252
				</td>
253
			</tr>
254
<?php
255
		endforeach
256
?>
257
		</tbody>
258
	</table>
259
</div>
260

    
261
	</div>
262
</div>
263

    
264
<script type="text/javascript">
265
//<![CDATA[
266
// Clear the "loading" div once the page has loaded"
267
events.push(function() {
268
	$('#loading').empty();
269

    
270
	// Make these controls plain buttons
271
	$("#btnsearch").prop('type', 'button');
272
	$("#btnclear").prop('type', 'button');
273

    
274
	// Search for a term in the entry name and/or dn
275
	$("#btnsearch").click(function() {
276
		var searchstr = $('#searchstr').val().toLowerCase();
277
		var table = $("table tbody");
278
		var where = $('#where').val();
279

    
280
		table.find('tr').each(function (i) {
281
			var $tds = $(this).find('td'),
282
				iface    = $tds.eq(0).text().trim().toLowerCase(),
283
				ipaddr   = $tds.eq(1).text().trim().toLowerCase();
284
				macaddr  = $tds.eq(2).text().trim().toLowerCase();
285
				hostname = $tds.eq(3).text().trim().toLowerCase();
286
				stat     = $tds.eq(4).text().trim().toLowerCase();
287
				linktype = $tds.eq(5).text().trim().toLowerCase();
288

    
289
			regexp = new RegExp(searchstr);
290
			if (searchstr.length > 0) {
291
				if (!(regexp.test(iface)    && ((where == 0) || (where == 6))) &&
292
				    !(regexp.test(ipaddr)   && ((where == 1) || (where == 6))) &&
293
				    !(regexp.test(macaddr)  && ((where == 2) || (where == 6))) &&
294
				    !(regexp.test(hostname) && ((where == 3) || (where == 6))) &&
295
				    !(regexp.test(stat)     && ((where == 4) || (where == 6))) &&
296
				    !(regexp.test(linktype) && ((where == 5) || (where == 6)))
297
				    ) {
298
					$(this).hide();
299
				} else {
300
					$(this).show();
301
				}
302
			} else {
303
				$(this).show();	// A blank search string shows all
304
			}
305
		});
306
	});
307

    
308
	// Clear the search term and unhide all rows (that were hidden during a previous search)
309
	$("#btnclear").click(function() {
310
		var table = $("table tbody");
311

    
312
		$('#searchstr').val("");
313

    
314
		table.find('tr').each(function (i) {
315
			$(this).show();
316
		});
317
	});
318

    
319
	// Hitting the enter key will do the same as clicking the search button
320
	$("#searchstr").on("keyup", function (event) {
321
		if (event.keyCode == 13) {
322
			$("#btnsearch").get(0).click();
323
		}
324
	});
325

    
326
});
327
//]]>
328
</script>
329

    
330
<div class="infoblock blockopen">
331
<?php
332
print_info_box(sprintf(gettext('Local IPv6 peers use %1$sNDP%2$s instead of ARP.'), '<a href="diag_ndp.php">', '</a>') . '<br />' .
333
   '<br />' . gettext('Permanent ARP entries are shown for local interfaces or static ARP entries.') .
334
   '<br />' . gettext('Normal dynamic ARP entries show a countdown timer until they will expire and then be re-checked.') .
335
   '<br />' . gettext('Incomplete ARP entries indicate that the target host has not yet replied to an ARP request.'), 'info', false);
336
?>
337
</div>
338

    
339
<?php
340
include("foot.inc");
341
?>
(8-8/227)