Revert "Imported Upstream version 7.53.1"
[platform/upstream/curl.git] / lib / tftp.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2016, 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 "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   int cb; /* Bytes currently read */
709
710   switch(event) {
711
712   case TFTP_EVENT_ACK:
713   case TFTP_EVENT_OACK:
714     if(event == TFTP_EVENT_ACK) {
715       /* Ack the packet */
716       rblock = getrpacketblock(&state->rpacket);
717
718       if(rblock != state->block &&
719          /* There's a bug in tftpd-hpa that causes it to send us an ack for
720           * 65535 when the block number wraps to 0. So when we're expecting
721           * 0, also accept 65535. See
722           * http://syslinux.zytor.com/archives/2010-September/015253.html
723           * */
724          !(state->block == 0 && rblock == 65535)) {
725         /* This isn't the expected block.  Log it and up the retry counter */
726         infof(data, "Received ACK for block %d, expecting %d\n",
727               rblock, state->block);
728         state->retries++;
729         /* Bail out if over the maximum */
730         if(state->retries>state->retry_max) {
731           failf(data, "tftp_tx: giving up waiting for block %d ack",
732                 state->block);
733           result = CURLE_SEND_ERROR;
734         }
735         else {
736           /* Re-send the data packet */
737           sbytes = sendto(state->sockfd, (void *)state->spacket.data,
738                           4+state->sbytes, SEND_4TH_ARG,
739                           (struct sockaddr *)&state->remote_addr,
740                           state->remote_addrlen);
741           /* Check all sbytes were sent */
742           if(sbytes<0) {
743             failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
744             result = CURLE_SEND_ERROR;
745           }
746         }
747
748         return result;
749       }
750       /* This is the expected packet.  Reset the counters and send the next
751          block */
752       time(&state->rx_time);
753       state->block++;
754     }
755     else
756       state->block = 1; /* first data block is 1 when using OACK */
757
758     state->retries = 0;
759     setpacketevent(&state->spacket, TFTP_EVENT_DATA);
760     setpacketblock(&state->spacket, state->block);
761     if(state->block > 1 && state->sbytes < (int)state->blksize) {
762       state->state = TFTP_STATE_FIN;
763       return CURLE_OK;
764     }
765
766     /* TFTP considers data block size < 512 bytes as an end of session. So
767      * in some cases we must wait for additional data to build full (512 bytes)
768      * data block.
769      * */
770     state->sbytes = 0;
771     state->conn->data->req.upload_fromhere = (char *)state->spacket.data+4;
772     do {
773       result = Curl_fillreadbuffer(state->conn, state->blksize - state->sbytes,
774                                    &cb);
775       if(result)
776         return result;
777       state->sbytes += cb;
778       state->conn->data->req.upload_fromhere += cb;
779     } while(state->sbytes < state->blksize && cb != 0);
780
781     sbytes = sendto(state->sockfd, (void *) state->spacket.data,
782                     4 + state->sbytes, SEND_4TH_ARG,
783                     (struct sockaddr *)&state->remote_addr,
784                     state->remote_addrlen);
785     /* Check all sbytes were sent */
786     if(sbytes<0) {
787       failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
788       return CURLE_SEND_ERROR;
789     }
790     /* Update the progress meter */
791     k->writebytecount += state->sbytes;
792     Curl_pgrsSetUploadCounter(data, k->writebytecount);
793     break;
794
795   case TFTP_EVENT_TIMEOUT:
796     /* Increment the retry counter and log the timeout */
797     state->retries++;
798     infof(data, "Timeout waiting for block %d ACK. "
799           " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries);
800     /* Decide if we've had enough */
801     if(state->retries > state->retry_max) {
802       state->error = TFTP_ERR_TIMEOUT;
803       state->state = TFTP_STATE_FIN;
804     }
805     else {
806       /* Re-send the data packet */
807       sbytes = sendto(state->sockfd, (void *)state->spacket.data,
808                       4+state->sbytes, SEND_4TH_ARG,
809                       (struct sockaddr *)&state->remote_addr,
810                       state->remote_addrlen);
811       /* Check all sbytes were sent */
812       if(sbytes<0) {
813         failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO));
814         return CURLE_SEND_ERROR;
815       }
816       /* since this was a re-send, we remain at the still byte position */
817       Curl_pgrsSetUploadCounter(data, k->writebytecount);
818     }
819     break;
820
821   case TFTP_EVENT_ERROR:
822     state->state = TFTP_STATE_FIN;
823     setpacketevent(&state->spacket, TFTP_EVENT_ERROR);
824     setpacketblock(&state->spacket, state->block);
825     (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG,
826                  (struct sockaddr *)&state->remote_addr,
827                  state->remote_addrlen);
828     /* don't bother with the return code, but if the socket is still up we
829      * should be a good TFTP client and let the server know we're done */
830     state->state = TFTP_STATE_FIN;
831     break;
832
833   default:
834     failf(data, "tftp_tx: internal error, event: %i", (int)(event));
835     break;
836   }
837
838   return result;
839 }
840
841 /**********************************************************
842  *
843  * tftp_translate_code
844  *
845  * Translate internal error codes to CURL error codes
846  *
847  **********************************************************/
848 static CURLcode tftp_translate_code(tftp_error_t error)
849 {
850   CURLcode result = CURLE_OK;
851
852   if(error != TFTP_ERR_NONE) {
853     switch(error) {
854     case TFTP_ERR_NOTFOUND:
855       result = CURLE_TFTP_NOTFOUND;
856       break;
857     case TFTP_ERR_PERM:
858       result = CURLE_TFTP_PERM;
859       break;
860     case TFTP_ERR_DISKFULL:
861       result = CURLE_REMOTE_DISK_FULL;
862       break;
863     case TFTP_ERR_UNDEF:
864     case TFTP_ERR_ILLEGAL:
865       result = CURLE_TFTP_ILLEGAL;
866       break;
867     case TFTP_ERR_UNKNOWNID:
868       result = CURLE_TFTP_UNKNOWNID;
869       break;
870     case TFTP_ERR_EXISTS:
871       result = CURLE_REMOTE_FILE_EXISTS;
872       break;
873     case TFTP_ERR_NOSUCHUSER:
874       result = CURLE_TFTP_NOSUCHUSER;
875       break;
876     case TFTP_ERR_TIMEOUT:
877       result = CURLE_OPERATION_TIMEDOUT;
878       break;
879     case TFTP_ERR_NORESPONSE:
880       result = CURLE_COULDNT_CONNECT;
881       break;
882     default:
883       result = CURLE_ABORTED_BY_CALLBACK;
884       break;
885     }
886   }
887   else
888     result = CURLE_OK;
889
890   return result;
891 }
892
893 /**********************************************************
894  *
895  * tftp_state_machine
896  *
897  * The tftp state machine event dispatcher
898  *
899  **********************************************************/
900 static CURLcode tftp_state_machine(tftp_state_data_t *state,
901                                    tftp_event_t event)
902 {
903   CURLcode result = CURLE_OK;
904   struct Curl_easy *data = state->conn->data;
905
906   switch(state->state) {
907   case TFTP_STATE_START:
908     DEBUGF(infof(data, "TFTP_STATE_START\n"));
909     result = tftp_send_first(state, event);
910     break;
911   case TFTP_STATE_RX:
912     DEBUGF(infof(data, "TFTP_STATE_RX\n"));
913     result = tftp_rx(state, event);
914     break;
915   case TFTP_STATE_TX:
916     DEBUGF(infof(data, "TFTP_STATE_TX\n"));
917     result = tftp_tx(state, event);
918     break;
919   case TFTP_STATE_FIN:
920     infof(data, "%s\n", "TFTP finished");
921     break;
922   default:
923     DEBUGF(infof(data, "STATE: %d\n", state->state));
924     failf(data, "%s", "Internal state machine error");
925     result = CURLE_TFTP_ILLEGAL;
926     break;
927   }
928
929   return result;
930 }
931
932 /**********************************************************
933  *
934  * tftp_disconnect
935  *
936  * The disconnect callback
937  *
938  **********************************************************/
939 static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection)
940 {
941   tftp_state_data_t *state = conn->proto.tftpc;
942   (void) dead_connection;
943
944   /* done, free dynamically allocated pkt buffers */
945   if(state) {
946     Curl_safefree(state->rpacket.data);
947     Curl_safefree(state->spacket.data);
948     free(state);
949   }
950
951   return CURLE_OK;
952 }
953
954 /**********************************************************
955  *
956  * tftp_connect
957  *
958  * The connect callback
959  *
960  **********************************************************/
961 static CURLcode tftp_connect(struct connectdata *conn, bool *done)
962 {
963   tftp_state_data_t *state;
964   int blksize, rc;
965
966   blksize = TFTP_BLKSIZE_DEFAULT;
967
968   state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t));
969   if(!state)
970     return CURLE_OUT_OF_MEMORY;
971
972   /* alloc pkt buffers based on specified blksize */
973   if(conn->data->set.tftp_blksize) {
974     blksize = (int)conn->data->set.tftp_blksize;
975     if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN)
976       return CURLE_TFTP_ILLEGAL;
977   }
978
979   if(!state->rpacket.data) {
980     state->rpacket.data = calloc(1, blksize + 2 + 2);
981
982     if(!state->rpacket.data)
983       return CURLE_OUT_OF_MEMORY;
984   }
985
986   if(!state->spacket.data) {
987     state->spacket.data = calloc(1, blksize + 2 + 2);
988
989     if(!state->spacket.data)
990       return CURLE_OUT_OF_MEMORY;
991   }
992
993   /* we don't keep TFTP connections up basically because there's none or very
994    * little gain for UDP */
995   connclose(conn, "TFTP");
996
997   state->conn = conn;
998   state->sockfd = state->conn->sock[FIRSTSOCKET];
999   state->state = TFTP_STATE_START;
1000   state->error = TFTP_ERR_NONE;
1001   state->blksize = TFTP_BLKSIZE_DEFAULT;
1002   state->requested_blksize = blksize;
1003
1004   ((struct sockaddr *)&state->local_addr)->sa_family =
1005     (unsigned short)(conn->ip_addr->ai_family);
1006
1007   tftp_set_timeouts(state);
1008
1009   if(!conn->bits.bound) {
1010     /* If not already bound, bind to any interface, random UDP port. If it is
1011      * reused or a custom local port was desired, this has already been done!
1012      *
1013      * We once used the size of the local_addr struct as the third argument
1014      * for bind() to better work with IPv6 or whatever size the struct could
1015      * have, but we learned that at least Tru64, AIX and IRIX *requires* the
1016      * size of that argument to match the exact size of a 'sockaddr_in' struct
1017      * when running IPv4-only.
1018      *
1019      * Therefore we use the size from the address we connected to, which we
1020      * assume uses the same IP version and thus hopefully this works for both
1021      * IPv4 and IPv6...
1022      */
1023     rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
1024               conn->ip_addr->ai_addrlen);
1025     if(rc) {
1026       failf(conn->data, "bind() failed; %s",
1027             Curl_strerror(conn, SOCKERRNO));
1028       return CURLE_COULDNT_CONNECT;
1029     }
1030     conn->bits.bound = TRUE;
1031   }
1032
1033   Curl_pgrsStartNow(conn->data);
1034
1035   *done = TRUE;
1036
1037   return CURLE_OK;
1038 }
1039
1040 /**********************************************************
1041  *
1042  * tftp_done
1043  *
1044  * The done callback
1045  *
1046  **********************************************************/
1047 static CURLcode tftp_done(struct connectdata *conn, CURLcode status,
1048                           bool premature)
1049 {
1050   CURLcode result = CURLE_OK;
1051   tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc;
1052
1053   (void)status; /* unused */
1054   (void)premature; /* not used */
1055
1056   if(Curl_pgrsDone(conn))
1057     return CURLE_ABORTED_BY_CALLBACK;
1058
1059   /* If we have encountered an error */
1060   if(state)
1061     result = tftp_translate_code(state->error);
1062
1063   return result;
1064 }
1065
1066 /**********************************************************
1067  *
1068  * tftp_getsock
1069  *
1070  * The getsock callback
1071  *
1072  **********************************************************/
1073 static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks,
1074                         int numsocks)
1075 {
1076   if(!numsocks)
1077     return GETSOCK_BLANK;
1078
1079   socks[0] = conn->sock[FIRSTSOCKET];
1080
1081   return GETSOCK_READSOCK(0);
1082 }
1083
1084 /**********************************************************
1085  *
1086  * tftp_receive_packet
1087  *
1088  * Called once select fires and data is ready on the socket
1089  *
1090  **********************************************************/
1091 static CURLcode tftp_receive_packet(struct connectdata *conn)
1092 {
1093   struct Curl_sockaddr_storage fromaddr;
1094   curl_socklen_t        fromlen;
1095   CURLcode              result = CURLE_OK;
1096   struct Curl_easy  *data = conn->data;
1097   tftp_state_data_t     *state = (tftp_state_data_t *)conn->proto.tftpc;
1098   struct SingleRequest  *k = &data->req;
1099
1100   /* Receive the packet */
1101   fromlen = sizeof(fromaddr);
1102   state->rbytes = (int)recvfrom(state->sockfd,
1103                                 (void *)state->rpacket.data,
1104                                 state->blksize+4,
1105                                 0,
1106                                 (struct sockaddr *)&fromaddr,
1107                                 &fromlen);
1108   if(state->remote_addrlen==0) {
1109     memcpy(&state->remote_addr, &fromaddr, fromlen);
1110     state->remote_addrlen = fromlen;
1111   }
1112
1113   /* Sanity check packet length */
1114   if(state->rbytes < 4) {
1115     failf(data, "Received too short packet");
1116     /* Not a timeout, but how best to handle it? */
1117     state->event = TFTP_EVENT_TIMEOUT;
1118   }
1119   else {
1120     /* The event is given by the TFTP packet time */
1121     state->event = (tftp_event_t)getrpacketevent(&state->rpacket);
1122
1123     switch(state->event) {
1124     case TFTP_EVENT_DATA:
1125       /* Don't pass to the client empty or retransmitted packets */
1126       if(state->rbytes > 4 &&
1127          (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) {
1128         result = Curl_client_write(conn, CLIENTWRITE_BODY,
1129                                    (char *)state->rpacket.data+4,
1130                                    state->rbytes-4);
1131         if(result) {
1132           tftp_state_machine(state, TFTP_EVENT_ERROR);
1133           return result;
1134         }
1135         k->bytecount += state->rbytes-4;
1136         Curl_pgrsSetDownloadCounter(data, (curl_off_t) k->bytecount);
1137       }
1138       break;
1139     case TFTP_EVENT_ERROR:
1140       state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
1141       infof(data, "%s\n", (const char *)state->rpacket.data+4);
1142       break;
1143     case TFTP_EVENT_ACK:
1144       break;
1145     case TFTP_EVENT_OACK:
1146       result = tftp_parse_option_ack(state,
1147                                      (const char *)state->rpacket.data+2,
1148                                      state->rbytes-2);
1149       if(result)
1150         return result;
1151       break;
1152     case TFTP_EVENT_RRQ:
1153     case TFTP_EVENT_WRQ:
1154     default:
1155       failf(data, "%s", "Internal error: Unexpected packet");
1156       break;
1157     }
1158
1159     /* Update the progress meter */
1160     if(Curl_pgrsUpdate(conn)) {
1161       tftp_state_machine(state, TFTP_EVENT_ERROR);
1162       return CURLE_ABORTED_BY_CALLBACK;
1163     }
1164   }
1165   return result;
1166 }
1167
1168 /**********************************************************
1169  *
1170  * tftp_state_timeout
1171  *
1172  * Check if timeouts have been reached
1173  *
1174  **********************************************************/
1175 static long tftp_state_timeout(struct connectdata *conn, tftp_event_t *event)
1176 {
1177   time_t                current;
1178   tftp_state_data_t     *state = (tftp_state_data_t *)conn->proto.tftpc;
1179
1180   if(event)
1181     *event = TFTP_EVENT_NONE;
1182
1183   time(&current);
1184   if(current > state->max_time) {
1185     DEBUGF(infof(conn->data, "timeout: %ld > %ld\n",
1186                  (long)current, (long)state->max_time));
1187     state->error = TFTP_ERR_TIMEOUT;
1188     state->state = TFTP_STATE_FIN;
1189     return 0;
1190   }
1191   else if(current > state->rx_time+state->retry_time) {
1192     if(event)
1193       *event = TFTP_EVENT_TIMEOUT;
1194     time(&state->rx_time); /* update even though we received nothing */
1195   }
1196
1197   /* there's a typecast below here since 'time_t' may in fact be larger than
1198      'long', but we estimate that a 'long' will still be able to hold number
1199      of seconds even if "only" 32 bit */
1200   return (long)(state->max_time - current);
1201 }
1202
1203 /**********************************************************
1204  *
1205  * tftp_multi_statemach
1206  *
1207  * Handle single RX socket event and return
1208  *
1209  **********************************************************/
1210 static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done)
1211 {
1212   int                   rc;
1213   tftp_event_t          event;
1214   CURLcode              result = CURLE_OK;
1215   struct Curl_easy  *data = conn->data;
1216   tftp_state_data_t     *state = (tftp_state_data_t *)conn->proto.tftpc;
1217   long                  timeout_ms = tftp_state_timeout(conn, &event);
1218
1219   *done = FALSE;
1220
1221   if(timeout_ms <= 0) {
1222     failf(data, "TFTP response timeout");
1223     return CURLE_OPERATION_TIMEDOUT;
1224   }
1225   else if(event != TFTP_EVENT_NONE) {
1226     result = tftp_state_machine(state, event);
1227     if(result)
1228       return result;
1229     *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
1230     if(*done)
1231       /* Tell curl we're done */
1232       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
1233   }
1234   else {
1235     /* no timeouts to handle, check our socket */
1236     rc = Curl_socket_ready(state->sockfd, CURL_SOCKET_BAD, 0);
1237
1238     if(rc == -1) {
1239       /* bail out */
1240       int error = SOCKERRNO;
1241       failf(data, "%s", Curl_strerror(conn, error));
1242       state->event = TFTP_EVENT_ERROR;
1243     }
1244     else if(rc != 0) {
1245       result = tftp_receive_packet(conn);
1246       if(result)
1247         return result;
1248       result = tftp_state_machine(state, state->event);
1249       if(result)
1250         return result;
1251       *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE;
1252       if(*done)
1253         /* Tell curl we're done */
1254         Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
1255     }
1256     /* if rc == 0, then select() timed out */
1257   }
1258
1259   return result;
1260 }
1261
1262 /**********************************************************
1263  *
1264  * tftp_doing
1265  *
1266  * Called from multi.c while DOing
1267  *
1268  **********************************************************/
1269 static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done)
1270 {
1271   CURLcode result;
1272   result = tftp_multi_statemach(conn, dophase_done);
1273
1274   if(*dophase_done) {
1275     DEBUGF(infof(conn->data, "DO phase is complete\n"));
1276   }
1277   else if(!result) {
1278     /* The multi code doesn't have this logic for the DOING state so we
1279        provide it for TFTP since it may do the entire transfer in this
1280        state. */
1281     if(Curl_pgrsUpdate(conn))
1282       result = CURLE_ABORTED_BY_CALLBACK;
1283     else
1284       result = Curl_speedcheck(conn->data, Curl_tvnow());
1285   }
1286   return result;
1287 }
1288
1289 /**********************************************************
1290  *
1291  * tftp_peform
1292  *
1293  * Entry point for transfer from tftp_do, sarts state mach
1294  *
1295  **********************************************************/
1296 static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done)
1297 {
1298   CURLcode              result = CURLE_OK;
1299   tftp_state_data_t     *state = (tftp_state_data_t *)conn->proto.tftpc;
1300
1301   *dophase_done = FALSE;
1302
1303   result = tftp_state_machine(state, TFTP_EVENT_INIT);
1304
1305   if((state->state == TFTP_STATE_FIN) || result)
1306     return result;
1307
1308   tftp_multi_statemach(conn, dophase_done);
1309
1310   if(*dophase_done)
1311     DEBUGF(infof(conn->data, "DO phase is complete\n"));
1312
1313   return result;
1314 }
1315
1316
1317 /**********************************************************
1318  *
1319  * tftp_do
1320  *
1321  * The do callback
1322  *
1323  * This callback initiates the TFTP transfer
1324  *
1325  **********************************************************/
1326
1327 static CURLcode tftp_do(struct connectdata *conn, bool *done)
1328 {
1329   tftp_state_data_t *state;
1330   CURLcode result;
1331
1332   *done = FALSE;
1333
1334   if(!conn->proto.tftpc) {
1335     result = tftp_connect(conn, done);
1336     if(result)
1337       return result;
1338   }
1339
1340   state = (tftp_state_data_t *)conn->proto.tftpc;
1341   if(!state)
1342     return CURLE_BAD_CALLING_ORDER;
1343
1344   result = tftp_perform(conn, done);
1345
1346   /* If tftp_perform() returned an error, use that for return code. If it
1347      was OK, see if tftp_translate_code() has an error. */
1348   if(!result)
1349     /* If we have encountered an internal tftp error, translate it. */
1350     result = tftp_translate_code(state->error);
1351
1352   return result;
1353 }
1354
1355 static CURLcode tftp_setup_connection(struct connectdata * conn)
1356 {
1357   struct Curl_easy *data = conn->data;
1358   char * type;
1359   char command;
1360
1361   conn->socktype = SOCK_DGRAM;   /* UDP datagram based */
1362
1363   /* TFTP URLs support an extension like ";mode=<typecode>" that
1364    * we'll try to get now! */
1365   type = strstr(data->state.path, ";mode=");
1366
1367   if(!type)
1368     type = strstr(conn->host.rawalloc, ";mode=");
1369
1370   if(type) {
1371     *type = 0;                   /* it was in the middle of the hostname */
1372     command = Curl_raw_toupper(type[6]);
1373
1374     switch (command) {
1375     case 'A': /* ASCII mode */
1376     case 'N': /* NETASCII mode */
1377       data->set.prefer_ascii = TRUE;
1378       break;
1379
1380     case 'O': /* octet mode */
1381     case 'I': /* binary mode */
1382     default:
1383       /* switch off ASCII */
1384       data->set.prefer_ascii = FALSE;
1385       break;
1386     }
1387   }
1388
1389   return CURLE_OK;
1390 }
1391 #endif