summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2004-08-06 03:45:45 +0000
committerrwatson <rwatson@FreeBSD.org>2004-08-06 03:45:45 +0000
commit11a2e8ce3c40516b1b505be3d5cdbf720ba8069f (patch)
tree38d3ac3c4e0dee27c2bff0875fc15138701f62ba /sys/netinet6
parent6680706c2bf89170fdfb9bd5bc9332aa7319a17a (diff)
downloadFreeBSD-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
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/in6_pcb.c18
-rw-r--r--sys/netinet6/in6_pcb.h2
-rw-r--r--sys/netinet6/raw_ip6.c3
-rw-r--r--sys/netinet6/udp6_usrreq.c4
4 files changed, 19 insertions, 8 deletions
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);
}
OpenPOWER on IntegriCloud