Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  ***************************************************************************/
     22 
     23 #include "curl_setup.h"
     24 
     25 #ifndef CURL_DISABLE_TFTP
     26 
     27 #ifdef HAVE_NETINET_IN_H
     28 #include <netinet/in.h>
     29 #endif
     30 #ifdef HAVE_NETDB_H
     31 #include <netdb.h>
     32 #endif
     33 #ifdef HAVE_ARPA_INET_H
     34 #include <arpa/inet.h>
     35 #endif
     36 #ifdef HAVE_NET_IF_H
     37 #include <net/if.h>
     38 #endif
     39 #ifdef HAVE_SYS_IOCTL_H
     40 #include <sys/ioctl.h>
     41 #endif
     42 
     43 #ifdef HAVE_SYS_PARAM_H
     44 #include <sys/param.h>
     45 #endif
     46 
     47 #include "urldata.h"
     48 #include <curl/curl.h>
     49 #include "transfer.h"
     50 #include "sendf.h"
     51 #include "tftp.h"
     52 #include "progress.h"
     53 #include "connect.h"
     54 #include "strerror.h"
     55 #include "sockaddr.h" /* required for Curl_sockaddr_storage */
     56 #include "multiif.h"
     57 #include "url.h"
     58 #include "rawstr.h"
     59 #include "speedcheck.h"
     60 #include "select.h"
     61 
     62 /* The last 3 #include files should be in this order */
     63 #include "curl_printf.h"
     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 Curl_easy *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 Curl_easy *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 Curl_easy *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 Curl_easy *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     /* optional addition of TFTP options */
    498     if(!data->set.tftp_no_options) {
    499       /* add tsize option */
    500       if(data->set.upload && (data->state.infilesize != -1))
    501         snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T,
    502                  data->state.infilesize);
    503       else
    504         strcpy(buf, "0"); /* the destination is large enough */
    505 
    506       sbytes += tftp_option_add(state, sbytes,
    507                                 (char *)state->spacket.data+sbytes,
    508                                 TFTP_OPTION_TSIZE);
    509       sbytes += tftp_option_add(state, sbytes,
    510                                 (char *)state->spacket.data+sbytes, buf);
    511       /* add blksize option */
    512       snprintf(buf, sizeof(buf), "%d", state->requested_blksize);
    513       sbytes += tftp_option_add(state, sbytes,
    514                                 (char *)state->spacket.data+sbytes,
    515                                 TFTP_OPTION_BLKSIZE);
    516       sbytes += tftp_option_add(state, sbytes,
    517                                 (char *)state->spacket.data+sbytes, buf);
    518 
    519       /* add timeout option */
    520       snprintf(buf, sizeof(buf), "%d", state->retry_time);
    521       sbytes += tftp_option_add(state, sbytes,
    522                                 (char *)state->spacket.data+sbytes,
    523                                 TFTP_OPTION_INTERVAL);
    524       sbytes += tftp_option_add(state, sbytes,
    525                                 (char *)state->spacket.data+sbytes, buf);
    526     }
    527 
    528     /* the typecase for the 3rd argument is mostly for systems that do
    529        not have a size_t argument, like older unixes that want an 'int' */
    530     senddata = sendto(state->sockfd, (void *)state->spacket.data,
    531                       (SEND_TYPE_ARG3)sbytes, 0,
    532                       state->conn->ip_addr->ai_addr,
    533                       state->conn->ip_addr->ai_addrlen);
    534     if(senddata != (ssize_t)sbytes) {
    535       failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
    536     }
    537     free(filename);
    538     break;
    539 
    540   case TFTP_EVENT_OACK:
    541     if(data->set.upload) {
    542       result = tftp_connect_for_tx(state, event);
    543     }
    544     else {
    545       result = tftp_connect_for_rx(state, event);
    546     }
    547     break;
    548 
    549   case TFTP_EVENT_ACK: /* Connected for transmit */
    550     result = tftp_connect_for_tx(state, event);
    551     break;
    552 
    553   case TFTP_EVENT_DATA: /* Connected for receive */
    554     result = tftp_connect_for_rx(state, event);
    555     break;
    556 
    557   case TFTP_EVENT_ERROR:
    558     state->state = TFTP_STATE_FIN;
    559     break;
    560 
    561   default:
    562     failf(state->conn->data, "tftp_send_first: internal error");
    563     break;
    564   }
    565 
    566   return result;
    567 }
    568 
    569 /* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit
    570    boundary */
    571 #define NEXT_BLOCKNUM(x) (((x)+1)&0xffff)
    572 
    573 /**********************************************************
    574  *
    575  * tftp_rx
    576  *
    577  * Event handler for the RX state
    578  *
    579  **********************************************************/
    580 static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
    581 {
    582   ssize_t sbytes;
    583   int rblock;
    584   struct Curl_easy *data = state->conn->data;
    585 
    586   switch(event) {
    587 
    588   case TFTP_EVENT_DATA:
    589     /* Is this the block we expect? */
    590     rblock = getrpacketblock(&state->rpacket);
    591     if(NEXT_BLOCKNUM(state->block) == rblock) {
    592       /* This is the expected block.  Reset counters and ACK it. */
    593       state->retries = 0;
    594     }
    595     else if(state->block == rblock) {
    596       /* This is the last recently received block again. Log it and ACK it
    597          again. */
    598       infof(data, "Received last DATA packet block %d again.\n", rblock);
    599     }
    600     else {
    601       /* totally unexpected, just log it */
    602       infof(data,
    603             "Received unexpected DATA packet block %d, expecting block %d\n",
    604             rblock, NEXT_BLOCKNUM(state->block));
    605       break;
    606     }
    607 
    608     /* ACK this block. */
    609     state->block = (unsigned short)rblock;
    610     setpacketevent(&state->spacket, TFTP_EVENT_ACK);
    611     setpacketblock(&state->spacket, state->block);
    612     sbytes = sendto(state->sockfd, (void *)state->spacket.data,
    613                     4, SEND_4TH_ARG,
    614                     (struct sockaddr *)&state->remote_addr,
    615                     state->remote_addrlen);
    616     if(sbytes < 0) {
    617       failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
    618       return CURLE_SEND_ERROR;
    619     }
    620 
    621     /* Check if completed (That is, a less than full packet is received) */
    622     if(state->rbytes < (ssize_t)state->blksize+4) {
    623       state->state = TFTP_STATE_FIN;
    624     }
    625     else {
    626       state->state = TFTP_STATE_RX;
    627     }
    628     time(&state->rx_time);
    629     break;
    630 
    631   case TFTP_EVENT_OACK:
    632     /* ACK option acknowledgement so we can move on to data */
    633     state->block = 0;
    634     state->retries = 0;
    635     setpacketevent(&state->spacket, TFTP_EVENT_ACK);
    636     setpacketblock(&state->spacket, state->block);
    637     sbytes = sendto(state->sockfd, (void *)state->spacket.data,
    638                     4, SEND_4TH_ARG,
    639                     (struct sockaddr *)&state->remote_addr,
    640                     state->remote_addrlen);
    641     if(sbytes < 0) {
    642       failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
    643       return CURLE_SEND_ERROR;
    644     }
    645 
    646     /* we're ready to RX data */
    647     state->state = TFTP_STATE_RX;
    648     time(&state->rx_time);
    649     break;
    650 
    651   case TFTP_EVENT_TIMEOUT:
    652     /* Increment the retry count and fail if over the limit */
    653     state->retries++;
    654     infof(data,
    655           "Timeout waiting for block %d ACK.  Retries = %d\n",
    656           NEXT_BLOCKNUM(state->block), state->retries);
    657     if(state->retries > state->retry_max) {
    658       state->error = TFTP_ERR_TIMEOUT;
    659       state->state = TFTP_STATE_FIN;
    660     }
    661     else {
    662       /* Resend the previous ACK */
    663       sbytes = sendto(state->sockfd, (void *)state->spacket.data,
    664                       4, SEND_4TH_ARG,
    665                       (struct sockaddr *)&state->remote_addr,
    666                       state->remote_addrlen);
    667       if(sbytes<0) {
    668         failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
    669         return CURLE_SEND_ERROR;
    670       }
    671     }
    672     break;
    673 
    674   case TFTP_EVENT_ERROR:
    675     setpacketevent(&state->spacket, TFTP_EVENT_ERROR);
    676     setpacketblock(&state->spacket, state->block);
    677     (void)sendto(state->sockfd, (void *)state->spacket.data,
    678                  4, SEND_4TH_ARG,
    679                  (struct sockaddr *)&state->remote_addr,
    680                  state->remote_addrlen);
    681     /* don't bother with the return code, but if the socket is still up we
    682      * should be a good TFTP client and let the server know we're done */
    683     state->state = TFTP_STATE_FIN;
    684     break;
    685 
    686   default:
    687     failf(data, "%s", "tftp_rx: internal error");
    688     return CURLE_TFTP_ILLEGAL; /* not really the perfect return code for
    689                                   this */
    690   }
    691   return CURLE_OK;
    692 }
    693 
    694 /**********************************************************
    695  *
    696  * tftp_tx
    697  *
    698  * Event handler for the TX state
    699  *
    700  **********************************************************/
    701 static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
    702 {
    703   struct Curl_easy *data = state->conn->data;
    704   ssize_t sbytes;
    705   int rblock;
    706   CURLcode result = CURLE_OK;
    707   struct SingleRequest *k = &data->req;
    708 
    709   switch(event) {
    710 
    711   case TFTP_EVENT_ACK:
    712   case TFTP_EVENT_OACK:
    713     if(event == TFTP_EVENT_ACK) {
    714       /* Ack the packet */
    715       rblock = getrpacketblock(&state->rpacket);
    716 
    717       if(rblock != state->block &&
    718          /* There's a bug in tftpd-hpa that causes it to send us an ack for
    719           * 65535 when the block number wraps to 0. So when we're expecting
    720           * 0, also accept 65535. See
    721           * http://syslinux.zytor.com/archives/2010-September/015253.html
    722           * */
    723          !(state->block == 0 && rblock == 65535)) {
    724         /* This isn't the expected block.  Log it and up the retry counter */
    725         infof(data, "Received ACK for block %d, expecting %d\n",
    726               rblock, state->block);
    727         state->retries++;
    728         /* Bail out if over the maximum */
    729         if(state->retries>state->retry_max) {
    730           failf(data, "tftp_tx: giving up waiting for block %d ack",
    731                 state->block);
    732           result = CURLE_SEND_ERROR;
    733         }
    734         else {
    735           /* Re-send the data packet */
    736           sbytes = sendto(state->sockfd, (void *)state->spacket.data,
    737                           4+state->sbytes, SEND_4TH_ARG,
    738                           (struct sockaddr *)&state->remote_addr,
    739                           state->remote_addrlen);
    740           /* Check all sbytes were sent */
    741           if(sbytes<0) {
    742             failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
    743             result = CURLE_SEND_ERROR;
    744           }
    745         }
    746 
    747         return result;
    748       }
    749       /* This is the expected packet.  Reset the counters and send the next
    750          block */
    751       time(&state->rx_time);
    752       state->block++;
    753     }
    754     else
    755       state->block = 1; /* first data block is 1 when using OACK */
    756 
    757     state->retries = 0;
    758     setpacketevent(&state->spacket, TFTP_EVENT_DATA);
    759     setpacketblock(&state->spacket, state->block);
    760     if(state->block > 1 && state->sbytes < (int)state->blksize) {
    761       state->state = TFTP_STATE_FIN;
    762       return CURLE_OK;
    763     }
    764 
    765     result = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes);
    766     if(result)
    767       return result;
    768 
    769     sbytes = sendto(state->sockfd, (void *) state->spacket.data,
    770                     4 + state->sbytes, SEND_4TH_ARG,
    771                     (struct sockaddr *)&state->remote_addr,
    772                     state->remote_addrlen);
    773     /* Check all sbytes were sent */
    774     if(sbytes<0) {
    775       failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
    776       return CURLE_SEND_ERROR;
    777     }
    778     /* Update the progress meter */
    779     k->writebytecount += state->sbytes;
    780     Curl_pgrsSetUploadCounter(data, k->writebytecount);
    781     break;
    782 
    783   case TFTP_EVENT_TIMEOUT:
    784     /* Increment the retry counter and log the timeout */
    785     state->retries++;
    786     infof(data, "Timeout waiting for block %d ACK. "
    787           " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries);
    788     /* Decide if we've had enough */
    789     if(state->retries > state->retry_max) {
    790       state->error = TFTP_ERR_TIMEOUT;
    791       state->state = TFTP_STATE_FIN;
    792     }
    793     else {
    794       /* Re-send the data packet */
    795       sbytes = sendto(state->sockfd, (void *)state->spacket.data,
    796                       4+state->sbytes, SEND_4TH_ARG,
    797                       (struct sockaddr *)&state->remote_addr,
    798                       state->remote_addrlen);
    799       /* Check all sbytes were sent */
    800       if(sbytes<0) {
    801         failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
    802         return CURLE_SEND_ERROR;
    803       }
    804       /* since this was a re-send, we remain at the still byte position */
    805       Curl_pgrsSetUploadCounter(data, k->writebytecount);
    806     }
    807     break;
    808 
    809   case TFTP_EVENT_ERROR:
    810     state->state = TFTP_STATE_FIN;
    811     setpacketevent(&state->spacket, TFTP_EVENT_ERROR);
    812     setpacketblock(&state->spacket, state->block);
    813     (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG,
    814                  (struct sockaddr *)&state->remote_addr,
    815                  state->remote_addrlen);
    816     /* don't bother with the return code, but if the socket is still up we
    817      * should be a good TFTP client and let the server know we're done */
    818     state->state = TFTP_STATE_FIN;
    819     break;
    820 
    821   default:
    822     failf(data, "tftp_tx: internal error, event: %i", (int)(event));
    823     break;
    824   }
    825 
    826   return result;
    827 }
    828 
    829 /**********************************************************
    830  *
    831  * tftp_translate_code
    832  *
    833  * Translate internal error codes to CURL error codes
    834  *
    835  **********************************************************/
    836 static CURLcode tftp_translate_code(tftp_error_t error)
    837 {
    838   CURLcode result = CURLE_OK;
    839 
    840   if(error != TFTP_ERR_NONE) {
    841     switch(error) {
    842     case TFTP_ERR_NOTFOUND:
    843       result = CURLE_TFTP_NOTFOUND;
    844       break;
    845     case TFTP_ERR_PERM:
    846       result = CURLE_TFTP_PERM;
    847       break;
    848     case TFTP_ERR_DISKFULL:
    849       result = CURLE_REMOTE_DISK_FULL;
    850       break;
    851     case TFTP_ERR_UNDEF:
    852     case TFTP_ERR_ILLEGAL:
    853       result = CURLE_TFTP_ILLEGAL;
    854       break;
    855     case TFTP_ERR_UNKNOWNID:
    856       result = CURLE_TFTP_UNKNOWNID;
    857       break;
    858     case TFTP_ERR_EXISTS:
    859       result = CURLE_REMOTE_FILE_EXISTS;
    860       break;
    861     case TFTP_ERR_NOSUCHUSER:
    862       result = CURLE_TFTP_NOSUCHUSER;
    863       break;
    864     case TFTP_ERR_TIMEOUT:
    865       result = CURLE_OPERATION_TIMEDOUT;
    866       break;
    867     case TFTP_ERR_NORESPONSE:
    868       result = CURLE_COULDNT_CONNECT;
    869       break;
    870     default:
    871       result = CURLE_ABORTED_BY_CALLBACK;
    872       break;
    873     }
    874   }
    875   else
    876     result = CURLE_OK;
    877 
    878   return result;
    879 }
    880 
    881 /**********************************************************
    882  *
    883  * tftp_state_machine
    884  *
    885  * The tftp state machine event dispatcher
    886  *
    887  **********************************************************/
    888 static CURLcode tftp_state_machine(tftp_state_data_t *state,
    889                                    tftp_event_t event)
    890 {
    891   CURLcode result = CURLE_OK;
    892   struct Curl_easy *data = state->conn->data;
    893 
    894   switch(state->state) {
    895   case TFTP_STATE_START:
    896     DEBUGF(infof(data, "TFTP_STATE_START\n"));
    897     result = tftp_send_first(state, event);
    898     break;
    899   case TFTP_STATE_RX:
    900     DEBUGF(infof(data, "TFTP_STATE_RX\n"));
    901     result = tftp_rx(state, event);
    902     break;
    903   case TFTP_STATE_TX:
    904     DEBUGF(infof(data, "TFTP_STATE_TX\n"));
    905     result = tftp_tx(state, event);
    906     break;
    907   case TFTP_STATE_FIN:
    908     infof(data, "%s\n", "TFTP finished");
    909     break;
    910   default:
    911     DEBUGF(infof(data, "STATE: %d\n", state->state));
    912     failf(data, "%s", "Internal state machine error");
    913     result = CURLE_TFTP_ILLEGAL;
    914     break;
    915   }
    916 
    917   return result;
    918 }
    919 
    920 /**********************************************************
    921  *
    922  * tftp_disconnect
    923  *
    924  * The disconnect callback
    925  *
    926  **********************************************************/
    927 static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
    928 {
    929   tftp_state_data_t *state = conn->proto.tftpc;
    930   (void) dead_connection;
    931 
    932   /* done, free dynamically allocated pkt buffers */
    933   if(state) {
    934     Curl_safefree(state->rpacket.data);
    935     Curl_safefree(state->spacket.data);
    936     free(state);
    937   }
    938 
    939   return CURLE_OK;
    940 }
    941 
    942 /**********************************************************
    943  *
    944  * tftp_connect
    945  *
    946  * The connect callback
    947  *
    948  **********************************************************/
    949 static CURLcode tftp_connect(struct connectdata *conn, bool *done)
    950 {
    951   tftp_state_data_t *state;
    952   int blksize, rc;
    953 
    954   blksize = TFTP_BLKSIZE_DEFAULT;
    955 
    956   state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t));
    957   if(!state)
    958     return CURLE_OUT_OF_MEMORY;
    959 
    960   /* alloc pkt buffers based on specified blksize */
    961   if(conn->data->set.tftp_blksize) {
    962     blksize = (int)conn->data->set.tftp_blksize;
    963     if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
    964       return CURLE_TFTP_ILLEGAL;
    965   }
    966 
    967   if(!state->rpacket.data) {
    968     state->rpacket.data = calloc(1, blksize + 2 + 2);
    969 
    970     if(!state->rpacket.data)
    971       return CURLE_OUT_OF_MEMORY;
    972   }
    973 
    974   if(!state->spacket.data) {
    975     state->spacket.data = calloc(1, blksize + 2 + 2);
    976 
    977     if(!state->spacket.data)
    978       return CURLE_OUT_OF_MEMORY;
    979   }
    980 
    981   /* we don't keep TFTP connections up basically because there's none or very
    982    * little gain for UDP */
    983   connclose(conn, "TFTP");
    984 
    985   state->conn = conn;
    986   state->sockfd = state->conn->sock[FIRSTSOCKET];
    987   state->state = TFTP_STATE_START;
    988   state->error = TFTP_ERR_NONE;
    989   state->blksize = TFTP_BLKSIZE_DEFAULT;
    990   state->requested_blksize = blksize;
    991 
    992   ((struct sockaddr *)&state->local_addr)->sa_family =
    993     (unsigned short)(conn->ip_addr->ai_family);
    994 
    995   tftp_set_timeouts(state);
    996 
    997   if(!conn->bits.bound) {
    998     /* If not already bound, bind to any interface, random UDP port. If it is
    999      * reused or a custom local port was desired, this has already been done!
   1000      *
   1001      * We once used the size of the local_addr struct as the third argument
   1002      * for bind() to better work with IPv6 or whatever size the struct could
   1003      * have, but we learned that at least Tru64, AIX and IRIX *requires* the
   1004      * size of that argument to match the exact size of a 'sockaddr_in' struct
   1005      * when running IPv4-only.
   1006      *
   1007      * Therefore we use the size from the address we connected to, which we
   1008      * assume uses the same IP version and thus hopefully this works for both
   1009      * IPv4 and IPv6...
   1010      */
   1011     rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
   1012               conn->ip_addr->ai_addrlen);
   1013     if(rc) {
   1014       failf(conn->data, "bind() failed; %s",
   1015             Curl_strerror(conn, SOCKERRNO));
   1016       return CURLE_COULDNT_CONNECT;
   1017     }
   1018     conn->bits.bound = TRUE;
   1019   }
   1020 
   1021   Curl_pgrsStartNow(conn->data);
   1022 
   1023   *done = TRUE;
   1024 
   1025   return CURLE_OK;
   1026 }
   1027 
   1028 /**********************************************************
   1029  *
   1030  * tftp_done
   1031  *
   1032  * The done callback
   1033  *
   1034  **********************************************************/
   1035 static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
   1036                           bool premature)
   1037 {
   1038   CURLcode result = CURLE_OK;
   1039   tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
   1040 
   1041   (void)status; /* unused */
   1042   (void)premature; /* not used */
   1043 
   1044   if(Curl_pgrsDone(conn))
   1045     return CURLE_ABORTED_BY_CALLBACK;
   1046 
   1047   /* If we have encountered an error */
   1048   if(state)
   1049     result = tftp_translate_code(state->error);
   1050 
   1051   return result;
   1052 }
   1053 
   1054 /**********************************************************
   1055  *
   1056  * tftp_getsock
   1057  *
   1058  * The getsock callback
   1059  *
   1060  **********************************************************/
   1061 static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks,
   1062                         int numsocks)
   1063 {
   1064   if(!numsocks)
   1065     return GETSOCK_BLANK;
   1066 
   1067   socks[0] = conn->sock[FIRSTSOCKET];
   1068 
   1069   return GETSOCK_READSOCK(0);
   1070 }
   1071 
   1072 /**********************************************************
   1073  *
   1074  * tftp_receive_packet
   1075  *
   1076  * Called once select fires and data is ready on the socket
   1077  *
   1078  **********************************************************/
   1079 static CURLcode tftp_receive_packet(struct connectdata *conn)
   1080 {
   1081   struct Curl_sockaddr_storage fromaddr;
   1082   curl_socklen_t        fromlen;
   1083   CURLcode              result = CURLE_OK;
   1084   struct Curl_easy  *data = conn->data;
   1085   tftp_state_data_t     *state = (tftp_state_data_t *)conn->proto.tftpc;
   1086   struct SingleRequest  *k = &data->req;
   1087 
   1088   /* Receive the packet */
   1089   fromlen = sizeof(fromaddr);
   1090   state->rbytes = (int)recvfrom(state->sockfd,
   1091                                 (void *)state->rpacket.data,
   1092                                 state->blksize+4,
   1093                                 0,
   1094                                 (struct sockaddr *)&fromaddr,
   1095                                 &fromlen);
   1096   if(state->remote_addrlen==0) {
   1097     memcpy(&state->remote_addr, &fromaddr, fromlen);
   1098     state->remote_addrlen = fromlen;
   1099   }
   1100 
   1101   /* Sanity check packet length */
   1102   if(state->rbytes < 4) {
   1103     failf(data, "Received too short packet");
   1104     /* Not a timeout, but how best to handle it? */
   1105     state->event = TFTP_EVENT_TIMEOUT;
   1106   }
   1107   else {
   1108     /* The event is given by the TFTP packet time */
   1109     state->event = (tftp_event_t)getrpacketevent(&state->rpacket);
   1110 
   1111     switch(state->event) {
   1112     case TFTP_EVENT_DATA:
   1113       /* Don't pass to the client empty or retransmitted packets */
   1114       if(state->rbytes > 4 &&
   1115          (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) {
   1116         result = Curl_client_write(conn, CLIENTWRITE_BODY,
   1117                                    (char *)state->rpacket.data+4,
   1118                                    state->rbytes-4);
   1119         if(result) {
   1120           tftp_state_machine(state, TFTP_EVENT_ERROR);
   1121           return result;
   1122         }
   1123         k->bytecount += state->rbytes-4;
   1124         Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount);
   1125       }
   1126       break;
   1127     case TFTP_EVENT_ERROR:
   1128       state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
   1129       infof(data, "%s\n", (const char *)state->rpacket.data+4);
   1130       break;
   1131     case TFTP_EVENT_ACK:
   1132       break;
   1133     case TFTP_EVENT_OACK:
   1134       result = tftp_parse_option_ack(state,
   1135                                      (const char *)state->rpacket.data+2,
   1136                                      state->rbytes-2);
   1137       if(result)
   1138         return result;
   1139       break;
   1140     case TFTP_EVENT_RRQ:
   1141     case TFTP_EVENT_WRQ:
   1142     default:
   1143       failf(data, "%s", "Internal error: Unexpected packet");
   1144       break;
   1145     }
   1146 
   1147     /* Update the progress meter */
   1148     if(Curl_pgrsUpdate(conn)) {
   1149       tftp_state_machine(state, TFTP_EVENT_ERROR);
   1150       return CURLE_ABORTED_BY_CALLBACK;
   1151     }
   1152   }
   1153   return result;
   1154 }
   1155 
   1156 /**********************************************************
   1157  *
   1158  * tftp_state_timeout
   1159  *
   1160  * Check if timeouts have been reached
   1161  *
   1162  **********************************************************/
   1163 static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
   1164 {
   1165   time_t                current;
   1166   tftp_state_data_t     *state = (tftp_state_data_t *)conn->proto.tftpc;
   1167 
   1168   if(event)
   1169     *event = TFTP_EVENT_NONE;
   1170 
   1171   time(&current);
   1172   if(current > state->max_time) {
   1173     DEBUGF(infof(conn->data, "timeout: %ld > %ld\n",
   1174                  (long)current, (long)state->max_time));
   1175     state->error = TFTP_ERR_TIMEOUT;
   1176     state->state = TFTP_STATE_FIN;
   1177     return 0;
   1178   }
   1179   else if(current > state->rx_time+state->retry_time) {
   1180     if(event)
   1181       *event = TFTP_EVENT_TIMEOUT;
   1182     time(&state->rx_time); /* update even though we received nothing */
   1183   }
   1184 
   1185   /* there's a typecast below here since 'time_t' may in fact be larger than
   1186      'long', but we estimate that a 'long' will still be able to hold number
   1187      of seconds even if "only" 32 bit */
   1188   return (long)(state->max_time - current);
   1189 }
   1190 
   1191 /**********************************************************
   1192  *
   1193  * tftp_multi_statemach
   1194  *
   1195  * Handle single RX socket event and return
   1196  *
   1197  **********************************************************/
   1198 static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
   1199 {
   1200   int                   rc;
   1201   tftp_event_t          event;
   1202   CURLcode              result = CURLE_OK;
   1203   struct Curl_easy  *data = conn->data;
   1204   tftp_state_data_t     *state = (tftp_state_data_t *)conn->proto.tftpc;
   1205   long                  timeout_ms = tftp_state_timeout(conn, &event);
   1206 
   1207   *done = FALSE;
   1208 
   1209   if(timeout_ms <= 0) {
   1210     failf(data, "TFTP response timeout");
   1211     return CURLE_OPERATION_TIMEDOUT;
   1212   }
   1213   else if(event != TFTP_EVENT_NONE) {
   1214     result = tftp_state_machine(state, event);
   1215     if(result)
   1216       return result;
   1217     *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
   1218     if(*done)
   1219       /* Tell curl we're done */
   1220       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
   1221   }
   1222   else {
   1223     /* no timeouts to handle, check our socket */
   1224     rc = Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD, 0);
   1225 
   1226     if(rc == -1) {
   1227       /* bail out */
   1228       int error = SOCKERRNO;
   1229       failf(data, "%s", Curl_strerror(conn, error));
   1230       state->event = TFTP_EVENT_ERROR;
   1231     }
   1232     else if(rc != 0) {
   1233       result = tftp_receive_packet(conn);
   1234       if(result)
   1235         return result;
   1236       result = tftp_state_machine(state, state->event);
   1237       if(result)
   1238         return result;
   1239       *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
   1240       if(*done)
   1241         /* Tell curl we're done */
   1242         Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
   1243     }
   1244     /* if rc == 0, then select() timed out */
   1245   }
   1246 
   1247   return result;
   1248 }
   1249 
   1250 /**********************************************************
   1251  *
   1252  * tftp_doing
   1253  *
   1254  * Called from multi.c while DOing
   1255  *
   1256  **********************************************************/
   1257 static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
   1258 {
   1259   CURLcode result;
   1260   result = tftp_multi_statemach(conn, dophase_done);
   1261 
   1262   if(*dophase_done) {
   1263     DEBUGF(infof(conn->data, "DO phase is complete\n"));
   1264   }
   1265   else if(!result) {
   1266     /* The multi code doesn't have this logic for the DOING state so we
   1267        provide it for TFTP since it may do the entire transfer in this
   1268        state. */
   1269     if(Curl_pgrsUpdate(conn))
   1270       result = CURLE_ABORTED_BY_CALLBACK;
   1271     else
   1272       result = Curl_speedcheck(conn->data, Curl_tvnow());
   1273   }
   1274   return result;
   1275 }
   1276 
   1277 /**********************************************************
   1278  *
   1279  * tftp_peform
   1280  *
   1281  * Entry point for transfer from tftp_do, sarts state mach
   1282  *
   1283  **********************************************************/
   1284 static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
   1285 {
   1286   CURLcode              result = CURLE_OK;
   1287   tftp_state_data_t     *state = (tftp_state_data_t *)conn->proto.tftpc;
   1288 
   1289   *dophase_done = FALSE;
   1290 
   1291   result = tftp_state_machine(state, TFTP_EVENT_INIT);
   1292 
   1293   if((state->state == TFTP_STATE_FIN) || result)
   1294     return result;
   1295 
   1296   tftp_multi_statemach(conn, dophase_done);
   1297 
   1298   if(*dophase_done)
   1299     DEBUGF(infof(conn->data, "DO phase is complete\n"));
   1300 
   1301   return result;
   1302 }
   1303 
   1304 
   1305 /**********************************************************
   1306  *
   1307  * tftp_do
   1308  *
   1309  * The do callback
   1310  *
   1311  * This callback initiates the TFTP transfer
   1312  *
   1313  **********************************************************/
   1314 
   1315 static CURLcode tftp_do(struct connectdata *conn, bool *done)
   1316 {
   1317   tftp_state_data_t *state;
   1318   CURLcode result;
   1319 
   1320   *done = FALSE;
   1321 
   1322   if(!conn->proto.tftpc) {
   1323     result = tftp_connect(conn, done);
   1324     if(result)
   1325       return result;
   1326   }
   1327 
   1328   state = (tftp_state_data_t *)conn->proto.tftpc;
   1329   if(!state)
   1330     return CURLE_BAD_CALLING_ORDER;
   1331 
   1332   result = tftp_perform(conn, done);
   1333 
   1334   /* If tftp_perform() returned an error, use that for return code. If it
   1335      was OK, see if tftp_translate_code() has an error. */
   1336   if(!result)
   1337     /* If we have encountered an internal tftp error, translate it. */
   1338     result = tftp_translate_code(state->error);
   1339 
   1340   return result;
   1341 }
   1342 
   1343 static CURLcode tftp_setup_connection(struct connectdata * conn)
   1344 {
   1345   struct Curl_easy *data = conn->data;
   1346   char * type;
   1347   char command;
   1348 
   1349   conn->socktype = SOCK_DGRAM;   /* UDP datagram based */
   1350 
   1351   /* TFTP URLs support an extension like ";mode=<typecode>" that
   1352    * we'll try to get now! */
   1353   type = strstr(data->state.path, ";mode=");
   1354 
   1355   if(!type)
   1356     type = strstr(conn->host.rawalloc, ";mode=");
   1357 
   1358   if(type) {
   1359     *type = 0;                   /* it was in the middle of the hostname */
   1360     command = Curl_raw_toupper(type[6]);
   1361 
   1362     switch (command) {
   1363     case 'A': /* ASCII mode */
   1364     case 'N': /* NETASCII mode */
   1365       data->set.prefer_ascii = TRUE;
   1366       break;
   1367 
   1368     case 'O': /* octet mode */
   1369     case 'I': /* binary mode */
   1370     default:
   1371       /* switch off ASCII */
   1372       data->set.prefer_ascii = FALSE;
   1373       break;
   1374     }
   1375   }
   1376 
   1377   return CURLE_OK;
   1378 }
   1379 #endif
   1380