Commit | Line | Data |
---|---|---|
0301524b OS |
1 | #! /bin/sh /usr/share/dpatch/dpatch-run |
2 | ## 04_getpeername.dpatch by Nico Golde <nion@debian.org> | |
3 | ## | |
4 | ## All lines beginning with `## DP:' are a description of the patch. | |
5 | ## DP: No description. | |
6 | ||
7 | --- a/acconfig.h | |
8 | +++ b/acconfig.h | |
9 | @@ -43,6 +43,9 @@ allows socksified DNS */ | |
10 | /* Prototype and function header for close function */ | |
11 | #undef CLOSE_SIGNATURE | |
12 | ||
13 | +/* Prototype and function header for getpeername function */ | |
14 | +#undef GETPEERNAME_SIGNATURE | |
15 | + | |
16 | /* Work out which function we have for conversion from string IPs to | |
17 | numerical ones */ | |
18 | #undef HAVE_INET_ADDR | |
19 | --- a/config.h.in | |
20 | +++ b/config.h.in | |
21 | @@ -46,6 +46,9 @@ allows socksified DNS */ | |
22 | /* Prototype and function header for close function */ | |
23 | #undef CLOSE_SIGNATURE | |
24 | ||
25 | +/* Prototype and function header for close function */ | |
26 | +#undef GETPEERNAME_SIGNATURE | |
27 | + | |
28 | /* Work out which function we have for conversion from string IPs to | |
29 | numerical ones */ | |
30 | #undef HAVE_INET_ADDR | |
31 | --- a/configure | |
32 | +++ b/configure | |
33 | @@ -2225,14 +2225,60 @@ cat >> confdefs.h <<EOF | |
34 | EOF | |
35 | ||
36 | ||
37 | + | |
38 | +echo $ac_n "checking for correct getpeername prototype""... $ac_c" 1>&6 | |
39 | +echo "configure:2231: checking for correct getpeername prototype" >&5 | |
40 | +PROTO= | |
41 | +PROTO1='int __fd, const struct sockaddr * __name, int *__namelen' | |
42 | +PROTO2='int __fd, const struct sockaddr_in * __name, socklen_t *__namelen' | |
43 | +PROTO3='int __fd, struct sockaddr * __name, socklen_t *__namelen' | |
44 | +PROTO4='int __fd, const struct sockaddr * __name, socklen_t *__namelen' | |
45 | +for testproto in "${PROTO1}" \ | |
46 | + "${PROTO2}" \ | |
47 | + "${PROTO3}" \ | |
48 | + "${PROTO4}" | |
49 | +do | |
50 | + if test "${PROTO}" = ""; then | |
51 | + cat > conftest.$ac_ext <<EOF | |
52 | +#line 2244 "configure" | |
53 | +#include "confdefs.h" | |
54 | + | |
55 | + #include <sys/socket.h> | |
56 | + int getpeername($testproto); | |
57 | + | |
58 | +int main() { | |
59 | + | |
60 | +; return 0; } | |
61 | +EOF | |
62 | +if { (eval echo configure:2254: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then | |
63 | + rm -rf conftest* | |
64 | + PROTO="$testproto"; | |
65 | +else | |
66 | + echo "configure: failed program was:" >&5 | |
67 | + cat conftest.$ac_ext >&5 | |
68 | +fi | |
69 | +rm -f conftest* | |
70 | + fi | |
71 | +done | |
72 | +if test "${PROTO}" = ""; then | |
73 | + { echo "configure: error: "no match found!"" 1>&2; exit 1; } | |
74 | +fi | |
75 | +echo "$ac_t""getpeername(${PROTO})" 1>&6 | |
76 | +cat >> confdefs.h <<EOF | |
77 | +#define GETPEERNAME_SIGNATURE ${PROTO} | |
78 | +EOF | |
79 | + | |
80 | + | |
81 | + | |
82 | + | |
83 | echo $ac_n "checking for correct poll prototype""... $ac_c" 1>&6 | |
84 | -echo "configure:2230: checking for correct poll prototype" >&5 | |
85 | +echo "configure:2276: checking for correct poll prototype" >&5 | |
86 | PROTO= | |
87 | for testproto in 'struct pollfd *ufds, unsigned long nfds, int timeout' | |
88 | do | |
89 | if test "${PROTO}" = ""; then | |
90 | cat > conftest.$ac_ext <<EOF | |
91 | -#line 2236 "configure" | |
92 | +#line 2282 "configure" | |
93 | #include "confdefs.h" | |
94 | ||
95 | #include <sys/poll.h> | |
96 | @@ -2242,7 +2288,7 @@ int main() { | |
97 | ||
98 | ; return 0; } | |
99 | EOF | |
100 | -if { (eval echo configure:2246: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then | |
101 | +if { (eval echo configure:2292: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then | |
102 | rm -rf conftest* | |
103 | PROTO="$testproto"; | |
104 | else | |
105 | --- a/configure.in | |
106 | +++ b/configure.in | |
107 | @@ -309,6 +309,34 @@ fi | |
108 | AC_MSG_RESULT([close(${PROTO})]) | |
109 | AC_DEFINE_UNQUOTED(CLOSE_SIGNATURE, [${PROTO}]) | |
110 | ||
111 | + | |
112 | +dnl Find the correct getpeername prototype on this machine | |
113 | +AC_MSG_CHECKING(for correct getpeername prototype) | |
114 | +PROTO= | |
115 | +PROTO1='int __fd, const struct sockaddr * __name, int *__namelen' | |
116 | +PROTO2='int __fd, const struct sockaddr_in * __name, socklen_t *__namelen' | |
117 | +PROTO3='int __fd, struct sockaddr * __name, socklen_t *__namelen' | |
118 | +PROTO4='int __fd, const struct sockaddr * __name, socklen_t *__namelen' | |
119 | +for testproto in "${PROTO1}" \ | |
120 | + "${PROTO2}" \ | |
121 | + "${PROTO3}" \ | |
122 | + "${PROTO4}" | |
123 | +do | |
124 | + if test "${PROTO}" = ""; then | |
125 | + AC_TRY_COMPILE([ | |
126 | + #include <sys/socket.h> | |
127 | + int getpeername($testproto); | |
128 | + ],,[PROTO="$testproto";],) | |
129 | + fi | |
130 | +done | |
131 | +if test "${PROTO}" = ""; then | |
132 | + AC_MSG_ERROR("no match found!") | |
133 | +fi | |
134 | +AC_MSG_RESULT([getpeername(${PROTO})]) | |
135 | +AC_DEFINE_UNQUOTED(GETPEERNAME_SIGNATURE, [${PROTO}]) | |
136 | + | |
137 | + | |
138 | + | |
139 | dnl Find the correct poll prototype on this machine | |
140 | AC_MSG_CHECKING(for correct poll prototype) | |
141 | PROTO= | |
142 | --- a/tsocks.c | |
143 | +++ b/tsocks.c | |
144 | @@ -62,6 +62,7 @@ static int (*realconnect)(CONNECT_SIGNAT | |
145 | static int (*realselect)(SELECT_SIGNATURE); | |
146 | static int (*realpoll)(POLL_SIGNATURE); | |
147 | static int (*realclose)(CLOSE_SIGNATURE); | |
148 | +static int (*realgetpeername)(GETPEERNAME_SIGNATURE); | |
149 | static struct parsedfile *config; | |
150 | static struct connreq *requests = NULL; | |
151 | static int suid = 0; | |
152 | @@ -73,6 +74,7 @@ int connect(CONNECT_SIGNATURE); | |
153 | int select(SELECT_SIGNATURE); | |
154 | int poll(POLL_SIGNATURE); | |
155 | int close(CLOSE_SIGNATURE); | |
156 | +int getpeername(GETPEERNAME_SIGNATURE); | |
157 | #ifdef USE_SOCKS_DNS | |
158 | int res_init(void); | |
159 | #endif | |
160 | @@ -109,14 +111,15 @@ void _init(void) { | |
161 | /* most programs that are run won't use our services, so */ | |
162 | /* we do our general initialization on first call */ | |
163 | ||
164 | - /* Determine the logging level */ | |
165 | - suid = (getuid() != geteuid()); | |
166 | + /* Determine the logging level */ | |
167 | + suid = (getuid() != geteuid()); | |
168 | ||
169 | #ifndef USE_OLD_DLSYM | |
170 | realconnect = dlsym(RTLD_NEXT, "connect"); | |
171 | realselect = dlsym(RTLD_NEXT, "select"); | |
172 | realpoll = dlsym(RTLD_NEXT, "poll"); | |
173 | realclose = dlsym(RTLD_NEXT, "close"); | |
174 | + realgetpeername = dlsym(RTLD_NEXT, "getpeername"); | |
175 | #ifdef USE_SOCKS_DNS | |
176 | realresinit = dlsym(RTLD_NEXT, "res_init"); | |
177 | #endif | |
178 | @@ -125,14 +128,15 @@ void _init(void) { | |
179 | realconnect = dlsym(lib, "connect"); | |
180 | realselect = dlsym(lib, "select"); | |
181 | realpoll = dlsym(lib, "poll"); | |
182 | + realgetpeername = dlsym(lib, "getpeername"); | |
183 | #ifdef USE_SOCKS_DNS | |
184 | realresinit = dlsym(lib, "res_init"); | |
185 | #endif | |
186 | - dlclose(lib); | |
187 | + dlclose(lib); | |
188 | ||
189 | lib = dlopen(LIBC, RTLD_LAZY); | |
190 | - realclose = dlsym(lib, "close"); | |
191 | - dlclose(lib); | |
192 | + realclose = dlsym(lib, "close"); | |
193 | + dlclose(lib); | |
194 | #endif | |
195 | } | |
196 | ||
197 | @@ -350,8 +354,10 @@ int select(SELECT_SIGNATURE) { | |
198 | ||
199 | /* If we're not currently managing any requests we can just | |
200 | * leave here */ | |
201 | - if (!requests) | |
202 | + if (!requests) { | |
203 | + show_msg(MSGDEBUG, "No requests waiting, calling real select\n"); | |
204 | return(realselect(n, readfds, writefds, exceptfds, timeout)); | |
205 | + } | |
206 | ||
207 | get_environment(); | |
208 | ||
209 | @@ -705,6 +711,50 @@ int close(CLOSE_SIGNATURE) { | |
210 | return(rc); | |
211 | } | |
212 | ||
213 | +/* If we are not done setting up the connection yet, return | |
214 | + * -1 and ENOTCONN, otherwise call getpeername | |
215 | + * | |
216 | + * This is necessary since some applications, when using non-blocking connect, | |
217 | + * (like ircII) use getpeername() to find out if they are connected already. | |
218 | + * | |
219 | + * This results in races sometimes, where the client sends data to the socket | |
220 | + * before we are done with the socks connection setup. Another solution would | |
221 | + * be to intercept send(). | |
222 | + * | |
223 | + * This could be extended to actually set the peername to the peer the | |
224 | + * client application has requested, but not for now. | |
225 | + * | |
226 | + * PP, Sat, 27 Mar 2004 11:30:23 +0100 | |
227 | + */ | |
228 | +int getpeername(GETPEERNAME_SIGNATURE) { | |
229 | + struct connreq *conn; | |
230 | + int rc; | |
231 | + | |
232 | + if (realgetpeername == NULL) { | |
233 | + show_msg(MSGERR, "Unresolved symbol: getpeername\n"); | |
234 | + return(-1); | |
235 | + } | |
236 | + | |
237 | + show_msg(MSGDEBUG, "Call to getpeername for fd %d\n", __fd); | |
238 | + | |
239 | + | |
240 | + rc = realgetpeername(__fd, __name, __namelen); | |
241 | + if (rc == -1) | |
242 | + return rc; | |
243 | + | |
244 | + /* Are we handling this connect? */ | |
245 | + if ((conn = find_socks_request(__fd, 1))) { | |
246 | + /* While we are at it, we might was well try to do something useful */ | |
247 | + handle_request(conn); | |
248 | + | |
249 | + if (conn->state != DONE) { | |
250 | + errno = ENOTCONN; | |
251 | + return(-1); | |
252 | + } | |
253 | + } | |
254 | + return rc; | |
255 | +} | |
256 | + | |
257 | static struct connreq *new_socks_request(int sockid, struct sockaddr_in *connaddr, | |
258 | struct sockaddr_in *serveraddr, | |
259 | struct serverent *path) { | |
260 | @@ -854,7 +904,7 @@ static int connect_server(struct connreq | |
261 | sizeof(conn->serveraddr)); | |
262 | ||
263 | show_msg(MSGDEBUG, "Connect returned %d, errno is %d\n", rc, errno); | |
264 | - if (rc) { | |
265 | + if (rc) { | |
266 | if (errno != EINPROGRESS) { | |
267 | show_msg(MSGERR, "Error %d attempting to connect to SOCKS " | |
268 | "server (%s)\n", errno, strerror(errno)); |