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) {