[Pkg-privacy-commits] [onioncat] 122/340: - disabled connect log if unprivileged user -2 is used - getpwnam() replaced by getpwnam_r() because valgrind reported an error ...but unfortunatelly it still does - improved process termination handling - illegal mem access fixed in termination process - Socks connect exchanged by timed select - added signal handler for SIGTERM (and SIGHUP without implementation) - uid is changed to -2 if default user does not exist

Ximin Luo infinity0 at moszumanska.debian.org
Sat Aug 22 13:04:31 UTC 2015


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch debian
in repository onioncat.

commit 69e4941435302a828a9e836f47112dd6d7469ba1
Author: eagle <eagle at 58e1ccc2-750e-0410-8d0d-f93ca75ab447>
Date:   Mon Feb 9 20:21:28 2009 +0000

     - disabled connect log if unprivileged user -2 is used
     - getpwnam() replaced by getpwnam_r() because valgrind reported an error
       ...but unfortunatelly it still does
     - improved process termination handling
     - illegal mem access fixed in termination process
     - Socks connect exchanged by timed select
     - added signal handler for SIGTERM (and SIGHUP without implementation)
     - uid is changed to -2 if default user does not exist
    
    
    git-svn-id: http://www.cypherpunk.at/svn/onioncat/trunk@434 58e1ccc2-750e-0410-8d0d-f93ca75ab447
---
 ChangeLog        |   8 +++
 TODO             |   1 +
 configure        |  22 ++++----
 hosts.onioncat   |   2 +-
 src/ocat.c       |  67 ++++++++++++++++-------
 src/ocat.h       |  26 +++++++--
 src/ocatlibe.c   |  10 +++-
 src/ocatlog.c    |  12 ++++-
 src/ocatroute.c  |  36 +++++++++----
 src/ocatsetup.c  |   3 +-
 src/ocatsocks.c  | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/ocatthread.c |  20 ++++---
 12 files changed, 309 insertions(+), 56 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4141f87..86908a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,12 @@
 * version 0.1.10
+ - disabled connect log if unprivileged user -2 is used
+ - getpwnam() replaced by getpwnam_r() because valgrind reported an error
+   ...but unfortunatelly it still does
+ - improved process termination handling
+ - illegal mem access fixed in termination process
+ - Socks connect exchanged by timed select
+ - added signal handler for SIGTERM (and SIGHUP without implementation)
+ - uid is changed to -2 if default user does not exist
  - fixed erroneous sockaddr size in socks connect (leaded to failure on
  OpenBSD)
  - improved tunnel name determination
diff --git a/TODO b/TODO
index bf657df..2526cc4 100644
--- a/TODO
+++ b/TODO
@@ -12,6 +12,7 @@
 * peer list should be improved
 * IPv6 routing table should be improved (is just a flat list yet)
 * controller interface should be improved (is not thread-safe)
+* controller interface should use basic IO and timed selects
 //* IPv6 adresses are not checked for their validity
 //* garbage collector for packet queue missing
 //* garbage collector for session cleanup
diff --git a/configure b/configure
index ab34e49..d8a2018 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for onioncat 0.1.10-432M.
+# Generated by GNU Autoconf 2.61 for onioncat 0.1.10-433M.
 #
 # Report bugs to <rahra at cypherpunk.at>.
 #
@@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='onioncat'
 PACKAGE_TARNAME='onioncat'
-PACKAGE_VERSION='0.1.10-432M'
-PACKAGE_STRING='onioncat 0.1.10-432M'
+PACKAGE_VERSION='0.1.10-433M'
+PACKAGE_STRING='onioncat 0.1.10-433M'
 PACKAGE_BUGREPORT='rahra at cypherpunk.at'
 
 # Factoring default headers for most tests.
@@ -1206,7 +1206,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures onioncat 0.1.10-432M to adapt to many kinds of systems.
+\`configure' configures onioncat 0.1.10-433M to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1272,7 +1272,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of onioncat 0.1.10-432M:";;
+     short | recursive ) echo "Configuration of onioncat 0.1.10-433M:";;
    esac
   cat <<\_ACEOF
 
@@ -1362,7 +1362,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-onioncat configure 0.1.10-432M
+onioncat configure 0.1.10-433M
 generated by GNU Autoconf 2.61
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1376,7 +1376,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by onioncat $as_me 0.1.10-432M, which was
+It was created by onioncat $as_me 0.1.10-433M, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   $ $0 $@
@@ -2066,7 +2066,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='onioncat'
- VERSION='0.1.10-432M'
+ VERSION='0.1.10-433M'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2217,7 +2217,7 @@ ac_config_headers="$ac_config_headers config.h"
 
 
 cat >>confdefs.h <<\_ACEOF
-#define SVN_REVISION "432M"
+#define SVN_REVISION "433M"
 _ACEOF
 
 
@@ -5300,7 +5300,7 @@ exec 6>&1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by onioncat $as_me 0.1.10-432M, which was
+This file was extended by onioncat $as_me 0.1.10-433M, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -5353,7 +5353,7 @@ Report bugs to <bug-autoconf at gnu.org>."
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-onioncat config.status 0.1.10-432M
+onioncat config.status 0.1.10-433M
 configured by $0, generated by GNU Autoconf 2.61,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
diff --git a/hosts.onioncat b/hosts.onioncat
index dbd4d6c..80a6420 100644
--- a/hosts.onioncat
+++ b/hosts.onioncat
@@ -1,3 +1,3 @@
 fd87:d87e:eb43:f683:64ac:73f9:61ac:9a00 dot.onioncat
 fd87:d87e:eb43:2243:5f84:5b12:7bb5:bbc2 irc.onioncat
-
+fd87:d87e:eb43:f947:ad24:ec81:8abe:753e second.onioncat
diff --git a/src/ocat.c b/src/ocat.c
index f5c6adb..1d2596f 100644
--- a/src/ocat.c
+++ b/src/ocat.c
@@ -19,10 +19,6 @@
 #include "ocat.h"
 
 
-//! set to one if SIGINT is catched
-static int sig_term_ = 0;
-
-
 void usage(const char *s)
 {
    fprintf(stderr, 
@@ -126,7 +122,13 @@ void background(void)
 /*! Signal handler for SIGINT. */
 void sig_handler(int sig)
 {
-   sig_term_ = 1;
+   switch (sig)
+   {
+      case SIGTERM:
+      case SIGINT:
+         CNF(sig_term) = 1;
+         break;
+   }
 }
 
 
@@ -137,14 +139,18 @@ void install_sig(void)
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = sig_handler;
    log_debug("installing signal handler");
+   if (sigaction(SIGTERM, &sa, NULL) == -1)
+      log_msg(LOG_ERR, "could not install SIGINT handler: \"%s\"", strerror(errno)), exit(1);
    if (sigaction(SIGINT, &sa, NULL) == -1)
-      log_msg(LOG_ERR, "could not install signal handler: \"%s\"", strerror(errno)), exit(1);
+      log_msg(LOG_ERR, "could not install SIGINT handler: \"%s\"", strerror(errno)), exit(1);
+   if (sigaction(SIGHUP, &sa, NULL) == -1)
+      log_msg(LOG_ERR, "could not install SIGHUP handler: \"%s\"", strerror(errno)), exit(1);
 }
 
 
 void cleanup_system(void)
 {
-   OcatPeer_t *peer;
+   OcatPeer_t *peer, *next;
 
    log_msg(LOG_NOTICE, "waiting for system cleanup...");
    // close tunnel interface
@@ -156,27 +162,38 @@ void cleanup_system(void)
    // close and delete all peers
    log_debug("deleting peers");
    lock_peers();
-   for (peer = get_first_peer(); peer; peer = peer->next)
+   for (peer = get_first_peer(); peer; peer = next)
    {
       lock_peer(peer);
       log_debug("closing tcpfd %d", peer->tcpfd);
       oe_close(peer->tcpfd);
       unlock_peer(peer);
+      // get pointer to next before freeing struct
+      next = peer->next;
       log_debug("deleting peer at %p", peer);
       delete_peer(peer);
    }
    unlock_peers();
 
+   sig_socks_connector();
+
    // join threads
-   join_threads();
+   if (join_threads() > 1)
+   {
+      // waiting for detached threads
+      log_debug("waiting %ds for detached threads", SELECT_TIMEOUT);
+      sleep(SELECT_TIMEOUT);
+   }
+
+   delete_listeners(CNF(oc_listen), CNF(oc_listen_fd), CNF(oc_listen_cnt));
 }
 
 
 int main(int argc, char *argv[])
 {
-   char *s, ip6addr[INET6_ADDRSTRLEN], hw[20], def[100];
+   char *s, ip6addr[INET6_ADDRSTRLEN], hw[20], def[100], pwdbuf[SIZE_1K];
    int c, runasroot = 0;
-   struct passwd *pwd;
+   struct passwd *pwd, pwdm;
    int urlconv = 0;
 
    snprintf(def, 100, "127.0.0.1:%d", OCAT_LISTEN_PORT);
@@ -362,9 +379,22 @@ int main(int argc, char *argv[])
    run_ocat_thread("cleaner", socket_cleaner, NULL);
 
    // getting passwd info for user
-   errno = 0;
-   if (!(pwd = getpwnam(CNF(usrname))))
-      log_msg(LOG_EMERG, "can't get information for user \"%s\": \"%s\"", CNF(usrname), errno ? strerror(errno) : "user not found"), exit(1);
+   log_debug("getting user info for \"%s\"", CNF(usrname));
+   c = getpwnam_r(CNF(usrname), &pwdm, pwdbuf, SIZE_1K, &pwd);
+   if (!pwd)
+   {
+      log_msg(LOG_WARNING, "can't get information for user \"%s\": \"%s\", defaulting to uid %d",
+            CNF(usrname), c ? strerror(c) : "user not found", OCAT_UNPRIV_UID);
+      // if no passwd entry exists then default to some unprivileged user
+      memset(&pwdm, 0, sizeof(pwdm));
+      pwd = &pwdm;
+      pwd->pw_name = OCAT_UNPRIV_UNAME;
+      pwd->pw_uid = OCAT_UNPRIV_UID;
+      pwd->pw_gid = OCAT_UNPRIV_UID;
+      CNF(usrname) = pwd->pw_name;
+      log_msg(LOG_NOTICE, "disabling connect log");
+      CNF(create_clog) = 0;
+   }
 
    // create pid_file
    mk_pid_file();
@@ -424,16 +454,15 @@ int main(int argc, char *argv[])
 
    // start forwarding packets from tunnel
    log_msg(LOG_INFO, "starting packet forwarder");
-   while (!sig_term_)
-      packet_forwarder();
+   packet_forwarder();
 
-   log_msg(LOG_NOTICE, "caught termination request");
-   // set global termination flag
-   set_term_req();
    // initiate termination
    cleanup_system();
 
    log_msg(LOG_INFO, "Thanks for using OnionCat. Good Bye!");
+
+   // delete main thread's struct
+   free((OcatThread_t*) get_thread());
    return 0;
 }
 
diff --git a/src/ocat.h b/src/ocat.h
index eece06f..9a2d5dd 100644
--- a/src/ocat.h
+++ b/src/ocat.h
@@ -128,8 +128,15 @@
 #define OCAT_DEST_PORT 8060
 //! SOCKS port of TOR proxy
 #define TOR_SOCKS_PORT 9050
+#ifdef __OpenBSD__
+#define OCAT_UNAME "_tor"
+#elif __FreeBSD
+#define OCAT_UNAME "_tor"
+#else
 #define OCAT_UNAME "tor"
-#define OCAT_UID 112
+#endif
+#define OCAT_UNPRIV_UID 65534
+#define OCAT_UNPRIV_UNAME "(unknown)"
 #define OCAT_URL "http://www.abenteuerland.at/onioncat/"
 #define OCAT_DIR ".ocat"
 #define OCAT_CONNECT_LOG "connect_log"
@@ -139,6 +146,9 @@
 //! Maximum frame (packet) size, should be able to keep one maximum size ipv6-packet: 2^16 + 40 + 4
 #define FRAME_SIZE 65580
 
+//! Standard buffer size 1024 bytes
+#define SIZE_1K 1024
+
 #define DEQUEUER_WAKEUP 3
 //! maximum number a packet stays in queue
 #define MAX_QUEUE_DELAY 10
@@ -160,6 +170,7 @@
 #define E_SOCKS_CONN -2
 #define E_SOCKS_REQ -3
 #define E_SOCKS_RQFAIL -4
+#define E_SOCKS_TERMREQ -5
 
 #define E_FWD_NOPEER -1
 #define E_FWD_NOBUF -2
@@ -278,7 +289,7 @@ struct OcatSetup
    int rand_addr;
    char version[VERSION_STRING_LEN];
    int sizeof_setup;
-   int term_req;
+   int sig_term, term_req;
    pthread_mutex_t mutex;
    //! listening sockets for controller interface
    struct sockaddr **ctrl_listen;
@@ -470,7 +481,13 @@ struct ip6_hdr
 #endif
 
 #ifndef WITHOUT_TUN
+#ifdef __FreeBSD__
+#define TUN_DEV "/dev/tun0"
+#elif __OpenBSD__
+#define TUN_DEV "/dev/tun0"
+#else
 #define TUN_DEV "/dev/net/tun"
+#endif
 extern char *tun_dev_;
 #endif
 
@@ -522,13 +539,15 @@ void *ctrl_handler(void *);
 int insert_peer(int, const SocksQueue_t *, time_t);
 int run_listeners(struct sockaddr **, int *, int, int (*)(int));
 int send_keepalive(OcatPeer_t *);
+void set_select_timeout(struct timeval *);
+void set_nonblock(int);
 
 /* ocatthread.c */
 const OcatThread_t *init_ocat_thread(const char *);
 int run_ocat_thread(const char *, void *(*)(void*), void*);
 const OcatThread_t *get_thread(void);
 int set_thread_name(const char *);
-void join_threads(void);
+int join_threads(void);
 void detach_thread(void);
 void print_threads(FILE *);
 int term_req(void);
@@ -590,6 +609,7 @@ int oe_remtr(char *);
 int strsockaddr(const char *, struct sockaddr *);
 void add_local_listeners(void);
 void add_listener(const char *, const char *);
+void delete_listeners(struct sockaddr **, int *, int);
 
 /* ocatipv6route.c */
 struct in6_addr *ipv6_lookup_route(const struct in6_addr *);
diff --git a/src/ocatlibe.c b/src/ocatlibe.c
index 1863050..33492c8 100644
--- a/src/ocatlibe.c
+++ b/src/ocatlibe.c
@@ -140,11 +140,13 @@ int strsockaddr(const char *src, struct sockaddr *addr)
 void add_listener(const char *buf, const char *def)
 {
    CNF(oc_listen_cnt)++;
+   log_debug("reallocating sockaddr list to %d elements", CNF(oc_listen_cnt));
    if (!(CNF(oc_listen) = realloc(CNF(oc_listen), sizeof(struct sockaddr*) * CNF(oc_listen_cnt))))
       log_msg(LOG_ERR, "could not get memory for listener list: \"%s\"", strerror(errno)), exit(1);
    if (!(CNF(oc_listen_fd) = realloc(CNF(oc_listen_fd), sizeof(int) * CNF(oc_listen_cnt))))
       log_msg(LOG_ERR, "could not get memory for listener fds: \"%s\"", strerror(errno)), exit(1);
 
+   log_debug("allocating sockaddr mem for \"%s\"", def);
    if (!(CNF(oc_listen)[CNF(oc_listen_cnt) - 1] = calloc(1, sizeof(struct sockaddr_in6))))
       log_msg(LOG_ERR, "could not get memory for listener : \"%s\"", strerror(errno)), exit(1);
 
@@ -159,7 +161,13 @@ void add_listener(const char *buf, const char *def)
 }
 
 
-void delete_listeners(struct sockaddr **adr, int *fd, int cnt)
+void delete_listeners(struct sockaddr **addr, int *fd, int cnt)
 {
+   log_debug("freeing %d sockaddrs", cnt);
+   for (; cnt; cnt--)
+      free(addr[cnt - 1]);
+   log_debug("freeing sockaddr lists");
+   free(addr);
+   free(fd);
 }
 
diff --git a/src/ocatlog.c b/src/ocatlog.c
index a5edb24..e132c4e 100644
--- a/src/ocatlog.c
+++ b/src/ocatlog.c
@@ -26,6 +26,10 @@
 #define TIMESTRLEN 64
 #define CBUFLEN 1024
 
+#ifndef LOG_PRI
+#define LOG_PRI(p) ((p) & LOG_PRIMASK)
+#endif
+
 static pthread_mutex_t log_mutex_ = PTHREAD_MUTEX_INITIALIZER;
 static const char *flty_[8] = {"emerg", "alert", "crit", "err", "warning", "notice", "info", "debug"};
 //! FILE pointer to connect log
@@ -45,6 +49,12 @@ int open_connect_log(const char *dir)
    if (clog_)
       return 0;
 
+   if (!dir)
+   {
+      log_debug("dir has NULL pointer");
+      return -1;
+   }
+
    strlcpy(buf, dir, CBUFLEN);
    strlcat(buf, "/", CBUFLEN);
    strlcat(buf, CNF(ocat_dir), CBUFLEN);
@@ -102,7 +112,7 @@ void vlog_msgf(FILE *out, int lf, const char *fmt, va_list ap)
    // if thread struct not in list
    if (!th)
    {
-      strlcpy(ths.name, "<NEW>", THREAD_NAME_LEN);
+      strlcpy(ths.name, "<NEW/DIE>", THREAD_NAME_LEN);
       ths.id = -1;
       th = &ths;
    }
diff --git a/src/ocatroute.c b/src/ocatroute.c
index 6ce0daa..3f628dc 100644
--- a/src/ocatroute.c
+++ b/src/ocatroute.c
@@ -255,6 +255,15 @@ int set_peer_dest(struct in6_addr *dest, const struct in6_addr *addr)
 }
 
 
+/*! Set select timeout a little bit "random" to diverse wakeup periods. */
+void set_select_timeout(struct timeval *tv)
+{
+   tv->tv_usec = rand() % 1000000;
+   tv->tv_sec = SELECT_TIMEOUT + (tv->tv_usec & 1);
+   log_debug("timeout %d.%06d", tv->tv_sec, tv->tv_usec);
+}
+
+
 void *socket_receiver(void *p)
 {
    int maxfd, len;
@@ -302,9 +311,8 @@ void *socket_receiver(void *p)
       }
       unlock_peers();
 
-      tv.tv_sec = SELECT_TIMEOUT;
-      tv.tv_usec = 0;
-      log_debug("selecting...");
+      set_select_timeout(&tv);
+      log_debug("selecting (maxfd = %d)", maxfd);
       if ((maxfd = select(maxfd + 1, &rset, NULL, NULL, &tv)) == -1)
       {
          log_msg(LOG_EMERG, "select encountered error: \"%s\", restarting", strerror(errno));
@@ -706,9 +714,8 @@ int run_listeners(struct sockaddr **addr, int *sockfd, int cnt, int (action_acce
          break;
       }
 
-      tv.tv_sec = SELECT_TIMEOUT;
-      tv.tv_usec = 0;
-      log_debug("selecting locally (maxfd = %d)", maxfd);
+      set_select_timeout(&tv);
+      log_debug("selecting (maxfd = %d)", maxfd);
       if ((maxfd = select(maxfd + 1, &rset, NULL, NULL, &tv)) == -1)
       {
          log_debug("select returned: \"%s\"", strerror(errno));
@@ -773,16 +780,25 @@ void packet_forwarder(void)
 
    for (;;)
    {
-      if ((rlen = read(CNF(tunfd[0]), buf, FRAME_SIZE)) == -1)
+      // check for termination request
+      if (term_req())
+         break;
+
+     if ((rlen = read(CNF(tunfd[0]), buf, FRAME_SIZE)) == -1)
       {
          rlen = errno;
          log_debug("read from tun %d returned on error: \"%s\"", CNF(tunfd[0]), strerror(rlen));
          if (rlen == EINTR)
          {
-            log_debug("signal caught, exiting from packet_forwarder");
-            return;
+            log_debug("signal caught");
+            if (CNF(sig_term))
+            {
+               log_msg(LOG_NOTICE, "caught termination request");
+               // set global termination flag
+               set_term_req();
+            }
          }
-         log_debug("restart reading");
+         log_debug("restarting");
          continue;
       }
 
diff --git a/src/ocatsetup.c b/src/ocatsetup.c
index 9fd4571..4530030 100644
--- a/src/ocatsetup.c
+++ b/src/ocatsetup.c
@@ -76,7 +76,8 @@ struct OcatSetup setup_ =
    0,
    {0},
    sizeof(struct OcatSetup),
-   0,
+   //! sig_term, term_req
+   0, 0,
    PTHREAD_MUTEX_INITIALIZER,
    // ctrl_listen
    ctrl_listen_ptr_,
diff --git a/src/ocatsocks.c b/src/ocatsocks.c
index 01ab278..29d2a11 100644
--- a/src/ocatsocks.c
+++ b/src/ocatsocks.c
@@ -34,7 +34,7 @@ static int socks_thread_cnt_ = 0;
 static pthread_mutex_t socks_queue_mutex_ = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t socks_queue_cond_ = PTHREAD_COND_INITIALIZER;
 
-
+#if 0
 int socks_srv_con(void)
 {
    int fd, t;
@@ -54,6 +54,109 @@ int socks_srv_con(void)
    log_debug("connected");
    return fd;
 }
+#else
+int socks_srv_con(void)
+{
+   int fd, t, maxfd, so_err;
+   socklen_t err_len;
+   char addr[INET6_ADDRSTRLEN];
+   fd_set cset;
+   struct timeval tv;
+
+   if ((fd = socket(CNF(socks_dst)->sin_family == AF_INET ? PF_INET : PF_INET6, SOCK_STREAM, 0)) < 0)
+      return E_SOCKS_SOCK;
+   set_nonblock(fd);
+
+   t = time(NULL);
+   if (connect(fd, (struct sockaddr*) CNF(socks_dst), SOCKADDR_SIZE(CNF(socks_dst))) == -1)
+   {
+      if (errno != EINPROGRESS)
+      {
+         log_msg(LOG_ERR, "connect() to SOCKS port %s:%d failed: \"%s\". Sleeping for %d seconds.", 
+            inet_ntop(CNF(socks_dst)->sin_family, 
+               CNF(socks_dst)->sin_family == AF_INET ? (char*) &CNF(socks_dst)->sin_addr : (char*) &CNF(socks_dst6)->sin6_addr, addr, sizeof(addr)), 
+            ntohs(CNF(socks_dst)->sin_port), strerror(errno), TOR_SOCKS_CONN_TIMEOUT);
+         oe_close(fd);
+         sleep(TOR_SOCKS_CONN_TIMEOUT);
+         return E_SOCKS_CONN;
+      }
+      log_debug("connection in progress");
+   }
+   else
+   {
+      log_debug("connected");
+      return fd;
+   }
+
+   for (;;)
+   {
+      if (term_req())
+      {
+         oe_close(fd);
+         return -1;
+      }
+
+      FD_ZERO(&cset);
+      FD_SET(fd, &cset);
+      maxfd = fd;
+
+      set_select_timeout(&tv);
+      log_debug("selecting (maxfd = %d)", maxfd);
+      if ((maxfd = select(maxfd + 1, NULL, &cset, NULL, &tv)) == -1)
+      {
+         log_msg(LOG_EMERG, "select encountered error: \"%s\", restarting", strerror(errno));
+         continue;
+      }
+      log_debug("select returned %d", maxfd);
+
+      if (!maxfd)
+      {
+         log_debug("select timed out, restarting");
+         continue;
+      }
+
+      if (!FD_ISSET(fd, &cset))
+      {
+         log_msg(LOG_ERR, "fd %d not in fd_set! Restarting.", fd);
+         continue;
+      }
+
+      /*
+      if (connect(fd, (struct sockaddr*) CNF(socks_dst), SOCKADDR_SIZE(CNF(socks_dst))) == -1)
+      {
+         log_msg(LOG_ERR, "connect() to SOCKS port %s:%d failed: \"%s\". Sleeping for %d seconds.", 
+               inet_ntop(CNF(socks_dst)->sin_family, 
+                  CNF(socks_dst)->sin_family == AF_INET ? (char*) &CNF(socks_dst)->sin_addr : (char*) &CNF(socks_dst6)->sin6_addr, addr, sizeof(addr)), 
+               ntohs(CNF(socks_dst)->sin_port), strerror(errno), TOR_SOCKS_CONN_TIMEOUT);
+         oe_close(fd);
+         sleep(TOR_SOCKS_CONN_TIMEOUT);
+         return E_SOCKS_CONN;
+      }
+      */
+
+      // test if connect() worked
+      log_debug("check socket error");
+      err_len = sizeof(so_err);
+      if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &so_err, &err_len) == -1)
+      {
+         log_msg(LOG_ERR, "getsockopt failed: \"%s\"", strerror(errno));
+         oe_close(fd);
+         return -1;
+      }
+      if (so_err)
+      {
+         log_msg(LOG_ERR, "getsockopt returned %d (\"%s\")", so_err, strerror(so_err));
+         oe_close(fd);
+         return -1;
+      }
+      // everything seems to be ok, break loop
+      break;
+   } // for (;;)
+
+   log_debug("connected");
+   return fd;
+}
+#endif
 
 
 int socks_connect(const SocksQueue_t *sq)
@@ -64,6 +167,9 @@ int socks_connect(const SocksQueue_t *sq)
    //char addr[INET6_ADDRSTRLEN];
    SocksHdr_t *shdr = (SocksHdr_t*) buf;
    OcatPeer_t *peer;
+   int maxfd;
+   fd_set rset;
+   struct timeval tv;
 
    /*
    memset(&in, 0, sizeof(in));
@@ -114,6 +220,40 @@ int socks_connect(const SocksQueue_t *sq)
       log_msg(LOG_ERR, "couldn't write %d bytes to SOCKS connection %d", len, fd);
    log_debug("connect request sent");
 
+   for (;;)
+   {
+      if (term_req())
+      {
+         oe_close(fd);
+         return E_SOCKS_TERMREQ;
+      }
+
+      FD_ZERO(&rset);
+      FD_SET(fd, &rset);
+      maxfd = fd;
+
+      set_select_timeout(&tv);
+      log_debug("selecting (maxfd = %d)", maxfd);
+      if ((maxfd = select(maxfd + 1, &rset, NULL, NULL, &tv)) == -1)
+      {
+         log_msg(LOG_EMERG, "select encountered error: \"%s\", restarting", strerror(errno));
+         continue;
+      }
+
+      log_debug("select returned %d", maxfd);
+      if (!maxfd)
+      {
+         log_debug("select timed out, restarting");
+         continue;
+      }
+
+      if (FD_ISSET(fd, &rset))
+         break;
+
+      log_msg(LOG_ERR, "fd %d not in fd_set! Restarting.", fd);
+      continue;
+   } // for (;;)
+
    if (read(fd, shdr, sizeof(SocksHdr_t)) < sizeof(SocksHdr_t))
    {
       log_msg(LOG_ERR | LOG_FCONN, "short read, closing.");
@@ -150,6 +290,12 @@ int socks_connect(const SocksQueue_t *sq)
 }
 
 
+void sig_socks_connector(void)
+{
+   pthread_cond_signal(&socks_queue_cond_);
+}
+
+
 void socks_queue(struct in6_addr addr, int perm)
 {
    SocksQueue_t *squeue;
@@ -168,7 +314,7 @@ void socks_queue(struct in6_addr addr, int perm)
       squeue->next = socks_queue_;
       socks_queue_ = squeue;
       log_debug("signalling connector");
-      pthread_cond_signal(&socks_queue_cond_);
+      sig_socks_connector();
    }
    else
       log_debug("connection already exists, not queueing SOCKS connection");
@@ -225,6 +371,12 @@ void *socks_connector(void *p)
 
          log_debug("waiting for new queue entry");
          pthread_cond_wait(&socks_queue_cond_, &socks_queue_mutex_);
+         // check termination request
+         if (term_req())
+         {
+            pthread_mutex_unlock(&socks_queue_mutex_);
+            return NULL;
+         }
       }
 
       // spawn spare thread if there is no one left
@@ -253,6 +405,8 @@ void *socks_connector(void *p)
       if (!peer)
          for (i = 0, ps = -1, t_abs = 0; ((i < SOCKS_MAX_RETRY) || squeue->perm) && ps < 0; i++)
          {
+            // FIXME: term_req should be checked here
+
             // every third connection attempt
             if (!(i % RECONN_ATTEMPTS))
             {
diff --git a/src/ocatthread.c b/src/ocatthread.c
index 06ddbde..c0b804d 100644
--- a/src/ocatthread.c
+++ b/src/ocatthread.c
@@ -29,6 +29,7 @@
 
 // global thread id var and mutex for thread initializiation
 static int thread_id_ = 0;
+static int exit_cnt_ = 0;
 pthread_mutex_t thread_mutex_ = PTHREAD_MUTEX_INITIALIZER;
 OcatThread_t *octh_ = NULL;
 
@@ -42,6 +43,7 @@ void init_ocat_thread_struct(OcatThread_t *th)
    th->next = octh_;
    octh_ = th;
    pthread_mutex_unlock(&thread_mutex_);
+   log_debug("_init_ thread %d", th->id);
 }
 
 
@@ -68,6 +70,7 @@ void *thread_run(void *p)
    OcatThread_t **tl;
    void *r;
    sigset_t ss;
+   int ecnt, icnt;
 
    // block all signals for the thread
    sigfillset(&ss);
@@ -77,9 +80,9 @@ void *thread_run(void *p)
    init_ocat_thread_struct((OcatThread_t *) p);
 
    // call thread entry function
-   log_debug("starting thread");
+   log_debug("calling thread entry");
    r = ((OcatThread_t*)p)->entry(((OcatThread_t*)p)->parm);
-   log_debug("terminating thread");
+   log_debug("thread function returned");
 
    // delete thread struct from list and free memory
    pthread_mutex_lock(&thread_mutex_);
@@ -92,9 +95,12 @@ void *thread_run(void *p)
       *tl = (*tl)->next;
       free(p);
    }
+   ecnt = ++exit_cnt_;
+   icnt = thread_id_;
    pthread_mutex_unlock(&thread_mutex_);
 
-   return NULL;
+   log_debug("_exit_ thread, %d inits, %d exits", icnt, ecnt);
+   return r;
 }
 
 
@@ -203,7 +209,7 @@ void print_threads(FILE *f)
 }
 
 
-void join_threads(void)
+int join_threads(void)
 {
    OcatThread_t *th, thb;
    void *ret;
@@ -212,7 +218,7 @@ void join_threads(void)
    for (;;)
    {
       pthread_mutex_lock(&thread_mutex_);
-      for (th = octh_; th && th->detached; th = th->next);
+      for (th = octh_, rc = 0; th && th->detached; th = th->next, rc++);
       if (!th)
       {
          pthread_mutex_unlock(&thread_mutex_);
@@ -225,9 +231,9 @@ void join_threads(void)
       if ((rc = pthread_join(thb.handle, &ret)))
          log_msg(LOG_ERR, "error joining thread: \"%s\"", strerror(rc));
       log_debug("thread successful joined and return %p", ret);
-      sleep(10);
    }
-   log_debug("no more joinable threads available");
+   log_debug("no more joinable threads available, %d detached", rc);
+   return rc;
 }
 
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/onioncat.git



More information about the Pkg-privacy-commits mailing list