tcpdump mailing list archives

Re: pcap_next/pcap_dispatch on VMware vmnet


From: "Guy Harris" <guy () alum mit edu>
Date: Tue, 10 Mar 2009 00:32:10 -0700 (PDT)

Chris Morgan wrote:
On Mon, Mar 9, 2009 at 7:51 PM, Guy Harris <guy () alum mit edu> wrote:
Well, the first question is "why is blocking forever an issue?"

Is the application also going to, for example, accept input from other
sources while it's reading captured packets?

Well I noticed the issue when I was trying to shut the capture down
gracefully.

Blocking may not be a huge issue. We can forcefully terminate the
capture thread if it doesn't respond within a period of time to a flag
that indicates it should shutdown, it just wasn't my first thought.

On UN*X systems, there are two possibilities I can think of offhand:

    1) if the shutdown done as the result of a signal, one could arrange
that the signal interrupt system calls and, in the signal handler, use
pcap_breakloop() - the system call reading packets will return an
error of EINTR (interrupted system call) when the signal handler
returns, and (at least in newer versions of libpcap that have
pcap_breakloop()) will, when they see that error, check whether the
"break the loop" flag is set and break out of the pcap_loop() or
pcap_dispatch() loop.

    2) a poll() or select() loop (but not poll() on OS X!) with a timeout
could be used, and the flag checked whenever select() or poll()
returns.  (That will also work with a signal, as select() or poll()
will give an error of EINTR.)

If you want one thread to be able to shutdown the capturing in another
thread that's running the capture loop, that might be harder.  From a
quick look at the Single UNIX Specification, one possibility might be that
all threads other than the capturing thread could block a signal such as
SIGUSR1 or SIGUSR2, the thread doing the capturing could catch that signal
and call pcap_breakloop(), and the thread trying to shutdown the capturing
could send that signal to the process with kill().

A similar scheme to the one described in the previous paragraph might work
on Windows - use WaitForSingleObjectEx() or WaitForMultipleObjectsEx(),
with the "bAlertable" argument being TRUE,  and with QueueUserAPC() used
to queue for the target thread an APC that calls pcap_breakloop().

One nagging question is the issue of passing the pointer of a managed
function into pcap. I'm wondering if terminating the thread will
result in additional events from pcap_dispatch(). The man page
indicates this is possible with pcap_loop() and pcap_breakloop() so we
might as well take care to not have the handler memory be garbage
collected too early.

Yes.

We currently create a thread for each capture device and call back the
user code when packets arrive. Does this remove the requirement for
buffering with timeout since we'll pass the packets off after each
arrives?

What do you mean by "requirement for buffering with timeout"?

Is the timeout something checked after each packet is received?

The timeout is implemented in the OS code that libpcap uses, not in
libpcap itself.  Some platforms don't have a timeout at all (e.g., Linux);
some platforms have a timer that's started when libpcap (or whatever code
is reading the packets) starts reading (*BSD, Mac OS X, Tru64 UNIX,
Windows with WinPcap); some platforms have a timer that's started when a
packet arrives (Solaris).

Is this why pcap_next() is blocking, because no packets are arriving?

That's why code that expects pcap_next() - or pcap_dispatch() or
pcap_loop() or pcap_next_ex() - not to block indefinitely until packets
arrive will not work on a number of OSes, including Linux and Solaris.


-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.


Current thread: