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