1
0
Fork 0
packetq/collector_sample/pq_tracesplit.pl

295 lines
7.6 KiB
Perl
Raw Permalink Normal View History

#!/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;
}