diff -r -U 5 stunnel-4.44/src/client.c stunnel-4.44-patched/src/client.c --- stunnel-4.44/src/client.c 2011-09-07 22:00:10.000000000 +0200 +++ stunnel-4.44-patched/src/client.c 2011-10-11 14:38:24.000000000 +0200 @@ -581,11 +581,77 @@ /* this update is also required for SSL_pending() to be used */ read_wants_read= ssl_open_rd && c->ssl_ptrsock_ptr && !write_wants_read; - + 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((read_wants_read && (ssl_can_rd || SSL_pending(c->ssl))) || /* it may be possible to read some pending data after * writesocket() above made some room in c->ssl_buff */ (read_wants_write && ssl_can_wr)) { Only in stunnel-4.44-patched/src: client.c.orig diff -r -U 5 stunnel-4.44/src/options.c stunnel-4.44-patched/src/options.c --- stunnel-4.44/src/options.c 2011-09-10 18:44:16.000000000 +0200 +++ stunnel-4.44-patched/src/options.c 2011-10-11 14:38:24.000000000 +0200 @@ -809,10 +809,33 @@ "engineNum"); break; } #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: section->option.program=0; section->execname=NULL; diff -r -U 5 stunnel-4.44/src/prototypes.h stunnel-4.44-patched/src/prototypes.h --- stunnel-4.44/src/prototypes.h 2011-09-13 15:36:52.000000000 +0200 +++ stunnel-4.44-patched/src/prototypes.h 2011-10-11 14:38:24.000000000 +0200 @@ -189,10 +189,11 @@ unsigned int remote:1; /* endpoint: connect */ unsigned int retry:1; /* loop remote+program */ unsigned int sessiond:1; unsigned int program:1; /* endpoint: exec */ unsigned int sni:1; /* endpoint: sni */ + unsigned int sendproxy:1; #ifndef USE_WIN32 unsigned int pty:1; unsigned int transparent_src:1; unsigned int transparent_dst:1; /* endpoint: transparent destination */ #endif @@ -378,10 +379,11 @@ int fd; /* temporary file descriptor */ /* data for transfer() function */ char sock_buff[BUFFSIZE]; /* socket read buffer */ char ssl_buff[BUFFSIZE]; /* SSL read buffer */ + unsigned 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 */ int sock_bytes, ssl_bytes; /* bytes written to socket and SSL */ s_poll_set fds; /* file descriptors */