1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2016, 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 #ifndef CURL_DISABLE_TFTP
26
27 #ifdef HAVE_NETINET_IN_H
28 #include <netinet/in.h>
29 #endif
30 #ifdef HAVE_NETDB_H
31 #include <netdb.h>
32 #endif
33 #ifdef HAVE_ARPA_INET_H
34 #include <arpa/inet.h>
35 #endif
36 #ifdef HAVE_NET_IF_H
37 #include <net/if.h>
38 #endif
39 #ifdef HAVE_SYS_IOCTL_H
40 #include <sys/ioctl.h>
41 #endif
42
43 #ifdef HAVE_SYS_PARAM_H
44 #include <sys/param.h>
45 #endif
46
47 #include "urldata.h"
48 #include <curl/curl.h>
49 #include "transfer.h"
50 #include "sendf.h"
51 #include "tftp.h"
52 #include "progress.h"
53 #include "connect.h"
54 #include "strerror.h"
55 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
56 #include "multiif.h"
57 #include "url.h"
58 #include "strcase.h"
59 #include "speedcheck.h"
60 #include "select.h"
61 #include "escape.h"
62
63 /* The last 3 #include files should be in this order */
64 #include "curl_printf.h"
65 #include "curl_memory.h"
66 #include "memdebug.h"
67
68 /* RFC2348 allows the block size to be negotiated */
69 #define TFTP_BLKSIZE_DEFAULT 512
70 #define TFTP_BLKSIZE_MIN 8
71 #define TFTP_BLKSIZE_MAX 65464
72 #define TFTP_OPTION_BLKSIZE "blksize"
73
74 /* from RFC2349: */
75 #define TFTP_OPTION_TSIZE "tsize"
76 #define TFTP_OPTION_INTERVAL "timeout"
77
78 typedef enum {
79 TFTP_MODE_NETASCII=0,
80 TFTP_MODE_OCTET
81 } tftp_mode_t;
82
83 typedef enum {
84 TFTP_STATE_START=0,
85 TFTP_STATE_RX,
86 TFTP_STATE_TX,
87 TFTP_STATE_FIN
88 } tftp_state_t;
89
90 typedef enum {
91 TFTP_EVENT_NONE = -1,
92 TFTP_EVENT_INIT = 0,
93 TFTP_EVENT_RRQ = 1,
94 TFTP_EVENT_WRQ = 2,
95 TFTP_EVENT_DATA = 3,
96 TFTP_EVENT_ACK = 4,
97 TFTP_EVENT_ERROR = 5,
98 TFTP_EVENT_OACK = 6,
99 TFTP_EVENT_TIMEOUT
100 } tftp_event_t;
101
102 typedef enum {
103 TFTP_ERR_UNDEF=0,
104 TFTP_ERR_NOTFOUND,
105 TFTP_ERR_PERM,
106 TFTP_ERR_DISKFULL,
107 TFTP_ERR_ILLEGAL,
108 TFTP_ERR_UNKNOWNID,
109 TFTP_ERR_EXISTS,
110 TFTP_ERR_NOSUCHUSER, /* This will never be triggered by this code */
111
112 /* The remaining error codes are internal to curl */
113 TFTP_ERR_NONE = -100,
114 TFTP_ERR_TIMEOUT,
115 TFTP_ERR_NORESPONSE
116 } tftp_error_t;
117
118 typedef struct tftp_packet {
119 unsigned char *data;
120 } tftp_packet_t;
121
122 typedef struct tftp_state_data {
123 tftp_state_t state;
124 tftp_mode_t mode;
125 tftp_error_t error;
126 tftp_event_t event;
127 struct connectdata *conn;
128 curl_socket_t sockfd;
129 int retries;
130 int retry_time;
131 int retry_max;
132 time_t start_time;
133 time_t max_time;
134 time_t rx_time;
135 unsigned short block;
136 struct Curl_sockaddr_storage local_addr;
137 struct Curl_sockaddr_storage remote_addr;
138 curl_socklen_t remote_addrlen;
139 int rbytes;
140 int sbytes;
141 int blksize;
142 int requested_blksize;
143 tftp_packet_t rpacket;
144 tftp_packet_t spacket;
145 } tftp_state_data_t;
146
147
148 /* Forward declarations */
149 static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event);
150 static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event);
151 static CURLcode tftp_connect(struct connectdata *conn, bool *done);
152 static CURLcode tftp_disconnect(struct connectdata *conn,
153 bool dead_connection);
154 static CURLcode tftp_do(struct connectdata *conn, bool *done);
155 static CURLcode tftp_done(struct connectdata *conn,
156 CURLcode, bool premature);
157 static CURLcode tftp_setup_connection(struct connectdata * conn);
158 static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done);
159 static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done);
160 static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks,
161 int numsocks);
162 static CURLcode tftp_translate_code(tftp_error_t error);
163
164
165 /*
166 * TFTP protocol handler.
167 */
168
169 const struct Curl_handler Curl_handler_tftp = {
170 "TFTP", /* scheme */
171 tftp_setup_connection, /* setup_connection */
172 tftp_do, /* do_it */
173 tftp_done, /* done */
174 ZERO_NULL, /* do_more */
175 tftp_connect, /* connect_it */
176 tftp_multi_statemach, /* connecting */
177 tftp_doing, /* doing */
178 tftp_getsock, /* proto_getsock */
179 tftp_getsock, /* doing_getsock */
180 ZERO_NULL, /* domore_getsock */
181 ZERO_NULL, /* perform_getsock */
182 tftp_disconnect, /* disconnect */
183 ZERO_NULL, /* readwrite */
184 PORT_TFTP, /* defport */
185 CURLPROTO_TFTP, /* protocol */
186 PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */
187 };
188
189 /**********************************************************
190 *
191 * tftp_set_timeouts -
192 *
193 * Set timeouts based on state machine state.
194 * Use user provided connect timeouts until DATA or ACK
195 * packet is received, then use user-provided transfer timeouts
196 *
197 *
198 **********************************************************/
tftp_set_timeouts(tftp_state_data_t * state)199 static CURLcode tftp_set_timeouts(tftp_state_data_t *state)
200 {
201 time_t maxtime, timeout;
202 time_t timeout_ms;
203 bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE;
204
205 time(&state->start_time);
206
207 /* Compute drop-dead time */
208 timeout_ms = Curl_timeleft(state->conn->data, NULL, start);
209
210 if(timeout_ms < 0) {
211 /* time-out, bail out, go home */
212 failf(state->conn->data, "Connection time-out");
213 return CURLE_OPERATION_TIMEDOUT;
214 }
215
216 if(start) {
217
218 maxtime = (time_t)(timeout_ms + 500) / 1000;
219 state->max_time = state->start_time+maxtime;
220
221 /* Set per-block timeout to total */
222 timeout = maxtime;
223
224 /* Average restart after 5 seconds */
225 state->retry_max = (int)timeout/5;
226
227 if(state->retry_max < 1)
228 /* avoid division by zero below */
229 state->retry_max = 1;
230
231 /* Compute the re-start interval to suit the timeout */
232 state->retry_time = (int)timeout/state->retry_max;
233 if(state->retry_time<1)
234 state->retry_time=1;
235
236 }
237 else {
238 if(timeout_ms > 0)
239 maxtime = (time_t)(timeout_ms + 500) / 1000;
240 else
241 maxtime = 3600;
242
243 state->max_time = state->start_time+maxtime;
244
245 /* Set per-block timeout to total */
246 timeout = maxtime;
247
248 /* Average reposting an ACK after 5 seconds */
249 state->retry_max = (int)timeout/5;
250 }
251 /* But bound the total number */
252 if(state->retry_max<3)
253 state->retry_max=3;
254
255 if(state->retry_max>50)
256 state->retry_max=50;
257
258 /* Compute the re-ACK interval to suit the timeout */
259 state->retry_time = (int)(timeout/state->retry_max);
260 if(state->retry_time<1)
261 state->retry_time=1;
262
263 infof(state->conn->data,
264 "set timeouts for state %d; Total %ld, retry %d maxtry %d\n",
265 (int)state->state, (long)(state->max_time-state->start_time),
266 state->retry_time, state->retry_max);
267
268 /* init RX time */
269 time(&state->rx_time);
270
271 return CURLE_OK;
272 }
273
274 /**********************************************************
275 *
276 * tftp_set_send_first
277 *
278 * Event handler for the START state
279 *
280 **********************************************************/
281
setpacketevent(tftp_packet_t * packet,unsigned short num)282 static void setpacketevent(tftp_packet_t *packet, unsigned short num)
283 {
284 packet->data[0] = (unsigned char)(num >> 8);
285 packet->data[1] = (unsigned char)(num & 0xff);
286 }
287
288
setpacketblock(tftp_packet_t * packet,unsigned short num)289 static void setpacketblock(tftp_packet_t *packet, unsigned short num)
290 {
291 packet->data[2] = (unsigned char)(num >> 8);
292 packet->data[3] = (unsigned char)(num & 0xff);
293 }
294
getrpacketevent(const tftp_packet_t * packet)295 static unsigned short getrpacketevent(const tftp_packet_t *packet)
296 {
297 return (unsigned short)((packet->data[0] << 8) | packet->data[1]);
298 }
299
getrpacketblock(const tftp_packet_t * packet)300 static unsigned short getrpacketblock(const tftp_packet_t *packet)
301 {
302 return (unsigned short)((packet->data[2] << 8) | packet->data[3]);
303 }
304
Curl_strnlen(const char * string,size_t maxlen)305 static size_t Curl_strnlen(const char *string, size_t maxlen)
306 {
307 const char *end = memchr (string, '\0', maxlen);
308 return end ? (size_t) (end - string) : maxlen;
309 }
310
tftp_option_get(const char * buf,size_t len,const char ** option,const char ** value)311 static const char *tftp_option_get(const char *buf, size_t len,
312 const char **option, const char **value)
313 {
314 size_t loc;
315
316 loc = Curl_strnlen(buf, len);
317 loc++; /* NULL term */
318
319 if(loc >= len)
320 return NULL;
321 *option = buf;
322
323 loc += Curl_strnlen(buf+loc, len-loc);
324 loc++; /* NULL term */
325
326 if(loc > len)
327 return NULL;
328 *value = &buf[strlen(*option) + 1];
329
330 return &buf[loc];
331 }
332
tftp_parse_option_ack(tftp_state_data_t * state,const char * ptr,int len)333 static CURLcode tftp_parse_option_ack(tftp_state_data_t *state,
334 const char *ptr, int len)
335 {
336 const char *tmp = ptr;
337 struct Curl_easy *data = state->conn->data;
338
339 /* if OACK doesn't contain blksize option, the default (512) must be used */
340 state->blksize = TFTP_BLKSIZE_DEFAULT;
341
342 while(tmp < ptr + len) {
343 const char *option, *value;
344
345 tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value);
346 if(tmp == NULL) {
347 failf(data, "Malformed ACK packet, rejecting");
348 return CURLE_TFTP_ILLEGAL;
349 }
350
351 infof(data, "got option=(%s) value=(%s)\n", option, value);
352
353 if(checkprefix(option, TFTP_OPTION_BLKSIZE)) {
354 long blksize;
355
356 blksize = strtol(value, NULL, 10);
357
358 if(!blksize) {
359 failf(data, "invalid blocksize value in OACK packet");
360 return CURLE_TFTP_ILLEGAL;
361 }
362 else if(blksize > TFTP_BLKSIZE_MAX) {
363 failf(data, "%s (%d)", "blksize is larger than max supported",
364 TFTP_BLKSIZE_MAX);
365 return CURLE_TFTP_ILLEGAL;
366 }
367 else if(blksize < TFTP_BLKSIZE_MIN) {
368 failf(data, "%s (%d)", "blksize is smaller than min supported",
369 TFTP_BLKSIZE_MIN);
370 return CURLE_TFTP_ILLEGAL;
371 }
372 else if(blksize > state->requested_blksize) {
373 /* could realloc pkt buffers here, but the spec doesn't call out
374 * support for the server requesting a bigger blksize than the client
375 * requests */
376 failf(data, "%s (%ld)",
377 "server requested blksize larger than allocated", blksize);
378 return CURLE_TFTP_ILLEGAL;
379 }
380
381 state->blksize = (int)blksize;
382 infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK",
383 state->blksize, "requested", state->requested_blksize);
384 }
385 else if(checkprefix(option, TFTP_OPTION_TSIZE)) {
386 long tsize = 0;
387
388 tsize = strtol(value, NULL, 10);
389 infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize);
390
391 /* tsize should be ignored on upload: Who cares about the size of the
392 remote file? */
393 if(!data->set.upload) {
394 if(!tsize) {
395 failf(data, "invalid tsize -:%s:- value in OACK packet", value);
396 return CURLE_TFTP_ILLEGAL;
397 }
398 Curl_pgrsSetDownloadSize(data, tsize);
399 }
400 }
401 }
402
403 return CURLE_OK;
404 }
405
tftp_option_add(tftp_state_data_t * state,size_t csize,char * buf,const char * option)406 static size_t tftp_option_add(tftp_state_data_t *state, size_t csize,
407 char *buf, const char *option)
408 {
409 if(( strlen(option) + csize + 1) > (size_t)state->blksize)
410 return 0;
411 strcpy(buf, option);
412 return strlen(option) + 1;
413 }
414
tftp_connect_for_tx(tftp_state_data_t * state,tftp_event_t event)415 static CURLcode tftp_connect_for_tx(tftp_state_data_t *state,
416 tftp_event_t event)
417 {
418 CURLcode result;
419 #ifndef CURL_DISABLE_VERBOSE_STRINGS
420 struct Curl_easy *data = state->conn->data;
421
422 infof(data, "%s\n", "Connected for transmit");
423 #endif
424 state->state = TFTP_STATE_TX;
425 result = tftp_set_timeouts(state);
426 if(result)
427 return result;
428 return tftp_tx(state, event);
429 }
430
tftp_connect_for_rx(tftp_state_data_t * state,tftp_event_t event)431 static CURLcode tftp_connect_for_rx(tftp_state_data_t *state,
432 tftp_event_t event)
433 {
434 CURLcode result;
435 #ifndef CURL_DISABLE_VERBOSE_STRINGS
436 struct Curl_easy *data = state->conn->data;
437
438 infof(data, "%s\n", "Connected for receive");
439 #endif
440 state->state = TFTP_STATE_RX;
441 result = tftp_set_timeouts(state);
442 if(result)
443 return result;
444 return tftp_rx(state, event);
445 }
446
tftp_send_first(tftp_state_data_t * state,tftp_event_t event)447 static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
448 {
449 size_t sbytes;
450 ssize_t senddata;
451 const char *mode = "octet";
452 char *filename;
453 char buf[64];
454 struct Curl_easy *data = state->conn->data;
455 CURLcode result = CURLE_OK;
456
457 /* Set ascii mode if -B flag was used */
458 if(data->set.prefer_ascii)
459 mode = "netascii";
460
461 switch(event) {
462
463 case TFTP_EVENT_INIT: /* Send the first packet out */
464 case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */
465 /* Increment the retry counter, quit if over the limit */
466 state->retries++;
467 if(state->retries>state->retry_max) {
468 state->error = TFTP_ERR_NORESPONSE;
469 state->state = TFTP_STATE_FIN;
470 return result;
471 }
472
473 if(data->set.upload) {
474 /* If we are uploading, send an WRQ */
475 setpacketevent(&state->spacket, TFTP_EVENT_WRQ);
476 state->conn->data->req.upload_fromhere =
477 (char *)state->spacket.data+4;
478 if(data->state.infilesize != -1)
479 Curl_pgrsSetUploadSize(data, data->state.infilesize);
480 }
481 else {
482 /* If we are downloading, send an RRQ */
483 setpacketevent(&state->spacket, TFTP_EVENT_RRQ);
484 }
485 /* As RFC3617 describes the separator slash is not actually part of the
486 file name so we skip the always-present first letter of the path
487 string. */
488 result = Curl_urldecode(data, &state->conn->data->state.path[1], 0,
489 &filename, NULL, FALSE);
490 if(result)
491 return result;
492
493 snprintf((char *)state->spacket.data+2,
494 state->blksize,
495 "%s%c%s%c", filename, '\0', mode, '\0');
496 sbytes = 4 + strlen(filename) + strlen(mode);
497
498 /* optional addition of TFTP options */
499 if(!data->set.tftp_no_options) {
500 /* add tsize option */
501 if(data->set.upload && (data->state.infilesize != -1))
502 snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
503 data->state.infilesize);
504 else
505 strcpy(buf, "0"); /* the destination is large enough */
506
507 sbytes += tftp_option_add(state, sbytes,
508 (char *)state->spacket.data+sbytes,
509 TFTP_OPTION_TSIZE);
510 sbytes += tftp_option_add(state, sbytes,
511 (char *)state->spacket.data+sbytes, buf);
512 /* add blksize option */
513 snprintf(buf, sizeof(buf), "%d", state->requested_blksize);
514 sbytes += tftp_option_add(state, sbytes,
515 (char *)state->spacket.data+sbytes,
516 TFTP_OPTION_BLKSIZE);
517 sbytes += tftp_option_add(state, sbytes,
518 (char *)state->spacket.data+sbytes, buf);
519
520 /* add timeout option */
521 snprintf(buf, sizeof(buf), "%d", state->retry_time);
522 sbytes += tftp_option_add(state, sbytes,
523 (char *)state->spacket.data+sbytes,
524 TFTP_OPTION_INTERVAL);
525 sbytes += tftp_option_add(state, sbytes,
526 (char *)state->spacket.data+sbytes, buf);
527 }
528
529 /* the typecase for the 3rd argument is mostly for systems that do
530 not have a size_t argument, like older unixes that want an 'int' */
531 senddata = sendto(state->sockfd, (void *)state->spacket.data,
532 (SEND_TYPE_ARG3)sbytes, 0,
533 state->conn->ip_addr->ai_addr,
534 state->conn->ip_addr->ai_addrlen);
535 if(senddata != (ssize_t)sbytes) {
536 failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
537 }
538 free(filename);
539 break;
540
541 case TFTP_EVENT_OACK:
542 if(data->set.upload) {
543 result = tftp_connect_for_tx(state, event);
544 }
545 else {
546 result = tftp_connect_for_rx(state, event);
547 }
548 break;
549
550 case TFTP_EVENT_ACK: /* Connected for transmit */
551 result = tftp_connect_for_tx(state, event);
552 break;
553
554 case TFTP_EVENT_DATA: /* Connected for receive */
555 result = tftp_connect_for_rx(state, event);
556 break;
557
558 case TFTP_EVENT_ERROR:
559 state->state = TFTP_STATE_FIN;
560 break;
561
562 default:
563 failf(state->conn->data, "tftp_send_first: internal error");
564 break;
565 }
566
567 return result;
568 }
569
570 /* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit
571 boundary */
572 #define NEXT_BLOCKNUM(x) (((x)+1)&0xffff)
573
574 /**********************************************************
575 *
576 * tftp_rx
577 *
578 * Event handler for the RX state
579 *
580 **********************************************************/
tftp_rx(tftp_state_data_t * state,tftp_event_t event)581 static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
582 {
583 ssize_t sbytes;
584 int rblock;
585 struct Curl_easy *data = state->conn->data;
586
587 switch(event) {
588
589 case TFTP_EVENT_DATA:
590 /* Is this the block we expect? */
591 rblock = getrpacketblock(&state->rpacket);
592 if(NEXT_BLOCKNUM(state->block) == rblock) {
593 /* This is the expected block. Reset counters and ACK it. */
594 state->retries = 0;
595 }
596 else if(state->block == rblock) {
597 /* This is the last recently received block again. Log it and ACK it
598 again. */
599 infof(data, "Received last DATA packet block %d again.\n", rblock);
600 }
601 else {
602 /* totally unexpected, just log it */
603 infof(data,
604 "Received unexpected DATA packet block %d, expecting block %d\n",
605 rblock, NEXT_BLOCKNUM(state->block));
606 break;
607 }
608
609 /* ACK this block. */
610 state->block = (unsigned short)rblock;
611 setpacketevent(&state->spacket, TFTP_EVENT_ACK);
612 setpacketblock(&state->spacket, state->block);
613 sbytes = sendto(state->sockfd, (void *)state->spacket.data,
614 4, SEND_4TH_ARG,
615 (struct sockaddr *)&state->remote_addr,
616 state->remote_addrlen);
617 if(sbytes < 0) {
618 failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
619 return CURLE_SEND_ERROR;
620 }
621
622 /* Check if completed (That is, a less than full packet is received) */
623 if(state->rbytes < (ssize_t)state->blksize+4) {
624 state->state = TFTP_STATE_FIN;
625 }
626 else {
627 state->state = TFTP_STATE_RX;
628 }
629 time(&state->rx_time);
630 break;
631
632 case TFTP_EVENT_OACK:
633 /* ACK option acknowledgement so we can move on to data */
634 state->block = 0;
635 state->retries = 0;
636 setpacketevent(&state->spacket, TFTP_EVENT_ACK);
637 setpacketblock(&state->spacket, state->block);
638 sbytes = sendto(state->sockfd, (void *)state->spacket.data,
639 4, SEND_4TH_ARG,
640 (struct sockaddr *)&state->remote_addr,
641 state->remote_addrlen);
642 if(sbytes < 0) {
643 failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
644 return CURLE_SEND_ERROR;
645 }
646
647 /* we're ready to RX data */
648 state->state = TFTP_STATE_RX;
649 time(&state->rx_time);
650 break;
651
652 case TFTP_EVENT_TIMEOUT:
653 /* Increment the retry count and fail if over the limit */
654 state->retries++;
655 infof(data,
656 "Timeout waiting for block %d ACK. Retries = %d\n",
657 NEXT_BLOCKNUM(state->block), state->retries);
658 if(state->retries > state->retry_max) {
659 state->error = TFTP_ERR_TIMEOUT;
660 state->state = TFTP_STATE_FIN;
661 }
662 else {
663 /* Resend the previous ACK */
664 sbytes = sendto(state->sockfd, (void *)state->spacket.data,
665 4, SEND_4TH_ARG,
666 (struct sockaddr *)&state->remote_addr,
667 state->remote_addrlen);
668 if(sbytes<0) {
669 failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
670 return CURLE_SEND_ERROR;
671 }
672 }
673 break;
674
675 case TFTP_EVENT_ERROR:
676 setpacketevent(&state->spacket, TFTP_EVENT_ERROR);
677 setpacketblock(&state->spacket, state->block);
678 (void)sendto(state->sockfd, (void *)state->spacket.data,
679 4, SEND_4TH_ARG,
680 (struct sockaddr *)&state->remote_addr,
681 state->remote_addrlen);
682 /* don't bother with the return code, but if the socket is still up we
683 * should be a good TFTP client and let the server know we're done */
684 state->state = TFTP_STATE_FIN;
685 break;
686
687 default:
688 failf(data, "%s", "tftp_rx: internal error");
689 return CURLE_TFTP_ILLEGAL; /* not really the perfect return code for
690 this */
691 }
692 return CURLE_OK;
693 }
694
695 /**********************************************************
696 *
697 * tftp_tx
698 *
699 * Event handler for the TX state
700 *
701 **********************************************************/
tftp_tx(tftp_state_data_t * state,tftp_event_t event)702 static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
703 {
704 struct Curl_easy *data = state->conn->data;
705 ssize_t sbytes;
706 int rblock;
707 CURLcode result = CURLE_OK;
708 struct SingleRequest *k = &data->req;
709 int cb; /* Bytes currently read */
710
711 switch(event) {
712
713 case TFTP_EVENT_ACK:
714 case TFTP_EVENT_OACK:
715 if(event == TFTP_EVENT_ACK) {
716 /* Ack the packet */
717 rblock = getrpacketblock(&state->rpacket);
718
719 if(rblock != state->block &&
720 /* There's a bug in tftpd-hpa that causes it to send us an ack for
721 * 65535 when the block number wraps to 0. So when we're expecting
722 * 0, also accept 65535. See
723 * http://syslinux.zytor.com/archives/2010-September/015253.html
724 * */
725 !(state->block == 0 && rblock == 65535)) {
726 /* This isn't the expected block. Log it and up the retry counter */
727 infof(data, "Received ACK for block %d, expecting %d\n",
728 rblock, state->block);
729 state->retries++;
730 /* Bail out if over the maximum */
731 if(state->retries>state->retry_max) {
732 failf(data, "tftp_tx: giving up waiting for block %d ack",
733 state->block);
734 result = CURLE_SEND_ERROR;
735 }
736 else {
737 /* Re-send the data packet */
738 sbytes = sendto(state->sockfd, (void *)state->spacket.data,
739 4+state->sbytes, SEND_4TH_ARG,
740 (struct sockaddr *)&state->remote_addr,
741 state->remote_addrlen);
742 /* Check all sbytes were sent */
743 if(sbytes<0) {
744 failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
745 result = CURLE_SEND_ERROR;
746 }
747 }
748
749 return result;
750 }
751 /* This is the expected packet. Reset the counters and send the next
752 block */
753 time(&state->rx_time);
754 state->block++;
755 }
756 else
757 state->block = 1; /* first data block is 1 when using OACK */
758
759 state->retries = 0;
760 setpacketevent(&state->spacket, TFTP_EVENT_DATA);
761 setpacketblock(&state->spacket, state->block);
762 if(state->block > 1 && state->sbytes < (int)state->blksize) {
763 state->state = TFTP_STATE_FIN;
764 return CURLE_OK;
765 }
766
767 /* TFTP considers data block size < 512 bytes as an end of session. So
768 * in some cases we must wait for additional data to build full (512 bytes)
769 * data block.
770 * */
771 state->sbytes = 0;
772 state->conn->data->req.upload_fromhere = (char *)state->spacket.data+4;
773 do {
774 result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes,
775 &cb);
776 if(result)
777 return result;
778 state->sbytes += cb;
779 state->conn->data->req.upload_fromhere += cb;
780 } while(state->sbytes < state->blksize && cb != 0);
781
782 sbytes = sendto(state->sockfd, (void *) state->spacket.data,
783 4 + state->sbytes, SEND_4TH_ARG,
784 (struct sockaddr *)&state->remote_addr,
785 state->remote_addrlen);
786 /* Check all sbytes were sent */
787 if(sbytes<0) {
788 failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
789 return CURLE_SEND_ERROR;
790 }
791 /* Update the progress meter */
792 k->writebytecount += state->sbytes;
793 Curl_pgrsSetUploadCounter(data, k->writebytecount);
794 break;
795
796 case TFTP_EVENT_TIMEOUT:
797 /* Increment the retry counter and log the timeout */
798 state->retries++;
799 infof(data, "Timeout waiting for block %d ACK. "
800 " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries);
801 /* Decide if we've had enough */
802 if(state->retries > state->retry_max) {
803 state->error = TFTP_ERR_TIMEOUT;
804 state->state = TFTP_STATE_FIN;
805 }
806 else {
807 /* Re-send the data packet */
808 sbytes = sendto(state->sockfd, (void *)state->spacket.data,
809 4+state->sbytes, SEND_4TH_ARG,
810 (struct sockaddr *)&state->remote_addr,
811 state->remote_addrlen);
812 /* Check all sbytes were sent */
813 if(sbytes<0) {
814 failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
815 return CURLE_SEND_ERROR;
816 }
817 /* since this was a re-send, we remain at the still byte position */
818 Curl_pgrsSetUploadCounter(data, k->writebytecount);
819 }
820 break;
821
822 case TFTP_EVENT_ERROR:
823 state->state = TFTP_STATE_FIN;
824 setpacketevent(&state->spacket, TFTP_EVENT_ERROR);
825 setpacketblock(&state->spacket, state->block);
826 (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG,
827 (struct sockaddr *)&state->remote_addr,
828 state->remote_addrlen);
829 /* don't bother with the return code, but if the socket is still up we
830 * should be a good TFTP client and let the server know we're done */
831 state->state = TFTP_STATE_FIN;
832 break;
833
834 default:
835 failf(data, "tftp_tx: internal error, event: %i", (int)(event));
836 break;
837 }
838
839 return result;
840 }
841
842 /**********************************************************
843 *
844 * tftp_translate_code
845 *
846 * Translate internal error codes to CURL error codes
847 *
848 **********************************************************/
tftp_translate_code(tftp_error_t error)849 static CURLcode tftp_translate_code(tftp_error_t error)
850 {
851 CURLcode result = CURLE_OK;
852
853 if(error != TFTP_ERR_NONE) {
854 switch(error) {
855 case TFTP_ERR_NOTFOUND:
856 result = CURLE_TFTP_NOTFOUND;
857 break;
858 case TFTP_ERR_PERM:
859 result = CURLE_TFTP_PERM;
860 break;
861 case TFTP_ERR_DISKFULL:
862 result = CURLE_REMOTE_DISK_FULL;
863 break;
864 case TFTP_ERR_UNDEF:
865 case TFTP_ERR_ILLEGAL:
866 result = CURLE_TFTP_ILLEGAL;
867 break;
868 case TFTP_ERR_UNKNOWNID:
869 result = CURLE_TFTP_UNKNOWNID;
870 break;
871 case TFTP_ERR_EXISTS:
872 result = CURLE_REMOTE_FILE_EXISTS;
873 break;
874 case TFTP_ERR_NOSUCHUSER:
875 result = CURLE_TFTP_NOSUCHUSER;
876 break;
877 case TFTP_ERR_TIMEOUT:
878 result = CURLE_OPERATION_TIMEDOUT;
879 break;
880 case TFTP_ERR_NORESPONSE:
881 result = CURLE_COULDNT_CONNECT;
882 break;
883 default:
884 result = CURLE_ABORTED_BY_CALLBACK;
885 break;
886 }
887 }
888 else
889 result = CURLE_OK;
890
891 return result;
892 }
893
894 /**********************************************************
895 *
896 * tftp_state_machine
897 *
898 * The tftp state machine event dispatcher
899 *
900 **********************************************************/
tftp_state_machine(tftp_state_data_t * state,tftp_event_t event)901 static CURLcode tftp_state_machine(tftp_state_data_t *state,
902 tftp_event_t event)
903 {
904 CURLcode result = CURLE_OK;
905 struct Curl_easy *data = state->conn->data;
906
907 switch(state->state) {
908 case TFTP_STATE_START:
909 DEBUGF(infof(data, "TFTP_STATE_START\n"));
910 result = tftp_send_first(state, event);
911 break;
912 case TFTP_STATE_RX:
913 DEBUGF(infof(data, "TFTP_STATE_RX\n"));
914 result = tftp_rx(state, event);
915 break;
916 case TFTP_STATE_TX:
917 DEBUGF(infof(data, "TFTP_STATE_TX\n"));
918 result = tftp_tx(state, event);
919 break;
920 case TFTP_STATE_FIN:
921 infof(data, "%s\n", "TFTP finished");
922 break;
923 default:
924 DEBUGF(infof(data, "STATE: %d\n", state->state));
925 failf(data, "%s", "Internal state machine error");
926 result = CURLE_TFTP_ILLEGAL;
927 break;
928 }
929
930 return result;
931 }
932
933 /**********************************************************
934 *
935 * tftp_disconnect
936 *
937 * The disconnect callback
938 *
939 **********************************************************/
tftp_disconnect(struct connectdata * conn,bool dead_connection)940 static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
941 {
942 tftp_state_data_t *state = conn->proto.tftpc;
943 (void) dead_connection;
944
945 /* done, free dynamically allocated pkt buffers */
946 if(state) {
947 Curl_safefree(state->rpacket.data);
948 Curl_safefree(state->spacket.data);
949 free(state);
950 }
951
952 return CURLE_OK;
953 }
954
955 /**********************************************************
956 *
957 * tftp_connect
958 *
959 * The connect callback
960 *
961 **********************************************************/
tftp_connect(struct connectdata * conn,bool * done)962 static CURLcode tftp_connect(struct connectdata *conn, bool *done)
963 {
964 tftp_state_data_t *state;
965 int blksize, rc;
966
967 blksize = TFTP_BLKSIZE_DEFAULT;
968
969 state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t));
970 if(!state)
971 return CURLE_OUT_OF_MEMORY;
972
973 /* alloc pkt buffers based on specified blksize */
974 if(conn->data->set.tftp_blksize) {
975 blksize = (int)conn->data->set.tftp_blksize;
976 if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
977 return CURLE_TFTP_ILLEGAL;
978 }
979
980 if(!state->rpacket.data) {
981 state->rpacket.data = calloc(1, blksize + 2 + 2);
982
983 if(!state->rpacket.data)
984 return CURLE_OUT_OF_MEMORY;
985 }
986
987 if(!state->spacket.data) {
988 state->spacket.data = calloc(1, blksize + 2 + 2);
989
990 if(!state->spacket.data)
991 return CURLE_OUT_OF_MEMORY;
992 }
993
994 /* we don't keep TFTP connections up basically because there's none or very
995 * little gain for UDP */
996 connclose(conn, "TFTP");
997
998 state->conn = conn;
999 state->sockfd = state->conn->sock[FIRSTSOCKET];
1000 state->state = TFTP_STATE_START;
1001 state->error = TFTP_ERR_NONE;
1002 state->blksize = TFTP_BLKSIZE_DEFAULT;
1003 state->requested_blksize = blksize;
1004
1005 ((struct sockaddr *)&state->local_addr)->sa_family =
1006 (unsigned short)(conn->ip_addr->ai_family);
1007
1008 tftp_set_timeouts(state);
1009
1010 if(!conn->bits.bound) {
1011 /* If not already bound, bind to any interface, random UDP port. If it is
1012 * reused or a custom local port was desired, this has already been done!
1013 *
1014 * We once used the size of the local_addr struct as the third argument
1015 * for bind() to better work with IPv6 or whatever size the struct could
1016 * have, but we learned that at least Tru64, AIX and IRIX *requires* the
1017 * size of that argument to match the exact size of a 'sockaddr_in' struct
1018 * when running IPv4-only.
1019 *
1020 * Therefore we use the size from the address we connected to, which we
1021 * assume uses the same IP version and thus hopefully this works for both
1022 * IPv4 and IPv6...
1023 */
1024 rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
1025 conn->ip_addr->ai_addrlen);
1026 if(rc) {
1027 failf(conn->data, "bind() failed; %s",
1028 Curl_strerror(conn, SOCKERRNO));
1029 return CURLE_COULDNT_CONNECT;
1030 }
1031 conn->bits.bound = TRUE;
1032 }
1033
1034 Curl_pgrsStartNow(conn->data);
1035
1036 *done = TRUE;
1037
1038 return CURLE_OK;
1039 }
1040
1041 /**********************************************************
1042 *
1043 * tftp_done
1044 *
1045 * The done callback
1046 *
1047 **********************************************************/
tftp_done(struct connectdata * conn,CURLcode status,bool premature)1048 static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
1049 bool premature)
1050 {
1051 CURLcode result = CURLE_OK;
1052 tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
1053
1054 (void)status; /* unused */
1055 (void)premature; /* not used */
1056
1057 if(Curl_pgrsDone(conn))
1058 return CURLE_ABORTED_BY_CALLBACK;
1059
1060 /* If we have encountered an error */
1061 if(state)
1062 result = tftp_translate_code(state->error);
1063
1064 return result;
1065 }
1066
1067 /**********************************************************
1068 *
1069 * tftp_getsock
1070 *
1071 * The getsock callback
1072 *
1073 **********************************************************/
tftp_getsock(struct connectdata * conn,curl_socket_t * socks,int numsocks)1074 static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks,
1075 int numsocks)
1076 {
1077 if(!numsocks)
1078 return GETSOCK_BLANK;
1079
1080 socks[0] = conn->sock[FIRSTSOCKET];
1081
1082 return GETSOCK_READSOCK(0);
1083 }
1084
1085 /**********************************************************
1086 *
1087 * tftp_receive_packet
1088 *
1089 * Called once select fires and data is ready on the socket
1090 *
1091 **********************************************************/
tftp_receive_packet(struct connectdata * conn)1092 static CURLcode tftp_receive_packet(struct connectdata *conn)
1093 {
1094 struct Curl_sockaddr_storage fromaddr;
1095 curl_socklen_t fromlen;
1096 CURLcode result = CURLE_OK;
1097 struct Curl_easy *data = conn->data;
1098 tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
1099 struct SingleRequest *k = &data->req;
1100
1101 /* Receive the packet */
1102 fromlen = sizeof(fromaddr);
1103 state->rbytes = (int)recvfrom(state->sockfd,
1104 (void *)state->rpacket.data,
1105 state->blksize+4,
1106 0,
1107 (struct sockaddr *)&fromaddr,
1108 &fromlen);
1109 if(state->remote_addrlen==0) {
1110 memcpy(&state->remote_addr, &fromaddr, fromlen);
1111 state->remote_addrlen = fromlen;
1112 }
1113
1114 /* Sanity check packet length */
1115 if(state->rbytes < 4) {
1116 failf(data, "Received too short packet");
1117 /* Not a timeout, but how best to handle it? */
1118 state->event = TFTP_EVENT_TIMEOUT;
1119 }
1120 else {
1121 /* The event is given by the TFTP packet time */
1122 state->event = (tftp_event_t)getrpacketevent(&state->rpacket);
1123
1124 switch(state->event) {
1125 case TFTP_EVENT_DATA:
1126 /* Don't pass to the client empty or retransmitted packets */
1127 if(state->rbytes > 4 &&
1128 (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) {
1129 result = Curl_client_write(conn, CLIENTWRITE_BODY,
1130 (char *)state->rpacket.data+4,
1131 state->rbytes-4);
1132 if(result) {
1133 tftp_state_machine(state, TFTP_EVENT_ERROR);
1134 return result;
1135 }
1136 k->bytecount += state->rbytes-4;
1137 Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount);
1138 }
1139 break;
1140 case TFTP_EVENT_ERROR:
1141 state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
1142 infof(data, "%s\n", (const char *)state->rpacket.data+4);
1143 break;
1144 case TFTP_EVENT_ACK:
1145 break;
1146 case TFTP_EVENT_OACK:
1147 result = tftp_parse_option_ack(state,
1148 (const char *)state->rpacket.data+2,
1149 state->rbytes-2);
1150 if(result)
1151 return result;
1152 break;
1153 case TFTP_EVENT_RRQ:
1154 case TFTP_EVENT_WRQ:
1155 default:
1156 failf(data, "%s", "Internal error: Unexpected packet");
1157 break;
1158 }
1159
1160 /* Update the progress meter */
1161 if(Curl_pgrsUpdate(conn)) {
1162 tftp_state_machine(state, TFTP_EVENT_ERROR);
1163 return CURLE_ABORTED_BY_CALLBACK;
1164 }
1165 }
1166 return result;
1167 }
1168
1169 /**********************************************************
1170 *
1171 * tftp_state_timeout
1172 *
1173 * Check if timeouts have been reached
1174 *
1175 **********************************************************/
tftp_state_timeout(struct connectdata * conn,tftp_event_t * event)1176 static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
1177 {
1178 time_t current;
1179 tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
1180
1181 if(event)
1182 *event = TFTP_EVENT_NONE;
1183
1184 time(¤t);
1185 if(current > state->max_time) {
1186 DEBUGF(infof(conn->data, "timeout: %ld > %ld\n",
1187 (long)current, (long)state->max_time));
1188 state->error = TFTP_ERR_TIMEOUT;
1189 state->state = TFTP_STATE_FIN;
1190 return 0;
1191 }
1192 else if(current > state->rx_time+state->retry_time) {
1193 if(event)
1194 *event = TFTP_EVENT_TIMEOUT;
1195 time(&state->rx_time); /* update even though we received nothing */
1196 }
1197
1198 /* there's a typecast below here since 'time_t' may in fact be larger than
1199 'long', but we estimate that a 'long' will still be able to hold number
1200 of seconds even if "only" 32 bit */
1201 return (long)(state->max_time - current);
1202 }
1203
1204 /**********************************************************
1205 *
1206 * tftp_multi_statemach
1207 *
1208 * Handle single RX socket event and return
1209 *
1210 **********************************************************/
tftp_multi_statemach(struct connectdata * conn,bool * done)1211 static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
1212 {
1213 int rc;
1214 tftp_event_t event;
1215 CURLcode result = CURLE_OK;
1216 struct Curl_easy *data = conn->data;
1217 tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
1218 long timeout_ms = tftp_state_timeout(conn, &event);
1219
1220 *done = FALSE;
1221
1222 if(timeout_ms <= 0) {
1223 failf(data, "TFTP response timeout");
1224 return CURLE_OPERATION_TIMEDOUT;
1225 }
1226 else if(event != TFTP_EVENT_NONE) {
1227 result = tftp_state_machine(state, event);
1228 if(result)
1229 return result;
1230 *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
1231 if(*done)
1232 /* Tell curl we're done */
1233 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
1234 }
1235 else {
1236 /* no timeouts to handle, check our socket */
1237 rc = SOCKET_READABLE(state->sockfd, 0);
1238
1239 if(rc == -1) {
1240 /* bail out */
1241 int error = SOCKERRNO;
1242 failf(data, "%s", Curl_strerror(conn, error));
1243 state->event = TFTP_EVENT_ERROR;
1244 }
1245 else if(rc != 0) {
1246 result = tftp_receive_packet(conn);
1247 if(result)
1248 return result;
1249 result = tftp_state_machine(state, state->event);
1250 if(result)
1251 return result;
1252 *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
1253 if(*done)
1254 /* Tell curl we're done */
1255 Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
1256 }
1257 /* if rc == 0, then select() timed out */
1258 }
1259
1260 return result;
1261 }
1262
1263 /**********************************************************
1264 *
1265 * tftp_doing
1266 *
1267 * Called from multi.c while DOing
1268 *
1269 **********************************************************/
tftp_doing(struct connectdata * conn,bool * dophase_done)1270 static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
1271 {
1272 CURLcode result;
1273 result = tftp_multi_statemach(conn, dophase_done);
1274
1275 if(*dophase_done) {
1276 DEBUGF(infof(conn->data, "DO phase is complete\n"));
1277 }
1278 else if(!result) {
1279 /* The multi code doesn't have this logic for the DOING state so we
1280 provide it for TFTP since it may do the entire transfer in this
1281 state. */
1282 if(Curl_pgrsUpdate(conn))
1283 result = CURLE_ABORTED_BY_CALLBACK;
1284 else
1285 result = Curl_speedcheck(conn->data, Curl_tvnow());
1286 }
1287 return result;
1288 }
1289
1290 /**********************************************************
1291 *
1292 * tftp_peform
1293 *
1294 * Entry point for transfer from tftp_do, sarts state mach
1295 *
1296 **********************************************************/
tftp_perform(struct connectdata * conn,bool * dophase_done)1297 static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
1298 {
1299 CURLcode result = CURLE_OK;
1300 tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
1301
1302 *dophase_done = FALSE;
1303
1304 result = tftp_state_machine(state, TFTP_EVENT_INIT);
1305
1306 if((state->state == TFTP_STATE_FIN) || result)
1307 return result;
1308
1309 tftp_multi_statemach(conn, dophase_done);
1310
1311 if(*dophase_done)
1312 DEBUGF(infof(conn->data, "DO phase is complete\n"));
1313
1314 return result;
1315 }
1316
1317
1318 /**********************************************************
1319 *
1320 * tftp_do
1321 *
1322 * The do callback
1323 *
1324 * This callback initiates the TFTP transfer
1325 *
1326 **********************************************************/
1327
tftp_do(struct connectdata * conn,bool * done)1328 static CURLcode tftp_do(struct connectdata *conn, bool *done)
1329 {
1330 tftp_state_data_t *state;
1331 CURLcode result;
1332
1333 *done = FALSE;
1334
1335 if(!conn->proto.tftpc) {
1336 result = tftp_connect(conn, done);
1337 if(result)
1338 return result;
1339 }
1340
1341 state = (tftp_state_data_t *)conn->proto.tftpc;
1342 if(!state)
1343 return CURLE_BAD_CALLING_ORDER;
1344
1345 result = tftp_perform(conn, done);
1346
1347 /* If tftp_perform() returned an error, use that for return code. If it
1348 was OK, see if tftp_translate_code() has an error. */
1349 if(!result)
1350 /* If we have encountered an internal tftp error, translate it. */
1351 result = tftp_translate_code(state->error);
1352
1353 return result;
1354 }
1355
tftp_setup_connection(struct connectdata * conn)1356 static CURLcode tftp_setup_connection(struct connectdata * conn)
1357 {
1358 struct Curl_easy *data = conn->data;
1359 char *type;
1360 char command;
1361
1362 conn->socktype = SOCK_DGRAM; /* UDP datagram based */
1363
1364 /* TFTP URLs support an extension like ";mode=<typecode>" that
1365 * we'll try to get now! */
1366 type = strstr(data->state.path, ";mode=");
1367
1368 if(!type)
1369 type = strstr(conn->host.rawalloc, ";mode=");
1370
1371 if(type) {
1372 *type = 0; /* it was in the middle of the hostname */
1373 command = Curl_raw_toupper(type[6]);
1374
1375 switch (command) {
1376 case 'A': /* ASCII mode */
1377 case 'N': /* NETASCII mode */
1378 data->set.prefer_ascii = TRUE;
1379 break;
1380
1381 case 'O': /* octet mode */
1382 case 'I': /* binary mode */
1383 default:
1384 /* switch off ASCII */
1385 data->set.prefer_ascii = FALSE;
1386 break;
1387 }
1388 }
1389
1390 return CURLE_OK;
1391 }
1392 #endif
1393