[or-cvs] [torsocks/master] Split SOCKS functions into separate file

hoganrobert at torproject.org hoganrobert at torproject.org
Sat Feb 19 17:39:33 UTC 2011


commit 91046642c2efa6bed622f524b95919563d2a40a5
Author: Robert Hogan <robert at roberthogan.net>
Date:   Sat Feb 19 13:20:21 2011 +0000

    Split SOCKS functions into separate file
---
 src/Makefile.am |    4 +-
 src/socks.c     |  629 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/socks.h     |  116 ++++++++++
 src/torsocks.c  |  572 +--------------------------------------------------
 src/torsocks.h  |  104 ---------
 5 files changed, 748 insertions(+), 677 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index cce43f2..cb69714 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,11 +25,11 @@ torsocksconfmanpage_DATA = torsocks.conf.5
 
 # Install main library to $(prefix)/lib/tor (must match torsocks.in)
 lib_LTLIBRARIES = libtorsocks.la
-libtorsocks_la_SOURCES = torsocks.c common.c parser.c dead_pool.c darwin_warts.c
+libtorsocks_la_SOURCES = torsocks.c common.c parser.c dead_pool.c darwin_warts.c socks.c
 libtorsocks_la_LDFLAGS = -version-info 1:0:0
 #libtorsocks_la_CFLAGS = -nostartfiles
 
-DISTCLEANFILES=parser.lo dead_pool.lo common.lo libtorsocks.lo tsocks.lo \
+DISTCLEANFILES=parser.lo dead_pool.lo common.lo libtorsocks.lo torsocks.lo darwin_warts.lo socks.lo\
 			   config.cache config.log config.h Makefile \
 			   aclocal.m4 config.status usewithtor torsocks \
 			   autom4te.cache .libs .deps 
diff --git a/src/socks.c b/src/socks.c
new file mode 100644
index 0000000..37b97f5
--- /dev/null
+++ b/src/socks.c
@@ -0,0 +1,629 @@
+/***************************************************************************
+ *                                                                         *
+ *   Copyright (C) 2000-2008 Shaun Clowes <delius at progsoc.org>             *
+ *   Copyright (C) 2008-2011 Robert Hogan <robert at roberthogan.net>         *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+/* PreProcessor Defines */
+#include <config.h>
+
+/*Defining _NONSTD_SOURCE causes library and kernel calls to behave as closely
+to Mac OS X 10.3's library and kernel calls as possible.*/
+#if defined(__APPLE__) || defined(__darwin__)
+/*
+From 'man compat' in OSX:
+64-BIT COMPILATION
+     When compiling for 64-bit architectures, the __LP64__ macro will be defined to 1, and UNIX conformance
+     is always on (the _DARWIN_FEATURE_UNIX_CONFORMANCE macro will also be defined to the SUS conformance
+     level).  Defining _NONSTD_SOURCE will cause a compilation error.
+*/
+#if !defined(__LP64__)
+#define _NONSTD_SOURCE 1
+#endif
+#include <sys/socket.h>
+#endif
+
+
+#ifdef USE_GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+/* Header Files */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <string.h>
+#include <strings.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <pwd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <common.h>
+#include <pthread.h>
+#include <stdarg.h>
+#if !defined(__APPLE__) && !defined(__darwin__)
+#include <sys/socket.h>
+#endif
+#include <resolv.h>
+
+#include "parser.h"
+#include "socks.h"
+#include "dead_pool.h"
+
+static int connect_server(struct connreq *conn);
+static int send_socks_request(struct connreq *conn);
+static int send_socksv4_request(struct connreq *conn);
+static int send_socksv5_method(struct connreq *conn);
+static int send_socksv5_connect(struct connreq *conn);
+static int send_buffer(struct connreq *conn);
+static int recv_buffer(struct connreq *conn);
+static int read_socksv5_method(struct connreq *conn);
+static int read_socksv4_req(struct connreq *conn);
+static int read_socksv5_connect(struct connreq *conn);
+static int read_socksv5_auth(struct connreq *conn);
+static int send_socksv4a_request(struct connreq *conn, const char *onion_host);
+
+struct connreq *new_socks_request(int sockid, struct sockaddr_in *connaddr,
+                                         struct sockaddr_in *serveraddr,
+                                         struct serverent *path)
+{
+    struct connreq *newconn;
+
+    if ((newconn = malloc(sizeof(*newconn))) == NULL) {
+        /* Could not malloc, we're stuffed */
+        show_msg(MSGERR, "Could not allocate memory for new socks request\n");
+        return(NULL);
+    }
+
+    /* Add this connection to be proxied to the list */
+    memset(newconn, 0x0, sizeof(*newconn));
+    newconn->sockid = sockid;
+    newconn->state = UNSTARTED;
+    newconn->path = path;
+    memcpy(&(newconn->connaddr), connaddr, sizeof(newconn->connaddr));
+    memcpy(&(newconn->serveraddr), serveraddr, sizeof(newconn->serveraddr));
+    newconn->next = requests;
+    requests = newconn;
+
+    return(newconn);
+}
+
+void kill_socks_request(struct connreq *conn)
+{
+    struct connreq *connnode;
+
+    if (requests == conn)
+        requests = conn->next;
+    else {
+        for (connnode = requests; connnode != NULL; connnode = connnode->next) {
+            if (connnode->next == conn) {
+                connnode->next = conn->next;
+                break;
+            }
+        }
+    }
+
+    free(conn);
+}
+
+struct connreq *find_socks_request(int sockid, int includefinished)
+{
+    struct connreq *connnode;
+
+    for (connnode = requests; connnode != NULL; connnode = connnode->next) {
+        if (connnode->sockid == sockid) {
+            if (((connnode->state == FAILED) || (connnode->state == DONE)) &&
+                !includefinished)
+                break;
+            else
+                return(connnode);
+        }
+    }
+
+    return(NULL);
+}
+
+int handle_request(struct connreq *conn)
+{
+    int rc = 0;
+    int i = 0;
+
+    show_msg(MSGDEBUG, "Beginning handle loop for socket %d\n", conn->sockid);
+
+    while ((rc == 0) &&
+            (conn->state != FAILED) &&
+            (conn->state != DONE) &&
+            (i++ < 20)) {
+        show_msg(MSGDEBUG, "In request handle loop for socket %d, "
+                           "current state of request is %d\n", conn->sockid,
+                           conn->state);
+        switch(conn->state) {
+          case UNSTARTED:
+          case CONNECTING:
+              rc = connect_server(conn);
+              break;
+          case CONNECTED:
+              rc = send_socks_request(conn);
+              break;
+          case SENDING:
+              rc = send_buffer(conn);
+              break;
+          case RECEIVING:
+              rc = recv_buffer(conn);
+              break;
+          case SENTV4REQ:
+              show_msg(MSGDEBUG, "Receiving reply to SOCKS V4 connect request\n");
+              conn->datalen = sizeof(struct sockrep);
+              conn->datadone = 0;
+              conn->state = RECEIVING;
+              conn->nextstate = GOTV4REQ;
+              break;
+          case GOTV4REQ:
+              rc = read_socksv4_req(conn);
+              break;
+          case SENTV5METHOD:
+              show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 method negotiation\n");
+              conn->datalen = 2;
+              conn->datadone = 0;
+              conn->state = RECEIVING;
+              conn->nextstate = GOTV5METHOD;
+              break;
+          case GOTV5METHOD:
+              rc = read_socksv5_method(conn);
+              break;
+          case SENTV5AUTH:
+              show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 authentication negotiation\n");
+              conn->datalen = 2;
+              conn->datadone = 0;
+              conn->state = RECEIVING;
+              conn->nextstate = GOTV5AUTH;
+              break;
+          case GOTV5AUTH:
+              rc = read_socksv5_auth(conn);
+              break;
+          case SENTV5CONNECT:
+              show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 connect request\n");
+              conn->datalen = 10;
+              conn->datadone = 0;
+              conn->state = RECEIVING;
+              conn->nextstate = GOTV5CONNECT;
+              break;
+          case GOTV5CONNECT:
+              rc = read_socksv5_connect(conn);
+              break;
+        }
+        conn->err = errno;
+    }
+
+    if (i == 20)
+        show_msg(MSGERR, "Ooops, state loop while handling request %d\n",
+                conn->sockid);
+
+    show_msg(MSGDEBUG, "Handle loop completed for socket %d in state %d, "
+                       "returning %d\n", conn->sockid, conn->state, rc);
+    return(rc);
+}
+
+static int connect_server(struct connreq *conn)
+{
+    int rc;
+
+    /* 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));
+
+    rc = realconnect(conn->sockid, (CONNECT_SOCKARG) &(conn->serveraddr),
+                     sizeof(conn->serveraddr));
+
+    show_msg(MSGDEBUG, "Connect returned %d, errno is %d\n", rc, errno);
+    if (rc && errno == EISCONN) {
+        rc = 0;
+        show_msg(MSGDEBUG, "Socket %d already connected to SOCKS server\n", conn->sockid);
+        conn->state = CONNECTED;
+    } else if (rc) {
+        if (errno != EINPROGRESS) {
+            show_msg(MSGERR, "Error %d attempting to connect to SOCKS "
+                             "server (%s)\n", errno, strerror(errno));
+            conn->state = FAILED;
+        } else {
+            show_msg(MSGDEBUG, "Connection in progress\n");
+            conn->state = CONNECTING;
+        }
+    } else {
+        show_msg(MSGDEBUG, "Socket %d connected to SOCKS server\n", conn->sockid);
+        conn->state = CONNECTED;
+    }
+
+    return((rc ? errno : 0));
+}
+
+static int send_socks_request(struct connreq *conn)
+{
+    int rc = 0;
+
+    if (conn->path->type == 4) {
+        char *name = get_pool_entry(pool, &(conn->connaddr.sin_addr));
+        if(name != NULL)
+            rc = send_socksv4a_request(conn,name);
+        else
+            rc = send_socksv4_request(conn);
+    } else
+        rc = send_socksv5_method(conn);
+    return(rc);
+}
+
+static int send_socksv4a_request(struct connreq *conn,const char *onion_host)
+{
+    struct passwd *user;
+    struct sockreq *thisreq;
+    int endOfUser;
+    /* Determine the current username */
+    user = getpwuid(getuid());
+
+    thisreq = (struct sockreq *) conn->buffer;
+    endOfUser=sizeof(struct sockreq) +
+    (user == NULL ? 0 : strlen(user->pw_name)) + 1;
+
+    /* Check the buffer has enough space for the request  */
+    /* and the user name                                  */
+    conn->datalen = endOfUser+
+                    (onion_host == NULL ? 0 : strlen(onion_host)) + 1;
+    if (sizeof(conn->buffer) < conn->datalen) {
+        show_msg(MSGERR, "The SOCKS username is too long");
+        conn->state = FAILED;
+        return(ECONNREFUSED);
+    }
+
+    /* Create the request */
+    thisreq->version = 4;
+    thisreq->command = 1;
+    thisreq->dstport = conn->connaddr.sin_port;
+    thisreq->dstip   = htonl(1);
+
+    /* Copy the username */
+    strcpy((char *) thisreq + sizeof(struct sockreq),
+          (user == NULL ? "" : user->pw_name));
+
+    /* Copy the onion host */
+    strcpy((char *) thisreq + endOfUser,
+          (onion_host == NULL ? "" : onion_host));
+
+    conn->datadone = 0;
+    conn->state = SENDING;
+    conn->nextstate = SENTV4REQ;
+
+    return(0);
+}
+
+static int send_socksv4_request(struct connreq *conn)
+{
+    struct passwd *user;
+    struct sockreq *thisreq;
+
+    /* Determine the current username */
+    user = getpwuid(getuid());
+
+    thisreq = (struct sockreq *) conn->buffer;
+
+    /* Check the buffer has enough space for the request  */
+    /* and the user name                                  */
+    conn->datalen = sizeof(struct sockreq) +
+                    (user == NULL ? 0 : strlen(user->pw_name)) + 1;
+    if (sizeof(conn->buffer) < conn->datalen) {
+        show_msg(MSGERR, "The SOCKS username is too long");
+        conn->state = FAILED;
+        return(ECONNREFUSED);
+    }
+
+    /* Create the request */
+    thisreq->version = 4;
+    thisreq->command = 1;
+    thisreq->dstport = conn->connaddr.sin_port;
+    thisreq->dstip   = conn->connaddr.sin_addr.s_addr;
+
+    /* Copy the username */
+    strcpy((char *) thisreq + sizeof(struct sockreq),
+            (user == NULL ? "" : user->pw_name));
+
+    conn->datadone = 0;
+    conn->state = SENDING;
+    conn->nextstate = SENTV4REQ;
+
+    return(0);
+}
+
+static int send_socksv5_method(struct connreq *conn)
+{
+    char verstring[] = { 0x05,    /* Version 5 SOCKS */
+                          0x02,    /* No. Methods     */
+                          0x00,    /* Null Auth       */
+                          0x02 };  /* User/Pass Auth  */
+
+    show_msg(MSGDEBUG, "Constructing V5 method negotiation\n");
+    conn->state = SENDING;
+    conn->nextstate = SENTV5METHOD;
+    memcpy(conn->buffer, verstring, sizeof(verstring));
+    conn->datalen = sizeof(verstring);
+    conn->datadone = 0;
+
+    return(0);
+}
+
+static int send_socksv5_connect(struct connreq *conn)
+{
+    int namelen = 0;
+    char *name = NULL;
+    char constring[] = { 0x05,    /* Version 5 SOCKS */
+                          0x01,    /* Connect request */
+                          0x00,    /* Reserved        */
+                          0x01 };  /* IP Version 4    */
+
+    show_msg(MSGDEBUG, "Constructing V5 connect request\n");
+    conn->datadone = 0;
+    conn->state = SENDING;
+    conn->nextstate = SENTV5CONNECT;
+    memcpy(conn->buffer, constring, sizeof(constring));
+    conn->datalen = sizeof(constring);
+
+    show_msg(MSGDEBUG, "send_socksv5_connect: looking for: %s\n",
+              inet_ntoa(conn->connaddr.sin_addr));
+
+    name = get_pool_entry(pool, &(conn->connaddr.sin_addr));
+    if(name != NULL) {
+        namelen = strlen(name);
+        if(namelen > 255)  /* "Can't happen" */
+            name = NULL;
+    }
+    if(name != NULL) {
+        show_msg(MSGDEBUG, "send_socksv5_connect: found it!\n");
+        /* Substitute the domain name from the pool into the SOCKS request. */
+        conn->buffer[3] = 0x03;  /* Change the ATYP field */
+        conn->buffer[4] = namelen;  /* Length of name */
+        conn->datalen++;
+        memcpy(&conn->buffer[conn->datalen], name, namelen);
+        conn->datalen += namelen;
+    } else {
+        show_msg(MSGDEBUG, "send_socksv5_connect: ip address not found\n");
+        /* Use the raw IP address */
+        memcpy(&conn->buffer[conn->datalen], &(conn->connaddr.sin_addr.s_addr),
+                sizeof(conn->connaddr.sin_addr.s_addr));
+        conn->datalen += sizeof(conn->connaddr.sin_addr.s_addr);
+    }
+    memcpy(&conn->buffer[conn->datalen], &(conn->connaddr.sin_port),
+          sizeof(conn->connaddr.sin_port));
+    conn->datalen += sizeof(conn->connaddr.sin_port);
+
+    return(0);
+}
+
+static int send_buffer(struct connreq *conn)
+{
+    int rc = 0;
+
+    show_msg(MSGDEBUG, "Writing to server (sending %d bytes)\n", conn->datalen);
+    while ((rc == 0) && (conn->datadone != conn->datalen)) {
+        rc = send(conn->sockid, conn->buffer + conn->datadone,
+                  conn->datalen - conn->datadone, 0);
+        if (rc > 0) {
+            conn->datadone += rc;
+            rc = 0;
+        } else {
+            if (errno != EWOULDBLOCK)
+                show_msg(MSGDEBUG, "Write failed, %s\n", strerror(errno));
+            rc = errno;
+        }
+    }
+
+    if (conn->datadone == conn->datalen)
+        conn->state = conn->nextstate;
+
+    show_msg(MSGDEBUG, "Sent %d bytes of %d bytes in buffer, return code is %d\n",
+              conn->datadone, conn->datalen, rc);
+    return(rc);
+}
+
+static int recv_buffer(struct connreq *conn)
+{
+    int rc = 0;
+
+    show_msg(MSGDEBUG, "Reading from server (expecting %d bytes)\n", conn->datalen);
+    while ((rc == 0) && (conn->datadone != conn->datalen)) {
+          rc = recv(conn->sockid, conn->buffer + conn->datadone,
+                    conn->datalen - conn->datadone, 0);
+          if (rc > 0) {
+              conn->datadone += rc;
+              rc = 0;
+          } else if (rc == 0) {
+              show_msg(MSGDEBUG, "Peer has shutdown but we only read %d of %d bytes.\n",
+                  conn->datadone, conn->datalen);
+              rc = ENOTCONN; /* ENOTCONN seems like the most fitting error message */
+          } else {
+              if (errno != EWOULDBLOCK)
+                  show_msg(MSGDEBUG, "Read failed, %s\n", strerror(errno));
+              rc = errno;
+          }
+    }
+
+    if (conn->datadone == conn->datalen)
+        conn->state = conn->nextstate;
+
+    show_msg(MSGDEBUG, "Received %d bytes of %d bytes expected, return code is %d\n",
+             conn->datadone, conn->datalen, rc);
+    return(rc);
+}
+
+static int read_socksv5_method(struct connreq *conn)
+{
+    struct passwd *nixuser;
+    char *uname, *upass;
+
+    /* See if we offered an acceptable method */
+    if (conn->buffer[1] == '\xff') {
+        show_msg(MSGERR, "SOCKS V5 server refused authentication methods\n");
+        conn->state = FAILED;
+        return(ECONNREFUSED);
+    }
+
+    /* If the socks server chose username/password authentication */
+    /* (method 2) then do that                                    */
+    if ((unsigned short int) conn->buffer[1] == 2) {
+        show_msg(MSGDEBUG, "SOCKS V5 server chose username/password authentication\n");
+
+        /* Determine the current *nix username */
+        nixuser = getpwuid(getuid());
+
+        if (((uname = conn->path->defuser) == NULL) &&
+          ((uname = getenv("TORSOCKS_USERNAME")) == NULL) &&
+            ((uname = (nixuser == NULL ? NULL : nixuser->pw_name)) == NULL)) {
+            show_msg(MSGERR, "Could not get SOCKS username from "
+                    "local passwd file, torsocks.conf "
+                    "or $TORSOCKS_USERNAME to authenticate "
+                    "with");
+            conn->state = FAILED;
+            return(ECONNREFUSED);
+        }
+
+        if (((upass = getenv("TORSOCKS_PASSWORD")) == NULL) &&
+          ((upass = conn->path->defpass) == NULL)) {
+            show_msg(MSGERR, "Need a password in torsocks.conf or "
+                    "$TORSOCKS_PASSWORD to authenticate with");
+            conn->state = FAILED;
+            return(ECONNREFUSED);
+        }
+
+        /* Check that the username / pass specified will */
+        /* fit into the buffer                */
+        if ((3 + strlen(uname) + strlen(upass)) >= sizeof(conn->buffer)) {
+            show_msg(MSGERR, "The supplied socks username or "
+                    "password is too long");
+            conn->state = FAILED;
+            return(ECONNREFUSED);
+        }
+
+        conn->datalen = 0;
+        conn->buffer[conn->datalen] = '\x01';
+        conn->datalen++;
+        conn->buffer[conn->datalen] = (int8_t) strlen(uname);
+        conn->datalen++;
+        memcpy(&(conn->buffer[conn->datalen]), uname, strlen(uname));
+        conn->datalen = conn->datalen + strlen(uname);
+        conn->buffer[conn->datalen] = (int8_t) strlen(upass);
+        conn->datalen++;
+        memcpy(&(conn->buffer[conn->datalen]), upass, strlen(upass));
+        conn->datalen = conn->datalen + strlen(upass);
+
+        conn->state = SENDING;
+        conn->nextstate = SENTV5AUTH;
+        conn->datadone = 0;
+    } else
+        return(send_socksv5_connect(conn));
+
+    return(0);
+}
+
+static int read_socksv5_auth(struct connreq *conn)
+{
+
+    if (conn->buffer[1] != '\x00') {
+        show_msg(MSGERR, "SOCKS authentication failed, check username and password\n");
+        conn->state = FAILED;
+        return(ECONNREFUSED);
+    }
+
+    /* Ok, we authenticated ok, send the connection request */
+    return(send_socksv5_connect(conn));
+}
+
+static int read_socksv5_connect(struct connreq *conn)
+{
+
+    /* See if the connection succeeded */
+    if (conn->buffer[1] != '\x00') {
+        show_msg(MSGERR, "SOCKS V5 connect failed: ");
+        conn->state = FAILED;
+        switch ((int8_t) conn->buffer[1]) {
+            case 1:
+                show_msg(MSGERR, "General SOCKS server failure\n");
+                return(ECONNABORTED);
+            case 2:
+                show_msg(MSGERR, "Connection denied by rule\n");
+                return(ECONNABORTED);
+            case 3:
+                show_msg(MSGERR, "Network unreachable\n");
+                return(ENETUNREACH);
+            case 4:
+                show_msg(MSGERR, "Host unreachable\n");
+                return(EHOSTUNREACH);
+            case 5:
+                show_msg(MSGERR, "Connection refused\n");
+                return(ECONNREFUSED);
+            case 6:
+                show_msg(MSGERR, "TTL Expired\n");
+                return(ETIMEDOUT);
+            case 7:
+                show_msg(MSGERR, "Command not supported\n");
+                return(ECONNABORTED);
+            case 8:
+                show_msg(MSGERR, "Address type not supported\n");
+                return(ECONNABORTED);
+            default:
+                show_msg(MSGERR, "Unknown error\n");
+                return(ECONNABORTED);
+        }
+    }
+    conn->state = DONE;
+
+    return(0);
+}
+
+static int read_socksv4_req(struct connreq *conn)
+{
+    struct sockrep *thisrep;
+
+    thisrep = (struct sockrep *) conn->buffer;
+
+    if (thisrep->result != 90) {
+        show_msg(MSGERR, "SOCKS V4 connect rejected:\n");
+        conn->state = FAILED;
+        switch(thisrep->result) {
+          case 91:
+              show_msg(MSGERR, "SOCKS server refused connection\n");
+              return(ECONNREFUSED);
+          case 92:
+              show_msg(MSGERR, "SOCKS server refused connection "
+                    "because of failed connect to identd "
+                    "on this machine\n");
+              return(ECONNREFUSED);
+          case 93:
+              show_msg(MSGERR, "SOCKS server refused connection "
+                    "because identd and this library "
+                    "reported different user-ids\n");
+              return(ECONNREFUSED);
+          default:
+              show_msg(MSGERR, "Unknown reason\n");
+              return(ECONNREFUSED);
+        }
+    }
+    conn->state = DONE;
+
+    return(0);
+}
diff --git a/src/socks.h b/src/socks.h
new file mode 100644
index 0000000..af26fa6
--- /dev/null
+++ b/src/socks.h
@@ -0,0 +1,116 @@
+/***************************************************************************
+ *                                                                         *
+ *   Copyright (C) 2000-2008 Shaun Clowes <delius at progsoc.org>             *
+ *   Copyright (C) 2008-2011 Robert Hogan <robert at roberthogan.net>         *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+/* socks.h - Structures used by torsocks to form SOCKS requests */
+
+#ifndef _SOCKS_H
+
+#define _SOCKS_H 1
+
+#include "parser.h"
+#include "dead_pool.h"
+
+/* Structure representing a socks connection request */
+struct sockreq {
+   int8_t version;
+   int8_t command;
+   int16_t dstport;
+   int32_t dstip;
+   /* A null terminated username goes here */
+};
+
+/* Structure representing a socks connection request response */
+struct sockrep {
+   int8_t version;
+   int8_t result;
+   int16_t ignore1;
+   int32_t ignore2;
+};
+
+/* Structure representing a socket which we are currently proxying */
+struct connreq {
+   /* Information about the socket and target */
+   int sockid;
+   struct sockaddr_in connaddr;
+   struct sockaddr_in serveraddr;
+
+   /* Pointer to the config entry for the socks server */
+   struct serverent *path;
+
+   /* Current state of this proxied socket */
+   int state;
+
+   /* Next state to go to when the send or receive is finished */
+   int nextstate;
+
+   /* When connections fail but an error number cannot be reported
+    * because the socket is non blocking we keep the connreq struct until
+    * the status is queried with connect() again, we then return
+    * this value */
+   int err;
+
+   /* Events that were set for this socket upon call to select() or
+    * poll() */
+   int selectevents;
+
+   /* Buffer for sending and receiving on the socket */
+   unsigned int datalen;
+   unsigned int datadone;
+   char buffer[2048];
+
+   struct connreq *next;
+};
+
+/* Connection statuses */
+#define UNSTARTED 0
+#define CONNECTING 1
+#define CONNECTED 2
+#define SENDING 3
+#define RECEIVING 4
+#define SENTV4REQ 5
+#define GOTV4REQ 6
+#define SENTV5METHOD 7
+#define GOTV5METHOD 8
+#define SENTV5AUTH 9
+#define GOTV5AUTH 10
+#define SENTV5CONNECT 11
+#define GOTV5CONNECT 12
+#define DONE 13
+#define FAILED 14
+
+/* Flags to indicate what events a socket was select()ed for */
+#define READ (1<<0)
+#define WRITE (1<<1)
+#define EXCEPT (1<<2)
+#define READWRITE (READ|WRITE)
+#define READWRITEEXCEPT (READ|WRITE|EXCEPT)
+
+/* Global Declarations */
+static dead_pool *pool = NULL;
+static struct connreq *requests = NULL;
+
+struct connreq *new_socks_request(int sockid, struct sockaddr_in *connaddr,
+                                         struct sockaddr_in *serveraddr,
+                                         struct serverent *path);
+void kill_socks_request(struct connreq *conn);
+struct connreq *find_socks_request(int sockid, int includefailed);
+int handle_request(struct connreq *conn);
+
+#endif
diff --git a/src/torsocks.c b/src/torsocks.c
index 4239ced..98af4b0 100644
--- a/src/torsocks.c
+++ b/src/torsocks.c
@@ -71,7 +71,7 @@ const char *torsocks_progname = "libtorsocks";         /* Name used in err msgs
 #include <resolv.h>
 
 #include "parser.h"
-#include "torsocks.h"
+#include "socks.h"
 #include "dead_pool.h"
 
 /* Some function names are macroized on Darwin. Allow those names
@@ -79,9 +79,6 @@ const char *torsocks_progname = "libtorsocks";         /* Name used in err msgs
 #define EXPAND_GUTS(x) torsocks_##x##_guts
 #define EXPAND_GUTS_NAME(x) EXPAND_GUTS(x)
 
-/* Global Declarations */
-static dead_pool *pool = NULL;
-
 /* Function prototypes for original functions that we patch */
 #ifdef SUPPORT_RES_API
 int (*realres_init)(void);
@@ -92,7 +89,6 @@ int (*realres_init)(void);
 #undef DARWIN_EXPANSION
 
 static struct parsedfile config;
-static struct connreq *requests = NULL;
 static int suid = 0;
 static char *conffile = NULL;
 static volatile int torsocks_init_complete = 0;
@@ -120,27 +116,7 @@ int res_init(void);
 
 static int get_config();
 static int get_environment();
-static int connect_server(struct connreq *conn);
-static int send_socks_request(struct connreq *conn);
-static struct connreq *new_socks_request(int sockid, struct sockaddr_in *connaddr, 
-                                         struct sockaddr_in *serveraddr, 
-                                         struct serverent *path);
-static void kill_socks_request(struct connreq *conn);
-static int handle_request(struct connreq *conn);
-static struct connreq *find_socks_request(int sockid, int includefailed);
-static int connect_server(struct connreq *conn);
-static int send_socks_request(struct connreq *conn);
-static int send_socksv4_request(struct connreq *conn);
-static int send_socksv5_method(struct connreq *conn);
-static int send_socksv5_connect(struct connreq *conn);
-static int send_buffer(struct connreq *conn);
-static int recv_buffer(struct connreq *conn);
-static int read_socksv5_method(struct connreq *conn);
-static int read_socksv4_req(struct connreq *conn);
-static int read_socksv5_connect(struct connreq *conn);
-static int read_socksv5_auth(struct connreq *conn);
 static int deadpool_init(void);
-static int send_socksv4a_request(struct connreq *conn, const char *onion_host);
 
 static pthread_mutex_t torsocks_init_mutex = PTHREAD_MUTEX_INITIALIZER;
 
@@ -898,552 +874,6 @@ int torsocks_getpeername_guts(GETPEERNAME_SIGNATURE,
     return rc;
 }
 
-static struct connreq *new_socks_request(int sockid, struct sockaddr_in *connaddr, 
-                                         struct sockaddr_in *serveraddr, 
-                                         struct serverent *path)
-{
-    struct connreq *newconn;
-
-    if ((newconn = malloc(sizeof(*newconn))) == NULL) {
-        /* Could not malloc, we're stuffed */
-        show_msg(MSGERR, "Could not allocate memory for new socks request\n");
-        return(NULL);
-    }
-
-    /* Add this connection to be proxied to the list */
-    memset(newconn, 0x0, sizeof(*newconn));
-    newconn->sockid = sockid;
-    newconn->state = UNSTARTED;
-    newconn->path = path;
-    memcpy(&(newconn->connaddr), connaddr, sizeof(newconn->connaddr));
-    memcpy(&(newconn->serveraddr), serveraddr, sizeof(newconn->serveraddr));
-    newconn->next = requests;
-    requests = newconn;
-
-    return(newconn);
-}
-
-static void kill_socks_request(struct connreq *conn)
-{
-    struct connreq *connnode;
-
-    if (requests == conn)
-        requests = conn->next;
-    else {
-        for (connnode = requests; connnode != NULL; connnode = connnode->next) {
-            if (connnode->next == conn) {
-                connnode->next = conn->next;
-                break;
-            }
-        }
-    }
-
-    free(conn);
-}
-
-static struct connreq *find_socks_request(int sockid, int includefinished)
-{
-    struct connreq *connnode;
-
-    for (connnode = requests; connnode != NULL; connnode = connnode->next) {
-        if (connnode->sockid == sockid) {
-            if (((connnode->state == FAILED) || (connnode->state == DONE)) &&
-                !includefinished)
-                break;
-            else
-                return(connnode);
-        }
-    }
-
-    return(NULL);
-}
-
-static int handle_request(struct connreq *conn)
-{
-    int rc = 0;
-    int i = 0;
-
-    show_msg(MSGDEBUG, "Beginning handle loop for socket %d\n", conn->sockid);
-
-    while ((rc == 0) &&
-            (conn->state != FAILED) &&
-            (conn->state != DONE) &&
-            (i++ < 20)) {
-        show_msg(MSGDEBUG, "In request handle loop for socket %d, "
-                           "current state of request is %d\n", conn->sockid,
-                           conn->state);
-        switch(conn->state) {
-          case UNSTARTED:
-          case CONNECTING:
-              rc = connect_server(conn);
-              break;
-          case CONNECTED:
-              rc = send_socks_request(conn);
-              break;
-          case SENDING:
-              rc = send_buffer(conn);
-              break;
-          case RECEIVING:
-              rc = recv_buffer(conn);
-              break;
-          case SENTV4REQ:
-              show_msg(MSGDEBUG, "Receiving reply to SOCKS V4 connect request\n");
-              conn->datalen = sizeof(struct sockrep);
-              conn->datadone = 0;
-              conn->state = RECEIVING;
-              conn->nextstate = GOTV4REQ;
-              break;
-          case GOTV4REQ:
-              rc = read_socksv4_req(conn);
-              break;
-          case SENTV5METHOD:
-              show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 method negotiation\n");
-              conn->datalen = 2;
-              conn->datadone = 0;
-              conn->state = RECEIVING;
-              conn->nextstate = GOTV5METHOD;
-              break;
-          case GOTV5METHOD:
-              rc = read_socksv5_method(conn);
-              break;
-          case SENTV5AUTH:
-              show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 authentication negotiation\n");
-              conn->datalen = 2;
-              conn->datadone = 0;
-              conn->state = RECEIVING;
-              conn->nextstate = GOTV5AUTH;
-              break;
-          case GOTV5AUTH:
-              rc = read_socksv5_auth(conn);
-              break;
-          case SENTV5CONNECT:
-              show_msg(MSGDEBUG, "Receiving reply to SOCKS V5 connect request\n");
-              conn->datalen = 10;
-              conn->datadone = 0;
-              conn->state = RECEIVING;
-              conn->nextstate = GOTV5CONNECT;
-              break;
-          case GOTV5CONNECT:
-              rc = read_socksv5_connect(conn);
-              break;
-        }
-        conn->err = errno;
-    }
-
-    if (i == 20)
-        show_msg(MSGERR, "Ooops, state loop while handling request %d\n",
-                conn->sockid);
-
-    show_msg(MSGDEBUG, "Handle loop completed for socket %d in state %d, "
-                       "returning %d\n", conn->sockid, conn->state, rc);
-    return(rc);
-}
-
-static int connect_server(struct connreq *conn)
-{
-    int rc;
-
-    /* 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));
-
-    rc = realconnect(conn->sockid, (CONNECT_SOCKARG) &(conn->serveraddr),
-                     sizeof(conn->serveraddr));
-
-    show_msg(MSGDEBUG, "Connect returned %d, errno is %d\n", rc, errno); 
-    if (rc && errno == EISCONN) {
-        rc = 0;
-        show_msg(MSGDEBUG, "Socket %d already connected to SOCKS server\n", conn->sockid);
-        conn->state = CONNECTED;
-    } else if (rc) {
-        if (errno != EINPROGRESS) {
-            show_msg(MSGERR, "Error %d attempting to connect to SOCKS "
-                             "server (%s)\n", errno, strerror(errno));
-            conn->state = FAILED;
-        } else {
-            show_msg(MSGDEBUG, "Connection in progress\n");
-            conn->state = CONNECTING;
-        }
-    } else {
-        show_msg(MSGDEBUG, "Socket %d connected to SOCKS server\n", conn->sockid);
-        conn->state = CONNECTED;
-    }
-
-    return((rc ? errno : 0));
-}
-
-static int send_socks_request(struct connreq *conn)
-{
-    int rc = 0;
-
-    if (conn->path->type == 4) {
-        char *name = get_pool_entry(pool, &(conn->connaddr.sin_addr));
-        if(name != NULL)
-            rc = send_socksv4a_request(conn,name);
-        else
-            rc = send_socksv4_request(conn);
-    } else
-        rc = send_socksv5_method(conn);
-    return(rc);
-}
-
-static int send_socksv4a_request(struct connreq *conn,const char *onion_host)
-{
-    struct passwd *user;
-    struct sockreq *thisreq;
-    int endOfUser;
-    /* Determine the current username */
-    user = getpwuid(getuid());
-
-    thisreq = (struct sockreq *) conn->buffer;
-    endOfUser=sizeof(struct sockreq) +
-    (user == NULL ? 0 : strlen(user->pw_name)) + 1;
-
-    /* Check the buffer has enough space for the request  */
-    /* and the user name                                  */
-    conn->datalen = endOfUser+
-                    (onion_host == NULL ? 0 : strlen(onion_host)) + 1;
-    if (sizeof(conn->buffer) < conn->datalen) {
-        show_msg(MSGERR, "The SOCKS username is too long");
-        conn->state = FAILED;
-        return(ECONNREFUSED);
-    }
-
-    /* Create the request */
-    thisreq->version = 4;
-    thisreq->command = 1;
-    thisreq->dstport = conn->connaddr.sin_port;
-    thisreq->dstip   = htonl(1);
-
-    /* Copy the username */
-    strcpy((char *) thisreq + sizeof(struct sockreq),
-          (user == NULL ? "" : user->pw_name));
-
-    /* Copy the onion host */
-    strcpy((char *) thisreq + endOfUser,
-          (onion_host == NULL ? "" : onion_host));
-
-    conn->datadone = 0;
-    conn->state = SENDING;
-    conn->nextstate = SENTV4REQ;
-
-    return(0);
-}
-
-static int send_socksv4_request(struct connreq *conn)
-{
-    struct passwd *user;
-    struct sockreq *thisreq;
-
-    /* Determine the current username */
-    user = getpwuid(getuid());
-
-    thisreq = (struct sockreq *) conn->buffer;
-
-    /* Check the buffer has enough space for the request  */
-    /* and the user name                                  */
-    conn->datalen = sizeof(struct sockreq) + 
-                    (user == NULL ? 0 : strlen(user->pw_name)) + 1;
-    if (sizeof(conn->buffer) < conn->datalen) {
-        show_msg(MSGERR, "The SOCKS username is too long");
-        conn->state = FAILED;
-        return(ECONNREFUSED);
-    }
-
-    /* Create the request */
-    thisreq->version = 4;
-    thisreq->command = 1;
-    thisreq->dstport = conn->connaddr.sin_port;
-    thisreq->dstip   = conn->connaddr.sin_addr.s_addr;
-
-    /* Copy the username */
-    strcpy((char *) thisreq + sizeof(struct sockreq),
-            (user == NULL ? "" : user->pw_name));
-
-    conn->datadone = 0;
-    conn->state = SENDING;
-    conn->nextstate = SENTV4REQ;
-
-    return(0);
-}
-
-static int send_socksv5_method(struct connreq *conn)
-{
-    char verstring[] = { 0x05,    /* Version 5 SOCKS */
-                          0x02,    /* No. Methods     */
-                          0x00,    /* Null Auth       */
-                          0x02 };  /* User/Pass Auth  */
-
-    show_msg(MSGDEBUG, "Constructing V5 method negotiation\n");
-    conn->state = SENDING;
-    conn->nextstate = SENTV5METHOD;
-    memcpy(conn->buffer, verstring, sizeof(verstring));
-    conn->datalen = sizeof(verstring);
-    conn->datadone = 0;
-
-    return(0);
-}
-
-static int send_socksv5_connect(struct connreq *conn)
-{
-    int namelen = 0;
-    char *name = NULL;
-    char constring[] = { 0x05,    /* Version 5 SOCKS */
-                          0x01,    /* Connect request */
-                          0x00,    /* Reserved        */
-                          0x01 };  /* IP Version 4    */
-
-    show_msg(MSGDEBUG, "Constructing V5 connect request\n");
-    conn->datadone = 0;
-    conn->state = SENDING;
-    conn->nextstate = SENTV5CONNECT;
-    memcpy(conn->buffer, constring, sizeof(constring));
-    conn->datalen = sizeof(constring);
-
-    show_msg(MSGDEBUG, "send_socksv5_connect: looking for: %s\n",
-              inet_ntoa(conn->connaddr.sin_addr));
-
-    name = get_pool_entry(pool, &(conn->connaddr.sin_addr));
-    if(name != NULL) {
-        namelen = strlen(name);
-        if(namelen > 255)  /* "Can't happen" */
-            name = NULL;
-    }
-    if(name != NULL) {
-        show_msg(MSGDEBUG, "send_socksv5_connect: found it!\n");
-        /* Substitute the domain name from the pool into the SOCKS request. */
-        conn->buffer[3] = 0x03;  /* Change the ATYP field */
-        conn->buffer[4] = namelen;  /* Length of name */
-        conn->datalen++;
-        memcpy(&conn->buffer[conn->datalen], name, namelen);
-        conn->datalen += namelen;
-    } else {
-        show_msg(MSGDEBUG, "send_socksv5_connect: ip address not found\n");
-        /* Use the raw IP address */
-        memcpy(&conn->buffer[conn->datalen], &(conn->connaddr.sin_addr.s_addr),
-                sizeof(conn->connaddr.sin_addr.s_addr));
-        conn->datalen += sizeof(conn->connaddr.sin_addr.s_addr);
-    }
-    memcpy(&conn->buffer[conn->datalen], &(conn->connaddr.sin_port),
-          sizeof(conn->connaddr.sin_port));
-    conn->datalen += sizeof(conn->connaddr.sin_port);
-
-    return(0);
-}
-
-static int send_buffer(struct connreq *conn)
-{
-    int rc = 0;
-
-    show_msg(MSGDEBUG, "Writing to server (sending %d bytes)\n", conn->datalen);
-    while ((rc == 0) && (conn->datadone != conn->datalen)) {
-        rc = send(conn->sockid, conn->buffer + conn->datadone,
-                  conn->datalen - conn->datadone, 0);
-        if (rc > 0) {
-            conn->datadone += rc;
-            rc = 0;
-        } else {
-            if (errno != EWOULDBLOCK)
-                show_msg(MSGDEBUG, "Write failed, %s\n", strerror(errno));
-            rc = errno;
-        }
-    }
-
-    if (conn->datadone == conn->datalen)
-        conn->state = conn->nextstate;
-
-    show_msg(MSGDEBUG, "Sent %d bytes of %d bytes in buffer, return code is %d\n",
-              conn->datadone, conn->datalen, rc);
-    return(rc);
-}
-
-static int recv_buffer(struct connreq *conn)
-{
-    int rc = 0;
-
-    show_msg(MSGDEBUG, "Reading from server (expecting %d bytes)\n", conn->datalen);
-    while ((rc == 0) && (conn->datadone != conn->datalen)) {
-          rc = recv(conn->sockid, conn->buffer + conn->datadone,
-                    conn->datalen - conn->datadone, 0);
-          if (rc > 0) {
-              conn->datadone += rc;
-              rc = 0;
-          } else if (rc == 0) {
-              show_msg(MSGDEBUG, "Peer has shutdown but we only read %d of %d bytes.\n",
-                  conn->datadone, conn->datalen);
-              rc = ENOTCONN; /* ENOTCONN seems like the most fitting error message */
-          } else {
-              if (errno != EWOULDBLOCK)
-                  show_msg(MSGDEBUG, "Read failed, %s\n", strerror(errno));
-              rc = errno;
-          }
-    }
-
-    if (conn->datadone == conn->datalen)
-        conn->state = conn->nextstate;
-
-    show_msg(MSGDEBUG, "Received %d bytes of %d bytes expected, return code is %d\n",
-             conn->datadone, conn->datalen, rc);
-    return(rc);
-}
-
-static int read_socksv5_method(struct connreq *conn)
-{
-    struct passwd *nixuser;
-    char *uname, *upass;
-
-    /* See if we offered an acceptable method */
-    if (conn->buffer[1] == '\xff') {
-        show_msg(MSGERR, "SOCKS V5 server refused authentication methods\n");
-        conn->state = FAILED;
-        return(ECONNREFUSED);
-    }
-
-    /* If the socks server chose username/password authentication */
-    /* (method 2) then do that                                    */
-    if ((unsigned short int) conn->buffer[1] == 2) {
-        show_msg(MSGDEBUG, "SOCKS V5 server chose username/password authentication\n");
-
-        /* Determine the current *nix username */
-        nixuser = getpwuid(getuid());
-
-        if (((uname = conn->path->defuser) == NULL) &&
-          ((uname = getenv("TORSOCKS_USERNAME")) == NULL) &&
-            ((uname = (nixuser == NULL ? NULL : nixuser->pw_name)) == NULL)) {
-            show_msg(MSGERR, "Could not get SOCKS username from "
-                    "local passwd file, torsocks.conf "
-                    "or $TORSOCKS_USERNAME to authenticate "
-                    "with");
-            conn->state = FAILED;
-            return(ECONNREFUSED);
-        }
-
-        if (((upass = getenv("TORSOCKS_PASSWORD")) == NULL) &&
-          ((upass = conn->path->defpass) == NULL)) {
-            show_msg(MSGERR, "Need a password in torsocks.conf or "
-                    "$TORSOCKS_PASSWORD to authenticate with");
-            conn->state = FAILED;
-            return(ECONNREFUSED);
-        }
-
-        /* Check that the username / pass specified will */
-        /* fit into the buffer                */
-        if ((3 + strlen(uname) + strlen(upass)) >= sizeof(conn->buffer)) {
-            show_msg(MSGERR, "The supplied socks username or "
-                    "password is too long");
-            conn->state = FAILED;
-            return(ECONNREFUSED);
-        }
-
-        conn->datalen = 0;
-        conn->buffer[conn->datalen] = '\x01';
-        conn->datalen++;
-        conn->buffer[conn->datalen] = (int8_t) strlen(uname);
-        conn->datalen++;
-        memcpy(&(conn->buffer[conn->datalen]), uname, strlen(uname));
-        conn->datalen = conn->datalen + strlen(uname);
-        conn->buffer[conn->datalen] = (int8_t) strlen(upass);
-        conn->datalen++;
-        memcpy(&(conn->buffer[conn->datalen]), upass, strlen(upass));
-        conn->datalen = conn->datalen + strlen(upass);
-
-        conn->state = SENDING;
-        conn->nextstate = SENTV5AUTH;
-        conn->datadone = 0;
-    } else
-        return(send_socksv5_connect(conn));
-
-    return(0);
-}
-
-static int read_socksv5_auth(struct connreq *conn)
-{
-
-    if (conn->buffer[1] != '\x00') {
-        show_msg(MSGERR, "SOCKS authentication failed, check username and password\n");
-        conn->state = FAILED;
-        return(ECONNREFUSED);
-    }
-
-    /* Ok, we authenticated ok, send the connection request */
-    return(send_socksv5_connect(conn));
-}
-
-static int read_socksv5_connect(struct connreq *conn)
-{
-
-    /* See if the connection succeeded */
-    if (conn->buffer[1] != '\x00') {
-        show_msg(MSGERR, "SOCKS V5 connect failed: ");
-        conn->state = FAILED;
-        switch ((int8_t) conn->buffer[1]) {
-            case 1:
-                show_msg(MSGERR, "General SOCKS server failure\n");
-                return(ECONNABORTED);
-            case 2:
-                show_msg(MSGERR, "Connection denied by rule\n");
-                return(ECONNABORTED);
-            case 3:
-                show_msg(MSGERR, "Network unreachable\n");
-                return(ENETUNREACH);
-            case 4:
-                show_msg(MSGERR, "Host unreachable\n");
-                return(EHOSTUNREACH);
-            case 5:
-                show_msg(MSGERR, "Connection refused\n");
-                return(ECONNREFUSED);
-            case 6:
-                show_msg(MSGERR, "TTL Expired\n");
-                return(ETIMEDOUT);
-            case 7:
-                show_msg(MSGERR, "Command not supported\n");
-                return(ECONNABORTED);
-            case 8:
-                show_msg(MSGERR, "Address type not supported\n");
-                return(ECONNABORTED);
-            default:
-                show_msg(MSGERR, "Unknown error\n");
-                return(ECONNABORTED);
-        }
-    }
-    conn->state = DONE;
-
-    return(0);
-}
-
-static int read_socksv4_req(struct connreq *conn)
-{
-    struct sockrep *thisrep;
-
-    thisrep = (struct sockrep *) conn->buffer;
-
-    if (thisrep->result != 90) {
-        show_msg(MSGERR, "SOCKS V4 connect rejected:\n");
-        conn->state = FAILED;
-        switch(thisrep->result) {
-          case 91:
-              show_msg(MSGERR, "SOCKS server refused connection\n");
-              return(ECONNREFUSED);
-          case 92:
-              show_msg(MSGERR, "SOCKS server refused connection "
-                    "because of failed connect to identd "
-                    "on this machine\n");
-              return(ECONNREFUSED);
-          case 93:
-              show_msg(MSGERR, "SOCKS server refused connection "
-                    "because identd and this library "
-                    "reported different user-ids\n");
-              return(ECONNREFUSED);
-          default:
-              show_msg(MSGERR, "Unknown reason\n");
-              return(ECONNREFUSED);
-        }
-    }
-    conn->state = DONE;
-
-    return(0);
-}
-
 #ifdef SUPPORT_RES_API
 int res_init(void)
 {
diff --git a/src/torsocks.h b/src/torsocks.h
deleted file mode 100644
index 396aa5e..0000000
--- a/src/torsocks.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/***************************************************************************
- *                                                                         *
- *   Copyright (C) 2000-2008 Shaun Clowes <delius at progsoc.org>             *
- *   Copyright (C) 2008-2011 Robert Hogan <robert at roberthogan.net>         *
- *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
- ***************************************************************************/
-/* torsocks.h - Structures used by torsocks to form SOCKS requests */
-
-#ifndef _TORSOCKS_H
-
-#define _TORSOCKS_H 1
-
-#include "parser.h"
-
-/* Structure representing a socks connection request */
-struct sockreq {
-   int8_t version;
-   int8_t command;
-   int16_t dstport;
-   int32_t dstip;
-   /* A null terminated username goes here */
-};
-
-/* Structure representing a socks connection request response */
-struct sockrep {
-   int8_t version;
-   int8_t result;
-   int16_t ignore1;
-   int32_t ignore2;
-};
-
-/* Structure representing a socket which we are currently proxying */
-struct connreq {
-   /* Information about the socket and target */
-   int sockid;
-   struct sockaddr_in connaddr;
-   struct sockaddr_in serveraddr;
-
-   /* Pointer to the config entry for the socks server */
-   struct serverent *path;
-
-   /* Current state of this proxied socket */
-   int state;
-
-   /* Next state to go to when the send or receive is finished */
-   int nextstate;
-
-   /* When connections fail but an error number cannot be reported 
-    * because the socket is non blocking we keep the connreq struct until
-    * the status is queried with connect() again, we then return
-    * this value */
-   int err;
-
-   /* Events that were set for this socket upon call to select() or
-    * poll() */
-   int selectevents;
-
-   /* Buffer for sending and receiving on the socket */
-   unsigned int datalen;
-   unsigned int datadone;
-   char buffer[2048];
-
-   struct connreq *next;
-};
-
-/* Connection statuses */
-#define UNSTARTED 0
-#define CONNECTING 1
-#define CONNECTED 2
-#define SENDING 3
-#define RECEIVING 4
-#define SENTV4REQ 5
-#define GOTV4REQ 6 
-#define SENTV5METHOD 7 
-#define GOTV5METHOD 8
-#define SENTV5AUTH 9
-#define GOTV5AUTH 10
-#define SENTV5CONNECT 11
-#define GOTV5CONNECT 12
-#define DONE 13 
-#define FAILED 14 
-   
-/* Flags to indicate what events a socket was select()ed for */
-#define READ (1<<0)
-#define WRITE (1<<1)
-#define EXCEPT (1<<2)
-#define READWRITE (READ|WRITE)
-#define READWRITEEXCEPT (READ|WRITE|EXCEPT)
-
-#endif





More information about the tor-commits mailing list