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 ...
随机推荐
- 极光推送NotificationServiceTest.appex文件变红不存在丢失解决办法
这个图片是文件丢失的 创建.appex文件 创建.appex文件 把极光demo里面的这两个文件复制粘贴到新的文件件(新创建的文件是 UIViewController类型的所以就把 (Notifica ...
- iOS 判断设备型号
+ (NSString*)deviceString { // 需要#import "sys/utsname.h" struct utsname systemInfo; uname( ...
- hdu 1258 Sum It Up(dfs+去重)
题目大意: 给你一个总和(total)和一列(list)整数,共n个整数,要求用这些整数相加,使相加的结果等于total,找出所有不相同的拼凑方法. 例如,total = 4,n = 6,list = ...
- (转载)python2+selenium自动化测试系列(一)
1.Selenium2+python自动化1-环境搭建 2.Selenium2+python自动化2-pip降级selenium3.0 3.Selenium2+python自动化3-解决pip使用异常 ...
- MVC后台数据赋值给前端JS对象
Controller中的数据,不管是使用的是ViewModel 还是ViewBag.Data,要将他传递到View中,这个很容易,但是如果要将它传递给JS中的某个对象,这个改如何处理呢? 后台的数据格 ...
- textArea 高度自适应
<textarea name="apparatus" class="dhxTextArea" style="width:100%;height: ...
- redis集群安装
1.普通安装 安装环境 centos 6.8 1.安装必要包 yum install gcc yum -y install wget 2.下载解压 wget http://download.redis ...
- 打造 html5 文件上传组件,实现进度显示及拖拽上传,支持秒传+分片上传+断点续传,兼容IE6+及其它标准浏览器
老早就注册了博客园帐号,昨天才发现,连博客都没开,Github也是一样,深觉惭愧,赶紧潜个水压压惊`(*∩_∩*)′ 言归正传.大概许多人都会用到文件上传的功能,上传的库貌似也不少,比如(jQuery ...
- 新的框架,新的感觉ASP.NET MVC 分享一个简单快速适合新手的框架
在ASP.NET世界中摸爬滚打好几年,用过了各种框架,在最初的ASP.NET web from 到现在的MVC 在起初的经典三层,到现在的MVC IOC 注入 . 突然发现,有些时候真不是跟风用一 ...
- gulp系列文章一 fis vs grunt vs gulp,为什么要是gulp呢?
gulp是最近火起来的前端构建工具,大有赶超grunt之势,它和grunt这种构建工具比较像. grunt是写一个Gruntfile.js来写配置代码,gulp则是写一个gulpfile.js来写配置 ...