Package: tsocks
Version: 1.8beta5-9.2
Severity: normal
Tags: upstream patch

Dear Maintainer,

Found that I could not use 'user mode' of qemu with tsocks (although I could
use proxychains) and so did some digging; proxychains does not support
specifying subnets to bypass a SOCKS server to so does not suit my needs.

Turns out qemu uses a non-blocking connect, and then always starts off
using the socket immediately with sendto("");sendto("....").  As tsocks has
not yet sent the SOCKS request header, my 'ssh -D 1080 ...' gets very annoyed
very quickly :)

----
[pid 23463] connect(46, {sa_family=AF_INET, sin_port=htons(1080), 
sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in 
progress)
[pid 23463] sendto(46, "", 0, 0, NULL, 0) = 0
[pid 23463] sendto(46, "GET /ncsi.txt HTTP/1.1\r\nConnecti"..., 97, 0, NULL, 0) 
= 97
[pid 23463] recvfrom(46, "", 8760, 0, NULL, NULL) = 0
[pid 23463] shutdown(46, 0 /* receive */) = 0
[pid 23463] shutdown(46, 1 /* send */)  = 0
----

The fix is to force the socket to connect() blocking (turns out peeking in
the proxychains source, they do just this).

The attached patch takes the ifdef 0'd lines at the end and splices them
into the connect_server() where I suspect they used to live a while back.

Now, 'TSOCKS_CONNECT_BLOCKING=1 tsocks qemu -net user ...' works great! :)
----
[pid 23488] connect(47, {sa_family=AF_INET, sin_port=htons(1080), 
sin_addr=inet_addr("127.0.0.1")}, 16) = 0
[pid 23488] sendto(47, "\5\2\0\2", 4, 0, NULL, 0) = 4
[pid 23488] recvfrom(47, "\5\0", 2, 0, NULL, NULL) = 2
[pid 23488] sendto(47, "\5\1\0\1\27?cj\0P", 10, 0, NULL, 0) = 10
[pid 23488] recvfrom(47, 0x7fd4c8897668, 10, 0, 0, 0) = -1 EAGAIN (Resource 
temporarily unavailable)
[pid 23488] sendto(47, "", 0, 0, NULL, 0) = 0
[pid 23488] sendto(47, "GET /ncsi.txt HTTP/1.1\r\nConnecti"..., 97, 0, NULL, 0) 
= 97
[pid 23488] recvfrom(47, "\5\0\0\1\0\0\0\0\0\0", 8760, 0, NULL, NULL) = 10
[pid 23488] shutdown(47, 1 /* send */)  = 0
[pid 23488] recvfrom(47, "HTTP/1.1 200 OK\r\nContent-Length:"..., 8750, 0, 
NULL, NULL) = 179
[pid 23488] recvfrom(47, "", 7300, 0, NULL, NULL) = 0
[pid 23488] shutdown(47, 0 /* receive */) = -1 ENOTCONN (Transport endpoint is 
not connected)
----

-- System Information:
Debian Release: 7.6
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.14-0.bpo.1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages tsocks depends on:
ii  libc6  2.13-38+deb7u3

tsocks recommends no packages.

tsocks suggests no packages.

-- Configuration Files:
/etc/tsocks.conf changed [not included]

-- no debconf information
--- tsocks.c.orig	2014-08-24 15:55:34.497950041 +0100
+++ tsocks.c	2014-08-24 16:19:19.905895517 +0100
@@ -67,6 +67,8 @@
 static int suid = 0;
 static char *conffile = NULL;
 
+static int connect_blocking = 0;
+
 /* Exported Function Prototypes */
 void _init(void);
 int connect(CONNECT_SIGNATURE);
@@ -156,6 +158,9 @@
    set_log_options(loglevel, logfile, 1);
 #endif
 
+   if ((env = getenv("TSOCKS_CONNECT_BLOCKING")))
+      connect_blocking = 1;
+
    done = 1;
 
    return(0);
@@ -845,14 +850,32 @@
 
 static int connect_server(struct connreq *conn) {
    int rc;
+   int sockflags;
 
 	/* Connect this socket to the socks server */
    show_msg(MSGDEBUG, "Connecting to %s port %d\n", 
             inet_ntoa(conn->serveraddr.sin_addr), ntohs(conn->serveraddr.sin_port));
 
+   /* If we are forcing the socket to connect() blocking...  */
+   /* Get the flags of the socket, (incase its non blocking) */
+   if (connect_blocking && (sockflags = fcntl(conn->sockid, F_GETFL)) == -1) {
+      sockflags = 0;
+   }
+
+   /* If the flags show the socket as blocking, set it to   */
+   /* blocking for our connection to the socks server       */
+   if (connect_blocking && (sockflags & O_NONBLOCK) != 0) {
+      fcntl(conn->sockid, F_SETFL, sockflags & (~(O_NONBLOCK)));
+   }
+
    rc = realconnect(conn->sockid, (CONNECT_SOCKARG) &(conn->serveraddr),
                     sizeof(conn->serveraddr));
 
+   /* If the socket was in non blocking mode, restore that */
+   if (connect_blocking && (sockflags & O_NONBLOCK) != 0) {
+      fcntl(conn->sockid, F_SETFL, sockflags);
+   }
+
    show_msg(MSGDEBUG, "Connect returned %d, errno is %d\n", rc, errno); 
 	if (rc) {
       if (errno != EINPROGRESS) {

Reply via email to