Hi ...

We are running a system where we use the libpcap to capture
packets from an ethernet device.  We've been observing a problem where
the monitor program goes into an endless loop and spins for ever.

I've compiled the program with debugging on and observed that the
call-back function is called repeatedly from the libpcap library.

I examined the library and ended up in the pcap_read function in 
pcap-bpf.c

The code follows
snip - snip - snip

round line 110 in 2.2.x  and in -current

------------------

#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);

----------

In our case (from the debug info obtained from our program, I can see that
bhp->bh_caplen and bhp->bh_hdrlen are both zero (0).

(gdb) p *(struct bpf_hdr *)pkt
$11 = {bh_tstamp = {tv_sec = 16652, tv_usec = 0}, bh_caplen = 0, 
  bh_datalen = 33555200, bh_hdrlen = 0}

pkt is bp received back from libpcap.

cnt is -1 when we installed the callback function.

As can be seen ... caplen and hdrlen is then set to 0. bp is smaller
than ep because cc >0 (data was read)

It enters the while loop, set caplen, hdrlen to 0, calls the callback
function.  libpcap then tries to increment bp with the BPF_WORDALIGN
macro.
>From bpf.h
#define BPF_ALIGNMENT sizeof(long)
#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))

This concludes to 
(gdb) p (((0)+(sizeof(long)-1))&~(sizeof(long)-1))
$12 = 0

so bp is NOT incremented and the whole process is repeated and here it
gets stuck in the loop.

I attached a possible fix for this, please review, edit as necessar and
commit :)

The patch is to -current file, put should apply to most other versions
too.

Thankyou

Reinier
Index: pcap-bpf.c
===================================================================
RCS file: /home/freebsd-cvs/src/contrib/libpcap/pcap-bpf.c,v
retrieving revision 1.1.1.3
diff -c -r1.1.1.3 pcap-bpf.c
*** pcap-bpf.c  1998/09/15 19:28:05     1.1.1.3
--- pcap-bpf.c  1999/09/10 10:11:49
***************
*** 117,122 ****
--- 117,130 ----
                 * XXX A bpf_hdr matches a pcap_pkthdr.
                 */
                (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
+               /* 
+                * If we can't increment bp, get out of the while 
+                * We've atleast called the callback with the data 
+                * we have at out disposal - NB : it might be garbage
+                */
+               if (!BPF_WORDALIGN(caplen + hdrlen)) {
+                       break;
+               }
                bp += BPF_WORDALIGN(caplen + hdrlen);
                if (++n >= cnt && cnt > 0) {
                        p->bp = bp;

Reply via email to