summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/udp6_usrreq.c
diff options
context:
space:
mode:
authortanimura <tanimura@FreeBSD.org>2002-05-20 05:41:09 +0000
committertanimura <tanimura@FreeBSD.org>2002-05-20 05:41:09 +0000
commit92d8381dd544a8237b3fd68c4e7fce9bd0903fb2 (patch)
tree2465ddbcecac65f96c5c6d5cef1a4fe3f1ac03f8 /sys/netinet6/udp6_usrreq.c
parent969293170b27461145f69a538d5abd15fea34ba1 (diff)
downloadFreeBSD-src-92d8381dd544a8237b3fd68c4e7fce9bd0903fb2.zip
FreeBSD-src-92d8381dd544a8237b3fd68c4e7fce9bd0903fb2.tar.gz
Lock down a socket, milestone 1.
o Add a mutex (sb_mtx) to struct sockbuf. This protects the data in a socket buffer. The mutex in the receive buffer also protects the data in struct socket. o Determine the lock strategy for each members in struct socket. o Lock down the following members: - so_count - so_options - so_linger - so_state o Remove *_locked() socket APIs. Make the following socket APIs touching the members above now require a locked socket: - sodisconnect() - soisconnected() - soisconnecting() - soisdisconnected() - soisdisconnecting() - sofree() - soref() - sorele() - sorwakeup() - sotryfree() - sowakeup() - sowwakeup() Reviewed by: alfred
Diffstat (limited to 'sys/netinet6/udp6_usrreq.c')
-rw-r--r--sys/netinet6/udp6_usrreq.c57
1 files changed, 49 insertions, 8 deletions
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 20913e6..0e58be5 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -269,10 +269,18 @@ udp6_input(mp, offp, proto)
* and m_copy() will copy M_PKTHDR
* only if offset is 0.
*/
- if (last->in6p_flags & IN6P_CONTROLOPTS
- || last->in6p_socket->so_options & SO_TIMESTAMP)
+ if (last->in6p_flags & IN6P_CONTROLOPTS)
ip6_savecontrol(last, &opts,
ip6, n);
+ else {
+ SOCK_LOCK(last->in6p_socket);
+ if (last->in6p_socket->so_options & SO_TIMESTAMP) {
+ SOCK_UNLOCK(last->in6p_socket);
+ ip6_savecontrol(last, &opts,
+ ip6, n);
+ } else
+ SOCK_UNLOCK(last->in6p_socket);
+ }
m_adj(n, off + sizeof(struct udphdr));
if (sbappendaddr(&last->in6p_socket->so_rcv,
@@ -282,8 +290,11 @@ udp6_input(mp, offp, proto)
if (opts)
m_freem(opts);
udpstat.udps_fullsock++;
- } else
+ } else {
+ SOCK_LOCK(last->in6p_socket);
sorwakeup(last->in6p_socket);
+ SOCK_UNLOCK(last->in6p_socket);
+ }
opts = NULL;
}
}
@@ -296,9 +307,13 @@ udp6_input(mp, offp, proto)
* port. It assumes that an application will never
* clear these options after setting them.
*/
+ SOCK_LOCK(last->in6p_socket);
if ((last->in6p_socket->so_options &
- (SO_REUSEPORT|SO_REUSEADDR)) == 0)
+ (SO_REUSEPORT|SO_REUSEADDR)) == 0) {
+ SOCK_UNLOCK(last->in6p_socket);
break;
+ } else
+ SOCK_UNLOCK(last->in6p_socket);
}
if (last == NULL) {
@@ -320,9 +335,16 @@ udp6_input(mp, offp, proto)
goto bad;
}
#endif /* IPSEC */
- if (last->in6p_flags & IN6P_CONTROLOPTS
- || last->in6p_socket->so_options & SO_TIMESTAMP)
+ if (last->in6p_flags & IN6P_CONTROLOPTS)
ip6_savecontrol(last, &opts, ip6, m);
+ else {
+ SOCK_LOCK(last->in6p_socket);
+ if (last->in6p_socket->so_options & SO_TIMESTAMP) {
+ SOCK_UNLOCK(last->in6p_socket);
+ ip6_savecontrol(last, &opts, ip6, m);
+ } else
+ SOCK_UNLOCK(last->in6p_socket);
+ }
m_adj(m, off + sizeof(struct udphdr));
if (sbappendaddr(&last->in6p_socket->so_rcv,
@@ -331,7 +353,9 @@ udp6_input(mp, offp, proto)
udpstat.udps_fullsock++;
goto bad;
}
+ SOCK_LOCK(last->in6p_socket);
sorwakeup(last->in6p_socket);
+ SOCK_UNLOCK(last->in6p_socket);
return IPPROTO_DONE;
}
/*
@@ -375,9 +399,16 @@ udp6_input(mp, offp, proto)
*/
init_sin6(&udp_in6, m); /* general init */
udp_in6.sin6_port = uh->uh_sport;
- if (in6p->in6p_flags & IN6P_CONTROLOPTS
- || in6p->in6p_socket->so_options & SO_TIMESTAMP)
+ if (in6p->in6p_flags & IN6P_CONTROLOPTS)
ip6_savecontrol(in6p, &opts, ip6, m);
+ else {
+ SOCK_LOCK(in6p->in6p_socket);
+ if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
+ SOCK_UNLOCK(in6p->in6p_socket);
+ ip6_savecontrol(in6p, &opts, ip6, m);
+ } else
+ SOCK_UNLOCK(in6p->in6p_socket);
+ }
m_adj(m, off + sizeof(struct udphdr));
if (sbappendaddr(&in6p->in6p_socket->so_rcv,
(struct sockaddr *)&udp_in6,
@@ -385,7 +416,9 @@ udp6_input(mp, offp, proto)
udpstat.udps_fullsock++;
goto bad;
}
+ SOCK_LOCK(in6p->in6p_socket);
sorwakeup(in6p->in6p_socket);
+ SOCK_UNLOCK(in6p->in6p_socket);
return IPPROTO_DONE;
bad:
if (m)
@@ -509,7 +542,9 @@ udp6_abort(struct socket *so)
inp = sotoinpcb(so);
if (inp == 0)
return EINVAL; /* ??? possible? panic instead? */
+ SOCK_LOCK(so);
soisdisconnected(so);
+ SOCK_UNLOCK(so);
s = splnet();
in6_pcbdetach(inp);
splx(s);
@@ -614,7 +649,9 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
if (error == 0) {
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
}
return error;
}
@@ -629,7 +666,9 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
}
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
}
return error;
}
@@ -673,7 +712,9 @@ udp6_disconnect(struct socket *so)
in6_pcbdisconnect(inp);
inp->in6p_laddr = in6addr_any;
splx(s);
+ SOCK_LOCK(so);
so->so_state &= ~SS_ISCONNECTED; /* XXX */
+ SOCK_UNLOCK(so);
return 0;
}
OpenPOWER on IntegriCloud