tcpdump mailing list archives

Re: pcap_next/pcap_dispatch on VMware vmnet


From: Chris Morgan <chmorgan () gmail com>
Date: Tue, 10 Mar 2009 12:52:58 -0400

On Tue, Mar 10, 2009 at 3:32 AM, Guy Harris <guy () alum mit edu> wrote:
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.)


Does mac osx have epoll? I'm leaning towards using the poll()/select()
approach with timeout vs. sending signals but I can't really say why.
I guess I know less about which signal to send and the potential side
effects of sending signals.



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().


You mentioned that Linux doesn't support a timeout, I see that the
call used by libpcap is a recvmsg() call. Does Windows have a timeout
on the packet read or do we need a os specific way of checking things
there as well?


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"?


Because we pass each packet off as we receive it we don't buffer
internal to SharpPcap. I thought that for performance reasons
Wireshark would group packets together and upon reaching a high water
mark or exceeding some interval, that the group of packets would be
passed somewhere. Maybe I'm not understanding your initial comments
about buffering but not holding onto packets forever if the buffer
never fills up.


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).


I know these may be dumb questions since if they made sense they would
likely have been implemented already.

Is there some reason not to implement pcap_breakloop() such that it
will send a signal to wake up the pcap_dispatch() thread?  I suppose
that opens a huge can of worms since now you are dealing with cross
platform thread synchronization issues.

Alternatively why not use poll() or select() inside of pcap_dispatch()
to avoid performing the read if there is no pending data? Wouldn't
that let you implement the timeout functionality and be relatively
cross platform?


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.


Ahh. Yeah and I see that pcap_next() calls pcap_dispatch() which
explains the man page recommendation to call pcap_breakloop() when
using pcap_next.

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


Current thread: