From owner-freebsd-current Fri Sep 10 3:24:31 1999 Delivered-To: freebsd-current@freebsd.org Received: from oskar.nanoteq.co.za (oskar.nanoteq.co.za [196.37.91.10]) by hub.freebsd.org (Postfix) with ESMTP id D791914EB5; Fri, 10 Sep 1999 03:21:03 -0700 (PDT) (envelope-from rbezuide@oskar.nanoteq.co.za) Received: (from rbezuide@localhost) by oskar.nanoteq.co.za (8.9.0/8.9.0) id MAA09680; Fri, 10 Sep 1999 12:23:18 +0200 (SAT) From: Reinier Bezuidenhout Message-Id: <199909101023.MAA09680@oskar.nanoteq.co.za> Subject: Endless loop in libpcap 2.2.x/3.x/-current To: freebsd-hackers@freebsd.org Date: Fri, 10 Sep 1999 12:23:14 +0200 (SAT) Cc: freebsd-current@freebsd.org X-Mailer: ELM [version 2.4ME+ PL28 (25)] MIME-Version: 1.0 Content-Type: multipart/mixed; boundary=ELM936958994-8969-0_ Content-Transfer-Encoding: 7bit Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG --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