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