[or-cvs] [torsocks/master] Add a rudimentary test suite

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


commit 6c84bdee0b3da63c1492024b0f267899ae4a4ca0
Author: Robert Hogan <robert at roberthogan.net>
Date:   Thu Feb 17 20:23:16 2011 +0000

    Add a rudimentary test suite
---
 Makefile.am              |    2 +-
 configure.in             |    2 +-
 src/common.h             |    5 +-
 src/dead_pool.c          |    7 +-
 src/parser.c             |    2 +-
 src/torsocks.c           |   26 ++--
 test/Makefile.am         |    6 +
 test/README              |    5 +-
 test/expectedresults.txt |  120 ++++++++++++
 test/gethostbyaddr.c     |   21 --
 test/resinit.c           |  204 ---------------------
 test/run_tests.sh        |   42 +++++
 test/test_torsocks.c     |  457 ++++++++++++++++++++++++++++++++++++++++++++++
 test/udp.c               |   89 ---------
 14 files changed, 652 insertions(+), 336 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 02520f2..44a7fbd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,4 +2,4 @@
 # have all needed files, that a GNU package needs
 AUTOMAKE_OPTIONS = foreign 1.4
 
-SUBDIRS = src
+SUBDIRS = src test
diff --git a/configure.in b/configure.in
index 614f34e..f238caa 100644
--- a/configure.in
+++ b/configure.in
@@ -612,5 +612,5 @@ AC_ENABLE_STATIC
 
 AC_CONFIG_FILES([src/usewithtor src/torsocks src/torsocks.conf.5 src/torsocks.8 src/usewithtor.1 src/torsocks.1])
 
-AC_OUTPUT(Makefile src/Makefile)
+AC_OUTPUT(Makefile src/Makefile test/Makefile)
 
diff --git a/src/common.h b/src/common.h
index 656aefb..1fc4589 100644
--- a/src/common.h
+++ b/src/common.h
@@ -64,8 +64,9 @@ unsigned int resolve_ip(char *, int, int);
 #define MSGNONE   -1
 #define MSGERR    0
 #define MSGWARN   1
-#define MSGNOTICE 2
-#define MSGDEBUG  2
+#define MSGTEST  2
+#define MSGNOTICE 3
+#define MSGDEBUG  3
 
 /* Required by some BSDs */
 #ifndef  MAP_ANONYMOUS
diff --git a/src/dead_pool.c b/src/dead_pool.c
index 6f4043a..0ef0d30 100644
--- a/src/dead_pool.c
+++ b/src/dead_pool.c
@@ -100,7 +100,7 @@ init_pool(unsigned int pool_size, struct in_addr deadrange_base,
         return NULL;
     }
 
-    show_msg(MSGWARN, "init_pool: sockshost %s \n", sockshost);
+    show_msg(MSGDEBUG, "init_pool: sockshost %s \n", sockshost);
 
     /* Initialize the dead_pool structure */
 #ifdef HAVE_INET_ATON
@@ -590,7 +590,7 @@ our_gethostbyaddr(dead_pool *pool, const void *_addr, socklen_t len, int type)
   he.h_addrtype  = type;
   he.h_addr_list = addrs;
 
-  show_msg(MSGDEBUG, "our_gethostbyaddr: resolved '%s' to: '%s'\n",
+  show_msg(MSGTEST, "our_gethostbyaddr: resolved '%s' to: '%s'\n",
            inet_ntoa(*((struct in_addr *)he.h_addr)), result_hostname);
 
   return &he;
@@ -605,7 +605,7 @@ our_gethostbyname(dead_pool *pool, const char *name)
   static struct hostent he;
   static char *addrs[2];
 
-  show_msg(MSGDEBUG, "our_gethostbyname: '%s' requested\n", name);
+  show_msg(MSGTEST, "our_gethostbyname: '%s' requested\n", name);
 
   pos = store_pool_entry(pool,(char *) name, &addr);
   if(pos == -1) {
@@ -735,6 +735,7 @@ our_getaddrinfo(dead_pool *pool, const char *node, const char *service,
         ret = realgetaddrinfo(node, service, hints, res);
     }
 
+    show_msg(MSGTEST, "our_getaddrinfo: '%s' requested\n", service);
     return ret;
 }
 
diff --git a/src/parser.c b/src/parser.c
index 592af18..c7c6290 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -82,7 +82,7 @@ int read_config (char *filename, struct parsedfile *config) {
         /* Insure null termination */
         line[sizeof(line) - 1] = (char) 0;
         filename = line;
-        show_msg(MSGWARN, "Configuration file not provided by TORSOCKS_CONF_FILE "
+        show_msg(MSGDEBUG, "Configuration file not provided by TORSOCKS_CONF_FILE "
                 "environment variable, attempting to use defaults in %s.\n", filename);
     }
 
diff --git a/src/torsocks.c b/src/torsocks.c
index 98af4b0..8099a5e 100644
--- a/src/torsocks.c
+++ b/src/torsocks.c
@@ -140,13 +140,11 @@ void torsocks_init(void)
     /* This has been observed on Snow Leopard for instance. */
     torsocks_init_complete = 1;
 
-    show_msg(MSGWARN, "In torsocks_init \n");
+    show_msg(MSGDEBUG, "In torsocks_init \n");
 
     get_environment();
     get_config();
 
-    show_msg(MSGWARN, "In torsocks_init after env/config\n");
-
 #ifdef USE_OLD_DLSYM
     void *lib;
 #endif
@@ -202,7 +200,7 @@ void torsocks_init(void)
     torsocks_init_complete=1;
     pthread_mutex_unlock(&torsocks_init_mutex);
 
-    show_msg(MSGWARN, "Exit torsocks_init \n");
+    show_msg(MSGDEBUG, "Exit torsocks_init \n");
 }
 
 static int get_environment()
@@ -220,7 +218,7 @@ static int get_environment()
         loglevel = atoi(env);
     if (((env = getenv("TORSOCKS_DEBUG_FILE"))) && !suid)
         logfile = env;
-    set_log_options(loglevel, logfile, 1);
+    set_log_options(loglevel, logfile, (loglevel == MSGTEST) ? 0 : 1);
 
     done = 1;
 
@@ -287,7 +285,7 @@ int torsocks_connect_guts(CONNECT_SIGNATURE, int (*original_connect)(CONNECT_SIG
         return(-1);
     }
 
-    show_msg(MSGDEBUG, "Got connection request\n");
+    show_msg(MSGTEST, "Got connection request\n");
 
     connaddr = (struct sockaddr_in *) __addr;
 
@@ -456,6 +454,7 @@ int torsocks_select_guts(SELECT_SIGNATURE, int (*original_select)(SELECT_SIGNATU
     if (!torsocks_init_complete)
         torsocks_init();
 
+    show_msg(MSGTEST, "Intercepted call to select\n");
     show_msg(MSGDEBUG, "Intercepted call to select with %d fds, "
               "0x%08x 0x%08x 0x%08x, timeout %08x\n", n,
               readfds, writefds, exceptfds, timeout);
@@ -641,6 +640,7 @@ int torsocks_poll_guts(POLL_SIGNATURE, int (*original_poll)(POLL_SIGNATURE))
     if (!torsocks_init_complete)
         torsocks_init();
 
+    show_msg(MSGTEST, "Intercepted call to poll\n");
     show_msg(MSGDEBUG, "Intercepted call to poll with %d fds, "
               "0x%08x timeout %d\n", nfds, ufds, timeout);
 
@@ -807,6 +807,7 @@ int torsocks_close_guts(CLOSE_SIGNATURE, int (*original_close)(CLOSE_SIGNATURE))
         return(-1);
     }
 
+    show_msg(MSGTEST, "Got call to close()\n");
     show_msg(MSGDEBUG, "Call to close(%d)\n", fd);
 
     rc = original_close(fd);
@@ -854,6 +855,7 @@ int torsocks_getpeername_guts(GETPEERNAME_SIGNATURE,
         return(-1);
     }
 
+    show_msg(MSGTEST, "Intercepted call to getpeername\n");
     show_msg(MSGDEBUG, "Call to getpeername for fd %d\n", __fd);
 
 
@@ -882,7 +884,7 @@ int res_init(void)
     if (!realres_init && ((realres_init = dlsym(RTLD_NEXT, "res_init")) == NULL))
         LOAD_ERROR("res_init", MSGERR);
 
-    show_msg(MSGDEBUG, "Got res_init request\n");
+    show_msg(MSGTEST, "Got res_init request\n");
 
     /* See comment in close() */
     if (!torsocks_init_complete)
@@ -907,7 +909,7 @@ int EXPAND_GUTS_NAME(res_query)(RES_QUERY_SIGNATURE, int (*original_res_query)(R
     if (!original_res_query && ((original_res_query = dlsym(RTLD_NEXT, "res_query")) == NULL))
         LOAD_ERROR("res_query", MSGERR);
 
-    show_msg(MSGDEBUG, "Got res_query request\n");
+    show_msg(MSGTEST, "Got res_query request\n");
 
     /* See comment in close() */
     if (!torsocks_init_complete)
@@ -967,7 +969,7 @@ int EXPAND_GUTS_NAME(res_search)(RES_SEARCH_SIGNATURE, int (*original_res_search
         ((original_res_search = dlsym(RTLD_NEXT, "res_search")) == NULL))
             LOAD_ERROR("res_search", MSGERR);
 
-    show_msg(MSGDEBUG, "Got res_search request\n");
+    show_msg(MSGTEST, "Got res_search request\n");
 
     /* See comment in close() */
     if (!torsocks_init_complete)
@@ -996,7 +998,7 @@ int EXPAND_GUTS_NAME(res_send)(RES_SEND_SIGNATURE, int (*original_res_send)(RES_
     if (!original_res_send && ((original_res_send = dlsym(RTLD_NEXT, "res_send")) == NULL))
             LOAD_ERROR("res_send", MSGERR);
 
-    show_msg(MSGDEBUG, "Got res_send request\n");
+    show_msg(MSGTEST, "Got res_send request\n");
 
     /* See comment in close() */
     if (!torsocks_init_complete)
@@ -1089,7 +1091,7 @@ ssize_t torsocks_sendto_guts(SENDTO_SIGNATURE, ssize_t (*original_sendto)(SENDTO
         return(-1);
     }
 
-    show_msg(MSGDEBUG, "Got sendto request\n");
+    show_msg(MSGTEST, "Got sendto request\n");
 
     /* Get the type of the socket */
     getsockopt(s, SOL_SOCKET, SO_TYPE,
@@ -1133,7 +1135,7 @@ ssize_t torsocks_sendmsg_guts(SENDMSG_SIGNATURE, ssize_t (*original_sendmsg)(SEN
         return(-1);
     }
 
-    show_msg(MSGDEBUG, "Got sendmsg request\n");
+    show_msg(MSGTEST, "Got sendmsg request\n");
 
     /* Get the type of the socket */
     getsockopt(s, SOL_SOCKET, SO_TYPE,
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..47b78f3
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,6 @@
+noinst_PROGRAMS= test_torsocks
+
+LIBS = -lresolv
+
+torsocks_test_SOURCES= test_torsocks.c
+CLEANFILES= test_torsocks
diff --git a/test/README b/test/README
index c746800..4d65948 100644
--- a/test/README
+++ b/test/README
@@ -1,2 +1,3 @@
-This folder contains some simple test utilties for various libc function that
-libtorsocks is expected to hook.
\ No newline at end of file
+To run the tests:
+$./run_tests.sh
+
diff --git a/test/expectedresults.txt b/test/expectedresults.txt
new file mode 100644
index 0000000..53f1105
--- /dev/null
+++ b/test/expectedresults.txt
@@ -0,0 +1,120 @@
+libtorsocks: The symbol getipnodebyname() was not found in any shared library. The error reported was: not found!
+libtorsocks: The symbol getipnodebyname() was not found in any shared library. The error reported was: not found!
+libtorsocks: The symbol getipnodebyname() was not found in any shared library. The error reported was: not found!
+libtorsocks: our_getaddrinfo: 'www.torproject.org' requested
+libtorsocks: Got sendmsg request
+libtorsocks: sendmsg: Connection is a UDP or ICMP stream, may be a DNS request or other form of leak: rejecting.
+libtorsocks: Got sendto request
+libtorsocks: sendto: Connection is a UDP or ICMP stream, may be a DNS request or other form of leak: rejecting.
+libtorsocks: Got sendto request
+libtorsocks: sendto: Connection is a UDP or ICMP stream, may be a DNS request or other form of leak: rejecting.
+libtorsocks: Got connection request
+libtorsocks: connect: Connection is a UDP or ICMP stream, may be a DNS request or other form of leak: rejecting.
+libtorsocks: our_gethostbyaddr: resolved '38.229.70.16' to: 'vescum.torproject.org'
+libtorsocks: our_gethostbyname: 'www.torproject.org' requested
+libtorsocks: Got connection request
+libtorsocks: connect: Connection is to a local address (192.168.1.1), may be a TCP DNS request to a local DNS server so have to reject to be safe. Please report a bug to http://code.google.com/p/torsocks/issues/entry if this is preventing a program from working properly with torsocks.
+libtorsocks: Got connection request
+libtorsocks: Intercepted call to getpeername
+libtorsocks: Got res_init request
+libtorsocks: Got connection request
+libtorsocks: Intercepted call to getpeername
+libtorsocks: Got connection request
+libtorsocks: Intercepted call to getpeername
+libtorsocks: Got connection request
+libtorsocks: Intercepted call to getpeername
+libtorsocks: Got connection request
+libtorsocks: Intercepted call to getpeername
+libtorsocks: Got res_init request
+libtorsocks: Got connection request
+libtorsocks: connect: Connection is to a local address (192.168.1.1), may be a TCP DNS request to a local DNS server so have to reject to be safe. Please report a bug to http://code.google.com/p/torsocks/issues/entry if this is preventing a program from working properly with torsocks.
+libtorsocks: Got connection request
+libtorsocks: connect: Connection is to a local address (192.168.1.1), may be a TCP DNS request to a local DNS server so have to reject to be safe. Please report a bug to http://code.google.com/p/torsocks/issues/entry if this is preventing a program from working properly with torsocks.
+libtorsocks: Got connection request
+libtorsocks: connect: Connection is to a local address (192.168.1.1), may be a TCP DNS request to a local DNS server so have to reject to be safe. Please report a bug to http://code.google.com/p/torsocks/issues/entry if this is preventing a program from working properly with torsocks.
+libtorsocks: Got connection request
+libtorsocks: connect: Connection is to a local address (192.168.1.1), may be a TCP DNS request to a local DNS server so have to reject to be safe. Please report a bug to http://code.google.com/p/torsocks/issues/entry if this is preventing a program from working properly with torsocks.
+libtorsocks: Got connection request
+libtorsocks: connect: Connection is to a local address (192.168.1.1), may be a TCP DNS request to a local DNS server so have to reject to be safe. Please report a bug to http://code.google.com/p/torsocks/issues/entry if this is preventing a program from working properly with torsocks.
+socket: Operation not permitted
+
+----------------------getaddrinfo() TEST-----------------
+
+getaddrinfo: Servname not supported for ai_socktype
+
+----------------------UDP TEST----------------------
+
+
+----------------------udp sendmsg() TEST-------------------
+
+sendmsg() returned ret=-1 wb=0
+
+----------------------udp sendto() TEST--------------------
+
+sendto() returned ret=-1 wb=0
+
+----------------------udp connect() TEST-------------------
+
+Connect returned ret=-1
+
+----------------------udp send() TEST----------------------
+
+Note: no interception by torsocks expected as send() requires a socket in a connected state.
+send() returned ret=-1 wb=0
+
+----------------------gethostbyaddr() TEST-----------------
+
+vescum.torproject.org -> 38.229.70.16
+
+----------------------gethostbyname() TEST-----------------
+
+www.torproject.org -> 38.229.70.16
+
+---------------------- local connect() TEST----------------------
+
+
+---------------------- internet connect() TEST----------------------
+
+
+---------------------- internet res_init() TEST----------------------
+
+nameserver for test: 8.8.8.8
+
+---------------------- internet res_query() TEST----------------------
+
+return code: 102
+
+---------------------- internet res_search() TEST----------------------
+
+return code: 102
+
+--------------- internet res_querydomain() TEST----------------------
+
+return code: -1
+
+---------------------- internet res_send() TEST----------------------
+
+return code: -1
+
+---------------------- local res_init() TEST----------------------
+
+nameserver for test: 192.168.1.1
+
+---------------------- local res_query() TEST----------------------
+
+return code: -1
+
+---------------------- local res_search() TEST----------------------
+
+return code: -1
+
+--------------- local res_querydomain() TEST----------------------
+
+return code: -1
+
+---------------------- local res_send() TEST----------------------
+
+return code: -1
+
+----------------icmp() TEST----------------------------
+
diff --git a/test/gethostbyaddr.c b/test/gethostbyaddr.c
deleted file mode 100644
index c3e719e..0000000
--- a/test/gethostbyaddr.c
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <netdb.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-//gcc -fPIC  -g -O2 -Wall -I. -o gethostbyaddr gethostbyaddr.c -lc
-int main() {
-  struct in_addr bar;
-  struct hostent *foo;
-  inet_aton("64.4.33.7",&bar);
-  foo=gethostbyaddr(&bar,4,AF_INET);
-  if (foo) {
-    int i;
-    for (i=0; foo->h_addr_list[i]; ++i)
-      printf("%s -> %s\n",foo->h_name,inet_ntoa(*(struct in_addr*)foo->h_addr_list[i]));
-    for (i=0; foo->h_aliases[i]; ++i)
-      printf("  also known as %s\n",foo->h_aliases[i]);
-  }
-  return 0;
-}
-
diff --git a/test/resinit.c b/test/resinit.c
deleted file mode 100644
index 73a9d57..0000000
--- a/test/resinit.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- *  Copyright (C) 2004 Tomasz Kojm <tkojm at clamav.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., 51 Franklin Street, Fifth Floor, Boston,
- *  MA 02110-1301, USA.
- */
-
-#include <stdio.h>
-
-#include <string.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-#include <sys/types.h>
-
-
-#include <netdb.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sysexits.h>
-#include <syslog.h>
-#include <pthread.h>
-
-#include <netdb.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-
-#ifndef LINUX
-#include <sys/queue.h>
-#else
-#include "queue.h"
-#endif
-
-#ifndef PACKETSZ
-#define PACKETSZ 512
-#endif
-
-static char *txtquery(const char *domain, unsigned int *ttl)
-{
-    unsigned char answer[PACKETSZ], *answend, *pt;
-    char *txt, host[128];
-    int len, type, qtype;
-    unsigned int cttl, size, txtlen = 0;
-
-
-    *ttl = 0;
-    if(res_init() < 0) {
-        printf("^res_init failed\n");
-        return NULL;
-    }
-
-    printf("*Querying %s\n", domain);
-
-    memset(answer, 0, PACKETSZ);
-    qtype = T_TXT;
-    if((len = res_query(domain, C_IN, qtype, answer, PACKETSZ)) < 0 || len > PACKETSZ) {
-        /*  The DNS server in the SpeedTouch Alcatel 510 modem can't
-         *  handle a TXT-query, but it can resolve an ANY-query to a
-         *  TXT-record, so we try an ANY-query now.  The thing we try
-         *  to resolve normally only has a TXT-record anyway.
-         */
-        memset(answer, 0, PACKETSZ);
-        qtype=T_ANY;
-        if((len = res_query(domain, C_IN, qtype, answer, PACKETSZ)) < 0) {
-            printf("^Can't query %s\n", domain);
-            return NULL;
-        }
-    }
-
-    answend = answer + len;
-    pt = answer + sizeof(HEADER);
-
-    if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) {
-        printf("^dn_expand failed\n");
-        return NULL;
-    }
-
-    pt += len;
-    if(pt > answend-4) {
-        printf("^Bad (too short) DNS reply\n");
-        return NULL;
-    }
-
-    GETSHORT(type, pt);
-    if(type != qtype) {
-        printf("^Broken DNS reply.\n");
-        return NULL;
-    }
-
-    pt += INT16SZ; /* class */
-    size = 0;
-    do { /* recurse through CNAME rr's */
-        pt += size;
-        if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) {
-            printf("^second dn_expand failed\n");
-            return NULL;
-        }
-        printf("^Host: %s\n", host);
-        pt += len;
-        if(pt > answend-10) {
-            printf("^Bad (too short) DNS reply\n");
-            return NULL;
-        }
-        GETSHORT(type, pt);
-        pt += INT16SZ; /* class */
-        GETLONG(cttl, pt);
-        GETSHORT(size, pt);
-        if(pt + size < answer || pt + size > answend) {
-            printf("^DNS rr overflow\n");
-            return NULL;
-        }
-    } while(type == T_CNAME);
-
-    if(type != T_TXT) {
-        printf("^Not a TXT record\n");
-        return NULL;
-    }
-
-    if(!size || (txtlen = *pt) >= size || !txtlen) {
-        printf("^Broken TXT record (txtlen = %d, size = %d)\n", txtlen, size);
-        return NULL;
-    }
-
-    if(!(txt = (char *) malloc(txtlen + 1)))
-        return NULL;
-
-    memcpy(txt, pt+1, txtlen);
-    txt[txtlen] = 0;
-    *ttl = cttl;
-
-    return txt;
-}
-
-
-//gcc -fPIC  -g -O2 -Wall -I. -o resinit resinit.c -lc -lresolv
-int main() {
-  unsigned char dnsreply[1024];
-  unsigned char host[128];
-  char *dnsrep;
-  int ret = 0;
-  unsigned int ttl=0;
-
-  memset( dnsreply, '\0', sizeof( dnsreply ));
-//   if (res_init() == -1)
-//   {
-//     printf("res_init failed\n");
-//     return -1;
-//   }
-
-  snprintf((char *)host, 127, "www.google.com");
-  dnsrep = txtquery((const char *)host, &ttl);
-  printf("RES_QUERY results: %s.", dnsrep);
-  printf("return code: %i\n", ret);
-  
-  snprintf((char *)host, 127, "www.google.com");
-  ret = res_query( (char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply ));
-  printf("RES_QUERY results: %s.", dnsreply);
-  printf("return code: %i\n", ret);
-  
-  memset( dnsreply, '\0', sizeof( dnsreply ));
-  ret = res_search( (char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply ));
-  printf("RES_SEARCH results: %s.", dnsreply);
-  printf("return code: %i\n", ret);
-  
-  memset( dnsreply, '\0', sizeof( dnsreply ));
-  ret = res_querydomain( "www.google.com", "google.com", C_IN, T_TXT, dnsreply, sizeof( dnsreply ));
-  printf("RES_QUERYDOMAIN results: %s.", dnsreply);
-  printf("return code: %i\n", ret);
-
-  memset( dnsreply, '\0', sizeof( dnsreply ));
-  ret = res_send( host, 32, dnsreply, sizeof( dnsreply ));
-  printf("RES_SEND results: %s.", dnsreply);
-  printf("return code: %i\n", ret);
-  
-  return ret;
-}
-
-
diff --git a/test/run_tests.sh b/test/run_tests.sh
new file mode 100755
index 0000000..5776bfe
--- /dev/null
+++ b/test/run_tests.sh
@@ -0,0 +1,42 @@
+#! /bin/sh
+# ***************************************************************************
+# *                                                                         *
+# *   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="`which torsocks`"
+
+if [ ! -x "$TORSOCKS" ]; then
+    echo "torsocks doesn't exist." >&2
+    echo "Perhaps you haven't installed torsocks yet?" >&2
+    exit 1
+fi
+
+if [ ! -f ./test_torsocks ]; then
+    echo "test_torsocks binary doesn't exist in this directory." >&2
+    echo "Perhaps you haven't compiled torsocks yet?" >&2
+    exit 1
+fi
+
+torsocks ./test_torsocks > /tmp/newresults.txt 2>&1
+output=`diff expectedresults.txt /tmp/newresults.txt`
+if ["$output" = ""]; then
+  echo "Tests passed"
+else
+  echo "Tests failed. Please post this output to http://code.google.com/p/torsocks/issues/entry"
+fi
+rm -f /tmp/newresults.txt
diff --git a/test/test_torsocks.c b/test/test_torsocks.c
new file mode 100644
index 0000000..e67de0a
--- /dev/null
+++ b/test/test_torsocks.c
@@ -0,0 +1,457 @@
+/***************************************************************************
+ *                                                                         *
+ * Copyright (c) 2000 Alessandro Iurlano.                                  *
+ * Copyright (C) 2004 Tomasz Kojm <tkojm at clamav.net>                       *
+ * Copyright (C) 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.             *
+ ***************************************************************************/
+
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <pthread.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <sysexits.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#ifndef LINUX
+#include <sys/queue.h>
+#else
+#include "queue.h"
+#endif
+
+#ifndef PACKETSZ
+#define PACKETSZ 512
+#endif
+
+static unsigned short csum (unsigned short *buf, int nwords)
+{
+    unsigned long sum;
+    for (sum = 0; nwords > 0; nwords--)
+        sum += *buf++;
+    sum = (sum >> 16) + (sum & 0xffff);
+    sum += (sum >> 16);
+    return ~sum;
+}
+
+static int icmp_test()
+{
+
+    int sockfd;
+    char datagram[400];
+    struct sockaddr_in dest;
+    struct ip *iphdr=(struct ip *) datagram;
+    struct icmphdr *icmphdr=(struct icmphdr *)(iphdr +1);
+    char *buff=(icmphdr +1);
+    printf("\n----------------icmp() TEST----------------------------\n\n");
+
+    if((sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))<0)
+    {
+        perror("socket");
+        exit(1);
+    }
+
+    memset(datagram,0,400);
+    strcpy(buff,"entzwei");
+    dest.sin_family=AF_INET;
+    dest.sin_addr.s_addr=inet_addr("192.168.1.33");
+
+    iphdr->ip_v=4;
+    iphdr->ip_hl=5;
+    iphdr->ip_len=sizeof(datagram);
+    iphdr->ip_id=htonl(54321);
+    iphdr->ip_off=0;
+    iphdr->ip_ttl=225;
+    iphdr->ip_p=1;
+    iphdr->ip_sum=0;
+    iphdr->ip_tos=0;
+    iphdr->ip_src.s_addr=inet_addr("192.168.1.35");
+    iphdr->ip_dst.s_addr=dest.sin_addr.s_addr;
+    iphdr->ip_sum=csum((unsigned short *)datagram,iphdr->ip_len >> 1);
+
+    icmphdr->type=130;
+    icmphdr->code=0;
+    icmphdr->checksum=htons(0xc3b0);
+    icmphdr->un.echo.sequence=0;
+    icmphdr->un.echo.id=0;
+
+        int one=1;
+        int *val=&one;
+        if(setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,val,sizeof(one))<0)
+            printf("cannot set HDRINCL!\n");
+
+
+    if(sendto(sockfd,datagram,35,0,(struct sockaddr *)&dest,sizeof(dest))<0)
+    {
+        perror("sendto");
+        exit(1);
+    }
+
+    return(0);
+}
+
+static char *txtquery(const char *domain, unsigned int *ttl)
+{
+    unsigned char answer[PACKETSZ], *answend, *pt;
+    char *txt, host[128];
+    int len, type, qtype;
+    unsigned int cttl, size, txtlen = 0;
+
+
+    *ttl = 0;
+    if(res_init() < 0) {
+        printf("^res_init failed\n");
+        return NULL;
+    }
+
+    printf("*Querying %s\n", domain);
+
+    memset(answer, 0, PACKETSZ);
+    qtype = T_TXT;
+    if((len = res_query(domain, C_IN, qtype, answer, PACKETSZ)) < 0 || len > PACKETSZ) {
+        /*  The DNS server in the SpeedTouch Alcatel 510 modem can't
+         *  handle a TXT-query, but it can resolve an ANY-query to a
+         *  TXT-record, so we try an ANY-query now.  The thing we try
+         *  to resolve normally only has a TXT-record anyway.
+         */
+        memset(answer, 0, PACKETSZ);
+        qtype=T_ANY;
+        if((len = res_query(domain, C_IN, qtype, answer, PACKETSZ)) < 0) {
+            printf("^Can't query %s\n", domain);
+            return NULL;
+        }
+    }
+
+    answend = answer + len;
+    pt = answer + sizeof(HEADER);
+
+    if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) {
+        printf("^dn_expand failed\n");
+        return NULL;
+    }
+
+    pt += len;
+    if(pt > answend-4) {
+        printf("^Bad (too short) DNS reply\n");
+        return NULL;
+    }
+
+    GETSHORT(type, pt);
+    if(type != qtype) {
+        printf("^Broken DNS reply.\n");
+        return NULL;
+    }
+
+    pt += INT16SZ; /* class */
+    size = 0;
+    do { /* recurse through CNAME rr's */
+        pt += size;
+        if((len = dn_expand(answer, answend, pt, host, sizeof(host))) < 0) {
+            printf("^second dn_expand failed\n");
+            return NULL;
+        }
+        printf("^Host: %s\n", host);
+        pt += len;
+        if(pt > answend-10) {
+            printf("^Bad (too short) DNS reply\n");
+            return NULL;
+        }
+        GETSHORT(type, pt);
+        pt += INT16SZ; /* class */
+        GETLONG(cttl, pt);
+        GETSHORT(size, pt);
+        if(pt + size < answer || pt + size > answend) {
+            printf("^DNS rr overflow\n");
+            return NULL;
+        }
+    } while(type == T_CNAME);
+
+    if(type != T_TXT) {
+        printf("^Not a TXT record\n");
+        return NULL;
+    }
+
+    if(!size || (txtlen = *pt) >= size || !txtlen) {
+        printf("^Broken TXT record (txtlen = %d, size = %d)\n", txtlen, size);
+        return NULL;
+    }
+
+    if(!(txt = (char *) malloc(txtlen + 1)))
+        return NULL;
+
+    memcpy(txt, pt+1, txtlen);
+    txt[txtlen] = 0;
+    *ttl = cttl;
+
+    return txt;
+}
+
+static int res_tests(char *ip, char *test) {
+    unsigned char dnsreply[1024];
+    unsigned char host[128];
+    int ret = 0, i;
+    char buf[16];
+    struct sockaddr_in addr;
+
+    memset( dnsreply, '\0', sizeof( dnsreply ));
+
+    printf("\n---------------------- %s res_init() TEST----------------------\n\n", test);
+    if (res_init() == -1) {
+      printf("res_init failed\n");
+      return -1;
+    }
+
+    inet_ntop(AF_INET, &_res.nsaddr_list[0].sin_addr.s_addr, buf, sizeof(buf));
+
+    addr.sin_family=AF_INET;
+    addr.sin_port=htons(53);
+    addr.sin_addr.s_addr=inet_addr(ip);
+
+    for (i = 0; i < _res.nscount; i++)
+        memcpy(&_res.nsaddr_list[i], &addr, sizeof(struct sockaddr_in));
+
+    inet_ntop(AF_INET, &_res.nsaddr_list[0].sin_addr.s_addr, buf, sizeof(buf));
+    printf("nameserver for test: %s\n", buf);
+
+    printf("\n---------------------- %s res_query() TEST----------------------\n\n", test);
+    snprintf((char *)host, 127, "www.google.com");
+    ret = res_nquery( &_res, (char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply ));
+//     printf("RES_QUERY results: %s.\n", dnsreply);
+    printf("return code: %i\n", ret);
+
+    printf("\n---------------------- %s res_search() TEST----------------------\n\n", test);
+    memset( dnsreply, '\0', sizeof( dnsreply ));
+    ret = res_nsearch( &_res,  (char *) host, C_IN, T_TXT, dnsreply, sizeof( dnsreply ));
+//     printf("RES_SEARCH results: %s.\n", dnsreply);
+    printf("return code: %i\n", ret);
+
+    printf("\n--------------- %s res_querydomain() TEST----------------------\n\n", test);
+    memset( dnsreply, '\0', sizeof( dnsreply ));
+    ret = res_nquerydomain( &_res,  "www.google.com", "google.com", C_IN, T_TXT, dnsreply, sizeof( dnsreply ));
+//     printf("RES_QUERYDOMAIN results: %s.\n", dnsreply);
+    printf("return code: %i\n", ret);
+
+    printf("\n---------------------- %s res_send() TEST----------------------\n\n", test);
+    memset( dnsreply, '\0', sizeof( dnsreply ));
+    ret = res_nsend( &_res,  host, 32, dnsreply, sizeof( dnsreply ));
+//     printf("RES_SEND results: %s.\n", dnsreply);
+    printf("return code: %i\n", ret);
+
+    return ret;
+}
+
+static int res_internet_tests() {
+    char *ip = "8.8.8.8";
+    char *test = "internet";
+    return res_tests(ip, test);
+}
+
+static int res_local_tests() {
+    char *ip = "192.168.1.1";
+    char *test = "local";
+    return res_tests(ip, test);
+}
+
+static int udp_test() {
+    struct sockaddr_in addr;
+    char testtext[]="This message should be sent via udp\nThis is row number 2\nAnd then number three\n";
+    int sock,ret,wb,flags=0;
+    char *ip = "6.6.6.6";
+
+    printf("\n----------------------UDP TEST----------------------\n\n");
+
+    addr.sin_family=AF_INET;
+    addr.sin_port=53;
+    addr.sin_addr.s_addr=inet_addr(ip);
+
+    sock=socket(AF_INET,SOCK_DGRAM,0);
+
+    struct iovec iov;
+    struct msghdr msg;
+
+    iov.iov_base = (void *)testtext;
+    iov.iov_len = strlen(testtext);
+
+    msg.msg_name = (struct sockaddr *)&addr;
+    msg.msg_namelen = sizeof(addr);
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+
+    printf("\n----------------------udp sendmsg() TEST-------------------\n\n");
+    wb=0;
+    ret=sendmsg(sock, &msg, flags);
+    printf("sendmsg() returned ret=%d wb=%d\n",ret,wb);
+
+    printf("\n----------------------udp sendto() TEST--------------------\n\n");
+    wb=0;
+    ret=sendto(sock,testtext,strlen(testtext)+1,wb, (struct sockaddr*)&addr, sizeof(addr));
+    ret=sendto(sock,"CiaoCiao",strlen("CiaoCiao")+1,wb, (struct sockaddr*)&addr, sizeof(addr));
+    printf("sendto() returned ret=%d wb=%d\n",ret,wb);
+
+    printf("\n----------------------udp connect() TEST-------------------\n\n");
+    ret=connect(sock,(struct sockaddr*)&addr,sizeof(addr));
+    printf("Connect returned ret=%d\n",ret);
+
+    printf("\n----------------------udp send() TEST----------------------\n\n");
+    wb=0;
+    ret=send(sock,testtext,strlen(testtext)+1,wb);
+    ret=send(sock,"CiaoCiao",strlen("CiaoCiao")+1,wb);
+    printf("Note: no interception by torsocks expected as send() requires a socket in a connected state.\n");
+    printf("send() returned ret=%d wb=%d\n",ret,wb);
+
+    return 0;
+}
+
+static int gethostbyname_test() {
+    struct hostent *foo;
+
+    printf("\n----------------------gethostbyname() TEST-----------------\n\n");
+
+    foo=gethostbyname("www.torproject.org");
+    if (foo) {
+      int i;
+      for (i=0; foo->h_addr_list[i]; ++i)
+        printf("%s -> %s\n",foo->h_name,inet_ntoa(*(struct in_addr*)foo->h_addr_list[i]));
+/*      for (i=0; foo->h_aliases[i]; ++i)
+        printf("  also known as %s\n",foo->h_aliases[i]);*/
+    }
+    return 0;
+}
+
+static int gethostbyaddr_test() {
+    struct in_addr bar;
+    struct hostent *foo;
+
+    printf("\n----------------------gethostbyaddr() TEST-----------------\n\n");
+
+    inet_aton("38.229.70.16",&bar);
+    foo=gethostbyaddr(&bar,4,AF_INET);
+    if (foo) {
+      int i;
+      for (i=0; foo->h_addr_list[i]; ++i)
+        printf("%s -> %s\n",foo->h_name,inet_ntoa(*(struct in_addr*)foo->h_addr_list[i]));
+      for (i=0; foo->h_aliases[i]; ++i)
+        printf("  also known as %s\n",foo->h_aliases[i]);
+    }
+    return 0;
+}
+
+static int getaddrinfo_test() {
+    struct addrinfo hints;
+    struct addrinfo *result;
+    int s;
+
+    printf("\n----------------------getaddrinfo() TEST-----------------\n\n");
+
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_family = AF_INET;    /* Allow IPv4 or IPv6 */
+    hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
+    hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
+    hints.ai_protocol = 0;          /* Any protocol */
+    hints.ai_canonname = NULL;
+    hints.ai_addr = NULL;
+    hints.ai_next = NULL;
+
+    s = getaddrinfo(NULL, "www.torproject.org", &hints, &result);
+    if (s != 0) {
+        printf("getaddrinfo: %s\n", gai_strerror(s));
+    }
+
+    return 0;
+}
+
+/* Unavailable in glibc. */
+/*
+static int getipnodebyname_test() {
+    int error;
+
+    printf("\n----------------------getipnodebyname() TEST-----------------\n\n");
+
+    getipnodebyname("www.torproject.org", AF_INET, 0, &error);
+    if (error != 0) {
+        printf("getipnodebyname error: %i\n", error);
+    }
+
+    return 0;
+}
+*/
+
+static int connect_test(const char *name, const char *ip, int port)
+{
+    int sock;
+    struct sockaddr_in addr;
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family      = AF_INET;
+    addr.sin_addr.s_addr = inet_addr(ip);
+    addr.sin_port        = htons(port);
+
+    printf("\n---------------------- %s connect() TEST----------------------\n\n", name);
+
+    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+        return 1;
+
+    if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0)
+        return 1;
+
+    return 0;
+}
+
+static int connect_local_test()
+{
+    const char *ip = "192.168.1.1";
+    const char *name = "local";
+    int port = 80;
+    return connect_test(name, ip, port);
+}
+
+static int connect_internet_test()
+{
+    const char *ip = "8.8.8.8";
+    int port = 53;
+    const char *name = "internet";
+    return connect_test(name, ip, port);
+}
+
+int main() {
+
+    getaddrinfo_test();
+    udp_test();
+    gethostbyaddr_test();
+    gethostbyname_test();
+    connect_local_test();
+    connect_internet_test();
+    res_internet_tests();
+    res_local_tests();
+    icmp_test();
+
+    return 0;
+}
diff --git a/test/udp.c b/test/udp.c
deleted file mode 100644
index 4926c66..0000000
--- a/test/udp.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * OSSO - A Micro Kernel OS
- * Copyright (c) 2000 Alessandro Iurlano.
- *
- * 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, 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.
- */
-
-/******************************* O S S O ***********************************
- * file : $Source: /home/robert/Development/torsockstosvn/torsocks-cvsbackup/torsocks/test/udp.c,v $
- * Description: UDP protocol testing program.
- ***************************************************************************
-
- ***************************************************************************
- * $Id: udp.c,v 1.1 2008-06-23 19:38:34 hoganrobert Exp $
- ***************************************************************************/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-//gcc -fPIC  -g -O2 -Wall -I. -o udp udp.c -lc
-
-struct sockaddr_in addr;
-char testtext[]="This message should be sent via udp\nThis is row number 2\nAnd then number three\n";
-
-
-int main(int argc, char *argv[]) {
-  int sock,ret,wb,flags=0;
-
-  printf("\n----------------------UDP TEST----------------------\n\n");
-
-  addr.sin_family=AF_INET;
-  addr.sin_port=53;
-  addr.sin_addr.s_addr=159|(134<<8)|(237<<16)|(6<<24);
-
-  sock=socket(AF_INET,SOCK_DGRAM,0);
-
-  printf("socket returned %d\n",sock);
-
-  struct iovec iov;
-  struct msghdr msg;
-
-  iov.iov_base = (void *)testtext;
-  iov.iov_len = strlen(testtext);
-
-  msg.msg_name = (struct sockaddr *)&addr;
-  msg.msg_namelen = sizeof(addr);
-  msg.msg_iov = &iov;
-  msg.msg_iovlen = 1;
-  msg.msg_control = NULL;
-  msg.msg_controllen = 0;
-
-  wb=0;
-  ret=sendmsg(sock, &msg, flags);
-  printf("sendmsg() returned ret=%d wb=%d\n",ret,wb);
-
-  wb=0;
-  ret=sendto(sock,testtext,strlen(testtext)+1,wb, (struct sockaddr*)&addr, sizeof(addr));
-  ret=sendto(sock,"CiaoCiao",strlen("CiaoCiao")+1,wb, (struct sockaddr*)&addr, sizeof(addr));
-  printf("sendto() returned ret=%d wb=%d\n",ret,wb);
-
-  ret=connect(sock,(struct sockaddr*)&addr,sizeof(addr));
-  printf("Connect returned ret=%d\n",ret);
-  wb=0;
-  ret=send(sock,testtext,strlen(testtext)+1,wb);
-  ret=send(sock,"CiaoCiao",strlen("CiaoCiao")+1,wb);
-  printf("send() returned ret=%d wb=%d\n",ret,wb);
-
-
-  return 0;
-}



More information about the tor-commits mailing list