304 lines
12 KiB
PHP
304 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* Observium
|
|
*
|
|
* This file is part of Observium.
|
|
*
|
|
* @package observium
|
|
* @subpackage web
|
|
* @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2023 Observium Limited
|
|
*
|
|
*/
|
|
|
|
$links = 1;
|
|
|
|
include_once("../includes/observium.inc.php");
|
|
|
|
if (!$config['web_iframe'] && is_iframe() &&
|
|
!http_match_referer('!/device/device=\d+/tab=ports/.*?/view=map/!')) { // allow run from device ports page
|
|
//bdump($_SERVER['HTTP_SEC_FETCH_DEST']);
|
|
//bdump($_SERVER['HTTP_REFERER']); //'HTTP_SEC_FETCH_SITE' => 'same-origin'
|
|
print_error_permission("Not allowed to run in a iframe!");
|
|
die();
|
|
}
|
|
|
|
include($config['html_dir'] . "/includes/authenticate.inc.php");
|
|
|
|
if ($_SESSION['authenticated']) {
|
|
// Do various queries which we use in multiple places
|
|
include($config['html_dir'] . "/includes/cache-data.inc.php");
|
|
|
|
if (!is_file($config['dot'])) {
|
|
print_error("Package 'graphviz' not installed. Map can not be displayed!");
|
|
return;
|
|
}
|
|
} else {
|
|
// not authenticated
|
|
die("Unauthenticated");
|
|
}
|
|
|
|
$vars = get_vars('GET');
|
|
|
|
// FIXME. Wtf is this (for 2023 year)?
|
|
if (strpos($_SERVER['REQUEST_URI'], "anon")) {
|
|
$anon = 1;
|
|
}
|
|
|
|
$sql = 'SELECT `devices`.*, COUNT(`neighbours`.`port_id`) AS `neighbours_count` FROM `devices` LEFT JOIN `neighbours` USING(`device_id`) ';
|
|
//'WHERE `neighbours`.`active` = '1' AND `device_id` = 286 GROUP BY `device_id` ORDER BY COUNT(`neighbours`.`port_id`) DESC ';
|
|
//$where = 'WHERE `neighbours`.`active` = ?';
|
|
$where = [];
|
|
$where[] = '`neighbours`.`active` = ?';
|
|
$params = [1];
|
|
if (isset($vars['device'])) {
|
|
if (device_permitted($vars['device'])) {
|
|
//$where .= ' AND `device_id` = ?';
|
|
$where[] = '`device_id` = ?';
|
|
$params[] = $vars['device'];
|
|
} else {
|
|
// not permitted
|
|
print_error_permission("Device not permitted");
|
|
return;
|
|
}
|
|
//$where = "WHERE D.`device_id` = ".$vars['device'];
|
|
} else {
|
|
//$where .= $cache['where']['devices_permitted'];
|
|
$where[] = $cache['where']['devices_permitted'];
|
|
}
|
|
//$where .= " AND L.`active` = '1'";
|
|
$where = generate_where_clause($where);
|
|
|
|
// FIXME this shit probably needs tidied up.
|
|
|
|
$format = isset($vars['format']) && in_array($vars['format'], ['dot', 'png', 'svg']) ? $vars['format'] : 'svg';
|
|
|
|
if (isset($vars['device'])) {
|
|
$rankdir = "LR";
|
|
} else {
|
|
$rankdir = "TB";
|
|
}
|
|
|
|
# $map = 'digraph G { bgcolor=transparent; splines=true; overlap=scale; concentrate=0; epsilon=0.001; rankdir=LR
|
|
|
|
$map = 'digraph G { bgcolor=transparent; splines=true; overlap=scale; rankdir=' . $rankdir . '; concentrate=0; epsilon=0.001;
|
|
node [ fontname="helvetica", fontstyle=bold, style=filled, color=white, fillcolor=lightgrey, overlap=false];
|
|
edge [ bgcolor=white, fontname="helvetica", fontstyle=bold, arrowhead=dot, arrowtail=dot];
|
|
graph [bgcolor=transparent;];';
|
|
|
|
if (!$_SESSION['authenticated']) {
|
|
// never will happen this if
|
|
$map .= "\"Not authenticated\" [fontsize=20 fillcolor=\"lightblue\", URL=\"/\" shape=box3d]\n";
|
|
} else {
|
|
$loc_count = 1;
|
|
$ranks = [];
|
|
|
|
//$cache['where']['devices_permitted'] = generate_query_permitted(['device'], ['device_table' => 'D']);
|
|
foreach (dbFetchRows($sql . $where . ' GROUP BY `device_id` ORDER BY `neighbours_count` DESC', $params) as $device) {
|
|
//foreach (dbFetch("SELECT D.*, COUNT(L.`port_id`) FROM `devices` AS D LEFT JOIN (`ports` AS I, `neighbours` AS L) ON (D.`device_id` = I.`device_id` AND I.port_id = L.port_id) ". $where . $cache['where']['devices_permitted'] . " GROUP BY D.hostname ORDER BY COUNT(L.port_id) DESC", NULL, TRUE) as $device)
|
|
//{
|
|
|
|
$device_name = device_name($device);
|
|
|
|
$links = dbFetchRows('SELECT * FROM `neighbours` LEFT JOIN `ports` USING(`device_id`, `port_id`) WHERE `device_id` = ? AND `active` = ? ORDER BY `remote_hostname`', [$device['device_id'], 1]);
|
|
$links_group = [];
|
|
foreach ($links as $index => $link) {
|
|
//$links_group[$link['device_id']][$link['port_id']][$link['remote_port']][$index] = $link['remote_hostname'] . '[' . nicecase($link['protocol']) . ']';
|
|
$links_group[$link['device_id']][$link['port_id']][$link['remote_port']]++;
|
|
}
|
|
//$links = dbFetch("SELECT * FROM ports AS I, neighbours AS L WHERE I.device_id = ? AND L.port_id = I.port_id ORDER BY L.remote_hostname", array($device['device_id']));
|
|
if (safe_count($links)) {
|
|
$ranktype = substr($device_name, 0, 2);
|
|
//$ranktype2 = substr($device_name, 0, 3);
|
|
//if (!strncmp($device_name, "c", 1) && !strstr($device_name, "kalooga"))
|
|
//{
|
|
$ranks[$ranktype][] = $device_name;
|
|
//} else {
|
|
// $ranks[$ranktype2][] = $device_name;
|
|
//}
|
|
if ($anon) {
|
|
$device_name = md5($device_name);
|
|
}
|
|
if (!isset($locations[$device['location']])) {
|
|
$locations[$device['location']] = $loc_count;
|
|
$loc_count++;
|
|
}
|
|
#$loc_id = $locations[$device['location']];
|
|
$loc_id = '"' . $ranktype . '"';
|
|
|
|
$map .= "\"" . $device_name . "\" [fontsize=20, fillcolor=\"lightblue\", group=" . $loc_id . " URL=\"" . generate_url(['page' => 'device', 'device' => $device['device_id'], 'tab' => 'ports', 'view' => 'map']) . "\" shape=box3d]\n";
|
|
}
|
|
|
|
foreach ($links as $link) {
|
|
$local_port_id = $link['port_id'];
|
|
$remote_port_id = $link['remote_port_id'];
|
|
|
|
// skip already done (groupped) links
|
|
// FIXME. Not done
|
|
$group_count = $links_group[$link['device_id']][$link['port_id']][$link['remote_port']];
|
|
if (!$group_count) {
|
|
continue;
|
|
}
|
|
$links_group[$link['device_id']][$link['port_id']][$link['remote_port']]--;
|
|
/*
|
|
if ($group_count > 1) {
|
|
$protocols = implode(",\n", $links_group[$link['device_id']][$link['port_id']][$link['remote_port']]);
|
|
} else {
|
|
$protocols = '';
|
|
}
|
|
unset($links_group[$link['device_id']][$link['port_id']][$link['remote_port']]);
|
|
*/
|
|
|
|
$i = 0;
|
|
$done = 0;
|
|
if ($linkdone[$remote_port_id][$local_port_id]) {
|
|
$done = 1;
|
|
}
|
|
|
|
if (!$done) {
|
|
$linkdone[$local_port_id][$remote_port_id] = TRUE;
|
|
|
|
$i++;
|
|
|
|
if ($link['ifSpeed'] >= "10000000000") {
|
|
$info = "color=red3 style=\"setlinewidth(4)\"";
|
|
} elseif ($link['ifSpeed'] >= "1000000000") {
|
|
$info = "color=lightblue style=\"setlinewidth(3)\"";
|
|
} elseif ($link['ifSpeed'] >= "100000000") {
|
|
$info = "color=lightgrey style=\"setlinewidth(2)\"";
|
|
} elseif ($link['ifSpeed'] >= "10000000") {
|
|
$info = "style=\"setlinewidth(1)\"";
|
|
} else {
|
|
$info = "style=\"setlinewidth(1)\"";
|
|
}
|
|
|
|
$src = $device_name;
|
|
if ($remote_port_id && $remote_device_id = get_device_id_by_port_id($remote_port_id)) {
|
|
$remote_device = device_by_id_cache($remote_device_id);
|
|
//$dst_query = dbFetchRow("SELECT D.`device_id`, `hostname` FROM `devices` AS D, `ports` AS I WHERE I.`port_id` = ? AND D.`device_id` = I.`device_id`".$cache['where']['devices_permitted'], array($remote_port_id));
|
|
$dst = device_name($remote_device);
|
|
$dst_host = $remote_device['device_id'];
|
|
} else {
|
|
unset($dst_host);
|
|
$dst = $link['remote_hostname'];
|
|
}
|
|
|
|
// anonymize
|
|
if ($anon) {
|
|
$dst = md5($dst);
|
|
$src = md5($src);
|
|
}
|
|
|
|
if (!port_permitted($link['port_id'])) {
|
|
continue;
|
|
}
|
|
$sif = get_port_by_id_cache($link['port_id']);
|
|
if ($remote_port_id && port_permitted($link['remote_port_id'])) {
|
|
$dif = get_port_by_id_cache($link['remote_port_id']);
|
|
} else {
|
|
$dif['port_label'] = $link['remote_port'];
|
|
$dif['port_id'] = $link['remote_hostname'] . '/' . $link['remote_port'];
|
|
}
|
|
|
|
if (!is_numeric($device['device_id'])) {
|
|
if (!$ifdone[$dst][$dif['port_id']] && !$ifdone[$src][$sif['port_id']]) {
|
|
$map .= "\"$src\" -> \"" . $dst . "\" [weight=500000, arrowsize=0, len=0, $info];\n";
|
|
}
|
|
$ifdone[$src][$sif['port_id']] = 1;
|
|
} else {
|
|
$map .= "\"" . $sif['port_id'] . "\" [label=\"" . $sif['port_label'] . "\", fontsize=12, fillcolor=lightblue, URL=\"" . generate_url(['page' => 'device', 'device' => $device['device_id'], 'tab' => 'port', 'port' => $local_port_id]) . "\"]\n";
|
|
if (!$ifdone[$src][$sif['port_id']]) {
|
|
$map .= "\"$src\" -> \"" . $sif['port_id'] . "\" [weight=500000, arrowsize=0, len=0];\n";
|
|
$ifdone[$src][$sif['port_id']] = 1;
|
|
}
|
|
|
|
if ($dst_host) {
|
|
$map .= "\"$dst\" [URL=\"" . generate_url(['page' => 'device', 'device' => $dst_host, 'tab' => 'ports', 'view' => 'map']) . "\", fontsize=20, shape=box3d]\n";
|
|
} else {
|
|
$map .= "\"$dst\" [ fontsize=20 shape=box3d]\n";
|
|
}
|
|
|
|
if ($dst_host == $device['device_id'] || !is_numeric($device['device_id'])) {
|
|
$map .= "\"" . $dif['port_id'] . "\" [label=\"" . $dif['port_label'] . "\", fontsize=12, fillcolor=lightblue, URL=\"" . generate_url(['page' => 'device', 'device' => $dst_host, 'tab' => 'port', 'port' => $remote_port_id]) . "\"]\n";
|
|
} else {
|
|
$map .= "\"" . $dif['port_id'] . "\" [label=\"" . $dif['port_label'] . " \", fontsize=12, fillcolor=lightgray";
|
|
if ($dst_host) {
|
|
$map .= ", URL=\"" . generate_url(['page' => 'device', 'device' => $dst_host, 'tab' => 'port', 'port' => $remote_port_id]) . "\"";
|
|
}
|
|
$map .= "]\n";
|
|
}
|
|
|
|
if (!$ifdone[$dst][$dif['port_id']]) {
|
|
$map .= "\"" . $dif['port_id'] . "\" -> \"$dst\" [weight=500000, arrowsize=0, len=0];\n";
|
|
$ifdone[$dst][$dif['port_id']] = 1;
|
|
}
|
|
$map .= "\"" . $sif['port_id'] . "\" -> \"" . $dif['port_id'] . "\" [weight=1, arrowhead=normal, arrowtail=normal, len=2, $info] \n";
|
|
}
|
|
}
|
|
}
|
|
|
|
$done = 0;
|
|
|
|
}
|
|
}
|
|
|
|
foreach ($ranks as $rank) {
|
|
if (substr($rank[0], 0, 2) == "cr") {
|
|
$map .= '{ rank=min; "' . implode('"; "', $rank) . "\"};\n";
|
|
} else {
|
|
$map .= '{ rank=same; "' . implode('"; "', $rank) . "\"};\n";
|
|
}
|
|
}
|
|
|
|
$map .= "\n};";
|
|
|
|
/*
|
|
if ($links > 30) // Unflatten if there are more than 10 links. beyond that it gets messy
|
|
{
|
|
$maptool = $config['unflatten'];
|
|
} else {
|
|
*/
|
|
$maptool = $config['dot'] . ' -Gpack -Goverlap=prism';
|
|
/*
|
|
}
|
|
|
|
if ($where == '')
|
|
{
|
|
$maptool = $config['unflatten'] . ' -f -l 5 | ' . $config['sfdp'] . ' -Gpack -Goverlap=prism -Gcharset=latin1 | dot';
|
|
// $maptool = $config['sfdp'] . ' -Gpack -Goverlap=prism -Gcharset=latin1 -Gsize=20,20';
|
|
// $maptool = $config['dot'];
|
|
$maptool = $config['circo'];
|
|
|
|
}
|
|
*/
|
|
|
|
switch ($format) {
|
|
case 'dot':
|
|
$img = "<pre>\n$map\n</pre>";
|
|
break;
|
|
case 'svg':
|
|
//$img = external_exec($maptool . ' -T' . $format);
|
|
$process = pipe_open($maptool . ' -T' . $format, $pipes);
|
|
if (is_resource($process)) {
|
|
$img = pipe_read($map, $pipes);
|
|
$img = str_replace("<a ", '<a target="_parent" ', $img);
|
|
}
|
|
pipe_close($process, $pipes);
|
|
header("Content-type: image/svg+xml");
|
|
break;
|
|
case 'png':
|
|
default:
|
|
$format = 'png:gd';
|
|
$img = external_exec($maptool . ' -T' . $format);
|
|
$process = pipe_open($maptool . ' -T' . $format, $pipes);
|
|
if (is_resource($process)) {
|
|
$img = pipe_read($map, $pipes);
|
|
}
|
|
pipe_close($process, $pipes);
|
|
header("Content-type: image/png");
|
|
break;
|
|
}
|
|
|
|
echo($img);
|
|
|
|
// EOF
|