Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

killing tcpdump without corrupting the capture

Tags:

perl

tcpdump

I'm trying to do a capture with tcpdump from within a perl script. The idea is to capture 10000 packets OR 10 seconds, whichever comes first. I have code that works for 10000 packets, but if I send a SIGINT or SIGTERM to tcpdump to cancel it, the output seems to get corrupt, causing problems with the rest of the script (which processes the raw output of the tcpdump).

Relevant perl code:

    defined(my $pid = fork()) or die "Cannot fork: $!";
    if($pid){
        #parent
        my ($kid,$wait_time) = (0,0);
        do{
            sleep 1;
            $wait_time++;
            $kid = waitpid(-1, WNOHANG);
        }until ($kid > 0 || $wait_time > $MAX_TIME_SEC);

        #kill the child
        if ($kid <= 0){
            kill('SIGTERM',$pid);
        } 
    }else{
        #child runs tcpdump to get raw data and write it to a temporary file
        exec('tcpdump','-ieth1','-s0','-c'.$MAX_PACKETS,'-w'.$dmp_name);
    }

What happens next is that the dump file produced by that tcpdump is fed into tshark which produces this error:

tshark: "TheDumpFileFromAbove" appears to have been cut short in the middle of a packet.

From what I read in the man page of tcpdump, sending a SIGTERM or SIGINT ought to work correctly (I've tried both):

if run with the -c flag, it will capture packets until it is interrupted by a SIGINT or SIGTERM signal or the specified number of packets have been processed.

like image 704
Ryley Avatar asked Dec 05 '25 05:12

Ryley


2 Answers

OK, so the issue turns out to be a race condition:

kill('SIGTERM',$pid);

That tells tcpdump to exit gracefully, and one of the things it does in there is write out statistics about the capture (i.e. how many packets). I noticed that if I put a print statement right after that kill, sometimes it showed up before the statistics, sometimes after. So the solution is to wait until tcpdump is done before continuing on to the next command that processes the output from tcpdump:

waitpid($pid,0);
system('tshark -r dumpcapfile ...')
like image 107
Ryley Avatar answered Dec 07 '25 21:12

Ryley


OK, so the issue turns out to be a race condition:

kill('SIGTERM',$pid);

That tells tcpdump to exit gracefully, and one of the things it does in there is write out statistics about the capture (i.e. how many packets). I noticed that if I put a print statement right after that kill, sometimes it showed up before the statistics, sometimes after. So the solution is to wait until tcpdump is done before continuing on to the next command that processes the output from tcpdump:

waitpid($pid,0);
system('tshark -r dumpcapfile ...')
like image 35
Ryley Avatar answered Dec 07 '25 22:12

Ryley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!