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

📄 tftplib.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
			errno = ESPIPE;			return (-1);		}		tfp->foffs = noffs;	}		return (tfp->foffs);}static inttftpioctl (fd, op, argp)    int fd;    int op;    void *argp;{	errno = ENOTTY;	return -1;}static inttftpclose (fd)    int fd;{	NetFile *nfp;	struct tftpfile *tfp;	struct tftphdr *tp;	nfp	= (NetFile *)_file[fd].data;	tfp = (struct tftpfile *)nfp->data;	tp = (struct tftphdr *) tfp->buf;	if ((tfp->flags & O_ACCMODE) == O_WRONLY) {		int n = 0;		/* flush last block */		tftpnxtblk (tfp);		tp->th_opcode = htons((u_short)DATA);		tp->th_block = htons((u_short)tfp->block);		n = tftpwrq (tfp, tp, tfp->end);		if (n >= 0 && tfp->end == SEGSIZE) {			/* last block == SEGSIZE, so send empty one to terminate */			tftpnxtblk (tfp);			tp->th_opcode = htons((u_short)DATA);			tp->th_block = htons((u_short)tfp->block);			(void) tftpwrq (tfp, tp, 0);		}	} else {		if (tfp->foffs < tfp->end || !tfp->eof) {			const char *msg;			int length;	    			/* didn't reach eof, so send a nak to terminate */			tp->th_opcode = htons((u_short)ERROR);			tp->th_code = htons((u_short)EUNDEF);			msg = "file closed";			strcpy(tp->th_msg, msg);			length = strlen(msg) + 4;#ifdef TFTPDBG			if (tftptrace)				tpacket("sent", tp, length);#endif			if (sendto(tfp->sock, tp, length, 0, (struct sockaddr *)&tfp->sin,				   sizeof (tfp->sin)) != length)				perror("sendto(eof)");		}	}	close (tfp->sock);	free (tfp);	return (0);}static voidtftpnxtblk (tfp)    struct tftpfile *tfp;{	tfp->block++;	if (tfp->flags & O_NONBLOCK)		dotik (20000, 0);}static int tftprrq (tfp, req, size)    struct tftpfile *tfp;    struct tftphdr *req;    int size;{	struct tftphdr *rp;	struct sockaddr_in from;	fd_set ifds;	int fromlen, n;	struct timeval timo;	int rexmt = 0;	while (1) {#ifdef TFTPDBG		if (tftptrace)			tpacket("sent", req, size);#endif		if (sendto(tfp->sock, req, size, 0, (struct sockaddr *)&tfp->sin,			   sizeof (tfp->sin)) != size) {			perror("tftp: sendto");			return (-1);		}		if (tfp->eof)			/* reached eof, no more to read */			return 0;		FD_ZERO(&ifds);		FD_SET(tfp->sock, &ifds);		timo.tv_sec = TIMEOUT; timo.tv_usec = 0;		switch (select (tfp->sock + 1, &ifds, 0, 0, &timo)) {			case -1:				perror("tftp: select");				return (-1);			case 0:				if (++rexmt > MAXREXMT) {					errno = ETIMEDOUT;					return (-1);				}				log (LOG_INFO, "tftp: timeout, retry %d\n", rexmt);				continue;		}		fromlen = sizeof (from);		rp = (struct tftphdr *) tfp->buf;		n = recvfrom(tfp->sock, rp, PKTSIZE, 0,			     (struct sockaddr *)&from, &fromlen);		if (n < 0) {			perror("tftp: recvfrom");			return (-1);		}#ifdef TFTPDBG		if (tftptrace)			tpacket("received", rp, n);#endif		if (tfp->block <= 1)			tfp->sin.sin_port = from.sin_port;		else if (from.sin_port != tfp->sin.sin_port)			continue;		/* should verify client address completely? */		rp->th_opcode = ntohs(rp->th_opcode);		rp->th_block = ntohs(rp->th_block);		if (rp->th_opcode == ERROR) {			if (rp->th_msg[0])				log(LOG_INFO, "tftp: %s\n", rp->th_msg);			errno = tftperrmap[rp->th_code & 7];			return (-1);		}		if (rp->th_opcode == DATA) {			int j;			if (rp->th_block == tfp->block) {				/* got the packet */				n -= 4;				if (n < SEGSIZE)					tfp->eof = 1;				return (n);			}			/* On an error, try to synchronize			 * both sides.			 */			j = synchnet(tfp->sock);			if (j)				log (LOG_INFO, "tftp: discarded %d packets\n", j);			if (rp->th_block != tfp->block - 1)				return (-1);		}	}}static int    tftpwrq (tfp, req, size)   struct tftpfile *tfp;struct tftphdr *req;int size;{	char ackbuf[PKTSIZE];	struct tftphdr *rp;	struct sockaddr_in from;	fd_set ifds;	int fromlen, n;	struct timeval timo;	int rexmt = 0;	while (1) {#ifdef TFTPDBG		if (tftptrace)			tpacket("sent", req, size);#endif		if (sendto(tfp->sock, req, size+4, 0, (struct sockaddr *)&tfp->sin,			   sizeof (tfp->sin)) != size+4) {			perror("tftp: sendto");			return (-1);		}		FD_ZERO(&ifds);		FD_SET(tfp->sock, &ifds);		timo.tv_sec = TIMEOUT; timo.tv_usec = 0;		switch (select (tfp->sock + 1, &ifds, 0, 0, &timo)) {			case -1:				perror("tftp: select");				return (-1);			case 0:				if (++rexmt > MAXREXMT) {					errno = ETIMEDOUT;					return (-1);				}				log (LOG_INFO, "tftp: timeout, retry %d\n", rexmt);				continue;		}		fromlen = sizeof (from);		rp = (struct tftphdr *) ackbuf;		n = recvfrom(tfp->sock, rp, PKTSIZE, 0,			     (struct sockaddr *)&from, &fromlen);		if (n < 0) {			perror("tftp: recvfrom");			return (-1);		}#ifdef TFTPDBG		if (tftptrace)			tpacket("received", rp, n);#endif		if (tfp->block == 0)			tfp->sin.sin_port = from.sin_port;		else if (from.sin_port != tfp->sin.sin_port)			continue;		/* should verify client address completely? */		rp->th_opcode = ntohs(rp->th_opcode);		rp->th_block = ntohs(rp->th_block);		if (rp->th_opcode == ERROR) {			if (rp->th_msg[0])				log(LOG_INFO, "tftp: %s\n", rp->th_msg);			errno = tftperrmap[rp->th_code & 7];			return (-1);		}		if (rp->th_opcode == ACK) {			int j;			if (rp->th_block == tfp->block)				/* acknowledged packet */				return (size);			/* On an error, try to synchronize			 * both sides.			 */			j = synchnet(tfp->sock);			if (j)				log (LOG_INFO, "tftp: discarded %d packets\n", j);			if (rp->th_block != tfp->block - 1)				return (-1);		}	}}static int   makerequest(request, name, tp, mode)   int request;const char *name, *mode;struct tftphdr *tp;{	register char *cp;	tp->th_opcode = htons((u_short)request);	cp = tp->th_stuff;	strcpy(cp, name);	cp += strlen(name);	*cp++ = '\0';	strcpy(cp, mode);	cp += strlen(mode);	*cp++ = '\0';	return (cp - (char *)tp);}#ifdef TFTPDBGstatic void   tpacket(s, tp, n)   char *s;struct tftphdr *tp;int n;{	static const char * const opcodes[] =					     { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR" };	register char *cp, *file;	u_short op = ntohs(tp->th_opcode);	if (op < RRQ || op > ERROR)		printf("%s opcode=%x ", s, op);	else		printf("%s %s ", s, opcodes[op]);	switch (op) {		case RRQ:		case WRQ:			n -= 2;			file = cp = tp->th_stuff;			cp += strlen(cp);			printf("<file=%s, mode=%s>\n", file, cp + 1);			break;		case DATA:			printf("<block=%d, %d bytes>\n", ntohs(tp->th_block), n - 4);			break;		case ACK:			printf("<block=%d>\n", ntohs(tp->th_block));			break;		case ERROR:			printf("<code=%d, msg=%s>\n", ntohs(tp->th_code), tp->th_msg);			break;	}}#endif/* When an error has occurred, it is possible that the two sides * are out of synch.  Ie: that what I think is the other side's * response to packet N is really their response to packet N-1. * * So, to try to prevent that, we flush all the input queued up * for us on the network connection on our host. * * We return the number of packets we flushed (mostly for reporting * when trace is active). */static int   synchnet(f)   int	f;		/* socket to flush */{	int i, j = 0;	char rbuf[PKTSIZE];	struct sockaddr_in from;	int fromlen;	while (1) {		(void) ioctl(f, FIONREAD, &i);		if (i) {			j++;			fromlen = sizeof from;			(void) recvfrom(f, rbuf, sizeof (rbuf), 0,					(struct sockaddr *)&from, &fromlen);		} else {			return(j);		}	}}

⌨️ 快捷键说明

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