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); }
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); }