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 break;
2137
2138#ifndef CURL_DISABLE_PROXY
2139 case CURLOPT_PROXY_SSL_OPTIONS:
2140 arg = va_arg(param, long);
2141 data->set.proxy_ssl.enable_beast =
2142 (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE);
2143 data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
2144 break;
2145#endif
2146
2147#endif
2148 case CURLOPT_IPRESOLVE:
2149 arg = va_arg(param, long);
2150 if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
2151 return CURLE_BAD_FUNCTION_ARGUMENT;
2152 data->set.ipver = arg;
2153 break;
2154
2155 case CURLOPT_MAXFILESIZE_LARGE:
2156 /*
2157 * Set the maximum size of a file to download.
2158 */
2159 bigsize = va_arg(param, curl_off_t);
2160 if(bigsize < 0)
2161 return CURLE_BAD_FUNCTION_ARGUMENT;
2162 data->set.max_filesize = bigsize;
2163 break;
2164
2165 case CURLOPT_TCP_NODELAY:
2166 /*
2167 * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
2168 * algorithm
2169 */
2170 data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
2171 break;
2172
2173 case CURLOPT_IGNORE_CONTENT_LENGTH:
2174 data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
2175 break;
2176
2177 case CURLOPT_CONNECT_ONLY:
2178 /*
2179 * No data transfer, set up connection and let application use the socket
2180 */
2181 data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
2182 break;
2183
2184 case CURLOPT_SOCKOPTFUNCTION:
2185 /*
2186 * socket callback function: called after socket() but before connect()
2187 */
2188 data->set.fsockopt = va_arg(param, curl_sockopt_callback);
2189 break;
2190
2191 case CURLOPT_SOCKOPTDATA:
2192 /*
2193 * socket callback data pointer. Might be NULL.
2194 */
2195 data->set.sockopt_client = va_arg(param, void *);
2196 break;
2197
2198 case CURLOPT_OPENSOCKETFUNCTION:
2199 /*
2200 * open/create socket callback function: called instead of socket(),
2201 * before connect()
2202 */
2203 data->set.fopensocket = va_arg(param, curl_opensocket_callback);
2204 break;
2205
2206 case CURLOPT_OPENSOCKETDATA:
2207 /*
2208 * socket callback data pointer. Might be NULL.
2209 */
2210 data->set.opensocket_client = va_arg(param, void *);
2211 break;
2212
2213 case CURLOPT_CLOSESOCKETFUNCTION:
2214 /*
2215 * close socket callback function: called instead of close()
2216 * when shutting down a connection
2217 */
2218 data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
2219 break;
2220
2221 case CURLOPT_RESOLVER_START_FUNCTION:
2222 /*
2223 * resolver start callback function: called before a new resolver request
2224 * is started
2225 */
2226 data->set.resolver_start = va_arg(param, curl_resolver_start_callback);
2227 break;
2228
2229 case CURLOPT_RESOLVER_START_DATA:
2230 /*
2231 * resolver start callback data pointer. Might be NULL.
2232 */
2233 data->set.resolver_start_client = va_arg(param, void *);
2234 break;
2235
2236 case CURLOPT_CLOSESOCKETDATA:
2237 /*
2238 * socket callback data pointer. Might be NULL.
2239 */
2240 data->set.closesocket_client = va_arg(param, void *);
2241 break;
2242
2243 case CURLOPT_SSL_SESSIONID_CACHE:
2244 data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ?
2245 TRUE : FALSE;
2246 data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
2247 break;
2248
2249#ifdef USE_SSH
2250 /* we only include SSH options if explicitly built to support SSH */
2251 case CURLOPT_SSH_AUTH_TYPES:
2252 data->set.ssh_auth_types = va_arg(param, long);
2253 break;
2254
2255 case CURLOPT_SSH_PUBLIC_KEYFILE:
2256 /*
2257 * Use this file instead of the $HOME/.ssh/id_dsa.pub file
2258 */
2259 result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
2260 va_arg(param, char *));
2261 break;
2262
2263 case CURLOPT_SSH_PRIVATE_KEYFILE:
2264 /*
2265 * Use this file instead of the $HOME/.ssh/id_dsa file
2266 */
2267 result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
2268 va_arg(param, char *));
2269 break;
2270 case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
2271 /*
2272 * Option to allow for the MD5 of the host public key to be checked
2273 * for validation purposes.
2274 */
2275 result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
2276 va_arg(param, char *));
2277 break;
2278
2279 case CURLOPT_SSH_KNOWNHOSTS:
2280 /*
2281 * Store the file name to read known hosts from.
2282 */
2283 result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
2284 va_arg(param, char *));
2285 break;
2286
2287 case CURLOPT_SSH_KEYFUNCTION:
2288 /* setting to NULL is fine since the ssh.c functions themselves will
2289 then rever to use the internal default */
2290 data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
2291 break;
2292
2293 case CURLOPT_SSH_KEYDATA:
2294 /*
2295 * Custom client data to pass to the SSH keyfunc callback
2296 */
2297 data->set.ssh_keyfunc_userp = va_arg(param, void *);
2298 break;
2299
2300 case CURLOPT_SSH_COMPRESSION:
2301 data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE;
2302 break;
2303#endif /* USE_SSH */
2304
2305 case CURLOPT_HTTP_TRANSFER_DECODING:
2306 /*
2307 * disable libcurl transfer encoding is used
2308 */
2309 data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
2310 break;
2311
2312 case CURLOPT_HTTP_CONTENT_DECODING:
2313 /*
2314 * raw data passed to the application when content encoding is used
2315 */
2316 data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
2317 break;
2318
2319#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
2320 case CURLOPT_NEW_FILE_PERMS:
2321 /*
2322 * Uses these permissions instead of 0644
2323 */
2324 arg = va_arg(param, long);
2325 if((arg < 0) || (arg > 0777))
2326 return CURLE_BAD_FUNCTION_ARGUMENT;
2327 data->set.new_file_perms = arg;
2328 break;
2329
2330 case CURLOPT_NEW_DIRECTORY_PERMS:
2331 /*
2332 * Uses these permissions instead of 0755
2333 */
2334 arg = va_arg(param, long);
2335 if((arg < 0) || (arg > 0777))
2336 return CURLE_BAD_FUNCTION_ARGUMENT;
2337 data->set.new_directory_perms = arg;
2338 break;
2339#endif
2340
2341 case CURLOPT_ADDRESS_SCOPE:
2342 /*
2343 * Use this scope id when using IPv6
2344 * We always get longs when passed plain numericals so we should check
2345 * that the value fits into an unsigned 32 bit integer.
2346 */
2347 uarg = va_arg(param, unsigned long);
2348#if SIZEOF_LONG > 4
2349 if(uarg > UINT_MAX)
2350 return CURLE_BAD_FUNCTION_ARGUMENT;
2351#endif
2352 data->set.scope_id = (unsigned int)uarg;
2353 break;
2354
2355 case CURLOPT_PROTOCOLS:
2356 /* set the bitmask for the protocols that are allowed to be used for the
2357 transfer, which thus helps the app which takes URLs from users or other
2358 external inputs and want to restrict what protocol(s) to deal
2359 with. Defaults to CURLPROTO_ALL. */
2360 data->set.allowed_protocols = va_arg(param, long);
2361 break;
2362
2363 case CURLOPT_REDIR_PROTOCOLS:
2364 /* set the bitmask for the protocols that libcurl is allowed to follow to,
2365 as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
2366 to be set in both bitmasks to be allowed to get redirected to. */
2367 data->set.redir_protocols = va_arg(param, long);
2368 break;
2369
2370 case CURLOPT_DEFAULT_PROTOCOL:
2371 /* Set the protocol to use when the URL doesn't include any protocol */
2372 result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
2373 va_arg(param, char *));
2374 break;
2375#ifndef CURL_DISABLE_SMTP
2376 case CURLOPT_MAIL_FROM:
2377 /* Set the SMTP mail originator */
2378 result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM],
2379 va_arg(param, char *));
2380 break;
2381
2382 case CURLOPT_MAIL_AUTH:
2383 /* Set the SMTP auth originator */
2384 result = Curl_setstropt(&data->set.str[STRING_MAIL_AUTH],
2385 va_arg(param, char *));
2386 break;
2387
2388 case CURLOPT_MAIL_RCPT:
2389 /* Set the list of mail recipients */
2390 data->set.mail_rcpt = va_arg(param, struct curl_slist *);
2391 break;
2392#endif
2393
2394 case CURLOPT_SASL_AUTHZID:
2395 /* Authorisation identity (identity to act as) */
2396 result = Curl_setstropt(&data->set.str[STRING_SASL_AUTHZID],
2397 va_arg(param, char *));
2398 break;
2399
2400 case CURLOPT_SASL_IR:
2401 /* Enable/disable SASL initial response */
2402 data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
2403 break;
2404#ifndef CURL_DISABLE_RTSP
2405 case CURLOPT_RTSP_REQUEST:
2406 {
2407 /*
2408 * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
2409 * Would this be better if the RTSPREQ_* were just moved into here?
2410 */
2411 long curl_rtspreq = va_arg(param, long);
2412 Curl_RtspReq rtspreq = RTSPREQ_NONE;
2413 switch(curl_rtspreq) {
2414 case CURL_RTSPREQ_OPTIONS:
2415 rtspreq = RTSPREQ_OPTIONS;
2416 break;
2417
2418 case CURL_RTSPREQ_DESCRIBE:
2419 rtspreq = RTSPREQ_DESCRIBE;
2420 break;
2421
2422 case CURL_RTSPREQ_ANNOUNCE:
2423 rtspreq = RTSPREQ_ANNOUNCE;
2424 break;
2425
2426 case CURL_RTSPREQ_SETUP:
2427 rtspreq = RTSPREQ_SETUP;
2428 break;
2429
2430 case CURL_RTSPREQ_PLAY:
2431 rtspreq = RTSPREQ_PLAY;
2432 break;
2433
2434 case CURL_RTSPREQ_PAUSE:
2435 rtspreq = RTSPREQ_PAUSE;
2436 break;
2437
2438 case CURL_RTSPREQ_TEARDOWN:
2439 rtspreq = RTSPREQ_TEARDOWN;
2440 break;
2441
2442 case CURL_RTSPREQ_GET_PARAMETER:
2443 rtspreq = RTSPREQ_GET_PARAMETER;
2444 break;
2445
2446 case CURL_RTSPREQ_SET_PARAMETER:
2447 rtspreq = RTSPREQ_SET_PARAMETER;
2448 break;
2449
2450 case CURL_RTSPREQ_RECORD:
2451 rtspreq = RTSPREQ_RECORD;
2452 break;
2453
2454 case CURL_RTSPREQ_RECEIVE:
2455 rtspreq = RTSPREQ_RECEIVE;
2456 break;
2457 default:
2458 rtspreq = RTSPREQ_NONE;
2459 }
2460
2461 data->set.rtspreq = rtspreq;
2462 break;
2463 }
2464
2465
2466 case CURLOPT_RTSP_SESSION_ID:
2467 /*
2468 * Set the RTSP Session ID manually. Useful if the application is
2469 * resuming a previously established RTSP session
2470 */
2471 result = Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
2472 va_arg(param, char *));
2473 break;
2474
2475 case CURLOPT_RTSP_STREAM_URI:
2476 /*
2477 * Set the Stream URI for the RTSP request. Unless the request is
2478 * for generic server options, the application will need to set this.
2479 */
2480 result = Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
2481 va_arg(param, char *));
2482 break;
2483
2484 case CURLOPT_RTSP_TRANSPORT:
2485 /*
2486 * The content of the Transport: header for the RTSP request
2487 */
2488 result = Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
2489 va_arg(param, char *));
2490 break;
2491
2492 case CURLOPT_RTSP_CLIENT_CSEQ:
2493 /*
2494 * Set the CSEQ number to issue for the next RTSP request. Useful if the
2495 * application is resuming a previously broken connection. The CSEQ
2496 * will increment from this new number henceforth.
2497 */
2498 data->state.rtsp_next_client_CSeq = va_arg(param, long);
2499 break;
2500
2501 case CURLOPT_RTSP_SERVER_CSEQ:
2502 /* Same as the above, but for server-initiated requests */
2503 data->state.rtsp_next_server_CSeq = va_arg(param, long);
2504 break;
2505
2506 case CURLOPT_INTERLEAVEDATA:
2507 data->set.rtp_out = va_arg(param, void *);
2508 break;
2509 case CURLOPT_INTERLEAVEFUNCTION:
2510 /* Set the user defined RTP write function */
2511 data->set.fwrite_rtp = va_arg(param, curl_write_callback);
2512 break;
2513#endif
2514#ifndef CURL_DISABLE_FTP
2515 case CURLOPT_WILDCARDMATCH:
2516 data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE;
2517 break;
2518 case CURLOPT_CHUNK_BGN_FUNCTION:
2519 data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
2520 break;
2521 case CURLOPT_CHUNK_END_FUNCTION:
2522 data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
2523 break;
2524 case CURLOPT_FNMATCH_FUNCTION:
2525 data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
2526 break;
2527 case CURLOPT_CHUNK_DATA:
2528 data->wildcard.customptr = va_arg(param, void *);
2529 break;
2530 case CURLOPT_FNMATCH_DATA:
2531 data->set.fnmatch_data = va_arg(param, void *);
2532 break;
2533#endif
2534#ifdef USE_TLS_SRP
2535 case CURLOPT_TLSAUTH_USERNAME:
2536 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
2537 va_arg(param, char *));
2538 if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
2539 data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2540 break;
2541 case CURLOPT_PROXY_TLSAUTH_USERNAME:
2542 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
2543 va_arg(param, char *));
2544 if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
2545 !data->set.proxy_ssl.authtype)
2546 data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2547 break;
2548 case CURLOPT_TLSAUTH_PASSWORD:
2549 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
2550 va_arg(param, char *));
2551 if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
2552 data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2553 break;
2554 case CURLOPT_PROXY_TLSAUTH_PASSWORD:
2555 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
2556 va_arg(param, char *));
2557 if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
2558 !data->set.proxy_ssl.authtype)
2559 data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
2560 break;
2561 case CURLOPT_TLSAUTH_TYPE:
2562 argptr = va_arg(param, char *);
2563 if(!argptr ||
2564 strncasecompare(argptr, "SRP", strlen("SRP")))
2565 data->set.ssl.authtype = CURL_TLSAUTH_SRP;
2566 else
2567 data->set.ssl.authtype = CURL_TLSAUTH_NONE;
2568 break;
2569 case CURLOPT_PROXY_TLSAUTH_TYPE:
2570 argptr = va_arg(param, char *);
2571 if(!argptr ||
2572 strncasecompare(argptr, "SRP", strlen("SRP")))
2573 data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
2574 else
2575 data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
2576 break;
2577#endif
2578#ifdef USE_ARES
2579 case CURLOPT_DNS_SERVERS:
2580 result = Curl_set_dns_servers(data, va_arg(param, char *));
2581 break;
2582 case CURLOPT_DNS_INTERFACE:
2583 result = Curl_set_dns_interface(data, va_arg(param, char *));
2584 break;
2585 case CURLOPT_DNS_LOCAL_IP4:
2586 result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
2587 break;
2588 case CURLOPT_DNS_LOCAL_IP6:
2589 result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
2590 break;
2591#endif
2592 case CURLOPT_TCP_KEEPALIVE:
2593 data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
2594 break;
2595 case CURLOPT_TCP_KEEPIDLE:
2596 arg = va_arg(param, long);
2597 if(arg < 0)
2598 return CURLE_BAD_FUNCTION_ARGUMENT;
2599 data->set.tcp_keepidle = arg;
2600 break;
2601 case CURLOPT_TCP_KEEPINTVL:
2602 arg = va_arg(param, long);
2603 if(arg < 0)
2604 return CURLE_BAD_FUNCTION_ARGUMENT;
2605 data->set.tcp_keepintvl = arg;
2606 break;
2607 case CURLOPT_TCP_FASTOPEN:
2608#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \
2609 defined(TCP_FASTOPEN_CONNECT)
2610 data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
2611#else
2612 result = CURLE_NOT_BUILT_IN;
2613#endif
2614 break;
2615#ifdef USE_NGHTTP2
2616 case CURLOPT_SSL_ENABLE_NPN:
2617 data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
2618 break;
2619 case CURLOPT_SSL_ENABLE_ALPN:
2620 data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
2621 break;
2622#endif
2623#ifdef USE_UNIX_SOCKETS
2624 case CURLOPT_UNIX_SOCKET_PATH:
2625 data->set.abstract_unix_socket = FALSE;
2626 result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
2627 va_arg(param, char *));
2628 break;
2629 case CURLOPT_ABSTRACT_UNIX_SOCKET:
2630 data->set.abstract_unix_socket = TRUE;
2631 result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
2632 va_arg(param, char *));
2633 break;
2634#endif
2635
2636 case CURLOPT_PATH_AS_IS:
2637 data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
2638 break;
2639 case CURLOPT_PIPEWAIT:
2640 data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
2641 break;
2642 case CURLOPT_STREAM_WEIGHT:
2643#ifndef USE_NGHTTP2
2644 return CURLE_NOT_BUILT_IN;
2645#else
2646 arg = va_arg(param, long);
2647 if((arg >= 1) && (arg <= 256))
2648 data->set.stream_weight = (int)arg;
2649 break;
2650#endif
2651 case CURLOPT_STREAM_DEPENDS:
2652 case CURLOPT_STREAM_DEPENDS_E:
2653 {
2654#ifndef USE_NGHTTP2
2655 return CURLE_NOT_BUILT_IN;
2656#else
2657 struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
2658 if(!dep || GOOD_EASY_HANDLE(dep)) {
2659 if(data->set.stream_depends_on) {
2660 Curl_http2_remove_child(data->set.stream_depends_on, data);
2661 }
2662 Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
2663 }
2664 break;
2665#endif
2666 }
2667 case CURLOPT_CONNECT_TO:
2668 data->set.connect_to = va_arg(param, struct curl_slist *);
2669 break;
2670 case CURLOPT_SUPPRESS_CONNECT_HEADERS:
2671 data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE;
2672 break;
2673 case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
2674 arg = va_arg(param, long);
2675 if(arg < 0)
2676 return CURLE_BAD_FUNCTION_ARGUMENT;
2677 data->set.happy_eyeballs_timeout = arg;
2678 break;
2679#ifndef CURL_DISABLE_SHUFFLE_DNS
2680 case CURLOPT_DNS_SHUFFLE_ADDRESSES:
2681 data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE;
2682 break;
2683#endif
2684 case CURLOPT_DISALLOW_USERNAME_IN_URL:
2685 data->set.disallow_username_in_url =
2686 (0 != va_arg(param, long)) ? TRUE : FALSE;
2687 break;
2688#ifndef CURL_DISABLE_DOH
2689 case CURLOPT_DOH_URL:
2690 result = Curl_setstropt(&data->set.str[STRING_DOH],
2691 va_arg(param, char *));
2692 data->set.doh = data->set.str[STRING_DOH]?TRUE:FALSE;
2693 break;
2694#endif
2695 case CURLOPT_UPKEEP_INTERVAL_MS:
2696 arg = va_arg(param, long);
2697 if(arg < 0)
2698 return CURLE_BAD_FUNCTION_ARGUMENT;
2699 data->set.upkeep_interval_ms = arg;
2700 break;
2701 case CURLOPT_MAXAGE_CONN:
2702 arg = va_arg(param, long);
2703 if(arg < 0)
2704 return CURLE_BAD_FUNCTION_ARGUMENT;
2705 data->set.maxage_conn = arg;
2706 break;
2707 case CURLOPT_TRAILERFUNCTION:
2708#ifndef CURL_DISABLE_HTTP
2709 data->set.trailer_callback = va_arg(param, curl_trailer_callback);
2710#endif
2711 break;
2712 case CURLOPT_TRAILERDATA:
2713#ifndef CURL_DISABLE_HTTP
2714 data->set.trailer_data = va_arg(param, void *);
2715#endif
2716 break;
2717#ifdef USE_ALTSVC
2718 case CURLOPT_ALTSVC:
2719 if(!data->asi) {
2720 data->asi = Curl_altsvc_init();
2721 if(!data->asi)
2722 return CURLE_OUT_OF_MEMORY;
2723 }
2724 argptr = va_arg(param, char *);
2725 result = Curl_setstropt(&data->set.str[STRING_ALTSVC], argptr);
2726 if(result)
2727 return result;
2728 if(argptr)
2729 (void)Curl_altsvc_load(data->asi, argptr);
2730 break;
2731 case CURLOPT_ALTSVC_CTRL:
2732 if(!data->asi) {
2733 data->asi = Curl_altsvc_init();
2734 if(!data->asi)
2735 return CURLE_OUT_OF_MEMORY;
2736 }
2737 arg = va_arg(param, long);
2738 result = Curl_altsvc_ctrl(data->asi, arg);
2739 if(result)
2740 return result;
2741 break;
2742#endif
2743 default:
2744 /* unknown tag and its companion, just ignore: */
2745 result = CURLE_UNKNOWN_OPTION;
2746 break;
2747 }
2748
2749 return result;
2750}
2751
2752/*
2753 * curl_easy_setopt() is the external interface for setting options on an
2754 * easy handle.
2755 *
2756 * NOTE: This is one of few API functions that are allowed to be called from
2757 * within a callback.
2758 */
2759
2760#undef curl_easy_setopt
2761CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...)
2762{
2763 va_list arg;
2764 CURLcode result;
2765
2766 if(!data)
2767 return CURLE_BAD_FUNCTION_ARGUMENT;
2768
2769 va_start(arg, tag);
2770
2771 result = Curl_vsetopt(data, tag, arg);
2772
2773 va_end(arg);
2774 return result;
2775}
2776