Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 537616 | Differences between
and this patch

Collapse All | Expand All

(-)a/src/clinet.c (-3 / +135 lines)
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; break; /* hostname with length field */
338
		case 0x04: skip_bytes = 16; break; /* 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
}

Return to bug 537616