aboutgitcodebugslistschat
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2026-05-13 17:18:20 +1000
committerStefano Brivio <sbrivio@redhat.com>2026-05-27 10:17:18 +0200
commit98e3c015b3791ff55381e5ee687f541721d1695e (patch)
treeddc88853aba8c5b20a75bfb984e72cd62634e586
parent038c51e324695b65c154bc0eee30bd19a7423ad2 (diff)
downloadpasst-98e3c015b3791ff55381e5ee687f541721d1695e.tar
passt-98e3c015b3791ff55381e5ee687f541721d1695e.tar.gz
passt-98e3c015b3791ff55381e5ee687f541721d1695e.tar.bz2
passt-98e3c015b3791ff55381e5ee687f541721d1695e.tar.lz
passt-98e3c015b3791ff55381e5ee687f541721d1695e.tar.xz
passt-98e3c015b3791ff55381e5ee687f541721d1695e.tar.zst
passt-98e3c015b3791ff55381e5ee687f541721d1695e.zip
tcp, tcp_splice: Make helper for setting SO_LINGER socket option
Both spliced and non-spliced TCP in some cases set the SO_LINGER socket option in order to to force a TCP RST on a socket side connection. In each case we open code the setsockopt() logic. We're shortly going to add another place that needs this, so move the setsockopt() and error handling logic into a shared helper. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r--tcp.c33
-rw-r--r--tcp_conn.h3
-rw-r--r--tcp_splice.c20
3 files changed, 26 insertions, 30 deletions
diff --git a/tcp.c b/tcp.c
index 0a613e9..67f7fb8 100644
--- a/tcp.c
+++ b/tcp.c
@@ -1398,29 +1398,36 @@ static int tcp_send_flag(const struct ctx *c, struct tcp_tap_conn *conn,
}
/**
- * tcp_sock_rst() - Close TCP connection forcing RST on socket side
- * @c: Execution context
- * @conn: Connection pointer
+ * tcp_linger0_() - Set SO_LINGER with 0 timeout on socket
+ * @f: Flow header (only for debug logging)
+ * @s: Socket to modify
*/
-static void tcp_sock_rst(const struct ctx *c, struct tcp_tap_conn *conn)
+void tcp_linger0_(const struct flow_common *f, int s)
{
const struct linger linger0 = {
.l_onoff = 1,
.l_linger = 0,
};
- /* Force RST on socket to inform the peer
- *
- * We do this by setting SO_LINGER with 0 timeout, which means that
- * close() will send an RST (unless the connection is already closed in
- * both directions).
+ /* Setting SO_LINGER with 0 timeout, means that close() will send an RST
+ * (unless the connection is already closed in both directions).
*/
- if (setsockopt(conn->sock, SOL_SOCKET,
- SO_LINGER, &linger0, sizeof(linger0)) < 0) {
- flow_dbg_perror(conn,
- "SO_LINGER failed, may not send RST to peer");
+ if (setsockopt(s, SOL_SOCKET, SO_LINGER,
+ &linger0, sizeof(linger0)) < 0) {
+ flow_log_perror_(f, LOG_DEBUG,
+ "SO_LINGER failed, may not send RST to peer");
}
+}
+/**
+ * tcp_sock_rst() - Close TCP connection forcing RST on socket side
+ * @c: Execution context
+ * @conn: Connection pointer
+ */
+static void tcp_sock_rst(const struct ctx *c, struct tcp_tap_conn *conn)
+{
+ /* Force RST on socket to inform the peer */
+ tcp_linger0(conn, conn->sock);
conn_event(c, conn, CLOSED);
}
diff --git a/tcp_conn.h b/tcp_conn.h
index c8381aa..d93ada7 100644
--- a/tcp_conn.h
+++ b/tcp_conn.h
@@ -239,6 +239,9 @@ struct tcp_splice_conn {
extern int init_sock_pool4 [TCP_SOCK_POOL_SIZE];
extern int init_sock_pool6 [TCP_SOCK_POOL_SIZE];
+void tcp_linger0_(const struct flow_common *f, int s);
+#define tcp_linger0(flow_, s_) tcp_linger0_(&(flow_)->f, (s_))
+
bool tcp_flow_defer(const struct tcp_tap_conn *conn);
int tcp_flow_repair_on(struct ctx *c, const struct tcp_tap_conn *conn);
diff --git a/tcp_splice.c b/tcp_splice.c
index af50e71..1f969a5 100644
--- a/tcp_splice.c
+++ b/tcp_splice.c
@@ -240,28 +240,14 @@ static void conn_event_do(struct tcp_splice_conn *conn, unsigned long event)
*/
static void tcp_splice_rst(struct tcp_splice_conn *conn)
{
- const struct linger linger0 = {
- .l_onoff = 1,
- .l_linger = 0,
- };
unsigned sidei;
if (conn->flags & CLOSING)
return; /* Nothing to do */
- /* Force RST on sockets to inform the peer
- *
- * We do this by setting SO_LINGER with 0 timeout, which means that
- * close() will send an RST (unless the connection is already closed in
- * both directions).
- */
- flow_foreach_sidei(sidei) {
- if (setsockopt(conn->s[sidei], SOL_SOCKET,
- SO_LINGER, &linger0, sizeof(linger0)) < 0) {
- flow_dbg_perror(conn,
-"SO_LINGER failed, may not send RST to peer");
- }
- }
+ /* Force RST on sockets to inform the peer */
+ flow_foreach_sidei(sidei)
+ tcp_linger0(conn, conn->s[sidei]);
conn_flag(conn, CLOSING);
}