Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel (at) 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.haxx.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  ***************************************************************************/
     22 
     23 #include "curl_setup.h"
     24 
     25 #include <limits.h>
     26 
     27 #ifdef HAVE_NETINET_IN_H
     28 #include <netinet/in.h>
     29 #endif
     30 
     31 #ifdef HAVE_LINUX_TCP_H
     32 #include <linux/tcp.h>
     33 #endif
     34 
     35 #include "urldata.h"
     36 #include "url.h"
     37 #include "progress.h"
     38 #include "content_encoding.h"
     39 #include "strcase.h"
     40 #include "share.h"
     41 #include "vtls/vtls.h"
     42 #include "warnless.h"
     43 #include "sendf.h"
     44 #include "http2.h"
     45 #include "setopt.h"
     46 
     47 /* The last 3 #include files should be in this order */
     48 #include "curl_printf.h"
     49 #include "curl_memory.h"
     50 #include "memdebug.h"
     51 
     52 CURLcode Curl_setstropt(char **charp, const char *s)
     53 {
     54   /* Release the previous storage at `charp' and replace by a dynamic storage
     55      copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
     56 
     57   Curl_safefree(*charp);
     58 
     59   if(s) {
     60     char *str = strdup(s);
     61 
     62     if(!str)
     63       return CURLE_OUT_OF_MEMORY;
     64 
     65     *charp = str;
     66   }
     67 
     68   return CURLE_OK;
     69 }
     70 
     71 static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
     72 {
     73   CURLcode result = CURLE_OK;
     74   char *user = NULL;
     75   char *passwd = NULL;
     76 
     77   /* Parse the login details if specified. It not then we treat NULL as a hint
     78      to clear the existing data */
     79   if(option) {
     80     result = Curl_parse_login_details(option, strlen(option),
     81                                       (userp ? &user : NULL),
     82                                       (passwdp ? &passwd : NULL),
     83                                       NULL);
     84   }
     85 
     86   if(!result) {
     87     /* Store the username part of option if required */
     88     if(userp) {
     89       if(!user && option && option[0] == ':') {
     90         /* Allocate an empty string instead of returning NULL as user name */
     91         user = strdup("");
     92         if(!user)
     93           result = CURLE_OUT_OF_MEMORY;
     94       }
     95 
     96       Curl_safefree(*userp);
     97       *userp = user;
     98     }
     99 
    100     /* Store the password part of option if required */
    101     if(passwdp) {
    102       Curl_safefree(*passwdp);
    103       *passwdp = passwd;
    104     }
    105   }
    106 
    107   return result;
    108 }
    109 
    110 #define C_SSLVERSION_VALUE(x) (x & 0xffff)
    111 #define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000)
    112 
    113 CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
    114                       va_list param)
    115 {
    116   char *argptr;
    117   CURLcode result = CURLE_OK;
    118   long arg;
    119   curl_off_t bigsize;
    120 
    121   switch(option) {
    122   case CURLOPT_DNS_CACHE_TIMEOUT:
    123     arg = va_arg(param, long);
    124     if(arg < -1)
    125       return CURLE_BAD_FUNCTION_ARGUMENT;
    126     data->set.dns_cache_timeout = arg;
    127     break;
    128   case CURLOPT_DNS_USE_GLOBAL_CACHE:
    129     /* remember we want this enabled */
    130     arg = va_arg(param, long);
    131     data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
    132     break;
    133   case CURLOPT_SSL_CIPHER_LIST:
    134     /* set a list of cipher we want to use in the SSL connection */
    135     result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
    136                             va_arg(param, char *));
    137     break;
    138   case CURLOPT_PROXY_SSL_CIPHER_LIST:
    139     /* set a list of cipher we want to use in the SSL connection for proxy */
    140     result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
    141                             va_arg(param, char *));
    142     break;
    143 
    144   case CURLOPT_RANDOM_FILE:
    145     /*
    146      * This is the path name to a file that contains random data to seed
    147      * the random SSL stuff with. The file is only used for reading.
    148      */
    149     result = Curl_setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
    150                             va_arg(param, char *));
    151     break;
    152   case CURLOPT_EGDSOCKET:
    153     /*
    154      * The Entropy Gathering Daemon socket pathname
    155      */
    156     result = Curl_setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
    157                             va_arg(param, char *));
    158     break;
    159   case CURLOPT_MAXCONNECTS:
    160     /*
    161      * Set the absolute number of maximum simultaneous alive connection that
    162      * libcurl is allowed to have.
    163      */
    164     arg = va_arg(param, long);
    165     if(arg < 0)
    166       return CURLE_BAD_FUNCTION_ARGUMENT;
    167     data->set.maxconnects = arg;
    168     break;
    169   case CURLOPT_FORBID_REUSE:
    170     /*
    171      * When this transfer is done, it must not be left to be reused by a
    172      * subsequent transfer but shall be closed immediately.
    173      */
    174     data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
    175     break;
    176   case CURLOPT_FRESH_CONNECT:
    177     /*
    178      * This transfer shall not use a previously cached connection but
    179      * should be made with a fresh new connect!
    180      */
    181     data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
    182     break;
    183   case CURLOPT_VERBOSE:
    184     /*
    185      * Verbose means infof() calls that give a lot of information about
    186      * the connection and transfer procedures as well as internal choices.
    187      */
    188     data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
    189     break;
    190   case CURLOPT_HEADER:
    191     /*
    192      * Set to include the header in the general data output stream.
    193      */
    194     data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
    195     break;
    196   case CURLOPT_NOPROGRESS:
    197     /*
    198      * Shut off the internal supported progress meter
    199      */
    200     data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
    201     if(data->set.hide_progress)
    202       data->progress.flags |= PGRS_HIDE;
    203     else
    204       data->progress.flags &= ~PGRS_HIDE;
    205     break;
    206   case CURLOPT_NOBODY:
    207     /*
    208      * Do not include the body part in the output data stream.
    209      */
    210     data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
    211     break;
    212   case CURLOPT_FAILONERROR:
    213     /*
    214      * Don't output the >=400 error code HTML-page, but instead only
    215      * return error.
    216      */
    217     data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
    218     break;
    219   case CURLOPT_KEEP_SENDING_ON_ERROR:
    220     data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
    221       TRUE : FALSE;
    222     break;
    223   case CURLOPT_UPLOAD:
    224   case CURLOPT_PUT:
    225     /*
    226      * We want to sent data to the remote host. If this is HTTP, that equals
    227      * using the PUT request.
    228      */
    229     data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
    230     if(data->set.upload) {
    231       /* If this is HTTP, PUT is what's needed to "upload" */
    232       data->set.httpreq = HTTPREQ_PUT;
    233       data->set.opt_no_body = FALSE; /* this is implied */
    234     }
    235     else
    236       /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
    237          then this can be changed to HEAD later on) */
    238       data->set.httpreq = HTTPREQ_GET;
    239     break;
    240   case CURLOPT_REQUEST_TARGET:
    241     result = Curl_setstropt(&data->set.str[STRING_TARGET],
    242                             va_arg(param, char *));
    243     break;
    244   case CURLOPT_FILETIME:
    245     /*
    246      * Try to get the file time of the remote document. The time will
    247      * later (possibly) become available using curl_easy_getinfo().
    248      */
    249     data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
    250     break;
    251   case CURLOPT_FTP_CREATE_MISSING_DIRS:
    252     /*
    253      * An FTP option that modifies an upload to create missing directories on
    254      * the server.
    255      */
    256     switch(va_arg(param, long)) {
    257     case 0:
    258       data->set.ftp_create_missing_dirs = 0;
    259       break;
    260     case 1:
    261       data->set.ftp_create_missing_dirs = 1;
    262       break;
    263     case 2:
    264       data->set.ftp_create_missing_dirs = 2;
    265       break;
    266     default:
    267       /* reserve other values for future use */
    268       result = CURLE_UNKNOWN_OPTION;
    269       break;
    270     }
    271     break;
    272   case CURLOPT_SERVER_RESPONSE_TIMEOUT:
    273     /*
    274      * Option that specifies how quickly an server response must be obtained
    275      * before it is considered failure. For pingpong protocols.
    276      */
    277     arg = va_arg(param, long);
    278     if((arg >= 0) && (arg <= (INT_MAX/1000)))
    279       data->set.server_response_timeout = arg * 1000;
    280     else
    281       return CURLE_BAD_FUNCTION_ARGUMENT;
    282     break;
    283   case CURLOPT_TFTP_NO_OPTIONS:
    284     /*
    285      * Option that prevents libcurl from sending TFTP option requests to the
    286      * server.
    287      */
    288     data->set.tftp_no_options = va_arg(param, long) != 0;
    289     break;
    290   case CURLOPT_TFTP_BLKSIZE:
    291     /*
    292      * TFTP option that specifies the block size to use for data transmission.
    293      */
    294     arg = va_arg(param, long);
    295     if(arg < 0)
    296       return CURLE_BAD_FUNCTION_ARGUMENT;
    297     data->set.tftp_blksize = arg;
    298     break;
    299   case CURLOPT_DIRLISTONLY:
    300     /*
    301      * An option that changes the command to one that asks for a list
    302      * only, no file info details.
    303      */
    304     data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
    305     break;
    306   case CURLOPT_APPEND:
    307     /*
    308      * We want to upload and append to an existing file.
    309      */
    310     data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
    311     break;
    312   case CURLOPT_FTP_FILEMETHOD:
    313     /*
    314      * How do access files over FTP.
    315      */
    316     arg = va_arg(param, long);
    317     if((arg < CURLFTPMETHOD_DEFAULT) || (arg > CURLFTPMETHOD_SINGLECWD))
    318       return CURLE_BAD_FUNCTION_ARGUMENT;
    319     data->set.ftp_filemethod = (curl_ftpfile)arg;
    320     break;
    321   case CURLOPT_NETRC:
    322     /*
    323      * Parse the $HOME/.netrc file
    324      */
    325     arg = va_arg(param, long);
    326     if((arg < CURL_NETRC_IGNORED) || (arg > CURL_NETRC_REQUIRED))
    327       return CURLE_BAD_FUNCTION_ARGUMENT;
    328     data->set.use_netrc = (enum CURL_NETRC_OPTION)arg;
    329     break;
    330   case CURLOPT_NETRC_FILE:
    331     /*
    332      * Use this file instead of the $HOME/.netrc file
    333      */
    334     result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE],
    335                             va_arg(param, char *));
    336     break;
    337   case CURLOPT_TRANSFERTEXT:
    338     /*
    339      * This option was previously named 'FTPASCII'. Renamed to work with
    340      * more protocols than merely FTP.
    341      *
    342      * Transfer using ASCII (instead of BINARY).
    343      */
    344     data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
    345     break;
    346   case CURLOPT_TIMECONDITION:
    347     /*
    348      * Set HTTP time condition. This must be one of the defines in the
    349      * curl/curl.h header file.
    350      */
    351     arg = va_arg(param, long);
    352     if((arg < CURL_TIMECOND_NONE) || (arg > CURL_TIMECOND_LASTMOD))
    353       return CURLE_BAD_FUNCTION_ARGUMENT;
    354     data->set.timecondition = (curl_TimeCond)arg;
    355     break;
    356   case CURLOPT_TIMEVALUE:
    357     /*
    358      * This is the value to compare with the remote document with the
    359      * method set with CURLOPT_TIMECONDITION
    360      */
    361     data->set.timevalue = (time_t)va_arg(param, long);
    362     break;
    363 
    364   case CURLOPT_SSLVERSION:
    365   case CURLOPT_PROXY_SSLVERSION:
    366     /*
    367      * Set explicit SSL version to try to connect with, as some SSL
    368      * implementations are lame.
    369      */
    370 #ifdef USE_SSL
    371     {
    372       long version, version_max;
    373       struct ssl_primary_config *primary = (option == CURLOPT_SSLVERSION ?
    374                                             &data->set.ssl.primary :
    375                                             &data->set.proxy_ssl.primary);
    376 
    377       arg = va_arg(param, long);
    378 
    379       version = C_SSLVERSION_VALUE(arg);
    380       version_max = C_SSLVERSION_MAX_VALUE(arg);
    381 
    382       if(version < CURL_SSLVERSION_DEFAULT ||
    383          version >= CURL_SSLVERSION_LAST ||
    384          version_max < CURL_SSLVERSION_MAX_NONE ||
    385          version_max >= CURL_SSLVERSION_MAX_LAST)
    386         return CURLE_BAD_FUNCTION_ARGUMENT;
    387 
    388       primary->version = version;
    389       primary->version_max = version_max;
    390     }
    391 #else
    392     result = CURLE_UNKNOWN_OPTION;
    393 #endif
    394     break;
    395 
    396 #ifndef CURL_DISABLE_HTTP
    397   case CURLOPT_AUTOREFERER:
    398     /*
    399      * Switch on automatic referer that gets set if curl follows locations.
    400      */
    401     data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
    402     break;
    403 
    404   case CURLOPT_ACCEPT_ENCODING:
    405     /*
    406      * String to use at the value of Accept-Encoding header.
    407      *
    408      * If the encoding is set to "" we use an Accept-Encoding header that
    409      * encompasses all the encodings we support.
    410      * If the encoding is set to NULL we don't send an Accept-Encoding header
    411      * and ignore an received Content-Encoding header.
    412      *
    413      */
    414     argptr = va_arg(param, char *);
    415     if(argptr && !*argptr) {
    416       argptr = Curl_all_content_encodings();
    417       if(!argptr)
    418         result = CURLE_OUT_OF_MEMORY;
    419       else {
    420         result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
    421         free(argptr);
    422       }
    423     }
    424     else
    425       result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr);
    426     break;
    427 
    428   case CURLOPT_TRANSFER_ENCODING:
    429     data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
    430       TRUE : FALSE;
    431     break;
    432 
    433   case CURLOPT_FOLLOWLOCATION:
    434     /*
    435      * Follow Location: header hints on a HTTP-server.
    436      */
    437     data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
    438     break;
    439 
    440   case CURLOPT_UNRESTRICTED_AUTH:
    441     /*
    442      * Send authentication (user+password) when following locations, even when
    443      * hostname changed.
    444      */
    445     data->set.allow_auth_to_other_hosts =
    446       (0 != va_arg(param, long)) ? TRUE : FALSE;
    447     break;
    448 
    449   case CURLOPT_MAXREDIRS:
    450     /*
    451      * The maximum amount of hops you allow curl to follow Location:
    452      * headers. This should mostly be used to detect never-ending loops.
    453      */
    454     arg = va_arg(param, long);
    455     if(arg < -1)
    456       return CURLE_BAD_FUNCTION_ARGUMENT;
    457     data->set.maxredirs = arg;
    458     break;
    459 
    460   case CURLOPT_POSTREDIR:
    461     /*
    462      * Set the behaviour of POST when redirecting
    463      * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
    464      * CURL_REDIR_POST_301 - POST is kept as POST after 301
    465      * CURL_REDIR_POST_302 - POST is kept as POST after 302
    466      * CURL_REDIR_POST_303 - POST is kept as POST after 303
    467      * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
    468      * other - POST is kept as POST after 301 and 302
    469      */
    470     arg = va_arg(param, long);
    471     if(arg < CURL_REDIR_GET_ALL)
    472       /* no return error on too high numbers since the bitmask could be
    473          extended in a future */
    474       return CURLE_BAD_FUNCTION_ARGUMENT;
    475     data->set.keep_post = arg & CURL_REDIR_POST_ALL;
    476     break;
    477 
    478   case CURLOPT_POST:
    479     /* Does this option serve a purpose anymore? Yes it does, when
    480        CURLOPT_POSTFIELDS isn't used and the POST data is read off the
    481        callback! */
    482     if(va_arg(param, long)) {
    483       data->set.httpreq = HTTPREQ_POST;
    484       data->set.opt_no_body = FALSE; /* this is implied */
    485     }
    486     else
    487       data->set.httpreq = HTTPREQ_GET;
    488     break;
    489 
    490   case CURLOPT_COPYPOSTFIELDS:
    491     /*
    492      * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
    493      * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
    494      *  CURLOPT_COPYPOSTFIELDS and not altered later.
    495      */
    496     argptr = va_arg(param, char *);
    497 
    498     if(!argptr || data->set.postfieldsize == -1)
    499       result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
    500     else {
    501       /*
    502        *  Check that requested length does not overflow the size_t type.
    503        */
    504 
    505       if((data->set.postfieldsize < 0) ||
    506          ((sizeof(curl_off_t) != sizeof(size_t)) &&
    507           (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
    508         result = CURLE_OUT_OF_MEMORY;
    509       else {
    510         char *p;
    511 
    512         (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
    513 
    514         /* Allocate even when size == 0. This satisfies the need of possible
    515            later address compare to detect the COPYPOSTFIELDS mode, and
    516            to mark that postfields is used rather than read function or
    517            form data.
    518         */
    519         p = malloc((size_t)(data->set.postfieldsize?
    520                             data->set.postfieldsize:1));
    521 
    522         if(!p)
    523           result = CURLE_OUT_OF_MEMORY;
    524         else {
    525           if(data->set.postfieldsize)
    526             memcpy(p, argptr, (size_t)data->set.postfieldsize);
    527 
    528           data->set.str[STRING_COPYPOSTFIELDS] = p;
    529         }
    530       }
    531     }
    532 
    533     data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
    534     data->set.httpreq = HTTPREQ_POST;
    535     break;
    536 
    537   case CURLOPT_POSTFIELDS:
    538     /*
    539      * Like above, but use static data instead of copying it.
    540      */
    541     data->set.postfields = va_arg(param, void *);
    542     /* Release old copied data. */
    543     (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
    544     data->set.httpreq = HTTPREQ_POST;
    545     break;
    546 
    547   case CURLOPT_POSTFIELDSIZE:
    548     /*
    549      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
    550      * figure it out. Enables binary posts.
    551      */
    552     bigsize = va_arg(param, long);
    553     if(bigsize < -1)
    554       return CURLE_BAD_FUNCTION_ARGUMENT;
    555 
    556     if(data->set.postfieldsize < bigsize &&
    557        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
    558       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
    559       (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
    560       data->set.postfields = NULL;
    561     }
    562 
    563     data->set.postfieldsize = bigsize;
    564     break;
    565 
    566   case CURLOPT_POSTFIELDSIZE_LARGE:
    567     /*
    568      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
    569      * figure it out. Enables binary posts.
    570      */
    571     bigsize = va_arg(param, curl_off_t);
    572     if(bigsize < -1)
    573       return CURLE_BAD_FUNCTION_ARGUMENT;
    574 
    575     if(data->set.postfieldsize < bigsize &&
    576        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
    577       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
    578       (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
    579       data->set.postfields = NULL;
    580     }
    581 
    582     data->set.postfieldsize = bigsize;
    583     break;
    584 
    585   case CURLOPT_HTTPPOST:
    586     /*
    587      * Set to make us do HTTP POST
    588      */
    589     data->set.httppost = va_arg(param, struct curl_httppost *);
    590     data->set.httpreq = HTTPREQ_POST_FORM;
    591     data->set.opt_no_body = FALSE; /* this is implied */
    592     break;
    593 #endif   /* CURL_DISABLE_HTTP */
    594 
    595   case CURLOPT_MIMEPOST:
    596     /*
    597      * Set to make us do MIME/form POST
    598      */
    599     result = Curl_mime_set_subparts(&data->set.mimepost,
    600                                     va_arg(param, curl_mime *), FALSE);
    601     if(!result) {
    602       data->set.httpreq = HTTPREQ_POST_MIME;
    603       data->set.opt_no_body = FALSE; /* this is implied */
    604     }
    605     break;
    606 
    607   case CURLOPT_REFERER:
    608     /*
    609      * String to set in the HTTP Referer: field.
    610      */
    611     if(data->change.referer_alloc) {
    612       Curl_safefree(data->change.referer);
    613       data->change.referer_alloc = FALSE;
    614     }
    615     result = Curl_setstropt(&data->set.str[STRING_SET_REFERER],
    616                             va_arg(param, char *));
    617     data->change.referer = data->set.str[STRING_SET_REFERER];
    618     break;
    619 
    620   case CURLOPT_USERAGENT:
    621     /*
    622      * String to use in the HTTP User-Agent field
    623      */
    624     result = Curl_setstropt(&data->set.str[STRING_USERAGENT],
    625                             va_arg(param, char *));
    626     break;
    627 
    628   case CURLOPT_HTTPHEADER:
    629     /*
    630      * Set a list with HTTP headers to use (or replace internals with)
    631      */
    632     data->set.headers = va_arg(param, struct curl_slist *);
    633     break;
    634 
    635 #ifndef CURL_DISABLE_HTTP
    636   case CURLOPT_PROXYHEADER:
    637     /*
    638      * Set a list with proxy headers to use (or replace internals with)
    639      *
    640      * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
    641      * long time we remain doing it this way until CURLOPT_PROXYHEADER is
    642      * used. As soon as this option has been used, if set to anything but
    643      * NULL, custom headers for proxies are only picked from this list.
    644      *
    645      * Set this option to NULL to restore the previous behavior.
    646      */
    647     data->set.proxyheaders = va_arg(param, struct curl_slist *);
    648     break;
    649 
    650   case CURLOPT_HEADEROPT:
    651     /*
    652      * Set header option.
    653      */
    654     arg = va_arg(param, long);
    655     data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
    656     break;
    657 
    658   case CURLOPT_HTTP200ALIASES:
    659     /*
    660      * Set a list of aliases for HTTP 200 in response header
    661      */
    662     data->set.http200aliases = va_arg(param, struct curl_slist *);
    663     break;
    664 
    665 #if !defined(CURL_DISABLE_COOKIES)
    666   case CURLOPT_COOKIE:
    667     /*
    668      * Cookie string to send to the remote server in the request.
    669      */
    670     result = Curl_setstropt(&data->set.str[STRING_COOKIE],
    671                             va_arg(param, char *));
    672     break;
    673 
    674   case CURLOPT_COOKIEFILE:
    675     /*
    676      * Set cookie file to read and parse. Can be used multiple times.
    677      */
    678     argptr = (char *)va_arg(param, void *);
    679     if(argptr) {
    680       struct curl_slist *cl;
    681       /* append the cookie file name to the list of file names, and deal with
    682          them later */
    683       cl = curl_slist_append(data->change.cookielist, argptr);
    684       if(!cl) {
    685         curl_slist_free_all(data->change.cookielist);
    686         data->change.cookielist = NULL;
    687         return CURLE_OUT_OF_MEMORY;
    688       }
    689       data->change.cookielist = cl; /* store the list for later use */
    690     }
    691     break;
    692 
    693   case CURLOPT_COOKIEJAR:
    694     /*
    695      * Set cookie file name to dump all cookies to when we're done.
    696      */
    697   {
    698     struct CookieInfo *newcookies;
    699     result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR],
    700                             va_arg(param, char *));
    701 
    702     /*
    703      * Activate the cookie parser. This may or may not already
    704      * have been made.
    705      */
    706     newcookies = Curl_cookie_init(data, NULL, data->cookies,
    707                                   data->set.cookiesession);
    708     if(!newcookies)
    709       result = CURLE_OUT_OF_MEMORY;
    710     data->cookies = newcookies;
    711   }
    712   break;
    713 
    714   case CURLOPT_COOKIESESSION:
    715     /*
    716      * Set this option to TRUE to start a new "cookie session". It will
    717      * prevent the forthcoming read-cookies-from-file actions to accept
    718      * cookies that are marked as being session cookies, as they belong to a
    719      * previous session.
    720      *
    721      * In the original Netscape cookie spec, "session cookies" are cookies
    722      * with no expire date set. RFC2109 describes the same action if no
    723      * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
    724      * a 'Discard' action that can enforce the discard even for cookies that
    725      * have a Max-Age.
    726      *
    727      * We run mostly with the original cookie spec, as hardly anyone implements
    728      * anything else.
    729      */
    730     data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
    731     break;
    732 
    733   case CURLOPT_COOKIELIST:
    734     argptr = va_arg(param, char *);
    735 
    736     if(argptr == NULL)
    737       break;
    738 
    739     if(strcasecompare(argptr, "ALL")) {
    740       /* clear all cookies */
    741       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
    742       Curl_cookie_clearall(data->cookies);
    743       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
    744     }
    745     else if(strcasecompare(argptr, "SESS")) {
    746       /* clear session cookies */
    747       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
    748       Curl_cookie_clearsess(data->cookies);
    749       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
    750     }
    751     else if(strcasecompare(argptr, "FLUSH")) {
    752       /* flush cookies to file, takes care of the locking */
    753       Curl_flush_cookies(data, 0);
    754     }
    755     else if(strcasecompare(argptr, "RELOAD")) {
    756       /* reload cookies from file */
    757       Curl_cookie_loadfiles(data);
    758       break;
    759     }
    760     else {
    761       if(!data->cookies)
    762         /* if cookie engine was not running, activate it */
    763         data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
    764 
    765       argptr = strdup(argptr);
    766       if(!argptr || !data->cookies) {
    767         result = CURLE_OUT_OF_MEMORY;
    768         free(argptr);
    769       }
    770       else {
    771         Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
    772 
    773         if(checkprefix("Set-Cookie:", argptr))
    774           /* HTTP Header format line */
    775           Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
    776 
    777         else
    778           /* Netscape format line */
    779           Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
    780 
    781         Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
    782         free(argptr);
    783       }
    784     }
    785 
    786     break;
    787 #endif /* !CURL_DISABLE_COOKIES */
    788 
    789   case CURLOPT_HTTPGET:
    790     /*
    791      * Set to force us do HTTP GET
    792      */
    793     if(va_arg(param, long)) {
    794       data->set.httpreq = HTTPREQ_GET;
    795       data->set.upload = FALSE; /* switch off upload */
    796       data->set.opt_no_body = FALSE; /* this is implied */
    797     }
    798     break;
    799 
    800   case CURLOPT_HTTP_VERSION:
    801     /*
    802      * This sets a requested HTTP version to be used. The value is one of
    803      * the listed enums in curl/curl.h.
    804      */
    805     arg = va_arg(param, long);
    806     if(arg < CURL_HTTP_VERSION_NONE)
    807       return CURLE_BAD_FUNCTION_ARGUMENT;
    808 #ifndef USE_NGHTTP2
    809     if(arg >= CURL_HTTP_VERSION_2)
    810       return CURLE_UNSUPPORTED_PROTOCOL;
    811 #else
    812     if(arg > CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE)
    813       return CURLE_UNSUPPORTED_PROTOCOL;
    814 #endif
    815     data->set.httpversion = arg;
    816     break;
    817 
    818   case CURLOPT_EXPECT_100_TIMEOUT_MS:
    819     /*
    820      * Time to wait for a response to a HTTP request containing an
    821      * Expect: 100-continue header before sending the data anyway.
    822      */
    823     arg = va_arg(param, long);
    824     if(arg < 0)
    825       return CURLE_BAD_FUNCTION_ARGUMENT;
    826     data->set.expect_100_timeout = arg;
    827     break;
    828 
    829 #endif   /* CURL_DISABLE_HTTP */
    830 
    831   case CURLOPT_HTTPAUTH:
    832     /*
    833      * Set HTTP Authentication type BITMASK.
    834      */
    835   {
    836     int bitcheck;
    837     bool authbits;
    838     unsigned long auth = va_arg(param, unsigned long);
    839 
    840     if(auth == CURLAUTH_NONE) {
    841       data->set.httpauth = auth;
    842       break;
    843     }
    844 
    845     /* the DIGEST_IE bit is only used to set a special marker, for all the
    846        rest we need to handle it as normal DIGEST */
    847     data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
    848 
    849     if(auth & CURLAUTH_DIGEST_IE) {
    850       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
    851       auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
    852     }
    853 
    854     /* switch off bits we can't support */
    855 #ifndef USE_NTLM
    856     auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
    857     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
    858 #elif !defined(NTLM_WB_ENABLED)
    859     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
    860 #endif
    861 #ifndef USE_SPNEGO
    862     auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
    863                                     GSS-API or SSPI */
    864 #endif
    865 
    866     /* check if any auth bit lower than CURLAUTH_ONLY is still set */
    867     bitcheck = 0;
    868     authbits = FALSE;
    869     while(bitcheck < 31) {
    870       if(auth & (1UL << bitcheck++)) {
    871         authbits = TRUE;
    872         break;
    873       }
    874     }
    875     if(!authbits)
    876       return CURLE_NOT_BUILT_IN; /* no supported types left! */
    877 
    878     data->set.httpauth = auth;
    879   }
    880   break;
    881 
    882   case CURLOPT_CUSTOMREQUEST:
    883     /*
    884      * Set a custom string to use as request
    885      */
    886     result = Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST],
    887                             va_arg(param, char *));
    888 
    889     /* we don't set
    890        data->set.httpreq = HTTPREQ_CUSTOM;
    891        here, we continue as if we were using the already set type
    892        and this just changes the actual request keyword */
    893     break;
    894 
    895 #ifndef CURL_DISABLE_PROXY
    896   case CURLOPT_HTTPPROXYTUNNEL:
    897     /*
    898      * Tunnel operations through the proxy instead of normal proxy use
    899      */
    900     data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
    901       TRUE : FALSE;
    902     break;
    903 
    904   case CURLOPT_PROXYPORT:
    905     /*
    906      * Explicitly set HTTP proxy port number.
    907      */
    908     arg = va_arg(param, long);
    909     if((arg < 0) || (arg > 65535))
    910       return CURLE_BAD_FUNCTION_ARGUMENT;
    911     data->set.proxyport = arg;
    912     break;
    913 
    914   case CURLOPT_PROXYAUTH:
    915     /*
    916      * Set HTTP Authentication type BITMASK.
    917      */
    918   {
    919     int bitcheck;
    920     bool authbits;
    921     unsigned long auth = va_arg(param, unsigned long);
    922 
    923     if(auth == CURLAUTH_NONE) {
    924       data->set.proxyauth = auth;
    925       break;
    926     }
    927 
    928     /* the DIGEST_IE bit is only used to set a special marker, for all the
    929        rest we need to handle it as normal DIGEST */
    930     data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
    931 
    932     if(auth & CURLAUTH_DIGEST_IE) {
    933       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
    934       auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
    935     }
    936     /* switch off bits we can't support */
    937 #ifndef USE_NTLM
    938     auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
    939     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
    940 #elif !defined(NTLM_WB_ENABLED)
    941     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
    942 #endif
    943 #ifndef USE_SPNEGO
    944     auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
    945                                     GSS-API or SSPI */
    946 #endif
    947 
    948     /* check if any auth bit lower than CURLAUTH_ONLY is still set */
    949     bitcheck = 0;
    950     authbits = FALSE;
    951     while(bitcheck < 31) {
    952       if(auth & (1UL << bitcheck++)) {
    953         authbits = TRUE;
    954         break;
    955       }
    956     }
    957     if(!authbits)
    958       return CURLE_NOT_BUILT_IN; /* no supported types left! */
    959 
    960     data->set.proxyauth = auth;
    961   }
    962   break;
    963 
    964   case CURLOPT_PROXY:
    965     /*
    966      * Set proxy server:port to use as proxy.
    967      *
    968      * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
    969      * we explicitly say that we don't want to use a proxy
    970      * (even though there might be environment variables saying so).
    971      *
    972      * Setting it to NULL, means no proxy but allows the environment variables
    973      * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
    974      */
    975     result = Curl_setstropt(&data->set.str[STRING_PROXY],
    976                             va_arg(param, char *));
    977     break;
    978 
    979   case CURLOPT_PRE_PROXY:
    980     /*
    981      * Set proxy server:port to use as SOCKS proxy.
    982      *
    983      * If the proxy is set to "" or NULL we explicitly say that we don't want
    984      * to use the socks proxy.
    985      */
    986     result = Curl_setstropt(&data->set.str[STRING_PRE_PROXY],
    987                             va_arg(param, char *));
    988     break;
    989 
    990   case CURLOPT_PROXYTYPE:
    991     /*
    992      * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
    993      */
    994     arg = va_arg(param, long);
    995     if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
    996       return CURLE_BAD_FUNCTION_ARGUMENT;
    997     data->set.proxytype = (curl_proxytype)arg;
    998     break;
    999 
   1000   case CURLOPT_PROXY_TRANSFER_MODE:
   1001     /*
   1002      * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
   1003      */
   1004     switch(va_arg(param, long)) {
   1005     case 0:
   1006       data->set.proxy_transfer_mode = FALSE;
   1007       break;
   1008     case 1:
   1009       data->set.proxy_transfer_mode = TRUE;
   1010       break;
   1011     default:
   1012       /* reserve other values for future use */
   1013       result = CURLE_UNKNOWN_OPTION;
   1014       break;
   1015     }
   1016     break;
   1017 #endif   /* CURL_DISABLE_PROXY */
   1018 
   1019   case CURLOPT_SOCKS5_AUTH:
   1020     data->set.socks5auth = va_arg(param, unsigned long);
   1021     if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
   1022       result = CURLE_NOT_BUILT_IN;
   1023     break;
   1024 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
   1025   case CURLOPT_SOCKS5_GSSAPI_NEC:
   1026     /*
   1027      * Set flag for NEC SOCK5 support
   1028      */
   1029     data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
   1030     break;
   1031 
   1032   case CURLOPT_SOCKS5_GSSAPI_SERVICE:
   1033   case CURLOPT_PROXY_SERVICE_NAME:
   1034     /*
   1035      * Set proxy authentication service name for Kerberos 5 and SPNEGO
   1036      */
   1037     result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
   1038                             va_arg(param, char *));
   1039     break;
   1040 #endif
   1041 
   1042 #if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) ||     \
   1043   defined(USE_SPNEGO)
   1044   case CURLOPT_SERVICE_NAME:
   1045     /*
   1046      * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
   1047      */
   1048     result = Curl_setstropt(&data->set.str[STRING_SERVICE_NAME],
   1049                             va_arg(param, char *));
   1050     break;
   1051 
   1052 #endif
   1053 
   1054   case CURLOPT_HEADERDATA:
   1055     /*
   1056      * Custom pointer to pass the header write callback function
   1057      */
   1058     data->set.writeheader = (void *)va_arg(param, void *);
   1059     break;
   1060   case CURLOPT_ERRORBUFFER:
   1061     /*
   1062      * Error buffer provided by the caller to get the human readable
   1063      * error string in.
   1064      */
   1065     data->set.errorbuffer = va_arg(param, char *);
   1066     break;
   1067   case CURLOPT_WRITEDATA:
   1068     /*
   1069      * FILE pointer to write to. Or possibly
   1070      * used as argument to the write callback.
   1071      */
   1072     data->set.out = va_arg(param, void *);
   1073     break;
   1074   case CURLOPT_FTPPORT:
   1075     /*
   1076      * Use FTP PORT, this also specifies which IP address to use
   1077      */
   1078     result = Curl_setstropt(&data->set.str[STRING_FTPPORT],
   1079                             va_arg(param, char *));
   1080     data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
   1081     break;
   1082 
   1083   case CURLOPT_FTP_USE_EPRT:
   1084     data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
   1085     break;
   1086 
   1087   case CURLOPT_FTP_USE_EPSV:
   1088     data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
   1089     break;
   1090 
   1091   case CURLOPT_FTP_USE_PRET:
   1092     data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
   1093     break;
   1094 
   1095   case CURLOPT_FTP_SSL_CCC:
   1096     arg = va_arg(param, long);
   1097     if((arg < CURLFTPSSL_CCC_NONE) || (arg > CURLFTPSSL_CCC_ACTIVE))
   1098       return CURLE_BAD_FUNCTION_ARGUMENT;
   1099     data->set.ftp_ccc = (curl_ftpccc)arg;
   1100     break;
   1101 
   1102   case CURLOPT_FTP_SKIP_PASV_IP:
   1103     /*
   1104      * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
   1105      * bypass of the IP address in PASV responses.
   1106      */
   1107     data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
   1108     break;
   1109 
   1110   case CURLOPT_READDATA:
   1111     /*
   1112      * FILE pointer to read the file to be uploaded from. Or possibly
   1113      * used as argument to the read callback.
   1114      */
   1115     data->set.in_set = va_arg(param, void *);
   1116     break;
   1117   case CURLOPT_INFILESIZE:
   1118     /*
   1119      * If known, this should inform curl about the file size of the
   1120      * to-be-uploaded file.
   1121      */
   1122     arg = va_arg(param, long);
   1123     if(arg < -1)
   1124       return CURLE_BAD_FUNCTION_ARGUMENT;
   1125     data->set.filesize = arg;
   1126     break;
   1127   case CURLOPT_INFILESIZE_LARGE:
   1128     /*
   1129      * If known, this should inform curl about the file size of the
   1130      * to-be-uploaded file.
   1131      */
   1132     bigsize = va_arg(param, curl_off_t);
   1133     if(bigsize < -1)
   1134       return CURLE_BAD_FUNCTION_ARGUMENT;
   1135     data->set.filesize = bigsize;
   1136     break;
   1137   case CURLOPT_LOW_SPEED_LIMIT:
   1138     /*
   1139      * The low speed limit that if transfers are below this for
   1140      * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
   1141      */
   1142     arg = va_arg(param, long);
   1143     if(arg < 0)
   1144       return CURLE_BAD_FUNCTION_ARGUMENT;
   1145     data->set.low_speed_limit = arg;
   1146     break;
   1147   case CURLOPT_MAX_SEND_SPEED_LARGE:
   1148     /*
   1149      * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
   1150      * bytes per second the transfer is throttled..
   1151      */
   1152     bigsize = va_arg(param, curl_off_t);
   1153     if(bigsize < 0)
   1154       return CURLE_BAD_FUNCTION_ARGUMENT;
   1155     data->set.max_send_speed = bigsize;
   1156     break;
   1157   case CURLOPT_MAX_RECV_SPEED_LARGE:
   1158     /*
   1159      * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
   1160      * second the transfer is throttled..
   1161      */
   1162     bigsize = va_arg(param, curl_off_t);
   1163     if(bigsize < 0)
   1164       return CURLE_BAD_FUNCTION_ARGUMENT;
   1165     data->set.max_recv_speed = bigsize;
   1166     break;
   1167   case CURLOPT_LOW_SPEED_TIME:
   1168     /*
   1169      * The low speed time that if transfers are below the set
   1170      * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
   1171      */
   1172     arg = va_arg(param, long);
   1173     if(arg < 0)
   1174       return CURLE_BAD_FUNCTION_ARGUMENT;
   1175     data->set.low_speed_time = arg;
   1176     break;
   1177   case CURLOPT_URL:
   1178     /*
   1179      * The URL to fetch.
   1180      */
   1181     if(data->change.url_alloc) {
   1182       /* the already set URL is allocated, free it first! */
   1183       Curl_safefree(data->change.url);
   1184       data->change.url_alloc = FALSE;
   1185     }
   1186     result = Curl_setstropt(&data->set.str[STRING_SET_URL],
   1187                             va_arg(param, char *));
   1188     data->change.url = data->set.str[STRING_SET_URL];
   1189     break;
   1190   case CURLOPT_PORT:
   1191     /*
   1192      * The port number to use when getting the URL
   1193      */
   1194     arg = va_arg(param, long);
   1195     if((arg < 0) || (arg > 65535))
   1196       return CURLE_BAD_FUNCTION_ARGUMENT;
   1197     data->set.use_port = arg;
   1198     break;
   1199   case CURLOPT_TIMEOUT:
   1200     /*
   1201      * The maximum time you allow curl to use for a single transfer
   1202      * operation.
   1203      */
   1204     arg = va_arg(param, long);
   1205     if((arg >= 0) && (arg <= (INT_MAX/1000)))
   1206       data->set.timeout = arg * 1000;
   1207     else
   1208       return CURLE_BAD_FUNCTION_ARGUMENT;
   1209     break;
   1210 
   1211   case CURLOPT_TIMEOUT_MS:
   1212     arg = va_arg(param, long);
   1213     if(arg < 0)
   1214       return CURLE_BAD_FUNCTION_ARGUMENT;
   1215     data->set.timeout = arg;
   1216     break;
   1217 
   1218   case CURLOPT_CONNECTTIMEOUT:
   1219     /*
   1220      * The maximum time you allow curl to use to connect.
   1221      */
   1222     arg = va_arg(param, long);
   1223     if((arg >= 0) && (arg <= (INT_MAX/1000)))
   1224       data->set.connecttimeout = arg * 1000;
   1225     else
   1226       return CURLE_BAD_FUNCTION_ARGUMENT;
   1227     break;
   1228 
   1229   case CURLOPT_CONNECTTIMEOUT_MS:
   1230     arg = va_arg(param, long);
   1231     if(arg < 0)
   1232       return CURLE_BAD_FUNCTION_ARGUMENT;
   1233     data->set.connecttimeout = arg;
   1234     break;
   1235 
   1236   case CURLOPT_ACCEPTTIMEOUT_MS:
   1237     /*
   1238      * The maximum time you allow curl to wait for server connect
   1239      */
   1240     arg = va_arg(param, long);
   1241     if(arg < 0)
   1242       return CURLE_BAD_FUNCTION_ARGUMENT;
   1243     data->set.accepttimeout = arg;
   1244     break;
   1245 
   1246   case CURLOPT_USERPWD:
   1247     /*
   1248      * user:password to use in the operation
   1249      */
   1250     result = setstropt_userpwd(va_arg(param, char *),
   1251                                &data->set.str[STRING_USERNAME],
   1252                                &data->set.str[STRING_PASSWORD]);
   1253     break;
   1254 
   1255   case CURLOPT_USERNAME:
   1256     /*
   1257      * authentication user name to use in the operation
   1258      */
   1259     result = Curl_setstropt(&data->set.str[STRING_USERNAME],
   1260                             va_arg(param, char *));
   1261     break;
   1262 
   1263   case CURLOPT_PASSWORD:
   1264     /*
   1265      * authentication password to use in the operation
   1266      */
   1267     result = Curl_setstropt(&data->set.str[STRING_PASSWORD],
   1268                             va_arg(param, char *));
   1269     break;
   1270 
   1271   case CURLOPT_LOGIN_OPTIONS:
   1272     /*
   1273      * authentication options to use in the operation
   1274      */
   1275     result = Curl_setstropt(&data->set.str[STRING_OPTIONS],
   1276                             va_arg(param, char *));
   1277     break;
   1278 
   1279   case CURLOPT_XOAUTH2_BEARER:
   1280     /*
   1281      * OAuth 2.0 bearer token to use in the operation
   1282      */
   1283     result = Curl_setstropt(&data->set.str[STRING_BEARER],
   1284                             va_arg(param, char *));
   1285     break;
   1286 
   1287   case CURLOPT_POSTQUOTE:
   1288     /*
   1289      * List of RAW FTP commands to use after a transfer
   1290      */
   1291     data->set.postquote = va_arg(param, struct curl_slist *);
   1292     break;
   1293   case CURLOPT_PREQUOTE:
   1294     /*
   1295      * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
   1296      */
   1297     data->set.prequote = va_arg(param, struct curl_slist *);
   1298     break;
   1299   case CURLOPT_QUOTE:
   1300     /*
   1301      * List of RAW FTP commands to use before a transfer
   1302      */
   1303     data->set.quote = va_arg(param, struct curl_slist *);
   1304     break;
   1305   case CURLOPT_RESOLVE:
   1306     /*
   1307      * List of NAME:[address] names to populate the DNS cache with
   1308      * Prefix the NAME with dash (-) to _remove_ the name from the cache.
   1309      *
   1310      * Names added with this API will remain in the cache until explicitly
   1311      * removed or the handle is cleaned up.
   1312      *
   1313      * This API can remove any name from the DNS cache, but only entries
   1314      * that aren't actually in use right now will be pruned immediately.
   1315      */
   1316     data->set.resolve = va_arg(param, struct curl_slist *);
   1317     data->change.resolve = data->set.resolve;
   1318     break;
   1319   case CURLOPT_PROGRESSFUNCTION:
   1320     /*
   1321      * Progress callback function
   1322      */
   1323     data->set.fprogress = va_arg(param, curl_progress_callback);
   1324     if(data->set.fprogress)
   1325       data->progress.callback = TRUE; /* no longer internal */
   1326     else
   1327       data->progress.callback = FALSE; /* NULL enforces internal */
   1328     break;
   1329 
   1330   case CURLOPT_XFERINFOFUNCTION:
   1331     /*
   1332      * Transfer info callback function
   1333      */
   1334     data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
   1335     if(data->set.fxferinfo)
   1336       data->progress.callback = TRUE; /* no longer internal */
   1337     else
   1338       data->progress.callback = FALSE; /* NULL enforces internal */
   1339 
   1340     break;
   1341 
   1342   case CURLOPT_PROGRESSDATA:
   1343     /*
   1344      * Custom client data to pass to the progress callback
   1345      */
   1346     data->set.progress_client = va_arg(param, void *);
   1347     break;
   1348 
   1349 #ifndef CURL_DISABLE_PROXY
   1350   case CURLOPT_PROXYUSERPWD:
   1351     /*
   1352      * user:password needed to use the proxy
   1353      */
   1354     result = setstropt_userpwd(va_arg(param, char *),
   1355                                &data->set.str[STRING_PROXYUSERNAME],
   1356                                &data->set.str[STRING_PROXYPASSWORD]);
   1357     break;
   1358   case CURLOPT_PROXYUSERNAME:
   1359     /*
   1360      * authentication user name to use in the operation
   1361      */
   1362     result = Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME],
   1363                             va_arg(param, char *));
   1364     break;
   1365   case CURLOPT_PROXYPASSWORD:
   1366     /*
   1367      * authentication password to use in the operation
   1368      */
   1369     result = Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD],
   1370                             va_arg(param, char *));
   1371     break;
   1372   case CURLOPT_NOPROXY:
   1373     /*
   1374      * proxy exception list
   1375      */
   1376     result = Curl_setstropt(&data->set.str[STRING_NOPROXY],
   1377                             va_arg(param, char *));
   1378     break;
   1379 #endif
   1380 
   1381   case CURLOPT_RANGE:
   1382     /*
   1383      * What range of the file you want to transfer
   1384      */
   1385     result = Curl_setstropt(&data->set.str[STRING_SET_RANGE],
   1386                             va_arg(param, char *));
   1387     break;
   1388   case CURLOPT_RESUME_FROM:
   1389     /*
   1390      * Resume transfer at the given file position
   1391      */
   1392     arg = va_arg(param, long);
   1393     if(arg < -1)
   1394       return CURLE_BAD_FUNCTION_ARGUMENT;
   1395     data->set.set_resume_from = arg;
   1396     break;
   1397   case CURLOPT_RESUME_FROM_LARGE:
   1398     /*
   1399      * Resume transfer at the given file position
   1400      */
   1401     bigsize = va_arg(param, curl_off_t);
   1402     if(bigsize < -1)
   1403       return CURLE_BAD_FUNCTION_ARGUMENT;
   1404     data->set.set_resume_from = bigsize;
   1405     break;
   1406   case CURLOPT_DEBUGFUNCTION:
   1407     /*
   1408      * stderr write callback.
   1409      */
   1410     data->set.fdebug = va_arg(param, curl_debug_callback);
   1411     /*
   1412      * if the callback provided is NULL, it'll use the default callback
   1413      */
   1414     break;
   1415   case CURLOPT_DEBUGDATA:
   1416     /*
   1417      * Set to a void * that should receive all error writes. This
   1418      * defaults to CURLOPT_STDERR for normal operations.
   1419      */
   1420     data->set.debugdata = va_arg(param, void *);
   1421     break;
   1422   case CURLOPT_STDERR:
   1423     /*
   1424      * Set to a FILE * that should receive all error writes. This
   1425      * defaults to stderr for normal operations.
   1426      */
   1427     data->set.err = va_arg(param, FILE *);
   1428     if(!data->set.err)
   1429       data->set.err = stderr;
   1430     break;
   1431   case CURLOPT_HEADERFUNCTION:
   1432     /*
   1433      * Set header write callback
   1434      */
   1435     data->set.fwrite_header = va_arg(param, curl_write_callback);
   1436     break;
   1437   case CURLOPT_WRITEFUNCTION:
   1438     /*
   1439      * Set data write callback
   1440      */
   1441     data->set.fwrite_func = va_arg(param, curl_write_callback);
   1442     if(!data->set.fwrite_func) {
   1443       data->set.is_fwrite_set = 0;
   1444       /* When set to NULL, reset to our internal default function */
   1445       data->set.fwrite_func = (curl_write_callback)fwrite;
   1446     }
   1447     else
   1448       data->set.is_fwrite_set = 1;
   1449     break;
   1450   case CURLOPT_READFUNCTION:
   1451     /*
   1452      * Read data callback
   1453      */
   1454     data->set.fread_func_set = va_arg(param, curl_read_callback);
   1455     if(!data->set.fread_func_set) {
   1456       data->set.is_fread_set = 0;
   1457       /* When set to NULL, reset to our internal default function */
   1458       data->set.fread_func_set = (curl_read_callback)fread;
   1459     }
   1460     else
   1461       data->set.is_fread_set = 1;
   1462     break;
   1463   case CURLOPT_SEEKFUNCTION:
   1464     /*
   1465      * Seek callback. Might be NULL.
   1466      */
   1467     data->set.seek_func = va_arg(param, curl_seek_callback);
   1468     break;
   1469   case CURLOPT_SEEKDATA:
   1470     /*
   1471      * Seek control callback. Might be NULL.
   1472      */
   1473     data->set.seek_client = va_arg(param, void *);
   1474     break;
   1475   case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
   1476     /*
   1477      * "Convert from network encoding" callback
   1478      */
   1479     data->set.convfromnetwork = va_arg(param, curl_conv_callback);
   1480     break;
   1481   case CURLOPT_CONV_TO_NETWORK_FUNCTION:
   1482     /*
   1483      * "Convert to network encoding" callback
   1484      */
   1485     data->set.convtonetwork = va_arg(param, curl_conv_callback);
   1486     break;
   1487   case CURLOPT_CONV_FROM_UTF8_FUNCTION:
   1488     /*
   1489      * "Convert from UTF-8 encoding" callback
   1490      */
   1491     data->set.convfromutf8 = va_arg(param, curl_conv_callback);
   1492     break;
   1493   case CURLOPT_IOCTLFUNCTION:
   1494     /*
   1495      * I/O control callback. Might be NULL.
   1496      */
   1497     data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
   1498     break;
   1499   case CURLOPT_IOCTLDATA:
   1500     /*
   1501      * I/O control data pointer. Might be NULL.
   1502      */
   1503     data->set.ioctl_client = va_arg(param, void *);
   1504     break;
   1505   case CURLOPT_SSLCERT:
   1506     /*
   1507      * String that holds file name of the SSL certificate to use
   1508      */
   1509     result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG],
   1510                             va_arg(param, char *));
   1511     break;
   1512   case CURLOPT_PROXY_SSLCERT:
   1513     /*
   1514      * String that holds file name of the SSL certificate to use for proxy
   1515      */
   1516     result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY],
   1517                             va_arg(param, char *));
   1518     break;
   1519   case CURLOPT_SSLCERTTYPE:
   1520     /*
   1521      * String that holds file type of the SSL certificate to use
   1522      */
   1523     result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
   1524                             va_arg(param, char *));
   1525     break;
   1526   case CURLOPT_PROXY_SSLCERTTYPE:
   1527     /*
   1528      * String that holds file type of the SSL certificate to use for proxy
   1529      */
   1530     result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
   1531                             va_arg(param, char *));
   1532     break;
   1533   case CURLOPT_SSLKEY:
   1534     /*
   1535      * String that holds file name of the SSL key to use
   1536      */
   1537     result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG],
   1538                             va_arg(param, char *));
   1539     break;
   1540   case CURLOPT_PROXY_SSLKEY:
   1541     /*
   1542      * String that holds file name of the SSL key to use for proxy
   1543      */
   1544     result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY],
   1545                             va_arg(param, char *));
   1546     break;
   1547   case CURLOPT_SSLKEYTYPE:
   1548     /*
   1549      * String that holds file type of the SSL key to use
   1550      */
   1551     result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
   1552                             va_arg(param, char *));
   1553     break;
   1554   case CURLOPT_PROXY_SSLKEYTYPE:
   1555     /*
   1556      * String that holds file type of the SSL key to use for proxy
   1557      */
   1558     result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
   1559                             va_arg(param, char *));
   1560     break;
   1561   case CURLOPT_KEYPASSWD:
   1562     /*
   1563      * String that holds the SSL or SSH private key password.
   1564      */
   1565     result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
   1566                             va_arg(param, char *));
   1567     break;
   1568   case CURLOPT_PROXY_KEYPASSWD:
   1569     /*
   1570      * String that holds the SSL private key password for proxy.
   1571      */
   1572     result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
   1573                             va_arg(param, char *));
   1574     break;
   1575   case CURLOPT_SSLENGINE:
   1576     /*
   1577      * String that holds the SSL crypto engine.
   1578      */
   1579     argptr = va_arg(param, char *);
   1580     if(argptr && argptr[0])
   1581       result = Curl_ssl_set_engine(data, argptr);
   1582     break;
   1583 
   1584   case CURLOPT_SSLENGINE_DEFAULT:
   1585     /*
   1586      * flag to set engine as default.
   1587      */
   1588     result = Curl_ssl_set_engine_default(data);
   1589     break;
   1590   case CURLOPT_CRLF:
   1591     /*
   1592      * Kludgy option to enable CRLF conversions. Subject for removal.
   1593      */
   1594     data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
   1595     break;
   1596 
   1597   case CURLOPT_INTERFACE:
   1598     /*
   1599      * Set what interface or address/hostname to bind the socket to when
   1600      * performing an operation and thus what from-IP your connection will use.
   1601      */
   1602     result = Curl_setstropt(&data->set.str[STRING_DEVICE],
   1603                             va_arg(param, char *));
   1604     break;
   1605   case CURLOPT_LOCALPORT:
   1606     /*
   1607      * Set what local port to bind the socket to when performing an operation.
   1608      */
   1609     arg = va_arg(param, long);
   1610     if((arg < 0) || (arg > 65535))
   1611       return CURLE_BAD_FUNCTION_ARGUMENT;
   1612     data->set.localport = curlx_sltous(arg);
   1613     break;
   1614   case CURLOPT_LOCALPORTRANGE:
   1615     /*
   1616      * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
   1617      */
   1618     arg = va_arg(param, long);
   1619     if((arg < 0) || (arg > 65535))
   1620       return CURLE_BAD_FUNCTION_ARGUMENT;
   1621     data->set.localportrange = curlx_sltosi(arg);
   1622     break;
   1623   case CURLOPT_KRBLEVEL:
   1624     /*
   1625      * A string that defines the kerberos security level.
   1626      */
   1627     result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL],
   1628                             va_arg(param, char *));
   1629     data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
   1630     break;
   1631   case CURLOPT_GSSAPI_DELEGATION:
   1632     /*
   1633      * GSS-API credential delegation bitmask
   1634      */
   1635     arg = va_arg(param, long);
   1636     if(arg < CURLGSSAPI_DELEGATION_NONE)
   1637       return CURLE_BAD_FUNCTION_ARGUMENT;
   1638     data->set.gssapi_delegation = arg;
   1639     break;
   1640   case CURLOPT_SSL_VERIFYPEER:
   1641     /*
   1642      * Enable peer SSL verifying.
   1643      */
   1644     data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
   1645       TRUE : FALSE;
   1646 
   1647     /* Update the current connection ssl_config. */
   1648     if(data->easy_conn) {
   1649       data->easy_conn->ssl_config.verifypeer =
   1650         data->set.ssl.primary.verifypeer;
   1651     }
   1652     break;
   1653   case CURLOPT_PROXY_SSL_VERIFYPEER:
   1654     /*
   1655      * Enable peer SSL verifying for proxy.
   1656      */
   1657     data->set.proxy_ssl.primary.verifypeer =
   1658       (0 != va_arg(param, long))?TRUE:FALSE;
   1659 
   1660     /* Update the current connection proxy_ssl_config. */
   1661     if(data->easy_conn) {
   1662       data->easy_conn->proxy_ssl_config.verifypeer =
   1663         data->set.proxy_ssl.primary.verifypeer;
   1664     }
   1665     break;
   1666   case CURLOPT_SSL_VERIFYHOST:
   1667     /*
   1668      * Enable verification of the host name in the peer certificate
   1669      */
   1670     arg = va_arg(param, long);
   1671 
   1672     /* Obviously people are not reading documentation and too many thought
   1673        this argument took a boolean when it wasn't and misused it. We thus ban
   1674        1 as a sensible input and we warn about its use. Then we only have the
   1675        2 action internally stored as TRUE. */
   1676 
   1677     if(1 == arg) {
   1678       failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
   1679       return CURLE_BAD_FUNCTION_ARGUMENT;
   1680     }
   1681 
   1682     data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
   1683 
   1684     /* Update the current connection ssl_config. */
   1685     if(data->easy_conn) {
   1686       data->easy_conn->ssl_config.verifyhost =
   1687         data->set.ssl.primary.verifyhost;
   1688     }
   1689     break;
   1690   case CURLOPT_PROXY_SSL_VERIFYHOST:
   1691     /*
   1692      * Enable verification of the host name in the peer certificate for proxy
   1693      */
   1694     arg = va_arg(param, long);
   1695 
   1696     /* Obviously people are not reading documentation and too many thought
   1697        this argument took a boolean when it wasn't and misused it. We thus ban
   1698        1 as a sensible input and we warn about its use. Then we only have the
   1699        2 action internally stored as TRUE. */
   1700 
   1701     if(1 == arg) {
   1702       failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
   1703       return CURLE_BAD_FUNCTION_ARGUMENT;
   1704     }
   1705 
   1706     data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
   1707 
   1708     /* Update the current connection proxy_ssl_config. */
   1709     if(data->easy_conn) {
   1710       data->easy_conn->proxy_ssl_config.verifyhost =
   1711         data->set.proxy_ssl.primary.verifyhost;
   1712     }
   1713     break;
   1714   case CURLOPT_SSL_VERIFYSTATUS:
   1715     /*
   1716      * Enable certificate status verifying.
   1717      */
   1718     if(!Curl_ssl_cert_status_request()) {
   1719       result = CURLE_NOT_BUILT_IN;
   1720       break;
   1721     }
   1722 
   1723     data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
   1724       TRUE : FALSE;
   1725 
   1726     /* Update the current connection ssl_config. */
   1727     if(data->easy_conn) {
   1728       data->easy_conn->ssl_config.verifystatus =
   1729         data->set.ssl.primary.verifystatus;
   1730     }
   1731     break;
   1732   case CURLOPT_SSL_CTX_FUNCTION:
   1733     /*
   1734      * Set a SSL_CTX callback
   1735      */
   1736 #ifdef USE_SSL
   1737     if(Curl_ssl->have_ssl_ctx)
   1738       data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
   1739     else
   1740 #endif
   1741       result = CURLE_NOT_BUILT_IN;
   1742     break;
   1743   case CURLOPT_SSL_CTX_DATA:
   1744     /*
   1745      * Set a SSL_CTX callback parameter pointer
   1746      */
   1747 #ifdef USE_SSL
   1748     if(Curl_ssl->have_ssl_ctx)
   1749       data->set.ssl.fsslctxp = va_arg(param, void *);
   1750     else
   1751 #endif
   1752       result = CURLE_NOT_BUILT_IN;
   1753     break;
   1754   case CURLOPT_SSL_FALSESTART:
   1755     /*
   1756      * Enable TLS false start.
   1757      */
   1758     if(!Curl_ssl_false_start()) {
   1759       result = CURLE_NOT_BUILT_IN;
   1760       break;
   1761     }
   1762 
   1763     data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
   1764     break;
   1765   case CURLOPT_CERTINFO:
   1766 #ifdef USE_SSL
   1767     if(Curl_ssl->have_certinfo)
   1768       data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
   1769     else
   1770 #endif
   1771       result = CURLE_NOT_BUILT_IN;
   1772         break;
   1773   case CURLOPT_PINNEDPUBLICKEY:
   1774     /*
   1775      * Set pinned public key for SSL connection.
   1776      * Specify file name of the public key in DER format.
   1777      */
   1778 #ifdef USE_SSL
   1779     if(Curl_ssl->have_pinnedpubkey)
   1780       result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
   1781                               va_arg(param, char *));
   1782     else
   1783 #endif
   1784       result = CURLE_NOT_BUILT_IN;
   1785     break;
   1786   case CURLOPT_PROXY_PINNEDPUBLICKEY:
   1787     /*
   1788      * Set pinned public key for SSL connection.
   1789      * Specify file name of the public key in DER format.
   1790      */
   1791 #ifdef USE_SSL
   1792     if(Curl_ssl->have_pinnedpubkey)
   1793       result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
   1794                               va_arg(param, char *));
   1795     else
   1796 #endif
   1797       result = CURLE_NOT_BUILT_IN;
   1798     break;
   1799   case CURLOPT_CAINFO:
   1800     /*
   1801      * Set CA info for SSL connection. Specify file name of the CA certificate
   1802      */
   1803     result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
   1804                             va_arg(param, char *));
   1805     break;
   1806   case CURLOPT_PROXY_CAINFO:
   1807     /*
   1808      * Set CA info SSL connection for proxy. Specify file name of the
   1809      * CA certificate
   1810      */
   1811     result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
   1812                             va_arg(param, char *));
   1813     break;
   1814   case CURLOPT_CAPATH:
   1815     /*
   1816      * Set CA path info for SSL connection. Specify directory name of the CA
   1817      * certificates which have been prepared using openssl c_rehash utility.
   1818      */
   1819 #ifdef USE_SSL
   1820     if(Curl_ssl->have_ca_path)
   1821       /* This does not work on windows. */
   1822       result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
   1823                               va_arg(param, char *));
   1824     else
   1825 #endif
   1826       result = CURLE_NOT_BUILT_IN;
   1827     break;
   1828   case CURLOPT_PROXY_CAPATH:
   1829     /*
   1830      * Set CA path info for SSL connection proxy. Specify directory name of the
   1831      * CA certificates which have been prepared using openssl c_rehash utility.
   1832      */
   1833 #ifdef USE_SSL
   1834     if(Curl_ssl->have_ca_path)
   1835       /* This does not work on windows. */
   1836       result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
   1837                               va_arg(param, char *));
   1838     else
   1839 #endif
   1840       result = CURLE_NOT_BUILT_IN;
   1841     break;
   1842   case CURLOPT_CRLFILE:
   1843     /*
   1844      * Set CRL file info for SSL connection. Specify file name of the CRL
   1845      * to check certificates revocation
   1846      */
   1847     result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
   1848                             va_arg(param, char *));
   1849     break;
   1850   case CURLOPT_PROXY_CRLFILE:
   1851     /*
   1852      * Set CRL file info for SSL connection for proxy. Specify file name of the
   1853      * CRL to check certificates revocation
   1854      */
   1855     result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
   1856                             va_arg(param, char *));
   1857     break;
   1858   case CURLOPT_ISSUERCERT:
   1859     /*
   1860      * Set Issuer certificate file
   1861      * to check certificates issuer
   1862      */
   1863     result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
   1864                             va_arg(param, char *));
   1865     break;
   1866   case CURLOPT_TELNETOPTIONS:
   1867     /*
   1868      * Set a linked list of telnet options
   1869      */
   1870     data->set.telnet_options = va_arg(param, struct curl_slist *);
   1871     break;
   1872 
   1873   case CURLOPT_BUFFERSIZE:
   1874     /*
   1875      * The application kindly asks for a differently sized receive buffer.
   1876      * If it seems reasonable, we'll use it.
   1877      */
   1878     arg = va_arg(param, long);
   1879 
   1880     if(arg > READBUFFER_MAX)
   1881       arg = READBUFFER_MAX;
   1882     else if(arg < 1)
   1883       arg = READBUFFER_SIZE;
   1884     else if(arg < READBUFFER_MIN)
   1885       arg = READBUFFER_MIN;
   1886 
   1887     /* Resize if new size */
   1888     if(arg != data->set.buffer_size) {
   1889       char *newbuff = realloc(data->state.buffer, arg + 1);
   1890       if(!newbuff) {
   1891         DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
   1892         result = CURLE_OUT_OF_MEMORY;
   1893       }
   1894       else
   1895         data->state.buffer = newbuff;
   1896     }
   1897     data->set.buffer_size = arg;
   1898 
   1899     break;
   1900 
   1901   case CURLOPT_NOSIGNAL:
   1902     /*
   1903      * The application asks not to set any signal() or alarm() handlers,
   1904      * even when using a timeout.
   1905      */
   1906     data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
   1907     break;
   1908 
   1909   case CURLOPT_SHARE:
   1910   {
   1911     struct Curl_share *set;
   1912     set = va_arg(param, struct Curl_share *);
   1913 
   1914     /* disconnect from old share, if any */
   1915     if(data->share) {
   1916       Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
   1917 
   1918       if(data->dns.hostcachetype == HCACHE_SHARED) {
   1919         data->dns.hostcache = NULL;
   1920         data->dns.hostcachetype = HCACHE_NONE;
   1921       }
   1922 
   1923 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
   1924       if(data->share->cookies == data->cookies)
   1925         data->cookies = NULL;
   1926 #endif
   1927 
   1928       if(data->share->sslsession == data->state.session)
   1929         data->state.session = NULL;
   1930 
   1931       data->share->dirty--;
   1932 
   1933       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
   1934       data->share = NULL;
   1935     }
   1936 
   1937     /* use new share if it set */
   1938     data->share = set;
   1939     if(data->share) {
   1940 
   1941       Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
   1942 
   1943       data->share->dirty++;
   1944 
   1945       if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
   1946         /* use shared host cache */
   1947         data->dns.hostcache = &data->share->hostcache;
   1948         data->dns.hostcachetype = HCACHE_SHARED;
   1949       }
   1950 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
   1951       if(data->share->cookies) {
   1952         /* use shared cookie list, first free own one if any */
   1953         Curl_cookie_cleanup(data->cookies);
   1954         /* enable cookies since we now use a share that uses cookies! */
   1955         data->cookies = data->share->cookies;
   1956       }
   1957 #endif   /* CURL_DISABLE_HTTP */
   1958       if(data->share->sslsession) {
   1959         data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
   1960         data->state.session = data->share->sslsession;
   1961       }
   1962       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
   1963 
   1964     }
   1965     /* check for host cache not needed,
   1966      * it will be done by curl_easy_perform */
   1967   }
   1968   break;
   1969 
   1970   case CURLOPT_PRIVATE:
   1971     /*
   1972      * Set private data pointer.
   1973      */
   1974     data->set.private_data = va_arg(param, void *);
   1975     break;
   1976 
   1977   case CURLOPT_MAXFILESIZE:
   1978     /*
   1979      * Set the maximum size of a file to download.
   1980      */
   1981     arg = va_arg(param, long);
   1982     if(arg < 0)
   1983       return CURLE_BAD_FUNCTION_ARGUMENT;
   1984     data->set.max_filesize = arg;
   1985     break;
   1986 
   1987 #ifdef USE_SSL
   1988   case CURLOPT_USE_SSL:
   1989     /*
   1990      * Make transfers attempt to use SSL/TLS.
   1991      */
   1992     arg = va_arg(param, long);
   1993     if((arg < CURLUSESSL_NONE) || (arg > CURLUSESSL_ALL))
   1994       return CURLE_BAD_FUNCTION_ARGUMENT;
   1995     data->set.use_ssl = (curl_usessl)arg;
   1996     break;
   1997 
   1998   case CURLOPT_SSL_OPTIONS:
   1999     arg = va_arg(param, long);
   2000     data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
   2001     data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
   2002     break;
   2003 
   2004   case CURLOPT_PROXY_SSL_OPTIONS:
   2005     arg = va_arg(param, long);
   2006     data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
   2007     data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
   2008     break;
   2009 
   2010 #endif
   2011   case CURLOPT_FTPSSLAUTH:
   2012     /*
   2013      * Set a specific auth for FTP-SSL transfers.
   2014      */
   2015     arg = va_arg(param, long);
   2016     if((arg < CURLFTPAUTH_DEFAULT) || (arg > CURLFTPAUTH_TLS))
   2017       return CURLE_BAD_FUNCTION_ARGUMENT;
   2018     data->set.ftpsslauth = (curl_ftpauth)arg;
   2019     break;
   2020 
   2021   case CURLOPT_IPRESOLVE:
   2022     arg = va_arg(param, long);
   2023     if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
   2024       return CURLE_BAD_FUNCTION_ARGUMENT;
   2025     data->set.ipver = arg;
   2026     break;
   2027 
   2028   case CURLOPT_MAXFILESIZE_LARGE:
   2029     /*
   2030      * Set the maximum size of a file to download.
   2031      */
   2032     bigsize = va_arg(param, curl_off_t);
   2033     if(bigsize < 0)
   2034       return CURLE_BAD_FUNCTION_ARGUMENT;
   2035     data->set.max_filesize = bigsize;
   2036     break;
   2037 
   2038   case CURLOPT_TCP_NODELAY:
   2039     /*
   2040      * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
   2041      * algorithm
   2042      */
   2043     data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
   2044     break;
   2045 
   2046   case CURLOPT_FTP_ACCOUNT:
   2047     result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT],
   2048                             va_arg(param, char *));
   2049     break;
   2050 
   2051   case CURLOPT_IGNORE_CONTENT_LENGTH:
   2052     data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
   2053     break;
   2054 
   2055   case CURLOPT_CONNECT_ONLY:
   2056     /*
   2057      * No data transfer, set up connection and let application use the socket
   2058      */
   2059     data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
   2060     break;
   2061 
   2062   case CURLOPT_FTP_ALTERNATIVE_TO_USER:
   2063     result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
   2064                             va_arg(param, char *));
   2065     break;
   2066 
   2067   case CURLOPT_SOCKOPTFUNCTION:
   2068     /*
   2069      * socket callback function: called after socket() but before connect()
   2070      */
   2071     data->set.fsockopt = va_arg(param, curl_sockopt_callback);
   2072     break;
   2073 
   2074   case CURLOPT_SOCKOPTDATA:
   2075     /*
   2076      * socket callback data pointer. Might be NULL.
   2077      */
   2078     data->set.sockopt_client = va_arg(param, void *);
   2079     break;
   2080 
   2081   case CURLOPT_OPENSOCKETFUNCTION:
   2082     /*
   2083      * open/create socket callback function: called instead of socket(),
   2084      * before connect()
   2085      */
   2086     data->set.fopensocket = va_arg(param, curl_opensocket_callback);
   2087     break;
   2088 
   2089   case CURLOPT_OPENSOCKETDATA:
   2090     /*
   2091      * socket callback data pointer. Might be NULL.
   2092      */
   2093     data->set.opensocket_client = va_arg(param, void *);
   2094     break;
   2095 
   2096   case CURLOPT_CLOSESOCKETFUNCTION:
   2097     /*
   2098      * close socket callback function: called instead of close()
   2099      * when shutting down a connection
   2100      */
   2101     data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
   2102     break;
   2103 
   2104   case CURLOPT_CLOSESOCKETDATA:
   2105     /*
   2106      * socket callback data pointer. Might be NULL.
   2107      */
   2108     data->set.closesocket_client = va_arg(param, void *);
   2109     break;
   2110 
   2111   case CURLOPT_SSL_SESSIONID_CACHE:
   2112     data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
   2113       TRUE : FALSE;
   2114     data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
   2115     break;
   2116 
   2117 #if defined(USE_LIBSSH2) || defined(USE_LIBSSH)
   2118     /* we only include SSH options if explicitly built to support SSH */
   2119   case CURLOPT_SSH_AUTH_TYPES:
   2120     data->set.ssh_auth_types = va_arg(param, long);
   2121     break;
   2122 
   2123   case CURLOPT_SSH_PUBLIC_KEYFILE:
   2124     /*
   2125      * Use this file instead of the $HOME/.ssh/id_dsa.pub file
   2126      */
   2127     result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
   2128                             va_arg(param, char *));
   2129     break;
   2130 
   2131   case CURLOPT_SSH_PRIVATE_KEYFILE:
   2132     /*
   2133      * Use this file instead of the $HOME/.ssh/id_dsa file
   2134      */
   2135     result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
   2136                             va_arg(param, char *));
   2137     break;
   2138   case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
   2139     /*
   2140      * Option to allow for the MD5 of the host public key to be checked
   2141      * for validation purposes.
   2142      */
   2143     result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
   2144                             va_arg(param, char *));
   2145     break;
   2146 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
   2147   case CURLOPT_SSH_KNOWNHOSTS:
   2148     /*
   2149      * Store the file name to read known hosts from.
   2150      */
   2151     result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
   2152                             va_arg(param, char *));
   2153     break;
   2154 
   2155   case CURLOPT_SSH_KEYFUNCTION:
   2156     /* setting to NULL is fine since the ssh.c functions themselves will
   2157        then rever to use the internal default */
   2158     data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
   2159     break;
   2160 
   2161   case CURLOPT_SSH_KEYDATA:
   2162     /*
   2163      * Custom client data to pass to the SSH keyfunc callback
   2164      */
   2165     data->set.ssh_keyfunc_userp = va_arg(param, void *);
   2166     break;
   2167 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
   2168 #endif /* USE_LIBSSH2 */
   2169 
   2170   case CURLOPT_HTTP_TRANSFER_DECODING:
   2171     /*
   2172      * disable libcurl transfer encoding is used
   2173      */
   2174     data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
   2175     break;
   2176 
   2177   case CURLOPT_HTTP_CONTENT_DECODING:
   2178     /*
   2179      * raw data passed to the application when content encoding is used
   2180      */
   2181     data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
   2182     break;
   2183 
   2184   case CURLOPT_NEW_FILE_PERMS:
   2185     /*
   2186      * Uses these permissions instead of 0644
   2187      */
   2188     arg = va_arg(param, long);
   2189     if((arg < 0) || (arg > 0777))
   2190       return CURLE_BAD_FUNCTION_ARGUMENT;
   2191     data->set.new_file_perms = arg;
   2192     break;
   2193 
   2194   case CURLOPT_NEW_DIRECTORY_PERMS:
   2195     /*
   2196      * Uses these permissions instead of 0755
   2197      */
   2198     arg = va_arg(param, long);
   2199     if((arg < 0) || (arg > 0777))
   2200       return CURLE_BAD_FUNCTION_ARGUMENT;
   2201     data->set.new_directory_perms = arg;
   2202     break;
   2203 
   2204   case CURLOPT_ADDRESS_SCOPE:
   2205     /*
   2206      * We always get longs when passed plain numericals, but for this value we
   2207      * know that an unsigned int will always hold the value so we blindly
   2208      * typecast to this type
   2209      */
   2210     arg = va_arg(param, long);
   2211     if((arg < 0) || (arg > 0xf))
   2212       return CURLE_BAD_FUNCTION_ARGUMENT;
   2213     data->set.scope_id = curlx_sltoui(arg);
   2214     break;
   2215 
   2216   case CURLOPT_PROTOCOLS:
   2217     /* set the bitmask for the protocols that are allowed to be used for the
   2218        transfer, which thus helps the app which takes URLs from users or other
   2219        external inputs and want to restrict what protocol(s) to deal
   2220        with. Defaults to CURLPROTO_ALL. */
   2221     data->set.allowed_protocols = va_arg(param, long);
   2222     break;
   2223 
   2224   case CURLOPT_REDIR_PROTOCOLS:
   2225     /* set the bitmask for the protocols that libcurl is allowed to follow to,
   2226        as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
   2227        to be set in both bitmasks to be allowed to get redirected to. Defaults
   2228        to all protocols except FILE and SCP. */
   2229     data->set.redir_protocols = va_arg(param, long);
   2230     break;
   2231 
   2232   case CURLOPT_DEFAULT_PROTOCOL:
   2233     /* Set the protocol to use when the URL doesn't include any protocol */
   2234     result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
   2235                             va_arg(param, char *));
   2236     break;
   2237 
   2238   case CURLOPT_MAIL_FROM:
   2239     /* Set the SMTP mail originator */
   2240     result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM],
   2241                             va_arg(param, char *));
   2242     break;
   2243 
   2244   case CURLOPT_MAIL_AUTH:
   2245     /* Set the SMTP auth originator */
   2246     result = Curl_setstropt(&data->set.str[STRING_MAIL_AUTH],
   2247                             va_arg(param, char *));
   2248     break;
   2249 
   2250   case CURLOPT_MAIL_RCPT:
   2251     /* Set the list of mail recipients */
   2252     data->set.mail_rcpt = va_arg(param, struct curl_slist *);
   2253     break;
   2254 
   2255   case CURLOPT_SASL_IR:
   2256     /* Enable/disable SASL initial response */
   2257     data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
   2258     break;
   2259 
   2260   case CURLOPT_RTSP_REQUEST:
   2261   {
   2262     /*
   2263      * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
   2264      * Would this be better if the RTSPREQ_* were just moved into here?
   2265      */
   2266     long curl_rtspreq = va_arg(param, long);
   2267     Curl_RtspReq rtspreq = RTSPREQ_NONE;
   2268     switch(curl_rtspreq) {
   2269     case CURL_RTSPREQ_OPTIONS:
   2270       rtspreq = RTSPREQ_OPTIONS;
   2271       break;
   2272 
   2273     case CURL_RTSPREQ_DESCRIBE:
   2274       rtspreq = RTSPREQ_DESCRIBE;
   2275       break;
   2276 
   2277     case CURL_RTSPREQ_ANNOUNCE:
   2278       rtspreq = RTSPREQ_ANNOUNCE;
   2279       break;
   2280 
   2281     case CURL_RTSPREQ_SETUP:
   2282       rtspreq = RTSPREQ_SETUP;
   2283       break;
   2284 
   2285     case CURL_RTSPREQ_PLAY:
   2286       rtspreq = RTSPREQ_PLAY;
   2287       break;
   2288 
   2289     case CURL_RTSPREQ_PAUSE:
   2290       rtspreq = RTSPREQ_PAUSE;
   2291       break;
   2292 
   2293     case CURL_RTSPREQ_TEARDOWN:
   2294       rtspreq = RTSPREQ_TEARDOWN;
   2295       break;
   2296 
   2297     case CURL_RTSPREQ_GET_PARAMETER:
   2298       rtspreq = RTSPREQ_GET_PARAMETER;
   2299       break;
   2300 
   2301     case CURL_RTSPREQ_SET_PARAMETER:
   2302       rtspreq = RTSPREQ_SET_PARAMETER;
   2303       break;
   2304 
   2305     case CURL_RTSPREQ_RECORD:
   2306       rtspreq = RTSPREQ_RECORD;
   2307       break;
   2308 
   2309     case CURL_RTSPREQ_RECEIVE:
   2310       rtspreq = RTSPREQ_RECEIVE;
   2311       break;
   2312     default:
   2313       rtspreq = RTSPREQ_NONE;
   2314     }
   2315 
   2316     data->set.rtspreq = rtspreq;
   2317     break;
   2318   }
   2319 
   2320 
   2321   case CURLOPT_RTSP_SESSION_ID:
   2322     /*
   2323      * Set the RTSP Session ID manually. Useful if the application is
   2324      * resuming a previously established RTSP session
   2325      */
   2326     result = Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
   2327                             va_arg(param, char *));
   2328     break;
   2329 
   2330   case CURLOPT_RTSP_STREAM_URI:
   2331     /*
   2332      * Set the Stream URI for the RTSP request. Unless the request is
   2333      * for generic server options, the application will need to set this.
   2334      */
   2335     result = Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
   2336                             va_arg(param, char *));
   2337     break;
   2338 
   2339   case CURLOPT_RTSP_TRANSPORT:
   2340     /*
   2341      * The content of the Transport: header for the RTSP request
   2342      */
   2343     result = Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
   2344                             va_arg(param, char *));
   2345     break;
   2346 
   2347   case CURLOPT_RTSP_CLIENT_CSEQ:
   2348     /*
   2349      * Set the CSEQ number to issue for the next RTSP request. Useful if the
   2350      * application is resuming a previously broken connection. The CSEQ
   2351      * will increment from this new number henceforth.
   2352      */
   2353     data->state.rtsp_next_client_CSeq = va_arg(param, long);
   2354     break;
   2355 
   2356   case CURLOPT_RTSP_SERVER_CSEQ:
   2357     /* Same as the above, but for server-initiated requests */
   2358     data->state.rtsp_next_client_CSeq = va_arg(param, long);
   2359     break;
   2360 
   2361   case CURLOPT_INTERLEAVEDATA:
   2362     data->set.rtp_out = va_arg(param, void *);
   2363     break;
   2364   case CURLOPT_INTERLEAVEFUNCTION:
   2365     /* Set the user defined RTP write function */
   2366     data->set.fwrite_rtp = va_arg(param, curl_write_callback);
   2367     break;
   2368 
   2369   case CURLOPT_WILDCARDMATCH:
   2370     data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
   2371     break;
   2372   case CURLOPT_CHUNK_BGN_FUNCTION:
   2373     data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
   2374     break;
   2375   case CURLOPT_CHUNK_END_FUNCTION:
   2376     data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
   2377     break;
   2378   case CURLOPT_FNMATCH_FUNCTION:
   2379     data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
   2380     break;
   2381   case CURLOPT_CHUNK_DATA:
   2382     data->wildcard.customptr = va_arg(param, void *);
   2383     break;
   2384   case CURLOPT_FNMATCH_DATA:
   2385     data->set.fnmatch_data = va_arg(param, void *);
   2386     break;
   2387 #ifdef USE_TLS_SRP
   2388   case CURLOPT_TLSAUTH_USERNAME:
   2389     result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
   2390                             va_arg(param, char *));
   2391     if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
   2392       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
   2393     break;
   2394   case CURLOPT_PROXY_TLSAUTH_USERNAME:
   2395     result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
   2396                             va_arg(param, char *));
   2397     if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
   2398        !data->set.proxy_ssl.authtype)
   2399       data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
   2400     break;
   2401   case CURLOPT_TLSAUTH_PASSWORD:
   2402     result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
   2403                             va_arg(param, char *));
   2404     if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
   2405       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
   2406     break;
   2407   case CURLOPT_PROXY_TLSAUTH_PASSWORD:
   2408     result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
   2409                             va_arg(param, char *));
   2410     if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
   2411        !data->set.proxy_ssl.authtype)
   2412       data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
   2413     break;
   2414   case CURLOPT_TLSAUTH_TYPE:
   2415     argptr = va_arg(param, char *);
   2416     if(!argptr ||
   2417        strncasecompare(argptr, "SRP", strlen("SRP")))
   2418       data->set.ssl.authtype = CURL_TLSAUTH_SRP;
   2419     else
   2420       data->set.ssl.authtype = CURL_TLSAUTH_NONE;
   2421     break;
   2422   case CURLOPT_PROXY_TLSAUTH_TYPE:
   2423     argptr = va_arg(param, char *);
   2424     if(!argptr ||
   2425        strncasecompare(argptr, "SRP", strlen("SRP")))
   2426       data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
   2427     else
   2428       data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
   2429     break;
   2430 #endif
   2431   case CURLOPT_DNS_SERVERS:
   2432     result = Curl_set_dns_servers(data, va_arg(param, char *));
   2433     break;
   2434   case CURLOPT_DNS_INTERFACE:
   2435     result = Curl_set_dns_interface(data, va_arg(param, char *));
   2436     break;
   2437   case CURLOPT_DNS_LOCAL_IP4:
   2438     result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
   2439     break;
   2440   case CURLOPT_DNS_LOCAL_IP6:
   2441     result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
   2442     break;
   2443 
   2444   case CURLOPT_TCP_KEEPALIVE:
   2445     data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
   2446     break;
   2447   case CURLOPT_TCP_KEEPIDLE:
   2448     arg = va_arg(param, long);
   2449     if(arg < 0)
   2450       return CURLE_BAD_FUNCTION_ARGUMENT;
   2451     data->set.tcp_keepidle = arg;
   2452     break;
   2453   case CURLOPT_TCP_KEEPINTVL:
   2454     arg = va_arg(param, long);
   2455     if(arg < 0)
   2456       return CURLE_BAD_FUNCTION_ARGUMENT;
   2457     data->set.tcp_keepintvl = arg;
   2458     break;
   2459   case CURLOPT_TCP_FASTOPEN:
   2460 #if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \
   2461    defined(TCP_FASTOPEN_CONNECT)
   2462     data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
   2463 #else
   2464     result = CURLE_NOT_BUILT_IN;
   2465 #endif
   2466     break;
   2467   case CURLOPT_SSL_ENABLE_NPN:
   2468     data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
   2469     break;
   2470   case CURLOPT_SSL_ENABLE_ALPN:
   2471     data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
   2472     break;
   2473 
   2474 #ifdef USE_UNIX_SOCKETS
   2475   case CURLOPT_UNIX_SOCKET_PATH:
   2476     data->set.abstract_unix_socket = FALSE;
   2477     result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
   2478                             va_arg(param, char *));
   2479     break;
   2480   case CURLOPT_ABSTRACT_UNIX_SOCKET:
   2481     data->set.abstract_unix_socket = TRUE;
   2482     result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
   2483                             va_arg(param, char *));
   2484     break;
   2485 #endif
   2486 
   2487   case CURLOPT_PATH_AS_IS:
   2488     data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
   2489     break;
   2490   case CURLOPT_PIPEWAIT:
   2491     data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
   2492     break;
   2493   case CURLOPT_STREAM_WEIGHT:
   2494 #ifndef USE_NGHTTP2
   2495     return CURLE_NOT_BUILT_IN;
   2496 #else
   2497     arg = va_arg(param, long);
   2498     if((arg >= 1) && (arg <= 256))
   2499       data->set.stream_weight = (int)arg;
   2500     break;
   2501 #endif
   2502   case CURLOPT_STREAM_DEPENDS:
   2503   case CURLOPT_STREAM_DEPENDS_E:
   2504   {
   2505 #ifndef USE_NGHTTP2
   2506     return CURLE_NOT_BUILT_IN;
   2507 #else
   2508     struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
   2509     if(!dep || GOOD_EASY_HANDLE(dep)) {
   2510       if(data->set.stream_depends_on) {
   2511         Curl_http2_remove_child(data->set.stream_depends_on, data);
   2512       }
   2513       Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
   2514     }
   2515     break;
   2516 #endif
   2517   }
   2518   case CURLOPT_CONNECT_TO:
   2519     data->set.connect_to = va_arg(param, struct curl_slist *);
   2520     break;
   2521   case CURLOPT_SUPPRESS_CONNECT_HEADERS:
   2522     data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
   2523     break;
   2524   case CURLOPT_SSH_COMPRESSION:
   2525     data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
   2526     break;
   2527   default:
   2528     /* unknown tag and its companion, just ignore: */
   2529     result = CURLE_UNKNOWN_OPTION;
   2530     break;
   2531   }
   2532 
   2533   return result;
   2534 }
   2535 
   2536 /*
   2537  * curl_easy_setopt() is the external interface for setting options on an
   2538  * easy handle.
   2539  */
   2540 
   2541 #undef curl_easy_setopt
   2542 CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
   2543 {
   2544   va_list arg;
   2545   CURLcode result;
   2546 
   2547   if(!data)
   2548     return CURLE_BAD_FUNCTION_ARGUMENT;
   2549 
   2550   va_start(arg, tag);
   2551 
   2552   result = Curl_vsetopt(data, tag, arg);
   2553 
   2554   va_end(arg);
   2555   return result;
   2556 }
   2557