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

📄 ftp.c

📁 proxy源代码,linux下的ftp 代理的源代码,大家多多支持啊
💻 C
📖 第 1 页 / 共 4 页
字号:
/*    File: ftpproxy/ftp.c    Copyright (C) 1999, 2000  Wolfgang Zekoll  <wzk@quietsche-entchen.de>    Copyright (C) 2000, 2003  Andreas Schoenberg  <asg@ftpproxy.org>      This software is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.      This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.      You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <stdarg.h>#include <time.h>#include <signal.h>#include <sys/wait.h>#include <ctype.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/fcntl.h>#include <sys/socket.h>#include <netdb.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <arpa/inet.h>#include <syslog.h>#include <sys/time.h>#include "ftp.h"#include "ip-lib.h"#include "lib.h"typedef struct _ftpcmd {    char	name[20];    int		par, ispath, useccp;    int		resp;    int		log;    } ftpcmd_t;ftpcmd_t cmdtab[] = {	/*	 * Einfache FTP Kommandos.	 */    { "ABOR", 0, 0, 0,	225, 1 },		/* oder 226 */    { "ACCT", 1, 0, 0,	230, 0 },    { "CDUP", 1, 1, 1,	200, 1 },    { "CWD",  1, 1, 1,	250, 1 },    { "DELE", 1, 1, 1,	250, 1 },    { "NOOP", 0, 0, 0,	200, 0 },    { "MDTM", 1, 1, 1,	257, 1 },    { "MKD",  1, 1, 1,	257, 1 },    { "MODE", 1, 0, 0,	200, 0 },    { "PWD",  0, 0, 0,	257, 0 },    { "QUIT", 0, 0, 0,	221, 0 },    { "REIN", 0, 0, 0,	0, /* 220, */ 0 },	/* wird nicht unterstuetzt */    { "REST", 1, 0, 0,	350, 0 },    { "RNFR", 1, 1, 1,	350, 1 },    { "RNTO", 1, 1, 1,	250, 1 },    { "RMD",  1, 1, 1,	250, 1 },    { "SITE", 1, 0, 1,	200, 0 },    { "SIZE", 1, 1, 1,	213, 1 },    { "SMNT", 1, 0, 0,	250, 0 },    { "STAT", 1, 1, 1,	211, 0 },			/* oder 212, 213 */    { "STRU", 1, 0, 0,	0, /* 200, */ 0 },	/* wird nicht unterstuetzt */    { "SYST", 0, 0, 0,	215, 0 },    { "TYPE", 1, 0, 0,	200, 0 },    { "XCUP", 1, 1, 1,	200, 1 },    { "XCWD", 1, 1, 1,	250, 1 },    { "XMKD", 1, 1, 1,	257, 1 },    { "XPWD", 0, 0, 0,	257, 0 },    { "XRMD", 1, 1, 1,	250, 1 },	/*	 * Nur der Vollstaendigkeit halber: FTP Kommandos die gesondert	 * behandelt werden.	 */    { "LIST", 1, 1, 1,	0, 0 },    { "NLST", 1, 1, 1,	0, 0 },    { "PORT", 1, 0, 0,	0, /* 200, */ 0 },    { "PASV", 0, 0, 0,	0, /* 200, */ 0 },    { "ALLO", 1, 0, 0,	0, /* 200, */ 0 },    { "RETR", 1, 1, 1,	0, 0 },    { "STOR", 1, 1, 1,	0, 0 },    { "STOU", 0, 0, 1,	0, 0 },    { "APPE", 1, 1, 1,	0, 0 },    { "HELP", 0, 0, 0,	0, 0 },    { "FEAT", 0, 0, 0,	0, 0 },    { "",     0, 0, 0,	0, 0 }    };unsigned get_interface_info(int pfd, char *ip, int max){	int	size;	unsigned int port;	struct sockaddr_in saddr;	size = sizeof(saddr);	if (getsockname(pfd, (struct sockaddr *) &saddr, &size) < 0) {		syslog(LOG_NOTICE, "-ERR: can't get interface info: %s", strerror(errno));		exit (-1);		}	copy_string(ip, (char *) inet_ntoa(saddr.sin_addr), max);	port = ntohs(saddr.sin_port);	return (port);}int get_client_info(ftp_t *x, int pfd){	int	size;	struct sockaddr_in saddr;	struct in_addr *addr;	struct hostent *hostp = NULL;	*x->client = 0;	size = sizeof(saddr);	if (getpeername(pfd, (struct sockaddr *) &saddr, &size) < 0 )		return (-1);			copy_string(x->client_ip, (char *) inet_ntoa(saddr.sin_addr), sizeof(x->client_ip));	if (x->config->numeric_only == 1)		copy_string(x->client, x->client_ip, sizeof(x->client));	else {		addr = &saddr.sin_addr,		hostp = gethostbyaddr((char *) addr,				sizeof (saddr.sin_addr.s_addr), AF_INET);		copy_string(x->client, hostp == NULL? x->client_ip: hostp->h_name, sizeof(x->client));		}	strlwr(x->client);	return (0);}	/*	 * Basic I/O functions	 */int close_ch(ftp_t *x, dtc_t *ch){	if (ch->isock >= 0)		close(ch->isock);	if (ch->osock >= 0)		close (ch->osock);	ch->isock     = -1;	ch->osock     = -1;	ch->state     = 0;	ch->operation = 0;	ch->seen150   = 0;	return (0);}int getc_fd(ftp_t *x, int fd){	int	c;	bio_t	*bio;	if (fd == 0)		bio = &x->cbuf;	else if (fd == x->fd.server)		bio = &x->sbuf;	else {		syslog(LOG_NOTICE, "-ERR: internal bio/fd error");		exit (1);		}	if (bio->here >= bio->len) {		int	rc, max, bytes, earlyreported;		struct timeval tov;		fd_set	available, fdset;		bio->len = bio->here = 0;		earlyreported = 0;		FD_ZERO(&fdset);		FD_SET(fd, &fdset);/*		x->fd.max = fd; */		max = fd;		if (x->ch.operation == 0)			/* nichts */ ;		else if (x->ch.state == PORT_LISTEN) {			if (x->ch.mode == MODE_PORT) {				FD_SET(x->ch.osock, &fdset);				if (x->ch.osock > max)					max = x->ch.osock;				x->ch.active = x->ch.osock;				}			else if (x->ch.mode == MODE_PASSIVE) {				FD_SET(x->ch.isock, &fdset);				if (x->ch.isock > max)					max = x->ch.isock;				x->ch.active = x->ch.isock;				}			else {				syslog(LOG_NOTICE, "-ERR: internal mode error");				exit (-1);				}			}		else if (x->ch.state == PORT_CONNECTED  &&  x->ch.seen150 == 1) {			FD_SET(x->ch.active, &fdset);			if (x->ch.active > max)				max = x->ch.active;			}					bytes = 0;		while (1) {/*			memmove(&available, &fdset, sizeof(fd_set)); */			available = fdset;			tov.tv_sec  = x->config->timeout;			tov.tv_usec = 0;			if (debug >= 2)				fprintf (stderr, "select max= %d\n", max);			rc = select(max + 1, &available, (fd_set *) NULL, (fd_set *) NULL, &tov);			if (rc < 0) {				syslog(LOG_NOTICE, "select() error: %s\n", strerror(errno));				break;				}			else if (rc == 0) {				syslog(LOG_NOTICE, "connection timed out: client= %s, server= %s:%u",					x->client, x->server.name, x->server.port);				return (-1);				}			if (FD_ISSET(fd, &available)) {				if ((bytes = read(fd, bio->buffer, sizeof(bio->buffer) - 2)) <= 0) {					if (debug != 0) {						if (bytes == 0)							fprintf (stderr, "received zero bytes on fd %d\n", fd);						else							fprintf (stderr, "received %d bytes on fd %d, errno= %d, error= %s\n", bytes, fd, errno, strerror(errno));						}					return (-1);					}				break;				}			else if (FD_ISSET(x->ch.active, &available)) {				if (x->ch.state == PORT_LISTEN) {					int	sock, adrlen;					struct sockaddr_in adr;					earlyreported = 0;					adrlen = sizeof(struct sockaddr);					sock = accept(x->ch.active, (struct sockaddr *) &adr, &adrlen);					if (debug != 0)						fprintf (stderr, "accept() on socket\n");					if (sock < 0) {						syslog(LOG_NOTICE, "-ERR: accept error: %s", strerror(errno));						exit (1);						}					else {						char	remote[80];						copy_string(remote, inet_ntoa(adr.sin_addr), sizeof(remote));						if (debug)							fprintf (stderr, "connection from %s\n", remote);						/*						 * Gegenstelle ueberpruefen.						 */						if (x->ch.mode == MODE_PORT) {							if (strcmp(x->server.ipnum, remote) != 0) {								if (x->config->allow_anyremote != 0)									/* configuration tells us not to care -- 31JAN02asg */ ;								else {									syslog(LOG_NOTICE, "-ERR: unexpected connect: %s, expected= %s", remote, x->server.ipnum);									exit (1);									}								}							}						else {							if (strcmp(x->client_ip, remote) != 0) {								if (x->config->allow_anyremote != 0)									/* ok -- 31JAN02asg */ ;								else {									syslog(LOG_NOTICE, "-ERR: unexpected connect: %s, expected= %s", remote, x->client_ip);									exit (1);									}								}							}						}					/*					 * Datenkanal zur anderen Seite aufbauen.					 */					if (x->ch.mode == MODE_PORT) {						dup2(sock, x->ch.osock);						close (sock);						x->ch.state = PORT_CONNECTED;						if (debug)							fprintf (stderr, "osock= %d\n", x->ch.osock);						if ((x->ch.isock = openip(x->ch.client.ipnum, x->ch.client.port, x->interface, x->config->dataport)) < 0) {							syslog(LOG_NOTICE, "-ERR: can't connect to client: %s", strerror(errno));							exit (1);							}						if (debug)							fprintf (stderr, "isock= %d\n", x->ch.isock);						}					else if (x->ch.mode == MODE_PASSIVE) {						dup2(sock, x->ch.isock);						close (sock);						x->ch.state = PORT_CONNECTED;						if (debug)							fprintf (stderr, "isock= %d\n", x->ch.isock);						if ((x->ch.osock = openip(x->ch.server.ipnum, x->ch.server.port, x->config->sourceip, 0)) < 0) {							syslog(LOG_NOTICE, "-ERR: can't connect to server: %s", strerror(errno));							exit (1);							}						if (debug)							fprintf (stderr, "osock= %d\n", x->ch.osock);						}					/*					 * Setzen der Datenquelle (Server oder Client).					 */					if (x->ch.operation == OP_GET) {						x->ch.active = x->ch.osock;						x->ch.other  = x->ch.isock;						}					else if (x->ch.operation == OP_PUT) {						x->ch.active = x->ch.isock;						x->ch.other  = x->ch.osock;						}					else {						syslog(LOG_NOTICE, "-ERR: transfer operation error");						exit (1);						}					if (x->ch.seen150 == 0) {						/*						 * And finally ... another attempt to solve the short						 * data transmission timing problem: If we didn't receive						 * the 150 response yet from the server we deactivate the						 * data channel until we have the 150 -- 030406asg						 */						if (debug >= 2)							fprintf (stderr, "150 not seen, deactivating data channel\n");						FD_ZERO(&fdset);						FD_SET(fd, &fdset);						max = fd;						}					else {						if (debug >= 2)							fprintf (stderr, "150 already seen, activating data channel\n");						FD_ZERO(&fdset);						FD_SET(fd, &fdset);						FD_SET(x->ch.active, &fdset);						max = (fd > x->ch.active)? fd: x->ch.active;						}					if (debug)						fprintf (stderr, "active= %d, other= %d\n", x->ch.active, x->ch.other);					x->ch.bytes = 0;					x->ch.started = time(NULL);					}				else if (x->ch.state == PORT_CONNECTED) {					int	wrote;					char	buffer[FTPMAXBSIZE + 10];					if (x->ch.operation == 0) {						if (earlyreported == 0) {							earlyreported = 1;							syslog(LOG_NOTICE, "early write/read event, sleeping 2 seconds");							sleep(2);							continue;							}						}					bytes = read(x->ch.active, buffer, x->config->bsize /* sizeof(buffer) */ );					/*					 * Handling servers that close the data connection -- 24APR02asg					 */					wrote = 0;					if ((bytes > 0)  &&  ((wrote = write(x->ch.other, buffer, bytes)) == bytes))						x->ch.bytes += bytes;					else {						if (wrote < 0)							syslog(LOG_NOTICE, "error writing data channel, error= %s", strerror(errno));						if (debug)							fprintf (stderr, "closing data connection\n");						close_ch(x, &x->ch);						FD_ZERO(&fdset);						FD_SET(fd, &fdset);						max = fd;						return (1);						}					}				}			}		bio->len  = bytes;		bio->here = 0;		}	if (bio->here >= bio->len)		return (-1);	c = (unsigned char) bio->buffer[bio->here++];	return (c);}char *readline_fd(ftp_t *x, int fd, char *line, int size){	int	c, k;	*line = 0;	size = size - 2;	c = getc_fd(x, fd);	if (c < 0)		return (NULL);	else if (c == 1) {		strcpy(line, "\001");		return (line);		}	k = 0;	while (c > 0  &&  c != '\n'  &&  c != 0) {		if (k < size)			line[k++] = c;		c = getc_fd(x, fd);		}	line[k] = 0;	noctrl(line);	k = 0;	while ((c = (unsigned char ) line[k]) != 0  &&  c > 126)		k++;	if (k > 0)		copy_string(line, &line[k], size);	return (line);}char *cfgets(ftp_t *x, char *line, int size){	char	*p;	*line = 0;	if ((p = readline_fd(x, 0, line, size)) == NULL)		return (NULL);	else if (debug != 0)		fprintf (stderr, "CLI >>>: %s\n", p);

⌨️ 快捷键说明

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