diff --git a/.github/scripts/spellcheck.words b/.github/scripts/spellcheck.words index 5e534846c815bf..ca544c8056b4db 100644 --- a/.github/scripts/spellcheck.words +++ b/.github/scripts/spellcheck.words @@ -502,6 +502,7 @@ monospace MorphOS MPE MPL +MPTCP mprintf MQTT mqtt @@ -522,6 +523,7 @@ mTLS MUA multicwd multiparts +multipath MultiSSL mumbo musedev diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc index deb4c7c326dc1c..75855f54572b81 100644 --- a/docs/cmdline-opts/Makefile.inc +++ b/docs/cmdline-opts/Makefile.inc @@ -161,6 +161,7 @@ DPAGES = \ max-redirs.md \ max-time.md \ metalink.md \ + mptcp.md \ negotiate.md \ netrc-file.md \ netrc-optional.md \ diff --git a/docs/cmdline-opts/mptcp.md b/docs/cmdline-opts/mptcp.md new file mode 100644 index 00000000000000..37a5281f89d6db --- /dev/null +++ b/docs/cmdline-opts/mptcp.md @@ -0,0 +1,41 @@ +--- +c: Copyright (C) Dorian Craps, +SPDX-License-Identifier: curl +Long: mptcp +Added: 8.8.0 +Help: Enable Multipath TCP (MPTCP) +Category: connection +Multi: boolean +See-also: + - tcp-fastopen +Example: + - --mptcp $URL +--- + +# `--mptcp` + +Enables the use of Multipath TCP (MPTCP) for connections. MPTCP is an extension +to the standard TCP that allows multiple TCP streams over different network +paths between the same source and destination. This can enhance bandwidth and +improve reliability by using multiple paths simultaneously. + +MPTCP is beneficial in networks where multiple paths exist between clients and +servers, such as mobile networks where a device may switch between WiFi and +cellular data or in wired networks with multiple Internet Service Providers. + +## Usage + +To use MPTCP for your connections, add the `--mptcp` option when using `curl'. + +## Requirements + +This feature is currently only supported on Linux starting from kernel 5.6. Only +TCP connections are modified, hence this option does not effect HTTP/3 (QUIC) +connections. + +The server you are connecting to must also support MPTCP. If not, the connection +seamlessly falls back to TCP. + +## Availability + +The `--mptcp` option is available starting from `curl` version 8.8.0. diff --git a/docs/libcurl/curl_easy_setopt.md b/docs/libcurl/curl_easy_setopt.md index b80d0b6640efb9..32155c5ead4bbb 100644 --- a/docs/libcurl/curl_easy_setopt.md +++ b/docs/libcurl/curl_easy_setopt.md @@ -425,6 +425,10 @@ Path to a Unix domain socket. See CURLOPT_UNIX_SOCKET_PATH(3) Path to an abstract Unix domain socket. See CURLOPT_ABSTRACT_UNIX_SOCKET(3) +## CURLOPT_MPTCP + +Enable Multipath TCP (MPTCP). See CURLOPT_MPTCP(3) + # NAMES and PASSWORDS OPTIONS (Authentication) ## CURLOPT_NETRC diff --git a/docs/libcurl/opts/CURLOPT_MPTCP.md b/docs/libcurl/opts/CURLOPT_MPTCP.md new file mode 100644 index 00000000000000..9d0ffa3224e980 --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_MPTCP.md @@ -0,0 +1,78 @@ +--- +c: Copyright (C) Dorian Craps, , et al. +SPDX-License-Identifier: curl +Title: CURLOPT_MPTCP +Section: 3 +Source: libcurl +See-also: + - CURLOPT_TCP_FASTOPEN (3) +Protocol: + - All +--- + +# NAME + +CURLOPT_MPTCP - enable Multipath TCP + +# SYNOPSIS + +~~~c +#include + +CURLcode curl_easy_setopt(CURL *handle, CURLOPT_MPTCP, long enable); +~~~ + +# DESCRIPTION + +Pass a long as parameter set to 1L to enable or 0 to disable. + +MPTCP is an extension to the standard TCP that allows multiple TCP streams +over different network paths between the same source and destination. +This can enhance bandwidth and improve reliability by using multiple paths +simultaneously. +MPTCP is beneficial in networks where multiple paths exist between clients +and servers, such as mobile networks where a device may switch between WiFi +and cellular data or in wired networks with multiple Internet Service Providers. + +Enabling MPTCP can improve the performance and reliability of network requests, +particularly in environments where multiple network paths (e.g., WiFi and +cellular) are available. + +MPTCP support depends on the underlying operating system and network +infrastructure. Some networks might drop unknown MPTCP, and its effectiveness +varies based on the network configuration and conditions. If MPTCP is not +supported by the network or the end server, the connection seamlessly falls back +to TCP. + +# DEFAULT + +0 + +# EXAMPLE + +~~~c +int main(void) +{ + CURL *curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); + curl_easy_setopt(curl, CURLOPT_MPTCP, 1L); + curl_easy_perform(curl); + } +} +~~~ + +# AVAILABILITY + +Support for MPTCP in libcurl requires Linux 5.6 or later. Only TCP connections +are modified, hence this option does not effect HTTP/3 (QUIC) connections. + +The features availability in libcurl can also depend on the version of libcurl. +Added in 8.8.0. + +# RETURN VALUE + +Returns CURLE_OK if MPTCP is successfully enabled for the connection, +otherwise returns an error code specific to the reason it could not be enabled, +which might include lack of operating system support or libcurl not being built +with MPTCP support. diff --git a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md index 42b44a5674dd69..41d9835b78d2c0 100644 --- a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md +++ b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.md @@ -6,6 +6,7 @@ Section: 3 Source: libcurl See-also: - CURLOPT_SSL_FALSESTART (3) + - CURLOPT_MPTCP (3) Protocol: - All --- diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc index bf5ea7645faac5..5cefb148a031b3 100644 --- a/docs/libcurl/opts/Makefile.inc +++ b/docs/libcurl/opts/Makefile.inc @@ -245,6 +245,7 @@ man_MANS = \ CURLOPT_MAXREDIRS.3 \ CURLOPT_MIME_OPTIONS.3 \ CURLOPT_MIMEPOST.3 \ + CURLOPT_MPTCP.3 \ CURLOPT_NETRC.3 \ CURLOPT_NETRC_FILE.3 \ CURLOPT_NEW_DIRECTORY_PERMS.3 \ diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index e5531df92cff01..40a5c8d19483e8 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -710,6 +710,7 @@ CURLOPT_MAXREDIRS 7.5 CURLOPT_MIME_OPTIONS 7.81.0 CURLOPT_MIMEPOST 7.56.0 CURLOPT_MUTE 7.1 7.8 7.15.5 +CURLOPT_MPTCP 8.8.0 CURLOPT_NETRC 7.1 CURLOPT_NETRC_FILE 7.11.0 CURLOPT_NEW_DIRECTORY_PERMS 7.16.4 diff --git a/docs/options-in-versions b/docs/options-in-versions index d3513ff119d7f6..816436754c34a7 100644 --- a/docs/options-in-versions +++ b/docs/options-in-versions @@ -126,6 +126,7 @@ --max-redirs 7.5 --max-time (-m) 4.0 --metalink 7.27.0 +--mptcp 8.8.0 --negotiate 7.10.6 --netrc (-n) 4.6 --netrc-file 7.21.5 diff --git a/include/curl/curl.h b/include/curl/curl.h index 25b3836b4e5275..31427740994e12 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -2213,6 +2213,9 @@ typedef enum { /* set ECH configuration */ CURLOPT(CURLOPT_ECH, CURLOPTTYPE_STRINGPOINT, 325), + /* Set MPTCP */ + CURLOPT(CURLOPT_MPTCP, CURLOPTTYPE_LONG, 326), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/cf-socket.c b/lib/cf-socket.c index eeae5f9950c542..bf458b4145fb98 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -244,6 +244,13 @@ void Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest, dest->socktype = SOCK_STREAM; dest->protocol = IPPROTO_IP; break; + case TRNSPRT_MPTCP: +#ifndef IPPROTO_MPTCP +#define IPPROTO_MPTCP 262 +#endif + dest->socktype = SOCK_STREAM; + dest->protocol = IPPROTO_MPTCP; + break; default: /* UDP and QUIC */ dest->socktype = SOCK_DGRAM; dest->protocol = IPPROTO_UDP; @@ -1602,6 +1609,16 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf, result = CURLE_OUT_OF_MEMORY; goto out; } + + if(data->set.mptcp) { +#ifdef __linux__ + transport = TRNSPRT_MPTCP; +#else + result = CURLE_UNSUPPORTED_PROTOCOL; + goto out; +#endif + } + cf_socket_ctx_init(ctx, ai, transport); result = Curl_cf_create(&cf, &Curl_cft_tcp, ctx); diff --git a/lib/easyoptions.c b/lib/easyoptions.c index c79d136707e4d4..85fe36528904bf 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -179,6 +179,7 @@ struct curl_easyoption Curl_easyopts[] = { {"MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE, CURLOT_OFF_T, 0}, {"MIMEPOST", CURLOPT_MIMEPOST, CURLOT_OBJECT, 0}, {"MIME_OPTIONS", CURLOPT_MIME_OPTIONS, CURLOT_LONG, 0}, + {"MPTCP", CURLOPT_MPTCP, CURLOT_LONG, 0}, {"NETRC", CURLOPT_NETRC, CURLOT_VALUES, 0}, {"NETRC_FILE", CURLOPT_NETRC_FILE, CURLOT_STRING, 0}, {"NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS, CURLOT_LONG, 0}, @@ -376,6 +377,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (325 + 1)); + return ((CURLOPT_LASTENTRY%10000) != (326 + 1)); } #endif diff --git a/lib/setopt.c b/lib/setopt.c index f719cc43dde297..d5d2091ee2e8d5 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -2940,6 +2940,9 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) result = CURLE_NOT_BUILT_IN; #endif break; + case CURLOPT_MPTCP: + data->set.mptcp = TRUE; + break; case CURLOPT_SSL_ENABLE_NPN: break; case CURLOPT_SSL_ENABLE_ALPN: diff --git a/lib/urldata.h b/lib/urldata.h index 8bccffb0f59b20..55a5be97103c0b 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -801,6 +801,7 @@ struct ldapconninfo; #define TRNSPRT_UDP 4 #define TRNSPRT_QUIC 5 #define TRNSPRT_UNIX 6 +#define TRNSPRT_MPTCP 7 /* * The connectdata struct contains all fields and variables that should be @@ -1876,6 +1877,7 @@ struct UserDefined { #ifdef USE_ECH int tls_ech; /* TLS ECH configuration */ #endif + BIT(mptcp); /* enable MPTCP support */ }; #ifndef CURL_DISABLE_MIME diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index 74d0c45f2ed121..5b930279de5c6f 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -292,6 +292,7 @@ struct OperationConfig { CLOBBER_NEVER, /* If the file exists, always fail */ CLOBBER_ALWAYS /* If the file exists, always overwrite it */ } file_clobber_mode; + bool mptcp; /* enable MPTCP support */ struct GlobalConfig *global; struct OperationConfig *prev; struct OperationConfig *next; /* Always last in the struct */ diff --git a/src/tool_getparam.c b/src/tool_getparam.c index f56981a743d868..9f9ba0819483f4 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -200,6 +200,7 @@ typedef enum { C_MAX_REDIRS, C_MAX_TIME, C_METALINK, + C_MPTCP, C_NEGOTIATE, C_NETRC, C_NETRC_FILE, @@ -482,6 +483,7 @@ static const struct LongShort aliases[]= { {"max-redirs", ARG_STRG, ' ', C_MAX_REDIRS}, {"max-time", ARG_STRG, 'm', C_MAX_TIME}, {"metalink", ARG_BOOL, ' ', C_METALINK}, + {"mptcp", ARG_BOOL, ' ', C_MPTCP}, {"negotiate", ARG_BOOL, ' ', C_NEGOTIATE}, {"netrc", ARG_BOOL, 'n', C_NETRC}, {"netrc-file", ARG_FILE, ' ', C_NETRC_FILE}, @@ -2794,6 +2796,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ } } break; + case C_MPTCP: /* --mptcp */ + config->mptcp = TRUE; + break; default: /* unknown flag */ err = PARAM_OPTION_UNKNOWN; break; diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c index 8429322045fa79..e0228ee513215f 100644 --- a/src/tool_listhelp.c +++ b/src/tool_listhelp.c @@ -381,6 +381,9 @@ const struct helptxt helptext[] = { {" --metalink", "Process given URLs as metalink XML file", CURLHELP_MISC}, + {" --mptcp", + "Enable Multipath TCP (MPTCP)", + CURLHELP_CONNECTION}, {" --negotiate", "Use HTTP Negotiate (SPNEGO) authentication", CURLHELP_AUTH | CURLHELP_HTTP}, diff --git a/src/tool_operate.c b/src/tool_operate.c index 9f14b3e5860353..437059a9f24123 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -1291,6 +1291,9 @@ static CURLcode single_transfer(struct GlobalConfig *global, if(config->tcp_fastopen) my_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L); + if(config->mptcp) + my_setopt(curl, CURLOPT_MPTCP, 1L); + /* where to store */ my_setopt(curl, CURLOPT_WRITEDATA, per); my_setopt(curl, CURLOPT_INTERLEAVEDATA, per);