From 6c2fd2d25d256525ae6abbc283af57511b33adb9 Mon Sep 17 00:00:00 2001 From: Dirk Ziegelmeier Date: Mon, 8 Oct 2018 12:45:29 +0200 Subject: [PATCH] Improve TFTP implementation - implement server/client mode (API is nicer to use) - Increase TFTP_MAX_MODE_LEN to be able to contain "netascii" transfer mode - Adapt tftp_example to changes --- contrib/examples/tftp/tftp_example.c | 50 ++++++++++++++++++---------- src/apps/tftp/tftp.c | 43 +++++++++++++++++++++--- src/include/lwip/apps/tftp_client.h | 1 + src/include/lwip/apps/tftp_common.h | 6 +++- src/include/lwip/apps/tftp_opts.h | 2 +- src/include/lwip/apps/tftp_server.h | 4 ++- 6 files changed, 82 insertions(+), 24 deletions(-) diff --git a/contrib/examples/tftp/tftp_example.c b/contrib/examples/tftp/tftp_example.c index 60a9c2f7..07c65a80 100644 --- a/contrib/examples/tftp/tftp_example.c +++ b/contrib/examples/tftp/tftp_example.c @@ -1,5 +1,5 @@ /* - * Redistribution and use in source and binary forms, with or without modification, + * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, @@ -8,21 +8,21 @@ * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * derived from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * This file is part of the lwIP TCP/IP stack. - * + * * Author: Dirk Ziegelmeier * */ @@ -32,13 +32,15 @@ #include "lwip/apps/tftp_server.h" #include "tftp_example.h" +#include + #if LWIP_UDP static void* tftp_open(const char* fname, const char* mode, u8_t is_write) { LWIP_UNUSED_ARG(mode); - + if (is_write) { return (void*)fopen(fname, "wb"); } else { @@ -46,7 +48,7 @@ tftp_open(const char* fname, const char* mode, u8_t is_write) } } -static void +static void tftp_close(void* handle) { fclose((FILE*)handle); @@ -71,7 +73,20 @@ tftp_write(void* handle, struct pbuf* p) } p = p->next; } - + + return 0; +} + +static int +tftp_error(void* handle, int err, const char* msg, int size) +{ + char message[100]; + + memset(message, 0, sizeof(message)); + MEMCPY(message, msg, LWIP_MIN(sizeof(message)-1, size)); + + printf("TFTP error: %d (%s)", err, message); + return 0; } @@ -79,13 +94,14 @@ static const struct tftp_context tftp = { tftp_open, tftp_close, tftp_read, - tftp_write + tftp_write, + tftp_error }; void tftp_example_init(void) { - tftp_init(&tftp); + tftp_init_server(&tftp); } #endif /* LWIP_UDP */ diff --git a/src/apps/tftp/tftp.c b/src/apps/tftp/tftp.c index c6cfc699..78742d0b 100644 --- a/src/apps/tftp/tftp.c +++ b/src/apps/tftp/tftp.c @@ -91,6 +91,7 @@ struct tftp_state { }; static struct tftp_state tftp_state; +static u8_t tftp_mode; static void tftp_tmr(void *arg); @@ -261,6 +262,11 @@ recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16 break; } + if ((tftp_mode & LWIP_TFTP_MODE_SERVER) == 0) { + send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "TFTP server not enabled"); + break; + } + sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); /* find \0 in pbuf -> end of filename string */ @@ -420,12 +426,13 @@ tftp_tmr(void *arg) } } -/** @ingroup tftp +/** * Initialize TFTP client/server. + * @param mode TFTP mode (client/server) * @param ctx TFTP callback struct */ err_t -tftp_init(const struct tftp_context *ctx) +tftp_init_common(u8_t mode, const struct tftp_context *ctx) { err_t ret; @@ -435,6 +442,8 @@ tftp_init(const struct tftp_context *ctx) return ERR_MEM; } + tftp_mode = mode; + ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT); if (ret != ERR_OK) { udp_remove(pcb); @@ -453,6 +462,26 @@ tftp_init(const struct tftp_context *ctx) return ERR_OK; } +/** @ingroup tftp + * Initialize TFTP server. + * @param ctx TFTP callback struct + */ +err_t +tftp_init_server(const struct tftp_context *ctx) +{ + return tftp_init_common(LWIP_TFTP_MODE_SERVER, ctx); +} + +/** @ingroup tftp + * Initialize TFTP client. + * @param ctx TFTP callback struct + */ +err_t +tftp_init_client(u8_t mode, const struct tftp_context *ctx) +{ + return tftp_init_common(LWIP_TFTP_MODE_CLIENT, ctx); +} + /** @ingroup tftp * Deinitialize ("turn off") TFTP client/server. */ @@ -465,7 +494,10 @@ void tftp_cleanup(void) } err_t -tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, const char* mode) { +tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, const char* mode) +{ + LWIP_ERROR("TFTP client is not enabled (tftp_init)", (tftp_mode & LWIP_TFTP_MODE_CLIENT) == 0, return ERR_VAL); + tftp_state.handle = handle; tftp_state.blknum = 1; tftp_state.mode_write = 1; // We want to receive data @@ -474,7 +506,10 @@ tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, con } err_t -tftp_put(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, const char* mode) { +tftp_put(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, const char* mode) +{ + LWIP_ERROR("TFTP client is not enabled (tftp_init)", (tftp_mode & LWIP_TFTP_MODE_CLIENT) == 0, return ERR_VAL); + tftp_state.handle = handle; tftp_state.blknum = 1; tftp_state.mode_write = 0; // We want to send data diff --git a/src/include/lwip/apps/tftp_client.h b/src/include/lwip/apps/tftp_client.h index 6f5df748..c65364ee 100644 --- a/src/include/lwip/apps/tftp_client.h +++ b/src/include/lwip/apps/tftp_client.h @@ -37,6 +37,7 @@ #include "lwip/apps/tftp_common.h" +err_t tftp_init_client(const struct tftp_context* ctx); err_t tftp_get(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, const char* mode); err_t tftp_put(void* handle, const ip_addr_t *addr, u16_t port, const char* fname, const char* mode); diff --git a/src/include/lwip/apps/tftp_common.h b/src/include/lwip/apps/tftp_common.h index a942852d..0fa5b524 100644 --- a/src/include/lwip/apps/tftp_common.h +++ b/src/include/lwip/apps/tftp_common.h @@ -94,7 +94,11 @@ struct tftp_context { void (*error)(void* handle, int err, const char* msg, int size); }; -err_t tftp_init(const struct tftp_context* ctx); +#define LWIP_TFTP_MODE_SERVER 0x01 +#define LWIP_TFTP_MODE_CLIENT 0x02 +#define LWIP_TFTP_MODE_CLIENTSERVER (LWIP_TFTP_MODE_SERVER | LWIP_TFTP_MODE_CLIENT) + +err_t tftp_init_common(u8_t mode, const struct tftp_context* ctx); void tftp_cleanup(void); #ifdef __cplusplus diff --git a/src/include/lwip/apps/tftp_opts.h b/src/include/lwip/apps/tftp_opts.h index 198f632b..624f103d 100644 --- a/src/include/lwip/apps/tftp_opts.h +++ b/src/include/lwip/apps/tftp_opts.h @@ -96,7 +96,7 @@ * Max. length of TFTP mode */ #if !defined TFTP_MAX_MODE_LEN || defined __DOXYGEN__ -#define TFTP_MAX_MODE_LEN 7 +#define TFTP_MAX_MODE_LEN 10 #endif /** diff --git a/src/include/lwip/apps/tftp_server.h b/src/include/lwip/apps/tftp_server.h index 16168c8e..a5769ce2 100644 --- a/src/include/lwip/apps/tftp_server.h +++ b/src/include/lwip/apps/tftp_server.h @@ -5,7 +5,7 @@ * */ -/* +/* * Redistribution and use in source and binary forms, with or without * modification,are permitted provided that the following conditions are met: * @@ -37,4 +37,6 @@ #include "lwip/apps/tftp_common.h" +err_t tftp_init_server(const struct tftp_context* ctx); + #endif /* LWIP_HDR_APPS_TFTP_SERVER_H */