⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tftp.c

📁 Embeded bootloader (rrload by ridgerun) for TI linux based platform v5.36
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * File: tftp.c * * This is an implementation of a tftp.h interface. This implementation * supplies a file byte stream as pulled from the UDP/IP/ether network stack * via TFTP. * * See Also *   tftp.h * * Copyright (C) 2002 RidgeRun, Inc. * Author: RidgeRun, Inc  <skranz@ridgerun.com> * *  This program is free software; you can redistribute  it and/or modify it *  under  the terms of  the GNU General  Public License as published by the *  Free Software Foundation;  either version 2 of the  License, or (at your *  option) any later version. * *  THIS  SOFTWARE  IS  PROVIDED  ``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. * *  You should have received a copy of the  GNU General Public License along *  with this program; if not, write  to the Free Software Foundation, Inc., *  675 Mass Ave, Cambridge, MA 02139, USA. * * Please report all bugs/problems to the author or <support@dsplinux.net> * * key: RRGPLCR (do not remove) * *//////////////////////////////////////////////////////////   A typical TFTP session goes like this:////     1. Device sends the read request to the remote server//        indicating the filename of interest and the UDP port//        number which is to receive the file blocks.//     2. Remote server sends the next 512 bytes of the file//        to the requesting device/port.//     3. Device processes the block of bytes and sends//        the remote server a TFTP ACK datagram signaling the//        server that the device is ready for the next block.//     4. goto step 2. Process continues until the last byte//        of the file has been retrieved. Device finishes//        up with a final TFTP ACK to the remote server after//        recieving the last block from the server.//        Last block can be identified by the one the has//        less than 512 bytes or has 0 bytes.////        For more info see page 427,//        "Internetworking With TCP/IP (3rd edition, vol 1)"///////////////////////////////////////////////////////#include "types.h"#include "io.h"#include "net.h"#include "util.h"#include "tftp.h"#define NORM_TFTP_PORT 69#define TFTP_RRQ   1#define TFTP_WRQ   2#define TFTP_DATA  3#define TFTP_ACK   4#define TFTP_ERROR 5typedef enum {  do_RRQ,  do_ACK} dg_type_t;#define MAX_FNAME_CHAR 200typedef struct {  unsigned short opcode;  unsigned char fname_and_mode[MAX_FNAME_CHAR]; // hmmm? that should be plenty.} tftp_RRQ_datagram_t;typedef struct {  unsigned short opcode;  unsigned char fname_and_mode[MAX_FNAME_CHAR]; // hmmm? that should be plenty.} tftp_WRQ_datagram_t;typedef struct {  unsigned short opcode;  unsigned short block_num;  unsigned char block_buff[512]; // size as per page 428, "Internetworking With TCP/IP (3rd edition, vol 1)"} tftp_DATA_datagram_t; // total bytes 516.typedef struct {  unsigned short opcode;  unsigned short block_num;} tftp_ACK_datagram_t;typedef struct {  unsigned short opcode;  unsigned short err_code;  unsigned char err_msg[MAX_FNAME_CHAR]; // hmmm? that should be plenty.} tftp_ERROR_datagram_t;// --tftp_datagram_t--// This datagram can take on any one of these// specific formats.  Of course, one at a time// since this is a "union" not a "struct".typedef union {  unsigned short opcode; // first 2 bytes indicate which format applies.  tftp_RRQ_datagram_t   RRQ;  tftp_WRQ_datagram_t   WRQ;  tftp_DATA_datagram_t  DATA;  tftp_ACK_datagram_t   ACK;  tftp_ERROR_datagram_t ERROR;} tftp_datagram_t; // total bytes 516 (the largest component of this union).// --full_ether_frame_t--// This memory represents the full buffer space needed// by the various levels of the network stack extending// from TFTP down to the ether chipset. The TFTP layer// will only deal with tftp_data_gram field and as we// pass it to the network stack the other fields will// be supplied as the datagram is furthur prepared before// finally being sent to the remote server as a full// ether frame.typedef struct {  ether_hdr_t reserved_space1;  ip_hdr_t reserved_space2;  udp_hdr_t reserved_space3;  tftp_datagram_t tftp_data_gram;  long dummy1; // See Note below} __attribute__ ((packed)) full_ether_frame_t;// Note: the dummy1 field just insures that we//       tack on an extra 32bits worth to give the//       underlying ethernet implementation used the//       freedom to round-up the incoming packet size//       to the nearest 32bit boudary and still have//       the bytes contained within what we define to//       be the longest ether frame. They may chose//       to round up for speed reasons.// Okay, I've carefully added up the number of bytes that// full_ether_frame_t should contain assuming no compiler// padding. We don't want compiler padding since the// network specs require contiguous fields side-by-side// with no compiler ejected padding. The following// constant will help us catch the padding case at// run-time. If one day we switch to a compiler that does// the padding we'll have to re-architect the way we've// currently choosen to express the full_ether_frame_t here.#define SIZEFULLFRAME (562)// Note:// The Start_Of_Session is a global variable that was added// to work around some network issues discovered on the c5471// platform. The idea is that sometimes the first tftp packet// will not arrive at the destination machine -- so a workaround// at the lowest levels (ether_c5471.c) was to recognize the// start of a tftp session so that if no response arrived at// the ether driver in X milliseconds following the outgoing// tftp packet, then it could retry the packet xmit a number// of times in the hopes to get things going. It seems that// once that first packet arrived at the destination machine// then the remaining packets of the TFTP session seemed to// go fine. The issue seemed to be getting that first packet// of a session to go out. Skranz Jan 2002.//int Start_Of_Session; // See Note Above.static full_ether_frame_t full_ether_frame;static tftp_datagram_t *data_gram;static unsigned char *block_buff_curr;static unsigned char *block_buff_end;static int new_connection;static int Whole_file_xferred;static unsigned short expected_block_num;static unsigned short reply_port;static char tftp_filename[MAX_FNAME_CHAR]; // hmmm?, should be plenty.static char tftp_device_IP[16]; // standard size. "100.200.300.400\0"static char tftp_server_IP[16]; // standard size. "100.200.300.400\0"static char tftp_device_MAC[18];// standard size. "00:e0:81:10:36:cf\0"static char tftp_server_MAC[18];// standard size. "00:50:DA:CC:5D:09\0"/****************************** Routine: Description:    Build a tftp datagram as per page 428,    "Internetworking With TCP/IP (3rd edition, vol 1)" ******************************/static void build_tftp_datagram(dg_type_t type,            // in                                tftp_datagram_t *data_g,   // out                                unsigned short *num_bytes) // out{   unsigned char *curr;   curr = (unsigned char *) data_g;   *num_bytes = 0;   switch (type) {     case do_RRQ:       *((unsigned short *)curr) = htons(TFTP_RRQ);       curr += 2;       util_strcpy (curr,tftp_filename);       curr += util_strlen(tftp_filename) + 1;       util_strcpy (curr, "octet");       curr += util_strlen("octet") + 1;       *num_bytes = curr - (unsigned char *)data_g;       break;     case do_ACK:       data_g->DATA.opcode = htons(TFTP_ACK);       data_g->DATA.block_num = htons(expected_block_num-1);       *num_bytes = sizeof(tftp_ACK_datagram_t);       break;     default:       SYSTEM_FATAL("Logic Error");       break;   }}/****************************** Routine: Description:    See tftp.h for more info. ******************************/void connect_tftp(char *device_IP,                  char *server_IP,                  char *device_MAC, // MACs may be NULL only if                   char *server_MAC,   // our network stack has ARP.                  char *fname){  // Just cache the values locally so we'll have them  // when we need them for the client's upcoming calls  // to getchar_tftp().  util_strcpy(tftp_filename,fname);  util_strcpy(tftp_device_IP,device_IP);  util_strcpy(tftp_server_IP,server_IP);  util_strcpy(tftp_device_MAC,device_MAC);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -