diff options
author | rwatson <rwatson@FreeBSD.org> | 2004-08-06 03:45:45 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2004-08-06 03:45:45 +0000 |
commit | 11a2e8ce3c40516b1b505be3d5cdbf720ba8069f (patch) | |
tree | 38d3ac3c4e0dee27c2bff0875fc15138701f62ba | |
parent | 6680706c2bf89170fdfb9bd5bc9332aa7319a17a (diff) | |
download | FreeBSD-src-11a2e8ce3c40516b1b505be3d5cdbf720ba8069f.zip FreeBSD-src-11a2e8ce3c40516b1b505be3d5cdbf720ba8069f.tar.gz |
Pass pcbinfo structures to in6_pcbnotify() rather than pcbhead
structures, allowing in6_pcbnotify() to lock the pcbinfo and each
inpcb that it notifies of ICMPv6 events. This prevents inpcb
assertions from firing when IPv6 generates and delievers event
notifications for inpcbs.
Reported by: kuriyama
Tested by: kuriyama
-rw-r--r-- | sys/netinet/tcp_subr.c | 4 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 4 | ||||
-rw-r--r-- | sys/netinet6/in6_pcb.c | 18 | ||||
-rw-r--r-- | sys/netinet6/in6_pcb.h | 2 | ||||
-rw-r--r-- | sys/netinet6/raw_ip6.c | 3 | ||||
-rw-r--r-- | sys/netinet6/udp6_usrreq.c | 4 |
6 files changed, 23 insertions, 12 deletions
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 1e23552..cab3e6b 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1236,7 +1236,7 @@ tcp6_ctlinput(cmd, sa, d) bzero(&th, sizeof(th)); m_copydata(m, off, sizeof(*thp), (caddr_t)&th); - in6_pcbnotify(&tcb, sa, th.th_dport, + in6_pcbnotify(&tcbinfo, sa, th.th_dport, (struct sockaddr *)ip6cp->ip6c_src, th.th_sport, cmd, NULL, notify); @@ -1247,7 +1247,7 @@ tcp6_ctlinput(cmd, sa, d) inc.inc_isipv6 = 1; syncache_unreach(&inc, &th); } else - in6_pcbnotify(&tcb, sa, 0, (const struct sockaddr *)sa6_src, + in6_pcbnotify(&tcbinfo, sa, 0, (const struct sockaddr *)sa6_src, 0, cmd, NULL, notify); } #endif /* INET6 */ diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 1e23552..cab3e6b 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -1236,7 +1236,7 @@ tcp6_ctlinput(cmd, sa, d) bzero(&th, sizeof(th)); m_copydata(m, off, sizeof(*thp), (caddr_t)&th); - in6_pcbnotify(&tcb, sa, th.th_dport, + in6_pcbnotify(&tcbinfo, sa, th.th_dport, (struct sockaddr *)ip6cp->ip6c_src, th.th_sport, cmd, NULL, notify); @@ -1247,7 +1247,7 @@ tcp6_ctlinput(cmd, sa, d) inc.inc_isipv6 = 1; syncache_unreach(&inc, &th); } else - in6_pcbnotify(&tcb, sa, 0, (const struct sockaddr *)sa6_src, + in6_pcbnotify(&tcbinfo, sa, 0, (const struct sockaddr *)sa6_src, 0, cmd, NULL, notify); } #endif /* INET6 */ diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 674dbd1..48d153f 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -610,8 +610,8 @@ in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam) * Must be called at splnet. */ void -in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, cmdarg, notify) - struct inpcbhead *head; +in6_pcbnotify(pcbinfo, dst, fport_arg, src, lport_arg, cmd, cmdarg, notify) + struct inpcbinfo *pcbinfo; struct sockaddr *dst; const struct sockaddr *src; u_int fport_arg, lport_arg; @@ -619,6 +619,7 @@ in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, cmdarg, notify) void *cmdarg; struct inpcb *(*notify) __P((struct inpcb *, int)); { + struct inpcbhead *head; struct inpcb *inp, *ninp; struct sockaddr_in6 sa6_src, *sa6_dst; u_short fport = fport_arg, lport = lport_arg; @@ -656,11 +657,16 @@ in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, cmdarg, notify) } errno = inet6ctlerrmap[cmd]; s = splnet(); + head = pcbinfo->listhead; + INP_INFO_WLOCK(pcbinfo); for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) { + INP_LOCK(inp); ninp = LIST_NEXT(inp, inp_list); - if ((inp->inp_vflag & INP_IPV6) == 0) + if ((inp->inp_vflag & INP_IPV6) == 0) { + INP_UNLOCK(inp); continue; + } /* * If the error designates a new path MTU for a destination @@ -698,13 +704,17 @@ in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, cmdarg, notify) (!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) && !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr)) || - (fport && inp->inp_fport != fport)) + (fport && inp->inp_fport != fport)) { + INP_UNLOCK(inp); continue; + } do_notify: if (notify) (*notify)(inp, errno); + INP_UNLOCK(inp); } + INP_INFO_WUNLOCK(pcbinfo); splx(s); } diff --git a/sys/netinet6/in6_pcb.h b/sys/netinet6/in6_pcb.h index f6cc209..cc8e643 100644 --- a/sys/netinet6/in6_pcb.h +++ b/sys/netinet6/in6_pcb.h @@ -85,7 +85,7 @@ struct inpcb * in6_pcblookup_hash __P((struct inpcbinfo *, struct in6_addr *, u_int, struct in6_addr *, u_int, int, struct ifnet *)); -void in6_pcbnotify __P((struct inpcbhead *, struct sockaddr *, +void in6_pcbnotify __P((struct inpcbinfo *, struct sockaddr *, u_int, const struct sockaddr *, u_int, int, void *, struct inpcb *(*)(struct inpcb *, int))); struct inpcb * diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 994cf5f..204ec29 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -298,7 +298,8 @@ rip6_ctlinput(cmd, sa, d) sa6_src = &sa6_any; } - (void) in6_pcbnotify(&ripcb, sa, 0, (const struct sockaddr *)sa6_src, + (void) in6_pcbnotify(&ripcbinfo, sa, 0, + (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify); } diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index c248ce2..6b1dc25 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -444,11 +444,11 @@ udp6_ctlinput(cmd, sa, d) bzero(&uh, sizeof(uh)); m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh); - (void) in6_pcbnotify(&udb, sa, uh.uh_dport, + (void) in6_pcbnotify(&udbinfo, sa, uh.uh_dport, (struct sockaddr *)ip6cp->ip6c_src, uh.uh_sport, cmd, cmdarg, notify); } else - (void) in6_pcbnotify(&udb, sa, 0, + (void) in6_pcbnotify(&udbinfo, sa, 0, (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify); } |