/**************************************************************************** * program: proxyd * module: proxyd.c * summary: provides proxy tcp service for a host on an isolated network. * * programmer: Carl Harris (ceharris@vt.edu) * date: 22 Feb 94 * * description: * This code implements a daemon process which listens for tcp connec- * tions on a specified port number. When a connection is established, * a child is forked to handle the new client. The child then estab- * lishes a tcp connection to a port on the isolated host. The child * then falls into a loop in which it writes data to the isolated host * for the client and vice-versa. Once a child has been forked, the * parent resumes listening for additional connections. * * The name of the isolated host and the port to serve as proxy for, * as well as the port number the server listen on are specified as * command line arguments. * ****************************************************************************/ #include #include #include #include #include #include #include #include <sys/stat.h> #include #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include #include <sys/ioctl.h> #include <sys/resource.h> #include <sys/wait.h> #define TCP_PROTO "tcp" int proxy_port; /* port to listen for proxy connections on */ struct sockaddr_in hostaddr; /* host addr assembled from gethostbyname() */ void parse_args(int argc, char **argv); void daemonize(int servfd); void do_proxy(int usersockfd); void reap_status(int sig); 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. * ****************************************************************************/ int main(int argc, char *argv[]) { unsigned 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) { perror("failed to create server socket"); exit(1); } int on=1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))==-1) { perror("setsockopt()"); exit(1); } /* ...and bind our address and port to it */ if (bind(sockfd,(struct sockaddr *)(&servaddr),sizeof(servaddr)) < 0) { perror("faild to bind server socket to specified port"); exit(1); } /* get ready to accept with at most 5 clients waiting to connect */ listen(sockfd, 5); /* turn ourselves into a daemon */ daemonize(sockfd); signal(SIGCHLD,reap_status); /* 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); 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); }else if (childpid < 0) { errorout("fork"); } /* if fork() failed, the connection is silently dropped -- oops! */ close(newsockfd); } return 0; } /**************************************************************************** * 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(int argc, char *argv[]) { int i; struct hostent *hostp; struct servent *servp; in_addr_t inaddr; struct { char proxy_port[16]; char isolated_host[64]; char service_name[32]; }pargs; if (argc < 4) { printf("usage: %s args",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) { hostaddr.sin_addr.s_addr = inaddr; }else if ((hostp = gethostbyname(pargs.isolated_host)) != NULL) { //hostaddr.sin_addr = *((struct in_addr *)hostp->h_addr); 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(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) { perror("failed to fork first child"); exit(1); }else if (childpid > 0) exit(0); /* terminate parent, continue in child */ /* dissociate from process group */ if (setpgid(0,getpid()) < 0) { perror("failed to become process group leader"); 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(SIGCHLD,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(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"); /* attempt a connection */ connstat = connect(isosockfd,(struct sockaddr *)&hostaddr,sizeof(hostaddr)); switch (connstat) { case 0: break; case ETIMEDOUT: case ECONNREFUSED: case ENETUNREACH: strcpy(buf,strerror(errno)); strcat(buf,""); 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 = read(usersockfd,buf,sizeof(buf))) <= 0) break; /* zero length means the client disconnected */ write(isosockfd,buf,iolen); /* copy to host -- blocking semantics */ } /* is the host sending data? */ if (FD_ISSET(isosockfd,&rdfdset)) { if ((iolen = read(isosockfd,buf,sizeof(buf))) <= 0) break; /* zero length means the host disconnected */ write(usersockfd,buf,iolen); /* copy to client -- blocking semantics */ } } /* 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(char *msg) { FILE *console; console = fopen("/dev/console","a"); fprintf(console,"proxyd: %s",msg); fclose(console); exit(1); } /**************************************************************************** * function: reap_status * description: handle a SIGCHLD 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 sig) { int pid; int status; while ((pid = waitpid(0, &status, WNOHANG)) > 0); /* loop while there are more dead children */ }

proxyd.c的更多相关文章

  1. sniffer 和 debug flow

    sniffer 和 debug flow sniffer 和 debug flow 复制模板,直接修改IP即可使用: diagnose sys session filter clear diagnos ...

  2. Proxy源代码分析——谈谈如何学习Linux网络编程

    Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到, Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该 ...

  3. Linux网络编程:一个简单的正向代理服务器的实现

    Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到, Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该 ...

  4. Proxy模式(代理[延迟]模式)

    Proxy?? Proxy是"代理人"的意思,它指的是代替别人进行工作的人.代理实际上就是使用委托的机制,在代理的过程中你可以做点其他的事情,然后再来执行被代理对象的代码. 知识储 ...

  5. Proxy Server源码及分析(TCP Proxy源码 Socket实现端口映射)

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/u014530704/article/de ...

  6. Proxy源代码分析--谈谈如何学习Linux网络编程

    http://blog.csdn.net/cloudtech/article/details/1823531 Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到,Linux ...

随机推荐

  1. Spring——(一)IoC

    1. 什么是IOC IOC:inversion of Control 控制反转. 控制反转:即控制权由应用程序代码转到了外部容器.(反转:就是控制权的转移).--降低业务对象之间的依赖程度,即实现了解 ...

  2. js 让浏览器全屏模式的方法launchFullscreen

    浏览器全屏模式的启动函数requestFullscreen仍然需要附带各浏览器的js方言前缀 // 判断各种浏览器,找到正确的方法 function launchFullscreen(element) ...

  3. 。net用lamda实现属性的优雅操作

    internal class ExtensionObjectURL { internal string name { get; set; } } internal static class Exten ...

  4. poj -- 1042 Gone Fishing(枚举+贪心)

    题意: John现有h个小时的空闲时间,他打算去钓鱼.钓鱼的地方共有n个湖,所有的湖沿着一条单向路顺序排列(John每在一个湖钓完鱼后,他只能走到下一个湖继续钓),John必须从1号湖开始钓起,但是他 ...

  5. 开源安卓Http文件下载框架file-downloader的使用

    file-downloader FileDownloader(https://github.com/wlfcolin/file-downloader)是本人开源的一个安卓Http文件下载框架,是根据自 ...

  6. 关于MVC中View使用自定义方法

    今天学习到了在MVC的View中使用自定义方法,很简单,下面分享一下. 1.首先在项目下面建立一个文件夹,用于存我们写的自定义方法. 2.在新建文件夹中新增一个类,命名随便取(最好还是和自定义方法关联 ...

  7. js jQuery中文字符串比较

    先说下普通字符串(英文)比较: 一般使用双等来判断(==),如果还需要类型相同那么就用三等(===) 1. 双等(==)是完全向后兼容的,如果两个操作数类型不一致,它会在某些时候自动对操作数进行类型转 ...

  8. 前端工作面试问题--摘取自github

    前端工作面试问题 本文包含了一些用于考查候选者的前端面试问题.不建议对单个候选者问及每个问题 (那需要好几个小时).只要从列表里挑选一些,就能帮助你考查候选者是否具备所需要的技能. 备注: 这些问题中 ...

  9. tomcat(三)--基本安装配置

    0x01  JDK和Tomcat安装 到oracle官网下载jdk,当前下载的版本是Linux x64 jdk-8u101-linux-x64.tar.gz 到apache官网下载tomcat,当前最 ...

  10. (python) 标准模块sys和os的使用

    一.sys模块 包含了系统的相关的功能.我们来学习sys.argv,它包含命令行参数. 例子:定义了一个add函数,用来实现两个整数的相加. #! coding=utf-8 # usersys.py ...