From: Andy Pan Date: Mon, 3 Jun 2024 07:15:55 +0000 (+0800) Subject: tcpkeepalive: support setting TCP keep-alive parameters on Solaris <11.4 X-Git-Tag: curl-8_9_0~314 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f51fa8f169f66792104cdea984b7243286116dea;p=thirdparty%2Fcurl.git tcpkeepalive: support setting TCP keep-alive parameters on Solaris <11.4 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 --- diff --git a/docs/cmdline-opts/keepalive-time.md b/docs/cmdline-opts/keepalive-time.md index 41c09031ec..7116bcdd91 100644 --- a/docs/cmdline-opts/keepalive-time.md +++ b/docs/cmdline-opts/keepalive-time.md @@ -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. diff --git a/lib/cf-socket.c b/lib/cf-socket.c index 09fa60ad2a..9ec4968743 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -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 }