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