- 论坛徽章:
- 0
|
大家好。
我现在在做一个tcp代理服务器,实现转发的功能。我有3台电脑,分别作为本地客户端,代理服务器以及远程客户端,其中代理服务器上面有2个网卡,一个
是内网的,一个是外网的。
本地客户机的ip:192.168.0.10
代理服务器的ip:
内网的ip:192.168.0.1
外网的ip:202.202.68.191
远程服务器的ip:202.202.68.201
最终就是想在本地客户机192.168.0.10的基础上通过cuteftp 登陆到远程主机202.202.68.201的ftp服务器上面,中间是
通过代理服务器实现转发的功能。
具体代码如下,现在能实现识别用户名和密码,但是在cuteftp上一直提示“数据socket建立失败”,请各位高人指点,这个代码该怎么修改和添加
才能实现ftp功能。在此先感谢了。
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <fcntl.h>
#define TCP_PROTO "tcp"
int proxy_port; /* port to listen for proxy connections on */
struct sockaddr_in hostaddr; /* remote computer's address */
extern int errno; /* defined by libc.a */
/*extern char *sys_errlist[];*/
void parse_args (int argc, char **argv);
void daemonize (int servfd);
void do_proxy (int usersockfd);
void reap_status (void);
void errorout (char *msg);
/
***************************************************************************­*
function: main
description: Main level driver. After daemonizing the process, a
socket
is opened to listen for connections on the proxy port,
connections are accepted and children are spawned to handle
each new connection.
arguments:
argc,argv you know what those are.
return value: none.
calls: parse_args, do_proxy.
globals: reads proxy_port.
***************************************************************************­*/
main (argc,argv)
int argc;
char **argv;
{
int clilen;
int childpid;
int sockfd, newsockfd;
struct sockaddr_in servaddr, cliaddr;
parse_args(argc,argv);
/* prepare an address struct to listen for connections */
bzero((char *) &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = proxy_port;
/* get a socket... */
if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
fputs("failed to create server socket",stderr);
exit(1);
}
printf("Create socket successful!\n");
/* ...and bind our address and port to it */
if (bind(sockfd,(struct sockaddr *) (&servaddr),sizeof(servaddr))
< 0) {
fputs("faild to bind server socket to specified port",stderr);
exit(1);
}
printf("Bind host succeed!\n");
/* get ready to accept with at most 5 clients waiting to connect
*/
listen(sockfd,5);
printf("listening \n");
/* turn ourselves into a daemon */
daemonize(sockfd);
/* fall into a loop to accept new connections and spawn children
*/
while (1) {
/* accept the next connection */
clilen = sizeof(struct sockaddr_in);
newsockfd = accept(sockfd, (struct sockaddr *) (&cliaddr),
&clilen);
printf("Create new connection!\n");
if (newsockfd < 0 && errno == EINTR)
continue; /* a signal might interrupt our accept() call */
else if (newsockfd < 0)
/* something quite amiss -- kill the server */
errorout("failed to accept connection");
/* fork a child to handle this connection */
if ((childpid = fork()) == 0) {
close(sockfd);
do_proxy(newsockfd);
exit(0);
}
/* if fork() failed, the connection is silently dropped --
oops! */
close(newsockfd);
}
}
/
***************************************************************************­*
function: parse_args
description: parse the command line args.
arguments:
argc,argv you know what these are.
return value: none.
calls: none.
globals: writes proxy_port, writes hostaddr.
***************************************************************************­*/
void parse_args (argc,argv)
int argc;
char **argv;
{
int i;
struct hostent *hostp;
struct servent *servp;
unsigned long inaddr;
struct {
char proxy_port [16];
char isolated_host [64];
char service_name [32];
} pargs;
/*input is abnormal*/
if (argc < 4) {
printf("usage: %s <proxy-port> <remote host> <server-name|port-
number>\r\n",argv[0]);
exit(1);
}
strcpy(pargs.proxy_port,argv[1]);
strcpy(pargs.isolated_host,argv[2]);
strcpy(pargs.service_name,argv[3]);
for (i = 0; i < strlen(pargs.proxy_port); i++)
if (!isdigit(*(pargs.proxy_port + i))) break;
if (i == strlen(pargs.proxy_port))
proxy_port = htons(atoi(pargs.proxy_port));
else {
printf("%s: invalid proxy port",pargs.proxy_port);
exit(0);
}
bzero(&hostaddr,sizeof(hostaddr));
hostaddr.sin_family = AF_INET;
if ((inaddr = inet_addr(pargs.isolated_host)) != INADDR_NONE)
bcopy(&inaddr,&hostaddr.sin_addr,sizeof(inaddr));
else if ((hostp = gethostbyname(pargs.isolated_host)) != NULL)
bcopy(hostp->h_addr,&hostaddr.sin_addr,hostp->h_length);
else {
printf("%s: unknown host",pargs.isolated_host);
exit(1);
}
if ((servp = getservbyname(pargs.service_name,TCP_PROTO)) !=
NULL)
hostaddr.sin_port = servp->s_port;
else if (atoi(pargs.service_name) > 0)
hostaddr.sin_port = htons(atoi(pargs.service_name));
else {
printf("%s: invalid/unknown service name or port
number",pargs.service_name);
exit(1);
}
}
/
***************************************************************************­*
function: daemonize
description: detach the server process from the current context,
creating a pristine, predictable environment in which it
will execute.
arguments:
servfd file descriptor in use by server.
return value: none.
calls: none.
globals: none.
***************************************************************************­*/
void daemonize (servfd)
int servfd;
{
int childpid, fd, fdtablesize;
/* ignore terminal I/O, stop signals */
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
/* fork to put us in the background (whether or not the user
specified '&' on the command line */
if ((childpid = fork()) < 0) {
fputs("failed to fork first child",stderr);
exit(1);
}
else if (childpid > 0)
exit(0); /* terminate parent, continue in child */
setsid();
/* dissociate from process group */
/*
if (setpgrp(0,getpid()) < 0) {
fputs("failed to become process group leader",stderr);
exit(1);
}
*/
/* lose controlling terminal */
if ((fd = open("/dev/tty",O_RDWR)) >= 0) {
ioctl(fd,TIOCNOTTY,NULL);
close(fd);
}
/* close any open file descriptors */
for (fd = 0, fdtablesize = getdtablesize(); fd < fdtablesize; fd+
+)
if (fd != servfd) close(fd);
/* set working directory to / to allow filesystems to be
unmounted */
chdir("/");
/* clear the inherited umask */
umask(0);
/* setup zombie prevention */
/*
signal(SIGCLD,reap_status);
*/
}
/
***************************************************************************­*
function: do_proxy
description: does the actual work of virtually connecting a client to
the telnet service on the isolated host.
arguments:
usersockfd socket to which the client is connected.
return value: none.
calls: none.
globals: reads hostaddr.
***************************************************************************­*/
void do_proxy (usersockfd)
int usersockfd;
{
int isosockfd;
fd_set rdfdset;
int connstat;
int iolen;
char buf [2048];
/* open a socket to connect to the isolated host */
if ((isosockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
errorout("failed to create socket to host");
printf("Succeed in creating new socket!\n");
/* attempt a connection */
connstat = connect(isosockfd,(struct sockaddr *)
&hostaddr,sizeof(hostaddr));
printf("Attempt a connection.\n");
switch (connstat) {
case 0:
break;
case ETIMEDOUT:
case ECONNREFUSED:
case ENETUNREACH:
strcpy(buf,strerror(errno)); /* sys_errlist outdated, we use
use strerror function now.added by liaoy*/
strcat(buf,"\r\n");
write(usersockfd,buf,strlen(buf));
close(usersockfd);
exit(1); /* die peacefully if we can't establish a connection
*/
break;
default:
errorout("failed to connect to host");
}
/* now we're connected, serve fall into the data echo loop */
while (1) {
/* Select for readability on either of our two sockets */
FD_ZERO(&rdfdset);
FD_SET(usersockfd,&rdfdset);
FD_SET(isosockfd,&rdfdset);
if (select(FD_SETSIZE,&rdfdset,NULL,NULL,NULL) < 0)
errorout("select failed");
/* is the client sending data? */
if (FD_ISSET(usersockfd,&rdfdset)) {
if ((iolen = recv(usersockfd,buf,sizeof(buf),0)) <= 0)
break; /* zero length means the client disconnected */
send(isosockfd,buf,iolen,0);
printf("Client sends data :%s",buf);
}
/* is the host sending data? */
if (FD_ISSET(isosockfd,&rdfdset)) {
if ((iolen = recv(isosockfd,buf,sizeof(buf),0))<= 0)
break; /* zero length means the host disconnected */
send(usersockfd,buf,iolen,0);
printf("Host sends data: %s",buf);
}
}
/* we're done with the sockets */
close(isosockfd);
close(usersockfd);
}
/
***************************************************************************­*
function: errorout
description: displays an error message on the console and kills the
current process.
arguments:
msg message to be displayed.
return value: none -- does not return.
calls: none.
globals: none.
***************************************************************************­*/
void errorout (msg)
char *msg;
{
FILE *console;
console = fopen("/dev/console","a");
fprintf(console,"proxyd: %s",msg);
fclose(console);
exit(1);
}
/
***************************************************************************­*
function: reap_status
description: handle a SIGCLD signal by reaping the exit status of the
perished child, and discarding it.
arguments: none.
return value: none.
calls: none.
globals: none.
***************************************************************************­*/
void reap_status ()
{
int pid;
union wait status;
while ((pid = wait3(&status,WNOHANG,NULL)) > 0); /* loop while
there are more dead children */ |
|