60#define TFTP_MAX_PAYLOAD_SIZE 512
61#define TFTP_HEADER_LENGTH 4
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
84 struct pbuf *last_data;
96static struct tftp_state tftp_state;
98static void tftp_tmr(
void *
arg);
106 if (tftp_state.last_data !=
NULL) {
108 tftp_state.last_data =
NULL;
111 sys_untimeout(tftp_tmr,
NULL);
113 if (tftp_state.handle) {
114 tftp_state.ctx->close(tftp_state.handle);
115 tftp_state.handle =
NULL;
138 size_t fname_length =
strlen(fname)+1;
140 struct pbuf*
p = init_packet(opcode, 0, fname_length + mode_length - 2);
165 p = init_packet(TFTP_ERROR,
code, str_length + 1);
184 p = init_packet(TFTP_ACK, blknum, 0);
220 if (tftp_state.last_data !=
NULL) {
224 tftp_state.last_data = init_packet(TFTP_DATA, tftp_state.blknum, TFTP_MAX_PAYLOAD_SIZE);
225 if (tftp_state.last_data ==
NULL) {
231 ret = tftp_state.ctx->read(tftp_state.handle, &
payload[2], TFTP_MAX_PAYLOAD_SIZE);
233 send_error(
addr,
port, TFTP_ERROR_ACCESS_VIOLATION,
"Error occurred while reading the file.");
251 if (((tftp_state.port != 0) && (
port != tftp_state.port)) ||
253 send_error(
addr,
port, TFTP_ERROR_ACCESS_VIOLATION,
"Only one connection at a time is supported");
260 tftp_state.last_pkt = tftp_state.timer;
261 tftp_state.retries = 0;
266 const char tftp_null = 0;
269 u16_t filename_end_offset;
270 u16_t mode_end_offset;
272 if (tftp_state.handle !=
NULL) {
273 send_error(
addr,
port, TFTP_ERROR_ACCESS_VIOLATION,
"Only one connection at a time is supported");
278 send_error(
addr,
port, TFTP_ERROR_ACCESS_VIOLATION,
"TFTP server not enabled");
285 filename_end_offset =
pbuf_memfind(
p, &tftp_null,
sizeof(tftp_null), 2);
287 send_error(
addr,
port, TFTP_ERROR_ACCESS_VIOLATION,
"Filename too long/not NULL terminated");
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");
301 tftp_state.blknum = 1;
303 if (!tftp_state.handle) {
304 send_error(
addr,
port, TFTP_ERROR_FILE_NOT_FOUND,
"Unable to open requested file.");
313 tftp_state.port =
port;
316 tftp_state.mode_write = 1;
319 tftp_state.mode_write = 0;
330 if (tftp_state.handle ==
NULL) {
331 send_error(
addr,
port, TFTP_ERROR_ACCESS_VIOLATION,
"No connection");
335 if (tftp_state.mode_write != 1) {
336 send_error(
addr,
port, TFTP_ERROR_ACCESS_VIOLATION,
"Not a write connection");
341 if (blknum == tftp_state.blknum) {
344 ret = tftp_state.ctx->write(tftp_state.handle,
p);
346 send_error(
addr,
port, TFTP_ERROR_ACCESS_VIOLATION,
"error writing file");
352 if (
p->tot_len < TFTP_MAX_PAYLOAD_SIZE) {
357 }
else if ((
u16_t)(blknum + 1) == tftp_state.blknum) {
361 send_error(
addr,
port, TFTP_ERROR_UNKNOWN_TRFR_ID,
"Wrong block number");
370 if (tftp_state.handle ==
NULL) {
371 send_error(
addr,
port, TFTP_ERROR_ACCESS_VIOLATION,
"No connection");
375 if (tftp_state.mode_write != 0) {
376 send_error(
addr,
port, TFTP_ERROR_ACCESS_VIOLATION,
"Not a read connection");
381 if (blknum != tftp_state.blknum) {
382 send_error(
addr,
port, TFTP_ERROR_UNKNOWN_TRFR_ID,
"Wrong block number");
388 if (tftp_state.last_data !=
NULL) {
389 lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH);
404 tftp_state.ctx->error(tftp_state.handle, sbuf[1], (
const char*)
p->payload,
p->len);
409 send_error(
addr,
port, TFTP_ERROR_ILLEGAL_OPERATION,
"Unknown operation");
423 if (tftp_state.handle ==
NULL) {
432 resend_data(&tftp_state.addr, tftp_state.port);
433 tftp_state.retries++;
463 tftp_state.handle =
NULL;
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;
471 udp_recv(pcb, tftp_recv,
NULL);
501 LWIP_ASSERT(
"Cleanup called on non-initialized TFTP", tftp_state.upcb !=
NULL);
502 udp_remove(tftp_state.upcb);
504 memset(&tftp_state, 0,
sizeof(tftp_state));
529 tftp_state.handle =
handle;
530 tftp_state.blknum = 1;
531 tftp_state.mode_write = 1;
542 tftp_state.handle =
handle;
543 tftp_state.blknum = 1;
544 tftp_state.mode_write = 0;
ACPI_SIZE strlen(const char *String)
#define LWIP_DEBUGF(debug, message)
#define LWIP_ERROR(message, expression, handler)
#define LWIP_ASSERT(message, assertion)
GLenum const GLvoid * addr
#define LWIP_UNUSED_ARG(x)
u16_t pbuf_memfind(const struct pbuf *p, const void *mem, u16_t mem_len, u16_t start_offset)
void pbuf_realloc(struct pbuf *p, u16_t new_len)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
#define TFTP_TIMEOUT_MSECS
#define TFTP_MAX_FILENAME_LEN
#define TFTP_MAX_MODE_LEN
#define ip_addr_eq(addr1, addr2)
#define ip_addr_copy(dest, src)
#define ip_addr_set_any(is_ipv6, ipaddr)
#define ip_addr_isany_val(ipaddr)
#define ip_addr_debug_print(debug, ipaddr)
#define MEMCPY(DST, SRC, BYTES)
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
err_t tftp_get(void *handle, const ip_addr_t *addr, u16_t port, const char *fname, enum tftp_transfer_mode mode)
err_t tftp_put(void *handle, const ip_addr_t *addr, u16_t port, const char *fname, enum tftp_transfer_mode mode)
err_t tftp_init_client(const struct tftp_context *ctx)
#define LWIP_TFTP_MODE_SERVER
err_t tftp_init_common(u8_t mode, const struct tftp_context *ctx)
#define LWIP_TFTP_MODE_CLIENT
err_t tftp_init_server(const struct tftp_context *ctx)