quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

config2setopts.c (36699B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 #include "tool_setup.h"
     25 
     26 #include "tool_cfgable.h"
     27 #include "tool_setopt.h"
     28 #include "tool_findfile.h"
     29 #include "tool_msgs.h"
     30 #include "tool_libinfo.h"
     31 #include "tool_cb_soc.h"
     32 #include "tool_operate.h"
     33 #include "config2setopts.h"
     34 #include "tool_ipfs.h"
     35 #include "tool_cb_wrt.h"
     36 #include "tool_cb_rea.h"
     37 #include "tool_cb_see.h"
     38 #include "tool_cb_dbg.h"
     39 #include "tool_helpers.h"
     40 
     41 #define BUFFER_SIZE 102400L
     42 
     43 /* When doing serial transfers, we use a single fixed error area */
     44 static char global_errorbuffer[CURL_ERROR_SIZE];
     45 
     46 #ifdef IP_TOS
     47 static int get_address_family(curl_socket_t sockfd)
     48 {
     49   struct sockaddr addr;
     50   curl_socklen_t addrlen = sizeof(addr);
     51   memset(&addr, 0, sizeof(addr));
     52   if(getsockname(sockfd, (struct sockaddr *)&addr, &addrlen) == 0)
     53     return addr.sa_family;
     54   return AF_UNSPEC;
     55 }
     56 #endif
     57 
     58 #ifndef SOL_IP
     59 #  define SOL_IP IPPROTO_IP
     60 #endif
     61 
     62 #if defined(IP_TOS) || defined(IPV6_TCLASS) || defined(SO_PRIORITY)
     63 static int sockopt_callback(void *clientp, curl_socket_t curlfd,
     64                             curlsocktype purpose)
     65 {
     66   struct OperationConfig *config = (struct OperationConfig *)clientp;
     67   if(purpose != CURLSOCKTYPE_IPCXN)
     68     return CURL_SOCKOPT_OK;
     69   (void)config;
     70   (void)curlfd;
     71 #if defined(IP_TOS) || defined(IPV6_TCLASS)
     72   if(config->ip_tos > 0) {
     73     int tos = (int)config->ip_tos;
     74     int result = 0;
     75     switch(get_address_family(curlfd)) {
     76     case AF_INET:
     77 #ifdef IP_TOS
     78       result = setsockopt(curlfd, SOL_IP, IP_TOS, (void *)&tos, sizeof(tos));
     79 #endif
     80       break;
     81 #if defined(IPV6_TCLASS) && defined(AF_INET6)
     82     case AF_INET6:
     83       result = setsockopt(curlfd, IPPROTO_IPV6, IPV6_TCLASS,
     84                           (void *)&tos, sizeof(tos));
     85       break;
     86 #endif
     87     }
     88     if(result < 0) {
     89       int error = errno;
     90       warnf(config->global,
     91             "Setting type of service to %d failed with errno %d: %s;\n",
     92             tos, error, strerror(error));
     93     }
     94   }
     95 #endif
     96 #ifdef SO_PRIORITY
     97   if(config->vlan_priority > 0) {
     98     int priority = (int)config->vlan_priority;
     99     if(setsockopt(curlfd, SOL_SOCKET, SO_PRIORITY,
    100       (void *)&priority, sizeof(priority)) != 0) {
    101       int error = errno;
    102       warnf(config->global, "VLAN priority %d failed with errno %d: %s;\n",
    103             priority, error, strerror(error));
    104     }
    105   }
    106 #endif
    107   return CURL_SOCKOPT_OK;
    108 }
    109 #endif /* IP_TOD || IPV6_TCLASS || SO_PRIORITY */
    110 
    111 /* return current SSL backend name, chop off multissl */
    112 static char *ssl_backend(void)
    113 {
    114   static char ssl_ver[80] = "no ssl";
    115   static bool already = FALSE;
    116   if(!already) { /* if there is no existing version */
    117     const char *v = curl_version_info(CURLVERSION_NOW)->ssl_version;
    118     if(v)
    119       msnprintf(ssl_ver, sizeof(ssl_ver), "%.*s", (int) strcspn(v, " "), v);
    120     already = TRUE;
    121   }
    122   return ssl_ver;
    123 }
    124 
    125 /*
    126  * Possibly rewrite the URL for IPFS and return the protocol token for the
    127  * scheme used in the given URL.
    128  */
    129 static CURLcode url_proto_and_rewrite(char **url,
    130                                       struct OperationConfig *config,
    131                                       const char **scheme)
    132 {
    133   CURLcode result = CURLE_OK;
    134   CURLU *uh = curl_url();
    135   const char *proto = NULL;
    136   *scheme = NULL;
    137 
    138   DEBUGASSERT(url && *url);
    139   if(uh) {
    140     char *schemep = NULL;
    141     if(!curl_url_set(uh, CURLUPART_URL, *url,
    142                      CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME) &&
    143        !curl_url_get(uh, CURLUPART_SCHEME, &schemep,
    144                      CURLU_DEFAULT_SCHEME)) {
    145 #ifdef CURL_DISABLE_IPFS
    146       (void)config;
    147 #else
    148       if(curl_strequal(schemep, proto_ipfs) ||
    149          curl_strequal(schemep, proto_ipns)) {
    150         result = ipfs_url_rewrite(uh, schemep, url, config);
    151         /* short-circuit proto_token, we know it is ipfs or ipns */
    152         if(curl_strequal(schemep, proto_ipfs))
    153           proto = proto_ipfs;
    154         else if(curl_strequal(schemep, proto_ipns))
    155           proto = proto_ipns;
    156         if(result)
    157           config->synthetic_error = TRUE;
    158       }
    159       else
    160 #endif /* !CURL_DISABLE_IPFS */
    161         proto = proto_token(schemep);
    162 
    163       curl_free(schemep);
    164     }
    165     curl_url_cleanup(uh);
    166   }
    167   else
    168     result = CURLE_OUT_OF_MEMORY;
    169 
    170   *scheme = proto ? proto : "?"; /* Never match if not found. */
    171   return result;
    172 }
    173 
    174 static CURLcode ssh_setopts(struct OperationConfig *config, CURL *curl)
    175 {
    176   struct GlobalConfig *global = config->global;
    177   CURLcode result;
    178 
    179   /* SSH and SSL private key uses same command-line option */
    180   /* new in libcurl 7.16.1 */
    181   my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key);
    182   /* new in libcurl 7.16.1 */
    183   my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey);
    184 
    185   /* new in libcurl 7.17.1: SSH host key md5 checking allows us
    186      to fail if we are not talking to who we think we should */
    187   my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5,
    188                 config->hostpubmd5);
    189 
    190   /* new in libcurl 7.80.0: SSH host key sha256 checking allows us
    191      to fail if we are not talking to who we think we should */
    192   my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256,
    193                 config->hostpubsha256);
    194 
    195   /* new in libcurl 7.56.0 */
    196   if(config->ssh_compression)
    197     my_setopt_long(curl, CURLOPT_SSH_COMPRESSION, 1);
    198 
    199   if(!config->insecure_ok) {
    200     char *known = global->knownhosts;
    201 
    202     if(!known)
    203       known = findfile(".ssh/known_hosts", FALSE);
    204     if(known) {
    205       /* new in curl 7.19.6 */
    206       result = my_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, known);
    207       if(result) {
    208         global->knownhosts = NULL;
    209         curl_free(known);
    210         return result;
    211       }
    212       /* store it in global to avoid repeated checks */
    213       global->knownhosts = known;
    214     }
    215     else if(!config->hostpubmd5 && !config->hostpubsha256) {
    216       errorf(global, "Couldn't find a known_hosts file");
    217       return CURLE_FAILED_INIT;
    218     }
    219     else
    220       warnf(global, "Couldn't find a known_hosts file");
    221   }
    222   return CURLE_OK; /* ignore if SHA256 did not work */
    223 }
    224 
    225 #ifdef CURL_CA_EMBED
    226 #ifndef CURL_DECLARED_CURL_CA_EMBED
    227 #define CURL_DECLARED_CURL_CA_EMBED
    228 extern const unsigned char curl_ca_embed[];
    229 #endif
    230 #endif
    231 
    232 /* only called if libcurl supports TLS */
    233 static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl)
    234 {
    235   struct GlobalConfig *global = config->global;
    236   CURLcode result = CURLE_OK;
    237 
    238   if(config->cacert)
    239     my_setopt_str(curl, CURLOPT_CAINFO, config->cacert);
    240   if(config->proxy_cacert)
    241     my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert);
    242 
    243   if(config->capath) {
    244     result = my_setopt_str(curl, CURLOPT_CAPATH, config->capath);
    245     if(result)
    246       return result;
    247   }
    248   /* For the time being if --proxy-capath is not set then we use the
    249      --capath value for it, if any. See #1257 */
    250   if(config->proxy_capath || config->capath) {
    251     result = my_setopt_str(curl, CURLOPT_PROXY_CAPATH,
    252                            (config->proxy_capath ? config->proxy_capath :
    253                             config->capath));
    254     if((result == CURLE_NOT_BUILT_IN) ||
    255        (result == CURLE_UNKNOWN_OPTION)) {
    256       if(config->proxy_capath) {
    257         warnf(global, "ignoring %s, not supported by libcurl with %s",
    258               config->proxy_capath ? "--proxy-capath" : "--capath",
    259               ssl_backend());
    260       }
    261     }
    262     else if(result)
    263       return result;
    264   }
    265 
    266 #ifdef CURL_CA_EMBED
    267   if(!config->cacert && !config->capath) {
    268     struct curl_blob blob;
    269     blob.data = CURL_UNCONST(curl_ca_embed);
    270     blob.len = strlen((const char *)curl_ca_embed);
    271     blob.flags = CURL_BLOB_NOCOPY;
    272     notef(config->global,
    273           "Using embedded CA bundle (%zu bytes)",
    274           blob.len);
    275     result = curl_easy_setopt(curl, CURLOPT_CAINFO_BLOB, &blob);
    276     if(result == CURLE_NOT_BUILT_IN) {
    277       warnf(global, "ignoring %s, not supported by libcurl with %s",
    278             "embedded CA bundle", ssl_backend());
    279     }
    280   }
    281   if(!config->proxy_cacert && !config->proxy_capath) {
    282     struct curl_blob blob;
    283     blob.data = CURL_UNCONST(curl_ca_embed);
    284     blob.len = strlen((const char *)curl_ca_embed);
    285     blob.flags = CURL_BLOB_NOCOPY;
    286     notef(config->global,
    287           "Using embedded CA bundle, for proxies (%zu bytes)",
    288           blob.len);
    289     result = curl_easy_setopt(curl, CURLOPT_PROXY_CAINFO_BLOB, &blob);
    290     if(result == CURLE_NOT_BUILT_IN) {
    291       warnf(global, "ignoring %s, not supported by libcurl with %s",
    292             "embedded CA bundle", ssl_backend());
    293     }
    294   }
    295 #endif
    296 
    297   if(config->crlfile)
    298     my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile);
    299   if(config->proxy_crlfile)
    300     my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile);
    301   else if(config->crlfile) /* CURLOPT_PROXY_CRLFILE default is crlfile */
    302     my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->crlfile);
    303 
    304   if(config->pinnedpubkey) {
    305     result = my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY,
    306                            config->pinnedpubkey);
    307     if(result == CURLE_NOT_BUILT_IN)
    308       warnf(global, "ignoring %s, not supported by libcurl with %s",
    309             "--pinnedpubkey", ssl_backend());
    310   }
    311   if(config->proxy_pinnedpubkey) {
    312     result = my_setopt_str(curl, CURLOPT_PROXY_PINNEDPUBLICKEY,
    313                            config->proxy_pinnedpubkey);
    314     if(result == CURLE_NOT_BUILT_IN)
    315       warnf(global, "ignoring %s, not supported by libcurl with %s",
    316             "--proxy-pinnedpubkey", ssl_backend());
    317   }
    318 
    319   if(config->ssl_ec_curves)
    320     my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves);
    321 
    322   if(config->ssl_signature_algorithms)
    323     my_setopt_str(curl, CURLOPT_SSL_SIGNATURE_ALGORITHMS,
    324                   config->ssl_signature_algorithms);
    325 
    326   if(config->writeout)
    327     my_setopt_long(curl, CURLOPT_CERTINFO, 1);
    328 
    329   my_setopt_str(curl, CURLOPT_SSLCERT, config->cert);
    330   my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert);
    331   my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type);
    332   my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE,
    333                 config->proxy_cert_type);
    334   my_setopt_str(curl, CURLOPT_SSLKEY, config->key);
    335   my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key);
    336   my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type);
    337   my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE,
    338                 config->proxy_key_type);
    339 
    340   /* libcurl default is strict verifyhost -> 1L, verifypeer -> 1L */
    341   if(config->insecure_ok) {
    342     my_setopt_long(curl, CURLOPT_SSL_VERIFYPEER, 0);
    343     my_setopt_long(curl, CURLOPT_SSL_VERIFYHOST, 0);
    344   }
    345 
    346   if(config->doh_insecure_ok) {
    347     my_setopt_long(curl, CURLOPT_DOH_SSL_VERIFYPEER, 0);
    348     my_setopt_long(curl, CURLOPT_DOH_SSL_VERIFYHOST, 0);
    349   }
    350 
    351   if(config->proxy_insecure_ok) {
    352     my_setopt_long(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0);
    353     my_setopt_long(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0);
    354   }
    355 
    356   if(config->verifystatus)
    357     my_setopt_long(curl, CURLOPT_SSL_VERIFYSTATUS, 1);
    358 
    359   if(config->doh_verifystatus)
    360     my_setopt_long(curl, CURLOPT_DOH_SSL_VERIFYSTATUS, 1);
    361 
    362   my_setopt_SSLVERSION(curl, CURLOPT_SSLVERSION,
    363                        config->ssl_version | config->ssl_version_max);
    364   if(config->proxy)
    365     my_setopt_SSLVERSION(curl, CURLOPT_PROXY_SSLVERSION,
    366                          config->proxy_ssl_version);
    367 
    368   {
    369     long mask =
    370       (config->ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
    371       (config->ssl_allow_earlydata ? CURLSSLOPT_EARLYDATA : 0) |
    372       (config->ssl_no_revoke ? CURLSSLOPT_NO_REVOKE : 0) |
    373       (config->ssl_revoke_best_effort ? CURLSSLOPT_REVOKE_BEST_EFFORT : 0) |
    374       (config->native_ca_store ? CURLSSLOPT_NATIVE_CA : 0) |
    375       (config->ssl_auto_client_cert ? CURLSSLOPT_AUTO_CLIENT_CERT : 0);
    376 
    377     if(mask)
    378       my_setopt_bitmask(curl, CURLOPT_SSL_OPTIONS, mask);
    379   }
    380 
    381   {
    382     long mask =
    383       (config->proxy_ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) |
    384       (config->proxy_ssl_auto_client_cert ?
    385        CURLSSLOPT_AUTO_CLIENT_CERT : 0) |
    386       (config->proxy_native_ca_store ? CURLSSLOPT_NATIVE_CA : 0);
    387 
    388     if(mask)
    389       my_setopt_bitmask(curl, CURLOPT_PROXY_SSL_OPTIONS, mask);
    390   }
    391 
    392   if(config->cipher_list) {
    393     result = my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST,
    394                            config->cipher_list);
    395     if(result == CURLE_NOT_BUILT_IN)
    396       warnf(global, "ignoring %s, not supported by libcurl with %s",
    397             "--ciphers", ssl_backend());
    398   }
    399   if(config->proxy_cipher_list) {
    400     result = my_setopt_str(curl, CURLOPT_PROXY_SSL_CIPHER_LIST,
    401                            config->proxy_cipher_list);
    402     if(result == CURLE_NOT_BUILT_IN)
    403       warnf(global, "ignoring %s, not supported by libcurl with %s",
    404             "--proxy-ciphers", ssl_backend());
    405   }
    406   if(config->cipher13_list) {
    407     result = my_setopt_str(curl, CURLOPT_TLS13_CIPHERS,
    408                            config->cipher13_list);
    409     if(result == CURLE_NOT_BUILT_IN)
    410       warnf(global, "ignoring %s, not supported by libcurl with %s",
    411             "--tls13-ciphers", ssl_backend());
    412   }
    413   if(config->proxy_cipher13_list) {
    414     result = my_setopt_str(curl, CURLOPT_PROXY_TLS13_CIPHERS,
    415                            config->proxy_cipher13_list);
    416     if(result == CURLE_NOT_BUILT_IN)
    417       warnf(global, "ignoring %s, not supported by libcurl with %s",
    418             "--proxy-tls13-ciphers", ssl_backend());
    419   }
    420 
    421   /* curl 7.16.0 */
    422   if(config->disable_sessionid)
    423     /* disable it */
    424     my_setopt_long(curl, CURLOPT_SSL_SESSIONID_CACHE, 0);
    425 
    426   if(feature_ech) {
    427     /* only if enabled in libcurl */
    428     if(config->ech) /* only if set (optional) */
    429       my_setopt_str(curl, CURLOPT_ECH, config->ech);
    430     if(config->ech_public) /* only if set (optional) */
    431       my_setopt_str(curl, CURLOPT_ECH, config->ech_public);
    432     if(config->ech_config) /* only if set (optional) */
    433       my_setopt_str(curl, CURLOPT_ECH, config->ech_config);
    434   }
    435 
    436   /* new in curl 7.9.3 */
    437   if(config->engine) {
    438     result = my_setopt_str(curl, CURLOPT_SSLENGINE, config->engine);
    439     if(result)
    440       return result;
    441   }
    442 
    443   /* new in curl 7.15.5 */
    444   if(config->ftp_ssl_reqd)
    445     my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
    446 
    447   /* new in curl 7.11.0 */
    448   else if(config->ftp_ssl)
    449     my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
    450 
    451   /* new in curl 7.16.0 */
    452   else if(config->ftp_ssl_control)
    453     my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_CONTROL);
    454 
    455   if(config->noalpn)
    456     my_setopt_long(curl, CURLOPT_SSL_ENABLE_ALPN, 0);
    457 
    458   return CURLE_OK;
    459 }
    460 
    461 /* only called for HTTP transfers */
    462 static CURLcode http_setopts(struct OperationConfig *config,
    463                              CURL *curl)
    464 {
    465   long postRedir = 0;
    466 
    467   my_setopt_long(curl, CURLOPT_FOLLOWLOCATION,
    468                  config->followlocation);
    469   my_setopt_long(curl, CURLOPT_UNRESTRICTED_AUTH,
    470                  config->unrestricted_auth);
    471   my_setopt_str(curl, CURLOPT_AWS_SIGV4, config->aws_sigv4);
    472   my_setopt_long(curl, CURLOPT_AUTOREFERER, config->autoreferer);
    473 
    474   /* new in libcurl 7.36.0 */
    475   if(config->proxyheaders) {
    476     my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders);
    477     my_setopt_long(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE);
    478   }
    479 
    480   /* new in libcurl 7.5 */
    481   my_setopt_long(curl, CURLOPT_MAXREDIRS, config->maxredirs);
    482 
    483   if(config->httpversion)
    484     my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion);
    485 
    486   /* curl 7.19.1 (the 301 version existed in 7.18.2),
    487      303 was added in 7.26.0 */
    488   if(config->post301)
    489     postRedir |= CURL_REDIR_POST_301;
    490   if(config->post302)
    491     postRedir |= CURL_REDIR_POST_302;
    492   if(config->post303)
    493     postRedir |= CURL_REDIR_POST_303;
    494   my_setopt_long(curl, CURLOPT_POSTREDIR, postRedir);
    495 
    496   /* new in libcurl 7.21.6 */
    497   if(config->encoding)
    498     my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, "");
    499 
    500   /* new in libcurl 7.21.6 */
    501   if(config->tr_encoding)
    502     my_setopt_long(curl, CURLOPT_TRANSFER_ENCODING, 1);
    503   /* new in libcurl 7.64.0 */
    504   my_setopt_long(curl, CURLOPT_HTTP09_ALLOWED, config->http09_allowed);
    505 
    506   if(config->altsvc)
    507     my_setopt_str(curl, CURLOPT_ALTSVC, config->altsvc);
    508 
    509   if(config->hsts)
    510     my_setopt_str(curl, CURLOPT_HSTS, config->hsts);
    511 
    512   /* new in 7.47.0 */
    513   if(config->expect100timeout_ms > 0)
    514     my_setopt_long(curl, CURLOPT_EXPECT_100_TIMEOUT_MS,
    515                    config->expect100timeout_ms);
    516 
    517   return CURLE_OK;
    518 }
    519 
    520 static CURLcode cookie_setopts(struct OperationConfig *config, CURL *curl)
    521 {
    522   CURLcode result = CURLE_OK;
    523   if(config->cookies) {
    524     struct dynbuf cookies;
    525     struct curl_slist *cl;
    526 
    527     /* The maximum size needs to match MAX_NAME in cookie.h */
    528 #define MAX_COOKIE_LINE 8200
    529     curlx_dyn_init(&cookies, MAX_COOKIE_LINE);
    530     for(cl = config->cookies; cl; cl = cl->next) {
    531       if(cl == config->cookies)
    532         result = curlx_dyn_addf(&cookies, "%s", cl->data);
    533       else
    534         result = curlx_dyn_addf(&cookies, ";%s", cl->data);
    535 
    536       if(result) {
    537         warnf(config->global,
    538               "skipped provided cookie, the cookie header "
    539               "would go over %u bytes", MAX_COOKIE_LINE);
    540         return result;
    541       }
    542     }
    543 
    544     my_setopt_str(curl, CURLOPT_COOKIE, curlx_dyn_ptr(&cookies));
    545     curlx_dyn_free(&cookies);
    546   }
    547 
    548   if(config->cookiefiles) {
    549     struct curl_slist *cfl;
    550 
    551     for(cfl = config->cookiefiles; cfl; cfl = cfl->next)
    552       my_setopt_str(curl, CURLOPT_COOKIEFILE, cfl->data);
    553   }
    554 
    555   /* new in libcurl 7.9 */
    556   if(config->cookiejar)
    557     my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar);
    558 
    559   /* new in libcurl 7.9.7 */
    560   my_setopt_long(curl, CURLOPT_COOKIESESSION, config->cookiesession);
    561 
    562   return result;
    563 }
    564 
    565 static CURLcode tcp_setopts(struct OperationConfig *config,
    566                             CURL *curl)
    567 {
    568   if(!config->tcp_nodelay)
    569     my_setopt_long(curl, CURLOPT_TCP_NODELAY, 0);
    570 
    571   if(config->tcp_fastopen)
    572     my_setopt_long(curl, CURLOPT_TCP_FASTOPEN, 1);
    573 
    574   if(config->mptcp)
    575     my_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, tool_socket_open_mptcp_cb);
    576 
    577   /* curl 7.17.1 */
    578   if(!config->nokeepalive) {
    579     my_setopt_long(curl, CURLOPT_TCP_KEEPALIVE, 1);
    580     if(config->alivetime) {
    581       my_setopt_long(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime);
    582       my_setopt_long(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime);
    583     }
    584     if(config->alivecnt)
    585       my_setopt_long(curl, CURLOPT_TCP_KEEPCNT, config->alivecnt);
    586   }
    587   else
    588     my_setopt_long(curl, CURLOPT_TCP_KEEPALIVE, 0);
    589   return CURLE_OK;
    590 }
    591 
    592 static CURLcode ftp_setopts(struct OperationConfig *config, CURL *curl)
    593 {
    594   my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport);
    595 
    596   /* new in libcurl 7.9.2: */
    597   if(config->disable_epsv)
    598     /* disable it */
    599     my_setopt_long(curl, CURLOPT_FTP_USE_EPSV, 0);
    600 
    601   /* new in libcurl 7.10.5 */
    602   if(config->disable_eprt)
    603     /* disable it */
    604     my_setopt_long(curl, CURLOPT_FTP_USE_EPRT, 0);
    605 
    606   /* new in curl 7.16.1 */
    607   if(config->ftp_ssl_ccc)
    608     my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC, (long)config->ftp_ssl_ccc_mode);
    609 
    610   my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account);
    611 
    612   /* curl 7.14.2 */
    613   my_setopt_long(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip);
    614 
    615   /* curl 7.15.1 */
    616   my_setopt_long(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);
    617 
    618     /* curl 7.15.5 */
    619   my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER,
    620                 config->ftp_alternative_to_user);
    621 
    622   /* curl 7.20.x */
    623   if(config->ftp_pret)
    624     my_setopt_long(curl, CURLOPT_FTP_USE_PRET, 1);
    625 
    626   return CURLE_OK;
    627 }
    628 
    629 static void gen_trace_setopts(struct OperationConfig *config, CURL *curl)
    630 {
    631   if(config->global->tracetype != TRACE_NONE) {
    632     my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb);
    633     my_setopt(curl, CURLOPT_DEBUGDATA, config);
    634     my_setopt_long(curl, CURLOPT_VERBOSE, 1L);
    635   }
    636 }
    637 
    638 static void gen_cb_setopts(struct OperationConfig *config,
    639                            struct per_transfer *per,
    640                            CURL *curl)
    641 {
    642   struct GlobalConfig *global = config->global;
    643   (void) config;
    644   /* where to store */
    645   my_setopt(curl, CURLOPT_WRITEDATA, per);
    646   my_setopt(curl, CURLOPT_INTERLEAVEDATA, per);
    647 
    648   /* what call to write */
    649   my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb);
    650 
    651   /* what to read */
    652   my_setopt(curl, CURLOPT_READDATA, per);
    653   my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb);
    654 
    655   /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what
    656      CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */
    657   my_setopt(curl, CURLOPT_SEEKDATA, per);
    658   my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb);
    659 
    660   if((global->progressmode == CURL_PROGRESS_BAR) &&
    661      !global->noprogress && !global->silent) {
    662     /* we want the alternative style, then we have to implement it
    663        ourselves! */
    664     my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb);
    665     my_setopt(curl, CURLOPT_XFERINFODATA, per);
    666   }
    667   else if(per->uploadfile && !strcmp(per->uploadfile, ".")) {
    668     /* when reading from stdin in non-blocking mode, we use the progress
    669        function to unpause a busy read */
    670     my_setopt_long(curl, CURLOPT_NOPROGRESS, 0);
    671     my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_readbusy_cb);
    672     my_setopt(curl, CURLOPT_XFERINFODATA, per);
    673   }
    674 
    675   my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb);
    676   my_setopt(curl, CURLOPT_HEADERDATA, per);
    677 }
    678 
    679 static CURLcode proxy_setopts(struct OperationConfig *config, CURL *curl)
    680 {
    681   if(config->proxy) {
    682     CURLcode result = my_setopt_str(curl, CURLOPT_PROXY, config->proxy);
    683 
    684     if(result) {
    685       errorf(config->global, "proxy support is disabled in this libcurl");
    686       config->synthetic_error = TRUE;
    687       return CURLE_NOT_BUILT_IN;
    688     }
    689   }
    690 
    691   /* new in libcurl 7.5 */
    692   if(config->proxy)
    693     my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver);
    694 
    695   my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
    696 
    697   /* new in libcurl 7.3 */
    698   my_setopt_long(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel);
    699 
    700   /* new in libcurl 7.52.0 */
    701   if(config->preproxy)
    702     my_setopt_str(curl, CURLOPT_PRE_PROXY, config->preproxy);
    703 
    704   /* new in libcurl 7.10.6 */
    705   if(config->proxyanyauth)
    706     my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, (long)CURLAUTH_ANY);
    707   else if(config->proxynegotiate)
    708     my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_GSSNEGOTIATE);
    709   else if(config->proxyntlm)
    710     my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
    711   else if(config->proxydigest)
    712     my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
    713   else if(config->proxybasic)
    714     my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
    715 
    716   /* new in libcurl 7.19.4 */
    717   my_setopt_str(curl, CURLOPT_NOPROXY, config->noproxy);
    718 
    719   my_setopt_long(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS,
    720                  config->suppress_connect_headers);
    721 
    722   /* new in curl 7.43.0 */
    723   if(config->proxy_service_name)
    724     my_setopt_str(curl, CURLOPT_PROXY_SERVICE_NAME,
    725                   config->proxy_service_name);
    726 
    727   /* new in 7.60.0 */
    728   if(config->haproxy_protocol)
    729     my_setopt_long(curl, CURLOPT_HAPROXYPROTOCOL, 1);
    730 
    731   /* new in 8.2.0 */
    732   if(config->haproxy_clientip)
    733     my_setopt_str(curl, CURLOPT_HAPROXY_CLIENT_IP, config->haproxy_clientip);
    734 
    735   return CURLE_OK;
    736 }
    737 
    738 static void tls_srp_setopts(struct OperationConfig *config, CURL *curl)
    739 {
    740   if(config->tls_username)
    741     my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME, config->tls_username);
    742   if(config->tls_password)
    743     my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD, config->tls_password);
    744   if(config->tls_authtype)
    745     my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE, config->tls_authtype);
    746   if(config->proxy_tls_username)
    747     my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_USERNAME,
    748                   config->proxy_tls_username);
    749   if(config->proxy_tls_password)
    750     my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD,
    751                   config->proxy_tls_password);
    752   if(config->proxy_tls_authtype)
    753     my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_TYPE,
    754                   config->proxy_tls_authtype);
    755 }
    756 
    757 CURLcode config2setopts(struct OperationConfig *config,
    758                         struct per_transfer *per,
    759                         CURL *curl,
    760                         CURLSH *share)
    761 {
    762   struct GlobalConfig *global = config->global;
    763   const char *use_proto;
    764   CURLcode result = url_proto_and_rewrite(&per->url, config, &use_proto);
    765 
    766   /* Avoid having this setopt added to the --libcurl source output. */
    767   if(!result)
    768     result = curl_easy_setopt(curl, CURLOPT_SHARE, share);
    769   if(result)
    770     return result;
    771 
    772 #ifndef DEBUGBUILD
    773   /* On most modern OSes, exiting works thoroughly,
    774      we will clean everything up via exit(), so do not bother with
    775      slow cleanups. Crappy ones might need to skip this.
    776      Note: avoid having this setopt added to the --libcurl source
    777      output. */
    778   result = curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L);
    779   if(result)
    780     return result;
    781 #endif
    782 
    783   gen_trace_setopts(config, curl);
    784 
    785   {
    786 #ifdef DEBUGBUILD
    787     char *env = getenv("CURL_BUFFERSIZE");
    788     if(env) {
    789       curl_off_t num;
    790       const char *p = env;
    791       if(!curlx_str_number(&p, &num, LONG_MAX))
    792         my_setopt_long(curl, CURLOPT_BUFFERSIZE, (long)num);
    793     }
    794     else
    795 #endif
    796       if(config->recvpersecond && (config->recvpersecond < BUFFER_SIZE))
    797         /* use a smaller sized buffer for better sleeps */
    798         my_setopt_long(curl, CURLOPT_BUFFERSIZE, (long)config->recvpersecond);
    799       else
    800         my_setopt_long(curl, CURLOPT_BUFFERSIZE, BUFFER_SIZE);
    801   }
    802 
    803   my_setopt_str(curl, CURLOPT_URL, per->url);
    804   my_setopt_long(curl, CURLOPT_NOPROGRESS,
    805                  global->noprogress || global->silent);
    806   /* call after the line above. It may override CURLOPT_NOPROGRESS */
    807   gen_cb_setopts(config, per, curl);
    808 
    809   if(config->no_body)
    810     my_setopt_long(curl, CURLOPT_NOBODY, 1);
    811 
    812   if(config->oauth_bearer)
    813     my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->oauth_bearer);
    814 
    815   result = proxy_setopts(config, curl);
    816   if(result)
    817     return result;
    818 
    819   my_setopt_long(curl, CURLOPT_FAILONERROR, config->failonerror);
    820   my_setopt_str(curl, CURLOPT_REQUEST_TARGET, config->request_target);
    821   my_setopt_long(curl, CURLOPT_UPLOAD, !!per->uploadfile);
    822   my_setopt_long(curl, CURLOPT_DIRLISTONLY, config->dirlistonly);
    823   my_setopt_long(curl, CURLOPT_APPEND, config->ftp_append);
    824 
    825   if(config->netrc_opt)
    826     my_setopt_enum(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
    827   else if(config->netrc || config->netrc_file)
    828     my_setopt_enum(curl, CURLOPT_NETRC, CURL_NETRC_REQUIRED);
    829   else
    830     my_setopt_enum(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED);
    831 
    832   if(config->netrc_file)
    833     my_setopt_str(curl, CURLOPT_NETRC_FILE, config->netrc_file);
    834 
    835   my_setopt_long(curl, CURLOPT_TRANSFERTEXT, config->use_ascii);
    836   if(config->login_options)
    837     my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options);
    838   my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd);
    839   my_setopt_str(curl, CURLOPT_RANGE, config->range);
    840   if(!global->parallel) {
    841     per->errorbuffer = global_errorbuffer;
    842     my_setopt(curl, CURLOPT_ERRORBUFFER, global_errorbuffer);
    843   }
    844   my_setopt_long(curl, CURLOPT_TIMEOUT_MS, config->timeout_ms);
    845 
    846   switch(config->httpreq) {
    847   case TOOL_HTTPREQ_SIMPLEPOST:
    848     if(config->resume_from) {
    849       errorf(global, "cannot mix --continue-at with --data");
    850       result = CURLE_FAILED_INIT;
    851     }
    852     else {
    853       my_setopt_str(curl, CURLOPT_POSTFIELDS,
    854                     curlx_dyn_ptr(&config->postdata));
    855       my_setopt_offt(curl, CURLOPT_POSTFIELDSIZE_LARGE,
    856                      curlx_dyn_len(&config->postdata));
    857     }
    858     break;
    859   case TOOL_HTTPREQ_MIMEPOST:
    860     /* free previous remainders */
    861     curl_mime_free(config->mimepost);
    862     config->mimepost = NULL;
    863     if(config->resume_from) {
    864       errorf(global, "cannot mix --continue-at with --form");
    865       result = CURLE_FAILED_INIT;
    866     }
    867     else {
    868       result = tool2curlmime(curl, config->mimeroot, &config->mimepost);
    869       if(!result)
    870         my_setopt_mimepost(curl, CURLOPT_MIMEPOST, config->mimepost);
    871     }
    872     break;
    873   default:
    874     break;
    875   }
    876   if(result)
    877     return result;
    878 
    879   /* new in libcurl 7.81.0 */
    880   if(config->mime_options)
    881     my_setopt_long(curl, CURLOPT_MIME_OPTIONS, config->mime_options);
    882 
    883   /* new in libcurl 7.10.6 (default is Basic) */
    884   if(config->authtype)
    885     my_setopt_bitmask(curl, CURLOPT_HTTPAUTH, config->authtype);
    886 
    887   my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers);
    888 
    889   if(proto_http || proto_rtsp) {
    890     my_setopt_str(curl, CURLOPT_REFERER, config->referer);
    891     my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent);
    892   }
    893 
    894   if(use_proto == proto_http || use_proto == proto_https) {
    895     result = http_setopts(config, curl);
    896     if(!result)
    897       result = cookie_setopts(config, curl);
    898     if(result)
    899       return result;
    900   }
    901 
    902   if(use_proto == proto_ftp || use_proto == proto_ftps) {
    903     result = ftp_setopts(config, curl);
    904     if(result)
    905       return result;
    906   }
    907 
    908   my_setopt_long(curl, CURLOPT_LOW_SPEED_LIMIT, config->low_speed_limit);
    909   my_setopt_long(curl, CURLOPT_LOW_SPEED_TIME, config->low_speed_time);
    910   my_setopt_offt(curl, CURLOPT_MAX_SEND_SPEED_LARGE, config->sendpersecond);
    911   my_setopt_offt(curl, CURLOPT_MAX_RECV_SPEED_LARGE, config->recvpersecond);
    912 
    913   if(config->use_resume)
    914     my_setopt_offt(curl, CURLOPT_RESUME_FROM_LARGE, config->resume_from);
    915   else
    916     my_setopt_offt(curl, CURLOPT_RESUME_FROM_LARGE, 0);
    917 
    918   my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd);
    919   my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd);
    920 
    921   if(use_proto == proto_scp || use_proto == proto_sftp) {
    922     result = ssh_setopts(config, curl);
    923     if(result)
    924       return result;
    925   }
    926 
    927   if(feature_ssl) {
    928     result = ssl_setopts(config, curl);
    929     if(result)
    930       return result;
    931   }
    932 
    933   if(config->path_as_is)
    934     my_setopt_long(curl, CURLOPT_PATH_AS_IS, 1);
    935 
    936   if(config->no_body || config->remote_time) {
    937     /* no body or use remote time */
    938     my_setopt_long(curl, CURLOPT_FILETIME, 1);
    939   }
    940 
    941   my_setopt_long(curl, CURLOPT_CRLF, config->crlf);
    942   my_setopt_slist(curl, CURLOPT_QUOTE, config->quote);
    943   my_setopt_slist(curl, CURLOPT_POSTQUOTE, config->postquote);
    944   my_setopt_slist(curl, CURLOPT_PREQUOTE, config->prequote);
    945 
    946   my_setopt_enum(curl, CURLOPT_TIMECONDITION, config->timecond);
    947   my_setopt_offt(curl, CURLOPT_TIMEVALUE_LARGE, config->condtime);
    948   my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest);
    949   customrequest_helper(config, config->httpreq, config->customrequest);
    950   my_setopt(curl, CURLOPT_STDERR, tool_stderr);
    951 
    952   /* three new ones in libcurl 7.3: */
    953   my_setopt_str(curl, CURLOPT_INTERFACE, config->iface);
    954   my_setopt_str(curl, CURLOPT_KRBLEVEL, config->krblevel);
    955   progressbarinit(&per->progressbar, config);
    956 
    957   /* new in libcurl 7.24.0: */
    958   if(config->dns_servers)
    959     my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers);
    960 
    961   /* new in libcurl 7.33.0: */
    962   if(config->dns_interface)
    963     my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface);
    964   if(config->dns_ipv4_addr)
    965     my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr);
    966   if(config->dns_ipv6_addr)
    967     my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr);
    968 
    969   /* new in libcurl 7.6.2: */
    970   my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
    971 
    972   /* new in libcurl 7.7: */
    973   my_setopt_long(curl, CURLOPT_CONNECTTIMEOUT_MS, config->connecttimeout_ms);
    974 
    975   if(config->doh_url)
    976     my_setopt_str(curl, CURLOPT_DOH_URL, config->doh_url);
    977 
    978   /* new in curl 7.10.7, extended in 7.19.4. Modified to use
    979      CREATE_DIR_RETRY in 7.49.0 */
    980   my_setopt_long(curl, CURLOPT_FTP_CREATE_MISSING_DIRS,
    981                  (config->ftp_create_dirs ?
    982                   CURLFTP_CREATE_DIR_RETRY : CURLFTP_CREATE_DIR_NONE));
    983 
    984   /* new in curl 7.10.8 */
    985   if(config->max_filesize)
    986     my_setopt_offt(curl, CURLOPT_MAXFILESIZE_LARGE,
    987                    config->max_filesize);
    988 
    989   my_setopt_long(curl, CURLOPT_IPRESOLVE, config->ip_version);
    990 
    991   /* new in curl 7.19.4 */
    992   if(config->socks5_gssapi_nec)
    993     my_setopt_long(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1);
    994 
    995   /* new in curl 7.55.0 */
    996   if(config->socks5_auth)
    997     my_setopt_bitmask(curl, CURLOPT_SOCKS5_AUTH, config->socks5_auth);
    998 
    999   /* new in curl 7.43.0 */
   1000   if(config->service_name)
   1001     my_setopt_str(curl, CURLOPT_SERVICE_NAME, config->service_name);
   1002 
   1003   /* curl 7.13.0 */
   1004   my_setopt_long(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
   1005 
   1006   /* curl 7.15.2 */
   1007   if(config->localport) {
   1008     my_setopt_long(curl, CURLOPT_LOCALPORT, config->localport);
   1009     my_setopt_long(curl, CURLOPT_LOCALPORTRANGE, config->localportrange);
   1010   }
   1011 
   1012   /* curl 7.16.2 */
   1013   if(config->raw) {
   1014     my_setopt_long(curl, CURLOPT_HTTP_CONTENT_DECODING, 0);
   1015     my_setopt_long(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0);
   1016   }
   1017 
   1018   result = tcp_setopts(config, curl);
   1019   if(result)
   1020     return result;
   1021 
   1022   /* curl 7.20.0 */
   1023   if(config->tftp_blksize && proto_tftp)
   1024     my_setopt_long(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize);
   1025 
   1026   if(config->mail_from)
   1027     my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from);
   1028 
   1029   if(config->mail_rcpt)
   1030     my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt);
   1031 
   1032   /* curl 7.69.x */
   1033   my_setopt_long(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS,
   1034                  config->mail_rcpt_allowfails);
   1035 
   1036   if(config->create_file_mode)
   1037     my_setopt_long(curl, CURLOPT_NEW_FILE_PERMS, config->create_file_mode);
   1038 
   1039   if(config->proto_present)
   1040     my_setopt_str(curl, CURLOPT_PROTOCOLS_STR, config->proto_str);
   1041   if(config->proto_redir_present)
   1042     my_setopt_str(curl, CURLOPT_REDIR_PROTOCOLS_STR, config->proto_redir_str);
   1043 
   1044   if(config->resolve)
   1045     /* new in 7.21.3 */
   1046     my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve);
   1047 
   1048   if(config->connect_to)
   1049     /* new in 7.49.0 */
   1050     my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to);
   1051 
   1052   /* new in 7.21.4 */
   1053   if(feature_tls_srp)
   1054     tls_srp_setopts(config, curl);
   1055 
   1056   /* new in 7.22.0 */
   1057   if(config->gssapi_delegation)
   1058     my_setopt_long(curl, CURLOPT_GSSAPI_DELEGATION, config->gssapi_delegation);
   1059 
   1060   if(config->mail_auth)
   1061     my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth);
   1062 
   1063   /* new in 7.66.0 */
   1064   if(config->sasl_authzid)
   1065     my_setopt_str(curl, CURLOPT_SASL_AUTHZID, config->sasl_authzid);
   1066 
   1067   /* new in 7.31.0 */
   1068   if(config->sasl_ir)
   1069     my_setopt_long(curl, CURLOPT_SASL_IR, 1);
   1070 
   1071   /* new in 7.40.0, abstract support added in 7.53.0 */
   1072   if(config->unix_socket_path) {
   1073     if(config->abstract_unix_socket) {
   1074       my_setopt_str(curl, CURLOPT_ABSTRACT_UNIX_SOCKET,
   1075                     config->unix_socket_path);
   1076     }
   1077     else {
   1078       my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH,
   1079                     config->unix_socket_path);
   1080     }
   1081   }
   1082 
   1083   /* new in 7.45.0 */
   1084   if(config->proto_default)
   1085     my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default);
   1086 
   1087   /* new in 7.48.0 */
   1088   if(config->tftp_no_options && proto_tftp)
   1089     my_setopt_long(curl, CURLOPT_TFTP_NO_OPTIONS, 1);
   1090 
   1091   /* new in 7.59.0 */
   1092   if(config->happy_eyeballs_timeout_ms != CURL_HET_DEFAULT)
   1093     my_setopt_long(curl, CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS,
   1094                    config->happy_eyeballs_timeout_ms);
   1095 
   1096   if(config->disallow_username_in_url)
   1097     my_setopt_long(curl, CURLOPT_DISALLOW_USERNAME_IN_URL, 1);
   1098 
   1099   /* new in 8.9.0 */
   1100   if(config->ip_tos > 0 || config->vlan_priority > 0) {
   1101 #if defined(IP_TOS) || defined(IPV6_TCLASS) || defined(SO_PRIORITY)
   1102     my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
   1103     my_setopt(curl, CURLOPT_SOCKOPTDATA, config);
   1104 #else
   1105     if(config->ip_tos > 0) {
   1106       errorf(config->global,
   1107              "Type of service is not supported in this build.");
   1108       result = CURLE_NOT_BUILT_IN;
   1109     }
   1110     if(config->vlan_priority > 0) {
   1111       errorf(config->global,
   1112              "VLAN priority is not supported in this build.");
   1113       result = CURLE_NOT_BUILT_IN;
   1114     }
   1115 #endif
   1116   }
   1117   /* new in 8.13.0 */
   1118   if(config->upload_flags)
   1119     my_setopt_long(curl, CURLOPT_UPLOAD_FLAGS, config->upload_flags);
   1120   return result;
   1121 }