> I believe there's a subtle problem in the description of pcap_dispatch:
>
> pcap_dispatch() is used to collect and process packets. cnt specifies
> the maximum number of packets to process before returning. A cnt of -1
> processes all the packets received in one buffer. A cnt of 0 processes
> all packets until an error occurs, EOF is reached, or the read times out
> (when doing live reads and a non-zero read timeout is specified).
There were actually some non-subtle problems in the description of
"pcap_dispatch()", namely "it doesn't reflect how 'pcap_dispatch()'
actually works" - a cnt of 0 doesn't process all packets until it runs out
of packets or gets a timeout, and, as far as I can tell, never did.
I rewrote the description to say:
pcap_dispatch() is used to collect and process packets. cnt
specifies the maximum number of packets to process before
returning. This is not a minimum number; when reading a
live capture, only one bufferful of packets is read at a
time, so fewer than cnt packets may be processed. A cnt of
-1 processes all the packets received in one buffer when
reading a live capture, or all the packets in the file when
reading a ``savefile''. callback specifies a routine to be
called with three arguments: a u_char pointer which is
passed in from pcap_dispatch(), a pointer to the pcap_pkthdr
struct (which precede the actual network headers and data),
and a u_char pointer to the packet data.
The number of packets read is returned. 0 is returned if no
packets were read from a live capture (if, for example, they
were discarded because they didn't pass the packet filter,
or if, on platforms that support a read timeout that starts
before any packets arrive, the timeout expires before any
packets arrive, or if the file descriptor for the capture
device is in non-blocking mode and no packets were available
to be read) or if no more packets are available in a ``save-
file.'' A return of -1 indicates an error in which case
pcap_perror() or pcap_geterr() may be used to display the
error text.
NOTE: when reading a live capture, pcap_dispatch() will not
necessarily return when the read times out; on some plat-
forms, the read timeout isn't supported, and, on other plat-
forms, the timer doesn't start until at least one packet
arrives. This means that the read timeout should NOT be
used in, for example, an interactive application, to allow
the packet capture loop to ``poll'' for user input periodi-
cally, as there's no guarantee that pcap_dispatch() will
return after the timeout expires.
However:
> There's some missing semantics... here's why:
>
> pcap_dispatch calls pcap_read (for each implementation type).
> pcap_read uses the count to figure out how many to dispatch,
> without retaining state from some previous block read...
are you certain that there are "pcap_read()" implementations that retain
no state from a previous block read? The BPF one does
cc = p->cc;
if (p->cc == 0) {
cc = read(p->fd, (char *)p->buffer, p->bufsize);
[handle errors] if cc < 0
bp = p->buffer;
} else
bp = p->bp;
/*
* Loop through each packet.
*/
#define bhp ((struct bpf_hdr *)bp)
ep = bp + cc;
while (bp < ep) {
register int caplen, hdrlen;
caplen = bhp->bh_caplen;
hdrlen = bhp->bh_hdrlen;
/*
* XXX A bpf_hdr matches a pcap_pkthdr.
*/
(*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
bp += BPF_WORDALIGN(caplen + hdrlen);
if (++n >= cnt && cnt > 0) {
p->bp = bp;
p->cc = ep - bp;
return (n);
}
}
#undef bhp
p->cc = 0;
return (n);
so it appears to keep state in "p->bp" and "p->cc" that keeps track of
how much data is left in the buffer it most recently read into and where
the beginning of that data is.
I think at least some of the other BPF implementations on platforms that
return more than one packet per read (for example, DLPI, which does that
if there's a "bufmod" STREAMS module) behave similarly.
Now, the description perhaps needs some more work to make it clear that
if not all packets in
> so, notice what would happen if someone believed:
>
> /*
> * we just want to dispatch one packet at a time.
> */
> pcap_dispatch( p, 1, target, rock );
>
> according to the description, all the packets should still get
> processed by target...
>
> but what happens instead is that only ONE packet from the
> front of EACH of the buffer's gets processed.. the rest
> get discarded.
>
> Now, that's fine, really, since cnt is meant to mainly deal with
> tcpdump's cnt option, but the description is misleading.
Ethereal uses "pcap_dispatch()" with a count of 1 to read packets during
a live capture; I've not heard of it losing packets in that situation -
are you certain that the other packets will be discarded?
-
This is the TCPDUMP workers list. It is archived at
http://www.tcpdump.org/lists/workers/index.html
To unsubscribe use mailto:[EMAIL PROTECTED]?body=unsubscribe