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

📄 tftp.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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 + -