--- redir.c.old Sun Dec 26 22:50:06 1999 +++ redir.c Thu Dec 13 20:44:08 2001 @@ -79,6 +79,9 @@ #include #include +/* hzd */ +#include + #ifdef USE_TCP_WRAPPERS #include #endif @@ -136,10 +139,21 @@ void do_accept(int servsock, struct sockaddr_in *target); int bindsock(char *addr, int port, int fail); +int get_orig_dest(int fd, struct sockaddr_in *addr) +{ + socklen_t len; + + len=sizeof(*addr); + return( getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, + (struct sockaddr*) addr, &len) ); +} + + #ifndef NO_SHAPER /* Used in this program to write something in a socket, it has the same parameters and return value as "write", but with the flag "in": true if it's the "in" socket and false if it's the "out" socket */ + static inline ssize_t redir_write (int fd, const void *buf, size_t size, int in) { ssize_t result; @@ -212,7 +226,7 @@ fprintf(stderr, "\t\t--lport=\t\tport to listen on\n"); fprintf(stderr, "\t\t--laddr=IP\t\taddress of interface to listen on\n"); fprintf(stderr, "\t\t--cport=\t\tport to connect to\n"); - fprintf(stderr, "\t\t--caddr=\t\tremote host to connect to\n"); + fprintf(stderr, "\t\t--caddr=\t\tremote host to connect to, \n\t\t\tif you are using --transproxy you can \n\t\t\tleave it empty and it will connect to original dest\n"); fprintf(stderr, "\t\t--inetd\t\trun from inetd\n"); fprintf(stderr, "\t\t--debug\t\toutput debugging info\n"); fprintf(stderr, "\t\t--timeout=\tset timeout to n seconds\n"); @@ -390,12 +404,14 @@ } } - if(tport == NULL) + if(tport == NULL && !transproxy) { redir_usage(argv[0]); exit(1); } - + else if (tport == NULL) + tport = lport; + if ((portdesc = getservbyname(tport, "tcp")) != NULL) { *target_port = ntohs(portdesc->s_port); } else { @@ -829,9 +845,10 @@ addr_out.sin_port = 0; } - if (bind_addr || transproxy) { + if (bind_addr || !transproxy) { /* this only makes sense if an outgoing IP addr has been forced; * at this point, we have a valid targetsock to bind() to.. */ + /* also, if we're in transparent proxy mode, this option never makes sense */ @@ -850,6 +867,10 @@ debug1("outgoing IP is %s\n", inet_ntoa(addr_out.sin_addr)); } +/* Connect to original destination address if in transparent mode && target == NULL */ + if (transproxy && target->sin_addr.s_addr == 0) + get_orig_dest (clisock, target); + if (connect(targetsock, (struct sockaddr *) target, sizeof(struct sockaddr_in)) < 0) { perror("target: connect"); @@ -1020,12 +1041,16 @@ exit(1); } memcpy(&target.sin_addr, hp->h_addr, hp->h_length); + } else if (target_addr == NULL && transproxy && !inetd) { + debug("will connect to original destination address\n"); + target.sin_addr.s_addr = 0; } else { debug("target is default\n"); target.sin_addr.s_addr = htonl(inet_addr("0.0.0.0")); } - target_ip = strdup(inet_ntoa(target.sin_addr)); + if (&target != NULL) + target_ip = strdup(inet_ntoa(target.sin_addr)); debug1("target IP address is %s\n", target_ip); debug1("target port is %d\n", target_port);