📄 tftp.c
字号:
/* SendTFTPRRQ():
* Pass the ether and ip address of the TFTP server, along with the
* filename and mode to start up a target-initiated TFTP download.
* The initial TftpState value is TFTPSENTRRQ, this is done so that incoming
* TFTP_DAT packets can be verified...
* - If a TFTP_DAT packet is received and TftpState is TFTPSENTRRQ, then
* the block number should be 1. If this is true, then that server's
* source port is stored away in TftpRmtPort so that all subsequent
* TFTP_DAT packets will be compared to the initial source port. If no
* match, then respond with a TFTP error or ICMP PortUnreachable message.
* - If a TFTP_DAT packet is received and TftpState is TFTPSENTRRQ, then
* if the block number is not 1, generate a error.
*/
int
SendTFTPRRQ(uchar *ipadd,uchar *eadd,char *filename,char *mode,uchar *loc)
{
uchar *tftpdat;
ushort ip_len;
struct ether_header *te;
struct ip *ti;
struct Udphdr *tu;
TftpChopCount = 0;
tftpGotoState(TFTPSENTRRQ);
TftpAddr = loc;
TftpCount = 0;
/* Retrieve an ethernet buffer from the driver and populate the
* ethernet level of packet:
*/
te = (struct ether_header *) getXmitBuffer();
memcpy((char *)&te->ether_shost,BinEnetAddr,6);
memcpy((char *)&te->ether_dhost,eadd,6);
te->ether_type = ecs(ETHERTYPE_IP);
/* Move to the IP portion of the packet and populate it appropriately: */
ti = (struct ip *) (te + 1);
ti->ip_vhl = IP_HDR_VER_LEN;
ti->ip_tos = 0;
ip_len = sizeof(struct ip) +
sizeof(struct Udphdr) + strlen(filename) + strlen(mode) + 4;
ti->ip_len = ecs(ip_len);
ti->ip_id = ipId();
ti->ip_off = 0;
ti->ip_ttl = UDP_TTL;
ti->ip_p = IP_UDP;
memcpy((char *)&ti->ip_src.s_addr,BinIpAddr,4);
memcpy((char *)&ti->ip_dst.s_addr,ipadd,4);
/* Now udp... */
tu = (struct Udphdr *) (ti + 1);
tu->uh_sport = getTftpSrcPort();
self_ecs(tu->uh_sport);
tu->uh_dport = ecs(TftpPort);
tu->uh_ulen = ecs((ushort)(ip_len - sizeof(struct ip)));
/* Finally, the TFTP specific stuff... */
tftpdat = (uchar *)(tu+1);
*(ushort *)(tftpdat) = ecs(TFTP_RRQ);
strcpy(tftpdat+2,filename);
strcpy(tftpdat+2+strlen(filename)+1,mode);
if (!strcmp(mode,"netascii"))
TftpWrqMode = MODE_NETASCII;
else
TftpWrqMode = MODE_OCTET;
storePktAndSend(ti, te,TFTPACKSIZE+strlen(filename)+strlen(mode));
if (EtherVerbose & SHOW_TFTP_STATE)
printf("\n Sent TFTP_RRQ (file=%s)\n",filename);
return(0);
}
/* SendTFTPAck():
*/
int
SendTFTPAck(struct ether_header *re,ushort block)
{
uchar *tftpdat;
ushort ip_len;
struct ether_header *te;
struct ip *ti, *ri;
struct Udphdr *tu, *ru;
te = EtherCopy(re);
ti = (struct ip *) (te + 1);
ri = (struct ip *) (re + 1);
ti->ip_vhl = ri->ip_vhl;
ti->ip_tos = ri->ip_tos;
ip_len = sizeof(struct ip) + sizeof(struct Udphdr) + 4;
ti->ip_len = ecs(ip_len);
ti->ip_id = ipId();
ti->ip_off = ri->ip_off;
ti->ip_ttl = UDP_TTL;
ti->ip_p = IP_UDP;
memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr),
sizeof(struct in_addr));
memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr),
sizeof(struct in_addr));
tu = (struct Udphdr *) (ti + 1);
ru = (struct Udphdr *) (ri + 1);
tu->uh_sport = ru->uh_dport;
tu->uh_dport = ru->uh_sport;
tu->uh_ulen = ecs((ushort)(ip_len - sizeof(struct ip)));
tftpdat = (uchar *)(tu+1);
*(ushort *)(tftpdat) = ecs(TFTP_ACK);
*(ushort *)(tftpdat+2) = ecs(block);
storePktAndSend(ti,te,TFTPACKSIZE);
if (EtherVerbose & SHOW_TFTP_STATE)
printf(" Sent TFTP_ACK (blk#%d)\n",block);
return(0);
}
/* SendTFTPErr():
*/
int
SendTFTPErr(struct ether_header *re,short errno,char *errmsg,int changestate)
{
short len, tftplen, hdrlen;
uchar *tftpmsg;
struct ether_header *te;
struct ip *ti, *ri;
struct Udphdr *tu, *ru;
if (changestate)
tftpGotoState(TFTPERROR);
tftplen = strlen(errmsg) + 1 + 4;
hdrlen = sizeof(struct ip) + sizeof(struct Udphdr);
len = tftplen + hdrlen ;
te = EtherCopy(re);
ti = (struct ip *) (te + 1);
ri = (struct ip *) (re + 1);
ti->ip_vhl = ri->ip_vhl;
ti->ip_tos = ri->ip_tos;
ti->ip_len = ecs(len);
ti->ip_id = ipId();
ti->ip_off = ri->ip_off;
ti->ip_ttl = UDP_TTL;
ti->ip_p = IP_UDP;
memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr),
sizeof(struct in_addr));
memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr),
sizeof(struct in_addr));
tu = (struct Udphdr *) (ti + 1);
ru = (struct Udphdr *) (ri + 1);
tu->uh_sport = ru->uh_dport;
tu->uh_dport = ru->uh_sport;
tu->uh_ulen = sizeof(struct Udphdr) + tftplen;
self_ecs(tu->uh_ulen);
tftpmsg = (uchar *)(tu+1);
*(ushort *)(tftpmsg) = ecs(TFTP_ERR);
* (ushort *)(tftpmsg+2) = ecs(errno);
strcpy(tftpmsg+4,errmsg);
storePktAndSend(ti,te,TFTPACKSIZE + strlen(errmsg) + 1);
if (EtherVerbose & SHOW_TFTP_STATE)
printf(" Sent TFTP Err#%d (%s) \n",errno,errmsg);
return(0);
}
/* SendTFTPData():
*/
int
SendTFTPData(struct ether_header *re,ushort block,uchar *data,int count)
{
int len, tftplen, hdrlen;
uchar *tftpmsg;
struct ether_header *te;
struct ip *ti, *ri;
struct Udphdr *tu, *ru;
if (count > TFTP_DATAMAX)
count = TFTP_DATAMAX;
tftplen = count + 2 + 2; /* sizeof (data + opcode + blockno) */
hdrlen = sizeof(struct ip) + sizeof(struct Udphdr);
len = tftplen + hdrlen ;
te = EtherCopy(re);
ti = (struct ip *) (te + 1);
ri = (struct ip *) (re + 1);
ti->ip_vhl = ri->ip_vhl;
ti->ip_tos = ri->ip_tos;
ti->ip_len = ecs(len);
ti->ip_id = ipId();
ti->ip_off = ri->ip_off;
ti->ip_ttl = UDP_TTL;
ti->ip_p = IP_UDP;
memcpy((char *)&(ti->ip_src.s_addr),(char *)&(ri->ip_dst.s_addr),
sizeof(struct in_addr));
memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr),
sizeof(struct in_addr));
tu = (struct Udphdr *) (ti + 1);
ru = (struct Udphdr *) (ri + 1);
tu->uh_sport = ru->uh_dport;
tu->uh_dport = ru->uh_sport;
tu->uh_ulen = sizeof(struct Udphdr) + tftplen;
self_ecs(tu->uh_ulen);
tftpmsg = (uchar *)(tu+1);
*(ushort *)(tftpmsg) = ecs(TFTP_DAT);
*(ushort *)(tftpmsg+2) = ecs(block);
memcpy(tftpmsg+4,data,count);
len+=sizeof(struct ether_header);
storePktAndSend(ti,te,len);
if (EtherVerbose & SHOW_TFTP_STATE)
printf(" Sent TFTP data blk#%d (%d bytes @ 0x%lx) \n",
block,count,(ulong)data);
return(0);
}
#if 0
THIS IS NOT YET TESTED
/* parseLongFilename():
* Given a full filename that may contain up to three different
* comma-delimited tokens, this function will parse that string and
* return the requested tokens.
*
* The syntax of fullname can be...
* - name
* - name,flags
* - name,flags,info
* - name,,info
*
* Return 0 if successful, -1 if failure.
*/
int
parseLongFilename(char *fullname,char *name, char *flags, char *info)
{
char *comma, *cp;
/* Parse the fullname string looking for commas to determine what
* information is in the string. Then, based on the presence of
* the commas, populate the incoming pointers with the appropriate
* portion of the fullname string.
* If the pointer is NULL, then just skip over that portion of the
* algorithm.
*/
cp = fullname;
comma = strchr(cp,',');
if (comma) {
if (name) {
while(cp != comma)
*name++ = *cp++;
*name = 0;
}
cp++;
comma = strchr(cp,',');
if (comma) {
if (flags) {
while(cp != comma)
*flags++ = *cp++;
*flags = 0;
}
cp++;
if (info) {
strcpy(info,cp);
}
}
else {
if (flags)
strcpy(flags,cp);
}
}
else {
if (name)
strcpy(name,fullname);
}
return(0);
}
#endif
/* Tftp():
* Initiate a tftp transfer at the target (target is client).
* Command line:
* tftp [options] {IP} {get|put} {file|addr} [len]...
* tftp [options] {IP} get file dest_addr
* tftp [options] {IP} put addr dest_file len
* Currently, only "get" is supported.
*/
char *TftpHelp[] = {
"Trivial file transfer protocol",
"-[aF:f:i:vV] [on|off|IP] {get filename [addr]}",
#if INCLUDE_VERBOSEHELP
" -a use netascii mode",
" -F {file} name of tfs file to copy to",
" -f {flgs} file flags (see tfs)",
" -i {info} file info (see tfs)",
" -v verbosity = ticker",
" -V verbosity = state",
#endif
0,
};
int
Tftp(int argc,char *argv[])
{
int opt, verbose;
char *mode, *file, *info, *flags;
ulong addr;
verbose = 0;
file = (char *)0;
info = (char *)0;
flags = (char *)0;
mode = "octet";
while ((opt=getopt(argc,argv,"aF:f:i:vV")) != -1) {
switch(opt) {
case 'a':
mode = "netascii";
break;
case 'f':
flags = optarg;
break;
case 'F':
file = optarg;
break;
case 'i':
info = optarg;
break;
case 'v':
verbose |= SHOW_TFTP_TICKER;
break;
case 'V':
verbose |= SHOW_TFTP_STATE;
break;
default:
return(CMD_PARAM_ERROR);
}
}
if (argc < (optind+1))
return(CMD_PARAM_ERROR);
if (argc == optind+1) {
if (!strcmp(argv[optind],"on"))
TftpTurnedOff = 0;
else if (!strcmp(argv[optind],"off")) {
TftpTurnedOff = 1;
tftpGotoState(TFTPIDLE);
}
else
return(CMD_PARAM_ERROR);
return(CMD_SUCCESS);
}
/* If either the info or flags field has been specified, but the */
/* filename is not specified, error here... */
if ((info || flags) && (!file)) {
printf("Filename missing\n");
return(CMD_FAILURE);
}
TftpTurnedOff = 0;
if (!strcmp(argv[optind+1],"get")) {
if (argc == optind+4)
addr = (ulong)strtol(argv[optind+3],0,0);
else if (argc == optind+3)
addr = getAppRamStart();
else
return(CMD_PARAM_ERROR);
EtherVerbose |= verbose;
tftpGet(addr,argv[optind],mode,argv[optind+2],file,flags,info);
EtherVerbose &= ~verbose;
}
else
return(CMD_PARAM_ERROR);
return(CMD_SUCCESS);
}
void
ShowTftpStats()
{
printf("Current TFTP state: %s\n",tftpStringState(TftpState));
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -