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