Beispiel #1
0
/* 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);
}
Beispiel #2
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);

}
Beispiel #3
0
/*
 * 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;
        }
    }
}