fixed a bug : stand alone expression was failing
[ikh.git] / proxy / vproxy.c
bloba472fd7fceee1fa659cf23f67f2ddd1389a0b70c
2 #include <stdio.h>
3 #include <signal.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <netdb.h>
7 #include <sys/types.h>
8 #include <sys/socket.h>
9 #include <netinet/in.h>
10 #include <arpa/inet.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <sys/param.h>
16 /* Generic Proxy 1.1 */
18 static void sig_usr(int);
20 void Usage(void);
22 #define BUFSIZE 1024
24 int main(int argc,char *argv[])
26 char c;
28 struct hostent *hostptr;
29 struct hostent *l_hostptr;
30 int rnewsockfd;
31 char rhost[100] = "127.0.0.1";
32 char lhost[100] = "0.0.0.0";
33 int rport = 9080;
34 int lport = 9081;
36 int len;
37 char buffer[BUFSIZE];
39 char logfile[MAXPATHLEN] = "";
40 char filename[MAXPATHLEN];
41 int status;
42 int inf;
43 int outf;
44 int to_log=0;
45 int in_bgr=1;
47 int rpid,lpid;
48 int sockfd, lnewsockfd, clilen;
49 struct sockaddr_in cli_addr, serv_addr;
53 while( (c = getopt(argc, argv, "A:a:S:s:R:r:L:l:D:d:Ffh")) != EOF ) {
54 switch( toupper(c) ) {
55 case 'S':
56 strcpy(rhost, optarg);
57 break;
58 case 'A':
59 strcpy(lhost, optarg);
60 break;
61 case 'R':
62 rport = atoi(optarg);
63 break;
64 case 'L':
65 lport = atoi(optarg);
66 break;
67 case 'D':
68 to_log = 1;
69 strcpy(logfile, optarg);
70 break;
71 case 'F':
72 in_bgr = 0;
73 break;
74 default:
75 Usage();
76 return -1;
80 if( strcmp(rhost, "") == 0 ) {
81 Usage();
82 return(-1);
85 printf("Starting proxy from %s:%d to remote %s:%d\n", lhost, lport, rhost,
86 rport);
88 hostptr = gethostbyname(rhost);
89 if( hostptr == NULL )
91 fprintf( stderr, "failed to resolve remote ip address: %s (h_errno=%d)\n",
92 rhost, h_errno );
93 exit(2);
95 l_hostptr = gethostbyname(lhost);
96 if( l_hostptr == NULL )
98 fprintf( stderr, "failed to resolve local ip address: %s (h_errno=%d)\n",
99 lhost, h_errno );
100 exit(2);
104 ** Opening a socket
106 sockfd = socket(AF_INET, SOCK_STREAM, 0);
107 serv_addr.sin_family = AF_INET;
108 (void) memcpy(&serv_addr.sin_addr.s_addr, *(l_hostptr->h_addr_list),
109 sizeof(serv_addr.sin_addr.s_addr)) ;
110 serv_addr.sin_port = htons(lport);
111 status = 1;
112 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&status, sizeof(int));
113 if( bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
114 perror("failed binding server socket");
115 exit(1);
119 ** Start running in background by default
121 if( in_bgr && fork() ) {
122 exit(0);
126 ** Set queue length and signal interrupt
128 listen(sockfd,5);
129 signal(SIGCHLD,sig_usr);
131 for ( ; ; ) {
134 ** Wait for new clients
136 clilen = sizeof(cli_addr);
137 lnewsockfd = -1;
138 while( lnewsockfd < 0 ) {
139 lnewsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
140 if( lnewsockfd > 0 )
141 break;
144 ** It might happen that we got a signal and exited accept
145 ** In this case restart accept and continue to wait
147 if( (lnewsockfd == -1) && (errno == EINTR) )
148 continue;
151 ** Otherwise, we've just failed, exit
153 perror("failed in accept");
154 exit(0);
157 printf( "Connecting client from %s to %s:%d\n",
158 inet_ntoa(cli_addr.sin_addr), rhost, rport);
161 ** Pass the new connection throught to the server
163 rnewsockfd = socket(AF_INET, SOCK_STREAM, 0);
164 serv_addr.sin_family = AF_INET;
165 (void) memcpy(&serv_addr.sin_addr.s_addr, *(hostptr->h_addr_list),
166 sizeof(serv_addr.sin_addr.s_addr)) ;
167 serv_addr.sin_port = htons(rport);
168 connect(rnewsockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
171 ** Forking the baby-sitter
173 if (fork() == 0) {
175 ** Starting first child. It will read from client and sent to
176 ** remote server
178 if ((lpid = fork()) == 0) {
179 if( strcmp(logfile, "") != 0 ) {
180 sprintf(filename, "%s.%d.out", logfile, getpid());
181 outf = open(filename, O_RDWR|O_TRUNC|O_CREAT, 0666);
183 while( (len = read(lnewsockfd, buffer, BUFSIZE)) > 0 ) {
184 if( len ) {
185 if( outf > 0 )
186 write(outf, buffer, len);
187 write(rnewsockfd, buffer, len);
192 ** When finished reading, exit
194 close(lnewsockfd);
195 close(rnewsockfd);
196 close(outf);
197 exit(0);
198 } else if (lpid < 0) {
200 ** Fork failed
202 perror("failed forking 1st child");
203 exit(1);
207 ** Start second child. It will read from the server and write
208 ** to our client
210 if ((rpid = fork()) == 0 ) {
211 if( strcmp(logfile, "") != 0 ) {
212 sprintf(filename, "%s.%d.in", logfile, getpid());
213 inf = open(filename, O_RDWR|O_TRUNC|O_CREAT, 0666);
215 while( (len = read(rnewsockfd, buffer, BUFSIZE)) > 0) {
216 if( len ) {
217 if( inf > 0 )
218 write(inf, buffer, len);
219 write(lnewsockfd, buffer, len);
224 ** When finished writing, exist
226 close(lnewsockfd);
227 close(rnewsockfd);
228 close(inf);
229 exit(0);
231 else if (rpid < 0) {
233 ** Fork failed
235 perror("failed forking 2nd child");
236 exit(1);
240 ** Now baby-sitter waits for any child to finish
242 close(lnewsockfd);
243 close(rnewsockfd);
244 wait(&status);
247 ** If any of the children terminated, kill all of them
249 kill(rpid,SIGKILL);
250 kill(lpid,SIGKILL);
251 exit(0);
252 } /* baby-sitter */
255 ** The main process closes files and goes on to wait for new clients
257 close(lnewsockfd);
258 close(rnewsockfd);
259 } /* forever */
261 } /* main */
263 void Usage()
265 printf("Usage: vproxy [-a local_ip=0.0.0.0] [-l local_port=9081] [-s remote_ip=127.0.0.1] [-r remote_port=9080] [-d log_prefix]\n");
269 static void sig_usr(int signo)
272 int status,pid;
274 pid = wait(&status);
275 signal(SIGCHLD,sig_usr);