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  */
tcp_connect(const struct ip_addr * ip,int port)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  */
tcp_match(const vector<host_map * > * map_list,const struct ip_addr * ip,int port)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 
quit_handler(int sig)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 
simple_buf_copy(int src_fd,int trg_fd)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 
simple_tcp_forward(int sd,struct ip_addr * remote_ip,int remote_port)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 
ftp_spawn(struct ip_addr * local_ip,int * local_port,struct ip_addr * remote_ip,int remote_port)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 
gc_clean(int fd)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 
gc_fill(int fd,pid_t pid)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 
ftp_active(const struct ip_addr * actv_ip,char * buf,int * rd,int src_fd,int trg_fd)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 
ftp_passive(const struct ip_addr * pasv_ip,char * buf,int * rd,int src_fd,int trg_fd)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 
buf_copy(int src_fd,int trg_fd,const struct ip_addr * actv_ip,const struct ip_addr * pasv_ip)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 
drop_privileges(int uid,int gid)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 
tcp_listen(const struct ip_addr * ip,int * port,int queue)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 
close_sockets(vector<int> * port_list)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:
sleeper(host_map * hm,struct sockaddr_in * cli_sa,struct ip_addr * ip,int cli_port,const struct ip_addr * src,struct sockaddr_in * local_cli_sa,int csd,fd_set * fds,int * dest_fd,int * maxfd)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 
queue()607   void queue() {
608     this->timeout = time(NULL) + 10;
609     if (tail)
610       tail->next = this;
611     else
612       sleepers = tail = this;
613   }
614 
pipe()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 
handle_first()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 
ready()656   static int ready() {
657     return sleepers != NULL && sleepers->timeout <= time(NULL);
658   }
659 
queued()660   static int queued() {
661     return sleepers != NULL;
662   }
663 
earliest()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 
mother_socket(int sd,fd_set * fds,int dest_fd[],int * maxfd,vector<host_map * > * map_list,const struct ip_addr * src,int fragile)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 
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)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 
tcp_forward(const struct ip_addr * listen,const struct ip_addr * source,vector<int> * port_list,vector<host_map * > * map_list,const struct ip_addr * actv_ip,const struct ip_addr * pasv_ip,int uid,int gid,int fragile)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 
do_udp_forward(const struct ip_addr * source,const struct sockaddr_in * cli_sa,const struct sockaddr_in * local_cli_sa,vector<host_map * > * map_list,const char * buf,int buf_len)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 
udp_listen(const struct ip_addr * ip,int port)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 
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)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 
974