tcpdump mailing list archives

Re: pcap_next/pcap_dispatch on VMware vmnet device


From: Chris Morgan <chmorgan () gmail com>
Date: Mon, 9 Mar 2009 20:51:08 -0400

On Mon, Mar 9, 2009 at 7:51 PM, Guy Harris <guy () alum mit edu> wrote:

On Mar 9, 2009, at 4:10 PM, Chris Morgan wrote:

Opening a live capture as root (using sudo), on a vmware bridge device
on Linux 2.6.27, using a timeout of 1000ms. I'm seeing pcap_next() and
pcap_dispatch() getting stuck reading, no timeouts are occurring. Is
there a robust and efficient way of reading packets that won't block
forever like this?

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


I'm doing this from that c# library so while I've
thought of using poll() on the devices file descriptor I wanted to
avoid doing low level calls like this so the code would work with
winpcap/pcap on windows/linux platforms.

At least in the case where the app is going to accept input from other
sources, that's what select(), poll(),
WaitForMultipleObjects/MsgWaitForMultipleObjects, etc. are intended for -
they'll wake up if packets arrive or if one of the other sources of input
have input available, rather than having a hack wherein one is (incorrectly)
expecting the timer for the timeout to

       1) exist (which it doesn't, on some platforms)

and

       2) start timing when you start the read rather than when and *if* the
first packet arrives (which it doesn't, on some platforms, e.g. Solaris; the
Solaris timer starts when the first packet is seen, and, at least according
to the bufmod(7) man page, restarts it on each packet - the man page says

       To ensure that messages do not languish forever in an accumulating
chunk, bufmod maintains a read timeout. Whenever this timeout expires, the
module closes off the current chunk and passes it upward. The module
restarts the timeout period when it receives a read side data message and a
timeout is not currently active. These two rules insure that bufmod
minimizes the number of chunks it produces during periods of intense message
activity and that it periodically disposes of all messages during slack
intervals, but avoids any timeout overhead when there is no activity.

          indicating that the purpose of the timeout is *not* to enable
polling, but to allow batching of packets without having packets remain
undelivered for an indefinite period of time).

Yes, it's platform-dependent, so you might have to find some way to hide
that beneath your C# class.

Given that, note also that there is at least one UN*X where, unfortunately,
poll() *doesn't* work on the descriptor you get for a pcap_t - Mac OS X,
where, unfortunately, in Mac OS X 10.4 and 10.5, poll() doesn't work on
*any* character special files, including not only the BPF devices that
libpcap uses but also ttys and pseudo-ttys (a source of a number of problems
with various bits of software).  select() *does* work on them;
unfortunately, a lot of apps - and libraries such as GLib, as used by GTK+,
for example - use poll() in their event loops.

There are also issues with select() and poll() and BPF devices, wherein you
don't get a wakeup if the read completes due to the timer expiring, so you
need to

       1) put the descriptor for the BPF device in non-blocking mode;

       2) use a timeout in select() or poll();

       3) read from the BPF device when select() or poll() returns,
*regardless* of whether select() or poll() indicates that a read is
possible.
-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.


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?

Is the timeout something checked after each packet is received? Is
this why pcap_next() is blocking, because no packets are arriving?

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


Current thread: