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

📄 tftpd.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
		}		if (*filename != '/') {			if (debug)				syslog(LOG_ERR,				       "Filename has to be absolute: %s\n",				       filename);			nak(EACCESS);			exit(1);		}		filename = strcat(strcpy(cp, rootdir), filename);	}		ecode = (*pf->f_validate)(filename, tp->th_opcode);	if (ecode) {		nak(ecode, ERROR);		exit(1);	}	isopts = ap != (ackbuf+2);	(tp->th_opcode == WRQ ? *pf->f_recv : *pf->f_send)		(pf, isopts ? ackbuf : NULL, isopts ? ap-ackbuf : 0);	exit(0);}FILE *file;/* * Validate file access.  Since we * have no uid or gid, for now require * file to exist and be publicly * readable/writable. * Note also, full path name must be * given as we have no login directory. */validate_access(filename, mode)	char *filename;	int mode;{	struct stat stbuf;	int	fd;	char	*cp;	isfilter = 0;	if (mode == RRQ) {		struct filters *fp = filters;		for (; fp; fp = fp->next) {			if (!strcmp(fp->fname,				    filename +				    (rootdir ? strlen(rootdir) : 0))) {				if (debug)					syslog(LOG_INFO, "Opening input "					       "filter: %s\n", filename);				if ((file = popen(filename, "r")) == NULL) {					syslog(LOG_ERR, "Failed to open input "					       "filter\n");					return (EACCESS); }				fd = fileno(file);				isfilter = 1;				return (0);			}		}	}				       	if (*filename != '/') {		if (debug)			syslog(LOG_ERR, "Filename has to be absolute: %s\n",			       filename);		return (EACCESS);	}	for (cp = filename; *cp; cp++)		if (*cp == '~' || *cp == '$' ||		    (*cp == '/' && cp[1] == '.' && cp[2] == '.')) {			if (debug)				syslog(LOG_ERR, "Illegal filename: %s\n",				       filename);			return (EACCESS);		}	if (debug)		syslog(LOG_INFO, "Validating \"%s\" for %sing\n",		       filename, mode == RRQ ? "read" : "writ");	if (stat(filename, &stbuf) < 0)		return (errno == ENOENT ? ENOTFOUND : EACCESS);	if (mode == RRQ) {		if ((stbuf.st_mode&(S_IREAD >> 6)) == 0)			return (EACCESS);	} else {		if ((stbuf.st_mode&(S_IWRITE >> 6)) == 0)			return (EACCESS);	}	fd = open(filename, mode == RRQ ? 0 : 1);	if (fd < 0)		return (errno + 100);	file = fdopen(fd, (mode == RRQ)? "r":"w");	if (file == NULL) {		return errno+100;	}	return (0);}int	timeout;jmp_buf	timeoutbuf;void timer(int sig){	timeout += rexmtval;	if (timeout >= maxtimeout) {		if (debug)			syslog(LOG_WARNING, "Timeout!\n");		exit(1);	}	longjmp(timeoutbuf, 1);}/* * Send the requested file. */sendfile(pf, oap, oacklen)	struct formats *pf;	struct tftphdr *oap;	int oacklen;{	struct tftphdr *dp, *r_init();	register struct tftphdr *ap;    /* ack packet */	register int size, n;	u_short block = 1;	signal(SIGALRM, timer);	ap = (struct tftphdr *)ackbuf;	if (oap) {		timeout = 0;		(void) setjmp(timeoutbuf);	oack:		if (send(peer, oap, oacklen, 0) != oacklen) {			syslog(LOG_ERR, "tftpd: write: %m\n");			goto abort;		}		for ( ; ; ) {			alarm(rexmtval);			n = recv(peer, ackbuf, sizeof (ackbuf), 0);			alarm(0);			if (n < 0) {				syslog(LOG_ERR, "tftpd: read: %m\n");				goto abort;			}			ap->th_opcode = ntohs((u_short)ap->th_opcode);			ap->th_block = ntohs(ap->th_block);						if (ap->th_opcode == ERROR) {				if (debug)					syslog(LOG_ERR, "Client does not "					       "accept options\n");				goto abort; }						if (ap->th_opcode == ACK) {				if (ap->th_block == 0) {					if (debug)						syslog(LOG_DEBUG,						       "RFC1782 option "						       "negotiation "						       "succeeded\n");					break;				}				/* Re-synchronize with the other side */				(void) synchnet(peer);				goto oack;			}		}	}		dp = r_init();	do {		size = readit(file, &dp, pf->f_convert);		if (size < 0) {			nak(errno + 100);			goto abort;		}		dp->th_opcode = htons((u_short)DATA);		dp->th_block = htons(block);		timeout = 0;		(void) setjmp(timeoutbuf);send_data:		if (send(peer, dp, size + 4, 0) != size + 4) {			syslog(LOG_ERR, "tftpd: write: %m\n");			goto abort;		}		read_ahead(file, pf->f_convert);		for ( ; ; ) {			alarm(rexmtval);        /* read the ack */			n = recv(peer, ackbuf, sizeof (ackbuf), 0);			alarm(0);			if (n < 0) {				syslog(LOG_ERR, "tftpd: read: %m\n");				goto abort;			}			ap->th_opcode = ntohs((u_short)ap->th_opcode);			ap->th_block = ntohs(ap->th_block);			if (ap->th_opcode == ERROR)				goto abort;						if (ap->th_opcode == ACK) {				if (ap->th_block == block) {					break;				}				/* Re-synchronize with the other side */				(void) synchnet(peer);				if (ap->th_block == (block -1)) {					goto send_data;				}			}		}		block++;	} while (size == segsize);abort:	if (isfilter)		pclose(file);	else		(void) fclose(file);	isfilter = 0;}void justquit(int sig){	exit(0);}/* * Receive a file. */recvfile(pf, oap, oacklen)	struct formats *pf;	struct tftphdr *oap;	int oacklen;{	struct tftphdr *dp, *w_init();	register struct tftphdr *ap;    /* ack buffer */	register int acksize, n, size;	u_short block = 0;	signal(SIGALRM, timer);	dp = w_init();	do {		timeout = 0;		if (!block++ && oap) {			ap = (struct tftphdr *)oap;			acksize = oacklen;		} else {			ap = (struct tftphdr *)ackbuf;			ap->th_opcode = htons((u_short)ACK);			ap->th_block = htons(block-1);			acksize = 4;		}		(void) setjmp(timeoutbuf);send_ack:		if (send(peer, (char *)ap, acksize, 0) != acksize) {			syslog(LOG_ERR, "tftpd: write: %m\n");			goto abort;		}		write_behind(file, pf->f_convert);		for ( ; ; ) {			alarm(rexmtval);			n = recv(peer, dp, segsize+4, 0);			alarm(0);			if (n < 0) {            /* really? */				syslog(LOG_ERR, "tftpd: read: %m\n");				goto abort;			}			dp->th_opcode = ntohs((u_short)dp->th_opcode);			dp->th_block = ntohs(dp->th_block);			if (dp->th_opcode == ERROR)				goto abort;			if (dp->th_opcode == DATA) {				if (dp->th_block == block) {					break;   /* normal */				}				/* Re-synchronize with the other side */				(void) synchnet(peer);				if (dp->th_block == (block-1))					goto send_ack;          /* rexmit */			}		}		/*  size = write(file, dp->th_data, n - 4); */		size = writeit(file, &dp, n - 4, pf->f_convert);		if (size != (n-4)) {                    /* ahem */			if (size < 0) nak(errno + 100);			else nak(ENOSPACE);			goto abort;		}	} while (size == segsize);	write_behind(file, pf->f_convert);	if (isfilter)		pclose(file);	else		(void) fclose(file);            /* close data file */	isfilter = 0;	ap = (struct tftphdr *)ackbuf;	ap->th_opcode = htons((u_short)ACK);    /* send the "final" ack */	ap->th_block = htons(block);	(void) send(peer, ackbuf, 4, 0);	signal(SIGALRM, justquit);      /* just quit on timeout */	alarm(rexmtval);	n = recv(peer, buf, segsize, 0); /* normally times out and quits */	alarm(0);	if (n >= 4 &&                   /* if read some data */	    dp->th_opcode == DATA &&    /* and got a data block */	    block == dp->th_block) {	/* then my last ack was lost */		(void) send(peer, ackbuf, 4, 0);     /* resend final ack */	}abort:	return;}struct errmsg {	int	e_code;	const char	*e_msg;} errmsgs[] = {	{ EUNDEF,	"Undefined error code" },	{ ENOTFOUND,	"File not found" },	{ EACCESS,	"Access violation" },	{ ENOSPACE,	"Disk full or allocation exceeded" },	{ EBADOP,	"Illegal TFTP operation" },	{ EBADID,	"Unknown transfer ID" },	{ EEXISTS,	"File already exists" },	{ ENOUSER,	"No such user" },	{ EOPTNEG,	"Failure to negotiate RFC1782 options" },	{ -1,		0 }};/* * Send a nak packet (error message). * Error code passed in is one of the * standard TFTP codes, or a UNIX errno * offset by 100. */nak(error)	int error;{	register struct tftphdr *tp;	int length;	register struct errmsg *pe;/*	extern char *sys_errlist[];	*/	tp = (struct tftphdr *)buf;	tp->th_opcode = htons((u_short)ERROR);	tp->th_code = htons((u_short)error);	for (pe = errmsgs; pe->e_code >= 0; pe++)		if (pe->e_code == error)			break;	if (pe->e_code < 0) {		pe->e_msg = sys_errlist[error -100];		tp->th_code = EUNDEF;   /* set 'undef' errorcode */	}	strcpy(tp->th_msg, pe->e_msg);	length = strlen(pe->e_msg);	tp->th_msg[length] = '\0';	length += 5;	if (debug)		syslog(LOG_ERR, "Negative acknowledge: %s\n", tp->th_msg);	if (send(peer, buf, length, 0) != length)		syslog(LOG_ERR, "nak: %m\n");}

⌨️ 快捷键说明

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