aboutsummaryrefslogtreecommitdiffstats
path: root/web/nms.gathering.org
diff options
context:
space:
mode:
Diffstat (limited to 'web/nms.gathering.org')
-rwxr-xr-xweb/nms.gathering.org/apkart.pl89
-rw-r--r--web/nms.gathering.org/bg07.pngbin0 -> 498409 bytes
-rwxr-xr-xweb/nms.gathering.org/dhcpkart.pl94
-rw-r--r--web/nms.gathering.org/index.html92
-rwxr-xr-xweb/nms.gathering.org/led.pl20
-rwxr-xr-xweb/nms.gathering.org/mbd-status.pl44
-rwxr-xr-xweb/nms.gathering.org/mygraph.pl179
-rw-r--r--web/nms.gathering.org/nettkart-continuous.html31
-rwxr-xr-xweb/nms.gathering.org/nettkart-telnet.pl47
-rwxr-xr-xweb/nms.gathering.org/nettkart-text.pl47
-rwxr-xr-xweb/nms.gathering.org/nettkart-web.pl47
-rwxr-xr-xweb/nms.gathering.org/nettkart.pl142
-rwxr-xr-xweb/nms.gathering.org/portkart.pl82
-rwxr-xr-xweb/nms.gathering.org/showswitch.pl221
-rw-r--r--web/nms.gathering.org/slide.html38
-rwxr-xr-xweb/nms.gathering.org/smanagement.pl239
-rwxr-xr-xweb/nms.gathering.org/ssendfile.pl48
-rwxr-xr-xweb/nms.gathering.org/sshow.pl257
-rwxr-xr-xweb/nms.gathering.org/stromkart.pl69
-rwxr-xr-xweb/nms.gathering.org/uplinkkart-text.pl38
-rwxr-xr-xweb/nms.gathering.org/uplinkkart.pl70
-rwxr-xr-xweb/nms.gathering.org/uplinktrafikkart.pl90
22 files changed, 1984 insertions, 0 deletions
diff --git a/web/nms.gathering.org/apkart.pl b/web/nms.gathering.org/apkart.pl
new file mode 100755
index 0000000..a89cb68
--- /dev/null
+++ b/web/nms.gathering.org/apkart.pl
@@ -0,0 +1,89 @@
+#! /usr/bin/perl
+use CGI qw(fatalsToBrowser);
+use GD;
+use DBI;
+use lib '../../include';
+use nms;
+use strict;
+use warnings;
+my $cgi = CGI->new;
+
+#my $greentimeout = 7200;
+my $greentimeout = 15*60;
+my $maxtimeout = $greentimeout*9;
+
+my $dbh = nms::db_connect();
+
+GD::Image->trueColor(1);
+
+my $img = GD::Image->new('bg07.png');
+
+my $blk = $img->colorResolve(0, 0, 0);
+my $red = $img->colorResolve(255, 0, 0);
+my $grn = $img->colorResolve(0, 255, 0);
+my $blu = $img->colorResolve(0, 0, 255);
+
+# Her ska' det bættre skrivas STORT jah!
+my $title = new GD::Image(75,15);
+$img->alphaBlending(1);
+$title->alphaBlending(1);
+my $titlebg = $title->colorResolve(255, 255, 255);
+$title->fill(0,0,$titlebg);
+$title->transparent($titlebg);
+$title->string(gdGiantFont,7,0,"APEKART",$title->colorResolve(255, 0, 0));
+$img->copyResampled($title, 500, 0, 0, 0, 400, 100, 75, 15);
+$img->copyResampled($title, 500, 550, 0, 0, 400, 100, 75, 15);
+
+$img->string(gdMediumBoldFont,0,0,"Access points",$blk);
+$img->string(gdSmallFont,0,20,"Shows if a Cisco access point is plugged into the port",$blk);
+
+my %palette = ( 'notpolled' => $blu, 'missing' => $red, 'present' => $grn );
+
+my @states = qw(present missing notpolled);
+
+for my $i (0..$#states) {
+ my $y = 60 + 20 * (4 - $i);
+ $img->filledRectangle(20, $y, 30, $y + 10, $palette{$states[$i]});
+ $img->rectangle(20, $y, 30, $y + 10, $blk);
+ $img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, $y + 10, $states[$i]);
+}
+
+my $q = $dbh->prepare("select switch,sysname,model,last_poll < now() - '30 seconds'::interval as notpolled,placement from switches natural join placements natural join ap_poll order by zorder");
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ my $sysname = $ref->{'sysname'};
+ my $model = $ref->{'model'};
+ my $state;
+ if ($ref->{'notpolled'}) {
+ $state = 'notpolled';
+ } elsif ($model =~ /^cisco AIR-/) {
+ $state = 'present';
+ } else {
+ $state = 'missing';
+ $sysname .= " $model";
+ }
+ my $clr = $palette{$state};
+
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+ $img->filledRectangle($3,$4,$1,$2,$clr);
+ $img->rectangle($3,$4,$1,$2,$blk);
+
+ my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4);
+ my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1;
+ while (length($sysname) * 6 > $max_textlen) {
+ # Try to abbreviate sysname if it is too long for the box
+ $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last;
+ }
+ if (($x2-$x1) > ($y2-$y1)) {
+ $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk);
+ } else {
+ $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk);
+ }
+}
+$dbh->disconnect;
+
+if (!defined($ARGV[0])) {
+ print $cgi->header(-type=>'image/png',
+ -refresh=>'10; ' . CGI::url());
+}
+print $img->png;
diff --git a/web/nms.gathering.org/bg07.png b/web/nms.gathering.org/bg07.png
new file mode 100644
index 0000000..ec54ad3
--- /dev/null
+++ b/web/nms.gathering.org/bg07.png
Binary files differ
diff --git a/web/nms.gathering.org/dhcpkart.pl b/web/nms.gathering.org/dhcpkart.pl
new file mode 100755
index 0000000..2af4272
--- /dev/null
+++ b/web/nms.gathering.org/dhcpkart.pl
@@ -0,0 +1,94 @@
+#! /usr/bin/perl
+use CGI qw(fatalsToBrowser);
+use GD;
+use DBI;
+use lib '../../include';
+use nms;
+my $cgi = CGI->new;
+
+#my $greentimeout = 7200;
+my $greentimeout = 15*60;
+my $maxtimeout = $greentimeout*9;
+
+my $dbh = nms::db_connect();
+
+GD::Image->trueColor(1);
+my $map = 'bg07.png';
+die "$map does not exist" unless -e $map;
+$img = GD::Image->new($map);
+
+my $blk = $img->colorResolve(0, 0, 0);
+
+$img->string(gdMediumBoldFont,0,0,"DHCP-lease status",$blk);
+$img->string(gdSmallFont,0,20,"Last received DHCP-request",$blk);
+
+# first 1/5: green (<30 min)
+# middle 3/5: yellow -> red (30 min - 6 hours)
+# last 1/5: blue (>6 hours)
+my $grn = $img->colorResolve(0, 255, 0);
+my $blu = $img->colorResolve(0, 0, 255);
+
+my $l1 = 42 + (236 - 42)/5;
+my $l2 = 236 - (236 - 42)/5;
+
+$img->filledRectangle(32, 42, 53, $l1, $grn);
+$img->string(gdSmallFont,56,$l1-8,($greentimeout/60)." min",$blk);
+
+$img->filledRectangle(32, $l2, 53, 237, $blu);
+$img->string(gdSmallFont,56,$l2-5,($maxtimeout/60)." min",$blk);
+
+for my $y ($l1..$l2) {
+ my $i = 1.0 - ($y - $l1) / ($l2 - $l1);
+ my $clr = get_color($i);
+
+ $img->filledRectangle(32,$y,53,$y+1,$clr);
+}
+
+my $q = $dbh->prepare('select switch,sysname,placement,EXTRACT(EPOCH FROM now() - last_ack) as age from switches natural join placements natural join dhcp order by sysname');
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ my $age = $ref->{'age'};
+ if (!defined($age) || $age > $maxtimeout) {
+ $clr = $img->colorResolve(0, 0, 255);
+ } elsif ($age < $greentimeout) {
+ $clr = $img->colorResolve(0, 255, 0);
+ } else {
+ # 30 minutes = 0.0
+ # 6 hours = 1.0
+
+ my $intensity = log($age / $greentimeout) / log($maxtimeout/$greentimeout);
+ $clr = get_color(1.0 - $intensity);
+ }
+
+ my $sysname = $ref->{'sysname'};
+ if ($sysname !~ m/d0/i) { # don't draw distro-switches
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+ $img->filledRectangle($3,$4,$1,$2,$clr);
+ $img->rectangle($3,$4,$1,$2,$blk);
+
+ my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4);
+ my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1;
+ while (length($sysname) * 6 > $max_textlen) {
+ # Try to abbreviate sysname if it is too long for the box
+ $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last;
+ }
+ if (($x2-$x1) > ($y2-$y1)) {
+ $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk);
+ } else {
+ $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk);
+ }
+ }
+}
+$dbh->disconnect;
+
+if (!defined($ARGV[0])) {
+ print $cgi->header(-type=>'image/png',
+ -refresh=>'10; ' . CGI::url());
+}
+print $img->png;
+
+sub get_color {
+ my $intensity = shift;
+ my $gamma = 1.0/1.90;
+ return $img->colorResolve(255.0, 255.0 * ($intensity ** $gamma), 0);
+}
diff --git a/web/nms.gathering.org/index.html b/web/nms.gathering.org/index.html
new file mode 100644
index 0000000..2857377
--- /dev/null
+++ b/web/nms.gathering.org/index.html
@@ -0,0 +1,92 @@
+<html>
+ <head>
+ <title>snmp</title>
+ </head>
+ <body>
+ <p>tg light &amp; magic. :-)</p>
+
+ <ul>
+ <li><a href="dhcpkart.pl">DHCP-kart</a>
+ <br /><i>Oversikt over DHCP-lease etter switch</i>
+ </li>
+
+ <br />
+
+ <li><a href="nettkart-text.pl">Nettkart</a>
+ <br /><i>Trafikkoversikt</i>
+ </li>
+
+ <br />
+
+ <li><a href="nettkart-telnet.pl">Nettkart</a>
+ <br /><i>Trafikkoversikt /m telnetlink</i>
+ </li>
+
+ <br />
+<!-- Kun moderat nyttig når vi har disablet alle webinterfacene...
+ <li><a href="nettkart-web.pl">Nettkart</a>
+ <br /><i>Trafikkoversikt /m weblink</i>
+ </li>
+
+ <br />
+-->
+ <li><a href="portkart.pl">Nettkart, per port</a>
+ <br /><i>Trafikkoversikt per port</i>
+ </li>
+
+ <br />
+
+ <li><a href="uplinkkart.pl">Uplink-kart</a>
+ <br /><i>Hvilke switcher har ikke to uplinker</i>
+ </li>
+
+ <br />
+
+ <li><a href="uplinktrafikkart.pl">Uplink-trafikkart</a>
+ <br /><i>Hvem burde hatt mer enn to uplinker</i>
+ </li>
+
+ <br />
+
+ <li><a href="stromkart.pl">Strømkart</a>
+ <br /><i>Hvilke switcher har færre enn fem tilkoblede klienter</i>
+ </li>
+
+ <br />
+
+ <li><a href="apkart.pl">Aksesspunkt-kart</a>
+ <br /><i>Hvilke aksesspunkter er plugget i</i>
+ </li>
+
+ <br />
+
+ <!--<li><a href="overlay.pl">Overlay-nettkart</a>
+ <br /><i>Teh magic 3D!</i>
+ </li>
+
+ <br /> -->
+
+ <li><a href="smanagement.pl">Kommander switcher</a>
+ <br /><i>Konfigurer switchene</i>
+ </li>
+
+ <br />
+
+ <li><a href="sshow.pl">Utførte og køede kommandoer</a>
+ <br /><i>Se og håndter kommandoer som er utført og fortsatt i køen</i>
+ </li>
+
+ <br />
+
+ <!--<li><a href="stempmap.pl">Temperaturkart</a>
+ <br /><i>Temperaturkart for switchene</i>
+ </li>
+
+ <br /> -->
+
+ <li><a href="mbd-status.pl">MBD-status</a>
+ <br /><i>Hva spiller folk mest?</i>
+ </li>
+ </ul>
+ </body>
+</html>
diff --git a/web/nms.gathering.org/led.pl b/web/nms.gathering.org/led.pl
new file mode 100755
index 0000000..a05041d
--- /dev/null
+++ b/web/nms.gathering.org/led.pl
@@ -0,0 +1,20 @@
+#! /usr/bin/perl
+use CGI;
+use GD;
+use DBI;
+use lib '../../include';
+use nms;
+my $cgi = CGI->new;
+
+my $dbh = nms::db_connect();
+
+print $cgi->header(-type=>'text/plain', -expires=>'now');
+
+my $q = $dbh->prepare('select * from ( SELECT switch,sysname,sum(bytes_in) AS bytes_in,sum(bytes_out) AS bytes_out from switches natural left join get_current_datarate() group by switch,sysname) t1 natural join placements order by zorder;');
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ my $sysname = $ref->{'sysname'};
+ next unless $sysname =~ /e\d+-\d+/;
+ printf "%s %s\n", $sysname, (defined($ref->{'bytes_in'}) ? 'on' : 'off');
+}
+$dbh->disconnect;
diff --git a/web/nms.gathering.org/mbd-status.pl b/web/nms.gathering.org/mbd-status.pl
new file mode 100755
index 0000000..d37781f
--- /dev/null
+++ b/web/nms.gathering.org/mbd-status.pl
@@ -0,0 +1,44 @@
+#! /usr/bin/perl
+use CGI;
+use DBI;
+use lib '../../include';
+use nms;
+my $cgi = CGI->new;
+
+my $dbh = nms::db_connect();
+print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'10; ' . CGI::url());
+
+print <<"EOF";
+<html>
+ <head>
+ <title>MBD status</title>
+ </head>
+ <body>
+ <h1>MBD status</h1>
+
+ <p>Spill søkt etter siste 15 minutter:</p>
+
+ <table>
+ <tr>
+ <th>Beskrivelse</th>
+ <th>Aktive servere</th>
+ </tr>
+EOF
+
+my $q = $dbh->prepare('select description,sum(active_servers) as active_servers from (select distinct on (game,port) * from mbd_log where ts >= now() - \'10 minutes\'::interval order by game,port,ts desc ) t1 group by description order by sum(active_servers) desc, description;');
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ print <<"EOF";
+ <tr>
+ <td>$ref->{'description'}</td>
+ <td>$ref->{'active_servers'}</td>
+ </tr>
+EOF
+}
+$dbh->disconnect;
+
+print <<"EOF";
+ </table>
+ </body>
+</html>
+EOF
diff --git a/web/nms.gathering.org/mygraph.pl b/web/nms.gathering.org/mygraph.pl
new file mode 100755
index 0000000..64104aa
--- /dev/null
+++ b/web/nms.gathering.org/mygraph.pl
@@ -0,0 +1,179 @@
+#! /usr/bin/perl -T
+use strict;
+use warnings;
+use GD;
+use POSIX;
+use Time::Zone;
+
+sub blendpx {
+ my ($gd, $x, $y, $r, $g, $b, $frac) = @_;
+ my ($ro, $go, $bo) = $gd->rgb($gd->getPixel($x, $y));
+
+ # workaround for icky 256-color graphs
+ # $frac = int($frac * 32) / 32;
+
+ my $rn = $ro * (1.0 - $frac) + $r * $frac;
+ my $gn = $go * (1.0 - $frac) + $g * $frac;
+ my $bn = $bo * (1.0 - $frac) + $b * $frac;
+
+ $gd->setPixel($x, $y, $gd->colorResolve($rn, $gn, $bn));
+}
+
+# Standard implementation of Wu's antialiased line algorithm.
+sub wuline {
+ my ($gd, $x1, $y1, $x2, $y2, $r, $g, $b, $a) = @_;
+ $x1 = POSIX::floor($x1);
+ $x2 = POSIX::floor($x2);
+ $y1 = POSIX::floor($y1);
+ $y2 = POSIX::floor($y2);
+
+ if (abs($x2 - $x1) > abs($y2 - $y1)) {
+ # x-directional
+ if ($y2 < $y1) {
+ ($x2, $y2, $x1, $y1) = ($x1, $y1, $x2, $y2);
+ }
+
+ my $y = POSIX::floor($y1);
+ my $frac = $y1 - $y;
+ my $dx = ($x2 > $x1) ? 1 : -1;
+ my $dy = ($y2 - $y1) / abs($x2 - $x1);
+
+ for (my $x = $x1; $x != $x2 + $dx; $x += $dx) {
+ blendpx($gd, $x, $y, $r, $g, $b, $a * (1.0 - $frac));
+ blendpx($gd, $x, $y + 1, $r, $g, $b, $a * $frac);
+ $frac += $dy;
+ if ($frac > 1) {
+ $frac -= 1;
+ ++$y;
+ }
+ }
+ } else {
+ # y-directional
+ if ($x2 < $x1) {
+ ($x2, $y2, $x1, $y1) = ($x1, $y1, $x2, $y2);
+ }
+ my $x = POSIX::floor($x1);
+ my $frac = $x1 - $x;
+ my $dy = ($y2 > $y1) ? 1 : -1;
+ my $dx = ($x2 - $x1) / abs($y2 - $y1);
+
+ for (my $y = $y1; $y != $y2 + $dy; $y += $dy) {
+ blendpx($gd, $x, $y, $r, $g, $b, $a * (1.0 - $frac));
+ blendpx($gd, $x + 1, $y, $r, $g, $b, $a * $frac);
+ $frac += $dx;
+ if ($frac > 1) {
+ $frac -= 1;
+ ++$x;
+ }
+ }
+ }
+}
+
+sub makegraph {
+ my $xoffset = 70;
+ my ($width, $height, $min_x, $max_x, $min_y, $max_y, $tickgran) = @_;
+
+ # Create our base graph
+ my $graph = new GD::Image($width, $height, 1);
+ my $white = $graph->colorAllocate(255, 255, 255);
+ my $gray = $graph->colorAllocate(230, 230, 255);
+ my $black = $graph->colorAllocate(0, 0, 0);
+
+# $graph->fill(0, 0, $white);
+ $graph->filledRectangle(0, 0, $width, $height, $white); # seems to work better
+
+ $::xs = ($width - ($xoffset+2)) / ($max_x - $min_x);
+ $::ys = ($height - 33) / ($min_y - $max_y);
+
+ # Hour marks
+ for my $i ($xoffset+1..$width-2) {
+ if (((($i-($xoffset+1)) / $::xs + $min_x) / 3600) % 2 == 1) {
+ $graph->line($i, 0, $i, $height - 1, $gray);
+ }
+ }
+
+ # Hour text
+ for my $i (0..23) {
+ my @bounds = GD::Image::stringFT(undef, $black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 0, 0, $i);
+ my $w = $bounds[2] - $bounds[0];
+
+ # Determine where the center of this will be
+ my $starthour = POSIX::fmod(($min_x + Time::Zone::tz_local_offset()) / 3600, 24);
+ my $diff = POSIX::fmod($i - $starthour + 24, 24);
+
+ my $center = ($diff * 3600 + 1800) * $::xs;
+
+ next if ($center - $w / 2 < 1 || $center + $w / 2 > $width - ($xoffset+2));
+ $graph->stringFT($black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, $xoffset + $center - $w / 2, $height - 6, $i);
+ }
+
+ #
+ # Y lines; we want max 11 of them (zero-line, plus five on each side, or
+ # whatever) but we don't want the ticks to be on minimum 50 (or
+ # whatever $tickgran is set to). However, if there would be
+ # really really few lines, go down an order of magnitude and try
+ # again.
+ #
+ my $ytick;
+ do {
+ $ytick = ($max_y - $min_y) / 11;
+ $ytick = POSIX::ceil($ytick / $tickgran) * $tickgran;
+ $tickgran *= 0.1;
+ } while (($max_y - $min_y) / $ytick < 4);
+
+ for my $i (-11..11) {
+ my $y = ($i * $ytick - $max_y) * $::ys + 10;
+ next if ($y < 2 || $y > $height - 18);
+
+ if ($i == 0) {
+ wuline($graph, $xoffset, $y, $width - 1, $y, 0, 0, 0, 1.0);
+ wuline($graph, $xoffset, $y + 1, $width - 1, $y + 1, 0, 0, 0, 1.0);
+ } else {
+ wuline($graph, $xoffset, $y, $width - 1, $y, 0, 0, 0, 0.2);
+ }
+
+ # text
+ my $traf = 8 * ($i * $ytick);
+ my $text;
+ if ($traf >= 500_000_000) {
+ $text = (sprintf "%.1f Gbit", ($traf/1_000_000_000));
+ } elsif ($traf >= 500_000) {
+ $text = (sprintf "%.1f Mbit", ($traf/1_000_000));
+ } else {
+ $text = (sprintf "%.1f kbit", ($traf/1_000));
+ }
+
+ my @bounds = GD::Image::stringFT(undef, $black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 0, 0, $text);
+ my $w = $bounds[2] - $bounds[0];
+ my $h = $bounds[1] - $bounds[5];
+
+ next if ($y - $h/2 < 2 || $y + $h/2 > $height - 12);
+ $graph->stringFT($black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, ($xoffset - 4) - $w, $y + $h/2, $text);
+ }
+
+ # Nice border(TM)
+ $graph->rectangle($xoffset, 0, $width - 1, $height - 1, $black);
+
+ return $graph;
+}
+
+sub plotseries {
+ my ($graph, $xvals, $yvals, $r, $g, $b, $min_x, $max_y) = @_;
+ my $xoffset = 70;
+
+ my @xvals = @{$xvals};
+ my @yvals = @{$yvals};
+
+ my $x = $xvals[0];
+ my $y = $yvals[0];
+ for my $i (1..$#xvals) {
+ next if ($::xs * ($xvals[$i] - $x) < 2 && $::ys * ($yvals[$i] - $y) > -2);
+
+ wuline($graph, ($x-$min_x) * $::xs + $xoffset + 1, ($y-$max_y) * $::ys + 10,
+ ($xvals[$i]-$min_x) * $::xs + $xoffset + 1, ($yvals[$i]-$max_y) * $::ys + 10, $r, $g, $b, 1.0);
+ $x = $xvals[$i];
+ $y = $yvals[$i];
+ }
+}
+
+1;
diff --git a/web/nms.gathering.org/nettkart-continuous.html b/web/nms.gathering.org/nettkart-continuous.html
new file mode 100644
index 0000000..e51eea0
--- /dev/null
+++ b/web/nms.gathering.org/nettkart-continuous.html
@@ -0,0 +1,31 @@
+<html>
+ <body>
+ <div id="d"></div>
+ <script type="text/javascript">
+ <!--
+ var existing_img = null;
+
+ function load_new() {
+ var i = document.createElement('img');
+ i.onload = function() { loaded(i); };
+ i.style.display = 'none';
+ i.src = '/nettkart.pl?random=' + (new Date()).getTime();
+ document.getElementById('d').appendChild(i);
+ }
+
+ function loaded(i) {
+ i.style.display = '';
+
+ if (existing_img) {
+ existing_img.parentElement.removeChild(existing_img);
+ }
+ existing_img = i;
+
+ setTimeout(function() { load_new(); }, 10000);
+ }
+
+ load_new();
+ -->
+ </script>
+ </body>
+</html>
diff --git a/web/nms.gathering.org/nettkart-telnet.pl b/web/nms.gathering.org/nettkart-telnet.pl
new file mode 100755
index 0000000..57cac19
--- /dev/null
+++ b/web/nms.gathering.org/nettkart-telnet.pl
@@ -0,0 +1,47 @@
+#! /usr/bin/perl
+use CGI;
+use DBI;
+use lib '../../include';
+use nms;
+my $cgi = CGI->new;
+
+my $dbh = nms::db_connect();
+print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'45; ' . CGI::url());
+
+print <<"EOF";
+<html>
+ <head>
+ <title>nettkart - telnet</title>
+ </head>
+ <body>
+ <map name="switches">
+EOF
+
+my $q = $dbh->prepare("select * from switches natural join placements where ip <> inet '127.0.0.1'");
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+
+ my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'}; # average and convert to bits (should be about the same in practice)
+ my $ttext;
+ if ($traffic >= 1_000_000_000) {
+ $ttext = sprintf "%.2f Gbit/port/sec", $traffic/1_000_000_000;
+ } elsif ($traffic => 1_000_000) {
+ $ttext = sprintf "%.2f Mbit/port/sec", $traffic/1_000_000;
+ } else {
+ $ttext = sprintf "%.2f kbit/port/sec", $traffic/1_000;
+ }
+
+ printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" target=\"blank\" href=\"telnet://$ref->{'ip'}\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n",
+ $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'},
+ $ttext, $ref->{'sysname'}, $ttext;
+}
+$dbh->disconnect;
+
+print <<"EOF";
+ </map>
+
+ <p><img src="nettkart.pl" usemap="#switches" /></p>
+ </body>
+</html>
+EOF
diff --git a/web/nms.gathering.org/nettkart-text.pl b/web/nms.gathering.org/nettkart-text.pl
new file mode 100755
index 0000000..d3f4be7
--- /dev/null
+++ b/web/nms.gathering.org/nettkart-text.pl
@@ -0,0 +1,47 @@
+#! /usr/bin/perl
+use CGI;
+use DBI;
+use lib '../../include';
+use nms;
+my $cgi = CGI->new;
+
+my $dbh = nms::db_connect();
+print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'10; ' . CGI::url());
+
+print <<"EOF";
+<html>
+ <head>
+ <title>nettkart</title>
+ </head>
+ <body>
+ <map name="switches">
+EOF
+
+my $q = $dbh->prepare("select * from switches natural join placements where ip <> inet '127.0.0.1'");
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+
+ my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'}; # average and convert to bits (should be about the same in practice)
+ my $ttext;
+ if ($traffic >= 1_000_000_000) {
+ $ttext = sprintf "%.2f Gbit/port/sec", $traffic/1_000_000_000;
+ } elsif ($traffic => 1_000_000) {
+ $ttext = sprintf "%.2f Mbit/port/sec", $traffic/1_000_000;
+ } else {
+ $ttext = sprintf "%.2f kbit/port/sec", $traffic/1_000;
+ }
+
+ printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" href=\"showswitch.pl?id=%u\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n",
+ $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'},
+ $ttext, $ref->{'sysname'}, $ttext;
+}
+$dbh->disconnect;
+
+print <<"EOF";
+ </map>
+
+ <p><img src="nettkart.pl" usemap="#switches" /></p>
+ </body>
+</html>
+EOF
diff --git a/web/nms.gathering.org/nettkart-web.pl b/web/nms.gathering.org/nettkart-web.pl
new file mode 100755
index 0000000..ce76c35
--- /dev/null
+++ b/web/nms.gathering.org/nettkart-web.pl
@@ -0,0 +1,47 @@
+#! /usr/bin/perl
+use CGI;
+use DBI;
+use lib '../../include';
+use nms;
+my $cgi = CGI->new;
+
+my $dbh = nms::db_connect();
+print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'45; ' . CGI::url());
+
+print <<"EOF";
+<html>
+ <head>
+ <title>nettkart - web</title>
+ </head>
+ <body>
+ <map name="switches">
+EOF
+
+my $q = $dbh->prepare("select * from switches natural join placements where ip <> inet '127.0.0.1'");
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+
+ my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'}; # average and convert to bits (should be about the same in practice)
+ my $ttext;
+ if ($traffic >= 1_000_000_000) {
+ $ttext = sprintf "%.2f Gbit/port/sec", $traffic/1_000_000_000;
+ } elsif ($traffic => 1_000_000) {
+ $ttext = sprintf "%.2f Mbit/port/sec", $traffic/1_000_000;
+ } else {
+ $ttext = sprintf "%.2f kbit/port/sec", $traffic/1_000;
+ }
+
+ printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" href=\"http://$ref->{'ip'}\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n",
+ $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'},
+ $ttext, $ref->{'sysname'}, $ttext;
+}
+$dbh->disconnect;
+
+print <<"EOF";
+ </map>
+
+ <p><img src="nettkart.pl" usemap="#switches" /></p>
+ </body>
+</html>
+EOF
diff --git a/web/nms.gathering.org/nettkart.pl b/web/nms.gathering.org/nettkart.pl
new file mode 100755
index 0000000..b9517f8
--- /dev/null
+++ b/web/nms.gathering.org/nettkart.pl
@@ -0,0 +1,142 @@
+#! /usr/bin/perl
+use CGI;
+use GD;
+use Image::Magick;
+use DBI;
+use lib '../../include';
+use nms;
+my $cgi = CGI->new;
+
+# Sekrit night-mode
+my $night = defined($cgi->param('night'));
+
+my $dbh = nms::db_connect();
+
+GD::Image->trueColor(1);
+my ($img, $text_img);
+
+my $img = GD::Image->new('bg07.png');
+if ($night) {
+ my ($width, $height) = ($img->width, $img->height);
+
+ $img = GD::Image->new($width, $height, 1);
+ $img->alphaBlending(0);
+ $img->saveAlpha(1);
+ my $blank = $img->colorAllocateAlpha(0, 0, 0, 127);
+ $img->filledRectangle(0, 0, $img->width - 1, $img->height - 1, $blank);
+
+ $text_img = GD::Image->new($width, $height, 1);
+ $text_img->alphaBlending(0);
+ $text_img->saveAlpha(1);
+ my $blank = $text_img->colorAllocateAlpha(0, 0, 0, 127);
+ $text_img->filledRectangle(0, 0, $text_img->width - 1, $text_img->height - 1, $blank);
+} else {
+ $img = GD::Image->new('bg07.png');
+ $text_img = $img;
+}
+
+my $blk = $img->colorResolve(0, 0, 0);
+
+for my $y (42..236) {
+ my $i = 4.0 * ($y - 236.0) / (42.0 - 237.0);
+ my $clr = get_color($i);
+
+ $img->filledRectangle(12, $y, 33, $y+1, $clr);
+ $text_img->filledRectangle(12, $y, 33, $y+1, $clr);
+}
+
+$text_img->rectangle(12,42,33,236,$blk);
+
+my $tclr = $night ? $text_img->colorResolve(255, 255, 255) : $blk;
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/4.0, "100 Gbit/sec");
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/4.0, "10 Gbit/sec");
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/4.0, "1 Gbit/sec");
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*3.0/4.0, "100 Mbit/sec");
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*4.0/4.0, "10 Mbit/sec");
+$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 700, "NMS (C) 2005-2012 Tech:Server");
+
+my $q = $dbh->prepare("select * from ( SELECT switch,sysname,sum(bytes_in) AS bytes_in,sum(bytes_out) AS bytes_out from switches natural left join get_current_datarate() where ip <> inet '127.0.0.1' group by switch,sysname) t1 natural join placements order by zorder;");
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+
+ # for now:
+ # 10Mbit/switch = green
+ # 100Mbit/switch = yellow
+ # 1Gbit/switch = red
+ # 10Gbit/switch = white
+
+ my $clr;
+
+ if (defined($ref->{'bytes_in'})) {
+ my $intensity = 0.0;
+ my $traffic = 4.0 * ($ref->{'bytes_in'} + $ref->{'bytes_out'}); # average and convert to bits (should be about the same in practice)
+
+ my $max = 100_000_000_000.0; # 100Gbit
+ my $min = 10_000_000.0; # 10Mbit
+ if ($traffic >= $min) {
+ $intensity = log($traffic / $min) / log(10);
+ $intensity = 4.0 if ($intensity > 4.0);
+ }
+ $clr = get_color($intensity);
+ } else {
+ $clr = $img->colorResolve(0, 0, 255);
+ }
+
+ my $sysname = $ref->{'sysname'};
+ $sysname =~ s/-sekrit//;
+
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+ $img->filledRectangle($3,$4,$1,$2,$clr);
+ $text_img->filledRectangle($3,$4,$1,$2,$clr);
+
+ $img->rectangle($3,$4,$1,$2,$blk);
+ $text_img->rectangle($3,$4,$1,$2,$blk);
+ my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4);
+ my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1;
+ while (length($sysname) * 6 > $max_textlen) {
+ # Try to abbreviate sysname if it is too long for the box
+ $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last;
+ }
+ if (($x2-$x1) > ($y2-$y1)) {
+ $text_img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk);
+ } else {
+ $text_img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk);
+ }
+}
+$dbh->disconnect;
+
+print $cgi->header(-type=>'image/png', -expires=>'now');
+if ($night) {
+ my $magick = Image::Magick->new;
+ $magick->BlobToImage($img->png);
+ $magick->Blur(sigma=>10.0, channel=>'All');
+ $magick->Gamma(gamma=>1.90);
+
+ my $m2 = Image::Magick->new;
+ $m2->Read('bg07.png');
+ $m2->Negate();
+ $m2->Composite(image=>$magick, compose=>'Atop');
+
+ my $m3 = Image::Magick->new;
+ $m3->BlobToImage($text_img->png);
+ $m2->Composite(image=>$m3, compose=>'Atop');
+
+ $img = $m2->ImageToBlob();
+ print $img;
+} else {
+ print $img->png;
+}
+
+sub get_color {
+ my $intensity = shift;
+ my $gamma = 1.0/1.90;
+ if ($intensity > 3.0) {
+ return $img->colorResolve(255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma));
+ } elsif ($intensity > 2.0) {
+ return $img->colorResolve(255.0, 255.0 * (($intensity - 2.0) ** $gamma), 255.0 * (($intensity - 2.0) ** $gamma));
+ } elsif ($intensity > 1.0) {
+ return $img->colorResolve(255.0, 255.0 * ((2.0 - $intensity) ** $gamma), 0);
+ } else {
+ return $img->colorResolve(255.0 * ($intensity ** $gamma), 255, 0);
+ }
+}
diff --git a/web/nms.gathering.org/portkart.pl b/web/nms.gathering.org/portkart.pl
new file mode 100755
index 0000000..1269173
--- /dev/null
+++ b/web/nms.gathering.org/portkart.pl
@@ -0,0 +1,82 @@
+#! /usr/bin/perl
+use CGI;
+use GD;
+use DBI;
+use lib '../../include';
+use nms;
+my $cgi = CGI->new;
+
+my $dbh = nms::db_connect();
+
+GD::Image->trueColor(1);
+$img = GD::Image->new('bg07.png');
+
+my $blk = $img->colorResolve(0, 0, 0);
+
+for my $y (42..236) {
+ my $i = 3.0 * ($y - 236.0) / (42.0 - 237.0);
+ my $clr = get_color($i);
+
+ $img->filledRectangle(12,$y,33,$y+1,$clr);
+}
+
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/3.0, "1 Gbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/3.0, "100 Mbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/3.0, "10 Mbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*3.0/3.0, "1 Mbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 620, "NMS (C) 2005-2007 Tech:Server");
+
+my $q = $dbh->prepare('select switch,port,bytes_in,bytes_out,placement,switchtype from switches natural join placements natural join get_datarate() where switchtype like \'%3100%\'');
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+
+ # for now:
+ # 100kbit/port = all green
+ # 1gbit/port = all red
+
+ my $clr;
+
+ if (defined($ref->{'bytes_in'})) {
+ my $intensity = 0.0;
+ my $traffic = 4.0 * ($ref->{'bytes_in'} + $ref->{'bytes_out'}); # average and convert to bits (should be about the same in practice)
+
+ my $max = 100_000_000_000.0; # 1Gbit
+ my $min = 1_000_000.0; # 1Mbit
+ if ($traffic >= $min) {
+ $intensity = log($traffic / $min) / log(10);
+ $intensity = 4.0 if ($intensity > 4.0);
+ }
+ $clr = get_color($intensity);
+ } else {
+ $clr = $img->colorResolve(0, 0, 255);
+ }
+
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+ my $npo = 48;
+ my $f = ($ref->{'port'} - 1) % 2;
+ my $po = ($ref->{'port'} - 1 - $f)/2;
+ my $h = 2*($2-$4)/$npo;
+ my $w = ($1-$3)/2;
+
+ $img->filledRectangle($3+$w*$f,$4+$po*$h,$3+$w+$w*$f,$4+$h*($po+1),$clr);
+# $img->rectangle($3+$w*$f,$4+$po*$h,$3+$w+$w*$f,$4+$h*($po+1),$blk);
+ $img->rectangle($3,$4,$1,$2,$blk);
+}
+$dbh->disconnect;
+
+print $cgi->header(-type=>'image/png');
+print $img->png;
+
+sub get_color {
+ my $intensity = shift;
+ my $gamma = 1.0/1.90;
+ if ($intensity > 3.0) {
+ return $img->colorResolve(255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma));
+ } elsif ($intensity > 2.0) {
+ return $img->colorResolve(255.0, 255.0 * (($intensity - 2.0) ** $gamma), 255.0 * (($intensity - 2.0) ** $gamma));
+ } elsif ($intensity > 1.0) {
+ return $img->colorResolve(255.0, 255.0 * ((2.0 - $intensity) ** $gamma), 0);
+ } else {
+ return $img->colorResolve(255.0 * ($intensity ** $gamma), 255, 0);
+ }
+}
diff --git a/web/nms.gathering.org/showswitch.pl b/web/nms.gathering.org/showswitch.pl
new file mode 100755
index 0000000..5ed0029
--- /dev/null
+++ b/web/nms.gathering.org/showswitch.pl
@@ -0,0 +1,221 @@
+#! /usr/bin/perl
+use CGI;
+use DBI;
+use Time::HiRes;
+use POSIX ":sys_wait_h";
+use strict;
+use warnings;
+use lib '../../include';
+use nms;
+my $cgi = CGI->new;
+my $switch = $cgi->param('id');
+my $width = $cgi->param('width');
+my $height = $cgi->param('height');
+my @pids = ();
+my $resthtml = "";
+
+$width = 500 unless (defined($width));
+$height = 250 unless (defined($height));
+
+require './mygraph.pl';
+
+my $start = [Time::HiRes::gettimeofday];
+my $dbh = nms::db_connect();
+
+# Fetch the name
+my $ref = $dbh->selectrow_hashref('SELECT sysname FROM switches WHERE switch=?', undef, $switch);
+
+print $cgi->header(-type=>'text/html; charset=utf-8');
+print <<"EOF";
+<html>
+ <head>
+ <title>snmp</title>
+ </head>
+ <body>
+ <h1>Switch $switch ($ref->{'sysname'})</h1>
+EOF
+
+my $q = $dbh->prepare('select port,coalesce(description, \'Port \' || port) as description,extract(epoch from time) as time,bytes_in,bytes_out from switches natural left join portnames natural join polls where time between now() - \'1 day\'::interval and now() and switch=? order by switch,port,time;') or die $dbh->errstr;
+$q->execute($switch) or die $dbh->errstr;
+
+my (@totx, @toty1, @toty2) = ();
+
+my (@x, @y1, @y2) = ();
+my $last_port = -1;
+my $portname = "";
+my $min_x = time;
+my $max_x = time - 86400;
+my ($min_y, $max_y, $prev_time, $prev_in, $prev_out);
+my ($if,$of,$ifv,$ofv);
+my $idx;
+my ($min_ty,$max_ty) = (0, 10_000_000/8);
+
+$prev_time = -1;
+my $last_totx;
+while (my $ref = $q->fetchrow_hashref()) {
+ my $time = $ref->{'time'};
+ my $in = $ref->{'bytes_in'};
+ my $out = $ref->{'bytes_out'};
+ next if ($time == $prev_time);
+
+ if ($ref->{'port'} != $last_port) {
+ if ($last_port != -1) {
+ my $filename = "$switch-$last_port-$width-$height.png";
+
+ # reap children
+ waitpid(-1, WNOHANG);
+
+ my $pid = fork();
+ if ($pid == 0) {
+# write out the graph
+ my $graph = makegraph($width, $height, $min_x, $max_x, $min_y, $max_y, 5);
+ plotseries($graph, \@x, \@y1, 255, 0, 0, $min_x, $max_y);
+ plotseries($graph, \@x, \@y2, 0, 0, 255, $min_x, $max_y);
+
+ open GRAPH, ">img/$filename"
+ or die "img/$filename: $!";
+ print GRAPH $graph->png;
+ close GRAPH;
+ exit;
+ }
+
+ push @pids, $pid;
+
+ $resthtml .= "<div style=\"float: left;\"><h2>$portname</h2>\n";
+ $resthtml .= "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n";
+ }
+
+ # Reset all the variables
+ @x = ();
+ @y1 = ();
+ @y2 = ();
+ ($min_y,$max_y) = (0, 10_000_000/8);
+ $prev_time = $ref->{'time'};
+ $prev_in = $ref->{'bytes_in'};
+ $prev_out = $ref->{'bytes_out'};
+ $last_port = $ref->{'port'};
+ $portname = $ref->{'description'};
+ ($if,$of,$ifv,$ofv) = (0,0,0,0);
+ ($prev_time,$prev_in,$prev_out) = ($time,$in,$out);
+ $idx = 0;
+ $last_totx = undef;
+ next;
+ }
+
+ # Assume overflow (unless the switch has been down for >10 minutes)
+ my ($calc_in, $calc_out) = ($in, $out);
+ if ($in < $prev_in || $out < $prev_out) {
+ if ($prev_in < 4294967296 && $prev_out < 4294967296) {
+ # ick, heuristics
+ if ($prev_time - $time > 600 || ($in + 4294967296 - $prev_in) > 2147483648 || ($out + 4294967296 - $prev_out) > 2147483648) {
+ ($prev_time,$prev_in,$prev_out) = ($time,$in,$out);
+ next;
+ }
+
+ $calc_in += 4294967296 if ($in < $prev_in);
+ $calc_out += 4294967296 if ($out < $prev_out);
+ } else {
+ $prev_in = 0;
+ $prev_out = 0;
+ }
+ }
+
+ # Remove dupes
+ if ($in == $prev_in && $out == $prev_out) {
+ ($prev_time,$prev_in,$prev_out) = ($time,$in,$out);
+ next;
+ }
+
+ # Find the current flow
+ my $if = ($calc_in - $prev_in) / ($time - $prev_time);
+ my $of = ($calc_out - $prev_out) / ($time - $prev_time);
+
+ # Summarize (we don't care about the summed variance for now)
+ $min_x = $time if (!defined($min_x) || $time < $min_x);
+ $max_x = $time if (!defined($max_x) || $time > $max_x);
+ $min_y = $if if (!defined($min_y) || $if < $min_y);
+ $min_y = $of if ($of < $min_y);
+ $max_y = $if if (!defined($max_y) || $if > $max_y);
+ $max_y = $of if ($of > $max_y);
+
+ my $pt = 0.5 * ($time + $prev_time);
+
+ push @x, $pt;
+ push @y1, $if;
+ push @y2, $of;
+
+ while ($idx < $#totx && $pt > $totx[$idx]) {
+ ++$idx;
+ }
+ if ($idx >= $#totx) {
+ push @totx, $pt;
+ push @toty1, $if;
+ push @toty2, $of;
+ ++$idx;
+
+ $min_ty = $if if (!defined($min_ty) || $if < $min_ty);
+ $min_ty = $of if ($of < $min_ty);
+ $max_ty = $if if (!defined($max_ty) || $if > $max_ty);
+ $max_ty = $of if ($of > $max_ty);
+ } else {
+ if (!defined($last_totx) || $last_totx != $idx) {
+ $toty1[$idx] += $if;
+ $toty2[$idx] += $of;
+ }
+ $last_totx = $idx;
+
+ $min_ty = $toty1[$idx] if (!defined($min_ty) || $toty1[$idx] < $min_ty);
+ $min_ty = $toty2[$idx] if ($toty2[$idx] < $min_ty);
+ $max_ty = $toty1[$idx] if (!defined($max_ty) || $toty1[$idx] > $max_ty);
+ $max_ty = $toty2[$idx] if ($toty2[$idx] > $max_ty);
+ }
+
+ ($prev_time,$prev_in,$prev_out) = ($time,$in,$out);
+}
+$dbh->disconnect;
+
+# last graph
+my $filename = "$switch-$last_port-$width-$height.png";
+
+my $pid = fork();
+if ($pid == 0) {
+ my $graph = makegraph($width, $height, $min_x, $max_x, $min_y, $max_y, 5);
+ plotseries($graph, \@x, \@y1, 255, 0, 0, $min_x, $max_y);
+ plotseries($graph, \@x, \@y2, 0, 0, 255, $min_x, $max_y);
+
+ open GRAPH, ">img/$filename"
+ or die "img/$filename: $!";
+ print GRAPH $graph->png;
+ close GRAPH;
+ exit;
+}
+
+push @pids, $pid;
+
+$resthtml .= "<div style=\"float: left;\"><h2>$portname</h2>\n";
+$resthtml .= "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n";
+
+# total graph
+my $graph = makegraph($width, $height, $min_x, $max_x, $min_ty, $max_ty, 5);
+plotseries($graph, \@totx, \@toty1, 255, 0, 0, $min_x, $max_ty);
+plotseries($graph, \@totx, \@toty2, 0, 0, 255, $min_x, $max_ty);
+
+$filename = "$switch-$width-$height.png";
+open GRAPH, ">img/$filename" or die "img/$filename: $!";
+print GRAPH $graph->png;
+close GRAPH;
+
+
+# Wait for all the other graphs to be done
+while (waitpid(-1, 0) != -1) {
+ 1;
+}
+
+print $resthtml;
+
+print "<div style=\"float: left;\"><h2>Total</h2>\n";
+print "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n";
+
+my $elapsed = Time::HiRes::tv_interval($start);
+printf "<p style=\"clear: both;\">Page and all graphs generated in %.2f seconds.</p>\n", $elapsed;
+print "</body>\n</html>\n";
diff --git a/web/nms.gathering.org/slide.html b/web/nms.gathering.org/slide.html
new file mode 100644
index 0000000..046020d
--- /dev/null
+++ b/web/nms.gathering.org/slide.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<html>
+ <body>
+ <iframe id="tgview" style="border: 0; width: 1536px; height: 864px"></iframe>
+
+ <script>
+ (function() {
+ var urls = [
+ 'http://onlineclock.net/',
+ 'http://nms.tg13.gathering.org/dhcpkart.pl',
+ 'http://nms.tg13.gathering.org/nettkart-text.pl',
+ 'http://nms.tg13.gathering.org/nettkart-text.pl',
+ 'http://nms.tg13.gathering.org/uplinkkart.pl',
+ 'http://nms.tg13.gathering.org/uplinktrafikkart.pl',
+ 'http://nms.tg13.gathering.org/apkart.pl',
+ 'http://stats.tg13.gathering.org/'
+ ];
+
+ var view = document.getElementById('tgview');
+ var fload = function( frame, url ) {
+ frame.src = url;
+ };
+
+ var i = 0;
+ (function rotation() {
+ //if ( i != l-1 ) {
+ if ( i != urls.length-1 ) {
+ i++
+ } else {
+ i = 0;
+ }
+ fload( view, urls[i] );
+ setTimeout( arguments.callee, 10000 );
+ })();
+ })();
+ </script>
+ </body>
+</html>
diff --git a/web/nms.gathering.org/smanagement.pl b/web/nms.gathering.org/smanagement.pl
new file mode 100755
index 0000000..c01c52d
--- /dev/null
+++ b/web/nms.gathering.org/smanagement.pl
@@ -0,0 +1,239 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use CGI;
+use DBI;
+use Data::Dumper;
+use Switch;
+use lib '../../include';
+use nms;
+
+# Grab from .htaccess-authentication
+my $user = $ENV{'REMOTE_USER'};
+
+my $dbh = nms::db_connect();
+$dbh->{AutoCommit} = 0;
+
+# Ugly casting, found no other way
+my $sinsert = $dbh->prepare( "INSERT INTO squeue
+ (gid, added, priority, addr, sysname, cmd, author)
+ VALUES(?::text::int, timeofday()::timestamptz, ?::text::int, ?::text::inet, ?, ?, ?)")
+ or die "Could not prepare sinsert";
+my $sgetip = $dbh->prepare("SELECT ip FROM switches WHERE sysname = ?")
+ or die "Could not prepare sgetip";
+my $sgid = $dbh->prepare("SELECT nextval('squeue_group_sequence') as gid");
+my $all_switches = $dbh->prepare("SELECT sysname FROM switches ORDER BY sysname");
+
+sub parse_range($) {
+ my $switches = $_;
+ my @range;
+
+ my @rangecomma = split(/\s*,\s*/, $switches);
+ foreach (@rangecomma) {
+ my ($first, $last) = $_ =~ /(e\d+\-(?:sw)?[123456])\s*\-\s*(e\d+\-(?:sw)?[123456])?/;
+ if (!defined($first) && $_ =~ /e\d+\-(sw)?[123456]/) {
+ $first = $_;
+ }
+ if (!defined($first)) {
+ print "<font color=\"red\">Parse error in: $_</font><br>\n";
+ next;
+ }
+ my ($rowstart, $placestart) = $first =~ /e(\d+)\-(?:sw)?([123456])/;
+ if (!defined($rowstart) || !defined($placestart)) {
+ print "<font color=\"red\">Parse error in: $_</font><br>\n";
+ next;
+ }
+ my ($rowend, $placeend);
+ if (!defined($last)) {
+ $rowend = $rowstart;
+ $placeend = $placestart;
+ }
+ else {
+ ($rowend, $placeend) = $last =~ /e(\d+)\-(?:sw)?([123456])/;
+ }
+ if (!defined($rowend) || !defined($placeend)) {
+ print "<font color=\"red\">Parse error in: $_</font><br>\n";
+ next;
+ }
+ #print "e $rowstart - $placestart to e $rowend - $placeend <br>\n";
+ for (my $i = $rowstart; $i <= $rowend; $i++) {
+ my $dostart;
+ if ($rowstart != $i) {
+ $dostart = 1;
+ }
+ else {
+ $dostart = $placestart;
+ }
+ for (my $j = $dostart; $j <= 6; $j++) {
+ last if ($i == $rowend && $j > $placeend);
+ push(@range, "e$i-$j");
+ }
+ }
+ }
+# foreach (@range) {
+# print ":: $_<br>\n";
+# }
+ return @range;
+}
+
+sub get_addr_from_switchnum($) {
+ my ($sysname) = @_;
+
+ $sgetip->execute($sysname);
+ if ($sgetip->rows() < 1) {
+ print "Could not get the ip for: ".$sysname;
+ return undef;
+ }
+ my $row = $sgetip->fetchrow_hashref();
+ return $row->{'ip'};
+}
+
+my $cgi = new CGI;
+
+print $cgi->header(-type=>'text/html; charset=utf-8');
+
+print << "EOF";
+<html>
+ <head>
+ <title>Switch managment</title>
+ </head>
+ <body>
+ <p>Du er logget inn som: $user</p>
+ <form method="POST" action="smanagement.pl">
+ <table>
+ <tr>
+ <td>Alle switchene</td>
+ <td><input type="radio" name="rangetype" value="all" /></td>
+ <td></td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Switch</td>
+ <td><input type="radio" checked name="rangetype" value="switch" /></td>
+ <td><input type="text" name="range" /></td>
+ <td>e1-2, e3-3 - e10-2</td>
+ </tr>
+ <tr>
+ <td>Regexp</td>
+ <td><input type="radio" name="rangetype" value="regexp" /></td>
+ <td><input type="text" name="regexp" /></td>
+ <td>Regulært uttrykk</td>
+ </tr>
+ <tr>
+ <td>Rad</td>
+ <td><input type="radio" name="rangetype" value="row" /></td>
+ <td><input type="text" name="range" /></td>
+ <td>1,3-5 (Disabled)</td>
+ </tr>
+ <tr>
+ <td><hr /></td>
+ <td><hr /></td>
+ <td><hr /></td>
+ <td><hr /></td>
+ </tr>
+ <tr>
+ <td>Prioritet</td>
+ <td></td>
+ <td>
+ <select name="priority">
+ <option value="1">1 (lavest)</option>
+ <option value="2">2</option>
+ <option selected value="3">3</option>
+ <option value="4">4</option>
+ <option value="5">5 (høyest)</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td>Kommando(er):</td>
+ <td></td>
+ <td><textarea name="cmd" cols="80" rows="24"></textarea></td>
+ <td>En kommando per linje. Linjer som begynner med ! sørger for at nms ikke venter på normal prompt, men fyrer av gårde neste linje umiddelbart. Kjekt for kommandoer av typen "!save\\nY"</td>
+ </td>
+ <tr>
+ <td><hr /></td>
+ <td><hr /></td>
+ <td><hr /></td>
+ <td><hr /></td>
+ </tr>
+ </table>
+ <input type="submit" value="Execute!" /><br />
+ </form>
+EOF
+
+print "<br />\n";
+
+my @switches = ();
+switch ($cgi->param('rangetype')) {
+ case 'all' {
+ print "Sender `".$cgi->param('cmd')."` til alle switchene<br />";
+ @switches = ();
+ $all_switches->execute();
+ while (my $ref = $all_switches->fetchrow_hashref) {
+ push @switches, $ref->{'sysname'};
+ }
+ }
+ case 'switch' {
+# print "Sender `".$cgi->param('cmd')."` til switchene `"
+# .$cgi->param('range')."`.<br />";
+ $_ = $cgi->param('range');
+ @switches = parse_range($_);
+ }
+ case 'regexp' {
+ @switches = ();
+ $all_switches->execute();
+ while (my $ref = $all_switches->fetchrow_hashref) {
+ push @switches, $ref->{'sysname'} if $ref->{'sysname'} =~ $cgi->param('regexp');
+ }
+ }
+ case 'row' {
+# print "Sender `".$cgi->param('cmd')."` til radene `"
+# .$cgi->param('range')."`.<br />";
+# print "This function does not work yet.";
+# $_ = $cgi->param('range');
+# @switches = &parse_row_range($_);
+# @switches = ();
+ print "<font color=\"red\">Slått av!</font>\n";
+ }
+}
+
+my $gid;
+if (@switches > 0) {
+ $sgid->execute();
+ my $row = $sgid->fetchrow_hashref();
+ $gid = $row->{gid};
+}
+
+my $pri = $cgi->param('priority');
+
+print "<pre>\n";
+foreach my $switch (@switches) {
+ my $addr = get_addr_from_switchnum($switch);
+ if (!defined($addr)) {
+ next;
+ }
+ my $cmd = $cgi->param('cmd');
+ print "$switch got addr $addr <br>\n";
+ print "Queuing commands for $switch:\n";
+ my $result = $sinsert->execute($gid, $pri, $addr, $switch, $cmd, $user);
+ if (!$result) {
+ print "\t<font color=\"red\">"
+ ."Could not execute query."
+ ."</font>\n";
+ print "\t".$dbh->errstr."\n";
+ }
+ else {
+ print "\tQueued: $cmd\n";
+ }
+ print "\n";
+}
+$dbh->commit;
+if (defined($gid)) {
+ print "<a href=\"sshow.pl?action=showgid&gid=".$gid."\">Vis resultat</a>\n";
+}
+print "</pre>\n";
+
+print << "EOF";
+ </body>
+</html>
+EOF
diff --git a/web/nms.gathering.org/ssendfile.pl b/web/nms.gathering.org/ssendfile.pl
new file mode 100755
index 0000000..ec2ebb8
--- /dev/null
+++ b/web/nms.gathering.org/ssendfile.pl
@@ -0,0 +1,48 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use lib '../../include';
+use POSIX;
+
+my $delaytime = 30;
+my $poll_frequency = 60;
+
+sub mylog {
+ my $msg = shift;
+ my $time = POSIX::ctime(time);
+ $time =~ s/\n.*$//;
+ printf STDERR "[%s] %s\n", $time, $msg;
+}
+
+if ($#ARGV != 1) {
+ die("Error in arguments passed\n".
+ "./ssendfile.pl addr configfile\n");
+}
+
+my $conn = nms::switch_connect($ARGV[0]);
+if (!defined($conn)) {
+ die("Could not connect to switch.\n");
+}
+
+open(CONFIG, $ARGV[1]);
+while (<CONFIG>) {
+ my $cmd = $_;
+ $cmd =~ s/[\r\n]+//g;
+ print "Executing: `$cmd`\n";
+# if ($cmd =~ /ip ifconfig swif0 (\d{1-3}\.\d{1-3}\.\d{1-3}\.\d{1-3})/) {
+# print "New ip: $1\n";
+# $conn->cmd( String => $cmd,
+# Timeout => 3);
+# $conn = nms::switch_connect($1);
+# if (!defined($conn)) {
+# die "Could not connect to new ip: $1\n";
+# }
+# }
+# else {
+ my @data = nms::switch_exec($cmd, $conn);
+ foreach my $line (@data) {
+ $line =~ s/[\r\n]+//g;
+ print "$line\n";
+ }
+# }
+}
diff --git a/web/nms.gathering.org/sshow.pl b/web/nms.gathering.org/sshow.pl
new file mode 100755
index 0000000..f406b69
--- /dev/null
+++ b/web/nms.gathering.org/sshow.pl
@@ -0,0 +1,257 @@
+#!/usr/bin/perl
+use lib '../../include';
+use nms;
+
+use warnings;
+use strict;
+use Switch;
+use CGI;
+use DBI;
+
+# Grab from .htaccess-authentication
+my $user = $ENV{'REMOTE_USER'};
+
+my $dbh = nms::db_connect();
+$dbh->{AutoCommit} = 0;
+
+my $sgetdone = $dbh->prepare(
+"SELECT *
+FROM squeue
+WHERE processed = 't'
+ORDER BY updated DESC, sysname
+LIMIT ?::text::int")
+ or die "Could not prepare sgetdone";
+
+my $sgetdonegid = $dbh->prepare(
+"SELECT *
+FROM squeue
+WHERE processed = 't' AND gid = ?::text::int
+ORDER BY updated DESC, sysname")
+ or die "Could not prepare sgetdonegid";
+
+my $slistdonegid = $dbh->prepare(
+"SELECT DISTINCT gid, cmd, author, added
+FROM squeue
+WHERE processed = 't'
+ORDER BY gid")
+ or die "Could not prepare slistdonegid";
+
+my $slistprocgid = $dbh->prepare(
+"SELECT DISTINCT gid, cmd, author, added
+FROM squeue
+WHERE processed = 'f'
+ORDER BY gid")
+ or die "Could not prepare slistdonegid";
+
+my $sgetgid = $dbh->prepare(
+"SELECT *
+FROM squeue
+WHERE gid = ?")
+ or die "Could not prepare sgetgid";
+
+my $sgetprocessing = $dbh->prepare(
+"SELECT *
+FROM squeue
+WHERE processed = 'f'
+ORDER BY updated DESC, gid, sysname")
+ or die "Could not prepare sgetdone";
+
+my $sgetnoconnect = $dbh->prepare(
+"SELECT *
+FROM squeue
+WHERE result = 'Could not connect to switch, delaying...'")
+ or die "Could not prepare sgetnoconnect";
+
+my $sdisablegid = $dbh->prepare("
+UPDATE squeue SET disabled = 't'
+WHERE gid = ?::text::int")
+ or die "Could not prepare sdisablegid";
+my $senablegid = $dbh->prepare("
+UPDATE squeue SET disabled = 'f'
+WHERE gid = ?::text::int")
+ or die "Could not prepare sdisablegid";
+
+
+my $cgi = new CGI;
+
+print $cgi->header(-type=>'text/html; charset=utf-8');
+
+print << "EOF";
+<html>
+ <head>
+ <title>Switch managment</title>
+ </head>
+ <body>
+ <p>Du er logget inn som: $user</p>
+ <form method="POST" action="sshow.pl">
+ <p>
+ Vis <input type="text" name="count" size="4" value="10" /> siste<br />
+ Vis: <select name="action" />
+ <option value="listgid">Grupper</option>
+ <option value="done">Ferdige</option>
+ <option value="processing">I kø</option>
+ </select>
+ <input type="submit" value="Vis" /><br />
+ </p>
+ </form>
+ <br />
+EOF
+
+my $limit = $cgi->param('count');
+if (!defined($limit)) {
+ $limit = 10;
+}
+my $action = $cgi->param('action');
+if (!defined($action)) {
+ $action = 'listgid';
+}
+
+if (defined($cgi->param('agid'))) {
+ my $gid = $cgi->param('gid');
+ if (!defined($gid)) {
+ print "<font color=\"red\">Du har ikke valgt en gid å slette.</font>\n";
+ print "<p>gid: ".$cgi->param('gid')." har blitt disablet.\n";
+ }
+ else {
+ $senablegid->execute($gid);
+ print "<p>gid: ".$cgi->param('gid')." har blitt enablet.\n";
+ }
+ $dbh->commit();
+}
+
+if ($action eq 'noconnect') {
+ print "<h3>Kunne ikke koble til disse switchene:</h3>\n";
+ $sgetnoconnect->execute();
+ print "<pre>\n";
+ while ((my $row = $sgetnoconnect->fetchrow_hashref())) {
+ print "$row->{'sysname'} : $row->{'cmd'} : Added: $row->{'added'} : Updated: $row->{'updated'}\n";
+ }
+ print "</pre>\n";
+}
+
+if ($action eq 'listgid') {
+ print "<pre>\n";
+ print "<a href=\"sshow.pl?action=noconnect\" />Kunne ikke koble til</a>\n\n\n";
+ print "<b>Ferdige:</b>\n";
+ $slistdonegid->execute();
+ my ($gid, $author);
+ $gid = -1;
+ while ((my $row = $slistdonegid->fetchrow_hashref())) {
+ $author = $row->{author};
+ if ($gid != $row->{gid}) {
+ $gid = $row->{gid};
+ print "GID: <a href=\"sshow.pl?action=showgid&gid=$gid\">$gid</a>\n";
+ print "Author: $author\n";
+ print "Added: ".$row->{added}."\n";
+ }
+ my $cmd = $row->{cmd};
+ print "\t$cmd\n";
+ }
+ print "\n\n";
+ print "<b>I kø:</b>\n";
+ $slistprocgid->execute();
+ $gid = -1;
+ while ((my $row = $slistprocgid->fetchrow_hashref())) {
+ $author = $row->{author};
+ if ($gid != $row->{gid}) {
+ $gid = $row->{gid};
+ print "GID: <a href=\"sshow.pl?action=showgid&gid=$gid\">$gid</a>\n";
+ print "Author: $author\n";
+ print "Added: ".$row->{added}."\n";
+ }
+ my $cmd = $row->{cmd};
+ print "\t$cmd\n";
+ }
+ $dbh->commit();
+ print "</pre>\n";
+}
+
+if ($action eq 'showgid') {
+ print "<pre>\n";
+ $sgetgid->execute($cgi->param('gid'));
+ my $row = $sgetgid->fetchrow_hashref();
+ print "GID: ".$row->{gid}."\n";
+ print "Author: ".$row->{author}."\n";
+ do {
+ print " <b>Name: ".$row->{sysname}." Addr: ".$row->{addr}."</b>\n";
+ print " `<b>".$row->{cmd}."`</b>\n";
+ print " <i>Added: ".$row->{added}." executed ".$row->{updated}."</i>\n";
+ my $data = $row->{result};
+ if (!defined($data)) {
+ $data = "Not executed yet!";
+ }
+ my @lines = split(/[\n\r]+/, $data);
+ foreach my $line (@lines) {
+ print "\t$line\n";
+ }
+ } while (($row = $sgetgid->fetchrow_hashref()));
+ print "</pre>\n";
+}
+
+if ($action eq 'done') {
+ print "<h3>Done</h3>\n";
+ print "<pre>\n";
+
+ my $squery;
+ if (defined($cgi->param('gid'))) {
+ my $gid = $cgi->param('gid');
+ $sgetdonegid->execute($gid);
+ $squery = $sgetdonegid;
+ }
+ else {
+ $sgetdone->execute($limit);
+ $squery = $sgetdone;
+ }
+ my $sysname = '';
+ while (my $row = $squery->fetchrow_hashref()) {
+ if ($sysname ne $row->{'sysname'}) {
+ $sysname = $row->{'sysname'};
+ print "$sysname (".$row->{addr}."):\n";
+ }
+ print " Author: ".$row->{author}."\n";
+ print " Cmd: ".$row->{cmd}."\n";
+ print " Added: ".$row->{added}." Updated: ".$row->{updated}."\n";
+ print " gID: ".$row->{gid}."\n";
+ my @result = split(/[\n\r]+/, $row->{result});
+ foreach (@result) {
+ print "\t".$_."\n";
+ }
+ print "\n";
+ }
+ $dbh->commit();
+ print "</pre>\n";
+}
+elsif ($action eq 'processing') {
+ print "<h3>Processing</h3>\n";
+ print "<pre>\n";
+ $sgetprocessing->execute();
+ while (my $row = $sgetprocessing->fetchrow_hashref()) {
+ my $sysname = $row->{'sysname'};
+ print "$sysname (".$row->{addr}."):\n";
+ print " Author: ".$row->{author}."\n";
+ print " Cmd: ".$row->{cmd}."\n";
+ my $updated;
+ if (defined($row->{updated})) { $updated = $row->{updated}; }
+ else { $updated = 'never'; }
+ print " Added: ".$row->{added}." Updated: ".$updated."\n";
+ print " Disabled: ".$row->{disabled}."\n";
+ print " Locked: ".$row->{locked}."\n";
+ print " gID: ".$row->{gid};
+ print " <form action=\"sshow.pl\" methos=\"POST\">";
+ print "<input type=\"hidden\" name=\"gid\" value=\"".$row->{gid}."\">";
+ print "<input type=\"hidden\" name=\"action\" value=\"processing\">";
+ if ($row->{disabled} == 0) {
+ print "<input type=\"submit\" name=\"agid\" value=\"Disable\">\n";
+ }
+ else {
+ print "<input type=\"submit\" name=\"agid\" value=\"Enable\">\n";
+ }
+ }
+ $dbh->commit();
+ print "</pre>\n";
+}
+
+print << "EOF";
+ </body>
+</html>
+EOF
diff --git a/web/nms.gathering.org/stromkart.pl b/web/nms.gathering.org/stromkart.pl
new file mode 100755
index 0000000..0aef634
--- /dev/null
+++ b/web/nms.gathering.org/stromkart.pl
@@ -0,0 +1,69 @@
+#! /usr/bin/perl
+use CGI qw(fatalsToBrowser);
+use GD;
+use DBI;
+use lib '../../include';
+use nms;
+use strict;
+use warnings;
+my $cgi = CGI->new;
+
+#my $greentimeout = 7200;
+my $greentimeout = 15*60;
+my $maxtimeout = $greentimeout*9;
+
+my $dbh = nms::db_connect();
+
+GD::Image->trueColor(1);
+my $img = GD::Image->new('bg07.png');
+
+my $blk = $img->colorResolve(0, 0, 0);
+
+$img->string(gdMediumBoldFont,0,0,"Switch uplink status",$blk);
+$img->string(gdSmallFont,0,20,"Number of ports with activity",$blk);
+
+my $red = $img->colorResolve(255, 0, 0);
+my $yel = $img->colorResolve(255, 255, 0);
+my $grn = $img->colorResolve(0, 255, 0);
+my $wht = $img->colorResolve(255, 255, 255);
+my $gry = $img->colorResolve(127, 127, 127);
+
+my $q = $dbh->prepare('select switch,sysname,(select placement from placements where placements.switch=switches.switch) as placement,count((bytes_in > 0 and bytes_out > 0) or null) as active_ports,(max(last_poll_time) >= current_timestamp - interval \'2 minutes\') as fresh from switches natural left join get_current_datarate() natural join placements where switchtype like \'dlink3100%\' group by switch,sysname');
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ my $ports = $ref->{'active_ports'};
+ my $sysname = $ref->{'sysname'};
+ my $clr;
+ if ($ports < 5) {
+ $clr = $red;
+ } else {
+ if (!$ref->{'fresh'}) {
+ $clr = $yel;
+ } else {
+ $clr = $grn;
+ }
+ }
+
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+ $img->filledRectangle($3,$4,$1,$2,$clr);
+ $img->rectangle($3,$4,$1,$2,$blk);
+
+ my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4);
+ my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1;
+ while (length($sysname) * 6 > $max_textlen) {
+ # Try to abbreviate sysname if it is too long for the box
+ $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last;
+ }
+ if (($x2-$x1) > ($y2-$y1)) {
+ $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk);
+ } else {
+ $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk);
+ }
+}
+$dbh->disconnect;
+
+if (!defined($ARGV[0])) {
+ print $cgi->header(-type=>'image/png',
+ -refresh=>'10; ' . CGI::url());
+}
+print $img->png;
diff --git a/web/nms.gathering.org/uplinkkart-text.pl b/web/nms.gathering.org/uplinkkart-text.pl
new file mode 100755
index 0000000..de91e92
--- /dev/null
+++ b/web/nms.gathering.org/uplinkkart-text.pl
@@ -0,0 +1,38 @@
+#! /usr/bin/perl
+use CGI;
+use DBI;
+use lib '../../include';
+use nms;
+my $cgi = CGI->new;
+
+my $dbh = nms::db_connect();
+print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'10; ' . CGI::url());
+
+print <<"EOF";
+<html>
+ <head>
+ <title>Uplinkkart</title>
+ </head>
+ <body>
+ <map name="switches">
+EOF
+
+my $q = $dbh->prepare("SELECT * FROM switches NATURAL JOIN placements WHERE switchtype = 'dlink3100'");
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+
+ my $ttext = 'FIXME: Put something here';
+ printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" href=\"switchdiag.pl?id=%u\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n",
+ $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'},
+ $ttext, $ref->{'sysname'}, $ttext;
+}
+$dbh->disconnect;
+
+print <<"EOF";
+ </map>
+
+ <p><img src="uplinkkart.pl" usemap="#switches" /></p>
+ </body>
+</html>
+EOF
diff --git a/web/nms.gathering.org/uplinkkart.pl b/web/nms.gathering.org/uplinkkart.pl
new file mode 100755
index 0000000..32581a6
--- /dev/null
+++ b/web/nms.gathering.org/uplinkkart.pl
@@ -0,0 +1,70 @@
+#! /usr/bin/perl
+use CGI qw(fatalsToBrowser);
+use GD;
+use DBI;
+use lib '../../include';
+use nms;
+use strict;
+use warnings;
+my $cgi = CGI->new;
+
+#my $greentimeout = 7200;
+my $greentimeout = 15*60;
+my $maxtimeout = $greentimeout*9;
+
+my $dbh = nms::db_connect();
+
+GD::Image->trueColor(1);
+my $img = GD::Image->new('bg07.png');
+
+my $blk = $img->colorResolve(0, 0, 0);
+
+$img->string(gdMediumBoldFont,0,0,"Switch uplink status",$blk);
+$img->string(gdSmallFont,0,20,"Number of ports with activity",$blk);
+
+my $red = $img->colorResolve(255, 0, 0);
+my $yel = $img->colorResolve(255, 255, 0);
+my $grn = $img->colorResolve(0, 255, 0);
+my $blu = $img->colorResolve(0, 0, 255);
+my $wht = $img->colorResolve(255, 255, 255);
+my $gry = $img->colorResolve(127, 127, 127);
+
+my @palette = ( $blu, $red, $yel, $grn, $wht );
+
+for my $ports (0..4) {
+ my $y = 60 + 20 * (4 - $ports);
+ $img->filledRectangle(20, $y, 30, $y + 10, $palette[$ports]);
+ $img->rectangle(20, $y, 30, $y + 10, $blk);
+ $img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, $y + 10, $ports);
+}
+
+my $q = $dbh->prepare('select switch,sysname,(select placement from placements where placements.switch=switches.switch) as placement,count((bytes_in > 0 and bytes_out > 0) or null) as active_ports from switches natural left join get_current_datarate() natural join placements where port between 45 and 48 and switchtype like \'dlink3100%\' group by switch,sysname');
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ my $ports = $ref->{'active_ports'};
+ my $sysname = $ref->{'sysname'};
+ my $clr = $palette[$ports];
+
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+ $img->filledRectangle($3,$4,$1,$2,$clr);
+ $img->rectangle($3,$4,$1,$2,$blk);
+
+ my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4);
+ my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1;
+ while (length($sysname) * 6 > $max_textlen) {
+ # Try to abbreviate sysname if it is too long for the box
+ $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last;
+ }
+ if (($x2-$x1) > ($y2-$y1)) {
+ $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk);
+ } else {
+ $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk);
+ }
+}
+$dbh->disconnect;
+
+if (!defined($ARGV[0])) {
+ print $cgi->header(-type=>'image/png',
+ -refresh=>'10; ' . CGI::url());
+}
+print $img->png;
diff --git a/web/nms.gathering.org/uplinktrafikkart.pl b/web/nms.gathering.org/uplinktrafikkart.pl
new file mode 100755
index 0000000..32869b3
--- /dev/null
+++ b/web/nms.gathering.org/uplinktrafikkart.pl
@@ -0,0 +1,90 @@
+#! /usr/bin/perl
+use CGI qw(fatalsToBrowser);
+use GD;
+use DBI;
+use lib '../../include';
+use nms;
+use strict;
+use warnings;
+my $cgi = CGI->new;
+
+#my $greentimeout = 7200;
+my $greentimeout = 15*60;
+my $maxtimeout = $greentimeout*9;
+
+my $dbh = nms::db_connect();
+
+GD::Image->trueColor(1);
+my $img = GD::Image->new('bg07.png');
+
+my $blk = $img->colorResolve(0, 0, 0);
+
+for my $y (42..236) {
+ my $i = 2.0 * ($y - 236.0) / (42.0 - 237.0);
+ my $clr = get_color($i);
+
+ $img->filledRectangle(12, $y, 33, $y+1, $clr);
+}
+
+$img->string(gdMediumBoldFont,0,0,"Switch uplink traffic",$blk);
+$img->string(gdSmallFont,0,20,"max of bytes in/out",$blk);
+
+my $red = $img->colorResolve(255, 0, 0);
+my $yel = $img->colorResolve(255, 255, 0);
+my $grn = $img->colorResolve(0, 255, 0);
+my $wht = $img->colorResolve(255, 255, 255);
+
+$img->rectangle(12,42,33,236,$blk);
+
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/2.0, "4 Gbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/2.0, "2 Gbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/2.0, "1 Gbit/sec");
+$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 700, "NMS (C) 2005-2012 Tech:Server");
+
+my $q = $dbh->prepare('select switch,sysname,(select placement from placements where placements.switch=switches.switch) as placement,greatest(sum(bytes_in),sum(bytes_out)) as traffic from switches natural left join get_current_datarate() natural join placements where port between 45 and 48 and switchtype like \'dlink3100%\' group by switch,sysname');
+$q->execute();
+while (my $ref = $q->fetchrow_hashref()) {
+ my $traffic = $ref->{'traffic'} * 8.0; # convert to bits
+ my $sysname = $ref->{'sysname'};
+
+ my $max = 4_000_000_000.0; # 2Gbit
+ my $min = 1_000_000_000.0; # 1Gbit
+ $traffic = $max if ($traffic > $max);
+ $traffic = $min if ($traffic < $min);
+ my $intensity = log($traffic / $min) / log(2);
+ my $clr = get_color($intensity);
+
+ $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/;
+ $img->filledRectangle($3,$4,$1,$2,$clr);
+ $img->rectangle($3,$4,$1,$2,$blk);
+
+ my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4);
+ my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1;
+ while (length($sysname) * 6 > $max_textlen) {
+ # Try to abbreviate sysname if it is too long for the box
+ $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last;
+ }
+ if (($x2-$x1) > ($y2-$y1)) {
+ $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk);
+ } else {
+ $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk);
+ }
+}
+$dbh->disconnect;
+
+if (!defined($ARGV[0])) {
+ print $cgi->header(-type=>'image/png',
+ -refresh=>'10; ' . CGI::url());
+}
+print $img->png;
+
+sub get_color {
+ my $intensity = shift;
+ my $gamma = 1.0/1.90;
+ if ($intensity > 1.0) {
+ $intensity -= 1.0;
+ return $img->colorResolve(255.0, 255.0 * ($intensity ** $gamma), 255.0 * ($intensity ** $gamma));
+ } else {
+ return $img->colorResolve(255.0 * ($intensity ** $gamma), 255.0 * (1.0 - ($intensity ** $gamma)), 0);
+ }
+}