📄 proxy.c
字号:
#include<stdio.h>#include<ctype.h>#include<errno.h>#include<signal.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/file.h>#include<sys/ioctl.h>#include<sys/wait.h>#include<netinet/in.h>#include<netdb.h>#define TCP_PROTO "TCP"/*extern variable*/int proxy_port ; /*port to listen for proxy connections on */struct sockaddr_in hostaddr ; /*host address from gethostbyname */extern int errno ; /*defined by libc.a*/extern_const char*_const sys_errlist[] ; /*defined by libc.a*//*Thoese function define in back of main() */void parse_args(int argc, char**argv) ; /*Analysis command line parameter*/void daemonize(int servfd) ; /*become into protect process*/void do_proxy(int usersockfd) ; /* Realize function of proxy */void reap_status() ; /*capture signal of SIGCHLD,process dead proecss*/void errorout(char *msg) ; /*output error *//*function main()*/main(int argc, char **argv){ int opt, len ; int clilen ; int childpid ; int sockfd, newsockfd ; struct sockaddr_in servaddr, cliaddr ; /*information structure*/ parse_args(argc, argv) ;/*analysis command parameter ,to get port of protect and information of the remote host */ bzero((char*)&servaddr, sizeof(servaddr)) ; /*initate server address*/ servaddr.sin_family = AF_INET ; servaddr.sin_addr.s_addr=htonl(INADDR_ANY) ; /*system will automatic fill ip informtion of this computer*/ servaddr.sin_port = proxy_port ; if((sockfd = socket(AF_INET,SOCK_STREAM,0))<0){ fputs("failed to create server socket\r\n",stderr) ; /* stderr where are from*/ exit(1) ; } /*below will bind port*/ opt = 1; len = sizeof(opt) ; /*this two variable will be,used in setsockopt*/ setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,&len) ; /*ensure when proxyd restart ,port of beginning will avilable */ if(bind(sockfd, (struct sockaddr_in)&servaddr, sizeof(servaddr)) < 0){ fputs("faild to bind server socket to specified port\r\n",stderr) ; exit(1) ; } /*get ready to accept with at most 10 clients waiting to connect */ listen(sockfd,10) ; daemonize(sockfd) ; /*become into protect process*/ signal(SIGCHLD,reap_status) ; /*capture terminal signal of child process */ /*below is circle of accept ,using a child process to deal with to per-child process*/ for(;;){ /*accept the next connection*/ clilen = sizeof(cliaddr) ; newsockfd = accept(sockfd,(struct sockaddr_in)&cliaddr, &clilen) ; /*waiting for client to connecting*/ if(newsockfd < 0 && errno == EINTR) continue ; /*a signal might interrpt out accept() call*/ else if(newsockfd < 0) errorout("failed to accept connection") ; /*something quite amiss --kill the server,accept executive failed*/ /*fork a child to handle this connection*/ if((childpid=fork())==0){ /*if childpid=0 ,is a child process*/ close(sockfd) ; /*close listen socket of parent process */ do_proxy(newsockfd) ; /*newsockfd is a waiting accept socket*/ exit(0) ; } close(newsockfd) ; /*newsockfd is no use for parent,so close it*/ }/*for*/}void parse_args(int argc, char **argv){ int i ; struct hostent *hostp ; /*use for client*/ struct servent *servp ; /*use for server*/ unsigned long inaddr ; struct{ char proxy_port[16] ; /*save port of proxy*/ char isolated_host[64] ; char service_name[32] ; }pargs ; if(argc<4){ printf("usage:%s<proxy-port><host><service-name|port-number>\r\n",argv[0]) ; } 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 not a number */ if(i == strlen(pargs.proxy_port)) proxy_port = htons(atoi(pargs.proxy_port)) ; /*atoi :string to int*/ else{ printf("%s:invalid proxy port",pargs.proxy_port) ; exit(0) ; /*if invalid */ } bzero(&hostaddr, sizeof(hostaddr)) ; hostaddr.sin_family = AF_INET ; if((inaddr = inet_addr(pargs.isolated_host))!=INADDR_NONE) /*if pargs.isoslated_host is a ip*/ bcopy(&inaddr, &hostaddr.sin_addr, sizeof(inaddr)) ; /*inaddr is a unsigned long*/ /*extern-struct sockaddr_in hostaddr*/ else if((hostp = gethostbyname(pargs.isolated_host))!=NULL) /*struct hostent *hostp*/ bcopy(hostp->h_addr,&hostddr.sin_addr,hostp->h_length) ; else{ printf("%s:invalid/unknown service name or port number\r\n",pargs.service_name) ; exit(1) ; } /*have fill with hostaddr structure,this structure will be used in do_proxy*/ } /*funtion: daemonize*//*this funtion let listen process become daemonize*/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()*/ if((childpid = fork()) < 0){ fputs("failed to fork first child\r\n",stderr) ; exit(1) ; } else if(childpid > 0) exit(0) ; /*terminate parent, continue in child*/ setsid() ; /*set child process to group process*/ /*child process escape from terminate*/ signal(SIGHUP,SIG_IGN) ; if(pid = fork()) exit(0) ; /*kill first child process, create second child process ,to get child process cann't open controling terminate*/ for(fd = 0, fdtablesize = getdtablesize() ; fd < fdtablesize ; fd++) if(fd != servfd) close(fd) ; chdir("/") ; /*set working directory to / to allow file systems to be unmounted*/ umask(0) ; /*clear the inherited umask*/}void do_proxy(int usersockfd){ /*usersockfd is a accept sockfd that have set in client of sides*/int isosockfd ;fd_set rdfdset ; /*declare a new file description */int connstat ;int iolen ;char buf[2048] ; /*get error information*//*open a socket to connect ot the isolated host*//*this is to connect to server*/if((isosockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) errorout("failed to create socket host") ;connstat = connect(isosockfd, (struct sockaddr*)&hostaddr, sizeof(hostaddr)) ; /*hostaddr is a struct sockaddr_in*/ switch(connstat){ case 0: /*it will return 0,if sucessfull*/ break ; case ETIMEDOUT: case ECONNREFUSED: case ENETUNREACH: strcpy(buf, sys_errlist[errno]) ; /*errno is extern int*/ strcat(buf,"\r\n") ; write(usersockfd,buf, strlen(buf)) ; /*this is doing*/ close(usersockfd) ; exit(1) ; /*die peacefully if we can't establish a connection*/ break ; default: errorout("failed to connect to host") ; } for(;;){ FD_ZERO(&rdfdset) ; /*clear set of file description */ FD_SET(usersockfd,&rdfdset) ; /*add new file description into set */ FD_SET(ioosockfd, &rdfdset) ; if(select(FD_SETSIZE, &rdfdset, NULL, NULL, NULL) < 0) errorout("select failed") ; /*when client sending data*/ if(FD_ISSET(usersockfd, &rdfset)){ if((iolen = read(usersockfd, buf, sizeof(buf))) <= 0) break ; write(isosockfd, buf, iolen) ; /*copy to host*/ } if(FD_ISSET(isosockfd, &rdfset)){ if( (iolen = read(ioosockfd, buf, sizeof(buf))) <= 0) break ; write(usersockfd, buf, iolen) ; } }/*for*/ close(isosockfd) ; close(usersockfd) ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -