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:
Robert Watson 2004-08-06 03:45:45 +00:00
parent 6f40c417ca
commit f31f65a708
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=133192
6 changed files with 23 additions and 12 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 *

View File

@ -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);
}

View File

@ -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);
}