Example #1
0
int
bpfwrite(dev_t dev, struct uio *uio, int ioflag)
{
	struct bpf_d *d;
	struct ifnet *ifp;
	struct mbuf *m;
	int error, s;
	struct sockaddr_storage dst;

	d = bpfilter_lookup(minor(dev));
	if (d->bd_bif == 0)
		return (ENXIO);

	ifp = d->bd_bif->bif_ifp;

	if ((ifp->if_flags & IFF_UP) == 0)
		return (ENETDOWN);

	if (uio->uio_resid == 0)
		return (0);

	error = bpf_movein(uio, d->bd_bif->bif_dlt, &m,
	    (struct sockaddr *)&dst, d->bd_wfilter);
	if (error)
		return (error);

	if (m->m_pkthdr.len > ifp->if_mtu) {
		m_freem(m);
		return (EMSGSIZE);
	}

	m->m_pkthdr.rdomain = ifp->if_rdomain;

	if (d->bd_hdrcmplt)
		dst.ss_family = pseudo_AF_HDRCMPLT;

	s = splsoftnet();
	error = (*ifp->if_output)(ifp, m, (struct sockaddr *)&dst,
	    (struct rtentry *)0);
	splx(s);
	/*
	 * The driver frees the mbuf.
	 */
	return (error);
}
Example #2
0
File: bpf.c Project: SbIm/xnu-env
int
bpfwrite(dev_t dev, struct uio *uio, __unused int ioflag)
{
	struct bpf_d *d;
	struct ifnet *ifp;
	struct mbuf *m = NULL;
	int error;
	char 		  dst_buf[SOCKADDR_HDR_LEN + MAX_DATALINK_HDR_LEN];
	int datlen = 0;

	lck_mtx_lock(bpf_mlock);

	d = bpf_dtab[minor(dev)];
	if (d == 0 || d == (void *)1) {
		lck_mtx_unlock(bpf_mlock);
		return (ENXIO);
	}
	if (d->bd_bif == 0) {
		lck_mtx_unlock(bpf_mlock);
		return (ENXIO);
	}

	ifp = d->bd_bif->bif_ifp;

	if (uio_resid(uio) == 0) {
		lck_mtx_unlock(bpf_mlock);
		return (0);
	}
	((struct sockaddr *)dst_buf)->sa_len = sizeof(dst_buf);
	error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, 
			   d->bd_hdrcmplt ? NULL : (struct sockaddr *)dst_buf,
			   &datlen);
	if (error) {
		lck_mtx_unlock(bpf_mlock);
		return (error);
	}

	if ((unsigned)datlen > ifp->if_mtu) {
		lck_mtx_unlock(bpf_mlock);
		m_freem(m);
		return (EMSGSIZE);
	}
	
	if ((error = ifp_use(ifp, kIfNetUseCount_MustNotBeZero)) != 0) {
		lck_mtx_unlock(bpf_mlock);
		m_freem(m);
		return (error);
	}

#if CONFIG_MACF_NET
	mac_mbuf_label_associate_bpfdesc(d, m);
#endif
	lck_mtx_unlock(bpf_mlock);

	if (d->bd_hdrcmplt) {
		if (d->bd_bif->bif_send)
			error = d->bd_bif->bif_send(ifp, d->bd_bif->bif_dlt, m);
		else
			error = dlil_output(ifp, 0, m, NULL, NULL, 1);
	}
	else {
		error = dlil_output(ifp, PF_INET, m, NULL, (struct sockaddr *)dst_buf, 0);
	}
	
	if (ifp_unuse(ifp) != 0)
		ifp_use_reached_zero(ifp);
	
	/*
	 * The driver frees the mbuf.
	 */
	return (error);
}