diff options
Diffstat (limited to 'sys/kern/uipc_socket.c')
-rw-r--r-- | sys/kern/uipc_socket.c | 68 |
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); |