git: 3a01a97d23a2 - main - mroute: partially sanitize the file

From: Mateusz Guzik <mjg_at_FreeBSD.org>
Date: Thu, 23 Feb 2023 13:38:43 UTC
The branch main has been updated by mjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=3a01a97d23a27cb522b3e9de5d95b825f421cf9b

commit 3a01a97d23a27cb522b3e9de5d95b825f421cf9b
Author:     Mateusz Guzik <mjg@FreeBSD.org>
AuthorDate: 2023-02-17 11:23:35 +0000
Commit:     Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2023-02-23 13:35:44 +0000

    mroute: partially sanitize the file
    
    There is rampant inconsistent formatting all around, make it mostly
    style(9)-conformant.
    
    While here:
    - drop malloc casts
    - rename a rw lock from mroute_mtx to mroute_lock
    - replace NOTREACHED comment with __assert_unreachable
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D38652
---
 sys/netinet/ip_mroute.c | 2783 +++++++++++++++++++++++------------------------
 1 file changed, 1387 insertions(+), 1396 deletions(-)

diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 6cabef8a1b16..15abe168e5c2 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -143,19 +143,19 @@ static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast forwarding cache");
  * structures.
  */
 
-static struct rwlock mrouter_mtx;
-#define	MRW_RLOCK()		rw_rlock(&mrouter_mtx)
-#define	MRW_WLOCK()		rw_wlock(&mrouter_mtx)
-#define	MRW_RUNLOCK()	rw_runlock(&mrouter_mtx)
-#define	MRW_WUNLOCK()	rw_wunlock(&mrouter_mtx)
-#define	MRW_UNLOCK()	rw_unlock(&mrouter_mtx)
-#define	MRW_LOCK_ASSERT()	rw_assert(&mrouter_mtx, RA_LOCKED)
-#define	MRW_WLOCK_ASSERT()	rw_assert(&mrouter_mtx, RA_WLOCKED)
-#define	MRW_LOCK_TRY_UPGRADE()	rw_try_upgrade(&mrouter_mtx)
-#define	MRW_WOWNED()	rw_wowned(&mrouter_mtx)
+static struct rwlock mrouter_lock;
+#define	MRW_RLOCK()		rw_rlock(&mrouter_lock)
+#define	MRW_WLOCK()		rw_wlock(&mrouter_lock)
+#define	MRW_RUNLOCK()		rw_runlock(&mrouter_lock)
+#define	MRW_WUNLOCK()		rw_wunlock(&mrouter_lock)
+#define	MRW_UNLOCK()		rw_unlock(&mrouter_lock)
+#define	MRW_LOCK_ASSERT()	rw_assert(&mrouter_lock, RA_LOCKED)
+#define	MRW_WLOCK_ASSERT()	rw_assert(&mrouter_lock, RA_WLOCKED)
+#define	MRW_LOCK_TRY_UPGRADE()	rw_try_upgrade(&mrouter_lock)
+#define	MRW_WOWNED()		rw_wowned(&mrouter_lock)
 #define	MRW_LOCK_INIT()						\
-	rw_init(&mrouter_mtx, "IPv4 multicast forwarding")
-#define	MRW_LOCK_DESTROY()	rw_destroy(&mrouter_mtx)
+	rw_init(&mrouter_lock, "IPv4 multicast forwarding")
+#define	MRW_LOCK_DESTROY()	rw_destroy(&mrouter_lock)
 
 static int ip_mrouter_cnt;	/* # of vnets with active mrouters */
 static int ip_mrouter_unloading; /* Allow no more V_ip_mrouter sockets */
@@ -392,7 +392,7 @@ static __inline struct mfc *
 mfc_alloc(void)
 {
 	struct mfc *rt;
-	rt = (struct mfc*) malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT | M_ZERO);
+	rt = malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT | M_ZERO);
 	if (rt == NULL)
 		return rt;
 
@@ -412,98 +412,94 @@ mfc_alloc(void)
 static int
 X_ip_mrouter_set(struct socket *so, struct sockopt *sopt)
 {
-    int	error, optval;
-    vifi_t	vifi;
-    struct	vifctl vifc;
-    struct	mfcctl2 mfc;
-    struct	bw_upcall bw_upcall;
-    uint32_t	i;
-
-    if (so != V_ip_mrouter && sopt->sopt_name != MRT_INIT)
-	return EPERM;
-
-    error = 0;
-    switch (sopt->sopt_name) {
-    case MRT_INIT:
-	error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval);
-	if (error)
-	    break;
-	error = ip_mrouter_init(so, optval);
-	break;
+	int error, optval;
+	vifi_t vifi;
+	struct vifctl vifc;
+	struct mfcctl2 mfc;
+	struct bw_upcall bw_upcall;
+	uint32_t i;
+
+	if (so != V_ip_mrouter && sopt->sopt_name != MRT_INIT)
+		return EPERM;
+
+	error = 0;
+	switch (sopt->sopt_name) {
+	case MRT_INIT:
+		error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval);
+		if (error)
+			break;
+		error = ip_mrouter_init(so, optval);
+		break;
+	case MRT_DONE:
+		error = ip_mrouter_done();
+		break;
+	case MRT_ADD_VIF:
+		error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc);
+		if (error)
+			break;
+		error = add_vif(&vifc);
+		break;
+	case MRT_DEL_VIF:
+		error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
+		if (error)
+			break;
+		error = del_vif(vifi);
+		break;
+	case MRT_ADD_MFC:
+	case MRT_DEL_MFC:
+		/*
+		 * select data size depending on API version.
+		 */
+		if (sopt->sopt_name == MRT_ADD_MFC &&
+		    V_mrt_api_config & MRT_API_FLAGS_ALL) {
+			error = sooptcopyin(sopt, &mfc, sizeof(struct mfcctl2),
+			    sizeof(struct mfcctl2));
+		} else {
+			error = sooptcopyin(sopt, &mfc, sizeof(struct mfcctl),
+			    sizeof(struct mfcctl));
+			bzero((caddr_t)&mfc + sizeof(struct mfcctl),
+			    sizeof(mfc) - sizeof(struct mfcctl));
+		}
+		if (error)
+			break;
+		if (sopt->sopt_name == MRT_ADD_MFC)
+			error = add_mfc(&mfc);
+		else
+			error = del_mfc(&mfc);
+		break;
 
-    case MRT_DONE:
-	error = ip_mrouter_done();
-	break;
+	case MRT_ASSERT:
+		error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval);
+		if (error)
+			break;
+		set_assert(optval);
+		break;
 
-    case MRT_ADD_VIF:
-	error = sooptcopyin(sopt, &vifc, sizeof vifc, sizeof vifc);
-	if (error)
-	    break;
-	error = add_vif(&vifc);
-	break;
+	case MRT_API_CONFIG:
+		error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
+		if (!error)
+			error = set_api_config(&i);
+		if (!error)
+			error = sooptcopyout(sopt, &i, sizeof i);
+		break;
 
-    case MRT_DEL_VIF:
-	error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
-	if (error)
-	    break;
-	error = del_vif(vifi);
-	break;
+	case MRT_ADD_BW_UPCALL:
+	case MRT_DEL_BW_UPCALL:
+		error = sooptcopyin(sopt, &bw_upcall, sizeof bw_upcall,
+		    sizeof bw_upcall);
+		if (error)
+			break;
+		if (sopt->sopt_name == MRT_ADD_BW_UPCALL)
+			error = add_bw_upcall(&bw_upcall);
+		else
+			error = del_bw_upcall(&bw_upcall);
+		break;
 
-    case MRT_ADD_MFC:
-    case MRT_DEL_MFC:
-	/*
-	 * select data size depending on API version.
-	 */
-	if (sopt->sopt_name == MRT_ADD_MFC &&
-		V_mrt_api_config & MRT_API_FLAGS_ALL) {
-	    error = sooptcopyin(sopt, &mfc, sizeof(struct mfcctl2),
-				sizeof(struct mfcctl2));
-	} else {
-	    error = sooptcopyin(sopt, &mfc, sizeof(struct mfcctl),
-				sizeof(struct mfcctl));
-	    bzero((caddr_t)&mfc + sizeof(struct mfcctl),
-			sizeof(mfc) - sizeof(struct mfcctl));
+	default:
+		error = EOPNOTSUPP;
+		break;
 	}
-	if (error)
-	    break;
-	if (sopt->sopt_name == MRT_ADD_MFC)
-	    error = add_mfc(&mfc);
-	else
-	    error = del_mfc(&mfc);
-	break;
-
-    case MRT_ASSERT:
-	error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval);
-	if (error)
-	    break;
-	set_assert(optval);
-	break;
-
-    case MRT_API_CONFIG:
-	error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
-	if (!error)
-	    error = set_api_config(&i);
-	if (!error)
-	    error = sooptcopyout(sopt, &i, sizeof i);
-	break;
-
-    case MRT_ADD_BW_UPCALL:
-    case MRT_DEL_BW_UPCALL:
-	error = sooptcopyin(sopt, &bw_upcall, sizeof bw_upcall,
-				sizeof bw_upcall);
-	if (error)
-	    break;
-	if (sopt->sopt_name == MRT_ADD_BW_UPCALL)
-	    error = add_bw_upcall(&bw_upcall);
-	else
-	    error = del_bw_upcall(&bw_upcall);
-	break;
-
-    default:
-	error = EOPNOTSUPP;
-	break;
-    }
-    return error;
+	return error;
 }
 
 /*
@@ -512,31 +508,30 @@ X_ip_mrouter_set(struct socket *so, struct sockopt *sopt)
 static int
 X_ip_mrouter_get(struct socket *so, struct sockopt *sopt)
 {
-    int error;
-
-    switch (sopt->sopt_name) {
-    case MRT_VERSION:
-	error = sooptcopyout(sopt, &mrt_api_version, sizeof mrt_api_version);
-	break;
-
-    case MRT_ASSERT:
-	error = sooptcopyout(sopt, &V_pim_assert_enabled,
-	    sizeof V_pim_assert_enabled);
-	break;
-
-    case MRT_API_SUPPORT:
-	error = sooptcopyout(sopt, &mrt_api_support, sizeof mrt_api_support);
-	break;
-
-    case MRT_API_CONFIG:
-	error = sooptcopyout(sopt, &V_mrt_api_config, sizeof V_mrt_api_config);
-	break;
-
-    default:
-	error = EOPNOTSUPP;
-	break;
-    }
-    return error;
+	int error;
+
+	switch (sopt->sopt_name) {
+	case MRT_VERSION:
+		error = sooptcopyout(sopt, &mrt_api_version,
+		    sizeof mrt_api_version);
+		break;
+	case MRT_ASSERT:
+		error = sooptcopyout(sopt, &V_pim_assert_enabled,
+		    sizeof V_pim_assert_enabled);
+		break;
+	case MRT_API_SUPPORT:
+		error = sooptcopyout(sopt, &mrt_api_support,
+		    sizeof mrt_api_support);
+		break;
+	case MRT_API_CONFIG:
+		error = sooptcopyout(sopt, &V_mrt_api_config,
+		    sizeof V_mrt_api_config);
+		break;
+	default:
+		error = EOPNOTSUPP;
+		break;
+	}
+	return error;
 }
 
 /*
@@ -545,30 +540,30 @@ X_ip_mrouter_get(struct socket *so, struct sockopt *sopt)
 static int
 X_mrt_ioctl(u_long cmd, caddr_t data, int fibnum __unused)
 {
-    int error = 0;
-
-    /*
-     * Currently the only function calling this ioctl routine is rtioctl_fib().
-     * Typically, only root can create the raw socket in order to execute
-     * this ioctl method, however the request might be coming from a prison
-     */
-    error = priv_check(curthread, PRIV_NETINET_MROUTE);
-    if (error)
-	return (error);
-    switch (cmd) {
-    case (SIOCGETVIFCNT):
-	error = get_vif_cnt((struct sioc_vif_req *)data);
-	break;
-
-    case (SIOCGETSGCNT):
-	error = get_sg_cnt((struct sioc_sg_req *)data);
-	break;
-
-    default:
-	error = EINVAL;
-	break;
-    }
-    return error;
+	int error;
+
+	/*
+	 * Currently the only function calling this ioctl routine is rtioctl_fib().
+	 * Typically, only root can create the raw socket in order to execute
+	 * this ioctl method, however the request might be coming from a prison
+	 */
+	error = priv_check(curthread, PRIV_NETINET_MROUTE);
+	if (error)
+		return (error);
+	switch (cmd) {
+	case (SIOCGETVIFCNT):
+		error = get_vif_cnt((struct sioc_vif_req *)data);
+		break;
+
+	case (SIOCGETSGCNT):
+		error = get_sg_cnt((struct sioc_sg_req *)data);
+		break;
+
+	default:
+		error = EINVAL;
+		break;
+	}
+	return error;
 }
 
 /*
@@ -577,20 +572,20 @@ X_mrt_ioctl(u_long cmd, caddr_t data, int fibnum __unused)
 static int
 get_sg_cnt(struct sioc_sg_req *req)
 {
-    struct mfc *rt;
-
-    MRW_RLOCK();
-    rt = mfc_find(&req->src, &req->grp);
-    if (rt == NULL) {
-	    MRW_RUNLOCK();
-	req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
-	return EADDRNOTAVAIL;
-    }
-    req->pktcnt = rt->mfc_pkt_cnt;
-    req->bytecnt = rt->mfc_byte_cnt;
-    req->wrong_if = rt->mfc_wrong_if;
-    MRW_RUNLOCK();
-    return 0;
+	struct mfc *rt;
+
+	MRW_RLOCK();
+	rt = mfc_find(&req->src, &req->grp);
+	if (rt == NULL) {
+		MRW_RUNLOCK();
+		req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
+		return EADDRNOTAVAIL;
+	}
+	req->pktcnt = rt->mfc_pkt_cnt;
+	req->bytecnt = rt->mfc_byte_cnt;
+	req->wrong_if = rt->mfc_wrong_if;
+	MRW_RUNLOCK();
+	return 0;
 }
 
 /*
@@ -599,73 +594,73 @@ get_sg_cnt(struct sioc_sg_req *req)
 static int
 get_vif_cnt(struct sioc_vif_req *req)
 {
-    vifi_t vifi = req->vifi;
+	vifi_t vifi = req->vifi;
 
-    MRW_RLOCK();
-    if (vifi >= V_numvifs) {
+	MRW_RLOCK();
+	if (vifi >= V_numvifs) {
+		MRW_RUNLOCK();
+		return EINVAL;
+	}
+
+	mtx_lock_spin(&V_viftable[vifi].v_spin);
+	req->icount = V_viftable[vifi].v_pkt_in;
+	req->ocount = V_viftable[vifi].v_pkt_out;
+	req->ibytes = V_viftable[vifi].v_bytes_in;
+	req->obytes = V_viftable[vifi].v_bytes_out;
+	mtx_unlock_spin(&V_viftable[vifi].v_spin);
 	MRW_RUNLOCK();
-	return EINVAL;
-    }
-
-    mtx_lock_spin(&V_viftable[vifi].v_spin);
-    req->icount = V_viftable[vifi].v_pkt_in;
-    req->ocount = V_viftable[vifi].v_pkt_out;
-    req->ibytes = V_viftable[vifi].v_bytes_in;
-    req->obytes = V_viftable[vifi].v_bytes_out;
-    mtx_unlock_spin(&V_viftable[vifi].v_spin);
-    MRW_RUNLOCK();
-
-    return 0;
+
+	return 0;
 }
 
 static void
 if_detached_event(void *arg __unused, struct ifnet *ifp)
 {
-    vifi_t vifi;
-    u_long i, vifi_cnt = 0;
-    struct ifnet *free_ptr;
+	vifi_t vifi;
+	u_long i, vifi_cnt = 0;
+	struct ifnet *free_ptr;
 
-    MRW_WLOCK();
+	MRW_WLOCK();
 
-    if (V_ip_mrouter == NULL) {
-	MRW_WUNLOCK();
-	return;
-    }
-
-    /*
-     * Tear down multicast forwarder state associated with this ifnet.
-     * 1. Walk the vif list, matching vifs against this ifnet.
-     * 2. Walk the multicast forwarding cache (mfc) looking for
-     *    inner matches with this vif's index.
-     * 3. Expire any matching multicast forwarding cache entries.
-     * 4. Free vif state. This should disable ALLMULTI on the interface.
-     */
-    for (vifi = 0; vifi < V_numvifs; vifi++) {
-	if (V_viftable[vifi].v_ifp != ifp)
-		continue;
-	for (i = 0; i < mfchashsize; i++) {
-		struct mfc *rt, *nrt;
+	if (V_ip_mrouter == NULL) {
+		MRW_WUNLOCK();
+		return;
+	}
 
-		LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) {
-			if (rt->mfc_parent == vifi) {
-				expire_mfc(rt);
+	/*
+	 * Tear down multicast forwarder state associated with this ifnet.
+	 * 1. Walk the vif list, matching vifs against this ifnet.
+	 * 2. Walk the multicast forwarding cache (mfc) looking for
+	 *    inner matches with this vif's index.
+	 * 3. Expire any matching multicast forwarding cache entries.
+	 * 4. Free vif state. This should disable ALLMULTI on the interface.
+	 */
+	for (vifi = 0; vifi < V_numvifs; vifi++) {
+		if (V_viftable[vifi].v_ifp != ifp)
+			continue;
+		for (i = 0; i < mfchashsize; i++) {
+			struct mfc *rt, *nrt;
+
+			LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) {
+				if (rt->mfc_parent == vifi) {
+					expire_mfc(rt);
+				}
 			}
 		}
+		del_vif_locked(vifi, &free_ptr);
+		if (free_ptr != NULL)
+			vifi_cnt++;
 	}
-	del_vif_locked(vifi, &free_ptr);
-	if (free_ptr != NULL)
-		vifi_cnt++;
-    }
 
-    MRW_WUNLOCK();
+	MRW_WUNLOCK();
 
-    /*
-     * Free IFP. We don't have to use free_ptr here as it is the same
-     * that ifp. Perform free as many times as required in case
-     * refcount is greater than 1.
-     */
-    for (i = 0; i < vifi_cnt; i++)
-	    if_free(ifp);
+	/*
+	 * Free IFP. We don't have to use free_ptr here as it is the same
+	 * that ifp. Perform free as many times as required in case
+	 * refcount is greater than 1.
+	 */
+	for (i = 0; i < vifi_cnt; i++)
+		if_free(ifp);
 }
 
 static void
@@ -687,55 +682,55 @@ static int
 ip_mrouter_init(struct socket *so, int version)
 {
 
-    CTR2(KTR_IPMF, "%s: so %p", __func__, so);
+	CTR2(KTR_IPMF, "%s: so %p", __func__, so);
 
-    if (version != 1)
-	return ENOPROTOOPT;
+	if (version != 1)
+		return ENOPROTOOPT;
 
-    MRW_WLOCK();
+	MRW_WLOCK();
 
-    if (ip_mrouter_unloading) {
-	MRW_WUNLOCK();
-	return ENOPROTOOPT;
-    }
+	if (ip_mrouter_unloading) {
+		MRW_WUNLOCK();
+		return ENOPROTOOPT;
+	}
 
-    if (V_ip_mrouter != NULL) {
-	MRW_WUNLOCK();
-	return EADDRINUSE;
-    }
+	if (V_ip_mrouter != NULL) {
+		MRW_WUNLOCK();
+		return EADDRINUSE;
+	}
 
-    V_mfchashtbl = hashinit_flags(mfchashsize, M_MRTABLE, &V_mfchash,
-	HASH_NOWAIT);
+	V_mfchashtbl = hashinit_flags(mfchashsize, M_MRTABLE, &V_mfchash,
+	    HASH_NOWAIT);
 
-    /* Create upcall ring */
-    mtx_init(&V_bw_upcalls_ring_mtx, "mroute upcall buf_ring mtx", NULL, MTX_DEF);
-    V_bw_upcalls_ring = buf_ring_alloc(BW_UPCALLS_MAX, M_MRTABLE,
-	M_NOWAIT, &V_bw_upcalls_ring_mtx);
-    if (!V_bw_upcalls_ring) {
-	MRW_WUNLOCK();
-	return (ENOMEM);
-    }
+	/* Create upcall ring */
+	mtx_init(&V_bw_upcalls_ring_mtx, "mroute upcall buf_ring mtx", NULL, MTX_DEF);
+	V_bw_upcalls_ring = buf_ring_alloc(BW_UPCALLS_MAX, M_MRTABLE,
+	    M_NOWAIT, &V_bw_upcalls_ring_mtx);
+	if (!V_bw_upcalls_ring) {
+		MRW_WUNLOCK();
+		return (ENOMEM);
+	}
 
-    TASK_INIT(&V_task, 0, ip_mrouter_upcall_thread, curvnet);
-    taskqueue_cancel(V_task_queue, &V_task, NULL);
-    taskqueue_unblock(V_task_queue);
+	TASK_INIT(&V_task, 0, ip_mrouter_upcall_thread, curvnet);
+	taskqueue_cancel(V_task_queue, &V_task, NULL);
+	taskqueue_unblock(V_task_queue);
 
-    callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls,
-	curvnet);
-    callout_reset(&V_bw_upcalls_ch, BW_UPCALLS_PERIOD, expire_bw_upcalls_send,
-	curvnet);
+	callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls,
+	    curvnet);
+	callout_reset(&V_bw_upcalls_ch, BW_UPCALLS_PERIOD, expire_bw_upcalls_send,
+	    curvnet);
 
-    V_ip_mrouter = so;
-    atomic_add_int(&ip_mrouter_cnt, 1);
+	V_ip_mrouter = so;
+	atomic_add_int(&ip_mrouter_cnt, 1);
 
-    /* This is a mutex required by buf_ring init, but not used internally */
-    mtx_init(&V_buf_ring_mtx, "mroute buf_ring mtx", NULL, MTX_DEF);
+	/* This is a mutex required by buf_ring init, but not used internally */
+	mtx_init(&V_buf_ring_mtx, "mroute buf_ring mtx", NULL, MTX_DEF);
 
-    MRW_WUNLOCK();
+	MRW_WUNLOCK();
 
-    CTR1(KTR_IPMF, "%s: done", __func__);
+	CTR1(KTR_IPMF, "%s: done", __func__);
 
-    return 0;
+	return 0;
 }
 
 /*
@@ -744,100 +739,100 @@ ip_mrouter_init(struct socket *so, int version)
 static int
 X_ip_mrouter_done(void)
 {
-    struct ifnet **ifps;
-    int nifp;
-    u_long i;
-    vifi_t vifi;
-    struct bw_upcall *bu;
-
-    if (V_ip_mrouter == NULL)
-	return (EINVAL);
-
-    /*
-     * Detach/disable hooks to the reset of the system.
-     */
-    V_ip_mrouter = NULL;
-    atomic_subtract_int(&ip_mrouter_cnt, 1);
-    V_mrt_api_config = 0;
-
-    /*
-     * Wait for all epoch sections to complete to ensure
-     * V_ip_mrouter = NULL is visible to others.
-     */
-    epoch_wait_preempt(net_epoch_preempt);
-
-    /* Stop and drain task queue */
-    taskqueue_block(V_task_queue);
-    while (taskqueue_cancel(V_task_queue, &V_task, NULL)) {
-    	taskqueue_drain(V_task_queue, &V_task);
-    }
-
-    ifps = malloc(MAXVIFS * sizeof(*ifps), M_TEMP, M_WAITOK);
-
-    MRW_WLOCK();
-    taskqueue_cancel(V_task_queue, &V_task, NULL);
-
-    /* Destroy upcall ring */
-    while ((bu = buf_ring_dequeue_mc(V_bw_upcalls_ring)) != NULL) {
-	free(bu, M_MRTABLE);
-    }
-    buf_ring_free(V_bw_upcalls_ring, M_MRTABLE);
-    mtx_destroy(&V_bw_upcalls_ring_mtx);
-
-    /*
-     * For each phyint in use, prepare to disable promiscuous reception
-     * of all IP multicasts.  Defer the actual call until the lock is released;
-     * just record the list of interfaces while locked.  Some interfaces use
-     * sx locks in their ioctl routines, which is not allowed while holding
-     * a non-sleepable lock.
-     */
-    KASSERT(V_numvifs <= MAXVIFS, ("More vifs than possible"));
-    for (vifi = 0, nifp = 0; vifi < V_numvifs; vifi++) {
-	if (!in_nullhost(V_viftable[vifi].v_lcl_addr) &&
-		!(V_viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) {
-	    ifps[nifp++] = V_viftable[vifi].v_ifp;
-	}
-    }
-    bzero((caddr_t)V_viftable, sizeof(*V_viftable) * MAXVIFS);
-    V_numvifs = 0;
-    V_pim_assert_enabled = 0;
-
-    callout_stop(&V_expire_upcalls_ch);
-    callout_stop(&V_bw_upcalls_ch);
-
-    /*
-     * Free all multicast forwarding cache entries.
-     * Do not use hashdestroy(), as we must perform other cleanup.
-     */
-    for (i = 0; i < mfchashsize; i++) {
-	struct mfc *rt, *nrt;
-
-	LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) {
-		expire_mfc(rt);
-	}
-    }
-    free(V_mfchashtbl, M_MRTABLE);
-    V_mfchashtbl = NULL;
-
-    bzero(V_nexpire, sizeof(V_nexpire[0]) * mfchashsize);
-
-    V_reg_vif_num = VIFI_INVALID;
-
-    mtx_destroy(&V_buf_ring_mtx);
-
-    MRW_WUNLOCK();
-
-    /*
-     * Now drop our claim on promiscuous multicast on the interfaces recorded
-     * above.  This is safe to do now because ALLMULTI is reference counted.
-     */
-    for (vifi = 0; vifi < nifp; vifi++)
-	    if_allmulti(ifps[vifi], 0);
-    free(ifps, M_TEMP);
-
-    CTR1(KTR_IPMF, "%s: done", __func__);
-
-    return 0;
+	struct ifnet **ifps;
+	int nifp;
+	u_long i;
+	vifi_t vifi;
+	struct bw_upcall *bu;
+
+	if (V_ip_mrouter == NULL)
+		return (EINVAL);
+
+	/*
+	 * Detach/disable hooks to the reset of the system.
+	 */
+	V_ip_mrouter = NULL;
+	atomic_subtract_int(&ip_mrouter_cnt, 1);
+	V_mrt_api_config = 0;
+
+	/*
+	 * Wait for all epoch sections to complete to ensure
+	 * V_ip_mrouter = NULL is visible to others.
+	 */
+	epoch_wait_preempt(net_epoch_preempt);
+
+	/* Stop and drain task queue */
+	taskqueue_block(V_task_queue);
+	while (taskqueue_cancel(V_task_queue, &V_task, NULL)) {
+		taskqueue_drain(V_task_queue, &V_task);
+	}
+
+	ifps = malloc(MAXVIFS * sizeof(*ifps), M_TEMP, M_WAITOK);
+
+	MRW_WLOCK();
+	taskqueue_cancel(V_task_queue, &V_task, NULL);
+
+	/* Destroy upcall ring */
+	while ((bu = buf_ring_dequeue_mc(V_bw_upcalls_ring)) != NULL) {
+		free(bu, M_MRTABLE);
+	}
+	buf_ring_free(V_bw_upcalls_ring, M_MRTABLE);
+	mtx_destroy(&V_bw_upcalls_ring_mtx);
+
+	/*
+	 * For each phyint in use, prepare to disable promiscuous reception
+	 * of all IP multicasts.  Defer the actual call until the lock is released;
+	 * just record the list of interfaces while locked.  Some interfaces use
+	 * sx locks in their ioctl routines, which is not allowed while holding
+	 * a non-sleepable lock.
+	 */
+	KASSERT(V_numvifs <= MAXVIFS, ("More vifs than possible"));
+	for (vifi = 0, nifp = 0; vifi < V_numvifs; vifi++) {
+		if (!in_nullhost(V_viftable[vifi].v_lcl_addr) &&
+		    !(V_viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) {
+			ifps[nifp++] = V_viftable[vifi].v_ifp;
+		}
+	}
+	bzero((caddr_t)V_viftable, sizeof(*V_viftable) * MAXVIFS);
+	V_numvifs = 0;
+	V_pim_assert_enabled = 0;
+
+	callout_stop(&V_expire_upcalls_ch);
+	callout_stop(&V_bw_upcalls_ch);
+
+	/*
+	 * Free all multicast forwarding cache entries.
+	 * Do not use hashdestroy(), as we must perform other cleanup.
+	 */
+	for (i = 0; i < mfchashsize; i++) {
+		struct mfc *rt, *nrt;
+
+		LIST_FOREACH_SAFE(rt, &V_mfchashtbl[i], mfc_hash, nrt) {
+			expire_mfc(rt);
+		}
+	}
+	free(V_mfchashtbl, M_MRTABLE);
+	V_mfchashtbl = NULL;
+
+	bzero(V_nexpire, sizeof(V_nexpire[0]) * mfchashsize);
+
+	V_reg_vif_num = VIFI_INVALID;
+
+	mtx_destroy(&V_buf_ring_mtx);
+
+	MRW_WUNLOCK();
+
+	/*
+	 * Now drop our claim on promiscuous multicast on the interfaces recorded
+	 * above.  This is safe to do now because ALLMULTI is reference counted.
+	 */
+	for (vifi = 0; vifi < nifp; vifi++)
+		if_allmulti(ifps[vifi], 0);
+	free(ifps, M_TEMP);
+
+	CTR1(KTR_IPMF, "%s: done", __func__);
+
+	return 0;
 }
 
 /*
@@ -846,12 +841,12 @@ X_ip_mrouter_done(void)
 static int
 set_assert(int i)
 {
-    if ((i != 1) && (i != 0))
-	return EINVAL;
+	if ((i != 1) && (i != 0))
+		return EINVAL;
 
-    V_pim_assert_enabled = i;
+	V_pim_assert_enabled = i;
 
-    return 0;
+	return 0;
 }
 
 /*
@@ -860,40 +855,40 @@ set_assert(int i)
 int
 set_api_config(uint32_t *apival)
 {
-    u_long i;
-
-    /*
-     * We can set the API capabilities only if it is the first operation
-     * after MRT_INIT. I.e.:
-     *  - there are no vifs installed
-     *  - pim_assert is not enabled
-     *  - the MFC table is empty
-     */
-    if (V_numvifs > 0) {
-	*apival = 0;
-	return EPERM;
-    }
-    if (V_pim_assert_enabled) {
-	*apival = 0;
-	return EPERM;
-    }
-
-    MRW_RLOCK();
-
-    for (i = 0; i < mfchashsize; i++) {
-	if (LIST_FIRST(&V_mfchashtbl[i]) != NULL) {
-	    MRW_RUNLOCK();
-	    *apival = 0;
-	    return EPERM;
-	}
-    }
-
-    MRW_RUNLOCK();
-
-    V_mrt_api_config = *apival & mrt_api_support;
-    *apival = V_mrt_api_config;
-
-    return 0;
+	u_long i;
+
+	/*
+	 * We can set the API capabilities only if it is the first operation
+	 * after MRT_INIT. I.e.:
+	 *  - there are no vifs installed
+	 *  - pim_assert is not enabled
+	 *  - the MFC table is empty
+	 */
+	if (V_numvifs > 0) {
+		*apival = 0;
+		return EPERM;
+	}
+	if (V_pim_assert_enabled) {
+		*apival = 0;
+		return EPERM;
+	}
+
+	MRW_RLOCK();
+
+	for (i = 0; i < mfchashsize; i++) {
+		if (LIST_FIRST(&V_mfchashtbl[i]) != NULL) {
+			MRW_RUNLOCK();
+			*apival = 0;
+			return EPERM;
+		}
+	}
+
+	MRW_RUNLOCK();
+
+	V_mrt_api_config = *apival & mrt_api_support;
+	*apival = V_mrt_api_config;
+
+	return 0;
 }
 
 /*
@@ -902,102 +897,101 @@ set_api_config(uint32_t *apival)
 static int
 add_vif(struct vifctl *vifcp)
 {
-    struct vif *vifp = V_viftable + vifcp->vifc_vifi;
-    struct sockaddr_in sin = {sizeof sin, AF_INET};
-    struct ifaddr *ifa;
-    struct ifnet *ifp;
-    int error;
-
-
-    if (vifcp->vifc_vifi >= MAXVIFS)
-	return EINVAL;
-    /* rate limiting is no longer supported by this code */
-    if (vifcp->vifc_rate_limit != 0) {
-	log(LOG_ERR, "rate limiting is no longer supported\n");
-	return EINVAL;
-    }
-
-    if (in_nullhost(vifcp->vifc_lcl_addr))
-	return EADDRNOTAVAIL;
-
-    /* Find the interface with an address in AF_INET family */
-    if (vifcp->vifc_flags & VIFF_REGISTER) {
-	/*
-	 * XXX: Because VIFF_REGISTER does not really need a valid
-	 * local interface (e.g. it could be 127.0.0.2), we don't
-	 * check its address.
-	 */
-	ifp = NULL;
-    } else {
-	struct epoch_tracker et;
+	struct vif *vifp = V_viftable + vifcp->vifc_vifi;
+	struct sockaddr_in sin = {sizeof sin, AF_INET};
+	struct ifaddr *ifa;
+	struct ifnet *ifp;
+	int error;
 
-	sin.sin_addr = vifcp->vifc_lcl_addr;
-	NET_EPOCH_ENTER(et);
-	ifa = ifa_ifwithaddr((struct sockaddr *)&sin);
-	if (ifa == NULL) {
-	    NET_EPOCH_EXIT(et);
-	    return EADDRNOTAVAIL;
+	if (vifcp->vifc_vifi >= MAXVIFS)
+		return EINVAL;
+	/* rate limiting is no longer supported by this code */
+	if (vifcp->vifc_rate_limit != 0) {
+		log(LOG_ERR, "rate limiting is no longer supported\n");
+		return EINVAL;
+	}
+
+	if (in_nullhost(vifcp->vifc_lcl_addr))
+		return EADDRNOTAVAIL;
+
+	/* Find the interface with an address in AF_INET family */
+	if (vifcp->vifc_flags & VIFF_REGISTER) {
+		/*
+		 * XXX: Because VIFF_REGISTER does not really need a valid
+		 * local interface (e.g. it could be 127.0.0.2), we don't
+		 * check its address.
+		 */
+		ifp = NULL;
+	} else {
+		struct epoch_tracker et;
+
+		sin.sin_addr = vifcp->vifc_lcl_addr;
+		NET_EPOCH_ENTER(et);
+		ifa = ifa_ifwithaddr((struct sockaddr *)&sin);
+		if (ifa == NULL) {
+			NET_EPOCH_EXIT(et);
+			return EADDRNOTAVAIL;
+		}
+		ifp = ifa->ifa_ifp;
+		/* XXX FIXME we need to take a ref on ifp and cleanup properly! */
+		NET_EPOCH_EXIT(et);
+	}
+
+	if ((vifcp->vifc_flags & VIFF_TUNNEL) != 0) {
+		CTR1(KTR_IPMF, "%s: tunnels are no longer supported", __func__);
+		return EOPNOTSUPP;
+	} else if (vifcp->vifc_flags & VIFF_REGISTER) {
+		ifp = V_multicast_register_if = if_alloc(IFT_LOOP);
*** 2270 LINES SKIPPED ***