2015-08-01 18:14:55 +00:00
< ? php
/**
2016-08-20 11:16:55 +00:00
* LibreNMS
2015-08-01 18:14:55 +00:00
*
2016-08-20 11:16:55 +00:00
* This file is part of LibreNMS .
2015-08-01 18:14:55 +00:00
*
* @ copyright ( C ) 2006 - 2012 Adam Armstrong
*/
2019-06-23 05:29:12 +00:00
use LibreNMS\Config ;
2021-04-30 03:42:18 +00:00
use LibreNMS\Util\Debug ;
2018-04-07 20:55:28 +00:00
2015-08-01 18:14:55 +00:00
$links = 1 ;
2020-09-21 12:54:51 +00:00
$init_modules = [ 'web' , 'auth' ];
2016-11-21 20:12:59 +00:00
require realpath ( __DIR__ . '/..' ) . '/includes/init.php' ;
2015-08-01 18:14:55 +00:00
2020-09-21 12:54:51 +00:00
if ( ! Auth :: check ()) {
exit ( 'Unauthorized' );
2019-04-12 04:26:42 +00:00
}
2018-07-13 22:08:00 +00:00
$options = getopt ( 'd::' );
2021-04-30 03:42:18 +00:00
if ( Debug :: set ( isset ( $options [ 'd' ]), false )) {
2018-07-13 22:08:00 +00:00
echo " DEBUG! \n " ;
}
2015-08-01 18:14:55 +00:00
if ( strpos ( $_SERVER [ 'REQUEST_URI' ], 'anon' )) {
$anon = 1 ;
}
2019-06-23 05:29:12 +00:00
if ( is_array ( Config :: get ( 'branding' ))) {
Config :: set ( 'branding' , array_replace_recursive ( Config :: get ( 'branding' ), Config :: get ( 'branding.' . $_SERVER [ 'SERVER_NAME' ]) ? : Config :: get ( 'branding.default' )));
2015-08-01 18:14:55 +00:00
}
Refactored and update Location Geocoding (#9359)
- Fix location so it is a regular database relation (this allows multiple devices to be accurately linked to one location and saves api calls)
- Parse coordinates from the location more consistently
- Add settings to webui
- ~~Used [PHP Geocoder](http://geocoder-php.org/), which has lots of backends and is well tested. (also includes reverse and geoip)~~
- Google Maps, Bing, Mapquest, and OpenStreetMap supported initially.
- Default to OpenStreetMap, which doesn't require a key. They will liberally hand out bans if you exceed 1 query per second though.
- All other Geocoding APIs require an API key. (Google requires a credit card on file, but seems to be the most accurate)
- Update all (I think) sql queries to handle the new structure
- Remove final vestiges of override_sysLocation as a device attribute
- Update existing device groups and rules in DB
- Tested all APIs with good/bad location, no/bad/good key, and no connection.
- Cannot fix advanced queries that use location
This blocks #8868
DO NOT DELETE THIS TEXT
#### Please note
> Please read this information carefully. You can run `./scripts/pre-commit.php` to check your code before submitting.
- [x] Have you followed our [code guidelines?](http://docs.librenms.org/Developing/Code-Guidelines/)
#### Testers
If you would like to test this pull request then please run: `./scripts/github-apply <pr_id>`, i.e `./scripts/github-apply 5926`
After you are done testing, you can remove the changes with `./scripts/github-remove`. If there are schema changes, you can ask on discord how to revert.
2018-11-28 22:49:18 +00:00
$where = '' ;
$param = [];
2018-11-29 19:04:11 +00:00
if ( isset ( $_GET [ 'device' ]) && is_numeric ( $_GET [ 'device' ])) {
Refactored and update Location Geocoding (#9359)
- Fix location so it is a regular database relation (this allows multiple devices to be accurately linked to one location and saves api calls)
- Parse coordinates from the location more consistently
- Add settings to webui
- ~~Used [PHP Geocoder](http://geocoder-php.org/), which has lots of backends and is well tested. (also includes reverse and geoip)~~
- Google Maps, Bing, Mapquest, and OpenStreetMap supported initially.
- Default to OpenStreetMap, which doesn't require a key. They will liberally hand out bans if you exceed 1 query per second though.
- All other Geocoding APIs require an API key. (Google requires a credit card on file, but seems to be the most accurate)
- Update all (I think) sql queries to handle the new structure
- Remove final vestiges of override_sysLocation as a device attribute
- Update existing device groups and rules in DB
- Tested all APIs with good/bad location, no/bad/good key, and no connection.
- Cannot fix advanced queries that use location
This blocks #8868
DO NOT DELETE THIS TEXT
#### Please note
> Please read this information carefully. You can run `./scripts/pre-commit.php` to check your code before submitting.
- [x] Have you followed our [code guidelines?](http://docs.librenms.org/Developing/Code-Guidelines/)
#### Testers
If you would like to test this pull request then please run: `./scripts/github-apply <pr_id>`, i.e `./scripts/github-apply 5926`
After you are done testing, you can remove the changes with `./scripts/github-remove`. If there are schema changes, you can ask on discord how to revert.
2018-11-28 22:49:18 +00:00
$where = '&& device_id = ?' ;
$param [] = $_GET [ 'device' ];
2015-08-01 18:14:55 +00:00
}
// FIXME this shit probably needs tidied up.
2020-09-21 13:59:34 +00:00
if ( isset ( $_GET [ 'format' ]) && preg_match ( '/^[a-z]*$/' , $_GET [ 'format' ])) {
2015-08-01 18:14:55 +00:00
$map = '
digraph G { bgcolor = transparent ; splines = true ; overlap = scale ; concentrate = 0 ; epsilon = 0.001 ; rankdir = LR ;
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 ];
' ;
2020-09-21 12:54:51 +00:00
if ( ! Auth :: check ()) {
2015-08-01 18:14:55 +00:00
$map .= " \" Not authenticated \" [fontsize=20 fillcolor= \" lightblue \" , URL= \" / \" shape=box3d] \n " ;
2016-08-19 01:28:22 +00:00
} else {
2019-05-10 16:02:39 +00:00
$locations = getlocations ();
2015-08-01 18:14:55 +00:00
$loc_count = 1 ;
2020-09-21 13:59:34 +00:00
foreach ( dbFetch ( 'SELECT *, locations.location FROM devices LEFT JOIN locations ON devices.location_id = locations.id WHERE 1 ' . $where , $param ) as $device ) {
2015-08-01 18:14:55 +00:00
if ( $device ) {
2020-09-21 13:59:34 +00:00
$links = dbFetch ( 'SELECT * from ports AS I, links AS L WHERE I.device_id = ? AND L.local_port_id = I.port_id ORDER BY L.remote_hostname' , [ $device [ 'device_id' ]]);
2015-08-01 18:14:55 +00:00
if ( count ( $links )) {
if ( $anon ) {
$device [ 'hostname' ] = md5 ( $device [ 'hostname' ]);
}
2020-09-21 12:54:51 +00:00
if ( ! isset ( $locations [ $device [ 'location' ]])) {
2016-08-19 01:28:22 +00:00
$locations [ $device [ 'location' ]] = $loc_count ;
$loc_count ++ ;
2015-08-01 18:14:55 +00:00
}
$loc_id = $locations [ $device [ 'location' ]];
2020-09-21 13:59:34 +00:00
$map .= '"' . $device [ 'hostname' ] . '" [fontsize=20, fillcolor="lightblue", group=' . $loc_id . ' URL="' . Config :: get ( 'base_url' ) . '/device/device=' . $device [ 'device_id' ] . " /tab=neighbours/selection=map/ \" shape=box3d] \n " ;
2015-08-01 18:14:55 +00:00
}
2016-08-19 01:28:22 +00:00
foreach ( $links as $link ) {
2015-08-01 18:14:55 +00:00
$local_port_id = $link [ 'local_port_id' ];
$remote_port_id = $link [ 'remote_port_id' ];
2016-08-19 01:28:22 +00:00
$i = 0 ;
$done = 0 ;
2015-08-01 18:14:55 +00:00
if ( $linkdone [ $remote_port_id ][ $local_port_id ]) {
$done = 1 ;
}
2020-09-21 12:54:51 +00:00
if ( ! $done ) {
2016-08-19 01:28:22 +00:00
$linkdone [ $local_port_id ][ $remote_port_id ] = true ;
2015-08-01 18:14:55 +00:00
$links ++ ;
2020-09-21 13:59:34 +00:00
if ( $link [ 'ifSpeed' ] >= '10000000000' ) {
$info = 'color=red3 style="setlinewidth(6)"' ;
} elseif ( $link [ 'ifSpeed' ] >= '1000000000' ) {
$info = 'color=lightblue style="setlinewidth(4)"' ;
} elseif ( $link [ 'ifSpeed' ] >= '100000000' ) {
$info = 'color=lightgrey style="setlinewidth(2)"' ;
} elseif ( $link [ 'ifSpeed' ] >= '10000000' ) {
$info = 'style="setlinewidth(1)"' ;
2016-08-19 01:28:22 +00:00
} else {
2020-09-21 13:59:34 +00:00
$info = 'style="setlinewidth(1)"' ;
2015-08-01 18:14:55 +00:00
}
$src = $device [ 'hostname' ];
if ( $anon ) {
$src = md5 ( $src );
}
if ( $remote_port_id ) {
2020-09-21 13:59:34 +00:00
$dst = dbFetchCell ( 'SELECT `hostname` FROM `devices` AS D, `ports` AS I WHERE I.port_id = ? AND D.device_id = I.device_id' , [ $remote_port_id ]);
$dst_host = dbFetchCell ( 'SELECT D.device_id FROM `devices` AS D, `ports` AS I WHERE I.port_id = ? AND D.device_id = I.device_id' , [ $remote_port_id ]);
2016-08-19 01:28:22 +00:00
} else {
2015-08-01 18:14:55 +00:00
unset ( $dst_host );
$dst = $link [ 'remote_hostname' ];
}
if ( $anon ) {
$dst = md5 ( $dst );
$src = md5 ( $src );
}
2020-09-21 13:59:34 +00:00
$sif = cleanPort ( dbFetchRow ( 'SELECT * FROM ports WHERE `port_id` = ?' , [ $link [ 'local_port_id' ]]), $device );
2015-08-01 18:14:55 +00:00
if ( $remote_port_id ) {
2020-09-21 13:59:34 +00:00
$dif = cleanPort ( dbFetchRow ( 'SELECT * FROM ports WHERE `port_id` = ?' , [ $link [ 'remote_port_id' ]]));
2016-08-19 01:28:22 +00:00
} else {
2015-08-01 18:14:55 +00:00
$dif [ 'label' ] = $link [ 'remote_port' ];
$dif [ 'port_id' ] = $link [ 'remote_hostname' ] . '/' . $link [ 'remote_port' ];
}
2020-09-21 13:59:34 +00:00
if ( $where == '' ) {
2020-09-21 12:54:51 +00:00
if ( ! $ifdone [ $dst ][ $dif [ 'port_id' ]] && ! $ifdone [ $src ][ $sif [ 'port_id' ]]) {
2015-08-01 18:14:55 +00:00
$map .= " \" $src\ " -> \ " " . $dst . " \" [weight=500000, arrowsize=0, len=0]; \n " ;
}
$ifdone [ $src ][ $sif [ 'port_id' ]] = 1 ;
2016-08-19 01:28:22 +00:00
} else {
2020-09-21 13:59:34 +00:00
$map .= '"' . $sif [ 'port_id' ] . '" [label="' . $sif [ 'label' ] . '", fontsize=12, fillcolor=lightblue, URL="' . Config :: get ( 'base_url' ) . '/device/device=' . $device [ 'device_id' ] . " /tab=port/port= $local_port_id / \" ] \n " ;
2020-09-21 12:54:51 +00:00
if ( ! $ifdone [ $src ][ $sif [ 'port_id' ]]) {
2015-08-01 18:14:55 +00:00
$map .= " \" $src\ " -> \ " " . $sif [ 'port_id' ] . " \" [weight=500000, arrowsize=0, len=0]; \n " ;
$ifdone [ $src ][ $sif [ 'port_id' ]] = 1 ;
}
if ( $dst_host ) {
2019-06-23 05:29:12 +00:00
$map .= " \" $dst\ " [ URL = \ " " . Config :: get ( 'base_url' ) . " /device/device= $dst_host /tab=neighbours/selection=map/ \" , fontsize=20, shape=box3d] \n " ;
2016-08-19 01:28:22 +00:00
} else {
2015-08-01 18:14:55 +00:00
$map .= " \" $dst\ " [ fontsize = 20 shape = box3d ] \n " ;
}
if ( $dst_host == $device [ 'device_id' ] || $where == '' ) {
2020-09-21 13:59:34 +00:00
$map .= '"' . $dif [ 'port_id' ] . '" [label="' . $dif [ 'label' ] . '", fontsize=12, fillcolor=lightblue, URL="' . Config :: get ( 'base_url' ) . " /device/device= $dst_host /tab=port/port= $remote_port_id / \" ] \n " ;
2016-08-19 01:28:22 +00:00
} else {
2020-09-21 13:59:34 +00:00
$map .= '"' . $dif [ 'port_id' ] . '" [label="' . $dif [ 'label' ] . ' ", fontsize=12, fillcolor=lightgray' ;
2015-08-01 18:14:55 +00:00
if ( $dst_host ) {
2020-09-21 13:59:34 +00:00
$map .= ', URL="' . Config :: get ( 'base_url' ) . " /device/device= $dst_host /tab=port/port= $remote_port_id / \" " ;
2015-08-01 18:14:55 +00:00
}
$map .= " ] \n " ;
}
2020-09-21 12:54:51 +00:00
if ( ! $ifdone [ $dst ][ $dif [ 'port_id' ]]) {
2020-09-21 13:59:34 +00:00
$map .= '"' . $dif [ 'port_id' ] . " \" -> \" $dst\ " [ weight = 500000 , arrowsize = 0 , len = 0 ]; \n " ;
2015-08-01 18:14:55 +00:00
$ifdone [ $dst ][ $dif [ 'port_id' ]] = 1 ;
}
2020-09-21 13:59:34 +00:00
$map .= '"' . $sif [ 'port_id' ] . '" -> "' . $dif [ 'port_id' ] . " \" [weight=1, arrowhead=normal, arrowtail=normal, len=2, $info ] \n " ;
2015-08-01 18:14:55 +00:00
}
}
}
$done = 0 ;
}
}
}
$map .= " \n }; " ;
if ( $_GET [ 'debug' ] == 1 ) {
echo '<pre>$map</pre>' ;
exit ();
}
switch ( $_GET [ 'format' ]) {
case 'svg' :
break ;
case 'png' :
$_GET [ 'format' ] = 'png:gd' ;
break ;
case 'dot' :
2020-09-21 12:54:51 +00:00
echo $map ;
2015-08-01 18:14:55 +00:00
exit ();
default :
$_GET [ 'format' ] = 'png:gd' ;
}
if ( $links > 30 ) {
// Unflatten if there are more than 10 links. beyond that it gets messy
2019-06-23 05:29:12 +00:00
$maptool = Config :: get ( 'dot' );
2016-08-19 01:28:22 +00:00
} else {
2019-06-23 05:29:12 +00:00
$maptool = Config :: get ( 'dot' );
2015-08-01 18:14:55 +00:00
}
if ( $where == '' ) {
2019-06-23 05:29:12 +00:00
$maptool = Config :: get ( 'sfdp' ) . ' -Gpack -Goverlap=prism -Gcharset=latin1 -Gsize=20,20' ;
$maptool = Config :: get ( 'dot' );
2015-08-01 18:14:55 +00:00
}
2020-09-21 13:59:34 +00:00
$descriptorspec = [ 0 => [ 'pipe' , 'r' ], 1 => [ 'pipe' , 'w' ]];
2015-08-01 18:14:55 +00:00
2020-09-21 13:59:34 +00:00
$mapfile = Config :: get ( 'temp_dir' ) . '/' . strgen () . '.png' ;
2015-08-01 18:14:55 +00:00
2020-09-21 12:54:51 +00:00
$process = proc_open ( $maptool . ' -T' . $_GET [ 'format' ], $descriptorspec , $pipes );
2015-08-01 18:14:55 +00:00
if ( is_resource ( $process )) {
2016-08-19 01:28:22 +00:00
fwrite ( $pipes [ 0 ], " $map " );
2015-08-01 18:14:55 +00:00
fclose ( $pipes [ 0 ]);
while ( ! feof ( $pipes [ 1 ])) {
$img .= fgets ( $pipes [ 1 ]);
}
fclose ( $pipes [ 1 ]);
$return_value = proc_close ( $process );
}
2020-09-21 13:59:34 +00:00
if ( $_GET [ 'format' ] == 'png:gd' ) {
header ( 'Content-type: image/png' );
} elseif ( $_GET [ 'format' ] == 'svg' ) {
header ( 'Content-type: image/svg+xml' );
$img = str_replace ( '<a ' , '<a target="_parent" ' , $img );
2015-08-01 18:14:55 +00:00
}
echo $img ;
2016-08-19 01:28:22 +00:00
} else {
2019-08-05 19:16:05 +00:00
if ( Auth :: check ()) {
2015-08-01 18:14:55 +00:00
// FIXME level 10 only?
echo ' < center >
2019-06-23 05:29:12 +00:00
< object width = 1200 height = 1000 data = " ' . Config::get('base_url') . '/network-map.php?format=svg " type = " image/svg+xml " ></ object >
2015-08-01 18:14:55 +00:00
</ center >
' ;
}
}