I need to connect tcpdump to a virtual interface, have it capture data basically forever, then ship that data to a pipe where another program will use the data. To do this, a thread in a program I am writing needs to fork() then spawn tcpdump in the child process.
Usually, getting a program to work after a fork() is not too big a problem; the syntax for execv/execl will vary by program but it isn't hard to figure out. For tcpdump, it was pretty awful to figure it out.
I googled on it and ran across lots of people saying: "you can't daemonize tcpdump". Find another way.
Well, I did it. This code works. I am providing it here (and likely in other places) just so people can find it and benefit from it.
- Code: Select all
void daemonize_tcpdumpr()
{
pid_t pid;
int rtn;
pid = fork();
if(pid == 0) {
setsid();
freopen("/tmp/tmpfile", "w", stdout);
freopen( "/dev/null", "w", stderr);
rtn = execl("/usr/bin/nice", "-0", "/usr/sbin/tcpdump", "-n", "-e", "-s", "0", "-i", "eth0", NULL);
printf( "Failed to start tcpdump. Error is %d\n", rtn);
_exit(rtn);
}
}
I needed these particular tcpdump options; other users might want other options.
Note that this code outputs to /tmp/tmpfile, which is identified by redirecting stdout. If you close stdout before calling this function (if the caller is daemonized), then you need to save the handle using dup so you can restore it here in order to reopen it.
This code works on linux and on freebsd. I actually need it for freebsd, but debugged it on linux because the tools are better.