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