FreeBSD/sys/net/bpf.c
/*
 * Set d's packet filter program to fp.  If this file already has a filter,
 * free it and replace it.  Returns EINVAL for bogus requests.
 *
 * Note we need global lock here to serialize bpf_setf() and bpf_setif() calls
 * since reading d->bd_bif can't be protected by d or interface lock due to
 * lock order.
 *
 * Additionally, we have to acquire interface write lock due to bpf_mtap() uses
 * interface read lock to read all filers.
 *
 */
Set d's packet filter program to fp.  If this file already has a filter,
free it and replace it.  Returns EINVAL for bogus requests.

Note we need global lock here to serialize bpf_setf() and bpf_setif() calls
since reading d->bd_bif can't be protected by d or interface lock due to
lock order.

Additionally, we have to acquire interface write lock due to bpf_mtap() uses
interface read lock to read all filers.
Set d ' s packet filter program to fp . If this file already has a filter free it and replace it . Returns EINVAL for bogus requests . Note we need global lock here to serialize bpf_setf () and bpf_setif () calls since reading d - > bd_bif can ' t be protected by d or interface lock due to lock order . Additionally we have to acquire interface write lock due to bpf_mtap () uses interface read lock to read all filers .
static int
bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
{
#ifdef COMPAT_FREEBSD32
	struct bpf_program fp_swab;
	struct bpf_program32 *fp32;
#endif
	struct bpf_insn *fcode, *old;
#ifdef BPF_JITTER
	bpf_jit_filter *jfunc, *ofunc;
#endif
	size_t size;
	u_int flen;
	int need_upgrade;
#ifdef COMPAT_FREEBSD32
	switch (cmd) {
	case BIOCSETF32:
	case BIOCSETWF32:
	case BIOCSETFNR32:
		fp32 = (struct bpf_program32 *)fp;
		fp_swab.bf_len = fp32->bf_len;
		fp_swab.bf_insns = (struct bpf_insn *)(uintptr_t)fp32->bf_insns;
		fp = &fp_swab;
		switch (cmd) {
		case BIOCSETF32:
			cmd = BIOCSETF;
			break;
		case BIOCSETWF32:
			cmd = BIOCSETWF;
			break;
		}
		break;
	}
#endif
	fcode = NULL;
#ifdef BPF_JITTER
	jfunc = ofunc = NULL;
#endif
	need_upgrade = 0;
	flen = fp->bf_len;
	if (flen > bpf_maxinsns || (fp->bf_insns == NULL && flen != 0))
		return (EINVAL);
	size = flen * sizeof(*fp->bf_insns);
	if (size > 0) {
		fcode = malloc(size, M_BPF, M_WAITOK);
		if (copyin(fp->bf_insns, fcode, size) != 0 ||
		    !bpf_validate(fcode, flen)) {
			free(fcode, M_BPF);
			return (EINVAL);
		}
#ifdef BPF_JITTER
		jfunc = bpf_jitter(fcode, flen);
#endif
	}
	BPF_LOCK();
	if (d->bd_bif != NULL)
		BPFIF_WLOCK(d->bd_bif);
	BPFD_LOCK(d);
	if (cmd == BIOCSETWF) {
		old = d->bd_wfilter;
		d->bd_wfilter = fcode;
	} else {
		old = d->bd_rfilter;
		d->bd_rfilter = fcode;
#ifdef BPF_JITTER
		ofunc = d->bd_bfilter;
		d->bd_bfilter = jfunc;
#endif
		if (cmd == BIOCSETF)
			reset_d(d);
		need_upgrade = bpf_check_upgrade(cmd, d, fcode, flen);
	}
	BPFD_UNLOCK(d);
	if (d->bd_bif != NULL)
		BPFIF_WUNLOCK(d->bd_bif);
	if (old != NULL)
		free(old, M_BPF);
#ifdef BPF_JITTER
	if (ofunc != NULL)
		bpf_destroy_jit_filter(ofunc);
#endif
	if (need_upgrade != 0)
		bpf_upgraded(d);
	BPF_UNLOCK();
	return (0);
}
static int bpf_setf ( struct bpf_d * d , struct bpf_program * fp , u_long cmd ) { #ifdef COMPAT_FREEBSD32 struct bpf_program fp_swab ; struct bpf_program32 * fp32 ; #endif struct bpf_insn * fcode , * old ; #ifdef BPF_JITTER bpf_jit_filter * jfunc , * ofunc ; #endif size_t size ; u_int flen ; int need_upgrade ; #ifdef COMPAT_FREEBSD32 switch ( cmd ) { case BIOCSETF32 : case BIOCSETWF32 : case BIOCSETFNR32 : fp32 = ( struct bpf_program32 * ) fp ; fp_swab . bf_len = fp32 -> bf_len ; fp_swab . bf_insns = ( struct bpf_insn * ) ( uintptr_t ) fp32 -> bf_insns ; fp = & fp_swab ; switch ( cmd ) { case BIOCSETF32 : cmd = BIOCSETF ; break ; case BIOCSETWF32 : cmd = BIOCSETWF ; break ; } break ; } #endif fcode = NULL ; #ifdef BPF_JITTER jfunc = ofunc = NULL ; #endif need_upgrade = 0 ; flen = fp -> bf_len ; if ( flen > bpf_maxinsns || ( fp -> bf_insns == NULL && flen != 0 ) ) return ( EINVAL ) ; size = flen * sizeof ( * fp -> bf_insns ) ; if ( size > 0 ) { fcode = malloc ( size , M_BPF , M_WAITOK ) ; if ( copyin ( fp -> bf_insns , fcode , size ) != 0 || ! bpf_validate ( fcode , flen ) ) { free ( fcode , M_BPF ) ; return ( EINVAL ) ; } #ifdef BPF_JITTER jfunc = bpf_jitter ( fcode , flen ) ; #endif } BPF_LOCK ( ) ; if ( d -> bd_bif != NULL ) BPFIF_WLOCK ( d -> bd_bif ) ; BPFD_LOCK ( d ) ; if ( cmd == BIOCSETWF ) { old = d -> bd_wfilter ; d -> bd_wfilter = fcode ; } else { old = d -> bd_rfilter ; d -> bd_rfilter = fcode ; #ifdef BPF_JITTER ofunc = d -> bd_bfilter ; d -> bd_bfilter = jfunc ; #endif if ( cmd == BIOCSETF ) reset_d ( d ) ; need_upgrade = bpf_check_upgrade ( cmd , d , fcode , flen ) ; } BPFD_UNLOCK ( d ) ; if ( d -> bd_bif != NULL ) BPFIF_WUNLOCK ( d -> bd_bif ) ; if ( old != NULL ) free ( old , M_BPF ) ; #ifdef BPF_JITTER if ( ofunc != NULL ) bpf_destroy_jit_filter ( ofunc ) ; #endif if ( need_upgrade != 0 ) bpf_upgraded ( d ) ; BPF_UNLOCK ( ) ; return ( 0 ) ; }
Set d's packet filter program to fp.
Set d ' s packet filter program to fp .
/*
	 * Check new filter validness before acquiring any locks.
	 * Allocate memory for new filter, if needed.
	 */ /* We're setting up new filter.  Copy and check actual data. */ /* Filter is copied inside fcode and is perfectly valid. */ /*
	 * Set up new filter.
	 * Protect filter change by interface lock.
	 * Additionally, we are protected by global lock here.
	 */ /* Move d to active readers list. */