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