/* ARGSUSED */ int bpfclose(dev_t dev, int flag, int mode, struct proc *p) { struct bpf_d *d; int s; d = bpfilter_lookup(minor(dev)); s = splnet(); if (d->bd_bif) bpf_detachd(d); bpf_wakeup(d); D_PUT(d); splx(s); return (0); }
/* * Detach bpf from an interface. This involves detaching each descriptor * associated with the interface, and leaving bd_bif NULL. Notify each * descriptor as it's detached so that any sleepers wake up and get * ENXIO. */ void bpfdetach(struct ifnet *ifp) { struct bpf_if *bp, *bp_prev, *bp_next; struct bpf_if *bp_free = NULL; struct bpf_d *d; lck_mtx_lock(bpf_mlock); /* Locate BPF interface information */ bp_prev = NULL; for (bp = bpf_iflist; bp != NULL; bp = bp_next) { bp_next = bp->bif_next; if (ifp != bp->bif_ifp) { bp_prev = bp; continue; } while ((d = bp->bif_dlist) != NULL) { bpf_detachd(d); bpf_wakeup(d); } if (bp_prev) { bp_prev->bif_next = bp->bif_next; } else { bpf_iflist = bp->bif_next; } bp->bif_next = bp_free; bp_free = bp; ifnet_release(ifp); } lck_mtx_unlock(bpf_mlock); FREE(bp, M_DEVBUF); }
/* * Move the packet data from interface memory (pkt) into the * store buffer. Return 1 if it's time to wakeup a listener (buffer full), * otherwise 0. "copy" is the routine called to do the actual data * transfer. bcopy is passed in to copy contiguous chunks, while * bpf_mcopy is passed in to copy mbuf chains. In the latter case, * pkt is really an mbuf. */ void bpf_catchpacket(struct bpf_d *d, u_char *pkt, size_t pktlen, size_t snaplen, void (*cpfn)(const void *, void *, size_t)) { struct bpf_hdr *hp; int totlen, curlen; int hdrlen = d->bd_bif->bif_hdrlen; struct timeval tv; /* * Figure out how many bytes to move. If the packet is * greater or equal to the snapshot length, transfer that * much. Otherwise, transfer the whole packet (unless * we hit the buffer size limit). */ totlen = hdrlen + min(snaplen, pktlen); if (totlen > d->bd_bufsize) totlen = d->bd_bufsize; /* * Round up the end of the previous packet to the next longword. */ curlen = BPF_WORDALIGN(d->bd_slen); if (curlen + totlen > d->bd_bufsize) { /* * This packet will overflow the storage buffer. * Rotate the buffers if we can, then wakeup any * pending reads. */ if (d->bd_fbuf == 0) { /* * We haven't completed the previous read yet, * so drop the packet. */ ++d->bd_dcount; return; } ROTATE_BUFFERS(d); bpf_wakeup(d); curlen = 0; } /* * Append the bpf header. */ hp = (struct bpf_hdr *)(d->bd_sbuf + curlen); microtime(&tv); hp->bh_tstamp.tv_sec = tv.tv_sec; hp->bh_tstamp.tv_usec = tv.tv_usec; hp->bh_datalen = pktlen; hp->bh_hdrlen = hdrlen; /* * Copy the packet data into the store buffer and update its length. */ (*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen)); d->bd_slen = curlen + totlen; if (d->bd_immediate) { /* * Immediate mode is set. A packet arrived so any * reads should be woken up. */ bpf_wakeup(d); } if (d->bd_rdStart && (d->bd_rtout + d->bd_rdStart < ticks)) { /* * we could be selecting on the bpf, and we * may have timeouts set. We got here by getting * a packet, so wake up the reader. */ if (d->bd_fbuf) { d->bd_rdStart = 0; ROTATE_BUFFERS(d); bpf_wakeup(d); curlen = 0; } } }