Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 Jan 2007 13:08:45 GMT
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 113664 for review
Message-ID:  <200701291308.l0TD8jDQ016841@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=113664

Change 113664 by rwatson@rwatson_cinnamon on 2007/01/29 13:08:15

	Trim a lot of stuff from bpf_buffer.c, mostly the right stuff sort of.

Affected files ...

.. //depot/projects/zcopybpf/src/sys/net/bpf_buffer.c#2 edit

Differences ...

==== //depot/projects/zcopybpf/src/sys/net/bpf_buffer.c#2 (text+ko) ====

@@ -86,373 +86,6 @@
 #define PRINET  26			/* interruptible */
 
 /*
- * bpf_iflist is a list of BPF interface structures, each corresponding to a
- * specific DLT.  The same network interface might have several BPF interface
- * structures registered by different layers in the stack (i.e., 802.11
- * frames, ethernet frames, etc).
- */
-static LIST_HEAD(, bpf_if)	bpf_iflist;
-static struct mtx	bpf_mtx;		/* bpf global lock */
-static int		bpf_bpfd_cnt;
-
-static void	bpf_allocbufs(struct bpf_d *);
-static void	bpf_attachd(struct bpf_d *, struct bpf_if *);
-static void	bpf_detachd(struct bpf_d *);
-static void	bpf_freed(struct bpf_d *);
-static void	bpf_mcopy(const void *, void *, size_t);
-static int	bpf_movein(struct uio *, int, int,
-		    struct mbuf **, struct sockaddr *, struct bpf_insn *);
-static int	bpf_setif(struct bpf_d *, struct ifreq *);
-static void	bpf_timed_out(void *);
-static __inline void
-		bpf_wakeup(struct bpf_d *);
-static void	catchpacket(struct bpf_d *, u_char *, u_int,
-		    u_int, void (*)(const void *, void *, size_t),
-		    struct timeval *);
-static void	reset_d(struct bpf_d *);
-static int	 bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd);
-static int	bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
-static int	bpf_setdlt(struct bpf_d *, u_int);
-static void	filt_bpfdetach(struct knote *);
-static int	filt_bpfread(struct knote *, long);
-static void	bpf_drvinit(void *);
-static void	bpf_clone(void *, struct ucred *, char *, int, struct cdev **);
-static int	bpf_stats_sysctl(SYSCTL_HANDLER_ARGS);
-
-/*
- * The default read buffer size is patchable.
- */
-SYSCTL_NODE(_net, OID_AUTO, bpf, CTLFLAG_RW, 0, "bpf sysctl");
-static int bpf_bufsize = 4096;
-SYSCTL_INT(_net_bpf, OID_AUTO, bufsize, CTLFLAG_RW,
-    &bpf_bufsize, 0, "");
-static int bpf_maxbufsize = BPF_MAXBUFSIZE;
-SYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,
-    &bpf_maxbufsize, 0, "");
-static int bpf_maxinsns = BPF_MAXINSNS;
-SYSCTL_INT(_net_bpf, OID_AUTO, maxinsns, CTLFLAG_RW,
-    &bpf_maxinsns, 0, "Maximum bpf program instructions");
-SYSCTL_NODE(_net_bpf, OID_AUTO, stats, CTLFLAG_RW,
-    bpf_stats_sysctl, "bpf statistics portal");
-
-static	d_open_t	bpfopen;
-static	d_close_t	bpfclose;
-static	d_read_t	bpfread;
-static	d_write_t	bpfwrite;
-static	d_ioctl_t	bpfioctl;
-static	d_poll_t	bpfpoll;
-static	d_kqfilter_t	bpfkqfilter;
-
-static struct cdevsw bpf_cdevsw = {
-	.d_version =	D_VERSION,
-	.d_flags =	D_NEEDGIANT,
-	.d_open =	bpfopen,
-	.d_close =	bpfclose,
-	.d_read =	bpfread,
-	.d_write =	bpfwrite,
-	.d_ioctl =	bpfioctl,
-	.d_poll =	bpfpoll,
-	.d_name =	"bpf",
-	.d_kqfilter =	bpfkqfilter,
-};
-
-static struct filterops bpfread_filtops =
-	{ 1, NULL, filt_bpfdetach, filt_bpfread };
-
-static int
-bpf_movein(struct uio *uio, int linktype, int mtu, struct mbuf **mp,
-    struct sockaddr *sockp, struct bpf_insn *wfilter)
-{
-	const struct ieee80211_bpf_params *p;
-	struct mbuf *m;
-	int error;
-	int len;
-	int hlen;
-	int slen;
-
-	/*
-	 * Build a sockaddr based on the data link layer type.
-	 * We do this at this level because the ethernet header
-	 * is copied directly into the data field of the sockaddr.
-	 * In the case of SLIP, there is no header and the packet
-	 * is forwarded as is.
-	 * Also, we are careful to leave room at the front of the mbuf
-	 * for the link level header.
-	 */
-	switch (linktype) {
-
-	case DLT_SLIP:
-		sockp->sa_family = AF_INET;
-		hlen = 0;
-		break;
-
-	case DLT_EN10MB:
-		sockp->sa_family = AF_UNSPEC;
-		/* XXX Would MAXLINKHDR be better? */
-		hlen = ETHER_HDR_LEN;
-		break;
-
-	case DLT_FDDI:
-		sockp->sa_family = AF_IMPLINK;
-		hlen = 0;
-		break;
-
-	case DLT_RAW:
-		sockp->sa_family = AF_UNSPEC;
-		hlen = 0;
-		break;
-
-	case DLT_NULL:
-		/*
-		 * null interface types require a 4 byte pseudo header which
-		 * corresponds to the address family of the packet.
-		 */
-		sockp->sa_family = AF_UNSPEC;
-		hlen = 4;
-		break;
-
-	case DLT_ATM_RFC1483:
-		/*
-		 * en atm driver requires 4-byte atm pseudo header.
-		 * though it isn't standard, vpi:vci needs to be
-		 * specified anyway.
-		 */
-		sockp->sa_family = AF_UNSPEC;
-		hlen = 12;	/* XXX 4(ATM_PH) + 3(LLC) + 5(SNAP) */
-		break;
-
-	case DLT_PPP:
-		sockp->sa_family = AF_UNSPEC;
-		hlen = 4;	/* This should match PPP_HDRLEN */
-		break;
-
-	case DLT_IEEE802_11:		/* IEEE 802.11 wireless */
-		sockp->sa_family = AF_IEEE80211;
-		hlen = 0;
-		break;
-
-	case DLT_IEEE802_11_RADIO:	/* IEEE 802.11 wireless w/ phy params */
-		sockp->sa_family = AF_IEEE80211;
-		sockp->sa_len = 12;	/* XXX != 0 */
-		hlen = sizeof(struct ieee80211_bpf_params);
-		break;
-
-	default:
-		return (EIO);
-	}
-
-	len = uio->uio_resid;
-
-	if (len - hlen > mtu)
-		return (EMSGSIZE);
-
-	if ((unsigned)len > MCLBYTES)
-		return (EIO);
-
-	if (len > MHLEN) {
-		m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR);
-	} else {
-		MGETHDR(m, M_TRYWAIT, MT_DATA);
-	}
-	if (m == NULL)
-		return (ENOBUFS);
-	m->m_pkthdr.len = m->m_len = len;
-	m->m_pkthdr.rcvif = NULL;
-	*mp = m;
-
-	if (m->m_len < hlen) {
-		error = EPERM;
-		goto bad;
-	}
-
-	error = uiomove(mtod(m, u_char *), len, uio);
-	if (error)
-		goto bad;
-
-	slen = bpf_filter(wfilter, mtod(m, u_char *), len, len);
-	if (slen == 0) {
-		error = EPERM;
-		goto bad;
-	}
-
-	/*
-	 * Make room for link header, and copy it to sockaddr
-	 */
-	if (hlen != 0) {
-		if (sockp->sa_family == AF_IEEE80211) {
-			/*
-			 * Collect true length from the parameter header
-			 * NB: sockp is known to be zero'd so if we do a
-			 *     short copy unspecified parameters will be
-			 *     zero.
-			 * NB: packet may not be aligned after stripping
-			 *     bpf params
-			 * XXX check ibp_vers
-			 */
-			p = mtod(m, const struct ieee80211_bpf_params *);
-			hlen = p->ibp_len;
-			if (hlen > sizeof(sockp->sa_data)) {
-				error = EINVAL;
-				goto bad;
-			}
-		}
-		bcopy(m->m_data, sockp->sa_data, hlen);
-		m->m_pkthdr.len -= hlen;
-		m->m_len -= hlen;
-#if BSD >= 199103
-		m->m_data += hlen; /* XXX */
-#else
-		m->m_off += hlen;
-#endif
-	}
-
-	return (0);
-bad:
-	m_freem(m);
-	return (error);
-}
-
-/*
- * Attach file to the bpf interface, i.e. make d listen on bp.
- */
-static void
-bpf_attachd(struct bpf_d *d, struct bpf_if *bp)
-{
-	/*
-	 * Point d at bp, and add d to the interface's list of listeners.
-	 * Finally, point the driver's bpf cookie at the interface so
-	 * it will divert packets to bpf.
-	 */
-	BPFIF_LOCK(bp);
-	d->bd_bif = bp;
-	LIST_INSERT_HEAD(&bp->bif_dlist, d, bd_next);
-
-	bpf_bpfd_cnt++;
-	BPFIF_UNLOCK(bp);
-}
-
-/*
- * Detach a file from its interface.
- */
-static void
-bpf_detachd(struct bpf_d *d)
-{
-	int error;
-	struct bpf_if *bp;
-	struct ifnet *ifp;
-
-	bp = d->bd_bif;
-	BPFIF_LOCK(bp);
-	BPFD_LOCK(d);
-	ifp = d->bd_bif->bif_ifp;
-
-	/*
-	 * Remove d from the interface's descriptor list.
-	 */
-	LIST_REMOVE(d, bd_next);
-
-	bpf_bpfd_cnt--;
-	d->bd_bif = NULL;
-	BPFD_UNLOCK(d);
-	BPFIF_UNLOCK(bp);
-
-	/*
-	 * Check if this descriptor had requested promiscuous mode.
-	 * If so, turn it off.
-	 */
-	if (d->bd_promisc) {
-		d->bd_promisc = 0;
-		error = ifpromisc(ifp, 0);
-		if (error != 0 && error != ENXIO) {
-			/*
-			 * ENXIO can happen if a pccard is unplugged
-			 * Something is really wrong if we were able to put
-			 * the driver into promiscuous mode, but can't
-			 * take it out.
-			 */
-			if_printf(bp->bif_ifp,
-				"bpf_detach: ifpromisc failed (%d)\n", error);
-		}
-	}
-}
-
-/*
- * Open ethernet device.  Returns ENXIO for illegal minor device number,
- * EBUSY if file is open by another process.
- */
-/* ARGSUSED */
-static	int
-bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
-{
-	struct bpf_d *d;
-
-	mtx_lock(&bpf_mtx);
-	d = dev->si_drv1;
-	/*
-	 * Each minor can be opened by only one process.  If the requested
-	 * minor is in use, return EBUSY.
-	 */
-	if (d != NULL) {
-		mtx_unlock(&bpf_mtx);
-		return (EBUSY);
-	}
-	dev->si_drv1 = (struct bpf_d *)~0;	/* mark device in use */
-	mtx_unlock(&bpf_mtx);
-
-	if ((dev->si_flags & SI_NAMED) == 0)
-		make_dev(&bpf_cdevsw, minor(dev), UID_ROOT, GID_WHEEL, 0600,
-		    "bpf%d", dev2unit(dev));
-	MALLOC(d, struct bpf_d *, sizeof(*d), M_BPF, M_WAITOK | M_ZERO);
-	dev->si_drv1 = d;
-	d->bd_bufsize = bpf_bufsize;
-	d->bd_sig = SIGIO;
-	d->bd_seesent = 1;
-	d->bd_pid = td->td_proc->p_pid;
-#ifdef MAC
-	mac_init_bpfdesc(d);
-	mac_create_bpfdesc(td->td_ucred, d);
-#endif
-	mtx_init(&d->bd_mtx, devtoname(dev), "bpf cdev lock", MTX_DEF);
-	callout_init(&d->bd_callout, NET_CALLOUT_MPSAFE);
-	knlist_init(&d->bd_sel.si_note, &d->bd_mtx, NULL, NULL, NULL);
-
-	return (0);
-}
-
-/*
- * Close the descriptor by detaching it from its interface,
- * deallocating its buffers, and marking it free.
- */
-/* ARGSUSED */
-static	int
-bpfclose(struct cdev *dev, int flags, int fmt, struct thread *td)
-{
-	struct bpf_d *d = dev->si_drv1;
-
-	BPFD_LOCK(d);
-	if (d->bd_state == BPF_WAITING)
-		callout_stop(&d->bd_callout);
-	d->bd_state = BPF_IDLE;
-	BPFD_UNLOCK(d);
-	funsetown(&d->bd_sigio);
-	mtx_lock(&bpf_mtx);
-	if (d->bd_bif)
-		bpf_detachd(d);
-	mtx_unlock(&bpf_mtx);
-	selwakeuppri(&d->bd_sel, PRINET);
-#ifdef MAC
-	mac_destroy_bpfdesc(d);
-#endif /* MAC */
-	knlist_destroy(&d->bd_sel.si_note);
-	bpf_freed(d);
-	dev->si_drv1 = NULL;
-	free(d, M_BPF);
-
-	return (0);
-}
-
-
-/*
  * Rotate the packet buffers in descriptor d.  Move the store buffer
  * into the hold slot, and the free buffer into the store slot.
  * Zero the length of the new store buffer.
@@ -565,701 +198,7 @@
 	return (error);
 }
 
-
-/*
- * If there are processes sleeping on this descriptor, wake them up.
- */
-static __inline void
-bpf_wakeup(struct bpf_d *d)
-{
-
-	BPFD_LOCK_ASSERT(d);
-	if (d->bd_state == BPF_WAITING) {
-		callout_stop(&d->bd_callout);
-		d->bd_state = BPF_IDLE;
-	}
-	wakeup(d);
-	if (d->bd_async && d->bd_sig && d->bd_sigio)
-		pgsigio(&d->bd_sigio, d->bd_sig, 0);
-
-	selwakeuppri(&d->bd_sel, PRINET);
-	KNOTE_LOCKED(&d->bd_sel.si_note, 0);
-}
-
-static void
-bpf_timed_out(void *arg)
-{
-	struct bpf_d *d = (struct bpf_d *)arg;
-
-	BPFD_LOCK(d);
-	if (d->bd_state == BPF_WAITING) {
-		d->bd_state = BPF_TIMED_OUT;
-		if (d->bd_slen != 0)
-			bpf_wakeup(d);
-	}
-	BPFD_UNLOCK(d);
-}
-
-static int
-bpfwrite(struct cdev *dev, struct uio *uio, int ioflag)
-{
-	struct bpf_d *d = dev->si_drv1;
-	struct ifnet *ifp;
-	struct mbuf *m;
-	int error;
-	struct sockaddr dst;
-
-	if (d->bd_bif == NULL)
-		return (ENXIO);
-
-	ifp = d->bd_bif->bif_ifp;
-
-	if ((ifp->if_flags & IFF_UP) == 0)
-		return (ENETDOWN);
-
-	if (uio->uio_resid == 0)
-		return (0);
-
-	bzero(&dst, sizeof(dst));
-	error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, ifp->if_mtu,
-	    &m, &dst, d->bd_wfilter);
-	if (error)
-		return (error);
-
-	if (d->bd_hdrcmplt)
-		dst.sa_family = pseudo_AF_HDRCMPLT;
-
-#ifdef MAC
-	BPFD_LOCK(d);
-	mac_create_mbuf_from_bpfdesc(d, m);
-	BPFD_UNLOCK(d);
-#endif
-	NET_LOCK_GIANT();
-	error = (*ifp->if_output)(ifp, m, &dst, NULL);
-	NET_UNLOCK_GIANT();
-	/*
-	 * The driver frees the mbuf.
-	 */
-	return (error);
-}
-
-/*
- * Reset a descriptor by flushing its packet buffer and clearing the
- * receive and drop counts.
- */
-static void
-reset_d(struct bpf_d *d)
-{
-
-	mtx_assert(&d->bd_mtx, MA_OWNED);
-	if (d->bd_hbuf) {
-		/* Free the hold buffer. */
-		d->bd_fbuf = d->bd_hbuf;
-		d->bd_hbuf = NULL;
-	}
-	d->bd_slen = 0;
-	d->bd_hlen = 0;
-	d->bd_rcount = 0;
-	d->bd_dcount = 0;
-	d->bd_fcount = 0;
-}
-
-/*
- *  FIONREAD		Check for read packet available.
- *  SIOCGIFADDR		Get interface address - convenient hook to driver.
- *  BIOCGBLEN		Get buffer len [for read()].
- *  BIOCSETF		Set ethernet read filter.
- *  BIOCSETWF		Set ethernet write filter.
- *  BIOCFLUSH		Flush read packet buffer.
- *  BIOCPROMISC		Put interface into promiscuous mode.
- *  BIOCGDLT		Get link layer type.
- *  BIOCGETIF		Get interface name.
- *  BIOCSETIF		Set interface.
- *  BIOCSRTIMEOUT	Set read timeout.
- *  BIOCGRTIMEOUT	Get read timeout.
- *  BIOCGSTATS		Get packet stats.
- *  BIOCIMMEDIATE	Set immediate mode.
- *  BIOCVERSION		Get filter language version.
- *  BIOCGHDRCMPLT	Get "header already complete" flag
- *  BIOCSHDRCMPLT	Set "header already complete" flag
- *  BIOCGSEESENT	Get "see packets sent" flag
- *  BIOCSSEESENT	Set "see packets sent" flag
- *  BIOCLOCK		Set "locked" flag
- */
-/* ARGSUSED */
-static	int
-bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
-    struct thread *td)
-{
-	struct bpf_d *d = dev->si_drv1;
-	int error = 0;
-
-	/* 
-	 * Refresh PID associated with this descriptor.
-	 */
-	BPFD_LOCK(d);
-	d->bd_pid = td->td_proc->p_pid;
-	if (d->bd_state == BPF_WAITING)
-		callout_stop(&d->bd_callout);
-	d->bd_state = BPF_IDLE;
-	BPFD_UNLOCK(d);
-
-	if (d->bd_locked == 1) {
-		switch (cmd) {
-		case BIOCGBLEN:
-		case BIOCFLUSH:
-		case BIOCGDLT:
-		case BIOCGDLTLIST: 
-		case BIOCGETIF:
-		case BIOCGRTIMEOUT:
-		case BIOCGSTATS:
-		case BIOCVERSION:
-		case BIOCGRSIG:
-		case BIOCGHDRCMPLT:
-		case FIONREAD:
-		case BIOCLOCK:
-		case BIOCSRTIMEOUT:
-		case BIOCIMMEDIATE:
-		case TIOCGPGRP:
-			break;
-		default:
-			return (EPERM);
-		}
-	}
-	switch (cmd) {
-
-	default:
-		error = EINVAL;
-		break;
-
-	/*
-	 * Check for read packet available.
-	 */
-	case FIONREAD:
-		{
-			int n;
-
-			BPFD_LOCK(d);
-			n = d->bd_slen;
-			if (d->bd_hbuf)
-				n += d->bd_hlen;
-			BPFD_UNLOCK(d);
-
-			*(int *)addr = n;
-			break;
-		}
-
-	case SIOCGIFADDR:
-		{
-			struct ifnet *ifp;
-
-			if (d->bd_bif == NULL)
-				error = EINVAL;
-			else {
-				ifp = d->bd_bif->bif_ifp;
-				error = (*ifp->if_ioctl)(ifp, cmd, addr);
-			}
-			break;
-		}
-
-	/*
-	 * Get buffer len [for read()].
-	 */
-	case BIOCGBLEN:
-		*(u_int *)addr = d->bd_bufsize;
-		break;
-
-	/*
-	 * Set buffer length.
-	 */
-	case BIOCSBLEN:
-		if (d->bd_bif != NULL)
-			error = EINVAL;
-		else {
-			u_int size = *(u_int *)addr;
-
-			if (size > bpf_maxbufsize)
-				*(u_int *)addr = size = bpf_maxbufsize;
-			else if (size < BPF_MINBUFSIZE)
-				*(u_int *)addr = size = BPF_MINBUFSIZE;
-			d->bd_bufsize = size;
-		}
-		break;
-
-	/*
-	 * Set link layer read filter.
-	 */
-	case BIOCSETF:
-	case BIOCSETWF:
-		error = bpf_setf(d, (struct bpf_program *)addr, cmd);
-		break;
-
-	/*
-	 * Flush read packet buffer.
-	 */
-	case BIOCFLUSH:
-		BPFD_LOCK(d);
-		reset_d(d);
-		BPFD_UNLOCK(d);
-		break;
-
-	/*
-	 * Put interface into promiscuous mode.
-	 */
-	case BIOCPROMISC:
-		if (d->bd_bif == NULL) {
-			/*
-			 * No interface attached yet.
-			 */
-			error = EINVAL;
-			break;
-		}
-		if (d->bd_promisc == 0) {
-			mtx_lock(&Giant);
-			error = ifpromisc(d->bd_bif->bif_ifp, 1);
-			mtx_unlock(&Giant);
-			if (error == 0)
-				d->bd_promisc = 1;
-		}
-		break;
-
-	/*
-	 * Get current data link type.
-	 */
-	case BIOCGDLT:
-		if (d->bd_bif == NULL)
-			error = EINVAL;
-		else
-			*(u_int *)addr = d->bd_bif->bif_dlt;
-		break;
-
-	/*
-	 * Get a list of supported data link types.
-	 */
-	case BIOCGDLTLIST:
-		if (d->bd_bif == NULL)
-			error = EINVAL;
-		else
-			error = bpf_getdltlist(d, (struct bpf_dltlist *)addr);
-		break;
-
-	/*
-	 * Set data link type.
-	 */
-	case BIOCSDLT:
-		if (d->bd_bif == NULL)
-			error = EINVAL;
-		else
-			error = bpf_setdlt(d, *(u_int *)addr);
-		break;
-
-	/*
-	 * Get interface name.
-	 */
-	case BIOCGETIF:
-		if (d->bd_bif == NULL)
-			error = EINVAL;
-		else {
-			struct ifnet *const ifp = d->bd_bif->bif_ifp;
-			struct ifreq *const ifr = (struct ifreq *)addr;
-
-			strlcpy(ifr->ifr_name, ifp->if_xname,
-			    sizeof(ifr->ifr_name));
-		}
-		break;
-
-	/*
-	 * Set interface.
-	 */
-	case BIOCSETIF:
-		error = bpf_setif(d, (struct ifreq *)addr);
-		break;
-
-	/*
-	 * Set read timeout.
-	 */
-	case BIOCSRTIMEOUT:
-		{
-			struct timeval *tv = (struct timeval *)addr;
-
-			/*
-			 * Subtract 1 tick from tvtohz() since this isn't
-			 * a one-shot timer.
-			 */
-			if ((error = itimerfix(tv)) == 0)
-				d->bd_rtout = tvtohz(tv) - 1;
-			break;
-		}
-
-	/*
-	 * Get read timeout.
-	 */
-	case BIOCGRTIMEOUT:
-		{
-			struct timeval *tv = (struct timeval *)addr;
-
-			tv->tv_sec = d->bd_rtout / hz;
-			tv->tv_usec = (d->bd_rtout % hz) * tick;
-			break;
-		}
-
-	/*
-	 * Get packet stats.
-	 */
-	case BIOCGSTATS:
-		{
-			struct bpf_stat *bs = (struct bpf_stat *)addr;
-
-			bs->bs_recv = d->bd_rcount;
-			bs->bs_drop = d->bd_dcount;
-			break;
-		}
-
-	/*
-	 * Set immediate mode.
-	 */
-	case BIOCIMMEDIATE:
-		d->bd_immediate = *(u_int *)addr;
-		break;
-
-	case BIOCVERSION:
-		{
-			struct bpf_version *bv = (struct bpf_version *)addr;
-
-			bv->bv_major = BPF_MAJOR_VERSION;
-			bv->bv_minor = BPF_MINOR_VERSION;
-			break;
-		}
-
-	/*
-	 * Get "header already complete" flag
-	 */
-	case BIOCGHDRCMPLT:
-		*(u_int *)addr = d->bd_hdrcmplt;
-		break;
-
-	case BIOCLOCK:
-		d->bd_locked = 1;
-		break;
-	/*
-	 * Set "header already complete" flag
-	 */
-	case BIOCSHDRCMPLT:
-		d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0;
-		break;
-
-	/*
-	 * Get "see sent packets" flag
-	 */
-	case BIOCGSEESENT:
-		*(u_int *)addr = d->bd_seesent;
-		break;
-
-	/*
-	 * Set "see sent packets" flag
-	 */
-	case BIOCSSEESENT:
-		d->bd_seesent = *(u_int *)addr;
-		break;
-
-	case FIONBIO:		/* Non-blocking I/O */
-		break;
-
-	case FIOASYNC:		/* Send signal on receive packets */
-		d->bd_async = *(int *)addr;
-		break;
-
-	case FIOSETOWN:
-		error = fsetown(*(int *)addr, &d->bd_sigio);
-		break;
-
-	case FIOGETOWN:
-		*(int *)addr = fgetown(&d->bd_sigio);
-		break;
-
-	/* This is deprecated, FIOSETOWN should be used instead. */
-	case TIOCSPGRP:
-		error = fsetown(-(*(int *)addr), &d->bd_sigio);
-		break;
-
-	/* This is deprecated, FIOGETOWN should be used instead. */
-	case TIOCGPGRP:
-		*(int *)addr = -fgetown(&d->bd_sigio);
-		break;
-
-	case BIOCSRSIG:		/* Set receive signal */
-		{
-			u_int sig;
-
-			sig = *(u_int *)addr;
-
-			if (sig >= NSIG)
-				error = EINVAL;
-			else
-				d->bd_sig = sig;
-			break;
-		}
-	case BIOCGRSIG:
-		*(u_int *)addr = d->bd_sig;
-		break;
-	}
-	return (error);
-}
-
-/*
- * 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.
- */
-static int
-bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
-{
-	struct bpf_insn *fcode, *old;
-	u_int wfilter, flen, size;
-#ifdef BPF_JITTER
-	bpf_jit_filter *ofunc;
-#endif
-
-	if (cmd == BIOCSETWF) {
-		old = d->bd_wfilter;
-		wfilter = 1;
-#ifdef BPF_JITTER
-		ofunc = NULL;
-#endif
-	} else {
-		wfilter = 0;
-		old = d->bd_rfilter;
-#ifdef BPF_JITTER
-		ofunc = d->bd_bfilter;
-#endif
-	}
-	if (fp->bf_insns == NULL) {
-		if (fp->bf_len != 0)
-			return (EINVAL);
-		BPFD_LOCK(d);
-		if (wfilter)
-			d->bd_wfilter = NULL;
-		else {
-			d->bd_rfilter = NULL;
-#ifdef BPF_JITTER
-			d->bd_bfilter = NULL;
-#endif
-		}
-		reset_d(d);
-		BPFD_UNLOCK(d);
-		if (old != NULL)
-			free((caddr_t)old, M_BPF);
-#ifdef BPF_JITTER
-		if (ofunc != NULL)
-			bpf_destroy_jit_filter(ofunc);
-#endif
-		return (0);
-	}
-	flen = fp->bf_len;
-	if (flen > bpf_maxinsns)
-		return (EINVAL);
-
-	size = flen * sizeof(*fp->bf_insns);
-	fcode = (struct bpf_insn *)malloc(size, M_BPF, M_WAITOK);
-	if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
-	    bpf_validate(fcode, (int)flen)) {
-		BPFD_LOCK(d);
-		if (wfilter)
-			d->bd_wfilter = fcode;
-		else {
-			d->bd_rfilter = fcode;
-#ifdef BPF_JITTER
-			d->bd_bfilter = bpf_jitter(fcode, flen);
-#endif
-		}
-		reset_d(d);
-		BPFD_UNLOCK(d);
-		if (old != NULL)
-			free((caddr_t)old, M_BPF);
-#ifdef BPF_JITTER
-		if (ofunc != NULL)
-			bpf_destroy_jit_filter(ofunc);
-#endif
-
-		return (0);
-	}
-	free((caddr_t)fcode, M_BPF);
-	return (EINVAL);
-}
-
-/*
- * 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, struct ifreq *ifr)
-{
-	struct bpf_if *bp;
-	struct ifnet *theywant;
-
-	theywant = ifunit(ifr->ifr_name);
-	if (theywant == NULL || theywant->if_bpf == NULL)
-		return (ENXIO);
-
-	bp = theywant->if_bpf;
-	/*
-	 * Allocate the packet buffers if we need to.
-	 * If we're already attached to requested interface,
-	 * just flush the buffer.
-	 */
-	if (d->bd_sbuf == NULL)
-		bpf_allocbufs(d);
-	if (bp != d->bd_bif) {
-		if (d->bd_bif)
-			/*
-			 * Detach if attached to something else.
-			 */
-			bpf_detachd(d);
-
-		bpf_attachd(d, bp);
-	}
-	BPFD_LOCK(d);
-	reset_d(d);
-	BPFD_UNLOCK(d);
-	return (0);
-}
-
-/*
- * Support for select() and poll() system calls
- *
- * Return true iff the specific operation will not block indefinitely.
- * Otherwise, return false but make a note that a selwakeup() must be done.
- */
-static int
-bpfpoll(struct cdev *dev, int events, struct thread *td)
-{
-	struct bpf_d *d;
-	int revents;
-
-	d = dev->si_drv1;
-	if (d->bd_bif == NULL)
-		return (ENXIO);
-
-	/*
-	 * Refresh PID associated with this descriptor.
-	 */
-	revents = events & (POLLOUT | POLLWRNORM);
-	BPFD_LOCK(d);
-	d->bd_pid = td->td_proc->p_pid;
-	if (events & (POLLIN | POLLRDNORM)) {
-		if (bpf_ready(d))
-			revents |= events & (POLLIN | POLLRDNORM);
-		else {
-			selrecord(td, &d->bd_sel);
-			/* Start the read timeout if necessary. */
-			if (d->bd_rtout > 0 && d->bd_state == BPF_IDLE) {
-				callout_reset(&d->bd_callout, d->bd_rtout,
-				    bpf_timed_out, d);
-				d->bd_state = BPF_WAITING;
-			}
-		}
-	}
-	BPFD_UNLOCK(d);
-	return (revents);
-}
-
-/*
- * Support for kevent() system call.  Register EVFILT_READ filters and
- * reject all others.
- */
-int
-bpfkqfilter(struct cdev *dev, struct knote *kn)
-{
-	struct bpf_d *d = (struct bpf_d *)dev->si_drv1;
-
-	if (kn->kn_filter != EVFILT_READ)
-		return (1);
-

>>> TRUNCATED FOR MAIL (1000 lines) <<<



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200701291308.l0TD8jDQ016841>