📄 tftp.c
字号:
/*****************************************************************************;; Project : Edimax; Creator :; File : tftp.c; Abstract:;;*****************************************************************************/#include <tftp.h>#include <ctype.h>#include <skbuff.h>#include <eth.h>#include <arp.h>#include <ip.h>#include <udp.h>#include <if_5120.h>#include <param.h>#include <bsp_cfg.h>#include <helpers.h>#include <test_def.h>static UINT32 remote_ip; // TFTP server ipstatic unsigned short remote_port; // TFTP server portstatic unsigned short remote_block; // TFTP server data block numberstatic int tftpc_read_start;/* The "gateway" and "mask" don't seem to be used anywhere */char errstr[] = "<error>";void print_tftpc_menu(char *dl_type){ char macstr[24]; char local_ipstr[16]; char tftp_ipstr[16]; char remfile[BSP_RFNAME_MAXLEN + 1]; buart_print("\r\n"); buart_print("\r\nTFTP Download to "); buart_print(dl_type); buart_print("\r\n===================================================="); buart_print("\r\n [m]: MAC address : "); buart_print(GetMAC(macstr) ? macstr : errstr); buart_print("\r\n [i]: Local IP address : "); buart_print(GetLocalIP(local_ipstr) ? local_ipstr : errstr); buart_print("\r\n [s]: TFTP server IP address : "); buart_print(GetTftpIP(tftp_ipstr) ? tftp_ipstr : errstr); buart_print("\r\n [f]: Remote file to download : "); buart_print(GetRemFile(remfile) ? remfile : errstr); buart_print("\r\n [a]: Accept values and continue"); buart_print("\r\n [c]: Cancel download"); buart_print("\r\n\r\nPlease enter your choice: ");}int tftp_client_menu(char *dltype){ char key; while (1) { print_tftpc_menu(dltype); key = buart_getchar(); buart_put(key); switch(key) { case 'M': case 'm': AskMAC(); break; case 'I': case 'i': AskLocalIP(); break; case 'S': case 's': AskTftpIP(); break; case 'F': case 'f': AskRemFile(); break; case 'A': case 'a': /* Continue with current network parameters */ return 1; case 'C': case 'c': /* Canceled. Do nothing. */ return 0; default: break; } } return 0;}int tftp_send_ack(int block){ struct tftphdr *tftp_ack; struct sk_buff skb; skb_headerinit(&skb); udp_skb_reserve(&skb); tftp_ack = (struct tftphdr *) skb_put(&skb, sizeof(struct tftphdr)); tftp_ack->th_opcode = htons(ACK); tftp_ack->th_block = htons(block); udp_send(&skb, remote_ip, TFTP, remote_port); return 0;}int tftp_send_rrq(UINT32 servip, char *filename){ struct sk_buff skb; char *temp; unsigned int rrqlen; short *opCode; int fileNameLen, i; skb_headerinit(&skb); udp_skb_reserve(&skb); temp = (char *) skb.data; /* Op code */ opCode = (short *) temp; *opCode = htons(RRQ); temp += 2; /* Remote file name */ fileNameLen = strlen(filename); strncpy(temp, filename, fileNameLen); temp += fileNameLen; /* String terminating byte */ *temp++ = 0; /* Op mode "octet" */ strncpy(temp, "octet", 5); temp += 5; /* String terminating byte */ *temp = 0; /* Opcode + filename + terminator + "octet" + terminator is the format of an RRQ */ rrqlen = 2 + fileNameLen + 1 + strlen("octet") + 1; skb.len = rrqlen; remote_ip = servip; remote_port = TFTP; remote_block = 1; udp_send(&skb, remote_ip, TFTP, remote_port); return 0;}int rcv_imgpkt(char *buf, int *buf_len){ struct sk_buff skb; int status; skb_headerinit(&skb); if (tftp_rcv_packet(&skb) == 1) { *buf_len = skb.len; memcpy(buf, skb.data, *buf_len); if (*buf_len < 512) status = TFTP_END; else status = TFTP_CONTINUE; } else { *buf_len = 0; status = TFTP_NO_DATA; } return status;}int tftp_rcv_packet(struct sk_buff *skb){ struct tftphdr *tftp_hdr; int data_flag, len; data_flag = 0; if (udp_rcv_packet(skb) == 1) { tftp_hdr = (struct tftphdr *) skb->data; if (ntohs(tftp_hdr->th_opcode) == DATA) { if (remote_ip != ip_get_source_ip(skb)) return data_flag; remote_port = udp_get_source_port(skb); if (remote_block == ntohs(tftp_hdr->th_block)) { tftpc_read_start = 1; skb_pull(skb, sizeof(struct tftphdr)); tftp_send_ack(remote_block); remote_block++; data_flag = 1; } else if (remote_block > ntohs(tftp_hdr->th_block)) tftp_send_ack(ntohs(tftp_hdr->th_block)); else tftp_send_ack(remote_block); } } return data_flag;}UINT32 tftpc(char *buf, int buf_size){ UINT32 ticks, servip, total_len; char servfile[15]; int transmit_flag, pkt_len = 0, rrqcount = 0; char *working = buf; if (get_tftp_param(&servip, servfile) != 0) { buart_print("\r\nBad TFTP Server IP or Filename."); return; } transmit_flag = TFTP_START; total_len = 0; if5120turnon(); tftp_send_rrq(servip, servfile); ticks = UpTime(); while (1) { if(buart_get(0) == 0x1B) { /* User can press ESC at any time to stop the transfer. */ total_len = 0; break; } if ((!tftpc_read_start) && ((UpTime()-ticks) > 100)) { tftp_send_rrq(servip, servfile); ticks = UpTime(); rrqcount++; buart_print("."); if (rrqcount == 5) { break; // FAIL } } /* This is the primary statement that gets TFTP's UDP data */ transmit_flag = rcv_imgpkt(working, &pkt_len); if (tftpc_read_start) { if (transmit_flag == TFTP_CONTINUE) { /* Got img packet successfully */ working += pkt_len; total_len += pkt_len; /* Dump a '.' to the console every 64K */ if ((total_len % (32 * 1024 * 2) == 0)) buart_put('.'); ticks = UpTime(); } else if (transmit_flag == TFTP_NO_DATA) { /* Couldn't get an img packet */ if ((UpTime()-ticks) > (5 * 100)) { /* Timeout */ total_len = 0; buart_print("\r\nTimeout after xfer started\r\n"); // already commented out break; } } else if (transmit_flag == TFTP_END) { /* Transmission successful */ working += pkt_len; total_len += pkt_len; break; } } } tftpc_read_start = 0; if5120shutdown(); return total_len;}void tftp_init(){ remote_port = TFTP; remote_block = 1; tftpc_read_start = 0; unsigned char mac[8]; // Init socket buffer skb_init(); // Init Ethernet protocol. bsp_GetMAC(mac); eth_init(mac); // Init ARP protocol arp_init(); // Init IP protocol bsp_GetTftpIp(&remote_ip); ip_init(); // Init UDP protocol udp_init(); // Init Data Receive Queue if (InitEthPktQueue() != 0) { buart_print("\n\rInit ethernet receive queue error"); panic(); } // Shutdown Switch until TFTP download starts if5120shutdown();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -