From c8aec28b821656417e8b676e51635bdad5eb3971 Mon Sep 17 00:00:00 2001
From: Gerhard <Gerhard>
Date: Thu, 13 Feb 2025 11:25:09 +0100
Subject: [PATCH] Added options setsockopt-socket and setsockopt-connected

---
 CHANGES      | 3 +++
 doc/socat.yo | 6 ++++++
 xio-socket.c | 2 ++
 xio-socket.h | 2 ++
 xioopts.c    | 4 ++++
 xioopts.h    | 2 ++
 6 files changed, 19 insertions(+)

diff --git a/CHANGES b/CHANGES
index 83ed6f0..8d8a30b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -110,6 +110,9 @@ Features:
 	Socat now prints an info message when implicitely setting SO_REUSEADDR.
 	Thanks to Michael Renner for this suggestion.
 
+	Added generic options setsockopt-socket and setsockopt-connected that
+	are applied after socket() or when connected.
+
 Building:
 	Disabling certain features during configure could break build process.
 
diff --git a/doc/socat.yo b/doc/socat.yo
index 6695d28..6cfd907 100644
--- a/doc/socat.yo
+++ b/doc/socat.yo
@@ -2408,6 +2408,12 @@ label(OPTION_SETSOCKOPT_STRING)dit(bf(tt(setsockopt-string=<level>:<optname>:<op
    Like tt(setsockopt), but <optval> is a link(string)(TYPE_STRING).
    This string is passed to the function with trailing null character, and the
    length parameter is automatically derived from the data.
+label(OPTION_SETSOCKOPT_SOCKET)dit(bf(tt(setsockopt-socket=<level>:<optname>:<optval>)))
+   Like tt(setsockopt), but is applied to the socket before other operations
+   (code(bind()), code(connect()), code(accept()), ...)
+label(OPTION_SETSOCKOPT_CONNECTED)dit(bf(tt(setsockopt-connected=<level>:<optname>:<optval>)))
+   Like tt(setsockopt), but is applied only when the socket has been connected
+   by a code(connect()) or code(listen()) call.
 enddit()
 
 startdit()enddit()nl()
diff --git a/xio-socket.c b/xio-socket.c
index 2eaed08..6400c01 100644
--- a/xio-socket.c
+++ b/xio-socket.c
@@ -191,6 +191,8 @@ const struct optdesc opt_setsockopt_int    = { "setsockopt-int",    "sockopt-int
 const struct optdesc opt_setsockopt_bin    = { "setsockopt-bin",    "sockopt-bin",    OPT_SETSOCKOPT_BIN,        GROUP_SOCKET,PH_CONNECTED, TYPE_INT_INT_BIN,     OFUNC_SOCKOPT_GENERIC, 0, 0 };
 const struct optdesc opt_setsockopt_string = { "setsockopt-string", "sockopt-string", OPT_SETSOCKOPT_STRING,     GROUP_SOCKET,PH_CONNECTED, TYPE_INT_INT_STRING,  OFUNC_SOCKOPT_GENERIC, 0, 0 };
 const struct optdesc opt_setsockopt_listen = { "setsockopt-listen", "sockopt-listen", OPT_SETSOCKOPT_LISTEN,     GROUP_SOCKET,PH_PREBIND,   TYPE_INT_INT_BIN,     OFUNC_SOCKOPT_GENERIC, 0, 0 };
+const struct optdesc opt_setsockopt_socket    = { "setsockopt-socket",    "sockopt-sock", OPT_SETSOCKOPT_SOCKET,    GROUP_SOCKET,PH_PASTSOCKET, TYPE_INT_INT_BIN,    OFUNC_SOCKOPT_GENERIC, 0, 0 };
+const struct optdesc opt_setsockopt_connected = { "setsockopt-connected", "sockopt-conn", OPT_SETSOCKOPT_CONNECTED, GROUP_SOCKET,PH_CONNECTED,  TYPE_INT_INT_BIN,    OFUNC_SOCKOPT_GENERIC, 0, 0 };
 
 const struct optdesc opt_null_eof = { "null-eof", NULL, OPT_NULL_EOF, GROUP_SOCKET, PH_OFFSET, TYPE_BOOL, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.null_eof) };
 
diff --git a/xio-socket.h b/xio-socket.h
index 2af3367..2ecb28b 100644
--- a/xio-socket.h
+++ b/xio-socket.h
@@ -83,6 +83,8 @@ extern const struct optdesc opt_setsockopt_bin;
 extern const struct optdesc opt_setsockopt_string;
 extern const struct optdesc opt_setsockopt_listen;
 extern const struct optdesc opt_null_eof;
+extern const struct optdesc opt_setsockopt_socket;
+extern const struct optdesc opt_setsockopt_connected;
 
 
 extern
diff --git a/xioopts.c b/xioopts.c
index db77499..aa2f525 100644
--- a/xioopts.c
+++ b/xioopts.c
@@ -1583,8 +1583,10 @@ const struct optname optionnames[] = {
 #endif
 	IF_SOCKET ("setsockopt",	&opt_setsockopt)
 	IF_SOCKET ("setsockopt-bin",	&opt_setsockopt_bin)
+	IF_SOCKET ("setsockopt-connected",	&opt_setsockopt_connected)
 	IF_SOCKET ("setsockopt-int",	&opt_setsockopt_int)
 	IF_SOCKET ("setsockopt-listen",	&opt_setsockopt_listen)
+	IF_SOCKET ("setsockopt-socket",		&opt_setsockopt_socket)
 	IF_SOCKET ("setsockopt-string",	&opt_setsockopt_string)
 	IF_ANY    ("setuid",	&opt_setuid)
 	IF_ANY    ("setuid-early",	&opt_setuid_early)
@@ -1719,8 +1721,10 @@ const struct optname optionnames[] = {
 #endif /* SO_USELOOPBACK */
 	IF_SOCKET ("sockopt",		&opt_setsockopt)
 	IF_SOCKET ("sockopt-bin",	&opt_setsockopt_bin)
+	IF_SOCKET ("sockopt-conn",	&opt_setsockopt_connected)
 	IF_SOCKET ("sockopt-int",	&opt_setsockopt_int)
 	IF_SOCKET ("sockopt-listen",	&opt_setsockopt_listen)
+	IF_SOCKET ("sockopt-sock",	&opt_setsockopt_socket)
 	IF_SOCKET ("sockopt-string",	&opt_setsockopt_string)
 	IF_SOCKS4 ("socksport",	&opt_socksport)
 	IF_SOCKS4 ("socksuser",	&opt_socksuser)
diff --git a/xioopts.h b/xioopts.h
index d40e34d..593fc5d 100644
--- a/xioopts.h
+++ b/xioopts.h
@@ -663,8 +663,10 @@ enum e_optcode {
    OPT_SETPGID,
    OPT_SETSID,
    OPT_SETSOCKOPT_BIN,
+   OPT_SETSOCKOPT_CONNECTED,
    OPT_SETSOCKOPT_INT,
    OPT_SETSOCKOPT_LISTEN,
+   OPT_SETSOCKOPT_SOCKET,
    OPT_SETSOCKOPT_STRING,
    OPT_SETUID,
    OPT_SETUID_EARLY,