diff options
Diffstat (limited to 'collector_sample/pq_tracesplit.pl')
-rw-r--r-- | collector_sample/pq_tracesplit.pl | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/collector_sample/pq_tracesplit.pl b/collector_sample/pq_tracesplit.pl new file mode 100644 index 0000000..3d03731 --- /dev/null +++ b/collector_sample/pq_tracesplit.pl @@ -0,0 +1,294 @@ +#!/usr/bin/perl +# usage: +# start daemon using /etc/packetq.conf: +# pq_tracesplit.pl + +# stop daemon: +# pq_tracesplit.pl stop + +# run in foreground with conf file +# pq_tracesplit.pl -f -c my.conf + +# stop with custom conf file +# pq_tracesplit.pl -c my.conf stop + + + + +use POSIX; +use POSIX qw(setsid); +use Sys::Syslog qw(:DEFAULT setlogsock); # default set, plus setlogsock() +use File::Path; +use File::Copy; +use Getopt::Std; +use Data::Dumper; +use strict; +no strict "subs"; + +my $conffile = "/etc/packetq.conf"; +my %opts; +getopts('fc:', \%opts); +if (defined $opts{c}) +{ + $conffile = $opts{c}; +} +my $foreground = undef; +$foreground = 1 if (defined $opts{f}); + +openlog('pqcollector','pid,perror','LOG_USER'); + +######### read config file + +my %config; +open(CONFIG,$conffile) or die "error reading config file $conffile exiting"; +while (<CONFIG>) +{ + chomp; + next if /^\s*\#/; + next unless /=/; + my ($key, $variable) = split(/=/,$_,2); + $variable =~ s/(\$(\w+))/$config{$2}/g; + $config{$key} = $variable; +} +close CONFIG; + +my $pidfile = $config{'pidfile'}; +my $logfile = "/dev/null"; + +##### start daemon + +if (-e $pidfile) +{ + open (PFILE, $pidfile); + my $pidfromfile = <PFILE>; + close PFILE; + + if (($pidfromfile =~ /[0-9]+/) && kill( 0, $pidfromfile)) + { + if ($ARGV[0] eq 'stop') + { + syslog 'info',"Stopping daemon pid: $pidfromfile\n"; + while (kill( 0, $pidfromfile)) + { + kill( - SIGQUIT, $pidfromfile); + sleep(1); + } + exit; + } + else + { + syslog LOG_INFO,"Pid file $pidfile exist and the program ($pidfromfile) is running ! exiting ...\n"; + } + exit; + } + else + { + unlink($pidfile); + } +} + +if ($ARGV[0] eq 'stop') +{ + syslog 'info',"Cannot stop packetq.pl as it's not running\n"; + exit; +} +&daemonize() unless defined $foreground; +open FILE, ">$pidfile" or die "unable to open pidfile : $pidfile $!"; +print FILE $$."\n"; +close FILE; + +##### catch signals + +my $keep_going = 1; +$SIG{HUP} = sub { print("Caught SIGHUP: exiting gracefully\n"); $keep_going = 0; }; +$SIG{INT} = sub { print("Caught SIGINT: exiting gracefully\n"); $keep_going = 0; }; +$SIG{QUIT} = sub { print("Caught SIGQUIT: exiting gracefully\n"); $keep_going = 0; }; +$SIG{TERM} = sub { print("Caught SIGTERM: exiting gracefully\n"); $keep_going = 0; }; + +########## start collection +foreach my $k (keys %config) +{ + print $k."=".$config{$k}."\n"; + $config{$k} =~ s/^\"(.*)\"$/$1/; +} + +my $interval = $config{'interval'}; +my $interface = $config{'interface'}; +my @interfaces = split(/,/,$interface); +my $filter = $config{'filter'}; +my $server = $config{'server'}; +my $destdir = $config{'destdir'}; + +my $stime = floor(time()/$interval) * $interval + $interval; + +syslog LOG_INFO,"Starting packetq collector daemon (pid:".$$.") destdir: $config{'destdir'}\n"; + +my @tdpid; +my @tspid; +my $ifcnt = 0; +foreach my $if (@interfaces) +{ + if ($config{'bsdpromischack'} eq "YES") + { + my $pid; + #my $tcpdumpcmd="$config{'tcpdump'} -i $if port 100 2>/dev/null"; + my $tcpdumpcmd="$config{'tcpdump'} -i $if port 100"; + $pid = spawn ($tcpdumpcmd); + print "tcp pid $pid"; + if ($pid == 0) + { + syslog LOG_ERROR,"Cannot run $tcpdumpcmd exiting \n"; + exit; + } + syslog LOG_INFO,"Keeping the interface ($if) in promisc mode by letting tcpdump ($pid) listen on port 100 \n"; + @tdpid[$ifcnt] = $pid; + } + + my $tracesplitcmd = $config{'tracesplit'}." pcapint:$if -s $stime -z $config{'compression_level'} -i $interval -f \"$filter\" pcapfile:$destdir/$server-$if"; + my $tspid = spawn($tracesplitcmd); + print "ts pid $tspid"; + if ($tspid == 0) + { + syslog LOG_ERROR,"Cannot run $tracesplitcmd exiting \n"; + exit; + } + syslog LOG_INFO,"Starting tracesplit \"$tracesplitcmd\"(pid:$tspid)\n"; + @tspid[$ifcnt] = $tspid; + + $ifcnt++; +} + +########## infinite loop +reaper(); + +while($keep_going == 1) +{ + foreach my $if (@interfaces) + { + opendir(DIR, $destdir) or last; + my @files; + + while (my $file = readdir(DIR)) + { + # Use a regular expression to ignore files beginning with a period + next if ($file =~ m/^\./); + next unless ($file =~ m/^$server-$if.*/); + push(@files,$file); + } + @files= sort(@files); + if (@files>1) + { + pop @files; + #print "files: \n".join("\n",@files)."\n"; + foreach my $f (@files) + { + if($f =~ /^$server-$if-(.*)\.gz/) + { + ##my ($sec, $min, $hour, $day,$month,$year) = (localtime($1))[0,1,2,3,4,5,6]; + my ($sec, $min, $hour, $day,$month,$year) = (gmtime($1))[0,1,2,3,4,5,6]; + $year+=1900; + $month++; + $sec = "0".$sec if $sec <10; + $min = "0".$min if $min <10; + $hour = "0".$hour if $hour <10; + $day = "0".$day if $day <10; + $month = "0".$month if $month<10; + + my $file = "$server-$year$month$day-$hour$min$sec-$if.pcap.gz"; + my $dir = "$year/$month/$day/$hour"; + my $cmd = $config{command}; + $cmd =~ s/%F/$file/g; + $cmd =~ s/%S/$server/g; + $cmd =~ s/%I/$if/g; + $cmd =~ s/%P/$dir/g; + $cmd =~ s/%Y/$year/g; + $cmd =~ s/%M/$month/g; + $cmd =~ s/%D/$day/g; + $cmd =~ s/%h/$hour/g; + $cmd =~ s/%m/$min/g; + $cmd =~ s/%s/$sec/g; + + #print "$cmd\n"; + + mkpath "$destdir/$dir"; + move ("$destdir/$f","$destdir/$dir/$file"); + spawn($cmd); + #print "hello $hour, $min, $sec,-- $day,$month,$year\n"; + #print "mkdir $dir\n"; + #print "mv $destdir/$f $destdir/$dir/$file\n"; + } + } + } + closedir(DIR); + } + #printf("blipp\n"); + sleep(5); +} + +########## exit cleanup + +syslog 'info',"Shutting down collector ...\n"; +foreach my $pid (@tspid) +{ + if ($pid ne 0) + { + print "Stopping tracesplit ($pid)\n"; + syslog LOG_INFO,"Stopping tracesplit ($pid)\n"; + kill( - SIGABRT, $pid); + } +} + +foreach my $pid (@tdpid) +{ + if ($pid ne 0) + { + syslog LOG_INFO,"Stopping tcpdump ($pid)\n"; + kill( - SIGABRT, $pid); + } +} + +syslog LOG_INFO,"removing pidfile\n"; +unlink($pidfile); + +syslog LOG_INFO,"bye bye\n"; +closelog; +exit; + +########## functions + +sub spawn +{ + my $cmd = shift; + defined(my $pid = fork) or die "Can't fork: $!"; + if ($pid == 0) + { + exec $cmd; + syslog LOG_ERROR,"Couldn't run $cmd\n"; + die "Couldn't run $cmd"; + } + return $pid; +} + +sub daemonize +{ + chdir '/' or die "Can't chdir to /: $!"; + defined(my $pid = fork) or die "Can't fork: $!"; + exit if $pid; + setsid or die "Can't start a new session: $!"; + umask 0; + + open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; + open STDOUT, ">>$logfile" or die "Can't write to $logfile: $!"; + open STDERR, ">>$logfile" or die "Can't write to $logfile: $!"; +} + +sub reaper { + my $stiff; + while ( ($stiff = waitpid(-1, &WNOHANG) ) > 0 ) + { + #print "child $stiff terminated -- status $?"; + } + $SIG{CHLD} = \&reaper; +} + + |