[Pkg-privacy-commits] [onioncat] 122/241: - 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
Intrigeri
intrigeri at moszumanska.debian.org
Wed Aug 26 16:16:48 UTC 2015
This is an automated email from the git hooks/post-receive script.
intrigeri pushed a commit to branch upstream-master
in repository onioncat.
commit 0afe6b9d12e70b51484d4fb9040208c23c845447
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: https://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