/** * \file * * * \brief TFTP protocol implementation * * This module implements a TFTP server with a handy KFile interface. * The call to tftp_listen() will block until a client tries to connect, * then it returns a KFile. * If you want to accept the transfer, start reading from the handle and * the transfer will continue. Otherwise, don't access it and immediately * call kfile_close(). * Close the KFile when you're done. * * The usage pattern is as follows: * \code * // initialize a TFTP session * tftp_init(); * // start listening for connections * KFile *f = tftp_listen(); * // now you can check the returned file name * // and change behaviour at runtime * if (!strcmp(filename, "firmware.bin")) * // do something * else if (!strcmp(filename, "conf.ini")) * // update the configuration * kfile_close(f); * \endcode * * * \author Luca Ottaviano * * $WIZ$ module_name = "tftp" * $WIZ$ module_configuration = "bertos/cfg/cfg_tftp.h" * $WIZ$ module_depends = "lwip", "kfile" */ #ifndef TFTP_H #define TFTP_H #include #include // sockaddr_in, socklen_t #include #define TFTP_RRQ 0x0100 /* TFTP read request packet (already in net endianess). */ #define TFTP_WRQ 0x0200 /* TFTP write request packet (already in net endianess). */ #define TFTP_DATA 03 /* TFTP data packet. */ #define TFTP_ACK 0x0400 /* TFTP acknowledgement packet (already in net endianess). */ #define TFTP_PROTOERR 0x0500 /* TFTP acknowledgement packet (already in net endianess). */ /* TFTP protocol error codes */ #define TFTP_PROTOERR_ACCESS_VIOLATION 0x0200 #define TFTP_SERVER_PORT 69 /* Return error codes */ #define TFTP_ERR_TIMEOUT -2 #define TFTP_ERR -1 struct PACKED TftpHeader { short opcode; ///< packet type */ union PACKED { short block; /* block # */ short code; /* error code */ char stuff[1]; /* request packet stuff */ } th_u; }; typedef struct PACKED Tftpframe { struct TftpHeader hdr; char data[512]; /* data or error string */ } Tftpframe; struct PACKED ackframe { short opcode; short block_num; }; struct PACKED errframe { short opcode; short errcode; char str; }; typedef enum { TFTP_READ, TFTP_WRITE, } TftpOpenMode; typedef struct TftpSession { struct sockaddr_in addr; socklen_t addr_len; int sock; unsigned short block; mtime_t timeout; int error; Tftpframe frame; size_t bytes_available; size_t valid_data; bool is_xfer_end; bool pending_ack; KFile kfile_request; } TftpSession; int tftp_init(TftpSession *ctx, unsigned short port, mtime_t timeout); KFile *tftp_listen(TftpSession *ctx, char *filename, size_t len, TftpOpenMode *mode); #endif // TFTP_H