Avoid recursion when processing residual inbuf data.
[shim.git] / main.c
blob5949fa9a01041e94c6307dc6928f18cdb7b789ab
1 #include "netheaders.h"
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 // XXX unistd/getopt isnt available everywhere!
7 #include <unistd.h>
8 #ifndef WIN32
9 #include <signal.h>
10 #endif
11 #include <event2/event.h>
12 #include <event2/dns.h>
13 #include <event2/util.h>
15 #include "config.h"
16 #include "proxy.h"
17 #include "conn.h"
18 #include "log.h"
19 #include "util.h"
21 #define DEFAULT_LISTEN_ADDR "127.0.0.1"
22 #define DEFAULT_LISTEN_PORT "8123"
24 static void
25 set_socks_server(const char *socks)
27 struct url *url;
28 enum socks_ver socksv;
30 url = url_tokenize(socks);
31 if (!url || !url->scheme) {
32 log_error("shim: bad socks server, %s", socks);
33 exit(1);
35 if (url->port < 0)
36 url->port = 1080;
38 if (!evutil_ascii_strcasecmp(url->scheme, "socks4"))
39 socksv = SOCKS_4;
40 else if (!evutil_ascii_strcasecmp(url->scheme, "socks4a"))
41 socksv = SOCKS_4a;
42 else {
43 log_error("shim: unknown socks version, %s",
44 url->scheme);
45 exit(1);
48 if (conn_set_socks_server(url->host, url->port, socksv) < 0)
49 exit(1);
51 url_free(url);
54 static void
55 start_listening(struct event_base *base, struct evdns_base *dns,
56 const char *laddr, const char *lport)
58 struct evutil_addrinfo hints;
59 struct evutil_addrinfo *ai = NULL;
60 int ret;
62 if (!evutil_ascii_strcasecmp(laddr, "any"))
63 laddr = NULL;
65 memset(&hints, 0, sizeof(hints));
66 hints.ai_family = AF_UNSPEC;
67 hints.ai_socktype = SOCK_STREAM;
68 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
69 * types we don't have an interface to connect to. */
70 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
72 ret = evutil_getaddrinfo(laddr, lport, &hints, &ai);
73 if (ret < 0) {
74 log_error("shim: bad listen address: %s",
75 evutil_gai_strerror(ret));
76 exit(1);
79 if (proxy_init(base, dns, ai->ai_addr, ai->ai_addrlen) < 0)
80 exit(1);
83 static void
84 decrease_log_verbosity(void)
86 switch (log_get_min_level()) {
87 case LOG_DEBUG:
88 log_set_min_level(LOG_INFO);
89 break;
90 case LOG_INFO:
91 log_set_min_level(LOG_NOTICE);
92 break;
93 case LOG_NOTICE:
94 log_set_min_level(LOG_WARN);
95 break;
96 case LOG_WARN:
97 log_set_min_level(LOG_ERROR);
98 break;
99 case LOG_ERROR:
100 log_set_min_level(LOG_FATAL);
101 break;
102 default:
103 break;
107 static void
108 increase_log_verbosity(void)
110 switch (log_get_min_level()) {
111 case LOG_FATAL:
112 log_set_min_level(LOG_ERROR);
113 break;
114 case LOG_ERROR:
115 log_set_min_level(LOG_WARN);
116 break;
117 case LOG_WARN:
118 log_set_min_level(LOG_NOTICE);
119 break;
120 case LOG_NOTICE:
121 log_set_min_level(LOG_INFO);
122 break;
123 case LOG_INFO:
124 log_set_min_level(LOG_DEBUG);
125 break;
126 default:
127 break;
131 static void
132 init_socket_stuff()
134 #ifdef WIN32
135 WSADATA WSAData;
136 WSAStartup(0x101, &WSAData);
137 #else
138 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
139 perror("signal");
140 exit(1);
142 #endif
145 static void
146 usage(void)
148 printf("shim [-l host] [-p port] [-qVv] "
149 "[ socks_version://address[:port] ]\n");
150 exit(1);
154 main(int argc, char **argv)
156 struct event_base *base;
157 struct evdns_base *dns = NULL;
158 int opt;
159 const char *laddr, *lport;
161 init_socket_stuff();
163 base = event_base_new();
164 #ifndef DISABLE_DIRECT_CONNECTIONS
165 dns = evdns_base_new(base, 1);
166 #endif
167 log_set_file(NULL);
169 laddr = DEFAULT_LISTEN_ADDR;
170 lport = DEFAULT_LISTEN_PORT;
172 while ((opt = getopt(argc, argv, "l:p:Vvq")) >= 0) {
173 switch (opt) {
174 case 'l':
175 laddr = optarg;
176 break;
177 case 'p':
178 lport = optarg;
179 break;
180 case 'V':
181 printf("%s\n", PACKAGE_STRING);
182 exit(1);
183 case 'v':
184 increase_log_verbosity();
185 break;
186 case 'q':
187 decrease_log_verbosity();
188 break;
189 default:
190 usage();
194 argc -= optind;
195 argv += optind;
197 if (argc)
198 set_socks_server(argv[0]);
199 start_listening(base, dns, laddr, lport);
200 event_base_dispatch(base);
202 return 0;