From 75bc929eb93145ae5418bed8965ff130efbcc9ed Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Wed, 18 Jul 2012 12:21:23 +0200 Subject: [PATCH] Update connections.cgi: Show byte counters. The connections.cgi file has been rewritten to read the needed information directly from the kernel. Byte counters have been added which show how much data has been transmitted over one connection in each direction. --- config/rootfiles/common/misc-progs | 1 + config/rootfiles/core/61/filelists/files | 1 + html/cgi-bin/connections.cgi | 641 ++++++++++++----------- src/misc-progs/Makefile | 6 +- src/misc-progs/getconntracktable.c | 31 ++ 5 files changed, 363 insertions(+), 317 deletions(-) create mode 100644 src/misc-progs/getconntracktable.c diff --git a/config/rootfiles/common/misc-progs b/config/rootfiles/common/misc-progs index adab51bc1..3c0b398d3 100644 --- a/config/rootfiles/common/misc-progs +++ b/config/rootfiles/common/misc-progs @@ -5,6 +5,7 @@ usr/local/bin/backupctrl usr/local/bin/dhcpctrl usr/local/bin/extrahdctrl usr/local/bin/fireinfoctrl +usr/local/bin/getconntracktable usr/local/bin/getipstat usr/local/bin/getiptstate #usr/local/bin/iowrap diff --git a/config/rootfiles/core/61/filelists/files b/config/rootfiles/core/61/filelists/files index 1624d83b5..9d4c2cc98 100644 --- a/config/rootfiles/core/61/filelists/files +++ b/config/rootfiles/core/61/filelists/files @@ -7,4 +7,5 @@ srv/web/ipfire/cgi-bin/ovpnmain.cgi srv/web/ipfire/cgi-bin/proxy.cgi var/ipfire/general-functions.pl var/ipfire/langs +usr/local/bin/getconntracktable usr/sbin/redirect_wrapper diff --git a/html/cgi-bin/connections.cgi b/html/cgi-bin/connections.cgi index 14ee20910..54089d0bb 100644 --- a/html/cgi-bin/connections.cgi +++ b/html/cgi-bin/connections.cgi @@ -2,7 +2,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2007-2011 IPFire Team # +# 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 # @@ -19,13 +19,10 @@ # # ############################################################################### -my @network=(); -my @masklen=(); -my @colour=(); +use strict; use Net::IPv4Addr qw( :all ); - -use strict; +use Switch; # enable only the following on debugging purpose #use warnings; @@ -35,42 +32,62 @@ require '/var/ipfire/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); +&Header::showhttpheaders(); -# Read various files +my @network=(); +my @masklen=(); +my @colour=(); my %netsettings=(); &General::readhash("${General::swroot}/ethernet/settings", \%netsettings); -open (ACTIVE, '/usr/local/bin/getiptstate |') or die 'Unable to open ip_conntrack'; -my @active = ; -close (ACTIVE); +#workaround to suppress a warning when a variable is used only once +my @dummy = ( ${Header::table1colour} ); +undef (@dummy); + +# Read the connection tracking table. +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} ); + my $redip = ; + close(IP); + + chomp $redip; + push(@network, $redip); + push(@masklen, '255.255.255.255'); + push(@colour, ${Header::colourfw}); } -my @vpn = `/usr/local/bin/ipsecctrl I 2>/dev/null|grep erouted|cut -d"]" -f3|cut -d"=" -f4|cut -d";" -f1| sed "s|/| |g"`; - foreach my $route (@vpn) { - chomp($route); - my @temp = split(/[\t ]+/, $route); - if ( $temp[0] eq '$redip' ){next;} - push(@network, $temp[0]); - push(@masklen, $temp[1]); - push(@colour, ${Header::colourvpn} ); - } +# 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); -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'}); @@ -85,32 +102,11 @@ 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} ); - } + chomp($route); + my @temp = split(/[\t ]+/, $route); + push(@network, $temp[0]); + push(@masklen, $temp[2]); + push(@colour, ${Header::colourgreen} ); } # Add Blue Firewall Interface @@ -120,304 +116,317 @@ 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} ); - } + 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 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 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'}); + 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 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}); + } - if ( ($ovpnsettings{'ENABLED_BLUE'} eq 'on') && $netsettings{'BLUE_DEV'} ) { - # add BLUE:port / proto - push(@network, $netsettings{'BLUE_ADDRESS'} ); - push(@masklen, '255.255.255.255' ); - push(@colour, ${Header::colourovpn} ); - } - if ( ($ovpnsettings{'ENABLED_ORANGE'} eq 'on') && $netsettings{'ORANGE_DEV'} ) { - # add ORANGE:port / proto - push(@network, $netsettings{'ORANGE_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 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} ); - } - } - } +open(IPSEC, "/var/ipfire/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}); } -# 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} ); - } -} - -#Establish simple filtering&sorting boxes on top of table - -our %cgiparams; -&Header::getcgihash(\%cgiparams); - -my @list_proto = ($Lang::tr{'all'}, 'icmp', 'udp', 'tcp'); -my @list_state = ($Lang::tr{'all'}, 'SYN_SENT', 'SYN_RECV', 'ESTABLISHED', 'FIN_WAIT', - 'CLOSE_WAIT', 'LAST_ACK', 'TIME_WAIT', 'CLOSE', 'LISTEN'); -my @list_mark = ($Lang::tr{'all'}, '[ASSURED]', '[UNREPLIED]'); -my @list_sort = ('orgsip','protocol', 'expires', 'status', 'orgdip', 'orgsp', - 'orgdp', 'exsip', 'exdip', 'exsp', 'exdp', 'marked'); - -# init or silently correct unknown value... -if ( ! grep ( /^$cgiparams{'SEE_PROTO'}$/ , @list_proto )) { $cgiparams{'SEE_PROTO'} = $list_proto[0] }; -if ( ! grep ( /^$cgiparams{'SEE_STATE'}$/ , @list_state )) { $cgiparams{'SEE_STATE'} = $list_state[0] }; -if ( ($cgiparams{'SEE_MARK'} ne $Lang::tr{'all'}) && # ok the grep should work but it doesn't because of - ($cgiparams{'SEE_MARK'} ne '[ASSURED]') && # the '[' & ']' interpreted as list separator. - ($cgiparams{'SEE_MARK'} ne '[UNREPLIED]') # So, explicitly enumerate items. - ) { $cgiparams{'SEE_MARK'} = $list_mark[0] }; -if ( ! grep ( /^$cgiparams{'SEE_SORT'}$/ , @list_sort )) { $cgiparams{'SEE_SORT'} = $list_sort[0] }; -# *.*.*.* or a valid IP -if ( $cgiparams{'SEE_SRC'} !~ /^(\*\.\*\.\*\.\*\.|\d+\.\d+\.\d+\.\d+)$/) { $cgiparams{'SEE_SRC'} = '*.*.*.*' }; -if ( $cgiparams{'SEE_DEST'} !~ /^(\*\.\*\.\*\.\*\.|\d+\.\d+\.\d+\.\d+)$/) { $cgiparams{'SEE_DEST'} = '*.*.*.*' }; - - -our %entries = (); # will hold the lines analyzed correctly -my $unknownlines = ''; # should be empty all the time... -my $index = 0; # just a counter to make unique entryies in entries - -&Header::showhttpheaders(); +# Show the page. &Header::openpage($Lang::tr{'connections'}, 1, ''); &Header::openbigbox('100%', 'left'); &Header::openbox('100%', 'left', $Lang::tr{'connection tracking'}); -# Build listbox objects -my $menu_proto = &make_select ('SEE_PROTO', $cgiparams{'SEE_PROTO'}, @list_proto); -my $menu_state = &make_select ('SEE_STATE', $cgiparams{'SEE_STATE'}, @list_state); - -print < - - - - - - - - - - -
$Lang::tr{'legend'} : $Lang::tr{'lan'}$Lang::tr{'internet'}$Lang::tr{'dmz'}$Lang::tr{'wireless'}IPFire$Lang::tr{'vpn'}$Lang::tr{'OpenVPN'}
-
- - - - - - - - - - - - - - - - - - - - - - +# Print legend. +print < + + + + + + + + + + +
$Lang::tr{'source ip and port'} $Lang::tr{'dest ip and port'} $Lang::tr{'protocol'}$Lang::tr{'connection'}

$Lang::tr{'status'}
$Lang::tr{'expires'}

($Lang::tr{'seconds'})
 $menu_proto$menu_state 
+ $Lang::tr{'legend'} : + + $Lang::tr{'lan'} + + $Lang::tr{'internet'} + + $Lang::tr{'dmz'} + + $Lang::tr{'wireless'} + + IPFire + + $Lang::tr{'vpn'} + + $Lang::tr{'OpenVPN'} +
+
END -; -my $i=0; -foreach my $line (@active) { - $i++; - if ($i < 3) { - next; - } - chomp($line); - my @temp = split(' ',$line); +# 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 - my ($sip, $sport) = split(':', $temp[0]); - my ($dip, $dport) = split(':', $temp[1]); - my $proto = $temp[2]; - my $state; my $ttl; - if ( $proto eq "esp" ){$state = "";$ttl = $temp[3];} - elsif ( $proto eq "icmp" ){$state = "";$ttl = $temp[4];} - else{$state = $temp[3];$ttl = $temp[4];} - - next if( !( - (($cgiparams{'SEE_PROTO'} eq $Lang::tr{'all'}) || ($proto eq $cgiparams{'SEE_PROTO'} )) - && (($cgiparams{'SEE_STATE'} eq $Lang::tr{'all'}) || ($state eq $cgiparams{'SEE_STATE'} )) - && (($cgiparams{'SEE_SRC'} eq "*.*.*.*") || ($sip eq $cgiparams{'SEE_SRC'} )) - && (($cgiparams{'SEE_DEST'} eq "*.*.*.*") || ($dip eq $cgiparams{'SEE_DEST'} )) - )); +foreach my $line (@conntrack) { + my @conn = split(' ', $line); - if (($proto eq 'udp') && ($ttl eq '')) { - $ttl = $state; - $state = ' '; - } + # The first bit is the l3 protocol. + my $l3proto = $conn[0]; - my $sipcol = ipcolour($sip); - my $dipcol = ipcolour($dip); + # Skip everything that is not IPv4. + if ($l3proto ne 'ipv4') { + next; + } + + # L4 protocol (tcp, udp, ...). + my $l4proto = $conn[2]; + + if ($l4proto eq 'unknown') { + $l4proto = ''; + } + + # Source and destination. + my $sip; + my $dip; + my $sport; + my $dport; + 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" { + $sip = $val; + } + case "dst" { + $dip = $val; + } + case "sport" { + $sport = $val; + } + case "dport" { + $dport = $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($proto))); - if ($sserv ne '') { - $sserv = " ($sserv)"; - } + $sserv = uc(getservbyport($sport, lc($l4proto))); + if ($sserv ne '') { + $sserv = " ($sserv)"; + } } my $dserv = ''; if ($dport < 1024) { - $dserv = uc(getservbyport($dport, lc($proto))); - if ($dserv ne '') { - $dserv = " ($dserv)"; - } + $dserv = uc(getservbyport($dport, lc($l4proto))); + if ($dserv ne '') { + $dserv = " ($dserv)"; + } } - print < - - - $sip - - - - - $sport$sserv - - - - - $dip - - - - - $dport$dserv - - - $proto - $state - $ttl - + my $bytes_in = format_bytes($bytes[0]); + my $bytes_out = format_bytes($bytes[1]); + + # Format TTL + $ttl = format_time($ttl); + + print < + $l4proto + + + $sip + + + + + $sport$sserv + + + + + $dip + + + + + $dport$dserv + + + + $bytes_in / $bytes_out + + $state + $ttl + END -; } -print ""; +# 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 $line; - my $colour = ${Header::colourred}; - my ($ip) = $_[0]; - my $found = 0; - foreach $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 -} + my $id = 0; + my $colour = ${Header::colourred}; + my ($ip) = $_[0]; + my $found = 0; -# Create a string containing a complete SELECT html object -# param1: name -# param2: current value selected -# param3: field list -sub make_select ($,$,$) { - my $select_name = shift; - my $selected = shift; - my $select = ""; - return $select; -} - -# Build a list of IP obtained from the %entries hash -# param1: IP field name -sub get_known_ips ($) { - my $field = shift; - my $qs = $cgiparams{'SEE_SORT'}; # switch the sort order - $cgiparams{'SEE_SORT'} = $field; - - my @liste=('*.*.*.*'); - foreach my $entry ( sort sort_entries keys %entries) { - push (@liste, $entries{$entry}->{$field}) if (! grep (/^$entries{$entry}->{$field}$/,@liste) ); - } - - $cgiparams{'SEE_SORT'} = $qs; #restore sort order - return @liste; -} - -# Used to sort the table containing the lines displayed. -sub sort_entries { #Reverse is not implemented - my $qs=$cgiparams{'SEE_SORT'}; - if ($qs =~ /orgsip|orgdip|exsip|exdip/) { - my @a = split(/\./,$entries{$a}->{$qs}); - my @b = split(/\./,$entries{$b}->{$qs}); - ($a[0]<=>$b[0]) || - ($a[1]<=>$b[1]) || - ($a[2]<=>$b[2]) || - ($a[3]<=>$b[3]); - } elsif ($qs =~ /expire|orgsp|orgdp|exsp|exdp/) { - $entries{$a}->{$qs} <=> $entries{$b}->{$qs}; - } else { - $entries{$a}->{$qs} cmp $entries{$b}->{$qs}; - } + return $colour; } 1; diff --git a/src/misc-progs/Makefile b/src/misc-progs/Makefile index 9f1e3f000..300e9ecbb 100644 --- a/src/misc-progs/Makefile +++ b/src/misc-progs/Makefile @@ -32,7 +32,8 @@ SUID_PROGS = setdmzholes setportfw setxtaccess \ wirelessctrl getipstat getiptstate qosctrl launch-ether-wake \ redctrl syslogdctrl extrahdctrl sambactrl upnpctrl tripwirectrl \ smartctrl clamavctrl addonctrl pakfire mpfirectrl wlanapctrl \ - setaliases urlfilterctrl updxlratorctrl fireinfoctrl rebuildroutes + setaliases urlfilterctrl updxlratorctrl fireinfoctrl rebuildroutes \ + getconntracktable SUID_UPDX = updxsetperms install : all @@ -160,3 +161,6 @@ fireinfoctrl: fireinfoctrl.c setuid.o ../install+setup/libsmooth/varval.o rebuildroutes: rebuildroutes.c setuid.o ../install+setup/libsmooth/varval.o $(COMPILE) -I../install+setup/libsmooth/ rebuildroutes.c setuid.o ../install+setup/libsmooth/varval.o -o $@ + +getconntracktable: getconntracktable.c setuid.o ../install+setup/libsmooth/varval.o + $(COMPILE) -I../install+setup/libsmooth/ getconntracktable.c setuid.o ../install+setup/libsmooth/varval.o -o $@ diff --git a/src/misc-progs/getconntracktable.c b/src/misc-progs/getconntracktable.c new file mode 100644 index 000000000..674b211b5 --- /dev/null +++ b/src/misc-progs/getconntracktable.c @@ -0,0 +1,31 @@ +/* IPFire helper program - getconntracktable + * + * This program is distributed under the terms of the GNU General Public + * Licence. See the file COPYING for details. + * + * The kernel's connection tracking table is not readable by + * non-root users. So this helper will just read and output it. + */ + +#include +#include +#include "setuid.h" + +int main(void) { + if (!(initsetuid())) + exit(1); + + FILE *fp = fopen("/proc/net/nf_conntrack", "r"); + if (fp == NULL) { + exit(1); + } + + /* Read content line by line and write it to stdout. */ + char linebuf[STRING_SIZE]; + while (fgets(linebuf, STRING_SIZE, fp)) { + printf("%s", linebuf); + } + + fclose(fp); + return 0; +}