Project

General

Profile

Download (9.92 KB) Statistics
| Branch: | Tag: | Revision:
1 93e1b16c Scott Ullrich
<?php
2
/*
3 c5d81585 Renato Botelho
 * diag_arp.php
4 9da2cf1c Stephen Beaver
 *
5 c5d81585 Renato Botelho
 * part of pfSense (https://www.pfsense.org)
6 81299b5c Renato Botelho
 * Copyright (c) 2004-2016 Rubicon Communications, LLC (Netgate)
7 c5d81585 Renato Botelho
 * All rights reserved.
8 fd9ebcd5 Stephen Beaver
 *
9 c5d81585 Renato Botelho
 * originally based on m0n0wall (http://m0n0.ch/wall)
10
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
11
 * All rights reserved.
12 fd9ebcd5 Stephen Beaver
 *
13 b12ea3fb Renato Botelho
 * Licensed under the Apache License, Version 2.0 (the "License");
14
 * you may not use this file except in compliance with the License.
15
 * You may obtain a copy of the License at
16 fd9ebcd5 Stephen Beaver
 *
17 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
18 fd9ebcd5 Stephen Beaver
 *
19 b12ea3fb Renato Botelho
 * Unless required by applicable law or agreed to in writing, software
20
 * distributed under the License is distributed on an "AS IS" BASIS,
21
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
 * See the License for the specific language governing permissions and
23
 * limitations under the License.
24 fd9ebcd5 Stephen Beaver
 */
25 93e1b16c Scott Ullrich
26 6b07c15a Matthew Grooms
##|+PRIV
27
##|*IDENT=page-diagnostics-arptable
28 5230f468 jim-p
##|*NAME=Diagnostics: ARP Table
29 6b07c15a Matthew Grooms
##|*DESCR=Allow access to the 'Diagnostics: ARP Table' page.
30
##|*MATCH=diag_arp.php*
31
##|-PRIV
32
33 868ba36d Scott Ullrich
@ini_set('zlib.output_compression', 0);
34
@ini_set('implicit_flush', 1);
35 6b07c15a Matthew Grooms
36 c81ef6e2 Phil Davis
require_once("guiconfig.inc");
37 6090e85b Bill Marquette
38 6ea0d41e stilez
// delete arp entry
39 7f4268b6 Steve Beaver
if (isset($_POST['deleteentry'])) {
40
	$ip = $_POST['deleteentry'];
41 6ea0d41e stilez
	if (is_ipaddrv4($ip)) {
42 7f4268b6 Steve Beaver
		$ret = mwexec("arp -d " . $_POST['deleteentry'], true);
43 6ea0d41e stilez
	} else {
44
		$ret = 1;
45
	}
46
	if ($ret) {
47
		$savemsg = sprintf(gettext("%s is not a valid IPv4 address or could not be deleted."), $ip);
48
		$savemsgtype = 'alert-warning';
49
	} else {
50
		$savemsg = sprintf(gettext("The ARP cache entry for %s has been deleted."), $ip);
51
		$savemsgtype = 'success';
52
	}
53
}
54
55 fc259334 Seth Mos
function leasecmp($a, $b) {
56 7f4268b6 Steve Beaver
	return strcmp($a[$_REQUEST['order']], $b[$_REQUEST['order']]);
57 fc259334 Seth Mos
}
58 93e1b16c Scott Ullrich
59 fc259334 Seth Mos
function adjust_gmt($dt) {
60
	$ts = strtotime($dt . " GMT");
61
	return strftime("%Y/%m/%d %H:%M:%S", $ts);
62
}
63 93e1b16c Scott Ullrich
64 fc259334 Seth Mos
function remove_duplicate($array, $field) {
65 5f601060 Phil Davis
	foreach ($array as $sub) {
66 20b9b335 Scott Ullrich
		$cmp[] = $sub[$field];
67 5f601060 Phil Davis
	}
68 fc259334 Seth Mos
	$unique = array_unique($cmp);
69 5f601060 Phil Davis
	foreach ($unique as $k => $rien) {
70 fc259334 Seth Mos
		$new[] = $array[$k];
71 5f601060 Phil Davis
	}
72 fc259334 Seth Mos
	return $new;
73
}
74 93e1b16c Scott Ullrich
75 20b9b335 Scott Ullrich
// Define path to AWK
76 fc259334 Seth Mos
$awk = "/usr/bin/awk";
77 20b9b335 Scott Ullrich
78
// Read in leases file
79
$leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases";
80
81 fc259334 Seth Mos
/* this pattern sticks comments into a single array item */
82
$cleanpattern = "'{ gsub(\"#.*\", \"\");} { gsub(\";\", \"\"); print;}'";
83 20b9b335 Scott Ullrich
84 fc259334 Seth Mos
/* We then split the leases file by } */
85
$splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'";
86 93e1b16c Scott Ullrich
87 5f601060 Phil Davis
/* stuff the leases file in a proper format into an array by line */
88 fc259334 Seth Mos
exec("cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content);
89
$leases_count = count($leases_content);
90
91
$pools = array();
92
$leases = array();
93
$i = 0;
94
$l = 0;
95
$p = 0;
96
// Put everything together again
97 5f601060 Phil Davis
while ($i < $leases_count) {
98 b45630bf jim-p
	/* split the line by space */
99
	$data = explode(" ", $leases_content[$i]);
100
	/* walk the fields */
101
	$f = 0;
102
	$fcount = count($data);
103
	/* with less then 20 fields there is nothing useful */
104 5f601060 Phil Davis
	if ($fcount < 20) {
105 b45630bf jim-p
		$i++;
106
		continue;
107
	}
108 5f601060 Phil Davis
	while ($f < $fcount) {
109
		switch ($data[$f]) {
110 b45630bf jim-p
			case "failover":
111
				$pools[$p]['name'] = $data[$f+2];
112
				$pools[$p]['mystate'] = $data[$f+7];
113
				$pools[$p]['peerstate'] = $data[$f+14];
114
				$pools[$p]['mydate'] = $data[$f+10];
115
				$pools[$p]['mydate'] .= " " . $data[$f+11];
116
				$pools[$p]['peerdate'] = $data[$f+17];
117
				$pools[$p]['peerdate'] .= " " . $data[$f+18];
118
				$p++;
119
				$i++;
120
				continue 3;
121
			case "lease":
122
				$leases[$l]['ip'] = $data[$f+1];
123
				$leases[$l]['type'] = "dynamic";
124
				$f = $f+2;
125
				break;
126
			case "starts":
127
				$leases[$l]['start'] = $data[$f+2];
128
				$leases[$l]['start'] .= " " . $data[$f+3];
129
				$f = $f+3;
130
				break;
131
			case "ends":
132
				$leases[$l]['end'] = $data[$f+2];
133
				$leases[$l]['end'] .= " " . $data[$f+3];
134
				$f = $f+3;
135
				break;
136
			case "tstp":
137
				$f = $f+3;
138
				break;
139
			case "tsfp":
140
				$f = $f+3;
141
				break;
142
			case "atsfp":
143
				$f = $f+3;
144
				break;
145
			case "cltt":
146
				$f = $f+3;
147
				break;
148
			case "binding":
149 699737d9 Phil Davis
				switch ($data[$f+2]) {
150 b45630bf jim-p
					case "active":
151
						$leases[$l]['act'] = "active";
152
						break;
153
					case "free":
154
						$leases[$l]['act'] = "expired";
155
						$leases[$l]['online'] = "offline";
156
						break;
157
					case "backup":
158
						$leases[$l]['act'] = "reserved";
159
						$leases[$l]['online'] = "offline";
160
						break;
161
				}
162
				$f = $f+1;
163
				break;
164
			case "next":
165
				/* skip the next binding statement */
166
				$f = $f+3;
167
				break;
168 f1273b82 jim-p
			case "rewind":
169
				/* skip the rewind binding statement */
170
				$f = $f+3;
171
				break;
172 b45630bf jim-p
			case "hardware":
173
				$leases[$l]['mac'] = $data[$f+2];
174
				/* check if it's online and the lease is active */
175 5f601060 Phil Davis
				if ($leases[$l]['act'] == "active") {
176 b45630bf jim-p
					$online = exec("/usr/sbin/arp -an |/usr/bin/awk '/{$leases[$l]['ip']}/ {print}'|wc -l");
177
					if ($online == 1) {
178
						$leases[$l]['online'] = 'online';
179
					} else {
180
						$leases[$l]['online'] = 'offline';
181
					}
182
				}
183
				$f = $f+2;
184
				break;
185
			case "client-hostname":
186 5f601060 Phil Davis
				if ($data[$f+1] <> "") {
187 699737d9 Phil Davis
					$leases[$l]['hostname'] = preg_replace('/"/', '', $data[$f+1]);
188 b45630bf jim-p
				} else {
189
					$hostname = gethostbyaddr($leases[$l]['ip']);
190 5f601060 Phil Davis
					if ($hostname <> "") {
191 b45630bf jim-p
						$leases[$l]['hostname'] = $hostname;
192
					}
193
				}
194
				$f = $f+1;
195
				break;
196
			case "uid":
197
				$f = $f+1;
198
				break;
199
		}
200
		$f++;
201
	}
202
	$l++;
203
	$i++;
204 fc259334 Seth Mos
}
205
206
/* remove duplicate items by mac address */
207 5f601060 Phil Davis
if (count($leases) > 0) {
208 699737d9 Phil Davis
	$leases = remove_duplicate($leases, "ip");
209 fc259334 Seth Mos
}
210
211 5f601060 Phil Davis
if (count($pools) > 0) {
212 699737d9 Phil Davis
	$pools = remove_duplicate($pools, "name");
213 b45630bf jim-p
	asort($pools);
214 fc259334 Seth Mos
}
215
216
// Put this in an easy to use form
217
$dhcpmac = array();
218
$dhcpip = array();
219 f8ec8de4 Renato Botelho
220 fc259334 Seth Mos
foreach ($leases as $value) {
221 f8ec8de4 Renato Botelho
	$dhcpmac[$value['mac']] = $value['hostname'];
222
	$dhcpip[$value['ip']] = $value['hostname'];
223 93e1b16c Scott Ullrich
}
224
225 699737d9 Phil Davis
exec("/usr/sbin/arp -an", $rawdata);
226 93e1b16c Scott Ullrich
227 f8ec8de4 Renato Botelho
$i = 0;
228 cbe3ea96 Ermal Luçi
229
/* if list */
230
$ifdescrs = get_configured_interface_with_descr();
231 93e1b16c Scott Ullrich
232 e7237dd0 jim-p
foreach ($ifdescrs as $key => $interface) {
233
	$thisif = convert_friendly_interface_to_real_interface_name($key);
234 5f601060 Phil Davis
	if (!empty($thisif)) {
235 e7237dd0 jim-p
		$hwif[$thisif] = $interface;
236 5f601060 Phil Davis
	}
237 93e1b16c Scott Ullrich
}
238
239
$data = array();
240
foreach ($rawdata as $line) {
241 9e3cb876 jim-p
	$elements = explode(' ', $line, 7);
242
	$arpent = array();
243
	$arpent['ip'] = trim(str_replace(array('(', ')'), '', $elements[1]));
244
	$arpent['mac'] = trim($elements[3]);
245
	$arpent['interface'] = trim($elements[5]);
246
	$arpent['status'] = trim(substr($elements[6], 0, strrpos($elements[6], ' ')));
247
	$arpent['linktype'] = trim(str_replace(array('[', ']'), '', strrchr($elements[6], ' ')));
248
	$data[] = $arpent;
249 93e1b16c Scott Ullrich
}
250
251 699737d9 Phil Davis
function _getHostName($mac, $ip) {
252 93e1b16c Scott Ullrich
	global $dhcpmac, $dhcpip;
253 f8ec8de4 Renato Botelho
254 5f601060 Phil Davis
	if ($dhcpmac[$mac]) {
255 93e1b16c Scott Ullrich
		return $dhcpmac[$mac];
256 5f601060 Phil Davis
	} else if ($dhcpip[$ip]) {
257 93e1b16c Scott Ullrich
		return $dhcpip[$ip];
258 5f601060 Phil Davis
	} else {
259 d31ca336 Renato Botelho
		exec("host -W 1 " . escapeshellarg($ip), $output);
260 699737d9 Phil Davis
		if (preg_match('/.*pointer ([A-Za-z_0-9.-]+)\..*/', $output[0], $matches)) {
261 5f601060 Phil Davis
			if ($matches[1] <> $ip) {
262 7d5b007c Sjon Hortensius
				return $matches[1];
263 5f601060 Phil Davis
			}
264 dd4bded7 Evgeny Yurchenko
		}
265
	}
266
	return "";
267 93e1b16c Scott Ullrich
}
268
269 699737d9 Phil Davis
$pgtitle = array(gettext("Diagnostics"), gettext("ARP Table"));
270 fc259334 Seth Mos
include("head.inc");
271 20b9b335 Scott Ullrich
272 6ea0d41e stilez
// Handle save msg if defined
273
if ($savemsg) {
274
	print_info_box(htmlentities($savemsg), $savemsgtype);
275
}
276 93e1b16c Scott Ullrich
?>
277 20b9b335 Scott Ullrich
278 a4af095c Renato Botelho
<!-- On modern hardware the table will load so fast you may never see this! -->
279 4a993c8f Scott Ullrich
<div id="loading">
280 a4af095c Renato Botelho
	<?= gettext(" Loading, please wait...")?>
281 4a993c8f Scott Ullrich
</div>
282
283
<?php
284
285 868ba36d Scott Ullrich
// Flush buffers out to client so that they see Loading, please wait....
286 5f601060 Phil Davis
for ($i = 0; $i < ob_get_level(); $i++) {
287
	ob_end_flush();
288
}
289 608947a8 Stephen Beaver
290 868ba36d Scott Ullrich
ob_implicit_flush(1);
291
292 20b9b335 Scott Ullrich
// Resolve hostnames and replace Z_ with "".  The intention
293
// is to sort the list by hostnames, alpha and then the non
294
// resolvable addresses will appear last in the list.
295 dd4bded7 Evgeny Yurchenko
$dnsavailable=1;
296 7d5b007c Sjon Hortensius
$dns = trim(_getHostName("", "8.8.8.8"));
297 5f601060 Phil Davis
if ($dns == "") {
298 7d5b007c Sjon Hortensius
	$dns = trim(_getHostName("", "8.8.4.4"));
299 5f601060 Phil Davis
	if ($dns == "") {
300
		$dnsavailable = 0;
301
	}
302 dd4bded7 Evgeny Yurchenko
}
303
304 4a993c8f Scott Ullrich
foreach ($data as &$entry) {
305 5f601060 Phil Davis
	if ($dnsavailable) {
306 dd4bded7 Evgeny Yurchenko
		$dns = trim(_getHostName($entry['mac'], $entry['ip']));
307 5f601060 Phil Davis
	} else {
308 dd4bded7 Evgeny Yurchenko
		$dns="";
309 5f601060 Phil Davis
	}
310
	if (trim($dns)) {
311 4a993c8f Scott Ullrich
		$entry['dnsresolve'] = "$dns";
312 5f601060 Phil Davis
	} else {
313 4a993c8f Scott Ullrich
		$entry['dnsresolve'] = "Z_ ";
314 5f601060 Phil Davis
	}
315 4a993c8f Scott Ullrich
}
316 8ed2d200 NewEraCracker
unset($entry);
317 20b9b335 Scott Ullrich
318
// Sort the data alpha first
319 4a993c8f Scott Ullrich
$data = msort($data, "dnsresolve");
320
321 57f2840e Evgeny
// Load MAC-Manufacturer table
322
$mac_man = load_mac_manufacturer_table();
323 4a993c8f Scott Ullrich
?>
324 ac950976 Colin Fleming
<div class="panel panel-default">
325
	<div class="panel-heading"><h2 class="panel-title"><?=gettext('ARP Table')?></h2></div>
326
	<div class="panel-body">
327
328 89f64f0f Sander van Leeuwen
<div class="table-responsive">
329 608947a8 Stephen Beaver
	<table class="sortable-theme-bootstrap table table-striped table-hover" data-sortable>
330 89f64f0f Sander van Leeuwen
		<thead>
331
			<tr>
332
				<th><?= gettext("Interface")?></th>
333
				<th><?= gettext("IP address")?></th>
334
				<th><?= gettext("MAC address")?></th>
335
				<th><?= gettext("Hostname")?></th>
336 9e3cb876 jim-p
				<th><?= gettext("Status")?></th>
337
				<th><?= gettext("Link Type")?></th>
338 6ea0d41e stilez
				<th data-sortable="false"><?=gettext("Actions")?></th>
339 89f64f0f Sander van Leeuwen
			</tr>
340
		</thead>
341
		<tbody>
342 947141fd Phil Davis
343 82afb104 Stephen Beaver
<?php
344
		foreach ($data as $entry): ?>
345 89f64f0f Sander van Leeuwen
			<tr>
346
				<td><?=$hwif[$entry['interface']]?></td>
347
				<td><?=$entry['ip']?></td>
348
				<td>
349
					<?=trim($entry['mac'])?>
350
				<?php
351
					$mac = trim($entry['mac']);
352
					$mac_hi = strtoupper($mac[0] . $mac[1] . $mac[3] . $mac[4] . $mac[6] . $mac[7]);
353
354 cba48c64 Colin Fleming
					if (isset($mac_man[$mac_hi])) {
355 89f64f0f Sander van Leeuwen
						print '<small>('. $mac_man[$mac_hi] .')</small>';
356 cba48c64 Colin Fleming
					}
357 89f64f0f Sander van Leeuwen
	?>
358
				</td>
359
				<td><?=trim(str_replace("Z_ ", "", $entry['dnsresolve']))?></td>
360 9e3cb876 jim-p
				<td><?=ucfirst($entry['status'])?></td>
361
				<td><?=$entry['linktype']?></td>
362 6ea0d41e stilez
				<td>
363 7f4268b6 Steve Beaver
					<a class="fa fa-trash" title="<?=gettext('Delete arp cache entry')?>"	href="diag_arp.php?deleteentry=<?=$entry['ip']?>" usepost></a>
364 6ea0d41e stilez
				</td>
365 89f64f0f Sander van Leeuwen
			</tr>
366
		<?php endforeach?>
367
		</tbody>
368
	</table>
369
</div>
370
371 ac950976 Colin Fleming
	</div>
372
</div>
373
374 cba48c64 Colin Fleming
<script type="text/javascript">
375 293ceb87 Colin Fleming
//<![CDATA[
376 a4af095c Renato Botelho
// Clear the "loading" div once the page has loaded"
377 947141fd Phil Davis
events.push(function() {
378 a4af095c Renato Botelho
	$('#loading').empty();
379
});
380 0da0d43e Phil Davis
//]]>
381 4a993c8f Scott Ullrich
</script>
382 a4af095c Renato Botelho
383 c40962e9 Phil Davis
<div class="infoblock blockopen">
384 0da0d43e Phil Davis
<?php
385 5db70796 Phil Davis
print_info_box(sprintf(gettext('Local IPv6 peers use %1$sNDP%2$s instead of ARP.'), '<a href="diag_ndp.php">', '</a>') . '<br />' .
386
   '<br />' . gettext('Permanent ARP entries are shown for local interfaces or static ARP entries.') .
387
   '<br />' . gettext('Normal dynamic ARP entries show a countdown timer until they will expire and then be re-checked.') .
388
   '<br />' . gettext('Incomplete ARP entries indicate that the target host has not yet replied to an ARP request.'), 'info', false);
389 c40962e9 Phil Davis
?>
390
</div>
391 93e1b16c Scott Ullrich
392 c40962e9 Phil Davis
<?php
393
include("foot.inc");
394
?>