> 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

Reply via email to