diff -urN ss5-3.8.9/common/Makefile ss5-3.8.9.patched/common/Makefile
--- ss5-3.8.9/common/Makefile	2012-01-11 13:03:52.000000000 +0100
+++ ss5-3.8.9.patched/common/Makefile	2013-12-04 01:02:49.807622531 +0100
@@ -5,10 +5,10 @@
 COMMONOBJ  = SS5OpenLdap.o SS5Radius.o SS5MySql.o
 
 
-CFLAGS=-g -O2 -DLINUX -D_FILE_OFFSET_BITS=64 -I . -I ../include   -ggdb -Wall -Wextra -pedantic -fno-strict-aliasing  -fPIC
-SRVCFLAGS=-g -O2 -DLINUX -D_FILE_OFFSET_BITS=64 -I . -I ../include  -ggdb -Wall -Wextra -pedantic -fno-strict-aliasing 
+CFLAGS=-g -O2 -DLINUX -D_FILE_OFFSET_BITS=64 -I . -I ../include   -D EPOLL_IO  -fPIC
+SRVCFLAGS=-g -O2 -DLINUX -D_FILE_OFFSET_BITS=64 -I . -I ../include  -D EPOLL_IO 
 
-LIBS = -lpthread -rdynamic -ldl -lssl -lldap -lpam -lpam_misc -lcrypto  
+LIBS = -lpthread -lm -rdynamic -ldl -lssl -lldap -lpam -lpam_misc -lcrypto  
 
 CC = gcc
 
diff -urN ss5-3.8.9/common/Makefile.in ss5-3.8.9.patched/common/Makefile.in
--- ss5-3.8.9/common/Makefile.in	2011-08-26 14:28:01.000000000 +0200
+++ ss5-3.8.9.patched/common/Makefile.in	2013-12-04 00:51:04.296890966 +0100
@@ -8,7 +8,7 @@
 CFLAGS=@CFLAGS@ -I . -I ../include  @EXTRA_CFLAGS@ -fPIC
 SRVCFLAGS=@CFLAGS@ -I . -I ../include @EXTRA_CFLAGS@
 
-LIBS = -lpthread @LIBS@ @EXTRA_LIBS@ 
+LIBS = -lpthread -lm @LIBS@ @EXTRA_LIBS@ 
 
 CC = gcc
 
diff -urN ss5-3.8.9/common/SS5Radius.c ss5-3.8.9.patched/common/SS5Radius.c
--- ss5-3.8.9/common/SS5Radius.c	2011-08-26 14:28:01.000000000 +0200
+++ ss5-3.8.9.patched/common/SS5Radius.c	2013-12-04 01:04:30.321425697 +0100
@@ -16,17 +16,34 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-
 #include "SS5Main.h"
 #include "SS5Mod_authentication.h"
 #include "SS5Radius.h"
+#include <math.h>
 
+void AddS5RadiusAttributes(char* radiusPacket, int* offset, struct _SS5ClientInfo *ci)
+{
+  register UINT i;
+  const char* nasid = "socks";
+
+  /* NAS-IP-Address */
+  radiusPacket[*offset] = ATT_NAS_IP_Address;
+  radiusPacket[*offset + 1] = 6;
+  SETXVAL_R(radiusPacket, ntohl(inet_addr(ci->SrvAddr)), *offset + 2)
+  *offset += 6;
+
+  /* NAS-Identifier */
+  radiusPacket[*offset] = ATT_NAS_Identifier;
+  radiusPacket[*offset + 1] = 7;
+  memcpy(radiusPacket + *offset + 2, nasid, 5);
+  *offset += 7;
+}
 
 UINT S5RadiusAuth( struct _SS5ClientInfo *ci, pid_t pid ) {
 
   char logString[256];
 
-  register UINT i; 
+  register UINT i, j; 
 
   fd_set fdset;
 
@@ -38,11 +55,16 @@
 
   int          offset,
                radiusSocket,
-               packetLen;
+               packetLen = HEADER_LEN;
 
   MD5_CTX md5;
 
-  uint8_t md5digest[MD5_DIGEST_LENGTH];
+  int pwlen = strlen(ci->Password);
+  int pwchunks = ceil((float)pwlen/MD5_DIGEST_LENGTH);
+  int digest_len = pwchunks * MD5_DIGEST_LENGTH;
+
+  uint8_t chunk_digest[MD5_DIGEST_LENGTH];
+  uint8_t *passwd_digest = (uint8_t*) malloc (digest_len * sizeof(uint8_t));
 
   struct in_addr in;
   struct sockaddr_in da_sin,sa_sin;
@@ -77,29 +99,52 @@
 
   memcpy(radiusPacket + OFF_VECTOR, radiusReqVector,VECTOR_LEN);
 
+  /* User-Name */
   len=strlen(ci->Username);
-  radiusPacket[HEADER_LEN] = 1;
-  radiusPacket[HEADER_LEN + 1] = len+2;
-
-  memcpy(radiusPacket + HEADER_LEN + 2,ci->Username,len);
+  radiusPacket[packetLen]=ATT_User_Name;
+  radiusPacket[packetLen + 1]=len + 2;
+  memcpy(radiusPacket + packetLen + 2,ci->Username,len);
+  packetLen += len + 2;
 
+  /* Creating first user-password chunk: RadiusSecret + Request Authenticator */
   MD5_Init(&md5);
-
   MD5_Update(&md5, S5Radius.Secret,strlen(S5Radius.Secret) );
   MD5_Update(&md5, radiusPacket + OFF_VECTOR, VECTOR_LEN);
+  MD5_Final(&chunk_digest[0], &md5);
 
-  MD5_Final(&md5digest[0], &md5);
+  for(i = 0; i < sizeof(chunk_digest); i++)
+    if( i < pwlen )
+      chunk_digest[i] ^= ci->Password[i];
 
-  for(i = 0; i < sizeof(md5digest); i++)
-    if( i < strlen(ci->Password))
-      md5digest[i] ^= ci->Password[i];
+  memcpy(passwd_digest, chunk_digest, sizeof(chunk_digest));
 
-  radiusPacket[HEADER_LEN + 2 + len]     = 2;
-  radiusPacket[HEADER_LEN + 2 + len + 1] = sizeof(md5digest) + 2;
+  if (pwlen > MD5_DIGEST_LENGTH)
+  {
+    i = 0;
+    while (i < pwchunks - 1) {
+       MD5_Init(&md5);
+       MD5_Update(&md5, S5Radius.Secret,strlen(S5Radius.Secret) );
+       MD5_Update(&md5, chunk_digest, sizeof(chunk_digest));
+       MD5_Final(&chunk_digest[0], &md5);
 
-  memcpy(radiusPacket + HEADER_LEN + 2 + len + 2,md5digest,sizeof(md5digest));
+       for(j = 0; j < sizeof(chunk_digest); j++)
+         if( j < pwlen - (i+1) * MD5_DIGEST_LENGTH )
+           chunk_digest[j] ^= ci->Password[(i+1) * MD5_DIGEST_LENGTH + j];
+
+       memcpy(passwd_digest + sizeof(chunk_digest), chunk_digest, sizeof(chunk_digest));
+       i++; 
+    }
+  }
+
+  /* User-Password */
+  len=digest_len;
+  radiusPacket[packetLen]=ATT_User_Password;
+  radiusPacket[packetLen + 1]=len + 2;
+  memcpy(radiusPacket + packetLen + 2,passwd_digest,len);
+  packetLen += len + 2;
+
+  AddS5RadiusAttributes(radiusPacket, &packetLen, ci);
 
-  packetLen = HEADER_LEN + 2 + len + 2 + sizeof(md5digest);
   SETPLEN_R(radiusPacket,packetLen,OFF_PACKET_LEN)
 
   memset((char *)&da_sin, 0, sizeof(struct sockaddr_in));
@@ -112,8 +157,10 @@
    */
   len=sizeof(struct sockaddr_in);
 
-  if ( (radiusSocket = socket(AF_INET,SOCK_DGRAM, 0)) == -1)
+  if ( (radiusSocket = socket(AF_INET,SOCK_DGRAM, 0)) == -1) {
+    free(passwd_digest);
     return ERR;
+  }
 
   /*
    * Send RADIUS Authentication request
@@ -122,6 +169,7 @@
   IFSOLARIS( if( sendto(radiusSocket, radiusPacket, packetLen, 0, (struct sockaddr *)&da_sin, (socklen_t)len ) == -1 ) { )
 
     close(radiusSocket);
+    free(passwd_digest);
     return ERR;
   }
 
@@ -141,6 +189,7 @@
                              (socklen_t *)&len)) == -1 ) {
 
         close(radiusSocket);
+        free(passwd_digest);
         return ERR;
       }
     }
@@ -159,6 +208,7 @@
     IFSOLARIS( if( sendto(radiusSocket, radiusPacket, packetLen, 0, (struct sockaddr *)&da_sin, (socklen_t)len ) == -1 ) { )
 
       close(radiusSocket);
+      free(passwd_digest);
       return ERR;
     }
 
@@ -180,6 +230,7 @@
                                (socklen_t *)&len)) == -1 ) {
   
           close(radiusSocket);
+          free(passwd_digest);
           return ERR;
         }
       }
@@ -193,6 +244,7 @@
         SS5Modules.mod_logging.Logging(logString);
       }
       close(radiusSocket);
+      free(passwd_digest);
       return ERR;
     }
   }
@@ -275,7 +327,7 @@
   MD5_Update(&md5, radiusPacket+20, packetLen - 20);
   MD5_Update(&md5, S5Radius.Secret,strlen(S5Radius.Secret) );
 
-  MD5_Final(&md5digest[0], &md5);
+  MD5_Final(&passwd_digest[0], &md5);
 
   if( DEBUG() ) {
     snprintf(logString,256 - 1,"[%u] [DEBU] Radius response code %d.",pid,radiusPacket[OFF_CODE]);
@@ -295,6 +347,7 @@
     }
 
     close(radiusSocket);
+    free(passwd_digest);
     return ERR;
   }
 
@@ -306,13 +359,14 @@
      * Verify radius authenticator vector
      */
     for(i = 0; i < VECTOR_LEN; i++) {
-      if( md5digest[i] != radiusRespVector[i] ) {
+      if( passwd_digest[i] != radiusRespVector[i] ) {
         if( VERBOSE() ) {
           snprintf(logString,256 - 1,"[%u] [VERB] Radius autenticator vector does not match.",pid);
           SS5Modules.mod_logging.Logging(logString);
         }
 
         close(radiusSocket);
+        free(passwd_digest);
         return ERR;
       }
     }
@@ -324,16 +378,19 @@
     }
 
     close(radiusSocket);
+    free(passwd_digest);
     return ERR;
   }
 
   close(radiusSocket);
+  free(passwd_digest);
 
   /*
    * Save session id for accounting
    */
   ci->sid=sid;
 
+
   return OK;
 
 }
@@ -467,6 +524,8 @@
   memcpy(radiusPacket + offset + 2,ci->SrcAddr,strlen(ci->SrcAddr));
   offset = offset + strlen(ci->SrcAddr) + 2;
 
+  AddS5RadiusAttributes(radiusPacket, &offset, ci);
+
   packetLen= offset;
   SETPLEN_R(radiusPacket,packetLen,2)
 
diff -urN ss5-3.8.9/include/SS5Main.h ss5-3.8.9.patched/include/SS5Main.h
--- ss5-3.8.9/include/SS5Main.h	2012-01-11 13:22:42.000000000 +0100
+++ ss5-3.8.9.patched/include/SS5Main.h	2013-12-03 23:57:07.699247818 +0100
@@ -302,6 +302,7 @@
   int  Socket;
   int  appSocket;
   char SrcAddr[16];
+  char SrvAddr[INET_ADDRSTRLEN];
   UINT SrcPort;
   UINT GssEnc;
 
diff -urN ss5-3.8.9/include/SS5Mod_authentication.h ss5-3.8.9.patched/include/SS5Mod_authentication.h
--- ss5-3.8.9/include/SS5Mod_authentication.h	2011-08-26 14:28:01.000000000 +0200
+++ ss5-3.8.9.patched/include/SS5Mod_authentication.h	2013-12-03 23:57:07.699247818 +0100
@@ -96,5 +96,9 @@
 			 struct _S5AuthCacheNode *node
 );
 
+void
+  DropAuthCache(	char *u,
+			char *p
+);
 
 #endif
diff -urN ss5-3.8.9/include/SS5Radius.h ss5-3.8.9.patched/include/SS5Radius.h
--- ss5-3.8.9/include/SS5Radius.h	2011-08-26 14:28:01.000000000 +0200
+++ ss5-3.8.9.patched/include/SS5Radius.h	2013-12-03 23:57:07.699247818 +0100
@@ -34,6 +34,7 @@
 #define ATT_User_Name          1
 #define ATT_User_Password      2
 #define ATT_NAS_Port           5
+#define ATT_NAS_IP_Address     4
 #define ATT_Framed_IP_Address  8
 #define ATT_Framed_Route      22 
 #define ATT_Session_Timeout   27
@@ -46,6 +47,7 @@
 #define ATT_Acct_Session_Time 46
 #define ATT_Acct_Delay_Time   41
 #define ATT_Calling_Station_Id   31
+#define ATT_NAS_Identifier   32
 #define ATT_Acct_Interim_Interval   85
 
 #define RADIUS_AUTH_PORT 1812
diff -urN ss5-3.8.9/include/SS5Server.h ss5-3.8.9.patched/include/SS5Server.h
--- ss5-3.8.9/include/SS5Server.h	2011-08-26 14:28:01.000000000 +0200
+++ ss5-3.8.9.patched/include/SS5Server.h	2013-12-03 23:57:07.699247818 +0100
@@ -64,5 +64,15 @@
                         pid_t pid
 );
 
+void
+  NVPNSetBoundAddress(	char *addr,
+			UINT sockfd
+);
+
+void
+  NVPNBindAppSocket(	char *addr,
+			UINT sockfd
+);
+
 
 #endif
diff -urN ss5-3.8.9/Makefile.in ss5-3.8.9.patched/Makefile.in
--- ss5-3.8.9/Makefile.in	2011-08-26 14:28:01.000000000 +0200
+++ ss5-3.8.9.patched/Makefile.in	2013-12-04 00:49:52.633462731 +0100
@@ -14,7 +14,7 @@
 
 CFLAGS=@CFLAGS@ -I . @EXTRA_CFLAGS@ 
 
-LIBS = -lpthread @EXTRA_LIBS@
+LIBS = -lpthread -lm @EXTRA_LIBS@
 
 all: common modules src
 
diff -urN ss5-3.8.9/modules/mod_authen/SS5Mod_authentication.c ss5-3.8.9.patched/modules/mod_authen/SS5Mod_authentication.c
--- ss5-3.8.9/modules/mod_authen/SS5Mod_authentication.c	2011-08-26 14:28:01.000000000 +0200
+++ ss5-3.8.9.patched/modules/mod_authen/SS5Mod_authentication.c	2013-12-03 23:57:07.699247818 +0100
@@ -18,6 +18,7 @@
 
 
 #include"SS5Main.h"
+#include"SS5Server.h"
 #include"SS5Mod_authentication.h"
 #include"SS5Mod_log.h"
 #include"SS5Basic.h"
@@ -25,6 +26,7 @@
 #include"SS5ExternalProgram.h"
 #include"SS5Pam.h"
 #include"SS5Supa.h"
+#include"SS5Server.h"
 
 #ifdef SS5_USE_GSSAPI
 #include"SS5GSSApi.h"
@@ -64,6 +66,9 @@
 
   memset(ci->Username,0,64);
   memset(ci->Password,0,64);
+  memset(ci->SrvAddr,0,INET_ADDRSTRLEN);
+
+  NVPNSetBoundAddress(ci->SrvAddr, ci->Socket);
 
   strncpy(ci->Username,"\"\"",strlen("\"\""));
 
@@ -253,6 +258,14 @@
               err = S5PwdFileCheck(ci);
           break;
         }
+
+	if (!err) {
+	      LOCKMUTEXAEC()
+	      DropAuthCache(ci->Username,ci->Password);
+              UNLOCKMUTEXAEC()
+              return ERR;
+	}
+
       }
       else {
         err = OK;
@@ -442,6 +455,33 @@
   return OK;
 }
 
+void DropAuthCache(char *u, char *p)
+{
+  register UINT index;
+  struct _S5AuthCacheNode *node, *next, *prev;
+
+    index=S5AuthCacheHash( u, p );
+
+    if( S5AuthCacheList[index]!= NULL ) {
+      next = NULL;
+      prev = NULL;
+      node = S5AuthCacheList[index];
+      do {
+        next = node->next;
+ 
+        if( STREQ(u,node->Usr,sizeof(node->Usr)) && STREQ(p,node->Pwd,sizeof(node->Pwd)) ) {
+	   if (prev != NULL) prev->next = next;
+	   else S5AuthCacheList[index] = NULL;
+	   free(node);
+	   node = next;
+        } else {
+           prev = node;
+           node = node->next;
+	}
+      } while(node != NULL );
+    }
+}
+
 UINT UpdateAuthCache(char *u, char *p)
 {
   register UINT index;
diff -urN ss5-3.8.9/modules/mod_socks5/SS5Mod_socks5.c ss5-3.8.9.patched/modules/mod_socks5/SS5Mod_socks5.c
--- ss5-3.8.9/modules/mod_socks5/SS5Mod_socks5.c	2012-01-11 13:09:35.000000000 +0100
+++ ss5-3.8.9.patched/modules/mod_socks5/SS5Mod_socks5.c	2013-12-03 23:57:07.700247866 +0100
@@ -1196,6 +1196,8 @@
       err=S5REQUEST_ISERROR;
     }
     else { 
+
+      NVPNBindAppSocket(ci->SrvAddr, ci->appSocket);
       /*
        * SS5: set bind interface if configured
        */ 
@@ -1630,6 +1632,9 @@
         err=S5REQUEST_ISERROR;
       }
       else {
+
+        NVPNBindAppSocket(ci->SrvAddr, ci->udpSocket);
+
         memset((char *)&serverbind_ssin, 0, sizeof(struct sockaddr_in));
         serverbind_ssin.sin_family      = AF_INET;
         serverbind_ssin.sin_port        = htons(0);
diff -urN ss5-3.8.9/src/Makefile.in ss5-3.8.9.patched/src/Makefile.in
--- ss5-3.8.9/src/Makefile.in	2011-08-26 14:28:01.000000000 +0200
+++ ss5-3.8.9.patched/src/Makefile.in	2013-12-04 00:57:14.658605831 +0100
@@ -22,7 +22,7 @@
 CFLAGS=@CFLAGS@ -I . -I ../include  @EXTRA_CFLAGS@ 
 SRVCFLAGS=@CFLAGS@ -I . -I ../include @EXTRA_CFLAGS@
 
-LIBS = -lpthread @LIBS@ @EXTRA_LIBS@ 
+LIBS = -lpthread -lm @LIBS@ @EXTRA_LIBS@ 
 
 CC = gcc
 
diff -urN ss5-3.8.9/src/SS5Server.c ss5-3.8.9.patched/src/SS5Server.c
--- ss5-3.8.9/src/SS5Server.c	2011-08-26 14:28:01.000000000 +0200
+++ ss5-3.8.9.patched/src/SS5Server.c	2013-12-03 23:57:07.700247866 +0100
@@ -289,3 +289,24 @@
   return OK;
 }
 
+void NVPNSetBoundAddress(char *addr, UINT sockfd)
+{
+	struct sockaddr_in sin;
+	socklen_t len = sizeof(sin);
+
+	memset(addr, '\0', INET_ADDRSTRLEN);
+	getsockname(sockfd, (struct sockaddr *)&sin, &len);
+
+	inet_ntop(AF_INET, &(sin.sin_addr), addr, INET_ADDRSTRLEN);
+}
+
+void NVPNBindAppSocket(char *addr, UINT sockfd)
+{
+	struct sockaddr_in nsin;
+	memset((char *)&nsin, 0, sizeof(struct sockaddr_in));
+	nsin.sin_family = AF_INET;
+	nsin.sin_port = htons(0);
+	nsin.sin_addr.s_addr = inet_addr(addr);
+	bind(sockfd,(struct sockaddr *)&nsin, sizeof(struct sockaddr_in));
+}
+
