summaryrefslogtreecommitdiffstats
path: root/sys/netinet
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
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')
-rw-r--r--sys/netinet/accf_data.c10
-rw-r--r--sys/netinet/accf_http.c31
-rw-r--r--sys/netinet/in_pcb.c77
-rw-r--r--sys/netinet/ip_divert.c21
-rw-r--r--sys/netinet/ip_input.c5
-rw-r--r--sys/netinet/ip_mroute.c2
-rw-r--r--sys/netinet/raw_ip.c52
-rw-r--r--sys/netinet/tcp_input.c102
-rw-r--r--sys/netinet/tcp_output.c17
-rw-r--r--sys/netinet/tcp_reass.c102
-rw-r--r--sys/netinet/tcp_subr.c14
-rw-r--r--sys/netinet/tcp_timer.c68
-rw-r--r--sys/netinet/tcp_timewait.c14
-rw-r--r--sys/netinet/tcp_usrreq.c63
-rw-r--r--sys/netinet/udp_usrreq.c41
15 files changed, 499 insertions, 120 deletions
diff --git a/sys/netinet/accf_data.c b/sys/netinet/accf_data.c
index 46c92e3..4470733 100644
--- a/sys/netinet/accf_data.c
+++ b/sys/netinet/accf_data.c
@@ -30,6 +30,8 @@
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/sysctl.h>
#include <sys/signalvar.h>
#include <sys/socketvar.h>
@@ -57,11 +59,15 @@ static void
sohasdata(struct socket *so, void *arg, int waitflag)
{
- if (!soreadable(so))
+ SOCK_LOCK(so);
+ if (!soreadable(so)) {
+ SOCK_UNLOCK(so);
return;
+ }
so->so_upcall = NULL;
so->so_rcv.sb_flags &= ~SB_UPCALL;
- soisconnected_locked(so);
+ soisconnected(so);
+ SOCK_UNLOCK(so);
return;
}
diff --git a/sys/netinet/accf_http.c b/sys/netinet/accf_http.c
index 4a3e17e..4849f6b 100644
--- a/sys/netinet/accf_http.c
+++ b/sys/netinet/accf_http.c
@@ -31,7 +31,9 @@
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/mbuf.h>
+#include <sys/mutex.h>
#include <sys/signalvar.h>
#include <sys/sysctl.h>
#include <sys/socketvar.h>
@@ -160,11 +162,13 @@ static void
sohashttpget(struct socket *so, void *arg, int waitflag)
{
+ SOCK_LOCK(so);
if ((so->so_state & SS_CANTRCVMORE) == 0 && !sbfull(&so->so_rcv)) {
struct mbuf *m;
char *cmp;
int cmplen, cc;
+ SOCK_UNLOCK(so);
m = so->so_rcv.sb_mb;
cc = so->so_rcv.sb_cc - 1;
if (cc < 1)
@@ -197,13 +201,16 @@ sohashttpget(struct socket *so, void *arg, int waitflag)
return;
}
DPRINT("mbufstrcmp bad");
- }
+ } else
+ SOCK_UNLOCK(so);
fallout:
DPRINT("fallout");
+ SOCK_LOCK(so);
so->so_upcall = NULL;
so->so_rcv.sb_flags &= ~SB_UPCALL;
- soisconnected_locked(so);
+ soisconnected(so);
+ SOCK_UNLOCK(so);
return;
}
@@ -213,8 +220,12 @@ soparsehttpvers(struct socket *so, void *arg, int waitflag)
struct mbuf *m, *n;
int i, cc, spaces, inspaces;
- if ((so->so_state & SS_CANTRCVMORE) != 0 || sbfull(&so->so_rcv))
+ SOCK_LOCK(so);
+ if ((so->so_state & SS_CANTRCVMORE) != 0 || sbfull(&so->so_rcv)) {
+ SOCK_UNLOCK(so);
goto fallout;
+ }
+ SOCK_UNLOCK(so);
m = so->so_rcv.sb_mb;
cc = so->so_rcv.sb_cc;
@@ -283,9 +294,11 @@ readmore:
fallout:
DPRINT("fallout");
+ SOCK_LOCK(so);
so->so_upcall = NULL;
so->so_rcv.sb_flags &= ~SB_UPCALL;
- soisconnected_locked(so);
+ soisconnected(so);
+ SOCK_UNLOCK(so);
return;
}
@@ -300,8 +313,12 @@ soishttpconnected(struct socket *so, void *arg, int waitflag)
int ccleft, copied;
DPRINT("start");
- if ((so->so_state & SS_CANTRCVMORE) != 0 || sbfull(&so->so_rcv))
+ SOCK_LOCK(so);
+ if ((so->so_state & SS_CANTRCVMORE) != 0 || sbfull(&so->so_rcv)) {
+ SOCK_UNLOCK(so);
goto gotit;
+ }
+ SOCK_UNLOCK(so);
/*
* Walk the socketbuffer and copy the last NCHRS (3) into a, b, and c
@@ -353,8 +370,10 @@ readmore:
return;
gotit:
+ SOCK_LOCK(so);
so->so_upcall = NULL;
so->so_rcv.sb_flags &= ~SB_UPCALL;
- soisconnected_locked(so);
+ soisconnected(so);
+ SOCK_UNLOCK(so);
return;
}
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index b4de80a..bd4bac9 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -183,15 +183,20 @@ in_pcbbind(inp, nam, td)
struct sockaddr_in *sin;
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
u_short lport = 0;
- int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
+ int wild = 0, reuseport;
int error, prison = 0;
+ SOCK_LOCK(so);
+ reuseport = (so->so_options & SO_REUSEPORT);
+ SOCK_UNLOCK(so);
if (TAILQ_EMPTY(&in_ifaddrhead)) /* XXX broken! */
return (EADDRNOTAVAIL);
if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
return (EINVAL);
+ SOCK_LOCK(so);
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
wild = 1;
+ SOCK_UNLOCK(so);
if (nam) {
sin = (struct sockaddr_in *)nam;
if (nam->sa_len != sizeof (*sin))
@@ -216,8 +221,10 @@ in_pcbbind(inp, nam, td)
* and a multicast address is bound on both
* new and duplicated sockets.
*/
+ SOCK_LOCK(so);
if (so->so_options & SO_REUSEADDR)
reuseport = SO_REUSEADDR|SO_REUSEPORT;
+ SOCK_UNLOCK(so);
} else if (sin->sin_addr.s_addr != INADDR_ANY) {
sin->sin_port = 0; /* yech... */
bzero(&sin->sin_zero, sizeof(sin->sin_zero));
@@ -237,22 +244,26 @@ in_pcbbind(inp, nam, td)
t = in_pcblookup_local(inp->inp_pcbinfo,
sin->sin_addr, lport,
prison ? 0 : INPLOOKUP_WILDCARD);
- if (t &&
- (ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
- ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
- (t->inp_socket->so_options &
- SO_REUSEPORT) == 0) &&
- (so->so_cred->cr_uid !=
- t->inp_socket->so_cred->cr_uid)) {
+ if (t != NULL) {
+ SOCK_LOCK(t->inp_socket);
+ if ((ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
+ ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
+ (t->inp_socket->so_options &
+ SO_REUSEPORT) == 0) &&
+ (so->so_cred->cr_uid !=
+ t->inp_socket->so_cred->cr_uid)) {
+ SOCK_UNLOCK(t->inp_socket);
#if defined(INET6)
- if (ntohl(sin->sin_addr.s_addr) !=
- INADDR_ANY ||
- ntohl(t->inp_laddr.s_addr) !=
- INADDR_ANY ||
- INP_SOCKAF(so) ==
- INP_SOCKAF(t->inp_socket))
+ if (ntohl(sin->sin_addr.s_addr) !=
+ INADDR_ANY ||
+ ntohl(t->inp_laddr.s_addr) !=
+ INADDR_ANY ||
+ INP_SOCKAF(so) ==
+ INP_SOCKAF(t->inp_socket))
#endif /* defined(INET6) */
- return (EADDRINUSE);
+ return (EADDRINUSE);
+ } else
+ SOCK_UNLOCK(t->inp_socket);
}
}
if (prison &&
@@ -260,17 +271,21 @@ in_pcbbind(inp, nam, td)
return (EADDRNOTAVAIL);
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
lport, prison ? 0 : wild);
- if (t &&
- (reuseport & t->inp_socket->so_options) == 0) {
+ if (t != NULL) {
+ SOCK_LOCK(t->inp_socket);
+ if ((reuseport & t->inp_socket->so_options) == 0) {
+ SOCK_UNLOCK(t->inp_socket);
#if defined(INET6)
- if (ntohl(sin->sin_addr.s_addr) !=
- INADDR_ANY ||
- ntohl(t->inp_laddr.s_addr) !=
- INADDR_ANY ||
- INP_SOCKAF(so) ==
- INP_SOCKAF(t->inp_socket))
+ if (ntohl(sin->sin_addr.s_addr) !=
+ INADDR_ANY ||
+ ntohl(t->inp_laddr.s_addr) !=
+ INADDR_ANY ||
+ INP_SOCKAF(so) ==
+ INP_SOCKAF(t->inp_socket))
#endif /* defined(INET6) */
- return (EADDRINUSE);
+ return (EADDRINUSE);
+ } else
+ SOCK_UNLOCK(t->inp_socket);
}
}
inp->inp_laddr = sin->sin_addr;
@@ -416,17 +431,21 @@ in_pcbladdr(inp, nam, plocal_sin)
* destination, in case of sharing the cache with IPv6.
*/
ro = &inp->inp_route;
+ SOCK_LOCK(inp->inp_socket);
if (ro->ro_rt &&
(ro->ro_dst.sa_family != AF_INET ||
satosin(&ro->ro_dst)->sin_addr.s_addr !=
sin->sin_addr.s_addr ||
inp->inp_socket->so_options & SO_DONTROUTE)) {
+ SOCK_UNLOCK(inp->inp_socket);
RTFREE(ro->ro_rt);
ro->ro_rt = (struct rtentry *)0;
+ SOCK_LOCK(inp->inp_socket);
}
if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
(ro->ro_rt == (struct rtentry *)0 ||
ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
+ SOCK_UNLOCK(inp->inp_socket);
/* No route yet, so try to acquire one */
bzero(&ro->ro_dst, sizeof(struct sockaddr_in));
ro->ro_dst.sa_family = AF_INET;
@@ -434,7 +453,8 @@ in_pcbladdr(inp, nam, plocal_sin)
((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
sin->sin_addr;
rtalloc(ro);
- }
+ } else
+ SOCK_UNLOCK(inp->inp_socket);
/*
* If we found a route, use the address
* corresponding to the outgoing interface
@@ -548,8 +568,12 @@ in_pcbdisconnect(inp)
inp->inp_faddr.s_addr = INADDR_ANY;
inp->inp_fport = 0;
in_pcbrehash(inp);
- if (inp->inp_socket->so_state & SS_NOFDREF)
+ SOCK_LOCK(inp->inp_socket);
+ if (inp->inp_socket->so_state & SS_NOFDREF) {
+ SOCK_UNLOCK(inp->inp_socket);
in_pcbdetach(inp);
+ } else
+ SOCK_UNLOCK(inp->inp_socket);
}
void
@@ -565,6 +589,7 @@ in_pcbdetach(inp)
inp->inp_gencnt = ++ipi->ipi_gencnt;
in_pcbremlists(inp);
so->so_pcb = 0;
+ SOCK_LOCK(so);
sotryfree(so);
if (inp->inp_options)
(void)m_free(inp->inp_options);
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index 8f56d2c..e297390 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -228,8 +228,11 @@ divert_packet(struct mbuf *m, int incoming, int port)
if (sbappendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc,
m, (struct mbuf *)0) == 0)
m_freem(m);
- else
+ else {
+ SOCK_LOCK(sa);
sorwakeup(sa);
+ SOCK_UNLOCK(sa);
+ }
} else {
m_freem(m);
ipstat.ips_noproto++;
@@ -255,6 +258,7 @@ div_output(so, m, addr, control)
register struct ip *const ip = mtod(m, struct ip *);
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
int error = 0;
+ int soopts;
if (control)
m_freem(control); /* XXX */
@@ -300,8 +304,11 @@ div_output(so, m, addr, control)
/* Send packet to output processing */
ipstat.ips_rawout++; /* XXX */
+ SOCK_LOCK(so);
+ soopts = so->so_options & SO_DONTROUTE;
+ SOCK_UNLOCK(so);
error = ip_output(m, inp->inp_options, &inp->inp_route,
- (so->so_options & SO_DONTROUTE) |
+ soopts |
IP_ALLOWBROADCAST | IP_RAWOUTPUT,
inp->inp_moptions);
} else {
@@ -365,7 +372,9 @@ div_attach(struct socket *so, int proto, struct thread *td)
inp->inp_flags |= INP_HDRINCL;
/* The socket is always "connected" because
we always know "where" to send the packet */
+ SOCK_LOCK(so);
so->so_state |= SS_ISCONNECTED;
+ SOCK_UNLOCK(so);
return 0;
}
@@ -384,15 +393,21 @@ div_detach(struct socket *so)
static int
div_abort(struct socket *so)
{
+ SOCK_LOCK(so);
soisdisconnected(so);
+ SOCK_UNLOCK(so);
return div_detach(so);
}
static int
div_disconnect(struct socket *so)
{
- if ((so->so_state & SS_ISCONNECTED) == 0)
+ SOCK_LOCK(so);
+ if ((so->so_state & SS_ISCONNECTED) == 0) {
+ SOCK_UNLOCK(so);
return ENOTCONN;
+ }
+ SOCK_UNLOCK(so);
return div_abort(so);
}
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index b7a882f..3627832 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1837,15 +1837,18 @@ ip_savecontrol(inp, mp, ip, m)
register struct ip *ip;
register struct mbuf *m;
{
+ SOCK_LOCK(inp->inp_socket);
if (inp->inp_socket->so_options & SO_TIMESTAMP) {
struct timeval tv;
+ SOCK_UNLOCK(inp->inp_socket);
microtime(&tv);
*mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
SCM_TIMESTAMP, SOL_SOCKET);
if (*mp)
mp = &(*mp)->m_next;
- }
+ } else
+ SOCK_UNLOCK(inp->inp_socket);
if (inp->inp_flags & INP_RECVDSTADDR) {
*mp = sbcreatecontrol((caddr_t) &ip->ip_dst,
sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 0be45ea..e2f85f2 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -1133,7 +1133,9 @@ socket_send(s, mm, src)
if (sbappendaddr(&s->so_rcv,
(struct sockaddr *)src,
mm, (struct mbuf *)0) != 0) {
+ SOCK_LOCK(s);
sorwakeup(s);
+ SOCK_UNLOCK(s);
return 0;
}
}
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 86915fc..aaeb61c 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -153,9 +153,16 @@ rip_input(m, off)
} else
#endif /*IPSEC*/
if (n) {
- if (last->inp_flags & INP_CONTROLOPTS ||
- last->inp_socket->so_options & SO_TIMESTAMP)
- ip_savecontrol(last, &opts, ip, n);
+ if (last->inp_flags & INP_CONTROLOPTS)
+ ip_savecontrol(last, &opts, ip, n);
+ else {
+ SOCK_LOCK(last->inp_socket);
+ if(last->inp_socket->so_options & SO_TIMESTAMP) {
+ SOCK_UNLOCK(last->inp_socket);
+ ip_savecontrol(last, &opts, ip, n);
+ } else
+ SOCK_UNLOCK(last->inp_socket);
+ }
if (sbappendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&ripsrc, n,
opts) == 0) {
@@ -163,8 +170,11 @@ rip_input(m, off)
m_freem(n);
if (opts)
m_freem(opts);
- } else
+ } else {
+ SOCK_LOCK(last->inp_socket);
sorwakeup(last->inp_socket);
+ SOCK_UNLOCK(last->inp_socket);
+ }
opts = 0;
}
}
@@ -180,16 +190,26 @@ rip_input(m, off)
} else
#endif /*IPSEC*/
if (last) {
- if (last->inp_flags & INP_CONTROLOPTS ||
- last->inp_socket->so_options & SO_TIMESTAMP)
+ if (last->inp_flags & INP_CONTROLOPTS)
ip_savecontrol(last, &opts, ip, m);
+ else {
+ SOCK_LOCK(last->inp_socket);
+ if (last->inp_socket->so_options & SO_TIMESTAMP) {
+ SOCK_UNLOCK(last->inp_socket);
+ ip_savecontrol(last, &opts, ip, m);
+ } else
+ SOCK_UNLOCK(last->inp_socket);
+ }
if (sbappendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&ripsrc, m, opts) == 0) {
m_freem(m);
if (opts)
m_freem(opts);
- } else
+ } else {
+ SOCK_LOCK(last->inp_socket);
sorwakeup(last->inp_socket);
+ SOCK_UNLOCK(last->inp_socket);
+ }
} else {
m_freem(m);
ipstat.ips_noproto++;
@@ -209,8 +229,11 @@ rip_output(m, so, dst)
{
register struct ip *ip;
register struct inpcb *inp = sotoinpcb(so);
- int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
+ int flags;
+ SOCK_LOCK(so);
+ flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
+ SOCK_UNLOCK(so);
/*
* If the user handed us a complete IP packet, use it.
* Otherwise, allocate an mbuf for a header and fill it in.
@@ -508,15 +531,21 @@ rip_detach(struct socket *so)
static int
rip_abort(struct socket *so)
{
+ SOCK_LOCK(so);
soisdisconnected(so);
+ SOCK_UNLOCK(so);
return rip_detach(so);
}
static int
rip_disconnect(struct socket *so)
{
- if ((so->so_state & SS_ISCONNECTED) == 0)
+ SOCK_LOCK(so);
+ if ((so->so_state & SS_ISCONNECTED) == 0) {
+ SOCK_UNLOCK(so);
return ENOTCONN;
+ }
+ SOCK_UNLOCK(so);
return rip_abort(so);
}
@@ -552,7 +581,9 @@ rip_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
(addr->sin_family != AF_IMPLINK))
return EAFNOSUPPORT;
inp->inp_faddr = addr->sin_addr;
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
return 0;
}
@@ -570,13 +601,16 @@ rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
struct inpcb *inp = sotoinpcb(so);
register u_long dst;
+ SOCK_LOCK(so);
if (so->so_state & SS_ISCONNECTED) {
+ SOCK_UNLOCK(so);
if (nam) {
m_freem(m);
return EISCONN;
}
dst = inp->inp_faddr.s_addr;
} else {
+ SOCK_UNLOCK(so);
if (nam == NULL) {
m_freem(m);
return ENOTCONN;
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index b193327..b5c6daf 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -281,15 +281,21 @@ present:
flags = q->tqe_th->th_flags & TH_FIN;
nq = LIST_NEXT(q, tqe_q);
LIST_REMOVE(q, tqe_q);
- if (so->so_state & SS_CANTRCVMORE)
+ SOCK_LOCK(so);
+ if (so->so_state & SS_CANTRCVMORE) {
+ SOCK_UNLOCK(so);
m_freem(q->tqe_m);
- else
+ } else {
+ SOCK_UNLOCK(so);
sbappend(&so->so_rcv, q->tqe_m);
+ }
FREE(q, M_TSEGQ);
q = nq;
} while (q && q->tqe_th->th_seq == tp->rcv_nxt);
ND6_HINT(tp);
+ SOCK_LOCK(so);
sorwakeup(so);
+ SOCK_UNLOCK(so);
return (flags);
}
@@ -638,6 +644,7 @@ findpcb:
tiwin = th->th_win;
so = inp->inp_socket;
+ SOCK_LOCK(so);
if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
struct in_conninfo inc;
#ifdef TCPDEBUG
@@ -654,8 +661,11 @@ findpcb:
}
#endif
/* skip if this isn't a listen socket */
- if ((so->so_options & SO_ACCEPTCONN) == 0)
+ if ((so->so_options & SO_ACCEPTCONN) == 0) {
+ SOCK_UNLOCK(so);
goto after_listen;
+ }
+ SOCK_UNLOCK(so);
#ifdef INET6
inc.inc_isipv6 = isipv6;
if (isipv6) {
@@ -868,11 +878,14 @@ findpcb:
tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN);
tcpstat.tcps_connects++;
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
goto trimthenstep6;
}
goto drop;
- }
+ } else
+ SOCK_UNLOCK(so);
after_listen:
/* XXX temp debugging */
@@ -1004,7 +1017,9 @@ after_listen:
tp->t_rxtcur,
tcp_timer_rexmt, tp);
+ SOCK_LOCK(so);
sowwakeup(so);
+ SOCK_UNLOCK(so);
if (so->so_snd.sb_cc)
(void) tcp_output(tp);
return;
@@ -1027,7 +1042,9 @@ after_listen:
*/
m_adj(m, drop_hdrlen); /* delayed header drop */
sbappend(&so->so_rcv, m);
+ SOCK_LOCK(so);
sorwakeup(so);
+ SOCK_UNLOCK(so);
if (DELAY_ACK(tp)) {
callout_reset(tp->tt_delack, tcp_delacktime,
tcp_timer_delack, tp);
@@ -1137,7 +1154,9 @@ after_listen:
} else
tp->t_flags &= ~TF_RCVD_CC;
tcpstat.tcps_connects++;
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
/* Do window scaling on this connection? */
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
(TF_RCVD_SCALE|TF_REQ_SCALE)) {
@@ -1467,13 +1486,16 @@ trimthenstep6:
* If new data are received on a connection after the
* user processes are gone, then RST the other end.
*/
+ SOCK_LOCK(so);
if ((so->so_state & SS_NOFDREF) &&
tp->t_state > TCPS_CLOSE_WAIT && tlen) {
+ SOCK_UNLOCK(so);
tp = tcp_close(tp);
tcpstat.tcps_rcvafterclose++;
rstreason = BANDLIM_UNLIMITED;
goto dropwithreset;
}
+ SOCK_UNLOCK(so);
/*
* If segment ends after window, drop trailing data
@@ -1563,7 +1585,9 @@ trimthenstep6:
case TCPS_SYN_RECEIVED:
tcpstat.tcps_connects++;
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
/* Do window scaling? */
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
(TF_RCVD_SCALE|TF_REQ_SCALE)) {
@@ -1822,7 +1846,9 @@ process_ACK:
tp->snd_wnd -= acked;
ourfinisacked = 0;
}
+ SOCK_LOCK(so);
sowwakeup(so);
+ SOCK_UNLOCK(so);
tp->snd_una = th->th_ack;
if (SEQ_LT(tp->snd_nxt, tp->snd_una))
tp->snd_nxt = tp->snd_una;
@@ -1843,11 +1869,14 @@ process_ACK:
* specification, but if we don't get a FIN
* we'll hang forever.
*/
+ SOCK_LOCK(so);
if (so->so_state & SS_CANTRCVMORE) {
- soisdisconnected_locked(so);
+ soisdisconnected(so);
+ SOCK_UNLOCK(so);
callout_reset(tp->tt_2msl, tcp_maxidle,
tcp_timer_2msl, tp);
- }
+ } else
+ SOCK_UNLOCK(so);
tp->t_state = TCPS_FIN_WAIT_2;
}
break;
@@ -1872,7 +1901,9 @@ process_ACK:
else
callout_reset(tp->tt_2msl, 2 * tcp_msl,
tcp_timer_2msl, tp);
+ SOCK_LOCK(so);
soisdisconnected(so);
+ SOCK_UNLOCK(so);
}
break;
@@ -1956,8 +1987,11 @@ step6:
tp->rcv_up = th->th_seq + th->th_urp;
so->so_oobmark = so->so_rcv.sb_cc +
(tp->rcv_up - tp->rcv_nxt) - 1;
- if (so->so_oobmark == 0)
+ if (so->so_oobmark == 0) {
+ SOCK_LOCK(so);
so->so_state |= SS_RCVATMARK;
+ SOCK_UNLOCK(so);
+ }
sohasoutofband(so);
tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA);
}
@@ -1967,13 +2001,19 @@ step6:
* but if two URG's are pending at once, some out-of-band
* data may creep in... ick.
*/
- if (th->th_urp <= (u_long)tlen
+ if (th->th_urp <= (u_long)tlen) {
#ifdef SO_OOBINLINE
- && (so->so_options & SO_OOBINLINE) == 0
+ SOCK_LOCK(so);
+ if ((so->so_options & SO_OOBINLINE) == 0) {
+ SOCK_UNLOCK(so);
#endif
- )
- tcp_pulloutofband(so, th, m,
- drop_hdrlen); /* hdr drop is delayed */
+ tcp_pulloutofband(so, th, m,
+ drop_hdrlen); /* hdr drop is delayed */
+#ifdef SO_OOBINLINE
+ } else
+ SOCK_UNLOCK(so);
+#endif
+ }
} else
/*
* If no out of band data is expected,
@@ -2019,7 +2059,9 @@ dodata: /* XXX */
tcpstat.tcps_rcvbyte += tlen;
ND6_HINT(tp);
sbappend(&so->so_rcv, m);
+ SOCK_LOCK(so);
sorwakeup(so);
+ SOCK_UNLOCK(so);
} else {
thflags = tcp_reass(tp, th, &tlen, m);
tp->t_flags |= TF_ACKNOW;
@@ -2098,7 +2140,9 @@ dodata: /* XXX */
else
callout_reset(tp->tt_2msl, 2 * tcp_msl,
tcp_timer_2msl, tp);
+ SOCK_LOCK(so);
soisdisconnected(so);
+ SOCK_UNLOCK(so);
break;
/*
@@ -2111,9 +2155,13 @@ dodata: /* XXX */
}
}
#ifdef TCPDEBUG
- if (so->so_options & SO_DEBUG)
+ SOCK_LOCK(so);
+ if (so->so_options & SO_DEBUG) {
+ SOCK_UNLOCK(so);
tcp_trace(TA_INPUT, ostate, tp, (void *)tcp_saveipgen,
&tcp_savetcp, 0);
+ } else
+ SOCK_UNLOCK(so);
#endif
/*
@@ -2146,9 +2194,13 @@ dropafterack:
goto dropwithreset;
}
#ifdef TCPDEBUG
- if (so->so_options & SO_DEBUG)
+ SOCK_LOCK(so);
+ if (so->so_options & SO_DEBUG) {
+ SOCK_UNLOCK(so);
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
&tcp_savetcp, 0);
+ } else
+ SOCK_UNLOCK(so);
#endif
m_freem(m);
tp->t_flags |= TF_ACKNOW;
@@ -2184,9 +2236,18 @@ dropwithreset:
goto drop;
#ifdef TCPDEBUG
- if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
+ if (tp == 0)
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
&tcp_savetcp, 0);
+ else {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
+ &tcp_savetcp, 0);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ }
#endif
if (thflags & TH_ACK)
/* mtod() below is safe as long as hdr dropping is delayed */
@@ -2206,9 +2267,18 @@ drop:
* Drop space held by incoming segment and return.
*/
#ifdef TCPDEBUG
- if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
+ if (tp == 0)
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
&tcp_savetcp, 0);
+ else {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
+ &tcp_savetcp, 0);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ }
#endif
m_freem(m);
return;
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 40ed7ee..dd2832b 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -126,6 +126,7 @@ tcp_output(tp)
#ifdef INET6
int isipv6;
#endif
+ int soopts;
#ifdef INET6
isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0;
@@ -819,8 +820,12 @@ send:
/*
* Trace.
*/
- if (so->so_options & SO_DEBUG)
+ SOCK_LOCK(so);
+ if (so->so_options & SO_DEBUG) {
+ SOCK_UNLOCK(so);
tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, void *), th, 0);
+ } else
+ SOCK_UNLOCK(so);
#endif
/*
@@ -854,10 +859,13 @@ send:
goto out;
}
#endif /*IPSEC*/
+ SOCK_LOCK(so);
+ soopts = (so->so_options & SO_DONTROUTE);
+ SOCK_UNLOCK(so);
error = ip6_output(m,
tp->t_inpcb->in6p_outputopts,
&tp->t_inpcb->in6p_route,
- (so->so_options & SO_DONTROUTE), NULL, NULL);
+ soopts, NULL, NULL);
} else
#endif /* INET6 */
{
@@ -889,8 +897,11 @@ send:
#ifdef IPSEC
ipsec_setsocket(m, so);
#endif /*IPSEC*/
+ SOCK_LOCK(so);
+ soopts = (so->so_options & SO_DONTROUTE);
+ SOCK_UNLOCK(so);
error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
- (so->so_options & SO_DONTROUTE), 0);
+ soopts, 0);
}
if (error) {
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index b193327..b5c6daf 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -281,15 +281,21 @@ present:
flags = q->tqe_th->th_flags & TH_FIN;
nq = LIST_NEXT(q, tqe_q);
LIST_REMOVE(q, tqe_q);
- if (so->so_state & SS_CANTRCVMORE)
+ SOCK_LOCK(so);
+ if (so->so_state & SS_CANTRCVMORE) {
+ SOCK_UNLOCK(so);
m_freem(q->tqe_m);
- else
+ } else {
+ SOCK_UNLOCK(so);
sbappend(&so->so_rcv, q->tqe_m);
+ }
FREE(q, M_TSEGQ);
q = nq;
} while (q && q->tqe_th->th_seq == tp->rcv_nxt);
ND6_HINT(tp);
+ SOCK_LOCK(so);
sorwakeup(so);
+ SOCK_UNLOCK(so);
return (flags);
}
@@ -638,6 +644,7 @@ findpcb:
tiwin = th->th_win;
so = inp->inp_socket;
+ SOCK_LOCK(so);
if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
struct in_conninfo inc;
#ifdef TCPDEBUG
@@ -654,8 +661,11 @@ findpcb:
}
#endif
/* skip if this isn't a listen socket */
- if ((so->so_options & SO_ACCEPTCONN) == 0)
+ if ((so->so_options & SO_ACCEPTCONN) == 0) {
+ SOCK_UNLOCK(so);
goto after_listen;
+ }
+ SOCK_UNLOCK(so);
#ifdef INET6
inc.inc_isipv6 = isipv6;
if (isipv6) {
@@ -868,11 +878,14 @@ findpcb:
tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN);
tcpstat.tcps_connects++;
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
goto trimthenstep6;
}
goto drop;
- }
+ } else
+ SOCK_UNLOCK(so);
after_listen:
/* XXX temp debugging */
@@ -1004,7 +1017,9 @@ after_listen:
tp->t_rxtcur,
tcp_timer_rexmt, tp);
+ SOCK_LOCK(so);
sowwakeup(so);
+ SOCK_UNLOCK(so);
if (so->so_snd.sb_cc)
(void) tcp_output(tp);
return;
@@ -1027,7 +1042,9 @@ after_listen:
*/
m_adj(m, drop_hdrlen); /* delayed header drop */
sbappend(&so->so_rcv, m);
+ SOCK_LOCK(so);
sorwakeup(so);
+ SOCK_UNLOCK(so);
if (DELAY_ACK(tp)) {
callout_reset(tp->tt_delack, tcp_delacktime,
tcp_timer_delack, tp);
@@ -1137,7 +1154,9 @@ after_listen:
} else
tp->t_flags &= ~TF_RCVD_CC;
tcpstat.tcps_connects++;
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
/* Do window scaling on this connection? */
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
(TF_RCVD_SCALE|TF_REQ_SCALE)) {
@@ -1467,13 +1486,16 @@ trimthenstep6:
* If new data are received on a connection after the
* user processes are gone, then RST the other end.
*/
+ SOCK_LOCK(so);
if ((so->so_state & SS_NOFDREF) &&
tp->t_state > TCPS_CLOSE_WAIT && tlen) {
+ SOCK_UNLOCK(so);
tp = tcp_close(tp);
tcpstat.tcps_rcvafterclose++;
rstreason = BANDLIM_UNLIMITED;
goto dropwithreset;
}
+ SOCK_UNLOCK(so);
/*
* If segment ends after window, drop trailing data
@@ -1563,7 +1585,9 @@ trimthenstep6:
case TCPS_SYN_RECEIVED:
tcpstat.tcps_connects++;
+ SOCK_LOCK(so);
soisconnected(so);
+ SOCK_UNLOCK(so);
/* Do window scaling? */
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
(TF_RCVD_SCALE|TF_REQ_SCALE)) {
@@ -1822,7 +1846,9 @@ process_ACK:
tp->snd_wnd -= acked;
ourfinisacked = 0;
}
+ SOCK_LOCK(so);
sowwakeup(so);
+ SOCK_UNLOCK(so);
tp->snd_una = th->th_ack;
if (SEQ_LT(tp->snd_nxt, tp->snd_una))
tp->snd_nxt = tp->snd_una;
@@ -1843,11 +1869,14 @@ process_ACK:
* specification, but if we don't get a FIN
* we'll hang forever.
*/
+ SOCK_LOCK(so);
if (so->so_state & SS_CANTRCVMORE) {
- soisdisconnected_locked(so);
+ soisdisconnected(so);
+ SOCK_UNLOCK(so);
callout_reset(tp->tt_2msl, tcp_maxidle,
tcp_timer_2msl, tp);
- }
+ } else
+ SOCK_UNLOCK(so);
tp->t_state = TCPS_FIN_WAIT_2;
}
break;
@@ -1872,7 +1901,9 @@ process_ACK:
else
callout_reset(tp->tt_2msl, 2 * tcp_msl,
tcp_timer_2msl, tp);
+ SOCK_LOCK(so);
soisdisconnected(so);
+ SOCK_UNLOCK(so);
}
break;
@@ -1956,8 +1987,11 @@ step6:
tp->rcv_up = th->th_seq + th->th_urp;
so->so_oobmark = so->so_rcv.sb_cc +
(tp->rcv_up - tp->rcv_nxt) - 1;
- if (so->so_oobmark == 0)
+ if (so->so_oobmark == 0) {
+ SOCK_LOCK(so);
so->so_state |= SS_RCVATMARK;
+ SOCK_UNLOCK(so);
+ }
sohasoutofband(so);
tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA);
}
@@ -1967,13 +2001,19 @@ step6:
* but if two URG's are pending at once, some out-of-band
* data may creep in... ick.
*/
- if (th->th_urp <= (u_long)tlen
+ if (th->th_urp <= (u_long)tlen) {
#ifdef SO_OOBINLINE
- && (so->so_options & SO_OOBINLINE) == 0
+ SOCK_LOCK(so);
+ if ((so->so_options & SO_OOBINLINE) == 0) {
+ SOCK_UNLOCK(so);
#endif
- )
- tcp_pulloutofband(so, th, m,
- drop_hdrlen); /* hdr drop is delayed */
+ tcp_pulloutofband(so, th, m,
+ drop_hdrlen); /* hdr drop is delayed */
+#ifdef SO_OOBINLINE
+ } else
+ SOCK_UNLOCK(so);
+#endif
+ }
} else
/*
* If no out of band data is expected,
@@ -2019,7 +2059,9 @@ dodata: /* XXX */
tcpstat.tcps_rcvbyte += tlen;
ND6_HINT(tp);
sbappend(&so->so_rcv, m);
+ SOCK_LOCK(so);
sorwakeup(so);
+ SOCK_UNLOCK(so);
} else {
thflags = tcp_reass(tp, th, &tlen, m);
tp->t_flags |= TF_ACKNOW;
@@ -2098,7 +2140,9 @@ dodata: /* XXX */
else
callout_reset(tp->tt_2msl, 2 * tcp_msl,
tcp_timer_2msl, tp);
+ SOCK_LOCK(so);
soisdisconnected(so);
+ SOCK_UNLOCK(so);
break;
/*
@@ -2111,9 +2155,13 @@ dodata: /* XXX */
}
}
#ifdef TCPDEBUG
- if (so->so_options & SO_DEBUG)
+ SOCK_LOCK(so);
+ if (so->so_options & SO_DEBUG) {
+ SOCK_UNLOCK(so);
tcp_trace(TA_INPUT, ostate, tp, (void *)tcp_saveipgen,
&tcp_savetcp, 0);
+ } else
+ SOCK_UNLOCK(so);
#endif
/*
@@ -2146,9 +2194,13 @@ dropafterack:
goto dropwithreset;
}
#ifdef TCPDEBUG
- if (so->so_options & SO_DEBUG)
+ SOCK_LOCK(so);
+ if (so->so_options & SO_DEBUG) {
+ SOCK_UNLOCK(so);
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
&tcp_savetcp, 0);
+ } else
+ SOCK_UNLOCK(so);
#endif
m_freem(m);
tp->t_flags |= TF_ACKNOW;
@@ -2184,9 +2236,18 @@ dropwithreset:
goto drop;
#ifdef TCPDEBUG
- if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
+ if (tp == 0)
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
&tcp_savetcp, 0);
+ else {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
+ &tcp_savetcp, 0);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ }
#endif
if (thflags & TH_ACK)
/* mtod() below is safe as long as hdr dropping is delayed */
@@ -2206,9 +2267,18 @@ drop:
* Drop space held by incoming segment and return.
*/
#ifdef TCPDEBUG
- if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
+ if (tp == 0)
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
&tcp_savetcp, 0);
+ else {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
+ &tcp_savetcp, 0);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ }
#endif
m_freem(m);
return;
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 13d8300..20d3bf5 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -469,8 +469,16 @@ tcp_respond(tp, ipgen, th, m, ack, seq, flags)
m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
}
#ifdef TCPDEBUG
- if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
+ if (tp == NULL)
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
+ else {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ }
#endif
#ifdef IPSEC
if (ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL) != 0) {
@@ -720,7 +728,9 @@ tcp_close(tp)
FREE(q, M_TSEGQ);
}
inp->inp_ppcb = NULL;
+ SOCK_LOCK(so);
soisdisconnected(so);
+ SOCK_UNLOCK(so);
#ifdef INET6
if (INP_CHECK_SOCKAF(so, AF_INET6))
in6_pcbdetach(inp);
@@ -793,9 +803,11 @@ tcp_notify(inp, error)
else
tp->t_softerror = error;
#if 0
+ SOCK_LOCK(so);
wakeup((caddr_t) &so->so_timeo);
sorwakeup(so);
sowwakeup(so);
+ SOCK_UNLOCK(so);
#endif
}
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 087e243..5ee54cf 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -39,13 +39,15 @@
#include "opt_tcpdebug.h"
#include <sys/param.h>
-#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/mbuf.h>
-#include <sys/sysctl.h>
+#include <sys/mutex.h>
+#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
-#include <sys/protosw.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
#include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */
@@ -211,9 +213,15 @@ tcp_timer_2msl(xtp)
tp = tcp_close(tp);
#ifdef TCPDEBUG
- if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
- tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
- PRU_SLOWTIMO);
+ if (tp != 0) {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
+ PRU_SLOWTIMO);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ }
#endif
splx(s);
}
@@ -243,9 +251,11 @@ tcp_timer_keep(xtp)
tcpstat.tcps_keeptimeo++;
if (tp->t_state < TCPS_ESTABLISHED)
goto dropit;
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
if ((always_keepalive ||
tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) &&
tp->t_state <= TCPS_CLOSING) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
if ((ticks - tp->t_rcvtime) >= tcp_keepidle + tcp_maxidle)
goto dropit;
/*
@@ -269,13 +279,19 @@ tcp_timer_keep(xtp)
(void) m_free(dtom(t_template));
}
callout_reset(tp->tt_keep, tcp_keepintvl, tcp_timer_keep, tp);
- } else
+ } else {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
callout_reset(tp->tt_keep, tcp_keepidle, tcp_timer_keep, tp);
+ }
#ifdef TCPDEBUG
- if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
PRU_SLOWTIMO);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
#endif
splx(s);
return;
@@ -285,9 +301,15 @@ dropit:
tp = tcp_drop(tp, ETIMEDOUT);
#ifdef TCPDEBUG
- if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
- tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
- PRU_SLOWTIMO);
+ if (tp != 0) {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
+ PRU_SLOWTIMO);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ }
#endif
splx(s);
}
@@ -335,9 +357,15 @@ tcp_timer_persist(xtp)
out:
#ifdef TCPDEBUG
- if (tp && tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
- tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
- PRU_SLOWTIMO);
+ if (tp != 0) {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
+ PRU_SLOWTIMO);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ }
#endif
splx(s);
}
@@ -470,9 +498,15 @@ tcp_timer_rexmt(xtp)
out:
#ifdef TCPDEBUG
- if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
- tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
- PRU_SLOWTIMO);
+ if (tp != 0) {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ tcp_trace(TA_USER, ostate, tp, (void *)0, (struct tcphdr *)0,
+ PRU_SLOWTIMO);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ }
#endif
splx(s);
}
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 13d8300..20d3bf5 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -469,8 +469,16 @@ tcp_respond(tp, ipgen, th, m, ack, seq, flags)
m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
}
#ifdef TCPDEBUG
- if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
+ if (tp == NULL)
tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
+ else {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
+ if ((tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
+ } else
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
+ }
#endif
#ifdef IPSEC
if (ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL) != 0) {
@@ -720,7 +728,9 @@ tcp_close(tp)
FREE(q, M_TSEGQ);
}
inp->inp_ppcb = NULL;
+ SOCK_LOCK(so);
soisdisconnected(so);
+ SOCK_UNLOCK(so);
#ifdef INET6
if (INP_CHECK_SOCKAF(so, AF_INET6))
in6_pcbdetach(inp);
@@ -793,9 +803,11 @@ tcp_notify(inp, error)
else
tp->t_softerror = error;
#if 0
+ SOCK_LOCK(so);
wakeup((caddr_t) &so->so_timeo);
sorwakeup(so);
sowwakeup(so);
+ SOCK_UNLOCK(so);
#endif
}
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index e1f4c1a..5d8934c 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -103,8 +103,17 @@ static struct tcpcb *
#ifdef TCPDEBUG
#define TCPDEBUG0 int ostate = 0
#define TCPDEBUG1() ostate = tp ? tp->t_state : 0
-#define TCPDEBUG2(req) if (tp && (so->so_options & SO_DEBUG)) \
- tcp_trace(TA_USER, ostate, tp, 0, 0, req)
+#define TCPDEBUG2(req) \
+ do { \
+ if (tp != 0) { \
+ SOCK_LOCK(so); \
+ if (so->so_options & SO_DEBUG) { \
+ SOCK_UNLOCK(so); \
+ tcp_trace(TA_USER, ostate, tp, 0, 0, req); \
+ } else \
+ SOCK_UNLOCK(so); \
+ } \
+ } while(0)
#else
#define TCPDEBUG0
#define TCPDEBUG1()
@@ -134,8 +143,10 @@ tcp_usr_attach(struct socket *so, int proto, struct thread *td)
if (error)
goto out;
+ SOCK_LOCK(so);
if ((so->so_options & SO_LINGER) && so->so_linger == 0)
so->so_linger = TCP_LINGERTIME;
+ SOCK_UNLOCK(so);
tp = sototcpcb(so);
out:
TCPDEBUG2(PRU_ATTACH);
@@ -424,10 +435,13 @@ tcp_usr_accept(struct socket *so, struct sockaddr **nam)
struct tcpcb *tp = NULL;
TCPDEBUG0;
+ SOCK_LOCK(so);
if (so->so_state & SS_ISDISCONNECTED) {
+ SOCK_UNLOCK(so);
error = ECONNABORTED;
goto out;
}
+ SOCK_UNLOCK(so);
if (inp == 0) {
splx(s);
return (EINVAL);
@@ -448,10 +462,13 @@ tcp6_usr_accept(struct socket *so, struct sockaddr **nam)
struct tcpcb *tp = NULL;
TCPDEBUG0;
+ SOCK_LOCK(so);
if (so->so_state & SS_ISDISCONNECTED) {
+ SOCK_UNLOCK(so);
error = ECONNABORTED;
goto out;
}
+ SOCK_UNLOCK(so);
if (inp == 0) {
splx(s);
return (EINVAL);
@@ -654,10 +671,16 @@ tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags)
struct tcpcb *tp;
COMMON_START();
+ SOCK_LOCK(so);
if ((so->so_oobmark == 0 &&
(so->so_state & SS_RCVATMARK) == 0) ||
- so->so_options & SO_OOBINLINE ||
- tp->t_oobflags & TCPOOB_HADDATA) {
+ so->so_options & SO_OOBINLINE) {
+ SOCK_UNLOCK(so);
+ error = EINVAL;
+ goto out;
+ }
+ SOCK_UNLOCK(so);
+ if (tp->t_oobflags & TCPOOB_HADDATA) {
error = EINVAL;
goto out;
}
@@ -755,7 +778,9 @@ tcp_connect(tp, nam, td)
(TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
tp->request_r_scale++;
+ SOCK_LOCK(so);
soisconnecting(so);
+ SOCK_UNLOCK(so);
tcpstat.tcps_connattempt++;
tp->t_state = TCPS_SYN_SENT;
callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp);
@@ -841,7 +866,9 @@ tcp6_connect(tp, nam, td)
(TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
tp->request_r_scale++;
+ SOCK_LOCK(so);
soisconnecting(so);
+ SOCK_UNLOCK(so);
tcpstat.tcps_connattempt++;
tp->t_state = TCPS_SYN_SENT;
callout_reset(tp->tt_keep, tcp_keepinit, tcp_timer_keep, tp);
@@ -1039,16 +1066,21 @@ tcp_attach(so, td)
inp->inp_vflag |= INP_IPV4;
tp = tcp_newtcpcb(inp);
if (tp == 0) {
- int nofd = so->so_state & SS_NOFDREF; /* XXX */
+ int nofd;
+ SOCK_LOCK(so);
+ nofd = so->so_state & SS_NOFDREF; /* XXX */
so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */
+ SOCK_UNLOCK(so);
#ifdef INET6
if (isipv6)
in6_pcbdetach(inp);
else
#endif
in_pcbdetach(inp);
+ SOCK_LOCK(so);
so->so_state |= nofd;
+ SOCK_UNLOCK(so);
return (ENOBUFS);
}
tp->t_state = TCPS_CLOSED;
@@ -1071,14 +1103,19 @@ tcp_disconnect(tp)
if (tp->t_state < TCPS_ESTABLISHED)
tp = tcp_close(tp);
- else if ((so->so_options & SO_LINGER) && so->so_linger == 0)
- tp = tcp_drop(tp, 0);
else {
- soisdisconnecting(so);
- sbflush(&so->so_rcv);
- tp = tcp_usrclosed(tp);
- if (tp)
- (void) tcp_output(tp);
+ SOCK_LOCK(so);
+ if ((so->so_options & SO_LINGER) && so->so_linger == 0) {
+ SOCK_UNLOCK(so);
+ tp = tcp_drop(tp, 0);
+ } else {
+ soisdisconnecting(so);
+ SOCK_UNLOCK(so);
+ sbflush(&so->so_rcv);
+ tp = tcp_usrclosed(tp);
+ if (tp)
+ (void) tcp_output(tp);
+ }
}
return (tp);
}
@@ -1120,7 +1157,9 @@ tcp_usrclosed(tp)
break;
}
if (tp && tp->t_state >= TCPS_FIN_WAIT_2) {
+ SOCK_LOCK(tp->t_inpcb->inp_socket);
soisdisconnected(tp->t_inpcb->inp_socket);
+ SOCK_UNLOCK(tp->t_inpcb->inp_socket);
/* To prevent the connection hanging in FIN_WAIT_2 forever. */
if (tp->t_state == TCPS_FIN_WAIT_2)
callout_reset(tp->tt_2msl, tcp_maxidle,
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