Просмотр исходного кода

Copy to master from devel - ready for 0.8

z3APA3A 10 лет назад
Родитель
Сommit
5287278fa5
74 измененных файлов с 3463 добавлено и 4624 удалено
  1. 1 0
      .gitignore
  2. BIN
      3proxy.ico
  3. 2 2
      3proxy.rc
  4. 4 10
      Makefile.Linux
  5. 0 1
      Makefile.Solaris
  6. 0 1
      Makefile.Solaris-gcc
  7. 2 3
      Makefile.ccc
  8. 0 1
      Makefile.debug
  9. 0 1
      Makefile.inc
  10. 0 1
      Makefile.intl
  11. 4 5
      Makefile.msvc
  12. 11 5
      Makefile.msvc64
  13. 0 1
      Makefile.msvcCE
  14. 2 3
      Makefile.unix
  15. 0 1
      Makefile.unix-install
  16. 1 2
      Makefile.win
  17. 2 3
      Makefile.winCE
  18. 3 3
      README
  19. 0 1
      Release.notes
  20. 0 1
      cfg/0.scenario.txt
  21. 0 1
      cfg/3proxy.cfg.sample
  22. 0 1
      cfg/counters.sample
  23. 0 1
      copying
  24. 0 3
      doc/html/faqe.html
  25. 0 3
      doc/html/faqr.html
  26. 0 1
      doc/html/howtoe.html
  27. 0 3
      doc/html/howtor.html
  28. 4 6
      doc/html/securityen.html
  29. 48 1825
      doc/ru/3proxy_for_dummies.rtf
  30. 0 1
      doc/ru/example1.txt
  31. 0 1
      doc/ru/iodbc.txt
  32. 34 11
      man/3proxy.cfg.3
  33. 17 1503
      src/3proxy.c
  34. 6 20
      src/Makefile.inc
  35. 302 263
      src/auth.c
  36. 0 1
      src/base64.c
  37. 211 75
      src/common.c
  38. 1685 0
      src/conf.c
  39. 109 126
      src/datatypes.c
  40. 1 3
      src/dighosts.c
  41. 57 42
      src/dnspr.c
  42. 14 13
      src/ftp.c
  43. 31 29
      src/ftppr.c
  44. 8 12
      src/icqpr.c
  45. 0 2
      src/libs/md4.c
  46. 1 2
      src/myalloc.c
  47. 0 1
      src/mycrypt.c
  48. 2 3
      src/ntlm.c
  49. 39 39
      src/plugins.c
  50. 34 14
      src/plugins/FilePlugin/FilePlugin.c
  51. 6 6
      src/plugins/PCREPlugin/pcre_plugin.c
  52. 1 1
      src/plugins/PamAuth/pamauth.c
  53. 35 14
      src/plugins/SSLPlugin/my_ssl.c
  54. 1 1
      src/plugins/SSLPlugin/my_ssl.h
  55. 53 15
      src/plugins/SSLPlugin/ssl_plugin.c
  56. 33 5
      src/plugins/TrafficPlugin/TrafficPlugin.c
  57. 0 1
      src/plugins/TransparentPlugin/transparent_plugin.c
  58. 0 1
      src/plugins/WindowsAuthentication/WindowsAuthentication.c
  59. 0 1
      src/plugins/utf8tocp1251/utf8tocp1251.c
  60. 2 3
      src/pop3p.c
  61. 67 72
      src/proxy.c
  62. 27 20
      src/proxy.h
  63. 257 192
      src/proxymain.c
  64. 2 2
      src/pstdint.h
  65. 12 13
      src/smtpp.c
  66. 10 10
      src/sockgetchar.c
  67. 24 25
      src/sockmap.c
  68. 141 105
      src/socks.c
  69. 3 3
      src/stringtable.c
  70. 127 50
      src/structures.h
  71. 0 1
      src/tcppm.c
  72. 15 14
      src/udppm.c
  73. 2 2
      src/version.h
  74. 10 17
      src/webadmin.c

+ 1 - 0
.gitignore

@@ -25,6 +25,7 @@ doc/html/index.html
 verfile.sh
 Makefile
 Changelog
+res
 copytgz.sh
 *~.nib
 local.properties


+ 2 - 2
3proxy.rc

@@ -3,8 +3,8 @@
 LANGUAGE 0x09, 0x01
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,7,0,0
- PRODUCTVERSION 0,7,0,0
+ FILEVERSION 0,8,0,0
+ PRODUCTVERSION 0,8,0,0
  FILETYPE 0x1L
  FILESUBTYPE 0x0L
 BEGIN

+ 4 - 10
Makefile.Linux

@@ -1,4 +1,3 @@
-#$Id: Makefile.Linux,v 1.24 2014-04-07 20:34:57 vlad Exp $
 #
 # 3 proxy Makefile for GCC/Linux/Cygwin
 #
@@ -11,17 +10,15 @@
 BUILDDIR =
 CC = gcc
 
-CFLAGS = -Wall -g -O2 -c -pthread -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE=4096 -DWITH_POLL
+CFLAGS = -g -O2 -c -pthread -DGETHOSTBYNAME_R -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE=4096 -DWITH_POLL
 COUT = -o 
 LN = gcc
 DCFLAGS = -fpic
-LDFLAGS = -Wall -O2 -pthread
+LDFLAGS = -O2 -pthread
 DLFLAGS = -shared
 DLSUFFICS = .ld.so
 # -lpthreads may be reuqired on some platforms instead of -pthreads
-#LIBS = -lcrypto -lssl -ldl 
-# libcrypto and libssl are required for SSLPlugin
-LIBS = -ldl 
+LIBS = -lcrypto -lssl -ldl 
 LNOUT = -o 
 EXESUFFICS =
 OBJSUFFICS = .o
@@ -31,9 +28,7 @@ REMOVECOMMAND = rm -f
 TYPECOMMAND = cat
 COMPATLIBS =
 MAKEFILE = Makefile.Linux
-#PLUGINS = SSLPlugin StringsPlugin TrafficPlugin PCREPlugin TransparentPlugin
-# SSLPlugin is not built by default because of external dependencies
-PLUGINS = StringsPlugin TrafficPlugin PCREPlugin TransparentPlugin
+PLUGINS = SSLPlugin StringsPlugin TrafficPlugin PCREPlugin TransparentPlugin
 
 include Makefile.inc
 
@@ -49,7 +44,6 @@ INSTALL		= /usr/bin/install
 INSTALL_BIN	= $(INSTALL) -m 755
 INSTALL_DATA	= $(INSTALL) -m 644
 INSTALL_OBJS	= src/3proxy \
-		  src/countersutil \
 		  src/dighosts \
 		  src/ftppr \
 		  src/mycrypt \

+ 0 - 1
Makefile.Solaris

@@ -1,4 +1,3 @@
-#$Id: Makefile.Solaris,v 1.18 2008/09/30 13:58:44 vlad Exp $
 #
 # 3 proxy Makefile for Solaris/SunCC
 #

+ 0 - 1
Makefile.Solaris-gcc

@@ -1,4 +1,3 @@
-#$Id: Makefile.Solaris-gcc,v 1.14 2008/09/30 13:58:44 vlad Exp $
 #
 # 3 proxy Makefile for Solaris/gcc
 #

+ 2 - 3
Makefile.ccc

@@ -1,4 +1,3 @@
-#$Id: Makefile.ccc,v 1.12 2007/04/10 16:29:25 vlad Exp $
 #
 # 3 proxy Makefile for Compaq C Compiler
 #
@@ -10,10 +9,10 @@
 
 BUILDDIR =
 CC = ccc
-CFLAGS = -Wall -O2 -c -pthread -D_THREAD_SAFE -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE=4096 -WITH_POLL
+CFLAGS = -O2 -c -pthread -D_THREAD_SAFE -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE=4096 -WITH_POLL
 COUT = -o 
 LN = ccc
-LDFLAGS = -Wall -O2 -pthread
+LDFLAGS = -O2 -pthread
 DCFLAGS = -fpic
 DLFLAGS = -shared
 DLSUFFICS = .ld.so

+ 0 - 1
Makefile.debug

@@ -1,4 +1,3 @@
-#$Id: Makefile.debug,v 1.7 2007/04/18 05:33:19 vlad Exp $
 #
 # 3 proxy Makefile for Microsoft Visual C compiler (for both make and nmake)
 #

+ 0 - 1
Makefile.inc

@@ -1,4 +1,3 @@
-#$Id: Makefile.inc,v 1.3 2007/01/23 16:00:26 vlad Exp $
 #
 # 3 proxy common Makefile
 #

+ 0 - 1
Makefile.intl

@@ -1,4 +1,3 @@
-#$Id: Makefile.intl,v 1.8 2007/07/21 18:47:00 vlad Exp $
 #
 # 3 proxy Makefile for Intel C compiler for Windows (for both make and nmake)
 #

+ 4 - 5
Makefile.msvc

@@ -1,4 +1,3 @@
-#$Id: Makefile.msvc,v 1.17 2010-11-11 14:44:11 v.dubrovin Exp $
 #
 # 3 proxy Makefile for Microsoft Visual C compiler (for both make and nmake)
 #
@@ -15,7 +14,7 @@ LN = link
 LDFLAGS = /nologo /subsystem:console /incremental:no /machine:I386
 DLFLAGS = /DLL
 DLSUFFICS = .dll
-LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib kernel32.lib Gdi32.lib 
+LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib kernel32.lib Gdi32.lib libeay32MT.lib ssleay32MT.lib
 LIBSOLD = libeay32MT.lib ssleay32MT.lib
 LIBEXT = .lib                                                                                               
 LNOUT = /out:
@@ -27,8 +26,8 @@ REMOVECOMMAND = del 2>NUL >NUL
 TYPECOMMAND = type
 COMPATLIBS =
 MAKEFILE = Makefile.msvc
-PLUGINS = utf8tocp1251 WindowsAuthentication TrafficPlugin StringsPlugin PCREPlugin lastFripper FilePlugin
-VERFILE = 3proxyres.obj $(VERFILE)
+PLUGINS = utf8tocp1251 WindowsAuthentication TrafficPlugin StringsPlugin PCREPlugin FilePlugin SSLPlugin
+VERFILE = $(VERFILE)
 
 include Makefile.inc
 
@@ -36,7 +35,7 @@ include Makefile.inc
 	rc /fo../3proxy.res ../3proxy.rc
 
 3proxyres.obj: ../3proxy.res
-	cvtres /out:3proxyres.obj /MACHINE:X86 ../3proxy.res
+	cvtres /out:3proxyres.obj /MACHINE:I386 ../3proxy.res
 
 allplugins:
 	for /D %%i in ($(PLUGINS)) do (copy Makefile plugins\%%i && copy Makefile.var plugins\%%i && cd plugins\%%i && nmake && del *.obj *.idb &&cd ..\..)

+ 11 - 5
Makefile.msvc64

@@ -1,4 +1,3 @@
-#$Id: Makefile.msvc64,v 1.14 2007/07/21 18:47:05 vlad Exp $
 #
 # 3 proxy Makefile for Microsoft Visual C compiler (for both make and nmake)
 #
@@ -15,7 +14,7 @@ LN = link
 LDFLAGS = /nologo /subsystem:console /incremental:no /machine:x64
 DLFLAGS = /DLL
 DLSUFFICS = .dll
-LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib kernel32.lib Gdi32.lib 
+LIBS = ws2_32.lib advapi32.lib odbc32.lib user32.lib kernel32.lib Gdi32.lib libeay32MT.lib ssleay32MT.lib
 LIBSOLD = libeay32MT.lib ssleay32MT.lib
 LIBEXT = .lib
 LNOUT = /out:
@@ -27,8 +26,14 @@ REMOVECOMMAND = del 2>NUL >NUL
 TYPECOMMAND = type
 COMPATLIBS =
 MAKEFILE = Makefile.msvc64
-PLUGINS = utf8tocp1251 WindowsAuthentication TrafficPlugin StringsPlugin PCREPlugin
-VERFILE = 3proxyres.obj $(VERFILE)
+PLUGINS = utf8tocp1251 WindowsAuthentication TrafficPlugin StringsPlugin PCREPlugin FilePlugin SSLPlugin
+VERFILE = $(VERFILE)
+
+#../3proxy.res:
+#	rc /fo../3proxy.res ../3proxy.rc
+
+#3proxyres.obj: ../3proxy.res
+#	cvtres /out:3proxyres.obj /MACHINE:X64 ../3proxy.res
 
 include Makefile.inc
 
@@ -36,7 +41,8 @@ include Makefile.inc
 	rc /fo../3proxy.res ../3proxy.rc
 
 3proxyres.obj: ../3proxy.res
-	cvtres /out:3proxyres.obj /MACHINE:X64 ../3proxy.res
+	cvtres /out:3proxyres.obj /machine:x64 ../3proxy.res
+
 
 allplugins:
 	for /D %%i in ($(PLUGINS)) do (copy Makefile plugins\%%i && copy Makefile.var plugins\%%i && cd plugins\%%i && nmake && del *.obj *.idb &&cd ..\..)

+ 0 - 1
Makefile.msvcCE

@@ -1,4 +1,3 @@
-#$Id: Makefile.msvc,v 1.14 2007/07/21 18:47:02 vlad Exp $
 #
 # 3 proxy Makefile for Microsoft Visual C compiler (for both make and nmake)
 #

+ 2 - 3
Makefile.unix

@@ -1,4 +1,3 @@
-#$Id: Makefile.unix,v 1.20 2007/04/10 16:29:25 vlad Exp $
 #
 # 3 proxy Makefile for GCC/Unix
 #
@@ -12,10 +11,10 @@ BUILDDIR =
 CC = gcc
 
 # you may need -L/usr/pkg/lib for older NetBSD versions
-CFLAGS = -Wall -g -O2 -c -pthread -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE=4096 -DWITH_POLL
+CFLAGS = -g -O2 -c -pthread -D_THREAD_SAFE -D_REENTRANT -DNOODBC -DWITH_STD_MALLOC -DFD_SETSIZE=4096 -DWITH_POLL
 COUT = -o 
 LN = gcc
-LDFLAGS = -Wall -O2 -pthread
+LDFLAGS = -O2 -pthread
 # -lpthreads may be reuqired on some platforms instead of -pthreads
 # -ldl or -lld may be required for some platforms
 DCFLAGS = -fpic

+ 0 - 1
Makefile.unix-install

@@ -7,7 +7,6 @@ INSTALL		= /usr/bin/install
 INSTALL_BIN	= $(INSTALL) -m 755
 INSTALL_DATA	= $(INSTALL) -m 644
 INSTALL_OBJS	= src/3proxy \
-		  src/countersutil \
 		  src/dighosts \
 		  src/ftppr \
 		  src/mycrypt \

+ 1 - 2
Makefile.win

@@ -1,4 +1,3 @@
-#$Id: Makefile.win,v 1.9 2007/08/20 15:26:27 vlad Exp $
 #
 # 3 proxy Makefile for GCC/windows
 #
@@ -11,7 +10,7 @@
 
 BUILDDIR = ../bin/
 CC = gcc
-CFLAGS = -O2 -s -c -mthreads -DWITH_STD_MALLOC
+CFLAGS = -O2 -s -c -mthreads -DWITH_STD_MALLOC -DNOIPV6
 COUT = -o 
 LN = gcc
 LDFLAGS = -O2 -s  -mthreads

+ 2 - 3
Makefile.winCE

@@ -1,4 +1,3 @@
-#$Id: Makefile.win,v 1.9 2007/08/20 15:26:27 vlad Exp $
 #
 # 3 proxy Makefile for GCC/windows
 #
@@ -11,10 +10,10 @@
 
 BUILDDIR = ../bin/
 CC = /opt/cegcc/arm-wince-cegcc/bin/gcc
-CFLAGS = -Wall -O2 -s -c -mthreads -DWITH_STD_MALLOC -DNOODBC -D_WINCE -D_WIN32 -D__USE_W32_SOCKETS
+CFLAGS = -O2 -s -c -mthreads -DWITH_STD_MALLOC -DNOODBC -D_WINCE -D_WIN32 -D__USE_W32_SOCKETS
 COUT = -o 
 LN = /opt/cegcc/arm-wince-cegcc/bin/gcc
-LDFLAGS = -Wall -O2 -s -mthreads
+LDFLAGS = -O2 -s -mthreads
 DLFLAGS = -shared
 DLSUFFICS = .dll
 LIBS = -lws2

+ 3 - 3
README

@@ -1,6 +1,6 @@
 /*
    3APA3A 3proxy tiny proxy server
-   (c) 2002-2014 by Vladimir '3APA3A' Dubrovin <3proxy@3proxy.ru>
+   (c) 2002-2016 by Vladimir '3APA3A' Dubrovin <3proxy@3proxy.ru>
 
    please read License Agreement
 */
@@ -39,7 +39,6 @@ smtpp    	SMTP proxy server, binds to port 25. You must specify
 icqpr    	ICQ/AIM proxy. Maps some TCP port to TCP port of ICQ
 		server and performs packets translation. Example:
 		icqpr 5190 login.icq.com 5190
-msnpr		MSN proxy (beta)
 tcppm    	TCP port mapping. Maps some TCP port on local machine to
 		TCP port on remote host.
 udppm    	UDP port mapping. Maps some UDP port on local machine to
@@ -56,9 +55,10 @@ mycrypt    	Program to obtain crypted password fro cleartext. Supports
 			mycrypt salt password
 		produces MD5/crypt password with salt "salt".
 dighosts    	Utility for building networks list from web page.
-countersutil	Utility to manage counters file
 
 
 Run utility with --help option for command line reference.
 
 Latest version is available from http://3proxy.ru/
+
+Want to donate the project? http://3proxy.ru/donations/

+ 0 - 1
Release.notes

@@ -104,4 +104,3 @@
    - Addon antiviral, HTTP cache filters modules, authentication
      modules for different protocols (RADIUS, PAM etc).
 
-$Id: Release.notes,v 1.9 2014-04-07 21:24:42 vlad Exp $

+ 0 - 1
cfg/0.scenario.txt

@@ -15,4 +15,3 @@ on the provider's Web server.
 Provider has proxy server 10.1.2.5. Traffic from proxy server is not free, but
 is cheaper than traffic from non-free networks.
 
-$Id: 0.scenario.txt,v 1.2 2004/07/23 13:33:39 vlad Exp $

+ 0 - 1
cfg/3proxy.cfg.sample

@@ -199,4 +199,3 @@ admin
 # now we needn't any root rights. We can chroot and setgid/setuid.
 
 
-###$Id: 3proxy.cfg.sample,v 1.7 2006/11/18 14:37:06 vlad Exp $#######

+ 0 - 1
cfg/counters.sample

@@ -50,4 +50,3 @@ internal 127.0.0.1
 allow user1
 admin
 
-#$Id: counters.sample,v 1.2 2004/07/23 13:33:39 vlad Exp $

+ 0 - 1
copying

@@ -59,4 +59,3 @@ terms of compatible license, including:
 	http://www.gnu.org/licenses/lgpl.txt
 
 
-$Id: License,v 1.3 2007/04/05 11:59:47 vlad Exp $

+ 0 - 3
doc/html/faqe.html

@@ -153,6 +153,3 @@ A: First, I'm not programmer. Second, 3proxy was 'proof of concept' in reply for
 
 <p><i>Q: Why do you use insecure strcpy, sprintf, etc?</i></p>
 A: Why not? I try to use insecure function in secure manner. You're welcome to look for vulnerabilities.
-<pre>
-$Id: faqe.html,v 1.10 2007/07/31 08:42:38 vlad Exp $
-</pre>

+ 0 - 3
doc/html/faqr.html

@@ -278,6 +278,3 @@
   ďóăŕňü.
   </p>
 </ul>
-<pre>
-$Id: faqr.html,v 1.28 2007/09/25 09:47:13 vlad Exp $
-</pre>

+ 0 - 1
doc/html/howtoe.html

@@ -832,4 +832,3 @@ You can control 3proxy service via "Services" administration ot via "net" comman
 
 </ul>
 
-<pre>$Id: howtoe.html,v 1.41 2009/02/02 10:04:49 vlad Exp $</pre>

+ 0 - 3
doc/html/howtor.html

@@ -1026,6 +1026,3 @@
 Только не пытайтесь задавать какие-либо вопросы, если вы просто не поняли этот
 HowTo.
 </ul> 
-<pre>
-$Id: howtor.html,v 1.40 2010/01/21 13:34:20 v.dubrovin Exp $
-</pre>

+ 4 - 6
doc/html/securityen.html

@@ -1,10 +1,10 @@
 <h3>3proxy security considirations</h3>
 </ul>
-<ol>
+<ul>
 <li>Never install 3proxy suid. If you need it to run suid write some
 wrapper with fixed configuration file.
 <li>Make configuration file only available to account 3proxy starts with.
-<li>Under Windows NT/2000/XP/2003 if 3proxy is used as service create new
+<li>Under Windows if 3proxy is used as service create new
 unprivileged local account without "logon locally" right. Assign this account
 to 3proxy service.
 <li>Under unix use chroot to jail 3proxy (make sure files included in
@@ -20,9 +20,8 @@ authentication method is currently available.
 <li>Always limit connections to internal network and localhost (to 127.0.0.1 and
 all interfaces) with ACLs. Be carefull, because BIND command in SOCKS requies
 BIND method with external interface IP address to be allowed.
-<li> Always use nserver and nscache under Unix, overwise DoS attack is possible
+<li> Before 3proxy 0.8 always use nserver and nscache under Unix, overwise DoS attack is possible
 with unreachable DNS server (because gethostbyname will block over threads).
-<li>Remember, that 'nbname' authentication is not reliable and can be spoofed.
 <li>Keep logs in secure location, because some confidential information from
 user's request can be logged.
 <li>Use -xyz+A character filtering sequences for 'logformat', especially with
@@ -31,7 +30,6 @@ ODBC logging to prevent SQL and log record injections.
 <li>Participate in code audit :)
 </ol>
  
-</ol>
+</ul>
 <p>
 
-<pre>$Id: securityen.html,v 1.4 2007/05/07 09:16:51 vlad Exp $</pre>

Разница между файлами не показана из-за своего большого размера
+ 48 - 1825
doc/ru/3proxy_for_dummies.rtf


+ 0 - 1
doc/ru/example1.txt

@@ -96,4 +96,3 @@ setuid 65534
 đĎÓĚĹ ÔĎÇĎ ËÁË ÍŮ ÓĎÚÄÁĚÉ ËĎÎĆÉÇŐŇÁĂÉĎÎÎŮĘ ĆÁĘĚ ÓĹŇ×ĹŇÁ, ÚÁĐŐÓËÁĹÍ 3proxy ËĎÍÁÎÄĎĘ:
 /usr/local/3proxy/3proxy /usr/local/3proxy/3proxy.cfg
 
-$Id: example1.txt,v 1.7 2007/04/20 19:58:42 vlad Exp $

+ 0 - 1
doc/ru/iodbc.txt

@@ -98,4 +98,3 @@ LIBS = -L /usr/local/lib -lodbc
 make clean
 make -f Makefile.unix
 
-$Id: iodbc.txt,v 1.3 2006/02/08 17:59:07 vlad Exp $

+ 34 - 11
man/3proxy.cfg.3

@@ -103,15 +103,29 @@ change default server port to NUMBER
 .B -n
 disable NTLM authentication (required if passwords are stored in Unix crypt format.
 .br
+.B -n1
+enable NTLMv1 authentication.
+.br
 .B -s
-(for admin) - allow only secure operations (currently only traffic counters
+(for admin) - secure, allow only secure operations (currently only traffic counters
 view without ability to reset).
 .br
+(for dnspr) - simple, do not use 'resolver' and 3proxy cache, always use external DNS server.
+.br
+(for udppm) - singlepacket, expect only one packet from both client and server
 .B -a
 (for proxy) - anonymous proxy (no information about client reported)
 .br
 .B -a1
 (for proxy) - anonymous proxy (random client information reported)
+.B -6
+Only resolve IPv6 addresses
+.B -4
+Only resolve IPv4 addresses
+.B -46
+Resolve IPv6 addresses if IPv4 address is not resolvable
+.B -64
+Resolve IPv4 addresses if IPv6 address is not resolvable
 .br
  Also, all options mentioned for 
 .BR proxy (8)
@@ -130,7 +144,9 @@ pop3username@pop3server. If POP3 proxy access must be authenticated, you can
 specify username as proxy_username:proxy_password:POP3_username@pop3server
 .br
  DNS proxy resolves any types of records but only hostnames are cached. It
-requires nserver/nscache to be configured.
+requires nserver/nscache to be configured. If nserver is configured as TCP,
+redirections are applied on connection, so parent proxy may be used to resolve
+names to IP.
 .br
  FTP proxy can be used as FTP server in any FTP client or configured as FTP
 proxy on a client with FTP proxy support. Username format is one of
@@ -328,20 +344,25 @@ Sets timeout values
 
 .br
 .B nserver
- <ipaddr>
+ <ipaddr>[:port][/tcp]
 .br
-Nameserver to use for name resolutions. If none spcified system
+Nameserver to use for name resolutions. If none specified 
 or name server fails system routines for name resolution will be
 used. It's better to specify nserver because gethostbyname() may
-be thread unsafe.
+be thread unsafe. Optional port number may be specified.
+If optional /tcp is added to IP address, name resolution will be
+performed over TCP.
 
 .br
 .B nscache
 <cachesize>
+.B nscache6
+<cachesize>
 .br
 
-Cache <cachesize> records for name resolution. Cachesize usually
-should be large enougth (for example 65536).
+Cache <cachesize> records for name resolution (nscache for IPv4,
+nscache6 for IPv6). Cachesize usually should be large enougth
+(for example 65536).
 
 .br
 .B nsrecord
@@ -375,7 +396,7 @@ http://dial.right.now/ from browser to set up connection.
 .br
 sets ip address of internal interface. This IP address will be used
 to bind gateways. Alternatively you can use -i option for individual
-gateways
+gateways. Since 0.8 version, IPv6 address may be used.
 
 .br
 .B external
@@ -383,7 +404,8 @@ gateways
 .br
 sets ip address of external interface. This IP address will be source
 address for all connections made by proxy. Alternatively you can use
--e option to specify individual address for gateway.
+-e option to specify individual address for gateway. Since 0.8 version
+External or -e can be given twice: once with IPv4 and once with IPv6 address.
    
 .br
 .B maxconn
@@ -486,8 +508,9 @@ Use auth type 'cache' for cached authentication
 Access control entries. All lists are comma-separated, no spaces are
 allowed. Usernames are case sensitive (if used with authtype nbname
 username must be in uppercase). Source and target lists may contain
-IP addresses (W.X.Y.Z) or CIDRs (W.X.Y.Z/L). Since 0.6, targetlist may also
-contain host names, instead of addresses. It's possible to use wildmask in
+IP addresses (W.X.Y.Z), ranges A.B.C.D - W.X.Y.Z (since 0.8) or CIDRs
+(W.X.Y.Z/L). Since 0.6, targetlist may also contain host names,
+instead of addresses. It's possible to use wildmask in
 the begginning and in the the end of hostname, e.g. *badsite.com or
 *badcontent*. Hostname is only checked if hostname presents in request.
 Targetportlist may contain ports (X) or port ranges lists (X-Y). For any field

Разница между файлами не показана из-за своего большого размера
+ 17 - 1503
src/3proxy.c


+ 6 - 20
src/Makefile.inc

@@ -1,9 +1,8 @@
-#$Id: Makefile.inc,v 1.19 2008/12/10 13:12:10 vlad Exp $
 #
 # 3 proxy common Makefile
 #
 
-all:	pre $(VERFILE) $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)mycrypt$(EXESUFFICS) $(BUILDDIR)dighosts$(EXESUFFICS) $(BUILDDIR)pop3p$(EXESUFFICS) $(BUILDDIR)smtpp$(EXESUFFICS) $(BUILDDIR)ftppr$(EXESUFFICS) $(BUILDDIR)tcppm$(EXESUFFICS) $(BUILDDIR)icqpr$(EXESUFFICS) $(BUILDDIR)msnpr$(EXESUFFICS) $(BUILDDIR)udppm$(EXESUFFICS) $(BUILDDIR)socks$(EXESUFFICS) $(BUILDDIR)proxy$(EXESUFFICS) $(BUILDDIR)countersutil$(EXESUFFICS) allplugins
+all:	pre $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)mycrypt$(EXESUFFICS) $(BUILDDIR)dighosts$(EXESUFFICS) $(BUILDDIR)pop3p$(EXESUFFICS) $(BUILDDIR)smtpp$(EXESUFFICS) $(BUILDDIR)ftppr$(EXESUFFICS) $(BUILDDIR)tcppm$(EXESUFFICS) $(BUILDDIR)icqpr$(EXESUFFICS) $(BUILDDIR)udppm$(EXESUFFICS) $(BUILDDIR)socks$(EXESUFFICS) $(BUILDDIR)proxy$(EXESUFFICS) allplugins
 
 
 pre:
@@ -53,9 +52,6 @@ tcppm$(OBJSUFFICS): tcppm.c proxy.h structures.h proxymain.c
 icqpr$(OBJSUFFICS): icqpr.c proxy.h structures.h proxymain.c
 	$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)PORTMAP icqpr.c
 
-msnpr$(OBJSUFFICS): msnpr.c proxy.h structures.h proxymain.c
-	$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)PORTMAP msnpr.c
-
 socks$(OBJSUFFICS): socks.c proxy.h structures.h proxymain.c
 	$(CC) $(CFLAGS) $(DEFINEOPTION)WITHMAIN $(DEFINEOPTION)NOPORTMAP socks.c
 
@@ -86,9 +82,6 @@ $(BUILDDIR)tcppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcp
 $(BUILDDIR)icqpr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) icqpr$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS)
 	$(LN) $(LNOUT)$(BUILDDIR)icqpr$(EXESUFFICS) $(LDFLAGS) $(VERFILE) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) icqpr$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
 
-$(BUILDDIR)msnpr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) msnpr$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS)
-	$(LN) $(LNOUT)$(BUILDDIR)msnpr$(EXESUFFICS) $(LDFLAGS) $(VERFILE) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) msnpr$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
-
 $(BUILDDIR)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS)
 	$(LN) $(LNOUT)$(BUILDDIR)udppm$(EXESUFFICS) $(LDFLAGS) $(VERFILE) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
 
@@ -115,9 +108,6 @@ srvtcppm$(OBJSUFFICS): tcppm.c proxy.h structures.h
 srvicqpr$(OBJSUFFICS): icqpr.c proxy.h structures.h
 	$(CC) $(COUT)srvicqpr$(OBJSUFFICS) $(CFLAGS) icqpr.c
 
-srvmsnpr$(OBJSUFFICS): msnpr.c proxy.h structures.h
-	$(CC) $(COUT)srvmsnpr$(OBJSUFFICS) $(CFLAGS) msnpr.c
-
 srvsocks$(OBJSUFFICS): socks.c proxy.h structures.h
 	$(CC) $(COUT)srvsocks$(OBJSUFFICS) $(CFLAGS) socks.c
 
@@ -133,6 +123,9 @@ srvdnspr$(OBJSUFFICS): dnspr.c proxy.h structures.h
 auth$(OBJSUFFICS): auth.c proxy.h structures.h
 	$(CC) $(COUT)auth$(OBJSUFFICS) $(CFLAGS) auth.c
 
+conf$(OBJSUFFICS): conf.c proxy.h structures.h
+	$(CC) $(COUT)conf$(OBJSUFFICS) $(CFLAGS) conf.c
+
 datatypes$(OBJSUFFICS): datatypes.c proxy.h structures.h
 	$(CC) $(COUT)datatypes$(OBJSUFFICS) $(CFLAGS) datatypes.c
 
@@ -145,13 +138,6 @@ dighosts$(OBJSUFFICS): dighosts.c
 $(BUILDDIR)dighosts$(EXESUFFICS): dighosts$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS)  $(COMPATLIBS)
 	$(LN) $(LNOUT)$(BUILDDIR)dighosts$(EXESUFFICS) $(LDFLAGS) $(VERFILE) dighosts$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
 
-countersutil$(OBJSUFFICS): countersutil.c
-	$(CC) $(COUT)countersutil$(OBJSUFFICS) $(CFLAGS) countersutil.c
-
-$(BUILDDIR)countersutil$(EXESUFFICS): countersutil$(OBJSUFFICS) $(COMPATLIBS)
-	$(LN) $(LNOUT)$(BUILDDIR)countersutil$(EXESUFFICS) $(LDFLAGS) $(VERFILE) countersutil$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
-
-
 mycryptmain$(OBJSUFFICS): mycrypt.c
 	$(CC) $(COUT)mycryptmain$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITHMAIN mycrypt.c
 
@@ -174,8 +160,8 @@ ntlm$(OBJSUFFICS):  ntlm.c
 stringtable$(OBJSUFFICS):  stringtable.c
 	$(CC) $(COUT)stringtable$(OBJSUFFICS) $(CFLAGS) stringtable.c
 
-$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvicqpr$(OBJSUFFICS) srvmsnpr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) mycrypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) smbdes$(OBJSUFFICS) ntlm$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS)
-	$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE)  3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvicqpr$(OBJSUFFICS) srvmsnpr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS) mycrypt$(OBJSUFFICS) md5$(OBJSUFFICS) md4$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) smbdes$(OBJSUFFICS) ntlm$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
+$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvicqpr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) mycrypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) smbdes$(OBJSUFFICS) ntlm$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS)
+	$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE)  3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvicqpr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) myalloc$(OBJSUFFICS) common$(OBJSUFFICS) mycrypt$(OBJSUFFICS) md5$(OBJSUFFICS) md4$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) smbdes$(OBJSUFFICS) ntlm$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
 
 clean:
 	@$(REMOVECOMMAND) *$(OBJSUFFICS) $(COMPFILES)

+ 302 - 263
src/auth.c

@@ -4,83 +4,28 @@
 
    please read License Agreement
 
-   $Id: auth.c,v 1.108 2012-04-11 23:01:18 vlad Exp $
 */
 
 #include "proxy.h"
 
-#define HEADERSIZE 57
-#define RECORDSIZE  18
-
-unsigned char request[] = {	
-		0xa2, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x20, 0x43, 0x4b, 0x41, 
-		0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
-		0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
-		0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
-		0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x21, 
-		0x00, 0x01};
-
-unsigned char * getNetBIOSnamebyip(unsigned long ip){
- unsigned char buf[1024];
- struct sockaddr_in sins;
- int res;
- SOCKET sock;
- unsigned char * username = NULL;
- int i;
- int j;
- int nnames;
- int type;
-
- if ( (sock=so._socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) == INVALID_SOCKET) return NULL;
- memset(&sins, 0, sizeof(sins));
- sins.sin_family = AF_INET;
- sins.sin_port = htons(0);
- sins.sin_addr.s_addr = INADDR_ANY;
- if(so._bind(sock,(struct sockaddr *)&sins,sizeof(sins))) {
-	so._closesocket(sock);
-	return NULL;
- }
- sins.sin_family = AF_INET;
- sins.sin_addr.s_addr = ip;
- sins.sin_port = htons(137);
- res=socksendto(sock, &sins, request, sizeof(request), conf.timeouts[SINGLEBYTE_L]*1000);
- if(res <= 0) {
-	so._closesocket(sock);
-	return NULL;
- }
- res = sockrecvfrom(sock, &sins, buf, sizeof(buf), conf.timeouts[SINGLEBYTE_L]*1000);
- so._closesocket(sock);
- if(res < (HEADERSIZE + RECORDSIZE)) {
-	return NULL;
- }
- nnames = buf[HEADERSIZE-1];
- if (res < (HEADERSIZE + (nnames * RECORDSIZE))) return NULL;
- for (i = 0; i < nnames; i++){
-	type = buf[HEADERSIZE + (i*RECORDSIZE) + 15];
-	if( type == 3) {
-		for(j = 14; j && buf[HEADERSIZE + (i*RECORDSIZE) + j] == ' '; j--)
-			buf[HEADERSIZE + (i*RECORDSIZE) + j] = 0;
-		if(username)myfree(username);
-		username = (unsigned char *)mystrdup((char *)buf + HEADERSIZE + i*RECORDSIZE);
-	}
-	buf[HEADERSIZE + (i*RECORDSIZE) + 15] = 0;
- }
- return username;
-} 
 
-int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned long ip, unsigned short port){
-	unsigned char buf[1024];
-	struct in_addr ina;
+int clientnegotiate(struct chain * redir, struct clientparam * param, struct sockaddr * addr){
+	unsigned char *buf;
+	unsigned char *username;
 	int res;
 	int len=0;
 	unsigned char * user, *pass;
 
-	ina.s_addr = ip;
 
-	
 	user = redir->extuser;
 	pass = redir->extpass;
+	if (param->srvinbuf < 4096){
+		if(param->srvbuf)myfree(param->srvbuf);
+		param->srvbuf = myalloc(4096);
+		param->srvbufsize = 4096;
+	}
+	buf = param->srvbuf;
+	username = buf + 2048;
 	if(user) {
 		if (*user == '*') {
 			if(!param->username) return 4;
@@ -95,17 +40,22 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l
 		case R_CONNECT:
 		case R_CONNECTP:
 		{
-			sprintf((char *)buf, "CONNECT ");
+			len = sprintf((char *)buf, "CONNECT ");
 			if(redir->type == R_CONNECTP && param->hostname) {
-				len = 8 + sprintf((char *)buf + 8, "%.256s", param->hostname);
+				char * needreplace;
+				needreplace = strchr(param->hostname, ':');
+				if(needreplace) buf[len++] = '[';
+				len =+ sprintf((char *)buf + len, "%.256s", param->hostname);
+				if(needreplace) buf[len++] = ']';
 			}
 			else {
-				len = 8 + myinet_ntoa(ina, (char *)buf+8);
+				if(*SAFAMILY(addr) == AF_INET6) buf[len++] = '[';
+				len += myinet_ntop(*SAFAMILY(addr), SAADDR(addr), (char *)buf+len, 256);
+				if(*SAFAMILY(addr) == AF_INET6) buf[len++] = ']';
 			}
 			len += sprintf((char *)buf + len,
-				":%hu HTTP/1.0\r\nProxy-Connection: keep-alive\r\n", ntohs(port));
+				":%hu HTTP/1.0\r\nProxy-Connection: keep-alive\r\n", ntohs(*SAPORT(addr)));
 			if(user){
-				unsigned char username[256];
 				len += sprintf((char *)buf + len, "Proxy-authorization: basic ");
 				sprintf((char *)username, "%.128s:%.64s", user, pass?pass:(unsigned char *)"");
 				en64(username, buf+len, (int)strlen((char *)username));
@@ -115,7 +65,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l
 			len += sprintf((char *)buf + len, "\r\n");
 			if(socksend(param->remsock, buf, len, conf.timeouts[CHAIN_TO]) != (int)strlen((char *)buf))
 				return 31;
-			param->statssrv+=len;
+			param->statssrv64+=len;
 			param->nwrites++;
 			if((res = sockgetlinebuf(param, SERVER,buf,13,'\n',conf.timeouts[CHAIN_TO])) < 13)
 				return 32;
@@ -129,14 +79,15 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l
 		case R_SOCKS4B:
 		{
 
+			if(*SAFAMILY(addr) != AF_INET) return 44;
 			buf[0] = 4;
 			buf[1] = 1;
-			memcpy(buf+2, &port, 2);
+			memcpy(buf+2, SAPORT(addr), 2);
 			if(redir->type == R_SOCKS4P && param->hostname) {
 				buf[4] = buf[5] = buf[6] = 0;
 				buf[7] = 3;
 			}
-			else memcpy(buf+4, &ip, 4);
+			else memcpy(buf+4, SAADDR(addr), 4);
 			if(!user)user = (unsigned char *)"anonymous";
 			len = (int)strlen((char *)user) + 1;
 			memcpy(buf+8, user, len);
@@ -152,7 +103,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l
 			if(socksend(param->remsock, buf, len, conf.timeouts[CHAIN_TO]) < len){
 				return 41;
 			}
-			param->statssrv+=len;
+			param->statssrv64+=len;
 			param->nwrites++;
 			if((len = sockgetlinebuf(param, SERVER, buf, (redir->type == R_SOCKS4B)? 3:8, EOF, conf.timeouts[CHAIN_TO])) != ((redir->type == R_SOCKS4B)? 3:8)){
 				return 42;
@@ -175,7 +126,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l
 			if(socksend(param->remsock, buf, 3, conf.timeouts[CHAIN_TO]) != 3){
 				return 51;
 			}
-			param->statssrv+=len;
+			param->statssrv64+=len;
 			param->nwrites++;
 			if(sockgetlinebuf(param, SERVER, buf, 2, EOF, conf.timeouts[CHAIN_TO]) != 2){
 				return 52;
@@ -197,7 +148,7 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l
 				if(socksend(param->remsock, buf, inbuf, conf.timeouts[CHAIN_TO]) != inbuf){
 					return 51;
 				}
-				param->statssrv+=inbuf;
+				param->statssrv64+=inbuf;
 				param->nwrites++;
 				if(sockgetlinebuf(param, SERVER, buf, 2, EOF, 60) != 2){
 					return 55;
@@ -218,16 +169,17 @@ int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned l
 				len += 5;
 			}
 			else {
-				buf[3] = 1;
-				memcpy(buf+4, &ip, 4);
-				len = 8;
+				len = 3;
+				buf[len++] = (*SAFAMILY(addr) == AF_INET)? 1 : 4;
+				memcpy(buf+len, SAADDR(addr), SAADDRLEN(addr));
+				len += SAADDRLEN(addr);
 			}
-			memcpy(buf+len, &port, 2);
+			memcpy(buf+len, SAPORT(addr), 2);
 			len += 2;
 			if(socksend(param->remsock, buf, len, conf.timeouts[CHAIN_TO]) != len){
 				return 51;
 			}
-			param->statssrv+=len;
+			param->statssrv64+=len;
 			param->nwrites++;
 			if(sockgetlinebuf(param, SERVER, buf, 4, EOF, conf.timeouts[CHAIN_TO]) != 4){
 				return 57;
@@ -261,16 +213,14 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
 	int done = 0;
 	struct chain * cur;
 	struct chain * redir = NULL;
-	unsigned long targetip;
-	unsigned short targetport;
 	int r2;
 
 	if(param->remsock != INVALID_SOCKET) {
 		return 0;
 	}
-	targetip = param->req.sin_addr.s_addr;
-	targetport = param->req.sin_port;
-	if(!targetip || !targetport) return 100;
+	if(SAISNULL(&param->req) || !*SAPORT(&param->req)) {
+		return 100;
+	}
 
 	r2 = (myrand(param, sizeof(struct clientparam))%1000);
 
@@ -291,7 +241,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
 			r2 = (myrand(param, sizeof(struct clientparam))%1000);
 		}
 		if(!connected){
-			if(!cur->redirip && !cur->redirport){
+			if(SAISNULL(&cur->addr) && !*SAPORT(&cur->addr)){
 				if(cur->extuser){
 					if(param->extusername)
 						myfree(param->extusername);
@@ -316,19 +266,25 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
 					case R_ICQ:
 						param->redirectfunc = icqprchild;
 						break;
+/*
 					case R_MSN:
 						param->redirectfunc = msnprchild;
 						break;
+*/
 					default:
 						param->redirectfunc = proxychild;
 				}
+				if(cur->next)continue;
 				return 0;
 			}
-			else if(!cur->redirip && cur->redirport) param->extport = cur->redirport;
-			else if(!cur->redirport && cur->redirip) param->extip = cur->redirip;
+			else if(!*SAPORT(&cur->addr) && !SAISNULL(&cur->addr)) {
+				unsigned short port = *SAPORT(&param->sinsr);
+				memcpy(&param->sinsr, &cur->addr, SASIZE(&cur->addr)); 
+				*SAPORT(&param->sinsr) = port;
+			}
+			else if(SAISNULL(&cur->addr) && *SAPORT(&cur->addr)) *SAPORT(&param->sinsr) = *SAPORT(&cur->addr);
 			else {
-				param->sins.sin_port = cur->redirport;
-				param->sins.sin_addr.s_addr = cur->redirip;
+				memcpy(&param->sinsr, &cur->addr, SASIZE(&cur->addr)); 
 			}
 
 			if((res = alwaysauth(param))){
@@ -336,7 +292,7 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
 			}
 		}
 		else {
-			res = redir?clientnegotiate(redir, param, cur->redirip, cur->redirport):0;
+			res = (redir)?clientnegotiate(redir, param, (struct sockaddr *)&cur->addr):0;
 			if(res) return res;
 		}
 		redir = cur;
@@ -359,9 +315,25 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
 	}
 
 	if(!connected) return 9;
-	return redir?clientnegotiate(redir, param, targetip, targetport):0;
+	return (redir)?clientnegotiate(redir, param, (struct sockaddr *)&param->req):0;
 }
 
+int IPInentry(struct sockaddr *sa, struct iplist *ipentry){
+	int addrlen;
+	unsigned char *ip, *ipf, *ipt;
+
+
+	ip = (unsigned char *)SAADDR(sa);
+	ipf = (unsigned char *)&ipentry->ip_from;
+	ipt = (unsigned char *)&ipentry->ip_to;
+
+	if(!sa || ! ipentry || *SAFAMILY(sa) != ipentry->family) return 0;
+	addrlen = SAADDRLEN(sa);
+	
+	if(memcmp(ip,ipf,addrlen) < 0 || memcmp(ip,ipt,addrlen) > 0) return 0;
+	return 1;
+	
+}
 
 int ACLmatches(struct ace* acentry, struct clientparam * param){
 	struct userlist * userentry;
@@ -376,14 +348,14 @@ int ACLmatches(struct ace* acentry, struct clientparam * param){
 	username = param->username?param->username:(unsigned char *)"-";
 	if(acentry->src) {
 	 for(ipentry = acentry->src; ipentry; ipentry = ipentry->next)
-		if(ipentry->ip == (param->sinc.sin_addr.s_addr & ipentry->mask)) {
+		if(IPInentry((struct sockaddr *)&param->sincr, ipentry)) {
 			break;
 		}
-		if(!ipentry) return 0;
+	 if(!ipentry) return 0;
 	}
-	if((acentry->dst && param->req.sin_addr.s_addr) || (acentry->dstnames && param->hostname)) {
+	if((acentry->dst && SAISNULL(&param->req)) || (acentry->dstnames && param->hostname)) {
 	 for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next)
-		if(ipentry->ip == (param->req.sin_addr.s_addr & ipentry->mask)) {
+		if(IPInentry((struct sockaddr *)&param->req, ipentry)) {
 			break;
 		}
 	 if(!ipentry) {
@@ -416,10 +388,10 @@ int ACLmatches(struct ace* acentry, struct clientparam * param){
 	 }
 	 if(!ipentry && !hstentry) return 0;
 	}
-	if(acentry->ports && param->req.sin_port) {
+	if(acentry->ports && *SAPORT(&param->req)) {
 	 for (portentry = acentry->ports; portentry; portentry = portentry->next)
-		if(ntohs(param->req.sin_port) >= portentry->startport &&
-			   ntohs(param->req.sin_port) <= portentry->endport) {
+		if(ntohs(*SAPORT(&param->req)) >= portentry->startport &&
+			   ntohs(*SAPORT(&param->req)) <= portentry->endport) {
 			break;
 		}
 		if(!portentry) return 0;
@@ -496,6 +468,7 @@ unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nb
 	sec = tv.tv_sec;
 	msec = tv.tv_usec;
 #endif
+	
 	if(!nbytesin && !nbytesout) return 0;
 	pthread_mutex_lock(&bandlim_mutex);
 	if(param->srv->version != conf.paused){
@@ -541,7 +514,6 @@ unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nb
 
 void trafcountfunc(struct clientparam *param){
 	struct trafcount * tc;
-	unsigned long val;
 	int countout = 0;
 
 	pthread_mutex_lock(&tc_mutex);
@@ -553,9 +525,7 @@ void trafcountfunc(struct clientparam *param){
 				countout = 1;
 				continue;
 			}
-			val = tc->traf + param->statssrv;
-			if(val < tc->traf) tc->trafgb++;
-			tc->traf = val;
+			tc->traf64 += param->statssrv64;
 			time(&t);
 			tc->updated = t;
 		}
@@ -567,9 +537,7 @@ void trafcountfunc(struct clientparam *param){
 			if(tc->ace->action != COUNTOUT) {
 				continue;
 			}
-			val = tc->traf + param->statscli;
-			if(val < tc->traf) tc->trafgb++;
-			tc->traf = val;
+			tc->traf64 += param->statscli64;
 			time(&t);
 			tc->updated = t;
 		}
@@ -596,15 +564,9 @@ int alwaysauth(struct clientparam * param){
 					continue;
 				}
 			
-				if((tc->traflimgb < tc->trafgb) ||
-					((tc->traflimgb == tc->trafgb) && (tc->traflim < tc->traf))
-				) return 10;
+				if(tc->traflim64 <= tc->traf64) return 10;
 				param->trafcountfunc = conf.trafcountfunc;
-				if(tc->traflimgb - tc->trafgb < 1 || ((tc->traflimgb - tc->trafgb) == 1 && tc->traf > tc->traflim)){
-					unsigned maxtraf = tc->traflim - tc->traf;
-					if(!param->maxtrafin || param->maxtrafin > maxtraf) param->maxtrafin = maxtraf;
-				}
-				if((tc->trafgb > tc->traflimgb) || (tc->trafgb == tc->traflimgb && tc->traf >= tc->traflim)) param->maxtrafin = 1; 
+				param->maxtrafin64 = tc->traflim64 - tc->traf64; 
 			}
 		}
 		if(countout)for(tc = conf.trafcounter; tc; tc = tc->next) {
@@ -615,15 +577,9 @@ int alwaysauth(struct clientparam * param){
 					continue;
 				}
 			
-				if((tc->traflimgb < tc->trafgb) ||
-					((tc->traflimgb == tc->trafgb) && (tc->traflim < tc->traf))
-				) return 10;
+				if(tc->traflim64 <= tc->traf64) return 10;
 				param->trafcountfunc = conf.trafcountfunc;
-				if(tc->traflimgb - tc->trafgb < 1 || ((tc->traflimgb - tc->trafgb) == 1 && tc->traf > tc->traflim)){
-					unsigned maxtraf = tc->traflim - tc->traf;
-					if(!param->maxtrafout || param->maxtrafout > maxtraf) param->maxtrafout = maxtraf;
-				}
-				if((tc->trafgb > tc->traflimgb) || (tc->trafgb == tc->traflimgb && tc->traf >= tc->traflim)) param->maxtrafout = 1; 
+				param->maxtrafout64 = tc->traflim64 - tc->traf64; 
 			}
 		}
 
@@ -647,7 +603,7 @@ int checkACL(struct clientparam * param){
 				if(param->operation < 256 && !(param->operation & CONNECT)){
 					continue;
 				}
-				if(param->redirected && acentry->chains && !acentry->chains->redirip && !acentry->chains->redirport) {
+				if(param->redirected && acentry->chains && SAISNULL(&acentry->chains->addr) && !*SAPORT(&acentry->chains->addr)) {
 					continue;
 				}
 				memcpy(&dup, acentry, sizeof(struct ace));
@@ -663,7 +619,11 @@ struct authcache {
 	char * username;
 	char * password;
 	time_t expires;
-	unsigned long ip;	
+#ifndef NOIPV6
+	struct sockaddr_in6 sa;
+#else
+	struct sockaddr_in sa;
+#endif
 	struct authcache *next;
 } *authc = NULL;
 
@@ -690,7 +650,7 @@ int cacheauth(struct clientparam * param){
 			
 		}
 		if(((!(conf.authcachetype&2)) || (param->username && ac->username && !strcmp(ac->username, param->username))) &&
-		   ((!(conf.authcachetype&1)) || ac->ip == param->sinc.sin_addr.s_addr) && 
+		   ((!(conf.authcachetype&1)) || (*SAFAMILY(&ac->sa) ==  *SAFAMILY(&param->sincr) && !memcmp(SAADDR(&ac->sa), &param->sincr, SAADDRLEN(&ac->sa)))) && 
 		   (!(conf.authcachetype&4) || (ac->password && param->password && !strcmp(ac->password, param->password)))) {
 			if(param->username){
 				myfree(param->username);
@@ -724,7 +684,7 @@ int doauth(struct clientparam * param){
 				pthread_mutex_lock(&hash_mutex);
 				for(ac = authc; ac; ac = ac->next){
 					if((!(conf.authcachetype&2) || !strcmp(ac->username, param->username)) &&
-					   (!(conf.authcachetype&1) || ac->ip == param->sinc.sin_addr.s_addr)  &&
+					   (!(conf.authcachetype&1) || (*SAFAMILY(&ac->sa) ==  *SAFAMILY(&param->sincr) && !memcmp(SAADDR(&ac->sa), &param->sincr, SAADDRLEN(&ac->sa))))  &&
 					   (!(conf.authcachetype&4) || (ac->password && !strcmp(ac->password, param->password)))) {
 						ac->expires = conf.time + conf.authcachetime;
 						if(strcmp(ac->username, param->username)){
@@ -737,7 +697,7 @@ int doauth(struct clientparam * param){
 							ac->password = mystrdup(param->password);
 							myfree(tmp);
 						}
-						ac->ip = param->sinc.sin_addr.s_addr;
+						memcpy(&ac->sa, &param->sincr, SASIZE(&param->sincr));
 						break;
 					}
 				}
@@ -746,7 +706,7 @@ int doauth(struct clientparam * param){
 					if(ac){
 						ac->expires = conf.time + conf.authcachetime;
 						ac->username = mystrdup(param->username);
-						ac->ip = param->sinc.sin_addr.s_addr;
+						memcpy(&ac->sa, &param->sincr, SASIZE(&param->sincr));
 						ac->password = NULL;
 						if((conf.authcachetype&4) && param->password) ac->password = mystrdup(param->password);
 					}
@@ -781,28 +741,37 @@ int userauth(struct clientparam * param){
 	return (param->username)? 0:4;
 }
 
-int nbnameauth(struct clientparam * param){
-	unsigned char * name = getNetBIOSnamebyip(param->sinc.sin_addr.s_addr);
-
-	if (param->username) myfree (param->username);
-	param->username = name;
-	return name? 0:4;
-}
-
 int dnsauth(struct clientparam * param){
-        char buf[32];
-	unsigned u = ntohl(param->sinc.sin_addr.s_addr);
+        char buf[128];
+	char addr[16];
+	char dig[]="0123456789abcdef";
 
-	sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", 
+	unsigned u;
+	int i;
 
+	if(*SAFAMILY(&param->sincr)!=AF_INET){
+		char *s = buf;
+		for(i=15; i>=0; i--){
+			unsigned char c=((unsigned char *)SAADDR(&param->sincr))[i];
+			*s++ = dig[(c&0xf)];
+			*s++ = '.';
+			*s++ = dig[(c>>4)];
+			*s++ = '.';
+		}
+		sprintf(s, "ip6.arpa");
+	}
+	else {
+		u = ntohl(*(unsigned long *)SAADDR(&param->sincr));
 
-	((u&0x000000FF)),
-	((u&0x0000FF00)>>8),
-	((u&0x00FF0000)>>16),
-	((u&0xFF000000)>>24));
+		sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", 
+			((u&0x000000FF)),
+			((u&0x0000FF00)>>8),
+			((u&0x00FF0000)>>16),
+			((u&0xFF000000)>>24));
 	
-
-	if(param->sinc.sin_addr.s_addr != udpresolve(buf, NULL, param, 1)) return 6;
+	}
+	if(!udpresolve(*SAFAMILY(&param->sincr), buf, addr, NULL, param, 1)) return 6;
+	if(!memcmp(SAADDR(&param->sincr), addr, SAADDRLEN(&param->sincr))) return 6;
 
 	return param->username? 0:4;
 }
@@ -872,25 +841,29 @@ struct auth authfuncs[] = {
 	{authfuncs+1, NULL, NULL, ""},
 	{authfuncs+2, ipauth, NULL, "iponly"},
 	{authfuncs+3, userauth, checkACL, "useronly"},
-	{authfuncs+4, nbnameauth, checkACL, "nbname"},
-	{authfuncs+5, dnsauth, checkACL, "dnsname"},
-	{authfuncs+6, strongauth, checkACL, "strong"},
-	{authfuncs+7, cacheauth, checkACL, "cache"},
-	{authfuncs+8, NULL, NULL, "none"},
+	{authfuncs+4, dnsauth, checkACL, "dnsname"},
+	{authfuncs+5, strongauth, checkACL, "strong"},
+	{authfuncs+6, cacheauth, checkACL, "cache"},
+	{authfuncs+7, NULL, NULL, "none"},
 
 	{NULL, NULL, NULL, ""}
 };
 
 
-struct hashtable dns_table = {0, NULL, NULL, NULL};
+
+struct hashtable dns_table = {0, 4, {0,0,0,0}, NULL, NULL, NULL};
+struct hashtable dns6_table = {0, 16, {0,0,0,0}, NULL, NULL, NULL};
 
 
-void nametohash(const unsigned char * name, unsigned char *hash){
-	unsigned i, j;
-	memset(hash, 0, sizeof(unsigned)*4);
-	for(i=0, j=0; name[j]; j++){
-		hash[i] += toupper(name[j]) - 32;
-		if(++i == sizeof(unsigned)*4) i = 0;
+void nametohash(const unsigned char * name, unsigned char *hash, unsigned char *rnd){
+	unsigned i, j, k;
+	memcpy(hash, rnd, sizeof(unsigned)*4);
+	for(i=0, j=0, k=0; name[j]; j++){
+		hash[i] += (toupper(name[j]) - 32)+rnd[((toupper(name[j]))*29277+rnd[(k+j+i)%16]+k+j+i)%16];
+		if(++i == sizeof(unsigned)*4) {
+			i = 0;
+			k++;
+		}
 	}
 }
 
@@ -918,8 +891,23 @@ void destroyhashtable(struct hashtable *ht){
 	pthread_mutex_unlock(&hash_mutex);
 }
 
+#define hvalue(I) ((struct hashentry *)((char *)ht->hashvalues + (I)*(sizeof(struct hashentry) + ht->recsize - 4)))
 int inithashtable(struct hashtable *ht, unsigned nhashsize){
 	unsigned i;
+	clock_t c;
+
+
+#ifdef _WIN32
+	struct timeb tb;
+
+	ftime(&tb);
+
+#else
+	struct timeval tb;
+	struct timezone tz;
+	gettimeofday(&tb, &tz);
+#endif
+	c = clock();
 
 	if(nhashsize<4) return 1;
 	pthread_mutex_lock(&hash_mutex);
@@ -932,82 +920,90 @@ int inithashtable(struct hashtable *ht, unsigned nhashsize){
 		ht->hashvalues = NULL;
 	}
 	ht->hashsize = 0;
-	if(!(ht->hashtable = myalloc((nhashsize>>2) * sizeof(struct hashentry *)))){
+	if(!(ht->hashtable = myalloc((nhashsize>>2) *  sizeof(struct hashentry *)))){
 		pthread_mutex_unlock(&hash_mutex);
 		return 2;
 	}
-	if(!(ht->hashvalues = myalloc(nhashsize * sizeof(struct hashentry)))){
+	if(!(ht->hashvalues = myalloc(nhashsize * (sizeof(struct hashentry) + (ht->recsize-4))))){
 		myfree(ht->hashtable);
 		ht->hashtable = NULL;
 		pthread_mutex_unlock(&hash_mutex);
 		return 3;
 	}
 	ht->hashsize = nhashsize;
+	ht->rnd[0] = myrand(&tb, sizeof(tb));
+	ht->rnd[1] = myrand(ht->hashtable, sizeof(ht->hashtable));
+	ht->rnd[2] = myrand(&c, sizeof(c));
+	ht->rnd[3] = myrand(ht->hashvalues,sizeof(ht->hashvalues));
 	memset(ht->hashtable, 0, (ht->hashsize>>2) * sizeof(struct hashentry *));
-	memset(ht->hashvalues, 0, ht->hashsize * sizeof(struct hashentry));
+	memset(ht->hashvalues, 0, ht->hashsize * (sizeof(struct hashentry) + ht->recsize -4));
+
 	for(i = 0; i< (ht->hashsize - 1); i++) {
-		(ht->hashvalues + i)->next = ht->hashvalues + i + 1;
+		hvalue(i)->next = hvalue(i+1);
 	}
 	ht->hashempty = ht->hashvalues;
 	pthread_mutex_unlock(&hash_mutex);
 	return 0;
 }
 
-int initdnshashtable(unsigned nhashsize){
-	return inithashtable(&dns_table, nhashsize);
-}
+void hashadd(struct hashtable *ht, const unsigned char* name, unsigned char* value, time_t expires){
+        struct hashentry * hen, *he;
+        struct hashentry ** hep;
 
-void hashadd(struct hashtable *ht, const unsigned char* name, unsigned long value, time_t expires){
-        struct hashentry * he;
 	unsigned index;
 	
 	pthread_mutex_lock(&hash_mutex);
-	if(!value||!name||!ht->hashtable||!ht->hashempty){
-	 pthread_mutex_unlock(&hash_mutex);
-	 return;
+	if(!ht||!value||!name||!ht->hashtable||!ht->hashempty) {
+		pthread_mutex_unlock(&hash_mutex);
+		return;
 	}
-	he = ht->hashempty;
+	hen = ht->hashempty;
 	ht->hashempty = ht->hashempty->next;
-	nametohash(name, he->hash);
-	he->value = value;
-	he->expires = expires;
-	he->next = NULL;
-	index = hashindex(ht, he->hash);
-	if(!ht->hashtable[index] || !memcmp(he->hash, ht->hashtable[index]->hash, sizeof(he->hash))){
-		he->next = ht->hashtable[index];
-		ht->hashtable[index] = he;
-	}
-	else {
-		memset(he, 0, sizeof(struct hashentry));
-		he->next = ht->hashempty;
-		ht->hashempty = he;
+	nametohash(name, hen->hash, (unsigned char *)ht->rnd);
+	memcpy(hen->value, value, ht->recsize);
+	hen->expires = expires;
+	hen->next = NULL;
+	index = hashindex(ht, hen->hash);
+
+	for(hep = ht->hashtable + index; (he = *hep)!=NULL; ){
+		if(he->expires < conf.time || !memcmp(hen->hash, he->hash, sizeof(he->hash))) {
+			(*hep) = he->next;
+			he->expires = 0;
+			he->next = ht->hashempty;
+			ht->hashempty = he;
+		}
+		else hep=&(he->next);
 	}
+	hen->next = ht->hashtable[index];
+	ht->hashtable[index] = hen;
 	pthread_mutex_unlock(&hash_mutex);
 }
 
-unsigned long hashresolv(struct hashtable *ht, const unsigned char* name, unsigned *ttl){
+unsigned long hashresolv(struct hashtable *ht, const unsigned char* name, unsigned char* value, unsigned *ttl){
 	unsigned char hash[sizeof(unsigned)*4];
         struct hashentry ** hep;
 	struct hashentry *he;
 	unsigned index;
-	time_t t;
 
-	if(!ht->hashtable || !name) return 0;
-	time(&t);
-	nametohash(name, hash);
-	index = hashindex(ht, hash);
 	pthread_mutex_lock(&hash_mutex);
+	if(!ht || !ht->hashtable || !name) {
+		pthread_mutex_unlock(&hash_mutex);
+		return 0;
+	}
+	nametohash(name, hash, (unsigned char *)ht->rnd);
+	index = hashindex(ht, hash);
 	for(hep = ht->hashtable + index; (he = *hep)!=NULL; ){
-		if((unsigned long)he->expires < (unsigned long)t) {
+		if(he->expires < conf.time) {
 			(*hep) = he->next;
 			he->expires = 0;
 			he->next = ht->hashempty;
 			ht->hashempty = he;
 		}
 		else if(!memcmp(hash, he->hash, sizeof(unsigned)*4)){
+			if(ttl) *ttl = (unsigned)(he->expires - conf.time);
+			memcpy(value, he->value, ht->recsize);
 			pthread_mutex_unlock(&hash_mutex);
-			if(ttl) *ttl = (unsigned)(he->expires - t);
-			return he->value;
+			return 1;
 		}
 		else hep=&(he->next);
 	}
@@ -1015,48 +1011,76 @@ unsigned long hashresolv(struct hashtable *ht, const unsigned char* name, unsign
 	return 0;
 }
 
-unsigned long nservers[MAXNSERVERS] = {0, 0, 0, 0, 0};
+struct nserver nservers[MAXNSERVERS] = {{{0},0}, {{0},0}, {{0},0}, {{0},0}, {{0},0}};
+struct nserver authnserver;
 
-unsigned long authnserver;
 
+unsigned long udpresolve(int af, unsigned char * name, unsigned char * value, unsigned *retttl, struct clientparam* param, int makeauth){
 
-unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientparam* param, int makeauth){
-
-	int i;
+	int i,n;
 	unsigned long retval;
 
-	if((retval = hashresolv(&dns_table, name, retttl))) {
+	if((af == AF_INET) && (retval = hashresolv(&dns_table, name, value, retttl))) {
 		return retval;
 	}
-	
-	for(i=0; (i<(makeauth && authnserver)? 1 : MAXNSERVERS) && ((makeauth && authnserver) || nservers[i]); i++){
-		unsigned short nquery, nq, na;
-		unsigned char buf[4096], *s1, *s2;
+	if((af == AF_INET6) && (retval = hashresolv(&dns6_table, name, value, retttl))) {
+		return retval;
+	}
+	n = (makeauth && !SAISNULL(&authnserver.addr))? 1 : numservers;
+	for(i=0; i<n; i++){
+		unsigned short nq, na;
+		unsigned char b[4098], *buf, *s1, *s2;
 		int j, k, len, flen;
 		SOCKET sock;
 		unsigned ttl;
-		time_t t;
-		struct sockaddr_in sin, *sinsp;
+#ifndef NOIPV6
+		struct sockaddr_in6 addr;
+#else
+		struct sockaddr_in addr;
+#endif
+		struct sockaddr *sinsr, *sinsl;
+		int usetcp = 0;
+		unsigned short serial = 1;
+
+		buf = b+2;
 
-		memset(&sin, 0, sizeof(sin));
-		sinsp = (param && !makeauth)? &param->sins : &sin;
+		sinsl = (param && !makeauth)? (struct sockaddr *)&param->sinsl : (struct sockaddr *)&addr;
+		sinsr = (param && !makeauth)? (struct sockaddr *)&param->sinsr : (struct sockaddr *)&addr;
+		memset(sinsl, 0, sizeof(addr));
+		memset(sinsr, 0, sizeof(addr));
 		
 
-		if((sock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) break;
-		sinsp->sin_family = AF_INET;
-		sinsp->sin_port = htons(0);
-		sinsp->sin_addr.s_addr = htonl(0);
-		if(so._bind(sock,(struct sockaddr *)sinsp,sizeof(struct sockaddr_in))) {
+		if(makeauth && !SAISNULL(&authnserver.addr)){
+			usetcp = authnserver.usetcp;
+			*SAFAMILY(sinsl) = *SAFAMILY(&authnserver.addr);
+		}
+		else {
+			usetcp = nservers[i].usetcp;
+			*SAFAMILY(sinsl) = *SAFAMILY(&nservers[i].addr);
+		}
+		if((sock=so._socket(SASOCK(sinsl), usetcp?SOCK_STREAM:SOCK_DGRAM, usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) break;
+		if(so._bind(sock,sinsl,sizeof(addr))){
 			so._shutdown(sock, SHUT_RDWR);
 			so._closesocket(sock);
 			break;
 		}
-		sinsp->sin_addr.s_addr = (makeauth && authnserver)?authnserver : nservers[i];
-		sinsp->sin_port = htons(53);
-
+		if(makeauth && !SAISNULL(&authnserver.addr)){
+			memcpy(sinsr, &authnserver.addr, sizeof(addr));
+		}
+		else {
+			memcpy(sinsr, &nservers[i].addr, sizeof(addr));
+		}
+		if(usetcp){
+			if(so._connect(sock,sinsr,sizeof(addr))) {
+				so._shutdown(sock, SHUT_RDWR);
+				so._closesocket(sock);
+				break;
+			}
+		}
 		len = (int)strlen((char *)name);
-		nquery = myrand(name, len);
-		*(unsigned short*)buf = nquery; /* query id */
+		
+		serial = myrand(name,len);
+		*(unsigned short*)buf = serial; /* query id */
 		buf[2] = 1; 			/* recursive */
 		buf[3] = 0;
 		buf[4] = 0;
@@ -1074,21 +1098,38 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa
 		*s2 = (len - (int)(s2 - buf)) - 1;
 		len++;
 		buf[len++] = 0;
-		buf[len++] = (makeauth == 1)? 0x0c : 0x01;	/* PTR:host address */
+		buf[len++] = (makeauth == 1)? 0x0c : (af==AF_INET6? 0x1c:0x01);	/* PTR:host address */
 		buf[len++] = 0;
 		buf[len++] = 1;			/* INET */
-		if(socksendto(sock, sinsp, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
+		if(usetcp){
+			buf-=2;
+			*(unsigned short*)buf = htons(len);
+			len+=2;
+		}
+
+		if(socksendto(sock, sinsr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
 			so._shutdown(sock, SHUT_RDWR);
 			so._closesocket(sock);
 			continue;
 		}
-		if(param) param->statscli += len;
-		len = sockrecvfrom(sock, sinsp, buf, 4096, 15000);
+		if(param) param->statscli64 += len;
+		len = sockrecvfrom(sock, sinsr, buf, 4096, 15000);
 		so._shutdown(sock, SHUT_RDWR);
 		so._closesocket(sock);
-		if(len <= 13) continue;
-		if(param) param->statssrv += len;
-		if(*(unsigned short *)buf != nquery)continue;
+		if(len <= 13) {
+			continue;
+		}
+		if(param) param->statssrv64 += len;
+		if(usetcp){
+			unsigned short us;
+			us = ntohs(*(unsigned short*)buf);
+			len-=2;
+			buf+=2;
+			if(us > 4096 || us < len || (us > len && sockrecvfrom(sock, sinsr, buf+len, us-len, 15000) != us-len)) {
+				continue;
+			}
+		}
+		if(*(unsigned short *)buf != serial)continue;
 		if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) {
 			return 0;
 		}
@@ -1105,25 +1146,27 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa
 		k += 4;
 		if(na > 255) na = 255;			/* somebody is very evil */
 		for (j = 0; j < na; j++) {		/* now there should be answers */
-			if((k+16) > len) {
+			if((k+(af == AF_INET6?28:16)) > len) {
 				break;
 			}
 			flen = buf[k+11] + (((unsigned short)buf[k+10])<<8);
-			if((k+12+flen) > len) break;
+			if((k+12+flen) > len) {
+				break;
+			}
 			if(makeauth != 1){
-				if(buf[k+2] != 0 || buf[k+3] != 0x01 || flen != 4) {
+				if(buf[k+2] != 0 || buf[k+3] != (af == AF_INET6?0x1c:0x1) || flen != (af == AF_INET6?16:4)) {
 					k+= (12 + flen);
 					continue; 		/* we need A IPv4 */
 				}
-				retval = *(unsigned long *)(buf + k + 12);
 				ttl = ntohl(*(unsigned long *)(buf + k + 6));
-				t = time(0);
-				if(ttl < 60 || ((unsigned)t)+ttl < ttl) ttl = 300;
+				memcpy(value, buf + k + 12, af == AF_INET6? 16:4);
+				if(ttl < 60 || ttl > (3600*12)) ttl = 300;
 				if(ttl){
-					hashadd(&dns_table, name, retval, ((unsigned)t)+ttl);
+					hashadd(af == AF_INET6?&dns6_table:&dns_table, name, value, conf.time+ttl);
+
 				}
 				if(retttl) *retttl = ttl;
-				return retval;
+				return 1;
 			}
 			else {
 				
@@ -1140,19 +1183,30 @@ unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientpa
 				if(param->username)myfree(param->username);
 				param->username = mystrdup (buf + k + 13);
 				
-				return udpresolve(param->username, NULL, NULL, 2);
+				return udpresolve(af,param->username, value, NULL, NULL, 2);
 			}
 		}
 	}
 	return 0;
 }
 
-unsigned long myresolver(unsigned char * name){
- return udpresolve(name, NULL, NULL, 0);
+unsigned long myresolver(int af, unsigned char * name, unsigned char * value){
+ return udpresolve(af, name, value, NULL, NULL, 0);
 }
 
-unsigned long fakeresolver (unsigned char *name){
- return htonl(0x7F000002);
+unsigned long fakeresolver (int af, unsigned char *name, unsigned char * value){
+ memset(value, 0, af == AF_INET6? 16 : 4);
+ if(af == AF_INET6){
+	memset(value, 0, 16);
+	value[15] = 2;
+ }
+ else {
+	value[0] = 127;
+	value[1] = 0;
+	value[2] = 0;
+	value[3] = 2;
+ }
+ return 1;
 }
 
 #ifndef NOODBC
@@ -1254,46 +1308,45 @@ void sqlerr (char *buf){
 		fprintf(conf.stdlog, "%s\n", buf);
 		fflush(conf.stdlog);
 	}
-	pthread_mutex_unlock(&odbc_mutex);
+	pthread_mutex_unlock(&log_mutex);
 }
 
 void logsql(struct clientparam * param, const unsigned char *s) {
-	unsigned char buf[4096];
 	SQLRETURN ret;
 	int len;
 
-	len = dobuf(param, buf, s, "\'");
 
 	if(param->nolog) return;
-	pthread_mutex_lock(&odbc_mutex);
+	pthread_mutex_lock(&log_mutex);
+	len = dobuf(param, tmpbuf, s, "\'");
 
 	if(attempt > 5){
 		time_t t;
 
 		t = time(0);
 		if (t - attempt_time < 180){
-			sqlerr(buf);
+			sqlerr(tmpbuf);
 			return;
 		}
 	}
 	if(!hstmt){
 		if(!init_sql(sqlstring)) {
-			sqlerr(buf);
+			sqlerr(tmpbuf);
 			return;
 		}
 	}
 	if(hstmt){
-		ret = SQLExecDirect(hstmt, (SQLCHAR *)buf, (SQLINTEGER)len);
+		ret = SQLExecDirect(hstmt, (SQLCHAR *)tmpbuf, (SQLINTEGER)len);
 		if(ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO){
 			close_sql();
 			if(!init_sql(sqlstring)){
-				sqlerr(buf);
+				sqlerr(tmpbuf);
 				return;
 			}
 			if(hstmt) {
-				ret = SQLExecDirect(hstmt, (SQLCHAR *)buf, (SQLINTEGER)len);
+				ret = SQLExecDirect(hstmt, (SQLCHAR *)tmpbuf, (SQLINTEGER)len);
 				if(ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO){
-					sqlerr(buf);
+					sqlerr(tmpbuf);
 					return;
 				}
 				attempt = 0;
@@ -1301,22 +1354,8 @@ void logsql(struct clientparam * param, const unsigned char *s) {
 		}
 		attempt = 0;
 	}
-	pthread_mutex_unlock(&odbc_mutex);
+	pthread_mutex_unlock(&log_mutex);
 }
 
 #endif
- 
-#ifdef WITHMAIN
-int main(int argc, unsigned char * argv[]) {
-	unsigned ip = 0;
- WSADATA wd;
- WSAStartup(MAKEWORD( 1, 1 ), &wd);
-	if(argc == 2)ip=getip(argv[1]);
-	if(!hp) {
-		printf("Not found");
-		return 0;
-	}
-	printf("Name: '%s'\n", getnamebyip(ip);
-	return 0;
-}
-#endif
+ 

+ 0 - 1
src/base64.c

@@ -3,7 +3,6 @@
  *
  * please read License Agreement
  *
- * $Id: base64.c,v 1.6 2008/01/08 21:46:36 vlad Exp $
  */
 
 #include <string.h>

+ 211 - 75
src/common.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: common.c,v 1.94 2014-04-07 21:24:45 vlad Exp $
 */
 
 
@@ -22,13 +21,22 @@ int randomizer = 1;
 
 unsigned char **stringtable = NULL;
 
-int myinet_ntoa(struct in_addr in, char * buf){
- unsigned u = ntohl(in.s_addr);
- return sprintf(buf, "%u.%u.%u.%u", 
-	((u&0xFF000000)>>24), 
-	((u&0x00FF0000)>>16),
-	((u&0x0000FF00)>>8),
-	((u&0x000000FF)));
+int myinet_ntop(int af, void *src, char *dst, socklen_t size){
+#ifndef NOIPV6
+ if(af != AF_INET6){
+#endif 
+	unsigned u = ntohl(((struct in_addr *)src)->s_addr);
+ 	return sprintf(dst, "%u.%u.%u.%u", 
+		((u&0xFF000000)>>24), 
+		((u&0x00FF0000)>>16),
+		((u&0x0000FF00)>>8),
+		((u&0x000000FF)));
+#ifndef NOIPV6
+ }
+ *dst = 0;
+ inet_ntop(af, src, dst, size);
+ return (int)strlen(dst);
+#endif 
 }
 
 char *rotations[] = {
@@ -56,8 +64,11 @@ struct extparam conf = {
 	NULL, NULL,
 	NONE, NONE,
 	NULL,
-	INADDR_ANY, INADDR_ANY, 
-	0, 0,
+#ifndef NOIPV6
+	{AF_INET},{AF_INET6},{AF_INET}, 
+#else
+	{AF_INET},{AF_INET}, 
+#endif
 	NULL,
 	NULL,
 	doconnect,
@@ -76,6 +87,10 @@ struct extparam conf = {
 	'@'
 };
 
+int numservers=0;
+
+char* NULLADDR="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
 int myrand(void * entropy, int len){
 	int i;
 	unsigned short init;
@@ -201,23 +216,45 @@ int ceparseargs(const char *str){
 
 #endif
 
+void parsehost(int family, char *host, struct sockaddr *sa){
+	char *sp=NULL,*se=NULL;
+	unsigned short port;
+
+	if(*host == '[') se=strchr(host, ']');
+	if ( (sp = strchr(se?se:host, ':')) ) *sp = 0;
+	if(se){
+		*se = 0;
+	}
+	if(sp){
+		port = atoi(sp+1);
+	}
+	getip46(family, host + (se!=0), (struct sockaddr *)sa);
+	if(se) *se = ']';
+	if(sp) *sp = ':';
+	*SAPORT(sa) = htons(port);
+}
+
 int parsehostname(char *hostname, struct clientparam *param, unsigned short port){
-	char *sp;
+	char *sp=NULL,*se=NULL;
 
 	if(!hostname || !*hostname)return 1;
-	if ( (sp = strchr(hostname, ':')) ) *sp = 0;
-	if(hostname != param->hostname){
+	if(*hostname == '[') se=strchr(hostname, ']');
+	if ( (sp = strchr(se?se:hostname, ':')) ) *sp = 0;
+	if(se){
+		*se = 0;
+	}
+	if(hostname != (char *)param->hostname){
 		if(param->hostname) myfree(param->hostname);
-		param->hostname = (unsigned char *)mystrdup(hostname);
+		param->hostname = (unsigned char *)mystrdup(hostname + (se!=0));
 	}
 	if(sp){
 		port = atoi(sp+1);
-		*sp = ':';
 	}
-	param->req.sin_port=htons(port);
-	param->req.sin_addr.s_addr = getip(param->hostname);
-	param->sins.sin_addr.s_addr = 0;
-	param->sins.sin_port = 0;
+	getip46(param->srv->family, param->hostname, (struct sockaddr *)&param->req);
+	if(se) *se = ']';
+	if(sp) *sp = ':';
+	*SAPORT(&param->req) = htons(port);
+	memset(&param->sinsr, 0, sizeof(param->sinsr));
 	return 0;
 }
 
@@ -260,6 +297,7 @@ int parseconnusername(char *username, struct clientparam *param, int extpasswd,
 	if(!username || !*username) return 1;
         if ((sb=strchr(username, conf.delimchar)) == NULL){
 		if(!param->hostname && param->remsock == INVALID_SOCKET) return 2;
+		if(param->hostname)parsehostname(param->hostname, param, port);
 		return parseusername(username, param, extpasswd);
 	}
 	while ((se=strchr(sb+1, conf.delimchar)))sb=se;
@@ -287,7 +325,7 @@ void clearstat(struct clientparam * param) {
 	param->time_start = (time_t)tv.tv_sec;
 	param->msec_start = (tv.tv_usec / 1000);
 #endif
-	param->statscli = param->statssrv = param->nreads = param->nwrites =
+	param->statscli64 = param->statssrv64 = param->nreads = param->nwrites =
 		param->nconnects = 0;
 }
 
@@ -306,7 +344,6 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 
 	long timezone;
 	unsigned delay;
-	struct in_addr tmpia;
 
 
 
@@ -378,10 +415,10 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 				 i+=10;
 				 break;
 				case 'b':
-				 i+=sprintf((char *)buf+i, "%u", delay?(unsigned)(param->statscli * 1000./delay):0);
+				 i+=sprintf((char *)buf+i, "%u", delay?(unsigned)(param->statscli64 * 1000./delay):0);
 				 break;
 				case 'B':
-				 i+=sprintf((char *)buf+i, "%u", delay?(unsigned)(param->statssrv * 1000./delay):0);
+				 i+=sprintf((char *)buf+i, "%u", delay?(unsigned)(param->statssrv64 * 1000./delay):0);
 				 break;				 
 				case 'D':
 				 i+=sprintf((char *)buf+i, "%u", delay);
@@ -412,7 +449,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 				 break;
 				case 'n':
 					len = param->hostname? (int)strlen((char *)param->hostname) : 0;
-					if (len > 0) for(len = 0; param->hostname[len] && i < 4000; len++, i++){
+					if (len > 0 && !strchr((char *)param->hostname, ':')) for(len = 0; param->hostname[len] && i < 4000; len++, i++){
 						buf[i] = param->hostname[len];
 					 	if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
 						if(doublec && strchr((char *)doublec, buf[i])) {
@@ -420,7 +457,12 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 							i++;
 						}
 					}
-					else i += myinet_ntoa(param->sins.sin_addr, (char *)buf + i);
+					else {
+						buf[i++] = '[';
+						i += myinet_ntop(*SAFAMILY(&param->req), SAADDR(&param->req), (char *)buf + i, 64);
+						buf[i++] = ']';
+						buf[i++] = 0;
+					}
 					break;
 
 				case 'N':
@@ -449,40 +491,39 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char
 				 }
 				 break;
 				case 'e':
-				 tmpia.s_addr = param->extip;
-				 i += myinet_ntoa(tmpia, (char *)buf + i);
+				 i += myinet_ntop(*SAFAMILY(&param->sinsl), SAADDR(&param->sinsl), (char *)buf + i, 64);
 				 break;
 				case 'C':
-				 i += myinet_ntoa(param->sinc.sin_addr, (char *)buf + i);
+				 i += myinet_ntop(*SAFAMILY(&param->sincr), SAADDR(&param->sincr), (char *)buf + i, 64);
 				 break;
 				case 'R':
-				 i += myinet_ntoa(param->sins.sin_addr, (char *)buf + i);
+				 i += myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf + i, 64);
 				 break;
 				case 'Q':
-				 i += myinet_ntoa(param->req.sin_addr, (char *)buf + i);
+				 i += myinet_ntop(*SAFAMILY(&param->req), SAADDR(&param->req), (char *)buf + i, 64);
 				 break;
 				case 'p':
-				 sprintf((char *)buf+i, "%hu", ntohs(param->srv->intport));
+				 sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->srv->intsa)));
 				 i += (int)strlen((char *)buf+i);
 				 break;
 				case 'c':
-				 sprintf((char *)buf+i, "%hu", ntohs(param->sinc.sin_port));
+				 sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->sincr)));
 				 i += (int)strlen((char *)buf+i);
 				 break;
 				case 'r':
-				 sprintf((char *)buf+i, "%hu", ntohs(param->sins.sin_port));
+				 sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->sinsr)));
 				 i += (int)strlen((char *)buf+i);
 				 break;
 				case 'q':
-				 sprintf((char *)buf+i, "%hu", ntohs(param->req.sin_port));
+				 sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->req)));
 				 i += (int)strlen((char *)buf+i);
 				 break;
 				case 'I':
-				 sprintf((char *)buf+i, "%lu", param->statssrv);
+				 sprintf((char *)buf+i, "%"PRINTF_INT64_MODIFIER"u", param->statssrv64);
 				 i += (int)strlen((char *)buf+i);
 				 break;
 				case 'O':
-				 sprintf((char *)buf+i, "%lu", param->statscli);
+				 sprintf((char *)buf+i, "%"PRINTF_INT64_MODIFIER"u", param->statscli64);
 				 i += (int)strlen((char *)buf+i);
 				 break;
 				case 'h':
@@ -560,77 +601,94 @@ void lognone(struct clientparam * param, const unsigned char *s) {
 	if(param->trafcountfunc)(*param->trafcountfunc)(param);
 	clearstat(param);
 }
-
+pthread_mutex_t log_mutex;
+int logmutexinit = 0;
+unsigned char tmpbuf[8192];
 
 void logstdout(struct clientparam * param, const unsigned char *s) {
-	unsigned char buf[4096];
 	FILE *log;
 
+	if(!logmutexinit){
+		pthread_mutex_init(&log_mutex, NULL);
+		logmutexinit = 1;
+	}
+	pthread_mutex_lock(&log_mutex);
 	log = param->srv->stdlog?param->srv->stdlog:conf.stdlog?conf.stdlog:stdout;
-	dobuf(param, buf, s, NULL);
-	if(!param->nolog)if(fprintf(log, "%s\n", buf) < 0) {
+	dobuf(param, tmpbuf, s, NULL);
+	if(!param->nolog)if(fprintf(log, "%s\n", tmpbuf) < 0) {
 		perror("printf()");
 	};
 	if(log != conf.stdlog)fflush(log);
+	pthread_mutex_unlock(&log_mutex);
 }
 #ifndef _WIN32
 void logsyslog(struct clientparam * param, const unsigned char *s) {
-	unsigned char buf[4096];
 
-	dobuf(param, buf, s, NULL);
-	if(!param->nolog)syslog(LOG_INFO, "%s", buf);
+	if(!logmutexinit){
+		pthread_mutex_init(&log_mutex, NULL);
+		logmutexinit = 1;
+	}
+	pthread_mutex_lock(&log_mutex);
+	dobuf(param, tmpbuf, s, NULL);
+	if(!param->nolog)syslog(LOG_INFO, "%s", tmpbuf);
+	pthread_mutex_unlock(&log_mutex);
 }
 #endif
 
 int doconnect(struct clientparam * param){
- SASIZETYPE size = sizeof(param->sins);
- struct sockaddr_in bindsa;
+ SASIZETYPE size = sizeof(param->sinsr);
+
+ if (*SAFAMILY(&param->sincr) == *SAFAMILY(&param->req) && !memcmp(SAADDR(&param->sincr), SAADDR(&param->req), SAADDRLEN(&param->req)) &&
+	*SAPORT(&param->sincr) == *SAPORT(&param->req)) return 519;
+
  if (param->operation == ADMIN || param->operation == DNSRESOLVE || param->operation == BIND || param->operation == UDPASSOC)
 	return 0;
  if (param->remsock != INVALID_SOCKET){
-	if(so._getpeername(param->remsock, (struct sockaddr *)&param->sins, &size)==-1) {return (15);}
+	if(so._getpeername(param->remsock, (struct sockaddr *)&param->sinsr, &size)==-1) {return (15);}
  }
  else {
-	struct linger lg;
+	struct linger lg = {1,conf.timeouts[SINGLEBYTE_S]};
+	int opt = 1;
 
-	if(!param->sins.sin_addr.s_addr)
-		if(!(param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr)) return 100;
-	if(!param->sins.sin_port)param->sins.sin_port = param->req.sin_port;
-	if ((param->remsock=so._socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {return (11);}
+	if(SAISNULL(&param->sinsr)){
+		if(SAISNULL(&param->req)) {
+			return 100;
+		}
+		*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req);
+		memcpy(SAADDR(&param->sinsr), SAADDR(&param->req), SAADDRLEN(&param->req)); 
+	}
+	if(!*SAPORT(&param->sinsr))*SAPORT(&param->sinsr) = *SAPORT(&param->req);
+	if ((param->remsock=so._socket(SASOCK(&param->sinsr), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {return (11);}
 	so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
-	memset(&bindsa, 0, sizeof(bindsa));
-	bindsa.sin_family = AF_INET;
-	bindsa.sin_port = param->extport;
-	bindsa.sin_addr.s_addr = param->extip;
-	if (param->srv->targetport && !bindsa.sin_port && ntohs(param->sinc.sin_port) > 1023) bindsa.sin_port = param->sinc.sin_port;
-	if(so._bind(param->remsock, (struct sockaddr*)&bindsa, sizeof(bindsa))==-1) {
-		memset(&bindsa, 0, sizeof(bindsa));
-		bindsa.sin_family = AF_INET;
-		bindsa.sin_addr.s_addr = param->extip;
-		bindsa.sin_port = 0;
-		if(so._bind(param->remsock, (struct sockaddr*)&bindsa, sizeof(bindsa))==-1) {
+	so._setsockopt(param->remsock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int));
+
+#ifndef NOIPV6
+	if(*SAFAMILY(&param->sinsr) == AF_INET6) memcpy(&param->sinsl, &param->srv->extsa6, sizeof(param->srv->extsa6));
+	else
+#endif
+		memcpy(&param->sinsl, &param->srv->extsa, sizeof(param->srv->extsa));
+	if (param->srv->targetport && !*SAPORT(&param->sinsl) && ntohs(*SAPORT(&param->sincr)) > 1023) *SAPORT(&param->sinsl) = *SAPORT(&param->sincr);
+	if(so._bind(param->remsock, (struct sockaddr*)&param->sinsl, sizeof(param->sinsl))==-1) {
+		*SAPORT(&param->sinsl) = 0;
+		if(so._bind(param->remsock, (struct sockaddr*)&param->sinsl, sizeof(param->sinsl))==-1) {
 			return 12;
 		}
 	}
 	
-	param->sins.sin_family = AF_INET;
 	if(param->operation >= 256 || (param->operation & CONNECT)){
 #ifdef _WIN32
 		unsigned long ul = 1;
 #endif
-		if(so._connect(param->remsock,(struct sockaddr *)&param->sins,sizeof(param->sins))) {return (13);}
+		if(so._connect(param->remsock,(struct sockaddr *)&param->sinsr,sizeof(param->sinsr))) {return (13);}
 		param->nconnects++;
 #ifdef _WIN32
 		ioctlsocket(param->remsock, FIONBIO, &ul);
 #else
 		fcntl(param->remsock,F_SETFL,O_NONBLOCK);
 #endif
-		if(so._getsockname(param->remsock, (struct sockaddr *)&bindsa, &size)==-1) {return (15);}
-		param->extip = bindsa.sin_addr.s_addr;
-	}
-	else {
-		if(so._getsockname(param->remsock, (struct sockaddr *)&param->sins, &size)==-1) {return (15);}
+		size = sizeof(param->sinsl);
 	}
+	if(so._getsockname(param->remsock, (struct sockaddr *)&param->sinsl, &size)==-1) {return (15);}
  }
  return 0;
 }
@@ -667,11 +725,13 @@ struct hostent * my_gethostbyname(char *name, char *buf, struct hostent *hp){
 }
 #endif
 
+#ifdef NOIPV6
 unsigned long getip(unsigned char *name){
 	unsigned long retval;
 	int i;
 	int ndots = 0;
 	struct hostent *hp=NULL;
+	RESOLVFUNC tmpresolv;
 
 #ifdef GETHOSTBYNAME_R
 	struct hostent he;
@@ -688,15 +748,14 @@ unsigned long getip(unsigned char *name){
 		if(name[i] <'0' || name[i] >'9') break;
 	}
 	if(!name[i] && ndots == 3){
-		unsigned long ip;
-		if(scanaddr(name, &ip, NULL) == 4){
-			return ip;
+		if(scanaddr(name, &retval, NULL) == 4){
+			return retval;
 		}
 	}
-	if(resolvfunc){
-		if((retval = (*resolvfunc)(name))) return retval;
+	if((tmpresolv=resolvfunc)){
+		if((*tmpresolv)(AF_INET, name, (unsigned char *)&retval)) return retval;
 		if(conf.demanddialprog) system(conf.demanddialprog);
-		return (*resolvfunc)(name);
+		return (*tmpresolv)(AF_INET, name, (unsigned char *)&retval)?retval:0;
 	}
 #if !defined(_WIN32) && !defined(GETHOSTBYNAME_R)
 	if(!ghbn_init){
@@ -719,3 +778,80 @@ unsigned long getip(unsigned char *name){
 #endif
 	return retval;
 }
+#endif
+
+unsigned long getip46(int family, unsigned char *name,  struct sockaddr *sa){
+#ifndef NOIPV6
+	int ndots=0, ncols=0, nhex=0;
+	struct addrinfo *ai, hint;
+	int i;
+        RESOLVFUNC tmpresolv;
+
+	if(!sa) return 0;
+	if(!family) {
+		family = 4;
+#else
+		((struct sockaddr_in *)sa)->sin_family = AF_INET;
+		return (((struct sockaddr_in *)sa)->sin_addr.s_addr = getip(name))? AF_INET:0;
+#endif
+#ifndef NOIPV6
+	}
+	for(i=0; name[i]; i++){
+		if(name[i] == '.'){
+			if(++ndots > 3) {
+				break;
+			}
+		}
+		else if(name[i] == ':'){
+			if(++ncols > 7) {
+				break;
+			}
+		}
+		else if(name[i] == '%' || (name[i] >= 'a' && name[i] <= 'f') || (name[i] >= 'A' && name[i] <= 'F')){
+			nhex++;
+		}
+		else if(name[i] <'0' || name[i] >'9') {
+			break;
+		}
+	}
+	if(!name[i]){
+		if(ndots == 3 && ncols == 0 && nhex == 0){
+			*SAFAMILY(sa)=(family == 6)?AF_INET6 : AF_INET;
+			return inet_pton(*SAFAMILY(sa), name, SAADDR(sa))? *SAFAMILY(sa) : 0; 
+		}
+		if(ncols >= 2) {
+			*SAFAMILY(sa)=AF_INET6;
+			return inet_pton(AF_INET6, name, SAADDR(sa))?(family==4? 0:AF_INET6) : 0;
+		}
+	}
+	if((tmpresolv = resolvfunc)){
+		int f = (family == 6 || family == 64)?AF_INET6:AF_INET;
+		*SAFAMILY(sa) = f;
+		if(tmpresolv(f, name, SAADDR(sa))) return f;
+		if(family == 4 || family == 6) return 0;
+		f = (family == 46)? AF_INET6 : AF_INET;
+		*SAFAMILY(sa) = f;
+		if(tmpresolv(f, name, SAADDR(sa))) return f;
+		return 0;
+	}
+	memset(&hint, 0, sizeof(hint));
+	hint.ai_family = (family == 6 || family == 64)?AF_INET6:AF_INET;
+	if (getaddrinfo(name, NULL, &hint, &ai)) {
+		if(family == 64 || family == 46){
+			hint.ai_family = (family == 64)?AF_INET:AF_INET6;
+			if (getaddrinfo(name, NULL, &hint, &ai)) return 0;
+		}
+		else return 0;
+	}
+	if(ai){
+		if(ai->ai_addr->sa_family == AF_INET || ai->ai_addr->sa_family == AF_INET6){
+			*SAFAMILY(sa)=ai->ai_addr->sa_family;
+			memcpy(SAADDR(sa), SAADDR(ai->ai_addr), SAADDRLEN(ai->ai_addr));
+			freeaddrinfo(ai);
+			return *SAFAMILY(sa);
+		}
+		freeaddrinfo(ai);
+	}
+	return 0;
+#endif
+}

+ 1685 - 0
src/conf.c

@@ -0,0 +1,1685 @@
+#include "proxy.h"
+#ifndef _WIN32
+#include <sys/resource.h>
+#ifndef NOPLUGINS
+#include <dlfcn.h>
+#endif
+#endif
+
+#ifndef DEFAULTCONFIG
+#define DEFAULTCONFIG conf.stringtable[25]
+#endif
+
+pthread_mutex_t bandlim_mutex;
+pthread_mutex_t tc_mutex;
+pthread_mutex_t pwl_mutex;
+pthread_mutex_t hash_mutex;
+pthread_mutex_t config_mutex;
+
+int haveerror = 0;
+int linenum = 0;
+
+FILE *writable;
+struct counter_header cheader = {"3CF", (time_t)0};
+struct counter_record crecord;
+
+int mainfunc (int argc, char** argv);
+
+struct proxydef childdef = {NULL, 0, 0, S_NOSERVICE, ""};
+
+#define STRINGBUF 65535
+#define NPARAMS	  4096
+
+#ifndef _WIN32
+char *chrootp = NULL;
+#endif
+char * curconf = NULL;
+
+FILE * confopen(){
+	curconf = conf.conffile;
+#ifndef _WIN32
+	if(chrootp){
+		if(strstr(curconf, chrootp) == curconf)
+			curconf += strlen(chrootp);
+	}
+#endif
+	if(writable) {
+		rewind(writable);
+		return writable;
+	}
+	return fopen(curconf, "r");
+}
+
+
+#ifdef _WIN32
+DWORD WINAPI startsrv(LPVOID data) {
+#else
+void * startsrv(void * data) {
+#endif
+  struct child *d = (struct child *)data;
+  mainfunc(d->argc, (char **)d->argv);
+  return 0;
+}
+
+int included =0;
+
+int getrotate(char c){
+	switch(c){
+	case 'c':
+	case 'C':
+		return MINUTELY;
+	case 'h':
+	case 'H':
+		return HOURLY;
+	case 'd':
+	case 'D':
+		return DAILY;
+	case 'w':
+	case 'W':
+		return WEEKLY;
+	case 'y':
+	case 'Y':
+		return ANNUALLY;
+	case 'm':
+	case 'M':
+		return MONTHLY;
+	default:
+		return NEVER;
+	}
+}
+
+
+unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t) {
+	struct tm *ts;
+
+	ts = localtime(&t);
+	if(strchr((char *)name, '%')){
+		struct clientparam fakecli;
+
+		memset(&fakecli, 0, sizeof(fakecli));
+		dobuf2(&fakecli, buf, NULL, NULL, ts, (char *)name);
+	}
+	else switch(lt){
+		case NONE:
+			sprintf((char *)buf, "%s", name);
+			break;
+		case ANNUALLY:
+			sprintf((char *)buf, "%s.%04d", name, ts->tm_year+1900);
+			break;
+		case MONTHLY:
+			sprintf((char *)buf, "%s.%04d.%02d", name, ts->tm_year+1900, ts->tm_mon+1);
+			break;
+		case WEEKLY:
+			t = t - (ts->tm_wday * (60*60*24));
+			ts = localtime(&t);
+			sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
+			break;
+		case DAILY:
+			sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
+			break;
+		case HOURLY:
+			sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour);
+			break;
+		case MINUTELY:
+			sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min);
+			break;
+		default:
+			break;
+	}
+	if(ext){
+		strcat((char *)buf, ".");
+		strcat((char *)buf, (char *)ext);
+	}
+	return buf;
+}
+
+int start_proxy_thread(struct child * chp){
+  pthread_t thread;
+#ifdef _WIN32
+  HANDLE h;
+#endif
+
+	conf.threadinit = 1;
+#ifdef _WIN32
+#ifndef _WINCE
+	h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, 16384, startsrv, (void *) chp, (DWORD)0, &thread);
+#else
+	h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, 16384, startsrv, (void *) chp, (DWORD)0, &thread);
+#endif
+	if(h)CloseHandle(h);
+#else
+	pthread_attr_init(&pa);
+	pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + 16384);
+	pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
+	pthread_create(&thread, &pa, startsrv, (void *)chp);
+#endif
+	while(conf.threadinit)usleep(SLEEPTIME);
+	if(haveerror)  {
+		fprintf(stderr, "Service not started on line: %d\n", linenum);
+		return(40);
+	}
+	return 0;
+}
+
+static int h_proxy(int argc, unsigned char ** argv){
+  struct child ch;
+
+	ch.argc = argc;
+	ch.argv = argv;
+	if(!strcmp((char *)argv[0], "proxy")) {
+		childdef.pf = proxychild;
+		childdef.port = 3128;
+		childdef.isudp = 0;
+		childdef.service = S_PROXY;
+		childdef.helpmessage = " -n - no NTLM support\n";
+#ifdef NOIPV6
+		if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize)){
+			fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, proxy may run very slow\n", linenum);
+		}
+#endif
+	}
+	else if(!strcmp((char *)argv[0], "pop3p")) {
+		childdef.pf = pop3pchild;
+		childdef.port = 110;
+		childdef.isudp = 0;
+		childdef.service = S_POP3P;
+		childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
+	}
+	else if(!strcmp((char *)argv[0], "smtpp")) {
+		childdef.pf = smtppchild;
+		childdef.port = 25;
+		childdef.isudp = 0;
+		childdef.service = S_SMTPP;
+		childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
+	}
+	else if(!strcmp((char *)argv[0], "ftppr")) {
+		childdef.pf = ftpprchild;
+		childdef.port = 21;
+		childdef.isudp = 0;
+		childdef.service = S_FTPPR;
+		childdef.helpmessage = " -hdefault_host[:port] - use this host and port as default if no host specified\n";
+	}
+	else if(!strcmp((char *)argv[0], "socks")) {
+		childdef.pf = sockschild;
+		childdef.port = 1080;
+		childdef.isudp = 0;
+		childdef.service = S_SOCKS;
+		childdef.helpmessage = " -n - no NTLM support\n";
+#ifdef NOIPV6
+		if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize)){
+			fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, socks may run very slow\n", linenum);
+		}
+#endif
+	}
+	else if(!strcmp((char *)argv[0], "tcppm")) {
+		childdef.pf = tcppmchild;
+		childdef.port = 0;
+		childdef.isudp = 0;
+		childdef.service = S_TCPPM;
+		childdef.helpmessage = "";
+	}
+	else if(!strcmp((char *)argv[0], "icqpr")) {
+		childdef.pf = icqprchild;
+		childdef.port = 0;
+		childdef.isudp = 0;
+		childdef.service = S_ICQPR;
+		childdef.helpmessage = "";
+	}
+/*
+	else if(!strcmp((char *)argv[0], "msnpr")) {
+		childdef.pf = msnprchild;
+		childdef.port = 0;
+		childdef.isudp = 0;
+		childdef.service = S_MSNPR;
+		childdef.helpmessage = "";
+	}
+*/
+	else if(!strcmp((char *)argv[0], "udppm")) {
+		childdef.pf = udppmchild;
+		childdef.port = 0;
+		childdef.isudp = 1;
+		childdef.service = S_UDPPM;
+		childdef.helpmessage = " -s single packet UDP service for request/reply (DNS-like) services\n";
+	}
+	else if(!strcmp((char *)argv[0], "admin")) {
+		childdef.pf = adminchild;
+		childdef.port = 80;
+		childdef.isudp = 0;
+		childdef.service = S_ADMIN;
+	}
+	else if(!strcmp((char *)argv[0], "dnspr")) {
+		childdef.pf = dnsprchild;
+		childdef.port = 53;
+		childdef.isudp = 1;
+		childdef.service = S_DNSPR;
+		childdef.helpmessage = " -s - simple DNS forwarding - do not use 3proxy resolver / name cache\n";
+#ifndef NOIPV6
+		if(!resolvfunc || (resolvfunc == myresolver && !dns_table.hashsize) || resolvfunc == fakeresolver){
+			fprintf(stderr, "[line %d] Warning: no nserver/nscache configured, dnspr will not work as expected\n", linenum);
+		}
+#endif
+	}
+	return start_proxy_thread(&ch);
+}
+
+static int h_internal(int argc, unsigned char ** argv){
+	getip46(46, argv[1], (struct sockaddr *)&conf.intsa);
+	return 0;
+}
+
+static int h_external(int argc, unsigned char ** argv){
+	int res;
+#ifndef NOIPV6
+	struct sockaddr_in6 sa6;
+	res = getip46(46, argv[1], (struct sockaddr *)&sa6);
+	if(!res) return 1; 
+	memcpy((*SAFAMILY(&sa6)==AF_INET)?(void *)&conf.extsa:(void *)&conf.extsa6, &sa6, SASIZE(&sa6)); 
+#else
+	res = getip46(46, argv[1], (struct sockaddr *)&conf.extsa);
+	if(!res) return 1; 
+#endif
+	return 0;
+}
+
+static int h_log(int argc, unsigned char ** argv){ 
+	conf.logfunc = logstdout;
+	if(conf.logtarget){
+		myfree(conf.logtarget);
+		conf.logtarget = NULL;
+	}
+	if(argc > 1) {
+		conf.logtarget = (unsigned char *)mystrdup((char *)argv[1]);
+		if(*argv[1]=='@'){
+#ifndef _WIN32
+			openlog((char *)conf.logtarget+1, LOG_PID, LOG_DAEMON);
+			conf.logfunc = logsyslog;
+#endif
+		}
+#ifndef NOODBC
+		else if(*argv[1]=='&'){
+			pthread_mutex_lock(&log_mutex);
+			close_sql();
+			init_sql((char *)argv[1]+1);
+			pthread_mutex_unlock(&log_mutex);
+			conf.logfunc = logsql;
+		}
+#endif
+		else {
+			FILE *fp;
+			if(argc > 2) {
+				conf.logtype = getrotate(*argv[2]);
+			}
+			conf.logtime = time(0);
+			if(conf.logname)myfree(conf.logname);
+			conf.logname = (unsigned char *)mystrdup((char *)argv[1]);
+			fp = fopen((char *)dologname (tmpbuf, conf.logname, NULL, conf.logtype, conf.logtime), "a");
+			if(!fp){
+				perror("fopen()");
+				return 1;
+			}
+			else {
+				pthread_mutex_lock(&log_mutex);
+				if(conf.stdlog)fclose(conf.stdlog);
+				conf.stdlog = fp;
+				pthread_mutex_unlock(&log_mutex);
+#ifdef _WINCE
+				freopen(tmpbuf, "w", stdout);
+				freopen(tmpbuf, "w", stderr);
+#endif
+			}
+		}
+	}
+	return 0;
+}
+
+static int h_service(int argc, unsigned char **argv){
+	return 0;
+}
+
+static int h_daemon(int argc, unsigned char **argv){
+	if(!conf.demon)daemonize();
+	conf.demon = 1;
+	return 0;
+}
+
+static int h_config(int argc, unsigned char **argv){
+	if(conf.conffile)myfree(conf.conffile);
+	conf.conffile = mystrdup((char *)argv[1]);
+	return 0;
+}
+
+static int h_include(int argc, unsigned char **argv){
+	int res;
+	FILE *fp1;
+
+	fp1 = fopen((char *)argv[1], "r");
+	if(!fp1){
+		fprintf(stderr, "Unable to open included file: %s\n", argv[1]);
+		return 1;
+	}
+	res = readconfig(fp1);
+	fclose(fp1);
+	return res;
+}
+
+static int h_archiver(int argc, unsigned char **argv){
+	int j;
+
+	conf.archiver = myalloc(argc * sizeof(char *));
+	if(conf.archiver) {
+		conf.archiverc = argc;
+		for(j = 0; j < conf.archiverc; j++) conf.archiver[j] = (unsigned char *)mystrdup((char *)argv[j]);
+	}
+	return 0;
+}
+
+static int h_counter(int argc, unsigned char **argv){
+	struct counter_header ch1;
+	if(conf.counterd >=0)close(conf.counterd);
+	if(!conf.trafcountfunc) conf.trafcountfunc = trafcountfunc;
+	conf.counterd = open((char *)argv[1], O_BINARY|O_RDWR|O_CREAT, 0660);
+	if(conf.counterd<0){
+		fprintf(stderr, "Unable to open counter file %s, line %d\n", argv[1], linenum);
+		return 1;
+	}
+	if(read(conf.counterd, &ch1, sizeof(ch1))==sizeof(ch1)){
+		if(memcmp(&ch1, &cheader, 4)){
+			fprintf(stderr, "Not a counter file %s, line %d\n", argv[1], linenum);
+			return 2;
+		}
+#ifdef  _MSC_VER
+#ifdef _TIME64_T_DEFINED
+#ifndef _MAX__TIME64_T
+#define _MAX__TIME64_T     0x793406fffi64
+#endif 
+#endif
+		if(ch1.updated >= _MAX__TIME64_T){
+			fprintf(stderr, "Invalid or corrupted counter file %s. Use countersutil utility to convert from older version\n", argv[1]);
+			return 3;
+		}
+#endif
+		cheader.updated = ch1.updated;
+	}
+	if(argc >=4) {
+		conf.countertype = getrotate(*argv[2]);
+		if(conf.counterfile) myfree(conf.counterfile);
+		conf.counterfile = mystrdup((char *)argv[3]);
+	}
+	return 0;
+}
+
+static int h_rotate(int argc, unsigned char **argv){
+	conf.rotate = atoi((char *)argv[1]);
+	return 0;
+}
+
+static int h_logformat(int argc, unsigned char **argv){
+	if(conf.logformat) myfree(conf.logformat);
+	conf.logformat = (unsigned char *)mystrdup((char *)argv[1]);
+	return 0;
+}
+
+static int h_timeouts(int argc, unsigned char **argv){
+	int j;
+
+	for(j = 0; conf.timeouts[j] && j + 1 < argc; j++) {
+		if((conf.timeouts[j] = atoi((char *)argv[j + 1])) <= 0 || conf.timeouts[j] > 2000000){
+			fprintf(stderr, "Invalid timeout: %s, line %d\n", argv[j + 1], linenum);
+			return(1);
+		}
+	}
+	return 0;
+}
+
+static int h_noop(int argc, unsigned char **argv){
+	return 0;
+}
+
+static int h_auth(int argc, unsigned char **argv){
+	struct auth *au, * newau;
+	
+	freeauth(conf.authfuncs);
+	conf.authfuncs = NULL;
+	if(!conf.bandlimfunc)conf.bandlimfunc = bandlimitfunc;
+	for(argc--; argc; argc--){
+	  for(au = authfuncs; au; au=au->next){
+		if(!strcmp((char *)argv[argc], au->desc)){
+			newau = myalloc(sizeof(struct auth));
+			newau->next = conf.authfuncs;
+			conf.authfuncs = newau;
+			conf.authfuncs->desc = au->desc;
+			conf.authfuncs->authenticate = au->authenticate;
+			conf.authfuncs->authorize = au->authorize;
+			break;
+		}
+	  }
+	  if(!au) return 1;
+	}
+	conf.authfunc = doauth;
+	return 0;
+}
+
+static int h_users(int argc, unsigned char **argv){
+  int j;
+  unsigned char *arg;
+  struct passwords *pwl = NULL;
+
+	for (j = 1; j<argc; j++) {
+		if(!(pwl = myalloc(sizeof(struct passwords)))) {
+			fprintf(stderr, "No memory for PWL entry, line %d\n", linenum);
+			return(1);
+		}
+		memset(pwl, 0, sizeof(struct passwords));
+
+		arg = (unsigned char *)strchr((char *)argv[j], ':');
+		if(!arg||!arg[1]||!arg[2]||arg[3]!=':')	{
+			pwl->user = (unsigned char *)mystrdup((char *)argv[j]);
+			pwl->pwtype = SYS;
+		}
+		else {
+			*arg = 0;
+			pwl->user = (unsigned char *)mystrdup((char *)argv[j]);
+			if((arg[1] == 'C' && arg[2] == 'L' && (pwl->pwtype = CL)) ||
+				(arg[1] == 'C' && arg[2] == 'R' && (pwl->pwtype = CR)) ||
+				(arg[1] == 'N' && arg[2] == 'T' && (pwl->pwtype = NT)) ||
+				(arg[1] == 'L' && arg[2] == 'M' && (pwl->pwtype = LM))){
+				pwl->password = (unsigned char *)mystrdup((char *)arg+4);
+			}
+			else {
+				pwl->password = (unsigned char *) mystrdup((char *)arg + 1);
+				pwl->pwtype = UN;
+			}
+		}
+		pthread_mutex_lock(&pwl_mutex);
+		pwl->next = conf.pwl;
+		conf.pwl = pwl;
+		pthread_mutex_unlock(&pwl_mutex);
+
+
+	}
+	return 0;
+}
+
+static int h_maxconn(int argc, unsigned char **argv){
+	conf.maxchild = atoi((char *)argv[1]);
+	if(!conf.maxchild) {
+		return(1);
+	}
+#ifndef _WIN32
+	{
+		struct rlimit rl;
+		if(!getrlimit(RLIMIT_NOFILE, &rl)){
+			if((conf.maxchild<<1) > rl.rlim_cur)
+				fprintf(stderr, "[line %d] Warning: current open file ulimits are too low (cur: %d/max: %d),"
+						" maxconn requires at least %d for every running service."
+						" Configure ulimits according to system documentation\n",
+						  linenum, (int)rl.rlim_cur, (int)rl.rlim_max, (conf.maxchild<<1));
+		}
+	}
+#endif
+	return 0;
+}
+
+static int h_flush(int argc, unsigned char **argv){
+	freeacl(conf.acl);
+	conf.acl = NULL;
+	return 0;
+}
+
+/*
+static int h_flushusers(int argc, unsigned char **argv){
+	freepwl(conf.pwl);
+	conf.pwl = NULL;
+	return 0;
+}
+*/
+
+static int h_nserver(int argc, unsigned char **argv){
+  char *str;
+
+	if(numservers < MAXNSERVERS) {
+		if((str = strchr((char *)argv[1], '/')))
+			*str = 0;
+		if(!getip46(46, argv[1], (struct sockaddr *)&nservers[numservers].addr)) return 1;
+		*SAPORT(&nservers[numservers].addr) = htons(53);
+		if(str) {
+			nservers[numservers].usetcp = strstr(str + 1, "tcp")? 1:0;
+			*str = '/';
+		}
+		numservers++;
+
+	}
+	resolvfunc = myresolver;
+	return 0;
+}
+
+static int h_authnserver(int argc, unsigned char **argv){
+  char *str;
+
+	if((str = strchr((char *)argv[1], '/')))
+		*str = 0;
+	if(!getip46(46, argv[1], (struct sockaddr *)&authnserver.addr)) return 1;
+	*SAPORT(&authnserver.addr) = htons(53);
+	if(str) {
+		authnserver.usetcp = strstr(str + 1, "tcp")? 1:0;
+		*str = '/';
+	}
+	return 0;
+}
+
+static int h_fakeresolve(int argc, unsigned char **argv){
+	resolvfunc = fakeresolver;
+	return 0;
+}
+
+static int h_nscache(int argc, unsigned char **argv){
+  int res;
+
+	res = atoi((char *)argv[1]);
+	if(res < 256) {
+		fprintf(stderr, "Invalid NS cache size: %d\n", res);
+		return 1;
+	}
+	if(inithashtable(&dns_table, (unsigned)res)){
+		fprintf(stderr, "Failed to initialize NS cache\n");
+		return 2;
+	}
+	return 0;
+}
+static int h_nscache6(int argc, unsigned char **argv){
+  int res;
+
+	res = atoi((char *)argv[1]);
+	if(res < 256) {
+		fprintf(stderr, "Invalid NS cache size: %d\n", res);
+		return 1;
+	}
+	if(inithashtable(&dns6_table, (unsigned)res)){
+		fprintf(stderr, "Failed to initialize NS cache\n");
+		return 2;
+	}
+	return 0;
+}
+
+static int h_nsrecord(int argc, unsigned char **argv){
+#ifndef NOIPV6
+	struct sockaddr_in6 sa;
+#else
+	struct sockaddr_in sa;
+#endif
+	memset(&sa, 0, sizeof(sa));
+	if(!getip46(46, argv[2], (struct sockaddr *)&sa)) return 1;
+
+	hashadd(*SAFAMILY(&sa)==AF_INET6?&dns6_table:&dns_table, argv[1], SAADDR(&sa), (time_t)0xffffffff);
+	return 0;
+}
+
+static int h_dialer(int argc, unsigned char **argv){
+	if(conf.demanddialprog) myfree(conf.demanddialprog);
+	conf.demanddialprog = mystrdup((char *)argv[1]);
+	return 0;
+}
+
+static int h_system(int argc, unsigned char **argv){
+  int res;
+
+	if((res = system((char *)argv[1])) == -1){
+		fprintf(stderr, "Failed to start %s\n", argv[1]);
+		return(1);
+	}
+	return 0;
+}
+
+static int h_pidfile(int argc, unsigned char **argv){
+  FILE *pidf;
+
+	if(!(pidf = fopen((char *)argv[1], "w"))){
+		fprintf(stderr, "Failed to open pid file %s\n", argv[1]);
+		return(1);
+	}
+	fprintf(pidf,"%u", (unsigned)getpid());
+	fclose(pidf);
+	return 0;
+}
+
+static int h_monitor(int argc, unsigned char **argv){
+  struct filemon * fm;
+
+	fm = myalloc(sizeof (struct filemon));
+	if(stat((char *)argv[1], &fm->sb)){
+		myfree(fm);
+		fprintf(stderr, "Warning: file %s doesn't exist on line %d\n", argv[1], linenum);
+	}
+	else {
+		fm->path = mystrdup((char *)argv[1]);
+		fm->next = conf.fmon;
+		conf.fmon = fm;
+	}
+	return 0;
+}
+
+static int h_parent(int argc, unsigned char **argv){
+  struct ace *acl = NULL;
+  struct chain *chains;
+
+	acl = conf.acl;
+	while(acl && acl->next) acl = acl->next;
+	if(!acl || (acl->action && acl->action != 2)) {
+		fprintf(stderr, "Chaining error: last ACL entry was not \"allow\" or \"redirect\" on line %d\n", linenum);
+		return(1);
+	}
+	acl->action = 2;
+
+	chains = NULL;
+	if(!acl->chains) {
+		chains = acl->chains = myalloc(sizeof(struct chain));
+	}
+	else {
+		chains = acl->chains;
+		while(chains->next)chains = chains->next;
+		chains->next = myalloc(sizeof(struct chain));
+		chains = chains->next;
+	}
+	memset(chains, 0, sizeof(struct chain));
+	if(!chains){
+		fprintf(stderr, "Chainig error: unable to allocate memory for chain\n");
+		return(2);
+	}
+	chains->weight = (unsigned)atoi((char *)argv[1]);
+	if(chains->weight == 0 || chains->weight >1000) {
+		fprintf(stderr, "Chaining error: bad chain weight %u line %d\n", chains->weight, linenum);
+		return(3);
+	}
+	if(!strcmp((char *)argv[2], "tcp"))chains->type = R_TCP;
+	else if(!strcmp((char *)argv[2], "http"))chains->type = R_HTTP;
+	else if(!strcmp((char *)argv[2], "connect"))chains->type = R_CONNECT;
+	else if(!strcmp((char *)argv[2], "socks4"))chains->type = R_SOCKS4;
+	else if(!strcmp((char *)argv[2], "socks5"))chains->type = R_SOCKS5;
+	else if(!strcmp((char *)argv[2], "connect+"))chains->type = R_CONNECTP;
+	else if(!strcmp((char *)argv[2], "socks4+"))chains->type = R_SOCKS4P;
+	else if(!strcmp((char *)argv[2], "socks5+"))chains->type = R_SOCKS5P;
+	else if(!strcmp((char *)argv[2], "socks4b"))chains->type = R_SOCKS4B;
+	else if(!strcmp((char *)argv[2], "socks5b"))chains->type = R_SOCKS5B;
+	else if(!strcmp((char *)argv[2], "pop3"))chains->type = R_POP3;
+	else if(!strcmp((char *)argv[2], "ftp"))chains->type = R_FTP;
+	else if(!strcmp((char *)argv[2], "admin"))chains->type = R_ADMIN;
+	else if(!strcmp((char *)argv[2], "icq"))chains->type = R_ICQ;
+	else if(!strcmp((char *)argv[2], "msn"))chains->type = R_MSN;
+	else {
+		fprintf(stderr, "Chaining error: bad chain type (%s)\n", argv[2]);
+		return(4);
+	}
+	if(!getip46(46, argv[3], (struct sockaddr *)&chains->addr)) return 5;
+	*SAPORT(&chains->addr) = htons((unsigned short)atoi((char *)argv[4]));
+	if(argc > 5) chains->extuser = (unsigned char *)mystrdup((char *)argv[5]);
+	if(argc > 6) chains->extpass = (unsigned char *)mystrdup((char *)argv[6]);
+	return 0;
+	
+}
+
+static int h_nolog(int argc, unsigned char **argv){
+  struct ace *acl = NULL;
+
+	acl = conf.acl;
+	if(!acl) {
+		fprintf(stderr, "Chaining error: last ACL entry was not \"allow/deny\" on line %d\n", linenum);
+		return(1);
+	}
+	while(acl->next) acl = acl->next;
+	if(!strcmp(argv[0],"nolog")) acl->nolog = 1;
+	else acl->weight = atoi((char*)argv[1]);
+	return 0;
+}
+
+int scanipl(unsigned char *arg, struct iplist *dst){
+#ifndef NOIPV6
+	struct sockaddr_in6 sa;
+#else
+	struct sockaddr_in sa;
+#endif
+        char * slash, *dash;
+	int masklen, addrlen;
+	if((slash = strchr(arg, '/'))) *slash = 0;
+	if((dash = strchr(arg,'-'))) *dash = 0;
+	
+	if(!getip46(46, arg, (struct sockaddr *)&sa)) return 1;
+	memcpy(&dst->ip_from, SAADDR(&sa), SAADDRLEN(&sa));
+	dst->family = *SAFAMILY(&sa);
+	if(dash){
+		if(!getip46(46, dash+1, (struct sockaddr *)&sa)) return 2;
+		memcpy(&dst->ip_to, SAADDR(&sa), SAADDRLEN(&sa));
+		if(*SAFAMILY(&sa) != dst->family || memcmp(&dst->ip_to, &dst->ip_from, SAADDRLEN(&sa)) < 0) return 3;
+		return 0;
+	}
+	memcpy(&dst->ip_to, &dst->ip_from, SAADDRLEN(&sa));
+	if(slash){
+		addrlen = SAADDRLEN(&sa);
+		masklen = atoi(slash+1);
+		if(masklen < 0 || masklen > (addrlen*8)) return 4;
+		else {
+			int i, nbytes = masklen / 8, nbits = (8 - (masklen % 8)) % 8;
+
+			for(i = addrlen; i>(nbytes + (nbits > 0)); i--){
+				((unsigned char *)&dst->ip_from)[i-1] = 0x00;
+				((unsigned char *)&dst->ip_to)[i-1] = 0xff;
+			}
+			for(;nbits;nbits--){
+				((unsigned char *)&dst->ip_from)[nbytes] &= ~(0x01<<(nbits-1));
+				((unsigned char *)&dst->ip_to)[nbytes] |= (0x01<<(nbits-1));
+			}
+			return 0;
+		}
+	}		
+	return 0;
+}
+
+struct ace * make_ace (int argc, unsigned char ** argv){
+	struct ace * acl;
+	unsigned char *arg;
+	struct iplist *ipl=NULL;
+	struct portlist *portl=NULL;
+	struct userlist *userl=NULL;
+	struct hostname *hostnamel=NULL;
+	int res;
+
+	acl = myalloc(sizeof(struct ace));
+	if(!acl) return acl;
+	memset(acl, 0, sizeof(struct ace));
+		if(argc > 0 && strcmp("*", (char *)argv[0])) {
+			arg = argv[0];
+			arg = (unsigned char *)strtok((char *)arg, ",");
+			do {
+				if(!acl->users) {
+					acl->users = userl = myalloc(sizeof(struct userlist));
+				}
+				else {
+					userl->next = myalloc(sizeof(struct userlist));
+					userl = userl -> next;
+				}
+				if(!userl) {
+					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
+					return(NULL);
+				}
+				memset(userl, 0, sizeof(struct userlist));
+				userl->user=(unsigned char*)mystrdup((char *)arg);
+			} while((arg = (unsigned char *)strtok((char *)NULL, ",")));
+		}
+		if(argc > 1  && strcmp("*", (char *)argv[1])) {
+			arg = (unsigned char *)strtok((char *)argv[1], ",");
+			do {
+				if(!acl->src) {
+					acl->src = ipl = myalloc(sizeof(struct iplist));
+				}
+				else {
+					ipl->next = myalloc(sizeof(struct iplist));
+					ipl = ipl -> next;
+				}
+				if(!ipl) {
+					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
+					return(NULL);
+				}
+				memset(ipl, 0, sizeof(struct iplist));
+				if (scanipl(arg, ipl)) {
+					fprintf(stderr, "Invalid IP, IP range or CIDR, line %d\n", linenum);
+					return(NULL);
+				}
+			} while((arg = (unsigned char *)strtok((char *)NULL, ",")));
+		}
+		if(argc > 2 && strcmp("*", (char *)argv[2])) {
+			arg = (unsigned char *)strtok((char *)argv[2], ",");
+			do {
+			 int arglen;
+			 unsigned char *pattern;
+			 
+			 arglen = (int)strlen((char *)arg);
+			 if(arglen > 0 && (arg[arglen-1] < '0' || arg[arglen-1] > '9')){
+				if(!acl->dstnames) {
+					acl->dstnames = hostnamel = myalloc(sizeof(struct hostname));
+				}
+				else {
+					hostnamel->next = myalloc(sizeof(struct hostname));
+					hostnamel = hostnamel -> next;
+				}
+				if(!hostnamel){
+					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
+					return(NULL);
+				}
+				memset(hostnamel, 0, sizeof(struct hostname));
+				hostnamel->matchtype = 3;
+				pattern = arg;
+				if(pattern[arglen-1] == '*'){
+					arglen --;
+					pattern[arglen] = 0;
+					hostnamel->matchtype ^= MATCHEND;
+				}
+				if(pattern[0] == '*'){
+					pattern++;
+					arglen--;
+					hostnamel->matchtype ^= MATCHBEGIN;
+				}
+				hostnamel->name = (unsigned char *) mystrdup( (char *)pattern);
+				if(!hostnamel->name) {
+					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
+					return(NULL);
+				}
+			 }
+			 else {
+				
+				if(!acl->dst) {
+					acl->dst = ipl = myalloc(sizeof(struct iplist));
+				}
+				else {
+					ipl->next = myalloc(sizeof(struct iplist));
+					ipl = ipl -> next;
+				}
+				if(!ipl) {
+					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
+					return(NULL);
+				}
+				memset(ipl, 0, sizeof(struct iplist));
+				if (scanipl(arg, ipl)) {
+						fprintf(stderr, "Invalid IP, IP range or CIDR, line %d\n", linenum);
+						return(NULL);
+				}
+			 }
+			}while((arg = (unsigned char *)strtok((char *)NULL, ",")));
+		}
+		if(argc > 3 && strcmp("*", (char *)argv[3])) {
+			arg = (unsigned char *)strtok((char *)argv[3], ",");
+			do {
+				if(!acl->ports) {
+					acl->ports = portl = myalloc(sizeof(struct portlist));
+				}
+				else {
+					portl->next = myalloc(sizeof(struct portlist));
+					portl = portl -> next;
+				}
+				if(!portl) {
+					fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
+					return(NULL);
+				}
+				memset(portl, 0, sizeof(struct portlist));
+				res = sscanf((char *)arg, "%hu-%hu", &portl->startport, &portl->endport);
+				if(res < 1) {
+					fprintf(stderr, "Invalid port or port range, line %d\n", linenum);
+					return(NULL);
+				}
+				if (res == 1) portl->endport = portl->startport;
+			} while((arg = (unsigned char *)strtok((char *)NULL, ",")));
+		}
+		if(argc > 4 && strcmp("*", (char *)argv[4])) {
+			arg = (unsigned char *)strtok((char *)argv[4], ",");	
+			do {
+				if(!strcmp((char *)arg, "CONNECT")){
+					acl->operation |= CONNECT;
+				}
+				else if(!strcmp((char *)arg, "BIND")){
+					acl->operation |= BIND;
+				}
+				else if(!strcmp((char *)arg, "UDPASSOC")){
+					acl->operation |= UDPASSOC;
+				}
+				else if(!strcmp((char *)arg, "ICMPASSOC")){
+					acl->operation |= ICMPASSOC;
+				}
+				else if(!strcmp((char *)arg, "HTTP_GET")){
+					acl->operation |= HTTP_GET;
+				}
+				else if(!strcmp((char *)arg, "HTTP_PUT")){
+					acl->operation |= HTTP_PUT;
+				}
+				else if(!strcmp((char *)arg, "HTTP_POST")){
+					acl->operation |= HTTP_POST;
+				}
+				else if(!strcmp((char *)arg, "HTTP_HEAD")){
+					acl->operation |= HTTP_HEAD;
+				}
+				else if(!strcmp((char *)arg, "HTTP_OTHER")){
+					acl->operation |= HTTP_OTHER;
+				}
+				else if(!strcmp((char *)arg, "HTTP_CONNECT")){
+					acl->operation |= HTTP_CONNECT;
+				}
+				else if(!strcmp((char *)arg, "HTTP")){
+					acl->operation |= HTTP;
+				}
+				else if(!strcmp((char *)arg, "HTTPS")){
+					acl->operation |= HTTPS;
+				}
+				else if(!strcmp((char *)arg, "FTP_GET")){
+					acl->operation |= FTP_GET;
+				}
+				else if(!strcmp((char *)arg, "FTP_PUT")){
+					acl->operation |= FTP_PUT;
+				}
+				else if(!strcmp((char *)arg, "FTP_LIST")){
+					acl->operation |= FTP_LIST;
+				}
+				else if(!strcmp((char *)arg, "FTP_DATA")){
+					acl->operation |= FTP_DATA;
+				}
+				else if(!strcmp((char *)arg, "FTP")){
+					acl->operation |= FTP;
+				}
+				else if(!strcmp((char *)arg, "ADMIN")){
+					acl->operation |= ADMIN;
+				}
+				else if(!strcmp((char *)arg, "DNSRESOLVE")){
+					acl->operation |= DNSRESOLVE;
+				}
+				else if(!strcmp((char *)arg, "ICQ")){
+					acl->operation |= IM_ICQ;
+				}
+				else {
+					fprintf(stderr, "Unknown operation type: %s line %d\n", arg, linenum);
+					return(NULL);
+				}
+			} while((arg = (unsigned char *)strtok((char *)NULL, ",")));
+		}
+		if(argc > 5){
+			for(arg = argv[5]; *arg;){
+				int val, val1;
+
+				if(!isnumber(*arg)){
+					arg++;
+					continue;
+				}
+				val1 = val = (*arg - '0');
+				arg++;
+				if(*arg == '-' && isnumber(*(arg+1)) && (*(arg+1) - '0') > val) {
+					val1 = (*(arg+1) - '0');
+					arg+=2;
+				}
+				for(; val<=val1; val++) acl->wdays |= (1 << (val % 7));
+			}
+			
+		}
+		if(argc > 6){
+			for(arg = argv[6]; strlen((char *)arg) >= 17 &&
+							isdigit(arg[0]) &&
+							isdigit(arg[1]) &&
+							isdigit(arg[3]) &&
+							isdigit(arg[4]) &&
+							isdigit(arg[6]) &&
+							isdigit(arg[7]) &&
+							isdigit(arg[9]) &&
+							isdigit(arg[10]) &&
+							isdigit(arg[12]) &&
+							isdigit(arg[13]) &&
+							isdigit(arg[15]) &&
+							isdigit(arg[16])
+							; arg+=18){
+
+				int t1, t2;
+				struct period *sp;
+
+				t1 = (arg[0] - '0') * 10 + (arg[1] - '0');
+				t1 = (t1 * 60) + (arg[3] - '0') * 10 + (arg[4] - '0');
+				t1 = (t1 * 60) + (arg[6] - '0') * 10 + (arg[7] - '0');
+				t2 = (arg[9] - '0') * 10 + (arg[10] - '0');
+				t2 = (t2 * 60) + (arg[12] - '0') * 10 + (arg[13] - '0');
+				t2 = (t2 * 60) + (arg[15] - '0') * 10 + (arg[16] - '0');
+				if(t2 < t1) break;
+				sp = myalloc(sizeof(struct period));
+				if(sp){
+					sp->fromtime = t1;
+					sp->totime = t2;
+					sp->next = acl->periods;
+					acl->periods = sp;
+				}
+				if(arg[17]!=',') break;
+			}
+		}
+	if (argc > 7){
+		acl->weight = atoi((char *)argv[7]);
+	}
+
+	return acl;
+}
+
+
+static int h_ace(int argc, unsigned char **argv){
+  int res = 0;
+  int offset = 0;
+  struct ace *acl = NULL;
+  struct bandlim * nbl;
+  struct trafcount * tl;
+
+	if(!strcmp((char *)argv[0], "allow")){
+		res = ALLOW;
+	}
+	else if(!strcmp((char *)argv[0], "deny")){
+		res = DENY;
+	}
+	else if(!strcmp((char *)argv[0], "redirect")){
+		res = REDIRECT;
+		offset = 2;
+	}
+	else if(!strcmp((char *)argv[0], "bandlimin")||!strcmp((char *)argv[0], "bandlimout")){
+		res = BANDLIM;
+		offset = 1;
+	}
+	else if(!strcmp((char *)argv[0], "nobandlimin")||!strcmp((char *)argv[0], "nobandlimout")){
+		res = NOBANDLIM;
+	}
+	else if(!strcmp((char *)argv[0], "countin")){
+		res = COUNTIN;
+		offset = 3;
+	}
+	else if(!strcmp((char *)argv[0], "nocountin")){
+		res = NOCOUNTIN;
+	}
+	else if(!strcmp((char *)argv[0], "countout")){
+		res = COUNTOUT;
+		offset = 3;
+	}
+	else if(!strcmp((char *)argv[0], "nocountout")){
+		res = NOCOUNTOUT;
+	}
+	acl = make_ace(argc - (offset+1), argv + (offset + 1));
+	if(!acl) {
+		fprintf(stderr, "Unable to parse ACL entry, line %d\n", linenum);
+		return(1);
+	}
+	acl->action = res;
+	switch(acl->action){
+	case REDIRECT:
+		acl->chains = myalloc(sizeof(struct chain));
+		memset(acl->chains, 0, sizeof(struct chain)); 
+		if(!acl->chains) {
+			fprintf(stderr, "No memory for ACL entry, line %d\n", linenum);
+			return(2);
+		}
+		acl->chains->type = R_HTTP;
+		if(!getip46(46, argv[1], (struct sockaddr *)&acl->chains->addr)) return 5;
+		*SAPORT(&acl->chains->addr) = htons((unsigned short)atoi((char *)argv[2]));
+		acl->chains->weight = 1000;
+		acl->chains->extuser = NULL;
+		acl->chains->extpass = NULL;
+		acl->chains->next = NULL;
+	case ALLOW:
+	case DENY:
+		if(!conf.acl){
+			conf.acl = acl;
+		}
+		else {
+			struct ace * acei;
+
+			for(acei = conf.acl; acei->next; acei = acei->next);
+			acei->next = acl;
+		}
+		break;
+	case BANDLIM:
+	case NOBANDLIM:
+
+		nbl = myalloc(sizeof(struct bandlim));
+		if(!nbl) {
+			fprintf(stderr, "No memory to create band limit filter\n");
+			return(3);
+		}
+		memset(nbl, 0, sizeof(struct bandlim));
+		nbl->ace = acl;
+		if(acl->action == BANDLIM) {
+			sscanf((char *)argv[1], "%u", &nbl->rate);
+			if(nbl->rate < 300) {
+				fprintf(stderr, "Wrong bandwidth specified, line %d\n", linenum);
+				return(4);
+			}
+		}
+		pthread_mutex_lock(&bandlim_mutex);
+		if(!strcmp((char *)argv[0], "bandlimin") || !strcmp((char *)argv[0], "nobandlimin")){
+			if(!conf.bandlimiter){
+				conf.bandlimiter = nbl;
+			}
+			else {
+				struct bandlim * bli;
+
+				for(bli = conf.bandlimiter; bli->next; bli = bli->next);
+				bli->next = nbl;
+			}
+		}
+		else {
+			if(!conf.bandlimiterout){
+				conf.bandlimiterout = nbl;
+			}
+			else {
+				struct bandlim * bli;
+
+				for(bli = conf.bandlimiterout; bli->next; bli = bli->next);
+				bli->next = nbl;
+			}
+		}
+
+		pthread_mutex_unlock(&bandlim_mutex);			
+		break;
+
+	case COUNTIN:
+	case NOCOUNTIN:
+	case COUNTOUT:
+	case NOCOUNTOUT:
+		tl = myalloc(sizeof(struct trafcount));
+		if(!tl) {
+			fprintf(stderr, "No memory to create traffic limit filter\n");
+			return(5);
+		}
+		memset(tl, 0, sizeof(struct trafcount));
+		tl->ace = acl;
+	
+		if((acl->action == COUNTIN)||(acl->action == COUNTOUT)) {
+			unsigned long lim;
+
+			tl->comment = ( char *)argv[1];
+			while(isdigit(*tl->comment))tl->comment++;
+			if(*tl->comment== '/')tl->comment++;
+			tl->comment = mystrdup(tl->comment);
+
+			sscanf((char *)argv[1], "%u", &tl->number);
+			sscanf((char *)argv[3], "%lu", &lim);
+			tl->type = getrotate(*argv[2]);
+			tl->traflim64 =  ((uint64_t)lim)*(1024*1024);
+			if(!tl->traflim64) {
+				fprintf(stderr, "Wrong traffic limit specified, line %d\n", linenum);
+				return(6);
+			}
+			if(tl->number != 0 && conf.counterd >= 0) {
+				lseek(conf.counterd, 
+					sizeof(struct counter_header) + (tl->number - 1) * sizeof(struct counter_record),
+					SEEK_SET);
+				memset(&crecord, 0, sizeof(struct counter_record));
+				read(conf.counterd, &crecord, sizeof(struct counter_record));
+				tl->traf64 = crecord.traf64;
+				tl->cleared = crecord.cleared;
+				tl->updated = crecord.updated;
+#ifdef _MAX__TIME64_T
+				if(tl->cleared >=  _MAX__TIME64_T || tl->updated >=  _MAX__TIME64_T){
+					fprintf(stderr, "Invalid or corrupted counter file. Use countersutil utility to convert from older version\n");
+					return(6);
+				}
+#endif
+			}
+		}
+		pthread_mutex_lock(&tc_mutex);
+		if(!conf.trafcounter){
+			conf.trafcounter = tl;
+		}
+		else {
+			struct trafcount * ntl;
+
+			for(ntl = conf.trafcounter; ntl->next; ntl = ntl->next);
+			ntl->next = tl;
+		}
+		pthread_mutex_unlock(&tc_mutex);
+			
+	}
+	return 0;
+}
+
+static int h_logdump(int argc, unsigned char **argv){
+	conf.logdumpsrv = (unsigned) atoi((char *) *(argv + 1));
+	if(argc > 2) conf.logdumpcli = (unsigned) atoi((char *) *(argv + 2));
+	return 0;
+}
+
+
+static int h_filtermaxsize(int argc, unsigned char **argv){
+	conf.filtermaxsize = atoi((char *) *(argv + 1));
+	return 0;
+}
+
+static int h_delimchar(int argc, unsigned char **argv){
+	conf.delimchar = *argv[1];
+	return 0;
+}
+
+static int h_authcache(int argc, unsigned char **argv){
+	conf.authcachetype = 0;
+	if(strstr((char *) *(argv + 1), "ip")) conf.authcachetype |= 1;
+	if(strstr((char *) *(argv + 1), "user")) conf.authcachetype |= 2;
+	if(strstr((char *) *(argv + 1), "pass")) conf.authcachetype |= 4;
+	if(argc > 2) conf.authcachetime = (unsigned) atoi((char *) *(argv + 2));
+	if(!conf.authcachetype) conf.authcachetype = 6;
+	if(!conf.authcachetime) conf.authcachetime = 600;
+	return 0;
+}
+
+static int h_plugin(int argc, unsigned char **argv){
+#ifdef NOPLUGINS
+	return 999;
+#else
+#ifdef _WIN32
+	HINSTANCE hi;
+	FARPROC fp;
+
+#ifdef _WINCE
+	hi = LoadLibraryW((LPCWSTR)CEToUnicode(argv[1]));
+#else
+	hi = LoadLibrary(argv[1]);
+#endif
+	if(!hi) {
+		fprintf(stderr, "Failed to load %s, code %d\n", argv[1], (int)GetLastError());
+		return 1;
+	}
+#ifdef _WINCE
+	fp = GetProcAddressW(hi, (LPCWSTR)CEToUnicode(argv[2]));
+#else
+	fp = GetProcAddress(hi, argv[2]);
+#endif
+	if(!fp) {
+		printf("%s not found in %s, code: %d\n", argv[2], argv[1], (int)GetLastError());
+		return 2;
+	}
+	return (*(PLUGINFUNC)fp)(&pluginlink, argc - 2, (char **)argv + 2);
+#else	
+	void *hi, *fp;
+	hi = dlopen((char *)argv[1], RTLD_LAZY);
+	if(!hi) return 1;
+	fp = dlsym(hi, (char *)argv[2]);
+	if(!fp) return 2;
+	return (*(PLUGINFUNC)fp)(&pluginlink, argc - 2, (char **)argv + 2);
+#endif
+#endif
+}
+
+#ifndef _WIN32
+static int h_setuid(int argc, unsigned char **argv){
+  int res;
+	res = atoi((char *)argv[1]);
+	if(!res || setuid(res)) {
+		fprintf(stderr, "Unable to set uid %d", res);
+		return(1);
+	}
+	return 0;
+}
+
+static int h_setgid(int argc, unsigned char **argv){
+  int res;
+
+	res = atoi((char *)argv[1]);
+	if(!res || setgid(res)) {
+		fprintf(stderr, "Unable to set gid %d", res);
+		return(1);
+	}
+	return 0;
+}
+
+
+static int h_chroot(int argc, unsigned char **argv){
+	if(!chrootp){
+		char *p;
+		if(chroot((char *)argv[1])) {
+			fprintf(stderr, "Unable to chroot %s", argv[1]);
+			return(1);
+		}
+		p = (char *)argv[1] + strlen((char *)argv[1]) ;
+		while (p > (char *)argv[1] && p[-1] == '/'){
+			p--;
+			*p = 0;
+		}
+		chrootp = mystrdup((char *)argv[1]);
+	}
+	return 0;
+}
+#endif
+
+
+struct commands specificcommands[]={
+#ifndef _WIN32
+	{specificcommands+1, "setuid", h_setuid, 2, 2},
+	{specificcommands+2, "setgid", h_setgid, 2, 2},
+	{specificcommands+3, "chroot", h_chroot, 2, 2},
+#endif
+	{NULL, 		"", h_noop, 1, 0}
+};
+
+struct commands commandhandlers[]={
+	{commandhandlers+1,  "", h_noop, 1, 0},
+	{commandhandlers+2,  "proxy", h_proxy, 1, 0},
+	{commandhandlers+3,  "pop3p", h_proxy, 1, 0},
+	{commandhandlers+4,  "ftppr", h_proxy, 1, 0},
+	{commandhandlers+5,  "socks", h_proxy, 1, 0},
+	{commandhandlers+6,  "tcppm", h_proxy, 4, 0},
+	{commandhandlers+7,  "udppm", h_proxy, 4, 0},
+	{commandhandlers+8,  "admin", h_proxy, 1, 0},
+	{commandhandlers+9,  "dnspr", h_proxy, 1, 0},
+	{commandhandlers+10,  "internal", h_internal, 2, 2},
+	{commandhandlers+11, "external", h_external, 2, 2},
+	{commandhandlers+12, "log", h_log, 1, 0},
+	{commandhandlers+13, "service", h_service, 1, 1},
+	{commandhandlers+14, "daemon", h_daemon, 1, 1},
+	{commandhandlers+15, "config", h_config, 2, 2},
+	{commandhandlers+16, "include", h_include, 2, 2},
+	{commandhandlers+17, "archiver", h_archiver, 3, 0},
+	{commandhandlers+18, "counter", h_counter, 2, 4},
+	{commandhandlers+19, "rotate", h_rotate, 2, 2},
+	{commandhandlers+20, "logformat", h_logformat, 2, 2},
+	{commandhandlers+21, "timeouts", h_timeouts, 2, 0},
+	{commandhandlers+22, "auth", h_auth, 2, 0},
+	{commandhandlers+23, "users", h_users, 2, 0},
+	{commandhandlers+24, "maxconn", h_maxconn, 2, 2},
+	{commandhandlers+25, "flush", h_flush, 1, 1},
+	{commandhandlers+26, "nserver", h_nserver, 2, 2},
+	{commandhandlers+27, "fakeresolve", h_fakeresolve, 1, 1},
+	{commandhandlers+28, "nscache", h_nscache, 2, 2},
+	{commandhandlers+29, "nscache6", h_nscache6, 2, 2},
+	{commandhandlers+30, "nsrecord", h_nsrecord, 3, 3},
+	{commandhandlers+31, "dialer", h_dialer, 2, 2},
+	{commandhandlers+32, "system", h_system, 2, 2},
+	{commandhandlers+33, "pidfile", h_pidfile, 2, 2},
+	{commandhandlers+34, "monitor", h_monitor, 2, 2},
+	{commandhandlers+35, "parent", h_parent, 5, 0},
+	{commandhandlers+36, "allow", h_ace, 1, 0},
+	{commandhandlers+37, "deny", h_ace, 1, 0},
+	{commandhandlers+38, "redirect", h_ace, 3, 0},
+	{commandhandlers+39, "bandlimin", h_ace, 2, 0},
+	{commandhandlers+40, "bandlimout", h_ace, 2, 0},
+	{commandhandlers+41, "nobandlimin", h_ace, 1, 0},
+	{commandhandlers+42, "nobandlimout", h_ace, 1, 0},
+	{commandhandlers+43, "countin", h_ace, 4, 0},
+	{commandhandlers+44, "nocountin", h_ace, 1, 0},
+	{commandhandlers+45, "countout", h_ace, 4, 0},
+	{commandhandlers+46, "nocountout", h_ace, 1, 0},
+	{commandhandlers+47, "plugin", h_plugin, 3, 0},
+	{commandhandlers+48, "logdump", h_logdump, 2, 3},
+	{commandhandlers+49, "filtermaxsize", h_filtermaxsize, 2, 2},
+	{commandhandlers+50, "nolog", h_nolog, 1, 1},
+	{commandhandlers+51, "weight", h_nolog, 2, 2},
+	{commandhandlers+52, "authcache", h_authcache, 2, 3},
+	{commandhandlers+53, "smtpp", h_proxy, 1, 0},
+	{commandhandlers+54, "icqpr", h_proxy, 4, 0},
+	{commandhandlers+55, "msnpr", h_proxy, 4, 0},
+	{commandhandlers+56, "delimchar",h_delimchar, 2, 2},
+	{commandhandlers+57, "authnserver", h_authnserver, 2, 2},
+	{specificcommands, 	 "", h_noop, 1, 0}
+};
+
+int parsestr (unsigned char *str, unsigned char **argm, int nitems, unsigned char ** buff, int *inbuf, int *bufsize){
+#define buf (*buff)
+	int argc = 0;
+	int space = 1;
+	int comment = 0;
+	unsigned char * incbegin = 0;
+	int fd;
+	int res, len;
+	int i = 1;
+	unsigned char *str1;
+
+	for(;;str++){
+	 if(*str == '\"'){
+		str1 = str;
+		do {
+			*str1 = *(str1 + 1);
+		}while(*(str1++));
+		if(!comment || *str != '\"'){
+			comment = !comment;
+		}
+	 }
+         switch(*str){
+		case '\0': 
+			if(comment) return -1;
+			argm[argc] = 0;
+			return argc;
+		case '$':
+			if(!comment && !included){
+				incbegin = str;
+				*str = 0;
+			}
+			break;
+		case '\r':
+		case '\n':
+		case '\t':
+		case ' ':
+			if(!comment){
+				*str = 0;
+				space = 1;
+				i = 0;
+				if(incbegin){
+					argc--;
+					if((fd = open((char *)incbegin+1, O_RDONLY)) <= 0){
+						fprintf(stderr, "Failed to open %s\n", incbegin+1);
+						break;
+					}
+					if((*bufsize - *inbuf) <STRINGBUF){
+						*bufsize += STRINGBUF;
+						if(!(buf = myrealloc(buf, *bufsize))){
+							fprintf(stderr, "Failed to allocate memory for %s\n", incbegin+1);
+							close(fd);
+							break;
+						}
+					}
+					len = 0;
+					if(argm[argc]!=(incbegin+1)) {
+						len = (int)strlen((char *)argm[argc]);
+						memmove(buf+*inbuf, argm[argc], len);
+					}
+					if((res = read(fd, buf+*inbuf+len, STRINGBUF-(1+len))) <= 0) {
+						perror((char *)incbegin+1);
+						close(fd);
+						break;
+					}
+					close(fd);
+					buf[*inbuf+res+len] = 0;
+					incbegin = buf + *inbuf;
+					(*inbuf) += (res + len + 1);
+					included++;
+					argc+=parsestr(incbegin, argm + argc, nitems - argc, buff, inbuf, bufsize);
+					included--;
+					incbegin = NULL;
+
+				}
+				break;
+			}
+		default:
+			i++;
+			if(space) {
+				if(comment && *str == '\"' && str[1] != '\"'){
+					str++;
+					comment = 0;
+				}
+				argm[argc++] = str;
+				if(argc >= nitems) return argc;
+				space = 0;
+			}
+	 }
+	}
+#undef buf
+}
+
+
+int readconfig(FILE * fp){
+ unsigned char ** argv = NULL;
+ unsigned char * buf = NULL;
+  int bufsize = STRINGBUF*2;
+  int inbuf = 0;
+  int argc;
+  struct commands * cm;
+  int res = 0;
+
+  if( !(buf = myalloc(bufsize)) || ! (argv = myalloc((NPARAMS + 1) * sizeof(unsigned char *))) ) {
+		fprintf(stderr, "No memory for configuration");
+		return(10);
+  }
+  for (linenum = 1; fgets((char *)buf, STRINGBUF, fp); linenum++){
+	if(!*buf || isspace(*buf) || (*buf) == '#')continue;
+
+	inbuf = (int)(strlen((char *)buf) + 1);
+	argc = parsestr (buf, argv, NPARAMS-1, &buf, &inbuf, &bufsize);
+	if(argc < 1) {
+		fprintf(stderr, "Parse error line %d\n", linenum);
+		return(21);
+	}
+	argv[argc] = NULL;
+	if(!strcmp((char *)argv[0], "end") && argc == 1) {	
+		break;
+	}
+	else if(!strcmp((char *)argv[0], "writable") && argc == 1) {	
+		if(!writable){
+			writable = freopen(curconf, "r+", fp);
+			if(!writable){
+				fprintf(stderr, "Unable to reopen config for writing: %s\n", curconf);
+				return 1;
+			}
+		}
+		continue;
+	}
+
+	res = 1;
+	for(cm = commandhandlers; cm; cm = cm->next){
+		if(!strcmp((char *)argv[0], (char *)cm->command) && argc >= cm->minargs && (!cm->maxargs || argc <= cm->maxargs)){
+			res = (*cm->handler)(argc, argv);
+			if(res > 0){
+				fprintf(stderr, "Command: '%s' failed with code %d, line %d\n", argv[0], res, linenum);
+				return(linenum);
+			}
+			if(!res) break;
+		}
+	}
+	if(res != 1)continue;
+	fprintf(stderr, "Unknown command: '%s' line %d\n", argv[0], linenum);
+	return(linenum);
+  }
+  myfree(buf);
+  myfree(argv);
+  return 0;
+
+}
+
+
+
+void freepwl(struct passwords *pwl){
+	for(; pwl; pwl = (struct passwords *)itfree(pwl, pwl->next)){
+		if(pwl->user)myfree(pwl->user);
+		if(pwl->password)myfree(pwl->password);
+	}
+}
+
+
+void freeconf(struct extparam *confp){
+ struct bandlim * bl;
+ struct bandlim * blout;
+ struct trafcount * tc;
+ struct passwords *pw;
+ struct ace *acl;
+ struct filemon *fm;
+ int counterd, archiverc;
+ unsigned char *logname, *logtarget;
+ unsigned char **archiver;
+ unsigned char * logformat;
+
+ int i;
+
+
+
+
+ pthread_mutex_lock(&tc_mutex);
+ confp->trafcountfunc = NULL;
+ tc = confp->trafcounter;
+ confp->trafcounter = NULL;
+ counterd = confp->counterd;
+ confp->counterd = -1;
+ confp->countertype = NONE;
+ pthread_mutex_unlock(&tc_mutex);
+
+ pthread_mutex_lock(&bandlim_mutex);
+ bl = confp->bandlimiter;
+ blout = confp->bandlimiterout;
+ confp->bandlimiter = NULL;
+ confp->bandlimiterout = NULL;
+ confp->bandlimfunc = NULL;
+ pthread_mutex_unlock(&bandlim_mutex);
+
+ pthread_mutex_lock(&pwl_mutex);
+ pw = confp->pwl;
+ confp->pwl = NULL;
+ pthread_mutex_unlock(&pwl_mutex);
+
+
+ logtarget = confp->logtarget;
+ confp->logtarget = NULL;
+ logformat = confp->logformat;
+ confp->logformat = NULL;
+ logname = confp->logname;
+ confp->logname = NULL;
+ confp->rotate = 0;
+ confp->logtype = NONE;
+
+ archiverc = confp->archiverc;
+ confp->archiverc = 0;
+ archiver = confp->archiver;
+ confp->archiver = NULL;
+ fm = confp->fmon;
+ confp->fmon = NULL;
+ confp->bandlimfunc = NULL;
+ memset(&confp->intsa, 0, sizeof(confp->intsa));
+ memset(&confp->extsa, 0, sizeof(confp->extsa));
+#ifndef NOIPV6
+ memset(&confp->extsa6, 0, sizeof(confp->extsa6));
+ *SAFAMILY(&confp->extsa6) = AF_INET6;
+#endif
+ *SAFAMILY(&confp->intsa) = AF_INET;
+ *SAFAMILY(&confp->extsa) = AF_INET;
+ confp->singlepacket = 0;
+ confp->maxchild = 100;
+ resolvfunc = NULL;
+ numservers = 0;
+ acl = confp->acl;
+ confp->acl = NULL;
+ confp->logtime = confp->time = 0;
+
+ usleep(SLEEPTIME);
+
+ {
+	char * args[] = {"auth", "iponly", NULL};
+  	h_auth(2, (unsigned char **)args);
+ }
+ if(tc)dumpcounters(tc,counterd);
+ for(; tc; tc = (struct trafcount *) itfree(tc, tc->next)){
+	if(tc->comment)myfree(tc->comment);
+	freeacl(tc->ace);
+ }
+
+ 
+ freeacl(acl);
+ freepwl(pw);
+ for(; bl; bl = (struct bandlim *) itfree(bl, bl->next)) freeacl(bl->ace);
+ for(; blout; blout = (struct bandlim *) itfree(blout, blout->next))freeacl(blout->ace);
+
+ if(counterd != -1) {
+	close(counterd);
+ }
+ for(; fm; fm = (struct filemon *)itfree(fm, fm->next)){
+	if(fm->path) myfree(fm->path);
+ }
+ if(logtarget) {
+	myfree(logtarget);
+ }
+ if(logname) {
+	myfree(logname);
+ }
+ if(logformat) {
+	myfree(logformat);
+ }
+ if(archiver) {
+	for(i = 0; i < archiverc; i++) myfree(archiver[i]);
+	myfree(archiver);
+ }
+
+}
+
+int reload (void){
+	FILE *fp;
+	int error = -2;
+
+	conf.paused++;
+	freeconf(&conf);
+	conf.paused++;
+
+	fp = confopen();
+	if(fp){
+		error = readconfig(fp);
+		if(error) {
+			 freeconf(&conf);
+		}
+		if(!writable)fclose(fp);
+	}
+	return error;
+}

+ 109 - 126
src/datatypes.c

@@ -3,11 +3,15 @@
  *
  * please read License Agreement
  *
- * $Id: datatypes.c,v 1.28 2009/08/14 09:56:21 v.dubrovin Exp $
  */
 
 #include "proxy.h"
 
+static void pr_unsigned64(struct node *node, CBFUNC cbf, void*cb){
+	char buf[32];
+	if(node->value)(*cbf)(cb, buf, sprintf(buf, "%"PRINTF_INT64_MODIFIER"u", *(uint64_t *)node->value));
+}
+
 static void pr_integer(struct node *node, CBFUNC cbf, void*cb){
 	char buf[16];
 	if(node->value)(*cbf)(cb, buf, sprintf(buf, "%d", *(int *)node->value));
@@ -52,19 +56,27 @@ static void pr_datetime(struct node *node, CBFUNC cbf, void*cb){
 	}
 }
 
-int ipprint(char *buf, unsigned uu){
-	unsigned u = ntohl(uu);
+static void pr_ip(struct node *node, CBFUNC cbf, void*cb){
+	char buf[16];
+	if(node->value)(*cbf)(cb, buf, myinet_ntop(AF_INET, node -> value, buf, 4));
+}
 
-	return sprintf(buf, "%u.%u.%u.%u", 
-		((u&0xFF000000)>>24), 
-		((u&0x00FF0000)>>16),
-		((u&0x0000FF00)>>8),
-		((u&0x000000FF)));
+static void pr_ip6(struct node *node, CBFUNC cbf, void*cb){
+	char buf[64];
+	if(node->value)(*cbf)(cb, buf, myinet_ntop(AF_INET6, node -> value, buf, 16));
 }
 
-static void pr_ip(struct node *node, CBFUNC cbf, void*cb){
-	char buf[16];
-	if(node->value)(*cbf)(cb, buf, ipprint(buf, *(unsigned *)node -> value));
+static void pr_sa(struct node *node, CBFUNC cbf, void*cb){
+#ifdef NOIPV6
+	if(node->value)return pr_ip(node, cbf, cb);
+#else
+	char buf[64];
+	buf[0] = '[';
+	buf[1] = 0;
+	inet_ntop(*SAFAMILY(node->value), node->value, buf+1, sizeof(buf)-10);
+	sprintf(buf + strlen(buf), "]:hu", (unsigned short)*SAPORT(node->value));
+	if(node->value)(*cbf)(cb, buf, strlen(buf));
+#endif
 }
 
 static void pr_wdays(struct node *node, CBFUNC cbf, void*cb){
@@ -225,9 +237,22 @@ static void pr_userlist(struct node *node, CBFUNC cbf, void*cb){
 	}
 }
 
+int printiple(char *buf, struct iplist* ipl){
+	 int addrlen = (ipl->family == AF_INET6)?16:4, i;
+	 i = myinet_ntop(ipl->family, &ipl->ip_from, buf, addrlen);
+	 if(memcmp(&ipl->ip_from, &ipl->ip_to, addrlen)){
+		buf[i++] = '-';
+		i += myinet_ntop(ipl->family, &ipl->ip_from, buf+i, addrlen);
+	 }
+	 if(ipl->next){
+		buf[i++] = ',';
+		buf[i++] = ' ';
+	}
+	return i;
+}
+
 static void pr_iplist(struct node *node, CBFUNC cbf, void*cb){
-	char buf[20];
-	int i;
+	char buf[128];
 	struct iplist *il = (struct iplist *)node->value;
 
 	if(!il) {
@@ -235,10 +260,7 @@ static void pr_iplist(struct node *node, CBFUNC cbf, void*cb){
 		return;
 	}
 	for(; il; il = il->next){
-	 i = ipprint(buf, il->ip);
-	 i += cidrprint(buf+i, il->mask);
-	 if(il->next)buf[i++] = ',';
-	 (*cbf)(cb, buf, i);
+	 (*cbf)(cb, buf, printiple(buf, il));
 	}
 }
 
@@ -259,18 +281,6 @@ static void * ef_iplist_next(struct node *node){
 	return (((struct iplist *)node->value) -> next);
 }
 
-static void * ef_iplist_ip(struct node *node){
-	return &(((struct iplist *)node->value) -> ip);
-}
-
-static void * ef_iplist_cidr(struct node *node){
-	return &(((struct iplist *)node->value) -> mask);
-}
-
-static void * ef_iplist_mask(struct node *node){
-	return &(((struct iplist *)node->value) -> mask);
-}
-
 static void * ef_userlist_next(struct node * node){
 	return (((struct userlist *)node->value) -> next);
 }
@@ -333,12 +343,8 @@ static void * ef_chain_type(struct node * node){
 	}
 }
 
-static void * ef_chain_ip(struct node * node){
-	return &((struct chain *)node->value) -> redirip;
-}
-
-static void * ef_chain_port(struct node * node){
-	return &((struct chain *)node->value) -> redirport;
+static void * ef_chain_addr(struct node * node){
+	return &((struct chain *)node->value) -> addr;
 }
 
 static void * ef_chain_weight(struct node * node){
@@ -446,12 +452,26 @@ static void * ef_trafcounter_type(struct node * node){
 	return &((struct trafcount *)node->value) -> type;
 }
 
-static void * ef_trafcounter_traffic(struct node * node){
-	return &((struct trafcount *)node->value) -> traf;
+static void * ef_trafcounter_traffic64(struct node * node){
+	return &((struct trafcount *)node->value) -> traf64;
+}
+static void * ef_trafcounter_limit64(struct node * node){
+	return &((struct trafcount *)node->value) -> traflim64;
+}
+static void * ef_client_maxtrafin64(struct node * node){
+	return &((struct clientparam *)node->value) -> maxtrafin64;
+}
+
+static void * ef_client_maxtrafout64(struct node * node){
+	return &((struct clientparam *)node->value) -> maxtrafout64;
+}
+
+static void * ef_client_bytesin64(struct node * node){
+	return &((struct clientparam *)node->value) -> statssrv64;
 }
 
-static void * ef_trafcounter_limit(struct node * node){
-	return &((struct trafcount *)node->value) -> traflim;
+static void * ef_client_bytesout64(struct node * node){
+	return &((struct clientparam *)node->value) -> statscli64;
 }
 
 static void * ef_trafcounter_cleared(struct node * node){
@@ -487,7 +507,6 @@ static void * ef_server_auth(struct node * node){
 	AUTHFUNC af = ((struct srvparam *)node->value) -> authfunc;
 
 	if(af == alwaysauth) return "none";
-	if(af == nbnameauth) return "nbname";
 	if(af == ipauth) return "iponly";
 	if(af == strongauth) return "strong";
 	return "uknown";
@@ -536,21 +555,19 @@ static void * ef_server_targetport(struct node * node){
 	return &((struct srvparam *)node->value) -> targetport;
 }
 
-static void * ef_server_intip(struct node * node){
-	return &((struct srvparam *)node->value) -> intip;
+static void * ef_server_intsa(struct node * node){
+	return &((struct srvparam *)node->value) -> intsa;
 }
 
-static void * ef_server_extip(struct node * node){
-	return &((struct srvparam *)node->value) -> extip;
+static void * ef_server_extsa(struct node * node){
+	return &((struct srvparam *)node->value) -> extsa;
 }
 
-static void * ef_server_intport(struct node * node){
-	return &((struct srvparam *)node->value) -> intport;
-}
-
-static void * ef_server_extport(struct node * node){
-	return &((struct srvparam *)node->value) -> extport;
+#ifndef NOIPV6
+static void * ef_server_extsa6(struct node * node){
+	return &((struct srvparam *)node->value) -> extsa6;
 }
+#endif
 
 static void * ef_server_acl(struct node * node){
 	return ((struct srvparam *)node->value) -> acl;
@@ -573,14 +590,6 @@ static void * ef_client_next(struct node * node){
 	return ((struct clientparam *)node->value) -> next;
 }
 
-static void * ef_client_maxtrafin(struct node * node){
-	return &((struct clientparam *)node->value) -> maxtrafin;
-}
-
-static void * ef_client_maxtrafout(struct node * node){
-	return &((struct clientparam *)node->value) -> maxtrafout;
-}
-
 static void * ef_client_type(struct node * node){
 	int service = ((struct clientparam *)node->value) -> service;
 	return (service>=0 && service < 15)? (void *)conf.stringtable[SERVICES + service] : (void *)"unknown";
@@ -617,36 +626,16 @@ static void * ef_client_extpassword(struct node * node){
 	return ((struct clientparam *)node->value) -> extpassword;
 }
 
-static void * ef_client_cliip(struct node * node){
-	return &((struct clientparam *)node->value) -> sinc.sin_addr.s_addr;
+static void * ef_client_clisa(struct node * node){
+	return &((struct clientparam *)node->value) -> sincr;
 }
 
-static void * ef_client_srvip(struct node * node){
-	return &((struct clientparam *)node->value) -> sins.sin_addr.s_addr;
+static void * ef_client_srvsa(struct node * node){
+	return &((struct clientparam *)node->value) -> sinsr;
 }
 
-static void * ef_client_reqip(struct node * node){
-	return &((struct clientparam *)node->value) -> req.sin_addr.s_addr;
-}
-
-static void * ef_client_reqport(struct node * node){
-	return &((struct clientparam *)node->value) -> req.sin_port;
-}
-
-static void * ef_client_srvport(struct node * node){
-	return &((struct clientparam *)node->value) -> sins.sin_port;
-}
-
-static void * ef_client_cliport(struct node * node){
-	return &((struct clientparam *)node->value) -> sinc.sin_port;
-}
-
-static void * ef_client_bytesin(struct node * node){
-	return &((struct clientparam *)node->value) -> statssrv;
-}
-
-static void * ef_client_bytesout(struct node * node){
-	return &((struct clientparam *)node->value) -> statscli;
+static void * ef_client_reqsa(struct node * node){
+	return &((struct clientparam *)node->value) -> req;
 }
 
 static void * ef_client_pwtype(struct node * node){
@@ -695,20 +684,12 @@ static struct property prop_pwlist[] = {
 	{NULL, "next", ef_pwlist_next, TYPE_PWLIST, "next"}
 };
 
-static struct property prop_iplist[] = {
-	{prop_iplist + 1, "ip", ef_iplist_ip, TYPE_IP, "ip address"},
-	{prop_iplist + 2, "cidr", ef_iplist_cidr, TYPE_CIDR, "ip mask length"},
-	{prop_iplist + 3, "mask", ef_iplist_mask, TYPE_IP, "ip mask"},
-	{NULL, "next", ef_iplist_next, TYPE_IPLIST, "next"}
-};
-
 static struct property prop_chain[] = {
-	{prop_chain + 1, "ip", ef_chain_ip, TYPE_IP, "parent ip address"},
-	{prop_chain + 2, "port", ef_chain_port, TYPE_PORT, "parent port"},
-	{prop_chain + 3, "type", ef_chain_type, TYPE_STRING, "parent type"},
-	{prop_chain + 4, "weight", ef_chain_weight, TYPE_SHORT, "parent weight 0-1000"},
-	{prop_chain + 5, "user", ef_chain_user, TYPE_STRING, "parent login"},
-	{prop_chain + 6, "password", ef_chain_password, TYPE_STRING, "parent password"},
+	{prop_chain + 1, "addr", ef_chain_addr, TYPE_SA, "parent address"},
+	{prop_chain + 2, "type", ef_chain_type, TYPE_STRING, "parent type"},
+	{prop_chain + 3, "weight", ef_chain_weight, TYPE_SHORT, "parent weight 0-1000"},
+	{prop_chain + 4, "user", ef_chain_user, TYPE_STRING, "parent login"},
+	{prop_chain + 5, "password", ef_chain_password, TYPE_STRING, "parent password"},
 	{NULL, "next", ef_chain_next, TYPE_CHAIN, "next"}
 };
 
@@ -742,8 +723,10 @@ static struct property prop_trafcounter[] = {
 	{prop_trafcounter + 2, "ace", ef_trafcounter_ace, TYPE_ACE, "traffic to count"},
 	{prop_trafcounter + 3, "number", ef_trafcounter_number, TYPE_UNSIGNED, "counter number"},
 	{prop_trafcounter + 4, "type", ef_trafcounter_type, TYPE_ROTATION, "rotation type"},
-	{prop_trafcounter + 5, "traffic", ef_trafcounter_traffic, TYPE_TRAFFIC, "counter value"},
-	{prop_trafcounter + 6, "limit", ef_trafcounter_limit, TYPE_TRAFFIC, "counter limit"},
+
+
+	{prop_trafcounter + 5, "traffic", ef_trafcounter_traffic64, TYPE_UNSIGNED64, "counter value"},
+	{prop_trafcounter + 6, "limit", ef_trafcounter_limit64, TYPE_UNSIGNED64, "counter limit"},
 	{prop_trafcounter + 7, "cleared", ef_trafcounter_cleared, TYPE_DATETIME, "last rotated"},
 	{prop_trafcounter + 8, "updated", ef_trafcounter_updated, TYPE_DATETIME, "last updated"},
 	{prop_trafcounter + 9, "comment", ef_trafcounter_comment, TYPE_STRING, "counter comment"},
@@ -758,21 +741,22 @@ static struct property prop_server[] = {
 	{prop_server + 2, "target", ef_server_target, TYPE_STRING, "portmapper target ip"},
 	{prop_server + 3, "targetport", ef_server_targetport, TYPE_PORT, "portmapper target port"},
 	{prop_server + 4, "starttime", ef_server_starttime, TYPE_DATETIME, "service started seconds"},
-	{prop_server + 5, "intip", ef_server_intip, TYPE_IP, "ip address of internal interface"},
-	{prop_server + 6, "extip", ef_server_extip, TYPE_IP, "ip address of external interface"},
-	{prop_server + 7, "intport", ef_server_intport, TYPE_PORT, "port to listen"},
-	{prop_server + 8, "extport", ef_server_extport, TYPE_PORT, "port to use for outgoing connection"},
-	{prop_server + 9, "auth", ef_server_auth, TYPE_STRING, "service authentication type"},
-	{prop_server + 10, "acl", ef_server_acl, TYPE_ACE, "access control list"},
-	{prop_server + 11, "singlepacket", ef_server_singlepacket, TYPE_INTEGER, "is single packet redirection"},
-	{prop_server + 12, "usentlm", ef_server_usentlm, TYPE_INTEGER, "allow NTLM authentication"},
-	{prop_server + 13, "log", ef_server_log, TYPE_STRING, "type of logging"},
-	{prop_server + 14, "logtarget", ef_server_logtarget, TYPE_STRING, "log target options"},
-	{prop_server + 15, "logformat", ef_server_logformat, TYPE_STRING, "logging format string"},
-	{prop_server + 16, "nonprintable", ef_server_nonprintable, TYPE_STRING, "non printable characters"},
-	{prop_server + 17, "replacement", ef_server_replacement, TYPE_CHAR, "replacement character"},
-	{prop_server + 18, "childcount", ef_server_childcount, TYPE_INTEGER, "number of servers connected"},
-	{prop_server + 19, "child", ef_server_child, TYPE_CLIENT, "connected clients"},
+	{prop_server + 5, "intsa", ef_server_intsa, TYPE_SA, "ip address of internal interface"},
+	{prop_server + 6, "extsa", ef_server_extsa, TYPE_SA, "ip address of external interface"},
+	{prop_server + 7, "auth", ef_server_auth, TYPE_STRING, "service authentication type"},
+	{prop_server + 8, "acl", ef_server_acl, TYPE_ACE, "access control list"},
+	{prop_server + 9, "singlepacket", ef_server_singlepacket, TYPE_INTEGER, "is single packet redirection"},
+	{prop_server + 10, "usentlm", ef_server_usentlm, TYPE_INTEGER, "allow NTLM authentication"},
+	{prop_server + 11, "log", ef_server_log, TYPE_STRING, "type of logging"},
+	{prop_server + 12, "logtarget", ef_server_logtarget, TYPE_STRING, "log target options"},
+	{prop_server + 13, "logformat", ef_server_logformat, TYPE_STRING, "logging format string"},
+	{prop_server + 14, "nonprintable", ef_server_nonprintable, TYPE_STRING, "non printable characters"},
+	{prop_server + 15, "replacement", ef_server_replacement, TYPE_CHAR, "replacement character"},
+	{prop_server + 16, "childcount", ef_server_childcount, TYPE_INTEGER, "number of servers connected"},
+	{prop_server + 17, "child", ef_server_child, TYPE_CLIENT, "connected clients"},
+#ifndef NOIPV6
+	{prop_server + 18, "extsa6", ef_server_extsa6, TYPE_SA, "ipv6 address of external interface"},
+#endif
 	{NULL, "next", ef_server_next, TYPE_SERVER, "next"}
 };
 
@@ -789,17 +773,14 @@ static struct property prop_client[] = {
 	{prop_client + 9, "extpassword", ef_client_extpassword, TYPE_STRING, "password for requested host"},
 	{prop_client + 10, "username", ef_client_username, TYPE_STRING, "client username"},
 	{prop_client + 11, "password", ef_client_password, TYPE_STRING, "client password"},
-	{prop_client + 12, "cliip", ef_client_cliip, TYPE_IP, "client ip"},
-	{prop_client + 13, "cliport", ef_client_cliport, TYPE_PORT, "client port"},
-	{prop_client + 14, "srvip", ef_client_srvip, TYPE_IP, "target server ip"},
-	{prop_client + 15, "srvport", ef_client_srvport, TYPE_PORT, "target server port"},
-	{prop_client + 16, "reqip", ef_client_reqip, TYPE_IP, "requested server ip"},
-	{prop_client + 17, "reqport", ef_client_reqport, TYPE_PORT, "requested server port"},
-	{prop_client + 18, "bytesin", ef_client_bytesin, TYPE_UNSIGNED, "bytes from server to client"},
-	{prop_client + 19, "bytesout", ef_client_bytesout, TYPE_UNSIGNED, "bytes from client to server"},
-	{prop_client + 20, "pwtype", ef_client_pwtype, TYPE_INTEGER, "type of client password"},
-	{prop_client + 21, "maxtrafin", ef_client_maxtrafin, TYPE_UNSIGNED, "maximum traffic allowed for download"},
-	{prop_client + 22, "maxtrafout", ef_client_maxtrafout, TYPE_UNSIGNED, "maximum traffic allowed for upload"},
+	{prop_client + 12, "clisa", ef_client_clisa, TYPE_SA, "client sa"},
+	{prop_client + 13, "srvsa", ef_client_srvsa, TYPE_IP, "target server sa"},
+	{prop_client + 14, "reqsa", ef_client_reqsa, TYPE_IP, "requested server sa"},
+	{prop_client + 15, "bytesin", ef_client_bytesin64, TYPE_UNSIGNED64, "bytes from server to client"},
+	{prop_client + 16, "bytesout", ef_client_bytesout64, TYPE_UNSIGNED64, "bytes from client to server"},
+	{prop_client + 17, "maxtrafin", ef_client_maxtrafin64, TYPE_UNSIGNED64, "maximum traffic allowed for download"},
+	{prop_client + 18, "maxtrafout", ef_client_maxtrafout64, TYPE_UNSIGNED64, "maximum traffic allowed for upload"},
+	{prop_client + 19, "pwtype", ef_client_pwtype, TYPE_INTEGER, "type of client password"},
 	{NULL, "next", ef_client_next, TYPE_CLIENT, "next"}
 
 	
@@ -810,16 +791,18 @@ struct datatype datatypes[64] = {
 	{"short", NULL, pr_short, NULL},
 	{"char", NULL, pr_char, NULL},
 	{"unsigned", NULL, pr_unsigned, NULL},
+	{"unsigned64", NULL, pr_unsigned64, NULL},
 	{"traffic", NULL, pr_traffic, NULL},
 	{"port", NULL, pr_port, NULL},
 	{"ip", NULL, pr_ip, NULL},
+	{"sa", NULL, pr_sa, NULL},
 	{"cidr", NULL, pr_cidr, NULL},
 	{"string", NULL, pr_string, NULL},
 	{"datetime", NULL, pr_datetime, NULL},
 	{"operations", NULL, pr_operations, NULL},
 	{"rotation", NULL, pr_rotation, NULL},
 	{"portlist", ef_portlist_next, pr_portlist, prop_portlist},
-	{"iplist", ef_iplist_next, pr_iplist, prop_iplist},
+	{"iplist", ef_iplist_next, pr_iplist, NULL},
 	{"userlist", ef_userlist_next, pr_userlist, prop_userlist},
 	{"pwlist", ef_pwlist_next, NULL, prop_pwlist},
 	{"chain", ef_chain_next, NULL, prop_chain},

+ 1 - 3
src/dighosts.c

@@ -3,7 +3,6 @@
  *
  * please read License Agreement
  *
- * $Id: dighosts.c,v 1.10 2009/10/06 08:38:00 v.dubrovin Exp $
  */
 
 #include "proxy.h"
@@ -84,12 +83,11 @@ int main(int argc, char *argv[]){
 		return 4;
 	}
 	*hostend = '/';
-	if(!(sa.sin_addr.s_addr = getip(host))) {
+	if(!getip46(4, host, (struct sockaddr *)&sa)) {
 		fprintf(stderr, "Unable to resolve %s\n", host);
 		return 5;
 	}
 	sa.sin_port = htons(80);
-	sa.sin_family = AF_INET;
 	if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) return 6;
 	sprintf((char *)buf, (char *)request, hostend, host);
 	if(connect(sock,(struct sockaddr *)&sa,sizeof(sa))) {

+ 57 - 42
src/dnspr.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: dnspr.c,v 1.22 2009/09/17 12:21:05 v.dubrovin Exp $
 */
 
 #include "proxy.h"
@@ -14,11 +13,12 @@
 #endif
 #define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
 
-#define BUFSIZE 4096
+#define BUFSIZE 16384
 
 
 void * dnsprchild(struct clientparam* param) {
  unsigned long ip = 0;
+ unsigned char *bbuf;
  unsigned char *buf, *s1, *s2;
  char * host = NULL;
  unsigned char c;
@@ -27,26 +27,28 @@ void * dnsprchild(struct clientparam* param) {
  int len;
  unsigned type=0;
  unsigned ttl;
+ unsigned char addr[16];
 #ifdef _WIN32
 	unsigned long ul = 1;
 #endif
 
 
- if(!(buf = myalloc(BUFSIZE))){
+ if(!(bbuf = myalloc(BUFSIZE+2))){
 	param->srv->fds.events = POLLIN;
 	RETURN (21);
  }
- size = sizeof(struct sockaddr_in);
- i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)&param->sinc, &size); 
+ buf = bbuf+2;
+ size = sizeof(param->sincr);
+ i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)&param->sincr, &size); 
+ size = sizeof(param->sinsl);
+ getsockname(param->srv->srvsock, (struct sockaddr *)&param->sincl, &size);
 #ifdef _WIN32
 	if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
 		RETURN(818);
 	}
 	ioctlsocket(param->clisock, FIONBIO, &ul);
-	size = sizeof(struct sockaddr_in);
-	if(so._getsockname(param->srv->srvsock, (struct sockaddr *)&param->sins, &size)) {RETURN(21);};
 	if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);};
-	if(so._bind(param->clisock,(struct sockaddr *)&param->sins,sizeof(struct sockaddr_in))) {
+	if(so._bind(param->clisock,(struct sockaddr *)&param->sincl,sizeof(param->sincl))) {
 		RETURN(822);
 	}
 
@@ -80,8 +82,8 @@ void * dnsprchild(struct clientparam* param) {
  *s2 = (len - (int)(s2 - buf)) - 1;
 
  type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2];
- if(type==1){
- 	 ip = udpresolve((unsigned char *)host, &ttl, param, 0);
+ if((type==0x01 || type==0x1c) && !param->srv->singlepacket){
+ 	ip = udpresolve((type==0x1c)?AF_INET6:AF_INET, (unsigned char *)host, addr, &ttl, param, 0);
  }
 
  len+=5;
@@ -95,19 +97,19 @@ void * dnsprchild(struct clientparam* param) {
  	memset(buf+len, 0, 16);
 	buf[len] = 0xc0;
 	buf[len+1] = 0x0c;
-	buf[len+3] = 1;
+	buf[len+3] = type;
 	buf[len+5] = 1;
 	ttl = htonl(ttl);
 	memcpy(buf + len + 6, &ttl, 4);
-	buf[len+11] = 4;
-	memcpy(buf+len+12,(void *)&ip,4);
-	len+=16;
+	buf[len+11] = type==1? 4:16;
+	memcpy(buf+len+12,(void *)&addr,type==1? 4:16);
+	len+=(type==1?16:28);
  }
- if(type == 0x0c) {
+ else if(type == 0x0c) {
 	unsigned a, b, c, d;
 	sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d);
 	ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a);
-	if(ip == param->srv->intip){
+	if(*SAFAMILY(&param->sincl) == AF_INET &&  ip == *(unsigned long*)SAADDR(&param->sincl)){
 		buf[2] = 0x85;
 		buf[3] = 0x80;
 		buf[6] = 0;
@@ -127,36 +129,52 @@ void * dnsprchild(struct clientparam* param) {
 	}
 	else ip = 0;
  }
- if(!ip && nservers[0] && type!=1){
-	if((param->remsock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
+ if(!ip && numservers){
+	if((param->remsock=so._socket(SASOCK(&nservers[0].addr), nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {
 		RETURN(818);
 	}
+	memset(&param->sinsl, 0, sizeof(param->sinsl));
+	*SAFAMILY(&param->sinsl) = *SAFAMILY(&nservers[0].addr);
+	if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,sizeof(param->sinsl))) {
+		RETURN(819);
+	}
+	memcpy(&param->sinsr, &nservers[0].addr, sizeof(param->sinsr));
+	if(nservers[0].usetcp) {
+		if(so._connect(param->remsock,(struct sockaddr *)&param->sinsr,sizeof(param->sinsr))) RETURN(830);
+		buf-=2;
+		*(unsigned short*)buf = htons(i);
+		i+=2;
+	}
+	else {
 #ifdef _WIN32
-	ioctlsocket(param->remsock, FIONBIO, &ul);
+/*		ioctlsocket(param->remsock, FIONBIO, &ul); */
 #else
-	fcntl(param->remsock,F_SETFL,O_NONBLOCK);
+/*		fcntl(param->remsock,F_SETFL,O_NONBLOCK);  */
 #endif
-	param->sins.sin_family = AF_INET;
-	param->sins.sin_port = htons(0);
-	param->sins.sin_addr.s_addr = htonl(0);
-	if(so._bind(param->remsock,(struct sockaddr *)&param->sins,sizeof(struct sockaddr_in))) {
-		RETURN(819);
 	}
-	param->sins.sin_addr.s_addr = nservers[0];
-	param->sins.sin_port = htons(53);
-	if(socksendto(param->remsock, &param->sins, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){
+
+	if(socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){
 		RETURN(820);
 	}
-	param->statscli += i;
+	param->statscli64 += i;
 	param->nwrites++;
-	len = sockrecvfrom(param->remsock, &param->sins, buf, BUFSIZE, 15000);
+	len = sockrecvfrom(param->remsock, (struct sockaddr *)&param->sinsr, buf, BUFSIZE, 15000);
 	if(len <= 13) {
 		RETURN(821);
 	}
-	param->statssrv += len;
+	param->statssrv64 += len;
 	param->nreads++;
+	if(nservers[0].usetcp) {
+		unsigned short us;
+		us = ntohs(*(unsigned short *)buf);
+		if(us > 4096) RETURN(833);
+		buf += 2;
+		len -= 2;
+		if(len < us) len += sockgetlinebuf(param, SERVER, buf+len, us - len, 0, conf.timeouts[SINGLEBYTE_L]);
+		if(len != us) RETURN(832);
+	}
 	if(buf[6] || buf[7]){
-		if(socksendto(param->clisock, &param->sinc, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
+		if(socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
 			RETURN(822);
 		}
 		RETURN(0);
@@ -167,25 +185,22 @@ void * dnsprchild(struct clientparam* param) {
 	buf[2] = 0x85;
 	buf[3] = 0x83;
  }
- usleep(SLEEPTIME);
- res = socksendto(param->clisock, &param->sinc, buf, len, conf.timeouts[SINGLEBYTE_L]*1000); 
+ res = socksendto(param->clisock, (struct sockaddr *)&param->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000); 
  if(res != len){RETURN(819);}
  if(!ip) {RETURN(888);}
 
 CLEANRET:
 
  if(param->res!=813){
-	sprintf((char *)buf, "%04x/%s(%u.%u.%u.%u)", 
+	sprintf((char *)buf, "%04x/%s/", 
 			(unsigned)type,
-			host?host:"",
-			(unsigned)(ntohl(ip)&0xff000000)>>24,
-			(unsigned)(ntohl(ip)&0x00ff0000)>>16,
-			(unsigned)(ntohl(ip)&0x0000ff00)>>8,
-			(unsigned)(ntohl(ip)&0x000000ff)
-	);
+			host?host:"");
+	if(ip && type == 0x01 || type == 0x1c){
+		myinet_ntop(type == 0x01? AF_INET:AF_INET6, addr, buf+strlen(buf), 64);
+	}
 	(*param->srv->logfunc)(param, buf);
  }
- if(buf)myfree(buf);
+ if(bbuf)myfree(bbuf);
  if(host)myfree(host);
 #ifndef _WIN32
  param->clisock = INVALID_SOCKET;

+ 14 - 13
src/ftp.c

@@ -3,7 +3,6 @@
  *
  * please read License Agreement
  *
- * $Id: ftp.c,v 1.34 2009/09/17 12:21:06 v.dubrovin Exp $
  */
 
 #include "proxy.h"
@@ -33,7 +32,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
 	if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
 		return 703;
 	}
-	param->statscli += (int)strlen(buf);
+	param->statscli64 += (int)strlen(buf);
 	param->nwrites++;
 	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
 	}
@@ -50,7 +49,7 @@ int ftplogin(struct clientparam *param, char *nbuf, int *innbuf) {
 		if((int)socksend(param->remsock, (unsigned char *)buf, res, conf.timeouts[STRING_S]) != (int)strlen(buf)){
 			return 705;
 		}
-		param->statscli += res;
+	param->statscli64 += res;
 		param->nwrites++;
 		while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0){
 			buf[i] = 0;
@@ -81,7 +80,7 @@ int ftpcd(struct clientparam *param, unsigned char* path, char *nbuf, int *innbu
 	if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
 		return 711;
 	}
-	param->statscli += (int)strlen(buf);
+	param->statscli64 += (int)strlen(buf);
 	param->nwrites++;
 	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
 		if(nbuf && innbuf && inbuf + i < *innbuf && i > 6) {
@@ -114,7 +113,7 @@ int ftpsyst(struct clientparam *param, unsigned char *buf, unsigned len){
 	if(socksend(param->remsock, (unsigned char *)"SYST\r\n", 6, conf.timeouts[STRING_S]) != 6){
 		return 721;
 	}
-	param->statscli+=6;
+	param->statscli64 += 6;
 	param->nwrites++;
 	while((i = sockgetlinebuf(param, SERVER, buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
 	}
@@ -133,7 +132,7 @@ int ftppwd(struct clientparam *param, unsigned char *buf, unsigned len){
 	if(socksend(param->remsock, (unsigned char *)"PWD\r\n", 5, conf.timeouts[STRING_S]) != 5){
 		return 731;
 	}
-	param->statscli += 5;
+	param->statscli64 += 5;
 	param->nwrites++;
 	while((i = sockgetlinebuf(param, SERVER, buf, len - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
 	}
@@ -158,7 +157,7 @@ int ftptype(struct clientparam *param, unsigned char* f_type){
 	if((int)socksend(param->remsock, (unsigned char *)buf, (int)strlen(buf), conf.timeouts[STRING_S]) != (int)strlen(buf)){
 		return 741;
 	}
-	param->statscli += (int)strlen(buf);
+	param->statscli64 += (int)strlen(buf);
 	param->nwrites++;
 	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
 	}
@@ -179,7 +178,7 @@ SOCKET ftpdata(struct clientparam *param){
 	if(socksend(param->remsock, (unsigned char *)"PASV\r\n", 6, conf.timeouts[STRING_S]) != 6){
 		return INVALID_SOCKET;
 	}
-	param->statscli+=6;
+	param->statscli64 += 6;
 	param->nwrites++;
 	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
 	}
@@ -190,12 +189,14 @@ SOCKET ftpdata(struct clientparam *param){
 	if(sscanf(sb+1, "%lu,%lu,%lu,%lu,%hu,%hu", &b1, &b2, &b3, &b4, &b5, &b6)!=6) return INVALID_SOCKET;
 	rem = param->remsock;
 	param->remsock = INVALID_SOCKET;
-	param->req.sin_family = AF_INET;
-	param->req.sin_port = param->sins.sin_port = htons((unsigned short)((b5<<8)^b6));
-	param->req.sin_addr.s_addr = param->sins.sin_addr.s_addr = htonl((b1<<24)^(b2<<16)^(b3<<8)^b4);
+	memcpy(&param->req,&param->sinsr,sizeof(param->req));
+	*SAPORT(&param->req) = *SAPORT(&param->sinsr) = htons((unsigned short)((b5<<8)^b6));
 	i = param->operation;
 	param->operation = FTP_DATA;
-	if((param->res = (*param->srv->authfunc)(param))) return INVALID_SOCKET;
+	if((param->res = (*param->srv->authfunc)(param))) {
+		param->remsock = rem;
+		return INVALID_SOCKET;
+	}
 	param->operation = i;
 	s = param->remsock;
 	param->remsock = rem;
@@ -217,7 +218,7 @@ SOCKET ftpcommand(struct clientparam *param, unsigned char * command, unsigned c
 		so._closesocket(s);
 		return INVALID_SOCKET;
 	}
-	param->statscli += (int)strlen(buf);
+	param->statscli64 += (int)strlen(buf);
 	param->nwrites++;
 	while((i = sockgetlinebuf(param, SERVER, (unsigned char *)buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L])) > 0 && (i < 3 || !isnumber(*buf) || buf[3] == '-')){
 	}

+ 31 - 29
src/ftppr.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: ftppr.c,v 1.45 2011-08-15 19:52:27 vlad Exp $
 */
 
 #include "proxy.h"
@@ -71,7 +70,7 @@ void * ftpprchild(struct clientparam* param) {
 		param->res = res;
 		if(inbuf && inbuf != BUFSIZE && socksend(param->ctrlsock, buf, inbuf, conf.timeouts[STRING_S])!=inbuf) {RETURN (807);}
 		if(!res) status = 3;
-		sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(param->sins.sin_port)==21)?0:':', ntohs(param->sins.sin_port));
+		sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(*SAPORT(&param->sinsr))==21)?0:':', ntohs(*SAPORT(&param->sinsr)));
 		req = mystrdup((char *)buf);
 #ifndef WITHMAIN
 		{
@@ -119,32 +118,35 @@ void * ftpprchild(struct clientparam* param) {
 			so._closesocket(clidatasock);
 			clidatasock = INVALID_SOCKET;
 		}
-		if ((clidatasock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
-		sasize = sizeof(struct sockaddr_in);
-		if(so._getsockname(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(824);}
-		param->sinc.sin_port = 0;
-		if(so._bind(clidatasock, (struct sockaddr *)&param->sinc, sasize)){RETURN(822);}
+		if ((clidatasock=socket(SASOCK(&param->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
+		sasize = sizeof(param->sincl);
+		*SAPORT(&param->sincl) = 0;
+		if(so._bind(clidatasock, (struct sockaddr *)&param->sincl, sasize)){RETURN(822);}
 		if (pasv) {
 			if(so._listen(clidatasock, 1)) {RETURN(823);}
-			if(so._getsockname(clidatasock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(824);}
-			sprintf((char *)buf, "227 OK (%u,%u,%u,%u,%u,%u)\r\n",
-				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[0]),
-				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[1]),
-				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[2]),
-				 (unsigned)(((unsigned char *)(&param->sinc.sin_addr.s_addr))[3]),
-				 (unsigned)(((unsigned char *)(&param->sinc.sin_port))[0]),
-				 (unsigned)(((unsigned char *)(&param->sinc.sin_port))[1])
-				);
+			if(so._getsockname(clidatasock, (struct sockaddr *)&param->sincl, &sasize)){RETURN(824);}
+			if(*SAFAMILY(&param->sincl) == AF_INET)
+				sprintf((char *)buf, "227 OK (%u,%u,%u,%u,%u,%u)\r\n",
+					 (unsigned)(((unsigned char *)(SAADDR(&param->sincl)))[0]),
+					 (unsigned)(((unsigned char *)(SAADDR(&param->sincl)))[1]),
+					 (unsigned)(((unsigned char *)(SAADDR(&param->sincl)))[2]),
+					 (unsigned)(((unsigned char *)(SAADDR(&param->sincl)))[3]),
+					 (unsigned)(((unsigned char *)(SAPORT(&param->sincl)))[0]),
+					 (unsigned)(((unsigned char *)(SAPORT(&param->sincl)))[1])
+					);
+			else sprintf((char *)buf, "227 OK (127,0,0,1,%u,%u)\r\n", 
+					 (unsigned)(((unsigned char *)(SAPORT(&param->sincl)))[0]),
+					 (unsigned)(((unsigned char *)(SAPORT(&param->sincl)))[1])
+					);			
 		}
 		else {
 			unsigned long b1, b2, b3, b4;
 			unsigned short b5, b6;
 
 			if(sscanf((char *)buf+5, "%lu,%lu,%lu,%lu,%hu,%hu", &b1, &b2, &b3, &b4, &b5, &b6)!=6) {RETURN(828);}
-			param->sinc.sin_family = AF_INET;
-			param->sinc.sin_port = htons((unsigned short)((b5<<8)^b6));
-			param->sinc.sin_addr.s_addr = htonl((b1<<24)^(b2<<16)^(b3<<8)^b4);
-			if(so._connect(clidatasock, (struct sockaddr *)&param->sinc, sasize)) {
+			*SAPORT(&param->sincr) = htons((unsigned short)((b5<<8)^b6));
+			sasize = sizeof(param->sincr);
+			if(so._connect(clidatasock, (struct sockaddr *)&param->sincr, sasize)) {
 				so._closesocket(clidatasock);
 				clidatasock = INVALID_SOCKET;
 				RETURN(826);
@@ -203,8 +205,8 @@ void * ftpprchild(struct clientparam* param) {
 			if(res != 1) {
 				RETURN(857);
 			}
-			sasize = sizeof(struct sockaddr_in);
-			ss = so._accept(clidatasock, (struct sockaddr *)&param->sinc, &sasize);
+			sasize = sizeof(param->sincr);
+			ss = so._accept(clidatasock, (struct sockaddr *)&param->sincr, &sasize);
 			if (ss == INVALID_SOCKET) { RETURN (858);}
 			so._shutdown(clidatasock, SHUT_RDWR);
 			so._closesocket(clidatasock);
@@ -274,7 +276,7 @@ void * ftpprchild(struct clientparam* param) {
 		buf[i++] = '\r';
 		buf[i++] = '\n';
 		if(socksend(param->remsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (811);}
-		param->statscli += i;
+ param->statscli64+=(i);
 		param->nwrites++;
 		while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', conf.timeouts[STRING_L])) > 0){
 			if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (812);}
@@ -283,9 +285,9 @@ void * ftpprchild(struct clientparam* param) {
 		if(status == 5) {RETURN (0);}
 		if(i < 3) {RETURN (813);}
 	}
-	sasize = sizeof(struct sockaddr_in);
-	if(so._getpeername(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize)){RETURN(819);}
-	if(req && (param->statscli || param->statssrv)){
+	sasize = sizeof(param->sincr);
+	if(so._getpeername(param->ctrlsock, (struct sockaddr *)&param->sincr, &sasize)){RETURN(819);}
+	if(req && (param->statscli64 || param->statssrv64)){
 		(*param->srv->logfunc)(param, (unsigned char *)req);
 	}
  }
@@ -304,9 +306,9 @@ CLEANRET:
 	so._shutdown(clidatasock, SHUT_RDWR);
 	so._closesocket(clidatasock);
  }
- sasize = sizeof(struct sockaddr_in);
- so._getpeername(param->ctrlsock, (struct sockaddr *)&param->sinc, &sasize);
- if(param->res != 0 || param->statscli || param->statssrv ){
+ sasize = sizeof(param->sincr);
+ so._getpeername(param->ctrlsock, (struct sockaddr *)&param->sincr, &sasize);
+ if(param->res != 0 || param->statscli64 || param->statssrv64 ){
 	(*param->srv->logfunc)(param, (unsigned char *)((req && (param->res > 802))? req:NULL));
  }
  if(req) myfree(req);

+ 8 - 12
src/icqpr.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: icqpr.c,v 1.30 2012-04-11 23:01:19 vlad Exp $
 */
 
 #include "proxy.h"
@@ -105,11 +104,11 @@ static void addbuffer(int increment, struct clientparam * param, unsigned char *
 		*buf_p = newbuf;
 		*bufsize_p = bufsize;
 	}
-	if(increment) len = sockrecvfrom(param->remsock, &param->sins, *buf_p + *length_p, increment, conf.timeouts[STRING_S]*1000);
+	if(increment) len = sockrecvfrom(param->remsock, (struct sockaddr *)&param->sinsr, *buf_p + *length_p, increment, conf.timeouts[STRING_S]*1000);
 	if(len > 0) {
 		*length_p += len;
 		param->nreads++;
-		param->statssrv += len;
+		param->statssrv64 += len;
 	}
 	return;
 }
@@ -118,7 +117,7 @@ static void addbuffer(int increment, struct clientparam * param, unsigned char *
 
 static int searchcookie(struct clientparam *param, struct flap_header * flap, int len, int * dif, struct tlv_header *tlv, int extra){
  struct icq_cookie *ic;
- char smallbuf[32];
+ char smallbuf[64];
  struct tlv_header *bostlv = NULL;
  struct sockaddr_in sa;
  SASIZETYPE size = sizeof(sa);
@@ -165,7 +164,7 @@ static int searchcookie(struct clientparam *param, struct flap_header * flap, in
 	pthread_mutex_unlock(&icq_cookie_mutex);
 	if(bostlv){
 		if(so._getsockname(param->clisock, (struct sockaddr *)&sa, &size)==-1) return 1;
-		len = myinet_ntoa(sa.sin_addr, smallbuf);
+		len = myinet_ntop(*SAFAMILY(&sa),SAADDR(&sa), smallbuf, 64);
 		if(strchr(ic->connectstring, ':'))sprintf(smallbuf+len, ":%hu", ntohs(sa.sin_port));
 		len = (int)strlen(smallbuf);
 		*dif = len - (int)ntohs(bostlv->size);
@@ -437,20 +436,17 @@ void * icqprchild(struct clientparam* param) {
 
  if(greet){
 	if(socksend(param->remsock, tmpsend, 10, conf.timeouts[STRING_S])!=10) {RETURN (1105);}
-	param->statscli += 10;
+	param->statscli64 += 10;
  }
  if(readflap(param, SERVER, tmpsend, 1024)) {RETURN (1111);}
- param->statssrv += (ntohs(((struct flap_header *)tmpsend)->size) + 6);
+ param->statssrv64 += (ntohs(((struct flap_header *)tmpsend)->size) + 6);
  mystate.srvseq = ntohs(((struct flap_header *)tmpsend)->seq) + 1;
  mystate.seq = 1;
  len = ntohs(flap->size) + 6;
  if((res=handledatfltcli(param,  &buf, &buflen, offset, &len))!=PASS) RETURN(res);
  if(socksend(param->remsock, buf+offset, len, conf.timeouts[STRING_S])!=(ntohs(flap->size)+6)) {RETURN (1106);}
  offset = 0;
- param->statscli += len;
-
-
-
+ param->statscli64 += len;
 
  if(logintype == ICQMD5) {
 	if(readflap(param, SERVER, buf, 65550)) {RETURN (1112);}
@@ -466,7 +462,7 @@ void * icqprchild(struct clientparam* param) {
 	len = ntohs(flap->size) + 6;
 	if((res=handledatfltcli(param,  &buf, &buflen, offset, &len))!=PASS) RETURN(res);
 	if(socksend(param->remsock, buf+offset, len, conf.timeouts[STRING_S])!=len) {RETURN (1115);}
-	param->statscli += len;
+	param->statscli64 += len;
 	offset = 0;
  }
  if(logintype != ICQCOOKIE) {

+ 0 - 2
src/libs/md4.c

@@ -1,8 +1,6 @@
 /*
  * md4c.c	MD4 message-digest algorithm
  *
- * Version:	$Id: md4.c,v 1.1 2010-11-11 11:32:32 v.dubrovin Exp $
- *
  *   License to copy and use this software is granted provided that it
  *   is identified as the "RSA Data Security, Inc. MD4 Message-Digest
  *   Algorithm" in all material mentioning or referencing this software

+ 1 - 2
src/myalloc.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: myalloc.c,v 1.5 2008/01/08 21:46:38 vlad Exp $
 */
 
 #include "proxy.h"
@@ -333,7 +332,7 @@ void *myrealloc(void *ptr, size_t size){
 	if(size <= memsizes[l]) return ptr;
 	p = myalloc(size);
 	if(p){
-		memcpy(p,ptr,size);
+		memmove(p,ptr,size);
 		myfree(ptr);
 	}
 	return p;	

+ 0 - 1
src/mycrypt.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: mycrypt.c,v 1.8 2008/01/08 21:46:38 vlad Exp $
 */
 #include "libs/md5.h"
 #include "libs/md4.h"

+ 2 - 3
src/ntlm.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: ntlm.c,v 1.9 2008/01/08 21:46:38 vlad Exp $
 */
 
 #include "proxy.h"
@@ -81,8 +80,8 @@ void genchallenge(struct clientparam *param, char * challenge, char *buf){
 	chal->flags[3] = 0xA0;
 	text2unicode(hostname, (char *)chal->data, 64);
 	time((time_t *)challenge);
-	memcpy(challenge+4, &param->sinc.sin_addr.s_addr, 4);
-	challenge[1]^=param->sinc.sin_port;
+	memcpy(challenge+4, SAADDR(&param->sincr), 4);
+	challenge[1]^=*SAPORT(&param->sincr);
 	for(i = 0; i < 8; i++) challenge[i] ^= myrand(challenge, 8);
 	memcpy(chal->challenge, challenge, 8);
 	en64((unsigned char *)tmpbuf, (unsigned char *)buf, (int)((unsigned char *)chal->data - (unsigned char *)chal) + len);	

+ 39 - 39
src/plugins.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: ntlm.c,v 1.8 2007/12/27 13:20:04 vlad Exp $
 */
 
 #include "proxy.h"
@@ -33,10 +32,10 @@ struct symbol symbols[] = {
 	{symbols+5, "sockgetcharcli", (void *) sockgetcharcli},
 	{symbols+6, "sockgetcharsrv", (void *) sockgetcharsrv},
 	{symbols+7, "sockgetlinebuf", (void *) sockgetlinebuf},
-	{symbols+8, "myinet_ntoa", (void *) myinet_ntoa},
+	{symbols+8, "myinet_ntop", (void *) myinet_ntop},
 	{symbols+9, "dobuf", (void *) dobuf},
 	{symbols+10, "scanaddr", (void *) scanaddr},
-	{symbols+11, "getip", (void *) getip},
+	{symbols+11, "getip46", (void *) getip46},
 	{symbols+12, "sockmap", (void *) sockmap},
 	{symbols+13, "sockfuncs", (void *) &so},
 	{symbols+14, "ACLmatches", (void *) ACLmatches},
@@ -44,40 +43,41 @@ struct symbol symbols[] = {
 	{symbols+16, "trafcountfunc", (void *) trafcountfunc},
 	{symbols+17, "alwaysauth", (void *) alwaysauth},
 	{symbols+18, "ipauth", (void *) ipauth},
-	{symbols+19, "nbnameauth", (void *) nbnameauth},
-	{symbols+20, "strongauth", (void *) strongauth},
-	{symbols+21, "checkACL", (void *) checkACL},
-	{symbols+22, "nametohash", (void *) nametohash},
-	{symbols+23, "hashindex", (void *) hashindex},
-	{symbols+24, "nservers", (void *) nservers},
-	{symbols+25, "udpresolve", (void *) udpresolve},
-	{symbols+26, "bandlim_mutex", (void *) &bandlim_mutex},
-	{symbols+27, "tc_mutex", (void *) &tc_mutex},
-	{symbols+28, "hash_mutex", (void *) &hash_mutex},
-	{symbols+29, "pwl_mutex", (void *) &pwl_mutex},
-	{symbols+30, "linenum", (void *) &linenum},
-	{symbols+31, "proxy_stringtable", (void *) proxy_stringtable},
-	{symbols+32, "en64", (void *) en64},
-	{symbols+33, "de64", (void *) de64},
-	{symbols+34, "tohex", (void *) tohex},
-	{symbols+35, "fromhex", (void *) fromhex},
-	{symbols+36, "dnspr", (void *) dnsprchild},
-	{symbols+37, "pop3p", (void *) pop3pchild},
-	{symbols+38, "proxy", (void *) proxychild},
-	{symbols+39, "socks", (void *) sockschild},
-	{symbols+40, "tcppm", (void *) tcppmchild},
-	{symbols+41, "udppm", (void *) udppmchild},
-	{symbols+42, "admin", (void *) adminchild},
-	{symbols+43, "ftppr", (void *) ftpprchild},
-	{symbols+44, "smtpp", (void *) smtppchild},
-	{symbols+45, "icqpr", (void *) icqprchild},
-	{symbols+46, "msnpr", (void *) msnprchild},
-	{symbols+47, "authfuncs", (void *) &authfuncs},
-	{symbols+48, "commandhandlers", (void *) &commandhandlers},
-	{symbols+49, "decodeurl", (void *) decodeurl},
-	{symbols+50, "parsestr", (void *) parsestr},
-	{symbols+51, "make_ace", (void *) make_ace},
-	{symbols+52, "freeacl", (void *) freeacl},
+	{symbols+19, "strongauth", (void *) strongauth},
+	{symbols+20, "checkACL", (void *) checkACL},
+	{symbols+21, "nametohash", (void *) nametohash},
+	{symbols+22, "hashindex", (void *) hashindex},
+	{symbols+23, "nservers", (void *) nservers},
+	{symbols+24, "udpresolve", (void *) udpresolve},
+	{symbols+25, "bandlim_mutex", (void *) &bandlim_mutex},
+	{symbols+26, "tc_mutex", (void *) &tc_mutex},
+	{symbols+27, "hash_mutex", (void *) &hash_mutex},
+	{symbols+28, "pwl_mutex", (void *) &pwl_mutex},
+	{symbols+29, "linenum", (void *) &linenum},
+	{symbols+30, "proxy_stringtable", (void *) proxy_stringtable},
+	{symbols+31, "en64", (void *) en64},
+	{symbols+32, "de64", (void *) de64},
+	{symbols+33, "tohex", (void *) tohex},
+	{symbols+34, "fromhex", (void *) fromhex},
+	{symbols+35, "dnspr", (void *) dnsprchild},
+	{symbols+36, "pop3p", (void *) pop3pchild},
+	{symbols+37, "proxy", (void *) proxychild},
+	{symbols+38, "socks", (void *) sockschild},
+	{symbols+39, "tcppm", (void *) tcppmchild},
+	{symbols+40, "udppm", (void *) udppmchild},
+	{symbols+41, "admin", (void *) adminchild},
+	{symbols+42, "ftppr", (void *) ftpprchild},
+	{symbols+43, "smtpp", (void *) smtppchild},
+	{symbols+44, "icqpr", (void *) icqprchild},
+/*
+	{symbols+45, "msnpr", (void *) msnprchild},
+*/
+	{symbols+45, "authfuncs", (void *) &authfuncs},
+	{symbols+46, "commandhandlers", (void *) &commandhandlers},
+	{symbols+47, "decodeurl", (void *) decodeurl},
+	{symbols+48, "parsestr", (void *) parsestr},
+	{symbols+49, "make_ace", (void *) make_ace},
+	{symbols+50, "freeacl", (void *) freeacl},
 	{NULL, "", NULL}
 };
 
@@ -103,11 +103,11 @@ struct pluginlink pluginlink = {
 	sockgetcharcli,
 	sockgetcharsrv,
 	sockgetlinebuf,
-	myinet_ntoa,
+	myinet_ntop,
 	dobuf,
 	dobuf2,
 	scanaddr,
-	getip,
+	getip46,
 	sockmap,
 	ACLmatches,		
 	alwaysauth,

+ 34 - 14
src/plugins/FilePlugin/FilePlugin.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: FilePlugin.c,v 1.8 2012-04-11 23:01:22 vlad Exp $
 */
 
 #include "../../structures.h"
@@ -847,6 +846,36 @@ static struct symbol fp_symbols[] = {
 	{NULL, "fp_stringtable", (void*) fp_stringtable}
 };
 
+static int h_cachedir(int argc, unsigned char **argv){
+	char * dirp;
+	size_t len;
+
+	dirp = (argc > 1)? argv[1] : getenv("TEMP");
+	len = strlen(dirp);
+	if(!dirp || !len || len > 200 || strchr(dirp, '%')) {
+		fprintf(stderr, "FilePlugin: invalid directory path: %s\n", dirp);
+		return (1);
+	}
+#ifdef _WIN32
+	if(dirp[len-1] == '\\') dirp[len-1] = 0;
+	sprintf(path, "%.256s\\%%07d.tmp", dirp);
+#else
+	if(dirp[len-1] == '/') dirp[len-1] = 0;
+	sprintf(path, "%.256s/%%07d.tmp", dirp);
+#endif
+	return 0;
+}
+
+static int h_preview(int argc, unsigned char **argv){
+	preview = atoi(argv[1]);
+	return 0;
+}
+
+static struct commands file_commandhandlers[] = {
+	{file_commandhandlers + 1, "file_cachedir", h_cachedir, 2, 2},
+	{NULL, "file_preview", h_preview, 2, 2},
+};
+
 static int file_loaded=0;
 
 
@@ -858,7 +887,6 @@ __declspec(dllexport)
  int file_plugin (struct pluginlink * pluginlink, 
 					 int argc, char** argv){
 
-	char * dirp;
 	if(!file_loaded){
 		pthread_mutex_init(&file_mutex, NULL);
 		file_loaded = 1;
@@ -875,19 +903,11 @@ __declspec(dllexport)
 		pl->conf->filters = &fp_filter;
 		fp_symbols[1].next = pl->symbols.next;
 		pl->symbols.next = fp_symbols;
+		file_commandhandlers[1].next = pl->commandhandlers->next;
+		pl->commandhandlers->next = file_commandhandlers;
 	}
-	dirp = (argc > 1)? argv[1] : getenv("TEMP");
-	if(strlen(dirp) > 200 || strchr(dirp, '%')) {
-		fprintf(stderr, "FilePlugin: invalid directory path: %s\n", dirp);
-		return (13001);
-	}
-#ifdef _WIN32
-	sprintf(path, "%.256s\\%%07d.tmp", dirp);
-#else
-	sprintf(path, "%.256s/%%07d.tmp", dirp);
-#endif
-	if(argc > 2) preview = atoi(argv[2]);
-	if(!preview) preview = 32768;
+	h_cachedir(0, NULL);
+	preview = 32768;
 
 	return 0;
 		

+ 6 - 6
src/plugins/PCREPlugin/pcre_plugin.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: pcre_plugin.c,v 1.11 2012-04-25 18:17:22 vlad Exp $
 */
 
 #include "../../structures.h"
@@ -230,12 +229,12 @@ static int h_pcre(int argc, unsigned char **argv){
 	struct filter *newf;
 	char *replace = NULL;
 	
-	if(!strcmp(argv[2], "allow")) action = PASS;
-	else if(!strcmp(argv[2], "deny")) action = REJECT;
-	else if(!strcmp(argv[2], "remove")) action = REMOVE;
-	else if(!strcmp(argv[2], "dunno")) action = CONTINUE;
+	if(!strncmp(argv[2], "allow",5)) action = PASS;
+	else if(!strncmp(argv[2], "deny",4)) action = REJECT;
+	else if(!strncmp(argv[2], "remove",6)) action = REMOVE;
+	else if(!strncmp(argv[2], "dunno",5)) action = CONTINUE;
 	else return 1;
-	if(!strcmp(argv[0], "pcre_rewrite")) {
+	if(!strncmp(argv[0], "pcre_rewrite", 12)) {
 		int i,j;
 		offset = 5;
 		replace = pl->mystrdup(argv[4]);
@@ -267,6 +266,7 @@ static int h_pcre(int argc, unsigned char **argv){
 		replace[j] = 0;
 	}
 	if(!(acl = pl->make_ace(argc - offset, argv + offset))) return 2;
+	acl->nolog = (strstr(argv[2],"log") == 0);
 	if(*argv[3] && !(*argv[3] == '*' && !argv[3][1]) ){
 		re = pcre_compile((char *)argv[3], pcre_options, &errptr, &offset, NULL);
 		if(!re) {

+ 1 - 1
src/plugins/PamAuth/pamauth.c

@@ -19,7 +19,7 @@ static int         already_loaded = 0;
 static struct auth pamauth;
 #ifdef USERCASE
 static int     usercaselow = 0;
-#edif
+#endif
 static unsigned char *service=NULL;
 static struct pluginlink * pl;
 

+ 35 - 14
src/plugins/SSLPlugin/my_ssl.c

@@ -2,12 +2,11 @@
 #define _CRT_SECURE_NO_WARNINGS
 
 #include "../../structures.h"
-#include "../../proxy.h"
-#include "my_ssl.h"
-
 #include <memory.h>
-#include <errno.h>
 #include <fcntl.h>
+#ifndef _WIN32
+#include <sys/file.h>
+#endif
 
 #include <openssl/crypto.h>
 #include <openssl/x509.h>
@@ -16,6 +15,12 @@
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 
+#include "../../proxy.h"
+#include "my_ssl.h"
+
+
+
+
 typedef struct _ssl_conn {
 	SSL_CTX *ctx;
 	SSL *ssl;
@@ -110,20 +115,23 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert)
 	static char hash_name[sizeof(src_cert->sha1_hash)*2 + 1];
 	static char cache_name[200];
 
-	pthread_mutex_lock(&ssl_file_mutex);
 	bin2hex(src_cert->sha1_hash, sizeof(src_cert->sha1_hash), hash_name, sizeof(hash_name));
 	sprintf(cache_name, "%s%s.pem", cert_path, hash_name);
 	/* check if certificate is already cached */
 	fcache = fopen(cache_name, "rb");
 	if ( fcache != NULL ) {
+#ifndef _WIN32
+		flock(fileno(fcache), LOCK_SH);
+#endif
 		dst_cert = PEM_read_X509(fcache, &dst_cert, NULL, NULL);
+#ifndef _WIN32
+		flock(fileno(fcache), LOCK_UN);
+#endif
 		fclose(fcache);
 		if ( dst_cert != NULL ){
-			pthread_mutex_unlock(&ssl_file_mutex);
 			return dst_cert;
 		}
 	}
-	pthread_mutex_unlock(&ssl_file_mutex);
 
 	/* proceed if certificate is not cached */
 	dst_cert = X509_dup(src_cert);
@@ -163,18 +171,22 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert)
 
 	/* write to cache */
 
-	pthread_mutex_lock(&ssl_file_mutex);
 	fcache = fopen(cache_name, "wb");
 	if ( fcache != NULL ) {
+#ifndef _WIN32
+		flock(fileno(fcache), LOCK_EX);
+#endif
 		PEM_write_X509(fcache, dst_cert);
+#ifndef _WIN32
+		flock(fileno(fcache), LOCK_UN);
+#endif
 		fclose(fcache);
 	}
-	pthread_mutex_unlock(&ssl_file_mutex);
 	return dst_cert;
 }
 
 
-SSL_CONN ssl_handshake_to_server(SOCKET s, SSL_CERT *server_cert, char **errSSL)
+SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CERT *server_cert, char **errSSL)
 {
 	int err = 0;
 	X509 *cert;
@@ -204,6 +216,7 @@ SSL_CONN ssl_handshake_to_server(SOCKET s, SSL_CERT *server_cert, char **errSSL)
 		ssl_conn_free(conn);
 		return NULL;
 	}
+	if(hostname && *hostname)SSL_set_tlsext_host_name(conn->ssl, hostname);
 	err = SSL_connect(conn->ssl);
 	if ( err == -1 ) {
 		*errSSL = ERR_error_string(ERR_get_error(), errbuf);
@@ -212,6 +225,10 @@ SSL_CONN ssl_handshake_to_server(SOCKET s, SSL_CERT *server_cert, char **errSSL)
 	}
 
 	cert = SSL_get_peer_certificate(conn->ssl);     
+	if(!cert) {
+		ssl_conn_free(conn);
+		return NULL;
+	}
 
 	/* TODO: Verify certificate */
 
@@ -312,10 +329,14 @@ void ssl_conn_free(SSL_CONN connection)
 {
 	ssl_conn *conn = (ssl_conn *) connection;
 
-	SSL_shutdown(conn->ssl);
-	SSL_free(conn->ssl);
-	SSL_CTX_free(conn->ctx);
-	free(conn);
+	if(conn){
+		if(conn->ssl){
+			SSL_shutdown(conn->ssl);
+			SSL_free(conn->ssl);
+		}
+		if(conn->ctx) SSL_CTX_free(conn->ctx);
+		free(conn);
+	}
 }
 
 void _ssl_cert_free(SSL_CERT cert)

+ 1 - 1
src/plugins/SSLPlugin/my_ssl.h

@@ -18,7 +18,7 @@ SSL_CERT ssl_copy_cert(SSL_CERT cert);
 //
 // SSL/TLS handshakes
 //
-SSL_CONN ssl_handshake_to_server(SOCKET s, SSL_CERT *server_cert, char **errSSL);
+SSL_CONN ssl_handshake_to_server(SOCKET s, char * hostname, SSL_CERT *server_cert, char **errSSL);
 SSL_CONN ssl_handshake_to_client(SOCKET s, SSL_CERT server_cert, char **errSSL);
 
 //

+ 53 - 15
src/plugins/SSLPlugin/ssl_plugin.c

@@ -4,17 +4,15 @@
 
    please read License Agreement
 
-   $Id: ssl_plugin.c,v 1.9 2010-11-11 11:32:33 v.dubrovin Exp $
 */
 
 #include "../../structures.h"
-#include "../../proxy.h"
 #include <openssl/rsa.h>       /* SSLeay stuff */
 #include <openssl/crypto.h>
 #include <openssl/x509.h>
 #include <openssl/pem.h>
 #include <openssl/ssl.h>
-#include <openssl/err.h>
+#include "../../proxy.h"
 #include "my_ssl.h"
 
 #ifndef _WIN32
@@ -54,13 +52,15 @@ struct SSLqueue {
 
 
 /*
- Todo: use hashtable
+ TO DO: use hashtable
 */
 static struct SSLqueue *searchSSL(SOCKET s){
-	struct SSLqueue *sslq;
+	struct SSLqueue *sslq = NULL;
+	pthread_mutex_lock(&ssl_mutex);
 	for(sslq = SSLq; sslq; sslq = sslq->next)
-		if(sslq->s == s) return sslq;
-	return NULL;
+		if(sslq->s == s) break;
+	pthread_mutex_unlock(&ssl_mutex);
+	return sslq;
 }
 
 static void addSSL(SOCKET s, SSL_CERT cert, SSL_CONN conn, struct clientparam* param){
@@ -235,7 +235,7 @@ int dossl(struct clientparam* param, SSL_CONN* ServerConnp, SSL_CONN* ClientConn
 	ul = ((unsigned long)ssl_connect_timeout)*1000;
 	setsockopt(param->remsock, SOL_SOCKET, SO_SNDTIMEO, (char *)&ul, 4);
  }
- ServerConn = ssl_handshake_to_server(param->remsock, &ServerCert, &errSSL);
+ ServerConn = ssl_handshake_to_server(param->remsock, (char *)param->hostname, &ServerCert, &errSSL);
  if ( ServerConn == NULL || ServerCert == NULL ) {
 	param->res = 8011;
 	param->srv->logfunc(param, (unsigned char *)"SSL handshake to server failed");
@@ -325,6 +325,47 @@ static struct filter ssl_filter = {
 	ssl_filter_close
 };
 
+int mitm = 0;
+
+static int h_mitm(int argc, unsigned char **argv){
+	if((mitm&1)) return 1;
+	if(mitm) usleep(100*SLEEPTIME);
+	ssl_filter.next = pl->conf->filters;
+	pl->conf->filters = &ssl_filter;
+	mitm++;
+	return 0;
+}
+
+static int h_nomitm(int argc, unsigned char **argv){
+	struct filter * sf;
+	if(!(mitm&1)) return 1;
+	if(mitm) usleep(100*SLEEPTIME);
+	if(pl->conf->filters == &ssl_filter) pl->conf->filters = ssl_filter.next;
+	else for(sf = pl->conf->filters; sf && sf->next; sf=sf->next){
+		if(sf->next == &ssl_filter) {
+			sf->next = ssl_filter.next;
+			break;
+		}
+	}
+	mitm++;
+	return 0;
+}
+
+static int h_certpath(int argc, unsigned char **argv){
+	size_t len;
+	len = strlen(argv[1]);
+	if(!len || (argv[1][len - 1] != '/' && argv[1][len - 1] != '\\')) return 1;
+	if(cert_path && *cert_path) free(cert_path);
+	cert_path = strdup(argv[1]);
+	return 0;
+}
+
+static struct commands ssl_commandhandlers[] = {
+	{ssl_commandhandlers+1, "ssl_mitm", h_mitm, 1, 1},
+	{ssl_commandhandlers+2, "ssl_nomitm", h_nomitm, 1, 1},
+	{NULL, "ssl_certcache", h_certpath, 2, 2},
+};
+
 
 #ifdef _WIN32
 __declspec(dllexport)
@@ -333,15 +374,9 @@ __declspec(dllexport)
  int ssl_plugin (struct pluginlink * pluginlink, 
 					 int argc, char** argv){
 	pl = pluginlink;
-	if(argc > 1) {
-		if(cert_path && *cert_path) free(cert_path);
-		cert_path = strdup(argv[1]);
-	}
 	if(!ssl_loaded){
 		ssl_loaded = 1;
 		pthread_mutex_init(&ssl_mutex, NULL);
-		ssl_filter.next = pl->conf->filters;
-		pl->conf->filters = &ssl_filter;
 		memcpy(&sso, pl->so, sizeof(struct sockfuncs));
 		pl->so->_send = ssl_send;
 		pl->so->_recv = ssl_recv;
@@ -349,10 +384,13 @@ __declspec(dllexport)
 		pl->so->_recvfrom = ssl_recvfrom;
 		pl->so->_closesocket = ssl_closesocket;
 		pl->so->_poll = ssl_poll;
+		ssl_commandhandlers[2].next = pl->commandhandlers->next;
+		pl->commandhandlers->next = ssl_commandhandlers;
 	}
-	else{
+	else {
 		ssl_release();
 	}
+
 	ssl_init();
 	tcppmfunc = (PROXYFUNC)pl->findbyname("tcppm");	
 	if(!tcppmfunc){return 13;}

+ 33 - 5
src/plugins/TrafficPlugin/TrafficPlugin.c

@@ -179,18 +179,27 @@ void mylogfunc(struct clientparam * param, const unsigned char * pz) {
 	int port;
 	int rule = 0;
 	struct trafcorrect * starttrafcorrect = firsttrafcorrect;
-	int statssrv_before, statscli_before;
+#ifndef NOPSTDINT
+	uint64_t  statssrv_before, statscli_before;
+#else
+	unsigned long statssrv_before, statscli_before;
+#endif
 	int ok = 0;
 	for (;starttrafcorrect != NULL; starttrafcorrect = starttrafcorrect->next) {
 		port = starttrafcorrect->port;
 		g_s = starttrafcorrect->p_service;
 		if (starttrafcorrect->p_service == S_NOSERVICE) g_s = param->service;
-		if (starttrafcorrect->port <= 0)  port = myhtons(param->sins.sin_port);
+		if (starttrafcorrect->port <= 0)  port = myhtons(*SAPORT(&param->sinsr));
 		
+#ifndef NOPSTDINT
+		statssrv_before = param->statssrv64;
+		statscli_before = param->statscli64;
+#else
 		statssrv_before = param->statssrv;
 		statscli_before = param->statscli;
+#endif
 		rule++;
-		if (((g_s == param->service) && (port == myhtons(param->sins.sin_port))) || 
+		if (((g_s == param->service) && (port == myhtons(*SAPORT(&param->sinsr)))) || 
 			( ((starttrafcorrect->type == UDP) && 
 				((param->operation == UDPASSOC)||
 				 (param->operation == DNSRESOLVE)||
@@ -201,28 +210,47 @@ void mylogfunc(struct clientparam * param, const unsigned char * pz) {
 				/* ôèëüòð ïîäîø¸ë. ìîæíî èçìåíÿòü çíà÷åíèå òðàôôèêà
 				   äîìíîæàåì íà ÷èñëî */
 				if (starttrafcorrect->type == MULTIPLAY) {
+#ifndef NOPSTDINT
+					param->statssrv64 = (unsigned)((double)param->statssrv64 *starttrafcorrect->coeff);
+					param->statscli64 = (unsigned)((double)param->statscli64 * starttrafcorrect->coeff);
+#else
 					param->statssrv = (unsigned)((double)param->statssrv *starttrafcorrect->coeff);
 					param->statscli = (unsigned)((double)param->statscli * starttrafcorrect->coeff);
+#endif
 				}
 				/* ñ ó÷¸òîì ïàêåòîâ */
 				if (starttrafcorrect->type == IPCORRECT) {
 					if (starttrafcorrect->con_type == TCP) {
+#ifndef NOPSTDINT
+						param->statssrv64+=(param->nreads + 3*param->nconnects)*starttrafcorrect->psize;
+						param->statscli64+=(param->nwrites + 3*param->nconnects)*starttrafcorrect->psize;
+#else
 						param->statssrv+=(param->nreads + 3*param->nconnects)*starttrafcorrect->psize;
 						param->statscli+=(param->nwrites + 3*param->nconnects)*starttrafcorrect->psize;
+#endif
 					} else {
+#ifndef NOPSTDINT
+						param->statssrv64+=param->nreads*starttrafcorrect->psize;
+						param->statscli64+=param->nwrites*starttrafcorrect->psize; 
+#else
 						param->statssrv+=param->nreads*starttrafcorrect->psize;
 						param->statscli+=param->nwrites*starttrafcorrect->psize; 
+#endif
 					}
 				}
 				if (DBGLEVEL == 1) {
-					fprintf(stdout, "Port=%hd; Before: srv=%d, cli=%d; After:  srv=%ld, cli=%ld; nreads=%ld; nwrites=%ld; Rule=%d\n",myhtons(param->sins.sin_port), statssrv_before, statscli_before, param->statssrv, param->statscli,param->nreads,param->nwrites,rule);
+#ifndef NOPSTDINT
+					fprintf(stdout, "Port=%hd; Before: srv=%"PRINTF_INT64_MODIFIER"d, cli=%"PRINTF_INT64_MODIFIER"d; After:  srv=%"PRINTF_INT64_MODIFIER"d, cli=%"PRINTF_INT64_MODIFIER"d; nreads=%ld; nwrites=%ld; Rule=%d\n",myhtons(*SAPORT(&param->sinsr)), statssrv_before, statscli_before, param->statssrv64, param->statscli64,param->nreads,param->nwrites,rule);
+#else
+					fprintf(stdout, "Port=%hd; Before: srv=%lu, cli=%lu; After:  srv=%lu, cli=%lu; nreads=%ld; nwrites=%ld; Rule=%d\n",myhtons(param->sins.sin_port), statssrv_before, statscli_before, param->statssrv, param->statscli,param->nreads,param->nwrites,rule);
+#endif
 				}
 				ok = 1;
 				break;
 		}
 	}
 	if ((!ok) && (DBGLEVEL == 1)) {
-		fprintf(stdout, "No rules specifed: service=%d, port=%d, operation=%d", param->service, param->sins.sin_port,param->operation);
+		fprintf(stdout, "No rules specifed: service=%d, port=%d, operation=%d", param->service, *SAPORT(&param->sinsr),param->operation);
 	}
 	origlogfunc(param, pz);
 }

+ 0 - 1
src/plugins/TransparentPlugin/transparent_plugin.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: transparent_plugin.c,v 1.9 2010-11-11 11:32:33 v.dubrovin Exp $
 */
 
 #include <sys/utsname.h>

+ 0 - 1
src/plugins/WindowsAuthentication/WindowsAuthentication.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: WindowsAuthentication.c,v 1.12 2011-04-12 13:05:58 v.dubrovin Exp $
 */
 
 #include "../../structures.h"

+ 0 - 1
src/plugins/utf8tocp1251/utf8tocp1251.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: utf8tocp1251.c,v 1.9 2009/09/03 05:32:56 v.dubrovin Exp $
 */
 
 #include "../../structures.h"

+ 2 - 3
src/pop3p.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: pop3p.c,v 1.17 2008/01/08 21:46:38 vlad Exp $
 */
 
 #include "proxy.h"
@@ -43,13 +42,13 @@ void * pop3pchild(struct clientparam* param) {
 	socksend(param->remsock, param->extusername, (int)strlen((char *)param->extusername), conf.timeouts[STRING_S]) <= 0 ||
 	socksend(param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2)
 		{RETURN(623);}
- param->statscli += (int)(strlen((char *)param->extusername) + 7);
+ param->statscli64 += (uint64_t)(strlen((char *)param->extusername) + 7);
  param->nwrites++;
  RETURN (sockmap(param, 180));
 CLEANRET:
 
  if(param->hostname&&param->extusername) {
-	sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(param->sins.sin_port)==110)?0:':', ntohs(param->sins.sin_port));
+	sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (*SAPORT(&param->sinsr)==110)?0:':', ntohs(*SAPORT(&param->sinsr)));
 	 (*param->srv->logfunc)(param, buf);
  }
  else (*param->srv->logfunc)(param, NULL);

+ 67 - 72
src/proxy.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: proxy.c,v 1.107 2014-04-07 20:35:07 vlad Exp $
 */
 
 
@@ -132,8 +131,9 @@ char * proxy_stringtable[] = {
 	NULL
 };
 
+#define BUFSIZE 8192
 #define LINESIZE 4096
-#define BUFSIZE (LINESIZE*2)
+#define FTPBUFSIZE 1536
 
 static void logurl(struct clientparam * param, char * buf, char * req, int ftp){
  char *sb;
@@ -217,7 +217,7 @@ void * proxychild(struct clientparam* param) {
  unsigned char *ftpbase=NULL;
  unsigned char username[1024];
  int keepalive = 0;
- unsigned long contentlength = 0;
+ uint64_t contentlength64 = 0;
  int hascontent =0;
  int isconnect = 0;
  int redirect = 0;
@@ -229,7 +229,8 @@ void * proxychild(struct clientparam* param) {
  int authenticate;
  struct pollfd fds[2];
  SOCKET ftps;
- SASIZETYPE sasize;
+ char ftpbuf[FTPBUFSIZE];
+ int inftpbuf = 0;
 #ifndef WITHMAIN
  FILTER_ACTION action;
 #endif
@@ -241,7 +242,7 @@ void * proxychild(struct clientparam* param) {
  bufsize = BUFSIZE;
  anonymous = param->srv->singlepacket;
 for(;;){
- memset(buf, 0, BUFSIZE);
+ memset(buf, 0, bufsize);
  inbuf = 0;
 
 
@@ -260,8 +261,6 @@ for(;;){
 		ckeepalive = 0;
 		so._shutdown(param->remsock, SHUT_RDWR);
 		so._closesocket(param->remsock);
-		param->sins.sin_addr.s_addr = 0;
-		param->sins.sin_port = 0;
 		param->remsock = INVALID_SOCKET;
 		param->redirected = 0;
 		param->redirtype = 0;
@@ -282,8 +281,6 @@ for(;;){
 			so._shutdown(param->remsock, SHUT_RDWR);
 			so._closesocket(param->remsock);
 		}
-		param->sins.sin_addr.s_addr = 0;
-		param->sins.sin_port = 0;
 		param->remsock = INVALID_SOCKET;
 		param->redirected = 0;
 		param->redirtype = 0;
@@ -388,14 +385,14 @@ for(;;){
 				while( (i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, '\n', conf.timeouts[STRING_S])) > 2){
 					if(i> 15 && (!strncasecmp((char *)(buf), "content-length", 14))){
 						buf[i]=0;
-						sscanf((char *)buf + 15, "%lu", &contentlength);
+						sscanf((char *)buf + 15, "%"PRINTF_INT64_MODIFIER"u", &contentlength64);
 					}
 				}
-				while( contentlength > 0 && (i = sockgetlinebuf(param, CLIENT, buf, (BUFSIZE < contentlength)? BUFSIZE - 1:contentlength, '\n', conf.timeouts[STRING_S])) > 0){
-					if ((unsigned long)i > contentlength) break;
-					contentlength-=i;
+				while( contentlength64 > 0 && (i = sockgetlinebuf(param, CLIENT, buf, (BUFSIZE < contentlength64)? BUFSIZE - 1:(int)contentlength64, '\n', conf.timeouts[STRING_S])) > 0){
+					if ((uint64_t)i > contentlength64) break;
+					contentlength64-=i;
 				}
-				contentlength = 0;
+				contentlength64 = 0;
 				if(param->password)myfree(param->password);
 				param->password = myalloc(32);
 				param->pwtype = 2;
@@ -492,15 +489,15 @@ for(;;){
 		if(!sb)continue;
 		++sb;
 		while(isspace(*sb))sb++;
-		sscanf(sb, "%lu",&contentlength);
-		if(param->maxtrafout && (param->maxtrafout < param->statscli || (unsigned)contentlength > param->maxtrafout - param->statscli)){
+		sscanf(sb, "%"PRINTF_INT64_MODIFIER"u",&contentlength64);
+		if(param->maxtrafout64 && (param->maxtrafout64 < param->statscli64 || contentlength64 > param->maxtrafout64 - param->statscli64)){
 			RETURN(10);
 		}
-		if(param->ndatfilterscli > 0 && contentlength > 0) continue;
+		if(param->ndatfilterscli > 0 && contentlength64 > 0) continue;
 	}
 	inbuf += i;
 	if((bufsize - inbuf) < LINESIZE){
-		if (bufsize > 20000){
+		if (bufsize > (LINESIZE * 16)){
 			RETURN (516);
 		}
 		if(!(newbuf = myrealloc(buf, bufsize + BUFSIZE))){RETURN (21);}
@@ -527,48 +524,35 @@ for(;;){
 	RETURN(0);
  }
  if(action != PASS) RETURN(517);
- if(param->ndatfilterscli > 0 && contentlength > 0){
-  unsigned long newlen;
-  newlen = sockfillbuffcli(param, contentlength, CONNECTION_S);
-  if(newlen == contentlength) {
+ if(param->ndatfilterscli > 0 && contentlength64 > 0){
+  uint64_t newlen64;
+  newlen64 = sockfillbuffcli(param, (unsigned long)contentlength64, CONNECTION_S);
+  if(newlen64 == contentlength64) {
 	action = handledatfltcli(param,  &param->clibuf, &param->clibufsize, 0, &param->cliinbuf);
 	if(action == HANDLED){
 		RETURN(0);
 	}
 	if(action != PASS) RETURN(517);
-	contentlength = param->cliinbuf;
+	contentlength64 = param->cliinbuf;
 	param->ndatfilterscli = 0;
   }
-  sprintf((char*)buf+strlen((char *)buf), "Content-Length: %lu\r\n", contentlength);
+  sprintf((char*)buf+strlen((char *)buf), "Content-Length: %"PRINTF_INT64_MODIFIER"u\r\n", contentlength64);
  }
 
 #endif
 
  if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
- if (param->sins.sin_addr.s_addr == param->srv->intip && param->sins.sin_port == param->srv->intport) {
-	RETURN(519);
- }
- sasize = sizeof(struct sockaddr_in);
- if(so._getpeername(param->remsock, (struct sockaddr *)&param->sins, &sasize)){
-	RETURN(520);
- }
-#define FTPBUFSIZE 1536
 
  if(ftp && param->redirtype != R_HTTP){
 	SOCKET s;
 	int mode = 0;
 	int i=0;
-	char ftpbuf[FTPBUFSIZE];
-	int inftpbuf = 0;
 
+	inftpbuf = 0;
 	if(!ckeepalive){
 		inftpbuf = FTPBUFSIZE - 20;
 		res = ftplogin(param, ftpbuf, &inftpbuf);
 		if(res){
-			if (res == 700 || res == 701){
-				socksend(param->clisock, (unsigned char *)proxy_stringtable[16], (int)strlen(proxy_stringtable[16]), conf.timeouts[STRING_S]);
-				socksend(param->clisock, (unsigned char *)ftpbuf, inftpbuf, conf.timeouts[STRING_S]);
-			}
 			RETURN(res);
 		}
 	}
@@ -619,7 +603,7 @@ for(;;){
 		socksend(param->clisock, (unsigned char *)proxy_stringtable[8], (int)strlen(proxy_stringtable[8]), conf.timeouts[STRING_S]);
 		s = param->remsock;
 		param->remsock = ftps;
-		if((param->operation == FTP_PUT) && (contentlength > 0)) param->waitclient = contentlength;
+		if((param->operation == FTP_PUT) && (contentlength64 > 0)) param->waitclient64 = contentlength64;
 		res = sockmap(param, conf.timeouts[CONNECTION_L]);
 		if (res == 99) res = 0;
 		so._closesocket(ftps);
@@ -821,23 +805,31 @@ for(;;){
 	 if(socksend(param->remsock, req , (res = (int)strlen((char *)req)), conf.timeouts[STRING_L]) != res) {
 		RETURN(518);
 	 }
-	 param->statscli += res;
+	 param->statscli64 += res;
 	 param->nwrites++;
  }
  inbuf = 0;
 #ifndef ANONYMOUS
- if(anonymous!=1){
+ if(!anonymous){
+		int len = strlen((char *)buf);
+		len += sprintf((char*)buf + len, "Forwarded: for=");
+		if(*SAFAMILY(&param->sincr) == AF_INET6) len += sprintf((char*)buf + len, "\"[");
+		len += myinet_ntop(*SAFAMILY(&param->sincr), SAADDR(&param->sincr), (char *)buf + len, 128);
+		if(*SAFAMILY(&param->sincr) == AF_INET6) len += sprintf((char*)buf + len, "]:%d\";by=", (int)ntohs(*SAPORT(&param->sincr)));
+		else len += sprintf((char*)buf + len, ":%d;by=", (int)ntohs(*SAPORT(&param->sincr)));
+		gethostname((char *)(buf + len), 256);
+		sprintf((char*)buf+strlen((char *)buf), ":%d\r\n", (int)ntohs(*SAPORT(&param->sincl)));
+ }
+ else if(anonymous>1){
 		sprintf((char*)buf+strlen((char *)buf), "Via: 1.1 ");
 		gethostname((char *)(buf+strlen((char *)buf)), 256);
-		sprintf((char*)buf+strlen((char *)buf), ":%d (%s %s)\r\nX-Forwarded-For: ", (int)ntohs(param->srv->intport), conf.stringtable?conf.stringtable[2]:(unsigned char *)"", conf.stringtable?conf.stringtable[3]:(unsigned char *)"");
-		if(!anonymous)myinet_ntoa(param->sinc.sin_addr, (char *)buf + strlen((char *)buf));
+		sprintf((char*)buf+strlen((char *)buf), ":%d (%s %s)\r\nX-Forwarded-For: ", (int)ntohs(*SAPORT(&param->srv->intsa)), conf.stringtable?conf.stringtable[2]:(unsigned char *)"", conf.stringtable?conf.stringtable[3]:(unsigned char *)"");
+		if(anonymous != 2)myinet_ntop(*SAFAMILY(&param->sincr), SAADDR(&param->sincr), (char *)buf + strlen((char *)buf), 128);
 		else {
 			unsigned long tmp;
 
-			tmp = param->sinc.sin_addr.s_addr;
-			param->sinc.sin_addr.s_addr = ((unsigned long)myrand(param, sizeof(struct clientparam))<<16)^(unsigned long)rand();
-			myinet_ntoa(param->sinc.sin_addr, (char *)buf + strlen((char *)buf));
-			param->sinc.sin_addr.s_addr = tmp;
+			tmp = ((unsigned long)myrand(param, sizeof(struct clientparam))<<16)^(unsigned long)rand();
+			myinet_ntop(AF_INET, &tmp, (char *)buf + strlen((char *)buf), 64);
 		}
 		sprintf((char*)buf+strlen((char *)buf), "\r\n");
  }
@@ -845,7 +837,7 @@ for(;;){
  if(keepalive <= 1) sprintf((char*)buf+strlen((char *)buf), "%s: %s\r\n", (param->redirtype == R_HTTP)?"Proxy-Connection":"Connection", keepalive? "keep-alive":"close");
  if(param->extusername){
 	sprintf((char*)buf + strlen((char *)buf), "%s: basic ", (redirect)?"Proxy-Authorization":"Authorization");
-	sprintf((char*)username, "%.32s:%.64s", param->extusername, param->extpassword?param->extpassword:(unsigned char*)"");
+	sprintf((char*)username, "%.128s:%.64s", param->extusername, param->extpassword?param->extpassword:(unsigned char*)"");
 	en64(username, buf+strlen((char *)buf), (int)strlen((char *)username));
 	sprintf((char*)buf + strlen((char *)buf), "\r\n");
  }
@@ -853,21 +845,21 @@ for(;;){
  if ((res = socksend(param->remsock, buf+reqlen, (int)strlen((char *)buf+reqlen), conf.timeouts[STRING_S])) != (int)strlen((char *)buf+reqlen)) {
 	RETURN(518);
  }
- param->statscli += res;
+ param->statscli64 += res;
  param->nwrites++;
  if(param->bandlimfunc) {
 	sleeptime = param->bandlimfunc(param, 0, (int)strlen((char *)buf));
  }
- if(contentlength > 0){
+ if(contentlength64 > 0){
 	 param->nolongdatfilter = 0;
-	 param->waitclient = contentlength;
+	 param->waitclient64 = contentlength64;
 	 res = sockmap(param, conf.timeouts[CONNECTION_S]);
-	 param->waitclient = 0;
+	 param->waitclient64 = 0;
 	 if(res != 99) {
 		RETURN(res);
 	}
  }
- contentlength = 0;
+ contentlength64 = 0;
  inbuf = 0;
  ckeepalive = keepalive;
  res = 0; 
@@ -900,13 +892,13 @@ for(;;){
 		if(!sb)continue;
 		++sb;
 		while(isspace(*sb))sb++;
-		sscanf(sb, "%lu", &contentlength);
+		sscanf(sb, "%"PRINTF_INT64_MODIFIER"u", &contentlength64);
 		hascontent = 1;
 		if(param->unsafefilter && param->ndatfilterssrv > 0) {
 			hascontent = 2;
 			continue;
 		}
-		if(param->maxtrafin && (param->maxtrafin < param->statssrv || (unsigned)contentlength > param->maxtrafin - param->statssrv)){
+		if(param->maxtrafin64 && (param->maxtrafin64 < param->statssrv64 || contentlength64 + param->statssrv64 > param->maxtrafin64)){
 			RETURN(10);
 		}
 	}
@@ -935,7 +927,7 @@ for(;;){
  }
  if((res == 304 || res == 204) && !hascontent){
 	hascontent = 1;
-	contentlength = 0;
+	contentlength64 = 0;
  }
  if(param->bandlimfunc) {
 	int st1;
@@ -959,25 +951,25 @@ for(;;){
  param->nolongdatfilter = 0;
 
  
- if (conf.filtermaxsize && contentlength > (unsigned long)conf.filtermaxsize) {
+ if (conf.filtermaxsize && contentlength64 > (uint64_t)conf.filtermaxsize) {
 	param->nolongdatfilter = 1;
  }
- else if(param->unsafefilter && param->ndatfilterssrv > 0 && contentlength > 0 && param->operation != HTTP_HEAD && res != 204 && res != 304){
-  unsigned long newlen;
-  newlen = sockfillbuffsrv(param, (unsigned long) contentlength, CONNECTION_S);
-  if(newlen == contentlength) {
+ else if(param->unsafefilter && param->ndatfilterssrv > 0 && contentlength64 > 0 && param->operation != HTTP_HEAD && res != 204 && res != 304){
+  uint64_t newlen;
+  newlen = (uint64_t)sockfillbuffsrv(param, (unsigned long) contentlength64, CONNECTION_S);
+  if(newlen == contentlength64) {
 	action = handledatfltsrv(param,  &param->srvbuf, &param->srvbufsize, 0, &param->srvinbuf);
 	param->nolongdatfilter = 1;
 	if(action == HANDLED){
 		RETURN(0);
 	}
 	if(action != PASS) RETURN(517);
-	contentlength = param->srvinbuf;
-	sprintf((char*)buf+strlen((char *)buf), "Content-Length: %lu\r\n", contentlength);
+	contentlength64 = param->srvinbuf;
+	sprintf((char*)buf+strlen((char *)buf), "Content-Length: %"PRINTF_INT64_MODIFIER"u\r\n", contentlength64);
 	hascontent = 1;
   }
  }
- if (contentlength > 0 && hascontent != 1) ckeepalive = 0;
+ if (contentlength64 > 0 && hascontent != 1) ckeepalive = 0;
 #else
 #endif
  if(!isconnect || param->operation){
@@ -996,7 +988,7 @@ for(;;){
 		RETURN(521);
 	 }
  }
- if((param->chunked || contentlength > 0) && param->operation != HTTP_HEAD && res != 204 && res != 304) {
+ if((param->chunked || contentlength64 > 0) && param->operation != HTTP_HEAD && res != 204 && res != 304) {
  	do {
 		if(param->chunked){
 			char smallbuf[32];
@@ -1021,18 +1013,18 @@ for(;;){
 				break;
 			}
 			smallbuf[i] = 0;
-			contentlength = 0;
-			sscanf(smallbuf, "%lx", &contentlength);
-			if(contentlength == 0) {
+			contentlength64 = 0;
+			sscanf(smallbuf, "%"PRINTF_INT64_MODIFIER"x", &contentlength64);
+			if(contentlength64 == 0) {
 				param->chunked = 2;
 			}
 		}
 		if(param->chunked != 2){
-			param->waitserver = contentlength;
+			param->waitserver64 = contentlength64;
 		 	if((res = sockmap(param, conf.timeouts[CONNECTION_S])) != 98){
 				RETURN(res);
 			}
-	 		param->waitserver = 0;
+	 		param->waitserver64 = 0;
 		}
         } while(param->chunked);
  }
@@ -1045,8 +1037,7 @@ for(;;){
  else if(!hascontent && !param->chunked) {
 	RETURN(sockmap(param, conf.timeouts[CONNECTION_S]));
  }
- contentlength = 0;
-
+ contentlength64 = 0;
 REQUESTEND:
 
  if((!ckeepalive || !keepalive) && param->remsock != INVALID_SOCKET){
@@ -1068,6 +1059,10 @@ CLEANRET:
 	if(param->res == 10) {
 		socksend(param->clisock, (unsigned char *)proxy_stringtable[2], (int)strlen(proxy_stringtable[2]), conf.timeouts[STRING_S]);
 	}
+	else if (res == 700 || res == 701){
+		socksend(param->clisock, (unsigned char *)proxy_stringtable[16], (int)strlen(proxy_stringtable[16]), conf.timeouts[STRING_S]);
+		socksend(param->clisock, (unsigned char *)ftpbuf, inftpbuf, conf.timeouts[STRING_S]);
+	}
 	else if(param->res == 100 || (param->res >10 && param->res < 20) || (param->res >701 && param->res <= 705)) {
 		socksend(param->clisock, (unsigned char *)proxy_stringtable[1], (int)strlen(proxy_stringtable[1]), conf.timeouts[STRING_S]);
 	}

+ 27 - 20
src/proxy.h

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: proxy.h,v 1.92 2012-04-11 23:01:20 vlad Exp $
 */
 
 #define COPYRIGHT "(c)2000-2009 3APA3A, Vladimir Dubrovin & 3proxy.ru\n"\
@@ -42,7 +41,7 @@
 #define NOCOUNTOUT	8
 
 #define UDPBUFSIZE 16384
-#define TCPBUFSIZE  4096
+#define TCPBUFSIZE  8192
 
 
 #ifdef _WIN32
@@ -59,13 +58,13 @@
 #ifndef FD_SETSIZE
 #define FD_SETSIZE 4096
 #endif
-#include <errno.h>
 #include <signal.h>
 #include <sys/uio.h>
 #include <sys/time.h>
 #include <unistd.h>
 #include <pthread.h>
 #include <syslog.h>
+#include <errno.h>
 #endif
 
 #ifdef __CYGWIN__
@@ -78,7 +77,13 @@
 #undef errno
 #endif
 #define errno WSAGetLastError()
+#ifdef EAGAIN
+#undef EAGAIN
+#endif
 #define EAGAIN WSAEWOULDBLOCK
+#ifdef EINTR
+#undef EINTR
+#endif
 #define EINTR WSAEWOULDBLOCK
 #define SLEEPTIME 1
 #define usleep Sleep
@@ -148,8 +153,8 @@ extern struct extparam conf;
 
 int sockmap(struct clientparam * param, int timeo);
 int socksend(SOCKET sock, unsigned char * buf, int bufsize, int to);
-int socksendto(SOCKET sock, struct sockaddr_in * sin, unsigned char * buf, int bufsize, int to);
-int sockrecvfrom(SOCKET sock, struct sockaddr_in * sin, unsigned char * buf, int bufsize, int to);
+int socksendto(SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to);
+int sockrecvfrom(SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to);
 
 
 int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec);
@@ -174,7 +179,6 @@ int init_sql(char * s);
 void close_sql();
 #endif
 int doconnect(struct clientparam * param);
-int nbnameauth(struct clientparam * param);
 int alwaysauth(struct clientparam * param);
 int ipauth(struct clientparam * param);
 int doauth(struct clientparam * param);
@@ -184,13 +188,14 @@ unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nb
 
 
 int scanaddr(const unsigned char *s, unsigned long * ip, unsigned long * mask);
-int myinet_ntoa(struct in_addr in, char * buf);
-extern unsigned long nservers[MAXNSERVERS];
-extern unsigned long authnserver;
+int myinet_ntop(int af, void *src, char *dst, socklen_t size);
+extern struct nserver nservers[MAXNSERVERS];
+struct nserver authnserver;
 unsigned long getip(unsigned char *name);
-unsigned long myresolver(unsigned char *);
-unsigned long fakeresolver (unsigned char *name);
-int initdnshashtable(unsigned nhashsize);
+unsigned long getip46(int family, unsigned char *name,  struct sockaddr *sa);
+unsigned long myresolver(int, unsigned char *, unsigned char *);
+unsigned long fakeresolver (int, unsigned char *, unsigned char*);
+int inithashtable(struct hashtable *hashtable, unsigned nhashsize);
 void freeparam(struct clientparam * param);
 void clearstat(struct clientparam * param);
 void dumpcounters(struct trafcount *tl, int counterd);
@@ -228,17 +233,20 @@ void mschap(const unsigned char *win_password,
 		 const unsigned char *challenge, unsigned char *response);
 
 struct hashtable;
-void hashadd(struct hashtable *ht, const unsigned char* name, unsigned long value, time_t expires);
+void hashadd(struct hashtable *ht, const unsigned char* name, unsigned char* value, time_t expires);
 
+void parsehost(int family, char *host, struct sockaddr *sa);
 int parsehostname(char *hostname, struct clientparam *param, unsigned short port);
 int parseusername(char *username, struct clientparam *param, int extpasswd);
 int parseconnusername(char *username, struct clientparam *param, int extpasswd, unsigned short port);
 int ACLmatches(struct ace* acentry, struct clientparam * param);
+int checkACL(struct clientparam * param);
 
-unsigned long udpresolve(unsigned char * name, unsigned *retttl, struct clientparam* param, int makeauth);
+unsigned long udpresolve(int af, unsigned char * name, unsigned char * value, unsigned *retttl, struct clientparam* param, int makeauth);
 
 struct ace * copyacl (struct ace *ac);
 struct auth * copyauth (struct auth *);
+void * itfree(void *data, void * retval);
 void freeacl(struct ace *ac);
 void freeauth(struct auth *);
 void freefilter(struct filter *filter);
@@ -258,6 +266,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param);
 void srvinit2(struct srvparam * srv, struct clientparam *param);
 void srvfree(struct srvparam * srv);
 unsigned char * dologname (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t);
+int readconfig(FILE * fp);
 
 
 int myrand(void * entropy, int len);
@@ -300,16 +309,14 @@ struct datatype;
 struct dictionary;
 struct node;
 struct property;
-
+extern unsigned char tmpbuf[8192];
+extern pthread_mutex_t config_mutex;
 extern pthread_mutex_t bandlim_mutex;
 extern pthread_mutex_t hash_mutex;
 extern pthread_mutex_t tc_mutex;
 extern pthread_mutex_t pwl_mutex;
-#ifndef NOODBC
-extern pthread_mutex_t odbc_mutex;
-#endif
-
-extern struct hashtable dns_table;
+extern pthread_mutex_t log_mutex;
+extern int logmutexinit;
 
 extern struct datatype datatypes[64];
 

+ 257 - 192
src/proxymain.c

@@ -4,14 +4,60 @@
 
    please read License Agreement
 
-   $Id: proxymain.c,v 1.85 2012-04-15 22:46:09 vlad Exp $
 */
 
 #include "proxy.h"
 
 
-
-
+#define param ((struct clientparam *) p)
+#ifdef _WIN32
+DWORD WINAPI threadfunc(LPVOID p) {
+#else
+void * threadfunc (void *p) {
+#endif
+ int i = 0;
+ if(param->srv->cbsock != INVALID_SOCKET){
+	SASIZETYPE size = sizeof(param->sinsr);
+	for(i=0; i<3; i++){
+		param->remsock = so._accept(param->srv->cbsock, (struct sockaddr*)&param->sinsr, &size);
+		if(param->remsock == INVALID_SOCKET) {
+			param->res = 13;
+			param->srv->logfunc(param, "Connect back accept() failed");
+			continue;
+		}
+#ifndef WITHMAIN
+		memcpy(&param->req, &param->sinsr, size);
+		if(param->srv->acl) param->res = checkACL(param);
+		if(param->res){
+			param->srv->logfunc(param, "Connect back ACL failed");
+			so._closesocket(param->remsock);
+			param->remsock = INVALID_SOCKET;
+			continue;
+		}
+#endif
+		if(so._sendto(param->remsock, "C", 1, 0, (struct sockaddr*)&param->sinsr, size) != 1){
+			param->srv->logfunc(param, "Connect back sending command failed");
+			so._closesocket(param->remsock);
+			param->remsock = INVALID_SOCKET;
+			continue;
+		}
+	
+		break;
+	}
+ }
+ if(i == 3){
+	freeparam(param);
+ }
+ else {
+	((struct clientparam *) p)->srv->pf((struct clientparam *)p);
+ }
+#ifdef _WIN32
+ return 0;
+#else
+ return NULL;
+#endif
+}
+#undef param
 
 
 
@@ -43,7 +89,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 
 
 
- SOCKET sock = INVALID_SOCKET;
+ SOCKET sock = INVALID_SOCKET, new_sock = INVALID_SOCKET;
  int i=0;
  SASIZETYPE size;
  pthread_t thread;
@@ -54,8 +100,15 @@ int MODULEMAINFUNC (int argc, char** argv){
  unsigned sleeptime;
  unsigned char buf[256];
  char *hostname=NULL;
- int opt = 1, isudp;
+ int opt = 1, isudp = 0, iscbl = 0, iscbc = 0;
+ unsigned char *cbc_string = NULL, *cbl_string = NULL;
+#ifndef NOIPV6
+ struct sockaddr_in6 cbsa;
+#else
+ struct sockaddr_in cbsa;
+#endif
  FILE *fp = NULL;
+ struct linger lg;
  int nlog = 5000;
  char loghelp[] =
 #ifdef STDMAIN
@@ -73,7 +126,13 @@ int MODULEMAINFUNC (int argc, char** argv){
 	" -bBUFSIZE size of network buffer (default 4096 for TCP, 16384 for UDP)\n"
 	" -t be silent (do not log service start/stop)\n"
 	" -iIP ip address or internal interface (clients are expected to connect)\n"
-	" -eIP ip address or external interface (outgoing connection will have this)\n";
+	" -eIP ip address or external interface (outgoing connection will have this)\n"
+	" -rIP:PORT Use IP:port for connect back proxy instead of listen port\n"
+	" -RPORT Use PORT to listen connect back proxy connection to pass data to\n"
+	" -4 Use IPv4 for outgoing connections\n"
+	" -6 Use IPv6 for outgoing connections\n"
+	" -46 Prefer IPv4 for outgoing connections, use both IPv4 and IPv6\n"
+	" -64 Prefer IPv6 for outgoing connections, use both IPv4 and IPv6\n";
 
 #ifdef _WIN32
  unsigned long ul = 1;
@@ -82,8 +141,6 @@ int MODULEMAINFUNC (int argc, char** argv){
  int inetd = 0;
 #endif
 #endif
- SOCKET new_sock = INVALID_SOCKET;
- struct linger lg;
 #ifdef _WIN32
  HANDLE h;
 #endif
@@ -116,7 +173,7 @@ int MODULEMAINFUNC (int argc, char** argv){
  signal(SIGPIPE, SIG_IGN);
 
  pthread_attr_init(&pa);
- pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + 16384);
+ pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + 8192);
  pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
 #endif
 #endif
@@ -150,7 +207,8 @@ int MODULEMAINFUNC (int argc, char** argv){
 			break;
 		 case 'l':
 			srv.logfunc = logstdout;
-			srv.logtarget = (unsigned char*)argv[i] + 2;
+			if(srv.logtarget) myfree(srv.logtarget);
+			srv.logtarget = mystrdup((unsigned char*)argv[i] + 2);
 			if(argv[i][2]) {
 				if(argv[i][2]=='@'){
 
@@ -173,13 +231,25 @@ int MODULEMAINFUNC (int argc, char** argv){
 			}
 			break;
 		 case 'i':
-			srv.intip = getip((unsigned char *)argv[i]+2);
+			getip46(46, argv[i]+2, (struct sockaddr *)&srv.intsa);
 			break;
 		 case 'e':
-			srv.extip = getip((unsigned char *)argv[i]+2);
+			{
+#ifndef NOIPV6
+				struct sockaddr_in6 sa6;
+				error = !getip46(46, argv[i]+2, (struct sockaddr *)&sa6);
+				if(!error) memcpy((*SAFAMILY(&sa6)==AF_INET)?(void *)&srv.extsa:(void *)&srv.extsa6, &sa6, SASIZE(&sa6)); 
+#else
+				error = !getip46(46, argv[i]+2, (struct sockaddr *)&srv.extsa);
+#endif
+			}
 			break;
 		 case 'p':
-			srv.intport = htons(atoi(argv[i]+2));
+			*SAPORT(&srv.intsa) = htons(atoi(argv[i]+2));
+			break;
+		 case '4':
+		 case '6':
+			srv.family = atoi(argv[i]+1);
 			break;
 		 case 'b':
 			srv.bufsize = atoi(argv[i]+2);
@@ -190,16 +260,17 @@ int MODULEMAINFUNC (int argc, char** argv){
 #ifdef STDMAIN
 #ifndef _WIN32
 		 case 'I':
-			size = sizeof(defparam.sinc);
-			if(so._getsockname(0, (struct sockaddr*)&defparam.sinc, &size) ||
-				defparam.sinc.sin_family != AF_INET) error = 1;
+			size = sizeof(defparam.sincl);
+			if(so._getsockname(0, (struct sockaddr*)&defparam.sincl, &size) ||
+				SAFAMILY(&defparam.sincl) != AF_INET) error = 1;
 
 			else inetd = 1;
 			break;
 #endif
 #endif
 		 case 'f':
-			srv.logformat = (unsigned char *)argv[i] + 2;
+			if(srv.logformat)myfree(srv.logformat);
+			srv.logformat = mystrdup((unsigned char *)argv[i] + 2);
 			break;
 		 case 't':
 			srv.silent = 1;
@@ -207,6 +278,14 @@ int MODULEMAINFUNC (int argc, char** argv){
 		 case 'h':
 			hostname = argv[i] + 2;
 			break;
+		 case 'r':
+			cbc_string = mystrdup(argv[i] + 2);
+			iscbc = 1;
+			break;
+		 case 'R':
+			cbl_string = mystrdup(argv[i] + 2);
+			iscbl = 1;
+			break;
 		 case 'u':
 			srv.nouser = 1;
 			break;
@@ -240,6 +319,8 @@ int MODULEMAINFUNC (int argc, char** argv){
 			"Available options are:\n"
 			"%s"
 			" -pPORT - service port to accept connections\n"
+			" -RIP:PORT - connect back IP:PORT to listen and accept connections\n"
+			" -rIP:PORT - connect back IP:PORT to establish connect back connection\n"
 			"%s"
 			"\tExample: %s -i127.0.0.1\n\n"
 			"%s", 
@@ -259,7 +340,7 @@ int MODULEMAINFUNC (int argc, char** argv){
  else {
 #endif
 #ifndef NOPORTMAP
-	if (error || argc != i+3 || *argv[i]=='-'|| (srv.intport = htons((unsigned short)atoi(argv[i])))==0 || (srv.targetport = htons((unsigned short)atoi(argv[i+2])))==0) {
+	if (error || argc != i+3 || *argv[i]=='-'|| (*SAPORT(&srv.intsa) = htons((unsigned short)atoi(argv[i])))==0 || (srv.targetport = htons((unsigned short)atoi(argv[i+2])))==0) {
 #ifndef STDMAIN
 		haveerror = 1;
 		conf.threadinit = 0;
@@ -269,6 +350,8 @@ int MODULEMAINFUNC (int argc, char** argv){
 			" [-e<external_ip>] <port_to_bind>"
 			" <target_hostname> <target_port>\n"
 			"Available options are:\n"
+			" -RIP:PORT - connect back IP:PORT to listen and accept connections\n"
+			" -rIP:PORT - connect back IP:PORT to establish connect back connection\n"
 			"%s"
 			"%s"
 			"\tExample: %s -d -i127.0.0.1 6666 serv.somehost.ru 6666\n\n"
@@ -311,8 +394,12 @@ int MODULEMAINFUNC (int argc, char** argv){
 
  
  srvinit2(&srv, &defparam);
- if(!srv.intport) srv.intport = htons(childdef.port);
- if(!defparam.sinc.sin_port) defparam.sinc.sin_port = htons(childdef.port);
+ if(!*SAFAMILY(&srv.intsa)) *SAFAMILY(&srv.intsa) = AF_INET;
+ if(!*SAPORT(&srv.intsa)) *SAPORT(&srv.intsa) = htons(childdef.port);
+ *SAFAMILY(&srv.extsa) = AF_INET;
+#ifndef NOIPV6
+ *SAFAMILY(&srv.extsa6) = AF_INET6;
+#endif
  if(hostname)parsehostname(hostname, &defparam, childdef.port);
 
 
@@ -324,58 +411,83 @@ int MODULEMAINFUNC (int argc, char** argv){
 
 #endif
 
- if(srv.srvsock == INVALID_SOCKET){
 
-	if(!isudp){
-		lg.l_onoff = 1;
-		lg.l_linger = conf.timeouts[STRING_L];
-		sock=so._socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-	}
-	else {
-		sock=so._socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
-	}
-	if( sock == INVALID_SOCKET) {
-		perror("socket()");
-		return -2;
-	}
+
+ if (!iscbc) {
+	if(srv.srvsock == INVALID_SOCKET){
+
+		if(!isudp){
+			lg.l_onoff = 1;
+			lg.l_linger = conf.timeouts[STRING_L];
+			sock=so._socket(SASOCK(&srv.intsa), SOCK_STREAM, IPPROTO_TCP);
+		}
+		else {
+			sock=so._socket(SASOCK(&srv.intsa), SOCK_DGRAM, IPPROTO_UDP);
+		}
+		if( sock == INVALID_SOCKET) {
+			perror("socket()");
+			return -2;
+		}
 #ifdef _WIN32
-	ioctlsocket(sock, FIONBIO, &ul);
+		ioctlsocket(sock, FIONBIO, &ul);
 #else
-	fcntl(sock,F_SETFL,O_NONBLOCK);
+		fcntl(sock,F_SETFL,O_NONBLOCK);
 #endif
-	srv.srvsock = sock;
-	if(so._setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int)))perror("setsockopt()");
+		srv.srvsock = sock;
+		opt = 1;
+		if(so._setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int)))perror("setsockopt()");
 #ifdef SO_REUSEPORT
-	so._setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int));
+		opt = 1;
+		so._setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int));
 #endif
- }
+	}
+	size = sizeof(srv.intsa);
+	for(sleeptime = SLEEPTIME * 100; so._bind(sock, (struct sockaddr*)&srv.intsa, size)==-1; usleep(sleeptime)) {
+		sprintf((char *)buf, "bind(): %s", strerror(errno));
+		if(!srv.silent)(*srv.logfunc)(&defparam, buf);	
+		sleeptime = (sleeptime<<1);	
+		if(!sleeptime) {
+			so._closesocket(sock);
+			return -3;
+		}
+	}
+ 	if(!isudp){
+ 		if(so._listen (sock, 1 + (srv.maxchild>>4))==-1) {
+			sprintf((char *)buf, "listen(): %s", strerror(errno));
+			if(!srv.silent)(*srv.logfunc)(&defparam, buf);
+			return -4;
+		}
+	}
+	else 
+		defparam.clisock = sock;
 
- size = sizeof(defparam.sinc);
- for(sleeptime = SLEEPTIME * 100; so._bind(sock, (struct sockaddr*)&defparam.sinc, size)==-1; usleep(sleeptime)) {
-	sprintf((char *)buf, "bind(): %s", strerror(errno));
-	if(!srv.silent)(*srv.logfunc)(&defparam, buf);	
-	sleeptime = (sleeptime<<1);	
-	if(!sleeptime) {
-		so._closesocket(sock);
-		return -3;
+	if(!srv.silent && !iscbc){
+		sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self());
+		(*srv.logfunc)(&defparam, buf);
 	}
  }
- if(!isudp){
- 	if(so._listen (sock, 1 + (srv.maxchild>>4))==-1) {
-		sprintf((char *)buf, "listen(): %s", strerror(errno));
-		if(!srv.silent)(*srv.logfunc)(&defparam, buf);
-		return -4;
+ if(iscbl){
+	parsehost(srv.family, cbl_string, (struct sockaddr *)&cbsa);
+	if((srv.cbsock=so._socket(SASOCK(&cbsa), SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) {
+		(*srv.logfunc)(&defparam, "Failed to allocate connect back socket");
+		return -6;
 	}
- }
- else 
-	 defparam.clisock = sock;
+	opt = 1;
+	so._setsockopt(srv.cbsock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int));
+#ifdef SO_REUSEPORT
+	opt = 1;
+	so._setsockopt(srv.cbsock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int));
+#endif
 
- if(!srv.silent){
-	sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self());
-	(*srv.logfunc)(&defparam, buf);
+	if(so._bind(srv.cbsock, (struct sockaddr*)&cbsa, sizeof(cbsa))==-1) {
+		(*srv.logfunc)(&defparam, "Failed to bind connect back socket");
+		return -7;
+	}
+	if(so._listen(srv.cbsock, 1 + (srv.maxchild>>4))==-1) {
+		(*srv.logfunc)(&defparam, "Failed to listen connect back socket");
+		return -8;
+	}
  }
- defparam.sinc.sin_addr.s_addr = defparam.sins.sin_addr.s_addr = 0;
- defparam.sinc.sin_port = defparam.sins.sin_port = 0;
 
  srv.fds.fd = sock;
  srv.fds.events = POLLIN;
@@ -392,6 +504,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 			}
 			usleep(SLEEPTIME);
 		}
+		if (iscbc) break;
 		if (conf.paused != srv.version) break;
 		if (srv.fds.events & POLLIN) {
 			error = so._poll(&srv.fds, 1, 1000);
@@ -407,14 +520,43 @@ int MODULEMAINFUNC (int argc, char** argv){
 			if(!srv.silent)(*srv.logfunc)(&defparam, buf);
 			break;
 		}
-		continue;
 	}
 	if((conf.paused != srv.version) || (error < 0)) break;
 	if(!isudp){
-		size = sizeof(defparam.sinc);
-		new_sock = so._accept(sock, (struct sockaddr*)&defparam.sinc, &size);
-		if(new_sock == INVALID_SOCKET){
-			sprintf((char *)buf, "accept(): %s", strerror(errno));
+		size = sizeof(defparam.sincr);
+		if(iscbc){
+			new_sock=so._socket(SASOCK(&defparam.sincr), SOCK_STREAM, IPPROTO_TCP);
+			if(new_sock != INVALID_SOCKET){
+				parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
+				if(so._connect(new_sock,(struct sockaddr *)&defparam.sincr,sizeof(defparam.sincr))) {
+					so._closesocket(new_sock);
+					new_sock = INVALID_SOCKET;
+					usleep(SLEEPTIME);
+					continue;
+				}
+				if(so._recvfrom(new_sock,buf,1,0,(struct sockaddr*)&defparam.sincr, &size) != 1) {
+					so._closesocket(new_sock);
+					new_sock = INVALID_SOCKET;
+					usleep(SLEEPTIME);
+					continue;
+				}
+			}
+			else {
+				usleep(SLEEPTIME);
+				continue;
+			}
+		}
+		else {
+			new_sock = so._accept(sock, (struct sockaddr*)&defparam.sincr, &size);
+			if(new_sock == INVALID_SOCKET){
+				sprintf((char *)buf, "accept(): %s", strerror(errno));
+				if(!srv.silent)(*srv.logfunc)(&defparam, buf);
+				continue;
+			}
+		}
+		size = sizeof(defparam.sincl);
+		if(so._getsockname(new_sock, (struct sockaddr *)&defparam.sincl, &size)){
+			sprintf((char *)buf, "getsockname(): %s", strerror(errno));
 			if(!srv.silent)(*srv.logfunc)(&defparam, buf);
 			continue;
 		}
@@ -426,8 +568,9 @@ int MODULEMAINFUNC (int argc, char** argv){
 		so._setsockopt(new_sock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
 		so._setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (unsigned char *)&opt, sizeof(int));
 	}
-	else 
+	else {
 		srv.fds.events = 0;
+	}
 	if(! (newparam = myalloc (sizeof(defparam)))){
 		if(!isudp) so._closesocket(new_sock);
 		defparam.res = 21;
@@ -456,9 +599,9 @@ int MODULEMAINFUNC (int argc, char** argv){
 	}
 #ifdef _WIN32
 #ifndef _WINCE
-	h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, (unsigned)16384, (BEGINTHREADFUNC)srv.pf, (void *) newparam, 0, &thread);
+	h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, (unsigned)16384, threadfunc, (void *) newparam, 0, &thread);
 #else
-	h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, (unsigned)32768, (BEGINTHREADFUNC)srv.pf, (void *) newparam, 0, &thread);
+	h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, (unsigned)16384, threadfunc, (void *) newparam, 0, &thread);
 #endif
 	srv.childcount++;
 	if (h) {
@@ -472,7 +615,7 @@ int MODULEMAINFUNC (int argc, char** argv){
 	}
 #else
 
-	error = pthread_create(&thread, &pa, (PTHREADFUNC)srv.pf, (void *)newparam);
+	error = pthread_create(&thread, &pa, threadfunc, (void *)newparam);
 	srv.childcount++;
 	if(error){
 		sprintf((char *)buf, "pthread_create(): %s", strerror(error));
@@ -484,22 +627,28 @@ int MODULEMAINFUNC (int argc, char** argv){
 	}
 #endif
 	pthread_mutex_unlock(&srv.counter_mutex);
-	memset(&defparam.sinc, 0, sizeof(defparam.sinc));
+	memset(&defparam.sincl, 0, sizeof(defparam.sincl));
+	memset(&defparam.sincr, 0, sizeof(defparam.sincr));
 	if(isudp) while(!srv.fds.events)usleep(SLEEPTIME);
  }
 
  if(!srv.silent) srv.logfunc(&defparam, (unsigned char *)"Exiting thread");
  if(fp) fclose(fp);
+
  srvfree(&srv);
- if(defparam.hostname)myfree(defparam.hostname);
 
 #ifndef STDMAIN
+ pthread_mutex_lock(&config_mutex);
  if(srv.next)srv.next->prev = srv.prev;
  if(srv.prev)srv.prev->next = srv.next;
  else conf.services = srv.next;
- freeacl(srv.acl);
- freeauth(srv.authfuncs);
+ pthread_mutex_unlock(&config_mutex);
 #endif
+
+ if(defparam.hostname)myfree(defparam.hostname);
+ if(cbc_string)myfree(cbc_string);
+ if(cbl_string)myfree(cbl_string);
+
  return 0;
 }
 
@@ -509,48 +658,66 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
  memset(srv, 0, sizeof(struct srvparam));
  srv->version = conf.paused;
  srv->logfunc = conf.logfunc;
- srv->logformat = conf.logformat;
+ if(srv->logformat)myfree(srv->logformat);
+ srv->logformat = conf.logformat? mystrdup(conf.logformat) : NULL;
  srv->authfunc = conf.authfunc;
  srv->usentlm = 0;
  srv->maxchild = conf.maxchild;
  srv->time_start = time(NULL);
- srv->logtarget = conf.logtarget;
+ if(conf.logtarget){
+	 if(srv->logtarget) myfree(srv->logtarget);
+	 srv->logtarget = mystrdup(conf.logtarget);
+ }
  srv->srvsock = INVALID_SOCKET;
  srv->logdumpsrv = conf.logdumpsrv;
  srv->logdumpcli = conf.logdumpcli;
+ srv->cbsock = INVALID_SOCKET; 
  memset(param, 0, sizeof(struct clientparam));
  param->srv = srv;
  param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET;
- param->req.sin_family = param->sins.sin_family = param->sinc.sin_family = AF_INET;
+ *SAFAMILY(&param->req) = *SAFAMILY(&param->sinsl) = *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->sincr) = *SAFAMILY(&param->sincl) = AF_INET;
  pthread_mutex_init(&srv->counter_mutex, NULL);
-
+ memcpy(&srv->intsa, &conf.intsa, sizeof(srv->intsa));
+ memcpy(&srv->extsa, &conf.extsa, sizeof(srv->extsa));
+#ifndef NOIPV6
+ memcpy(&srv->extsa6, &conf.extsa6, sizeof(srv->extsa6));
+#endif
 }
 
 void srvinit2(struct srvparam * srv, struct clientparam *param){
  if(srv->logformat){
 	char *s;
 	if(*srv->logformat == '-' && (s = strchr((char *)srv->logformat + 1, '+')) && s[1]){
+		char* logformat = srv->logformat;
+
 		*s = 0;
 		srv->nonprintable = (unsigned char *)mystrdup((char *)srv->logformat + 1);
 		srv->replace = s[1];
 		srv->logformat = (unsigned char *)mystrdup(s + 2);
 		*s = '+';
+		myfree(logformat);
 	}
-	else srv->logformat = (unsigned char *)mystrdup((char *)srv->logformat);
  }
- if(srv->logtarget) srv->logtarget = (unsigned char *)mystrdup((char *)srv->logtarget);
- if(!srv->intip) srv->intip = conf.intip;
- param->sinc.sin_addr.s_addr = srv->intip;
- param->sinc.sin_port = srv->intport;
- if(!srv->extip) srv->extip = conf.extip;
- param->sins.sin_addr.s_addr = param->extip = srv->extip;
- if(!srv->extport) srv->extport = htons(conf.extport);
- param->sins.sin_port = param->extport = srv->extport;
+ memset(&param->sinsl, 0, sizeof(param->sinsl));
+ memset(&param->sinsr, 0, sizeof(param->sinsr));
+ memset(&param->req, 0, sizeof(param->req));
+ *SAFAMILY(&param->sinsl) = AF_INET;
+ *SAFAMILY(&param->sinsr) = AF_INET;
+ *SAFAMILY(&param->req) = AF_INET;
+ memcpy(&param->sincr, &srv->intsa, sizeof(param->sincr));
+ memcpy(&param->sincl, &srv->intsa, sizeof(param->sincl));
+#ifndef NOIPV6
+ memcpy(&param->sinsr, (srv->family == 6 || srv->family == 64)? (void *)&srv->extsa6: (void *)&srv->extsa, sizeof(param->sinsl));
+#else
+ memcpy(&param->sinsr, &srv->extsa, sizeof(param->sinsl));
+#endif
 }
 
 void srvfree(struct srvparam * srv){
  if(srv->srvsock != INVALID_SOCKET) so._closesocket(srv->srvsock);
  srv->srvsock = INVALID_SOCKET;
+ if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->cbsock);
+ srv->cbsock = INVALID_SOCKET;
  srv->service = S_ZOMBIE;
  while(srv->child) usleep(SLEEPTIME * 100);
 #ifndef STDMAIN
@@ -563,6 +730,9 @@ void srvfree(struct srvparam * srv){
 	}
 	myfree(srv->filter);
  }
+
+ if(srv->acl)freeacl(srv->acl);
+ if(srv->authfuncs)freeauth(srv->authfuncs);
 #endif
  pthread_mutex_destroy(&srv->counter_mutex);
  if(srv->target) myfree(srv->target);
@@ -746,18 +916,11 @@ FILTER_ACTION makefilters (struct srvparam *srv, struct clientparam *param){
 	return res;
 }
 
-static void * itfree(void *data, void * retval){
+void * itfree(void *data, void * retval){
 	myfree(data);
 	return retval;
 }
 
-void freepwl(struct passwords *pwl){
-	for(; pwl; pwl = (struct passwords *)itfree(pwl, pwl->next)){
-		if(pwl->user)myfree(pwl->user);
-		if(pwl->password)myfree(pwl->password);
-	}
-}
-
 void freeauth(struct auth * authfuncs){
 	for(; authfuncs; authfuncs = (struct auth *)itfree(authfuncs, authfuncs->next));
 }
@@ -787,104 +950,6 @@ void freeacl(struct ace *ac){
 	}
 }
 
-void freeconf(struct extparam *confp){
- struct bandlim * bl;
- struct bandlim * blout;
- struct trafcount * tc;
- struct passwords *pw;
- struct ace *acl;
- struct filemon *fm;
- int counterd, archiverc;
- unsigned char *logname, *logtarget;
- unsigned char **archiver;
- unsigned char * logformat;
-
- int i;
-
-
-
-
- pthread_mutex_lock(&tc_mutex);
- confp->trafcountfunc = NULL;
- tc = confp->trafcounter;
- confp->trafcounter = NULL;
- counterd = confp->counterd;
- confp->counterd = -1;
- pthread_mutex_unlock(&tc_mutex);
- if(tc)dumpcounters(tc,counterd);
- for(; tc; tc = (struct trafcount *) itfree(tc, tc->next)){
-	if(tc->comment)myfree(tc->comment);
-	freeacl(tc->ace);
- }
- confp->countertype = NONE;
-
-
-
- logtarget = confp->logtarget;
- confp->logtarget = NULL;
- logformat = confp->logformat;
- confp->logformat = NULL;
-
- pthread_mutex_lock(&bandlim_mutex);
- bl = confp->bandlimiter;
- blout = confp->bandlimiterout;
- confp->bandlimiter = NULL;
- confp->bandlimiterout = NULL;
- confp->bandlimfunc = NULL;
- pthread_mutex_unlock(&bandlim_mutex);
-
- logname = confp->logname;
- confp->logname = NULL;
- archiverc = confp->archiverc;
- confp->archiverc = 0;
- archiver = confp->archiver;
- confp->archiver = NULL;
- fm = confp->fmon;
- confp->fmon = NULL;
- pw = confp->pwl;
- confp->pwl = NULL;
- confp->rotate = 0;
- confp->logtype = NONE;
- confp->authfunc = ipauth;
- confp->bandlimfunc = NULL;
- confp->intip = confp->extip = 0;
- confp->intport = confp->extport = 0;
- confp->singlepacket = 0;
- confp->maxchild = 100;
- resolvfunc = NULL;
- acl = confp->acl;
- confp->acl = NULL;
- confp->logtime = confp->time = 0;
-
- usleep(SLEEPTIME);
-
- 
- freeacl(acl);
- freepwl(pw);
- for(; bl; bl = (struct bandlim *) itfree(bl, bl->next)) freeacl(bl->ace);
- for(; blout; blout = (struct bandlim *) itfree(blout, blout->next))freeacl(blout->ace);
-
- if(counterd != -1) {
-	close(counterd);
- }
- for(; fm; fm = (struct filemon *)itfree(fm, fm->next)){
-	if(fm->path) myfree(fm->path);
- }
- if(logtarget) {
-	myfree(logtarget);
- }
- if(logname) {
-	myfree(logname);
- }
- if(logformat) {
-	myfree(logformat);
- }
- if(archiver) {
-	for(i = 0; i < archiverc; i++) myfree(archiver[i]);
-	myfree(archiver);
- }
-}
-
 FILTER_ACTION handlereqfilters(struct clientparam *param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
 	FILTER_ACTION action;
 	int i;

+ 2 - 2
src/pstdint.h

@@ -191,7 +191,7 @@
  *  do nothing else.  On the Mac OS X version of gcc this is _STDINT_H_.
  */
 
-#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED)
+#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 4)) )) && !defined (_PSTDINT_H_INCLUDED)
 #include <stdint.h>
 #define _PSTDINT_H_INCLUDED
 # ifndef PRINTF_INT64_MODIFIER
@@ -797,4 +797,4 @@ int main () {
 	return EXIT_SUCCESS;
 }
 
-#endif
+#endif

+ 12 - 13
src/smtpp.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: smtpp.c,v 1.13 2011-06-10 20:48:46 vlad Exp $
 */
 
 #include "proxy.h"
@@ -83,7 +82,7 @@ int readdata (struct clientparam* param) {
 		return -1;
 	}
 #endif
-	socksendto(param->remsock, &param->sins, buf, i, conf.timeouts[STRING_S]);	
+	socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf, i, conf.timeouts[STRING_S]);	
  } 
  if(i < 1) {
 	myfree(buf);
@@ -99,7 +98,6 @@ void * smtppchild(struct clientparam* param) {
  int i=0, res;
  unsigned char buf[320];
  unsigned char username[256];
- unsigned long ul;
  char * command = NULL;
  int login = 0;
 
@@ -188,10 +186,11 @@ void * smtppchild(struct clientparam* param) {
  if( i < 3 ) {RETURN(671);}
  buf[i] = 0;
  if(strncasecmp((char *)buf, "220", 3)||!strncasecmp((char *)buf+4, "PROXY", 5)){RETURN(672);}
- ul = param->extip;
- i = sprintf(buf, "EHLO [%lu.%lu.%lu.%lu]\r\n", ((ul&0xFF000000)>>24), ((ul&0x00FF0000)>>16), ((ul&0x0000FF00)>>8), ((ul&0x000000FF)));
+ i = sprintf(buf, "EHLO [");
+ i += myinet_ntop(*SAFAMILY(&param->sinsl), SAADDR(&param->sinsl), buf+strlen(buf), 64);
+ i += sprintf(buf+strlen(buf), "]\r\n");
  if(socksend(param->remsock, buf, i, conf.timeouts[STRING_S])!= i) {RETURN(673);}
- param->statscli+=i;
+ param->statscli64+=i;
  param->nwrites++;
  login = 0;
  do {
@@ -209,26 +208,26 @@ void * smtppchild(struct clientparam* param) {
 	}
 	if ((login & 1)) {
 		socksend(param->remsock, "AUTH LOGIN\r\n", 12, conf.timeouts[STRING_S]);
-		param->statscli+=12;
+ param->statscli64+=12;
 		param->nwrites++;
 		i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
 		if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(680);}
 		en64(param->extusername, buf, (int)strlen(param->extusername));
 		socksend(param->remsock, buf, (int)strlen(buf), conf.timeouts[STRING_S]);
 		socksend(param->remsock, "\r\n", 2, conf.timeouts[STRING_S]);
-		param->statscli+=(i+2);
+ param->statscli64+=(i+2);
 		param->nwrites+=2;
 		i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
 		if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(681);}
 		en64(param->extpassword, buf, (int)strlen(param->extpassword));
 		socksend(param->remsock, buf, (int)strlen(buf), conf.timeouts[STRING_S]);
 		socksend(param->remsock, "\r\n", 2, conf.timeouts[STRING_S]);
-		param->statscli+=(i+2);
+ param->statscli64+=(i+2);
 		param->nwrites+=2;
 	}
 	else if((login & 2)){
 		socksend(param->remsock, "AUTH PLAIN\r\n", 12, conf.timeouts[STRING_S]);
-		param->statscli+=12;
+ param->statscli64+=(12);
 		param->nwrites++;
 		i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]);
 		if(i<4 || strncasecmp((char *)buf, "334", 3)) {RETURN(682);}
@@ -243,7 +242,7 @@ void * smtppchild(struct clientparam* param) {
 		i = (int)strlen(buf);
 		socksend(param->remsock, buf, i, conf.timeouts[STRING_S]);
 		socksend(param->remsock, "\r\n", 2, conf.timeouts[STRING_S]);
-		param->statscli+=(i+2);
+ param->statscli64+=(i+2);
 		param->nwrites+=2;
 	}
 	if(command) {
@@ -257,7 +256,7 @@ void * smtppchild(struct clientparam* param) {
 	if(!strncasecmp(command, "MAIL", 4) || !strncasecmp(command, "RCPT", 4) || !strncasecmp(command, "STARTTLS", 8) || !strncasecmp(command, "TURN", 4)){
 		res = (int)strlen(command);
 		command[res] = 0;
-		res = handlehdrfilterscli(param, &command, &res, 0, &res);
+		res = handlehdrfilterscli(param, (unsigned char **)&command, &res, 0, &res);
 		if(res != PASS) {
 			if(res == HANDLED) res = 2;
 			else RETURN(677);
@@ -292,7 +291,7 @@ void * smtppchild(struct clientparam* param) {
 CLEANRET:
 
  if(param->hostname&&param->extusername) {
-	sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(param->sins.sin_port)==25)?0:':', ntohs(param->sins.sin_port));
+	sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, *SAPORT(&param->sinsr)==25?0:':',ntohs(*SAPORT(&param->sinsr)));
 	 (*param->srv->logfunc)(param, buf);
  }
  else (*param->srv->logfunc)(param, NULL);

+ 10 - 10
src/sockgetchar.c

@@ -33,7 +33,7 @@ int socksend(SOCKET sock, unsigned char * buf, int bufsize, int to){
 }
 
 
-int socksendto(SOCKET sock, struct sockaddr_in * sin, unsigned char * buf, int bufsize, int to){
+int socksendto(SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to){
  int sent = 0;
  int res;
  struct pollfd fds;
@@ -45,7 +45,7 @@ int socksendto(SOCKET sock, struct sockaddr_in * sin, unsigned char * buf, int b
  	res = so._poll(&fds, 1, to);
 	if(res < 0 && (errno == EAGAIN || errno == EINTR)) continue;
 	if(res < 1) break;
-	res = so._sendto(sock, buf + sent, bufsize - sent, 0,  (struct sockaddr *)sin, sizeof(struct sockaddr_in));
+	res = so._sendto(sock, buf + sent, bufsize - sent, 0, sin, SASIZE(sin));
 	if(res < 0) {
 		if(errno !=  EAGAIN && errno != EINTR) break;
 		continue;
@@ -55,7 +55,7 @@ int socksendto(SOCKET sock, struct sockaddr_in * sin, unsigned char * buf, int b
  return sent;
 }
 
-int sockrecvfrom(SOCKET sock, struct sockaddr_in * sin, unsigned char * buf, int bufsize, int to){
+int sockrecvfrom(SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to){
 	struct pollfd fds;
 	SASIZETYPE sasize;
 	int res;
@@ -64,7 +64,7 @@ int sockrecvfrom(SOCKET sock, struct sockaddr_in * sin, unsigned char * buf, int
 	fds.events = POLLIN;
 	if(conf.timetoexit) return EOF;
 	if (so._poll(&fds, 1, to)<1) return 0;
-	sasize = sizeof(struct sockaddr_in);
+	sasize = SASIZE(sin);
 	do {
 		res = so._recvfrom(sock, buf, bufsize, 0, (struct sockaddr *)sin, &sasize);
 	} while (res < 0 && (errno == EAGAIN || errno == EINTR));
@@ -83,7 +83,7 @@ int sockgetcharcli(struct clientparam * param, int timeosec, int timeousec){
 		return (int)param->clibuf[param->clioffset++];
 	}
 	param->clioffset = param->cliinbuf = 0;
-	if ((len = sockrecvfrom(param->clisock, &param->sinc, param->clibuf, param->clibufsize, timeosec*1000 + timeousec))<=0) return EOF;
+	if ((len = sockrecvfrom(param->clisock, (struct sockaddr *)&param->sincr, param->clibuf, param->clibufsize, timeosec*1000 + timeousec))<=0) return EOF;
 	param->cliinbuf = len;
 	param->clioffset = 1;
 	return (int)*param->clibuf;
@@ -103,7 +103,7 @@ int sockfillbuffcli(struct clientparam * param, unsigned long size, int timeosec
 	}
 	if(size <= param->cliinbuf) return size;
 	size -= param->cliinbuf;
-	if((len = sockrecvfrom(param->clisock, &param->sinc, param->clibuf + param->cliinbuf, (param->clibufsize - param->cliinbuf) < size? param->clibufsize - param->cliinbuf:size, timeosec*1000)) > 0){
+	if((len = sockrecvfrom(param->clisock, (struct sockaddr *)&param->sincr, param->clibuf + param->cliinbuf, (param->clibufsize - param->cliinbuf) < size? param->clibufsize - param->cliinbuf:size, timeosec*1000)) > 0){
 		param->cliinbuf += len;
 	}
 	return param->cliinbuf;
@@ -123,10 +123,10 @@ int sockfillbuffsrv(struct clientparam * param, unsigned long size, int timeosec
 	}
 	if(size <= param->srvinbuf) return size;
 	size -= param->srvinbuf;
-	if((len = sockrecvfrom(param->remsock, &param->sinc, param->srvbuf + param->srvinbuf, (param->srvbufsize - param->srvinbuf) < size? param->srvbufsize - param->srvinbuf:size, timeosec*1000)) > 0){
+	if((len = sockrecvfrom(param->remsock, (struct sockaddr *)&param->sinsr, param->srvbuf + param->srvinbuf, (param->srvbufsize - param->srvinbuf) < size? param->srvbufsize - param->srvinbuf:size, timeosec*1000)) > 0){
 		param->srvinbuf += len;
 		param->nreads++;
-		param->statssrv += len;
+		param->statssrv64 += len;
 	}
 	return param->srvinbuf;
 }
@@ -148,11 +148,11 @@ int sockgetcharsrv(struct clientparam * param, int timeosec, int timeousec){
 		return (int)param->srvbuf[param->srvoffset++];
 	}
 	param->srvoffset = param->srvinbuf = 0;
-	if ((len = sockrecvfrom(param->remsock, &param->sins, param->srvbuf, param->srvbufsize, timeosec*1000 + timeousec))<=0) return EOF;
+	if ((len = sockrecvfrom(param->remsock, (struct sockaddr *)&param->sinsr, param->srvbuf, param->srvbufsize, timeosec*1000 + timeousec))<=0) return EOF;
 	param->srvinbuf = len;
 	param->srvoffset = 1;
 	param->nreads++;
-	param->statssrv += len;
+	param->statssrv64 += len;
 	return (int)*param->srvbuf;
 }
 

+ 24 - 25
src/sockmap.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: sockmap.c,v 1.64 2014-04-07 20:35:09 vlad Exp $
 */
 
 #include "proxy.h"
@@ -13,7 +12,7 @@
 
 int sockmap(struct clientparam * param, int timeo){
  int res=0;
- unsigned sent=0, received=0;
+ uint64_t sent=0, received=0;
  SASIZETYPE sasize;
  struct pollfd fds[2];
  int sleeptime = 0, stop = 0;
@@ -32,12 +31,12 @@ int sockmap(struct clientparam * param, int timeo){
 #if DEBUGLEVEL > 2
 (*param->srv->logfunc)(param, "Starting sockets mapping");
 #endif
- if(!param->waitclient){
+ if(!param->waitclient64){
 	if(!param->srvbuf && (!(param->srvbuf=myalloc(bufsize)) || !(param->srvbufsize = bufsize))){
 		return (21);
 	}
  }
- if(!param->waitserver){
+ if(!param->waitserver64){
 	if(!param->clibuf && (!(param->clibuf=myalloc(bufsize)) || !(param->clibufsize = bufsize))){
 		return (21);
 	}
@@ -69,33 +68,33 @@ int sockmap(struct clientparam * param, int timeo){
 
  while (!stop&&!conf.timetoexit){
 	sasize = sizeof(struct sockaddr_in);
-	if((param->maxtrafin && param->statssrv >= param->maxtrafin) || (param->maxtrafout && param->statscli >= param->maxtrafout)){
+	if((param->maxtrafin64 && param->statssrv64 >= param->maxtrafin64) || (param->maxtrafout64 && param->statscli64 >= param->maxtrafout64)){
 		return (10);
 	}
-	if((param->srv->logdumpsrv && (param->statssrv > param->srv->logdumpsrv)) ||
-		(param->srv->logdumpcli && (param->statscli > param->srv->logdumpcli)))
+	if((param->srv->logdumpsrv && (param->statssrv64 > param->srv->logdumpsrv)) ||
+		(param->srv->logdumpcli && (param->statscli64 > param->srv->logdumpcli)))
 			(*param->srv->logfunc)(param, NULL);
 	fds[0].events = fds[1].events = 0;
-	if(param->srvinbuf > param->srvoffset && !param->waitclient) {
+	if(param->srvinbuf > param->srvoffset && !param->waitclient64) {
 #if DEBUGLEVEL > 2
 (*param->srv->logfunc)(param, "will send to client");
 #endif
 		fds[0].events |= POLLOUT;
 	}
-	if((param->srvbufsize - param->srvinbuf) > minsize && !param->waitclient && (!param->waitserver ||(received + param->srvinbuf - param->srvoffset < param->waitserver))) {
+	if((param->srvbufsize - param->srvinbuf) > minsize && !param->waitclient64 && (!param->waitserver64 ||(received + param->srvinbuf - param->srvoffset < param->waitserver64))) {
 #if DEBUGLEVEL > 2
 (*param->srv->logfunc)(param, "Will recv from server");
 #endif
 		fds[1].events |= POLLIN;
 	}
 
-	if(param->cliinbuf > param->clioffset && !param->waitserver) {
+	if(param->cliinbuf > param->clioffset && !param->waitserver64) {
 #if DEBUGLEVEL > 2
 (*param->srv->logfunc)(param, "Will send to server");
 #endif
 		fds[1].events |= POLLOUT;
 	}
-    	if((param->clibufsize - param->cliinbuf) > minsize  && !param->waitserver &&(!param->srv->singlepacket || param->service != S_UDPPM) ) {
+    	if((param->clibufsize - param->cliinbuf) > minsize  && !param->waitserver64 &&(!param->srv->singlepacket || param->service != S_UDPPM) ) {
 #if DEBUGLEVEL > 2
 (*param->srv->logfunc)(param, "Will recv from client");
 #endif
@@ -128,7 +127,7 @@ int sockmap(struct clientparam * param, int timeo){
 		if(param->bandlimfunc) {
 			sleeptime = (*param->bandlimfunc)(param, param->srvinbuf - param->srvoffset, 0);
 		}
-		res = so._sendto(param->clisock, param->srvbuf + param->srvoffset,(!param->waitserver || ((unsigned)param->waitserver - received) > (param->srvinbuf - param->srvoffset))? param->srvinbuf - param->srvoffset : param->waitserver - received, 0, (struct sockaddr*)&param->sinc, sasize);
+		res = so._sendto(param->clisock, param->srvbuf + param->srvoffset,(!param->waitserver64 || (param->waitserver64 - received) > (param->srvinbuf - param->srvoffset))? param->srvinbuf - param->srvoffset : (int)(param->waitserver64 - received), 0, (struct sockaddr*)&param->sincr, sasize);
 		if(res < 0) {
 			if(errno != EAGAIN && errno != EINTR) return 96;
 			if(errno == EINTR) usleep(SLEEPTIME);
@@ -137,7 +136,7 @@ int sockmap(struct clientparam * param, int timeo){
 		param->srvoffset += res;
 		received += res;
 		if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0;
-		if(param->waitserver && param->waitserver<= received){
+		if(param->waitserver64 && param->waitserver64<= received){
 			return (98);
 		}
 		if(param->service == S_UDPPM && param->srv->singlepacket) {
@@ -154,18 +153,18 @@ int sockmap(struct clientparam * param, int timeo){
 			sl1 = (*param->bandlimfunc)(param, 0, param->cliinbuf - param->clioffset);
 			if(sl1 > sleeptime) sleeptime = sl1;
 		}
-		res = so._sendto(param->remsock, param->clibuf + param->clioffset, (!param->waitclient || ((unsigned)param->waitclient - sent) > (param->cliinbuf - param->clioffset))? param->cliinbuf - param->clioffset : param->waitclient - sent, 0, (struct sockaddr*)&param->sins, sasize);
+		res = so._sendto(param->remsock, param->clibuf + param->clioffset, (!param->waitclient64 || (param->waitclient64 - sent) > (param->cliinbuf - param->clioffset))? param->cliinbuf - param->clioffset : (int)(param->waitclient64 - sent), 0, (struct sockaddr*)&param->sinsr, sasize);
 		if(res < 0) {
 			if(errno != EAGAIN && errno != EINTR) return 97;
 			if(errno == EINTR) usleep(SLEEPTIME);
 			continue;
 		}
 		param->clioffset += res;
+		if(param->clioffset == param->cliinbuf) param->clioffset = param->cliinbuf = 0;
 		sent += res;
-		param->statscli += res;
 		param->nwrites++;
-		if(param->clioffset == param->cliinbuf) param->clioffset = param->cliinbuf = 0;
-		if(param->waitclient && param->waitclient<= sent) {
+		param->statscli64 += res;
+		if(param->waitclient64 && param->waitclient64<= sent) {
 			return (99);
 		}
 	}
@@ -173,7 +172,7 @@ int sockmap(struct clientparam * param, int timeo){
 #if DEBUGLEVEL > 2
 (*param->srv->logfunc)(param, "recv from client");
 #endif
-		res = so._recvfrom(param->clisock, param->clibuf + param->cliinbuf, param->clibufsize - param->cliinbuf, 0, (struct sockaddr *)&param->sinc, &sasize);
+		res = so._recvfrom(param->clisock, param->clibuf + param->cliinbuf, param->clibufsize - param->cliinbuf, 0, (struct sockaddr *)&param->sincr, &sasize);
 		if (res==0) {
 			so._shutdown(param->clisock, SHUT_RDWR);
 			so._closesocket(param->clisock);
@@ -219,7 +218,7 @@ int sockmap(struct clientparam * param, int timeo){
 			}
 			param->srvinbuf += res;
 			param->nreads++;
-			param->statssrv += res;
+			param->statssrv64 += res;
 			if(!param->nolongdatfilter){
 				action = handledatfltsrv(param,  &param->srvbuf, &param->srvbufsize, param->srvinbuf - res, &param->srvinbuf);
 				if(action == HANDLED){
@@ -241,26 +240,26 @@ int sockmap(struct clientparam * param, int timeo){
 #if DEBUGLEVEL > 2
 (*param->srv->logfunc)(param, "finished with mapping");
 #endif
- while(!param->waitclient && param->srvinbuf > param->srvoffset && param->clisock != INVALID_SOCKET){
+ while(!param->waitclient64 && param->srvinbuf > param->srvoffset && param->clisock != INVALID_SOCKET){
 #if DEBUGLEVEL > 2
 (*param->srv->logfunc)(param, "flushing buffer to client");
 #endif
-	res = socksendto(param->clisock, &param->sinc, param->srvbuf + param->srvoffset, param->srvinbuf - param->srvoffset, conf.timeouts[STRING_S] * 1000);
+	res = socksendto(param->clisock, (struct sockaddr *)&param->sincr, param->srvbuf + param->srvoffset, param->srvinbuf - param->srvoffset, conf.timeouts[STRING_S] * 1000);
 	if(res > 0){
 		param->srvoffset += res;
-		param->statssrv += res;
+		param->statssrv64 += res;
 		if(param->srvoffset == param->srvinbuf) param->srvoffset = param->srvinbuf = 0;
 	}
 	else break;
  } 
- while(!param->waitserver && param->cliinbuf > param->clioffset && param->remsock != INVALID_SOCKET){
+ while(!param->waitserver64 && param->cliinbuf > param->clioffset && param->remsock != INVALID_SOCKET){
 #if DEBUGLEVEL > 2
 (*param->srv->logfunc)(param, "flushing buffer to server");
 #endif
-	res = socksendto(param->remsock, &param->sins, param->clibuf + param->clioffset, param->cliinbuf - param->clioffset, conf.timeouts[STRING_S] * 1000);
+	res = socksendto(param->remsock, (struct sockaddr *)&param->sinsr, param->clibuf + param->clioffset, param->cliinbuf - param->clioffset, conf.timeouts[STRING_S] * 1000);
 	if(res > 0){
 		param->clioffset += res;
-		param->statscli += res;
+		param->statscli64 += res;
 		if(param->cliinbuf == param->clioffset) param->cliinbuf = param->clioffset = 0;
 	}
 	else break;

+ 141 - 105
src/socks.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: socks.c,v 1.34 2009/09/17 12:21:09 v.dubrovin Exp $
 */
 
 #include "proxy.h"
@@ -22,17 +21,21 @@ void * sockschild(struct clientparam* param) {
  SOCKET s;
  unsigned size;
  SASIZETYPE sasize;
+ unsigned short port = 0;
  unsigned char * buf=NULL;
  unsigned char c;
  unsigned char command=0;
  struct pollfd fds[3];
  int ver=0;
  int havepass = 0;
- struct sockaddr_in sin;
+#ifndef NOIPV6
+ struct sockaddr_in6 sin = {AF_INET6};
+#else
+ struct sockaddr_in sin = {AF_INET};
+#endif
  int len;
 
 
- param->req.sin_addr.s_addr = 0;
  param->service = S_SOCKS;
 
  if(!(buf = myalloc(BUFSIZE))) {RETURN(21);}
@@ -44,29 +47,29 @@ void * sockschild(struct clientparam* param) {
  if(ver == 5){
 	 if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */
 	 for (; i; i--) {
-		if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(442);}
+		if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
 		if (res == 2 && !param->srv->nouser) {
 			havepass = res;
 		}
 	 }
 	 buf[0] = 5;
 	 buf[1] = havepass;
-	 if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);}
+	 if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(401);}
 	 if (havepass) {
 		if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) {
 			RETURN(412);
 		}
-		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(443);}
-		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(444);};
+		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
+		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);};
 		buf[i] = 0;
 		if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf);
 		if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);}
-		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(446);};
+		if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(441);};
 		buf[i] = 0;
 		if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf);
 		buf[0] = 1;
 		buf[1] = 0;
-		if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);}
+		if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(481);}
 	 }
 	 if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) {
 		RETURN(421);
@@ -78,113 +81,134 @@ void * sockschild(struct clientparam* param) {
 	 c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */
  }
  else {
-	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(448);}
+	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
 	buf[0] = (unsigned char) res;
-	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(449);}
+	if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
 	buf[1] = (unsigned char) res;
-	param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf;
+	port = *(unsigned short*)buf;
 	c = 1;
  }
  
+ size = 4;
+ *SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET;
  switch(c) {
+#ifndef NOIPV6
+	case 4:
+		if(param->srv->family == 4) RETURN(997);
+		size = 16;
+		*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET6;
+#endif
 	case 1:
-		for (i = 0; i<4; i++){
-			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(450);}
+		for (i = 0; i<size; i++){
+			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
 			buf[i] = (unsigned char)res;
 		}
-		param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = *(unsigned long *)buf;
-		if(command==1 && !param->req.sin_addr.s_addr) {
-			RETURN(422);
+#ifndef NOIPV6
+		if (c == 1 && param->srv->family==6){
+			char prefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255};
+			*SAFAMILY(&param->sinsr) = *SAFAMILY(&param->req) = AF_INET6;
+			memcpy(SAADDR(&param->sinsr), prefix, 12);
+			memcpy(12 + (char *)SAADDR(&param->sinsr), buf, 4);
+			memcpy(SAADDR(&param->req), prefix, 12);
+			memcpy(12 + (char *)SAADDR(&param->req), buf, 4);
+		}
+		else {
+#endif
+			memcpy(SAADDR(&param->sinsr), buf, size);
+			memcpy(SAADDR(&param->req), buf, size);
+#ifndef NOIPV6
+		}
+#endif
+		if(SAISNULL(&param->req)) {
+			RETURN(421);
 		}
-		myinet_ntoa(param->sins.sin_addr, (char *)buf);
+		myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf, 64);
 		break;
 	case 3:
 		if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */
 		for (i=0; i<size; i++){ /* size < 256 */
-			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(452);}
+			if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);}
 			buf[i] = (unsigned char)res;
 		}
 		buf[i] = 0;
-		param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf);
-		if(command==1 && !param->req.sin_addr.s_addr) {
-			RETURN(100);
-		}
+		if(!getip46(param->srv->family, buf, (struct sockaddr *) &param->req)) RETURN(100);
+		memcpy(&param->sinsr, &param->req, sizeof(param->req));
 		break;
 	default:
-		RETURN(998);
+		RETURN(997);
  }
  if(param->hostname)myfree(param->hostname);
  param->hostname = (unsigned char *)mystrdup((char *)buf);
  if (ver == 5) {
-	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(453);}
+	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
 	 buf[0] = (unsigned char) res;
-	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(454);}
+	 if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);}
 	 buf[1] = (unsigned char) res;
-	 param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf;
+	 port = *(unsigned short*)buf;
+
  }
  else {
 	sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
 	buf[127] = 0;
 	if(!param->srv->nouser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf);
-	if(param->sins.sin_addr.s_addr && ntohl(param->sins.sin_addr.s_addr)<256){
+	if(!memcmp(SAADDR(&param->req), "\0\0\0", 3)){
 		param->service = S_SOCKS45;
 		sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]);
 		buf[127] = 0;
 		if(param->hostname)myfree(param->hostname);
 		param->hostname = (unsigned char *)mystrdup((char *)buf);
-		param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf);
+		if(!getip46(param->srv->family, buf, (struct sockaddr *) &param->req)) RETURN(100);
+		memcpy(&param->sinsr, &param->req, sizeof(&param->req));
 	}
  }
- if(command == 1 && !param->req.sin_port) {RETURN(424);}
- param->sins.sin_family = AF_INET;
+
+ *SAPORT(&param->sinsr) = *SAPORT(&param->req) = port;
+ if(command == 1 && !*SAPORT(&param->sinsr)) {RETURN(421);}
  switch(command) { 
 	case 1:
 	 param->operation = CONNECT;
 	 break;
  	case 2:
-	 param->sins.sin_addr.s_addr = param->extip;
-	 param->sins.sin_port = param->extport?param->extport:param->req.sin_port;
-	 if ((param->remsock=so._socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
-	 param->operation = BIND;
-	 break;
 	case 3:
-	 param->sins.sin_port = param->extport?param->extport:param->req.sin_port;
-	 param->sins.sin_addr.s_addr = param->extip;
-	 if ((param->remsock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
-	 param->operation = UDPASSOC;
+
+#ifndef NOIPV6	 
+	 memcpy(&param->sinsl, *SAFAMILY(&param->req)==AF_INET6? (struct sockaddr *)&param->srv->extsa6:(struct sockaddr *)&param->srv->extsa, SASIZE(&param->req)); 
+#else
+	 memcpy(&param->sinsl, &param->srv->extsa, SASIZE(&param->req)); 
+#endif
+	 if ((param->remsock=so._socket(SASOCK(&param->req), command == 2? SOCK_STREAM:SOCK_DGRAM, command == 2?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
+	 param->operation = command == 2?BIND:UDPASSOC;
 	 break;
+
 	default:
 	 RETURN(997);
  }
 
- if((res = (*param->srv->authfunc)(param))) {RETURN(res);}
+ if((res = (*param->srv->authfunc)(param))) {
+	RETURN(res);
+ }
 
  if(command > 1) {
-	if(so._bind(param->remsock,(struct sockaddr *)&param->sins,sizeof(param->sins))) {
-		param->sins.sin_port = 0;
-		if(so._bind(param->remsock,(struct sockaddr *)&param->sins,sizeof(param->sins)))RETURN (12);
+	if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,SASIZE(&param->sinsl))) {
+		*SAPORT(&param->sinsl) = 0;
+		if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,SASIZE(&param->sinsl)))RETURN (12);
 #if SOCKSTRACE > 0
-fprintf(stderr, "%s:%hu binded to communicate with server\n",
-			inet_ntoa(param->sins.sin_addr),
-			ntohs(param->sins.sin_port)
-	);
+fprintf(stderr, "%hu binded to communicate with server\n", *SAPORT(&param->sins));
 fflush(stderr);
 #endif
 	}
-	sasize = sizeof(struct sockaddr_in);
-	so._getsockname(param->remsock, (struct sockaddr *)&param->sins,  &sasize);
+	sasize = SASIZE(&param->sinsl);
+	so._getsockname(param->remsock, (struct sockaddr *)&param->sinsl,  &sasize);
 	if(command == 3) {
 		param->ctrlsock = param->clisock;
-		param->clisock = so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+		param->clisock = so._socket(SASOCK(&param->sincr), SOCK_DGRAM, IPPROTO_UDP);
 		if(param->clisock == INVALID_SOCKET) {RETURN(11);}
-		sin.sin_family = AF_INET;
-		sin.sin_addr.s_addr = param->srv->intip;
-		sin.sin_port = htons(0);
-		if(so._bind(param->clisock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))) {RETURN (12);}
+		memcpy(&sin, &param->sincl, sizeof(&sin));
+		*SAPORT(&sin) = 0;
+		if(so._bind(param->clisock,(struct sockaddr *)&sin,sizeof(sin))) {RETURN (12);}
 #if SOCKSTRACE > 0
-fprintf(stderr, "%s:%hu binded to communicate with client\n",
-			inet_ntoa(sin.sin_addr),
-			ntohs(sin.sin_port)
+fprintf(stderr, "%hu binded to communicate with client\n",
+			ntohs(*SAPORT(&sin))
 	);
 fflush(stderr);
 #endif
@@ -195,7 +219,9 @@ fflush(stderr);
 CLEANRET:
 
  if(param->clisock != INVALID_SOCKET){
-	sasize = sizeof(struct sockaddr_in);
+	int repcode;
+
+	sasize = sizeof(sin);
 	if(command != 3) so._getsockname(param->remsock, (struct sockaddr *)&sin,  &sasize);
 	else so._getsockname(param->clisock, (struct sockaddr *)&sin,  &sasize);
 #if SOCKSTRACE > 0
@@ -207,20 +233,27 @@ fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\
 	);
 fflush(stderr);
 #endif
+	if(!param->res) repcode = 0;
+	else if(param->res <= 10) repcode = 2;
+	else if (param->res < 20) repcode = 5;
+	else if (param->res < 30) repcode = 1;
+	else if (param->res < 100) repcode = 4;
+	else repcode = param->res%10;
+
 	if(ver == 5){
 		buf[0] = 5;
-		buf[1] = param->res%10;
+		buf[1] = repcode;
 		buf[2] = 0;
-		buf[3] = 1;
-		memcpy(buf+4, &sin.sin_addr.s_addr, 4);
-		memcpy(buf+8, &sin.sin_port, 2);
-		socksend((command == 3)?param->ctrlsock:param->clisock, buf, 10, conf.timeouts[STRING_S]);
+		buf[3] = (*SAFAMILY(&sin) == AF_INET)?1:4;
+		memcpy(buf+4, SAADDR(&sin), SAADDRLEN(&sin));
+		memcpy(buf+4+SAADDRLEN(&sin), SAPORT(&sin), 2);
+		socksend((command == 3)?param->ctrlsock:param->clisock, buf, 6+SAADDRLEN(&sin), conf.timeouts[STRING_S]);
 	}
 	else{
 		buf[0] = 0;
-		buf[1] = 90 + (param->res%10);
-		memcpy(buf+2, &sin.sin_port, 2);
-		memcpy(buf+4, &sin.sin_addr.s_addr, 4);
+		buf[1] = 90 + !!(repcode);
+		memcpy(buf+2, SAPORT(&sin), 2);
+		memcpy(buf+4, SAADDR(&sin), 4);
 		socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
 	}
 
@@ -239,48 +272,48 @@ fflush(stderr);
 				fds[0].fd = param->remsock;
 				fds[1].fd = param->clisock;
 				fds[0].events = fds[1].events = POLLIN;
-				res = so._poll(fds, 2, conf.timeouts[(param->req.sin_addr.s_addr)?CONNECTION_S:CONNECTION_L] * 1000);
+				res = so._poll(fds, 2, conf.timeouts[CONNECTION_L] * 1000);
 				if (res < 1 || fds[1].revents) {
 					res = 460;
 					break;
 				}
-				sasize = sizeof(param->sins);
-				s = so._accept(param->remsock, (struct sockaddr *)&param->sins, &sasize);
+				sasize = sizeof(param->sinsr);
+				s = so._accept(param->remsock, (struct sockaddr *)&param->sinsr, &sasize);
 				so._closesocket(param->remsock);
 				param->remsock = s;
 				if(s == INVALID_SOCKET) {
 					param->res = 462;
 					break;
 				}
-				if(param->req.sin_addr.s_addr && param->req.sin_addr.s_addr != param->sins.sin_addr.s_addr) {
+				if(SAISNULL(&param->req) &&
+				 memcmp(SAADDR(&param->req),SAADDR(&param->sinsr),SAADDRLEN(&param->req))) {
 					param->res = 470;
 					break;
 				}
 #if SOCKSTRACE > 0
-fprintf(stderr, "Sending incoming connection to client with code %d for %s with %s:%hu\n",
+fprintf(stderr, "Sending incoming connection to client with code %d for %s with %hu\n",
 			param->res,
 			commands[command],
-			inet_ntoa(param->sins.sin_addr),
-			ntohs(param->sins.sin_port)
+			*SAPORT(param->sins);
 	);
 fflush(stderr);
 #endif
 				if(ver == 5){
-					memcpy (buf+4, &param->sins.sin_addr, 4);
-					memcpy (buf+8, &param->sins.sin_port, 2);
-					socksend(param->clisock, buf, 10, conf.timeouts[STRING_S]);
+					buf[3] = (*SAFAMILY(&param->sinsr) == AF_INET)?1:4;
+					memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
+					memcpy(buf+4+SAADDRLEN(&param->sinsr), SAPORT(&param->sinsr), 2);
+					socksend(param->clisock, buf, 6+SAADDRLEN(&param->sinsr), conf.timeouts[STRING_S]);
 				}
 				else {
-					memcpy (buf+2, &param->sins.sin_port, 2);
-					memcpy (buf+4, &param->sins.sin_addr, 4);
+					memcpy (buf+2, SAPORT(&param->sinsr), 2);
+					memcpy (buf+4, SAADDR(&param->sinsr), 4);
 					socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]);
 				}
 
 				param->res = sockmap(param, conf.timeouts[CONNECTION_S]);
 				break;
 			case 3:
-				param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr;
-				param->sins.sin_port = param->req.sin_port;
+				memcpy(&param->sinsr, &param->req, sizeof(param->sinsr));
 				myfree(buf);
 				if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);}
 
@@ -300,12 +333,12 @@ fflush(stderr);
 						break;
 					}
 					if (fds[1].revents) {
-						sasize = sizeof(struct sockaddr_in);
+						sasize = sizeof(sin);
 						if((len = so._recvfrom(param->clisock, buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) {
 							param->res = 464;
 							break;
 						}
-						if(sin.sin_addr.s_addr != param->sinc.sin_addr.s_addr){
+						if(SAADDRLEN(&sin) != SAADDRLEN(&param->sincr) || memcmp(SAADDR(&sin), SAADDR(&param->sincr), SAADDRLEN(&sin))){
 							param->res = 465;
 							break;
 						}
@@ -313,10 +346,14 @@ fflush(stderr);
 							param->res = 466;
 							break;
 						}
+						size = 4;
 						switch(buf[3]) {
+							case 4:
+								size = 16;
 							case 1:
-								i = 8;
-								memcpy(&param->sins.sin_addr.s_addr, buf+4, 4);
+								i = 4+size;
+								memcpy(SAADDR(&param->sinsr), buf+4, size);
+								*SAFAMILY(&param->sinsr) = (size == 4)?AF_INET:AF_INET6;
 								break;
 							case 3:
 								size = buf[4];
@@ -324,22 +361,22 @@ fflush(stderr);
 									buf[i] = buf[i+1];
 								}
 								buf[i++] = 0;
-								param->sins.sin_addr.s_addr = getip(buf+4);
+								if(!getip46(param->srv->family, buf, (struct sockaddr *) &param->sinsr)) RETURN(100);
 								break;
 							default:
-								RETURN(996);
+								RETURN(997);
 						 }
 
-						memcpy(&param->sins.sin_port, buf+i, 2);
+						memcpy(SAPORT(&param->sinsr), buf+i, 2);
 						i+=2;
 
-						sasize = sizeof(param->sins);
+						sasize = sizeof(param->sinsr);
 						if(len > (int)i){
-							if(socksendto(param->remsock, &param->sins, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){
+							if(socksendto(param->remsock, (struct sockaddr *)&param->sinsr, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){
 								param->res = 467;
 								break;
 							}
-							param->statscli+=(len - i);
+							param->statscli64+=(len - i);
 							param->nwrites++;
 #if SOCKSTRACE > 1
 fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n",
@@ -358,27 +395,25 @@ fflush(stderr);
 
 					}
 					if (fds[0].revents) {
-						struct sockaddr_in tsin;
-						sasize = sizeof(tsin);
+						sasize = sizeof(param->sinsr);
 						buf[0]=buf[1]=buf[2]=0;
-						buf[3]=1;
-						if((len = so._recvfrom(param->remsock, buf+10, 65535 - 10, 0, (struct sockaddr *)&tsin, &sasize)) <= 0) {
+						buf[3]=(*SAFAMILY(&param->sinsl) == AF_INET)?1:4;
+						if((len = so._recvfrom(param->remsock, buf+6+SAADDRLEN(&param->sinsl), 65535 - 10, 0, (struct sockaddr *)&param->sinsr, &sasize)) <= 0) {
 							param->res = 468;
 							break;
 						}
-						param->statssrv+=len;
+						param->statssrv64+=len;
 						param->nreads++;
-						memcpy(buf+4, &tsin.sin_addr.s_addr, 4);
-						memcpy(buf+8, &tsin.sin_port, 2);
-						sasize = sizeof(param->sins);
-						if(socksendto(param->clisock, &sin, buf, len + 10, conf.timeouts[SINGLEBYTE_L]*1000) <=0){
+						memcpy(buf+4, SAADDR(&param->sinsr), SAADDRLEN(&param->sinsr));
+						memcpy(buf+4+SAADDRLEN(&param->sinsr), SAPORT(&param->sinsr), 2);
+						sasize = sizeof(sin);
+						if(socksendto(param->clisock, (struct sockaddr *)&sin, buf, len + 6 + SAADDRLEN(&param->sinsr), conf.timeouts[SINGLEBYTE_L]*1000) <=0){
 							param->res = 469;
 							break;
 						}
 #if SOCKSTRACE > 1
-fprintf(stderr, "UDP packet relayed to client from %s:%hu size %d\n",
-			inet_ntoa(tsin.sin_addr),
-			ntohs(tsin.sin_port),
+fprintf(stderr, "UDP packet relayed to client from %hu size %d\n",
+			ntohs(*SAPORT(&param->sinsr)),
 			len
 	);
 fflush(stderr);
@@ -400,8 +435,9 @@ fflush(stderr);
 	 if(param->hostname){
 	  sprintf((char *)buf + strlen((char *)buf), "%.265s", param->hostname);
 	 }
-	 else myinet_ntoa(param->req.sin_addr, (char *)buf+strlen((char *)buf));
-         sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(param->req.sin_port));
+	 else 
+		myinet_ntop(*SAFAMILY(&param->req), SAADDR(&param->req), (char *)buf + strlen((char *)buf), 64);
+         sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(*SAPORT(&param->req)));
 	 (*param->srv->logfunc)(param, buf);
 	 myfree(buf);
  }

+ 3 - 3
src/stringtable.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: stringtable.c,v 1.16 2009/07/20 18:16:03 v.dubrovin Exp $
 */
 
 #include <stdio.h>
@@ -30,8 +29,9 @@ unsigned char * strings[] = {
 /* 16 */	(unsigned char *)"FTPPR",
 /* 17 */	(unsigned char *)"SMTPP",
 /* 18 */	(unsigned char *)"ICQPR",
-/* 19 */	(unsigned char *)"MSNPR",
-/* 20 */	(unsigned char *)"ZOMBIE",
+/* 19 	(unsigned char *)"MSNPR", */
+/* 19 */	(unsigned char *)"ZOMBIE",
+/* 20 */	NULL,
 /* 21 */	NULL,
 /* 22 */	NULL,
 /* 23 */	NULL,

+ 127 - 50
src/structures.h

@@ -6,6 +6,12 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifndef NOPSTDINT
+#include "pstdint.h"
+#else
+typedef unsigned long uint64_t
+#define PRINTF_INT64_MODIFIER "l"
+#endif
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -22,12 +28,12 @@ extern "C" {
 #define INVALID_SOCKET  (-1)
 #else
 #include <winsock2.h>
+#include <Ws2tcpip.h>
 #define pthread_mutex_t CRITICAL_SECTION
 #define pthread_mutex_init(x, y) InitializeCriticalSection(x)
 #define pthread_mutex_lock(x) EnterCriticalSection(x)
 #define pthread_mutex_unlock(x) LeaveCriticalSection(x)
 #define pthread_mutex_destroy(x) DeleteCriticalSection(x)
-typedef unsigned (__stdcall *BEGINTHREADFUNC)(void *);
 #ifdef MSVC
 #pragma warning (disable : 4996)
 #endif
@@ -92,6 +98,26 @@ int
 #define IM_MSN		0x00400000
 #define ADMIN		0x01000000
 
+
+#define SAFAMILY(sa) (&(((struct sockaddr_in *)sa)->sin_family))
+
+#ifndef NOIPV6
+#define SAPORT(sa)  (((struct sockaddr_in *)sa)->sin_family == AF_INET6? &((struct sockaddr_in6 *)sa)->sin6_port : &((struct sockaddr_in *)sa)->sin_port)
+#define SAADDR(sa)  (((struct sockaddr_in *)sa)->sin_family == AF_INET6? (unsigned char *)&((struct sockaddr_in6 *)sa)->sin6_addr : (unsigned char *)&((struct sockaddr_in *)sa)->sin_addr.s_addr)
+#define SAADDRLEN(sa) (((struct sockaddr_in *)sa)->sin_family == AF_INET6? 16:4)
+#define SASOCK(sa) (((struct sockaddr_in *)sa)->sin_family == AF_INET6? PF_INET6:PF_INET)
+#define SASIZE(sa) (((struct sockaddr_in *)sa)->sin_family == AF_INET6? sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in))
+#define SAISNULL(sa) (!memcmp(((struct sockaddr_in *)sa)->sin_family == AF_INET6? (unsigned char *)&((struct sockaddr_in6 *)sa)->sin6_addr : (unsigned char *)&((struct sockaddr_in *)sa)->sin_addr.s_addr, NULLADDR,  (((struct sockaddr_in *)sa)->sin_family == AF_INET6? 16:4))) 
+#else
+#define SAPORT(sa)  (&((struct sockaddr_in *)sa)->sin_port)
+#define SAADDR(sa)  ((unsigned char *)&((struct sockaddr_in *)sa)->sin_addr.s_addr)
+#define SAADDRLEN(sa) (4)
+#define SASOCK(sa) (PF_INET)
+#define SASIZE(sa) (sizeof(struct sockaddr_in))
+#define SAISNULL(sa) (((struct sockaddr_in *)sa)->sin_addr.s_addr == 0) 
+#endif
+
+extern char* NULLADDR;
 typedef enum {
 	CLIENT,
 	SERVER
@@ -113,7 +139,11 @@ typedef enum {
 	S_FTPPR,
 	S_SMTPP,
 	S_ICQPR,
+	S_REVLI,
+	S_REVCO,
+/*
 	S_MSNPR,
+*/
 	S_ZOMBIE
 }PROXYSERVICE;
 
@@ -126,14 +156,13 @@ struct srvparam;
 typedef void (*LOGFUNC)(struct clientparam * param, const unsigned char *);
 typedef int (*AUTHFUNC)(struct clientparam * param);
 typedef void * (*REDIRECTFUNC)(struct clientparam * param);
-typedef unsigned long (*RESOLVFUNC)(unsigned char *);
+typedef unsigned long (*RESOLVFUNC)(int af, unsigned char *name, unsigned char *value);
 typedef unsigned (*BANDLIMFUNC)(struct clientparam * param, unsigned nbytesin, unsigned nbytesout);
 typedef void (*TRAFCOUNTFUNC)(struct clientparam * param);
 typedef void * (*EXTENDFUNC) (struct node *node);
 typedef void (*CBFUNC)(void *cb, char * buf, int inbuf);
 typedef void (*PRINTFUNC) (struct node *node, CBFUNC cbf, void*cb);
 typedef int (*PLUGINFUNC) (struct pluginlink *pluginlink, int argc, char** argv);
-typedef void * (*PTHREADFUNC)(void *);
 
 struct auth {
 	struct auth *next;
@@ -144,8 +173,14 @@ struct auth {
 
 struct iplist {
 	struct iplist *next;
-	unsigned long ip;
-	unsigned long mask;
+	int family;
+#ifndef NOIPV6
+	struct in6_addr ip_from;
+	struct in6_addr ip_to;
+#else
+	struct in_addr ip_from;
+	struct in_addr ip_to;
+#endif
 };
 
 struct portlist {
@@ -196,8 +231,11 @@ typedef enum {
 struct chain {
 	struct chain * next;
 	int type;
-	unsigned long redirip;
-	unsigned short redirport;
+#ifndef NOIPV6
+	struct sockaddr_in6 addr;
+#else
+	struct sockaddr_in addr;
+#endif
 	unsigned short weight;
 	unsigned char * extuser;
 	unsigned char * extpass;
@@ -257,16 +295,24 @@ struct trafcount {
 	struct ace *ace;
 	unsigned number;
 	ROTATION type;
-	unsigned long traf;
-	unsigned long trafgb;
-	unsigned long traflim;
-	unsigned long traflimgb;
+	uint64_t traf64;
+	uint64_t traflim64;
 	char * comment;
 	int disabled;
 	time_t cleared;
 	time_t updated;
 };
 
+struct nserver {
+#ifndef NOIPV6
+	struct sockaddr_in6 addr;
+#else
+	struct sockaddr_in addr;
+#endif
+	int usetcp;
+};
+extern int numservers;
+
 typedef void * (* PROXYFUNC)(struct clientparam *);
 
 typedef enum {
@@ -314,7 +360,7 @@ struct srvparam {
 	LOGFUNC logfunc;
 	AUTHFUNC authfunc;
 	PROXYFUNC pf;
-	SOCKET srvsock;
+	SOCKET srvsock, cbsock;
 	int childcount;
 	int maxchild;
 	int version;
@@ -324,10 +370,17 @@ struct srvparam {
 	int silent;
 	int transparent;
 	int nfilters, nreqfilters, nhdrfilterscli, nhdrfilterssrv, npredatfilters, ndatfilterscli, ndatfilterssrv;
+	int family;
 	unsigned bufsize;
 	unsigned logdumpsrv, logdumpcli;
-	unsigned long intip;
-	unsigned long extip;
+#ifndef NOIPV6
+	struct sockaddr_in6 intsa;
+	struct sockaddr_in6 extsa6;
+	struct sockaddr_in6 extsa;
+#else
+	struct sockaddr_in intsa;
+	struct sockaddr_in extsa;
+#endif
 	pthread_mutex_t counter_mutex;
 	struct pollfd fds;
 	FILE *stdlog;
@@ -340,8 +393,6 @@ struct srvparam {
 	unsigned char * logformat;
 	unsigned char * logtarget;
 	unsigned char * nonprintable;
-	unsigned short intport;
-	unsigned short extport;
 	unsigned short targetport;
 	unsigned char replace;
 	time_t time_start;
@@ -377,8 +428,8 @@ struct clientparam {
 
 	int	res,
 		status;
-	unsigned	waitclient,
-			waitserver;
+	uint64_t	waitclient64,
+			waitserver64;
 	int	pwtype,
 		threadid,
 		weight,
@@ -402,26 +453,26 @@ struct clientparam {
 			srvoffset,
 			clibufsize,
 			srvbufsize,
-			msec_start,
-			maxtrafin,
-			maxtrafout;
-
-	struct sockaddr_in	sinc,
-				sins,
-				req;
+			msec_start;
+	uint64_t
+			maxtrafin64,
+			maxtrafout64;
+#ifndef NOIPV6
+	struct sockaddr_in6	sincl, sincr, sinsl, sinsr, req;
+#else
+	struct sockaddr_in	sincl, sincr, sinsl, sinsr, req;
+#endif
 
-	unsigned long	statscli,
-			statssrv,
+	uint64_t	statscli64,
+			statssrv64;
+	unsigned long
 			nreads,
 			nwrites,
-			nconnects,
-			extip;
+			nconnects;
 
 	struct bandlim	*bandlims[MAXBANDLIMS],
 			*bandlimsout[MAXBANDLIMS];
 
-	unsigned short extport;
-
 	time_t time_start;
 };
 
@@ -446,8 +497,14 @@ struct extparam {
 	unsigned char *logname, **archiver;
 	ROTATION logtype, countertype;
 	char * counterfile;
-	unsigned long intip, extip;
-	unsigned short intport, extport;
+#ifndef NOIPV6
+	struct sockaddr_in6 intsa;
+	struct sockaddr_in6 extsa6;
+	struct sockaddr_in6 extsa;
+#else
+	struct sockaddr_in intsa;
+	struct sockaddr_in extsa;
+#endif
 	struct passwords *pwl;
 	struct auth * authenticate;
 	AUTHFUNC authfunc;
@@ -525,6 +582,25 @@ struct child {
 	unsigned char **argv;
 };
 
+struct hashentry {
+	unsigned char hash[sizeof(unsigned)*4];
+	time_t expires;
+	struct hashentry *next;
+	char value[4];
+};
+
+struct hashtable {
+	unsigned hashsize;
+	unsigned recsize;
+	unsigned rnd[4];
+	struct hashentry ** hashtable;
+	void * hashvalues;
+	struct hashentry * hashempty;
+};
+
+extern struct hashtable dns_table;
+extern struct hashtable dns6_table;
+
 struct sockfuncs {
 #ifdef _WIN32
 	SOCKET (WINAPI *_socket)(int domain, int type, int protocol);
@@ -567,22 +643,22 @@ extern struct sockfuncs so;
 struct pluginlink {
 	struct symbol symbols;
 	struct extparam *conf;
-	unsigned long *nservers;
+	struct nserver *nservers;
 	int * linenum;
 	struct auth *authfuncs;
 	struct commands * commandhandlers;
 	void * (*findbyname)(const char *name);
 	int (*socksend)(SOCKET sock, unsigned char * buf, int bufsize, int to);
-	int (*socksendto)(SOCKET sock, struct sockaddr_in * sin, unsigned char * buf, int bufsize, int to);
-	int (*sockrecvfrom)(SOCKET sock, struct sockaddr_in * sin, unsigned char * buf, int bufsize, int to);
+	int (*socksendto)(SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to);
+	int (*sockrecvfrom)(SOCKET sock, struct sockaddr * sin, unsigned char * buf, int bufsize, int to);
 	int (*sockgetcharcli)(struct clientparam * param, int timeosec, int timeousec);
 	int (*sockgetcharsrv)(struct clientparam * param, int timeosec, int timeousec);
 	int (*sockgetlinebuf)(struct clientparam * param, DIRECTION which, unsigned char * buf, int bufsize, int delim, int to);
-	int (*myinet_ntoa)(struct in_addr in, char * buf);
+	int (*myinet_ntop)(int af, void *src, char *dst, socklen_t size);
 	int (*dobuf)(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec);
 	int (*dobuf2)(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format);
 	int (*scanaddr)(const unsigned char *s, unsigned long * ip, unsigned long * mask);
-	unsigned long (*getip)(unsigned char *name);
+	unsigned long (*getip46)(int family, unsigned char *name,  struct sockaddr *sa);
 	int (*sockmap)(struct clientparam * param, int timeo);
 	int (*ACLMatches)(struct ace* acentry, struct clientparam * param);
 	int (*alwaysauth)(struct clientparam * param);
@@ -615,6 +691,17 @@ struct pluginlink {
 	unsigned char * (*dologname) (unsigned char *buf, unsigned char *name, const unsigned char *ext, ROTATION lt, time_t t);
 };
 
+struct counter_header {
+	unsigned char sig[4];
+	time_t updated;
+};
+
+struct counter_record {
+	uint64_t traf64;
+	time_t cleared;
+	time_t updated;
+};
+
 extern struct pluginlink pluginlink;
 extern char *rotations[];
 
@@ -634,9 +721,11 @@ typedef enum {
 	TYPE_SHORT,
 	TYPE_CHAR,
 	TYPE_UNSIGNED,
+	TYPE_UNSIGNED64,
 	TYPE_TRAFFIC,
 	TYPE_PORT,
 	TYPE_IP,
+	TYPE_SA,
 	TYPE_CIDR,
 	TYPE_STRING,
 	TYPE_DATETIME,
@@ -657,19 +746,7 @@ typedef enum {
 	TYPE_SERVER
 }DATA_TYPE;
 
-struct hashentry {
-	unsigned char hash[sizeof(unsigned)*4];
-	unsigned long value;
-	time_t expires;
-	struct hashentry *next;
-};
 
-struct hashtable {
-	unsigned hashsize;
-	struct hashentry ** hashtable;
-	struct hashentry * hashvalues;
-	struct hashentry * hashempty;
-};
 
 #ifdef  __cplusplus
 }

+ 0 - 1
src/tcppm.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: tcppm.c,v 1.15 2012-02-05 22:29:02 vlad Exp $
 */
 
 #include "proxy.h"

+ 15 - 14
src/udppm.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: udppm.c,v 1.27 2012-02-05 22:29:03 vlad Exp $
 */
 
 #include "proxy.h"
@@ -40,7 +39,7 @@ void * udppmchild(struct clientparam* param) {
 
 
  if(!param->hostname)parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport));
- if (!param->req.sin_addr.s_addr) {
+ if (SAISNULL(&param->req)) {
 	param->srv->fds.events = POLLIN;
 	RETURN (100);
  }
@@ -49,7 +48,7 @@ void * udppmchild(struct clientparam* param) {
 	RETURN (21);
  }
  param->cliinbuf = param->clioffset = 0;
- i = sockrecvfrom(param->srv->srvsock, &param->sinc, param->clibuf, param->clibufsize, 0);
+ i = sockrecvfrom(param->srv->srvsock, (struct sockaddr *)&param->sincr, param->clibuf, param->clibufsize, 0);
  if(i<=0){
 	param->srv->fds.events = POLLIN;
 	RETURN (214);
@@ -57,32 +56,34 @@ void * udppmchild(struct clientparam* param) {
  param->cliinbuf = i;
 
 #ifdef _WIN32
-	if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
+	if((param->clisock=so._socket(SASOCK(&param->sincr), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
 		RETURN(818);
 	}
 	if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);};
 	ioctlsocket(param->clisock, FIONBIO, &ul);
-	size = sizeof(struct sockaddr_in);
-	if(so._getsockname(param->srv->srvsock, (struct sockaddr *)&param->sins, &size)) {RETURN(21);};
-	if(so._bind(param->clisock,(struct sockaddr *)&param->sins,sizeof(struct sockaddr_in))) {
+	size = sizeof(param->sinsl);
+	if(so._getsockname(param->srv->srvsock, (struct sockaddr *)&param->sinsl, &size)) {RETURN(21);};
+	if(so._bind(param->clisock,(struct sockaddr *)&param->sinsl,sizeof(struct sockaddr_in))) {
 		RETURN(822);
 	}
 #else
 	param->clisock = param->srv->srvsock;
 #endif
 
- param->sins.sin_family = AF_INET;
- param->sins.sin_port = htons(0);
- param->sins.sin_addr.s_addr = param->extip;
- if ((param->remsock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
- if(so._bind(param->remsock,(struct sockaddr *)&param->sins,sizeof(param->sins))) {RETURN (12);}
+#ifndef NOIPV6
+ memcpy(&param->sinsl, *SAFAMILY(&param->req) == AF_INET? (struct sockaddr *)&param->srv->extsa : (struct sockaddr *)&param->srv->extsa6, SASIZE(&param->req));
+#else
+ memcpy(&param->sinsl, &param->srv->extsa, SASIZE(&param->req));
+#endif
+ *SAPORT(&param->sinsl) = 0;
+ if ((param->remsock=so._socket(SASOCK(&param->sinsl), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);}
+ if(so._bind(param->remsock,(struct sockaddr *)&param->sinsl,sizeof(param->sinsl))) {RETURN (12);}
 #ifdef _WIN32
 	ioctlsocket(param->remsock, FIONBIO, &ul);
 #else
 	fcntl(param->remsock,F_SETFL,O_NONBLOCK);
 #endif
- param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr;
- param->sins.sin_port = param->req.sin_port;
+ memcpy(&param->sinsr, &param->req, sizeof(param->req));
 
  param->operation = UDPASSOC;
  if((res = (*param->srv->authfunc)(param))) {RETURN(res);}

+ 2 - 2
src/version.h

@@ -1,2 +1,2 @@
-#define VERSION "3proxy-0.7.1.3"
-#define BUILDDATE "150916004303"
+#define VERSION "3proxy-0.8b-devel"
+#define BUILDDATE "160107200335"

+ 10 - 17
src/webadmin.c

@@ -4,7 +4,6 @@
 
    please read License Agreement
 
-   $Id: webadmin.c,v 1.44 2014-04-07 20:35:12 vlad Exp $
 */
 
 #include "proxy.h"
@@ -319,21 +318,15 @@ static int printuserlist(char *buf, int bufsize, struct userlist* ul, char * del
 	return printed;
 }
 
+
+int printiple(char *buf, struct iplist* ipl);
+
 static int printiplist(char *buf, int bufsize, struct iplist* ipl, char * delim){
 	int printed = 0;
 	for(; ipl; ipl = ipl->next){
-		if(printed > (bufsize - 64)) break;
-		printed += sprintf(buf+printed, "%u.%u.%u.%u mask %u.%u.%u.%u%s",
-			(unsigned)(ntohl(ipl->ip)&0xff000000)>>24,
-			(unsigned)(ntohl(ipl->ip)&0x00ff0000)>>16,
-			(unsigned)(ntohl(ipl->ip)&0x0000ff00)>>8,
-			(unsigned)(ntohl(ipl->ip)&0x000000ff),
-			(unsigned)(ntohl(ipl->mask)&0xff000000)>>24,
-			(unsigned)(ntohl(ipl->mask)&0x00ff0000)>>16,
-			(unsigned)(ntohl(ipl->mask)&0x0000ff00)>>8,
-			(unsigned)(ntohl(ipl->mask)&0x000000ff),
-			ipl->next?delim:"");
-		if(printed > (bufsize - 64)) {
+		if(printed > (bufsize - 128)) break;
+		printed += printiple(buf+printed, ipl);
+		if(printed > (bufsize - 128)) {
 			printed += sprintf(buf+printed, "...");
 			break;
 		}
@@ -476,13 +469,13 @@ void * adminchild(struct clientparam* param) {
 			 }
 			 else {
 			  inbuf += sprintf(buf+inbuf,	
-					"</td><td>%.3f</td>"
+					"</td><td>%"PRINTF_INT64_MODIFIER"u</td>"
 					"<td>MB%s</td>"
-					"<td>%.3f MB</td>"
+					"<td>%"PRINTF_INT64_MODIFIER"u</td>"
 					"<td>%s</td>",
-				 (4 * 1024.0 * (float)cp->traflimgb) + (float)cp->traflim/(1024.*1024.),
+				 cp->traflim64,
 				 rotations[cp->type],
-				 (4 * 1024.0 * (float)cp->trafgb) + (float)cp->traf/(1024.*1024.),
+				 cp->traf64,
 				 cp->cleared?ctime(&cp->cleared):"never"
 				);
 			 inbuf += sprintf(buf + inbuf,

Некоторые файлы не были показаны из-за большого количества измененных файлов