Question

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.

Was it helpful?

Solution

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 ...')
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top