Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Sep 1999 12:23:14 +0200 (SAT)
From:      Reinier Bezuidenhout <rbezuide@oskar.nanoteq.co.za>
To:        freebsd-hackers@freebsd.org
Cc:        freebsd-current@freebsd.org
Subject:   Endless loop in libpcap 2.2.x/3.x/-current
Message-ID:  <199909101023.MAA09680@oskar.nanoteq.co.za>

next in thread | raw e-mail | index | archive | help

--ELM936958994-8969-0_
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit

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

--ELM936958994-8969-0_
Content-Type: text/plain; charset=ISO-8859-1
Content-Disposition: attachment; filename=pcap.diff
Content-Description: /tmp/pcap.diff
Content-Transfer-Encoding: 7bit

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;

--ELM936958994-8969-0_--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199909101023.MAA09680>