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