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

📄 tftpd.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley.  The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#ifndef lintchar copyright[] ="@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)tftpd.c	5.8 (Berkeley) 6/18/88";#endif /* not lint *//* * Trivial file transfer protocol server. * * This version includes many modifications by Jim Guyton <guyton@rand-unix> * * Further modifications by Markus Gutschke <gutschk@math.uni-muenster.de> *  - RFC1782 option parsing *  - RFC1783 extended blocksize *  - "-c" option for changing the root directory *  - "-d" option for debugging output */#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/wait.h>#include <sys/stat.h>#include <netinet/in.h>#include <arpa/tftp.h>#include <alloca.h>#include <string.h>#include <signal.h>#include <stdio.h>#include <errno.h>#include <ctype.h>#include <netdb.h>#include <setjmp.h>#include <syslog.h>#define	TIMEOUT		5#ifndef	OACK#define	OACK	06#endif#ifndef EOPTNEG#define	EOPTNEG	8#endifextern	int errno;struct	sockaddr_in sin = { AF_INET };int	peer;int	rexmtval = TIMEOUT;int	maxtimeout = 5*TIMEOUT;#define	PKTSIZE	(1432+4) /* SEGSIZE+4 */int	segsize = SEGSIZE;char	buf[PKTSIZE];char	ackbuf[PKTSIZE];struct	sockaddr_in from;int	fromlen;char	*rootdir = NULL;int	debug = 0;struct filters {	struct filters *next;	char           *fname;} *filters = NULL;int     isfilter = 0;main(argc, argv)	char *argv[];{	register struct tftphdr *tp;	register int n;	int on = 1;	extern int optind;	extern char *optarg;	openlog(argv[0], LOG_PID, LOG_DAEMON);	while ((n = getopt(argc, argv, "c:dr:")) >= 0) {		switch (n) {		case 'c':			if (rootdir)				goto usage;			rootdir = optarg;			break;		case 'd':			debug++;			break;		case 'r': {			struct filters *fp = (void *)				             malloc(sizeof(struct filters) +						    strlen(optarg) + 1);			fp->next  = filters;			fp->fname = (char *)(fp + 1);			strcpy(fp->fname, optarg);			filters   = fp;			break; }		default:		usage:			syslog(LOG_ERR, "Usage: %s [-c chroot] "			       "[-r readfilter] [-d]\n",			       argv[0]);			exit(1);		}	}	if (argc-optind != 0)		goto usage;	ioctl(0, FIONBIO, &on);/*	if (ioctl(0, FIONBIO, &on) < 0) {		syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");		exit(1);	}*/	fromlen = sizeof (from);	n = recvfrom(0, buf, segsize+4, 0,	    (struct sockaddr *)&from, &fromlen);	if (n < 0) {		syslog(LOG_ERR, "recvfrom: %m\n");		exit(1);	}	/*	 * Now that we have read the message out of the UDP	 * socket, we fork and exit.  Thus, inetd will go back	 * to listening to the tftp port, and the next request	 * to come in will start up a new instance of tftpd.	 *	 * We do this so that inetd can run tftpd in "wait" mode.	 * The problem with tftpd running in "nowait" mode is that	 * inetd may get one or more successful "selects" on the	 * tftp port before we do our receive, so more than one	 * instance of tftpd may be started up.  Worse, if tftpd	 * break before doing the above "recvfrom", inetd would	 * spawn endless instances, clogging the system.	 */	{		int pid;		int i, j;		for (i = 1; i < 20; i++) {		    pid = fork();		    if (pid < 0) {				sleep(i);				/*				 * flush out to most recently sent request.				 *				 * This may drop some request, but those				 * will be resent by the clients when				 * they timeout.  The positive effect of				 * this flush is to (try to) prevent more				 * than one tftpd being started up to service				 * a single request from a single client.				 */				j = sizeof from;				i = recvfrom(0, buf, segsize+4, 0,				    (struct sockaddr *)&from, &j);				if (i > 0) {					n = i;					fromlen = j;				}		    } else {				break;		    }		}		if (pid < 0) {			syslog(LOG_ERR, "fork: %m\n");			exit(1);		} else if (pid != 0) {			exit(0);		}	}	from.sin_family = AF_INET;	alarm(0);	close(0);	close(1);	peer = socket(AF_INET, SOCK_DGRAM, 0);	if (peer < 0) {		syslog(LOG_ERR, "socket: %m\n");		exit(1);	}	if (bind(peer, (struct sockaddr *)&sin, sizeof (sin)) < 0) {		syslog(LOG_ERR, "bind: %m\n");		exit(1);	}	if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) {		syslog(LOG_ERR, "connect: %m\n");		exit(1);	}	tp = (struct tftphdr *)buf;	tp->th_opcode = ntohs(tp->th_opcode);	if (tp->th_opcode == RRQ || tp->th_opcode == WRQ)		tftp(tp, n);	exit(1);}int	validate_access();int	sendfile(), recvfile();struct formats {	char	*f_mode;	int	(*f_validate)();	int	(*f_send)();	int	(*f_recv)();	int	f_convert;} formats[] = {	{ "netascii",	validate_access,	sendfile,	recvfile, 1 },	{ "octet",	validate_access,	sendfile,	recvfile, 0 },#ifdef notdef	{ "mail",	validate_user,		sendmail,	recvmail, 1 },#endif	{ 0 }};int	set_blksize();struct options {	char	*o_opt;	int	(*o_fnc)();} options[] = {	{ "blksize",	set_blksize },	{ 0 }};/* * Set a non-standard block size (c.f. RFC1783) */set_blksize(val, ret)	char *val;	char **ret;{	static char b_ret[5];	int sz = atoi(val);	if (sz < 8) {		if (debug)			syslog(LOG_ERR, "Requested packetsize %d < 8\n", sz);		return(0);	} else if (sz > PKTSIZE-4) {		if (debug)			syslog(LOG_INFO, "Requested packetsize %d > %d\n",			       sz, PKTSIZE-4);		sz = PKTSIZE-4;	} else if (debug)		syslog(LOG_INFO, "Adjusted packetsize to %d octets\n", sz);		segsize = sz;	sprintf(*ret = b_ret, "%d", sz);	return(1);}/* * Parse RFC1782 style options */do_opt(opt, val, ap)	char *opt;	char *val;	char **ap;{	struct options *po;	char *ret;	for (po = options; po->o_opt; po++)		if (strcasecmp(po->o_opt, opt) == 0) {			if (po->o_fnc(val, &ret)) {				if (*ap + strlen(opt) + strlen(ret) + 2 >=				    ackbuf + sizeof(ackbuf)) {					if (debug)						syslog(LOG_ERR,						       "Ackbuf overflow\n");					nak(ENOSPACE);					exit(1);				}				*ap = strrchr(strcpy(strrchr(strcpy(*ap, opt),							     '\000')+1, val),					      '\000')+1;			} else {				nak(EOPTNEG);				exit(1);			}			break;		}	if (debug && !po->o_opt)		syslog(LOG_WARNING, "Unhandled option: %d = %d\n", opt, val);	return;}/* * Handle initial connection protocol. */tftp(tp, size)	struct tftphdr *tp;	int size;{	register char *cp;	int argn = 0, ecode;	register struct formats *pf;	char *filename, *mode;	char *val, *opt;	char *ap = ackbuf+2;	int  isopts;	((struct tftphdr *)ackbuf)->th_opcode = ntohs(OACK);	filename = cp = tp->th_stuff;again:	while (cp < buf + size) {		if (*cp == '\0')			break;		cp++;	}	if (*cp != '\0') {		if (debug)			syslog(LOG_WARNING, "Received illegal request\n");		nak(EBADOP);		exit(1);	}	if (!argn++) {		mode = ++cp;		goto again;	} else {		if (debug && argn == 3)			syslog(LOG_INFO, "Found RFC1782 style options\n");		*(argn & 1 ? &val : &opt) = ++cp;		if (argn & 1)			do_opt(opt, val, &ap);		if (cp < buf + size && *cp != '\000')			goto again;	}		for (cp = mode; *cp; cp++)		if (isupper(*cp))			*cp = tolower(*cp);	for (pf = formats; pf->f_mode; pf++)		if (strcmp(pf->f_mode, mode) == 0)			break;	if (pf->f_mode == 0) {		if (debug)			syslog(LOG_WARNING, "Unknown data format: %s\n", mode);		nak(EBADOP);		exit(1);	}	if (rootdir) {		cp = alloca(strlen(rootdir) + strlen(filename) + 1);		if (cp == NULL) {			nak(100+ENOMEM);			exit(1);

⌨️ 快捷键说明

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