Project

General

Profile

Download (10.9 KB) Statistics
| Branch: | Tag: | Revision:
1 93e1b16c Scott Ullrich
<?php
2
/*
3
	diag_arp.php
4 20b9b335 Scott Ullrich
	part of the pfSense project	(http://www.pfsense.org)
5 13d193c2 Scott Ullrich
	Copyright (C) 2004-2009 Scott Ullrich <sullrich@gmail.com>
6 93e1b16c Scott Ullrich
7 20b9b335 Scott Ullrich
	originally part of m0n0wall (http://m0n0.ch/wall)
8 93e1b16c Scott Ullrich
	Copyright (C) 2005 Paul Taylor (paultaylor@winndixie.com) and Manuel Kasper <mk@neon1.net>.
9
	All rights reserved.
10
11
	Redistribution and use in source and binary forms, with or without
12
	modification, are permitted provided that the following conditions are met:
13
14
	1. Redistributions of source code must retain the above copyright notice,
15
	this list of conditions and the following disclaimer.
16
17
	2. Redistributions in binary form must reproduce the above copyright
18
	notice, this list of conditions and the following disclaimer in the
19
	documentation and/or other materials provided with the distribution.
20
21
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
	POSSIBILITY OF SUCH DAMAGE.
31
*/
32
33 13d193c2 Scott Ullrich
/*
34
	pfSense_BUILDER_BINARIES:	/bin/cat		/usr/sbin/arp
35
	pfSense_MODULE:	arp
36
*/
37
38 6b07c15a Matthew Grooms
##|+PRIV
39
##|*IDENT=page-diagnostics-arptable
40
##|*NAME=Diagnostics: ARP Table page
41
##|*DESCR=Allow access to the 'Diagnostics: ARP Table' page.
42
##|*MATCH=diag_arp.php*
43
##|-PRIV
44
45 868ba36d Scott Ullrich
@ini_set('zlib.output_compression', 0);
46
@ini_set('implicit_flush', 1);
47 6b07c15a Matthew Grooms
48 93e1b16c Scott Ullrich
require("guiconfig.inc");
49 6090e85b Bill Marquette
50 fc259334 Seth Mos
function leasecmp($a, $b) {
51
	return strcmp($a[$_GET['order']], $b[$_GET['order']]);
52
}
53 93e1b16c Scott Ullrich
54 fc259334 Seth Mos
function adjust_gmt($dt) {
55
	$ts = strtotime($dt . " GMT");
56
	return strftime("%Y/%m/%d %H:%M:%S", $ts);
57
}
58 93e1b16c Scott Ullrich
59 fc259334 Seth Mos
function remove_duplicate($array, $field) {
60 20b9b335 Scott Ullrich
	foreach ($array as $sub)
61
		$cmp[] = $sub[$field];
62 fc259334 Seth Mos
	$unique = array_unique($cmp);
63
	foreach ($unique as $k => $rien)
64
		$new[] = $array[$k];
65
	return $new;
66
}
67 93e1b16c Scott Ullrich
68 20b9b335 Scott Ullrich
// Define path to AWK
69 fc259334 Seth Mos
$awk = "/usr/bin/awk";
70 20b9b335 Scott Ullrich
71
// Read in leases file
72
$leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases";
73
74 fc259334 Seth Mos
/* this pattern sticks comments into a single array item */
75
$cleanpattern = "'{ gsub(\"#.*\", \"\");} { gsub(\";\", \"\"); print;}'";
76 20b9b335 Scott Ullrich
77 fc259334 Seth Mos
/* We then split the leases file by } */
78
$splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'";
79 93e1b16c Scott Ullrich
80 fc259334 Seth Mos
/* stuff the leases file in a proper format into a array by line */
81
exec("cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content);
82
$leases_count = count($leases_content);
83
84
$pools = array();
85
$leases = array();
86
$i = 0;
87
$l = 0;
88
$p = 0;
89
// Put everything together again
90
while($i < $leases_count) {
91
        /* split the line by space */
92
        $data = explode(" ", $leases_content[$i]);
93
        /* walk the fields */
94
        $f = 0;
95
        $fcount = count($data);
96
        /* with less then 20 fields there is nothing useful */
97
        if($fcount < 20) {
98
                $i++;
99
                continue;
100
        }
101
        while($f < $fcount) {
102
                switch($data[$f]) {
103
                        case "failover":
104
                                $pools[$p]['name'] = $data[$f+2];
105
                                $pools[$p]['mystate'] = $data[$f+7];
106
                                $pools[$p]['peerstate'] = $data[$f+14];
107
                                $pools[$p]['mydate'] = $data[$f+10];
108
                                $pools[$p]['mydate'] .= " " . $data[$f+11];
109
                                $pools[$p]['peerdate'] = $data[$f+17];
110
                                $pools[$p]['peerdate'] .= " " . $data[$f+18];
111
                                $p++;
112
                                $i++;
113
                                continue 3;
114
                        case "lease":
115
                                $leases[$l]['ip'] = $data[$f+1];
116
                                $leases[$l]['type'] = "dynamic";
117
                                $f = $f+2;
118
                                break;
119
                        case "starts":
120
                                $leases[$l]['start'] = $data[$f+2];
121
                                $leases[$l]['start'] .= " " . $data[$f+3];
122
                                $f = $f+3;
123
                                break;
124
                        case "ends":
125
                                $leases[$l]['end'] = $data[$f+2];
126
                                $leases[$l]['end'] .= " " . $data[$f+3];
127
                                $f = $f+3;
128
                                break;
129
                        case "tstp":
130
                                $f = $f+3;
131
                                break;
132
                        case "tsfp":
133
                                $f = $f+3;
134
                                break;
135
                        case "atsfp":
136
                                $f = $f+3;
137
                                break;
138
                        case "cltt":
139
                                $f = $f+3;
140
                                break;
141
                        case "binding":
142
                                switch($data[$f+2]) {
143
                                        case "active":
144
                                                $leases[$l]['act'] = "active";
145
                                                break;
146
                                        case "free":
147
                                                $leases[$l]['act'] = "expired";
148
                                                $leases[$l]['online'] = "offline";
149
                                                break;
150
                                        case "backup":
151
                                                $leases[$l]['act'] = "reserved";
152
                                                $leases[$l]['online'] = "offline";
153
                                                break;
154
                                }
155
                                $f = $f+1;
156
                                break;
157
                        case "next":
158
                                /* skip the next binding statement */
159
                                $f = $f+3;
160
                                break;
161
                        case "hardware":
162
                                $leases[$l]['mac'] = $data[$f+2];
163
                                /* check if it's online and the lease is active */
164
                                if($leases[$l]['act'] == "active") {
165
                                        $online = exec("/usr/sbin/arp -an |/usr/bin/awk '/{$leases[$l]['ip']}/ {print}'|wc -l");
166
                                        if ($online == 1) {
167
                                                $leases[$l]['online'] = 'online';
168
                                        } else {
169
                                                $leases[$l]['online'] = 'offline';
170
                                        }
171
                                }
172
                                $f = $f+2;
173
                                break;
174
                        case "client-hostname":
175
                                if($data[$f+1] <> "") {
176
                                        $leases[$l]['hostname'] = preg_replace('/"/','',$data[$f+1]);
177
                                } else {
178
                                        $hostname = gethostbyaddr($leases[$l]['ip']);
179
                                        if($hostname <> "") {
180
                                                $leases[$l]['hostname'] = $hostname;
181
                                        }
182
                                }
183
                                $f = $f+1;
184
                                break;
185
                        case "uid":
186
                                $f = $f+1;
187
                                break;
188
                }
189
                $f++;
190
        }
191
        $l++;
192
        $i++;
193
}
194
195
/* remove duplicate items by mac address */
196
if(count($leases) > 0) {
197
        $leases = remove_duplicate($leases,"ip");
198
}
199
200
if(count($pools) > 0) {
201
        $pools = remove_duplicate($pools,"name");
202
        asort($pools);
203
}
204
205
// Put this in an easy to use form
206
$dhcpmac = array();
207
$dhcpip = array();
208 f8ec8de4 Renato Botelho
209 fc259334 Seth Mos
foreach ($leases as $value) {
210 f8ec8de4 Renato Botelho
	$dhcpmac[$value['mac']] = $value['hostname'];
211
	$dhcpip[$value['ip']] = $value['hostname'];
212 93e1b16c Scott Ullrich
}
213
214
exec("/usr/sbin/arp -an",$rawdata);
215
216 f8ec8de4 Renato Botelho
$i = 0;
217 cbe3ea96 Ermal Luçi
218
/* if list */
219
$ifdescrs = get_configured_interface_with_descr();
220 93e1b16c Scott Ullrich
221
foreach ($ifdescrs as $key =>$interface) {
222
	$hwif[$config['interfaces'][$key]['if']] = $interface;
223
}
224
225
$data = array();
226
foreach ($rawdata as $line) {
227
	$elements = explode(' ',$line);
228 f8ec8de4 Renato Botelho
229 93e1b16c Scott Ullrich
	if ($elements[3] != "(incomplete)") {
230
		$arpent = array();
231
		$arpent['ip'] = trim(str_replace(array('(',')'),'',$elements[1]));
232
		$arpent['mac'] = trim($elements[3]);
233
		$arpent['interface'] = trim($elements[5]);
234
		$data[] = $arpent;
235
	}
236
}
237
238 4d71d68c Renato Botelho
function _getHostName($mac,$ip)
239 93e1b16c Scott Ullrich
{
240
	global $dhcpmac, $dhcpip;
241 f8ec8de4 Renato Botelho
242 93e1b16c Scott Ullrich
	if ($dhcpmac[$mac])
243
		return $dhcpmac[$mac];
244
	else if ($dhcpip[$ip])
245
		return $dhcpip[$ip];
246 4dedef58 Scott Ullrich
	else if(gethostbyaddr($ip) <> "" and gethostbyaddr($ip) <> $ip)
247
		return gethostbyaddr($ip);
248 f8ec8de4 Renato Botelho
	else
249
		return "";
250 93e1b16c Scott Ullrich
}
251
252 f8ec8de4 Renato Botelho
$pgtitle = array(gettext("Diagnostics"),gettext("ARP Table"));
253 fc259334 Seth Mos
include("head.inc");
254 20b9b335 Scott Ullrich
255 93e1b16c Scott Ullrich
?>
256 20b9b335 Scott Ullrich
257 fc259334 Seth Mos
<body link="#000000" vlink="#000000" alink="#000000">
258 f8ec8de4 Renato Botelho
259 20b9b335 Scott Ullrich
<?php include("fbegin.inc"); ?>
260 4a993c8f Scott Ullrich
261
<div id="loading">
262 dc9975f4 Warren Baker
	<img src="/themes/<?=$g['theme'];?>/images/misc/loader.gif"><?= gettext("Loading, please wait..."); ?>
263 4a993c8f Scott Ullrich
	<p/>&nbsp;
264
</div>
265
266
<?php
267
268 868ba36d Scott Ullrich
// Flush buffers out to client so that they see Loading, please wait....
269
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
270
ob_implicit_flush(1);
271
272 20b9b335 Scott Ullrich
// Resolve hostnames and replace Z_ with "".  The intention
273
// is to sort the list by hostnames, alpha and then the non
274
// resolvable addresses will appear last in the list.
275 4a993c8f Scott Ullrich
foreach ($data as &$entry) {
276 4d71d68c Renato Botelho
	$dns = trim(_getHostName($entry['mac'], $entry['ip']));
277 4a993c8f Scott Ullrich
	if(trim($dns))
278
		$entry['dnsresolve'] = "$dns";
279 f8ec8de4 Renato Botelho
	else
280 4a993c8f Scott Ullrich
		$entry['dnsresolve'] = "Z_ ";
281
}
282 20b9b335 Scott Ullrich
283
// Sort the data alpha first
284 4a993c8f Scott Ullrich
$data = msort($data, "dnsresolve");
285
286
?>
287 fc259334 Seth Mos
<table width="100%" border="0" cellpadding="0" cellspacing="0">
288 20b9b335 Scott Ullrich
	<tr>
289
		<td>
290
			<table class="tabcont sortable" width="100%" border="0" cellpadding="0" cellspacing="0">
291
				<tr>
292 f8ec8de4 Renato Botelho
					<td class="listhdrr"><?= gettext("IP address"); ?></td>
293
					<td class="listhdrr"><?= gettext("MAC address"); ?></td>
294
					<td class="listhdrr"><?= gettext("Hostname"); ?></td>
295
					<td class="listhdr"><?= gettext("Interface"); ?></td>
296 20b9b335 Scott Ullrich
					<td class="list"></td>
297
				</tr>
298
				<?php foreach ($data as $entry): ?>
299
					<tr>
300
						<td class="listlr"><?=$entry['ip'];?></td>
301
						<td class="listr"><?=$entry['mac'];?></td>
302
						<td class="listr">
303
							<?php
304
							echo str_replace("Z_ ", "", $entry['dnsresolve']);
305
							?>
306
						</td>
307
						<td class="listr"><?=$hwif[$entry['interface']];?></td>
308
					</tr>
309
				<?php endforeach; ?>
310
			</table>
311
		</td>
312
	</tr>
313 93e1b16c Scott Ullrich
</table>
314
315
<?php include("fend.inc"); ?>
316 4a993c8f Scott Ullrich
317
<script type="text/javascript">
318
	$('loading').innerHTML = '';
319
</script>