quickjs-tart

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

setopt.c (89634B)


      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 
     25 #include "curl_setup.h"
     26 
     27 #include <limits.h>
     28 
     29 #ifdef HAVE_NETINET_IN_H
     30 #include <netinet/in.h>
     31 #endif
     32 
     33 #ifdef HAVE_LINUX_TCP_H
     34 #include <linux/tcp.h>
     35 #elif defined(HAVE_NETINET_TCP_H)
     36 #include <netinet/tcp.h>
     37 #endif
     38 
     39 #include "urldata.h"
     40 #include "url.h"
     41 #include "progress.h"
     42 #include "content_encoding.h"
     43 #include "strcase.h"
     44 #include "share.h"
     45 #include "vtls/vtls.h"
     46 #include "curlx/warnless.h"
     47 #include "sendf.h"
     48 #include "hostip.h"
     49 #include "http2.h"
     50 #include "setopt.h"
     51 #include "multiif.h"
     52 #include "altsvc.h"
     53 #include "hsts.h"
     54 #include "tftp.h"
     55 #include "strdup.h"
     56 #include "escape.h"
     57 
     58 /* The last 3 #include files should be in this order */
     59 #include "curl_printf.h"
     60 #include "curl_memory.h"
     61 #include "memdebug.h"
     62 
     63 
     64 static CURLcode setopt_set_timeout_sec(timediff_t *ptimeout_ms, long secs)
     65 {
     66   if(secs < 0)
     67     return CURLE_BAD_FUNCTION_ARGUMENT;
     68 #if LONG_MAX > (TIMEDIFF_T_MAX/1000)
     69   if(secs > (TIMEDIFF_T_MAX/1000)) {
     70     *ptimeout_ms = TIMEDIFF_T_MAX;
     71     return CURLE_OK;
     72   }
     73 #endif
     74   *ptimeout_ms = (timediff_t)secs * 1000;
     75   return CURLE_OK;
     76 }
     77 
     78 static CURLcode setopt_set_timeout_ms(timediff_t *ptimeout_ms, long ms)
     79 {
     80   if(ms < 0)
     81     return CURLE_BAD_FUNCTION_ARGUMENT;
     82 #if LONG_MAX > TIMEDIFF_T_MAX
     83   if(ms > TIMEDIFF_T_MAX) {
     84     *ptimeout_ms = TIMEDIFF_T_MAX;
     85     return CURLE_OK;
     86   }
     87 #endif
     88   *ptimeout_ms = (timediff_t)ms;
     89   return CURLE_OK;
     90 }
     91 
     92 CURLcode Curl_setstropt(char **charp, const char *s)
     93 {
     94   /* Release the previous storage at `charp' and replace by a dynamic storage
     95      copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
     96 
     97   Curl_safefree(*charp);
     98 
     99   if(s) {
    100     if(strlen(s) > CURL_MAX_INPUT_LENGTH)
    101       return CURLE_BAD_FUNCTION_ARGUMENT;
    102 
    103     *charp = strdup(s);
    104     if(!*charp)
    105       return CURLE_OUT_OF_MEMORY;
    106   }
    107 
    108   return CURLE_OK;
    109 }
    110 
    111 CURLcode Curl_setblobopt(struct curl_blob **blobp,
    112                          const struct curl_blob *blob)
    113 {
    114   /* free the previous storage at `blobp' and replace by a dynamic storage
    115      copy of blob. If CURL_BLOB_COPY is set, the data is copied. */
    116 
    117   Curl_safefree(*blobp);
    118 
    119   if(blob) {
    120     struct curl_blob *nblob;
    121     if(blob->len > CURL_MAX_INPUT_LENGTH)
    122       return CURLE_BAD_FUNCTION_ARGUMENT;
    123     nblob = (struct curl_blob *)
    124       malloc(sizeof(struct curl_blob) +
    125              ((blob->flags & CURL_BLOB_COPY) ? blob->len : 0));
    126     if(!nblob)
    127       return CURLE_OUT_OF_MEMORY;
    128     *nblob = *blob;
    129     if(blob->flags & CURL_BLOB_COPY) {
    130       /* put the data after the blob struct in memory */
    131       nblob->data = (char *)nblob + sizeof(struct curl_blob);
    132       memcpy(nblob->data, blob->data, blob->len);
    133     }
    134 
    135     *blobp = nblob;
    136     return CURLE_OK;
    137   }
    138 
    139   return CURLE_OK;
    140 }
    141 
    142 static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
    143 {
    144   char *user = NULL;
    145   char *passwd = NULL;
    146 
    147   DEBUGASSERT(userp);
    148   DEBUGASSERT(passwdp);
    149 
    150   /* Parse the login details if specified. It not then we treat NULL as a hint
    151      to clear the existing data */
    152   if(option) {
    153     size_t len = strlen(option);
    154     CURLcode result;
    155     if(len > CURL_MAX_INPUT_LENGTH)
    156       return CURLE_BAD_FUNCTION_ARGUMENT;
    157 
    158     result = Curl_parse_login_details(option, len, &user, &passwd, NULL);
    159     if(result)
    160       return result;
    161   }
    162 
    163   free(*userp);
    164   *userp = user;
    165 
    166   free(*passwdp);
    167   *passwdp = passwd;
    168 
    169   return CURLE_OK;
    170 }
    171 
    172 static CURLcode setstropt_interface(char *option, char **devp,
    173                                     char **ifacep, char **hostp)
    174 {
    175   char *dev = NULL;
    176   char *iface = NULL;
    177   char *host = NULL;
    178   CURLcode result;
    179 
    180   DEBUGASSERT(devp);
    181   DEBUGASSERT(ifacep);
    182   DEBUGASSERT(hostp);
    183 
    184   if(option) {
    185     /* Parse the interface details if set, otherwise clear them all */
    186     result = Curl_parse_interface(option, &dev, &iface, &host);
    187     if(result)
    188       return result;
    189   }
    190   free(*devp);
    191   *devp = dev;
    192 
    193   free(*ifacep);
    194   *ifacep = iface;
    195 
    196   free(*hostp);
    197   *hostp = host;
    198 
    199   return CURLE_OK;
    200 }
    201 
    202 #define C_SSLVERSION_VALUE(x) (x & 0xffff)
    203 #define C_SSLVERSION_MAX_VALUE(x) ((unsigned long)x & 0xffff0000)
    204 
    205 static CURLcode protocol2num(const char *str, curl_prot_t *val)
    206 {
    207   /*
    208    * We are asked to cherry-pick protocols, so play it safe and disallow all
    209    * protocols to start with, and re-add the wanted ones back in.
    210    */
    211   *val = 0;
    212 
    213   if(!str)
    214     return CURLE_BAD_FUNCTION_ARGUMENT;
    215 
    216   if(curl_strequal(str, "all")) {
    217     *val = ~(curl_prot_t) 0;
    218     return CURLE_OK;
    219   }
    220 
    221   do {
    222     const char *token = str;
    223     size_t tlen;
    224 
    225     str = strchr(str, ',');
    226     tlen = str ? (size_t) (str - token) : strlen(token);
    227     if(tlen) {
    228       const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen);
    229 
    230       if(!h)
    231         return CURLE_UNSUPPORTED_PROTOCOL;
    232 
    233       *val |= h->protocol;
    234     }
    235   } while(str && str++);
    236 
    237   if(!*val)
    238     /* no protocol listed */
    239     return CURLE_BAD_FUNCTION_ARGUMENT;
    240   return CURLE_OK;
    241 }
    242 
    243 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_PROXY)
    244 static CURLcode httpauth(struct Curl_easy *data, bool proxy,
    245                          unsigned long auth)
    246 {
    247   if(auth != CURLAUTH_NONE) {
    248     int bitcheck = 0;
    249     bool authbits = FALSE;
    250     /* the DIGEST_IE bit is only used to set a special marker, for all the
    251        rest we need to handle it as normal DIGEST */
    252     bool iestyle = !!(auth & CURLAUTH_DIGEST_IE);
    253     if(proxy)
    254       data->state.authproxy.iestyle = iestyle;
    255     else
    256       data->state.authhost.iestyle = iestyle;
    257 
    258     if(auth & CURLAUTH_DIGEST_IE) {
    259       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
    260       auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
    261     }
    262 
    263     /* switch off bits we cannot support */
    264 #ifndef USE_NTLM
    265     auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
    266 #endif
    267 #ifndef USE_SPNEGO
    268     auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without GSS-API
    269                                     or SSPI */
    270 #endif
    271 
    272     /* check if any auth bit lower than CURLAUTH_ONLY is still set */
    273     while(bitcheck < 31) {
    274       if(auth & (1UL << bitcheck++)) {
    275         authbits = TRUE;
    276         break;
    277       }
    278     }
    279     if(!authbits)
    280       return CURLE_NOT_BUILT_IN; /* no supported types left! */
    281   }
    282   if(proxy)
    283     data->set.proxyauth = auth;
    284   else
    285     data->set.httpauth = auth;
    286   return CURLE_OK;
    287 }
    288 #endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_PROXY */
    289 
    290 #ifndef CURL_DISABLE_HTTP
    291 static CURLcode setopt_HTTP_VERSION(struct Curl_easy *data, long arg)
    292 {
    293   /*
    294    * This sets a requested HTTP version to be used. The value is one of
    295    * the listed enums in curl/curl.h.
    296    */
    297   switch(arg) {
    298   case CURL_HTTP_VERSION_NONE:
    299     /* accepted */
    300     break;
    301   case CURL_HTTP_VERSION_1_0:
    302   case CURL_HTTP_VERSION_1_1:
    303     /* accepted */
    304     break;
    305 #ifdef USE_HTTP2
    306   case CURL_HTTP_VERSION_2_0:
    307   case CURL_HTTP_VERSION_2TLS:
    308   case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE:
    309     /* accepted */
    310     break;
    311 #endif
    312 #ifdef USE_HTTP3
    313   case CURL_HTTP_VERSION_3:
    314   case CURL_HTTP_VERSION_3ONLY:
    315     /* accepted */
    316     break;
    317 #endif
    318   default:
    319     /* not accepted */
    320     if(arg < CURL_HTTP_VERSION_NONE)
    321       return CURLE_BAD_FUNCTION_ARGUMENT;
    322     return CURLE_UNSUPPORTED_PROTOCOL;
    323   }
    324   data->set.httpwant = (unsigned char)arg;
    325   return CURLE_OK;
    326 }
    327 #endif /* ! CURL_DISABLE_HTTP */
    328 
    329 #ifdef USE_SSL
    330 static CURLcode setopt_SSLVERSION(struct Curl_easy *data, CURLoption option,
    331                                   long arg)
    332 {
    333   /*
    334    * Set explicit SSL version to try to connect with, as some SSL
    335    * implementations are lame.
    336    */
    337   {
    338     long version, version_max;
    339     struct ssl_primary_config *primary = &data->set.ssl.primary;
    340 #ifndef CURL_DISABLE_PROXY
    341     if(option != CURLOPT_SSLVERSION)
    342       primary = &data->set.proxy_ssl.primary;
    343 #else
    344     if(option) {}
    345 #endif
    346     version = C_SSLVERSION_VALUE(arg);
    347     version_max = (long)C_SSLVERSION_MAX_VALUE(arg);
    348 
    349     if(version < CURL_SSLVERSION_DEFAULT ||
    350        version == CURL_SSLVERSION_SSLv2 ||
    351        version == CURL_SSLVERSION_SSLv3 ||
    352        version >= CURL_SSLVERSION_LAST ||
    353        version_max < CURL_SSLVERSION_MAX_NONE ||
    354        version_max >= CURL_SSLVERSION_MAX_LAST)
    355       return CURLE_BAD_FUNCTION_ARGUMENT;
    356 
    357     primary->version = (unsigned char)version;
    358     primary->version_max = (unsigned int)version_max;
    359   }
    360   return CURLE_OK;
    361 }
    362 #endif /* ! USE_SSL */
    363 
    364 #ifndef CURL_DISABLE_RTSP
    365 static CURLcode setopt_RTSP_REQUEST(struct Curl_easy *data, long arg)
    366 {
    367   /*
    368    * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
    369    * Would this be better if the RTSPREQ_* were just moved into here?
    370    */
    371   Curl_RtspReq rtspreq = RTSPREQ_NONE;
    372   switch(arg) {
    373   case CURL_RTSPREQ_OPTIONS:
    374     rtspreq = RTSPREQ_OPTIONS;
    375     break;
    376 
    377   case CURL_RTSPREQ_DESCRIBE:
    378     rtspreq = RTSPREQ_DESCRIBE;
    379     break;
    380 
    381   case CURL_RTSPREQ_ANNOUNCE:
    382     rtspreq = RTSPREQ_ANNOUNCE;
    383     break;
    384 
    385   case CURL_RTSPREQ_SETUP:
    386     rtspreq = RTSPREQ_SETUP;
    387     break;
    388 
    389   case CURL_RTSPREQ_PLAY:
    390     rtspreq = RTSPREQ_PLAY;
    391     break;
    392 
    393   case CURL_RTSPREQ_PAUSE:
    394     rtspreq = RTSPREQ_PAUSE;
    395     break;
    396 
    397   case CURL_RTSPREQ_TEARDOWN:
    398     rtspreq = RTSPREQ_TEARDOWN;
    399     break;
    400 
    401   case CURL_RTSPREQ_GET_PARAMETER:
    402     rtspreq = RTSPREQ_GET_PARAMETER;
    403     break;
    404 
    405   case CURL_RTSPREQ_SET_PARAMETER:
    406     rtspreq = RTSPREQ_SET_PARAMETER;
    407     break;
    408 
    409   case CURL_RTSPREQ_RECORD:
    410     rtspreq = RTSPREQ_RECORD;
    411     break;
    412 
    413   case CURL_RTSPREQ_RECEIVE:
    414     rtspreq = RTSPREQ_RECEIVE;
    415     break;
    416   default:
    417     return CURLE_BAD_FUNCTION_ARGUMENT;
    418   }
    419 
    420   data->set.rtspreq = rtspreq;
    421   return CURLE_OK;
    422 }
    423 #endif /* ! CURL_DISABLE_RTSP */
    424 
    425 #ifdef USE_SSL
    426 static void set_ssl_options(struct ssl_config_data *ssl,
    427                             struct ssl_primary_config *config,
    428                             long arg)
    429 {
    430   config->ssl_options = (unsigned char)(arg & 0xff);
    431   ssl->enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
    432   ssl->no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
    433   ssl->no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
    434   ssl->revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
    435   ssl->native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
    436   ssl->auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
    437   ssl->earlydata = !!(arg & CURLSSLOPT_EARLYDATA);
    438 }
    439 #endif
    440 
    441 static CURLcode setopt_long(struct Curl_easy *data, CURLoption option,
    442                             long arg)
    443 {
    444   bool enabled = (0 != arg);
    445   unsigned long uarg = (unsigned long)arg;
    446   switch(option) {
    447   case CURLOPT_DNS_CACHE_TIMEOUT:
    448     if(arg < -1)
    449       return CURLE_BAD_FUNCTION_ARGUMENT;
    450     else if(arg > INT_MAX)
    451       arg = INT_MAX;
    452 
    453     data->set.dns_cache_timeout = (int)arg;
    454     break;
    455   case CURLOPT_CA_CACHE_TIMEOUT:
    456     if(Curl_ssl_supports(data, SSLSUPP_CA_CACHE)) {
    457       if(arg < -1)
    458         return CURLE_BAD_FUNCTION_ARGUMENT;
    459       else if(arg > INT_MAX)
    460         arg = INT_MAX;
    461 
    462       data->set.general_ssl.ca_cache_timeout = (int)arg;
    463     }
    464     else
    465       return CURLE_NOT_BUILT_IN;
    466     break;
    467   case CURLOPT_MAXCONNECTS:
    468     /*
    469      * Set the absolute number of maximum simultaneous alive connection that
    470      * libcurl is allowed to have.
    471      */
    472     if(uarg > UINT_MAX)
    473       return CURLE_BAD_FUNCTION_ARGUMENT;
    474     data->set.maxconnects = (unsigned int)uarg;
    475     break;
    476   case CURLOPT_FORBID_REUSE:
    477     /*
    478      * When this transfer is done, it must not be left to be reused by a
    479      * subsequent transfer but shall be closed immediately.
    480      */
    481     data->set.reuse_forbid = enabled;
    482     break;
    483   case CURLOPT_FRESH_CONNECT:
    484     /*
    485      * This transfer shall not use a previously cached connection but
    486      * should be made with a fresh new connect!
    487      */
    488     data->set.reuse_fresh = enabled;
    489     break;
    490   case CURLOPT_VERBOSE:
    491     /*
    492      * Verbose means infof() calls that give a lot of information about
    493      * the connection and transfer procedures as well as internal choices.
    494      */
    495     data->set.verbose = enabled;
    496     break;
    497   case CURLOPT_HEADER:
    498     /*
    499      * Set to include the header in the general data output stream.
    500      */
    501     data->set.include_header = enabled;
    502     break;
    503   case CURLOPT_NOPROGRESS:
    504     /*
    505      * Shut off the internal supported progress meter
    506      */
    507     data->progress.hide = enabled;
    508     break;
    509   case CURLOPT_NOBODY:
    510     /*
    511      * Do not include the body part in the output data stream.
    512      */
    513     data->set.opt_no_body = enabled;
    514 #ifndef CURL_DISABLE_HTTP
    515     if(data->set.opt_no_body)
    516       /* in HTTP lingo, no body means using the HEAD request... */
    517       data->set.method = HTTPREQ_HEAD;
    518     else if(data->set.method == HTTPREQ_HEAD)
    519       data->set.method = HTTPREQ_GET;
    520 #endif
    521     break;
    522   case CURLOPT_FAILONERROR:
    523     /*
    524      * Do not output the >=400 error code HTML-page, but instead only
    525      * return error.
    526      */
    527     data->set.http_fail_on_error = enabled;
    528     break;
    529   case CURLOPT_KEEP_SENDING_ON_ERROR:
    530     data->set.http_keep_sending_on_error = enabled;
    531     break;
    532   case CURLOPT_UPLOAD:
    533   case CURLOPT_PUT:
    534     /*
    535      * We want to sent data to the remote host. If this is HTTP, that equals
    536      * using the PUT request.
    537      */
    538     if(arg) {
    539       /* If this is HTTP, PUT is what's needed to "upload" */
    540       data->set.method = HTTPREQ_PUT;
    541       data->set.opt_no_body = FALSE; /* this is implied */
    542     }
    543     else
    544       /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
    545          then this can be changed to HEAD later on) */
    546       data->set.method = HTTPREQ_GET;
    547     break;
    548   case CURLOPT_FILETIME:
    549     /*
    550      * Try to get the file time of the remote document. The time will
    551      * later (possibly) become available using curl_easy_getinfo().
    552      */
    553     data->set.get_filetime = enabled;
    554     break;
    555   case CURLOPT_SERVER_RESPONSE_TIMEOUT:
    556     /*
    557      * Option that specifies how quickly a server response must be obtained
    558      * before it is considered failure. For pingpong protocols.
    559      */
    560     return setopt_set_timeout_sec(&data->set.server_response_timeout, arg);
    561 
    562   case CURLOPT_SERVER_RESPONSE_TIMEOUT_MS:
    563     /*
    564      * Option that specifies how quickly a server response must be obtained
    565      * before it is considered failure. For pingpong protocols.
    566      */
    567     return setopt_set_timeout_ms(&data->set.server_response_timeout, arg);
    568 
    569 #ifndef CURL_DISABLE_TFTP
    570   case CURLOPT_TFTP_NO_OPTIONS:
    571     /*
    572      * Option that prevents libcurl from sending TFTP option requests to the
    573      * server.
    574      */
    575     data->set.tftp_no_options = enabled;
    576     break;
    577   case CURLOPT_TFTP_BLKSIZE:
    578     /*
    579      * TFTP option that specifies the block size to use for data transmission.
    580      */
    581     if(arg < TFTP_BLKSIZE_MIN)
    582       arg = 512;
    583     else if(arg > TFTP_BLKSIZE_MAX)
    584       arg = TFTP_BLKSIZE_MAX;
    585     data->set.tftp_blksize = arg;
    586     break;
    587 #endif
    588 #ifndef CURL_DISABLE_NETRC
    589   case CURLOPT_NETRC:
    590     /*
    591      * Parse the $HOME/.netrc file
    592      */
    593     if((arg < CURL_NETRC_IGNORED) || (arg >= CURL_NETRC_LAST))
    594       return CURLE_BAD_FUNCTION_ARGUMENT;
    595     data->set.use_netrc = (unsigned char)arg;
    596     break;
    597 #endif
    598   case CURLOPT_TRANSFERTEXT:
    599     /*
    600      * This option was previously named 'FTPASCII'. Renamed to work with
    601      * more protocols than merely FTP.
    602      *
    603      * Transfer using ASCII (instead of BINARY).
    604      */
    605     data->set.prefer_ascii = enabled;
    606     break;
    607   case CURLOPT_TIMECONDITION:
    608     /*
    609      * Set HTTP time condition. This must be one of the defines in the
    610      * curl/curl.h header file.
    611      */
    612     if((arg < CURL_TIMECOND_NONE) || (arg >= CURL_TIMECOND_LAST))
    613       return CURLE_BAD_FUNCTION_ARGUMENT;
    614     data->set.timecondition = (unsigned char)arg;
    615     break;
    616   case CURLOPT_TIMEVALUE:
    617     /*
    618      * This is the value to compare with the remote document with the
    619      * method set with CURLOPT_TIMECONDITION
    620      */
    621     data->set.timevalue = (time_t)arg;
    622     break;
    623   case CURLOPT_SSLVERSION:
    624 #ifndef CURL_DISABLE_PROXY
    625   case CURLOPT_PROXY_SSLVERSION:
    626 #endif
    627 #ifdef USE_SSL
    628     return setopt_SSLVERSION(data, option, arg);
    629 #else
    630     return CURLE_NOT_BUILT_IN;
    631 #endif
    632 
    633   case CURLOPT_POSTFIELDSIZE:
    634     /*
    635      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
    636      * figure it out. Enables binary posts.
    637      */
    638     if(arg < -1)
    639       return CURLE_BAD_FUNCTION_ARGUMENT;
    640 
    641     if(data->set.postfieldsize < arg &&
    642        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
    643       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
    644       Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
    645       data->set.postfields = NULL;
    646     }
    647 
    648     data->set.postfieldsize = arg;
    649     break;
    650 #ifndef CURL_DISABLE_HTTP
    651 #if !defined(CURL_DISABLE_COOKIES)
    652   case CURLOPT_COOKIESESSION:
    653     /*
    654      * Set this option to TRUE to start a new "cookie session". It will
    655      * prevent the forthcoming read-cookies-from-file actions to accept
    656      * cookies that are marked as being session cookies, as they belong to a
    657      * previous session.
    658      */
    659     data->set.cookiesession = enabled;
    660     break;
    661 #endif
    662   case CURLOPT_AUTOREFERER:
    663     /*
    664      * Switch on automatic referer that gets set if curl follows locations.
    665      */
    666     data->set.http_auto_referer = enabled;
    667     break;
    668 
    669   case CURLOPT_TRANSFER_ENCODING:
    670     data->set.http_transfer_encoding = enabled;
    671     break;
    672 
    673   case CURLOPT_FOLLOWLOCATION:
    674     /*
    675      * Follow Location: header hints on an HTTP-server.
    676      */
    677     if(uarg > 3)
    678       return CURLE_BAD_FUNCTION_ARGUMENT;
    679     data->set.http_follow_mode = (unsigned char)uarg;
    680     break;
    681 
    682   case CURLOPT_UNRESTRICTED_AUTH:
    683     /*
    684      * Send authentication (user+password) when following locations, even when
    685      * hostname changed.
    686      */
    687     data->set.allow_auth_to_other_hosts = enabled;
    688     break;
    689 
    690   case CURLOPT_MAXREDIRS:
    691     /*
    692      * The maximum amount of hops you allow curl to follow Location:
    693      * headers. This should mostly be used to detect never-ending loops.
    694      */
    695     if(arg < -1)
    696       return CURLE_BAD_FUNCTION_ARGUMENT;
    697     data->set.maxredirs = arg;
    698     break;
    699 
    700   case CURLOPT_POSTREDIR:
    701     /*
    702      * Set the behavior of POST when redirecting
    703      * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
    704      * CURL_REDIR_POST_301 - POST is kept as POST after 301
    705      * CURL_REDIR_POST_302 - POST is kept as POST after 302
    706      * CURL_REDIR_POST_303 - POST is kept as POST after 303
    707      * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
    708      * other - POST is kept as POST after 301 and 302
    709      */
    710     if(arg < CURL_REDIR_GET_ALL)
    711       /* no return error on too high numbers since the bitmask could be
    712          extended in a future */
    713       return CURLE_BAD_FUNCTION_ARGUMENT;
    714     data->set.keep_post = arg & CURL_REDIR_POST_ALL;
    715     break;
    716 
    717   case CURLOPT_POST:
    718     /* Does this option serve a purpose anymore? Yes it does, when
    719        CURLOPT_POSTFIELDS is not used and the POST data is read off the
    720        callback! */
    721     if(arg) {
    722       data->set.method = HTTPREQ_POST;
    723       data->set.opt_no_body = FALSE; /* this is implied */
    724     }
    725     else
    726       data->set.method = HTTPREQ_GET;
    727     break;
    728   case CURLOPT_HEADEROPT:
    729     /*
    730      * Set header option.
    731      */
    732     data->set.sep_headers = !!(arg & CURLHEADER_SEPARATE);
    733     break;
    734   case CURLOPT_HTTPAUTH:
    735     return httpauth(data, FALSE, uarg);
    736 
    737   case CURLOPT_HTTPGET:
    738     /*
    739      * Set to force us do HTTP GET
    740      */
    741     if(enabled) {
    742       data->set.method = HTTPREQ_GET;
    743       data->set.opt_no_body = FALSE; /* this is implied */
    744     }
    745     break;
    746 
    747   case CURLOPT_HTTP_VERSION:
    748     return setopt_HTTP_VERSION(data, arg);
    749 
    750   case CURLOPT_EXPECT_100_TIMEOUT_MS:
    751     /*
    752      * Time to wait for a response to an HTTP request containing an
    753      * Expect: 100-continue header before sending the data anyway.
    754      */
    755     if(arg < 0)
    756       return CURLE_BAD_FUNCTION_ARGUMENT;
    757     data->set.expect_100_timeout = arg;
    758     break;
    759 
    760   case CURLOPT_HTTP09_ALLOWED:
    761     data->set.http09_allowed = enabled;
    762     break;
    763 #endif /* ! CURL_DISABLE_HTTP */
    764 
    765 #ifndef CURL_DISABLE_MIME
    766   case CURLOPT_MIME_OPTIONS:
    767     data->set.mime_formescape = !!(arg & CURLMIMEOPT_FORMESCAPE);
    768     break;
    769 #endif
    770 #ifndef CURL_DISABLE_PROXY
    771   case CURLOPT_HTTPPROXYTUNNEL:
    772     /*
    773      * Tunnel operations through the proxy instead of normal proxy use
    774      */
    775     data->set.tunnel_thru_httpproxy = enabled;
    776     break;
    777 
    778   case CURLOPT_PROXYPORT:
    779     /*
    780      * Explicitly set HTTP proxy port number.
    781      */
    782     if((arg < 0) || (arg > 65535))
    783       return CURLE_BAD_FUNCTION_ARGUMENT;
    784     data->set.proxyport = (unsigned short)arg;
    785     break;
    786 
    787   case CURLOPT_PROXYAUTH:
    788     return httpauth(data, TRUE, uarg);
    789 
    790   case CURLOPT_PROXYTYPE:
    791     /*
    792      * Set proxy type.
    793      */
    794     if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
    795       return CURLE_BAD_FUNCTION_ARGUMENT;
    796     data->set.proxytype = (unsigned char)(curl_proxytype)arg;
    797     break;
    798 
    799   case CURLOPT_PROXY_TRANSFER_MODE:
    800     /*
    801      * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
    802      */
    803     if(uarg > 1)
    804       /* reserve other values for future use */
    805       return CURLE_BAD_FUNCTION_ARGUMENT;
    806     data->set.proxy_transfer_mode = (bool)uarg;
    807     break;
    808   case CURLOPT_SOCKS5_AUTH:
    809     if(uarg & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
    810       return CURLE_NOT_BUILT_IN;
    811     data->set.socks5auth = (unsigned char)uarg;
    812     break;
    813   case CURLOPT_HAPROXYPROTOCOL:
    814     /*
    815      * Set to send the HAProxy Proxy Protocol header
    816      */
    817     data->set.haproxyprotocol = enabled;
    818     break;
    819   case CURLOPT_PROXY_SSL_VERIFYPEER:
    820     /*
    821      * Enable peer SSL verifying for proxy.
    822      */
    823     data->set.proxy_ssl.primary.verifypeer = enabled;
    824 
    825     /* Update the current connection proxy_ssl_config. */
    826     Curl_ssl_conn_config_update(data, TRUE);
    827     break;
    828   case CURLOPT_PROXY_SSL_VERIFYHOST:
    829     /*
    830      * Enable verification of the hostname in the peer certificate for proxy
    831      */
    832     data->set.proxy_ssl.primary.verifyhost = enabled;
    833 
    834     /* Update the current connection proxy_ssl_config. */
    835     Curl_ssl_conn_config_update(data, TRUE);
    836     break;
    837 #endif /* ! CURL_DISABLE_PROXY */
    838 
    839 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
    840   case CURLOPT_SOCKS5_GSSAPI_NEC:
    841     /*
    842      * Set flag for NEC SOCK5 support
    843      */
    844     data->set.socks5_gssapi_nec = enabled;
    845     break;
    846 #endif
    847 #ifdef CURL_LIST_ONLY_PROTOCOL
    848   case CURLOPT_DIRLISTONLY:
    849     /*
    850      * An option that changes the command to one that asks for a list only, no
    851      * file info details. Used for FTP, POP3 and SFTP.
    852      */
    853     data->set.list_only = enabled;
    854     break;
    855 #endif
    856   case CURLOPT_APPEND:
    857     /*
    858      * We want to upload and append to an existing file. Used for FTP and
    859      * SFTP.
    860      */
    861     data->set.remote_append = enabled;
    862     break;
    863 
    864 #ifndef CURL_DISABLE_FTP
    865   case CURLOPT_FTP_FILEMETHOD:
    866     /*
    867      * How do access files over FTP.
    868      */
    869     if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST))
    870       return CURLE_BAD_FUNCTION_ARGUMENT;
    871     data->set.ftp_filemethod = (unsigned char)arg;
    872     break;
    873   case CURLOPT_FTP_USE_EPRT:
    874     data->set.ftp_use_eprt = enabled;
    875     break;
    876 
    877   case CURLOPT_FTP_USE_EPSV:
    878     data->set.ftp_use_epsv = enabled;
    879     break;
    880 
    881   case CURLOPT_FTP_USE_PRET:
    882     data->set.ftp_use_pret = enabled;
    883     break;
    884 
    885   case CURLOPT_FTP_SSL_CCC:
    886     if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST))
    887       return CURLE_BAD_FUNCTION_ARGUMENT;
    888     data->set.ftp_ccc = (unsigned char)arg;
    889     break;
    890 
    891   case CURLOPT_FTP_SKIP_PASV_IP:
    892     /*
    893      * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
    894      * bypass of the IP address in PASV responses.
    895      */
    896     data->set.ftp_skip_ip = enabled;
    897     break;
    898 
    899   case CURLOPT_FTPSSLAUTH:
    900     /*
    901      * Set a specific auth for FTP-SSL transfers.
    902      */
    903     if((arg < CURLFTPAUTH_DEFAULT) || (arg >= CURLFTPAUTH_LAST))
    904       return CURLE_BAD_FUNCTION_ARGUMENT;
    905     data->set.ftpsslauth = (unsigned char)(curl_ftpauth)arg;
    906     break;
    907   case CURLOPT_ACCEPTTIMEOUT_MS:
    908     /*
    909      * The maximum time for curl to wait for FTP server connect
    910      */
    911     return setopt_set_timeout_ms(&data->set.accepttimeout, arg);
    912 
    913   case CURLOPT_WILDCARDMATCH:
    914     data->set.wildcard_enabled = enabled;
    915     break;
    916 #endif /* ! CURL_DISABLE_FTP */
    917 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
    918   case CURLOPT_FTP_CREATE_MISSING_DIRS:
    919     /*
    920      * An FTP/SFTP option that modifies an upload to create missing
    921      * directories on the server.
    922      */
    923     /* reserve other values for future use */
    924     if((arg < CURLFTP_CREATE_DIR_NONE) || (arg > CURLFTP_CREATE_DIR_RETRY))
    925       return CURLE_BAD_FUNCTION_ARGUMENT;
    926     data->set.ftp_create_missing_dirs = (unsigned char)arg;
    927     break;
    928 #endif /* ! CURL_DISABLE_FTP || USE_SSH */
    929   case CURLOPT_INFILESIZE:
    930     /*
    931      * If known, this should inform curl about the file size of the
    932      * to-be-uploaded file.
    933      */
    934     if(arg < -1)
    935       return CURLE_BAD_FUNCTION_ARGUMENT;
    936     data->set.filesize = arg;
    937     break;
    938   case CURLOPT_LOW_SPEED_LIMIT:
    939     /*
    940      * The low speed limit that if transfers are below this for
    941      * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
    942      */
    943     if(arg < 0)
    944       return CURLE_BAD_FUNCTION_ARGUMENT;
    945     data->set.low_speed_limit = arg;
    946     break;
    947   case CURLOPT_LOW_SPEED_TIME:
    948     /*
    949      * The low speed time that if transfers are below the set
    950      * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
    951      */
    952     if(arg < 0)
    953       return CURLE_BAD_FUNCTION_ARGUMENT;
    954     data->set.low_speed_time = arg;
    955     break;
    956   case CURLOPT_PORT:
    957     /*
    958      * The port number to use when getting the URL. 0 disables it.
    959      */
    960     if((arg < 0) || (arg > 65535))
    961       return CURLE_BAD_FUNCTION_ARGUMENT;
    962     data->set.use_port = (unsigned short)arg;
    963     break;
    964   case CURLOPT_TIMEOUT:
    965     /*
    966      * The maximum time you allow curl to use for a single transfer
    967      * operation.
    968      */
    969     return setopt_set_timeout_sec(&data->set.timeout, arg);
    970 
    971   case CURLOPT_TIMEOUT_MS:
    972     return setopt_set_timeout_ms(&data->set.timeout, arg);
    973 
    974   case CURLOPT_CONNECTTIMEOUT:
    975     /*
    976      * The maximum time you allow curl to use to connect.
    977      */
    978     return setopt_set_timeout_sec(&data->set.connecttimeout, arg);
    979 
    980   case CURLOPT_CONNECTTIMEOUT_MS:
    981     return setopt_set_timeout_ms(&data->set.connecttimeout, arg);
    982 
    983   case CURLOPT_RESUME_FROM:
    984     /*
    985      * Resume transfer at the given file position
    986      */
    987     if(arg < -1)
    988       return CURLE_BAD_FUNCTION_ARGUMENT;
    989     data->set.set_resume_from = arg;
    990     break;
    991 
    992   case CURLOPT_CRLF:
    993     /*
    994      * Kludgy option to enable CRLF conversions. Subject for removal.
    995      */
    996     data->set.crlf = enabled;
    997     break;
    998 
    999 #ifndef CURL_DISABLE_BINDLOCAL
   1000   case CURLOPT_LOCALPORT:
   1001     /*
   1002      * Set what local port to bind the socket to when performing an operation.
   1003      */
   1004     if((arg < 0) || (arg > 65535))
   1005       return CURLE_BAD_FUNCTION_ARGUMENT;
   1006     data->set.localport = curlx_sltous(arg);
   1007     break;
   1008   case CURLOPT_LOCALPORTRANGE:
   1009     /*
   1010      * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
   1011      */
   1012     if((arg < 0) || (arg > 65535))
   1013       return CURLE_BAD_FUNCTION_ARGUMENT;
   1014     data->set.localportrange = curlx_sltous(arg);
   1015     break;
   1016 #endif
   1017 
   1018 #ifdef HAVE_GSSAPI
   1019   case CURLOPT_GSSAPI_DELEGATION:
   1020     /*
   1021      * GSS-API credential delegation bitmask
   1022      */
   1023     data->set.gssapi_delegation = (unsigned char)uarg&
   1024       (CURLGSSAPI_DELEGATION_POLICY_FLAG|CURLGSSAPI_DELEGATION_FLAG);
   1025     break;
   1026 #endif
   1027   case CURLOPT_SSL_VERIFYPEER:
   1028     /*
   1029      * Enable peer SSL verifying.
   1030      */
   1031     data->set.ssl.primary.verifypeer = enabled;
   1032 
   1033     /* Update the current connection ssl_config. */
   1034     Curl_ssl_conn_config_update(data, FALSE);
   1035     break;
   1036 #ifndef CURL_DISABLE_DOH
   1037   case CURLOPT_DOH_SSL_VERIFYPEER:
   1038     /*
   1039      * Enable peer SSL verifying for DoH.
   1040      */
   1041     data->set.doh_verifypeer = enabled;
   1042     break;
   1043   case CURLOPT_DOH_SSL_VERIFYHOST:
   1044     /*
   1045      * Enable verification of the hostname in the peer certificate for DoH
   1046      */
   1047     data->set.doh_verifyhost = enabled;
   1048     break;
   1049   case CURLOPT_DOH_SSL_VERIFYSTATUS:
   1050     /*
   1051      * Enable certificate status verifying for DoH.
   1052      */
   1053     if(!Curl_ssl_cert_status_request())
   1054       return CURLE_NOT_BUILT_IN;
   1055 
   1056     data->set.doh_verifystatus = enabled;
   1057     break;
   1058 #endif /* ! CURL_DISABLE_DOH */
   1059   case CURLOPT_SSL_VERIFYHOST:
   1060     /*
   1061      * Enable verification of the hostname in the peer certificate
   1062      */
   1063 
   1064     /* Obviously people are not reading documentation and too many thought
   1065        this argument took a boolean when it was not and misused it.
   1066        Treat 1 and 2 the same */
   1067     data->set.ssl.primary.verifyhost = enabled;
   1068 
   1069     /* Update the current connection ssl_config. */
   1070     Curl_ssl_conn_config_update(data, FALSE);
   1071     break;
   1072   case CURLOPT_SSL_VERIFYSTATUS:
   1073     /*
   1074      * Enable certificate status verifying.
   1075      */
   1076     if(!Curl_ssl_cert_status_request())
   1077       return CURLE_NOT_BUILT_IN;
   1078 
   1079     data->set.ssl.primary.verifystatus = enabled;
   1080 
   1081     /* Update the current connection ssl_config. */
   1082     Curl_ssl_conn_config_update(data, FALSE);
   1083     break;
   1084   case CURLOPT_SSL_FALSESTART:
   1085     /*
   1086      * No TLS backends support false start anymore.
   1087      */
   1088     return CURLE_NOT_BUILT_IN;
   1089   case CURLOPT_CERTINFO:
   1090 #ifdef USE_SSL
   1091     if(Curl_ssl_supports(data, SSLSUPP_CERTINFO))
   1092       data->set.ssl.certinfo = enabled;
   1093     else
   1094 #endif
   1095       return CURLE_NOT_BUILT_IN;
   1096     break;
   1097   case CURLOPT_BUFFERSIZE:
   1098     /*
   1099      * The application kindly asks for a differently sized receive buffer.
   1100      * If it seems reasonable, we will use it.
   1101      */
   1102     if(arg > READBUFFER_MAX)
   1103       arg = READBUFFER_MAX;
   1104     else if(arg < 1)
   1105       arg = READBUFFER_SIZE;
   1106     else if(arg < READBUFFER_MIN)
   1107       arg = READBUFFER_MIN;
   1108 
   1109     data->set.buffer_size = (unsigned int)arg;
   1110     break;
   1111 
   1112   case CURLOPT_UPLOAD_BUFFERSIZE:
   1113     /*
   1114      * The application kindly asks for a differently sized upload buffer.
   1115      * Cap it to sensible.
   1116      */
   1117     if(arg > UPLOADBUFFER_MAX)
   1118       arg = UPLOADBUFFER_MAX;
   1119     else if(arg < UPLOADBUFFER_MIN)
   1120       arg = UPLOADBUFFER_MIN;
   1121 
   1122     data->set.upload_buffer_size = (unsigned int)arg;
   1123     break;
   1124 
   1125   case CURLOPT_NOSIGNAL:
   1126     /*
   1127      * The application asks not to set any signal() or alarm() handlers,
   1128      * even when using a timeout.
   1129      */
   1130     data->set.no_signal = enabled;
   1131     break;
   1132   case CURLOPT_MAXFILESIZE:
   1133     /*
   1134      * Set the maximum size of a file to download.
   1135      */
   1136     if(arg < 0)
   1137       return CURLE_BAD_FUNCTION_ARGUMENT;
   1138     data->set.max_filesize = arg;
   1139     break;
   1140 
   1141 #ifdef USE_SSL
   1142   case CURLOPT_USE_SSL:
   1143     /*
   1144      * Make transfers attempt to use SSL/TLS.
   1145      */
   1146     if((arg < CURLUSESSL_NONE) || (arg >= CURLUSESSL_LAST))
   1147       return CURLE_BAD_FUNCTION_ARGUMENT;
   1148     data->set.use_ssl = (unsigned char)arg;
   1149     break;
   1150   case CURLOPT_SSL_OPTIONS:
   1151     set_ssl_options(&data->set.ssl, &data->set.ssl.primary, arg);
   1152     break;
   1153 
   1154 #ifndef CURL_DISABLE_PROXY
   1155   case CURLOPT_PROXY_SSL_OPTIONS:
   1156     set_ssl_options(&data->set.proxy_ssl, &data->set.proxy_ssl.primary, arg);
   1157     break;
   1158 #endif
   1159 
   1160 #endif /* USE_SSL */
   1161   case CURLOPT_IPRESOLVE:
   1162     if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
   1163       return CURLE_BAD_FUNCTION_ARGUMENT;
   1164     data->set.ipver = (unsigned char) arg;
   1165     break;
   1166   case CURLOPT_TCP_NODELAY:
   1167     /*
   1168      * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
   1169      * algorithm
   1170      */
   1171     data->set.tcp_nodelay = enabled;
   1172     break;
   1173 
   1174   case CURLOPT_IGNORE_CONTENT_LENGTH:
   1175     data->set.ignorecl = enabled;
   1176     break;
   1177 
   1178   case CURLOPT_CONNECT_ONLY:
   1179     /*
   1180      * No data transfer.
   1181      * (1) - only do connection
   1182      * (2) - do first get request but get no content
   1183      */
   1184     if(arg > 2)
   1185       return CURLE_BAD_FUNCTION_ARGUMENT;
   1186     data->set.connect_only = !!arg;
   1187     data->set.connect_only_ws = (arg == 2);
   1188     break;
   1189 
   1190   case CURLOPT_SSL_SESSIONID_CACHE:
   1191     data->set.ssl.primary.cache_session = enabled;
   1192 #ifndef CURL_DISABLE_PROXY
   1193     data->set.proxy_ssl.primary.cache_session =
   1194       data->set.ssl.primary.cache_session;
   1195 #endif
   1196     break;
   1197 
   1198 #ifdef USE_SSH
   1199     /* we only include SSH options if explicitly built to support SSH */
   1200   case CURLOPT_SSH_AUTH_TYPES:
   1201     data->set.ssh_auth_types = (int)arg;
   1202     break;
   1203   case CURLOPT_SSH_COMPRESSION:
   1204     data->set.ssh_compression = enabled;
   1205     break;
   1206 #endif
   1207 
   1208   case CURLOPT_HTTP_TRANSFER_DECODING:
   1209     /*
   1210      * disable libcurl transfer encoding is used
   1211      */
   1212     data->set.http_te_skip = !enabled; /* reversed */
   1213     break;
   1214 
   1215   case CURLOPT_HTTP_CONTENT_DECODING:
   1216     /*
   1217      * raw data passed to the application when content encoding is used
   1218      */
   1219     data->set.http_ce_skip = !enabled; /* reversed */
   1220     break;
   1221 
   1222 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
   1223   case CURLOPT_NEW_FILE_PERMS:
   1224     /*
   1225      * Uses these permissions instead of 0644
   1226      */
   1227     if((arg < 0) || (arg > 0777))
   1228       return CURLE_BAD_FUNCTION_ARGUMENT;
   1229     data->set.new_file_perms = (unsigned int)arg;
   1230     break;
   1231 #endif
   1232 #ifdef USE_SSH
   1233   case CURLOPT_NEW_DIRECTORY_PERMS:
   1234     /*
   1235      * Uses these permissions instead of 0755
   1236      */
   1237     if((arg < 0) || (arg > 0777))
   1238       return CURLE_BAD_FUNCTION_ARGUMENT;
   1239     data->set.new_directory_perms = (unsigned int)arg;
   1240     break;
   1241 #endif
   1242 #ifdef USE_IPV6
   1243   case CURLOPT_ADDRESS_SCOPE:
   1244     /*
   1245      * Use this scope id when using IPv6
   1246      * We always get longs when passed plain numericals so we should check
   1247      * that the value fits into an unsigned 32-bit integer.
   1248      */
   1249 #if SIZEOF_LONG > 4
   1250     if(uarg > UINT_MAX)
   1251       return CURLE_BAD_FUNCTION_ARGUMENT;
   1252 #endif
   1253     data->set.scope_id = (unsigned int)uarg;
   1254     break;
   1255 #endif
   1256   case CURLOPT_PROTOCOLS:
   1257     /* set the bitmask for the protocols that are allowed to be used for the
   1258        transfer, which thus helps the app which takes URLs from users or other
   1259        external inputs and want to restrict what protocol(s) to deal with.
   1260        Defaults to CURLPROTO_ALL. */
   1261     data->set.allowed_protocols = (curl_prot_t)arg;
   1262     break;
   1263 
   1264   case CURLOPT_REDIR_PROTOCOLS:
   1265     /* set the bitmask for the protocols that libcurl is allowed to follow to,
   1266        as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol
   1267        needs to be set in both bitmasks to be allowed to get redirected to. */
   1268     data->set.redir_protocols = (curl_prot_t)arg;
   1269     break;
   1270 
   1271 #ifndef CURL_DISABLE_SMTP
   1272   case CURLOPT_MAIL_RCPT_ALLOWFAILS:
   1273     /* allow RCPT TO command to fail for some recipients */
   1274     data->set.mail_rcpt_allowfails = enabled;
   1275     break;
   1276 #endif /* !CURL_DISABLE_SMTP */
   1277   case CURLOPT_SASL_IR:
   1278     /* Enable/disable SASL initial response */
   1279     data->set.sasl_ir = enabled;
   1280     break;
   1281 #ifndef CURL_DISABLE_RTSP
   1282   case CURLOPT_RTSP_REQUEST:
   1283     return setopt_RTSP_REQUEST(data, arg);
   1284   case CURLOPT_RTSP_CLIENT_CSEQ:
   1285     /*
   1286      * Set the CSEQ number to issue for the next RTSP request. Useful if the
   1287      * application is resuming a previously broken connection. The CSEQ
   1288      * will increment from this new number henceforth.
   1289      */
   1290     data->state.rtsp_next_client_CSeq = arg;
   1291     break;
   1292 
   1293   case CURLOPT_RTSP_SERVER_CSEQ:
   1294     /* Same as the above, but for server-initiated requests */
   1295     data->state.rtsp_next_server_CSeq = arg;
   1296     break;
   1297 
   1298 #endif /* ! CURL_DISABLE_RTSP */
   1299 
   1300   case CURLOPT_TCP_KEEPALIVE:
   1301     data->set.tcp_keepalive = enabled;
   1302     break;
   1303   case CURLOPT_TCP_KEEPIDLE:
   1304     if(arg < 0)
   1305       return CURLE_BAD_FUNCTION_ARGUMENT;
   1306     else if(arg > INT_MAX)
   1307       arg = INT_MAX;
   1308     data->set.tcp_keepidle = (int)arg;
   1309     break;
   1310   case CURLOPT_TCP_KEEPINTVL:
   1311     if(arg < 0)
   1312       return CURLE_BAD_FUNCTION_ARGUMENT;
   1313     else if(arg > INT_MAX)
   1314       arg = INT_MAX;
   1315     data->set.tcp_keepintvl = (int)arg;
   1316     break;
   1317   case CURLOPT_TCP_KEEPCNT:
   1318     if(arg < 0)
   1319       return CURLE_BAD_FUNCTION_ARGUMENT;
   1320     else if(arg > INT_MAX)
   1321       arg = INT_MAX;
   1322     data->set.tcp_keepcnt = (int)arg;
   1323     break;
   1324   case CURLOPT_TCP_FASTOPEN:
   1325 #if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) ||        \
   1326   defined(TCP_FASTOPEN_CONNECT)
   1327     data->set.tcp_fastopen = enabled;
   1328 #else
   1329     return CURLE_NOT_BUILT_IN;
   1330 #endif
   1331     break;
   1332   case CURLOPT_SSL_ENABLE_NPN:
   1333     break;
   1334   case CURLOPT_SSL_ENABLE_ALPN:
   1335     data->set.ssl_enable_alpn = enabled;
   1336     break;
   1337   case CURLOPT_PATH_AS_IS:
   1338     data->set.path_as_is = enabled;
   1339     break;
   1340   case CURLOPT_PIPEWAIT:
   1341     data->set.pipewait = enabled;
   1342     break;
   1343   case CURLOPT_STREAM_WEIGHT:
   1344 #if defined(USE_HTTP2) || defined(USE_HTTP3)
   1345     if((arg >= 1) && (arg <= 256))
   1346       data->set.priority.weight = (int)arg;
   1347     break;
   1348 #else
   1349     return CURLE_NOT_BUILT_IN;
   1350 #endif
   1351   case CURLOPT_SUPPRESS_CONNECT_HEADERS:
   1352     data->set.suppress_connect_headers = enabled;
   1353     break;
   1354   case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
   1355     return setopt_set_timeout_ms(&data->set.happy_eyeballs_timeout, arg);
   1356 
   1357 #ifndef CURL_DISABLE_SHUFFLE_DNS
   1358   case CURLOPT_DNS_SHUFFLE_ADDRESSES:
   1359     data->set.dns_shuffle_addresses = enabled;
   1360     break;
   1361 #endif
   1362   case CURLOPT_DISALLOW_USERNAME_IN_URL:
   1363     data->set.disallow_username_in_url = enabled;
   1364     break;
   1365 
   1366   case CURLOPT_UPKEEP_INTERVAL_MS:
   1367     if(arg < 0)
   1368       return CURLE_BAD_FUNCTION_ARGUMENT;
   1369     data->set.upkeep_interval_ms = arg;
   1370     break;
   1371   case CURLOPT_MAXAGE_CONN:
   1372     return setopt_set_timeout_sec(&data->set.conn_max_idle_ms, arg);
   1373 
   1374   case CURLOPT_MAXLIFETIME_CONN:
   1375     return setopt_set_timeout_sec(&data->set.conn_max_age_ms, arg);
   1376 
   1377 #ifndef CURL_DISABLE_HSTS
   1378   case CURLOPT_HSTS_CTRL:
   1379     if(arg & CURLHSTS_ENABLE) {
   1380       if(!data->hsts) {
   1381         data->hsts = Curl_hsts_init();
   1382         if(!data->hsts)
   1383           return CURLE_OUT_OF_MEMORY;
   1384       }
   1385     }
   1386     else
   1387       Curl_hsts_cleanup(&data->hsts);
   1388     break;
   1389 #endif /* ! CURL_DISABLE_HSTS */
   1390 #ifndef CURL_DISABLE_ALTSVC
   1391   case CURLOPT_ALTSVC_CTRL:
   1392     if(!arg) {
   1393       DEBUGF(infof(data, "bad CURLOPT_ALTSVC_CTRL input"));
   1394       return CURLE_BAD_FUNCTION_ARGUMENT;
   1395     }
   1396     if(!data->asi) {
   1397       data->asi = Curl_altsvc_init();
   1398       if(!data->asi)
   1399         return CURLE_OUT_OF_MEMORY;
   1400     }
   1401     return Curl_altsvc_ctrl(data->asi, arg);
   1402 #endif /* ! CURL_DISABLE_ALTSVC */
   1403 #ifndef CURL_DISABLE_WEBSOCKETS
   1404   case CURLOPT_WS_OPTIONS:
   1405     data->set.ws_raw_mode = (bool)(arg & CURLWS_RAW_MODE);
   1406     data->set.ws_no_auto_pong = (bool)(arg & CURLWS_NOAUTOPONG);
   1407     break;
   1408 #endif
   1409   case CURLOPT_QUICK_EXIT:
   1410     data->set.quick_exit = enabled;
   1411     break;
   1412   case CURLOPT_DNS_USE_GLOBAL_CACHE:
   1413     /* deprecated */
   1414     break;
   1415   case CURLOPT_SSLENGINE_DEFAULT:
   1416     /*
   1417      * flag to set engine as default.
   1418      */
   1419     Curl_safefree(data->set.str[STRING_SSL_ENGINE]);
   1420     return Curl_ssl_set_engine_default(data);
   1421   case CURLOPT_UPLOAD_FLAGS:
   1422     data->set.upload_flags = (unsigned char)arg;
   1423     break;
   1424   default:
   1425     /* unknown option */
   1426     return CURLE_UNKNOWN_OPTION;
   1427   }
   1428   return CURLE_OK;
   1429 }
   1430 
   1431 static CURLcode setopt_slist(struct Curl_easy *data, CURLoption option,
   1432                              struct curl_slist *slist)
   1433 {
   1434   CURLcode result = CURLE_OK;
   1435   switch(option) {
   1436 #ifndef CURL_DISABLE_PROXY
   1437   case CURLOPT_PROXYHEADER:
   1438     /*
   1439      * Set a list with proxy headers to use (or replace internals with)
   1440      *
   1441      * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
   1442      * long time we remain doing it this way until CURLOPT_PROXYHEADER is
   1443      * used. As soon as this option has been used, if set to anything but
   1444      * NULL, custom headers for proxies are only picked from this list.
   1445      *
   1446      * Set this option to NULL to restore the previous behavior.
   1447      */
   1448     data->set.proxyheaders = slist;
   1449     break;
   1450 #endif
   1451 #ifndef CURL_DISABLE_HTTP
   1452   case CURLOPT_HTTP200ALIASES:
   1453     /*
   1454      * Set a list of aliases for HTTP 200 in response header
   1455      */
   1456     data->set.http200aliases = slist;
   1457     break;
   1458 #endif
   1459 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
   1460   case CURLOPT_POSTQUOTE:
   1461     /*
   1462      * List of RAW FTP commands to use after a transfer
   1463      */
   1464     data->set.postquote = slist;
   1465     break;
   1466   case CURLOPT_PREQUOTE:
   1467     /*
   1468      * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
   1469      */
   1470     data->set.prequote = slist;
   1471     break;
   1472   case CURLOPT_QUOTE:
   1473     /*
   1474      * List of RAW FTP commands to use before a transfer
   1475      */
   1476     data->set.quote = slist;
   1477     break;
   1478 #endif
   1479   case CURLOPT_RESOLVE:
   1480     /*
   1481      * List of HOST:PORT:[addresses] strings to populate the DNS cache with
   1482      * Entries added this way will remain in the cache until explicitly
   1483      * removed or the handle is cleaned up.
   1484      *
   1485      * Prefix the HOST with plus sign (+) to have the entry expire just like
   1486      * automatically added entries.
   1487      *
   1488      * Prefix the HOST with dash (-) to _remove_ the entry from the cache.
   1489      *
   1490      * This API can remove any entry from the DNS cache, but only entries
   1491      * that are not actually in use right now will be pruned immediately.
   1492      */
   1493     data->set.resolve = slist;
   1494     data->state.resolve = data->set.resolve;
   1495     break;
   1496 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MIME)
   1497   case CURLOPT_HTTPHEADER:
   1498     /*
   1499      * Set a list with HTTP headers to use (or replace internals with)
   1500      */
   1501     data->set.headers = slist;
   1502     break;
   1503 #endif
   1504 #ifndef CURL_DISABLE_TELNET
   1505   case CURLOPT_TELNETOPTIONS:
   1506     /*
   1507      * Set a linked list of telnet options
   1508      */
   1509     data->set.telnet_options = slist;
   1510     break;
   1511 #endif
   1512 #ifndef CURL_DISABLE_SMTP
   1513   case CURLOPT_MAIL_RCPT:
   1514     /* Set the list of mail recipients */
   1515     data->set.mail_rcpt = slist;
   1516     break;
   1517 #endif
   1518   case CURLOPT_CONNECT_TO:
   1519     data->set.connect_to = slist;
   1520     break;
   1521   default:
   1522     return CURLE_UNKNOWN_OPTION;
   1523   }
   1524   return result;
   1525 }
   1526 
   1527 /* assorted pointer type arguments */
   1528 static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
   1529                                 va_list param)
   1530 {
   1531   CURLcode result = CURLE_OK;
   1532   switch(option) {
   1533 #ifndef CURL_DISABLE_HTTP
   1534 #ifndef CURL_DISABLE_FORM_API
   1535   case CURLOPT_HTTPPOST:
   1536     /*
   1537      * Set to make us do HTTP POST. Legacy API-style.
   1538      */
   1539     data->set.httppost = va_arg(param, struct curl_httppost *);
   1540     data->set.method = HTTPREQ_POST_FORM;
   1541     data->set.opt_no_body = FALSE; /* this is implied */
   1542     Curl_mime_cleanpart(data->state.formp);
   1543     Curl_safefree(data->state.formp);
   1544     data->state.mimepost = NULL;
   1545     break;
   1546 #endif /* ! CURL_DISABLE_FORM_API */
   1547 #endif /* ! CURL_DISABLE_HTTP */
   1548 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) ||       \
   1549     !defined(CURL_DISABLE_IMAP)
   1550 # ifndef CURL_DISABLE_MIME
   1551   case CURLOPT_MIMEPOST:
   1552     /*
   1553      * Set to make us do MIME POST
   1554      */
   1555     result = Curl_mime_set_subparts(&data->set.mimepost,
   1556                                     va_arg(param, curl_mime *),
   1557                                     FALSE);
   1558     if(!result) {
   1559       data->set.method = HTTPREQ_POST_MIME;
   1560       data->set.opt_no_body = FALSE; /* this is implied */
   1561 #ifndef CURL_DISABLE_FORM_API
   1562       Curl_mime_cleanpart(data->state.formp);
   1563       Curl_safefree(data->state.formp);
   1564       data->state.mimepost = NULL;
   1565 #endif
   1566     }
   1567     break;
   1568 #endif /* ! CURL_DISABLE_MIME */
   1569 #endif /* ! disabled HTTP, SMTP or IMAP */
   1570   case CURLOPT_STDERR:
   1571     /*
   1572      * Set to a FILE * that should receive all error writes. This
   1573      * defaults to stderr for normal operations.
   1574      */
   1575     data->set.err = va_arg(param, FILE *);
   1576     if(!data->set.err)
   1577       data->set.err = stderr;
   1578     break;
   1579   case CURLOPT_SHARE:
   1580   {
   1581     struct Curl_share *set = va_arg(param, struct Curl_share *);
   1582 
   1583     /* disconnect from old share, if any */
   1584     if(data->share) {
   1585       Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
   1586 
   1587 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
   1588       if(data->share->cookies == data->cookies)
   1589         data->cookies = NULL;
   1590 #endif
   1591 
   1592 #ifndef CURL_DISABLE_HSTS
   1593       if(data->share->hsts == data->hsts)
   1594         data->hsts = NULL;
   1595 #endif
   1596 #ifdef USE_LIBPSL
   1597       if(data->psl == &data->share->psl)
   1598         data->psl = data->multi ? &data->multi->psl : NULL;
   1599 #endif
   1600       if(data->share->specifier & (1 << CURL_LOCK_DATA_DNS)) {
   1601         Curl_resolv_unlink(data, &data->state.dns[0]);
   1602         Curl_resolv_unlink(data, &data->state.dns[1]);
   1603       }
   1604 
   1605       data->share->dirty--;
   1606 
   1607       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
   1608       data->share = NULL;
   1609     }
   1610 
   1611     if(GOOD_SHARE_HANDLE(set))
   1612       /* use new share if it set */
   1613       data->share = set;
   1614     if(data->share) {
   1615 
   1616       Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
   1617 
   1618       data->share->dirty++;
   1619 
   1620 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
   1621       if(data->share->cookies) {
   1622         /* use shared cookie list, first free own one if any */
   1623         Curl_cookie_cleanup(data->cookies);
   1624         /* enable cookies since we now use a share that uses cookies! */
   1625         data->cookies = data->share->cookies;
   1626       }
   1627 #endif   /* CURL_DISABLE_HTTP */
   1628 #ifndef CURL_DISABLE_HSTS
   1629       if(data->share->hsts) {
   1630         /* first free the private one if any */
   1631         Curl_hsts_cleanup(&data->hsts);
   1632         data->hsts = data->share->hsts;
   1633       }
   1634 #endif
   1635 #ifdef USE_LIBPSL
   1636       if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL))
   1637         data->psl = &data->share->psl;
   1638 #endif
   1639 
   1640       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
   1641     }
   1642     /* check for host cache not needed,
   1643      * it will be done by curl_easy_perform */
   1644   }
   1645   break;
   1646 
   1647 #ifdef USE_HTTP2
   1648   case CURLOPT_STREAM_DEPENDS:
   1649   case CURLOPT_STREAM_DEPENDS_E: {
   1650     struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
   1651     if(!dep || GOOD_EASY_HANDLE(dep))
   1652       return Curl_data_priority_add_child(dep, data,
   1653                                           option == CURLOPT_STREAM_DEPENDS_E);
   1654     break;
   1655   }
   1656 #endif
   1657 
   1658   default:
   1659     return CURLE_UNKNOWN_OPTION;
   1660   }
   1661   return result;
   1662 }
   1663 
   1664 static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
   1665                             char *ptr)
   1666 {
   1667   CURLcode result = CURLE_OK;
   1668   switch(option) {
   1669   case CURLOPT_SSL_CIPHER_LIST:
   1670     if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST))
   1671       /* set a list of cipher we want to use in the SSL connection */
   1672       return Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST], ptr);
   1673     else
   1674       return CURLE_NOT_BUILT_IN;
   1675 #ifndef CURL_DISABLE_PROXY
   1676   case CURLOPT_PROXY_SSL_CIPHER_LIST:
   1677     if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST)) {
   1678       /* set a list of cipher we want to use in the SSL connection for proxy */
   1679       return Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
   1680                             ptr);
   1681     }
   1682     else
   1683       return CURLE_NOT_BUILT_IN;
   1684 #endif
   1685   case CURLOPT_TLS13_CIPHERS:
   1686     if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) {
   1687       /* set preferred list of TLS 1.3 cipher suites */
   1688       return Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST], ptr);
   1689     }
   1690     else
   1691       return CURLE_NOT_BUILT_IN;
   1692 #ifndef CURL_DISABLE_PROXY
   1693   case CURLOPT_PROXY_TLS13_CIPHERS:
   1694     if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES))
   1695       /* set preferred list of TLS 1.3 cipher suites for proxy */
   1696       return Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY],
   1697                             ptr);
   1698     else
   1699       return CURLE_NOT_BUILT_IN;
   1700 #endif
   1701   case CURLOPT_RANDOM_FILE:
   1702     break;
   1703   case CURLOPT_EGDSOCKET:
   1704     break;
   1705   case CURLOPT_REQUEST_TARGET:
   1706     return Curl_setstropt(&data->set.str[STRING_TARGET], ptr);
   1707 #ifndef CURL_DISABLE_NETRC
   1708   case CURLOPT_NETRC_FILE:
   1709     /*
   1710      * Use this file instead of the $HOME/.netrc file
   1711      */
   1712     return Curl_setstropt(&data->set.str[STRING_NETRC_FILE], ptr);
   1713 #endif
   1714 
   1715 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
   1716   case CURLOPT_COPYPOSTFIELDS:
   1717     /*
   1718      * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
   1719      * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
   1720      *  CURLOPT_COPYPOSTFIELDS and not altered later.
   1721      */
   1722     if(!ptr || data->set.postfieldsize == -1)
   1723       result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], ptr);
   1724     else {
   1725       if(data->set.postfieldsize < 0)
   1726         return CURLE_BAD_FUNCTION_ARGUMENT;
   1727 #if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T
   1728       /*
   1729        *  Check that requested length does not overflow the size_t type.
   1730        */
   1731       else if(data->set.postfieldsize > SIZE_T_MAX)
   1732         return CURLE_OUT_OF_MEMORY;
   1733 #endif
   1734       else {
   1735         /* Allocate even when size == 0. This satisfies the need of possible
   1736            later address compare to detect the COPYPOSTFIELDS mode, and to
   1737            mark that postfields is used rather than read function or form
   1738            data.
   1739         */
   1740         char *p = Curl_memdup0(ptr, (size_t)data->set.postfieldsize);
   1741         if(!p)
   1742           return CURLE_OUT_OF_MEMORY;
   1743         else {
   1744           free(data->set.str[STRING_COPYPOSTFIELDS]);
   1745           data->set.str[STRING_COPYPOSTFIELDS] = p;
   1746         }
   1747       }
   1748     }
   1749 
   1750     data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
   1751     data->set.method = HTTPREQ_POST;
   1752     break;
   1753 
   1754   case CURLOPT_POSTFIELDS:
   1755     /*
   1756      * Like above, but use static data instead of copying it.
   1757      */
   1758     data->set.postfields = ptr;
   1759     /* Release old copied data. */
   1760     Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
   1761     data->set.method = HTTPREQ_POST;
   1762     break;
   1763 #endif /* ! CURL_DISABLE_HTTP || ! CURL_DISABLE_MQTT */
   1764 
   1765 #ifndef CURL_DISABLE_HTTP
   1766   case CURLOPT_ACCEPT_ENCODING:
   1767     /*
   1768      * String to use at the value of Accept-Encoding header.
   1769      *
   1770      * If the encoding is set to "" we use an Accept-Encoding header that
   1771      * encompasses all the encodings we support.
   1772      * If the encoding is set to NULL we do not send an Accept-Encoding header
   1773      * and ignore an received Content-Encoding header.
   1774      *
   1775      */
   1776     if(ptr && !*ptr) {
   1777       char all[256];
   1778       Curl_all_content_encodings(all, sizeof(all));
   1779       return Curl_setstropt(&data->set.str[STRING_ENCODING], all);
   1780     }
   1781     return Curl_setstropt(&data->set.str[STRING_ENCODING], ptr);
   1782 
   1783 #if !defined(CURL_DISABLE_AWS)
   1784   case CURLOPT_AWS_SIGV4:
   1785     /*
   1786      * String that is merged to some authentication
   1787      * parameters are used by the algorithm.
   1788      */
   1789     result = Curl_setstropt(&data->set.str[STRING_AWS_SIGV4], ptr);
   1790     /*
   1791      * Basic been set by default it need to be unset here
   1792      */
   1793     if(data->set.str[STRING_AWS_SIGV4])
   1794       data->set.httpauth = CURLAUTH_AWS_SIGV4;
   1795     break;
   1796 #endif
   1797   case CURLOPT_REFERER:
   1798     /*
   1799      * String to set in the HTTP Referer: field.
   1800      */
   1801     if(data->state.referer_alloc) {
   1802       Curl_safefree(data->state.referer);
   1803       data->state.referer_alloc = FALSE;
   1804     }
   1805     result = Curl_setstropt(&data->set.str[STRING_SET_REFERER], ptr);
   1806     data->state.referer = data->set.str[STRING_SET_REFERER];
   1807     break;
   1808 
   1809   case CURLOPT_USERAGENT:
   1810     /*
   1811      * String to use in the HTTP User-Agent field
   1812      */
   1813     return Curl_setstropt(&data->set.str[STRING_USERAGENT], ptr);
   1814 
   1815 #if !defined(CURL_DISABLE_COOKIES)
   1816   case CURLOPT_COOKIE:
   1817     /*
   1818      * Cookie string to send to the remote server in the request.
   1819      */
   1820     return Curl_setstropt(&data->set.str[STRING_COOKIE], ptr);
   1821 
   1822   case CURLOPT_COOKIEFILE:
   1823     /*
   1824      * Set cookie file to read and parse. Can be used multiple times.
   1825      */
   1826     if(ptr) {
   1827       struct curl_slist *cl;
   1828       /* general protection against mistakes and abuse */
   1829       if(strlen(ptr) > CURL_MAX_INPUT_LENGTH)
   1830         return CURLE_BAD_FUNCTION_ARGUMENT;
   1831       /* append the cookie filename to the list of filenames, and deal with
   1832          them later */
   1833       cl = curl_slist_append(data->state.cookielist, ptr);
   1834       if(!cl) {
   1835         curl_slist_free_all(data->state.cookielist);
   1836         data->state.cookielist = NULL;
   1837         return CURLE_OUT_OF_MEMORY;
   1838       }
   1839       data->state.cookielist = cl; /* store the list for later use */
   1840     }
   1841     else {
   1842       /* clear the list of cookie files */
   1843       curl_slist_free_all(data->state.cookielist);
   1844       data->state.cookielist = NULL;
   1845 
   1846       if(!data->share || !data->share->cookies) {
   1847         /* throw away all existing cookies if this is not a shared cookie
   1848            container */
   1849         Curl_cookie_clearall(data->cookies);
   1850         Curl_cookie_cleanup(data->cookies);
   1851       }
   1852       /* disable the cookie engine */
   1853       data->cookies = NULL;
   1854     }
   1855     break;
   1856 
   1857   case CURLOPT_COOKIEJAR:
   1858     /*
   1859      * Set cookie filename to dump all cookies to when we are done.
   1860      */
   1861     result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR], ptr);
   1862     if(!result) {
   1863       /*
   1864        * Activate the cookie parser. This may or may not already
   1865        * have been made.
   1866        */
   1867       struct CookieInfo *newcookies =
   1868         Curl_cookie_init(data, NULL, data->cookies, data->set.cookiesession);
   1869       if(!newcookies)
   1870         result = CURLE_OUT_OF_MEMORY;
   1871       data->cookies = newcookies;
   1872     }
   1873     break;
   1874 
   1875   case CURLOPT_COOKIELIST:
   1876     if(!ptr)
   1877       break;
   1878 
   1879     if(curl_strequal(ptr, "ALL")) {
   1880       /* clear all cookies */
   1881       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
   1882       Curl_cookie_clearall(data->cookies);
   1883       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
   1884     }
   1885     else if(curl_strequal(ptr, "SESS")) {
   1886       /* clear session cookies */
   1887       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
   1888       Curl_cookie_clearsess(data->cookies);
   1889       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
   1890     }
   1891     else if(curl_strequal(ptr, "FLUSH")) {
   1892       /* flush cookies to file, takes care of the locking */
   1893       Curl_flush_cookies(data, FALSE);
   1894     }
   1895     else if(curl_strequal(ptr, "RELOAD")) {
   1896       /* reload cookies from file */
   1897       Curl_cookie_loadfiles(data);
   1898       break;
   1899     }
   1900     else {
   1901       if(!data->cookies) {
   1902         /* if cookie engine was not running, activate it */
   1903         data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
   1904         if(!data->cookies)
   1905           return CURLE_OUT_OF_MEMORY;
   1906       }
   1907 
   1908       /* general protection against mistakes and abuse */
   1909       if(strlen(ptr) > CURL_MAX_INPUT_LENGTH)
   1910         return CURLE_BAD_FUNCTION_ARGUMENT;
   1911 
   1912       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
   1913       if(checkprefix("Set-Cookie:", ptr))
   1914         /* HTTP Header format line */
   1915         Curl_cookie_add(data, data->cookies, TRUE, FALSE, ptr + 11, NULL,
   1916                         NULL, TRUE);
   1917       else
   1918         /* Netscape format line */
   1919         Curl_cookie_add(data, data->cookies, FALSE, FALSE, ptr, NULL,
   1920                         NULL, TRUE);
   1921       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
   1922     }
   1923     break;
   1924 #endif /* !CURL_DISABLE_COOKIES */
   1925 
   1926 #endif /* ! CURL_DISABLE_HTTP */
   1927 
   1928   case CURLOPT_CUSTOMREQUEST:
   1929     /*
   1930      * Set a custom string to use as request
   1931      */
   1932     return Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST], ptr);
   1933 
   1934     /* we do not set
   1935        data->set.method = HTTPREQ_CUSTOM;
   1936        here, we continue as if we were using the already set type
   1937        and this just changes the actual request keyword */
   1938 
   1939 #ifndef CURL_DISABLE_PROXY
   1940   case CURLOPT_PROXY:
   1941     /*
   1942      * Set proxy server:port to use as proxy.
   1943      *
   1944      * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
   1945      * we explicitly say that we do not want to use a proxy
   1946      * (even though there might be environment variables saying so).
   1947      *
   1948      * Setting it to NULL, means no proxy but allows the environment variables
   1949      * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
   1950      */
   1951     return Curl_setstropt(&data->set.str[STRING_PROXY], ptr);
   1952 
   1953   case CURLOPT_PRE_PROXY:
   1954     /*
   1955      * Set proxy server:port to use as SOCKS proxy.
   1956      *
   1957      * If the proxy is set to "" or NULL we explicitly say that we do not want
   1958      * to use the socks proxy.
   1959      */
   1960     return Curl_setstropt(&data->set.str[STRING_PRE_PROXY], ptr);
   1961 #endif   /* CURL_DISABLE_PROXY */
   1962 
   1963 #ifndef CURL_DISABLE_PROXY
   1964   case CURLOPT_SOCKS5_GSSAPI_SERVICE:
   1965   case CURLOPT_PROXY_SERVICE_NAME:
   1966     /*
   1967      * Set proxy authentication service name for Kerberos 5 and SPNEGO
   1968      */
   1969     return Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME], ptr);
   1970 #endif
   1971   case CURLOPT_SERVICE_NAME:
   1972     /*
   1973      * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
   1974      */
   1975     return Curl_setstropt(&data->set.str[STRING_SERVICE_NAME], ptr);
   1976 
   1977   case CURLOPT_HEADERDATA:
   1978     /*
   1979      * Custom pointer to pass the header write callback function
   1980      */
   1981     data->set.writeheader = ptr;
   1982     break;
   1983   case CURLOPT_READDATA:
   1984     /*
   1985      * FILE pointer to read the file to be uploaded from. Or possibly used as
   1986      * argument to the read callback.
   1987      */
   1988     data->set.in_set = ptr;
   1989     break;
   1990   case CURLOPT_WRITEDATA:
   1991     /*
   1992      * FILE pointer to write to. Or possibly used as argument to the write
   1993      * callback.
   1994      */
   1995     data->set.out = ptr;
   1996     break;
   1997   case CURLOPT_DEBUGDATA:
   1998     /*
   1999      * Set to a void * that should receive all error writes. This
   2000      * defaults to CURLOPT_STDERR for normal operations.
   2001      */
   2002     data->set.debugdata = ptr;
   2003     break;
   2004   case CURLOPT_PROGRESSDATA:
   2005     /*
   2006      * Custom client data to pass to the progress callback
   2007      */
   2008     data->set.progress_client = ptr;
   2009     break;
   2010   case CURLOPT_SEEKDATA:
   2011     /*
   2012      * Seek control callback. Might be NULL.
   2013      */
   2014     data->set.seek_client = ptr;
   2015     break;
   2016   case CURLOPT_IOCTLDATA:
   2017     /*
   2018      * I/O control data pointer. Might be NULL.
   2019      */
   2020     data->set.ioctl_client = ptr;
   2021     break;
   2022   case CURLOPT_SSL_CTX_DATA:
   2023     /*
   2024      * Set an SSL_CTX callback parameter pointer
   2025      */
   2026 #ifdef USE_SSL
   2027     if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX)) {
   2028       data->set.ssl.fsslctxp = ptr;
   2029       break;
   2030     }
   2031     else
   2032 #endif
   2033       return CURLE_NOT_BUILT_IN;
   2034   case CURLOPT_SOCKOPTDATA:
   2035     /*
   2036      * socket callback data pointer. Might be NULL.
   2037      */
   2038     data->set.sockopt_client = ptr;
   2039     break;
   2040   case CURLOPT_OPENSOCKETDATA:
   2041     /*
   2042      * socket callback data pointer. Might be NULL.
   2043      */
   2044     data->set.opensocket_client = ptr;
   2045     break;
   2046   case CURLOPT_RESOLVER_START_DATA:
   2047     /*
   2048      * resolver start callback data pointer. Might be NULL.
   2049      */
   2050     data->set.resolver_start_client = ptr;
   2051     break;
   2052   case CURLOPT_CLOSESOCKETDATA:
   2053     /*
   2054      * socket callback data pointer. Might be NULL.
   2055      */
   2056     data->set.closesocket_client = ptr;
   2057     break;
   2058   case CURLOPT_TRAILERDATA:
   2059 #ifndef CURL_DISABLE_HTTP
   2060     data->set.trailer_data = ptr;
   2061 #endif
   2062     break;
   2063   case CURLOPT_PREREQDATA:
   2064     data->set.prereq_userp = ptr;
   2065     break;
   2066 
   2067   case CURLOPT_ERRORBUFFER:
   2068     /*
   2069      * Error buffer provided by the caller to get the human readable error
   2070      * string in.
   2071      */
   2072     data->set.errorbuffer = ptr;
   2073     break;
   2074 
   2075 #ifndef CURL_DISABLE_FTP
   2076   case CURLOPT_FTPPORT:
   2077     /*
   2078      * Use FTP PORT, this also specifies which IP address to use
   2079      */
   2080     result = Curl_setstropt(&data->set.str[STRING_FTPPORT], ptr);
   2081     data->set.ftp_use_port = !!(data->set.str[STRING_FTPPORT]);
   2082     break;
   2083 
   2084   case CURLOPT_FTP_ACCOUNT:
   2085     return Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT], ptr);
   2086 
   2087   case CURLOPT_FTP_ALTERNATIVE_TO_USER:
   2088     return Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER], ptr);
   2089 
   2090 #ifdef HAVE_GSSAPI
   2091   case CURLOPT_KRBLEVEL:
   2092     /*
   2093      * A string that defines the kerberos security level.
   2094      */
   2095     result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL], ptr);
   2096     data->set.krb = !!(data->set.str[STRING_KRB_LEVEL]);
   2097     break;
   2098 #endif
   2099 #endif
   2100   case CURLOPT_URL:
   2101     /*
   2102      * The URL to fetch.
   2103      */
   2104     if(data->state.url_alloc) {
   2105       Curl_safefree(data->state.url);
   2106       data->state.url_alloc = FALSE;
   2107     }
   2108     result = Curl_setstropt(&data->set.str[STRING_SET_URL], ptr);
   2109     data->state.url = data->set.str[STRING_SET_URL];
   2110     break;
   2111 
   2112   case CURLOPT_USERPWD:
   2113     /*
   2114      * user:password to use in the operation
   2115      */
   2116     return setstropt_userpwd(ptr, &data->set.str[STRING_USERNAME],
   2117                              &data->set.str[STRING_PASSWORD]);
   2118 
   2119   case CURLOPT_USERNAME:
   2120     /*
   2121      * authentication username to use in the operation
   2122      */
   2123     return Curl_setstropt(&data->set.str[STRING_USERNAME], ptr);
   2124 
   2125   case CURLOPT_PASSWORD:
   2126     /*
   2127      * authentication password to use in the operation
   2128      */
   2129     return Curl_setstropt(&data->set.str[STRING_PASSWORD], ptr);
   2130 
   2131   case CURLOPT_LOGIN_OPTIONS:
   2132     /*
   2133      * authentication options to use in the operation
   2134      */
   2135     return Curl_setstropt(&data->set.str[STRING_OPTIONS], ptr);
   2136 
   2137   case CURLOPT_XOAUTH2_BEARER:
   2138     /*
   2139      * OAuth 2.0 bearer token to use in the operation
   2140      */
   2141     return Curl_setstropt(&data->set.str[STRING_BEARER], ptr);
   2142 
   2143 #ifndef CURL_DISABLE_PROXY
   2144   case CURLOPT_PROXYUSERPWD: {
   2145     /*
   2146      * user:password needed to use the proxy
   2147      */
   2148     char *u = NULL;
   2149     char *p = NULL;
   2150     result = setstropt_userpwd(ptr, &u, &p);
   2151 
   2152     /* URL decode the components */
   2153     if(!result && u) {
   2154       Curl_safefree(data->set.str[STRING_PROXYUSERNAME]);
   2155       result = Curl_urldecode(u, 0, &data->set.str[STRING_PROXYUSERNAME], NULL,
   2156                               REJECT_ZERO);
   2157     }
   2158     if(!result && p) {
   2159       Curl_safefree(data->set.str[STRING_PROXYPASSWORD]);
   2160       result = Curl_urldecode(p, 0, &data->set.str[STRING_PROXYPASSWORD], NULL,
   2161                               REJECT_ZERO);
   2162     }
   2163     free(u);
   2164     free(p);
   2165   }
   2166     break;
   2167   case CURLOPT_PROXYUSERNAME:
   2168     /*
   2169      * authentication username to use in the operation
   2170      */
   2171     return Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME], ptr);
   2172 
   2173   case CURLOPT_PROXYPASSWORD:
   2174     /*
   2175      * authentication password to use in the operation
   2176      */
   2177     return Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD], ptr);
   2178 
   2179   case CURLOPT_NOPROXY:
   2180     /*
   2181      * proxy exception list
   2182      */
   2183     return Curl_setstropt(&data->set.str[STRING_NOPROXY], ptr);
   2184 #endif /* ! CURL_DISABLE_PROXY */
   2185 
   2186   case CURLOPT_RANGE:
   2187     /*
   2188      * What range of the file you want to transfer
   2189      */
   2190     return Curl_setstropt(&data->set.str[STRING_SET_RANGE], ptr);
   2191 
   2192   case CURLOPT_CURLU:
   2193     /*
   2194      * pass CURLU to set URL
   2195      */
   2196     if(data->state.url_alloc) {
   2197       Curl_safefree(data->state.url);
   2198       data->state.url_alloc = FALSE;
   2199     }
   2200     else
   2201       data->state.url = NULL;
   2202     Curl_safefree(data->set.str[STRING_SET_URL]);
   2203     data->set.uh = (CURLU *)ptr;
   2204     break;
   2205   case CURLOPT_SSLCERT:
   2206     /*
   2207      * String that holds filename of the SSL certificate to use
   2208      */
   2209     return Curl_setstropt(&data->set.str[STRING_CERT], ptr);
   2210 
   2211 #ifndef CURL_DISABLE_PROXY
   2212   case CURLOPT_PROXY_SSLCERT:
   2213     /*
   2214      * String that holds filename of the SSL certificate to use for proxy
   2215      */
   2216     return Curl_setstropt(&data->set.str[STRING_CERT_PROXY], ptr);
   2217 
   2218 #endif
   2219   case CURLOPT_SSLCERTTYPE:
   2220     /*
   2221      * String that holds file type of the SSL certificate to use
   2222      */
   2223     return Curl_setstropt(&data->set.str[STRING_CERT_TYPE], ptr);
   2224 
   2225 #ifndef CURL_DISABLE_PROXY
   2226   case CURLOPT_PROXY_SSLCERTTYPE:
   2227     /*
   2228      * String that holds file type of the SSL certificate to use for proxy
   2229      */
   2230     return Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY], ptr);
   2231 
   2232 #endif
   2233   case CURLOPT_SSLKEY:
   2234     /*
   2235      * String that holds filename of the SSL key to use
   2236      */
   2237     return Curl_setstropt(&data->set.str[STRING_KEY], ptr);
   2238 
   2239 #ifndef CURL_DISABLE_PROXY
   2240   case CURLOPT_PROXY_SSLKEY:
   2241     /*
   2242      * String that holds filename of the SSL key to use for proxy
   2243      */
   2244     return Curl_setstropt(&data->set.str[STRING_KEY_PROXY], ptr);
   2245 
   2246 #endif
   2247   case CURLOPT_SSLKEYTYPE:
   2248     /*
   2249      * String that holds file type of the SSL key to use
   2250      */
   2251     return Curl_setstropt(&data->set.str[STRING_KEY_TYPE], ptr);
   2252 
   2253 #ifndef CURL_DISABLE_PROXY
   2254   case CURLOPT_PROXY_SSLKEYTYPE:
   2255     /*
   2256      * String that holds file type of the SSL key to use for proxy
   2257      */
   2258     return Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY], ptr);
   2259 
   2260 #endif
   2261   case CURLOPT_KEYPASSWD:
   2262     /*
   2263      * String that holds the SSL or SSH private key password.
   2264      */
   2265     return Curl_setstropt(&data->set.str[STRING_KEY_PASSWD], ptr);
   2266 
   2267 #ifndef CURL_DISABLE_PROXY
   2268   case CURLOPT_PROXY_KEYPASSWD:
   2269     /*
   2270      * String that holds the SSL private key password for proxy.
   2271      */
   2272     return Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY], ptr);
   2273 
   2274 #endif
   2275   case CURLOPT_SSLENGINE:
   2276     /*
   2277      * String that holds the SSL crypto engine.
   2278      */
   2279     if(ptr && ptr[0]) {
   2280       result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], ptr);
   2281       if(!result) {
   2282         result = Curl_ssl_set_engine(data, ptr);
   2283       }
   2284     }
   2285     break;
   2286 
   2287 #ifndef CURL_DISABLE_PROXY
   2288   case CURLOPT_HAPROXY_CLIENT_IP:
   2289     /*
   2290      * Set the client IP to send through HAProxy PROXY protocol
   2291      */
   2292     result = Curl_setstropt(&data->set.str[STRING_HAPROXY_CLIENT_IP], ptr);
   2293     /* enable the HAProxy protocol */
   2294     data->set.haproxyprotocol = TRUE;
   2295     break;
   2296 
   2297 #endif
   2298   case CURLOPT_INTERFACE:
   2299     /*
   2300      * Set what interface or address/hostname to bind the socket to when
   2301      * performing an operation and thus what from-IP your connection will use.
   2302      */
   2303     return setstropt_interface(ptr,
   2304                                &data->set.str[STRING_DEVICE],
   2305                                &data->set.str[STRING_INTERFACE],
   2306                                &data->set.str[STRING_BINDHOST]);
   2307 
   2308   case CURLOPT_PINNEDPUBLICKEY:
   2309     /*
   2310      * Set pinned public key for SSL connection.
   2311      * Specify filename of the public key in DER format.
   2312      */
   2313 #ifdef USE_SSL
   2314     if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
   2315       return Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY], ptr);
   2316 #endif
   2317     return CURLE_NOT_BUILT_IN;
   2318 
   2319 #ifndef CURL_DISABLE_PROXY
   2320   case CURLOPT_PROXY_PINNEDPUBLICKEY:
   2321     /*
   2322      * Set pinned public key for SSL connection.
   2323      * Specify filename of the public key in DER format.
   2324      */
   2325 #ifdef USE_SSL
   2326     if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
   2327       return Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
   2328                             ptr);
   2329 #endif
   2330     return CURLE_NOT_BUILT_IN;
   2331 #endif
   2332   case CURLOPT_CAINFO:
   2333     /*
   2334      * Set CA info for SSL connection. Specify filename of the CA certificate
   2335      */
   2336     return Curl_setstropt(&data->set.str[STRING_SSL_CAFILE], ptr);
   2337 
   2338 #ifndef CURL_DISABLE_PROXY
   2339   case CURLOPT_PROXY_CAINFO:
   2340     /*
   2341      * Set CA info SSL connection for proxy. Specify filename of the
   2342      * CA certificate
   2343      */
   2344     return Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY], ptr);
   2345 
   2346 #endif
   2347   case CURLOPT_CAPATH:
   2348     /*
   2349      * Set CA path info for SSL connection. Specify directory name of the CA
   2350      * certificates which have been prepared using openssl c_rehash utility.
   2351      */
   2352 #ifdef USE_SSL
   2353     if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
   2354       /* This does not work on Windows. */
   2355       return Curl_setstropt(&data->set.str[STRING_SSL_CAPATH], ptr);
   2356 #endif
   2357     return CURLE_NOT_BUILT_IN;
   2358 #ifndef CURL_DISABLE_PROXY
   2359   case CURLOPT_PROXY_CAPATH:
   2360     /*
   2361      * Set CA path info for SSL connection proxy. Specify directory name of the
   2362      * CA certificates which have been prepared using openssl c_rehash utility.
   2363      */
   2364 #ifdef USE_SSL
   2365     if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
   2366       /* This does not work on Windows. */
   2367       return Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY], ptr);
   2368 #endif
   2369     return CURLE_NOT_BUILT_IN;
   2370 #endif
   2371   case CURLOPT_CRLFILE:
   2372     /*
   2373      * Set CRL file info for SSL connection. Specify filename of the CRL
   2374      * to check certificates revocation
   2375      */
   2376     return Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE], ptr);
   2377 
   2378 #ifndef CURL_DISABLE_PROXY
   2379   case CURLOPT_PROXY_CRLFILE:
   2380     /*
   2381      * Set CRL file info for SSL connection for proxy. Specify filename of the
   2382      * CRL to check certificates revocation
   2383      */
   2384     return Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY], ptr);
   2385 
   2386 #endif
   2387   case CURLOPT_ISSUERCERT:
   2388     /*
   2389      * Set Issuer certificate file
   2390      * to check certificates issuer
   2391      */
   2392     return Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT], ptr);
   2393 
   2394 #ifndef CURL_DISABLE_PROXY
   2395   case CURLOPT_PROXY_ISSUERCERT:
   2396     /*
   2397      * Set Issuer certificate file
   2398      * to check certificates issuer
   2399      */
   2400     return Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_PROXY], ptr);
   2401 
   2402 #endif
   2403   case CURLOPT_PRIVATE:
   2404     /*
   2405      * Set private data pointer.
   2406      */
   2407     data->set.private_data = ptr;
   2408     break;
   2409 
   2410 #ifdef USE_SSL
   2411   case CURLOPT_SSL_EC_CURVES:
   2412     /*
   2413      * Set accepted curves in SSL connection setup.
   2414      * Specify colon-delimited list of curve algorithm names.
   2415      */
   2416     return Curl_setstropt(&data->set.str[STRING_SSL_EC_CURVES], ptr);
   2417 
   2418   case CURLOPT_SSL_SIGNATURE_ALGORITHMS:
   2419     /*
   2420      * Set accepted signature algorithms.
   2421      * Specify colon-delimited list of signature scheme names.
   2422      */
   2423     if(Curl_ssl_supports(data, SSLSUPP_SIGNATURE_ALGORITHMS))
   2424       return Curl_setstropt(&data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS],
   2425                             ptr);
   2426     return CURLE_NOT_BUILT_IN;
   2427 #endif
   2428 #ifdef USE_SSH
   2429   case CURLOPT_SSH_PUBLIC_KEYFILE:
   2430     /*
   2431      * Use this file instead of the $HOME/.ssh/id_dsa.pub file
   2432      */
   2433     return Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY], ptr);
   2434 
   2435   case CURLOPT_SSH_PRIVATE_KEYFILE:
   2436     /*
   2437      * Use this file instead of the $HOME/.ssh/id_dsa file
   2438      */
   2439     return Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY], ptr);
   2440 
   2441 #if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
   2442   case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
   2443     /*
   2444      * Option to allow for the MD5 of the host public key to be checked
   2445      * for validation purposes.
   2446      */
   2447     return Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], ptr);
   2448 
   2449   case CURLOPT_SSH_KNOWNHOSTS:
   2450     /*
   2451      * Store the filename to read known hosts from.
   2452      */
   2453     return Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS], ptr);
   2454 #endif
   2455   case CURLOPT_SSH_KEYDATA:
   2456     /*
   2457      * Custom client data to pass to the SSH keyfunc callback
   2458      */
   2459     data->set.ssh_keyfunc_userp = ptr;
   2460     break;
   2461 #ifdef USE_LIBSSH2
   2462   case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256:
   2463     /*
   2464      * Option to allow for the SHA256 of the host public key to be checked
   2465      * for validation purposes.
   2466      */
   2467     return Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256],
   2468                           ptr);
   2469 
   2470   case CURLOPT_SSH_HOSTKEYDATA:
   2471     /*
   2472      * Custom client data to pass to the SSH keyfunc callback
   2473      */
   2474     data->set.ssh_hostkeyfunc_userp = ptr;
   2475     break;
   2476 #endif /* USE_LIBSSH2 */
   2477 #endif /* USE_SSH */
   2478   case CURLOPT_PROTOCOLS_STR:
   2479     if(ptr)
   2480       return protocol2num(ptr, &data->set.allowed_protocols);
   2481     /* make a NULL argument reset to default */
   2482     data->set.allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
   2483     break;
   2484 
   2485   case CURLOPT_REDIR_PROTOCOLS_STR:
   2486     if(ptr)
   2487       return protocol2num(ptr, &data->set.redir_protocols);
   2488     /* make a NULL argument reset to default */
   2489     data->set.redir_protocols = (curl_prot_t) CURLPROTO_REDIR;
   2490     break;
   2491 
   2492   case CURLOPT_DEFAULT_PROTOCOL:
   2493     /* Set the protocol to use when the URL does not include any protocol */
   2494     return Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL], ptr);
   2495 
   2496 #ifndef CURL_DISABLE_SMTP
   2497   case CURLOPT_MAIL_FROM:
   2498     /* Set the SMTP mail originator */
   2499     return Curl_setstropt(&data->set.str[STRING_MAIL_FROM], ptr);
   2500 
   2501   case CURLOPT_MAIL_AUTH:
   2502     /* Set the SMTP auth originator */
   2503     return Curl_setstropt(&data->set.str[STRING_MAIL_AUTH], ptr);
   2504 #endif
   2505   case CURLOPT_SASL_AUTHZID:
   2506     /* Authorization identity (identity to act as) */
   2507     return Curl_setstropt(&data->set.str[STRING_SASL_AUTHZID], ptr);
   2508 
   2509 #ifndef CURL_DISABLE_RTSP
   2510   case CURLOPT_RTSP_SESSION_ID:
   2511     /*
   2512      * Set the RTSP Session ID manually. Useful if the application is
   2513      * resuming a previously established RTSP session
   2514      */
   2515     return Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID], ptr);
   2516 
   2517   case CURLOPT_RTSP_STREAM_URI:
   2518     /*
   2519      * Set the Stream URI for the RTSP request. Unless the request is
   2520      * for generic server options, the application will need to set this.
   2521      */
   2522     return Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI], ptr);
   2523 
   2524   case CURLOPT_RTSP_TRANSPORT:
   2525     /*
   2526      * The content of the Transport: header for the RTSP request
   2527      */
   2528     return Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT], ptr);
   2529 
   2530   case CURLOPT_INTERLEAVEDATA:
   2531     data->set.rtp_out = ptr;
   2532     break;
   2533 #endif /* ! CURL_DISABLE_RTSP */
   2534 #ifndef CURL_DISABLE_FTP
   2535   case CURLOPT_CHUNK_DATA:
   2536     data->set.wildcardptr = ptr;
   2537     break;
   2538   case CURLOPT_FNMATCH_DATA:
   2539     data->set.fnmatch_data = ptr;
   2540     break;
   2541 #endif
   2542 #ifdef USE_TLS_SRP
   2543   case CURLOPT_TLSAUTH_USERNAME:
   2544     return Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME], ptr);
   2545 
   2546 #ifndef CURL_DISABLE_PROXY
   2547   case CURLOPT_PROXY_TLSAUTH_USERNAME:
   2548     return Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], ptr);
   2549 
   2550 #endif
   2551   case CURLOPT_TLSAUTH_PASSWORD:
   2552     return Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], ptr);
   2553 
   2554 #ifndef CURL_DISABLE_PROXY
   2555   case CURLOPT_PROXY_TLSAUTH_PASSWORD:
   2556     return Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], ptr);
   2557 #endif
   2558   case CURLOPT_TLSAUTH_TYPE:
   2559     if(ptr && !curl_strequal(ptr, "SRP"))
   2560       return CURLE_BAD_FUNCTION_ARGUMENT;
   2561     break;
   2562 #ifndef CURL_DISABLE_PROXY
   2563   case CURLOPT_PROXY_TLSAUTH_TYPE:
   2564     if(ptr && !curl_strequal(ptr, "SRP"))
   2565       return CURLE_BAD_FUNCTION_ARGUMENT;
   2566     break;
   2567 #endif
   2568 #endif
   2569 #ifdef CURLRES_ARES
   2570   case CURLOPT_DNS_SERVERS:
   2571     result = Curl_setstropt(&data->set.str[STRING_DNS_SERVERS], ptr);
   2572     if(result)
   2573       return result;
   2574     return Curl_async_ares_set_dns_servers(data);
   2575 
   2576   case CURLOPT_DNS_INTERFACE:
   2577     result = Curl_setstropt(&data->set.str[STRING_DNS_INTERFACE], ptr);
   2578     if(result)
   2579       return result;
   2580     return Curl_async_ares_set_dns_interface(data);
   2581 
   2582   case CURLOPT_DNS_LOCAL_IP4:
   2583     result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP4], ptr);
   2584     if(result)
   2585       return result;
   2586     return Curl_async_ares_set_dns_local_ip4(data);
   2587 
   2588   case CURLOPT_DNS_LOCAL_IP6:
   2589     result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP6], ptr);
   2590     if(result)
   2591       return result;
   2592     return Curl_async_ares_set_dns_local_ip6(data);
   2593 
   2594 #endif
   2595 #ifdef USE_UNIX_SOCKETS
   2596   case CURLOPT_UNIX_SOCKET_PATH:
   2597     data->set.abstract_unix_socket = FALSE;
   2598     return Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], ptr);
   2599 
   2600   case CURLOPT_ABSTRACT_UNIX_SOCKET:
   2601     data->set.abstract_unix_socket = TRUE;
   2602     return Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], ptr);
   2603 
   2604 #endif
   2605 
   2606 #ifndef CURL_DISABLE_DOH
   2607   case CURLOPT_DOH_URL:
   2608     result = Curl_setstropt(&data->set.str[STRING_DOH], ptr);
   2609     data->set.doh = !!(data->set.str[STRING_DOH]);
   2610     break;
   2611 #endif
   2612 #ifndef CURL_DISABLE_HSTS
   2613   case CURLOPT_HSTSREADDATA:
   2614     data->set.hsts_read_userp = ptr;
   2615     break;
   2616   case CURLOPT_HSTSWRITEDATA:
   2617     data->set.hsts_write_userp = ptr;
   2618     break;
   2619   case CURLOPT_HSTS: {
   2620     struct curl_slist *h;
   2621     if(!data->hsts) {
   2622       data->hsts = Curl_hsts_init();
   2623       if(!data->hsts)
   2624         return CURLE_OUT_OF_MEMORY;
   2625     }
   2626     if(ptr) {
   2627       result = Curl_setstropt(&data->set.str[STRING_HSTS], ptr);
   2628       if(result)
   2629         return result;
   2630       /* this needs to build a list of filenames to read from, so that it can
   2631          read them later, as we might get a shared HSTS handle to load them
   2632          into */
   2633       h = curl_slist_append(data->state.hstslist, ptr);
   2634       if(!h) {
   2635         curl_slist_free_all(data->state.hstslist);
   2636         data->state.hstslist = NULL;
   2637         return CURLE_OUT_OF_MEMORY;
   2638       }
   2639       data->state.hstslist = h; /* store the list for later use */
   2640     }
   2641     else {
   2642       /* clear the list of HSTS files */
   2643       curl_slist_free_all(data->state.hstslist);
   2644       data->state.hstslist = NULL;
   2645       if(!data->share || !data->share->hsts)
   2646         /* throw away the HSTS cache unless shared */
   2647         Curl_hsts_cleanup(&data->hsts);
   2648     }
   2649     break;
   2650   }
   2651 #endif /* ! CURL_DISABLE_HSTS */
   2652 #ifndef CURL_DISABLE_ALTSVC
   2653   case CURLOPT_ALTSVC:
   2654     if(!data->asi) {
   2655       data->asi = Curl_altsvc_init();
   2656       if(!data->asi)
   2657         return CURLE_OUT_OF_MEMORY;
   2658     }
   2659     result = Curl_setstropt(&data->set.str[STRING_ALTSVC], ptr);
   2660     if(result)
   2661       return result;
   2662     if(ptr)
   2663       (void)Curl_altsvc_load(data->asi, ptr);
   2664     break;
   2665 #endif /* ! CURL_DISABLE_ALTSVC */
   2666 #ifdef USE_ECH
   2667   case CURLOPT_ECH: {
   2668     size_t plen = 0;
   2669 
   2670     if(!ptr) {
   2671       data->set.tls_ech = CURLECH_DISABLE;
   2672       return CURLE_OK;
   2673     }
   2674     plen = strlen(ptr);
   2675     if(plen > CURL_MAX_INPUT_LENGTH) {
   2676       data->set.tls_ech = CURLECH_DISABLE;
   2677       return CURLE_BAD_FUNCTION_ARGUMENT;
   2678     }
   2679     /* set tls_ech flag value, preserving CLA_CFG bit */
   2680     if(!strcmp(ptr, "false"))
   2681       data->set.tls_ech = CURLECH_DISABLE |
   2682         (data->set.tls_ech & CURLECH_CLA_CFG);
   2683     else if(!strcmp(ptr, "grease"))
   2684       data->set.tls_ech = CURLECH_GREASE |
   2685         (data->set.tls_ech & CURLECH_CLA_CFG);
   2686     else if(!strcmp(ptr, "true"))
   2687       data->set.tls_ech = CURLECH_ENABLE |
   2688         (data->set.tls_ech & CURLECH_CLA_CFG);
   2689     else if(!strcmp(ptr, "hard"))
   2690       data->set.tls_ech = CURLECH_HARD |
   2691         (data->set.tls_ech & CURLECH_CLA_CFG);
   2692     else if(plen > 5 && !strncmp(ptr, "ecl:", 4)) {
   2693       result = Curl_setstropt(&data->set.str[STRING_ECH_CONFIG], ptr + 4);
   2694       if(result)
   2695         return result;
   2696       data->set.tls_ech |= CURLECH_CLA_CFG;
   2697     }
   2698     else if(plen > 4 && !strncmp(ptr, "pn:", 3)) {
   2699       result = Curl_setstropt(&data->set.str[STRING_ECH_PUBLIC], ptr + 3);
   2700       if(result)
   2701         return result;
   2702     }
   2703     break;
   2704   }
   2705 #endif
   2706   default:
   2707     return CURLE_UNKNOWN_OPTION;
   2708   }
   2709   return result;
   2710 }
   2711 
   2712 static CURLcode setopt_func(struct Curl_easy *data, CURLoption option,
   2713                             va_list param)
   2714 {
   2715   switch(option) {
   2716   case CURLOPT_PROGRESSFUNCTION:
   2717     /*
   2718      * Progress callback function
   2719      */
   2720     data->set.fprogress = va_arg(param, curl_progress_callback);
   2721     if(data->set.fprogress)
   2722       data->progress.callback = TRUE; /* no longer internal */
   2723     else
   2724       data->progress.callback = FALSE; /* NULL enforces internal */
   2725     break;
   2726 
   2727   case CURLOPT_XFERINFOFUNCTION:
   2728     /*
   2729      * Transfer info callback function
   2730      */
   2731     data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
   2732     if(data->set.fxferinfo)
   2733       data->progress.callback = TRUE; /* no longer internal */
   2734     else
   2735       data->progress.callback = FALSE; /* NULL enforces internal */
   2736 
   2737     break;
   2738   case CURLOPT_DEBUGFUNCTION:
   2739     /*
   2740      * stderr write callback.
   2741      */
   2742     data->set.fdebug = va_arg(param, curl_debug_callback);
   2743     /*
   2744      * if the callback provided is NULL, it will use the default callback
   2745      */
   2746     break;
   2747   case CURLOPT_HEADERFUNCTION:
   2748     /*
   2749      * Set header write callback
   2750      */
   2751     data->set.fwrite_header = va_arg(param, curl_write_callback);
   2752     break;
   2753   case CURLOPT_WRITEFUNCTION:
   2754     /*
   2755      * Set data write callback
   2756      */
   2757     data->set.fwrite_func = va_arg(param, curl_write_callback);
   2758     if(!data->set.fwrite_func)
   2759       /* When set to NULL, reset to our internal default function */
   2760       data->set.fwrite_func = (curl_write_callback)fwrite;
   2761     break;
   2762   case CURLOPT_READFUNCTION:
   2763     /*
   2764      * Read data callback
   2765      */
   2766     data->set.fread_func_set = va_arg(param, curl_read_callback);
   2767     if(!data->set.fread_func_set) {
   2768       data->set.is_fread_set = 0;
   2769       /* When set to NULL, reset to our internal default function */
   2770       data->set.fread_func_set = (curl_read_callback)fread;
   2771     }
   2772     else
   2773       data->set.is_fread_set = 1;
   2774     break;
   2775   case CURLOPT_SEEKFUNCTION:
   2776     /*
   2777      * Seek callback. Might be NULL.
   2778      */
   2779     data->set.seek_func = va_arg(param, curl_seek_callback);
   2780     break;
   2781   case CURLOPT_IOCTLFUNCTION:
   2782     /*
   2783      * I/O control callback. Might be NULL.
   2784      */
   2785     data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
   2786     break;
   2787   case CURLOPT_SSL_CTX_FUNCTION:
   2788     /*
   2789      * Set an SSL_CTX callback
   2790      */
   2791 #ifdef USE_SSL
   2792     if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX)) {
   2793       data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
   2794       break;
   2795     }
   2796     else
   2797 #endif
   2798       return CURLE_NOT_BUILT_IN;
   2799 
   2800   case CURLOPT_SOCKOPTFUNCTION:
   2801     /*
   2802      * socket callback function: called after socket() but before connect()
   2803      */
   2804     data->set.fsockopt = va_arg(param, curl_sockopt_callback);
   2805     break;
   2806 
   2807   case CURLOPT_OPENSOCKETFUNCTION:
   2808     /*
   2809      * open/create socket callback function: called instead of socket(),
   2810      * before connect()
   2811      */
   2812     data->set.fopensocket = va_arg(param, curl_opensocket_callback);
   2813     break;
   2814 
   2815   case CURLOPT_CLOSESOCKETFUNCTION:
   2816     /*
   2817      * close socket callback function: called instead of close()
   2818      * when shutting down a connection
   2819      */
   2820     data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
   2821     break;
   2822 
   2823   case CURLOPT_RESOLVER_START_FUNCTION:
   2824     /*
   2825      * resolver start callback function: called before a new resolver request
   2826      * is started
   2827      */
   2828     data->set.resolver_start = va_arg(param, curl_resolver_start_callback);
   2829     break;
   2830 
   2831 #ifdef USE_SSH
   2832 #ifdef USE_LIBSSH2
   2833   case CURLOPT_SSH_HOSTKEYFUNCTION:
   2834     /* the callback to check the hostkey without the knownhost file */
   2835     data->set.ssh_hostkeyfunc = va_arg(param, curl_sshhostkeycallback);
   2836     break;
   2837 #endif
   2838 
   2839   case CURLOPT_SSH_KEYFUNCTION:
   2840     /* setting to NULL is fine since the ssh.c functions themselves will
   2841        then revert to use the internal default */
   2842     data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
   2843     break;
   2844 
   2845 #endif /* USE_SSH */
   2846 
   2847 #ifndef CURL_DISABLE_RTSP
   2848   case CURLOPT_INTERLEAVEFUNCTION:
   2849     /* Set the user defined RTP write function */
   2850     data->set.fwrite_rtp = va_arg(param, curl_write_callback);
   2851     break;
   2852 #endif
   2853 #ifndef CURL_DISABLE_FTP
   2854   case CURLOPT_CHUNK_BGN_FUNCTION:
   2855     data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
   2856     break;
   2857   case CURLOPT_CHUNK_END_FUNCTION:
   2858     data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
   2859     break;
   2860   case CURLOPT_FNMATCH_FUNCTION:
   2861     data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
   2862     break;
   2863 #endif
   2864 #ifndef CURL_DISABLE_HTTP
   2865   case CURLOPT_TRAILERFUNCTION:
   2866     data->set.trailer_callback = va_arg(param, curl_trailer_callback);
   2867     break;
   2868 #endif
   2869 #ifndef CURL_DISABLE_HSTS
   2870   case CURLOPT_HSTSREADFUNCTION:
   2871     data->set.hsts_read = va_arg(param, curl_hstsread_callback);
   2872     break;
   2873   case CURLOPT_HSTSWRITEFUNCTION:
   2874     data->set.hsts_write = va_arg(param, curl_hstswrite_callback);
   2875     break;
   2876 #endif
   2877   case CURLOPT_PREREQFUNCTION:
   2878     data->set.fprereq = va_arg(param, curl_prereq_callback);
   2879     break;
   2880   default:
   2881     return CURLE_UNKNOWN_OPTION;
   2882   }
   2883   return CURLE_OK;
   2884 }
   2885 
   2886 static CURLcode setopt_offt(struct Curl_easy *data, CURLoption option,
   2887                             curl_off_t offt)
   2888 {
   2889   switch(option) {
   2890   case CURLOPT_TIMEVALUE_LARGE:
   2891     /*
   2892      * This is the value to compare with the remote document with the
   2893      * method set with CURLOPT_TIMECONDITION
   2894      */
   2895     data->set.timevalue = (time_t)offt;
   2896     break;
   2897 
   2898     /* MQTT "borrows" some of the HTTP options */
   2899   case CURLOPT_POSTFIELDSIZE_LARGE:
   2900     /*
   2901      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
   2902      * figure it out. Enables binary posts.
   2903      */
   2904     if(offt < -1)
   2905       return CURLE_BAD_FUNCTION_ARGUMENT;
   2906 
   2907     if(data->set.postfieldsize < offt &&
   2908        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
   2909       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
   2910       Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
   2911       data->set.postfields = NULL;
   2912     }
   2913     data->set.postfieldsize = offt;
   2914     break;
   2915   case CURLOPT_INFILESIZE_LARGE:
   2916     /*
   2917      * If known, this should inform curl about the file size of the
   2918      * to-be-uploaded file.
   2919      */
   2920     if(offt < -1)
   2921       return CURLE_BAD_FUNCTION_ARGUMENT;
   2922     data->set.filesize = offt;
   2923     break;
   2924   case CURLOPT_MAX_SEND_SPEED_LARGE:
   2925     /*
   2926      * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
   2927      * bytes per second the transfer is throttled..
   2928      */
   2929     if(offt < 0)
   2930       return CURLE_BAD_FUNCTION_ARGUMENT;
   2931     data->set.max_send_speed = offt;
   2932     break;
   2933   case CURLOPT_MAX_RECV_SPEED_LARGE:
   2934     /*
   2935      * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
   2936      * second the transfer is throttled..
   2937      */
   2938     if(offt < 0)
   2939       return CURLE_BAD_FUNCTION_ARGUMENT;
   2940     data->set.max_recv_speed = offt;
   2941     break;
   2942   case CURLOPT_RESUME_FROM_LARGE:
   2943     /*
   2944      * Resume transfer at the given file position
   2945      */
   2946     if(offt < -1)
   2947       return CURLE_BAD_FUNCTION_ARGUMENT;
   2948     data->set.set_resume_from = offt;
   2949     break;
   2950   case CURLOPT_MAXFILESIZE_LARGE:
   2951     /*
   2952      * Set the maximum size of a file to download.
   2953      */
   2954     if(offt < 0)
   2955       return CURLE_BAD_FUNCTION_ARGUMENT;
   2956     data->set.max_filesize = offt;
   2957     break;
   2958 
   2959   default:
   2960     return CURLE_UNKNOWN_OPTION;
   2961   }
   2962   return CURLE_OK;
   2963 }
   2964 
   2965 static CURLcode setopt_blob(struct Curl_easy *data, CURLoption option,
   2966                             struct curl_blob *blob)
   2967 {
   2968   switch(option) {
   2969   case CURLOPT_SSLCERT_BLOB:
   2970     /*
   2971      * Blob that holds file content of the SSL certificate to use
   2972      */
   2973     return Curl_setblobopt(&data->set.blobs[BLOB_CERT], blob);
   2974 #ifndef CURL_DISABLE_PROXY
   2975   case CURLOPT_PROXY_SSLCERT_BLOB:
   2976     /*
   2977      * Blob that holds file content of the SSL certificate to use for proxy
   2978      */
   2979     return Curl_setblobopt(&data->set.blobs[BLOB_CERT_PROXY], blob);
   2980   case CURLOPT_PROXY_SSLKEY_BLOB:
   2981     /*
   2982      * Blob that holds file content of the SSL key to use for proxy
   2983      */
   2984     return Curl_setblobopt(&data->set.blobs[BLOB_KEY_PROXY], blob);
   2985   case CURLOPT_PROXY_CAINFO_BLOB:
   2986     /*
   2987      * Blob that holds CA info for SSL connection proxy.
   2988      * Specify entire PEM of the CA certificate
   2989      */
   2990 #ifdef USE_SSL
   2991     if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
   2992       return Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY], blob);
   2993 #endif
   2994     return CURLE_NOT_BUILT_IN;
   2995   case CURLOPT_PROXY_ISSUERCERT_BLOB:
   2996     /*
   2997      * Blob that holds Issuer certificate to check certificates issuer
   2998      */
   2999     return Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY],
   3000                            blob);
   3001 #endif
   3002   case CURLOPT_SSLKEY_BLOB:
   3003     /*
   3004      * Blob that holds file content of the SSL key to use
   3005      */
   3006     return Curl_setblobopt(&data->set.blobs[BLOB_KEY], blob);
   3007   case CURLOPT_CAINFO_BLOB:
   3008     /*
   3009      * Blob that holds CA info for SSL connection.
   3010      * Specify entire PEM of the CA certificate
   3011      */
   3012 #ifdef USE_SSL
   3013     if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
   3014       return Curl_setblobopt(&data->set.blobs[BLOB_CAINFO], blob);
   3015 #endif
   3016     return CURLE_NOT_BUILT_IN;
   3017   case CURLOPT_ISSUERCERT_BLOB:
   3018     /*
   3019      * Blob that holds Issuer certificate to check certificates issuer
   3020      */
   3021     return Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT], blob);
   3022 
   3023   default:
   3024     return CURLE_UNKNOWN_OPTION;
   3025   }
   3026   /* unreachable */
   3027 }
   3028 
   3029 /*
   3030  * Do not make Curl_vsetopt() static: it is called from
   3031  * packages/OS400/ccsidcurl.c.
   3032  */
   3033 CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
   3034 {
   3035   if(option < CURLOPTTYPE_OBJECTPOINT)
   3036     return setopt_long(data, option, va_arg(param, long));
   3037   else if(option < CURLOPTTYPE_FUNCTIONPOINT) {
   3038     /* unfortunately, different pointer types cannot be identified any other
   3039        way than being listed explicitly */
   3040     switch(option) {
   3041     case CURLOPT_HTTPHEADER:
   3042     case CURLOPT_QUOTE:
   3043     case CURLOPT_POSTQUOTE:
   3044     case CURLOPT_TELNETOPTIONS:
   3045     case CURLOPT_PREQUOTE:
   3046     case CURLOPT_HTTP200ALIASES:
   3047     case CURLOPT_MAIL_RCPT:
   3048     case CURLOPT_RESOLVE:
   3049     case CURLOPT_PROXYHEADER:
   3050     case CURLOPT_CONNECT_TO:
   3051       return setopt_slist(data, option, va_arg(param, struct curl_slist *));
   3052     case CURLOPT_HTTPPOST:         /* curl_httppost * */
   3053     case CURLOPT_MIMEPOST:         /* curl_mime * */
   3054     case CURLOPT_STDERR:           /* FILE * */
   3055     case CURLOPT_SHARE:            /* CURLSH * */
   3056     case CURLOPT_STREAM_DEPENDS:   /* CURL * */
   3057     case CURLOPT_STREAM_DEPENDS_E: /* CURL * */
   3058       return setopt_pointers(data, option, param);
   3059     default:
   3060       break;
   3061     }
   3062     /* the char pointer options */
   3063     return setopt_cptr(data, option, va_arg(param, char *));
   3064   }
   3065   else if(option < CURLOPTTYPE_OFF_T)
   3066     return setopt_func(data, option, param);
   3067   else if(option < CURLOPTTYPE_BLOB)
   3068     return setopt_offt(data, option, va_arg(param, curl_off_t));
   3069   return setopt_blob(data, option, va_arg(param, struct curl_blob *));
   3070 }
   3071 
   3072 /*
   3073  * curl_easy_setopt() is the external interface for setting options on an
   3074  * easy handle.
   3075  *
   3076  * NOTE: This is one of few API functions that are allowed to be called from
   3077  * within a callback.
   3078  */
   3079 
   3080 #undef curl_easy_setopt
   3081 CURLcode curl_easy_setopt(CURL *d, CURLoption tag, ...)
   3082 {
   3083   va_list arg;
   3084   CURLcode result;
   3085   struct Curl_easy *data = d;
   3086 
   3087   if(!data)
   3088     return CURLE_BAD_FUNCTION_ARGUMENT;
   3089 
   3090   va_start(arg, tag);
   3091 
   3092   result = Curl_vsetopt(data, tag, arg);
   3093 
   3094   va_end(arg);
   3095   if(result == CURLE_BAD_FUNCTION_ARGUMENT)
   3096     failf(data, "setopt 0x%x got bad argument", tag);
   3097   return result;
   3098 }