Esempio n. 1
0
function getRacktablesObjects($type_id, $attr_id, $attr_value)
{
    $r = usePreparedSelectBlade('select o.id, o.name, o.objtype_id, o.label, i.ip, i.type, i.name as ifname,
        av.attr_id as zabbix_flag_id, av.uint_value as zabbix_flag_value, av2.attr_id as sw_type_id,
        av2.uint_value as sw_type_value from Object AS o
            INNER JOIN IPv4Allocation as i ON (o.id = i.object_id AND o.objtype_id = ?)
            INNER JOIN AttributeValue av on (av.object_id = o.id AND av.attr_id = ? AND av.uint_value = ?)
			LEFT JOIN AttributeValue av2 on (av2.object_id = o.id AND av2.attr_id = ?)', array($type_id, $attr_id, $attr_value, RACKTABLES_SOFTWARE_TYPE_ID));
    $items = $r->fetchAll(PDO::FETCH_ASSOC);
    $result = array();
    foreach ($items as $item) {
        $ip = ip_format(ip4_int2bin($item['ip']));
        if (!isset($result[$item['id']])) {
            if (!empty($item['ifname'])) {
                $item['ip'] = array($item['ifname'] => $ip);
            } else {
                $item['ip'] = array($ip);
            }
            $result[$item['id']] = $item;
        } else {
            if (is_array($result[$item['id']]['ip'])) {
                if (!empty($item['ifname'])) {
                    $result[$item['id']]['ip'][$item['ifname']] = $ip;
                } else {
                    $result[$item['id']]['ip'][] = $ip;
                }
            }
        }
    }
    return $result;
}
Esempio n. 2
0
function ripeTab($id)
{
    $ripe_db = "http://rest.db.ripe.net/search.xml?source=ripe&query-string=";
    assertUIntArg('id');
    $net = spotEntity('ipv4net', $id);
    loadIPAddrList($net);
    $startip = ip4_bin2int($net['ip_bin']);
    $endip = ip4_bin2int(ip_last($net));
    // Get Data from RIPE
    $ripe_inetnum_str = ip4_format(ip4_int2bin($startip)) . ' - ' . ip4_format(ip4_int2bin($endip));
    $ripe_query = $ripe_db . ip4_format(ip4_int2bin($startip));
    $ripe_result_str = file_get_contents($ripe_query, false, NULL);
    $ripe_result = simplexml_load_string($ripe_result_str);
    // Check inetnum object
    $ripe_inetnum_check = "/whois-resources/objects/object[@type='inetnum']/attributes/attribute[@name='inetnum'][@value='{$ripe_inetnum_str}']";
    $ripe_inetnum = $ripe_result->xpath($ripe_inetnum_check);
    if (empty($ripe_inetnum)) {
        echo "<div class=trerror><center><h1>{$net['ip']}/{$net['mask']}</h1><h2>{$net['name']}</h2></center></div>\n";
    } else {
        $ripe_netname_check = "/whois-resources/objects/object[@type='inetnum']/attributes/attribute[@name='netname']";
        $ripe_netname = $ripe_result->xpath($ripe_netname_check);
        $netname = trim($ripe_netname[0]['value']);
        if (strcmp($netname, $net['name']) != 0) {
            echo "<div class=trwarning><center><h1>{$net['ip']}/{$net['mask']}</h1><h2>{$net['name']}</h2></center></div><div><center>";
        } else {
            echo "<div class=trok><center><h1>{$net['ip']}/{$net['mask']}</h1><h2>{$net['name']}</h2></center></div><div><center>";
        }
        printOpFormIntro('importRipeData', array('ripe_query' => $ripe_query, 'net_id' => $id, 'net_name' => $netname));
        echo "<input type=submit value='Import RIPE records in to comments'></center></div>";
        echo "</form>";
    }
    // echo '<em>'.$ripe_query.'</em>';
    echo "<table border=0 width='100%'><tr><td class=pcleft>";
    $filedir = realpath(dirname(__FILE__));
    $ripe_xsl = simplexml_load_file($filedir . '/ripe_html.xsl');
    startPortlet("RIPE Information Datatbase<br>{$ripe_inetnum_str}");
    $proc = new XSLTProcessor();
    $proc->importStyleSheet($ripe_xsl);
    echo '<div class=commentblock>' . trim($proc->transformToXML($ripe_result)) . '</div>';
    finishPortlet();
    echo "</td></tr></table>\n";
}
Esempio n. 3
0
function getIPv4AddressSearchResult($terms)
{
    $query = "select ip, name from IPv4Address where ";
    $or = '';
    $qparams = array();
    foreach (explode(' ', $terms) as $term) {
        $query .= $or . "name like ?";
        $or = ' or ';
        $qparams[] = "%{$term}%";
    }
    $result = usePreparedSelectBlade($query, $qparams);
    $ret = array();
    while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
        $ip_bin = ip4_int2bin($row['ip']);
        $row['ip'] = $ip_bin;
        $ret[$ip_bin] = $row;
    }
    return $ret;
}
Esempio n. 4
0
function convertSLBTablesToBinIPs()
{
    global $dbxlink;
    $dbxlink->query("DROP TABLE IF EXISTS `IPv4VS_new`, `IPv4RS_new`, `IPv4VS_old`, `IPv4RS_old`");
    $dbxlink->query(<<<END
CREATE TABLE `IPv4VS_new` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `vip` varbinary(16) NOT NULL,
  `vport` smallint(5) unsigned default NULL,
  `proto` enum('TCP','UDP','MARK') NOT NULL default 'TCP',
  `name` char(255) default NULL,
  `vsconfig` text,
  `rsconfig` text,
  PRIMARY KEY  (`id`),
  KEY `vip` (`vip`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
END
);
    $result = $dbxlink->query("SELECT * FROM IPv4VS");
    $rows = $result->fetchAll(PDO::FETCH_ASSOC);
    unset($result);
    foreach ($rows as $row) {
        $row['vip'] = ip4_int2bin($row['vip']);
        usePreparedInsertBlade('IPv4VS_new', $row);
    }
    $dbxlink->query(<<<END
CREATE TABLE `IPv4RS_new` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `inservice` enum('yes','no') NOT NULL default 'no',
  `rsip` varbinary(16) NOT NULL,
  `rsport` smallint(5) unsigned default NULL,
  `rspool_id` int(10) unsigned default NULL,
  `rsconfig` text,
  `comment` varchar(255) DEFAULT NULL,
  PRIMARY KEY  (`id`),
  KEY `rsip` (`rsip`),
  UNIQUE KEY `pool-endpoint` (`rspool_id`,`rsip`,`rsport`),
  CONSTRAINT `IPRS-FK` FOREIGN KEY (`rspool_id`) REFERENCES `IPv4RSPool` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
END
);
    $result = $dbxlink->query("SELECT * FROM IPv4RS");
    $rows = $result->fetchAll(PDO::FETCH_ASSOC);
    unset($result);
    foreach ($rows as $row) {
        $row['rsip'] = ip4_int2bin($row['rsip']);
        usePreparedInsertBlade('IPv4RS_new', $row);
    }
    $dbxlink->query(<<<END
RENAME TABLE
\t`IPv4VS` TO `IPv4VS_old`,
\t`IPv4VS_new` TO `IPv4VS`,
\t`IPv4RS` TO `IPv4RS_old`,
\t`IPv4RS_new` TO `IPv4RS`
END
);
    // re-create foreign key in IPv4LB
    $dbxlink->query("ALTER TABLE `IPv4LB` DROP FOREIGN KEY `IPv4LB-FK-vs_id`");
    $dbxlink->query("ALTER TABLE `IPv4LB` ADD CONSTRAINT `IPv4LB-FK-vs_id` FOREIGN KEY (`vs_id`) REFERENCES `IPv4VS` (`id`)");
    $dbxlink->query("DROP TABLE `IPv4VS_old`, `IPv4RS_old`");
    // re-create foreign key in IPv4RS
    $dbxlink->query("ALTER TABLE `IPv4RS` DROP FOREIGN KEY `IPRS-FK`");
    $dbxlink->query("ALTER TABLE `IPv4RS` ADD CONSTRAINT `IPv4RS-FK` FOREIGN KEY (`rspool_id`) REFERENCES `IPv4RSPool` (`id`) ON DELETE CASCADE");
}
Esempio n. 5
0
/**
 *
 * Fing tab handler
 *
 */
function FingTab($id)
{
    $can_import = permitted(NULL, NULL, 'importFingData');
    //
    // allocation settings
    //
    // address allocation code, IPv4 networks view
    $aac_left = array('regular' => '', 'virtual' => '<span class="aac-left" title="Loopback">L:</span>', 'shared' => '<span class="aac-left" title="Shared">S:</span>', 'router' => '<span class="aac-left" title="Router">R:</span>', 'point2point' => '<span class="aac-left" title="Point-to-point">P:</span>');
    //
    // header
    //
    global $pageno, $tabno;
    $maxperpage = getConfigVar('IPV4_ADDRS_PER_PAGE');
    $range = spotEntity('ipv4net', $id);
    loadIPAddrList($range);
    echo "<center><h1>{$range['ip']}/{$range['mask']}</h1><h2>{$range['name']}</h2></center>\n";
    //
    // execute fing
    //
    try {
        $known_ips = get_fing_scan($range['ip'], $range['mask']);
        $fing_cfg = get_fing_settings($range['ip'], $range['mask']);
        $fing_gw = $fing_cfg["gateway"];
    } catch (FingException $e) {
        render_fing_error("Could not get network scan via fing:", $e->getMessage());
        return FALSE;
    }
    echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
    startPortlet('overlook fing (via: ' . $fing_gw . ')');
    //
    // pagination
    //
    if (isset($_REQUEST['pg'])) {
        $page = $_REQUEST['pg'];
    } else {
        $page = 0;
    }
    $startip = ip4_bin2int($range['ip_bin']);
    $endip = ip4_bin2int(ip_last($range));
    $numpages = 0;
    if ($endip - $startip > $maxperpage) {
        $numpages = ($endip - $startip) / $maxperpage;
        $startip = $startip + $page * $maxperpage;
        $endip = $startip + $maxperpage - 1;
    }
    echo "<center>";
    if ($numpages) {
        echo '<h3>' . ip4_format(ip4_int2bin($startip)) . ' ~ ' . ip4_format(ip4_int2bin($endip)) . '</h3>';
    }
    for ($i = 0; $i < $numpages; $i++) {
        if ($i == $page) {
            echo "<b>{$i}</b> ";
        } else {
            echo "<a href='" . makeHref(array('page' => $pageno, 'tab' => $tabno, 'id' => $id, 'pg' => $i)) . "'>{$i}</a> ";
        }
    }
    echo "</center>";
    if ($can_import) {
        printOpFormIntro('importFingData', array('addrcount' => $endip - $startip + 1));
        $box_counter = 1;
    }
    echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center'>\n";
    echo "<tr><th class='tdleft'>address</th><th class='tdleft'>state</th><th class='tdleft'>current name</th><th class='tdleft'>DNS name</th><th class='tdleft'>MAC</th><th class='tdleft'>Allocation</th>";
    if ($can_import) {
        echo '<th>import</th>';
    }
    echo "</tr>\n";
    //
    // Loop through all IPs
    //
    $cnt_match = $cnt_missing = $cnt_mismatch = $cnt_total = 0;
    for ($ip = $startip; $ip <= $endip; $ip++) {
        $cnt_total++;
        $print_cbox = FALSE;
        $ip_bin = ip4_int2bin($ip);
        $addr = isset($range['addrlist'][$ip_bin]) ? $range['addrlist'][$ip_bin] : array('name' => '', 'reserved' => 'no');
        $straddr = ip4_format($ip_bin);
        list($fing_hostname, $fing_state, $fing_mac_vendor) = get_fing_info($straddr, $known_ips);
        $ip_is_up = strtoupper($fing_state) == "UP" ? TRUE : FALSE;
        if ($can_import) {
            echo "<input type=hidden name=addr_{$cnt_total} value={$straddr}>\n";
            echo "<input type=hidden name=descr_{$cnt_total} value={$fing_hostname}>\n";
            echo "<input type=hidden name=rsvd_{$cnt_total} value={$addr['reserved']}>\n";
        }
        $skip_dns_check = FALSE;
        echo "<tr";
        // Ignore network and broadcast addresses
        if ($ip == $startip && $addr['name'] == 'network' || $ip == $endip && $addr['name'] == 'broadcast') {
            echo " class='trbusy'";
            $skip_dns_check = TRUE;
        } elseif (!$ip_is_up) {
            echo " class='trnull'";
        }
        // set line color depending if we have the name already in the DB
        if (!$skip_dns_check) {
            if ($addr['name'] == $fing_hostname) {
                if (strlen($fing_hostname)) {
                    echo ' class=trok';
                    $cnt_match++;
                }
            } elseif (!strlen($addr['name']) or !strlen($fing_hostname)) {
                echo ' class=trwarning';
                $print_cbox = TRUE;
                $cnt_missing++;
            } else {
                echo ' class=trerror';
                $print_cbox = TRUE;
                $cnt_mismatch++;
            }
        }
        //IP
        echo "><td class='tdleft";
        if (isset($range['addrlist'][$ip_bin]['class']) and strlen($range['addrlist'][$ip_bin]['class'])) {
            echo ' ' . $range['addrlist'][$ip_bin]['class'];
        }
        echo "'><a href='" . makeHref(array('page' => 'ipaddress', 'ip' => $straddr)) . "'>{$straddr}</a></td>";
        //other columns
        if ($skip_dns_check) {
            echo "<td class='tdleft'>&nbsp;</td>";
        } else {
            if (!$ip_is_up) {
                echo "<td class='tdleft'>" . $fing_state . "</td>";
            } else {
                echo "<td class='tdleft'><div class='strong'>" . $fing_state . "</div></td>";
            }
        }
        echo "<td class=tdleft>{$addr['name']}</td>";
        echo "<td class='tdleft'>" . $fing_hostname . "</td>";
        echo "<td class='tdleft'>" . $fing_mac_vendor . "</td>";
        //allocation
        echo "<td>";
        $delim = '';
        if ($addr['reserved'] == 'yes') {
            echo "<strong>RESERVED</strong> ";
            $delim = '; ';
        }
        foreach ($addr['allocs'] as $ref) {
            echo $delim . $aac_left[$ref['type']];
            echo makeIPAllocLink($ip_bin, $ref, TRUE);
            $delim = '; ';
        }
        if ($delim != '') {
            $delim = '<br>';
        }
        foreach ($addr['vslist'] as $vs_id) {
            $vs = spotEntity('ipv4vs', $vs_id);
            echo $delim . mkA("{$vs['name']}:{$vs['vport']}/{$vs['proto']}", 'ipv4vs', $vs['id']) . '&rarr;';
            $delim = '<br>';
        }
        foreach ($addr['vsglist'] as $vs_id) {
            $vs = spotEntity('ipvs', $vs_id);
            echo $delim . mkA($vs['name'], 'ipvs', $vs['id']) . '&rarr;';
            $delim = '<br>';
        }
        foreach ($addr['rsplist'] as $rsp_id) {
            $rsp = spotEntity('ipv4rspool', $rsp_id);
            echo "{$delim}&rarr;" . mkA($rsp['name'], 'ipv4rspool', $rsp['id']);
            $delim = '<br>';
        }
        echo "</td>";
        // import column
        if ($can_import) {
            echo '<td>';
            if ($print_cbox) {
                echo "<input type=checkbox name=import_{$cnt_total} id=atom_1_" . $box_counter++ . "_1>";
            } else {
                echo '&nbsp;';
            }
            echo '</td>';
        }
        echo "</tr>";
    }
    if ($can_import && $box_counter > 1) {
        echo '<tr><td colspan=4 align=center><input type=submit value="Import selected records"></td><td colspan=2 align=right>';
        addJS('js/racktables.js');
        echo --$box_counter ? "<a href='javascript:;' onclick=\"toggleColumnOfAtoms(1, 1, {$box_counter})\">(toggle selection)</a>" : '&nbsp;';
        echo '</td></tr>';
    }
    echo "</table>";
    if ($can_import) {
        echo '</form>';
    }
    finishPortlet();
    echo "</td><td class=pcright>";
    //
    // PING Statistics
    //
    startPortlet('ping stats');
    $cnt_ping_up = get_fing_up_count($known_ips);
    echo "<table border=0 width='100%' cellspacing=0 cellpadding=2>";
    echo "<tr class=trok><th class=tdright>Replied to Ping</th><td class=tdleft>{$cnt_ping_up}</td></tr>\n";
    echo "<tr class=trwarning><th class=tdright>No Response</th><td class=tdleft>" . ($cnt_total - $cnt_ping_up) . "</td></tr>\n";
    echo "</table>\n";
    finishPortlet();
    //
    // DNS Statistics
    //
    startPortlet('dns stats');
    echo "<table border=0 width='100%' cellspacing=0 cellpadding=2>";
    echo "<tr class=trok><th class=tdright>Exact matches:</th><td class=tdleft>{$cnt_match}</td></tr>\n";
    echo "<tr class=trwarning><th class=tdright>Missing from DB/DNS:</th><td class=tdleft>{$cnt_missing}</td></tr>\n";
    if ($cnt_mismatch) {
        echo "<tr class=trerror><th class=tdright>Mismatches:</th><td class=tdleft>{$cnt_mismatch}</td></tr>\n";
    }
    echo "</table>\n";
    finishPortlet();
}
Esempio n. 6
0
function renderLivePTR($id)
{
    if (isset($_REQUEST['pg'])) {
        $page = $_REQUEST['pg'];
    } else {
        $page = 0;
    }
    global $pageno, $tabno;
    $maxperpage = getConfigVar('IPV4_ADDRS_PER_PAGE');
    $range = spotEntity('ipv4net', $id);
    loadIPAddrList($range);
    $can_import = permitted(NULL, NULL, 'importPTRData');
    echo "<center><h1>{$range['ip']}/{$range['mask']}</h1><h2>{$range['name']}</h2></center>\n";
    echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
    startPortlet('current records');
    $startip = ip4_bin2int($range['ip_bin']);
    $endip = ip4_bin2int(ip_last($range));
    $numpages = 0;
    if ($endip - $startip > $maxperpage) {
        $numpages = ($endip - $startip) / $maxperpage;
        $startip = $startip + $page * $maxperpage;
        $endip = $startip + $maxperpage - 1;
    }
    echo "<center>";
    if ($numpages) {
        echo '<h3>' . ip4_format(ip4_int2bin($startip)) . ' ~ ' . ip4_format(ip4_int2bin($endip)) . '</h3>';
    }
    for ($i = 0; $i < $numpages; $i++) {
        if ($i == $page) {
            echo "<b>{$i}</b> ";
        } else {
            echo "<a href='" . makeHref(array('page' => $pageno, 'tab' => $tabno, 'id' => $id, 'pg' => $i)) . "'>{$i}</a> ";
        }
    }
    echo "</center>";
    // FIXME: address counter could be calculated incorrectly in some cases
    if ($can_import) {
        printOpFormIntro('importPTRData', array('addrcount' => $endip - $startip + 1));
        $idx = 1;
        $box_counter = 1;
    }
    echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center'>\n";
    echo '<tr><th>address</th><th>current name</th><th>DNS data</th>';
    if ($can_import) {
        echo '<th>import</th>';
    }
    echo '</tr>';
    $cnt_match = $cnt_mismatch = $cnt_missing = 0;
    for ($ip = $startip; $ip <= $endip; $ip++) {
        // Find the (optional) DB name and the (optional) DNS record, then
        // compare values and produce a table row depending on the result.
        $ip_bin = ip4_int2bin($ip);
        $addr = isset($range['addrlist'][$ip_bin]) ? $range['addrlist'][$ip_bin] : array('name' => '', 'reserved' => 'no');
        $straddr = ip4_format($ip_bin);
        $ptrname = gethostbyaddr($straddr);
        if ($ptrname == $straddr) {
            $ptrname = '';
        }
        if ($can_import) {
            echo "<input type=hidden name=addr_{$idx} value={$straddr}>\n";
            echo "<input type=hidden name=descr_{$idx} value={$ptrname}>\n";
            echo "<input type=hidden name=rsvd_{$idx} value={$addr['reserved']}>\n";
        }
        echo '<tr';
        $print_cbox = FALSE;
        // Ignore network and broadcast addresses
        if ($ip == $startip && $addr['name'] == 'network' || $ip == $endip && $addr['name'] == 'broadcast') {
            echo ' class=trbusy';
        }
        if ($addr['name'] == $ptrname) {
            if (strlen($ptrname)) {
                echo ' class=trok';
                $cnt_match++;
            }
        } elseif (!strlen($addr['name']) or !strlen($ptrname)) {
            echo ' class=trwarning';
            $print_cbox = TRUE;
            $cnt_missing++;
        } else {
            echo ' class=trerror';
            $print_cbox = TRUE;
            $cnt_mismatch++;
        }
        echo "><td class='tdleft";
        if (isset($range['addrlist'][$ip_bin]['class']) and strlen($range['addrlist'][$ip_bin]['class'])) {
            echo ' ' . $range['addrlist'][$ip_bin]['class'];
        }
        echo "'>" . mkA($straddr, 'ipaddress', $straddr) . '</td>';
        echo "<td class=tdleft>{$addr['name']}</td><td class=tdleft>{$ptrname}</td>";
        if ($can_import) {
            echo '<td>';
            if ($print_cbox) {
                echo "<input type=checkbox name=import_{$idx} tabindex={$idx} id=atom_1_" . $box_counter++ . "_1>";
            } else {
                echo '&nbsp;';
            }
            echo '</td>';
            $idx++;
        }
        echo "</tr>\n";
    }
    if ($can_import && $box_counter > 1) {
        echo '<tr><td colspan=3 align=center><input type=submit value="Import selected records"></td><td>';
        addJS('js/racktables.js');
        echo --$box_counter ? "<a href='javascript:;' onclick=\"toggleColumnOfAtoms(1, 1, {$box_counter})\">(toggle selection)</a>" : '&nbsp;';
        echo '</td></tr>';
    }
    echo "</table>";
    if ($can_import) {
        echo '</form>';
    }
    finishPortlet();
    echo "</td><td class=pcright>";
    startPortlet('stats');
    echo "<table border=0 width='100%' cellspacing=0 cellpadding=2>";
    echo "<tr class=trok><th class=tdright>Exact matches:</th><td class=tdleft>{$cnt_match}</td></tr>\n";
    echo "<tr class=trwarning><th class=tdright>Missing from DB/DNS:</th><td class=tdleft>{$cnt_missing}</td></tr>\n";
    if ($cnt_mismatch) {
        echo "<tr class=trerror><th class=tdright>Mismatches:</th><td class=tdleft>{$cnt_mismatch}</td></tr>\n";
    }
    echo "</table>\n";
    finishPortlet();
    echo "</td></tr></table>\n";
}
Esempio n. 7
0
function PingTab($id)
{
    $pingtimeout = "50";
    if (isset($_REQUEST['pg'])) {
        $page = $_REQUEST['pg'];
    } else {
        $page = 0;
    }
    global $pageno, $tabno;
    $maxperpage = getConfigVar('IPV4_ADDRS_PER_PAGE');
    $range = spotEntity('ipv4net', $id);
    loadIPAddrList($range);
    echo "<center><h1>{$range['ip']}/{$range['mask']}</h1><h2>{$range['name']}</h2></center>\n";
    echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
    startPortlet('icmp ping comparrison:');
    $startip = ip4_bin2int($range['ip_bin']);
    $endip = ip4_bin2int(ip_last($range));
    $realstartip = $startip;
    $realendip = $endip;
    $numpages = 0;
    if ($endip - $startip > $maxperpage) {
        $numpages = ($endip - $startip) / $maxperpage;
        $startip = $startip + $page * $maxperpage;
        $endip = $startip + $maxperpage - 1;
    }
    echo "<center>";
    if ($numpages) {
        echo '<h3>' . ip4_format(ip4_int2bin($startip)) . ' ~ ' . ip4_format(ip4_int2bin($endip)) . '</h3>';
    }
    for ($i = 0; $i < $numpages; $i++) {
        if ($i == $page) {
            echo "<b>{$i}</b> ";
        } else {
            echo "<a href='" . makeHref(array('page' => $pageno, 'tab' => $tabno, 'id' => $id, 'pg' => $i)) . "'>{$i}</a> ";
        }
    }
    echo "</center>";
    echo "<table class='widetable' border=0 cellspacing=0 cellpadding=5 align='center'>\n";
    echo "<tr><th>address</th><th>name</th><th>response</th></tr>\n";
    $idx = 1;
    $box_counter = 1;
    $cnt_ok = $cnt_noreply = $cnt_mismatch = 0;
    for ($ip = $startip; $ip <= $endip; $ip++) {
        $ip_bin = ip4_int2bin($ip);
        $addr = isset($range['addrlist'][$ip_bin]) ? $range['addrlist'][$ip_bin] : array('name' => '', 'reserved' => 'no');
        $straddr = ip4_format($ip_bin);
        system("/usr/sbin/fping -q -c 1 -t {$pingtimeout} {$straddr}", $pingreply);
        // FIXME: This is a huge and ugly IF/ELSE block. Prettify anyone?
        if (!$pingreply) {
            if (!empty($addr['name']) and $addr['reserved'] == 'no' or !empty($addr['allocs'])) {
                echo '<tr class=trok';
                $cnt_ok++;
            } else {
                echo $addr['reserved'] == 'yes' ? '<tr class=trwarning' : '<tr class=trerror';
                $cnt_mismatch++;
            }
        } else {
            if (!empty($addr['name']) and $addr['reserved'] == 'no' or !empty($addr['allocs'])) {
                echo '<tr class=trwarning';
                $cnt_noreply++;
            } else {
                echo '<tr';
            }
        }
        echo "><td class='tdleft";
        if (isset($range['addrlist'][$ip_bin]['class']) and strlen($range['addrlist'][$ip_bin]['class'])) {
            echo ' ' . $range['addrlist'][$ip_bin]['class'];
        }
        echo "'><a href='" . makeHref(array('page' => 'ipaddress', 'ip' => $straddr)) . "'>{$straddr}</a></td>";
        echo "<td class=tdleft>{$addr['name']}</td><td class=tderror>";
        if (!$pingreply) {
            echo "Yes";
        } else {
            echo "No";
        }
        echo "</td></tr>\n";
        $idx++;
    }
    echo "</td></tr>";
    echo "</table>";
    echo "</form>";
    finishPortlet();
    echo "</td><td class=pcright>";
    startPortlet('stats');
    echo "<table border=0 width='100%' cellspacing=0 cellpadding=2>";
    echo "<tr class=trok><th class=tdright>OKs:</th><td class=tdleft>{$cnt_ok}</td></tr>\n";
    echo "<tr class=trwarning><th class=tdright>Did not reply:</th><td class=tdleft>{$cnt_noreply}</td></tr>\n";
    if ($cnt_mismatch) {
        echo "<tr class=trerror><th class=tdright>Unallocated answer:</th><td class=tdleft>{$cnt_mismatch}</td></tr>\n";
    }
    echo "</table>\n";
    finishPortlet();
    echo "</td></tr></table>\n";
}