1 #! /bin/sh /usr/share/dpatch/dpatch-run
2 ## 04_getpeername.dpatch by Nico Golde <nion@debian.org>
4 ## All lines beginning with `## DP:' are a description of the patch.
9 @@ -43,6 +43,9 @@ allows socksified DNS */
10 /* Prototype and function header for close function */
11 #undef CLOSE_SIGNATURE
13 +/* Prototype and function header for getpeername function */
14 +#undef GETPEERNAME_SIGNATURE
16 /* Work out which function we have for conversion from string IPs to
21 @@ -46,6 +46,9 @@ allows socksified DNS */
22 /* Prototype and function header for close function */
23 #undef CLOSE_SIGNATURE
25 +/* Prototype and function header for close function */
26 +#undef GETPEERNAME_SIGNATURE
28 /* Work out which function we have for conversion from string IPs to
33 @@ -2225,14 +2225,60 @@ cat >> confdefs.h <<EOF
38 +echo $ac_n "checking for correct getpeername prototype""... $ac_c" 1>&6
39 +echo "configure:2231: checking for correct getpeername prototype" >&5
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}" \
50 + if test "${PROTO}" = ""; then
51 + cat > conftest.$ac_ext <<EOF
52 +#line 2244 "configure"
53 +#include "confdefs.h"
55 + #include <sys/socket.h>
56 + int getpeername($testproto);
62 +if { (eval echo configure:2254: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
66 + echo "configure: failed program was:" >&5
67 + cat conftest.$ac_ext >&5
72 +if test "${PROTO}" = ""; then
73 + { echo "configure: error: "no match found!"" 1>&2; exit 1; }
75 +echo "$ac_t""getpeername(${PROTO})" 1>&6
76 +cat >> confdefs.h <<EOF
77 +#define GETPEERNAME_SIGNATURE ${PROTO}
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
87 for testproto in 'struct pollfd *ufds, unsigned long nfds, int timeout'
89 if test "${PROTO}" = ""; then
90 cat > conftest.$ac_ext <<EOF
91 -#line 2236 "configure"
92 +#line 2282 "configure"
96 @@ -2242,7 +2288,7 @@ int main() {
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
107 @@ -309,6 +309,34 @@ fi
108 AC_MSG_RESULT([close(${PROTO})])
109 AC_DEFINE_UNQUOTED(CLOSE_SIGNATURE, [${PROTO}])
112 +dnl Find the correct getpeername prototype on this machine
113 +AC_MSG_CHECKING(for correct getpeername prototype)
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}" \
124 + if test "${PROTO}" = ""; then
126 + #include <sys/socket.h>
127 + int getpeername($testproto);
128 + ],,[PROTO="$testproto";],)
131 +if test "${PROTO}" = ""; then
132 + AC_MSG_ERROR("no match found!")
134 +AC_MSG_RESULT([getpeername(${PROTO})])
135 +AC_DEFINE_UNQUOTED(GETPEERNAME_SIGNATURE, [${PROTO}])
139 dnl Find the correct poll prototype on this machine
140 AC_MSG_CHECKING(for correct poll prototype)
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;
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);
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 */
164 - /* Determine the logging level */
165 - suid = (getuid() != geteuid());
166 + /* Determine the logging level */
167 + suid = (getuid() != geteuid());
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");
176 realresinit = dlsym(RTLD_NEXT, "res_init");
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");
184 realresinit = dlsym(lib, "res_init");
189 lib = dlopen(LIBC, RTLD_LAZY);
190 - realclose = dlsym(lib, "close");
192 + realclose = dlsym(lib, "close");
197 @@ -350,8 +354,10 @@ int select(SELECT_SIGNATURE) {
199 /* If we're not currently managing any requests we can just
203 + show_msg(MSGDEBUG, "No requests waiting, calling real select\n");
204 return(realselect(n, readfds, writefds, exceptfds, timeout));
209 @@ -705,6 +711,50 @@ int close(CLOSE_SIGNATURE) {
213 +/* If we are not done setting up the connection yet, return
214 + * -1 and ENOTCONN, otherwise call getpeername
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.
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().
223 + * This could be extended to actually set the peername to the peer the
224 + * client application has requested, but not for now.
226 + * PP, Sat, 27 Mar 2004 11:30:23 +0100
228 +int getpeername(GETPEERNAME_SIGNATURE) {
229 + struct connreq *conn;
232 + if (realgetpeername == NULL) {
233 + show_msg(MSGERR, "Unresolved symbol: getpeername\n");
237 + show_msg(MSGDEBUG, "Call to getpeername for fd %d\n", __fd);
240 + rc = realgetpeername(__fd, __name, __namelen);
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);
249 + if (conn->state != DONE) {
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));
263 show_msg(MSGDEBUG, "Connect returned %d, errno is %d\n", rc, errno);
266 if (errno != EINPROGRESS) {
267 show_msg(MSGERR, "Error %d attempting to connect to SOCKS "
268 "server (%s)\n", errno, strerror(errno));