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
This commit is contained in:
parent
4447e914e8
commit
e43cc4ae36
@ -48,6 +48,7 @@
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
|
||||
#include <netinet/igmp_var.h>
|
||||
|
||||
@ -68,6 +69,9 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
|
||||
|
||||
struct in_multihead in_multihead; /* XXX BSS initialization */
|
||||
|
||||
extern struct inpcbinfo ripcbinfo;
|
||||
extern struct inpcbinfo udbinfo;
|
||||
|
||||
/*
|
||||
* Return 1 if an internet address is for a ``local'' host
|
||||
* (one to which we have a connection). If subnetsarelocal
|
||||
@ -402,6 +406,14 @@ in_control(so, cmd, data, ifp, p)
|
||||
* a routing process they will come back.
|
||||
*/
|
||||
in_ifadown(&ia->ia_ifa, 1);
|
||||
/*
|
||||
* XXX horrible hack to detect that we are being called
|
||||
* from if_detach()
|
||||
*/
|
||||
if (!ifnet_addrs[ifp->if_index - 1]) {
|
||||
in_pcbpurgeif0(LIST_FIRST(ripcbinfo.listhead), ifp);
|
||||
in_pcbpurgeif0(LIST_FIRST(udbinfo.listhead), ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Protect from ipintr() traversing address list
|
||||
|
@ -689,6 +689,44 @@ in_pcbnotifyall(head, faddr, errno, notify)
|
||||
splx(s);
|
||||
}
|
||||
|
||||
void
|
||||
in_pcbpurgeif0(head, ifp)
|
||||
struct inpcb *head;
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct inpcb *inp;
|
||||
struct ip_moptions *imo;
|
||||
int i, gap;
|
||||
|
||||
for (inp = head; inp != NULL; inp = LIST_NEXT(inp, inp_list)) {
|
||||
imo = inp->inp_moptions;
|
||||
if ((inp->inp_vflag & INP_IPV4) &&
|
||||
imo != NULL) {
|
||||
/*
|
||||
* Unselect the outgoing interface if it is being
|
||||
* detached.
|
||||
*/
|
||||
if (imo->imo_multicast_ifp == ifp)
|
||||
imo->imo_multicast_ifp = NULL;
|
||||
|
||||
/*
|
||||
* Drop multicast group membership if we joined
|
||||
* through the interface being detached.
|
||||
*/
|
||||
for (i = 0, gap = 0; i < imo->imo_num_memberships;
|
||||
i++) {
|
||||
if (imo->imo_membership[i]->inm_ifp == ifp) {
|
||||
in_delmulti(imo->imo_membership[i]);
|
||||
gap++;
|
||||
} else if (gap != 0)
|
||||
imo->imo_membership[i - gap] =
|
||||
imo->imo_membership[i];
|
||||
}
|
||||
imo->imo_num_memberships -= gap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for alternatives when higher level complains
|
||||
* about service problems. For now, invalidate cached
|
||||
|
@ -275,6 +275,7 @@ extern int ipport_lastauto;
|
||||
extern int ipport_hifirstauto;
|
||||
extern int ipport_hilastauto;
|
||||
|
||||
void in_pcbpurgeif0 __P((struct inpcb *, struct ifnet *));
|
||||
void in_losing __P((struct inpcb *));
|
||||
void in_rtchange __P((struct inpcb *, int));
|
||||
int in_pcballoc __P((struct socket *, struct inpcbinfo *, struct proc *));
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 *));
|
||||
|
Loading…
x
Reference in New Issue
Block a user