summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/ip6_mroute.c
diff options
context:
space:
mode:
authorsuz <suz@FreeBSD.org>2005-12-09 04:42:19 +0000
committersuz <suz@FreeBSD.org>2005-12-09 04:42:19 +0000
commit4f9b4499560a6797b5e9701812a95260e331572c (patch)
tree828cf74bfb51e819e939820c2e3443383cb90998 /sys/netinet6/ip6_mroute.c
parentb2df0e75f4b35aa66c5dc2921f8e4786ab0839b8 (diff)
downloadFreeBSD-src-4f9b4499560a6797b5e9701812a95260e331572c.zip
FreeBSD-src-4f9b4499560a6797b5e9701812a95260e331572c.tar.gz
fixed a kernel crash at the initialization time of PIM-SM register interface
MFC after: 2 days
Diffstat (limited to 'sys/netinet6/ip6_mroute.c')
-rw-r--r--sys/netinet6/ip6_mroute.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c
index c00fdbf..a719ddf 100644
--- a/sys/netinet6/ip6_mroute.c
+++ b/sys/netinet6/ip6_mroute.c
@@ -101,6 +101,7 @@
#include <sys/time.h>
#include <net/if.h>
+#include <net/if_types.h>
#include <net/raw_cb.h>
#include <net/route.h>
@@ -169,12 +170,15 @@ extern struct socket *ip_mrouter;
/*
* 'Interfaces' associated with decapsulator (so we can tell
* packets that went through it from ones that get reflected
- * by a broken gateway). These interfaces are never linked into
- * the system ifnet list & no routes point to them. I.e., packets
- * can't be sent this way. They only exist as a placeholder for
- * multicast source verification.
+ * by a broken gateway). Different from IPv4 register_if,
+ * these interfaces are linked into the system ifnet list,
+ * because per-interface IPv6 statistics are maintained in
+ * ifp->if_afdata. But it does not have any routes point
+ * to them. I.e., packets can't be sent this way. They
+ * only exist as a placeholder for multicast source
+ * verification.
*/
-struct ifnet multicast_register_if6;
+static struct ifnet *multicast_register_if6;
#define ENCAP_HOPS 64
@@ -552,9 +556,11 @@ ip6_mrouter_done()
/*
* Reset register interface
*/
- if (reg_mif_num != (mifi_t)-1) {
- if_detach(&multicast_register_if6);
+ if (reg_mif_num != (mifi_t)-1 && multicast_register_if6 != NULL) {
+ if_detach(multicast_register_if6);
+ if_free(multicast_register_if6);
reg_mif_num = (mifi_t)-1;
+ multicast_register_if6 = NULL;
}
ip6_mrouter = NULL;
@@ -596,14 +602,22 @@ add_m6if(mifcp)
ifp = ifnet_byindex(mifcp->mif6c_pifi);
if (mifcp->mif6c_flags & MIFF_REGISTER) {
- ifp = &multicast_register_if6;
-
if (reg_mif_num == (mifi_t)-1) {
+ ifp = if_alloc(IFT_OTHER);
+
if_initname(ifp, "register_mif", 0);
ifp->if_flags |= IFF_LOOPBACK;
- ifp->if_index = mifcp->mif6c_mifi;
- reg_mif_num = mifcp->mif6c_mifi;
if_attach(ifp);
+ multicast_register_if6 = ifp;
+ reg_mif_num = mifcp->mif6c_mifi;
+ /*
+ * it is impossible to guess the ifindex of the
+ * register interface. So mif6c_pifi is automatically
+ * calculated.
+ */
+ mifcp->mif6c_pifi = ifp->if_index;
+ } else {
+ ifp = multicast_register_if6;
}
} /* if REGISTER */
@@ -676,9 +690,12 @@ del_m6if(mifip)
if_allmulti(ifp, 0);
} else {
- if (reg_mif_num != (mifi_t)-1) {
- if_detach(&multicast_register_if6);
+ if (reg_mif_num != (mifi_t)-1 &&
+ multicast_register_if6 != NULL) {
+ if_detach(multicast_register_if6);
+ if_free(multicast_register_if6);
reg_mif_num = (mifi_t)-1;
+ multicast_register_if6 = NULL;
}
}
OpenPOWER on IntegriCloud