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