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