📄 tftp.c
字号:
#include <setup.h>#include <stdio.h>#include <command.h>#include <time.h>#include <network.h>#include <string.h>//#define TIMEOUT 1#define TIMEOUT (CLOCKS_PER_SEC * 2)// TFTP operations.#define TFTP_RRQ 1#define TFTP_WRQ 2#define TFTP_DATA 3#define TFTP_ACK 4#define TFTP_ERROR 5#define TFTP_NONE 0#define TFTP_STATE_RRQ 1#define TFTP_STATE_DATA 2#define TFTP_STATE_SUCCESS 3#define TFTP_STATE_FAILURE 4#define PORT_TFTPS 69#define report(fmt, args...) printf(fmt, ##args)#define assert(fmt, args...) printf(fmt, ##args)#define failed(fmt, args...) printf(fmt, ##args)static uint32 destip;static uint16 destport;//static int tftpState;static bool wait;static uint16 lastblk;static void *tftpbuff;static ulong maxsize;static ulong received; clock_t timeout;static bool tftp_start(char *filename);static bool do_tftp(int argc, char **argv);static void tftp_usage(void);static bool tftp_send_packet(int dport, void *packet, int len);static bool send_tftp_request_packet(char *filename);static bool send_tftp_ack_packet(int blknum);struct command_t cmd_tftp = { .name = "tftp", .run = do_tftp, .usage = tftp_usage};static void tftp_usage(void){ usage_format("tftp filename {loader/kernel/root/ramdisk}", ""); return;}static bool do_tftp(int argc, char **argv){ bool res; ulong tmp; char *filename; struct map *mp; /* destination ip address */ if (argc == 4){ destip = inet_addr(argv[1]); argc--; argv++; } else { destip = setup->destipaddr; } if (argc != 3) goto invalid; /* filename */ filename = argv[1]; /* buff address */ mp = find_map(argv[2]); if (mp){ tftpbuff = (void *)mp->dramb; maxsize = mp->maxs; } else if (strtoul(argv[2], &tmp, 16)){ tftpbuff = (void *)tmp; maxsize = -1; } else goto invalid; if (!destip){ printf(" error : invalid ip address\n"); goto invalid; } res = tftp_start(filename); if (mp) mp->drams = received; return res;invalid : tftp_usage(); return false;}static bool tftp_start(char *filename){ report(" tftp start...\n"); report(" my ip address : %s\n", inet_ntoa(setup->myipaddr)); report(" server ip address : %s\n", inet_ntoa(destip)); report(" filename : %s\n", filename); report(" store at : 0x%08lX\n", (ulong)tftpbuff); report(" loading start...\n"); wait = true; timeout = clock() + TIMEOUT ; received = lastblk = destport = 0; send_tftp_request_packet(filename); // printf("tftp start() begin receive true packe\n"); while (clock() < timeout){ net_recv_poll(); if (!wait) break; } if (wait) report(" error : timed out.\n"); return received ? true : false;}static inline bool tftp_send_packet(int dport, void *packet, int len){ int n; void *dmac; dmac = find_mac_addr(destip); if (!dmac) return false; n = set_udp_header(packet, dport, PORT_TFTP_CLIENT, len); packet -= n; len += n; n = set_ip_header(packet, setup->myipaddr, destip, IP_P_UDP, len); packet -= n; len += n; n = set_ether_header(packet, dmac, PROT_IP); packet -= n; len += n; return net_send_packet(packet, len);}static bool send_tftp_request_packet(char *filename){ int len; uchar buff[1024], *packet, *s; packet = buff + 100; s = packet; *(uint16 *)s = htons(TFTP_RRQ); s += 2; strcpy(s, filename); s += strlen(filename) + 1; strcpy(s, "octet"); s += strlen("octet") + 1; len = s - packet; return tftp_send_packet(PORT_TFTPS, packet, len);}static bool send_tftp_ack_packet(int blknum){ int len; uchar buff[1024], *packet, *s; packet = buff + 100; s = packet; *(uint16 *)s = htons(TFTP_ACK); s += 2; *(uint16 *)s = htons(blknum); s += 2; len = s - packet; return tftp_send_packet(destport, packet, len);}bool tftp_recv(int port, void *packet, int len){ uint16 ptype, blknum; uchar *s = packet; // printf("tftp_recv()\n"); if (!wait) return false; if (!destport) destport = port; if (port != destport) return false; // handling received data. ptype = ntohs(*(uint16 *)s); s += 2; len -= 2; switch (ptype){ case TFTP_DATA : if (len < 2) break; blknum = ntohs(*(uint16 *)s); s += 2; len -= 2; /* check expected block number */ if (blknum != lastblk + 1) break; lastblk = blknum; timeout = clock() + TIMEOUT; /* check remained buff size */ if (blknum * 512 > maxsize){ report(" error : size too big(cur=0x%lx, max=0x%lx)\n", (ulong)blknum * 512, maxsize); wait = false; } /* store received data */ memcpy((void *)(tftpbuff+(blknum-1)*512), s, len); /* display progress */ if (!((blknum) % 128)){ int total = blknum * 512; report("\r %d (0x%08X) bytes received.", total, total); } /* send ack packet */ send_tftp_ack_packet(blknum); /* we received the whole thing */ if (len < 512){ int total = (blknum-1) * 512 + len; report("\r %d (0x%08X) bytes received. done.\n", total, total); received = total; wait = false; } break; case TFTP_ERROR : report(" error : '%s' (%d)\n", s+2, ntohs(*(uint16 *)s)); wait = false; break; default: break; } return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -