Lines 31-36
Link Here
|
31 |
|
31 |
|
32 |
#include <stdio.h> |
32 |
#include <stdio.h> |
33 |
#include <stdlib.h> |
33 |
#include <stdlib.h> |
|
|
34 |
#include <stddef.h> |
34 |
#include <unistd.h> |
35 |
#include <unistd.h> |
35 |
#include <string.h> |
36 |
#include <string.h> |
36 |
#include <fcntl.h> |
37 |
#include <fcntl.h> |
Lines 42-49
Link Here
|
42 |
#include <sys/types.h> |
43 |
#include <sys/types.h> |
43 |
#include <sys/socket.h> |
44 |
#include <sys/socket.h> |
44 |
|
45 |
|
|
|
46 |
#include <arpa/inet.h> |
45 |
#include <netinet/in.h> |
47 |
#include <netinet/in.h> |
46 |
#include <netinet/tcp.h> |
48 |
#include <netinet/tcp.h> |
|
|
49 |
#include <sys/un.h> |
47 |
|
50 |
|
48 |
#include <netdb.h> |
51 |
#include <netdb.h> |
49 |
|
52 |
|
Lines 161-167
out_failed:
Link Here
|
161 |
/** |
164 |
/** |
162 |
* Open a socket to a tcp remote host with the specified port. |
165 |
* Open a socket to a tcp remote host with the specified port. |
163 |
**/ |
166 |
**/ |
164 |
int dcc_connect_by_name(const char *host, int port, int *p_fd) |
167 |
static int dcc_connect_by_name_real(const char *host, int port, int *p_fd) |
165 |
{ |
168 |
{ |
166 |
struct addrinfo hints; |
169 |
struct addrinfo hints; |
167 |
struct addrinfo *res; |
170 |
struct addrinfo *res; |
Lines 201-207
int dcc_connect_by_name(const char *host, int port, int *p_fd)
Link Here
|
201 |
* |
204 |
* |
202 |
* @todo Don't try for too long to connect. |
205 |
* @todo Don't try for too long to connect. |
203 |
**/ |
206 |
**/ |
204 |
int dcc_connect_by_name(const char *host, int port, int *p_fd) |
207 |
static int dcc_connect_by_name_real(const char *host, int port, int *p_fd) |
205 |
{ |
208 |
{ |
206 |
struct sockaddr_in sock_out; |
209 |
struct sockaddr_in sock_out; |
207 |
struct hostent *hp; |
210 |
struct hostent *hp; |
Lines 224-226
int dcc_connect_by_name(const char *host, int port, int *p_fd)
Link Here
|
224 |
} |
227 |
} |
225 |
|
228 |
|
226 |
#endif /* not ENABLE_RFC2553 */ |
229 |
#endif /* not ENABLE_RFC2553 */ |
227 |
- |
230 |
|
|
|
231 |
static int dcc_connect_via_socks5(const char *host, int port, int *p_fd, const char *proxy) |
232 |
{ |
233 |
int ret; |
234 |
char *proxy_host, *proxy_it; |
235 |
int proxy_port; |
236 |
char buf[262]; |
237 |
int host_length; |
238 |
struct sockaddr_in addr_buf; |
239 |
int skip_bytes; |
240 |
|
241 |
host_length = strlen(host); |
242 |
if (host_length > 255) { |
243 |
rs_log_error("hostname \"%s\" too long for SOCKSv5 (over 255 chars)", host); |
244 |
return EXIT_CONNECT_FAILED; |
245 |
} |
246 |
|
247 |
if (proxy[0] == '/') { /* UNIX socket */ |
248 |
struct sockaddr_un unix_addr; |
249 |
|
250 |
if (strlen(proxy) >= sizeof(unix_addr.sun_path)) |
251 |
{ |
252 |
rs_log_error("UNIX socket path \"%s\" too long", proxy); |
253 |
return EXIT_CONNECT_FAILED; |
254 |
} |
255 |
|
256 |
unix_addr.sun_family = AF_UNIX; |
257 |
strcpy(unix_addr.sun_path, proxy); |
258 |
|
259 |
ret = dcc_connect_by_addr((struct sockaddr *) &unix_addr, |
260 |
offsetof(struct sockaddr_un, sun_path) + strlen(proxy) + 1, |
261 |
p_fd); |
262 |
|
263 |
} else { /* hostname? IP address? */ |
264 |
proxy_host = strdup(proxy); |
265 |
if (proxy_host == NULL) return EXIT_OUT_OF_MEMORY; |
266 |
|
267 |
proxy_it = strrchr(proxy_host, ':'); |
268 |
if (proxy_it) { |
269 |
*(proxy_it++) = 0; |
270 |
proxy_port = atoi(proxy_it); |
271 |
|
272 |
if (proxy_port <= 0) { |
273 |
rs_log_error("invalid proxy port \"%s\"", proxy_it); |
274 |
free(proxy_host); |
275 |
return EXIT_CONNECT_FAILED; |
276 |
} |
277 |
} |
278 |
else |
279 |
proxy_port = 1080; |
280 |
|
281 |
ret = dcc_connect_by_name_real(proxy_host, proxy_port, p_fd); |
282 |
free(proxy_host); |
283 |
} |
284 |
|
285 |
if (ret != 0) |
286 |
return ret; |
287 |
|
288 |
/* connected to proxy, now identifier/method selection */ |
289 |
buf[0] = 0x05; /* SOCKSv5 */ |
290 |
buf[1] = 0x01; /* one method */ |
291 |
buf[2] = 0x00; /* NO AUTHENTICATION REQUIRED */ |
292 |
ret = dcc_writex(*p_fd, buf, 3); |
293 |
if (ret != 0) |
294 |
return ret; |
295 |
|
296 |
/* wait for method selection */ |
297 |
ret = dcc_readx(*p_fd, buf, 2); |
298 |
if (ret != 0) |
299 |
return ret; |
300 |
if (buf[0] != 0x05 || buf[1] != 0x00) { /* version, method */ |
301 |
rs_log_error("invalid proxy reply (version 0x%02x, method 0x%02x)", |
302 |
buf[0], buf[1]); |
303 |
return EXIT_CONNECT_FAILED; |
304 |
} |
305 |
|
306 |
/* send connect request */ |
307 |
buf[0] = 0x05; /* SOCKSv5 */ |
308 |
buf[1] = 0x01; /* CONNECT command */ |
309 |
buf[2] = 0x00; /* reserved */ |
310 |
buf[3] = 0x03; /* DOMAINNAME address type */ |
311 |
buf[4] = host_length; |
312 |
memcpy(&buf[5], host, host_length); |
313 |
addr_buf.sin_port = htons(port); |
314 |
memcpy(&buf[5 + host_length], &addr_buf.sin_port, 2); |
315 |
ret = dcc_writex(*p_fd, buf, 7 + host_length); |
316 |
if (ret != 0) |
317 |
return ret; |
318 |
|
319 |
/* wait for the connection */ |
320 |
/* read first 4 bytes of reply + 2 extra bytes we know will be there */ |
321 |
ret = dcc_readx(*p_fd, buf, 6); |
322 |
if (ret != 0) |
323 |
return ret; |
324 |
if (buf[0] != 0x05 || buf[2] != 0x00) { /* version, reserved */ |
325 |
rs_log_error("invalid proxy reply (version 0x%02x, reserved 0x%02x)", |
326 |
buf[0], buf[2]); |
327 |
return EXIT_CONNECT_FAILED; |
328 |
} |
329 |
if (buf[1] != 0x00) { /* reply */ |
330 |
rs_log_error("proxy connection failed, reason=0x%02x", buf[1]); |
331 |
return EXIT_CONNECT_FAILED; |
332 |
} |
333 |
|
334 |
/* now read the remaining (packet size - 6) bytes */ |
335 |
switch (buf[3]) { /* address type */ |
336 |
case 0x01: skip_bytes = 4; break; /* IPv4 */ |
337 |
case 0x03: skip_bytes = buf[4] + 1; /* hostname with length field */ |
338 |
case 0x04: skip_bytes = 16; /* IPv6 */ |
339 |
default: |
340 |
rs_log_error("invalid proxy reply (address type 0x%02x)", buf[3]); |
341 |
return EXIT_CONNECT_FAILED; |
342 |
} |
343 |
ret = dcc_readx(*p_fd, buf, skip_bytes); |
344 |
if (ret != 0) |
345 |
return ret; |
346 |
|
347 |
return 0; |
348 |
} |
349 |
|
350 |
int dcc_connect_by_name(const char *host, int port, int *p_fd) |
351 |
{ |
352 |
const char *proxy; |
353 |
|
354 |
proxy = getenv("DISTCC_SOCKS_PROXY"); |
355 |
if (proxy) |
356 |
return dcc_connect_via_socks5(host, port, p_fd, proxy); |
357 |
else |
358 |
return dcc_connect_by_name_real(host, port, p_fd); |
359 |
} |