. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgment: * "This product includes software developed by the pfSense Project * for use in the pfSense® software distribution. (http://www.pfsense.org/). * * 4. The names "pfSense" and "pfSense Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * coreteam@pfsense.org. * * 5. Products derived from this software may not be called "pfSense" * nor may "pfSense" appear in their names without prior written * permission of the Electric Sheep Fencing, LLC. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * * "This product includes software developed by the pfSense Project * for use in the pfSense software distribution (http://www.pfsense.org/). * * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ ##|+PRIV ##|*IDENT=page-diagnostics-arptable ##|*NAME=Diagnostics: ARP Table ##|*DESCR=Allow access to the 'Diagnostics: ARP Table' page. ##|*MATCH=diag_arp.php* ##|-PRIV @ini_set('zlib.output_compression', 0); @ini_set('implicit_flush', 1); require_once("guiconfig.inc"); // delete arp entry if (isset($_GET['deleteentry'])) { $ip = $_GET['deleteentry']; if (is_ipaddrv4($ip)) { $ret = mwexec("arp -d " . $_GET['deleteentry'], true); } else { $ret = 1; } if ($ret) { $savemsg = sprintf(gettext("%s is not a valid IPv4 address or could not be deleted."), $ip); $savemsgtype = 'alert-warning'; } else { $savemsg = sprintf(gettext("The ARP cache entry for %s has been deleted."), $ip); $savemsgtype = 'success'; } } function leasecmp($a, $b) { return strcmp($a[$_GET['order']], $b[$_GET['order']]); } function adjust_gmt($dt) { $ts = strtotime($dt . " GMT"); return strftime("%Y/%m/%d %H:%M:%S", $ts); } function remove_duplicate($array, $field) { foreach ($array as $sub) { $cmp[] = $sub[$field]; } $unique = array_unique($cmp); foreach ($unique as $k => $rien) { $new[] = $array[$k]; } return $new; } // Define path to AWK $awk = "/usr/bin/awk"; // Read in leases file $leasesfile = "{$g['dhcpd_chroot_path']}/var/db/dhcpd.leases"; /* this pattern sticks comments into a single array item */ $cleanpattern = "'{ gsub(\"#.*\", \"\");} { gsub(\";\", \"\"); print;}'"; /* We then split the leases file by } */ $splitpattern = "'BEGIN { RS=\"}\";} {for (i=1; i<=NF; i++) printf \"%s \", \$i; printf \"}\\n\";}'"; /* stuff the leases file in a proper format into an array by line */ exec("cat {$leasesfile} | {$awk} {$cleanpattern} | {$awk} {$splitpattern}", $leases_content); $leases_count = count($leases_content); $pools = array(); $leases = array(); $i = 0; $l = 0; $p = 0; // Put everything together again while ($i < $leases_count) { /* split the line by space */ $data = explode(" ", $leases_content[$i]); /* walk the fields */ $f = 0; $fcount = count($data); /* with less then 20 fields there is nothing useful */ if ($fcount < 20) { $i++; continue; } while ($f < $fcount) { switch ($data[$f]) { case "failover": $pools[$p]['name'] = $data[$f+2]; $pools[$p]['mystate'] = $data[$f+7]; $pools[$p]['peerstate'] = $data[$f+14]; $pools[$p]['mydate'] = $data[$f+10]; $pools[$p]['mydate'] .= " " . $data[$f+11]; $pools[$p]['peerdate'] = $data[$f+17]; $pools[$p]['peerdate'] .= " " . $data[$f+18]; $p++; $i++; continue 3; case "lease": $leases[$l]['ip'] = $data[$f+1]; $leases[$l]['type'] = "dynamic"; $f = $f+2; break; case "starts": $leases[$l]['start'] = $data[$f+2]; $leases[$l]['start'] .= " " . $data[$f+3]; $f = $f+3; break; case "ends": $leases[$l]['end'] = $data[$f+2]; $leases[$l]['end'] .= " " . $data[$f+3]; $f = $f+3; break; case "tstp": $f = $f+3; break; case "tsfp": $f = $f+3; break; case "atsfp": $f = $f+3; break; case "cltt": $f = $f+3; break; case "binding": switch ($data[$f+2]) { case "active": $leases[$l]['act'] = "active"; break; case "free": $leases[$l]['act'] = "expired"; $leases[$l]['online'] = "offline"; break; case "backup": $leases[$l]['act'] = "reserved"; $leases[$l]['online'] = "offline"; break; } $f = $f+1; break; case "next": /* skip the next binding statement */ $f = $f+3; break; case "rewind": /* skip the rewind binding statement */ $f = $f+3; break; case "hardware": $leases[$l]['mac'] = $data[$f+2]; /* check if it's online and the lease is active */ if ($leases[$l]['act'] == "active") { $online = exec("/usr/sbin/arp -an |/usr/bin/awk '/{$leases[$l]['ip']}/ {print}'|wc -l"); if ($online == 1) { $leases[$l]['online'] = 'online'; } else { $leases[$l]['online'] = 'offline'; } } $f = $f+2; break; case "client-hostname": if ($data[$f+1] <> "") { $leases[$l]['hostname'] = preg_replace('/"/', '', $data[$f+1]); } else { $hostname = gethostbyaddr($leases[$l]['ip']); if ($hostname <> "") { $leases[$l]['hostname'] = $hostname; } } $f = $f+1; break; case "uid": $f = $f+1; break; } $f++; } $l++; $i++; } /* remove duplicate items by mac address */ if (count($leases) > 0) { $leases = remove_duplicate($leases, "ip"); } if (count($pools) > 0) { $pools = remove_duplicate($pools, "name"); asort($pools); } // Put this in an easy to use form $dhcpmac = array(); $dhcpip = array(); foreach ($leases as $value) { $dhcpmac[$value['mac']] = $value['hostname']; $dhcpip[$value['ip']] = $value['hostname']; } exec("/usr/sbin/arp -an", $rawdata); $i = 0; /* if list */ $ifdescrs = get_configured_interface_with_descr(); foreach ($ifdescrs as $key => $interface) { $thisif = convert_friendly_interface_to_real_interface_name($key); if (!empty($thisif)) { $hwif[$thisif] = $interface; } } $data = array(); foreach ($rawdata as $line) { $elements = explode(' ', $line); if ($elements[3] != "(incomplete)") { $arpent = array(); $arpent['ip'] = trim(str_replace(array('(', ')'), '', $elements[1])); $arpent['mac'] = trim($elements[3]); $arpent['interface'] = trim($elements[5]); $data[] = $arpent; } } function _getHostName($mac, $ip) { global $dhcpmac, $dhcpip; if ($dhcpmac[$mac]) { return $dhcpmac[$mac]; } else if ($dhcpip[$ip]) { return $dhcpip[$ip]; } else { exec("host -W 1 " . escapeshellarg($ip), $output); if (preg_match('/.*pointer ([A-Za-z_0-9.-]+)\..*/', $output[0], $matches)) { if ($matches[1] <> $ip) { return $matches[1]; } } } return ""; } $pgtitle = array(gettext("Diagnostics"), gettext("ARP Table")); include("head.inc"); // Handle save msg if defined if ($savemsg) { print_info_box(htmlentities($savemsg), $savemsgtype); } ?>

('. $mac_man[$mac_hi] .')'; } ?>
' . gettext("NDP") . '' . gettext(" instead of ARP."), 'info', false); ?>