3 * redir - a utility for redirecting tcp connections
5 * Author: Nigel Metheringham
6 * Nigel.Metheringham@ThePLAnet.net
8 * Based on, but much modified from, code originally written by
9 * sammy@freenet.akron.oh.us - original header is below.
11 * redir is released under the GNU General Public license,
12 * version 2, or at your discretion, any later version.
17 * redir is currently maintained by Sam Creasey (sammy@oh.verio.com).
18 * Please send patches, etc. there.
23 * added some nice new features:
25 * --bind_addr=my.other.ip.address
26 * forces to use my.other.ip.address for the outgoing connection
28 * you can also specify, that redir listens not on all IP addresses of
29 * your system but only for the given one, i.e.:
30 * if my host has the addresses
31 * irc.thishost.my.domain and mail.thishost.my.domain
32 * but you want that your users do connect for the irc redir service
33 * only on irc.thishost.my.domain, then do it this way:
34 * redir irc.fu-berlin.de irc.thishost.mydomain:6667 6667
36 * addr1.first.domain 6667 redirects to irc.first.net port 6667
37 * and addr2.second.domain 6667 redirects to irc.second.net port 6667
38 * while addr1 and addr2 are the same maschine and the ports can be equal.
41 * - thomas <thomas@x-berg.in-berlin.de>, <dl9sau@db0tud.ampr.org>
43 * btw: i tried without success implementing code for the following scenario:
44 * redir --force_addr irc.fu-berlin.de 6667 6667
45 * if "--force_addr" is given and a user connects to my system, that address
46 * of my system will be used on the outgoing connection that the user
48 * i was not successful to determine, to which of my addresses the user
52 /* 990320 added support for ftp connection done by the client, now this code
53 * should work for all ftp clients.
55 * - harald <harald.holzer@eunet.at>
58 /* 991221 added options to simulate a slow connection and to limit
61 * - Emmanuel Chantr�au <echant@maretmanu.org>
64 #define VERSION "2.2.1"
73 #include <sys/types.h>
74 #include <sys/socket.h>
77 #include <netinet/in.h>
78 #include <arpa/inet.h>
82 #ifdef USE_TCP_WRAPPERS
86 #define debug(x) if (dodebug) fprintf(stderr, x)
87 #define debug1(x,y) if (dodebug) fprintf(stderr, x, y)
89 /* let's set up some globals... */
92 unsigned char reuse_addr
= 1;
93 unsigned char linger_opt
= 0;
94 char * bind_addr
= NULL
;
95 struct sockaddr_in addr_out
;
105 int max_bandwidth
= 0;
107 int wait_in_out
=3; /* bit 0: wait for "in", bit 1: wait for "out" */
112 unsigned int bufsize
=4096;
113 char *connect_str
= NULL
; /* CONNECT string passed to proxy */
117 /* what ftp to redirect */
122 #ifdef USE_TCP_WRAPPERS
123 struct request_info request
;
124 int allow_severity
= LOG_INFO
;
125 int deny_severity
= LOG_WARNING
;
126 #endif /* USE_TCP_WRAPPERS */
129 #define strrchr rindex
130 #endif /* NEED_STRRCHR */
135 /* prototype anything needing it */
136 void do_accept(int servsock
, struct sockaddr_in
*target
);
137 int bindsock(char *addr
, int port
, int fail
);
140 /* Used in this program to write something in a socket, it has the same
141 parameters and return value as "write", but with the flag "in": true if
142 it's the "in" socket and false if it's the "out" socket */
143 static inline ssize_t
redir_write (int fd
, const void *buf
, size_t size
, int in
)
148 wait
=in
? wait_in
: wait_out
;
149 if( random_wait
> 0 && wait
) {
151 struct timeval waitbw
; /* for bandwidth */
156 rand_time
=rand()%(random_wait
*2);
157 debug1("random wait: %u\n", rand_time
);
158 waitbw
.tv_sec
=rand_time
/1000;
159 waitbw
.tv_usec
=rand_time
%1000;
161 select (1, &empty
, NULL
, NULL
, &waitbw
);
164 result
=write(fd
, buf
, size
);
166 if( max_bandwidth
> 0 && wait
) {
169 struct timeval waitbw
; /* for bandwidth */
173 /* wait to be sure tu be below the allowed bandwidth */
175 debug1("bandwidth wait: %lu\n", 1000*bits
/max_bandwidth
);
176 waitbw
.tv_sec
=bits
/max_bandwidth
;
177 waitbw
.tv_usec
=(1000*(bits
%max_bandwidth
))/max_bandwidth
;
179 select (1, &empty
, NULL
, NULL
, &waitbw
);
185 /* macro if traffic shaper is disabled */
186 #define redir_write(fd, buf, size, in) write(fd, buf,size)
196 if (result
= (char *) malloc(strlen(str
) + 1))
201 #endif /* NEED_STRDUP */
204 redir_usage(char *name
)
206 fprintf(stderr
,"usage:\n");
208 "\t%s --lport=<n> --cport=<n> [options]\n",
210 fprintf(stderr
, "\t%s --inetd --cport=<n>\n", name
);
211 fprintf(stderr
, "\n\tOptions are:-\n");
212 fprintf(stderr
, "\t\t--lport=<n>\t\tport to listen on\n");
213 fprintf(stderr
, "\t\t--laddr=IP\t\taddress of interface to listen on\n");
214 fprintf(stderr
, "\t\t--cport=<n>\t\tport to connect to\n");
215 fprintf(stderr
, "\t\t--caddr=<host>\t\tremote host to connect to\n");
216 fprintf(stderr
, "\t\t--inetd\t\trun from inetd\n");
217 fprintf(stderr
, "\t\t--debug\t\toutput debugging info\n");
218 fprintf(stderr
, "\t\t--timeout=<n>\tset timeout to n seconds\n");
219 fprintf(stderr
, "\t\t--syslog\tlog messages to syslog\n");
220 fprintf(stderr
, "\t\t--name=<str>\ttag syslog messages with 'str'\n");
221 fprintf(stderr
, "\t\t--connect=<str>\tCONNECT string passed to proxy server\n");
222 #ifdef USE_TCP_WRAPPERS
223 fprintf(stderr
, "\t\t \tAlso used as service name for TCP wrappers\n");
224 #endif /* USE_TCP_WRAPPERS */
225 fprintf(stderr
, "\t\t--bind_addr=IP\tbind() outgoing IP to given addr\n");
228 fprintf(stderr
, "\t\t--ftp=<type>\t\tredirect ftp connections\n");
229 fprintf(stderr
, "\t\t\twhere type is either port, pasv, both\n");
232 fprintf(stderr
, "\t\t--transproxy\trun in linux's transparent proxy mode\n");
234 /* options for bandwidth */
235 fprintf(stderr
, "\t\t--bufsize=<octets>\tsize of the buffer\n");
236 fprintf(stderr
, "\t\t--maxbandwidth=<bit-per-sec>\tlimit the bandwidth\n");
237 fprintf(stderr
, "\t\t--random_wait=<millisec>\twait before each packet\n");
238 fprintf(stderr
, "\t\t--wait_in_out=<flag>\t1 wait for in, 2 out, 3 in&out\n");
239 /* end options for bandwidth */
241 fprintf(stderr
, "\n\tVersion %s.\n", VERSION
);
262 unsigned int * bufsize
,
269 static struct option long_options
[] = {
270 {"lport", required_argument
, 0, 'l'},
271 {"laddr", required_argument
, 0, 'a'},
272 {"cport", required_argument
, 0, 'r'},
273 {"caddr", required_argument
, 0, 'c'},
274 {"bind_addr", required_argument
, 0, 'b'},
275 {"debug", no_argument
, 0, 'd'},
276 {"timeout", required_argument
, 0, 't'},
277 {"inetd", no_argument
, 0, 'i'},
278 {"ident", required_argument
, 0, 'n'},
279 {"name", required_argument
, 0, 'n'},
280 {"syslog", no_argument
, 0, 's'},
281 {"ftp", required_argument
, 0, 'f'},
282 {"transproxy", no_argument
, 0, 'p'},
283 {"connect", required_argument
, 0, 'x'},
284 {"bufsize", required_argument
, 0, 'z'},
285 {"max_bandwidth", required_argument
, 0, 'm'},
286 {"random_wait", required_argument
, 0, 'w'},
287 {"wait_in_out", required_argument
, 0, 'o'},
288 {0,0,0,0} /* End marker */
291 int option_index
= 0;
294 struct servent
*portdesc
;
298 char *ftp_type
= NULL
;
306 while ((opt
= getopt_long(argc
, argv
, "disfpn:t:b:a:l:r:c:x:z:m:w:o:",
307 long_options
, &option_index
)) != -1) {
310 *connect_str
= optarg
;
313 *local_addr
= optarg
;
325 *target_addr
= optarg
;
337 *timeout
= atol(optarg
);
345 /* This is the ident which is added to syslog messages */
357 redir_usage(argv
[0]);
369 *bufsize
= (unsigned int)atol(optarg
);
373 *max_bandwidth
= atol(optarg
);
377 *random_wait
= atol(optarg
);
381 *wait_in_out
= atol(optarg
);
382 wait_in
=*wait_in_out
& 1;
383 wait_out
=*wait_in_out
& 2;
387 redir_usage(argv
[0]);
395 redir_usage(argv
[0]);
399 if ((portdesc
= getservbyname(tport
, "tcp")) != NULL
) {
400 *target_port
= ntohs(portdesc
->s_port
);
402 *target_port
= atol(tport
);
405 /* only check local port if not running from inetd */
409 redir_usage(argv
[0]);
413 if ((portdesc
= getservbyname(lport
, "tcp")) != NULL
)
414 *local_port
= ntohs(portdesc
->s_port
);
416 *local_port
= atol(lport
);
420 if ((ident
= (char *) strrchr(argv
[0], '/'))) {
428 /* some kind of ftp being forwarded? */
430 if(!strncasecmp(ftp_type
, "port", 4))
432 else if(!strncasecmp(ftp_type
, "pasv", 4))
434 else if(!strncasecmp(ftp_type
, "both", 4))
435 *ftp
= FTP_PORT
| FTP_PASV
;
437 redir_usage(argv
[0]);
443 openlog(ident
, LOG_PID
, LOG_DAEMON
);
449 /* with the --ftp option, this one changes passive mode replies from
450 the ftp server to point to a new redirector which we spawn,
451 now it also change the PORT commando when the client accept the
454 void ftp_clean(int send
, char *buf
, unsigned long *bytes
, int ftpsrv
)
458 int rporthi
, lporthi
;
459 int lportlo
, rportlo
;
463 int socksize
= sizeof(struct sockaddr_in
);
465 struct sockaddr_in newsession
;
466 struct sockaddr_in sockname
;
470 /* is this a port commando ? */
471 if(strncmp(buf
, "PORT", 4)) {
472 redir_write(send
, buf
, (*bytes
), REDIR_OUT
);
475 /* parse the old address out of the buffer */
476 port_start
= strchr(buf
, ' ');
478 sscanf(port_start
, " %d,%d,%d,%d,%d,%d", &remip
[0], &remip
[1],
479 &remip
[2], &remip
[3], &rporthi
, &rportlo
);
481 /* is this a passive mode return ? */
482 if(strncmp(buf
, "227", 3)) {
483 redir_write(send
, buf
, (*bytes
), REDIR_OUT
);
487 /* parse the old address out of the buffer */
488 port_start
= strchr(buf
, '(');
490 sscanf(port_start
, "(%d,%d,%d,%d,%d,%d", &remip
[0], &remip
[1],
491 &remip
[2], &remip
[3], &rporthi
, &rportlo
);
494 /* get the outside interface so we can listen */
495 if(getsockname(send
, (struct sockaddr
*)&sockname
, &socksize
) != 0) {
496 perror("getsockname");
500 rport
= (rporthi
<< 8) | rportlo
;
502 /* we need to listen on a port for the incoming connection.
503 we will use the port 0, so let the system pick one. */
505 localsock
= bindsock(inet_ntoa(sockname
.sin_addr
), 0, 1);
508 /* get the real info */
509 if(getsockname(localsock
, (struct sockaddr
*)&sockname
, &socksize
) < 0) {
510 perror("getsockname");
512 syslog(LOG_ERR
, "getsockname failed: %m");
516 lport
= ntohs(sockname
.sin_port
);
518 lporthi
=(lport
>> 8 ) & 0xff;
519 lportlo
=lport
& 0xff;
521 /* check to see if we bound */
522 if(localsock
== -1) {
523 fprintf(stderr
, "ftp: unable to bind new listening address\n");
527 /* send the new port and ipaddress to the server */
528 (*bytes
) = sprintf(buf
, "PORT %d,%d,%d,%d,%d,%d\n",
529 sockname
.sin_addr
.s_addr
& 0xff,
530 (sockname
.sin_addr
.s_addr
>> 8) & 0xff,
531 (sockname
.sin_addr
.s_addr
>> 16) & 0xff,
532 sockname
.sin_addr
.s_addr
>> 24, lporthi
, lportlo
);
534 /* send the new port and ipaddress to the client */
535 (*bytes
) = sprintf(buf
, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\n",
536 sockname
.sin_addr
.s_addr
& 0xff,
537 (sockname
.sin_addr
.s_addr
>> 8) & 0xff,
538 (sockname
.sin_addr
.s_addr
>> 16) & 0xff,
539 sockname
.sin_addr
.s_addr
>> 24, lporthi
, lportlo
);
541 newsession
.sin_port
= htons(rport
);
542 newsession
.sin_family
= AF_INET
;
543 newsession
.sin_addr
.s_addr
= remip
[0] | (remip
[1] << 8)
544 | (remip
[2] << 16) | (remip
[3] << 24);
546 debug1("ftpdata server ip: %s\n", inet_ntoa(newsession
.sin_addr
));
547 debug1("ftpdata server port: %d\n", rport
);
548 debug1("listening for ftpdata on port %d\n", lport
);
549 debug1("listening for ftpdata on addr %s\n", inet_ntoa(sockname
.sin_addr
));
552 /* now that we're bound and listening, we can safely send the new
553 string without fear of them getting a connection refused. */
554 redir_write(send
, buf
, (*bytes
), REDIR_OUT
);
556 /* make a new process to handle the dataconnection correctly,
557 for the PASV mode this isn't a problem because after sending the
558 PASV command, the data connection, get active. For the PORT command
559 the server must send a success, if starting here with the copyloop
560 the success command never arrive the client.*/
565 syslog(LOG_ERR
, "Couldn't fork: %m");
569 /* turn off ftp checking while the data connection is active */
571 do_accept(localsock
, &newsession
);
575 default: /* Parent */
576 { close(localsock
); }
590 int max_fd
; /* Maximum numbered fd used */
591 struct timeval timeout
;
593 unsigned long bytes_in
= 0;
594 unsigned long bytes_out
= 0;
595 unsigned int start_time
, end_time
;
598 /* Record start time */
599 start_time
= (unsigned int) time(NULL
);
602 timeout
.tv_sec
= timeout_secs
;
605 /* file descriptor bits */
607 FD_SET(insock
, &iofds
);
608 FD_SET(outsock
, &iofds
);
611 if (insock
> outsock
) {
617 debug1("Entering copyloop() - timeout is %d\n", timeout_secs
);
619 (void) memcpy(&c_iofds
, &iofds
, sizeof(iofds
));
622 if (select(max_fd
+ 1,
626 (timeout_secs
? &timeout
: NULL
)) <= 0) {
627 /* syslog(LLEV,"connection timeout: %d sec",timeout.tv_sec);*/
631 if(FD_ISSET(insock
, &c_iofds
)) {
632 if((bytes
= read(insock
, buf
, sizeof(buf
))) <= 0)
636 /* if we're correcting FTP, lookup for a PORT commando
637 in the buffer, if yes change this and establish
638 a new redirector for the data */
639 ftp_clean(outsock
, buf
, &bytes
,0);
642 if(redir_write(outsock
, buf
, bytes
, REDIR_OUT
) != bytes
)
646 if(FD_ISSET(outsock
, &c_iofds
)) {
647 if((bytes
= read(outsock
, buf
, sizeof(buf
))) <= 0)
649 /* if we're correcting for PASV on ftp redirections, then
650 fix buf and bytes to have the new address, among other
654 ftp_clean(insock
, buf
, &bytes
,1);
657 if(redir_write(insock
, buf
, bytes
, REDIR_IN
) != bytes
)
662 debug("Leaving main copyloop\n");
665 setsockopt(insock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));
666 setsockopt(insock, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(SO_LINGER));
667 setsockopt(outsock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));
668 setsockopt(outsock, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(SO_LINGER));
675 debug("copyloop - sockets shutdown and closed\n");
676 end_time
= (unsigned int) time(NULL
);
677 debug1("copyloop - connect time: %8d seconds\n", end_time
- start_time
);
678 debug1("copyloop - transfer in: %8ld bytes\n", bytes_in
);
679 debug1("copyloop - transfer out: %8ld bytes\n", bytes_out
);
681 syslog(LOG_NOTICE
, "disconnect %d secs, %ld in %ld out",
682 (end_time
- start_time
), bytes_in
, bytes_out
);
687 void doproxyconnect(int socket
)
691 /* write CONNECT string to proxy */
692 sprintf((char *) &buf
, "CONNECT %s HTTP/1.0\n\n", connect_str
);
693 x
= write(socket
, (char *) &buf
, strlen(buf
));
695 perror("doproxyconnect: failed");
698 /* now read result */
699 x
= read(socket
, (char *) &buf
, sizeof(buf
));
701 perror("doproxyconnect: failed reading fra proxy");
704 /* no more error checking for now -- something should be added later */
705 /* HTTP/1.0 200 Connection established */
709 /* lwait for a connection and move into copyloop... again,
710 ftp redir will call this, so we don't dupilcate it. */
713 do_accept(int servsock
, struct sockaddr_in
*target
)
718 struct sockaddr_in client
;
719 int clientlen
= sizeof(client
);
722 debug("top of accept loop\n");
723 if ((clisock
= accept(servsock
, (struct sockaddr
*) &client
,
726 accept_errno
= errno
;
727 perror("server: accept");
730 syslog(LOG_ERR
, "accept failed: %m");
732 /* determine if this error is fatal */
733 switch(accept_errno
) {
734 /* non-fatal errors */
740 /* all other errors assumed fatal */
747 debug1("peer IP is %s\n", inet_ntoa(client
.sin_addr
));
748 debug1("peer socket is %d\n", client
.sin_port
);
751 * Double fork here so we don't have to wait later
752 * This detaches us from our parent so that the parent
753 * does not need to pick up dead kids later.
755 * This needs to be done before the hosts_access stuff, because
756 * extended hosts_access options expect to be run from a child.
761 perror("(server) fork");
764 syslog(LOG_ERR
, "(server) fork failed: %m");
769 default: /* Parent */
773 /* Wait for child (who has forked off grandchild) */
774 (void) wait(&status
);
776 /* Close sockets to prevent confusion */
783 /* We are now the first child. Fork again and exit */
788 perror("(child) fork");
791 syslog(LOG_ERR
, "(child) fork failed: %m");
796 default: /* Parent */
800 /* We are now the grandchild */
802 #ifdef USE_TCP_WRAPPERS
803 request_init(&request
, RQ_DAEMON
, ident
, RQ_FILE
, clisock
, 0);
805 sock_hostname(&request
);
806 sock_hostaddr(&request
);
808 if (!hosts_access(&request
)) {
814 syslog(LOG_INFO
, "accepted connect from %s", eval_client(&request
));
815 #endif /* USE_TCP_WRAPPERS */
817 if ((targetsock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
819 perror("target: socket");
822 syslog(LOG_ERR
, "socket failed: %m");
828 memcpy(&addr_out
, &client
, sizeof(struct sockaddr_in
));
829 addr_out
.sin_port
= 0;
832 if (bind_addr
|| transproxy
) {
833 /* this only makes sense if an outgoing IP addr has been forced;
834 * at this point, we have a valid targetsock to bind() to.. */
835 /* also, if we're in transparent proxy mode, this option
838 if (bind(targetsock
, (struct sockaddr
*) &addr_out
,
839 sizeof(struct sockaddr_in
)) < 0) {
840 perror("bind_addr: cannot bind to forcerd outgoing addr");
842 /* the port parameter fetch the really port we are listening, it should
843 only be different if the input value is 0 (let the system pick a
846 syslog(LOG_ERR
, "bind failed: %m");
850 debug1("outgoing IP is %s\n", inet_ntoa(addr_out
.sin_addr
));
853 if (connect(targetsock
, (struct sockaddr
*) target
,
854 sizeof(struct sockaddr_in
)) < 0) {
855 perror("target: connect");
858 syslog(LOG_ERR
, "bind failed: %m");
863 debug1("connected to %s\n", inet_ntoa(target
->sin_addr
));
865 /* thanks to Anders Vannman for the fix to make proper syslogging
869 char tmp1
[20], tmp2
[20];
870 strcpy(tmp1
, inet_ntoa(client
.sin_addr
));
871 strcpy(tmp2
, inet_ntoa(target
->sin_addr
));
873 syslog(LOG_NOTICE
, "connecting %s/%d to %s/%d",
874 tmp1
, client
.sin_port
,
875 tmp2
, target
->sin_port
);
880 doproxyconnect(targetsock
);
883 /* initialise random number if necessary */
884 if( random_wait
> 0 ) {
889 copyloop(clisock
, targetsock
, timeout
);
890 exit(0); /* Exit after copy */
893 /* bind to a new socket, we do this out here because passive-fixups
894 are going to call it too, and there's no sense dupliciting the
896 /* fail is true if we should just return a -1 on error, false if we
899 int bindsock(char *addr
, int port
, int fail
)
903 struct sockaddr_in server
;
906 * Get a socket to work with. This socket will
907 * be in the Internet domain, and will be a
911 if ((servsock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
916 perror("server: socket");
919 syslog(LOG_ERR
, "socket failed: %m");
925 memset(&server
, 0, sizeof(server
));
926 server
.sin_family
= AF_INET
;
927 server
.sin_port
= htons(port
);
931 debug1("listening on %s\n", addr
);
932 if ((hp
= gethostbyname(addr
)) == NULL
) {
933 fprintf(stderr
, "%s: cannot resolve hostname.\n", addr
);
936 memcpy(&server
.sin_addr
, hp
->h_addr
, hp
->h_length
);
938 debug("local IP is default\n");
939 server
.sin_addr
.s_addr
= htonl(inet_addr("0.0.0.0"));
942 setsockopt(servsock
, SOL_SOCKET
, SO_REUSEADDR
, &reuse_addr
, sizeof(reuse_addr
));
943 setsockopt(servsock
, SOL_SOCKET
, SO_LINGER
, &linger_opt
, sizeof(SO_LINGER
));
946 * Try to bind the address to the socket.
949 if (bind(servsock
, (struct sockaddr
*) &server
,
950 sizeof(server
)) < 0) {
955 perror("server: bind");
958 syslog(LOG_ERR
, "bind failed: %m");
965 * Listen on the socket.
968 if (listen(servsock
, 10) < 0) {
973 perror("server: listen");
976 syslog(LOG_ERR
, "listen failed: %m");
986 main(int argc
, char *argv
[])
989 struct sockaddr_in target
;
998 debug("parse args\n");
999 parse_args(argc
, argv
, &target_addr
, &target_port
, &local_addr
,
1000 &local_port
, &timeout
, &dodebug
, &inetd
, &dosyslog
, &bind_addr
,
1006 &bufsize
, &max_bandwidth
, &random_wait
,
1012 target
.sin_family
= AF_INET
;
1013 target
.sin_port
= htons(target_port
);
1014 if (target_addr
!= NULL
) {
1017 debug1("target is %s\n", target_addr
);
1018 if ((hp
= gethostbyname(target_addr
)) == NULL
) {
1019 fprintf(stderr
, "%s: host unknown.\n", target_addr
);
1022 memcpy(&target
.sin_addr
, hp
->h_addr
, hp
->h_length
);
1024 debug("target is default\n");
1025 target
.sin_addr
.s_addr
= htonl(inet_addr("0.0.0.0"));
1028 target_ip
= strdup(inet_ntoa(target
.sin_addr
));
1029 debug1("target IP address is %s\n", target_ip
);
1030 debug1("target port is %d\n", target_port
);
1032 /* Set up outgoing IP addr (optional);
1033 * we have to wait for bind until targetsock = socket() is done
1035 if (bind_addr
&& !transproxy
) {
1038 fprintf(stderr
, "bind_addr is %s\n", bind_addr
);
1039 addr_out
.sin_family
= AF_INET
;
1040 addr_out
.sin_port
= 0;
1041 if ((hp
= gethostbyname(bind_addr
)) == NULL
) {
1042 fprintf(stderr
, "%s: cannot resolve forced outgoing IP address.\n", bind_addr
);
1045 memcpy(&addr_out
.sin_addr
, hp
->h_addr
, hp
->h_length
);
1047 ip_to_target
= strdup(inet_ntoa(addr_out
.sin_addr
));
1048 debug1("IP address for target is %s\n", ip_to_target
);
1054 struct sockaddr_in client
;
1055 int client_size
= sizeof(client
);
1057 #ifdef USE_TCP_WRAPPERS
1058 request_init(&request
, RQ_DAEMON
, ident
, RQ_FILE
, 0, 0);
1059 sock_host(&request
);
1060 sock_hostname(&request
);
1061 sock_hostaddr(&request
);
1063 if (!hosts_access(&request
))
1065 #endif /* USE_TCP_WRAPPERS */
1067 if (!getpeername(0, (struct sockaddr
*) &client
, &client_size
)) {
1068 debug1("peer IP is %s\n", inet_ntoa(client
.sin_addr
));
1069 debug1("peer socket is %d\n", client
.sin_port
);
1071 if ((targetsock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
1072 perror("target: socket");
1075 syslog(LOG_ERR
, "targetsock failed: %m");
1081 memcpy(&addr_out
, &client
, sizeof(struct sockaddr_in
));
1082 addr_out
.sin_port
= 0;
1085 if (bind_addr
|| transproxy
) {
1086 /* this only makes sense if an outgoing IP addr has been forced;
1087 * at this point, we have a valid targetsock to bind() to.. */
1088 if (bind(targetsock
, (struct sockaddr
*) &addr_out
,
1089 sizeof(addr_out
)) < 0) {
1090 perror("bind_addr: cannot bind to forcerd outgoing addr");
1093 syslog(LOG_ERR
, "bind failed: %m");
1097 debug1("outgoing IP is %s\n", inet_ntoa(addr_out
.sin_addr
));
1100 if (connect(targetsock
, (struct sockaddr
*) &target
,
1101 sizeof(target
)) < 0) {
1102 perror("target: connect");
1105 syslog(LOG_ERR
, "connect failed: %m");
1111 syslog(LOG_NOTICE
, "connecting %s/%d to %s/%d",
1112 inet_ntoa(client
.sin_addr
), client
.sin_port
,
1113 target_ip
, target
.sin_port
);
1116 /* Just start copying - one side of the loop is stdin - 0 */
1117 copyloop(0, targetsock
, timeout
);
1122 servsock
= bindsock(local_addr
, local_port
, 0);
1124 servsock
= bindsock(NULL
, local_port
, 0);
1127 * Accept connections. When we accept one, ns
1128 * will be connected to the client. client will
1129 * contain the address of the client.
1133 do_accept(servsock
, &target
);
1136 /* this should really never be reached */