diff --git a/sys/net/bpf.c b/sys/net/bpf.c --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -261,6 +261,8 @@ .f_event = filt_bpfwrite, }; +static eventhandler_tag bpf_ifdetach_cookie = NULL; + /* * LOCKING MODEL USED BY BPF * @@ -2887,6 +2889,39 @@ BPF_UNLOCK(); } +/* + * Interface departure handler. Detach descriptors on departure event. + * Note departure event does not guarantee interface is going down. + * Interface renaming is currently done via departure/arrival event set. + */ +static void +bpf_ifdetach(void *arg __unused, struct ifnet *ifp) +{ + struct bpf_if *bp; + struct bpf_d *d; + + /* Ignore ifnet renaming. */ + if ((ifp->if_flags & IFF_RENAMING) != 0) + return; + + BPF_LOCK(); + CK_LIST_FOREACH(bp, &bpf_iflist, bif_next) { + if (bp->bif_ifp != ifp) + continue; + + /* Detach common descriptors */ + while ((d = CK_LIST_FIRST(&bp->bif_dlist)) != NULL) { + bpf_detachd_locked(d, true); + } + + /* Detach writer-only descriptors */ + while ((d = CK_LIST_FIRST(&bp->bif_wlist)) != NULL) { + bpf_detachd_locked(d, true); + } + } + BPF_UNLOCK(); +} + bool bpf_peers_present_if(struct ifnet *ifp) { @@ -2984,6 +3019,11 @@ dev = make_dev(&bpf_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "bpf"); /* For compatibility */ make_dev_alias(dev, "bpf0"); + + /* Register interface departure handler */ + bpf_ifdetach_cookie = EVENTHANDLER_REGISTER( + ifnet_departure_event, bpf_ifdetach, NULL, + EVENTHANDLER_PRI_ANY); } /*