[Pkg-privacy-commits] [onioncat] 45/241: completely restructured controller and acceptor split to a generic acceptor that calls specific functions for TOR acception or controller acception

Intrigeri intrigeri at moszumanska.debian.org
Wed Aug 26 16:16:24 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 9adec785fcb46dcc31cdfbddd3e38b1818909911
Author: eagle <eagle at 58e1ccc2-750e-0410-8d0d-f93ca75ab447>
Date:   Tue Apr 22 15:30:26 2008 +0000

    completely restructured controller and acceptor split to a generic acceptor that calls specific functions for TOR acception or controller acception
    
    git-svn-id: https://www.cypherpunk.at/svn/onioncat/trunk@197 58e1ccc2-750e-0410-8d0d-f93ca75ab447
---
 src/ocat.c       |  22 ++--
 src/ocat.h       |   3 +-
 src/ocatroute.c  | 339 +++++++++++++++++++++++++++++++++++++------------------
 src/ocatthread.c |   7 +-
 4 files changed, 252 insertions(+), 119 deletions(-)

diff --git a/src/ocat.c b/src/ocat.c
index 3054dda..37fbb9a 100644
--- a/src/ocat.c
+++ b/src/ocat.c
@@ -30,6 +30,7 @@ void usage(const char *s)
          "onioncat (c) Bernhard R. Fischer -- compiled %s %s\n"
          "usage: %s [OPTIONS] <onion_hostname>\n"
          "   -h                    display usage message\n"
+         "   -C                    disable local controller interface\n"
          "   -d <n>                set debug level to n, default = %d\n"
          "   -i <onion_hostname>   convert onion hostname to IPv6 and exit\n"
          "   -l <port>             set ocat listen port, default = %d\n"
@@ -58,14 +59,18 @@ int main(int argc, char *argv[])
    int c, runasroot = 0;
    char *usrname = OCAT_UNAME;
    struct passwd *pwd;
-   int urlconv = 0, test_only = 0;
+   int urlconv = 0, test_only = 0, controller = 1;
 
    if (argc < 2)
       usage(argv[0]), exit(1);
 
-   while ((c = getopt(argc, argv, "d:hriopl:t:T:s:u:")) != -1)
+   while ((c = getopt(argc, argv, "Cd:hriopl:t:T:s:u:")) != -1)
       switch (c)
       {
+         case 'C':
+            controller = 0;
+            break;
+
          case 'd':
             debug_level_ = atoi(optarg);
             break;
@@ -168,11 +173,11 @@ int main(int argc, char *argv[])
    log_msg(L_DEBUG, "tun frameheader = 0x%08x", ntohl(fhd_key_));
 
    // start socket receiver thread
-   run_ocat_thread("receiver", socket_receiver);
+   run_ocat_thread("receiver", socket_receiver, NULL);
    // create listening socket and start socket acceptor
-   run_ocat_thread("acceptor", socket_acceptor);
+   run_ocat_thread("acceptor", socket_acceptor, NULL);
    // starting socket cleaner
-   run_ocat_thread("cleaner", socket_cleaner);
+   run_ocat_thread("cleaner", socket_cleaner, NULL);
 
    if (!runasroot && !getuid())
    {
@@ -189,11 +194,12 @@ int main(int argc, char *argv[])
    log_msg(L_DEBUG, "uid/gid = %d/%d", getuid(), getgid());
 
    // create socks connector thread
-   run_ocat_thread("connector", socks_connector);
+   run_ocat_thread("connector", socks_connector, NULL);
    // start packet dequeuer
-   run_ocat_thread("dequeuer", packet_dequeuer);
+   run_ocat_thread("dequeuer", packet_dequeuer, NULL);
    // start controller socket thread
-   run_ocat_thread("controller", ocat_controller);
+   if (controller)
+      run_ocat_thread("controller", ocat_controller, NULL);
 
    // start forwarding packets from tunnel
    log_msg(L_NOTICE, "starting packet forwarder");
diff --git a/src/ocat.h b/src/ocat.h
index bf4a8da..af8b680 100644
--- a/src/ocat.h
+++ b/src/ocat.h
@@ -111,6 +111,7 @@ typedef struct OcatThread
    int id;
    char name[THREAD_NAME_LEN];
    void *(*entry)(void*);
+   void *parm;
 } OcatThread_t;
 
 typedef struct SocksQueue
@@ -218,7 +219,7 @@ void *ocat_controller(void *);
 
 /* ocatthread.c */
 const OcatThread_t *init_ocat_thread(const char *);
-int run_ocat_thread(const char *, void *(*)(void*));
+int run_ocat_thread(const char *, void *(*)(void*), void*);
 const OcatThread_t *get_thread(void);
 
 
diff --git a/src/ocatroute.c b/src/ocatroute.c
index bf0ded7..4ca7102 100644
--- a/src/ocatroute.c
+++ b/src/ocatroute.c
@@ -28,7 +28,9 @@
 
 
 // file descriptor of tcp listener
-static int sockfd_;
+static int sockfd_[2];
+// file descriptors of control port
+static int ctrlfd_[2];
 // file descriptors of socket_receiver pipe
 // used for internal communication
 static int lpfd_[2];
@@ -56,6 +58,7 @@ uint32_t fhd_key_ = 0;
 uint16_t tor_socks_port_ = TOR_SOCKS_PORT;
 uint16_t ocat_listen_port_ = OCAT_LISTEN_PORT;
 uint16_t ocat_dest_port_ = OCAT_DEST_PORT;
+uint16_t ocat_ctrl_port_ = OCAT_CTRL_PORT;
 
 int vrec_ = 0;
 
@@ -540,40 +543,133 @@ int insert_peer(int fd, const struct in6_addr *addr, time_t dly)
 }
 
 
-void *socket_acceptor(void *p)
+int insert_anon_peer(int fd)
+{
+   return insert_peer(fd, NULL, 0);
+}
+
+
+int create_listener(struct sockaddr *addr, int sock_len)
+{
+   int family;
+   int fd;
+
+   switch (addr->sa_family)
+   {
+      case AF_INET:
+         family = PF_INET;
+         break;
+      case AF_INET6:
+         family = PF_INET6;
+         break;
+      default:
+         log_msg(L_FATAL, "unknown address family %d", addr->sa_family);
+         return -1;
+   }
+
+   if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
+   {
+      log_msg(L_FATAL, "could not create listener socker: \"%s\"", strerror(errno));
+      return -1;
+   }
+
+   if (bind(fd, addr, sock_len) < 0)
+   {
+      log_msg(L_FATAL, "could not bind listener %d: \"%s\"", fd, strerror(errno));
+      close(fd);
+      return -1;
+   }
+
+   if (listen(fd, 32) < 0)
+   {
+      log_msg(L_FATAL, "could not bring listener %d to listening state: \"%s\"", fd, strerror(errno));
+      close(fd);
+      return -1;
+   }
+
+   log_msg(L_NOTICE, "created listener, fd = %d", fd);
+   return fd;
+}
+
+
+/** run_local_listeners(...) is a generic socket acceptor for
+ *  local TCP ports (IPv4+IPv6).
+ *  Every time a connection comes in the function action_accept is
+ *  called with the incoming file descriptor as parameter.
+ */
+int run_local_listeners(short port, int *sockfd, int (action_accept)(int))
 {
    int fd;
    struct sockaddr_in in;
+   struct sockaddr_in6 in6;
+   fd_set rset;
+   int maxfd, i;
 
    memset(&in, 0, sizeof(in));
+   memset(&in6, 0, sizeof(in6));
+
    in.sin_family = AF_INET;
-   in.sin_port = htons(ocat_listen_port_);
+   in.sin_port = htons(port);
    in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+   in6.sin6_family = AF_INET6;
+   in6.sin6_port = htons(port);
+   memcpy(&in6.sin6_addr.s6_addr, &in6addr_loopback, sizeof(in6addr_loopback));
+
 #ifdef HAVE_SIN_LEN
    in.sin_len = sizeof(in);
+   in6.sin6_len = sizeof(in6);
 #endif
 
-   if ((sockfd_ = socket(PF_INET, SOCK_STREAM, 0)) < 0)
-      log_msg(L_FATAL, "could not create listener socker: \"%s\"", strerror(errno)), exit(1);
+   log_msg(L_DEBUG, "creating IPv4 listener");
+   if ((sockfd[0] = create_listener((struct sockaddr*) &in, sizeof(in))) == -1)
+      log_msg(L_FATAL, "exiting"), exit(1);
 
-   if (bind(sockfd_, (struct sockaddr*) &in, sizeof(struct sockaddr_in)) < 0)
-      log_msg(L_FATAL, "could not bind listener: \"%s\"", strerror(errno)), exit(1);
-
-   if (listen(sockfd_, 32) < 0)
-      log_msg(L_FATAL, "could not bring listener to listening state: \"%s\"", strerror(errno)), exit(1);
-   
-   log_msg(L_NOTICE, "created local listener %d on port %d", sockfd_, ocat_listen_port_);
+   log_msg(L_DEBUG, "creating IPv6 listener");
+   if ((sockfd[1] = create_listener((struct sockaddr*) &in6, sizeof(in6))) == -1)
+      log_msg(L_FATAL, "exiting"), exit(1);
 
    for (;;)
    {
-      log_msg(L_DEBUG, "[socket acceptor] is accepting further connections");
-      if ((fd = accept(sockfd_, NULL, NULL)) < 0)
-         perror("onion_receiver:accept"), exit(1);
+      log_msg(L_DEBUG, "setting up fd_set");
+      FD_ZERO(&rset);
+      FD_SET(sockfd[0], &rset);
+      FD_SET(sockfd[1], &rset);
 
-      log_msg(L_NOTICE, "connection %d accepted on listener %d", fd, sockfd_);
-      insert_peer(fd, NULL, 0);
+      maxfd = sockfd[0] > sockfd[1] ? sockfd[0] : sockfd[1];
+      log_msg(L_DEBUG, "selecting locally (maxfd = %d)", maxfd);
+      if ((maxfd = select(maxfd + 1, &rset, NULL, NULL, NULL)) == -1)
+      {
+         log_msg(L_DEBUG, "select returned: \"%s\"", strerror(errno));
+         continue;
+      }
+      log_msg(L_DEBUG, "select returned %d fds ready", maxfd);
+
+      for (i = 0; maxfd && (i < 2); i++)
+      {
+         log_msg(L_DEBUG, "checking fd %d (maxfd = %d, i = %d)", sockfd[i], maxfd, i);
+         if (!FD_ISSET(sockfd[i], &rset))
+            continue;
+         maxfd--;
+         log_msg(L_DEBUG, "accepting connection on %d", sockfd[i]);
+         if ((fd = accept(sockfd[i], NULL, NULL)) < 0)
+         {
+            log_msg(L_ERROR, "error accepting connection on %d: \"%s\"", sockfd[i], strerror(errno));
+            // FIXME: there should be additional error handling!
+            continue;
+         }
+
+         log_msg(L_NOTICE, "connection %d accepted on listener %d", fd, sockfd[i]);
+         (void) action_accept(fd);
+      }
    }
+   return 0;
+}
 
+
+void *socket_acceptor(void *p)
+{
+   run_local_listeners(ocat_listen_port_, sockfd_, insert_anon_peer);
    return NULL;
 }
 
@@ -701,7 +797,7 @@ void *socks_connector(void *p)
       (*squeue)->state = SOCKS_CONNECTING;
       socks_connect_cnt_++;
       if (socks_thread_cnt_ <= socks_connect_cnt_)
-         run_ocat_thread("connector", socks_connector);
+         run_ocat_thread("connector", socks_connector, NULL);
       pthread_mutex_unlock(&socks_queue_mutex_);
 
       // search for existing peer
@@ -814,115 +910,144 @@ void *socket_cleaner(void *ptr)
 }
 
 
-void *ocat_controller(void *p)
+void _remtr(char *s)
 {
-   int fd, sfd;
-   struct sockaddr_in in;
+   if (!s[0])
+      return;
+   if (s[strlen(s) - 1] != '\n' && s[strlen(s) - 1] != '\r')
+      return;
+   s[strlen(s) - 1] = '\0';
+   _remtr(s);
+}
+
+
+/**! ctrl_handler handles connections to local control port.
+ *   @param p void* typcasted to int contains fd of connected socket.
+ *   @return Currently always returns NULL.
+ */
+// FIXME: ctrl_handler probably is not thread-safe.
+void *ctrl_handler(void *p)
+{
+
+   int fd;
+   FILE *ff;
    char buf[FRAME_SIZE], addrstr[INET6_ADDRSTRLEN], onionstr[ONION_NAME_SIZE], timestr[32];
    int rlen, cfd;
    struct tm *tm;
    OcatThread_t *th;
    OcatPeer_t *peer;
 
-   memset(&in, 0, sizeof(in));
-   in.sin_family = AF_INET;
-   in.sin_port = htons(OCAT_CTRL_PORT);
-   in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-#ifdef HAVE_SIN_LEN
-   in.sin_len = sizeof(in);
-#endif
-
-   if ((sfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
-      log_msg(L_FATAL, "could not create listener socker: \"%s\"", strerror(errno)), exit(1);
+   if ((rlen = pthread_detach(pthread_self())))
+      log_msg(L_ERROR, "thread couldn't self-detach: \"%s\"", strerror(rlen));
+   log_msg(L_DEBUG, "thread detached");
 
-   if (bind(sfd, (struct sockaddr*) &in, sizeof(struct sockaddr_in)) < 0)
-      log_msg(L_FATAL, "could not bind listener: \"%s\"", strerror(errno)), exit(1);
-
-   if (listen(sfd, 5) < 0)
-      log_msg(L_FATAL, "could not bring listener to listening state: \"%s\"", strerror(errno)), exit(1);
-   
-   log_msg(L_NOTICE, "created local listener %d on port %d", sfd, ocat_listen_port_);
+   fd = (int) p;
+   if (!(ff = fdopen(fd, "r+")))
+   {
+      log_msg(L_ERROR, "could not open %d for writing", fd);
+      return NULL;
+   }
+   log_msg(L_DEBUG, "fd %d fdopen'ed", fd);
 
    for (;;)
    {
-      log_msg(L_DEBUG, "accepting connections on %d", sfd);
-      if ((fd = accept(sfd, NULL, NULL)) < 0)
-         log_msg(L_FATAL, "error in acception: \"%s\"", strerror(errno)), exit(1);
-      log_msg(L_NOTICE, "connection %d accepted on %d", fd, sfd);
-
-      for (;;)
+      fprintf(ff, "> ");
+      if (!fgets(buf, FRAME_SIZE, ff))
       {
-         if (write(fd, "> ", 2) != 2)
-            log_msg(L_ERROR, "couldn't write %d bytes to control socket %d", 2, fd);
-
-         if ((rlen = read(fd, buf, FRAME_SIZE)) == -1)
-         {
-            log_msg(L_FATAL, "read error on %d: \"%s\", closing", fd, strerror(errno));
-            break;
-         }
+         if (!feof(ff))
+            log_msg(L_ERROR, "error reading from %d");
+         break;
+      }
+      // remove trailing \r\n character
+      _remtr(buf);
+      // continue if string now is empty
+      if (!buf[0])
+         continue;
 
-         if (!rlen || buf[0] == 4 || !strncmp(buf, "exit", 4) || !strncmp(buf, "quit", 4))
-            break;
-         else if (!strncmp(buf, "status", 6))
-         {
-            pthread_mutex_lock(&peer_mutex_);
-            for (peer = peer_; peer; peer = peer->next)
-               if (peer->state == PEER_ACTIVE)
-               {
-                  tm = localtime(&peer->otime);
-                  strftime(timestr, 32, "%c", tm);
-                  sprintf(buf, "[%s]\n fd = %d\n addr = %s\n dir = \"%s\"\n idle = %lds\n bytes_in = %ld\n bytes_out = %ld\n setup_delay = %lds\n opening_time = \"%s\"\n",
-                        ipv6tonion(&peer->addr, onionstr), peer->tcpfd,
-                        inet_ntop(AF_INET6, &peer->addr, addrstr, INET6_ADDRSTRLEN),
-                        peer->dir == PEER_INCOMING ? "in" : "out",
-                        time(NULL) - peer->time, peer->in, peer->out, peer->sdelay, timestr);
-                  if (write(fd, buf, strlen(buf)) != strlen(buf))
-                     log_msg(L_ERROR, "couldn't write %d bytes to control socket %d", strlen(buf), fd);
-               }
-            pthread_mutex_unlock(&peer_mutex_);
-         }
-         else if (!strncmp(buf, "close ", 6))
-         {
-            cfd = atoi(&buf[6]);
-            pthread_mutex_lock(&peer_mutex_);
-            for (peer = peer_; peer; peer = peer->next)
-               if (peer->tcpfd == cfd)
-               {
-                  log_msg(L_NOTICE, "close request for %d", cfd);
-                  close(cfd);
-                  delete_peer(peer);
-                  break;
-               }
-            pthread_mutex_unlock(&peer_mutex_);
-         }
-         else if (!strncmp(buf, "threads", 7))
-         {
-            pthread_mutex_lock(&thread_mutex_);
-            for (th = octh_; th; th = th->next)
+      // "exit"/"quit" => terminate thread
+      if (buf[0] == 4 || !strncmp(buf, "exit", 4) || !strncmp(buf, "quit", 4))
+         break;
+      // "status"
+      else if (!strncmp(buf, "status", 6))
+      {
+         pthread_mutex_lock(&peer_mutex_);
+         for (peer = peer_; peer; peer = peer->next)
+            if (peer->state == PEER_ACTIVE)
             {
-               sprintf(buf, "%2d: %s\n", th->id, th->name);
-               if (write(fd, buf, strlen(buf)) != strlen(buf))
-                  log_msg(L_ERROR, "couldn't write %d bytes to control socket %d", strlen(buf), fd);
+               tm = localtime(&peer->otime);
+               strftime(timestr, 32, "%c", tm);
+               fprintf(ff, "[%s]\n fd = %d\n addr = %s\n dir = \"%s\"\n idle = %lds\n bytes_in = %ld\n bytes_out = %ld\n setup_delay = %lds\n opening_time = \"%s\"\n",
+                     ipv6tonion(&peer->addr, onionstr), peer->tcpfd,
+                     inet_ntop(AF_INET6, &peer->addr, addrstr, INET6_ADDRSTRLEN),
+                     peer->dir == PEER_INCOMING ? "in" : "out",
+                     time(NULL) - peer->time, peer->in, peer->out, peer->sdelay, timestr);
             }
-            pthread_mutex_unlock(&thread_mutex_);
-         }
-         else if (!strncmp(buf, "terminate", 9))
-         {
-            log_msg(L_NOTICE, "terminate request from control port");
-            //FIXME: fds should be closed properly
-            exit(0);
-         }
-         else
+         pthread_mutex_unlock(&peer_mutex_);
+      }
+      else if (!strncmp(buf, "close ", 6))
+      {
+         cfd = atoi(&buf[6]);
+         pthread_mutex_lock(&peer_mutex_);
+         for (peer = peer_; peer; peer = peer->next)
+            if (peer->tcpfd == cfd)
+            {
+               log_msg(L_NOTICE, "close request for %d", cfd);
+               close(cfd);
+               delete_peer(peer);
+               break;
+            }
+         if (!peer)
          {
-            strcpy(buf, "unknown command\n");
-            if (write(fd, buf, strlen(buf)) != strlen(buf))
-               log_msg(L_ERROR, "couldn't write %d bytes to control socket %d", strlen(buf), fd);
+            log_msg(L_NOTICE, "no peer with fd %d exists\n", cfd);
+            fprintf(ff, "no peer with fd %d exists\n", cfd);
          }
+         pthread_mutex_unlock(&peer_mutex_);
+      }
+      else if (!strncmp(buf, "threads", 7))
+      {
+         pthread_mutex_lock(&thread_mutex_);
+         for (th = octh_; th; th = th->next)
+            fprintf(ff, "%2d: %s\n", th->id, th->name);
+         pthread_mutex_unlock(&thread_mutex_);
+      }
+      else if (!strncmp(buf, "terminate", 9))
+      {
+         log_msg(L_NOTICE, "terminate request from control port");
+         //FIXME: fds should be closed properly
+         exit(0);
+      }
+      else if (!strncmp(buf, "fds", 3))
+      {
+         fprintf(ff, "acceptor sockets: %d/%d\nconntroller sockets: %d/%d\n", sockfd_[0], sockfd_[1], ctrlfd_[0], ctrlfd_[1]);
+      }
+      else if (!strncmp(buf, "help", 4))
+      {
+         fprintf(ff, "commands:\nexit\nquit\nterminate\nclose <n>\nstatus\nthreads\nfds\n");
+      }
+      else
+      {
+         fprintf(ff, "unknown command: \"%s\"\n", buf);
       }
-      log_msg(L_NOTICE, "closing session %d", fd);
-      close(fd);
    }
 
+   log_msg(L_NOTICE, "closing session %d", fd);
+   if (fclose(ff) == EOF)
+      log_msg(L_ERROR, "error closing control stream: \"%s\"", strerror(errno));
+   // fclose also closes the fd according to the man page
+
+   return NULL;
+}
+
+
+int run_ctrl_handler(int fd)
+{
+   return (int) run_ocat_thread("ctrl_handler", ctrl_handler, (void*) fd);
+}
+
+
+void *ocat_controller(void *p)
+{
+   run_local_listeners(ocat_ctrl_port_, ctrlfd_, run_ctrl_handler);
    return NULL;
 }
 
diff --git a/src/ocatthread.c b/src/ocatthread.c
index 9154ff0..370e733 100644
--- a/src/ocatthread.c
+++ b/src/ocatthread.c
@@ -45,7 +45,6 @@ const OcatThread_t *init_ocat_thread(const char *name)
 }
 
 
-
 void *thread_run(void *p)
 {
    OcatThread_t **tl;
@@ -61,7 +60,7 @@ void *thread_run(void *p)
 
    // call thread entry function
    log_msg(L_NOTICE, "running");
-   r = ((OcatThread_t*)p)->entry(NULL);
+   r = ((OcatThread_t*)p)->entry(((OcatThread_t*)p)->parm);
    log_msg(L_NOTICE, "terminating");
 
    pthread_mutex_lock(&thread_mutex_);
@@ -80,7 +79,7 @@ void *thread_run(void *p)
 }
 
 
-int run_ocat_thread(const char *name, void *(*thfunc)(void*))
+int run_ocat_thread(const char *name, void *(*thfunc)(void*), void *parm)
 {
    int rc;
    OcatThread_t *th;
@@ -97,7 +96,9 @@ int run_ocat_thread(const char *name, void *(*thfunc)(void*))
    }
 
    strncpy(th->name, name, THREAD_NAME_LEN);
+   th->name[THREAD_NAME_LEN - 1] = '\0';
    th->entry = thfunc;
+   th->parm = parm;
 
    log_msg(L_DEBUG, "starting [%s]", name);
    if ((rc = pthread_create(&th->handle, NULL, thread_run, th)))

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