/**************************************************************************** * 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. Java基础知识系列——数组

    数组是我们在编程中常用到的一种数据结构. 数组创建有三种方式,以int类型为例: 1.int value[] = new int[]{1,2,3,4,5}; //{}中的是元素 2.int value ...

  2. 3 Longest Substring Without Repeating Characters

    public int lengthOfLongestSubstring(String s) { long length = s.length(); String tmp = ""; ...

  3. nginx日志轮巡切割

    通过编辑脚本的方式来实现日志每日以及每天的切割纪录.可以通过计划任务的方式实现每天执行脚本,具体情况需要更加实际情况 vim /root/cut_nginx_log.sh #!bin/sh Datef ...

  4. <button> 标签 id 与 function 重复时发生的问题

    今天遇到一种情况,在调用js自定义方法的时候,总是提示“import:660 Uncaught TypeError: ... is not a function”. 仔细检查了代码,并没有问题.甚至把 ...

  5. Eclipse:Dubug快捷键

    Debug快捷键 F5单步调试进入函数内部.   F6单步调试不进入函数内部,如果装了金山词霸2006则要把"取词开关"的快捷键改成其他的.   F7由函数内部返回到调用处.   ...

  6. iOS中坐标转换

    坐标转换,可以用UIVIew的方法 //由要转换坐标view的superView执行该方法,rect为待转换view的frame,view是要显示到哪儿的 - (CGRect)convertRect: ...

  7. zTree树的模糊搜索

    工作需要,所以做了一个比较方便的搜索功能:1.功能实现都是基于zTree的API:2.如有更好的建议,欢迎拍我:其中要说明下的是flag 这个字段, 这是我自己定义的扩展字段,代码中涉及到flag 请 ...

  8. DBCC SHOWCONTIG、DBCC DBREINDEX。

    use dbname declare @table_id int set @table_id=object_id('tablename') dbcc showcontig(@table_id) 解释如 ...

  9. dos2unix unix2dos

    实现windows和linux之间的文件自动转换,消除^M.

  10. DOCTYPE的详细图解

    之前有一次写代码的时候忘记写了<!DOCTYPE html> 导致样式的效果一直有点问题,查了很久才发现时候这个的锅.之后自己详细的来查找了DOCTYPE的作用. 在目前,基本上都是采用浏 ...