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

📄 tftpd.c

📁 压缩包中包含LINUX下多个命令的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983, 1993 *	The 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. * 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 lintstatic char copyright[] ="@(#) Copyright (c) 1983, 1993\n\	The Regents of the University of California.  All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)tftpd.c	8.1 (Berkeley) 6/4/93";#endif /* not lint *//* * Trivial file transfer protocol server. * * This version includes many modifications by Jim Guyton * <guyton@rand-unix>. */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <sys/param.h>#include <sys/ioctl.h>#ifdef HAVE_SYS_FILIO_H#include <sys/filio.h>#endif#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/tftp.h>#include <arpa/inet.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <getopt.h>#include <netdb.h>#include <setjmp.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <syslog.h>#include <unistd.h>#include "tftpsubs.h"#if !HAVE_DECL_STRERRORextern const char *strerror __P ((int));#endif#define	TIMEOUT		5#ifndef LOG_FTP#define LOG_FTP LOG_DAEMON	/* Use generic facility.  */#endifint	peer;int	rexmtval = TIMEOUT;int	maxtimeout = 5*TIMEOUT;#define	PKTSIZE	SEGSIZE+4char	buf[PKTSIZE];char	ackbuf[PKTSIZE];struct	sockaddr_in from;int	fromlen;void	tftp __P((struct tftphdr *, int));/* * Null-terminated directory prefix list for absolute pathname requests and * search list for relative pathname requests. * * MAXDIRS should be at least as large as the number of arguments that * inetd allows (currently 20). */#define MAXDIRS	20static struct dirlist {	char	*name;	int	len;} dirs[MAXDIRS+1];static int	suppress_naks;static int	logging;static const char *errtomsg __P((int));static void  nak __P((int));static const char *verifyhost __P((struct sockaddr_in *));intmain(int argc, char *argv[]){	register struct tftphdr *tp;	register int n;	int ch, on;	struct sockaddr_in sin;	openlog("tftpd", LOG_PID, LOG_FTP);	while ((ch = getopt(argc, argv, "ln")) != EOF) {		switch (ch) {		case 'l':			logging = 1;			break;		case 'n':			suppress_naks = 1;			break;		default:			syslog(LOG_WARNING, "ignoring unknown option -%c", ch);		}	}	if (optind < argc) {		struct dirlist *dirp;		/* Get list of directory prefixes. Skip relative pathnames. */		for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS];		     optind++) {			if (argv[optind][0] == '/') {				dirp->name = argv[optind];				dirp->len  = strlen(dirp->name);				dirp++;			}		}	}	on = 1;	if (ioctl(0, FIONBIO, &on) < 0) {		syslog(LOG_ERR, "ioctl(FIONBIO): %m\n");		exit(1);	}	fromlen = sizeof (from);	n = recvfrom(0, buf, sizeof (buf), 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, sizeof (buf), 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);	}	memset(&sin, 0, sizeof(sin));	sin.sin_family = AF_INET;	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);}struct formats;int	validate_access __P((char **, int));void	send_file __P((struct formats *));void	recvfile __P((struct formats *));struct formats {	char	*f_mode;	int	(*f_validate) __P((char **, int));	void	(*f_send) __P((struct formats *));	void	(*f_recv) __P((struct formats *));	int	f_convert;} formats[] = {	{ "netascii",	validate_access,	send_file,	recvfile, 1 },	{ "octet",	validate_access,	send_file,	recvfile, 0 },#ifdef notdef	{ "mail",	validate_user,		sendmail,	recvmail, 1 },#endif	{ 0 }};/* * Handle initial connection protocol. */voidtftp(struct tftphdr *tp, int size){	register char *cp;	int first = 1, ecode;	register struct formats *pf;	char *filename, *mode;	filename = cp = tp->th_stuff;again:	while (cp < buf + size) {		if (*cp == '\0')			break;		cp++;	}	if (*cp != '\0') {		nak(EBADOP);		exit(1);	}	if (first) {		mode = ++cp;		first = 0;		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) {		nak(EBADOP);		exit(1);	}	ecode = (*pf->f_validate)(&filename, tp->th_opcode);	if (logging) {		syslog(LOG_INFO, "%s: %s request for %s: %s",			verifyhost(&from),			tp->th_opcode == WRQ ? "write" : "read",			filename, errtomsg(ecode));	}	if (ecode) {		/*		 * Avoid storms of naks to a RRQ broadcast for a relative		 * bootfile pathname from a diskless Sun.		 */		if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)			exit(0);		nak(ecode);		exit(1);	}	if (tp->th_opcode == WRQ)		(*pf->f_recv)(pf);	else		(*pf->f_send)(pf);	exit(0);}FILE *file;/* * Validate file access.  Since we * have no uid or gid, for now require * file to exist and be publicly

⌨️ 快捷键说明

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