mirror of
https://github.com/curl/curl.git
synced 2026-04-18 20:53:51 +03:00
To include what's actually used. Also: - drop unused includes. - scope includes where possible. - drop `curlx/curlx.h` umbrella header. - config2setopts: include `netinet/in.h` for Cygwin/MSYS2. Previously included by chance via an unused curlx include. Closes #20776
1065 lines
35 KiB
C
1065 lines
35 KiB
C
/***************************************************************************
|
|
* _ _ ____ _
|
|
* Project ___| | | | _ \| |
|
|
* / __| | | | |_) | |
|
|
* | (__| |_| | _ <| |___
|
|
* \___|\___/|_| \_\_____|
|
|
*
|
|
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
|
*
|
|
* This software is licensed as described in the file COPYING, which
|
|
* you should have received as part of this distribution. The terms
|
|
* are also available at https://curl.se/docs/copyright.html.
|
|
*
|
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
* copies of the Software, and permit persons to whom the Software is
|
|
* furnished to do so, under the terms of the COPYING file.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
* SPDX-License-Identifier: curl
|
|
*
|
|
***************************************************************************/
|
|
#include "tool_setup.h"
|
|
|
|
#include "tool_cfgable.h"
|
|
#include "tool_setopt.h"
|
|
#include "tool_findfile.h"
|
|
#include "tool_formparse.h"
|
|
#include "tool_msgs.h"
|
|
#include "tool_libinfo.h"
|
|
#include "tool_cb_soc.h"
|
|
#include "tool_operate.h"
|
|
#include "config2setopts.h"
|
|
#include "tool_ipfs.h"
|
|
#include "tool_cb_wrt.h"
|
|
#include "tool_cb_rea.h"
|
|
#include "tool_cb_see.h"
|
|
#include "tool_cb_dbg.h"
|
|
#include "tool_helpers.h"
|
|
#include "tool_version.h"
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
#include <netinet/in.h> /* IPPROTO_IPV6 */
|
|
#endif
|
|
|
|
#define BUFFER_SIZE 102400L
|
|
|
|
#ifdef IP_TOS
|
|
static int get_address_family(curl_socket_t sockfd)
|
|
{
|
|
struct sockaddr addr;
|
|
curl_socklen_t addrlen = sizeof(addr);
|
|
memset(&addr, 0, sizeof(addr));
|
|
if(getsockname(sockfd, &addr, &addrlen) == 0)
|
|
return addr.sa_family;
|
|
return AF_UNSPEC;
|
|
}
|
|
#endif
|
|
|
|
#ifndef SOL_IP
|
|
#define SOL_IP IPPROTO_IP
|
|
#endif
|
|
|
|
#if defined(IP_TOS) || defined(IPV6_TCLASS) || defined(SO_PRIORITY)
|
|
static int sockopt_callback(void *clientp, curl_socket_t curlfd,
|
|
curlsocktype purpose)
|
|
{
|
|
struct OperationConfig *config = (struct OperationConfig *)clientp;
|
|
if(purpose != CURLSOCKTYPE_IPCXN)
|
|
return CURL_SOCKOPT_OK;
|
|
(void)config;
|
|
(void)curlfd;
|
|
#if defined(IP_TOS) || defined(IPV6_TCLASS)
|
|
if(config->ip_tos > 0) {
|
|
int tos = (int)config->ip_tos;
|
|
int result = 0;
|
|
switch(get_address_family(curlfd)) {
|
|
case AF_INET:
|
|
#ifdef IP_TOS
|
|
result = setsockopt(curlfd, SOL_IP, IP_TOS, (void *)&tos, sizeof(tos));
|
|
#endif
|
|
break;
|
|
#if defined(IPV6_TCLASS) && defined(AF_INET6)
|
|
case AF_INET6:
|
|
result = setsockopt(curlfd, IPPROTO_IPV6, IPV6_TCLASS,
|
|
(void *)&tos, sizeof(tos));
|
|
break;
|
|
#endif
|
|
}
|
|
if(result < 0) {
|
|
char buffer[STRERROR_LEN];
|
|
int error = errno;
|
|
warnf("Setting type of service to %d failed with errno %d: %s", tos,
|
|
error, curlx_strerror(error, buffer, sizeof(buffer)));
|
|
}
|
|
}
|
|
#endif
|
|
#ifdef SO_PRIORITY
|
|
if(config->vlan_priority > 0) {
|
|
int priority = (int)config->vlan_priority;
|
|
if(setsockopt(curlfd, SOL_SOCKET, SO_PRIORITY,
|
|
(void *)&priority, sizeof(priority)) != 0) {
|
|
char buffer[STRERROR_LEN];
|
|
int error = errno;
|
|
warnf("VLAN priority %d failed with errno %d: %s", priority,
|
|
error, curlx_strerror(error, buffer, sizeof(buffer)));
|
|
}
|
|
}
|
|
#endif
|
|
return CURL_SOCKOPT_OK;
|
|
}
|
|
#endif /* IP_TOD || IPV6_TCLASS || SO_PRIORITY */
|
|
|
|
/* return current SSL backend name, chop off multissl */
|
|
static char *ssl_backend(void)
|
|
{
|
|
static char ssl_ver[80] = "no ssl";
|
|
static bool already = FALSE;
|
|
if(!already) { /* if there is no existing version */
|
|
const char *v = curl_version_info(CURLVERSION_NOW)->ssl_version;
|
|
if(v)
|
|
curl_msnprintf(ssl_ver, sizeof(ssl_ver),
|
|
"%.*s", (int)strcspn(v, " "), v);
|
|
already = TRUE;
|
|
}
|
|
return ssl_ver;
|
|
}
|
|
|
|
/*
|
|
* Possibly rewrite the URL for IPFS and return the protocol token for the
|
|
* scheme used in the given URL.
|
|
*/
|
|
static CURLcode url_proto_and_rewrite(char **url,
|
|
struct OperationConfig *config,
|
|
const char **scheme)
|
|
{
|
|
CURLcode result = CURLE_OK;
|
|
CURLU *uh = curl_url();
|
|
const char *proto = NULL;
|
|
*scheme = NULL;
|
|
|
|
DEBUGASSERT(url && *url);
|
|
if(uh) {
|
|
char *schemep = NULL;
|
|
CURLUcode uc =
|
|
curl_url_set(uh, CURLUPART_URL, *url,
|
|
CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME);
|
|
if(!uc) {
|
|
uc = curl_url_get(uh, CURLUPART_SCHEME, &schemep, CURLU_DEFAULT_SCHEME);
|
|
if(!uc) {
|
|
#ifdef CURL_DISABLE_IPFS
|
|
(void)config;
|
|
#else
|
|
if(curl_strequal(schemep, proto_ipfs) ||
|
|
curl_strequal(schemep, proto_ipns)) {
|
|
result = ipfs_url_rewrite(uh, schemep, url, config);
|
|
/* short-circuit proto_token, we know it is ipfs or ipns */
|
|
if(curl_strequal(schemep, proto_ipfs))
|
|
proto = proto_ipfs;
|
|
else if(curl_strequal(schemep, proto_ipns))
|
|
proto = proto_ipns;
|
|
if(result)
|
|
config->synthetic_error = TRUE;
|
|
}
|
|
else
|
|
#endif /* !CURL_DISABLE_IPFS */
|
|
proto = proto_token(schemep);
|
|
curl_free(schemep);
|
|
}
|
|
else if(uc == CURLUE_OUT_OF_MEMORY)
|
|
result = CURLE_OUT_OF_MEMORY;
|
|
}
|
|
else if(uc == CURLUE_OUT_OF_MEMORY)
|
|
result = CURLE_OUT_OF_MEMORY;
|
|
curl_url_cleanup(uh);
|
|
}
|
|
else
|
|
result = CURLE_OUT_OF_MEMORY;
|
|
|
|
*scheme = proto ? proto : "?"; /* Never match if not found. */
|
|
return result;
|
|
}
|
|
|
|
static CURLcode ssh_setopts(struct OperationConfig *config, CURL *curl,
|
|
const char *use_proto)
|
|
{
|
|
CURLcode result;
|
|
|
|
if(use_proto != proto_scp && use_proto != proto_sftp)
|
|
return CURLE_OK;
|
|
|
|
/* SSH and SSL private key uses same command-line option */
|
|
MY_SETOPT_STR(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
|
|
MY_SETOPT_STR(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
|
|
|
|
/* SSH host key md5 checking allows us to fail if we are not talking to who
|
|
we think we should */
|
|
MY_SETOPT_STR(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, config->hostpubmd5);
|
|
|
|
/* SSH host key sha256 checking allows us to fail if we are not talking to
|
|
who we think we should */
|
|
MY_SETOPT_STR(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
|
|
config->hostpubsha256);
|
|
|
|
if(config->ssh_compression)
|
|
my_setopt_long(curl, CURLOPT_SSH_COMPRESSION, 1);
|
|
|
|
if(!config->insecure_ok) {
|
|
char *known = config->knownhosts;
|
|
if(!known)
|
|
known = findfile(".ssh/known_hosts", FALSE);
|
|
if(known) {
|
|
result = my_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, known);
|
|
if(result) {
|
|
config->knownhosts = NULL;
|
|
curl_free(known);
|
|
return result;
|
|
}
|
|
/* store it in global to avoid repeated checks */
|
|
config->knownhosts = known;
|
|
}
|
|
else if(!config->hostpubmd5 && !config->hostpubsha256) {
|
|
errorf("Could not find a known_hosts file");
|
|
return CURLE_FAILED_INIT;
|
|
}
|
|
else
|
|
warnf("Could not find a known_hosts file");
|
|
}
|
|
return CURLE_OK; /* ignore if SHA256 did not work */
|
|
}
|
|
|
|
static long tlsversion(unsigned char mintls,
|
|
unsigned char maxtls)
|
|
{
|
|
long tlsver = 0;
|
|
if(!mintls) { /* minimum is at default */
|
|
/* minimum is set to default, which we want to be 1.2 */
|
|
if(maxtls && (maxtls < 3))
|
|
/* max is set lower than 1.2 and minimum is default, change minimum to
|
|
the same as max */
|
|
mintls = maxtls;
|
|
}
|
|
switch(mintls) {
|
|
case 1:
|
|
tlsver = CURL_SSLVERSION_TLSv1_0;
|
|
break;
|
|
case 2:
|
|
tlsver = CURL_SSLVERSION_TLSv1_1;
|
|
break;
|
|
case 0: /* let default minimum be 1.2 */
|
|
case 3:
|
|
tlsver = CURL_SSLVERSION_TLSv1_2;
|
|
break;
|
|
case 4:
|
|
default: /* in case */
|
|
tlsver = CURL_SSLVERSION_TLSv1_3;
|
|
break;
|
|
}
|
|
switch(maxtls) {
|
|
case 0: /* not set, leave it */
|
|
break;
|
|
case 1:
|
|
tlsver |= CURL_SSLVERSION_MAX_TLSv1_0;
|
|
break;
|
|
case 2:
|
|
tlsver |= CURL_SSLVERSION_MAX_TLSv1_1;
|
|
break;
|
|
case 3:
|
|
tlsver |= CURL_SSLVERSION_MAX_TLSv1_2;
|
|
break;
|
|
case 4:
|
|
default: /* in case */
|
|
tlsver |= CURL_SSLVERSION_MAX_TLSv1_3;
|
|
break;
|
|
}
|
|
return tlsver;
|
|
}
|
|
|
|
/* only called if libcurl supports TLS */
|
|
static CURLcode ssl_ca_setopts(struct OperationConfig *config, CURL *curl)
|
|
{
|
|
CURLcode result = CURLE_OK;
|
|
|
|
if(config->cacert)
|
|
MY_SETOPT_STR(curl, CURLOPT_CAINFO, config->cacert);
|
|
if(config->proxy_cacert)
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert);
|
|
if(config->capath)
|
|
MY_SETOPT_STR(curl, CURLOPT_CAPATH, config->capath);
|
|
|
|
/* For the time being if --proxy-capath is not set then we use the
|
|
--capath value for it, if any. See #1257 */
|
|
if(config->proxy_capath || config->capath) {
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_CAPATH,
|
|
(config->proxy_capath ? config->proxy_capath :
|
|
config->capath));
|
|
if(result && config->proxy_capath) {
|
|
warnf("ignoring %s, not supported by libcurl with %s",
|
|
config->proxy_capath ? "--proxy-capath" : "--capath",
|
|
ssl_backend());
|
|
}
|
|
}
|
|
if(result)
|
|
return result;
|
|
|
|
#ifdef CURL_CA_EMBED
|
|
if(!config->cacert && !config->capath) {
|
|
struct curl_blob blob;
|
|
blob.data = CURL_UNCONST(curl_ca_embed);
|
|
blob.len = strlen((const char *)curl_ca_embed);
|
|
blob.flags = CURL_BLOB_NOCOPY;
|
|
notef("Using embedded CA bundle (%zu bytes)", blob.len);
|
|
result = curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, &blob);
|
|
if((result == CURLE_NOT_BUILT_IN) || (result == CURLE_UNKNOWN_OPTION)) {
|
|
warnf("ignoring %s, not supported by libcurl with %s",
|
|
"embedded CA bundle", ssl_backend());
|
|
result = CURLE_OK;
|
|
}
|
|
}
|
|
if(!config->proxy_cacert && !config->proxy_capath) {
|
|
struct curl_blob blob;
|
|
blob.data = CURL_UNCONST(curl_ca_embed);
|
|
blob.len = strlen((const char *)curl_ca_embed);
|
|
blob.flags = CURL_BLOB_NOCOPY;
|
|
notef("Using embedded CA bundle, for proxies (%zu bytes)", blob.len);
|
|
result = curl_easy_setopt(curl, CURLOPT_PROXY_CAINFO_BLOB, &blob);
|
|
if((result == CURLE_NOT_BUILT_IN) || (result == CURLE_UNKNOWN_OPTION)) {
|
|
warnf("ignoring %s, not supported by libcurl with %s",
|
|
"embedded CA bundle", ssl_backend());
|
|
result = CURLE_OK;
|
|
}
|
|
}
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
/* only called if libcurl supports TLS */
|
|
static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl)
|
|
{
|
|
CURLcode result = CURLE_OK;
|
|
|
|
if(config->crlfile)
|
|
MY_SETOPT_STR(curl, CURLOPT_CRLFILE, config->crlfile);
|
|
if(config->proxy_crlfile)
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile);
|
|
else if(config->crlfile)
|
|
/* CURLOPT_PROXY_CRLFILE default is crlfile */
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_CRLFILE, config->crlfile);
|
|
|
|
if(config->pinnedpubkey) {
|
|
MY_SETOPT_STR(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey);
|
|
if(result)
|
|
warnf("ignoring %s, not supported by libcurl with %s",
|
|
"--pinnedpubkey", ssl_backend());
|
|
}
|
|
if(config->proxy_pinnedpubkey) {
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_PINNEDPUBLICKEY,
|
|
config->proxy_pinnedpubkey);
|
|
if(result)
|
|
warnf("ignoring %s, not supported by libcurl with %s",
|
|
"--proxy-pinnedpubkey", ssl_backend());
|
|
}
|
|
|
|
if(config->ssl_ec_curves)
|
|
MY_SETOPT_STR(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
|
|
|
|
if(config->ssl_signature_algorithms)
|
|
MY_SETOPT_STR(curl, CURLOPT_SSL_SIGNATURE_ALGORITHMS,
|
|
config->ssl_signature_algorithms);
|
|
|
|
if(config->writeout)
|
|
my_setopt_long(curl, CURLOPT_CERTINFO, 1);
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_SSLCERT, config->cert);
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert);
|
|
MY_SETOPT_STR(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_SSLCERTTYPE, config->proxy_cert_type);
|
|
MY_SETOPT_STR(curl, CURLOPT_SSLKEY, config->key);
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
|
|
MY_SETOPT_STR(curl, CURLOPT_SSLKEYTYPE, config->key_type);
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_SSLKEYTYPE, config->proxy_key_type);
|
|
|
|
/* libcurl default is strict verifyhost -> 1L, verifypeer -> 1L */
|
|
if(config->insecure_ok) {
|
|
my_setopt_long(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
|
my_setopt_long(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
|
}
|
|
|
|
if(config->doh_insecure_ok) {
|
|
my_setopt_long(curl, CURLOPT_DOH_SSL_VERIFYPEER, 0);
|
|
my_setopt_long(curl, CURLOPT_DOH_SSL_VERIFYHOST, 0);
|
|
}
|
|
|
|
if(config->proxy_insecure_ok) {
|
|
my_setopt_long(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0);
|
|
my_setopt_long(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0);
|
|
}
|
|
|
|
if(config->verifystatus)
|
|
my_setopt_long(curl, CURLOPT_SSL_VERIFYSTATUS, 1);
|
|
|
|
if(config->doh_verifystatus)
|
|
my_setopt_long(curl, CURLOPT_DOH_SSL_VERIFYSTATUS, 1);
|
|
|
|
my_setopt_SSLVERSION(curl, CURLOPT_SSLVERSION,
|
|
tlsversion(config->ssl_version,
|
|
config->ssl_version_max));
|
|
if(config->proxy)
|
|
my_setopt_SSLVERSION(curl, CURLOPT_PROXY_SSLVERSION,
|
|
config->proxy_ssl_version);
|
|
|
|
{
|
|
long mask =
|
|
(config->ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
|
|
(config->ssl_allow_earlydata ? CURLSSLOPT_EARLYDATA : 0) |
|
|
(config->ssl_no_revoke ? CURLSSLOPT_NO_REVOKE : 0) |
|
|
(config->ssl_revoke_best_effort ? CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
|
|
(config->native_ca_store ? CURLSSLOPT_NATIVE_CA : 0) |
|
|
(config->ssl_auto_client_cert ? CURLSSLOPT_AUTO_CLIENT_CERT : 0);
|
|
|
|
if(mask)
|
|
my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
|
|
}
|
|
|
|
{
|
|
long mask =
|
|
(config->proxy_ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
|
|
(config->proxy_ssl_auto_client_cert ? CURLSSLOPT_AUTO_CLIENT_CERT : 0) |
|
|
(config->proxy_native_ca_store ? CURLSSLOPT_NATIVE_CA : 0);
|
|
|
|
if(mask)
|
|
my_setopt_bitmask(curl, CURLOPT_PROXY_SSL_OPTIONS, mask);
|
|
}
|
|
|
|
if(config->cipher_list) {
|
|
MY_SETOPT_STR(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list);
|
|
if(result)
|
|
warnf("ignoring %s, not supported by libcurl with %s",
|
|
"--ciphers", ssl_backend());
|
|
}
|
|
if(config->proxy_cipher_list) {
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_SSL_CIPHER_LIST,
|
|
config->proxy_cipher_list);
|
|
if(result)
|
|
warnf("ignoring %s, not supported by libcurl with %s",
|
|
"--proxy-ciphers", ssl_backend());
|
|
}
|
|
if(config->cipher13_list) {
|
|
MY_SETOPT_STR(curl, CURLOPT_TLS13_CIPHERS, config->cipher13_list);
|
|
if(result)
|
|
warnf("ignoring %s, not supported by libcurl with %s",
|
|
"--tls13-ciphers", ssl_backend());
|
|
}
|
|
if(config->proxy_cipher13_list) {
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_TLS13_CIPHERS,
|
|
config->proxy_cipher13_list);
|
|
if(result)
|
|
warnf("ignoring %s, not supported by libcurl with %s",
|
|
"--proxy-tls13-ciphers", ssl_backend());
|
|
}
|
|
|
|
/* curl 7.16.0 */
|
|
if(config->disable_sessionid)
|
|
/* disable it */
|
|
my_setopt_long(curl, CURLOPT_SSL_SESSIONID_CACHE, 0);
|
|
|
|
if(feature_ech) {
|
|
/* only if enabled in libcurl */
|
|
if(config->ech) /* only if set (optional) */
|
|
MY_SETOPT_STR(curl, CURLOPT_ECH, config->ech);
|
|
if(config->ech_public) /* only if set (optional) */
|
|
MY_SETOPT_STR(curl, CURLOPT_ECH, config->ech_public);
|
|
if(config->ech_config) /* only if set (optional) */
|
|
MY_SETOPT_STR(curl, CURLOPT_ECH, config->ech_config);
|
|
}
|
|
|
|
if(config->engine)
|
|
MY_SETOPT_STR(curl, CURLOPT_SSLENGINE, config->engine);
|
|
|
|
if(config->ftp_ssl_reqd)
|
|
my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
|
|
|
|
else if(config->ftp_ssl)
|
|
my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
|
|
|
|
else if(config->ftp_ssl_control)
|
|
my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_CONTROL);
|
|
|
|
if(config->noalpn)
|
|
my_setopt_long(curl, CURLOPT_SSL_ENABLE_ALPN, 0);
|
|
|
|
return CURLE_OK;
|
|
}
|
|
|
|
static CURLcode cookie_setopts(struct OperationConfig *config, CURL *curl)
|
|
{
|
|
CURLcode result = CURLE_OK;
|
|
if(config->cookies) {
|
|
struct dynbuf cookies;
|
|
struct curl_slist *cl;
|
|
|
|
/* The maximum size needs to match MAX_NAME in cookie.h */
|
|
#define MAX_COOKIE_LINE 8200
|
|
curlx_dyn_init(&cookies, MAX_COOKIE_LINE);
|
|
for(cl = config->cookies; cl; cl = cl->next) {
|
|
if(cl == config->cookies)
|
|
result = curlx_dyn_add(&cookies, cl->data);
|
|
else
|
|
result = curlx_dyn_addf(&cookies, ";%s%s",
|
|
ISBLANK(cl->data[0]) ? "" : " ", cl->data);
|
|
if(result) {
|
|
warnf("skipped provided cookie, the cookie header "
|
|
"would go over %u bytes", MAX_COOKIE_LINE);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
result = my_setopt_str(curl, CURLOPT_COOKIE, curlx_dyn_ptr(&cookies));
|
|
curlx_dyn_free(&cookies);
|
|
if(result)
|
|
return result;
|
|
}
|
|
|
|
if(config->cookiefiles) {
|
|
struct curl_slist *cfl;
|
|
|
|
for(cfl = config->cookiefiles; cfl; cfl = cfl->next)
|
|
MY_SETOPT_STR(curl, CURLOPT_COOKIEFILE, cfl->data);
|
|
}
|
|
|
|
if(config->cookiejar)
|
|
MY_SETOPT_STR(curl, CURLOPT_COOKIEJAR, config->cookiejar);
|
|
|
|
my_setopt_long(curl, CURLOPT_COOKIESESSION, config->cookiesession);
|
|
|
|
return result;
|
|
}
|
|
|
|
/* only for HTTP transfers */
|
|
static CURLcode http_setopts(struct OperationConfig *config, CURL *curl,
|
|
const char *use_proto)
|
|
{
|
|
CURLcode result = CURLE_OK;
|
|
long postRedir = 0;
|
|
|
|
if(use_proto != proto_http && use_proto != proto_https)
|
|
return CURLE_OK;
|
|
|
|
my_setopt_long(curl, CURLOPT_FOLLOWLOCATION, config->followlocation);
|
|
my_setopt_long(curl, CURLOPT_UNRESTRICTED_AUTH, config->unrestricted_auth);
|
|
#ifndef CURL_DISABLE_AWS
|
|
MY_SETOPT_STR(curl, CURLOPT_AWS_SIGV4, config->aws_sigv4);
|
|
#endif
|
|
my_setopt_long(curl, CURLOPT_AUTOREFERER, config->autoreferer);
|
|
|
|
if(config->proxyheaders) {
|
|
my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders);
|
|
}
|
|
|
|
my_setopt_long(curl, CURLOPT_MAXREDIRS, config->maxredirs);
|
|
|
|
if(config->httpversion)
|
|
my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion);
|
|
|
|
if(config->post301)
|
|
postRedir |= CURL_REDIR_POST_301;
|
|
if(config->post302)
|
|
postRedir |= CURL_REDIR_POST_302;
|
|
if(config->post303)
|
|
postRedir |= CURL_REDIR_POST_303;
|
|
my_setopt_long(curl, CURLOPT_POSTREDIR, postRedir);
|
|
|
|
if(config->encoding)
|
|
MY_SETOPT_STR(curl, CURLOPT_ACCEPT_ENCODING, "");
|
|
|
|
if(config->tr_encoding)
|
|
my_setopt_long(curl, CURLOPT_TRANSFER_ENCODING, 1);
|
|
|
|
my_setopt_long(curl, CURLOPT_HTTP09_ALLOWED, config->http09_allowed);
|
|
|
|
if(config->altsvc)
|
|
MY_SETOPT_STR(curl, CURLOPT_ALTSVC, config->altsvc);
|
|
|
|
if(config->hsts)
|
|
MY_SETOPT_STR(curl, CURLOPT_HSTS, config->hsts);
|
|
|
|
if(config->expect100timeout_ms > 0)
|
|
my_setopt_long(curl, CURLOPT_EXPECT_100_TIMEOUT_MS,
|
|
config->expect100timeout_ms);
|
|
|
|
if(!result)
|
|
result = cookie_setopts(config, curl);
|
|
if(result)
|
|
return result;
|
|
/* Enable header separation when using a proxy with HTTPS or proxytunnel
|
|
* to prevent --header content from leaking into CONNECT requests */
|
|
if((config->proxy || config->proxyheaders) &&
|
|
(use_proto == proto_https || config->proxytunnel))
|
|
my_setopt_long(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE);
|
|
return result;
|
|
}
|
|
|
|
static void tcp_setopts(struct OperationConfig *config, CURL *curl)
|
|
{
|
|
if(!config->tcp_nodelay)
|
|
my_setopt_long(curl, CURLOPT_TCP_NODELAY, 0);
|
|
|
|
if(config->tcp_fastopen)
|
|
my_setopt_long(curl, CURLOPT_TCP_FASTOPEN, 1);
|
|
|
|
if(config->mptcp)
|
|
my_setopt_ptr(curl, CURLOPT_OPENSOCKETFUNCTION, tool_socket_open_mptcp_cb);
|
|
|
|
/* curl 7.17.1 */
|
|
if(!config->nokeepalive) {
|
|
my_setopt_long(curl, CURLOPT_TCP_KEEPALIVE, 1);
|
|
if(config->alivetime) {
|
|
my_setopt_long(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime);
|
|
my_setopt_long(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime);
|
|
}
|
|
if(config->alivecnt)
|
|
my_setopt_long(curl, CURLOPT_TCP_KEEPCNT, config->alivecnt);
|
|
}
|
|
else
|
|
my_setopt_long(curl, CURLOPT_TCP_KEEPALIVE, 0);
|
|
}
|
|
|
|
static CURLcode ftp_setopts(struct OperationConfig *config, CURL *curl,
|
|
const char *use_proto)
|
|
{
|
|
CURLcode result;
|
|
|
|
if(use_proto != proto_ftp && use_proto != proto_ftps)
|
|
return CURLE_OK;
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_FTPPORT, config->ftpport);
|
|
|
|
if(config->disable_epsv)
|
|
/* disable it */
|
|
my_setopt_long(curl, CURLOPT_FTP_USE_EPSV, 0);
|
|
|
|
if(config->disable_eprt)
|
|
/* disable it */
|
|
my_setopt_long(curl, CURLOPT_FTP_USE_EPRT, 0);
|
|
|
|
if(config->ftp_ssl_ccc)
|
|
my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC, config->ftp_ssl_ccc_mode);
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
|
|
my_setopt_long(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip);
|
|
my_setopt_long(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);
|
|
MY_SETOPT_STR(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER,
|
|
config->ftp_alternative_to_user);
|
|
|
|
if(config->ftp_pret)
|
|
my_setopt_long(curl, CURLOPT_FTP_USE_PRET, 1);
|
|
|
|
return result;
|
|
}
|
|
|
|
static void gen_trace_setopts(struct OperationConfig *config, CURL *curl)
|
|
{
|
|
if(global->tracetype != TRACE_NONE) {
|
|
my_setopt_ptr(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
|
|
my_setopt_ptr(curl, CURLOPT_DEBUGDATA, config);
|
|
my_setopt_long(curl, CURLOPT_VERBOSE, 1L);
|
|
}
|
|
}
|
|
|
|
static void gen_cb_setopts(struct OperationConfig *config,
|
|
struct per_transfer *per,
|
|
CURL *curl)
|
|
{
|
|
(void)config; /* when --libcurl is disabled */
|
|
|
|
/* where to store */
|
|
my_setopt_ptr(curl, CURLOPT_WRITEDATA, per);
|
|
my_setopt_ptr(curl, CURLOPT_INTERLEAVEDATA, per);
|
|
|
|
/* what call to write */
|
|
my_setopt_ptr(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
|
|
|
|
/* what to read */
|
|
my_setopt_ptr(curl, CURLOPT_READDATA, per);
|
|
my_setopt_ptr(curl, CURLOPT_READFUNCTION, tool_read_cb);
|
|
|
|
/* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
|
|
CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
|
|
my_setopt_ptr(curl, CURLOPT_SEEKDATA, per);
|
|
my_setopt_ptr(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
|
|
|
|
if((global->progressmode == CURL_PROGRESS_BAR) &&
|
|
!global->noprogress && !global->silent) {
|
|
/* we want the alternative style, then we have to implement it
|
|
ourselves! */
|
|
my_setopt_ptr(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
|
|
my_setopt_ptr(curl, CURLOPT_XFERINFODATA, per);
|
|
}
|
|
else if(per->uploadfile && !strcmp(per->uploadfile, ".")) {
|
|
/* when reading from stdin in non-blocking mode, we use the progress
|
|
function to unpause a busy read */
|
|
my_setopt_long(curl, CURLOPT_NOPROGRESS, 0);
|
|
my_setopt_ptr(curl, CURLOPT_XFERINFOFUNCTION, tool_readbusy_cb);
|
|
my_setopt_ptr(curl, CURLOPT_XFERINFODATA, per);
|
|
}
|
|
|
|
my_setopt_ptr(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
|
|
my_setopt_ptr(curl, CURLOPT_HEADERDATA, per);
|
|
}
|
|
|
|
static CURLcode proxy_setopts(struct OperationConfig *config, CURL *curl)
|
|
{
|
|
CURLcode result;
|
|
if(config->proxy) {
|
|
result = my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
|
|
if(result) {
|
|
errorf("proxy support is disabled in this libcurl");
|
|
config->synthetic_error = TRUE;
|
|
return CURLE_NOT_BUILT_IN;
|
|
}
|
|
}
|
|
|
|
if(config->proxy)
|
|
my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver);
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
|
|
my_setopt_long(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
|
|
if(config->preproxy)
|
|
MY_SETOPT_STR(curl, CURLOPT_PRE_PROXY, config->preproxy);
|
|
|
|
if(config->proxyanyauth)
|
|
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
|
|
else if(config->proxynegotiate)
|
|
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_GSSNEGOTIATE);
|
|
else if(config->proxyntlm)
|
|
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
|
|
else if(config->proxydigest)
|
|
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
|
|
else if(config->proxybasic)
|
|
my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_NOPROXY, config->noproxy);
|
|
my_setopt_long(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS,
|
|
config->suppress_connect_headers);
|
|
|
|
if(config->proxy_service_name)
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_SERVICE_NAME,
|
|
config->proxy_service_name);
|
|
|
|
if(config->haproxy_protocol)
|
|
my_setopt_long(curl, CURLOPT_HAPROXYPROTOCOL, 1);
|
|
|
|
if(config->haproxy_clientip)
|
|
MY_SETOPT_STR(curl, CURLOPT_HAPROXY_CLIENT_IP, config->haproxy_clientip);
|
|
|
|
return result;
|
|
}
|
|
|
|
static CURLcode tls_srp_setopts(struct OperationConfig *config, CURL *curl)
|
|
{
|
|
CURLcode result = CURLE_OK;
|
|
if(config->tls_username)
|
|
MY_SETOPT_STR(curl, CURLOPT_TLSAUTH_USERNAME, config->tls_username);
|
|
if(config->tls_password)
|
|
MY_SETOPT_STR(curl, CURLOPT_TLSAUTH_PASSWORD, config->tls_password);
|
|
if(config->tls_authtype)
|
|
MY_SETOPT_STR(curl, CURLOPT_TLSAUTH_TYPE, config->tls_authtype);
|
|
if(config->proxy_tls_username)
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_TLSAUTH_USERNAME,
|
|
config->proxy_tls_username);
|
|
if(config->proxy_tls_password)
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD,
|
|
config->proxy_tls_password);
|
|
if(config->proxy_tls_authtype)
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_TLSAUTH_TYPE,
|
|
config->proxy_tls_authtype);
|
|
return result;
|
|
}
|
|
|
|
static CURLcode setopt_post(struct OperationConfig *config, CURL *curl)
|
|
{
|
|
CURLcode result = CURLE_OK;
|
|
switch(config->httpreq) {
|
|
case TOOL_HTTPREQ_SIMPLEPOST:
|
|
if(config->resume_from) {
|
|
errorf("cannot mix --continue-at with --data");
|
|
result = CURLE_FAILED_INIT;
|
|
}
|
|
else {
|
|
MY_SETOPT_STR(curl, CURLOPT_POSTFIELDS,
|
|
curlx_dyn_ptr(&config->postdata));
|
|
my_setopt_offt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
|
|
curlx_dyn_len(&config->postdata));
|
|
}
|
|
break;
|
|
case TOOL_HTTPREQ_MIMEPOST:
|
|
/* free previous remainders */
|
|
curl_mime_free(config->mimepost);
|
|
config->mimepost = NULL;
|
|
if(config->resume_from) {
|
|
errorf("cannot mix --continue-at with --form");
|
|
result = CURLE_FAILED_INIT;
|
|
}
|
|
else {
|
|
result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
|
|
if(!result)
|
|
result = my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static void buffersize(struct OperationConfig *config, CURL *curl)
|
|
{
|
|
#ifdef DEBUGBUILD
|
|
char *env = getenv("CURL_BUFFERSIZE");
|
|
if(env) {
|
|
curl_off_t num;
|
|
const char *p = env;
|
|
if(!curlx_str_number(&p, &num, LONG_MAX))
|
|
my_setopt_long(curl, CURLOPT_BUFFERSIZE, (long)num);
|
|
return;
|
|
}
|
|
#endif
|
|
if(config->recvpersecond && (config->recvpersecond < BUFFER_SIZE))
|
|
/* use a smaller sized buffer for better sleeps */
|
|
my_setopt_long(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
|
|
else
|
|
my_setopt_long(curl, CURLOPT_BUFFERSIZE, BUFFER_SIZE);
|
|
}
|
|
|
|
CURLcode config2setopts(struct OperationConfig *config,
|
|
struct per_transfer *per,
|
|
CURL *curl,
|
|
CURLSH *share)
|
|
{
|
|
const char *use_proto;
|
|
CURLcode result = url_proto_and_rewrite(&per->url, config, &use_proto);
|
|
|
|
/* Avoid having this setopt added to the --libcurl source output. */
|
|
if(!result)
|
|
result = curl_easy_setopt(curl, CURLOPT_SHARE, share);
|
|
if(result)
|
|
return result;
|
|
|
|
#ifndef DEBUGBUILD
|
|
/* On most modern OSes, exiting works thoroughly,
|
|
we clean everything up via exit(), so do not bother with slow
|
|
cleanups. Crappy ones might need to skip this.
|
|
Note: avoid having this setopt added to the --libcurl source
|
|
output. */
|
|
result = curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L);
|
|
if(result)
|
|
return result;
|
|
#endif
|
|
|
|
gen_trace_setopts(config, curl);
|
|
|
|
buffersize(config, curl);
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_URL, per->url);
|
|
my_setopt_long(curl, CURLOPT_NOPROGRESS,
|
|
global->noprogress || global->silent);
|
|
/* call after the line above. It may override CURLOPT_NOPROGRESS */
|
|
gen_cb_setopts(config, per, curl);
|
|
|
|
my_setopt_long(curl, CURLOPT_NOBODY, config->no_body);
|
|
MY_SETOPT_STR(curl, CURLOPT_XOAUTH2_BEARER, config->oauth_bearer);
|
|
result = proxy_setopts(config, curl);
|
|
if(setopt_bad(result) || config->synthetic_error)
|
|
return result;
|
|
|
|
my_setopt_long(curl, CURLOPT_FAILONERROR, config->fail == FAIL_WO_BODY);
|
|
MY_SETOPT_STR(curl, CURLOPT_REQUEST_TARGET, config->request_target);
|
|
my_setopt_long(curl, CURLOPT_UPLOAD, !!per->uploadfile);
|
|
my_setopt_long(curl, CURLOPT_DIRLISTONLY, config->dirlistonly);
|
|
my_setopt_long(curl, CURLOPT_APPEND, config->ftp_append);
|
|
|
|
if(config->netrc_opt)
|
|
my_setopt_enum(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
|
|
else if(config->netrc || config->netrc_file)
|
|
my_setopt_enum(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
|
|
else
|
|
my_setopt_enum(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED);
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_NETRC_FILE, config->netrc_file);
|
|
my_setopt_long(curl, CURLOPT_TRANSFERTEXT, config->use_ascii);
|
|
MY_SETOPT_STR(curl, CURLOPT_LOGIN_OPTIONS, config->login_options);
|
|
MY_SETOPT_STR(curl, CURLOPT_USERPWD, config->userpwd);
|
|
MY_SETOPT_STR(curl, CURLOPT_RANGE, config->range);
|
|
my_setopt_ptr(curl, CURLOPT_ERRORBUFFER, per->errorbuffer);
|
|
my_setopt_long(curl, CURLOPT_TIMEOUT_MS, config->timeout_ms);
|
|
|
|
result = setopt_post(config, curl);
|
|
if(result)
|
|
return result;
|
|
|
|
if(config->mime_options)
|
|
my_setopt_long(curl, CURLOPT_MIME_OPTIONS, config->mime_options);
|
|
|
|
if(config->authtype)
|
|
my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, config->authtype);
|
|
|
|
my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
|
|
|
|
if(proto_http || proto_rtsp) {
|
|
MY_SETOPT_STR(curl, CURLOPT_REFERER, config->referer);
|
|
MY_SETOPT_STR(curl, CURLOPT_USERAGENT, config->useragent ?
|
|
config->useragent : CURL_NAME "/" CURL_VERSION);
|
|
}
|
|
|
|
result = http_setopts(config, curl, use_proto);
|
|
if(!result)
|
|
result = ftp_setopts(config, curl, use_proto);
|
|
if(result)
|
|
return result;
|
|
|
|
my_setopt_long(curl, CURLOPT_LOW_SPEED_LIMIT, config->low_speed_limit);
|
|
my_setopt_long(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
|
|
my_setopt_offt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, config->sendpersecond);
|
|
my_setopt_offt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, config->recvpersecond);
|
|
|
|
if(config->use_resume)
|
|
my_setopt_offt(curl, CURLOPT_RESUME_FROM_LARGE, config->resume_from);
|
|
else
|
|
my_setopt_offt(curl, CURLOPT_RESUME_FROM_LARGE, 0);
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_KEYPASSWD, config->key_passwd);
|
|
MY_SETOPT_STR(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
|
|
|
|
result = ssh_setopts(config, curl, use_proto);
|
|
if(setopt_bad(result))
|
|
return result;
|
|
|
|
if(feature_ssl) {
|
|
result = ssl_ca_setopts(config, curl);
|
|
if(!result)
|
|
result = ssl_setopts(config, curl);
|
|
if(setopt_bad(result))
|
|
return result;
|
|
}
|
|
|
|
if(config->path_as_is)
|
|
my_setopt_long(curl, CURLOPT_PATH_AS_IS, 1);
|
|
|
|
if(config->no_body || config->remote_time)
|
|
/* no body or use remote time */
|
|
my_setopt_long(curl, CURLOPT_FILETIME, 1);
|
|
|
|
my_setopt_long(curl, CURLOPT_CRLF, config->crlf);
|
|
my_setopt_slist(curl, CURLOPT_QUOTE, config->quote);
|
|
my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote);
|
|
my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote);
|
|
|
|
my_setopt_enum(curl, CURLOPT_TIMECONDITION, config->timecond);
|
|
my_setopt_offt(curl, CURLOPT_TIMEVALUE_LARGE, config->condtime);
|
|
MY_SETOPT_STR(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
|
|
customrequest_helper(config->httpreq, config->customrequest);
|
|
my_setopt_ptr(curl, CURLOPT_STDERR, tool_stderr);
|
|
MY_SETOPT_STR(curl, CURLOPT_INTERFACE, config->iface);
|
|
progressbarinit(&per->progressbar, config);
|
|
MY_SETOPT_STR(curl, CURLOPT_DNS_SERVERS, config->dns_servers);
|
|
MY_SETOPT_STR(curl, CURLOPT_DNS_INTERFACE, config->dns_interface);
|
|
MY_SETOPT_STR(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
|
|
MY_SETOPT_STR(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
|
|
my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
|
|
my_setopt_long(curl, CURLOPT_CONNECTTIMEOUT_MS, config->connecttimeout_ms);
|
|
MY_SETOPT_STR(curl, CURLOPT_DOH_URL, config->doh_url);
|
|
my_setopt_long(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
|
|
(config->ftp_create_dirs ?
|
|
CURLFTP_CREATE_DIR_RETRY : CURLFTP_CREATE_DIR_NONE));
|
|
my_setopt_offt(curl, CURLOPT_MAXFILESIZE_LARGE, config->max_filesize);
|
|
my_setopt_long(curl, CURLOPT_IPRESOLVE, config->ip_version);
|
|
if(config->socks5_gssapi_nec)
|
|
my_setopt_long(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1);
|
|
if(config->socks5_auth)
|
|
my_setopt_bitmask(curl, CURLOPT_SOCKS5_AUTH, config->socks5_auth);
|
|
MY_SETOPT_STR(curl, CURLOPT_SERVICE_NAME, config->service_name);
|
|
my_setopt_long(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
|
|
|
|
if(config->localport) {
|
|
my_setopt_long(curl, CURLOPT_LOCALPORT, config->localport);
|
|
my_setopt_long(curl, CURLOPT_LOCALPORTRANGE, config->localportrange);
|
|
}
|
|
|
|
if(config->raw) {
|
|
my_setopt_long(curl, CURLOPT_HTTP_CONTENT_DECODING, 0);
|
|
my_setopt_long(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0);
|
|
}
|
|
|
|
tcp_setopts(config, curl);
|
|
|
|
if(config->tftp_blksize && proto_tftp)
|
|
my_setopt_long(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_MAIL_FROM, config->mail_from);
|
|
my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
|
|
my_setopt_long(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS,
|
|
config->mail_rcpt_allowfails);
|
|
if(config->create_file_mode)
|
|
my_setopt_long(curl, CURLOPT_NEW_FILE_PERMS, config->create_file_mode);
|
|
|
|
if(config->proto_present)
|
|
MY_SETOPT_STR(curl, CURLOPT_PROTOCOLS_STR, config->proto_str);
|
|
if(config->proto_redir_present)
|
|
MY_SETOPT_STR(curl, CURLOPT_REDIR_PROTOCOLS_STR, config->proto_redir_str);
|
|
|
|
my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve);
|
|
my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to);
|
|
|
|
if(feature_tls_srp) {
|
|
result = tls_srp_setopts(config, curl);
|
|
if(setopt_bad(result))
|
|
return result;
|
|
}
|
|
|
|
if(config->gssapi_delegation)
|
|
my_setopt_long(curl, CURLOPT_GSSAPI_DELEGATION, config->gssapi_delegation);
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
|
|
MY_SETOPT_STR(curl, CURLOPT_SASL_AUTHZID, config->sasl_authzid);
|
|
my_setopt_long(curl, CURLOPT_SASL_IR, config->sasl_ir);
|
|
|
|
if(config->unix_socket_path) {
|
|
if(config->abstract_unix_socket)
|
|
MY_SETOPT_STR(curl, CURLOPT_ABSTRACT_UNIX_SOCKET,
|
|
config->unix_socket_path);
|
|
else
|
|
MY_SETOPT_STR(curl, CURLOPT_UNIX_SOCKET_PATH,
|
|
config->unix_socket_path);
|
|
}
|
|
|
|
MY_SETOPT_STR(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default);
|
|
my_setopt_long(curl, CURLOPT_TFTP_NO_OPTIONS,
|
|
config->tftp_no_options && proto_tftp);
|
|
|
|
if(config->happy_eyeballs_timeout_ms != CURL_HET_DEFAULT)
|
|
my_setopt_long(curl, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
|
|
config->happy_eyeballs_timeout_ms);
|
|
|
|
my_setopt_long(curl, CURLOPT_DISALLOW_USERNAME_IN_URL,
|
|
config->disallow_username_in_url);
|
|
|
|
if(config->ip_tos > 0 || config->vlan_priority > 0) {
|
|
#if defined(IP_TOS) || defined(IPV6_TCLASS) || defined(SO_PRIORITY)
|
|
my_setopt_ptr(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
|
|
my_setopt_ptr(curl, CURLOPT_SOCKOPTDATA, config);
|
|
#else
|
|
if(config->ip_tos > 0) {
|
|
errorf("Type of service is not supported in this build.");
|
|
result = CURLE_NOT_BUILT_IN;
|
|
}
|
|
if(config->vlan_priority > 0) {
|
|
errorf("VLAN priority is not supported in this build.");
|
|
result = CURLE_NOT_BUILT_IN;
|
|
}
|
|
#endif
|
|
}
|
|
my_setopt_long(curl, CURLOPT_UPLOAD_FLAGS, config->upload_flags);
|
|
return result;
|
|
}
|