diff -ur stunnel-4.33/src/client.c stunnel-4.33.sendproxy/src/client.c --- stunnel-4.33/src/client.c 2010-04-04 23:00:29.000000000 +0200 +++ stunnel-4.33.sendproxy/src/client.c 2010-10-15 17:33:13.625135151 +0200 @@ -88,6 +88,8 @@ c->opt=opt; c->local_rfd.fd=rfd; c->local_wfd.fd=wfd; + if (c->opt->option.sendproxy) + c->sendproxy = 1; return c; } @@ -591,7 +593,73 @@ watchdog=0; /* reset watchdog */ } } - + if (c->sendproxy && !c->ssl_ptr) { + int cfd; + struct sockaddr_storage local_addr; + struct sockaddr_storage peer_addr; + u_char family = AF_UNSPEC; + + cfd = SSL_get_fd(c->ssl); + if (cfd != -1) { + size_t namelen; + + namelen = sizeof(local_addr); + if (!getsockname(cfd, (struct sockaddr *)&local_addr, &namelen)) { + namelen = sizeof(peer_addr); + if (!getpeername(cfd, (struct sockaddr *)&peer_addr, &namelen)) + family = peer_addr.ss_family; + } + } + + if (family == AF_INET) { + + if (BUFFSIZE >= 11) { + memcpy(c->ssl_buff, "PROXY TCP4 ", 11); + c->ssl_ptr += 11; + } + + if (inet_ntop(peer_addr.ss_family, &((struct sockaddr_in*)&peer_addr)->sin_addr, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr)) { + c->ssl_ptr += strlen(c->ssl_buff+c->ssl_ptr); + } + if (c->ssl_ptr != BUFFSIZE) { + c->ssl_buff[c->ssl_ptr] = ' '; + c->ssl_ptr++; + } + if (inet_ntop(local_addr.ss_family, &((struct sockaddr_in*)&local_addr)->sin_addr, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr)) { + c->ssl_ptr += strlen(c->ssl_buff+c->ssl_ptr); + } + c->ssl_ptr += snprintf(c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr, " %u %u\r\n", ntohs(((struct sockaddr_in*)&peer_addr)->sin_port), ntohs(((struct sockaddr_in*)&local_addr)->sin_port)); + } +#if defined(USE_IPv6) && !defined(USE_WIN32) + else if (family == AF_INET6) { + + if (BUFFSIZE >= 11) { + memcpy(c->ssl_buff, "PROXY TCP6 ", 11); + c->ssl_ptr += 11; + } + + if (inet_ntop(peer_addr.ss_family, &((struct sockaddr_in6*)&peer_addr)->sin6_addr, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr)) { + c->ssl_ptr += strlen(c->ssl_buff+c->ssl_ptr); + } + if (c->ssl_ptr != BUFFSIZE) { + c->ssl_buff[c->ssl_ptr] = ' '; + c->ssl_ptr++; + } + if (inet_ntop(local_addr.ss_family, &((struct sockaddr_in6*)&local_addr)->sin6_addr, c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr)) { + c->ssl_ptr += strlen(c->ssl_buff+c->ssl_ptr); + } + c->ssl_ptr += snprintf(c->ssl_buff+c->ssl_ptr, BUFFSIZE-c->ssl_ptr, " %u %u\r\n", ntohs(((struct sockaddr_in6*)&peer_addr)->sin6_port), ntohs(((struct sockaddr_in6*)&local_addr)->sin6_port)); + } +#endif + else { + if (BUFFSIZE >= 15) { + memcpy(c->ssl_buff, "PROXY UNKNOWN\r\n ", 15); + c->ssl_ptr += 15; + } + } + c->sendproxy = 0; + } + /****************************** read from SSL */ if((SSL_read_wants_read && ssl_can_rd) || (SSL_read_wants_write && ssl_can_wr) || diff -ur stunnel-4.33/src/options.c stunnel-4.33.sendproxy/src/options.c --- stunnel-4.33/src/options.c 2010-04-05 20:44:43.000000000 +0200 +++ stunnel-4.33.sendproxy/src/options.c 2010-10-15 16:51:58.706136512 +0200 @@ -792,6 +792,29 @@ } #endif + /* sendproxy */ + switch(cmd) { + case CMD_INIT: + section->option.sendproxy=0; + break; + case CMD_EXEC: + if(strcasecmp(opt, "sendproxy")) + break; + if(!strcasecmp(arg, "yes")) + section->option.sendproxy=1; + else if(!strcasecmp(arg, "no")) + section->option.sendproxy=0; + else + return "argument should be either 'yes' or 'no'"; + return NULL; /* OK */ + case CMD_DEFAULT: + break; + case CMD_HELP: + s_log(LOG_NOTICE, "%-15s = yes|no append proxy prefix", + "sendproxy"); + break; + } + /* exec */ switch(cmd) { case CMD_INIT: diff -ur stunnel-4.33/src/prototypes.h stunnel-4.33.sendproxy/src/prototypes.h --- stunnel-4.33/src/prototypes.h 2010-04-04 20:34:27.000000000 +0200 +++ stunnel-4.33.sendproxy/src/prototypes.h 2010-10-15 16:56:35.129137473 +0200 @@ -178,6 +178,7 @@ unsigned int retry:1; /* loop remote+program */ unsigned int sessiond:1; unsigned int program:1; + unsigned int sendproxy:1; #ifndef USE_WIN32 unsigned int pty:1; unsigned int transparent:1; @@ -346,6 +347,7 @@ char sock_buff[BUFFSIZE]; /* socket read buffer */ char ssl_buff[BUFFSIZE]; /* SSL read buffer */ + int sendproxy; int sock_ptr, ssl_ptr; /* index of first unused byte in buffer */ FD *sock_rfd, *sock_wfd; /* read and write socket descriptors */ FD *ssl_rfd, *ssl_wfd; /* read and write SSL descriptors */