proxyd.c
/**************************************************************************** * 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的更多相关文章
- sniffer 和 debug flow
sniffer 和 debug flow sniffer 和 debug flow 复制模板,直接修改IP即可使用: diagnose sys session filter clear diagnos ...
- Proxy源代码分析——谈谈如何学习Linux网络编程
Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到, Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该 ...
- Linux网络编程:一个简单的正向代理服务器的实现
Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到, Linux和Windows这样的"傻瓜"操作系统(这里丝毫没有贬低Windows的意思,相反这应该 ...
- Proxy模式(代理[延迟]模式)
Proxy?? Proxy是"代理人"的意思,它指的是代替别人进行工作的人.代理实际上就是使用委托的机制,在代理的过程中你可以做点其他的事情,然后再来执行被代理对象的代码. 知识储 ...
- Proxy Server源码及分析(TCP Proxy源码 Socket实现端口映射)
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/u014530704/article/de ...
- Proxy源代码分析--谈谈如何学习Linux网络编程
http://blog.csdn.net/cloudtech/article/details/1823531 Linux是一个可靠性非常高的操作系统,但是所有用过Linux的朋友都会感觉到,Linux ...
随机推荐
- TCP数据包的封包和拆包
//该段博文为引用,非原创. 封包和拆包 作者:fengge8ylf 博客:http://blog.csdn.net/fengge8ylf 对于基于TCP开发的通讯程序,有个很重要的问题需要解决,就 ...
- 利用bootstrap写图片轮播
利用bootstrap写图片轮播 缺点是轮播没有固定样式图片样式会改变外框的大小,所以要再设置 以及左右按钮的style也要从新设置 <div class="carousel slid ...
- Spring HTTP下载
(1)HTTP 协议可以在客户端和服务器之间传递任何类型的文件. HTTP协议下载文档到客户端时候, 必须通过响应头Content-Type设置文件类型. 例如: contentType=text/h ...
- 关于一个程序的编译过程 zkjg面试
http://blog.csdn.net/gengyichao/article/details/6544266 一 以下是C程序一般的编译过程: 从图中看到: 将编写的一个c程序(源代码 )转换成可以 ...
- flash拖动条移出flash无法拖动
原因:flash拖动条的拖动事件被嵌入flash的div的鼠标事件给截获了!
- C++基础-02
函数重载 - 函数重载依据参数列表,而不依据返回类型 - 重载函数匹配规则: 精确匹配,不需要类型转换,但可以数组名到指针.函数名到指针和T到const T 提升匹配,bool.short.char到 ...
- Android开发学习---sharedpreference的使用
在前面文章中,为了使数据回显,使用的技术思路是,首先,将数据持久化写到ROM或者SDCard中,其中name和password以":"分隔;然后,将数据记取出来,再用split方法 ...
- 全栈开发必备的10款Sublime Text 插件
Sublime Text 具有漂亮的用户界面和强大的功能,例如代码缩略图,多重选择,快捷命令等.Sublime Text 更妙的是它的可扩展性.所以,这里挑选了全栈开发必备的10款 Sublime T ...
- controller错误统一处理--------@ExceptionHandler
用@RequestBody,@ResponseBody,不费吹灰之力就解决了JSon自动绑定.接着就发现,如果遇到RuntimeException,需要给出一个默认返回JSON 三种方式: 1.当这个 ...
- 深入理解Java虚拟机(三)、垃圾收集算法
1.第一门真正使用内存动态分配和垃圾收集技术的语言:Lisp 2.程序计数器.虚拟机栈.本地方法栈这3个区域随线程而生灭,这几个区域的内存会随着方法结束或线程结束而回收,GC关注的是Java堆和方法区 ...