Search code examples
bashtcpdump

pass as parameter tcpdump output


I want to execute something like this:

sudo tcpdump -n dst port 40010 -X

pass each packet received to bash file read.sh

and foreach packet received execute read.sh

It's like

sudo bash read.sh -y (tcpdump -n dst port 40010 -X)

Or

tcpdump -n dst port 40010 -X > read.sh

Solution

  • The general way to pass output from one command to another is a pipeline.

    tcpdump | script
    

    However, this will cause script to receive a continuous stream of output, one line at a time. The output from tcpdump splits one packet over several lines, so if script assumes it will receive a single packet, you will need to parse the output somehow.

    Based on brief experimentation, something like the following should work:

    tcpdump -n dst port 40010 -X |
    awk '/^[0-9]/ && $2 != "packets" {
            if (p) { print p | "script"; close("script"); } p=$0 }
        /^[ \t]/ { p=p "\n" $0 }
        END { if(p) print p | "script" }'
    

    An additional quirk is that pressing ctrl-C will terminate the whole pipeline, so you will lose the last few packets completely. I avoided this by specifying a number of packets with -c but you could also protect the Awk script by running it with a trap to block signals. However, at this point, I would perhaps consider switching to Python or something. Of course, incorporating the packet splitting into script itself would also help.