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>