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