1 /**
2  *
3  * @file tftp.c
4  *
5  * @author   Logan Gunthorpe <logang@deltatee.com>
6  *           Dirk Ziegelmeier <dziegel@gmx.de>
7  *
8  * @brief    Trivial File Transfer Protocol (RFC 1350)
9  *
10  * Copyright (c) Deltatee Enterprises Ltd. 2013
11  * All rights reserved.
12  *
13  */
14 
15 /*
16  * Redistribution and use in source and binary forms, with or without
17  * modification,are permitted provided that the following conditions are met:
18  *
19  * 1. Redistributions of source code must retain the above copyright notice,
20  *    this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright notice,
22  *    this list of conditions and the following disclaimer in the documentation
23  *    and/or other materials provided with the distribution.
24  * 3. The name of the author may not be used to endorse or promote products
25  *    derived from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
28  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
30  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
32  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *
38  * Author: Logan Gunthorpe <logang@deltatee.com>
39  *         Dirk Ziegelmeier <dziegel@gmx.de>
40  *
41  */
42 
43 /**
44  * @defgroup tftp TFTP client/server
45  * @ingroup apps
46  *
47  * This is simple TFTP client/server for the lwIP raw API.
48  * You need to increase MEMP_NUM_SYS_TIMEOUT by one if you use TFTP!
49  */
50 
51 #include "lwip/apps/tftp_client.h"
52 #include "lwip/apps/tftp_server.h"
53 
54 #if LWIP_UDP
55 
56 #include "lwip/udp.h"
57 #include "lwip/timeouts.h"
58 #include "lwip/debug.h"
59 
60 #define TFTP_MAX_PAYLOAD_SIZE 512
61 #define TFTP_HEADER_LENGTH    4
62 
63 #define TFTP_RRQ   1
64 #define TFTP_WRQ   2
65 #define TFTP_DATA  3
66 #define TFTP_ACK   4
67 #define TFTP_ERROR 5
68 
69 enum tftp_error {
70   TFTP_ERROR_FILE_NOT_FOUND    = 1,
71   TFTP_ERROR_ACCESS_VIOLATION  = 2,
72   TFTP_ERROR_DISK_FULL         = 3,
73   TFTP_ERROR_ILLEGAL_OPERATION = 4,
74   TFTP_ERROR_UNKNOWN_TRFR_ID   = 5,
75   TFTP_ERROR_FILE_EXISTS       = 6,
76   TFTP_ERROR_NO_SUCH_USER      = 7
77 };
78 
79 #include <string.h>
80 
81 struct tftp_state {
82   const struct tftp_context *ctx;
83   void *handle;
84   struct pbuf *last_data;
85   struct udp_pcb *upcb;
86   ip_addr_t addr;
87   u16_t port;
88   int timer;
89   int last_pkt;
90   u16_t blknum;
91   u8_t retries;
92   u8_t mode_write;
93   u8_t tftp_mode;
94 };
95 
96 static struct tftp_state tftp_state;
97 
98 static void tftp_tmr(void *arg);
99 
100 static void
101 close_handle(void)
102 {
103   tftp_state.port = 0;
104   ip_addr_set_any(0, &tftp_state.addr);
105 
106   if (tftp_state.last_data != NULL) {
107     pbuf_free(tftp_state.last_data);
108     tftp_state.last_data = NULL;
109   }
110 
111   sys_untimeout(tftp_tmr, NULL);
112 
113   if (tftp_state.handle) {
114     tftp_state.ctx->close(tftp_state.handle);
115     tftp_state.handle = NULL;
116     LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n"));
117   }
118 }
119 
120 static struct pbuf*
121 init_packet(u16_t opcode, u16_t extra, size_t size)
122 {
123   struct pbuf* p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(TFTP_HEADER_LENGTH + size), PBUF_RAM);
124   u16_t* payload;
125 
126   if (p != NULL) {
127     payload = (u16_t*) p->payload;
128     payload[0] = PP_HTONS(opcode);
129     payload[1] = lwip_htons(extra);
130   }
131 
132   return p;
133 }
134 
135 static err_t
136 send_request(const ip_addr_t *addr, u16_t port, u16_t opcode, const char* fname, const char* mode)
137 {
138   size_t fname_length = strlen(fname)+1;
139   size_t mode_length = strlen(mode)+1;
140   struct pbuf* p = init_packet(opcode, 0, fname_length + mode_length - 2);
141   char* payload;
142   err_t ret;
143 
144   if (p == NULL) {
145     return ERR_MEM;
146   }
147 
148   payload = (char*) p->payload;
149   MEMCPY(payload+2,              fname, fname_length);
150   MEMCPY(payload+2+fname_length, mode,  mode_length);
151 
152   ret = udp_sendto(tftp_state.upcb, p, addr, port);
153   pbuf_free(p);
154   return ret;
155 }
156 
157 static err_t
158 send_error(const ip_addr_t *addr, u16_t port, enum tftp_error code, const char *str)
159 {
160   int str_length = strlen(str);
161   struct pbuf *p;
162   u16_t *payload;
163   err_t ret;
164 
165   p = init_packet(TFTP_ERROR, code, str_length + 1);
166   if (p == NULL) {
167     return ERR_MEM;
168   }
169 
170   payload = (u16_t *) p->payload;
171   MEMCPY(&payload[2], str, str_length + 1);
172 
173   ret = udp_sendto(tftp_state.upcb, p, addr, port);
174   pbuf_free(p);
175   return ret;
176 }
177 
178 static err_t
179 send_ack(const ip_addr_t *addr, u16_t port, u16_t blknum)
180 {
181   struct pbuf *p;
182   err_t ret;
183 
184   p = init_packet(TFTP_ACK, blknum, 0);
185   if (p == NULL) {
186     return ERR_MEM;
187   }
188 
189   ret = udp_sendto(tftp_state.upcb, p, addr, port);
190   pbuf_free(p);
191   return ret;
192 }
193 
194 static err_t
195 resend_data(const ip_addr_t *addr, u16_t port)
196 {
197   err_t ret;
198   struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, tftp_state.last_data->len, PBUF_RAM);
199   if (p == NULL) {
200     return ERR_MEM;
201   }
202 
203   ret = pbuf_copy(p, tftp_state.last_data);
204   if (ret != ERR_OK) {
205     pbuf_free(p);
206     return ret;
207   }
208 
209   ret = udp_sendto(tftp_state.upcb, p, addr, port);
210   pbuf_free(p);
211   return ret;
212 }
213 
214 static void
215 send_data(const ip_addr_t *addr, u16_t port)
216 {
217   u16_t *payload;
218   int ret;
219 
220   if (tftp_state.last_data != NULL) {
221     pbuf_free(tftp_state.last_data);
222   }
223 
224   tftp_state.last_data = init_packet(TFTP_DATA, tftp_state.blknum, TFTP_MAX_PAYLOAD_SIZE);
225   if (tftp_state.last_data == NULL) {
226     return;
227   }
228 
229   payload = (u16_t *) tftp_state.last_data->payload;
230 
231   ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE);
232   if (ret < 0) {
233     send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Error occurred while reading the file.");
234     close_handle();
235     return;
236   }
237 
238   pbuf_realloc(tftp_state.last_data, (u16_t)(TFTP_HEADER_LENGTH + ret));
239   resend_data(addr, port);
240 }
241 
242 static void
243 tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
244 {
245   u16_t *sbuf = (u16_t *) p->payload;
246   int opcode;
247 
248   LWIP_UNUSED_ARG(arg);
249   LWIP_UNUSED_ARG(upcb);
250 
251   if (((tftp_state.port != 0) && (port != tftp_state.port)) ||
252       (!ip_addr_isany_val(tftp_state.addr) && !ip_addr_eq(&tftp_state.addr, addr))) {
253     send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported");
254     pbuf_free(p);
255     return;
256   }
257 
258   opcode = sbuf[0];
259 
260   tftp_state.last_pkt = tftp_state.timer;
261   tftp_state.retries = 0;
262 
263   switch (opcode) {
264     case PP_HTONS(TFTP_RRQ): /* fall through */
265     case PP_HTONS(TFTP_WRQ): {
266       const char tftp_null = 0;
267       char filename[TFTP_MAX_FILENAME_LEN + 1];
268       char mode[TFTP_MAX_MODE_LEN + 1];
269       u16_t filename_end_offset;
270       u16_t mode_end_offset;
271 
272       if (tftp_state.handle != NULL) {
273         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported");
274         break;
275       }
276 
277       if ((tftp_state.tftp_mode & LWIP_TFTP_MODE_SERVER) == 0) {
278         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "TFTP server not enabled");
279         break;
280       }
281 
282       sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL);
283 
284       /* find \0 in pbuf -> end of filename string */
285       filename_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), 2);
286       if ((u16_t)(filename_end_offset - 1) > sizeof(filename)) {
287         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Filename too long/not NULL terminated");
288         break;
289       }
290       pbuf_copy_partial(p, filename, filename_end_offset - 1, 2);
291 
292       /* find \0 in pbuf -> end of mode string */
293       mode_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), filename_end_offset + 1);
294       if ((u16_t)(mode_end_offset - filename_end_offset) > sizeof(mode)) {
295         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Mode too long/not NULL terminated");
296         break;
297       }
298       pbuf_copy_partial(p, mode, mode_end_offset - filename_end_offset, filename_end_offset + 1);
299 
300       tftp_state.handle = tftp_state.ctx->open(filename, mode, opcode == PP_HTONS(TFTP_WRQ));
301       tftp_state.blknum = 1;
302 
303       if (!tftp_state.handle) {
304         send_error(addr, port, TFTP_ERROR_FILE_NOT_FOUND, "Unable to open requested file.");
305         break;
306       }
307 
308       LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: %s request from ", (opcode == PP_HTONS(TFTP_WRQ)) ? "write" : "read"));
309       ip_addr_debug_print(TFTP_DEBUG | LWIP_DBG_STATE, addr);
310       LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, (" for '%s' mode '%s'\n", filename, mode));
311 
312       ip_addr_copy(tftp_state.addr, *addr);
313       tftp_state.port = port;
314 
315       if (opcode == PP_HTONS(TFTP_WRQ)) {
316         tftp_state.mode_write = 1;
317         send_ack(addr, port, 0);
318       } else {
319         tftp_state.mode_write = 0;
320         send_data(addr, port);
321       }
322 
323       break;
324     }
325 
326     case PP_HTONS(TFTP_DATA): {
327       int ret;
328       u16_t blknum;
329 
330       if (tftp_state.handle == NULL) {
331         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection");
332         break;
333       }
334 
335       if (tftp_state.mode_write != 1) {
336         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a write connection");
337         break;
338       }
339 
340       blknum = lwip_ntohs(sbuf[1]);
341       if (blknum == tftp_state.blknum) {
342         pbuf_remove_header(p, TFTP_HEADER_LENGTH);
343 
344         ret = tftp_state.ctx->write(tftp_state.handle, p);
345         if (ret < 0) {
346           send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "error writing file");
347           close_handle();
348         } else {
349           send_ack(addr, port, blknum);
350         }
351 
352         if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) {
353           close_handle();
354         } else {
355           tftp_state.blknum++;
356         }
357       } else if ((u16_t)(blknum + 1) == tftp_state.blknum) {
358         /* retransmit of previous block, ack again (casting to u16_t to care for overflow) */
359         send_ack(addr, port, blknum);
360       } else {
361         send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number");
362       }
363       break;
364     }
365 
366     case PP_HTONS(TFTP_ACK): {
367       u16_t blknum;
368       int lastpkt;
369 
370       if (tftp_state.handle == NULL) {
371         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection");
372         break;
373       }
374 
375       if (tftp_state.mode_write != 0) {
376         send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a read connection");
377         break;
378       }
379 
380       blknum = lwip_ntohs(sbuf[1]);
381       if (blknum != tftp_state.blknum) {
382         send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number");
383         break;
384       }
385 
386       lastpkt = 0;
387 
388       if (tftp_state.last_data != NULL) {
389         lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH);
390       }
391 
392       if (!lastpkt) {
393         tftp_state.blknum++;
394         send_data(addr, port);
395       } else {
396         close_handle();
397       }
398 
399       break;
400     }
401     case PP_HTONS(TFTP_ERROR):
402       if (tftp_state.handle != NULL) {
403         pbuf_remove_header(p, TFTP_HEADER_LENGTH);
404         tftp_state.ctx->error(tftp_state.handle, sbuf[1], (const char*)p->payload, p->len);
405         close_handle();
406       }
407       break;
408     default:
409       send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation");
410       break;
411   }
412 
413   pbuf_free(p);
414 }
415 
416 static void
417 tftp_tmr(void *arg)
418 {
419   LWIP_UNUSED_ARG(arg);
420 
421   tftp_state.timer++;
422 
423   if (tftp_state.handle == NULL) {
424     return;
425   }
426 
427   sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL);
428 
429   if ((tftp_state.timer - tftp_state.last_pkt) > (TFTP_TIMEOUT_MSECS / TFTP_TIMER_MSECS)) {
430     if ((tftp_state.last_data != NULL) && (tftp_state.retries < TFTP_MAX_RETRIES)) {
431       LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout, retrying\n"));
432       resend_data(&tftp_state.addr, tftp_state.port);
433       tftp_state.retries++;
434     } else {
435       LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout\n"));
436       close_handle();
437     }
438   }
439 }
440 
441 /**
442  * Initialize TFTP client/server.
443  * @param mode TFTP mode (client/server)
444  * @param ctx TFTP callback struct
445  */
446 err_t
447 tftp_init_common(u8_t mode, const struct tftp_context *ctx)
448 {
449   err_t ret;
450 
451   /* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */
452   struct udp_pcb *pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
453   if (pcb == NULL) {
454     return ERR_MEM;
455   }
456 
457   ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT);
458   if (ret != ERR_OK) {
459     udp_remove(pcb);
460     return ret;
461   }
462 
463   tftp_state.handle    = NULL;
464   tftp_state.port      = 0;
465   tftp_state.ctx       = ctx;
466   tftp_state.timer     = 0;
467   tftp_state.last_data = NULL;
468   tftp_state.upcb      = pcb;
469   tftp_state.tftp_mode = mode;
470 
471   udp_recv(pcb, tftp_recv, NULL);
472 
473   return ERR_OK;
474 }
475 
476 /** @ingroup tftp
477  * Initialize TFTP server.
478  * @param ctx TFTP callback struct
479  */
480 err_t
481 tftp_init_server(const struct tftp_context *ctx)
482 {
483   return tftp_init_common(LWIP_TFTP_MODE_SERVER, ctx);
484 }
485 
486 /** @ingroup tftp
487  * Initialize TFTP client.
488  * @param ctx TFTP callback struct
489  */
490 err_t
491 tftp_init_client(const struct tftp_context *ctx)
492 {
493   return tftp_init_common(LWIP_TFTP_MODE_CLIENT, ctx);
494 }
495 
496 /** @ingroup tftp
497  * Deinitialize ("turn off") TFTP client/server.
498  */
499 void tftp_cleanup(void)
500 {
501   LWIP_ASSERT("Cleanup called on non-initialized TFTP", tftp_state.upcb != NULL);
502   udp_remove(tftp_state.upcb);
503   close_handle();
504   memset(&tftp_state, 0, sizeof(tftp_state));
505 }
506 
507 static const char *
508 mode_to_string(enum tftp_transfer_mode mode)
509 {
510   if (mode == TFTP_MODE_OCTET) {
511     return "octet";
512   }
513   if (mode == TFTP_MODE_NETASCII) {
514     return "netascii";
515   }
516   if (mode == TFTP_MODE_BINARY) {
517     return "binary";
518   }
519   return NULL;
520 }
521 
522 err_t
523 tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode)
524 {
525   LWIP_ERROR("TFTP client is not enabled (tftp_init)", (tftp_state.tftp_mode & LWIP_TFTP_MODE_CLIENT) != 0, return ERR_VAL);
526   LWIP_ERROR("tftp_get: invalid file name", fname != NULL, return ERR_VAL);
527   LWIP_ERROR("tftp_get: invalid mode", mode <= TFTP_MODE_BINARY, return ERR_VAL);
528 
529   tftp_state.handle = handle;
530   tftp_state.blknum = 1;
531   tftp_state.mode_write = 1; /* We want to receive data */
532   return send_request(addr, port, TFTP_RRQ, fname, mode_to_string(mode));
533 }
534 
535 err_t
536 tftp_put(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, enum tftp_transfer_mode mode)
537 {
538   LWIP_ERROR("TFTP client is not enabled (tftp_init)", (tftp_state.tftp_mode & LWIP_TFTP_MODE_CLIENT) != 0, return ERR_VAL);
539   LWIP_ERROR("tftp_put: invalid file name", fname != NULL, return ERR_VAL);
540   LWIP_ERROR("tftp_put: invalid mode", mode <= TFTP_MODE_BINARY, return ERR_VAL);
541 
542   tftp_state.handle = handle;
543   tftp_state.blknum = 1;
544   tftp_state.mode_write = 0; /* We want to send data */
545   return send_request(addr, port, TFTP_WRQ, fname, mode_to_string(mode));
546 }
547 
548 #endif /* LWIP_UDP */
549