Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

IP Accounting parser

by Viking (Beadle)
on Jan 11, 2001 at 14:49 UTC ( #51111=sourcecode: print w/replies, xml ) Need Help??
Category: Networking Code
Author/Contact Info Bjorn <>
Description: This parses a log file of ipchains IP accounting data and spits it out as a csv. I use this at work for statistical and billing purposes. It is still a work in progress (but it does work) so I'm interested in any comments. The log file is created from a shell script run from a cron, which you will find at the end of the code.

use strict;
use warnings;

my $logfile = $ARGV[0];

my $start_date;
my $end_date;
my %log_totals;

open (FILE< $logfile) or die "Could not open $logfile: $!\n";

for (<FILE>) {
        if (/^\d+/) {
                ($start_date) = m/^(\d+)/o unless ($start_date);
                ($end_date) = m/^(\d+)/o;
        } elsif (/^\s+\d+/o) {
                my ($bytes,$source,$destination,$ports) =
                        ^\s+\d+\s+(\d+)                 # pkts & bytes
                        .+                              # bla bla bla
                        \s+(\S+)                        # source
                        \s+(\S+)                        # destination
                        \s+(n\/a|\w+\s+->\s+\w+)$       # ports

                my ($src_port,$dest_port) = ('any','any');

                ($src_port,$dest_port) = $ports =~ m/(\w+)\s+->\s+(\w+
                        unless ($ports eq 'n/a');
                # print "$bytes,$source,$src_port,$destination,$dest_p

my $start = localtime($start_date);
my $end = localtime($end_date);

print "From: $start\n";
print "To: $end\n";
print "Source Address,Source Port,Destination Address,Destination Port
for my $key (keys %log_totals) {
        print "$key,$log_totals{$key}\n";

sub data2hash {
        my ($bytes,$src_addr,$src_port,$dest_addr,$dest_port) = @_;

        if ($src_addr ne 'anywhere') { # we have a src address match
                if ($src_port ne 'any') { # we have a src port match
                        $log_totals{"$src_addr,$src_port,,"} += $bytes
                } elsif ($dest_port ne 'any') { # we have a dest port 
                        $log_totals{"$src_addr,,,$dest_port"} += $byte
                } else { # only src address match
                        $log_totals{"$src_addr,,,"} += $bytes;
        } elsif ($dest_addr ne 'anywhere') { # we have a dest address 
                if ($src_port ne 'any') { # we have a src port match
                        $log_totals{",$src_port,$dest_addr,"} += $byte
                } elsif ($dest_port ne 'any') { # we have a dest port 
                        $log_totals{",,$dest_addr,$dest_port"} += $byt
                } else { # only dest address match
                        $log_totals{",,$dest_addr,"} += $bytes;
        } else { # shouldn't get here
                print STDERR "eh?\n";

close FILE;

/bin/date +%s >>/var/log/ip-acc/ip-acc.log
/sbin/ipchains -L ip-acc -v -x >>/var/log/ip-acc/ip-acc.log
/sbin/ipchains -Z ip-acc
Replies are listed 'Best First'.
Re: IP Accounting parser
by turnstep (Parson) on Jan 12, 2001 at 02:52 UTC

    Erk! This code:

    open FILE, $logfile || die $!;
    does not act the way you want it to. Because the || has a higher precedence than the comma, what actually happens is this:
    open FILE, ($logfile || die $!);
    see perlop for the complete precedence list.

    If you really want to use the || then put parenthesis around things like so:

    open (FILE, $logfile) || die "Could not open $logfile: $!\n";

    Better yet, use the super-low-priority or, which allows you to acheive your original effect:

    open FILE, $logfile or die "Could not open $logfile: $!\n";

    Best of all, be correct and non-ambigous and use both:

    open (FILE< $logfile) or die "Could not open $logfile: $!\n";

      I always get || and or mixed up, I will attempt to burn the precedence list into my brain.

        It may help to think of or and and as 'lowercase', and thus 'lower precedence' as opposed to || and && which require the use of the shift key, and therefore are 'uppercase' and 'upper precedence'

        You could also just remember that nothing is lower in precedence than and and or

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: sourcecode [id://51111]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (8)
As of 2018-05-24 16:44 GMT
Find Nodes?
    Voting Booth?