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

📄 tftpd.c

📁 This book was written to provide a single reference for network administration in a Linux environmen
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#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.13 (Berkeley) 2/26/91";#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 * * Further modifications by Gero Kuhlmann <gero@gkminix.han.de> *  - RFC1784 filesize option */#include <sys/types.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <signal.h>#include <fcntl.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/tftp.h>#include <netdb.h>#include <setjmp.h>#include <syslog.h>#include <stdio.h>#include <errno.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#define	TIMEOUT		5#ifndef OACK#define OACK		6#endif#ifndef EOPTNEG#define EOPTNEG		8#endifextern	int errno;struct	sockaddr_in sockin = { AF_INET };int	peer;int	rexmtval = TIMEOUT;int	maxtimeout = 5*TIMEOUT;#define	PKTSIZE	(1432 + 4)int     segsize = SEGSIZE;char	buf[PKTSIZE];char	ackbuf[PKTSIZE];struct	sockaddr_in from;int	fromlen;off_t   filesize;#define MAXARG	4char	*dirs[MAXARG+1];main(ac, av)	char **av;{	register struct tftphdr *tp;	register int n = 0;	int on = 1;	ac--; av++;	while (ac-- > 0 && n < MAXARG)		dirs[n++] = *av++;	openlog("tftpd", LOG_PID, LOG_DAEMON);	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 *)&sockin, sizeof (sockin)) < 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();int	set_filesize();struct options {	char	*o_opt;	int	(*o_fnc)();} options[] = {	{ "blksize",	set_blksize },	{ "tsize",	set_filesize },	{ NULL,		NULL }};/* * 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)		return(0);	else if (sz > PKTSIZE - 4)		sz = PKTSIZE - 4;	segsize = sz;	sprintf(*ret = b_ret, "%d", sz);	return(1);}/* * Return a file size (c.f. RFC1784) */set_filesize(val, ret)	char *val;	char **ret;{	static char b_ret[10];	off_t sz = atol(val);	if (sz == 0)		sz = filesize;	sprintf(*ret = b_ret, "%lu", 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)) {					nak(ENOSPACE);					exit(1);				}				*ap = strrchr(strcpy(strrchr(strcpy(*ap, opt),						'\000') + 1, ret), '\000') + 1;			} else {				nak(EOPTNEG);				exit(1);			}			break;		}	return;}/* * Handle initial connection protocol. */tftp(tp, size)	struct tftphdr *tp;	int size;{	register char *cp;	int argn = 0, ecode;	register struct formats *pf = NULL;	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') {		nak(EBADOP);		exit(1);	}	if (!argn++) {		mode = ++cp;		goto again;	} else if (argn == 2) {		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) {

⌨️ 快捷键说明

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