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