git: abe8379b4f24 - main - sockets: repair wakeup of accept(2) by shutdown(2)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 15 Feb 2024 18:49:03 UTC
The branch main has been updated by glebius:
URL: https://cgit.FreeBSD.org/src/commit/?id=abe8379b4f244aa12f13a603124eb6b41faabec5
commit abe8379b4f244aa12f13a603124eb6b41faabec5
Author: Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2024-02-15 18:48:44 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2024-02-15 18:48:44 +0000
sockets: repair wakeup of accept(2) by shutdown(2)
That was lost in transition from one-for-all soshutdown() to protocol
specific methods. Only protocols that listen(2) were affected. This is
not a documented or specified feature, but some software relies on it. At
least the FreeSWITCH telephony software uses this behavior on
PF_INET/SOCK_STREAM.
Fixes: 5bba2728079ed4da33f727dbc2b6ae1de02ba897
---
sys/kern/uipc_usrreq.c | 17 ++++++++---------
sys/netinet/sctp_usrreq.c | 11 +++++------
sys/netinet/tcp_usrreq.c | 11 +++++------
3 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index db226a16674e..20facd9b0a44 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -1669,7 +1669,14 @@ uipc_shutdown(struct socket *so, enum shutdown_how how)
int error;
SOCK_LOCK(so);
- if ((so->so_state &
+ if (SOLISTENING(so)) {
+ if (how != SHUT_WR) {
+ so->so_error = ECONNABORTED;
+ solisten_wakeup(so); /* unlocks so */
+ } else
+ SOCK_UNLOCK(so);
+ return (ENOTCONN);
+ } else if ((so->so_state &
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
/*
* POSIX mandates us to just return ENOTCONN when shutdown(2) is
@@ -1691,14 +1698,6 @@ uipc_shutdown(struct socket *so, enum shutdown_how how)
}
} else
error = 0;
- if (SOLISTENING(so)) {
- if (how != SHUT_WR) {
- so->so_error = ECONNABORTED;
- solisten_wakeup(so); /* unlocks so */
- } else
- SOCK_UNLOCK(so);
- return (0);
- }
SOCK_UNLOCK(so);
switch (how) {
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 70fe021be766..3b0da87edce3 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -794,18 +794,17 @@ sctp_shutdown(struct socket *so, enum shutdown_how how)
return (EOPNOTSUPP);
SOCK_LOCK(so);
- if ((so->so_state &
- (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
- SOCK_UNLOCK(so);
- return (ENOTCONN);
- }
if (SOLISTENING(so)) {
if (how != SHUT_WR) {
so->so_error = ECONNABORTED;
solisten_wakeup(so); /* unlocks so */
} else
SOCK_UNLOCK(so);
- return (0);
+ return (ENOTCONN);
+ } else if ((so->so_state &
+ (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
+ SOCK_UNLOCK(so);
+ return (ENOTCONN);
}
SOCK_UNLOCK(so);
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index a283d308801f..9bb953617d99 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -807,18 +807,17 @@ tcp_usr_shutdown(struct socket *so, enum shutdown_how how)
int error = 0;
SOCK_LOCK(so);
- if ((so->so_state &
- (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
- SOCK_UNLOCK(so);
- return (ENOTCONN);
- }
if (SOLISTENING(so)) {
if (how != SHUT_WR) {
so->so_error = ECONNABORTED;
solisten_wakeup(so); /* unlocks so */
} else
SOCK_UNLOCK(so);
- return (0);
+ return (ENOTCONN);
+ } else if ((so->so_state &
+ (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
+ SOCK_UNLOCK(so);
+ return (ENOTCONN);
}
SOCK_UNLOCK(so);