Index: ossp-pkg/flow2rrd/flow2rrd.cfg RCS File: /v/ossp/cvs/ossp-pkg/flow2rrd/flow2rrd.cfg,v rcsdiff -q -kk '-r1.1' '-r1.2' -u '/v/ossp/cvs/ossp-pkg/flow2rrd/flow2rrd.cfg,v' 2>/dev/null --- flow2rrd.cfg 2004/12/23 10:24:02 1.1 +++ flow2rrd.cfg 2004/12/23 21:08:32 1.2 @@ -3,7 +3,7 @@ ## # Round-Robin Database -Database /tmp/flow2rrd.rrd; +Database /var/tmp/flow2rrd.rrd; # Protocol Definitions Protocol icmp 1; Index: ossp-pkg/flow2rrd/flow2rrd.pl RCS File: /v/ossp/cvs/ossp-pkg/flow2rrd/flow2rrd.pl,v rcsdiff -q -kk '-r1.1' '-r1.2' -u '/v/ossp/cvs/ossp-pkg/flow2rrd/flow2rrd.pl,v' 2>/dev/null --- flow2rrd.pl 2004/12/23 10:24:02 1.1 +++ flow2rrd.pl 2004/12/23 21:08:32 1.2 @@ -1,4 +1,4 @@ -#!/usr/lpkg/bin/perl +#!/usr/opkg/bin/perl ## ## flow2rrd -- store NetFlow data in Round-Robin Database (RRD) ## Copyright (c) 2004 Ralf S. Engelschall @@ -29,7 +29,8 @@ # fixed program information my $my = { - -progname => 'flow2rrd', + -progname => 'OSSP flow2rrd', + -proghome => 'http://www.ossp.org/pkg/tool/flow2rrd/', -progvers => '0.1.0', -progdate => '20-Dec-2004', }; @@ -570,10 +571,10 @@ push(@args, '--base', 1024); push(@args, '--x-grid', "HOUR:1:DAY:1:DAY:1:0:%d-%b-%Y"); push(@args, '--vertical-label', 'Bit/s'); - push(@args, '--color', 'CANVAS#ffffff'); - push(@args, '--color', 'BACK#e0e0e0'); - push(@args, '--color', 'SHADEA#f8f8f8'); - push(@args, '--color', 'SHADEB#999999'); + push(@args, '--color', 'CANVAS#f0f0ff'); + push(@args, '--color', 'BACK#e0e0f0'); + push(@args, '--color', 'SHADEA#e5e5f5'); + push(@args, '--color', 'SHADEB#d0d0e0'); push(@args, '--color', 'GRID#cccccc'); push(@args, '--color', 'MGRID#000000'); push(@args, '--color', 'FONT#000000'); @@ -583,7 +584,6 @@ push(@args, @def); push(@args, @cdef); push(@args, @draw); - print STDERR join(" ", @args)."\n"; my ($rrd_averages, $rrd_xsize, $rrd_ysize) = RRDs::graph(@args); my $err = RRDs::error(); die "failed to generate graph from RRD file: $err" if (defined($err)); @@ -650,10 +650,10 @@ push(@args, '--base', 1024); push(@args, '--x-grid', "HOUR:1:DAY:1:DAY:1:0:%d-%b-%Y"); push(@args, '--vertical-label', 'Bit/s'); - push(@args, '--color', 'CANVAS#ffffff'); - push(@args, '--color', 'BACK#e0e0e0'); - push(@args, '--color', 'SHADEA#f8f8f8'); - push(@args, '--color', 'SHADEB#999999'); + push(@args, '--color', 'CANVAS#f0f0ff'); + push(@args, '--color', 'BACK#e0e0f0'); + push(@args, '--color', 'SHADEA#e5e5f5'); + push(@args, '--color', 'SHADEB#d0d0e0'); push(@args, '--color', 'GRID#cccccc'); push(@args, '--color', 'MGRID#000000'); push(@args, '--color', 'FONT#000000'); @@ -663,7 +663,6 @@ push(@args, @def); push(@args, @cdef); push(@args, @draw); - print STDERR join(" ", @args)."\n"; my ($rrd_averages, $rrd_xsize, $rrd_ysize) = RRDs::graph(@args); my $err = RRDs::error(); die "failed to generate graph from RRD file: $err" if (defined($err)); @@ -678,19 +677,117 @@ if ($opt->{-cgi}) { my $cgi = new CGI; - if (defined(my $graph = $cgi->param("graph"))) { + # error handler + $SIG{__DIE__} = sub { + my ($msg) = @_; + my $hint = ''; + if ($msg =~ m|line\s+(\d+)|) { + my $line = $1; + my $io = new IO::File "<$0"; + my @code = $io->getlines(); + $io->close(); + my $i = -1; + $hint = join("", map { s/^/sprintf("%d: ", $line+$i++)/se; $_; } @code[$line-2..$line]); + } + print STDOUT + "Content-Type: text/html; charset=ISO-8859-1\n" . + "\n" . + "\n" . + " \n" . + " OSSP flow2rrd: ERROR\n" . + " \n" . + " \n" . + "

OSSP flow2rrd: ERROR

\n" . + "

\n" . + " \n" . + " $msg
\n" . + "
\n" . + "

\n$hint
\n" . + " \n" . + "\n"; + exit(0); + }; + + if (defined($cgi->param("css"))) { + # + # output Cascading Style Sheet (CSS) + # + + my $css = q{ + body { + background: #c0c0c0; + color: #ffffff; + font-family: helvetica,arial,tahoma,verdana,sans-serif; + } + TABLE.flow2rrd { + background: #000000; + border: 2px solid #000000; + } + TABLE.flow2rrd TD.header { + color: #ffffff; + font-family: tahoma,helvetica,arial,tahoma,verdana,sans-serif; + font-weight: bold; + font-size: 200%; + padding: 4px; + text-align: center; + } + TABLE.flow2rrd TD.header A { + text-decoration: none; + color: #ffffff; + } + TABLE.flow2rrd TD.footer { + color: #ffffff; + font-family: tahoma,helvetica,arial,tahoma,verdana,sans-serif; + padding: 4px; + text-align: center; + } + TABLE.flow2rrd TD.footer A { + text-decoration: none; + font-weight: bold; + color: #ffffff; + } + TABLE.flow2rrd TABLE.explore TD.toolbar { + background: #333333; + padding: 10px; + } + TABLE.flow2rrd TABLE.explore TD.toolbar INPUT.textfield { + background: #333333; + color: #ffffff; + border: 0px; + border-bottom: 1px solid #999999; + } + TABLE.flow2rrd TABLE.explore TD.toolbar INPUT.submit { + background: #666666; + color: #ffffff; + margin-top: 10px; + border: 1px solid #999999; + font-weight: bold; + width: 100%; + } + }; + + # send out page + $css =~ s|^ ||mg; + print STDOUT $cgi->header( + -type => 'text/css', + -content_length => length($css), + -expires => '+5m' + ) . $css; + } + elsif (defined(my $graph = $cgi->param("graph"))) { # # output graph image # # prepare graph generation - my (undef, $tmpfile) = mkstemp(($ENV{'TMPDIR'} || '/tmp') . "/flow2rrd.tmp"); - $graph =~ s|\@|\@$tmpfile|s; + my (undef, $tmpfile) = mkstemp(($ENV{'TMPDIR'} || '/tmp') . "/flow2rrd.XXXXXX"); + $graph =~ s|\@|\@$tmpfile:|s; # generate graph image + #die "$0 --graph $graph"; my $rc = system("$0 --graph $graph"); - if ($rc != 0 or not -s $tmpfile) { - die "failed to generate graph image"; + if ($rc != 0) { # or not -s $tmpfile) { + die "failed to generate graph image: $!"; } # read graph image @@ -708,30 +805,242 @@ # cleanup unlink($tmpfile) } - else { + elsif (defined(my $explore = $cgi->param("explore"))) { # - # output HTML page + # output HTML page: EXPLORE A GRAPH # - # generate HTML page + # generate HTML page diversion my $html = new String::Divert; $html->overload(1); - $html .= "\n" . - " \n" . - " " . $html->folder("head") . - " \n" . - " \n" . - " " . $html->folder("body") . - " \n" . - "\n"; + + $html .= + "\n" . + " \n" . + " " . $html->folder("head") . + " \n" . + " \n" . + " " . $html->folder("body") . + " \n" . + "\n"; + + $html >> "head"; + $html .= "url(-relative => 1)."?css=1\">\n"; + $html << 1; + $html >> "body"; - $html .= "foo\n"; + $html .= "\n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= "
\n"; + $html .= " " . $html->folder("header"); + $html .= "
\n"; + $html .= " " . $html->folder("canvas"); + $html .= "
\n"; + $html .= " " . $html->folder("footer"); + $html .= "
\n"; + $html << 1; + + $html >> "header"; + $html .= "url(-relative => 1)."\">Real-Time Network Statistics"; + $html << 1; + $html >> "footer"; + $html .= "{-proghome}\">$my->{-progname} $my->{-progvers} ($my->{-progdate})"; $html << 1; + + my $width = ($cgi->param("width") || "800"); + my $height = ($cgi->param("height") || "200"); + my $start = ($cgi->param("start") || "-48h"); + my $end = ($cgi->param("end") || "now"); + my $ulimit = ($cgi->param("ulimit") || "0"); + my $llimit = ($cgi->param("llimit") || "0"); + + $html >> "canvas"; + $html .= $cgi->start_form( + -method => "POST", + -action => $cgi->url(-relative => 1) . "?explore=$explore", + -enctype => "application/x-www-form-urlencoded" + ); + $html .= $cgi->hidden(-name => "explore", -default => $cgi->url(-relative => 1) . "?explore=$explore")."\n"; + $html .= "\n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= "
\n"; + $html .= " " . $html->folder("view"); + $html .= "
\n"; + $html .= " " . $html->folder("toolbar"); + $html .= "
\n"; + $html .= $cgi->end_form(); + $html << 1; + + my $img = $cgi->url(-relative => 1) . "?graph=$explore\@$width:$height:$start:$end:$ulimit:$llimit"; + $html >> "view"; + $html .= "\n"; + $html << 1; + + $html >> "toolbar"; + $html .= "\n"; + + $html .= ""; + + $html .= ""; + + $html .= ""; + + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + + $html .= "
Graph Size:" . $cgi->textfield( + -name => 'width', + -default => $width, + -size => 15, + -maxlength => 4, + -class => 'textfield', + ) . "x" . $cgi->textfield( + -name => 'height', + -default => $height, + -size => 15, + -maxlength => 4, + -class => 'textfield', + ) . "(pixels)Examples: '400 x 100', '800 x 200', ...
Data X-Range:" . $cgi->textfield( + -name => 'start', + -default => $start, + -size => 15, + -maxlength => 20, + -class => 'textfield', + ) . "-" . $cgi->textfield( + -name => 'end', + -default => $end, + -size => 15, + -maxlength => 20, + -class => 'textfield', + ) . "(time)Examples: '-2d - now', '24-Dec-2004 - +48h', ...
Data Y-Range:" . $cgi->textfield( + -name => 'ulimit', + -default => $ulimit, + -size => 15, + -maxlength => 10, + -class => 'textfield', + ) . "-" . $cgi->textfield( + -name => 'llimit', + -default => $llimit, + -size => 15, + -maxlength => 10, + -class => 'textfield', + ) . "(Bit/s)Examples: '2K - -1K', '4M - 2M', ...
". $cgi->submit(-name => "Update Graph", -class => "submit") . "
\n"; + $html << 1; + + + # send out page $html->undivert(0); + print STDOUT $cgi->header( + -type => 'text/html', + -content_length => length($html), + -expires => '+5m' + ) . $html; + + # cleanup + undef $html; + } + else { + # + # output HTML page: TOP-LEVEL SUMMARY + # + + # generate HTML page diversion + my $html = new String::Divert; + $html->overload(1); + + $html .= + "\n" . + " \n" . + " " . $html->folder("head") . + " \n" . + " \n" . + " " . $html->folder("body") . + " \n" . + "\n"; - # FIXME + $html >> "head"; + $html .= "url(-relative => 1)."?css=1\">\n"; + $html << 1; + + $html >> "body"; + $html .= "\n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + $html .= "
\n"; + $html .= " " . $html->folder("header"); + $html .= "
\n"; + $html .= " " . $html->folder("canvas"); + $html .= "
\n"; + $html .= " " . $html->folder("footer"); + $html .= "
\n"; + $html << 1; + + $html >> "header"; + $html .= "url(-relative => 1)."\">Real-Time Network Statistics"; + $html << 1; + $html >> "footer"; + $html .= "{-proghome}\">$my->{-progname} $my->{-progvers} ($my->{-progdate})"; + $html << 1; + + $html >> "canvas"; + $html .= "\n"; + $html .= " \n"; + for (my $i = 0; $i < @{$cfg->{'Host'}}; $i++) { + $html .= " \n"; + } + $html .= " \n"; + $html .= "
\n"; + $html .= " " . $html->folder("col$i"); + $html .= "
\n"; + $html << 1; + + for (my $i = 0; $i < @{$cfg->{'Host'}}; $i++) { + my $host = $cfg->{'Host'}->[$i]; + $html >> "col$i"; + $html .= "\n"; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + foreach my $target (@{$host->{-target}->{-order}}) { + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; + } + $html .= "
\n"; + my $url = $cgi->url(-relative => 1) . "?explore=$host->{-name}"; + my $img = $cgi->url(-relative => 1) . "?graph=$host->{-name}\@400:100:-48h:now:0:0"; + $html .= " \n"; + $html .= "
\n"; + my $url = $cgi->url(-relative => 1) . "?explore=$host->{-name}:$target"; + my $img = $cgi->url(-relative => 1) . "?graph=$host->{-name}:$target\@400:100:-48h:now:0:0"; + $html .= " \n"; + $html .= "
\n"; + $html << 1; + } # send out page + $html->undivert(0); print STDOUT $cgi->header( -type => 'text/html', -content_length => length($html),