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

📄 ftpd.c

📁 伯克利大学的一个ftp协议的实现源代码,包括客户端和服务器端.
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	(void) fclose(din);	data = -1;	pdata = -1;done:	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);	(*closefunc)(fout);}static FILE *getdatasock(mode)	const char *mode;{	int on = 1, s, t, tries;	sigset_t allsigs;	if (data >= 0)		return (fdopen(data, mode));	sigfillset(&allsigs);	sigprocmask (SIG_BLOCK, &allsigs, NULL);	(void) seteuid((uid_t)0);	s = socket(AF_INET, SOCK_STREAM, 0);	if (s < 0)		goto bad;	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,	    (char *) &on, sizeof(on)) < 0)		goto bad;	/* anchor socket to avoid multi-homing problems */#ifndef __linux__	data_source.sin_len = sizeof(struct sockaddr_in);#endif	data_source.sin_family = AF_INET;	data_source.sin_addr = ctrl_addr.sin_addr;	for (tries = 1; ; tries++) {		if (bind(s, (struct sockaddr *)&data_source,		    sizeof(data_source)) >= 0)			break;		if (errno != EADDRINUSE || tries > 10)			goto bad;		sleep(tries);	}	(void) seteuid((uid_t)pw->pw_uid);	sigfillset(&allsigs);	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);#ifdef IP_TOS	on = IPTOS_THROUGHPUT;	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");#endif#ifdef TCP_NOPUSH	/*	 * Turn off push flag to keep sender TCP from sending short packets	 * at the boundaries of each write().  Should probably do a SO_SNDBUF	 * to set the send buffer size as well, but that may not be desirable	 * in heavy-load situations.	 */	on = 1;	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0)		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");#endif#ifdef SO_SNDBUF	on = 65536;	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0)		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");#endif	return (fdopen(s, mode));bad:	/* Return the real value of errno (close may change it) */	t = errno;	(void) seteuid((uid_t)pw->pw_uid);	sigfillset (&allsigs);	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);	(void) close(s);	errno = t;	return (NULL);}static FILE *dataconn(name, size, mode)	const char *name;	off_t size;	const char *mode;{	char sizebuf[32];	FILE *file;	int retry = 0, tos;	file_size = size;	byte_count = 0;	if (size != (off_t) -1) {		(void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)", 				(quad_t) size);	} else		sizebuf[0] = '\0';	if (pdata >= 0) {		struct sockaddr_in from;		int s, fromlen = sizeof(from);		signal (SIGALRM, toolong);		(void) alarm ((unsigned) timeout);		s = accept(pdata, (struct sockaddr *)&from, &fromlen);		(void) alarm (0);		if (s < 0) {			reply(425, "Can't open data connection.");			(void) close(pdata);			pdata = -1;			return (NULL);		}		if (ntohs(from.sin_port) < IPPORT_RESERVED) {			perror_reply(425, "Can't build data connection");			(void) close(pdata);			(void) close(s);			pdata = -1;			return (NULL);		}		if (from.sin_addr.s_addr != his_addr.sin_addr.s_addr) {			perror_reply(435, "Can't build data connection"); 			(void) close(pdata);			(void) close(s);			pdata = -1;			return (NULL);		}		(void) close(pdata);		pdata = s;#ifdef IP_TOS		tos = IPTOS_THROUGHPUT;		(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,		    sizeof(int));#endif		reply(150, "Opening %s mode data connection for '%s'%s.",		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);		return (fdopen(pdata, mode));	}	if (data >= 0) {		reply(125, "Using existing data connection for '%s'%s.",		    name, sizebuf);		usedefault = 1;		return (fdopen(data, mode));	}	if (usedefault)		data_dest = his_addr;	usedefault = 1;	file = getdatasock(mode);	if (file == NULL) {		reply(425, "Can't create data socket (%s,%d): %s.",		    inet_ntoa(data_source.sin_addr),		    ntohs(data_source.sin_port), strerror(errno));		return (NULL);	}	data = fileno(file);	/*	 * attempt to connect to reserved port on client machine;	 * this looks like an attack	 */	if (ntohs(data_dest.sin_port) < IPPORT_RESERVED ||	    ntohs(data_dest.sin_port) == 2049) {		/* XXX */		perror_reply(425, "Can't build data connection");		(void) fclose(file);		data = -1;		return NULL;	}	if (data_dest.sin_addr.s_addr != his_addr.sin_addr.s_addr) {		perror_reply(435, "Can't build data connection");		(void) fclose(file);		data = -1;		return NULL;	}	while (connect(data, (struct sockaddr *)&data_dest,	    sizeof(data_dest)) < 0) {		if (errno == EADDRINUSE && retry < swaitmax) {			sleep((unsigned) swaitint);			retry += swaitint;			continue;		}		perror_reply(425, "Can't build data connection");		(void) fclose(file);		data = -1;		return (NULL);	}	reply(150, "Opening %s mode data connection for '%s'%s.",	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);	return (file);}/* * Tranfer the contents of "instr" to "outstr" peer using the appropriate * encapsulation of the data subject to Mode, Structure, and Type. * * NB: Form isn't handled. */static voidsend_data(instr, outstr, blksize, filesize, isreg)	FILE *instr, *outstr;	off_t blksize;	off_t filesize;	int isreg;{	int c, cnt, filefd, netfd;	char *buf, *bp;	size_t len;	transflag++;	if (setjmp(urgcatch)) {		transflag = 0;		return;	}	switch (type) {	case TYPE_A:		while ((c = getc(instr)) != EOF) {			byte_count++;			if (c == '\n') {				if (ferror(outstr))					goto data_err;				(void) putc('\r', outstr);			}			(void) putc(c, outstr);		}		fflush(outstr);		transflag = 0;		if (ferror(instr))			goto file_err;		if (ferror(outstr))			goto data_err;		reply(226, "Transfer complete.");		return;	case TYPE_I:	case TYPE_L:		/*		 * isreg is only set if we are not doing restart and we		 * are sending a regular file		 */		netfd = fileno(outstr);		filefd = fileno(instr);		if (isreg && filesize < (off_t)16 * 1024 * 1024) {			buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd,				   (off_t)0);			if (buf==MAP_FAILED || buf==NULL) {				syslog(LOG_WARNING, "mmap(%lu): %m",				       (unsigned long)filesize);				goto oldway;			}			bp = buf;			len = filesize;			do {				cnt = write(netfd, bp, len);				len -= cnt;				bp += cnt;				if (cnt > 0) byte_count += cnt;			} while(cnt > 0 && len > 0);			transflag = 0;			munmap(buf, (size_t)filesize);			if (cnt < 0)				goto data_err;			reply(226, "Transfer complete.");			return;		}oldway:		if ((buf = malloc((u_int)blksize)) == NULL) {			transflag = 0;			perror_reply(451, "Local resource failure: malloc");			return;		}		while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&		    write(netfd, buf, cnt) == cnt)			byte_count += cnt;		transflag = 0;		(void)free(buf);		if (cnt != 0) {			if (cnt < 0)				goto file_err;			goto data_err;		}		reply(226, "Transfer complete.");		return;	default:		transflag = 0;		reply(550, "Unimplemented TYPE %d in send_data", type);		return;	}data_err:	transflag = 0;	perror_reply(426, "Data connection");	return;file_err:	transflag = 0;	perror_reply(551, "Error on input file");}/* * Transfer data from peer to "outstr" using the appropriate encapulation of * the data subject to Mode, Structure, and Type. * * N.B.: Form isn't handled. */static intreceive_data(instr, outstr)	FILE *instr, *outstr;{	int c;	int cnt;	volatile int bare_lfs = 0;	char buf[BUFSIZ];	transflag++;	if (setjmp(urgcatch)) {		transflag = 0;		return (-1);	}	switch (type) {	case TYPE_I:	case TYPE_L:		while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {			if (write(fileno(outstr), buf, cnt) != cnt)				goto file_err;			byte_count += cnt;		}		if (cnt < 0)			goto data_err;		transflag = 0;		return (0);	case TYPE_E:		reply(553, "TYPE E not implemented.");		transflag = 0;		return (-1);	case TYPE_A:		while ((c = getc(instr)) != EOF) {			byte_count++;			if (c == '\n')				bare_lfs++;			while (c == '\r') {				if (ferror(outstr))					goto data_err;				if ((c = getc(instr)) != '\n') {					(void) putc ('\r', outstr);					if (c == '\0' || c == EOF)						goto contin2;				}			}			(void) putc(c, outstr);	contin2:	;		}		fflush(outstr);		if (ferror(instr))			goto data_err;		if (ferror(outstr))			goto file_err;		transflag = 0;		if (bare_lfs) {			lreply(226,		"WARNING! %d bare linefeeds received in ASCII mode",			    bare_lfs);		(void)printf("   File may not have transferred correctly.\r\n");		}		return (0);	default:		reply(550, "Unimplemented TYPE %d in receive_data", type);		transflag = 0;		return (-1);	}data_err:	transflag = 0;	perror_reply(426, "Data Connection");	return (-1);file_err:	transflag = 0;	perror_reply(452, "Error writing file");	return (-1);}voidstatfilecmd(filename)	char *filename;{	FILE *fin;	int c;	char line[LINE_MAX];	(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);	fin = ftpd_popen(line, "r");	lreply(211, "status of %s:", filename);	while ((c = getc(fin)) != EOF) {		if (c == '\n') {			if (ferror(stdout)){				perror_reply(421, "control connection");				(void) ftpd_pclose(fin);				dologout(1);				/* NOTREACHED */			}			if (ferror(fin)) {				perror_reply(551, filename);				(void) ftpd_pclose(fin);				return;			}			(void) putc('\r', stdout);		}		(void) putc(c, stdout);	}	(void) ftpd_pclose(fin);	reply(211, "End of Status");}voidstatcmd(){	struct sockaddr_in *sn;	u_char *a, *p;	lreply(211, "%s FTP server status:", hostname, version);	printf("     %s\r\n", version);	printf("     Connected to %s", remotehost);	if (!isdigit(remotehost[0]))		printf(" (%s)", inet_ntoa(his_addr.sin_addr));	printf("\r\n");	if (logged_in) {		if (guest)			printf("     Logged in anonymously\r\n");		else			printf("     Logged in as %s\r\n", pw->pw_name);	} else if (askpasswd)		printf("     Waiting for password\r\n");	else		printf("     Waiting for user name\r\n");	printf("     TYPE: %s", typenames[type]);	if (type == TYPE_A || type == TYPE_E)		printf(", FORM: %s", formnames[form]);	if (type == TYPE_L)#if CHAR_BIT == 8		printf(" %d", CHAR_BIT);#else		printf(" %d", bytesize);	/* need definition! */#endif	printf("; STRUcture: %s; transfer MODE: %s\r\n",	    strunames[stru], modenames[mode]);	if (data != -1)		printf("     Data connection open\r\n");	else if (pdata != -1) {		printf("     in Passive mode");		sn = &pasv_addr;		goto printaddr;	} else if (usedefault == 0) {		printf("     PORT");		sn = &data_dest;printaddr:		a = (u_char *) &sn->sin_addr;		p = (u_char *) &sn->sin_port;#define UC(b) (((int) b) & 0xff)		printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),			UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));#undef UC	} else		printf("     No data connection\r\n");	reply(211, "End of status");}voidfatal(s)	const char *s;{	reply(451, "Error in server: %s\n", s);	reply(221, "Closing connection due to server error.");	dologout(0);	/* NOTREACHED */}void#if __STDC__reply(int n, const char *fmt, ...)#elsereply(n, fmt, va_alist)	int n;	char *fmt;        va_dcl#endif{	va_list ap;#if __STDC__	va_start(ap, fmt);#else	va_start(ap);#endif	(void)printf("%d ", n);	(void)vprintf(fmt, ap);	(void)printf("\r\n");	(void)fflush(stdout);	if (debug) {		syslog(LOG_DEBUG, "<--- %d ", n);		vsyslog(LOG_DEBUG, fmt, ap);	}}void#if __STDC__lreply(int n, const char *fmt, ...)#elselreply(n, fmt, va_alist)	int n;	char *fmt;        va_dcl#endif{	va_list ap;#if __STDC__	va_start(ap, fmt);#else	va_start(ap);#endif	(void)printf("%d- ", n);	(void)vprintf(fmt, ap);	(void)printf("\r\n");	(void)fflush(stdout);	if (debug) {		syslog(LOG_DEBUG, "<--- %d- ", n);		vsyslog(LOG_DEBUG, fmt, ap);	}}static voidack(s)	const char *s;{	reply(250, "%s command successful.", s);}voidnack(s)	const char *s;{	reply(502, "%s command not implemented.", s);

⌨️ 快捷键说明

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