summaryrefslogtreecommitdiffstats
path: root/sys/netinet/udp_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/netinet/udp_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/netinet/udp_usrreq.c')
-rw-r--r--sys/netinet/udp_usrreq.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index af4769f..1522966 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -319,8 +319,12 @@ udp_input(m, off)
* port. It * assumes that an application will never
* clear these options after setting them.
*/
- if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0)
+ SOCK_LOCK(last->inp_socket);
+ if ((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0) {
+ SOCK_UNLOCK(last->inp_socket);
break;
+ } else
+ SOCK_UNLOCK(last->inp_socket);
}
if (last == NULL) {
@@ -384,8 +388,10 @@ udp_input(m, off)
*/
udp_in.sin_port = uh->uh_sport;
udp_in.sin_addr = ip->ip_src;
+ SOCK_LOCK(inp->inp_socket);
if (inp->inp_flags & INP_CONTROLOPTS
|| inp->inp_socket->so_options & SO_TIMESTAMP) {
+ SOCK_UNLOCK(inp->inp_socket);
#ifdef INET6
if (inp->inp_vflag & INP_IPV6) {
int savedflags;
@@ -398,7 +404,8 @@ udp_input(m, off)
} else
#endif
ip_savecontrol(inp, &opts, ip, m);
- }
+ } else
+ SOCK_UNLOCK(inp->inp_socket);
m_adj(m, iphlen + sizeof(struct udphdr));
#ifdef INET6
if (inp->inp_vflag & INP_IPV6) {
@@ -411,7 +418,9 @@ udp_input(m, off)
udpstat.udps_fullsock++;
goto bad;
}
+ SOCK_LOCK(inp->inp_socket);
sorwakeup(inp->inp_socket);
+ SOCK_UNLOCK(inp->inp_socket);
return;
bad:
m_freem(m);
@@ -453,8 +462,10 @@ udp_append(last, ip, n, off)
struct sockaddr *append_sa;
struct mbuf *opts = 0;
+ SOCK_LOCK(last->inp_socket);
if (last->inp_flags & INP_CONTROLOPTS ||
last->inp_socket->so_options & SO_TIMESTAMP) {
+ SOCK_UNLOCK(last->inp_socket);
#ifdef INET6
if (last->inp_vflag & INP_IPV6) {
int savedflags;
@@ -470,7 +481,8 @@ udp_append(last, ip, n, off)
} else
#endif
ip_savecontrol(last, &opts, ip, n);
- }
+ } else
+ SOCK_UNLOCK(last->inp_socket);
#ifdef INET6
if (last->inp_vflag & INP_IPV6) {
if (udp_in6.uin6_init_done == 0) {
@@ -487,8 +499,11 @@ udp_append(last, ip, n, off)
if (opts)
m_freem(opts);
udpstat.udps_fullsock++;
- } else
+ } else {
+ SOCK_LOCK(last->inp_socket);
sorwakeup(last->inp_socket);
+ SOCK_UNLOCK(last->inp_socket);
+ }
}
/*
@@ -501,8 +516,10 @@ udp_notify(inp, errno)
int errno;
{
inp->inp_socket->so_error = errno;
+ SOCK_LOCK(inp->inp_socket);
sorwakeup(inp->inp_socket);
sowwakeup(inp->inp_socket);
+ SOCK_UNLOCK(inp->inp_socket);
}
void
@@ -678,7 +695,7 @@ udp_output(inp, m, addr, control, td)
register int len = m->m_pkthdr.len;
struct in_addr laddr;
struct sockaddr_in *sin;
- int s = 0, error = 0;
+ int s = 0, error = 0, soopts;
if (control)
m_freem(control); /* XXX */
@@ -759,8 +776,11 @@ udp_output(inp, m, addr, control, td)
goto release;
}
#endif /*IPSEC*/
+ SOCK_LOCK(inp->inp_socket);
+ soopts = inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST);
+ SOCK_UNLOCK(inp->inp_socket);
error = ip_output(m, inp->inp_options, &inp->inp_route,
- (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)),
+ soopts,
inp->inp_moptions);
if (addr) {
@@ -799,7 +819,9 @@ udp_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();
in_pcbdetach(inp);
splx(s);
@@ -864,8 +886,11 @@ udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
error = in_pcbconnect(inp, nam, td);
splx(s);
- if (error == 0)
+ if (error == 0) {
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
+ }
return error;
}
@@ -900,7 +925,9 @@ udp_disconnect(struct socket *so)
in_pcbdisconnect(inp);
inp->inp_laddr.s_addr = INADDR_ANY;
splx(s);
+ SOCK_LOCK(so);
so->so_state &= ~SS_ISCONNECTED; /* XXX */
+ SOCK_UNLOCK(so);
return 0;
}
OpenPOWER on IntegriCloud