Project

General

Profile

Download (9.32 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	diag_arp.php
4
	part of the pfSense project	(https://www.pfsense.org)
5
	Copyright (C) 2004-2009 Scott Ullrich <sullrich@gmail.com>
6
        Copyright (C) 2013-2014 Electric Sheep Fencing, LP
7

    
8
	originally part of m0n0wall (http://m0n0.ch/wall)
9
	Copyright (C) 2005 Paul Taylor (paultaylor@winndixie.com) and Manuel Kasper <mk@neon1.net>.
10
	All rights reserved.
11

    
12
	Redistribution and use in source and binary forms, with or without
13
	modification, are permitted provided that the following conditions are met:
14

    
15
	1. Redistributions of source code must retain the above copyright notice,
16
	this list of conditions and the following disclaimer.
17

    
18
	2. Redistributions in binary form must reproduce the above copyright
19
	notice, this list of conditions and the following disclaimer in the
20
	documentation and/or other materials provided with the distribution.
21

    
22
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
26
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
	POSSIBILITY OF SUCH DAMAGE.
32
*/
33

    
34
/*
35
	pfSense_BUILDER_BINARIES:	/bin/cat		/usr/sbin/arp
36
	pfSense_MODULE:	arp
37
*/
38

    
39
##|+PRIV
40
##|*IDENT=page-diagnostics-arptable
41
##|*NAME=Diagnostics: ARP Table page
42
##|*DESCR=Allow access to the 'Diagnostics: ARP Table' page.
43
##|*MATCH=diag_arp.php*
44
##|-PRIV
45

    
46
@ini_set('zlib.output_compression', 0);
47
@ini_set('implicit_flush', 1);
48

    
49
require("guiconfig.inc");
50

    
51
function leasecmp($a, $b) {
52
	return strcmp($a[$_GET['order']], $b[$_GET['order']]);
53
}
54

    
55
function adjust_gmt($dt) {
56
	$ts = strtotime($dt . " GMT");
57
	return strftime("%Y/%m/%d %H:%M:%S", $ts);
58
}
59

    
60
function remove_duplicate($array, $field) {
61
	foreach ($array as $sub)
62
		$cmp[] = $sub[$field];
63
	$unique = array_unique($cmp);
64
	foreach ($unique as $k => $rien)
65
		$new[] = $array[$k];
66
	return $new;
67
}
68

    
69
// Define path to AWK
70
$awk = "/usr/bin/awk";
71

    
72
// Read in leases file
73
$leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases";
74

    
75
/* this pattern sticks comments into a single array item */
76
$cleanpattern = "'{ gsub(\"#.*\", \"\");} { gsub(\";\", \"\"); print;}'";
77

    
78
/* We then split the leases file by } */
79
$splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'";
80

    
81
/* stuff the leases file in a proper format into a array by line */
82
exec("cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content);
83
$leases_count = count($leases_content);
84

    
85
$pools = array();
86
$leases = array();
87
$i = 0;
88
$l = 0;
89
$p = 0;
90
// Put everything together again
91
while($i < $leases_count) {
92
	/* split the line by space */
93
	$data = explode(" ", $leases_content[$i]);
94
	/* walk the fields */
95
	$f = 0;
96
	$fcount = count($data);
97
	/* with less then 20 fields there is nothing useful */
98
	if($fcount < 20) {
99
		$i++;
100
		continue;
101
	}
102
	while($f < $fcount) {
103
		switch($data[$f]) {
104
			case "failover":
105
				$pools[$p]['name'] = $data[$f+2];
106
				$pools[$p]['mystate'] = $data[$f+7];
107
				$pools[$p]['peerstate'] = $data[$f+14];
108
				$pools[$p]['mydate'] = $data[$f+10];
109
				$pools[$p]['mydate'] .= " " . $data[$f+11];
110
				$pools[$p]['peerdate'] = $data[$f+17];
111
				$pools[$p]['peerdate'] .= " " . $data[$f+18];
112
				$p++;
113
				$i++;
114
				continue 3;
115
			case "lease":
116
				$leases[$l]['ip'] = $data[$f+1];
117
				$leases[$l]['type'] = "dynamic";
118
				$f = $f+2;
119
				break;
120
			case "starts":
121
				$leases[$l]['start'] = $data[$f+2];
122
				$leases[$l]['start'] .= " " . $data[$f+3];
123
				$f = $f+3;
124
				break;
125
			case "ends":
126
				$leases[$l]['end'] = $data[$f+2];
127
				$leases[$l]['end'] .= " " . $data[$f+3];
128
				$f = $f+3;
129
				break;
130
			case "tstp":
131
				$f = $f+3;
132
				break;
133
			case "tsfp":
134
				$f = $f+3;
135
				break;
136
			case "atsfp":
137
				$f = $f+3;
138
				break;
139
			case "cltt":
140
				$f = $f+3;
141
				break;
142
			case "binding":
143
				switch($data[$f+2]) {
144
					case "active":
145
						$leases[$l]['act'] = "active";
146
						break;
147
					case "free":
148
						$leases[$l]['act'] = "expired";
149
						$leases[$l]['online'] = "offline";
150
						break;
151
					case "backup":
152
						$leases[$l]['act'] = "reserved";
153
						$leases[$l]['online'] = "offline";
154
						break;
155
				}
156
				$f = $f+1;
157
				break;
158
			case "next":
159
				/* skip the next binding statement */
160
				$f = $f+3;
161
				break;
162
			case "rewind":
163
				/* skip the rewind binding statement */
164
				$f = $f+3;
165
				break;
166
			case "hardware":
167
				$leases[$l]['mac'] = $data[$f+2];
168
				/* check if it's online and the lease is active */
169
				if($leases[$l]['act'] == "active") {
170
					$online = exec("/usr/sbin/arp -an |/usr/bin/awk '/{$leases[$l]['ip']}/ {print}'|wc -l");
171
					if ($online == 1) {
172
						$leases[$l]['online'] = 'online';
173
					} else {
174
						$leases[$l]['online'] = 'offline';
175
					}
176
				}
177
				$f = $f+2;
178
				break;
179
			case "client-hostname":
180
				if($data[$f+1] <> "") {
181
					$leases[$l]['hostname'] = preg_replace('/"/','',$data[$f+1]);
182
				} else {
183
					$hostname = gethostbyaddr($leases[$l]['ip']);
184
					if($hostname <> "") {
185
						$leases[$l]['hostname'] = $hostname;
186
					}
187
				}
188
				$f = $f+1;
189
				break;
190
			case "uid":
191
				$f = $f+1;
192
				break;
193
		}
194
		$f++;
195
	}
196
	$l++;
197
	$i++;
198
}
199

    
200
/* remove duplicate items by mac address */
201
if(count($leases) > 0) {
202
	$leases = remove_duplicate($leases,"ip");
203
}
204

    
205
if(count($pools) > 0) {
206
	$pools = remove_duplicate($pools,"name");
207
	asort($pools);
208
}
209

    
210
// Put this in an easy to use form
211
$dhcpmac = array();
212
$dhcpip = array();
213

    
214
foreach ($leases as $value) {
215
	$dhcpmac[$value['mac']] = $value['hostname'];
216
	$dhcpip[$value['ip']] = $value['hostname'];
217
}
218

    
219
exec("/usr/sbin/arp -an",$rawdata);
220

    
221
$i = 0;
222

    
223
/* if list */
224
$ifdescrs = get_configured_interface_with_descr();
225

    
226
foreach ($ifdescrs as $key => $interface) {
227
	$thisif = convert_friendly_interface_to_real_interface_name($key);
228
	if (!empty($thisif))
229
		$hwif[$thisif] = $interface;
230
}
231

    
232
$data = array();
233
foreach ($rawdata as $line) {
234
	$elements = explode(' ',$line);
235

    
236
	if ($elements[3] != "(incomplete)") {
237
		$arpent = array();
238
		$arpent['ip'] = trim(str_replace(array('(',')'),'',$elements[1]));
239
		$arpent['mac'] = trim($elements[3]);
240
		$arpent['interface'] = trim($elements[5]);
241
		$data[] = $arpent;
242
	}
243
}
244

    
245
function _getHostName($mac,$ip) {
246
	global $dhcpmac, $dhcpip;
247

    
248
	if ($dhcpmac[$mac])
249
		return $dhcpmac[$mac];
250
	else if ($dhcpip[$ip])
251
		return $dhcpip[$ip];
252
	else{
253
		exec("host -W 1 " . escapeshellarg($ip), $output);
254
		if (preg_match('/.*pointer ([A-Za-z0-9.-]+)\..*/',$output[0],$matches)) {
255
			if ($matches[1] <> $ip)
256
				return $matches[1]; 
257
		}
258
	}
259
	return "";
260
}
261

    
262
$pgtitle = array(gettext("Diagnostics"),gettext("ARP Table"));
263
include("head.inc");
264

    
265
?>
266

    
267
<body link="#000000" vlink="#000000" alink="#000000">
268

    
269
<?php include("fbegin.inc"); ?>
270

    
271
<div id="loading">
272
	<img src="/themes/<?=$g['theme'];?>/images/misc/loader.gif" alt="loader" /><?= gettext("Loading, please wait..."); ?>
273
	<p>&nbsp;</p>
274
</div>
275

    
276
<?php
277

    
278
// Flush buffers out to client so that they see Loading, please wait....
279
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
280
ob_implicit_flush(1);
281

    
282
// Resolve hostnames and replace Z_ with "".  The intention
283
// is to sort the list by hostnames, alpha and then the non
284
// resolvable addresses will appear last in the list.
285
$dnsavailable=1;
286
$dns = trim(_getHostName("", "8.8.8.8")); 
287
if ($dns == ""){
288
	$dns = trim(_getHostName("", "8.8.4.4")); 
289
	if ($dns == "") $dnsavailable =0;
290
}
291

    
292
foreach ($data as &$entry) {
293
	if ($dnsavailable){
294
		$dns = trim(_getHostName($entry['mac'], $entry['ip']));
295
	}else
296
		$dns="";
297
	if(trim($dns))
298
		$entry['dnsresolve'] = "$dns";
299
	else
300
		$entry['dnsresolve'] = "Z_ ";
301
}
302

    
303
// Sort the data alpha first
304
$data = msort($data, "dnsresolve");
305

    
306
// Load MAC-Manufacturer table
307
$mac_man = load_mac_manufacturer_table();
308
?>
309
<table width="100%" border="0" cellpadding="0" cellspacing="0" summary="diag arp">
310
	<tr>
311
		<td>
312
			<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0" summary="tabcont">
313
				<tr>
314
					<td class="listhdrr"><?= gettext("IP address"); ?></td>
315
					<td class="listhdrr"><?= gettext("MAC address"); ?></td>
316
					<td class="listhdrr"><?= gettext("Hostname"); ?></td>
317
					<td class="listhdr"><?= gettext("Interface"); ?></td>
318
					<td class="list"></td>
319
				</tr>
320
				<?php foreach ($data as $entry): ?>
321
					<tr>
322
						<td class="listlr"><?=$entry['ip'];?></td>
323
						<td class="listr">
324
						<?php
325
						$mac=trim($entry['mac']);
326
						$mac_hi = strtoupper($mac[0] . $mac[1] . $mac[3] . $mac[4] . $mac[6] . $mac[7]);
327
						print $mac;
328
						if(isset($mac_man[$mac_hi])){ print "<br /><font size=\"-2\"><i>{$mac_man[$mac_hi]}</i></font>"; }
329
						?>
330
						</td>
331
						<td class="listr">
332
							<?php
333
							echo trim(str_replace("Z_ ", "", $entry['dnsresolve']));
334
							?>
335
						</td>
336
						<td class="listr"><?=$hwif[$entry['interface']];?></td>
337
					</tr>
338
				<?php endforeach; ?>
339
			</table>
340
		</td>
341
	</tr>
342
	<tr>
343
		<td><br /><?= gettext("NOTE: Local IPv6 peers use") ?> <a href="diag_ndp.php"><?= gettext("NDP") ?></a> <?= gettext("instead of ARP") ?>.</td>
344
	</tr>
345
</table>
346

    
347
<?php include("fend.inc"); ?>
348

    
349
<script type="text/javascript">
350
//<![CDATA[
351
	jQuery('#loading').html('');
352
//]]>
353
</script>
354
</body>
355
</html>
(5-5/256)