summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2001-08-04 17:10:14 +0000
committerume <ume@FreeBSD.org>2001-08-04 17:10:14 +0000
commit215c0c107efbdc79c1fc7eb07321d5285fc338d2 (patch)
tree7b7ce4133ecd9652e3448fa7d662f6e27859de96 /sys/netinet6
parentedba6eee5eb38b18947df183e9a90212979525ed (diff)
downloadFreeBSD-src-215c0c107efbdc79c1fc7eb07321d5285fc338d2.zip
FreeBSD-src-215c0c107efbdc79c1fc7eb07321d5285fc338d2.tar.gz
When running aplication joined multicast address,
removing network card, and kill aplication. imo_membership[].inm_ifp refer interface pointer after removing interface. When kill aplication, release socket,and imo_membership. imo_membership use already not exist interface pointer. Then, kernel panic. PR: 29345 Submitted by: Inoue Yuichi <inoue@nd.net.fujitsu.co.jp> Obtained from: KAME MFC after: 3 days
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/in6_ifattach.c7
-rw-r--r--sys/netinet6/in6_pcb.c39
-rw-r--r--sys/netinet6/in6_pcb.h1
3 files changed, 47 insertions, 0 deletions
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 516826d..3e41bd7 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -47,10 +47,12 @@
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
+#include <netinet/in_pcb.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_var.h>
+#include <netinet6/in6_pcb.h>
#include <netinet6/in6_ifattach.h>
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
@@ -72,6 +74,9 @@ int ip6_auto_linklocal = 1; /* enable by default */
struct callout in6_tmpaddrtimer_ch;
+extern struct inpcbinfo udbinfo;
+extern struct inpcbinfo ripcbinfo;
+
static int get_rand_ifid __P((struct ifnet *, struct in6_addr *));
static int generate_tmp_ifid __P((u_int8_t *, const u_int8_t *, u_int8_t *));
static int get_hw_ifid __P((struct ifnet *, struct in6_addr *));
@@ -942,6 +947,8 @@ in6_ifdetach(ifp)
}
/* leave from all multicast groups joined */
+ in6_pcbpurgeif0(LIST_FIRST(udbinfo.listhead), ifp);
+ in6_pcbpurgeif0(LIST_FIRST(ripcbinfo.listhead), ifp);
for (in6m = LIST_FIRST(&in6_multihead); in6m; in6m = in6m_next) {
in6m_next = LIST_NEXT(in6m, in6m_entry);
if (in6m->in6m_ifp != ifp)
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index 9175a65..de4f1a8 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -932,6 +932,45 @@ in6_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
}
}
+void
+in6_pcbpurgeif0(head, ifp)
+ struct in6pcb *head;
+ struct ifnet *ifp;
+{
+ struct in6pcb *in6p;
+ struct ip6_moptions *im6o;
+ struct in6_multi_mship *imm, *nimm;
+
+ for (in6p = head; in6p != NULL; in6p = LIST_NEXT(in6p, inp_list)) {
+ im6o = in6p->in6p_moptions;
+ if ((in6p->inp_vflag & INP_IPV6) &&
+ im6o) {
+ /*
+ * Unselect the outgoing interface if it is being
+ * detached.
+ */
+ if (im6o->im6o_multicast_ifp == ifp)
+ im6o->im6o_multicast_ifp = NULL;
+
+ /*
+ * Drop multicast group membership if we joined
+ * through the interface being detached.
+ * XXX controversial - is it really legal for kernel
+ * to force this?
+ */
+ for (imm = im6o->im6o_memberships.lh_first;
+ imm != NULL; imm = nimm) {
+ nimm = imm->i6mm_chain.le_next;
+ if (imm->i6mm_maddr->in6m_ifp == ifp) {
+ LIST_REMOVE(imm, i6mm_chain);
+ in6_delmulti(imm->i6mm_maddr);
+ free(imm, M_IPMADDR);
+ }
+ }
+ }
+ }
+}
+
/*
* Check for alternatives when higher level complains
* about service problems. For now, invalidate cached
diff --git a/sys/netinet6/in6_pcb.h b/sys/netinet6/in6_pcb.h
index 15cd033..df8e2c8 100644
--- a/sys/netinet6/in6_pcb.h
+++ b/sys/netinet6/in6_pcb.h
@@ -74,6 +74,7 @@
#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
+void in6_pcbpurgeif0 __P((struct in6pcb *, struct ifnet *));
void in6_losing __P((struct inpcb *));
int in6_pcballoc __P((struct socket *, struct inpcbinfo *, struct proc *));
int in6_pcbbind __P((struct inpcb *, struct sockaddr *, struct proc *));
OpenPOWER on IntegriCloud