]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tcpkeepalive: support setting TCP keep-alive parameters on Solaris <11.4
authorAndy Pan <i@andypan.me>
Mon, 3 Jun 2024 07:15:55 +0000 (15:15 +0800)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 3 Jun 2024 21:04:05 +0000 (23:04 +0200)
Solaris didn't support TCP_KEEPIDLE and TCP_KEEPINTVL until 11.4,
before that it use TCP_KEEPALIVE_THRESHOLD and TCP_KEEPALIVE_ABORT_THRESHOLD
as the substitute. Therefore, for Solaris <11.4 we need to use this substitute
for setting TCP keep-alive parameters.

Ref:
https://docs.oracle.com/cd/E86824_01/html/E54777/tcp-7p.html
https://docs.oracle.com/cd/E88353_01/html/E37851/tcp-4p.html

Closes #13864

docs/cmdline-opts/keepalive-time.md
lib/cf-socket.c

index 41c09031ec597f9ec82ecf5201eedc031fa07de2..7116bcdd919e577d87b0fba4d1b105b86ee70ac6 100644 (file)
@@ -19,9 +19,10 @@ Example:
 Set the time a connection needs to remain idle before sending keepalive probes
 and the time between individual keepalive probes. It is currently effective on
 operating systems offering the `TCP_KEEPIDLE` and `TCP_KEEPINTVL` socket
-options (meaning Linux, recent AIX, HP-UX and more). Keepalive is used by the
-TCP stack to detect broken networks on idle connections. The number of missed
-keepalive probes before declaring the connection down is OS dependent and is
-commonly 9 or 10. This option has no effect if --no-keepalive is used.
+options (meaning Linux, *BSD/macOS, Windows, Solaris, and recent AIX, HP-UX and more).
+Keepalive is used by the TCP stack to detect broken networks on idle connections.
+The number of missed keepalive probes before declaring the connection down is OS
+dependent and is commonly 8 (*BSD/macOS/AIX), 9 (Linux/AIX) or 5/10 (Windows).
+This option has no effect if --no-keepalive is used.
 
 If unspecified, the option defaults to 60 seconds.
index 09fa60ad2aee07fe9b9e90a48eb4cd07b7794d2e..9ec496874355399e20376d7bf00576605cd6315e 100644 (file)
@@ -143,8 +143,10 @@ static void nosigpipe(struct Curl_easy *data,
 #endif
 
 #if defined(USE_WINSOCK) || \
+   (defined(__sun) && !defined(TCP_KEEPIDLE)) || \
    (defined(__DragonFly__) && __DragonFly_version < 500702)
-/* DragonFlyBSD < 500702 and Windows use millisecond units */
+/* Solaris < 11.4, DragonFlyBSD < 500702 and Windows
+ * use millisecond units. */
 #define KEEPALIVE_FACTOR(x) (x *= 1000)
 #else
 #define KEEPALIVE_FACTOR(x)
@@ -210,6 +212,16 @@ tcpkeepalive(struct Curl_easy *data,
             "%" CURL_FORMAT_SOCKET_T ": errno %d",
             sockfd, SOCKERRNO);
     }
+#elif defined(TCP_KEEPALIVE_THRESHOLD)
+    /* Solaris <11.4 style */
+    optval = curlx_sltosi(data->set.tcp_keepidle);
+    KEEPALIVE_FACTOR(optval);
+    if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
+      (void *)&optval, sizeof(optval)) < 0) {
+      infof(data, "Failed to set TCP_KEEPALIVE_THRESHOLD on fd "
+            "%" CURL_FORMAT_SOCKET_T ": errno %d",
+            sockfd, SOCKERRNO);
+    }
 #endif
 #ifdef TCP_KEEPINTVL
     optval = curlx_sltosi(data->set.tcp_keepintvl);
@@ -220,6 +232,26 @@ tcpkeepalive(struct Curl_easy *data,
             "%" CURL_FORMAT_SOCKET_T ": errno %d",
             sockfd, SOCKERRNO);
     }
+#elif defined(TCP_KEEPALIVE_ABORT_THRESHOLD)
+    /* Solaris <11.4 style */
+    /* TCP_KEEPALIVE_ABORT_THRESHOLD should equal to
+     * TCP_KEEPCNT * TCP_KEEPINTVL on other platforms.
+     * The default value of TCP_KEEPCNT is 9 on Linux,
+     * 8 on *BSD/macOS, 5 or 10 on Windows. We choose
+     * 9 for Solaris <11.4 because there is no default
+     * value for TCP_KEEPCNT on Solaris 11.4.
+     *
+     * Note that the consequent probes will not be sent
+     * at equal intervals on Solaris, but will be sent
+     * using the exponential backoff algorithm. */
+    optval = 9 * curlx_sltosi(data->set.tcp_keepintvl);
+    KEEPALIVE_FACTOR(optval);
+    if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD,
+          (void *)&optval, sizeof(optval)) < 0) {
+      infof(data, "Failed to set TCP_KEEPALIVE_ABORT_THRESHOLD on fd "
+            "%" CURL_FORMAT_SOCKET_T ": errno %d",
+            sockfd, SOCKERRNO);
+    }
 #endif
 #endif
   }