1 |
mgorny 15/02/27 21:14:21 |
2 |
|
3 |
Added: distcc-3.2_rc1-socks5.patch |
4 |
Log: |
5 |
Add support for SOCKSv5 proxy, bug #537616. Needed for network-sandbox support in Portage. |
6 |
|
7 |
(Portage version: 2.2.17/cvs/Linux x86_64, signed Manifest commit with key EFB4464E!) |
8 |
|
9 |
Revision Changes Path |
10 |
1.1 sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch |
11 |
|
12 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch?rev=1.1&view=markup |
13 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/sys-devel/distcc/files/distcc-3.2_rc1-socks5.patch?rev=1.1&content-type=text/plain |
14 |
|
15 |
Index: distcc-3.2_rc1-socks5.patch |
16 |
=================================================================== |
17 |
From fdd93b1e9545b66d1b3a2a1ec24d4c8613ee43fb Mon Sep 17 00:00:00 2001 |
18 |
From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= <mgorny@g.o> |
19 |
Date: Sat, 24 Jan 2015 23:59:21 +0100 |
20 |
Subject: [PATCH] Support SOCKSv5 proxy |
21 |
|
22 |
Support using a SOCKSv5 proxy specified as DISTCC_SOCKS_PROXY. |
23 |
The variable can either a hostname, a host:port pair or an absolute path |
24 |
to a UNIX socket. When SOCKS is used, the hostname is passed to |
25 |
the proxy and therefore the name resolution is done remotely. |
26 |
--- |
27 |
src/clinet.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
28 |
1 file changed, 135 insertions(+), 2 deletions(-) |
29 |
|
30 |
diff --git a/src/clinet.c b/src/clinet.c |
31 |
index 010a884..4773d8b 100644 |
32 |
--- a/src/clinet.c |
33 |
+++ b/src/clinet.c |
34 |
@@ -31,6 +31,7 @@ |
35 |
|
36 |
#include <stdio.h> |
37 |
#include <stdlib.h> |
38 |
+#include <stddef.h> |
39 |
#include <unistd.h> |
40 |
#include <string.h> |
41 |
#include <fcntl.h> |
42 |
@@ -42,8 +43,10 @@ |
43 |
#include <sys/types.h> |
44 |
#include <sys/socket.h> |
45 |
|
46 |
+#include <arpa/inet.h> |
47 |
#include <netinet/in.h> |
48 |
#include <netinet/tcp.h> |
49 |
+#include <sys/un.h> |
50 |
|
51 |
#include <netdb.h> |
52 |
|
53 |
@@ -161,7 +164,7 @@ out_failed: |
54 |
/** |
55 |
* Open a socket to a tcp remote host with the specified port. |
56 |
**/ |
57 |
-int dcc_connect_by_name(const char *host, int port, int *p_fd) |
58 |
+static int dcc_connect_by_name_real(const char *host, int port, int *p_fd) |
59 |
{ |
60 |
struct addrinfo hints; |
61 |
struct addrinfo *res; |
62 |
@@ -201,7 +204,7 @@ int dcc_connect_by_name(const char *host, int port, int *p_fd) |
63 |
* |
64 |
* @todo Don't try for too long to connect. |
65 |
**/ |
66 |
-int dcc_connect_by_name(const char *host, int port, int *p_fd) |
67 |
+static int dcc_connect_by_name_real(const char *host, int port, int *p_fd) |
68 |
{ |
69 |
struct sockaddr_in sock_out; |
70 |
struct hostent *hp; |
71 |
@@ -224,3 +227,133 @@ int dcc_connect_by_name(const char *host, int port, int *p_fd) |
72 |
} |
73 |
|
74 |
#endif /* not ENABLE_RFC2553 */ |
75 |
+ |
76 |
+static int dcc_connect_via_socks5(const char *host, int port, int *p_fd, const char *proxy) |
77 |
+{ |
78 |
+ int ret; |
79 |
+ char *proxy_host, *proxy_it; |
80 |
+ int proxy_port; |
81 |
+ char buf[262]; |
82 |
+ int host_length; |
83 |
+ struct sockaddr_in addr_buf; |
84 |
+ int skip_bytes; |
85 |
+ |
86 |
+ host_length = strlen(host); |
87 |
+ if (host_length > 255) { |
88 |
+ rs_log_error("hostname \"%s\" too long for SOCKSv5 (over 255 chars)", host); |
89 |
+ return EXIT_CONNECT_FAILED; |
90 |
+ } |
91 |
+ |
92 |
+ if (proxy[0] == '/') { /* UNIX socket */ |
93 |
+ struct sockaddr_un unix_addr; |
94 |
+ |
95 |
+ if (strlen(proxy) >= sizeof(unix_addr.sun_path)) |
96 |
+ { |
97 |
+ rs_log_error("UNIX socket path \"%s\" too long", proxy); |
98 |
+ return EXIT_CONNECT_FAILED; |
99 |
+ } |
100 |
+ |
101 |
+ unix_addr.sun_family = AF_UNIX; |
102 |
+ strcpy(unix_addr.sun_path, proxy); |
103 |
+ |
104 |
+ ret = dcc_connect_by_addr((struct sockaddr *) &unix_addr, |
105 |
+ offsetof(struct sockaddr_un, sun_path) + strlen(proxy) + 1, |
106 |
+ p_fd); |
107 |
+ |
108 |
+ } else { /* hostname? IP address? */ |
109 |
+ proxy_host = strdup(proxy); |
110 |
+ if (proxy_host == NULL) return EXIT_OUT_OF_MEMORY; |
111 |
+ |
112 |
+ proxy_it = strrchr(proxy_host, ':'); |
113 |
+ if (proxy_it) { |
114 |
+ *(proxy_it++) = 0; |
115 |
+ proxy_port = atoi(proxy_it); |
116 |
+ |
117 |
+ if (proxy_port <= 0) { |
118 |
+ rs_log_error("invalid proxy port \"%s\"", proxy_it); |
119 |
+ free(proxy_host); |
120 |
+ return EXIT_CONNECT_FAILED; |
121 |
+ } |
122 |
+ } |
123 |
+ else |
124 |
+ proxy_port = 1080; |
125 |
+ |
126 |
+ ret = dcc_connect_by_name_real(proxy_host, proxy_port, p_fd); |
127 |
+ free(proxy_host); |
128 |
+ } |
129 |
+ |
130 |
+ if (ret != 0) |
131 |
+ return ret; |
132 |
+ |
133 |
+ /* connected to proxy, now identifier/method selection */ |
134 |
+ buf[0] = 0x05; /* SOCKSv5 */ |
135 |
+ buf[1] = 0x01; /* one method */ |
136 |
+ buf[2] = 0x00; /* NO AUTHENTICATION REQUIRED */ |
137 |
+ ret = dcc_writex(*p_fd, buf, 3); |
138 |
+ if (ret != 0) |
139 |
+ return ret; |
140 |
+ |
141 |
+ /* wait for method selection */ |
142 |
+ ret = dcc_readx(*p_fd, buf, 2); |
143 |
+ if (ret != 0) |
144 |
+ return ret; |
145 |
+ if (buf[0] != 0x05 || buf[1] != 0x00) { /* version, method */ |
146 |
+ rs_log_error("invalid proxy reply (version 0x%02x, method 0x%02x)", |
147 |
+ buf[0], buf[1]); |
148 |
+ return EXIT_CONNECT_FAILED; |
149 |
+ } |
150 |
+ |
151 |
+ /* send connect request */ |
152 |
+ buf[0] = 0x05; /* SOCKSv5 */ |
153 |
+ buf[1] = 0x01; /* CONNECT command */ |
154 |
+ buf[2] = 0x00; /* reserved */ |
155 |
+ buf[3] = 0x03; /* DOMAINNAME address type */ |
156 |
+ buf[4] = host_length; |
157 |
+ memcpy(&buf[5], host, host_length); |
158 |
+ addr_buf.sin_port = htons(port); |
159 |
+ memcpy(&buf[5 + host_length], &addr_buf.sin_port, 2); |
160 |
+ ret = dcc_writex(*p_fd, buf, 7 + host_length); |
161 |
+ if (ret != 0) |
162 |
+ return ret; |
163 |
+ |
164 |
+ /* wait for the connection */ |
165 |
+ /* read first 4 bytes of reply + 2 extra bytes we know will be there */ |
166 |
+ ret = dcc_readx(*p_fd, buf, 6); |
167 |
+ if (ret != 0) |
168 |
+ return ret; |
169 |
+ if (buf[0] != 0x05 || buf[2] != 0x00) { /* version, reserved */ |
170 |
+ rs_log_error("invalid proxy reply (version 0x%02x, reserved 0x%02x)", |
171 |
+ buf[0], buf[2]); |
172 |
+ return EXIT_CONNECT_FAILED; |
173 |
+ } |
174 |
+ if (buf[1] != 0x00) { /* reply */ |
175 |
+ rs_log_error("proxy connection failed, reason=0x%02x", buf[1]); |
176 |
+ return EXIT_CONNECT_FAILED; |
177 |
+ } |
178 |
+ |
179 |
+ /* now read the remaining (packet size - 6) bytes */ |
180 |
+ switch (buf[3]) { /* address type */ |
181 |
+ case 0x01: skip_bytes = 4; break; /* IPv4 */ |
182 |
+ case 0x03: skip_bytes = buf[4] + 1; break; /* hostname with length field */ |
183 |
+ case 0x04: skip_bytes = 16; break; /* IPv6 */ |
184 |
+ default: |
185 |
+ rs_log_error("invalid proxy reply (address type 0x%02x)", buf[3]); |
186 |
+ return EXIT_CONNECT_FAILED; |
187 |
+ } |
188 |
+ ret = dcc_readx(*p_fd, buf, skip_bytes); |
189 |
+ if (ret != 0) |
190 |
+ return ret; |
191 |
+ |
192 |
+ return 0; |
193 |
+} |
194 |
+ |
195 |
+int dcc_connect_by_name(const char *host, int port, int *p_fd) |
196 |
+{ |
197 |
+ const char *proxy; |
198 |
+ |
199 |
+ proxy = getenv("DISTCC_SOCKS_PROXY"); |
200 |
+ if (proxy) |
201 |
+ return dcc_connect_via_socks5(host, port, p_fd, proxy); |
202 |
+ else |
203 |
+ return dcc_connect_by_name_real(host, port, p_fd); |
204 |
+} |
205 |
-- |
206 |
2.3.0 |