269 lines
8.0 KiB
Diff
269 lines
8.0 KiB
Diff
#! /bin/sh /usr/share/dpatch/dpatch-run
|
|
## 04_getpeername.dpatch by Nico Golde <nion@debian.org>
|
|
##
|
|
## All lines beginning with `## DP:' are a description of the patch.
|
|
## DP: No description.
|
|
|
|
--- a/acconfig.h
|
|
+++ b/acconfig.h
|
|
@@ -43,6 +43,9 @@ allows socksified DNS */
|
|
/* Prototype and function header for close function */
|
|
#undef CLOSE_SIGNATURE
|
|
|
|
+/* Prototype and function header for getpeername function */
|
|
+#undef GETPEERNAME_SIGNATURE
|
|
+
|
|
/* Work out which function we have for conversion from string IPs to
|
|
numerical ones */
|
|
#undef HAVE_INET_ADDR
|
|
--- a/config.h.in
|
|
+++ b/config.h.in
|
|
@@ -46,6 +46,9 @@ allows socksified DNS */
|
|
/* Prototype and function header for close function */
|
|
#undef CLOSE_SIGNATURE
|
|
|
|
+/* Prototype and function header for close function */
|
|
+#undef GETPEERNAME_SIGNATURE
|
|
+
|
|
/* Work out which function we have for conversion from string IPs to
|
|
numerical ones */
|
|
#undef HAVE_INET_ADDR
|
|
--- a/configure
|
|
+++ b/configure
|
|
@@ -2225,14 +2225,60 @@ cat >> confdefs.h <<EOF
|
|
EOF
|
|
|
|
|
|
+
|
|
+echo $ac_n "checking for correct getpeername prototype""... $ac_c" 1>&6
|
|
+echo "configure:2231: checking for correct getpeername prototype" >&5
|
|
+PROTO=
|
|
+PROTO1='int __fd, const struct sockaddr * __name, int *__namelen'
|
|
+PROTO2='int __fd, const struct sockaddr_in * __name, socklen_t *__namelen'
|
|
+PROTO3='int __fd, struct sockaddr * __name, socklen_t *__namelen'
|
|
+PROTO4='int __fd, const struct sockaddr * __name, socklen_t *__namelen'
|
|
+for testproto in "${PROTO1}" \
|
|
+ "${PROTO2}" \
|
|
+ "${PROTO3}" \
|
|
+ "${PROTO4}"
|
|
+do
|
|
+ if test "${PROTO}" = ""; then
|
|
+ cat > conftest.$ac_ext <<EOF
|
|
+#line 2244 "configure"
|
|
+#include "confdefs.h"
|
|
+
|
|
+ #include <sys/socket.h>
|
|
+ int getpeername($testproto);
|
|
+
|
|
+int main() {
|
|
+
|
|
+; return 0; }
|
|
+EOF
|
|
+if { (eval echo configure:2254: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
|
+ rm -rf conftest*
|
|
+ PROTO="$testproto";
|
|
+else
|
|
+ echo "configure: failed program was:" >&5
|
|
+ cat conftest.$ac_ext >&5
|
|
+fi
|
|
+rm -f conftest*
|
|
+ fi
|
|
+done
|
|
+if test "${PROTO}" = ""; then
|
|
+ { echo "configure: error: "no match found!"" 1>&2; exit 1; }
|
|
+fi
|
|
+echo "$ac_t""getpeername(${PROTO})" 1>&6
|
|
+cat >> confdefs.h <<EOF
|
|
+#define GETPEERNAME_SIGNATURE ${PROTO}
|
|
+EOF
|
|
+
|
|
+
|
|
+
|
|
+
|
|
echo $ac_n "checking for correct poll prototype""... $ac_c" 1>&6
|
|
-echo "configure:2230: checking for correct poll prototype" >&5
|
|
+echo "configure:2276: checking for correct poll prototype" >&5
|
|
PROTO=
|
|
for testproto in 'struct pollfd *ufds, unsigned long nfds, int timeout'
|
|
do
|
|
if test "${PROTO}" = ""; then
|
|
cat > conftest.$ac_ext <<EOF
|
|
-#line 2236 "configure"
|
|
+#line 2282 "configure"
|
|
#include "confdefs.h"
|
|
|
|
#include <sys/poll.h>
|
|
@@ -2242,7 +2288,7 @@ int main() {
|
|
|
|
; return 0; }
|
|
EOF
|
|
-if { (eval echo configure:2246: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
|
+if { (eval echo configure:2292: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
|
|
rm -rf conftest*
|
|
PROTO="$testproto";
|
|
else
|
|
--- a/configure.in
|
|
+++ b/configure.in
|
|
@@ -309,6 +309,34 @@ fi
|
|
AC_MSG_RESULT([close(${PROTO})])
|
|
AC_DEFINE_UNQUOTED(CLOSE_SIGNATURE, [${PROTO}])
|
|
|
|
+
|
|
+dnl Find the correct getpeername prototype on this machine
|
|
+AC_MSG_CHECKING(for correct getpeername prototype)
|
|
+PROTO=
|
|
+PROTO1='int __fd, const struct sockaddr * __name, int *__namelen'
|
|
+PROTO2='int __fd, const struct sockaddr_in * __name, socklen_t *__namelen'
|
|
+PROTO3='int __fd, struct sockaddr * __name, socklen_t *__namelen'
|
|
+PROTO4='int __fd, const struct sockaddr * __name, socklen_t *__namelen'
|
|
+for testproto in "${PROTO1}" \
|
|
+ "${PROTO2}" \
|
|
+ "${PROTO3}" \
|
|
+ "${PROTO4}"
|
|
+do
|
|
+ if test "${PROTO}" = ""; then
|
|
+ AC_TRY_COMPILE([
|
|
+ #include <sys/socket.h>
|
|
+ int getpeername($testproto);
|
|
+ ],,[PROTO="$testproto";],)
|
|
+ fi
|
|
+done
|
|
+if test "${PROTO}" = ""; then
|
|
+ AC_MSG_ERROR("no match found!")
|
|
+fi
|
|
+AC_MSG_RESULT([getpeername(${PROTO})])
|
|
+AC_DEFINE_UNQUOTED(GETPEERNAME_SIGNATURE, [${PROTO}])
|
|
+
|
|
+
|
|
+
|
|
dnl Find the correct poll prototype on this machine
|
|
AC_MSG_CHECKING(for correct poll prototype)
|
|
PROTO=
|
|
--- a/tsocks.c
|
|
+++ b/tsocks.c
|
|
@@ -62,6 +62,7 @@ static int (*realconnect)(CONNECT_SIGNAT
|
|
static int (*realselect)(SELECT_SIGNATURE);
|
|
static int (*realpoll)(POLL_SIGNATURE);
|
|
static int (*realclose)(CLOSE_SIGNATURE);
|
|
+static int (*realgetpeername)(GETPEERNAME_SIGNATURE);
|
|
static struct parsedfile *config;
|
|
static struct connreq *requests = NULL;
|
|
static int suid = 0;
|
|
@@ -73,6 +74,7 @@ int connect(CONNECT_SIGNATURE);
|
|
int select(SELECT_SIGNATURE);
|
|
int poll(POLL_SIGNATURE);
|
|
int close(CLOSE_SIGNATURE);
|
|
+int getpeername(GETPEERNAME_SIGNATURE);
|
|
#ifdef USE_SOCKS_DNS
|
|
int res_init(void);
|
|
#endif
|
|
@@ -109,14 +111,15 @@ void _init(void) {
|
|
/* most programs that are run won't use our services, so */
|
|
/* we do our general initialization on first call */
|
|
|
|
- /* Determine the logging level */
|
|
- suid = (getuid() != geteuid());
|
|
+ /* Determine the logging level */
|
|
+ suid = (getuid() != geteuid());
|
|
|
|
#ifndef USE_OLD_DLSYM
|
|
realconnect = dlsym(RTLD_NEXT, "connect");
|
|
realselect = dlsym(RTLD_NEXT, "select");
|
|
realpoll = dlsym(RTLD_NEXT, "poll");
|
|
realclose = dlsym(RTLD_NEXT, "close");
|
|
+ realgetpeername = dlsym(RTLD_NEXT, "getpeername");
|
|
#ifdef USE_SOCKS_DNS
|
|
realresinit = dlsym(RTLD_NEXT, "res_init");
|
|
#endif
|
|
@@ -125,14 +128,15 @@ void _init(void) {
|
|
realconnect = dlsym(lib, "connect");
|
|
realselect = dlsym(lib, "select");
|
|
realpoll = dlsym(lib, "poll");
|
|
+ realgetpeername = dlsym(lib, "getpeername");
|
|
#ifdef USE_SOCKS_DNS
|
|
realresinit = dlsym(lib, "res_init");
|
|
#endif
|
|
- dlclose(lib);
|
|
+ dlclose(lib);
|
|
|
|
lib = dlopen(LIBC, RTLD_LAZY);
|
|
- realclose = dlsym(lib, "close");
|
|
- dlclose(lib);
|
|
+ realclose = dlsym(lib, "close");
|
|
+ dlclose(lib);
|
|
#endif
|
|
}
|
|
|
|
@@ -350,8 +354,10 @@ int select(SELECT_SIGNATURE) {
|
|
|
|
/* If we're not currently managing any requests we can just
|
|
* leave here */
|
|
- if (!requests)
|
|
+ if (!requests) {
|
|
+ show_msg(MSGDEBUG, "No requests waiting, calling real select\n");
|
|
return(realselect(n, readfds, writefds, exceptfds, timeout));
|
|
+ }
|
|
|
|
get_environment();
|
|
|
|
@@ -705,6 +711,50 @@ int close(CLOSE_SIGNATURE) {
|
|
return(rc);
|
|
}
|
|
|
|
+/* If we are not done setting up the connection yet, return
|
|
+ * -1 and ENOTCONN, otherwise call getpeername
|
|
+ *
|
|
+ * This is necessary since some applications, when using non-blocking connect,
|
|
+ * (like ircII) use getpeername() to find out if they are connected already.
|
|
+ *
|
|
+ * This results in races sometimes, where the client sends data to the socket
|
|
+ * before we are done with the socks connection setup. Another solution would
|
|
+ * be to intercept send().
|
|
+ *
|
|
+ * This could be extended to actually set the peername to the peer the
|
|
+ * client application has requested, but not for now.
|
|
+ *
|
|
+ * PP, Sat, 27 Mar 2004 11:30:23 +0100
|
|
+ */
|
|
+int getpeername(GETPEERNAME_SIGNATURE) {
|
|
+ struct connreq *conn;
|
|
+ int rc;
|
|
+
|
|
+ if (realgetpeername == NULL) {
|
|
+ show_msg(MSGERR, "Unresolved symbol: getpeername\n");
|
|
+ return(-1);
|
|
+ }
|
|
+
|
|
+ show_msg(MSGDEBUG, "Call to getpeername for fd %d\n", __fd);
|
|
+
|
|
+
|
|
+ rc = realgetpeername(__fd, __name, __namelen);
|
|
+ if (rc == -1)
|
|
+ return rc;
|
|
+
|
|
+ /* Are we handling this connect? */
|
|
+ if ((conn = find_socks_request(__fd, 1))) {
|
|
+ /* While we are at it, we might was well try to do something useful */
|
|
+ handle_request(conn);
|
|
+
|
|
+ if (conn->state != DONE) {
|
|
+ errno = ENOTCONN;
|
|
+ return(-1);
|
|
+ }
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
static struct connreq *new_socks_request(int sockid, struct sockaddr_in *connaddr,
|
|
struct sockaddr_in *serveraddr,
|
|
struct serverent *path) {
|
|
@@ -854,7 +904,7 @@ static int connect_server(struct connreq
|
|
sizeof(conn->serveraddr));
|
|
|
|
show_msg(MSGDEBUG, "Connect returned %d, errno is %d\n", rc, errno);
|
|
- if (rc) {
|
|
+ if (rc) {
|
|
if (errno != EINPROGRESS) {
|
|
show_msg(MSGERR, "Error %d attempting to connect to SOCKS "
|
|
"server (%s)\n", errno, strerror(errno));
|