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
This commit is contained in:
parent
6f40c417ca
commit
f31f65a708
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=133192
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 *
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user