Return to BSD News archive
Xref: sserve comp.os.386bsd.apps:28 comp.os.386bsd.development:136 Newsgroups: comp.os.386bsd.apps,comp.os.386bsd.development Path: sserve!newshost.anu.edu.au!munnari.oz.au!comp.vuw.ac.nz!duncan From: duncan@comp.vuw.ac.nz (Duncan McEwan) Subject: WD8003 Promiscuous mode, Berkeley Packet Filter, and tcpdump Nntp-Posting-Host: bats.comp.vuw.ac.nz Message-ID: <C3nqox.7MC@comp.vuw.ac.nz> Organization: Dept. of Comp. Sci., Victoria Uni. of Wellington, New Zealand. Sender: news@comp.vuw.ac.nz (News Admin) Date: Wed, 10 Mar 1993 05:17:20 GMT Lines: 91 I have built a kernel with the berkeley packet filter included, by following the instructions in the bpf/README file of the tcpdump distribution. Although I've got tcpdump more-or-less working, there are some loose ends that need tidying up. The main problem is that I'm not sure how to put the WD8003 ethernet controller into promiscuous mode, so tcpdump only prints packets sent from, or received by that interface. I don't have a programmers manual for the controller, but I looked at the code in isa/if_we.c and isa/if_wereg.c, and guessed that changing the line in weinit() that read outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_MON); to outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_MON | WD_R_PRO); might work. It didn't :-( The networking stuff still works quite happily with that change, but the interface (or at least, tcpdump) only sees packets sent to or from that interface. A related problem is that I don't understand how the control flow that results in the interface being put into promiscuous mode can work. It looks something like this. tcpdump does ioctl(..., BIOCPROMISC, ...) on the bpf device. bpfioctl calls ifpromisc() (both routines are in net/bpf.c). ifpromisc() sets the IFF_PROMISC flag in ifp->if_flags and calls (*ifp->if_ioctl)(), the device specific ioctl routine, in this case, weioctl(..., SIOCSIFFLAGS, ...). weioctl(), case SIOCSIFFLAGS looks like this: case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) { ifp->if_flags &= ~IFF_RUNNING; westop(ifp->if_unit); } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0) weinit(ifp->if_unit); break; weinit() was modified as per the bpf installation instructions to contain the following... #if NBPFILTER > 0 if (sc->we_if.if_flags & IFF_PROMISC) { /* set the promiscuous bit */ printf("promisc on\n"); /* DEBUG */ outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_MOD | WD_R_PRO); } else { printf("promisc off\n"); /* DEBUG */ outb(sc->we_io_nic_addr + WD_P0_RCR, WD_R_MON); } #endif When I first tried tcpdump the message "promisc on" was not printed, even though a modified ifconfig showed that the IFF_PROMISC flag was set on "we0". On looking closer at the code in weioctl that calls weinit, it seemed to me that whenever tcpdump tries to put the interface into promiscuous mode, both IFF_UP and IFF_RUNNING will be set in if_flags (since up until that time the interface has been working normally). If that is the case, weinit() would never be called. To test this theory, I changed the "else" clause in weioctl() to make it call weinit() unconditionally. After that weinit() was called when tcpdump started up (the "promisc on" message was written out). There is still the problem that my method for putting the interface into promiscuous mode is incorrect, but at least it's a step closer! The above is based on the code for the "we" driver, (after the modifications for bpf have been made), and it is quite likely that I have made some mistake making those modifications. But the "le" (Lance driver) code distributed with the BPF source has essentially identical code in it's leioctl(), so the question of how it expects to put the interface into promiscuous mode applies there as well. Any suggestions as to what I am missing will be gratefully accepted... Duncan.