Exemple #1
0
/* ARGSUSED */
int
bpfclose(dev_t dev, __unused int flags, __unused int fmt,
	 __unused struct proc *p)
{
	struct bpf_d *d;

	/* Take BPF lock to ensure no other thread is using the device */
	lck_mtx_lock(bpf_mlock);

	d = bpf_dtab[minor(dev)];
	if (d == 0 || d == (void *)1) {
		lck_mtx_unlock(bpf_mlock);
		return (ENXIO);
	}	
	bpf_dtab[minor(dev)] = (void *)1;		/* Mark closing */

	if (d->bd_bif)
		bpf_detachd(d);
	selthreadclear(&d->bd_sel);
#if CONFIG_MACF_NET
	mac_bpfdesc_label_destroy(d);
#endif
	bpf_freed(d);

	/* Mark free in same context as bpfopen comes to check */
	bpf_dtab[minor(dev)] = NULL;			/* Mark closed */
	lck_mtx_unlock(bpf_mlock);
	
	_FREE(d, M_DEVBUF);
	
	return (0);
}
Exemple #2
0
/*
 * Detach a file from its current interface (if attached at all) and attach
 * to the interface indicated by the name stored in ifr.
 * Return an errno or 0.
 */
int
bpf_setif(struct bpf_d *d, struct ifreq *ifr)
{
    struct bpf_if *bp, *candidate = NULL;
    int s, error;

    /*
     * Look through attached interfaces for the named one.
     */
    for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
        struct ifnet *ifp = bp->bif_ifp;

        if (ifp == 0 ||
                strcmp(ifp->if_xname, ifr->ifr_name) != 0)
            continue;

        /*
         * We found the requested interface.
         */
        if (candidate == NULL || candidate->bif_dlt > bp->bif_dlt)
            candidate = bp;
    }

    if (candidate != NULL) {
        /*
         * Allocate the packet buffers if we need to.
         * If we're already attached to requested interface,
         * just flush the buffer.
         */
        if (d->bd_sbuf == 0) {
            error = bpf_allocbufs(d);
            if (error != 0)
                return (error);
        }
        s = splnet();
        if (candidate != d->bd_bif) {
            if (d->bd_bif)
                /*
                 * Detach if attached to something else.
                 */
                bpf_detachd(d);

            bpf_attachd(d, candidate);
        }
        bpf_reset_d(d);
        splx(s);
        return (0);
    }
    /* Not found. */
    return (ENXIO);
}
Exemple #3
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);
}
Exemple #4
0
/*
 * Detach a file from its current interface (if attached at all) and attach
 * to the interface indicated by the name stored in ifr.
 * Return an errno or 0.
 */
static int
bpf_setif(struct bpf_d *d, ifnet_t theywant, u_int32_t dlt)
{
	struct bpf_if *bp;
	int error;
	
	/*
	 * Look through attached interfaces for the named one.
	 */
	for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
		struct ifnet *ifp = bp->bif_ifp;

		if (ifp == 0 || ifp != theywant || (dlt != 0 && dlt != bp->bif_dlt))
			continue;
		/*
		 * We found the requested interface.
		 * If it's not up, return an error.
		 * Allocate the packet buffers if we need to.
		 * If we're already attached to requested interface,
		 * just flush the buffer.
		 */
		if ((ifp->if_flags & IFF_UP) == 0)
			return (ENETDOWN);

		if (d->bd_sbuf == 0) {
			error = bpf_allocbufs(d);
			if (error != 0)
				return (error);
		}
		if (bp != d->bd_bif) {
			if (d->bd_bif)
				/*
				 * Detach if attached to something else.
				 */
				bpf_detachd(d);

			if (bpf_attachd(d, bp) != 0) {
				return ENXIO;
			}
		}
		reset_d(d);
		return (0);
	}
	/* Not found. */
	return (ENXIO);
}
Exemple #5
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);

}
Exemple #6
0
/*
 * Set the data link type of a BPF instance.
 */
static int
bpf_setdlt(struct bpf_d *d, uint32_t dlt)
	

{
	int error, opromisc;
	struct ifnet *ifp;
	struct bpf_if *bp;
	
	if (d->bd_bif->bif_dlt == dlt)
		return (0);
	ifp = d->bd_bif->bif_ifp;
	for (bp = bpf_iflist; bp; bp = bp->bif_next) {
		if (bp->bif_ifp == ifp && bp->bif_dlt == dlt)
			break;
	}
	if (bp != NULL) {
		opromisc = d->bd_promisc;
		bpf_detachd(d);
		error = bpf_attachd(d, bp);
		if (error) {
			printf("bpf_setdlt: bpf_attachd %s%d failed (%d)\n",
				ifnet_name(bp->bif_ifp), ifnet_unit(bp->bif_ifp), error);
			return error;
		}
		reset_d(d);
		if (opromisc) {
			lck_mtx_unlock(bpf_mlock);
			error = ifnet_set_promiscuous(bp->bif_ifp, 1);
			lck_mtx_lock(bpf_mlock);
			if (error)
				printf("bpf_setdlt: ifpromisc %s%d failed (%d)\n",
					   ifnet_name(bp->bif_ifp), ifnet_unit(bp->bif_ifp), error);
			else
				d->bd_promisc = 1;
		}
	}
	return (bp == NULL ? EINVAL : 0);
}