diff options
author | ume <ume@FreeBSD.org> | 2001-08-04 17:10:14 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2001-08-04 17:10:14 +0000 |
commit | 215c0c107efbdc79c1fc7eb07321d5285fc338d2 (patch) | |
tree | 7b7ce4133ecd9652e3448fa7d662f6e27859de96 /sys/netinet | |
parent | edba6eee5eb38b18947df183e9a90212979525ed (diff) | |
download | FreeBSD-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/netinet')
-rw-r--r-- | sys/netinet/in.c | 12 | ||||
-rw-r--r-- | sys/netinet/in_pcb.c | 38 | ||||
-rw-r--r-- | sys/netinet/in_pcb.h | 1 |
3 files changed, 51 insertions, 0 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 170a343..7242545 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -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 diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 2d31c30..c967851 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -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 diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 1ae93d2..2b01db4 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -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 *)); |