mirror of
https://github.com/manuelkasper/AS-Stats.git
synced 2025-02-20 11:44:12 +08:00
* add support for NetFlow v9
* add support for IPv6 * add support for 4-byte ASNs
This commit is contained in:
parent
436fe23352
commit
3ff7930189
21
README
21
README
@ -1,11 +1,23 @@
|
||||
AS-Stats v1.36 (2012-07-25)
|
||||
AS-Stats v1.40 (2012-11-23)
|
||||
a simple tool to generate per-AS traffic graphs from NetFlow/sFlow records
|
||||
by Manuel Kasper, Monzoon Networks AG <mkasper@monzoon.net>
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Changes
|
||||
-------
|
||||
vx.xx Add links to PeeringDB and robtex
|
||||
v1.40 Add support for NetFlow v9 to netflow-asstatd.pl
|
||||
(sponsored by Xplornet Communications Inc.)
|
||||
|
||||
Add support for IPv6 (for NetFlow v9 and sFlow). Note: existing
|
||||
RRDs need to be upgraded (new data sources added for v6) for
|
||||
this to work. Enable $showv6 in www/config.inc to see separate
|
||||
graphs for IPv6.
|
||||
|
||||
Add support for 4-byte ASNs (NetFlow v9 and sFlow). Needs testing.
|
||||
|
||||
Add RRA for 1 month at 4 hour resolution to newly created RRD files.
|
||||
|
||||
Add links to PeeringDB and robtex
|
||||
(suggested by Steve Glendinning)
|
||||
|
||||
Fix AS-SET lookup on systems where the whois command returns
|
||||
@ -188,8 +200,9 @@ sFlow data.
|
||||
will reach the machine running xx-asstatd.pl (firewall etc.).
|
||||
|
||||
- NetFlow only:
|
||||
Have your router(s) send NetFlow v8 AS aggregation records to your machine.
|
||||
This is typically done with commands like the following (Cisco IOS):
|
||||
Have your router(s) send NetFlow v8 or v9 AS aggregation records to
|
||||
your machine. This is typically done with commands like the following
|
||||
(Cisco IOS):
|
||||
|
||||
ip flow-cache timeout active 5
|
||||
|
||||
|
@ -21,9 +21,11 @@ my $ascache_flush_number = 0;
|
||||
|
||||
my $server_port = 9000;
|
||||
my $MAXREAD = 8192;
|
||||
my $header_len = 28;
|
||||
my $flowrec_len = 28;
|
||||
my $v8_header_len = 28;
|
||||
my $v8_flowrec_len = 28;
|
||||
my $v9_header_len = 20;
|
||||
my $childrunning = 0;
|
||||
my $v9_templates = {};
|
||||
|
||||
use vars qw/ %opt /;
|
||||
getopts('r:p:k:s:', \%opt);
|
||||
@ -85,34 +87,186 @@ while (1) {
|
||||
|
||||
my ($port, $ipaddr) = sockaddr_in($server->peername);
|
||||
|
||||
my ($version) = unpack("n", $datagram);
|
||||
|
||||
if ($version == 8) {
|
||||
parse_netflow_v8($datagram, $ipaddr);
|
||||
} elsif ($version == 9) {
|
||||
parse_netflow_v9($datagram, $ipaddr);
|
||||
} else {
|
||||
print "unknown NetFlow version: $version\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_netflow_v8 {
|
||||
my $datagram = shift;
|
||||
my $ipaddr = shift;
|
||||
|
||||
my ($version, $count, $sysuptime, $unix_secs, $unix_nsecs,
|
||||
$flow_sequence, $engine_type, $engine_id, $aggregation,
|
||||
$agg_version) = unpack("nnNNNNCCCC", $datagram);
|
||||
|
||||
if ($version != 8 || $aggregation != 1 || ($agg_version != 0 && $agg_version != 2)) {
|
||||
if ($aggregation != 1 || ($agg_version != 0 && $agg_version != 2)) {
|
||||
print "unknown version: $version/$aggregation/$agg_version\n";
|
||||
next;
|
||||
return;
|
||||
}
|
||||
|
||||
my $flowrecs = substr($datagram, $header_len);
|
||||
my $flowrecs = substr($datagram, $v8_header_len);
|
||||
|
||||
for (my $i = 0; $i < $count; $i++) {
|
||||
my $flowrec = substr($datagram, $header_len + ($i*$flowrec_len), $flowrec_len);
|
||||
my $flowrec = substr($datagram, $v8_header_len + ($i*$v8_flowrec_len), $v8_flowrec_len);
|
||||
my @flowdata = unpack("NNNNNnnnn", $flowrec);
|
||||
handleflow($ipaddr, @flowdata);
|
||||
handleflow($ipaddr, $flowdata[2], $flowdata[5], $flowdata[6], $flowdata[7], $flowdata[8], 4);
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_netflow_v9 {
|
||||
my $datagram = shift;
|
||||
my $ipaddr = shift;
|
||||
|
||||
# Parse packet
|
||||
my ($version, $count, $sysuptime, $unix_secs, $seqno, $source_id, @flowsets) = unpack("nnNNNN(nnX4/a)*", $datagram);
|
||||
|
||||
# Loop through FlowSets and take appropriate action
|
||||
for (my $i = 0; $i < scalar @flowsets; $i += 2) {
|
||||
my $flowsetid = $flowsets[$i];
|
||||
my $flowsetdata = substr($flowsets[$i+1], 4); # chop off id/length
|
||||
if ($flowsetid == 0) {
|
||||
# 0 = Template FlowSet
|
||||
parse_netflow_v9_template_flowset($flowsetdata, $ipaddr, $source_id);
|
||||
} elsif ($flowsetid == 1) {
|
||||
# 1 - Options Template FlowSet
|
||||
} elsif ($flowsetid > 255) {
|
||||
# > 255: Data FlowSet
|
||||
parse_netflow_v9_data_flowset($flowsetid, $flowsetdata, $ipaddr, $source_id);
|
||||
} else {
|
||||
# reserved FlowSet
|
||||
print "Unknown FlowSet ID $flowsetid found\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_netflow_v9_template_flowset {
|
||||
my $templatedata = shift;
|
||||
my $ipaddr = shift;
|
||||
my $source_id = shift;
|
||||
|
||||
# Note: there may be multiple templates in a Template FlowSet
|
||||
|
||||
my @template_ints = unpack("n*", $templatedata);
|
||||
|
||||
my $i = 0;
|
||||
while ($i < scalar @template_ints) {
|
||||
my $template_id = $template_ints[$i];
|
||||
my $fldcount = $template_ints[$i+1];
|
||||
|
||||
last if (!defined($template_id) || !defined($fldcount));
|
||||
|
||||
#print "Updated template ID $template_id (source ID $source_id, from " . inet_ntoa($ipaddr) . ")\n";
|
||||
my $template = [@template_ints[($i+2) .. ($i+2+$fldcount*2-1)]];
|
||||
$v9_templates->{$ipaddr}->{$source_id}->{$template_id}->{'template'} = $template;
|
||||
|
||||
# Calculate total length of template data
|
||||
my $totallen = 0;
|
||||
for (my $j = 1; $j < scalar @$template; $j += 2) {
|
||||
$totallen += $template->[$j];
|
||||
}
|
||||
|
||||
$v9_templates->{$ipaddr}->{$source_id}->{$template_id}->{'len'} = $totallen;
|
||||
|
||||
$i += (2 + $fldcount*2);
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_netflow_v9_data_flowset {
|
||||
my $flowsetid = shift;
|
||||
my $flowsetdata = shift;
|
||||
my $ipaddr = shift;
|
||||
my $source_id = shift;
|
||||
|
||||
my $template = $v9_templates->{$ipaddr}->{$source_id}->{$flowsetid}->{'template'};
|
||||
if (!defined($template)) {
|
||||
#print "Template ID $flowsetid from $source_id/" . inet_ntoa($ipaddr) . " does not (yet) exist\n";
|
||||
return;
|
||||
}
|
||||
|
||||
my $len = $v9_templates->{$ipaddr}->{$source_id}->{$flowsetid}->{'len'};
|
||||
|
||||
my $ofs = 0;
|
||||
my $datalen = length($flowsetdata);
|
||||
while (($ofs + $len) <= $datalen) {
|
||||
# Interpret values according to template
|
||||
my ($inoctets, $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion);
|
||||
|
||||
$inoctets = 0;
|
||||
$outoctets = 0;
|
||||
$ipversion = 4;
|
||||
|
||||
for (my $i = 0; $i < scalar @$template; $i += 2) {
|
||||
my $cur_fldtype = $template->[$i];
|
||||
my $cur_fldlen = $template->[$i+1];
|
||||
|
||||
my $cur_fldval = substr($flowsetdata, $ofs, $cur_fldlen);
|
||||
$ofs += $cur_fldlen;
|
||||
|
||||
if ($cur_fldtype == 16) { # SRC_AS
|
||||
if ($cur_fldlen == 2) {
|
||||
$srcas = unpack("n", $cur_fldval);
|
||||
} elsif ($cur_fldlen == 4) {
|
||||
$srcas = unpack("N", $cur_fldval);
|
||||
}
|
||||
} elsif ($cur_fldtype == 17) { # DST_AS
|
||||
if ($cur_fldlen == 2) {
|
||||
$dstas = unpack("n", $cur_fldval);
|
||||
} elsif ($cur_fldlen == 4) {
|
||||
$dstas = unpack("N", $cur_fldval);
|
||||
}
|
||||
} elsif ($cur_fldtype == 10) { # INPUT_SNMP
|
||||
if ($cur_fldlen == 2) {
|
||||
$snmpin = unpack("n", $cur_fldval);
|
||||
} elsif ($cur_fldlen == 4) {
|
||||
$snmpin = unpack("N", $cur_fldval);
|
||||
}
|
||||
} elsif ($cur_fldtype == 14) { # OUTPUT_SNMP
|
||||
if ($cur_fldlen == 2) {
|
||||
$snmpout = unpack("n", $cur_fldval);
|
||||
} elsif ($cur_fldlen == 4) {
|
||||
$snmpout = unpack("N", $cur_fldval);
|
||||
}
|
||||
} elsif ($cur_fldtype == 1) { # IN_BYTES
|
||||
if ($cur_fldlen == 4) {
|
||||
$inoctets = unpack("N", $cur_fldval);
|
||||
} elsif ($cur_fldlen == 8) {
|
||||
$inoctets = unpack("Q", $cur_fldval);
|
||||
}
|
||||
} elsif ($cur_fldtype == 23) { # OUT_BYTES
|
||||
if ($cur_fldlen == 4) {
|
||||
$outoctets = unpack("N", $cur_fldval);
|
||||
} elsif ($cur_fldlen == 8) {
|
||||
$outoctets = unpack("Q", $cur_fldval);
|
||||
}
|
||||
} elsif ($cur_fldtype == 60) { # IP_PROTOCOL_VERSION
|
||||
$ipversion = unpack("C", $cur_fldval);
|
||||
} elsif ($cur_fldtype == 27 || $cur_fldtype == 28) { # IPV6_SRC_ADDR/IPV6_DST_ADDR
|
||||
$ipversion = 6;
|
||||
}
|
||||
}
|
||||
|
||||
if (defined($srcas) && defined($dstas) && defined($snmpin) && defined($snmpout)) {
|
||||
handleflow($ipaddr, $inoctets + $outoctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub handleflow {
|
||||
my ($routerip, $nflows, $npackets, $noctets, $firstts, $lastts,
|
||||
$srcas, $dstas, $snmpin, $snmpout) = @_;
|
||||
my ($routerip, $noctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion) = @_;
|
||||
|
||||
if ($srcas == 0 && $dstas == 0) {
|
||||
# don't care about internal traffic
|
||||
return;
|
||||
}
|
||||
|
||||
#print "$srcas => $dstas ($noctets octets)\n";
|
||||
#print "$srcas => $dstas ($noctets octets, version $ipversion, snmpin $snmpin, snmpout $snmpout)\n";
|
||||
|
||||
# determine direction and interface alias name (if known)
|
||||
my $direction;
|
||||
@ -128,10 +282,8 @@ sub handleflow {
|
||||
$direction = "in";
|
||||
$ifalias = $knownlinks{inet_ntoa($routerip) . '_' . $snmpin};
|
||||
} else {
|
||||
handleflow($routerip, $nflows, $npackets, $noctets, $firstts, $lastts,
|
||||
$srcas, 0, $snmpin, $snmpout);
|
||||
handleflow($routerip, $nflows, $npackets, $noctets, $firstts, $lastts,
|
||||
0, $dstas, $snmpin, $snmpout);
|
||||
handleflow($routerip, $noctets, $srcas, 0, $snmpin, $snmpout, $ipversion);
|
||||
handleflow($routerip, $noctets, 0, $dstas, $snmpin, $snmpout, $ipversion);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -140,7 +292,12 @@ sub handleflow {
|
||||
return;
|
||||
}
|
||||
|
||||
my $dsname = "${ifalias}_${direction}";
|
||||
my $dsname;
|
||||
if ($ipversion == 6) {
|
||||
$dsname = "${ifalias}_v6_${direction}";
|
||||
} else {
|
||||
$dsname = "${ifalias}_${direction}";
|
||||
}
|
||||
|
||||
# put it into the cache
|
||||
if (!$ascache->{$as}) {
|
||||
@ -238,9 +395,12 @@ sub getrrdfile {
|
||||
foreach my $alias (keys %links) {
|
||||
push(@args, "DS:${alias}_in:ABSOLUTE:300:U:U");
|
||||
push(@args, "DS:${alias}_out:ABSOLUTE:300:U:U");
|
||||
push(@args, "DS:${alias}_v6_in:ABSOLUTE:300:U:U");
|
||||
push(@args, "DS:${alias}_v6_out:ABSOLUTE:300:U:U");
|
||||
}
|
||||
push(@args, "RRA:AVERAGE:0.99999:1:576"); # 48 hours at 5 minute resolution
|
||||
push(@args, "RRA:AVERAGE:0.99999:12:168"); # 1 week at 1 hour resolution
|
||||
push(@args, "RRA:AVERAGE:0.99999:48:180"); # 1 month at 4 hour resolution
|
||||
push(@args, "RRA:AVERAGE:0.99999:288:366"); # 1 year at 1 day resolution
|
||||
RRDs::create($rrdfile, "--start", $startts, @args);
|
||||
|
||||
|
@ -69,7 +69,7 @@ open(STATSFILE, ">$statsfile.tmp");
|
||||
# print header line
|
||||
print STATSFILE "as";
|
||||
foreach my $link (@links) {
|
||||
print STATSFILE "\t${link}_in\t${link}_out";
|
||||
print STATSFILE "\t${link}_in\t${link}_out\t${link}_v6_in\t${link}_v6_out";
|
||||
}
|
||||
print STATSFILE "\n";
|
||||
|
||||
@ -78,8 +78,10 @@ foreach my $as (@asorder) {
|
||||
print STATSFILE "$as";
|
||||
|
||||
foreach my $link (@links) {
|
||||
print STATSFILE "\t" . $astraffic->{$as}->{"${link}_in"};
|
||||
print STATSFILE "\t" . $astraffic->{$as}->{"${link}_out"};
|
||||
print STATSFILE "\t" . undefaszero($astraffic->{$as}->{"${link}_in"});
|
||||
print STATSFILE "\t" . undefaszero($astraffic->{$as}->{"${link}_out"});
|
||||
print STATSFILE "\t" . undefaszero($astraffic->{$as}->{"${link}_v6_in"});
|
||||
print STATSFILE "\t" . undefaszero($astraffic->{$as}->{"${link}_v6_out"});
|
||||
}
|
||||
|
||||
print STATSFILE "\n";
|
||||
@ -89,6 +91,15 @@ close(STATSFILE);
|
||||
|
||||
rename("$statsfile.tmp", $statsfile);
|
||||
|
||||
sub undefaszero {
|
||||
my $val = shift;
|
||||
if (!defined($val)) {
|
||||
return 0;
|
||||
} else {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
|
||||
sub gettraffic {
|
||||
|
||||
my $as = shift;
|
||||
@ -103,11 +114,16 @@ sub gettraffic {
|
||||
my $rrdfile = "$dirname/$as.rrd";
|
||||
|
||||
# get list of available DS
|
||||
my $have_v6 = 0;
|
||||
|
||||
my $availableds = {};
|
||||
my $rrdinfo = RRDs::info($rrdfile);
|
||||
foreach my $ri (keys %$rrdinfo) {
|
||||
if ($ri =~ /^ds\[(.+)\]\.type$/) {
|
||||
$availableds->{$1} = 1;
|
||||
if ($1 =~ /_v6_/) {
|
||||
$have_v6 = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,8 +134,21 @@ sub gettraffic {
|
||||
push(@cmd, "DEF:${link}_out=$rrdfile:${link}_out:AVERAGE");
|
||||
push(@cmd, "VDEF:${link}_in_v=${link}_in,TOTAL");
|
||||
push(@cmd, "VDEF:${link}_out_v=${link}_out,TOTAL");
|
||||
|
||||
if ($have_v6) {
|
||||
push(@cmd, "DEF:${link}_v6_in=$rrdfile:${link}_v6_in:AVERAGE");
|
||||
push(@cmd, "DEF:${link}_v6_out=$rrdfile:${link}_v6_out:AVERAGE");
|
||||
push(@cmd, "VDEF:${link}_v6_in_v=${link}_v6_in,TOTAL");
|
||||
push(@cmd, "VDEF:${link}_v6_out_v=${link}_v6_out,TOTAL");
|
||||
}
|
||||
|
||||
push(@cmd, "PRINT:${link}_in_v:%lf");
|
||||
push(@cmd, "PRINT:${link}_out_v:%lf");
|
||||
|
||||
if ($have_v6) {
|
||||
push(@cmd, "PRINT:${link}_v6_in_v:%lf");
|
||||
push(@cmd, "PRINT:${link}_v6_out_v:%lf");
|
||||
}
|
||||
}
|
||||
|
||||
my @res = RRDs::graph(@cmd);
|
||||
@ -131,20 +160,24 @@ sub gettraffic {
|
||||
my $lines = $res[0];
|
||||
|
||||
for (my $i = 0; $i < scalar(@links); $i++) {
|
||||
my $in = $lines->[$i*2];
|
||||
chomp($in);
|
||||
if (isnan($in)) {
|
||||
$in = 0;
|
||||
my @vals;
|
||||
my $numds = ($have_v6 ? 4 : 2);
|
||||
|
||||
for (my $j = 0; $j < $numds; $j++) {
|
||||
$vals[$j] = $lines->[$i*$numds+$j];
|
||||
chomp($vals[$j]);
|
||||
if (isnan($vals[$j])) {
|
||||
$vals[$j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
my $out = $lines->[$i*2+1];
|
||||
chomp($out);
|
||||
if (isnan($out)) {
|
||||
$out = 0;
|
||||
}
|
||||
$retdata->{$links[$i] . '_in'} = $vals[0];
|
||||
$retdata->{$links[$i] . '_out'} = $vals[1];
|
||||
|
||||
$retdata->{$links[$i] . '_in'} = $in;
|
||||
$retdata->{$links[$i] . '_out'} = $out;
|
||||
if ($have_v6) {
|
||||
$retdata->{$links[$i] . '_v6_in'} = $vals[2];
|
||||
$retdata->{$links[$i] . '_v6_out'} = $vals[3];
|
||||
}
|
||||
}
|
||||
|
||||
return $retdata;
|
||||
|
@ -102,6 +102,8 @@ while (1) {
|
||||
}
|
||||
|
||||
foreach my $sFlowSample (@{$sFlowSamplesRef}) {
|
||||
my $ipversion = 4;
|
||||
|
||||
# only process standard structures
|
||||
next if ($sFlowSample->{'sampleTypeEnterprise'} != 0);
|
||||
|
||||
@ -121,6 +123,9 @@ while (1) {
|
||||
my $noctets;
|
||||
if ($sFlowSample->{'IPv4Packetlength'}) {
|
||||
$noctets = $sFlowSample->{'IPv4Packetlength'};
|
||||
} elsif ($sFlowSample->{'IPv6Packetlength'}) {
|
||||
$noctets = $sFlowSample->{'IPv6Packetlength'};
|
||||
$ipversion = 6;
|
||||
} else {
|
||||
$noctets = $sFlowSample->{'HeaderFrameLength'} - 14;
|
||||
}
|
||||
@ -152,12 +157,12 @@ while (1) {
|
||||
$dstas = 0;
|
||||
}
|
||||
|
||||
handleflow($ipaddr, $noctets, $srcas, $dstas, $snmpin, $snmpout);
|
||||
handleflow($ipaddr, $noctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion);
|
||||
}
|
||||
}
|
||||
|
||||
sub handleflow {
|
||||
my ($routerip, $noctets, $srcas, $dstas, $snmpin, $snmpout) = @_;
|
||||
my ($routerip, $noctets, $srcas, $dstas, $snmpin, $snmpout, $ipversion) = @_;
|
||||
|
||||
if ($srcas == 0 && $dstas == 0) {
|
||||
# don't care about internal traffic
|
||||
@ -180,8 +185,8 @@ sub handleflow {
|
||||
$direction = "in";
|
||||
$ifalias = $knownlinks{inet_ntoa($routerip) . '_' . $snmpin};
|
||||
} else {
|
||||
handleflow($routerip, $noctets, $srcas, 0, $snmpin, $snmpout);
|
||||
handleflow($routerip, $noctets, 0, $dstas, $snmpin, $snmpout);
|
||||
handleflow($routerip, $noctets, $srcas, 0, $snmpin, $snmpout, $ipversion);
|
||||
handleflow($routerip, $noctets, 0, $dstas, $snmpin, $snmpout, $ipversion);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -190,7 +195,12 @@ sub handleflow {
|
||||
return;
|
||||
}
|
||||
|
||||
my $dsname = "${ifalias}_${direction}";
|
||||
my $dsname;
|
||||
if ($ipversion == 6) {
|
||||
$dsname = "${ifalias}_v6_${direction}";
|
||||
} else {
|
||||
$dsname = "${ifalias}_${direction}";
|
||||
}
|
||||
|
||||
# put it into the cache
|
||||
if (!$ascache->{$as}) {
|
||||
@ -285,9 +295,12 @@ sub getrrdfile {
|
||||
while (my ($key, $alias) = each(%knownlinks)) {
|
||||
push(@args, "DS:${alias}_in:ABSOLUTE:300:U:U");
|
||||
push(@args, "DS:${alias}_out:ABSOLUTE:300:U:U");
|
||||
push(@args, "DS:${alias}_v6_in:ABSOLUTE:300:U:U");
|
||||
push(@args, "DS:${alias}_v6_out:ABSOLUTE:300:U:U");
|
||||
}
|
||||
push(@args, "RRA:AVERAGE:0.99999:1:576"); # 48 hours at 5 minute resolution
|
||||
push(@args, "RRA:AVERAGE:0.99999:12:168"); # 1 week at 1 hour resolution
|
||||
push(@args, "RRA:AVERAGE:0.99999:48:180"); # 1 month at 4 hour resolution
|
||||
push(@args, "RRA:AVERAGE:0.99999:288:366"); # 1 year at 1 day resolution
|
||||
RRDs::create($rrdfile, "--start", $startts, @args);
|
||||
|
||||
|
18103
www/asinfo.txt
18103
www/asinfo.txt
File diff suppressed because it is too large
Load Diff
@ -153,14 +153,7 @@ AS-SET: <input type="text" name="asset" size="20" />
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<div id="footer">
|
||||
AS-Stats v1.36 written by Manuel Kasper, Monzoon Networks AG.<br/>
|
||||
<?php if ($outispositive): ?>
|
||||
Outbound traffic: positive / Inbound traffic: negative
|
||||
<?php else: ?>
|
||||
Inbound traffic: positive / Outbound traffic: negative
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php include('footer.inc'); ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -11,6 +11,7 @@ $knownlinksfile = "/data/knownlinks";
|
||||
$outispositive = true;
|
||||
|
||||
$ntop = 20;
|
||||
$showv6 = true;
|
||||
|
||||
$whois = "/usr/bin/whois";
|
||||
$assetpath = "asset";
|
||||
|
8
www/footer.inc
Normal file
8
www/footer.inc
Normal file
@ -0,0 +1,8 @@
|
||||
<div id="footer">
|
||||
AS-Stats v1.40 written by Manuel Kasper, Monzoon Networks AG.<br/>
|
||||
<?php if ($outispositive): ?>
|
||||
Outbound traffic: positive / Inbound traffic: negative
|
||||
<?php else: ?>
|
||||
Inbound traffic: positive / Outbound traffic: negative
|
||||
<?php endif; ?>
|
||||
</div>
|
13
www/func.inc
13
www/func.inc
@ -115,15 +115,22 @@ function getasstats_top($ntop) {
|
||||
$as = $els[0];
|
||||
$tot_in = 0;
|
||||
$tot_out = 0;
|
||||
$tot_v6_in = 0;
|
||||
$tot_v6_out = 0;
|
||||
|
||||
for ($i = 1; $i < count($els); $i++) {
|
||||
if (strpos($cols[$i], "_in") !== false)
|
||||
if (strpos($cols[$i], "_in") !== false) {
|
||||
$tot_in += $els[$i];
|
||||
else
|
||||
if (strpos($cols[$i], "_v6_") !== false)
|
||||
$tot_v6_in += $els[$i];
|
||||
} else {
|
||||
$tot_out += $els[$i];
|
||||
if (strpos($cols[$i], "_v6_") !== false)
|
||||
$tot_v6_out += $els[$i];
|
||||
}
|
||||
}
|
||||
|
||||
$asstats[$as] = array($tot_in, $tot_out);
|
||||
$asstats[$as] = array($tot_in, $tot_out, $tot_v6_in, $tot_v6_out);
|
||||
|
||||
if (count($asstats) >= $ntop)
|
||||
break;
|
||||
|
@ -19,6 +19,9 @@ if (isset($_GET['width']))
|
||||
$width = (int)$_GET['width'];
|
||||
if (isset($_GET['height']))
|
||||
$height = (int)$_GET['height'];
|
||||
$v6_el = "";
|
||||
if (@$_GET['v'] == 6)
|
||||
$v6_el = "v6_";
|
||||
|
||||
$knownlinks = getknownlinks();
|
||||
$rrdfile = getRRDFileForAS($as);
|
||||
@ -27,6 +30,9 @@ $cmd = "$rrdtool graph - " .
|
||||
"--slope-mode --alt-autoscale -u 0 -l 0 --imgformat=PNG --base=1000 --height=$height --width=$width " .
|
||||
"--color BACK#ffffff00 --color SHADEA#ffffff00 --color SHADEB#ffffff00 ";
|
||||
|
||||
if (@$_GET['v'])
|
||||
$cmd .= "--title IPv" . $_GET['v'] . " ";
|
||||
|
||||
if (isset($_GET['nolegend']))
|
||||
$cmd .= "--no-legend ";
|
||||
|
||||
@ -38,18 +44,18 @@ if (isset($_GET['end']) && is_numeric($_GET['end']))
|
||||
|
||||
/* geneate RRD DEFs */
|
||||
foreach ($knownlinks as $link) {
|
||||
$cmd .= "DEF:{$link['tag']}_in=\"$rrdfile\":{$link['tag']}_in:AVERAGE ";
|
||||
$cmd .= "DEF:{$link['tag']}_out=\"$rrdfile\":{$link['tag']}_out:AVERAGE ";
|
||||
$cmd .= "DEF:{$link['tag']}_{$v6_el}in=\"$rrdfile\":{$link['tag']}_{$v6_el}in:AVERAGE ";
|
||||
$cmd .= "DEF:{$link['tag']}_{$v6_el}out=\"$rrdfile\":{$link['tag']}_{$v6_el}out:AVERAGE ";
|
||||
}
|
||||
|
||||
/* generate a CDEF for each DEF to multiply by 8 (bytes to bits), and reverse for outbound */
|
||||
foreach ($knownlinks as $link) {
|
||||
if ($outispositive) {
|
||||
$cmd .= "CDEF:{$link['tag']}_in_bits={$link['tag']}_in,-8,* ";
|
||||
$cmd .= "CDEF:{$link['tag']}_out_bits={$link['tag']}_out,8,* ";
|
||||
$cmd .= "CDEF:{$link['tag']}_{$v6_el}in_bits={$link['tag']}_{$v6_el}in,-8,* ";
|
||||
$cmd .= "CDEF:{$link['tag']}_{$v6_el}out_bits={$link['tag']}_{$v6_el}out,8,* ";
|
||||
} else {
|
||||
$cmd .= "CDEF:{$link['tag']}_in_bits={$link['tag']}_in,8,* ";
|
||||
$cmd .= "CDEF:{$link['tag']}_out_bits={$link['tag']}_out,-8,* ";
|
||||
$cmd .= "CDEF:{$link['tag']}_{$v6_el}in_bits={$link['tag']}_{$v6_el}in,8,* ";
|
||||
$cmd .= "CDEF:{$link['tag']}_{$v6_el}out_bits={$link['tag']}_{$v6_el}out,-8,* ";
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +66,7 @@ foreach ($knownlinks as $link) {
|
||||
$col = $link['color'] . "BB";
|
||||
else
|
||||
$col = $link['color'];
|
||||
$cmd .= "AREA:{$link['tag']}_in_bits#{$col}:\"{$link['descr']}\"";
|
||||
$cmd .= "AREA:{$link['tag']}_{$v6_el}in_bits#{$col}:\"{$link['descr']}\"";
|
||||
if ($i > 0)
|
||||
$cmd .= ":STACK";
|
||||
$cmd .= " ";
|
||||
@ -74,7 +80,7 @@ foreach ($knownlinks as $link) {
|
||||
$col = $link['color'];
|
||||
else
|
||||
$col = $link['color'] . "BB";
|
||||
$cmd .= "AREA:{$link['tag']}_out_bits#{$col}:";
|
||||
$cmd .= "AREA:{$link['tag']}_{$v6_el}out_bits#{$col}:";
|
||||
if ($i > 0)
|
||||
$cmd .= ":STACK";
|
||||
$cmd .= " ";
|
||||
|
@ -37,16 +37,36 @@ $rrdfile = getRRDFileForAS($as);
|
||||
<p>No data found for AS <?php echo $as; ?></p>
|
||||
<?php else: ?>
|
||||
<div class="title">Daily</div>
|
||||
<?php if ($showv6): ?>
|
||||
<img class="detailgraph" src="gengraph.php?v=4&as=<?php echo $as; ?>" alt="daily graph" />
|
||||
<img class="detailgraph2" src="gengraph.php?v=6&as=<?php echo $as; ?>" alt="daily graph" />
|
||||
<?php else: ?>
|
||||
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>" alt="daily graph" />
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="title">Weekly</div>
|
||||
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&start=<?php echo (time() - 7*86400);?>&end=<?php echo time(); ?>" alt="weekly graph" />
|
||||
<?php if ($showv6): ?>
|
||||
<img class="detailgraph" src="gengraph.php?v=4&as=<?php echo $as; ?>&start=<?php echo (time() - 7*86400);?>&end=<?php echo time(); ?>" alt="weekly graph" />
|
||||
<img class="detailgraph2" src="gengraph.php?v=6&as=<?php echo $as; ?>&start=<?php echo (time() - 7*86400);?>&end=<?php echo time(); ?>" alt="weekly graph" />
|
||||
<?php else: ?>
|
||||
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&start=<?php echo (time() - 7*86400);?>&end=<?php echo time(); ?>" alt="weekly graph" />
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="title">Monthly</div>
|
||||
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&start=<?php echo (time() - 30*86400);?>&end=<?php echo time(); ?>" alt="monthly graph" />
|
||||
<?php if ($showv6): ?>
|
||||
<img class="detailgraph" src="gengraph.php?v=4&as=<?php echo $as; ?>&start=<?php echo (time() - 30*86400);?>&end=<?php echo time(); ?>" alt="monthly graph" />
|
||||
<img class="detailgraph2" src="gengraph.php?v=6&as=<?php echo $as; ?>&start=<?php echo (time() - 30*86400);?>&end=<?php echo time(); ?>" alt="monthly graph" />
|
||||
<?php else: ?>
|
||||
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&start=<?php echo (time() - 30*86400);?>&end=<?php echo time(); ?>" alt="monthly graph" />
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="title">Yearly</div>
|
||||
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&start=<?php echo (time() - 365*86400);?>&end=<?php echo time(); ?>" alt="yearly graph" />
|
||||
<?php if ($showv6): ?>
|
||||
<img class="detailgraph" src="gengraph.php?v=4&as=<?php echo $as; ?>&start=<?php echo (time() - 365*86400);?>&end=<?php echo time(); ?>" alt="yearly graph" />
|
||||
<img class="detailgraph2" src="gengraph.php?v=6&as=<?php echo $as; ?>&start=<?php echo (time() - 365*86400);?>&end=<?php echo time(); ?>" alt="yearly graph" />
|
||||
<?php else: ?>
|
||||
<img class="detailgraph" src="gengraph.php?as=<?php echo $as; ?>&start=<?php echo (time() - 365*86400);?>&end=<?php echo time(); ?>" alt="yearly graph" />
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
|
||||
@ -58,14 +78,7 @@ AS: <input type="text" name="as" size="6" />
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<div id="footer">
|
||||
AS-Stats v1.36 written by Manuel Kasper, Monzoon Networks AG.<br/>
|
||||
<?php if ($outispositive): ?>
|
||||
Outbound traffic: positive / Inbound traffic: negative
|
||||
<?php else: ?>
|
||||
Inbound traffic: positive / Outbound traffic: negative
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php include('footer.inc'); ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -14,6 +14,9 @@ $link = $_GET['link'];
|
||||
if (!preg_match("/^[0-9a-zA-Z][0-9a-zA-Z\-]+$/", $link))
|
||||
die("Invalid link");
|
||||
|
||||
if (@$_GET['v'] == 6)
|
||||
$link .= "_v6";
|
||||
|
||||
/* first step: walk the data for all ASes to determine the top 5 for the given link */
|
||||
$fd = fopen($daystatsfile, "r");
|
||||
$cols = explode("\t", trim(fgets($fd)));
|
||||
@ -68,6 +71,9 @@ $cmd = "$rrdtool graph - " .
|
||||
"--slope-mode --alt-autoscale -u 0 -l 0 --imgformat=PNG --base=1000 --height=$height --width=$width " .
|
||||
"--color BACK#ffffff00 --color SHADEA#ffffff00 --color SHADEB#ffffff00 ";
|
||||
|
||||
if (@$_GET['v'])
|
||||
$cmd .= "--title IPv" . $_GET['v'] . " ";
|
||||
|
||||
/* geneate RRD DEFs */
|
||||
foreach ($topas as $as => $traffic) {
|
||||
$rrdfile = getRRDFileForAS($as);
|
||||
|
@ -37,21 +37,19 @@ $class = (($i % 2) == 0) ? "even" : "odd";
|
||||
</div>
|
||||
</th>
|
||||
<td>
|
||||
<?php if ($showv6): ?>
|
||||
<img alt="link graph" src="linkgraph.php?link=<?php echo $link['tag']; ?>&width=500&height=300&v=4" width="581" height="505" border="0" />
|
||||
<img alt="link graph" src="linkgraph.php?link=<?php echo $link['tag']; ?>&width=500&height=300&v=6" width="581" height="505" border="0" />
|
||||
<?php else: ?>
|
||||
<img alt="link graph" src="linkgraph.php?link=<?php echo $link['tag']; ?>&width=500&height=300" width="581" height="494" border="0" />
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php $i++; endforeach; ?>
|
||||
|
||||
</table>
|
||||
|
||||
<div id="footer">
|
||||
AS-Stats v1.36 written by Manuel Kasper, Monzoon Networks AG.<br/>
|
||||
<?php if ($outispositive): ?>
|
||||
Outbound traffic: positive / Inbound traffic: negative
|
||||
<?php else: ?>
|
||||
Inbound traffic: positive / Outbound traffic: negative
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php include('footer.inc'); ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -30,6 +30,10 @@
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.vsmall {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.rank {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
@ -71,13 +75,17 @@ table.astable th {
|
||||
width: 25em;
|
||||
}
|
||||
|
||||
.detailgraph {
|
||||
.detailgraph, .detailgraph2 {
|
||||
border: 1px solid #aaa;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 0.8em;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
.detailgraph2 {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
div#legend {
|
||||
position: fixed;
|
||||
right: 20px;
|
||||
|
20
www/top.php
20
www/top.php
@ -56,6 +56,10 @@ $class = (($i % 2) == 0) ? "even" : "odd";
|
||||
</div>
|
||||
<div class="small">~ <?php echo format_bytes($nbytes[0]); ?> in /
|
||||
<?php echo format_bytes($nbytes[1]); ?> out in the last 24 hours</div>
|
||||
<?php if ($showv6): ?>
|
||||
<div class="vsmall">IPv6: ~ <?php echo format_bytes($nbytes[2]); ?> in /
|
||||
<?php echo format_bytes($nbytes[3]); ?> out</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($customlinks)): ?>
|
||||
<div class="customlinks">
|
||||
@ -75,7 +79,12 @@ echo join(" | ", $htmllinks);
|
||||
</div>
|
||||
</th>
|
||||
<td>
|
||||
<a href="history.php?as=<?php echo $as; ?>" target="_blank"><img alt="AS graph" src="gengraph.php?as=<?php echo $as; ?>&width=500&height=150&nolegend=1" width="581" height="204" border="0" /></a>
|
||||
<?php if ($showv6): ?>
|
||||
<a href="history.php?v=4&as=<?php echo $as; ?>" target="_blank"><img alt="AS graph" src="gengraph.php?as=<?php echo $as; ?>&width=500&height=150&v=4&nolegend=1" width="581" height="215" border="0" /></a>
|
||||
<a href="history.php?v=6&as=<?php echo $as; ?>" target="_blank"><img alt="AS graph" src="gengraph.php?as=<?php echo $as; ?>&width=500&height=150&v=6&nolegend=1" width="581" height="215" border="0" /></a>
|
||||
<?php else: ?>
|
||||
<a href="history.php?as=<?php echo $as; ?>" target="_blank"><img alt="AS graph" src="gengraph.php?as=<?php echo $as; ?>&width=500&height=150&nolegend=1" width="581" height="204" border="0" /></a>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php $i++; endforeach; ?>
|
||||
@ -100,14 +109,7 @@ foreach ($knownlinks as $link) {
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="footer">
|
||||
AS-Stats v1.36 written by Manuel Kasper, Monzoon Networks AG.<br/>
|
||||
<?php if ($outispositive): ?>
|
||||
Outbound traffic: positive / Inbound traffic: negative
|
||||
<?php else: ?>
|
||||
Inbound traffic: positive / Outbound traffic: negative
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php include('footer.inc'); ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
x
Reference in New Issue
Block a user