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