"Fossies" - the Fresh Open Source Software Archive

Member "portfwd-0.29/src/forward.cc" (30 May 2005, 23174 Bytes) of package /linux/privat/old/portfwd-0.29.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2   forward.c
    3 
    4   $Id: forward.cc,v 1.12 2005/05/30 02:13:28 evertonm Exp $
    5  */
    6 
    7 #include <stdlib.h>
    8 #include <sys/time.h>
    9 #include <sys/types.h>
   10 #include <sys/socket.h>
   11 #include <netinet/in.h>
   12 #include <errno.h>
   13 #include <string.h>
   14 #include <strings.h>
   15 #include <unistd.h>
   16 #include <arpa/inet.h>
   17 #include <syslog.h>
   18 #include <signal.h>
   19 #include "portfwd.h"
   20 #include "forward.h"
   21 #include "util.h"
   22 #include "solve.h"
   23 #include "host_map.hpp"
   24 #include "iterator.hpp"
   25 
   26 int grandchild_pid[PORTFWD_MAX_FD];
   27 
   28 /*
   29  * Returns -1 on failure; file descriptor on success.
   30  */
   31 int tcp_connect(const struct ip_addr *ip, int port)
   32 {
   33   int rsd = socket(PF_INET, SOCK_STREAM, get_protonumber(P_TCP));
   34   if (rsd == -1) {
   35     syslog(LOG_ERR, "tcp_connect: Can't create TCP socket: %m");
   36     return -1;
   37   }
   38   DEBUGFD(syslog(LOG_DEBUG, "socket open: FD %d", rsd));
   39 
   40   struct sockaddr_in sa;
   41   sa.sin_family      = PF_INET;
   42   sa.sin_port        = htons(port);
   43   sa.sin_addr.s_addr = *((unsigned int *) ip->addr);
   44   memset((char *) sa.sin_zero, 0, sizeof(sa.sin_zero));
   45 
   46   if (connect(rsd, (struct sockaddr *) &sa, sizeof(sa))) {
   47     syslog(LOG_ERR, "tcp_connect: Can't connect to %s:%d: %m", inet_ntoa(sa.sin_addr), port);
   48     socket_close(rsd);
   49     return -1;
   50   }
   51 
   52   return rsd;
   53 }
   54 
   55 /*
   56  * Returns host_map success; NULL on failure.
   57  */
   58 host_map *tcp_match(const vector<host_map*> *map_list, const struct ip_addr *ip, int port)
   59 {
   60   host_map *hm;
   61   iterator<vector<host_map*>,host_map*> it(*map_list);
   62   for (it.start(); it.cont(); it.next()) {
   63     hm = it.get();
   64     if (hm->tcp_match(ip, port))
   65       return hm;
   66   }
   67   return 0;
   68 }
   69 
   70 void quit_handler(int sig)
   71 {
   72   ONVERBOSE(syslog(LOG_DEBUG, "child: quit_handler: Grandchild with PID %d exiting under request", getpid()));
   73 
   74   exit(0);
   75 }
   76 
   77 int simple_buf_copy(int src_fd, int trg_fd)
   78 {
   79   char buf[BUF_SZ];
   80   int rd = read(src_fd, buf, BUF_SZ);
   81   if (!rd)
   82     return -1;
   83   if (rd < 0) {
   84     syslog(LOG_ERR, "simple_copy: Failure reading from socket: %m");
   85     return -1;
   86   }
   87 
   88   int wr = write(trg_fd, buf, rd);
   89   if (wr == -1) {
   90     if (errno == EPIPE)
   91       ONVERBOSE2(syslog(LOG_DEBUG, "simple_copy: Broken pipe: %m"));
   92     return -1;
   93   }
   94   if (wr < rd) {
   95     ONVERBOSE(syslog(LOG_WARNING, "simple_copy: Partial write to socket: %m"));
   96     return -1;
   97   }
   98 
   99   return 0;
  100 }
  101 
  102 void simple_tcp_forward(int sd, struct ip_addr *remote_ip, int remote_port)
  103 {
  104   int dest_fd[PORTFWD_MAX_FD];
  105 
  106   fd_set fds, tmp_fds;
  107   int fd_set_len = sizeof(fd_set);
  108   FD_ZERO(&fds);
  109   int maxfd = 0;
  110   fdset(sd, &fds, &maxfd);
  111   int nd;
  112 
  113   for (;;) { /* forever */
  114     /*
  115      * Restores tmp_fds from fds.
  116      */
  117     memcpy(&tmp_fds, &fds, fd_set_len);
  118 
  119     /*
  120      * Wait for event: connection on sd or data on anyone else.
  121      */
  122     DEBUGFD(syslog(LOG_DEBUG, "simple_forward: TCP select(): %d FDs", maxfd));
  123     nd = select(maxfd, &tmp_fds, 0, 0, 0);
  124     if (nd == -1) {
  125       syslog(LOG_ERR, "simple_forward: TCP select() failed: %m");
  126       continue;
  127     }
  128 
  129     /*
  130      * Let's handle sd here (mother socket).
  131      */
  132     if (FD_ISSET(sd, &tmp_fds)) {
  133 
  134       --nd;
  135 
  136       /*
  137        * Clear sd so it's ignored below in the
  138        * loop for the client sockets.
  139        */
  140       FD_CLR(sd, &tmp_fds); 
  141 
  142       struct sockaddr_in cli_sa;
  143       socklen_t cli_sa_len = sizeof(cli_sa);
  144       int csd = accept(sd, (struct sockaddr *) &cli_sa, &cli_sa_len);
  145       if (csd < 0)
  146     syslog(LOG_ERR, "simple_forward: Can't accept TCP socket: %m");
  147       else {
  148     int cli_port = ntohs(cli_sa.sin_port);
  149     ONVERBOSE(syslog(LOG_DEBUG, "simple_forward: TCP connection from %s:%d", inet_ntoa(cli_sa.sin_addr), cli_port));
  150 
  151     /*
  152      * Connect to destination.
  153      */
  154       
  155     int rsd = tcp_connect(remote_ip, remote_port);
  156     if (rsd != -1) {
  157       if ((csd >= PORTFWD_MAX_FD) || (rsd >= PORTFWD_MAX_FD)) {
  158         syslog(LOG_ERR, "simple_forward: Destination socket descriptors overflow");
  159         socket_close(csd);
  160         socket_close(rsd);
  161       }
  162       else {
  163         /*
  164          * Add pair of communicating sockets.
  165          */
  166         fdset(csd, &fds, &maxfd);
  167         fdset(rsd, &fds, &maxfd);
  168       
  169         /*
  170          * Save peers so they can be remembered later.
  171          */
  172         dest_fd[csd] = rsd;
  173         dest_fd[rsd] = csd;
  174       }
  175     }
  176       }
  177 
  178     } /* sd (mother socket) handled */
  179 
  180     /*
  181      * Now all other sockets.
  182      */
  183     for (int src_fd = 0; nd; ++src_fd)
  184       if (FD_ISSET(src_fd, &tmp_fds)) {
  185     --nd;
  186     int trg_fd = dest_fd[src_fd];
  187     /*
  188      * Copy data.
  189      */
  190     int fail = simple_buf_copy(src_fd, trg_fd);
  191     if (fail) {
  192       /*
  193        * Remove pair of communicating sockets.
  194        */
  195       DEBUGFD(syslog(LOG_DEBUG, "simple_forward: closed socket (FD %d or %d)", src_fd, trg_fd));
  196 
  197       fdclear(src_fd, &fds, &maxfd);
  198       fdclear(trg_fd, &fds, &maxfd);
  199       socket_close(src_fd);
  200       socket_close(trg_fd);
  201     }
  202       }
  203 
  204   } /* main loop */
  205 
  206 }
  207 
  208 int ftp_spawn(struct ip_addr *local_ip, int *local_port, struct ip_addr *remote_ip, int remote_port)
  209 {
  210   int sd = tcp_listen(local_ip, local_port, 3);
  211   if (sd == -1) {
  212     syslog(LOG_ERR, "FTP spawn: Can't listen: %m");
  213     return -1;
  214   }
  215 
  216   pid_t pid = fork();
  217 
  218   /* Fork failed? */
  219   if (pid < 0) {
  220 
  221     /* Fork failed */
  222 
  223     syslog(LOG_ERR, "FTP spawn: fork() failed: %m");
  224 
  225     socket_close(sd); /* the socket won't be used at all */
  226     return pid;
  227   }
  228 
  229   if (pid) {
  230 
  231     /* Child */
  232 
  233     socket_close(sd); /* the child won't use the socket */
  234     return pid;
  235   }
  236 
  237   /* Grandchild */
  238 
  239   void (*prev_handler)(int);
  240   prev_handler = signal(SIGCHLD, SIG_IGN);
  241   if (prev_handler == SIG_ERR) {
  242     syslog(LOG_ERR, "signal() failed on ignore: %m");
  243     exit(1);
  244   }
  245   prev_handler = signal(SIGUSR1, quit_handler);
  246   if (prev_handler == SIG_ERR) {
  247     syslog(LOG_ERR, "signal() failed for grandchild's quit handler: %m");
  248     exit(1);
  249   }
  250 
  251   simple_tcp_forward(sd, remote_ip, remote_port);
  252 
  253   syslog(LOG_ERR, "Grandchild exiting (!)");
  254   exit(1);
  255 }
  256 
  257 void gc_clean(int fd)
  258 {
  259   pid_t pid = grandchild_pid[fd];
  260   if (pid != -1) {
  261     ONVERBOSE(syslog(LOG_DEBUG, "Requesting termination of PID %d for FD %d", pid, fd));
  262 
  263     if (kill(pid, SIGUSR1))
  264       syslog(LOG_ERR, "Can't request grandchild termination for PID: %d: %m", pid);
  265     grandchild_pid[fd] = -1;
  266   }
  267 }
  268 
  269 void gc_fill(int fd, pid_t pid)
  270 {
  271   gc_clean(fd);
  272 
  273   grandchild_pid[fd] = pid;
  274 
  275   ONVERBOSE(syslog(LOG_DEBUG, "PID %d stored for termination request on FD %d", pid, fd));
  276 }
  277 
  278 int ftp_active(const struct ip_addr *actv_ip, char *buf, int *rd, int src_fd, int trg_fd)
  279 {
  280   if (strncasecmp(buf, "port", 4))
  281     return 0;
  282 
  283   ONVERBOSE(syslog(LOG_DEBUG, "Active FTP request detected: %s", buf));
  284 
  285   char *i = strchr(buf, ' ');
  286   if (!i) {
  287     syslog(LOG_ERR, "Missing remote address in active FTP request");
  288     return -1;
  289   }
  290   ++i;
  291 
  292   int ad[4];
  293   int port[2];
  294   
  295   if (sscanf(i, "%d,%d,%d,%d,%d,%d", 
  296         &ad[0], &ad[1], &ad[2], &ad[3],
  297         &port[0], &port[1]) < 6) {
  298     syslog(LOG_ERR, "Active FTP request mismatch");
  299     return -1;
  300   }
  301 
  302   /*
  303    * Remote address.
  304    */
  305 
  306   char addr[4];
  307   addr[0] = ad[0];
  308   addr[1] = ad[1];
  309   addr[2] = ad[2];
  310   addr[3] = ad[3];
  311 
  312   struct ip_addr remote_ip;
  313   remote_ip.len = addr_len;
  314   remote_ip.addr = addr;
  315   int remote_port = (port[0] << 8) | port[1];
  316 
  317   ONVERBOSE(syslog(LOG_DEBUG, "Remote address extracted: %s:%d", addrtostr(&remote_ip), remote_port));
  318 
  319   /*
  320    * Local address (0.0.0.0).
  321    */
  322 
  323   int laddr = INADDR_ANY;
  324   struct ip_addr local_ip;
  325   local_ip.len = addr_len;
  326   local_ip.addr = (char *) &laddr;
  327 
  328   /*
  329    * FTP forwarder.
  330    */
  331     
  332   int local_port = 0;
  333 
  334   pid_t pid = ftp_spawn(&local_ip, &local_port, &remote_ip, remote_port);
  335   if (pid == -1) {
  336     syslog(LOG_ERR, "Can't spawn FTP forwarder");
  337     /* free(local_ip.addr); */
  338     return -1;
  339   }
  340 
  341   /*
  342    * Address rewriting (IP given by ftp-active-mode-on).
  343    */
  344   const char *local_addr = actv_ip->addr;
  345   if (snprintf(buf, BUF_SZ, "PORT %u,%u,%u,%u,%u,%u\n", 
  346            (unsigned char) local_addr[0], 
  347            (unsigned char) local_addr[1], 
  348            (unsigned char) local_addr[2], 
  349            (unsigned char) local_addr[3],
  350            (local_port >> 8) & 0xFF, local_port & 0xFF) == -1)
  351     syslog(LOG_WARNING, "Active FTP request truncated");
  352 
  353   *rd = strlen(buf);
  354 
  355   /*
  356    * Store forwarder's PID so it can be terminated.
  357    */
  358   gc_fill(src_fd, pid);
  359   gc_fill(trg_fd, pid);
  360 
  361   return 0;
  362 }
  363 
  364 int ftp_passive(const struct ip_addr *pasv_ip, char *buf, int *rd, int src_fd, int trg_fd)
  365 {
  366   if (memcmp(buf, "227", 3))
  367     return 0;
  368 
  369   ONVERBOSE(syslog(LOG_DEBUG, "Passive FTP reply detected: %s", buf));
  370 
  371   char *i = strchr(buf, '(');
  372   if (!i) {
  373     syslog(LOG_ERR, "Missing remote address in passive FTP reply");
  374     return -1;
  375   }
  376   ++i;
  377 
  378   int ad[4];
  379   int port[2];
  380   
  381   if (sscanf(i, "%d,%d,%d,%d,%d,%d", 
  382         &ad[0], &ad[1], &ad[2], &ad[3],
  383         &port[0], &port[1]) < 6) {
  384     syslog(LOG_ERR, "Passive FTP reply mismatch");
  385     return -1;
  386   }
  387 
  388   /*
  389    * Remote address.
  390    */
  391 
  392   char addr[4];
  393   addr[0] = ad[0];
  394   addr[1] = ad[1];
  395   addr[2] = ad[2];
  396   addr[3] = ad[3];
  397 
  398   struct ip_addr remote_ip;
  399   remote_ip.len = addr_len;
  400   remote_ip.addr = addr;
  401   int remote_port = (port[0] << 8) | port[1];
  402 
  403   ONVERBOSE(syslog(LOG_DEBUG, "Remote address extracted: %s:%d", addrtostr(&remote_ip), remote_port));
  404 
  405   /*
  406    * Local address (0.0.0.0).
  407    */
  408 
  409   int laddr = INADDR_ANY;
  410   struct ip_addr local_ip;
  411   local_ip.len = addr_len;
  412   local_ip.addr = (char *) &laddr;
  413 
  414   /*
  415    * FTP forwarder.
  416    */
  417     
  418   int local_port = 0;
  419 
  420   pid_t pid = ftp_spawn(&local_ip, &local_port, &remote_ip, remote_port);
  421   if (pid == -1) {
  422     syslog(LOG_ERR, "Can't spawn FTP forwarder");
  423     return -1;
  424   }
  425 
  426   /*
  427    * Address rewriting (IP given by ftp-passive-mode-on).
  428    */
  429   const char *local_addr = pasv_ip->addr;
  430   if (snprintf(buf, BUF_SZ, "227 Portfwd Passive Mode (%u,%u,%u,%u,%u,%u)\n", 
  431            (unsigned char) local_addr[0], 
  432            (unsigned char) local_addr[1], 
  433            (unsigned char) local_addr[2], 
  434            (unsigned char) local_addr[3],
  435            (local_port >> 8) & 0xFF, local_port & 0xFF) == -1)
  436     syslog(LOG_WARNING, "Passive FTP reply truncated");
  437 
  438   *rd = strlen(buf);
  439 
  440   /*
  441    * Store forwarder's PID so it can be terminated.
  442    */
  443   gc_fill(src_fd, pid);
  444   gc_fill(trg_fd, pid);
  445 
  446   return 0;
  447 }
  448 
  449 int buf_copy(int src_fd, int trg_fd, const struct ip_addr *actv_ip, const struct ip_addr *pasv_ip)
  450 {
  451   char buf[BUF_SZ];
  452   int rd = read(src_fd, buf, BUF_SZ);
  453   if (!rd)
  454     return -1;
  455   if (rd < 0) {
  456     syslog(LOG_ERR, "copy: Failure reading from socket: %m");
  457     return -1;
  458   }
  459 
  460   if (actv_ip)
  461     if (ftp_active(actv_ip, buf, &rd, src_fd, trg_fd))
  462       return -1;
  463 
  464   if (pasv_ip)
  465     if (ftp_passive(pasv_ip, buf, &rd, src_fd, trg_fd))
  466       return -1;
  467 
  468   int wr = write(trg_fd, buf, rd);
  469   if (wr == -1) {
  470     if (errno == EPIPE)
  471       ONVERBOSE2(syslog(LOG_DEBUG, "copy: Broken pipe: %m"));
  472     return -1;
  473   }
  474   if (wr < rd) {
  475     ONVERBOSE(syslog(LOG_WARNING, "copy: Partial write to socket: %m"));
  476     return -1;
  477   }
  478 
  479   return 0;
  480 }
  481 
  482 int drop_privileges(int uid, int gid)
  483 {
  484   if (gid != -1)
  485     if (setregid(gid, gid)) {
  486       syslog(LOG_ERR, "Can't switch to group: %d: %m", gid);
  487       return -1;
  488     }
  489 
  490   if (uid != -1)
  491     if (setreuid(uid, uid)) {
  492       syslog(LOG_ERR, "Can't switch to user: %d: %m", uid);
  493       return -1;
  494     }
  495 
  496   return 0;
  497 }
  498 
  499 int tcp_listen(const struct ip_addr *ip, int *port, int queue)
  500 {
  501   int sd = socket(PF_INET, SOCK_STREAM, get_protonumber(P_TCP));
  502   if (sd == -1) {
  503     syslog(LOG_ERR, "listen: Can't create TCP socket: %m");
  504     return -1;
  505   }
  506   DEBUGFD(syslog(LOG_DEBUG, "socket open: FD %d", sd));
  507     
  508   int prt = port ? *port : 0;
  509   
  510   struct sockaddr_in sa;
  511   socklen_t sa_len = sizeof(sa);
  512   sa.sin_family      = PF_INET;
  513   sa.sin_port        = htons(prt);
  514   sa.sin_addr.s_addr = *((unsigned int *) ip->addr);
  515   memset((char *) sa.sin_zero, 0, sizeof(sa.sin_zero));
  516 
  517 
  518 #ifndef NO_SO_REUSEADDR
  519   /*
  520    * Allow reuse of local addresses 
  521    */
  522   {
  523     int one = 1;
  524     
  525     ONVERBOSE(syslog(LOG_DEBUG, "Setting SO_REUSEADDR for TCP listening socket on port %d", prt));
  526 
  527     if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) == -1)
  528       syslog(LOG_WARNING, "tcp_listen(): Can't allow reuse of local addresses: setsockopt(SO_REUSEADDR) failed: %m") ;
  529   }
  530 #endif /* NO_SO_REUSEADDR */
  531 
  532 
  533   if (bind(sd, (struct sockaddr *) &sa, sa_len)) {
  534     syslog(LOG_ERR, "listen: Can't bind TCP socket: %m: %s:%d", inet_ntoa(sa.sin_addr), prt);
  535     fprintf(stderr, "listen: Can't bind TCP socket: %m: %s:%d", inet_ntoa(sa.sin_addr), prt);
  536     socket_close(sd);
  537     return -1;
  538   }
  539 
  540   if (getsockname(sd, (struct sockaddr *) &sa, &sa_len)) {
  541     syslog(LOG_ERR, "listen: Can't get local sockname: %m");
  542     fprintf(stderr, "listen: Can't get local sockname: %m");
  543     return -1;
  544   }
  545   prt = ntohs(sa.sin_port);
  546 
  547   if (listen(sd, queue)) {
  548     syslog(LOG_ERR, "listen: Can't listen TCP socket: %m");
  549     fprintf(stderr, "listen: Can't listen TCP socket: %m");
  550     socket_close(sd);
  551     return -1;
  552   }
  553 
  554   syslog(LOG_DEBUG, "Listening TCP connection on %s:%d", inet_ntoa(sa.sin_addr), prt);
  555 
  556   if (port)
  557     *port = prt;
  558 
  559   return sd;
  560 }
  561 
  562 void close_sockets(vector<int> *port_list) 
  563 {
  564   iterator<vector<int>,int> it(*port_list);
  565   for (it.start(); it.cont(); it.next())
  566     close(it.get());
  567   DEBUGFD(syslog(LOG_DEBUG, "close_sockets(): Sockets closed: %d", port_list->get_size()));
  568 }
  569 
  570 
  571 class sleeper {
  572 private:
  573   static sleeper *sleepers;
  574   static sleeper *tail;
  575 
  576   time_t timeout;
  577   host_map *hm;
  578   struct sockaddr_in cli_sa;
  579   struct ip_addr ip;
  580   int cli_port;
  581   const struct ip_addr *src;
  582   struct sockaddr_in local_cli_sa;
  583   int csd;
  584   fd_set *fds;
  585   int *maxfd;
  586   int *dest_fd;
  587 
  588   sleeper *next;
  589 
  590 public:
  591   sleeper(host_map *hm, struct sockaddr_in *cli_sa, struct ip_addr *ip,
  592           int cli_port, const struct ip_addr *src, struct sockaddr_in *local_cli_sa,
  593           int csd, fd_set *fds, int *dest_fd, int *maxfd) {
  594     this->hm = hm;
  595     this->cli_sa = *cli_sa;
  596     this->ip = *ip;
  597     this->cli_port = cli_port;
  598     this->src = src;
  599     this->local_cli_sa = *local_cli_sa;
  600     this->csd = csd;
  601     this->fds = fds;
  602     this->dest_fd = dest_fd;
  603     this->maxfd = maxfd;
  604     this->next = NULL;
  605   }
  606 
  607   void queue() {
  608     this->timeout = time(NULL) + 10;
  609     if (tail)
  610       tail->next = this;
  611     else
  612       sleepers = tail = this;
  613   }
  614 
  615   int pipe() {
  616     int rsd = 0;
  617     socklen_t cli_sa_len = sizeof(cli_sa);
  618 
  619     if (hm->pipe(&rsd, &cli_sa, cli_sa_len, &ip, cli_port, src, &local_cli_sa)) {
  620       return 1;
  621     }
  622 
  623     if ((csd >= PORTFWD_MAX_FD) || (rsd >= PORTFWD_MAX_FD)) {
  624       syslog(LOG_ERR, "Destination socket descriptors overflow");
  625       socket_close(csd);
  626       socket_close(rsd);
  627       return 0;
  628     }
  629 
  630     /*
  631      * Add pair of communicating sockets.
  632      */
  633     fdset(csd, fds, maxfd);
  634     fdset(rsd, fds, maxfd);
  635   
  636     /*
  637      * Save peers so they can be remembered later.
  638      */
  639     dest_fd[csd] = rsd;
  640     dest_fd[rsd] = csd;
  641     return 0;
  642   }
  643 
  644   static void handle_first() {
  645     sleeper *s = sleepers;
  646     sleepers = sleepers->next;
  647     if (sleepers == NULL)
  648       tail = NULL;
  649     if (s->pipe()) {
  650       s->queue();
  651     } else {
  652       delete s;
  653     }
  654   }
  655 
  656   static int ready() {
  657     return sleepers != NULL && sleepers->timeout <= time(NULL);
  658   }
  659 
  660   static int queued() {
  661     return sleepers != NULL;
  662   }
  663 
  664   static time_t earliest() {
  665     return sleepers->timeout;
  666   }
  667 
  668 };
  669 
  670 
  671 sleeper *sleeper::sleepers = NULL;
  672 sleeper *sleeper::tail = NULL;
  673 
  674 
  675 void mother_socket(int sd, fd_set *fds, int dest_fd[], int *maxfd, vector<host_map*> *map_list, const struct ip_addr *src, int fragile)
  676 {
  677   struct sockaddr_in cli_sa;
  678   socklen_t cli_sa_len = sizeof(cli_sa);
  679 
  680   /*
  681    * Accept new client on "csd"
  682    */
  683   int csd = accept(sd, (struct sockaddr *) &cli_sa, &cli_sa_len);
  684   if (csd < 0) {
  685     syslog(LOG_ERR, "Can't accept TCP socket: %m");
  686     return;
  687   }
  688     
  689   int cli_port = ntohs(cli_sa.sin_port);
  690 
  691   /*
  692    * Get local address
  693    */
  694   struct sockaddr_in local_cli_sa;
  695   socklen_t local_cli_sa_len = sizeof(local_cli_sa);
  696   if (getsockname(sd, (struct sockaddr *) &local_cli_sa, &local_cli_sa_len)) {
  697     syslog(LOG_ERR, "mother_socket(): Can't get local sockname: %m");
  698     socket_close(csd);
  699     return;
  700   }
  701 
  702   ONVERBOSE(syslog(LOG_DEBUG, "TCP connection from %s:%d", inet_ntoa(cli_sa.sin_addr), cli_port));
  703   
  704   /*
  705    * Check client address (ip, port).
  706    */
  707   struct ip_addr ip;
  708   ip.addr = (char *) &(cli_sa.sin_addr.s_addr);
  709   ip.len  = addr_len;
  710 
  711   host_map *hm = tcp_match(map_list, &ip, cli_port);
  712   if (!hm) {
  713     ONVERBOSE(syslog(LOG_DEBUG, "Address miss"));
  714     socket_close(csd);
  715     return;
  716   }
  717   ONVERBOSE(syslog(LOG_DEBUG, "Address match"));
  718 
  719   /*
  720    * Connect to destination on "rsd"
  721    */
  722   sleeper *s = new sleeper(hm, &cli_sa, &ip, cli_port, src, &local_cli_sa,
  723                            csd, fds, dest_fd, maxfd);
  724   if (s->pipe()) {
  725     if (fragile)
  726       s->queue();
  727     else {
  728       ONVERBOSE(syslog(LOG_DEBUG, "Could not connect to remote destination"));
  729       socket_close(csd);
  730       delete s;
  731     }
  732   }
  733 }
  734 
  735 void client_socket(int src_fd, fd_set *fds, int dest_fd[], int *maxfd, const struct ip_addr *actv_ip, const struct ip_addr *pasv_ip)
  736 {
  737   /*
  738    * Copy data.
  739    */
  740   int trg_fd = dest_fd[src_fd];
  741   int fail = buf_copy(src_fd, trg_fd, actv_ip, pasv_ip);
  742   if (fail) {
  743     /*
  744      * Remove pair of communicating sockets.
  745      */
  746     DEBUGFD(syslog(LOG_DEBUG, "client_socket: closed socket (FD %d or %d)", src_fd, trg_fd));
  747 
  748     fdclear(src_fd, fds, maxfd);
  749     fdclear(trg_fd, fds, maxfd);
  750     socket_close(src_fd);
  751     socket_close(trg_fd);
  752     gc_clean(src_fd);
  753     gc_clean(trg_fd);
  754   }
  755 }
  756 
  757 void tcp_forward(const struct ip_addr *listen, const struct ip_addr *source, vector<int> *port_list,
  758                  vector<host_map*> *map_list, const struct ip_addr *actv_ip, const struct ip_addr *pasv_ip,
  759                  int uid, int gid, int fragile)
  760 {
  761   fd_set fds, tmp_fds, ms_fds;
  762   int fd_set_len = sizeof(fd_set);
  763   int maxfd = 0;
  764 
  765   FD_ZERO(&fds);
  766   FD_ZERO(&ms_fds);
  767 
  768   iterator<vector<int>,int> it(*port_list);
  769   for (it.start(); it.cont(); it.next()) {
  770 
  771     int port = it.get();
  772     int sd = tcp_listen(listen, &port, 3);
  773     if (sd == -1) {
  774       close_sockets(port_list);
  775       return;
  776     }
  777 
  778     fdset(sd, &fds, &maxfd); /* Add sd to set for select() */
  779     FD_SET(sd, &ms_fds);     /* Mark sd as mother socket */
  780   }
  781 
  782   if (drop_privileges(uid, gid)) {
  783     close_sockets(port_list);
  784     return;
  785   }
  786 
  787   int dest_fd[PORTFWD_MAX_FD];
  788 
  789   for (int fd = 0; fd < PORTFWD_MAX_FD; ++fd)
  790     grandchild_pid[fd] = -1;
  791 
  792   for (;;) { /* forever */
  793     /*
  794      * Restores tmp_fds from fds.
  795      */
  796     memcpy(&tmp_fds, &fds, fd_set_len);
  797 
  798     struct timeval tv;
  799     struct timeval *tvp = NULL;
  800     if (sleeper::queued()) {
  801       time_t now = time(NULL);
  802       tv.tv_sec = MAX(sleeper::earliest() - now, 0);
  803       tv.tv_usec = 0;
  804       tvp = &tv;
  805     }
  806 
  807     /*
  808      * Wait for event: connection on mother sockets or data on anything else.
  809      */
  810     DEBUGFD(syslog(LOG_DEBUG, "TCP select(): %d FDs", maxfd));
  811     int nd = select(maxfd, &tmp_fds, 0, 0, tvp);
  812     if (nd == -1) {
  813       if (errno != EINTR)
  814     syslog(LOG_ERR, "TCP select() failed: %m");
  815       continue;
  816     }
  817 
  818     while (sleeper::ready())
  819         sleeper::handle_first();
  820 
  821     for (int fd = 0; nd; ++fd)
  822       if (FD_ISSET(fd, &tmp_fds)) {
  823     --nd;
  824     if (FD_ISSET(fd, &ms_fds))
  825       mother_socket(fd, &fds, dest_fd, &maxfd, map_list, source, fragile);
  826     else
  827       client_socket(fd, &fds, dest_fd, &maxfd, actv_ip, pasv_ip);
  828       }
  829 
  830   } /* main loop */
  831 
  832 }
  833 
  834 static void do_udp_forward(const struct ip_addr *source, 
  835                const struct sockaddr_in *cli_sa, 
  836                const struct sockaddr_in *local_cli_sa,
  837                vector<host_map*> *map_list, 
  838                const char *buf, int buf_len)
  839 {
  840   int            port = ntohs(cli_sa->sin_port);
  841   struct ip_addr ip;
  842 
  843   ONVERBOSE(syslog(LOG_DEBUG, "UDP packet from: %s:%d\n", 
  844            inet_ntoa(cli_sa->sin_addr), 
  845            ntohs(cli_sa->sin_port)));
  846 
  847   ip.addr = (char *) &(cli_sa->sin_addr.s_addr);
  848   ip.len  = addr_len;
  849 
  850   iterator<vector<host_map*>,host_map*> it(*map_list);
  851   for (it.start(); it.cont(); it.next()) {
  852     host_map *hm = it.get();
  853     if (hm->udp_match(&ip, port, buf, buf_len)) {
  854       hm->udp_forward(source, cli_sa, local_cli_sa, &ip, port, buf, buf_len);
  855       break;
  856     }
  857   }
  858 }
  859 
  860 int udp_listen(const struct ip_addr *ip, int port)
  861 {
  862   int sd = socket(PF_INET, SOCK_DGRAM, get_protonumber(P_UDP));
  863   if (sd == -1) {
  864     syslog(LOG_ERR, "Can't create UDP socket: %m");
  865     return -1;
  866   }
  867   DEBUGFD(syslog(LOG_DEBUG, "socket open: FD %d", sd));
  868     
  869   struct sockaddr_in sa;
  870   sa.sin_family      = PF_INET;
  871   sa.sin_port        = htons(port);
  872   sa.sin_addr.s_addr = *((unsigned int *) ip->addr);
  873   memset((char *) sa.sin_zero, 0, sizeof(sa.sin_zero));
  874 
  875   if (bind(sd, (struct sockaddr *) &sa, sizeof(sa))) {
  876     syslog(LOG_ERR, "Can't bind UDP socket: %m: %s:%d", inet_ntoa(sa.sin_addr), port);
  877     socket_close(sd);
  878     return -1;
  879   }
  880 
  881   /* 
  882    * Allow incoming broadcast datagrams
  883    */
  884 #ifndef NO_SO_BROADCAST
  885   {
  886     int one = 1;
  887 
  888     ONVERBOSE2(syslog(LOG_DEBUG, "Setting SO_BROADCAST for incoming UDP socket"));
  889 
  890     if (setsockopt(sd, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof(one)))
  891       syslog(LOG_ERR, "host_map::udp_forward(): Can't allow broadcast datagrams for incoming UDP socket port %d: setsockopt(SO_BROADCAST) failed: %m", port);
  892   }
  893 #endif /* NO_SO_BROADCAST */
  894 
  895   ONVERBOSE(syslog(LOG_DEBUG, "Waiting UDP packet on %s:%d", inet_ntoa(sa.sin_addr), port));
  896 
  897   return sd;
  898 }
  899 
  900 void udp_forward(const struct ip_addr *listen_addr, const struct ip_addr *source, vector<int> *port_list, vector<host_map*> *map_list, int uid, int gid)
  901 {
  902   fd_set fds, tmp_fds;
  903   int fd_set_len = sizeof(fd_set);
  904   int maxfd = 0;
  905 
  906   FD_ZERO(&fds);
  907 
  908   iterator<vector<int>,int> it(*port_list);
  909   for (it.start(); it.cont(); it.next()) {
  910 
  911     int port = it.get();
  912     int sd = udp_listen(listen_addr, port);
  913     if (sd == -1) {
  914       close_sockets(port_list);
  915       return;
  916     }
  917 
  918     fdset(sd, &fds, &maxfd);
  919   }
  920 
  921   if (drop_privileges(uid, gid)) {
  922     close_sockets(port_list);
  923     return;
  924   }
  925 
  926   char buf[BUF_SZ];
  927   struct sockaddr_in cli_sa;
  928   socklen_t cli_sa_len = sizeof(struct sockaddr_in);
  929 
  930   for (;;) { /* forever */
  931     /*
  932      * Restores tmp_fds from fds.
  933      */
  934     memcpy(&tmp_fds, &fds, fd_set_len);
  935 
  936     /*
  937      * Wait for data.
  938      */
  939     DEBUGFD(syslog(LOG_DEBUG, "UDP select(): %d FDs", maxfd));
  940     int nd = select(maxfd, &tmp_fds, 0, 0, 0);
  941     if (nd == -1) {
  942       if (errno != EINTR)
  943     syslog(LOG_ERR, "UDP select() failed: %m");
  944       continue;
  945     }
  946 
  947     for (int fd = 0; nd; ++fd)
  948       if (FD_ISSET(fd, &tmp_fds)) {
  949     --nd;
  950 
  951     int rd = recvfrom(fd, buf, BUF_SZ, 0, (struct sockaddr *) &cli_sa, &cli_sa_len);
  952     if (rd == -1) {
  953       syslog(LOG_ERR, "Can't receive UDP packet: %m");
  954       continue;
  955     }
  956 
  957     /*
  958      * Get local address
  959      */
  960     struct sockaddr_in local_cli_sa;
  961     socklen_t local_cli_sa_len = sizeof(local_cli_sa);
  962     if (getsockname(fd, (struct sockaddr *) &local_cli_sa, &local_cli_sa_len)) {
  963       syslog(LOG_ERR, "udp_forward(): Can't get local sockname: %m");
  964       memset(&local_cli_sa, 0, local_cli_sa_len);
  965     }
  966 
  967     do_udp_forward(source, &cli_sa, &local_cli_sa, map_list, buf, rd);
  968       }
  969 
  970   } /* main loop */
  971 
  972 }
  973