summaryrefslogtreecommitdiff
path: root/sys/kern/uipc_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/uipc_socket.c')
-rw-r--r--sys/kern/uipc_socket.c68
1 files changed, 44 insertions, 24 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 9824d161c0c..af0f62164a9 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket.c,v 1.306 2023/07/22 14:30:39 mvs Exp $ */
+/* $OpenBSD: uipc_socket.c,v 1.307 2023/08/03 09:49:08 mvs Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@@ -1789,12 +1789,12 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
{
int error = 0;
- soassertlocked(so);
-
if (level != SOL_SOCKET) {
if (so->so_proto->pr_ctloutput) {
+ solock(so);
error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
level, optname, m);
+ sounlock(so);
return (error);
}
error = ENOPROTOOPT;
@@ -1813,9 +1813,16 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
mtod(m, struct linger *)->l_linger < 0 ||
mtod(m, struct linger *)->l_linger > SHRT_MAX)
return (EINVAL);
+
+ solock(so);
so->so_linger = mtod(m, struct linger *)->l_linger;
- /* FALLTHROUGH */
+ if (*mtod(m, int *))
+ so->so_options |= optname;
+ else
+ so->so_options &= ~optname;
+ sounlock(so);
+ break;
case SO_BINDANY:
case SO_DEBUG:
case SO_KEEPALIVE:
@@ -1828,12 +1835,15 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
case SO_ZEROIZE:
if (m == NULL || m->m_len < sizeof (int))
return (EINVAL);
+
+ solock(so);
if (*mtod(m, int *))
so->so_options |= optname;
else
so->so_options &= ~optname;
- break;
+ sounlock(so);
+ break;
case SO_DONTROUTE:
if (m == NULL || m->m_len < sizeof (int))
return (EINVAL);
@@ -1853,23 +1863,32 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
cnt = *mtod(m, int *);
if ((long)cnt <= 0)
cnt = 1;
- switch (optname) {
+ solock(so);
+ switch (optname) {
case SO_SNDBUF:
- if (so->so_snd.sb_state & SS_CANTSENDMORE)
- return (EINVAL);
+ if (so->so_snd.sb_state & SS_CANTSENDMORE) {
+ error = EINVAL;
+ break;
+ }
if (sbcheckreserve(cnt, so->so_snd.sb_wat) ||
- sbreserve(so, &so->so_snd, cnt))
- return (ENOBUFS);
+ sbreserve(so, &so->so_snd, cnt)) {
+ error = ENOBUFS;
+ break;
+ }
so->so_snd.sb_wat = cnt;
break;
case SO_RCVBUF:
- if (so->so_rcv.sb_state & SS_CANTRCVMORE)
- return (EINVAL);
+ if (so->so_rcv.sb_state & SS_CANTRCVMORE) {
+ error = EINVAL;
+ break;
+ }
if (sbcheckreserve(cnt, so->so_rcv.sb_wat) ||
- sbreserve(so, &so->so_rcv, cnt))
- return (ENOBUFS);
+ sbreserve(so, &so->so_rcv, cnt)) {
+ error = ENOBUFS;
+ break;
+ }
so->so_rcv.sb_wat = cnt;
break;
@@ -1884,6 +1903,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
so->so_rcv.sb_hiwat : cnt;
break;
}
+ sounlock(so);
break;
}
@@ -1903,8 +1923,9 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
return (EDOM);
if (nsecs == 0)
nsecs = INFSLP;
- switch (optname) {
+ solock(so);
+ switch (optname) {
case SO_SNDTIMEO:
so->so_snd.sb_timeo_nsecs = nsecs;
break;
@@ -1912,6 +1933,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
so->so_rcv.sb_timeo_nsecs = nsecs;
break;
}
+ sounlock(so);
break;
}
@@ -1923,19 +1945,20 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
so->so_proto->pr_domain;
level = dom->dom_protosw->pr_protocol;
+ solock(so);
error = (*so->so_proto->pr_ctloutput)
(PRCO_SETOPT, so, level, optname, m);
- return (error);
- }
- error = ENOPROTOOPT;
+ sounlock(so);
+ } else
+ error = ENOPROTOOPT;
break;
-
#ifdef SOCKET_SPLICE
case SO_SPLICE:
+ solock(so);
if (m == NULL) {
error = sosplice(so, -1, 0, NULL);
} else if (m->m_len < sizeof(int)) {
- return (EINVAL);
+ error = EINVAL;
} else if (m->m_len < sizeof(struct splice)) {
error = sosplice(so, *mtod(m, int *), 0, NULL);
} else {
@@ -1944,6 +1967,7 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
mtod(m, struct splice *)->sp_max,
&mtod(m, struct splice *)->sp_idle);
}
+ sounlock(so);
break;
#endif /* SOCKET_SPLICE */
@@ -1951,10 +1975,6 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
error = ENOPROTOOPT;
break;
}
- if (error == 0 && so->so_proto->pr_ctloutput) {
- (*so->so_proto->pr_ctloutput)(PRCO_SETOPT, so,
- level, optname, m);
- }
}
return (error);