Annotation of embedaddon/curl/lib/tftp.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>