3 #include <sys/select.h>
8 #define _FILE_OFFSET_BITS 64 /* for curl_off_t magic */
11 #define VERSION "0.1-dev"
13 struct gengetopt_args_info
{
25 static void print_options(void)
27 printf("curltunnel\nCopyright 2007 curltunnel Project\nV " VERSION
"\n"
29 "-h --help Print help and exit\n"
30 "-p --proxy=STRING Proxy host:port combination to connect to\n"
31 "-u --user=STRING User:Password combination to send to proxy\n"
32 "-d --dest=STRING Host:port combination to tunnel to\n"
33 "-v --verbose Print messages about what's going on\n");
36 static char * gengetopt_strdup(char *s
)
40 n
=(char *)malloc(1+ps
-s
);
43 for(ps
=s
,pn
=n
;*ps
;ps
++,pn
++)
50 static int command_line_parser(int argc
, char * const *argv
, struct gengetopt_args_info
*args_info
)
56 args_info->help_given = 0;\
57 args_info->verbose_given = 0;\
58 args_info->user_given = 0;\
59 args_info->proxy_given = 0;\
60 args_info->dest_given = 0;\
61 args_info->proxy_arg = NULL;\
62 args_info->user_arg = NULL;\
63 args_info->dest_arg = NULL;\
76 static struct option long_options
[] = {
77 { "help", 0, NULL
, 'h' },
78 { "verbose", 0, NULL
, 'v' },
79 { "proxy", 1, NULL
, 'p' },
80 { "user", 1, NULL
, 'u' },
81 { "dest", 1, NULL
, 'd' },
85 c
= getopt_long(argc
,argv
,"hvp:u:d:", long_options
, &option_index
);
96 args_info
->verbose_given
= !(args_info
->verbose_given
);
97 if(args_info
->verbose_given
)
98 printf("Verbose mode on\n");
101 if(args_info
->proxy_given
)
103 fprintf(stderr
,"curltunnel: `--proxy' (`-p') option given more than once\n");
107 args_info
->proxy_given
= 1;
108 args_info
->proxy_arg
= gengetopt_strdup(optarg
);
111 if(args_info
->user_given
)
113 fprintf(stderr
,"curltunnel: `--user' (`-u') option given more than once\n");
117 args_info
->user_given
= 1;
118 args_info
->user_arg
= gengetopt_strdup(optarg
);
121 if(args_info
->dest_given
)
123 fprintf(stderr
,"curltunnel: `--dest' (`-d') option given more than once\n");
127 args_info
->dest_given
= 1;
128 args_info
->dest_arg
= gengetopt_strdup(optarg
);
133 if(!args_info
->proxy_given
|| !args_info
->dest_given
)
143 static int fd_read(int fd
, void *buf
, size_t len
)
146 bytes_read
= read(fd
,buf
,len
);
150 static int fd_write(int fd
, void *buf
, size_t len
)
153 bytes_written
= write(fd
,buf
,len
);
154 return bytes_written
;
157 static int fdcopy(int fdin
, int fdout
)
162 if((n
=fd_read(fdin
,buf
,SIZE
))<0)
164 fprintf(stderr
,"Read Error\n");
171 if(fd_write(fdout
,buf
,n
)!=n
)
173 fprintf(stderr
,"Write Error\n");
180 static void wait_and_act(int sockfd
, int verbose
)
182 struct timeval timeout
;
183 int rc
; /* select() return code */
184 long timeout_ms
= 10000;
197 /* set timeout to wait */
198 timeout
.tv_sec
= timeout_ms
/1000;
199 timeout
.tv_usec
= (timeout_ms
%1000)*1000;
201 FD_SET(fileno(stdin
), &fdread
);
202 FD_SET(sockfd
, &fdread
);
203 /* FD_SET(sockfd, &fdwrite); */
208 (fd_set
*)&fdexcep
, &timeout
);
212 fprintf(stderr
,"select() error\n");
217 /* fprintf(stderr,"Timeout\n"); */
219 fprintf(stderr
,"VERBOSE: Timeout after %ldms\n", timeout_ms
);
223 /* use FD_ISSET() to check what happened, then read/write accordingly */
224 if (FD_ISSET(fileno(stdin
), &fdread
))
226 rc
=fdcopy(fileno(stdin
),sockfd
);
230 fprintf(stderr
,"VERBOSE: Sent %d bytes from stdin to socket\n", rc
);
232 if (FD_ISSET(sockfd
,&fdread
))
234 rc
=fdcopy(sockfd
,fileno(stdout
));
238 fprintf(stderr
,"VERBOSE: Sent %d bytes from socket to stdin\n", rc
);
244 int main(int argc
, char *argv
[])
248 struct gengetopt_args_info args_info
;
250 command_line_parser(argc
,argv
,&args_info
);
252 CURL
*hnd
= curl_easy_init();
254 curl_easy_setopt(hnd
, CURLOPT_URL
, args_info
.dest_arg
);
255 curl_easy_setopt(hnd
, CURLOPT_PROXY
, args_info
.proxy_arg
);
256 curl_easy_setopt(hnd
, CURLOPT_PROXYUSERPWD
, args_info
.user_arg
);
257 curl_easy_setopt(hnd
, CURLOPT_USERAGENT
, "curltunnel/" VERSION
);
258 curl_easy_setopt(hnd
, CURLOPT_HTTPPROXYTUNNEL
, 1);
259 curl_easy_setopt(hnd
, CURLOPT_CONNECT_ONLY
, 1);
260 if(args_info
.verbose_given
)
261 curl_easy_setopt(hnd
, CURLOPT_VERBOSE
, 1);
262 ret
= curl_easy_perform(hnd
);
266 /* Extract socket, and select() */
267 ret
= curl_easy_getinfo(hnd
, CURLINFO_LASTSOCKET
, &sckt
);
269 if((sckt
==-1) || ret
){
270 fprintf(stderr
,"[ERR] Couldn't get socket");
274 wait_and_act((int)sckt
, args_info
.verbose_given
);
276 curl_easy_cleanup(hnd
);