X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=html%2Fcgi-bin%2Fconnections.cgi;h=f1ed2125a2cb9e253ca332f7de01c1b09985e601;hb=612ce881824ebb63c3cd1ecbc3b381ef70fb0fbf;hp=8fe8f8aa9af7a22b922bb8921860965d25f94565;hpb=cd1a2927226c734d96478e12bb768256fb64a06a;p=ipfire-2.x.git diff --git a/html/cgi-bin/connections.cgi b/html/cgi-bin/connections.cgi index 8fe8f8aa9a..f1ed2125a2 100644 --- a/html/cgi-bin/connections.cgi +++ b/html/cgi-bin/connections.cgi @@ -1,329 +1,678 @@ -#!/usr/bin/perl -# -# (c) 2001 Jack Beglinger -# -# (c) 2003 Dave Roberts - colour coded netfilter/iptables rewrite for 1.3 -# -# $Id: connections.cgi,v 1.6.2.11 2005/02/24 07:44:35 gespinasse Exp $ -# - -# Setup GREEN, ORANGE, IPCOP, VPN CIDR networks, masklengths and colours only once - -my @network=(); -my @masklen=(); -my @colour=(); - -use Net::IPv4Addr qw( :all ); - -use strict; - -# enable only the following on debugging purpose -#use warnings; -#use CGI::Carp 'fatalsToBrowser'; - -require 'CONFIG_ROOT/general-functions.pl'; -require "${General::swroot}/lang.pl"; -require "${General::swroot}/header.pl"; - -#workaround to suppress a warning when a variable is used only once -my @dummy = ( ${Header::table1colour} ); -undef (@dummy); - -# Read various files - -my %netsettings=(); -&General::readhash("${General::swroot}/ethernet/settings", \%netsettings); - -open (ACTIVE, "/proc/net/ip_conntrack") or die 'Unable to open ip_conntrack'; -my @active = ; -close (ACTIVE); - -my @vpn = ('none'); -open (ACTIVE, "/proc/net/ipsec_eroute") and @vpn = ; close (ACTIVE); - -my $aliasfile = "${General::swroot}/ethernet/aliases"; -open(ALIASES, $aliasfile) or die 'Unable to open aliases file.'; -my @aliases = ; -close(ALIASES); - -# Add Green Firewall Interface -push(@network, $netsettings{'GREEN_ADDRESS'}); -push(@masklen, "255.255.255.255" ); -push(@colour, ${Header::colourfw} ); - -# Add Green Network to Array -push(@network, $netsettings{'GREEN_NETADDRESS'}); -push(@masklen, $netsettings{'GREEN_NETMASK'} ); -push(@colour, ${Header::colourgreen} ); - -# Add Green Routes to Array -my @routes = `/sbin/route -n | /bin/grep $netsettings{'GREEN_DEV'}`; -foreach my $route (@routes) { - chomp($route); - my @temp = split(/[\t ]+/, $route); - push(@network, $temp[0]); - push(@masklen, $temp[2]); - push(@colour, ${Header::colourgreen} ); -} - -# Add Firewall Localhost 127.0.0.1 -push(@network, '127.0.0.1'); -push(@masklen, '255.255.255.255' ); -push(@colour, ${Header::colourfw} ); - -# Add Orange Network -if ($netsettings{'ORANGE_DEV'}) { - push(@network, $netsettings{'ORANGE_NETADDRESS'}); - push(@masklen, $netsettings{'ORANGE_NETMASK'} ); - push(@colour, ${Header::colourorange} ); - # Add Orange Routes to Array - @routes = `/sbin/route -n | /bin/grep $netsettings{'ORANGE_DEV'}`; - foreach my $route (@routes) { - chomp($route); - my @temp = split(/[\t ]+/, $route); - push(@network, $temp[0]); - push(@masklen, $temp[2]); - push(@colour, ${Header::colourorange} ); - } -} - -# Add Blue Network -if ($netsettings{'BLUE_DEV'}) { - push(@network, $netsettings{'BLUE_NETADDRESS'}); - push(@masklen, $netsettings{'BLUE_NETMASK'} ); - push(@colour, ${Header::colourblue} ); - # Add Blue Routes to Array - @routes = `/sbin/route -n | /bin/grep $netsettings{'BLUE_DEV'}`; - foreach my $route (@routes) { - chomp($route); - my @temp = split(/[\t ]+/, $route); - push(@network, $temp[0]); - push(@masklen, $temp[2]); - push(@colour, ${Header::colourblue} ); - } -} - -# Add STATIC RED aliases -if ($netsettings{'RED_DEV'}) { - # We have a RED eth iface - if ($netsettings{'RED_TYPE'} eq 'STATIC') { - # We have a STATIC RED eth iface - foreach my $line (@aliases) - { - chomp($line); - my @temp = split(/\,/,$line); - if ( $temp[0] ) { - push(@network, $temp[0]); - push(@masklen, $netsettings{'RED_NETMASK'} ); - push(@colour, ${Header::colourfw} ); - } - } - } -} - -# Add VPNs -if ( $vpn[0] ne 'none' ) { - foreach my $line (@vpn) { - my @temp = split(/[\t ]+/,$line); - my @temp1 = split(/[\/:]+/,$temp[3]); - push(@network, $temp1[0]); - push(@masklen, ipv4_cidr2msk($temp1[1])); - push(@colour, ${Header::colourvpn} ); - } -} -if (open(IP, "${General::swroot}/red/local-ipaddress")) { - my $redip = ; - close(IP); - chomp $redip; - push(@network, $redip); - push(@masklen, '255.255.255.255' ); - push(@colour, ${Header::colourfw} ); -} - -&Header::showhttpheaders(); -&Header::openpage($Lang::tr{'connections'}, 1, ''); -&Header::openbigbox('100%', 'left'); -&Header::openbox('100%', 'left', $Lang::tr{'connection tracking'}); - -print < -$Lang::tr{'legend'} : - $Lang::tr{'lan'} - $Lang::tr{'internet'} - $Lang::tr{'dmz'} - $Lang::tr{'wireless'} - IPCop - $Lang::tr{'vpn'} - - -
- - - - - - - - - - - -END -; - -foreach my $line (@active) -{ - my $protocol=''; - my $expires=''; - my $connstatus=''; - my $orgsip=''; - my $orgdip=''; - my $orgsp=''; - my $orgdp=''; - my $exsip=''; - my $exdip=''; - my $exsp=''; - my $exdp=''; - my $marked=''; - my $use=''; - my $orgsipcolour=''; - my $orgdipcolour=''; - my $exsipcolour=''; - my $exdipcolour=''; - - chomp($line); - my @temp = split(' ',$line); - print "\n"; - if ($temp[0] eq 'udp') { - my $offset = 0; - $marked = ''; - $protocol = $temp[0] . " (" . $temp[1] . ")"; - $expires = $temp[2]; - $connstatus = ' '; - $orgsip = substr $temp[3], 4; - $orgdip = substr $temp[4], 4; - $orgsp = substr $temp[5], 6; - $orgdp = substr $temp[6], 6; - if ($temp[7] eq '[UNREPLIED]') { - $marked = $temp[7]; - $offset = 1; - } - else { - $connstatus = ' '; - } - - $exsip = substr $temp[7 + $offset], 4; - $exdip = substr $temp[8 + $offset], 4; - $exsp = substr $temp[9 + $offset], 6; - $exdp = substr $temp[10 + $offset], 6; - if ($marked eq '[UNREPLIED]') { - $use = substr $temp[11 + $offset], 4; - } - else { - $marked = $temp[11 + $offset]; - $use = substr $marked, 0, 3; - if ($use eq 'use' ) { - $marked = ''; - $use = substr $temp[11 + $offset], 4; - } - else { - $use = substr $temp[12 + $offset], 4; - } - } - } - if ($temp[0] eq 'tcp') { - my $offset = 0; - $protocol = $temp[0] . " (" . $temp[1] . ")"; - $expires = $temp[2]; - $connstatus = $temp[3]; - $orgsip = substr $temp[4], 4; - $orgdip = substr $temp[5], 4; - $orgsp = substr $temp[6], 6; - $orgdp = substr $temp[7], 6; - if ($temp[8] eq '[UNREPLIED]') { - $marked = $temp[8]; - $offset = 1; - $use = substr $temp[13], 4; - } - else { - $marked = $temp[12]; - $use = substr $temp[13], 4; - } - - $exsip = substr $temp[8 + $offset], 4; - $exdip = substr $temp[9 + $offset], 4; - $exsp = substr $temp[10 + $offset], 6; - $exdp = substr $temp[11 + $offset], 6; - } - if ($temp[0] eq 'unknown') { - my $offset = 0; - $protocol = "??? (" . $temp[1] . ")"; - $protocol = "esp (" . $temp[1] . ")" if ($temp[1] == 50); - $protocol = " ah (" . $temp[1] . ")" if ($temp[1] == 51); - $expires = $temp[2]; - $connstatus = ' '; - $orgsip = substr $temp[3], 4; - $orgdip = substr $temp[4], 4; - $orgsp = ' '; - $orgdp = ' '; - $exsip = substr $temp[5], 4; - $exdip = substr $temp[6], 4; - $exsp = ' '; - $exdp = ' '; - $marked = ' '; - $use = ' '; - } - if ($temp[0] eq 'gre') { - my $offset = 0; - $protocol = $temp[0] . " (" . $temp[1] . ")"; - $expires = $temp[2]; - $orgsip = substr $temp[5], 4; - $orgdip = substr $temp[6], 4; - $orgsp = ' '; - $orgdp = ' '; - $exsip = substr $temp[11], 4; - $exdip = substr $temp[12], 4; - $exsp = ' '; - $exdp = ' '; - $marked = $temp[17]; - $use = $temp[18]; - } - $orgsipcolour = &ipcolour($orgsip); - $orgdipcolour = &ipcolour($orgdip); - $exsipcolour = &ipcolour($exsip); - $exdipcolour = &ipcolour($exdip); - print <$protocol - - - - - - - - -END - ; -} -print "
$Lang::tr{'protocol'}$Lang::tr{'expires'}
($Lang::tr{'seconds'})
$Lang::tr{'connection'}
$Lang::tr{'status'}
$Lang::tr{'original'}
$Lang::tr{'source ip and port'}
$Lang::tr{'original'}
$Lang::tr{'dest ip and port'}
$Lang::tr{'expected'}
$Lang::tr{'source ip and port'}
$Lang::tr{'expected'}
$Lang::tr{'dest ip and port'}
$Lang::tr{'marked'}$Lang::tr{'use'}
$expires$connstatus$orgsip:$orgsp$orgdip:$orgdp$exsip:$exsp$exdip:$exdp$marked$use
\n"; - -&Header::closebox(); -&Header::closebigbox(); -&Header::closepage(); - -sub ipcolour($) { - my $id = 0; - my $line; - my $colour = ${Header::colourred}; - my ($ip) = $_[0]; - my $found = 0; - foreach $line (@network) - { - if (!$found && ipv4_in_network( $network[$id] , $masklen[$id], $ip) ) { - $found = 1; - $colour = $colour[$id]; - } - $id++; - } - return $colour -} +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2012 IPFire Team # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +use strict; + +use Net::IPv4Addr qw( :all ); +use Switch; + +# enable only the following on debugging purpose +#use warnings; +#use CGI::Carp 'fatalsToBrowser'; + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/lang.pl"; +require "${General::swroot}/header.pl"; + +my $colour_multicast = "#A0A0A0"; + +# sort arguments for connection tracking table +# the sort field. eg. 1=src IP, 2=dst IP, 3=src port, 4=dst port +my $SORT_FIELD = 0; +# the sort order. (a)scending orr (d)escending +my $SORT_ORDER = 0; +# cgi query arguments +my %cgiin; +# debug mode +my $debug = 0; + +# retrieve query arguments +# note: let a-z A-Z and 0-9 pass as value only +if (length ($ENV{'QUERY_STRING'}) > 0){ + my $name; + my $value; + my $buffer = $ENV{'QUERY_STRING'}; + my @pairs = split(/&/, $buffer); + foreach my $pair (@pairs){ + ($name, $value) = split(/=/, $pair); + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; # e.g. "%20" => " " + $value =~ s/[^a-zA-Z0-9]*//g; # a-Z 0-9 will pass + $cgiin{$name} = $value; + } +} + +&Header::showhttpheaders(); + +my @network=(); +my @masklen=(); +my @colour=(); + +my %netsettings=(); +&General::readhash("${General::swroot}/ethernet/settings", \%netsettings); + +# output cgi query arrguments to browser on debug +if ( $debug ){ + &Header::openbox('100%', 'center', 'DEBUG'); + my $debugCount = 0; + foreach my $line (sort keys %cgiin) { + print "$line = '$cgiin{$line}'
\n"; + $debugCount++; + } + print " Count: $debugCount\n"; + &Header::closebox(); +} + +#workaround to suppress a warning when a variable is used only once +my @dummy = ( ${Header::table1colour} ); +undef (@dummy); + +# check sorting arguments +if ( $cgiin{'sort_field'} ~~ [ '1','2','3','4','5','6','7','8','9' ] ) { + $SORT_FIELD = $cgiin{'sort_field'}; + + if ( $cgiin{'sort_order'} ~~ [ 'a','d','A','D' ] ) { + $SORT_ORDER = lc($cgiin{'sort_order'}); + } +} + +# Read and sort the connection tracking table +# do sorting +if ($SORT_FIELD and $SORT_ORDER) { + # field sorting when sorting arguments are sane + open(CONNTRACK, "/usr/local/bin/getconntracktable | /usr/local/bin/consort.sh $SORT_FIELD $SORT_ORDER |") or die "Unable to read conntrack table"; +} else { + # default sorting with no query arguments + open(CONNTRACK, "/usr/local/bin/getconntracktable | sort -k 5,5 --numeric-sort --reverse |") or die "Unable to read conntrack table"; +} +my @conntrack = ; +close(CONNTRACK); + +# Collect data for the @network array. + +# Add Firewall Localhost 127.0.0.1 +push(@network, '127.0.0.1'); +push(@masklen, '255.255.255.255'); +push(@colour, ${Header::colourfw}); + +if (open(IP, "${General::swroot}/red/local-ipaddress")) { + my $redip = ; + close(IP); + + chomp $redip; + push(@network, $redip); + push(@masklen, '255.255.255.255'); + push(@colour, ${Header::colourfw}); +} + +# Add STATIC RED aliases +if ($netsettings{'RED_DEV'}) { + my $aliasfile = "${General::swroot}/ethernet/aliases"; + open(ALIASES, $aliasfile) or die 'Unable to open aliases file.'; + my @aliases = ; + close(ALIASES); + + # We have a RED eth iface + if ($netsettings{'RED_TYPE'} eq 'STATIC') { + # We have a STATIC RED eth iface + foreach my $line (@aliases) { + chomp($line); + my @temp = split(/\,/,$line); + if ($temp[0]) { + push(@network, $temp[0]); + push(@masklen, $netsettings{'RED_NETMASK'} ); + push(@colour, ${Header::colourfw} ); + } + } + } +} + +# Add Green Firewall Interface +push(@network, $netsettings{'GREEN_ADDRESS'}); +push(@masklen, "255.255.255.255" ); +push(@colour, ${Header::colourfw} ); + +# Add Green Network to Array +push(@network, $netsettings{'GREEN_NETADDRESS'}); +push(@masklen, $netsettings{'GREEN_NETMASK'} ); +push(@colour, ${Header::colourgreen} ); + +# Add Green Routes to Array +my @routes = `/sbin/route -n | /bin/grep $netsettings{'GREEN_DEV'}`; +foreach my $route (@routes) { + chomp($route); + my @temp = split(/[\t ]+/, $route); + push(@network, $temp[0]); + push(@masklen, $temp[2]); + push(@colour, ${Header::colourgreen} ); +} + +# Add Blue Firewall Interface +push(@network, $netsettings{'BLUE_ADDRESS'}); +push(@masklen, "255.255.255.255" ); +push(@colour, ${Header::colourfw} ); + +# Add Blue Network +if ($netsettings{'BLUE_DEV'}) { + push(@network, $netsettings{'BLUE_NETADDRESS'}); + push(@masklen, $netsettings{'BLUE_NETMASK'} ); + push(@colour, ${Header::colourblue} ); + + # Add Blue Routes to Array + @routes = `/sbin/route -n | /bin/grep $netsettings{'BLUE_DEV'}`; + foreach my $route (@routes) { + chomp($route); + my @temp = split(/[\t ]+/, $route); + push(@network, $temp[0]); + push(@masklen, $temp[2]); + push(@colour, ${Header::colourblue} ); + } +} + +# Add Orange Firewall Interface +push(@network, $netsettings{'ORANGE_ADDRESS'}); +push(@masklen, "255.255.255.255" ); +push(@colour, ${Header::colourfw} ); + +# Add Orange Network +if ($netsettings{'ORANGE_DEV'}) { + push(@network, $netsettings{'ORANGE_NETADDRESS'}); + push(@masklen, $netsettings{'ORANGE_NETMASK'} ); + push(@colour, ${Header::colourorange} ); + # Add Orange Routes to Array + @routes = `/sbin/route -n | /bin/grep $netsettings{'ORANGE_DEV'}`; + foreach my $route (@routes) { + chomp($route); + my @temp = split(/[\t ]+/, $route); + push(@network, $temp[0]); + push(@masklen, $temp[2]); + push(@colour, ${Header::colourorange} ); + } +} + +# Highlight multicast connections. +push(@network, "224.0.0.0"); +push(@masklen, "239.0.0.0"); +push(@colour, $colour_multicast); + +# Add OpenVPN net and RED/BLUE/ORANGE entry (when appropriate) +if (-e "${General::swroot}/ovpn/settings") { + my %ovpnsettings = (); + &General::readhash("${General::swroot}/ovpn/settings", \%ovpnsettings); + my @tempovpnsubnet = split("\/",$ovpnsettings{'DOVPN_SUBNET'}); + + # add OpenVPN net + push(@network, $tempovpnsubnet[0]); + push(@masklen, $tempovpnsubnet[1]); + push(@colour, ${Header::colourovpn} ); + + # add BLUE:port / proto + if (($ovpnsettings{'ENABLED_BLUE'} eq 'on') && $netsettings{'BLUE_DEV'}) { + push(@network, $netsettings{'BLUE_ADDRESS'} ); + push(@masklen, '255.255.255.255' ); + push(@colour, ${Header::colourovpn}); + } + + # add ORANGE:port / proto + if (($ovpnsettings{'ENABLED_ORANGE'} eq 'on') && $netsettings{'ORANGE_DEV'}) { + push(@network, $netsettings{'ORANGE_ADDRESS'} ); + push(@masklen, '255.255.255.255' ); + push(@colour, ${Header::colourovpn} ); + } +} + +# Add OpenVPN net for custom OVPNs +if (-e "${General::swroot}/ovpn/ccd.conf") { + open(OVPNSUB, "${General::swroot}/ovpn/ccd.conf"); + my @ovpnsub = ; + close(OVPNSUB); + + foreach (@ovpnsub) { + my ($network, $mask) = split '/', (split ',', $_)[2]; + + $mask = ipv4_cidr2msk($mask) unless &General::validip($mask); + + push(@network, $network); + push(@masklen, $mask); + push(@colour, ${Header::colourovpn}); + } +} + +open(IPSEC, "${General::swroot}/vpn/config"); +my @ipsec = ; +close(IPSEC); + +foreach my $line (@ipsec) { + my @vpn = split(',', $line); + my ($network, $mask) = split("/", $vpn[12]); + + if (!&General::validip($mask)) { + $mask = ipv4_cidr2msk($mask); + } + + push(@network, $network); + push(@masklen, $mask); + push(@colour, ${Header::colourvpn}); +} + +if (-e "${General::swroot}/ovpn/n2nconf") { + open(OVPNN2N, "${General::swroot}/ovpn/ovpnconfig"); + my @ovpnn2n = ; + close(OVPNN2N); + + foreach my $line (@ovpnn2n) { + my @ovpn = split(',', $line); + next if ($ovpn[4] ne 'net'); + + my ($network, $mask) = split("/", $ovpn[12]); + if (!&General::validip($mask)) { + $mask = ipv4_cidr2msk($mask); + } + + push(@network, $network); + push(@masklen, $mask); + push(@colour, ${Header::colourovpn}); + } +} + +# Show the page. +&Header::openpage($Lang::tr{'connections'}, 1, ''); +&Header::openbigbox('100%', 'left'); +&Header::openbox('100%', 'left', $Lang::tr{'connection tracking'}); + +# Print legend. +print < + + + $Lang::tr{'legend'} : + + + $Lang::tr{'lan'} + + + $Lang::tr{'internet'} + + + $Lang::tr{'dmz'} + + + $Lang::tr{'wireless'} + + + IPFire + + + $Lang::tr{'vpn'} + + + $Lang::tr{'OpenVPN'} + + + Multicast + + + +
+END + +if ($SORT_FIELD and $SORT_ORDER) { + my @sort_field_name = ( + $Lang::tr{'source ip'}, + $Lang::tr{'destination ip'}, + $Lang::tr{'source port'}, + $Lang::tr{'destination port'}, + $Lang::tr{'protocol'}, + $Lang::tr{'connection'}.' '.$Lang::tr{'status'}, + $Lang::tr{'expires'}.' ('.$Lang::tr{'seconds'}.')', + $Lang::tr{'download'}, + $Lang::tr{'upload'} + ); + my $sort_order_name; + if (lc($SORT_ORDER) eq "a") { + $sort_order_name = $Lang::tr{'sort ascending'}; + } else { + $sort_order_name = $Lang::tr{'sort descending'}; + } + +print < + $sort_order_name: $sort_field_name[$SORT_FIELD-1] + +END +; +} + +# Print table header. +print < + + + + + + + + +          + + + + + + +        + + + + + + +      + + + + + + + + + + + + + + + $Lang::tr{'protocol'} + + + $Lang::tr{'source ip and port'} + + + $Lang::tr{'dest ip and port'} + + + $Lang::tr{'download'} / +
$Lang::tr{'upload'} + + + $Lang::tr{'connection'}
$Lang::tr{'status'} + + + $Lang::tr{'expires'}
($Lang::tr{'seconds'}) + + +END + +foreach my $line (@conntrack) { + my @conn = split(' ', $line); + + # The first bit is the l3 protocol. + my $l3proto = $conn[0]; + + # Skip everything that is not IPv4. + if ($l3proto ne 'ipv4') { + next; + } + + # L4 protocol (tcp, udp, ...). + my $l4proto = $conn[2]; + + # Translate unknown protocols. + if ($l4proto eq 'unknown') { + my $l4protonum = $conn[3]; + if ($l4protonum eq '2') { + $l4proto = 'IGMP'; + } elsif ($l4protonum eq '4') { + $l4proto = 'IPv4 Encap'; + } elsif ($l4protonum eq '33') { + $l4proto = 'DCCP'; + } elsif ($l4protonum eq '41') { + $l4proto = 'IPv6 Encap'; + } elsif ($l4protonum eq '50') { + $l4proto = 'ESP'; + } elsif ($l4protonum eq '51') { + $l4proto = 'AH'; + } elsif ($l4protonum eq '132') { + $l4proto = 'SCTP'; + } else { + $l4proto = $l4protonum; + } + } else { + $l4proto = uc($l4proto); + } + + # Source and destination. + my $sip; + my $sip_ret; + my $dip; + my $dip_ret; + my $sport; + my $sport_ret; + my $dport; + my $dport_ret; + my @packets; + my @bytes; + + my $ttl = $conn[4]; + my $state; + if ($l4proto eq 'TCP') { + $state = $conn[5]; + } + + # Kick out everything that is not IPv4. + foreach my $item (@conn) { + my ($key, $val) = split('=', $item); + + switch ($key) { + case "src" { + if ($sip == "") { + $sip = $val; + } else { + $dip_ret = $val; + } + } + case "dst" { + if ($dip == "") { + $dip = $val; + } else { + $sip_ret = $val; + } + } + case "sport" { + if ($sport == "") { + $sport = $val; + } else { + $dport_ret = $val; + } + } + case "dport" { + if ($dport == "") { + $dport = $val; + } else { + $sport_ret = $val; + } + } + case "packets" { + push(@packets, $val); + } + case "bytes" { + push(@bytes, $val); + } + } + } + + my $sip_colour = ipcolour($sip); + my $dip_colour = ipcolour($dip); + + my $sserv = ''; + if ($sport < 1024) { + $sserv = uc(getservbyport($sport, lc($l4proto))); + } + + my $dserv = ''; + if ($dport < 1024) { + $dserv = uc(getservbyport($dport, lc($l4proto))); + } + + my $bytes_in = format_bytes($bytes[0]); + my $bytes_out = format_bytes($bytes[1]); + + # Format TTL + $ttl = format_time($ttl); + + my $sip_extra; + if ($sip ne $sip_ret) { + $sip_extra = "> "; + $sip_extra .= ""; + $sip_extra .= " $sip_ret"; + $sip_extra .= ""; + } + + my $dip_extra; + if ($dip ne $dip_ret) { + $dip_extra = "> "; + $dip_extra .= ""; + $dip_extra .= " $dip_ret"; + $dip_extra .= ""; + } + + + my $sport_extra; + if ($sport ne $sport_ret) { + my $sserv_ret = ''; + if ($sport_ret < 1024) { + $sserv_ret = uc(getservbyport($sport_ret, lc($l4proto))); + } + + $sport_extra = "> "; + $sport_extra .= ""; + $sport_extra .= " $sport_ret"; + $sport_extra .= ""; + } + + my $dport_extra; + if ($dport ne $dport_ret) { + my $dserv_ret = ''; + if ($dport_ret < 1024) { + $dserv_ret = uc(getservbyport($dport_ret, lc($l4proto))); + } + + $dport_extra = "> "; + $dport_extra .= ""; + $dport_extra .= " $dport_ret"; + $dport_extra .= ""; + } + + print < + $l4proto + + + $sip + + $sip_extra + + + + $sport + + $sport_extra + + + + $dip + + $dip_extra + + + + $dport + + $dport_extra + + + $bytes_in / $bytes_out + + $state + $ttl + +END +} + +# Close the main table. +print ""; + +&Header::closebox(); +&Header::closebigbox(); +&Header::closepage(); + +sub format_bytes($) { + my $bytes = shift; + my @units = ("B", "k", "M", "G", "T"); + + foreach my $unit (@units) { + if ($bytes < 1024) { + return sprintf("%d%s", $bytes, $unit); + } + + $bytes /= 1024; + } + + return sprintf("%d%s", $bytes, $units[$#units]); +} + +sub format_time($) { + my $time = shift; + + my $seconds = $time % 60; + my $minutes = $time / 60; + + my $hours = 0; + if ($minutes >= 60) { + $hours = $minutes / 60; + $minutes %= 60; + } + + return sprintf("%3d:%02d:%02d", $hours, $minutes, $seconds); +} + +sub ipcolour($) { + my $id = 0; + my $colour = ${Header::colourred}; + my ($ip) = $_[0]; + my $found = 0; + + foreach my $line (@network) { + if ($network[$id] eq '') { + $id++; + } else { + if (!$found && ipv4_in_network($network[$id], $masklen[$id], $ip) ) { + $found = 1; + $colour = $colour[$id]; + } + $id++; + } + } + + return $colour; +} + +1;