git: 3a01a97d23a2 - main - mroute: partially sanitize the file
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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 ***