Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) 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  **********************************************************/
    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 
    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 
    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 
    295 static unsigned short getrpacketevent(const tftp_packet_t *packet)
    296 {
    297   return (unsigned short)((packet->data[0] << 8) | packet->data[1]);
    298 }
    299 
    300 static unsigned short getrpacketblock(const tftp_packet_t *packet)
    301 {
    302   return (unsigned short)((packet->data[2] << 8) | packet->data[3]);
    303 }
    304 
    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 
    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 
    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 
    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 
    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 
    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 
    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  **********************************************************/
    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  **********************************************************/
    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  **********************************************************/
    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  **********************************************************/
    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  **********************************************************/
    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  **********************************************************/
    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  **********************************************************/
   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  **********************************************************/
   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  **********************************************************/
   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  **********************************************************/
   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(&current);
   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  **********************************************************/
   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  **********************************************************/
   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  **********************************************************/
   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 
   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 
   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