Observium_CE/html/includes/print/routing.inc.php

449 lines
18 KiB
PHP

<?php
/**
* Observium
*
* This file is part of Observium.
*
* @package observium
* @subpackage web
* @copyright (C) Adam Armstrong
*
*/
/**
* Display bgp peers.
*
* Display pages with BGP Peers.
* Examples:
* print_bgp() - display all bgp peers from all devices
* print_bgp(array('pagesize' => 99)) - display 99 bgp peers from all device
* print_bgp(array('pagesize' => 10, 'pageno' => 3, 'pagination' => TRUE)) - display 10 bgp peers from page 3 with
* pagination header print_bgp(array('pagesize' => 10, 'device' = 4)) - display 10 bgp peers for device_id 4
*
* @param array $vars
*
* @return void
*
*/
function print_bgp_peer_table($vars)
{
$entries = get_bgp_array($vars);
//r($entries);
if (!$entries['count']) {
// There have been no entries returned. Print the warning.
print_warning('<h4>No BGP peers found!</h4>');
return;
}
// Entries have been returned. Print the table.
$list = ['device' => FALSE];
if ($vars['page'] !== 'device') {
$list['device'] = TRUE;
}
switch ($vars['graph']) {
case 'prefixes_ipv4unicast':
case 'prefixes_ipv4multicast':
case 'prefixes_ipv4vpn':
case 'prefixes_ipv6unicast':
case 'prefixes_ipv6multicast':
case 'macaccounting_bits':
case 'macaccounting_pkts':
case 'updates':
$table_class = 'table-striped-two';
$list['graph'] = TRUE;
break;
default:
$table_class = 'table-striped';
$list['graph'] = FALSE;
}
$string = generate_box_open();
$string .= '<table class="table ' . $table_class . ' table-hover table-condensed ">' . PHP_EOL;
$cols = [
[NULL, 'class="state-marker"'],
[NULL, 'style="width: 1px;"'],
'device' => ['Local address', 'style="width: 150px;"'],
'local_as' => ['Local AS / VRF', 'style="width: 110px;"'],
[NULL, 'style="width: 20px;"'],
'peer_ip' => ['Peer address', 'style="width: 150px;"'],
'peer_as' => ['Remote AS', 'style="width: 90px;"'],
'type' => ['Type', 'style="width: 50px;"'],
['Family', 'style="width: 50px;"'],
'state' => 'State',
'uptime' => 'Uptime / Updates',
];
//if (!$list['device']) { unset($cols['device']); }
$string .= get_table_header($cols, $vars);
$string .= ' <tbody>' . PHP_EOL;
foreach ($entries['entries'] as $peer) {
$local_dev = device_by_id_cache($peer['device_id']);
$local_as = ($list['device'] ? ' (AS' . $peer['human_local_as'] . ')' : '');
$local_name = generate_device_link_short($local_dev, ['tab' => 'routing', 'proto' => 'bgp'], 18);
$local_ip = generate_device_link($local_dev, $peer['human_localip'] . $local_as, ['tab' => 'routing', 'proto' => 'bgp']);
$peer_as = 'AS' . $peer['human_remote_as'];
if ($peer['peer_device_id']) {
$peer_dev = device_by_id_cache($peer['peer_device_id']);
$peer_name = generate_device_link_short($peer_dev, ['tab' => 'routing', 'proto' => 'bgp'], 18);
} else {
$peer_name = $peer['reverse_dns'];
}
$peer_ip = generate_entity_link("bgp_peer", $peer, $peer['human_remoteip']);
$peer_ip = generate_link($peer['human_remoteip'], ['page' => 'routing' , 'proto' => 'bgp', 'peer_ip' => $peer['human_remoteip'], 'view' => 'graphs', 'graph' => 'updates']);
$peer_afis = &$entries['afisafi'][$peer['device_id']][$peer['bgpPeer_id']];
$peer_afis_html = [];
// Generate AFI/SAFI labels
foreach ($peer_afis as $peer_afi) {
// $peer_afi_html = '<span class="label-group">';
if (isset($GLOBALS['config']['routing_afis_name'][$peer_afi['afi']])) {
$afi_num = $GLOBALS['config']['routing_afis_name'][$peer_afi['afi']];
$afi_class = $GLOBALS['config']['routing_afis'][$afi_num]['class'];
} else {
$afi_class = 'default';
}
if (isset($GLOBALS['config']['routing_safis_name'][$peer_afi['safi']])) {
// Named SAFI
$safi_num = $GLOBALS['config']['routing_safis_name'][$peer_afi['safi']];
$safi_class = $GLOBALS['config']['routing_safis'][$safi_num]['class'];
} elseif (isset($GLOBALS['config']['routing_safis'][$peer_afi['safi']])) {
// Numeric SAFI
$safi_num = $peer_afi['safi'];
$peer_afi['safi'] = $GLOBALS['config']['routing_safis'][$safi_num]['name'];
$safi_class = $GLOBALS['config']['routing_safis'][$safi_num]['class'];
} else {
$safi_class = 'default';
}
$peer_afi_items = [
['event' => $afi_class, 'text' => $peer_afi['afi']],
['event' => $safi_class, 'text' => $peer_afi['safi']],
];
$peer_afi_html = get_label_group($peer_afi_items);
//r($peer_afi_html);
$peer_afis_html[] = $peer_afi_html;
}
$string .= ' <tr class="' . $peer['html_row_class'] . '">' . PHP_EOL;
$string .= ' <td class="state-marker"></td>' . PHP_EOL;
$string .= ' <td></td>' . PHP_EOL;
$string .= ' <td style="white-space: nowrap" class="entity">' . $local_ip . '<br />' . $local_name . '</td>' . PHP_EOL;
$string .= ' <td><strong><span class="label label-' . $peer['peer_local_class'] . '">AS' . $peer['human_local_as'] . '</span></strong>';
if (!safe_empty($peer['virtual_name'])) {
$vitual_type = isset($GLOBALS['config']['os'][$local_dev['os']]['snmp']['virtual_type']) ? nicecase($GLOBALS['config']['os'][$local_dev['os']]['snmp']['virtual_type']) : 'VRF';
$string .= '<br /><span class="label label-primary">' . $vitual_type . ': ' . $peer['virtual_name'] . '</span>';
}
$string .= '</td>' . PHP_EOL;
$string .= ' <td><span class="text-success"><i class="glyphicon glyphicon-arrow-right"></i></span></td>' . PHP_EOL;
$string .= ' <td style="white-space: nowrap" class="entity">' . $peer_ip . '<br />' . $peer_name . '</td>' . PHP_EOL;
$string .= ' <td><a href="'.generate_url(['page' => 'routing' , 'proto' => 'bgp', 'peer_as' => $peer['human_remote_as'], 'view' => 'graphs', 'graph' => 'updates']).'">
<span class="label label-' . $peer['peer_type_class'] . '">' . $peer_as . '</span>
</a>
<br /><small>' . $peer['astext'] . '</small></td>' . PHP_EOL;
$string .= ' <td><span class="label label-' . $peer['peer_type_class'] . '">' . $peer['peer_type'] . '</span></td>' . PHP_EOL;
$string .= ' <td>' . implode('<br />', $peer_afis_html) . '</td>' . PHP_EOL;
$string .= ' <td><strong><span class=" label label-' . $peer['admin_class'] . '">' . $peer['bgpPeerAdminStatus'] . '</span><br /><span class="label label-' . $peer['state_class'] . '">' . $peer['bgpPeerState'] . '</span></strong></td>' . PHP_EOL;
$string .= ' <td style="white-space: nowrap">' . format_uptime($peer['bgpPeerFsmEstablishedTime']) . '<br />
Updates: <i class="icon-circle-arrow-down text-success"></i> ' . format_si($peer['bgpPeerInUpdates']) . ' <i class="icon-circle-arrow-up text-primary"></i> ' . format_si($peer['bgpPeerOutUpdates']) . '</td>' . PHP_EOL;
$string .= ' </tr>' . PHP_EOL;
// Graphs
$peer_graph = FALSE;
switch ($vars['graph']) {
case 'prefixes_ipv4unicast':
case 'prefixes_ipv4multicast':
case 'prefixes_ipv4vpn':
case 'prefixes_ipv6unicast':
case 'prefixes_ipv6multicast':
$afisafi = preg_replace('/prefixes_(ipv[46])(\w+)/', '$1.$2', $vars['graph']); // prefixes_ipv6unicast ->> ipv6.unicast
if (isset($peer_afis[$afisafi]) && $peer['bgpPeer_id']) {
$graph_array['type'] = 'bgp_' . $vars['graph'];
$graph_array['id'] = $peer['bgpPeer_id'];
$peer_graph = TRUE;
}
break;
case 'updates':
if ($peer['bgpPeer_id']) {
$graph_array['type'] = 'bgp_updates';
$graph_array['id'] = $peer['bgpPeer_id'];
$peer_graph = TRUE;
}
break;
case 'macaccounting_bits':
case 'macaccounting_pkts':
// FIXME. I really still not know it works or not? -- mike
// This part copy-pasted from old code as is
$acc = dbFetchRow("SELECT * FROM `mac_accounting` AS M
LEFT JOIN `ip_mac` AS I ON M.mac = I.mac_address
LEFT JOIN `ports` AS P ON P.port_id = M.port_id
LEFT JOIN `devices` AS D ON D.device_id = P.device_id
WHERE I.ip_address = ?", [$peer['bgpPeerRemoteAddr']]);
$database = get_rrd_path($device, "cip-" . $acc['ifIndex'] . "-" . $acc['mac'] . ".rrd");
if (is_array($acc) && is_file($database)) {
$peer_graph = TRUE;
$graph_array['id'] = $acc['ma_id'];
$graph_array['type'] = $vars['graph'];
}
break;
}
if ($peer_graph) {
$graph_array['to'] = get_time();
$string .= ' <tr class="' . $peer['html_row_class'] . '">' . PHP_EOL;
$string .= ' <td class="state-marker"></td><td colspan="10" style="white-space: nowrap">' . PHP_EOL;
$string .= generate_graph_row($graph_array);
$string .= ' </td>' . PHP_EOL . ' </tr>' . PHP_EOL;
} elseif ($list['graph']) {
// Empty row for correct view class table-striped-two
$string .= ' <tr class="' . $peer['html_row_class'] . '"><td class="state-marker"></td><td colspan="10"></td></tr>' . PHP_EOL;
}
}
$string .= ' </tbody>' . PHP_EOL;
$string .= '</table>';
$string .= generate_box_close();
// Print pagination header
if ($entries['pagination_html']) {
$string = $entries['pagination_html'] . $string . $entries['pagination_html'];
}
// Print
echo $string;
}
// Populate bgp page specific bgp stuff. FIXME - replace
function bgp_cache_populate()
{
global $config;
global $cache;
foreach (dbFetchRows('SELECT `device_id`,`bgpPeer_id`,`local_as`,`bgpPeerState`,`bgpPeerAdminStatus`,`bgpPeerRemoteAs` FROM `bgpPeers`' . generate_where_clause(generate_query_permitted_ng(['device']))) as $bgp) {
if (!$config['web_show_disabled']) {
if (in_array($bgp['device_id'], $cache['devices']['disabled'])) {
continue;
}
}
// Cast id. Seems there's no need to do this as it's the db's primary key.
//$bgp['bgpPeer_id'] = (int)$bgp['bgpPeer_id'];
if (device_permitted($bgp)) {
$cache['bgp']['permitted'][] = $bgp['bgpPeer_id']; // Collect permitted peers
if ($bgp['bgpPeerAdminStatus'] === 'start' || $bgp['bgpPeerAdminStatus'] === 'running') {
$cache['bgp']['start'][] = $bgp['bgpPeer_id']; // Collect START peers (bgpPeerAdminStatus = (start || running))
if ($bgp['bgpPeerState'] !== 'established') {
} else {
$cache['bgp']['up'][] = $bgp['bgpPeer_id']; // Collect UP peers (bgpPeerAdminStatus = (start || running), bgpPeerState = established)
}
} else {
$cache['routing']['bgp']['down']++;
}
if ($bgp['local_as'] == $bgp['bgpPeerRemoteAs']) {
$cache['bgp']['internal'][] = $bgp['bgpPeer_id']; // Collect iBGP peers
} else {
$cache['bgp']['external'][] = $bgp['bgpPeer_id']; // Collect eBGP peers
}
}
}
}
/**
* Params:
*
* pagination, pageno, pagesize
* device, type, adminstatus, state
*/
function get_bgp_array($vars)
{
$array = [];
// With pagination? (display page numbers in header)
//$array['pagination'] = (isset($vars['pagination']) && $vars['pagination']);
$array['pagination'] = TRUE;
pagination($vars, 0, TRUE); // Get default pagesize/pageno
$array['pageno'] = $vars['pageno'];
$array['pagesize'] = $vars['pagesize'];
$start = $array['pagesize'] * $array['pageno'] - $array['pagesize'];
$pagesize = $array['pagesize'];
// populate bgp cache for use here
bgp_cache_populate();
$cache_bgp = &$GLOBALS['cache']['bgp'];
// Begin query generate
$single_device = FALSE;
$param = [];
$where = [];
foreach ($vars as $var => $value) {
if (!safe_empty($value)) {
switch ($var) {
case "group":
case "group_id":
$values = get_group_entities($value);
$where[] = generate_query_values($values, 'bgpPeer_id');
break;
case 'device':
case 'device_id':
$where[] = generate_query_values($value, 'device_id');
$single_device = $vars['page'] === 'device' && device_permitted($value);
break;
case 'peer':
case 'peer_id':
$where[] = generate_query_values($value, 'peer_device_id');
break;
case 'local_ip':
$where[] = generate_query_values(ip_uncompress($value), 'bgpPeerLocalAddr');
break;
case 'peer_ip':
$where[] = generate_query_values(ip_uncompress($value), 'bgpPeerRemoteAddr');
break;
case 'local_as':
$where[] = generate_query_values(bgp_asdot_to_asplain($value), 'local_as');
break;
case 'peer_as':
if (is_string($value) && preg_match_all('/AS(?<as>[\d\.]+):/', $value, $matches)) {
//r($matches);
$value = $matches['as'];
}
$where[] = generate_query_values(bgp_asdot_to_asplain($value), 'bgpPeerRemoteAs');
break;
case 'type':
if ($value === 'external' || $value === 'ebgp') {
$where[] = generate_query_values($cache_bgp['external'], 'bgpPeer_id');
} elseif ($value === 'internal' || $value === 'ibgp') {
$where[] = generate_query_values($cache_bgp['internal'], 'bgpPeer_id');
}
break;
case 'adminstatus':
if ($value === 'stop') {
$where[] = generate_query_values($cache_bgp['start'], 'bgpPeer_id', '!='); // NOT IN
} elseif ($value === 'start') {
$where[] = generate_query_values($cache_bgp['start'], 'bgpPeer_id');
}
break;
case 'state':
if ($value === 'down') {
$where[] = generate_query_values($cache_bgp['up'], 'bgpPeer_id', '!='); // NOT IN
} elseif ($value === 'up') {
$where[] = generate_query_values($cache_bgp['up'], 'bgpPeer_id');
}
break;
}
}
}
// Show peers only for permitted devices
/*
if ($single_device) {
// skip extra permissions check
} elseif ($_SESSION['userlevel'] < 5) {
$where[] = generate_query_values_ng($cache_bgp['permitted'], 'bgpPeer_id');
} elseif (!$GLOBALS['config']['web_show_disabled'] && $GLOBALS['cache']['devices']['stat']['disabled']) {
// Exclude disabled devices for Global Read+
$where[] = generate_query_values_ng($GLOBALS['cache']['devices']['disabled'], 'device_id', '!=');
} */
$where[] = generate_query_permitted_ng('device');
$where = generate_where_clause($where);
$query_count = 'SELECT COUNT(*) FROM `bgpPeers` ' . $where; // Use only bgpPeer_id and device_id in query!
$array['count'] = dbFetchCell($query_count, $param);
//$array['count'] = dbFetchCell($query_count, $param, TRUE);
// Pagination
$array['pagination_html'] = pagination($vars, $array['count']);
$query = 'SELECT `hostname`, `bgpLocalAs`, `bgpPeers`.*';
$query .= ' FROM `bgpPeers`';
$query .= ' JOIN `devices` USING (`device_id`) ';
$query .= $where;
$sort_dir = $vars['sort_order'] === 'desc' ? ' DESC' : '';
switch ($vars['sort']) {
case "device":
$sort = " ORDER BY `hostname`" . $sort_dir;
break;
case "local_as":
$sort = " ORDER BY `local_as`$sort_dir, `virtual_name`$sort_dir";
break;
case "peer_ip":
$sort = " ORDER BY `bgpPeerRemoteAddr`" . $sort_dir;
break;
case "peer_as":
$sort = " ORDER BY `bgpPeerRemoteAs`" . $sort_dir;
break;
case 'state':
$sort = " ORDER BY `bgpPeerAdminStatus`" . $sort_dir . ", `bgpPeerState`" . $sort_dir;
break;
case 'uptime':
$sort = " ORDER BY `bgpPeerFsmEstablishedTime`" . $sort_dir;
break;
default:
$sort = " ORDER BY `hostname`" . $sort_dir . ", `bgpPeerRemoteAs`" . $sort_dir . ", `bgpPeerRemoteAddr`" . $sort_dir;
}
$query .= $sort;
$query .= " LIMIT $start,$pagesize";
$peer_devices = [];
// Query BGP
foreach (dbFetchRows($query, $param) as $entry) {
humanize_bgp($entry);
// Collect peer devices for AFI/SAFI
$peer_devices[$entry['device_id']] = 1;
$array['entries'][] = $entry;
}
// Query AFI/SAFI
if (!safe_empty($peer_devices)) {
$query_afi = 'SELECT * FROM `bgpPeers_cbgp` WHERE 1' . generate_query_values_and(array_keys($peer_devices), 'device_id');
foreach (dbFetchRows($query_afi) as $entry) {
$array['afisafi'][$entry['device_id']][$entry['bgpPeer_id']][$entry['afi'] . '.' . $entry['safi']] = ['afi' => $entry['afi'], 'safi' => $entry['safi']];
}
}
return $array;
}
// EOF