# HG changeset patch # User Igor Sysoev # Date 1242590400 -14400 # Node ID 98143f74eb3d9d87babc0934c9cd7c40b7af277a # Parent bb2281a3edb67076a5de0ba31dde7d4831551208 nginx 0.7.58 *) Feature: a "listen" directive of the mail proxy module supports IPv6. *) Feature: the "image_filter_jpeg_quality" directive. *) Feature: the "client_body_in_single_buffer" directive. *) Feature: the $request_body variable. *) Bugfix: in ngx_http_autoindex_module in file name links having a ":" symbol in the name. *) Bugfix: "make upgrade" procedure did not work; the bug had appeared in 0.7.53. Thanks to Denis F. Latypoff. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,22 @@ +Changes with nginx 0.7.58 18 May 2009 + + *) Feature: a "listen" directive of the mail proxy module supports IPv6. + + *) Feature: the "image_filter_jpeg_quality" directive. + + *) Feature: the "client_body_in_single_buffer" directive. + + *) Feature: the $request_body variable. + + *) Bugfix: in ngx_http_autoindex_module in file name links having a ":" + symbol in the name. + + *) Bugfix: "make upgrade" procedure did not work; the bug had appeared + in 0.7.53. + Thanks to Denis F. Latypoff. + + Changes with nginx 0.7.57 12 May 2009 *) Bugfix: a segmentation fault occurred in worker process, if the diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,23 @@ +Изменения в nginx 0.7.58 18.05.2009 + + *) Добавление: директива listen почтового прокси-сервера поддерживает + IPv6. + + *) Добавление: директива image_filter_jpeg_quality. + + *) Добавление: директива client_body_in_single_buffer. + + *) Добавление: переменная $request_body. + + *) Исправление: в модуле ngx_http_autoindex_module в ссылках на имена + файлов, содержащих символ ":". + + *) Исправление: процедура "make upgrade" не работала; ошибка появилась + в 0.7.53. + Спасибо Денису Латыпову. + + Изменения в nginx 0.7.57 12.05.2009 *) Исправление: при перенаправлении ошибок модуля diff --git a/auto/cc/owc b/auto/cc/owc --- a/auto/cc/owc +++ b/auto/cc/owc @@ -88,8 +88,16 @@ ngx_binext=".exe" ngx_regex_dirsep='\\' ngx_dirsep="\\" -ngx_regex_cont=' ' -ngx_long_regex_cont=' ' -ngx_cont=' ' -ngx_long_cont=' ' -ngx_tab=' ' +ngx_long_start=' ' +ngx_long_end=' ' +ngx_long_regex_cont=' \&\ + ' +ngx_long_cont=' & + ' + +ngx_regex_cont=' \&\ + ' +ngx_cont=' & + ' +ngx_tab=' & + ' diff --git a/auto/init b/auto/init --- a/auto/init +++ b/auto/init @@ -43,36 +43,8 @@ fi cat << END > Makefile -build: - \$(MAKE) -f $NGX_MAKEFILE - -install: - \$(MAKE) -f $NGX_MAKEFILE install +default: build clean: rm -rf Makefile $NGX_OBJS - -upgrade: - $NGX_SBIN_PATH -t - - kill -USR2 \`cat $NGX_PID_PATH\` - sleep 1 - test -f $NGX_PID_PATH.oldbin - - kill -QUIT \`cat $NGX_PID_PATH.oldbin\` - -upgrade1: - # upgrade 0.1.x to 0.2+ - - $NGX_SBIN_PATH -t - - cp $NGX_PID_PATH $NGX_PID_PATH.oldbin - - kill -USR2 \`cat $NGX_PID_PATH\` - sleep 1 - test -f $NGX_PID_PATH.oldbin - - cp $NGX_PID_PATH $NGX_PID_PATH.newbin - - kill -QUIT \`cat $NGX_PID_PATH.oldbin\` END diff --git a/auto/install b/auto/install --- a/auto/install +++ b/auto/install @@ -124,3 +124,39 @@ if test -n "\$(DESTDIR)$NGX_ERROR_LOG_PA END fi + + +# create Makefile + +cat << END >> Makefile + +build: + \$(MAKE) -f $NGX_MAKEFILE + +install: + \$(MAKE) -f $NGX_MAKEFILE install + +upgrade: + $NGX_SBIN_PATH -t + + kill -USR2 \`cat $NGX_PID_PATH\` + sleep 1 + test -f $NGX_PID_PATH.oldbin + + kill -QUIT \`cat $NGX_PID_PATH.oldbin\` + +upgrade1: + # upgrade 0.1.x to 0.2+ + + $NGX_SBIN_PATH -t + + cp $NGX_PID_PATH $NGX_PID_PATH.oldbin + + kill -USR2 \`cat $NGX_PID_PATH\` + sleep 1 + test -f $NGX_PID_PATH.oldbin + + cp $NGX_PID_PATH $NGX_PID_PATH.newbin + + kill -QUIT \`cat $NGX_PID_PATH.oldbin\` +END diff --git a/auto/lib/md5/make b/auto/lib/md5/make --- a/auto/lib/md5/make +++ b/auto/lib/md5/make @@ -7,16 +7,19 @@ case "$NGX_CC_NAME" in msvc*) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC MD5_ASM=$MD5_ASM" + ngx_md5="MD5=\"$MD5\"" ;; owc*) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" + ngx_md5=`echo MD5=\"$MD5\" | sed -e "s/\//$ngx_regex_dirsep/g"` ;; bcc) ngx_makefile=makefile.bcc ngx_opt="-DCPU_OPT=\"$CPU_OPT\" -DMD5_ASM=$MD5_ASM" + ngx_md5=`echo \-DMD5=\"$MD5\" | sed -e "s/\//$ngx_regex_dirsep/g"` ;; esac @@ -28,14 +31,10 @@ done=NO case "$NGX_PLATFORM" in win32) - cp auto/lib/md5/$ngx_makefile $MD5 - cat << END >> $NGX_MAKEFILE `echo "$MD5/md5.lib: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"` - cd `echo $MD5 | sed -e "s/\//$ngx_regex_dirsep/g"` - \$(MAKE) -f $ngx_makefile $ngx_opt - cd \$(CURDIR) + \$(MAKE) -f auto/lib/md5/$ngx_makefile $ngx_opt $ngx_md5 END diff --git a/auto/lib/md5/makefile.bcc b/auto/lib/md5/makefile.bcc --- a/auto/lib/md5/makefile.bcc +++ b/auto/lib/md5/makefile.bcc @@ -7,12 +7,14 @@ CFLAGS = -q -O2 -tWM $(CPU_OPT) -DL_ENDI !if "$(MD5_ASM)" == "YES" md5.lib: + cd $(MD5) bcc32 -c $(CFLAGS) -DMD5_ASM md5_dgst.c tlib md5.lib +md5_dgst.obj +"asm\m-win32.obj" !else md5.lib: + cd $(MD5) bcc32 -c $(CFLAGS) md5_dgst.c tlib md5.lib +md5_dgst.obj diff --git a/auto/lib/md5/makefile.msvc b/auto/lib/md5/makefile.msvc --- a/auto/lib/md5/makefile.msvc +++ b/auto/lib/md5/makefile.msvc @@ -7,12 +7,14 @@ CFLAGS = -nologo -O2 -Ob1 -Oi -Gs $(LIBC !IF "$(MD5_ASM)" == "YES" md5.lib: + cd $(MD5) cl -c $(CFLAGS) -D MD5_ASM md5_dgst.c link -lib -out:md5.lib md5_dgst.obj asm/m-win32.obj !ELSE md5.lib: + cd $(MD5) cl -c $(CFLAGS) md5_dgst.c link -lib -out:md5.lib md5_dgst.obj diff --git a/auto/lib/md5/makefile.owc b/auto/lib/md5/makefile.owc --- a/auto/lib/md5/makefile.owc +++ b/auto/lib/md5/makefile.owc @@ -5,5 +5,6 @@ CFLAGS = -zq -bt=nt -bm -ot -op -oi -oe -s $(CPU_OPT) md5.lib: + cd $(MD5) wcl386 -c $(CFLAGS) -dL_ENDIAN md5_dgst.c wlib -n md5.lib md5_dgst.obj diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf --- a/auto/lib/openssl/conf +++ b/auto/lib/openssl/conf @@ -3,19 +3,19 @@ if [ $OPENSSL != NONE ]; then - CORE_INCS="$CORE_INCS $OPENSSL/include" case "$CC" in - cl|bcc32) + cl | bcc32) have=NGX_OPENSSL . auto/have have=NGX_SSL . auto/have - LINK_DEPS="$LINK_DEPS $OPENSSL/out32/ssleay32.lib" - CORE_LIBS="$CORE_LIBS $OPENSSL/out32/ssleay32.lib" + CFLAGS="$CFLAGS -DNO_SYS_TYPES_H" - LINK_DEPS="$LINK_DEPS $OPENSSL/out32/libeay32.lib" - CORE_LIBS="$CORE_LIBS $OPENSSL/out32/libeay32.lib" + CORE_INCS="$CORE_INCS $OPENSSL/openssl/include" + CORE_DEPS="$CORE_DEPS $OPENSSL/openssl/include/openssl/ssl.h" + CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/ssleay32.lib" + CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libeay32.lib" # libeay32.lib requires gdi32.lib CORE_LIBS="$CORE_LIBS gdi32.lib" @@ -24,6 +24,8 @@ if [ $OPENSSL != NONE ]; then *) have=NGX_OPENSSL . auto/have have=NGX_SSL . auto/have + + CORE_INCS="$CORE_INCS $OPENSSL/include" LINK_DEPS="$LINK_DEPS $OPENSSL/libssl.a $OPENSSL/libcrypto.a" CORE_LIBS="$CORE_LIBS $OPENSSL/libssl.a $OPENSSL/libcrypto.a" ;; diff --git a/auto/lib/openssl/make b/auto/lib/openssl/make --- a/auto/lib/openssl/make +++ b/auto/lib/openssl/make @@ -3,7 +3,7 @@ if test -n "$OPENSSL_OPT"; then - NGX_OPENSSL_CONFIG="./Configure \"$OPENSSL_OPT\"" + NGX_OPENSSL_CONFIG="./Configure $OPENSSL_OPT" else NGX_OPENSSL_CONFIG="./config" fi @@ -14,32 +14,37 @@ case $USE_THREADS in esac case "$CC" in + cl) + cat << END >> $NGX_MAKEFILE -$OPENSSL/out32/ssleay32.lib: - cd $OPENSSL - perl Configure VC-WIN32 no-shared - ms\\do_ms - \$(MAKE) -f ms\\nt.mak - cd \$(CURDIR) +$OPENSSL/openssl/include/openssl/ssl.h: $NGX_MAKEFILE + \$(MAKE) -f auto/lib/openssl/makefile.msvc \ + OPENSSL="$OPENSSL" OPENSSL_OPT="$OPENSSL_OPT" END ;; - bcc32) + cl | bcc32) + + ngx_opt=`echo "-DOPENSSL=\"$OPENSSL\" -DOPENSSL_OPT=\"$OPENSSL_OPT\"" \ + | sed -e "s/\//$ngx_regex_dirsep/g"` + cat << END >> $NGX_MAKEFILE -`echo "$OPENSSL\\out32\\libeay32.lib: $OPENSSL\\out32\\ssleay32.lib" \ +`echo "$OPENSSL\\openssl\\lib\\libeay32.lib: \ + $OPENSSL\\openssl\\include\\openssl\\ssl.h" \ | sed -e "s/\//$ngx_regex_dirsep/g"` -`echo "$OPENSSL\\out32\\ssleay32.lib:" | sed -e "s/\//$ngx_regex_dirsep/g"` - cd `echo "$OPENSSL" | sed -e "s/\//$ngx_regex_dirsep/g"` - perl Configure BC-32 no-shared - ms\\do_nasm - \$(MAKE) -f ms\\bcb.mak - cd \$(CURDIR) +`echo "$OPENSSL\\openssl\\lib\\ssleay32.lib: \ + $OPENSSL\\openssl\\include\\openssl\\ssl.h" \ + | sed -e "s/\//$ngx_regex_dirsep/g"` + +`echo "$OPENSSL\\openssl\\include\\openssl\\ssl.h: $NGX_MAKEFILE" \ + | sed -e "s/\//$ngx_regex_dirsep/g"` + \$(MAKE) -f auto/lib/openssl/makefile.bcc $ngx_opt END @@ -48,7 +53,7 @@ END *) cat << END >> $NGX_MAKEFILE -$OPENSSL/libssl.a: +$OPENSSL/libssl.a: $NGX_MAKEFILE cd $OPENSSL \\ && \$(MAKE) clean \\ && $NGX_OPENSSL_CONFIG no-shared \\ diff --git a/auto/lib/openssl/makefile.bcc b/auto/lib/openssl/makefile.bcc new file mode 100644 --- /dev/null +++ b/auto/lib/openssl/makefile.bcc @@ -0,0 +1,18 @@ + +# Copyright (C) Igor Sysoev + + +all: + cd $(OPENSSL) + + perl Configure BC-32 no-shared --prefix=openssl -DNO_SYS_TYPES_H \ + $(OPENSSL_OPT) + + ms\do_nasm + + $(MAKE) -f ms\bcb.mak + $(MAKE) -f ms\bcb.mak install + + # Borland's make does not expand "[ch]" in + # copy "inc32\openssl\*.[ch]" "openssl\include\openssl" + copy inc32\openssl\*.h openssl\include\openssl diff --git a/auto/lib/openssl/makefile.msvc b/auto/lib/openssl/makefile.msvc new file mode 100644 --- /dev/null +++ b/auto/lib/openssl/makefile.msvc @@ -0,0 +1,14 @@ + +# Copyright (C) Igor Sysoev + + +all: + cd $(OPENSSL) + + perl Configure VC-WIN32 no-shared --prefix=openssl -DNO_SYS_TYPES_H \ + $(OPENSSL_OPT) + + ms\do_ms + + $(MAKE) -f ms\nt.mak + $(MAKE) -f ms\nt.mak install diff --git a/auto/lib/pcre/make b/auto/lib/pcre/make --- a/auto/lib/pcre/make +++ b/auto/lib/pcre/make @@ -7,16 +7,19 @@ case "$NGX_CC_NAME" in msvc*) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC" + ngx_pcre="PCRE=\"$PCRE\"" ;; owc*) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" + ngx_pcre=`echo PCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"` ;; bcc) ngx_makefile=makefile.bcc ngx_opt="-DCPU_OPT=\"$CPU_OPT\"" + ngx_pcre=`echo \-DPCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"` ;; esac @@ -25,25 +28,14 @@ esac case "$NGX_PLATFORM" in win32) - cp auto/lib/pcre/patch.pcre.in $PCRE - cp auto/lib/pcre/patch.pcre.in.owc $PCRE - cp auto/lib/pcre/patch.config.in $PCRE - cp auto/lib/pcre/patch.pcre.c $PCRE - cp auto/lib/pcre/$ngx_makefile $PCRE - - ngx_pcre=`echo $PCRE | sed -e "s/\//$ngx_regex_dirsep/g"` cat << END >> $NGX_MAKEFILE -`echo "$PCRE/pcre.h: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"` - cd $ngx_pcre - \$(MAKE) -f $ngx_makefile pcre.h - cd \$(CURDIR) +`echo "$PCRE/pcre.lib: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"` + \$(MAKE) -f auto/lib/pcre/$ngx_makefile $ngx_pcre $ngx_opt -`echo "$PCRE/pcre.lib: $PCRE/pcre.h" | sed -e "s/\//$ngx_regex_dirsep/g"` - cd $ngx_pcre - \$(MAKE) -f $ngx_makefile $ngx_opt - cd \$(CURDIR) +`echo "$PCRE/pcre.h:" | sed -e "s/\//$ngx_regex_dirsep/g"` + \$(MAKE) -f auto/lib/pcre/$ngx_makefile $ngx_pcre pcre.h END @@ -60,7 +52,6 @@ END && CC="\$(CC)" CFLAGS="$PCRE_OPT" \\ ./configure --disable-shared - $PCRE/.libs/libpcre.a: $PCRE/Makefile cd $PCRE \\ && \$(MAKE) libpcre.la diff --git a/auto/lib/pcre/makefile.bcc b/auto/lib/pcre/makefile.bcc --- a/auto/lib/pcre/makefile.bcc +++ b/auto/lib/pcre/makefile.bcc @@ -3,19 +3,23 @@ CFLAGS = -q -O2 -tWM -w-8004 $(CPU_OPT) -PCREFLAGS = -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 +PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 -pcre.lib: pcre.h - bcc32 -q -edftables dftables.c +pcre.lib: + cd $(PCRE) + + bcc32 -c $(CFLAGS) -I. $(PCREFLAGS) pcre_*.c - dftables > chartables.c + > pcre.lst + for %n in (*.obj) do @echo +%n & >> pcre.lst + echo + >> pcre.lst - bcc32 -c $(CFLAGS) $(PCREFLAGS) maketables.c get.c study.c pcre.c - - tlib pcre.lib +maketables.obj +get.obj +study.obj +pcre.obj + tlib pcre.lib @pcre.lst pcre.h: - patch -o pcre.h pcre.in patch.pcre.in - patch -o config.h config.in patch.config.in - patch < patch.pcre.c + cd $(PCRE) + + copy /y pcre.h.generic pcre.h + copy /y config.h.generic config.h + copy /y pcre_chartables.c.dist pcre_chartables.c diff --git a/auto/lib/pcre/makefile.msvc b/auto/lib/pcre/makefile.msvc --- a/auto/lib/pcre/makefile.msvc +++ b/auto/lib/pcre/makefile.msvc @@ -3,21 +3,19 @@ CFLAGS = -O2 -Ob1 -Oi -Gs $(LIBC) $(CPU_OPT) -PCREFLAGS = -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 +PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 -pcre.lib: pcre.h - cl -Fedftables dftables.c - - dftables > chartables.c +pcre.lib: + cd $(PCRE) - cl -nologo -c $(CFLAGS) $(PCREFLAGS) \ - maketables.c get.c study.c pcre.c + cl -nologo -c $(CFLAGS) -I . $(PCREFLAGS) pcre_*.c - link -lib -out:pcre.lib -verbose:lib \ - maketables.obj get.obj study.obj pcre.obj + link -lib -out:pcre.lib -verbose:lib pcre_*.obj pcre.h: - patch -o pcre.h pcre.in patch.pcre.in - patch -o config.h config.in patch.config.in - patch < patch.pcre.c + cd $(PCRE) + + copy /y pcre.h.generic pcre.h + copy /y config.h.generic config.h + copy /y pcre_chartables.c.dist pcre_chartables.c diff --git a/auto/lib/pcre/makefile.owc b/auto/lib/pcre/makefile.owc --- a/auto/lib/pcre/makefile.owc +++ b/auto/lib/pcre/makefile.owc @@ -3,17 +3,21 @@ CFLAGS = -c -zq -bt=nt -ot -op -oi -oe -s -bm $(CPU_OPT) -PCREFLAGS = -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 +PCREFLAGS = -DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10 -pcre.lib: pcre.h - wcl386 -zq -bt=nt -l=nt -fe=dftables dftables.c - dftables > chartables.c +pcre.lib: + cd $(PCRE) - wcl386 $(CFLAGS) $(PCREFLAGS) maketables.c get.c study.c pcre.c - wlib -n pcre.lib maketables.obj get.obj study.obj pcre.obj + wcl386 $(CFLAGS) -i=. $(PCREFLAGS) pcre_*.c + dir /b *.obj > pcre.lst + + wlib -n pcre.lib @pcre.lst pcre.h: - patch -o pcre.h pcre.in patch.pcre.in.owc - patch -o config.h config.in patch.config.in + cd $(PCRE) + + copy /y pcre.h.generic pcre.h + copy /y config.h.generic config.h + copy /y pcre_chartables.c.dist pcre_chartables.c diff --git a/auto/lib/pcre/patch.config.in b/auto/lib/pcre/patch.config.in deleted file mode 100644 --- a/auto/lib/pcre/patch.config.in +++ /dev/null @@ -1,11 +0,0 @@ ---- config.in Thu Aug 21 14:43:07 2003 -+++ config.in Sun Mar 7 02:37:24 2004 -@@ -28,7 +28,7 @@ - found. */ - - #define HAVE_STRERROR 0 --#define HAVE_MEMMOVE 0 -+#define HAVE_MEMMOVE 1 - - /* There are some non-Unix systems that don't even have bcopy(). If this macro - is false, an emulation is used. If HAVE_MEMMOVE is set to 1, the value of diff --git a/auto/lib/pcre/patch.pcre.c b/auto/lib/pcre/patch.pcre.c deleted file mode 100644 --- a/auto/lib/pcre/patch.pcre.c +++ /dev/null @@ -1,13 +0,0 @@ ---- pcre.c Thu Aug 21 14:43:07 2003 -+++ pcre.c Tue Mar 22 12:56:59 2005 -@@ -246,8 +246,8 @@ - extern "C" void (*pcre_free)(void *) = free; - extern "C" int (*pcre_callout)(pcre_callout_block *) = NULL; - #else --void *(*pcre_malloc)(size_t) = malloc; --void (*pcre_free)(void *) = free; -+void *(__cdecl *pcre_malloc)(size_t) = malloc; -+void (__cdecl *pcre_free)(void *) = free; - int (*pcre_callout)(pcre_callout_block *) = NULL; - #endif - #endif diff --git a/auto/lib/pcre/patch.pcre.in b/auto/lib/pcre/patch.pcre.in deleted file mode 100644 --- a/auto/lib/pcre/patch.pcre.in +++ /dev/null @@ -1,26 +0,0 @@ ---- pcre.in Thu Aug 21 14:43:07 2003 -+++ pcre.h Tue Mar 22 12:56:59 2005 -@@ -10,9 +10,9 @@ - /* The file pcre.h is build by "configure". Do not edit it; instead - make changes to pcre.in. */ - --#define PCRE_MAJOR @PCRE_MAJOR@ --#define PCRE_MINOR @PCRE_MINOR@ --#define PCRE_DATE @PCRE_DATE@ -+#define PCRE_MAJOR 4 -+#define PCRE_MINOR 4 -+#define PCRE_DATE 21-August-2003 - - /* Win32 uses DLL by default */ - -@@ -143,8 +143,8 @@ - have to be different again. */ - - #ifndef VPCOMPAT --PCRE_DATA_SCOPE void *(*pcre_malloc)(size_t); --PCRE_DATA_SCOPE void (*pcre_free)(void *); -+PCRE_DATA_SCOPE void *(__cdecl *pcre_malloc)(size_t); -+PCRE_DATA_SCOPE void (__cdecl *pcre_free)(void *); - PCRE_DATA_SCOPE int (*pcre_callout)(pcre_callout_block *); - #else /* VPCOMPAT */ - extern void *pcre_malloc(size_t); diff --git a/auto/lib/pcre/patch.pcre.in.owc b/auto/lib/pcre/patch.pcre.in.owc deleted file mode 100644 --- a/auto/lib/pcre/patch.pcre.in.owc +++ /dev/null @@ -1,15 +0,0 @@ ---- pcre.in Thu Aug 21 14:43:07 2003 -+++ pcre.h Tue Mar 22 12:56:59 2005 -@@ -10,9 +10,9 @@ - /* The file pcre.h is build by "configure". Do not edit it; instead - make changes to pcre.in. */ - --#define PCRE_MAJOR @PCRE_MAJOR@ --#define PCRE_MINOR @PCRE_MINOR@ --#define PCRE_DATE @PCRE_DATE@ -+#define PCRE_MAJOR 4 -+#define PCRE_MINOR 4 -+#define PCRE_DATE 21-August-2003 - - /* Win32 uses DLL by default */ - diff --git a/auto/lib/sha1/make b/auto/lib/sha1/make --- a/auto/lib/sha1/make +++ b/auto/lib/sha1/make @@ -7,16 +7,19 @@ case "$NGX_CC_NAME" in msvc*) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC SHA1_ASM=$SHA1_ASM" + ngx_sha1="SHA1=\"$SHA1\"" ;; owc*) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" + ngx_sha1=`echo SHA1=\"$SHA1\" | sed -e "s/\//$ngx_regex_dirsep/g"` ;; bcc) ngx_makefile=makefile.bcc ngx_opt="-DCPU_OPT=\"$CPU_OPT\" -DSHA1_ASM=$SHA1_ASM" + ngx_sha1=`echo \-DSHA1=\"$SHA1\" | sed -e "s/\//$ngx_regex_dirsep/g"` ;; esac @@ -28,14 +31,10 @@ done=NO case "$NGX_PLATFORM" in win32) - cp auto/lib/sha1/$ngx_makefile $SHA1 - cat << END >> $NGX_MAKEFILE `echo "$SHA1/sha1.lib: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"` - cd `echo $SHA1 | sed -e "s/\//$ngx_regex_dirsep/g"` - \$(MAKE) -f $ngx_makefile $ngx_opt - cd \$(CURDIR) + \$(MAKE) -f auto/lib/sha1/$ngx_makefile $ngx_opt $ngx_sha1 END diff --git a/auto/lib/sha1/makefile.bcc b/auto/lib/sha1/makefile.bcc --- a/auto/lib/sha1/makefile.bcc +++ b/auto/lib/sha1/makefile.bcc @@ -7,12 +7,14 @@ CFLAGS = -q -O2 -tWM $(CPU_OPT) -DL_ENDI !if "$(SHA1_ASM)" == "YES" sha1.lib: + cd $(SHA1) bcc32 -c $(CFLAGS) -DSHA1_ASM sha1dgst.c tlib sha1.lib +sha1dgst.obj +"asm\s-win32.obj" !else sha1.lib: + cd $(SHA1) bcc32 -c $(CFLAGS) sha1dgst.c tlib sha1.lib +sha1dgst.obj diff --git a/auto/lib/sha1/makefile.msvc b/auto/lib/sha1/makefile.msvc --- a/auto/lib/sha1/makefile.msvc +++ b/auto/lib/sha1/makefile.msvc @@ -7,12 +7,14 @@ CFLAGS = -nologo -O2 -Ob1 -Oi -Gs $(LIBC !IF "$(SHA1_ASM)" == "YES" sha1.lib: + cd $(SHA1) cl -c $(CFLAGS) -D SHA1_ASM sha1dgst.c link -lib -out:sha1.lib sha1dgst.obj asm/s-win32.obj !ELSE sha1.lib: + cd $(SHA1) cl -c $(CFLAGS) sha1dgst.c link -lib -out:sha1.lib sha1dgst.obj diff --git a/auto/lib/sha1/makefile.owc b/auto/lib/sha1/makefile.owc --- a/auto/lib/sha1/makefile.owc +++ b/auto/lib/sha1/makefile.owc @@ -5,5 +5,6 @@ CFLAGS = -zq -bt=nt -bm -ot -op -oi -oe -s $(CPU_OPT) sha1.lib: + cd $(SHA1) wcl386 -c $(CFLAGS) -dL_ENDIAN sha1dgst.c wlib -n sha1.lib sha1dgst.obj diff --git a/auto/lib/zlib/make b/auto/lib/zlib/make --- a/auto/lib/zlib/make +++ b/auto/lib/zlib/make @@ -7,17 +7,20 @@ case "$NGX_CC_NAME" in msvc*) ngx_makefile=makefile.msvc ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC" + ngx_zlib="ZLIB=\"$ZLIB\"" ;; owc*) ngx_makefile=makefile.owc ngx_opt="CPU_OPT=\"$CPU_OPT\"" + ngx_zlib=`echo ZLIB=\"$ZLIB\" | sed -e "s/\//$ngx_regex_dirsep/g"` ;; bcc) ngx_makefile=makefile.bcc ngx_opt="-DCPU_OPT=\"$CPU_OPT\"" + ngx_zlib=`echo \-DZLIB=\"$ZLIB\" | sed -e "s/\//$ngx_regex_dirsep/g"` ;; esac @@ -29,14 +32,10 @@ done=NO case "$NGX_PLATFORM" in win32) - cp auto/lib/zlib/$ngx_makefile $ZLIB - cat << END >> $NGX_MAKEFILE `echo "$ZLIB/zlib.lib: $NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"` - cd `echo $ZLIB | sed -e "s/\//$ngx_regex_dirsep/g"` - \$(MAKE) -f $ngx_makefile $ngx_opt - cd \$(CURDIR) + \$(MAKE) -f auto/lib/zlib/$ngx_makefile $ngx_opt $ngx_zlib END diff --git a/auto/lib/zlib/makefile.bcc b/auto/lib/zlib/makefile.bcc --- a/auto/lib/zlib/makefile.bcc +++ b/auto/lib/zlib/makefile.bcc @@ -5,6 +5,8 @@ CFLAGS = -q -O2 -tWM -w-8004 -w-8012 $(CPU_OPT) zlib.lib: + cd $(ZLIB) + bcc32 -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c \ compress.c diff --git a/auto/lib/zlib/makefile.msvc b/auto/lib/zlib/makefile.msvc --- a/auto/lib/zlib/makefile.msvc +++ b/auto/lib/zlib/makefile.msvc @@ -5,6 +5,8 @@ CFLAGS = -nologo -O2 -Ob1 -Oi -Gs $(LIBC) $(CPU_OPT) zlib.lib: + cd $(ZLIB) + cl -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c compress.c link -lib -out:zlib.lib adler32.obj crc32.obj deflate.obj \ diff --git a/auto/lib/zlib/makefile.owc b/auto/lib/zlib/makefile.owc --- a/auto/lib/zlib/makefile.owc +++ b/auto/lib/zlib/makefile.owc @@ -5,5 +5,9 @@ CFLAGS = -zq -bt=nt -ot -op -oi -oe -s -bm $(CPU_OPT) zlib.lib: - wcl386 -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c compress.c - wlib -n zlib.lib adler32.obj crc32.obj deflate.obj trees.obj zutil.obj compress.obj + cd $(ZLIB) + + wcl386 -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c & + compress.c + wlib -n zlib.lib adler32.obj crc32.obj deflate.obj trees.obj & + zutil.obj compress.obj diff --git a/auto/make b/auto/make --- a/auto/make +++ b/auto/make @@ -22,7 +22,6 @@ CC = $CC CFLAGS = $CFLAGS CPP = $CPP LINK = $LINK -CURDIR = `pwd` END diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,8 +8,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 7057 -#define NGINX_VERSION "0.7.57" +#define nginx_version 7058 +#define NGINX_VERSION "0.7.58" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -446,7 +446,9 @@ ngx_conf_read_token(ngx_conf_t *cf) last_space = 1; sharp_comment = 0; variable = 0; - quoted = s_quoted = d_quoted = 0; + quoted = 0; + s_quoted = 0; + d_quoted = 0; cf->args->nelts = 0; b = cf->conf_file->buffer; diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -811,6 +811,66 @@ ngx_close_connection(ngx_connection_t *c ngx_int_t +ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, + ngx_uint_t port) +{ + socklen_t len; + ngx_uint_t addr; + u_char sa[NGX_SOCKADDRLEN]; + struct sockaddr_in *sin; +#if (NGX_HAVE_INET6) + ngx_uint_t i; + struct sockaddr_in6 *sin6; +#endif + + switch (c->local_sockaddr->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) c->local_sockaddr; + + for (addr = 0, i = 0; addr == 0 && i < 16; i++) { + addr |= sin6->sin6_addr.s6_addr[i]; + } + + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) c->local_sockaddr; + addr = sin->sin_addr.s_addr; + break; + } + + if (addr == 0) { + + len = NGX_SOCKADDRLEN; + + if (getsockname(c->fd, (struct sockaddr *) &sa, &len) == -1) { + ngx_connection_error(c, ngx_socket_errno, "getsockname() failed"); + return NGX_ERROR; + } + + c->local_sockaddr = ngx_palloc(c->pool, len); + if (c->local_sockaddr == NULL) { + return NGX_ERROR; + } + + c->local_socklen = len; + ngx_memcpy(c->local_sockaddr, &sa, len); + } + + if (s == NULL) { + return NGX_OK; + } + + s->len = ngx_sock_ntop(c->local_sockaddr, s->data, s->len, port); + + return NGX_OK; +} + + +ngx_int_t ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text) { ngx_uint_t level; diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -170,6 +170,8 @@ ngx_int_t ngx_open_listening_sockets(ngx void ngx_configure_listening_sockets(ngx_cycle_t *cycle); void ngx_close_listening_sockets(ngx_cycle_t *cycle); void ngx_close_connection(ngx_connection_t *c); +ngx_int_t ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, + ngx_uint_t port); ngx_int_t ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text); ngx_connection_t *ngx_get_connection(ngx_socket_t s, ngx_log_t *log); diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -518,7 +518,6 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx (void) ngx_cpystrn(p, host, len); - u->addr.in_addr = inet_addr((const char *) p); sin->sin_addr.s_addr = inet_addr((const char *) p); if (sin->sin_addr.s_addr == INADDR_NONE) { @@ -530,7 +529,6 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx return NGX_ERROR; } - u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]); sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]); } @@ -541,7 +539,6 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx ngx_free(p); } else { - u->addr.in_addr = INADDR_ANY; sin->sin_addr.s_addr = INADDR_ANY; u->wildcard = 1; } diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h --- a/src/core/ngx_inet.h +++ b/src/core/ngx_inet.h @@ -61,11 +61,6 @@ typedef struct { } ngx_cidr_t; -typedef union { - in_addr_t in_addr; -} ngx_url_addr_t; - - typedef struct { struct sockaddr *sockaddr; socklen_t socklen; @@ -91,8 +86,6 @@ typedef struct { unsigned no_port:1; unsigned wildcard:1; - ngx_url_addr_t addr; - socklen_t socklen; u_char sockaddr[NGX_SOCKADDRLEN]; diff --git a/src/event/modules/ngx_aio_module.c b/src/event/modules/ngx_aio_module.c --- a/src/event/modules/ngx_aio_module.c +++ b/src/event/modules/ngx_aio_module.c @@ -134,12 +134,14 @@ ngx_aio_del_connection(ngx_connection_t ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "aio_cancel: %d", rc); if (rc == AIO_CANCELED) { - c->read->active = c->write->active = 0; + c->read->active = 0; + c->write->active = 0; return NGX_OK; } if (rc == AIO_ALLDONE) { - c->read->active = c->write->active = 0; + c->read->active = 0; + c->write->active = 0; ngx_log_error(NGX_LOG_ALERT, c->log, 0, "aio_cancel() returned AIO_ALLDONE"); return NGX_OK; diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c --- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -25,8 +25,11 @@ typedef struct { typedef struct { ngx_str_t name; size_t utf_len; - ngx_uint_t escape; - ngx_uint_t dir; + size_t escape; + + unsigned dir:1; + unsigned colon:1; + time_t mtime; off_t size; } ngx_http_autoindex_entry_t; @@ -338,6 +341,8 @@ ngx_http_autoindex_handler(ngx_http_requ entry->utf_len = len; } + entry->colon = (ngx_strchr(entry->name.data, ':') != NULL); + entry->dir = ngx_de_is_dir(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); @@ -363,7 +368,7 @@ ngx_http_autoindex_handler(ngx_http_requ + entry[i].name.len + entry[i].escape + 1 /* 1 is for "/" */ + sizeof("\">") - 1 - + entry[i].name.len - entry[i].utf_len + + entry[i].name.len - entry[i].utf_len + entry[i].colon * 2 + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof(">") - 2 + sizeof("") - 1 + sizeof(" 28-Sep-1970 12:00 ") - 1 @@ -396,6 +401,11 @@ ngx_http_autoindex_handler(ngx_http_requ for (i = 0; i < entries.nelts; i++) { b->last = ngx_cpymem(b->last, "last++ = '.'; + *b->last++ = '/'; + } + if (entry[i].escape) { ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len, NGX_ESCAPE_HTML); diff --git a/src/http/modules/ngx_http_image_filter_module.c b/src/http/modules/ngx_http_image_filter_module.c --- a/src/http/modules/ngx_http_image_filter_module.c +++ b/src/http/modules/ngx_http_image_filter_module.c @@ -38,6 +38,7 @@ typedef struct { ngx_uint_t filter; ngx_uint_t width; ngx_uint_t height; + ngx_int_t jpeg_quality; size_t buffer_size; } ngx_http_image_filter_conf_t; @@ -98,6 +99,13 @@ static ngx_command_t ngx_http_image_fil 0, NULL }, + { ngx_string("image_filter_jpeg_quality"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_image_filter_conf_t, jpeg_quality), + NULL }, + { ngx_string("image_filter_buffer"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_size_slot, @@ -886,15 +894,17 @@ static u_char * ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img, int *size) { - char *failed; - u_char *out; + char *failed; + u_char *out; + ngx_http_image_filter_conf_t *conf; out = NULL; switch (type) { case NGX_HTTP_IMAGE_JPEG: - out = gdImageJpegPtr(img, size, /* default quality */ -1); + conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); + out = gdImageJpegPtr(img, size, conf->jpeg_quality); failed = "gdImageJpegPtr() failed"; break; @@ -939,6 +949,7 @@ ngx_http_image_filter_create_conf(ngx_co } conf->filter = NGX_CONF_UNSET_UINT; + conf->jpeg_quality = NGX_CONF_UNSET; conf->buffer_size = NGX_CONF_UNSET_SIZE; return conf; @@ -963,6 +974,9 @@ ngx_http_image_filter_merge_conf(ngx_con } } + /* 75 is libjpeg default quality */ + ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75); + ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 1 * 1024 * 1024); diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c --- a/src/http/modules/ngx_http_userid_filter_module.c +++ b/src/http/modules/ngx_http_userid_filter_module.c @@ -390,12 +390,13 @@ ngx_http_userid_set_uid(ngx_http_request } else { if (conf->service == NGX_CONF_UNSET) { - if (ngx_http_server_addr(r, NULL) != NGX_OK) { + + c = r->connection; + + if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { return NGX_ERROR; } - c = r->connection; - switch (c->local_sockaddr->sa_family) { #if (NGX_HAVE_INET6) diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.7.57'; +our $VERSION = '0.7.58'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -18,7 +18,7 @@ static ngx_int_t ngx_http_init_phase_han ngx_http_core_main_conf_t *cmcf); static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf, - ngx_array_t *servers, ngx_array_t *in_ports); + ngx_array_t *servers, ngx_array_t *ports); static ngx_int_t ngx_http_add_ports(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, ngx_array_t *ports, ngx_http_listen_t *listen); @@ -122,7 +122,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma char *rv; ngx_uint_t mi, m, s; ngx_conf_t pcf; - ngx_array_t in_ports; + ngx_array_t ports; ngx_http_module_t *module; ngx_http_conf_ctx_t *ctx; ngx_http_core_loc_conf_t *clcf; @@ -367,14 +367,14 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma * to find quickly the server core module configuration at run-time */ - if (ngx_http_init_server_lists(cf, &cmcf->servers, &in_ports) != NGX_OK) { + if (ngx_http_init_server_lists(cf, &cmcf->servers, &ports) != NGX_OK) { return NGX_CONF_ERROR; } /* optimize the lists of ports, addresses and server names */ - if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) { + if (ngx_http_optimize_servers(cf, cmcf, &ports) != NGX_OK) { return NGX_CONF_ERROR; } @@ -1180,12 +1180,12 @@ ngx_http_add_ports(ngx_conf_t *cf, ngx_h continue; } - /* a port is already in the in_port list */ + /* a port is already in the port list */ return ngx_http_add_addresses(cf, cscf, &port[i], listen); } - /* add a port to the in_port list */ + /* add a port to the port list */ port = ngx_array_push(ports); if (port == NULL) { @@ -1279,7 +1279,7 @@ ngx_http_add_addresses(ngx_conf_t *cf, n /* * add the server address, the server names and the server core module - * configurations to the port (in_port) + * configurations to the port list */ static ngx_int_t diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -355,12 +355,19 @@ static ngx_command_t ngx_http_core_comm NULL }, { ngx_string("client_body_in_file_only"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_enum_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_core_loc_conf_t, client_body_in_file_only), &ngx_http_core_request_body_in_file }, + { ngx_string("client_body_in_single_buffer"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, client_body_in_single_buffer), + NULL }, + { ngx_string("sendfile"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_TAKE1, @@ -1317,6 +1324,8 @@ ngx_http_update_location_config(ngx_http r->request_body_file_log_level = NGX_LOG_WARN; } + r->request_body_in_single_buf = clcf->client_body_in_single_buffer; + if (r->keepalive && clcf->keepalive_timeout == 0) { r->keepalive = 0; } @@ -1819,68 +1828,6 @@ ngx_http_auth_basic_user(ngx_http_reques } -ngx_int_t -ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s) -{ - socklen_t len; - ngx_uint_t addr; - ngx_connection_t *c; - u_char sa[NGX_SOCKADDRLEN]; - struct sockaddr_in *sin; -#if (NGX_HAVE_INET6) - ngx_uint_t i; - struct sockaddr_in6 *sin6; -#endif - - c = r->connection; - - switch (c->local_sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) c->local_sockaddr; - - for (addr = 0, i = 0; addr == 0 && i < 16; i++) { - addr |= sin6->sin6_addr.s6_addr[i]; - } - - break; -#endif - - default: /* AF_INET */ - sin = (struct sockaddr_in *) c->local_sockaddr; - addr = sin->sin_addr.s_addr; - break; - } - - if (addr == 0) { - - len = NGX_SOCKADDRLEN; - - if (getsockname(c->fd, (struct sockaddr *) &sa, &len) == -1) { - ngx_connection_error(c, ngx_socket_errno, "getsockname() failed"); - return NGX_ERROR; - } - - c->local_sockaddr = ngx_palloc(r->connection->pool, len); - if (c->local_sockaddr == NULL) { - return NGX_ERROR; - } - - c->local_socklen = len; - ngx_memcpy(c->local_sockaddr, &sa, len); - } - - if (s == NULL) { - return NGX_OK; - } - - s->len = ngx_sock_ntop(c->local_sockaddr, s->data, s->len, 0); - - return NGX_OK; -} - - #if (NGX_HTTP_GZIP) ngx_int_t @@ -2953,8 +2900,9 @@ ngx_http_core_create_loc_conf(ngx_conf_t lcf->client_body_timeout = NGX_CONF_UNSET_MSEC; lcf->satisfy = NGX_CONF_UNSET_UINT; lcf->if_modified_since = NGX_CONF_UNSET_UINT; + lcf->client_body_in_file_only = NGX_CONF_UNSET_UINT; + lcf->client_body_in_single_buffer = NGX_CONF_UNSET; lcf->internal = NGX_CONF_UNSET; - lcf->client_body_in_file_only = NGX_CONF_UNSET; lcf->sendfile = NGX_CONF_UNSET; lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE; lcf->directio = NGX_CONF_UNSET; @@ -3144,9 +3092,11 @@ ngx_http_core_merge_loc_conf(ngx_conf_t NGX_HTTP_SATISFY_ALL); ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since, NGX_HTTP_IMS_EXACT); + ngx_conf_merge_uint_value(conf->client_body_in_file_only, + prev->client_body_in_file_only, 0); + ngx_conf_merge_value(conf->client_body_in_single_buffer, + prev->client_body_in_single_buffer, 0); ngx_conf_merge_value(conf->internal, prev->internal, 0); - ngx_conf_merge_value(conf->client_body_in_file_only, - prev->client_body_in_file_only, 0); ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0); ngx_conf_merge_size_value(conf->sendfile_max_chunk, prev->sendfile_max_chunk, 0); diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -339,9 +339,11 @@ struct ngx_http_core_loc_conf_s { ngx_uint_t satisfy; /* satisfy */ ngx_uint_t if_modified_since; /* if_modified_since */ + ngx_uint_t client_body_in_file_only; /* client_body_in_file_only */ + ngx_flag_t client_body_in_single_buffer; + /* client_body_in_singe_buffer */ ngx_flag_t internal; /* internal */ - ngx_flag_t client_body_in_file_only; /* client_body_in_file_only */ ngx_flag_t sendfile; /* sendfile */ ngx_flag_t tcp_nopush; /* tcp_nopush */ ngx_flag_t tcp_nodelay; /* tcp_nodelay */ @@ -438,7 +440,6 @@ ngx_int_t ngx_http_set_exten(ngx_http_re u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name, size_t *root_length, size_t reserved); ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r); -ngx_int_t ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s); #if (NGX_HTTP_GZIP) ngx_int_t ngx_http_gzip_ok(ngx_http_request_t *r); #endif diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -165,6 +165,7 @@ ngx_http_header_filter(ngx_http_request_ ngx_chain_t out; ngx_list_part_t *part; ngx_table_elt_t *header; + ngx_connection_t *c; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; struct sockaddr_in *sin; @@ -309,6 +310,8 @@ ngx_http_header_filter(ngx_http_request_ len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1; } + c = r->connection; + if (r->headers_out.location && r->headers_out.location->value.len && r->headers_out.location->value.data[0] == '/') @@ -326,21 +329,21 @@ ngx_http_header_filter(ngx_http_request_ host.len = NGX_SOCKADDR_STRLEN; host.data = addr; - if (ngx_http_server_addr(r, &host) != NGX_OK) { + if (ngx_connection_local_sockaddr(c, &host, 0) != NGX_OK) { return NGX_ERROR; } } - switch (r->connection->local_sockaddr->sa_family) { + switch (c->local_sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: - sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr; + sin6 = (struct sockaddr_in6 *) c->local_sockaddr; port = ntohs(sin6->sin6_port); break; #endif default: /* AF_INET */ - sin = (struct sockaddr_in *) r->connection->local_sockaddr; + sin = (struct sockaddr_in *) c->local_sockaddr; port = ntohs(sin->sin_port); break; } @@ -352,7 +355,7 @@ ngx_http_header_filter(ngx_http_request_ if (clcf->port_in_redirect) { #if (NGX_HTTP_SSL) - if (r->connection->ssl) + if (c->ssl) port = (port == 443) ? 0 : port; else #endif @@ -511,7 +514,7 @@ ngx_http_header_filter(ngx_http_request_ sizeof("Location: http") - 1); #if (NGX_HTTP_SSL) - if (r->connection->ssl) { + if (c->ssl) { *b->last++ ='s'; } #endif @@ -588,7 +591,7 @@ ngx_http_header_filter(ngx_http_request_ *b->last++ = CR; *b->last++ = LF; } - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "%*s", (size_t) (b->last - b->pos), b->pos); /* the end of HTTP header */ diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -310,7 +310,7 @@ ngx_http_init_request(ngx_event_t *rev) * is required to determine a server address */ - if (ngx_http_server_addr(r, NULL) != NGX_OK) { + if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { ngx_http_close_connection(c); return; } @@ -321,7 +321,7 @@ ngx_http_init_request(ngx_event_t *rev) case AF_INET6: sin6 = (struct sockaddr_in6 *) c->local_sockaddr; - addr6 = (ngx_http_in6_addr_t *) port->addrs; + addr6 = port->addrs; /* the last address is "*" */ @@ -360,7 +360,7 @@ ngx_http_init_request(ngx_event_t *rev) #if (NGX_HAVE_INET6) case AF_INET6: - addr6 = (ngx_http_in6_addr_t *) port->addrs; + addr6 = port->addrs; addr_conf = &addr6[0].conf; break; #endif diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -972,7 +972,9 @@ ngx_http_upstream_connect(ngx_http_reque u->output.sendfile = c->sendfile; c->pool = r->pool; - c->read->log = c->write->log = c->log = r->connection->log; + c->log = r->connection->log; + c->read->log = c->log; + c->write->log = c->log; /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */ diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -62,6 +62,8 @@ static ngx_int_t ngx_http_variable_body_ ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_request_body(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -202,6 +204,10 @@ static ngx_http_variable_t ngx_http_cor ngx_http_variable_request_completion, 0, 0, 0 }, + { ngx_string("request_body"), NULL, + ngx_http_variable_request_body, + 0, 0, 0 }, + { ngx_string("request_body_file"), NULL, ngx_http_variable_request_body_file, 0, 0, 0 }, @@ -932,7 +938,7 @@ ngx_http_variable_server_addr(ngx_http_r s.len = NGX_SOCKADDR_STRLEN; s.data = addr; - if (ngx_http_server_addr(r, &s) != NGX_OK) { + if (ngx_connection_local_sockaddr(r->connection, &s, 0) != NGX_OK) { return NGX_ERROR; } @@ -968,7 +974,7 @@ ngx_http_variable_server_port(ngx_http_r v->no_cacheable = 0; v->not_found = 0; - if (ngx_http_server_addr(r, NULL) != NGX_OK) { + if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) { return NGX_ERROR; } @@ -1478,6 +1484,56 @@ ngx_http_variable_request_completion(ngx static ngx_int_t +ngx_http_variable_request_body(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + size_t len; + ngx_buf_t *buf, *next; + ngx_chain_t *cl; + + if (r->request_body == NULL || r->request_body->temp_file) { + v->not_found = 1; + + return NGX_OK; + } + + cl = r->request_body->bufs; + buf = cl->buf; + + if (cl->next == NULL) { + v->len = buf->last - buf->pos; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = buf->pos; + + return NGX_OK; + } + + next = cl->next->buf; + len = (buf->last - buf->pos) + (next->last - next->pos); + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + v->data = p; + + p = ngx_cpymem(p, buf->pos, buf->last - buf->pos); + ngx_memcpy(p, next->pos, next->last - next->pos); + + v->len = len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c +++ b/src/mail/ngx_mail.c @@ -11,7 +11,16 @@ static char *ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static ngx_int_t ngx_mail_cmp_conf_in_addrs(const void *one, const void *two); +static ngx_int_t ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports, + ngx_mail_listen_t *listen); +static char *ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports); +static ngx_int_t ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr); +#if (NGX_HAVE_INET6) +static ngx_int_t ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr); +#endif +static ngx_int_t ngx_mail_cmp_conf_addrs(const void *one, const void *two); ngx_uint_t ngx_mail_max_module; @@ -64,19 +73,12 @@ static char * ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; - u_char *text; - size_t len; - ngx_uint_t i, a, l, m, mi, s, p, last, bind_all, done; + ngx_uint_t i, m, mi, s; ngx_conf_t pcf; - ngx_array_t in_ports; - ngx_listening_t *ls; - ngx_mail_listen_t *mls; + ngx_array_t ports; + ngx_mail_listen_t *listen; ngx_mail_module_t *module; - struct sockaddr_in sin; - ngx_mail_in_port_t *mip; ngx_mail_conf_ctx_t *ctx; - ngx_mail_conf_in_port_t *in_port; - ngx_mail_conf_in_addr_t *in_addr; ngx_mail_core_srv_conf_t **cscfp; ngx_mail_core_main_conf_t *cmcf; @@ -217,98 +219,149 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma *cf = pcf; - if (ngx_array_init(&in_ports, cf->temp_pool, 4, - sizeof(ngx_mail_conf_in_port_t)) + if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_mail_conf_port_t)) != NGX_OK) { return NGX_CONF_ERROR; } - mls = cmcf->listen.elts; - - for (l = 0; l < cmcf->listen.nelts; l++) { - - /* AF_INET only */ + listen = cmcf->listen.elts; - in_port = in_ports.elts; - for (p = 0; p < in_ports.nelts; p++) { - if (in_port[p].port == mls[l].port) { - in_port = &in_port[p]; - goto found; - } - } - - in_port = ngx_array_push(&in_ports); - if (in_port == NULL) { - return NGX_CONF_ERROR; - } - - in_port->port = mls[l].port; - - if (ngx_array_init(&in_port->addrs, cf->temp_pool, 2, - sizeof(ngx_mail_conf_in_addr_t)) - != NGX_OK) - { + for (i = 0; i < cmcf->listen.nelts; i++) { + if (ngx_mail_add_ports(cf, &ports, &listen[i]) != NGX_OK) { return NGX_CONF_ERROR; } + } - found: + return ngx_mail_optimize_servers(cf, &ports); +} + + +static ngx_int_t +ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports, + ngx_mail_listen_t *listen) +{ + in_port_t p; + ngx_uint_t i; + struct sockaddr *sa; + struct sockaddr_in *sin; + ngx_mail_conf_port_t *port; + ngx_mail_conf_addr_t *addr; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif + + sa = (struct sockaddr *) &listen->sockaddr; - in_addr = ngx_array_push(&in_port->addrs); - if (in_addr == NULL) { - return NGX_CONF_ERROR; + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + p = sin6->sin6_port; + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) sa; + p = sin->sin_port; + break; + } + + port = ports->elts; + for (i = 0; i < ports->nelts; i++) { + if (p == port[i].port && sa->sa_family == port[i].family) { + + /* a port is already in the port list */ + + port = &port[i]; + goto found; } - - in_addr->addr = mls[l].addr; - in_addr->ctx = mls[l].ctx; - in_addr->bind = mls[l].bind; -#if (NGX_MAIL_SSL) - in_addr->ssl = mls[l].ssl; -#endif } - /* optimize the lists of ports and addresses */ + /* add a port to the port list */ + + port = ngx_array_push(ports); + if (port == NULL) { + return NGX_ERROR; + } + + port->family = sa->sa_family; + port->port = p; - /* AF_INET only */ + if (ngx_array_init(&port->addrs, cf->temp_pool, 2, + sizeof(ngx_mail_conf_addr_t)) + != NGX_OK) + { + return NGX_ERROR; + } + +found: + + addr = ngx_array_push(&port->addrs); + if (addr == NULL) { + return NGX_ERROR; + } - in_port = in_ports.elts; - for (p = 0; p < in_ports.nelts; p++) { + addr->sockaddr = (struct sockaddr *) &listen->sockaddr; + addr->socklen = listen->socklen; + addr->ctx = listen->ctx; + addr->bind = listen->bind; + addr->wildcard = listen->wildcard; +#if (NGX_MAIL_SSL) + addr->ssl = listen->ssl; +#endif +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + addr->ipv6only = listen->ipv6only; +#endif + + return NGX_OK; +} + - ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts, - sizeof(ngx_mail_conf_in_addr_t), ngx_mail_cmp_conf_in_addrs); +static char * +ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports) +{ + ngx_uint_t i, p, last, bind_wildcard; + ngx_listening_t *ls; + ngx_mail_port_t *mport; + ngx_mail_conf_port_t *port; + ngx_mail_conf_addr_t *addr; - in_addr = in_port[p].addrs.elts; - last = in_port[p].addrs.nelts; + port = ports->elts; + for (p = 0; p < ports->nelts; p++) { + + ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts, + sizeof(ngx_mail_conf_addr_t), ngx_mail_cmp_conf_addrs); + + addr = port[p].addrs.elts; + last = port[p].addrs.nelts; /* * if there is the binding to the "*:port" then we need to bind() * to the "*:port" only and ignore the other bindings */ - if (in_addr[last - 1].addr == INADDR_ANY) { - in_addr[last - 1].bind = 1; - bind_all = 0; + if (addr[last - 1].wildcard) { + addr[last - 1].bind = 1; + bind_wildcard = 1; } else { - bind_all = 1; + bind_wildcard = 0; } - for (a = 0; a < last; /* void */ ) { + i = 0; - if (!bind_all && !in_addr[a].bind) { - a++; + while (i < last) { + + if (bind_wildcard && !addr[i].bind) { + i++; continue; } - ngx_memzero(&sin, sizeof(struct sockaddr_in)); - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = in_addr[a].addr; - sin.sin_port = htons(in_port[p].port); - - ls = ngx_create_listening(cf, &sin, sizeof(struct sockaddr_in)); + ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen); if (ls == NULL) { - return NULL; + return NGX_CONF_ERROR; } ls->addr_ntop = 1; @@ -320,75 +373,42 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma ls->log.data = &ls->addr_text; ls->log.handler = ngx_accept_log_error; - mip = ngx_palloc(cf->pool, sizeof(ngx_mail_in_port_t)); - if (mip == NULL) { +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + ls->ipv6only = addr[i].ipv6only; +#endif + + mport = ngx_palloc(cf->pool, sizeof(ngx_mail_port_t)); + if (mport == NULL) { return NGX_CONF_ERROR; } - ls->servers = mip; - - in_addr = in_port[p].addrs.elts; + ls->servers = mport; - if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) { - mip->naddrs = 1; - done = 0; - - } else if (in_port[p].addrs.nelts > 1 - && in_addr[last - 1].addr == INADDR_ANY) - { - mip->naddrs = last; - done = 1; + if (i == last - 1) { + mport->naddrs = last; } else { - mip->naddrs = 1; - done = 0; + mport->naddrs = 1; + i = 0; } -#if 0 - ngx_log_error(NGX_LOG_ALERT, cf->log, 0, - "%ui: %V %d %ui %ui", - a, &ls->addr_text, in_addr[a].bind, - mip->naddrs, last); -#endif - - mip->addrs = ngx_pcalloc(cf->pool, - mip->naddrs * sizeof(ngx_mail_in_addr_t)); - if (mip->addrs == NULL) { - return NGX_CONF_ERROR; - } - - for (i = 0; i < mip->naddrs; i++) { - mip->addrs[i].addr = in_addr[i].addr; - mip->addrs[i].ctx = in_addr[i].ctx; - - text = ngx_pnalloc(cf->pool, - NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1); - if (text == NULL) { + switch (ls->sockaddr->sa_family) { +#if (NGX_HAVE_INET6) + case AF_INET6: + if (ngx_mail_add_addrs6(cf, mport, addr) != NGX_OK) { return NGX_CONF_ERROR; } - - len = ngx_inet_ntop(AF_INET, &in_addr[i].addr, text, - NGX_INET_ADDRSTRLEN); - - len = ngx_sprintf(text + len, ":%d", in_port[p].port) - text; - - mip->addrs[i].addr_text.len = len; - mip->addrs[i].addr_text.data = text; - -#if (NGX_MAIL_SSL) - mip->addrs[i].ssl = in_addr[i].ssl; + break; #endif - } - - if (done) { + default: /* AF_INET */ + if (ngx_mail_add_addrs(cf, mport, addr) != NGX_OK) { + return NGX_CONF_ERROR; + } break; } - in_addr++; - in_port[p].addrs.elts = in_addr; + addr++; last--; - - a = 0; } } @@ -397,15 +417,111 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma static ngx_int_t -ngx_mail_cmp_conf_in_addrs(const void *one, const void *two) +ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr) { - ngx_mail_conf_in_addr_t *first, *second; + u_char *p; + size_t len; + ngx_uint_t i; + ngx_mail_in_addr_t *addrs; + struct sockaddr_in *sin; + u_char buf[NGX_SOCKADDR_STRLEN]; + + mport->addrs = ngx_pcalloc(cf->pool, + mport->naddrs * sizeof(ngx_mail_in_addr_t)); + if (mport->addrs == NULL) { + return NGX_ERROR; + } + + addrs = mport->addrs; + + for (i = 0; i < mport->naddrs; i++) { + + sin = (struct sockaddr_in *) addr[i].sockaddr; + addrs[i].addr = sin->sin_addr.s_addr; + + addrs[i].conf.ctx = addr[i].ctx; +#if (NGX_MAIL_SSL) + addrs[i].conf.ssl = addr[i].ssl; +#endif + + len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1); + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, buf, len); + + addrs[i].conf.addr_text.len = len; + addrs[i].conf.addr_text.data = p; + } + + return NGX_OK; +} + + +#if (NGX_HAVE_INET6) - first = (ngx_mail_conf_in_addr_t *) one; - second = (ngx_mail_conf_in_addr_t *) two; +static ngx_int_t +ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport, + ngx_mail_conf_addr_t *addr) +{ + u_char *p; + size_t len; + ngx_uint_t i; + ngx_mail_in6_addr_t *addrs6; + struct sockaddr_in6 *sin6; + u_char buf[NGX_SOCKADDR_STRLEN]; + + mport->addrs = ngx_pcalloc(cf->pool, + mport->naddrs * sizeof(ngx_mail_in6_addr_t)); + if (mport->addrs == NULL) { + return NGX_ERROR; + } + + addrs6 = mport->addrs; + + for (i = 0; i < mport->naddrs; i++) { + + sin6 = (struct sockaddr_in6 *) addr[i].sockaddr; + addrs6[i].addr6 = sin6->sin6_addr; + + addrs6[i].conf.ctx = addr[i].ctx; +#if (NGX_MAIL_SSL) + addrs6[i].conf.ssl = addr[i].ssl; +#endif - if (first->addr == INADDR_ANY) { - /* the INADDR_ANY must be the last resort, shift it to the end */ + len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1); + + p = ngx_pnalloc(cf->pool, len); + if (p == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(p, buf, len); + + addrs6[i].conf.addr_text.len = len; + addrs6[i].conf.addr_text.data = p; + } + + return NGX_OK; +} + +#endif + + +static ngx_int_t +ngx_mail_cmp_conf_addrs(const void *one, const void *two) +{ + ngx_mail_conf_addr_t *first, *second; + + first = (ngx_mail_conf_addr_t *) one; + second = (ngx_mail_conf_addr_t *) two; + + if (first->wildcard) { + /* a wildcard must be the last resort, shift it to the end */ return 1; } diff --git a/src/mail/ngx_mail.h b/src/mail/ngx_mail.h --- a/src/mail/ngx_mail.h +++ b/src/mail/ngx_mail.h @@ -26,50 +26,76 @@ typedef struct { typedef struct { - in_addr_t addr; - in_port_t port; - int family; + u_char sockaddr[NGX_SOCKADDRLEN]; + socklen_t socklen; /* server ctx */ ngx_mail_conf_ctx_t *ctx; unsigned bind:1; + unsigned wildcard:1; #if (NGX_MAIL_SSL) unsigned ssl:1; #endif +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + unsigned ipv6only:2; +#endif } ngx_mail_listen_t; typedef struct { - in_addr_t addr; ngx_mail_conf_ctx_t *ctx; ngx_str_t addr_text; #if (NGX_MAIL_SSL) ngx_uint_t ssl; /* unsigned ssl:1; */ #endif +} ngx_mail_addr_conf_t; + +typedef struct { + in_addr_t addr; + ngx_mail_addr_conf_t conf; } ngx_mail_in_addr_t; +#if (NGX_HAVE_INET6) + typedef struct { - ngx_mail_in_addr_t *addrs; /* array of ngx_mail_in_addr_t */ - ngx_uint_t naddrs; -} ngx_mail_in_port_t; + struct in6_addr addr6; + ngx_mail_addr_conf_t conf; +} ngx_mail_in6_addr_t; + +#endif typedef struct { + /* ngx_mail_in_addr_t or ngx_mail_in6_addr_t */ + void *addrs; + ngx_uint_t naddrs; +} ngx_mail_port_t; + + +typedef struct { + int family; in_port_t port; - ngx_array_t addrs; /* array of ngx_mail_conf_in_addr_t */ -} ngx_mail_conf_in_port_t; + ngx_array_t addrs; /* array of ngx_mail_conf_addr_t */ +} ngx_mail_conf_port_t; typedef struct { - in_addr_t addr; + struct sockaddr *sockaddr; + socklen_t socklen; + ngx_mail_conf_ctx_t *ctx; + unsigned bind:1; + unsigned wildcard:1; #if (NGX_MAIL_SSL) unsigned ssl:1; #endif -} ngx_mail_conf_in_addr_t; +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + unsigned ipv6only:2; +#endif +} ngx_mail_conf_addr_t; typedef struct { diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c --- a/src/mail/ngx_mail_auth_http_module.c +++ b/src/mail/ngx_mail_auth_http_module.c @@ -771,6 +771,8 @@ ngx_mail_auth_http_process_headers(ngx_m return; } + /* AF_INET only */ + sin = ngx_pcalloc(s->connection->pool, sizeof(struct sockaddr_in)); if (sin == NULL) { ngx_destroy_pool(ctx->pool); diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -274,19 +274,24 @@ ngx_mail_core_server(ngx_conf_t *cf, ngx } -/* AF_INET only */ - static char * ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_mail_core_srv_conf_t *cscf = conf; + size_t len, off; + in_port_t port; ngx_str_t *value; ngx_url_t u; ngx_uint_t i, m; + struct sockaddr *sa; ngx_mail_listen_t *ls; ngx_mail_module_t *module; + struct sockaddr_in *sin; ngx_mail_core_main_conf_t *cmcf; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; +#endif value = cf->args->elts; @@ -305,18 +310,42 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx return NGX_CONF_ERROR; } - if (u.family != AF_INET) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "listen supports IPv4 only"); - return NGX_CONF_ERROR; - } - cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); ls = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts; i++) { - if (ls[i].addr != u.addr.in_addr || ls[i].port != u.port) { + sa = (struct sockaddr *) ls[i].sockaddr; + + if (sa->sa_family != u.family) { + continue; + } + + switch (sa->sa_family) { + +#if (NGX_HAVE_INET6) + case AF_INET6: + off = offsetof(struct sockaddr_in6, sin6_addr); + len = 16; + sin6 = (struct sockaddr_in6 *) sa; + port = sin6->sin6_port; + break; +#endif + + default: /* AF_INET */ + off = offsetof(struct sockaddr_in, sin_addr); + len = 4; + sin = (struct sockaddr_in *) sa; + port = sin->sin_port; + break; + } + + if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) { + continue; + } + + if (port != u.port) { continue; } @@ -332,9 +361,10 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx ngx_memzero(ls, sizeof(ngx_mail_listen_t)); - ls->addr = u.addr.in_addr; - ls->port = u.port; - ls->family = u.family; + ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen); + + ls->socklen = u.socklen; + ls->wildcard = u.wildcard; ls->ctx = cf->ctx; for (m = 0; ngx_modules[m]; m++) { @@ -363,6 +393,47 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx continue; } + if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { +#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) + struct sockaddr *sa; + u_char buf[NGX_SOCKADDR_STRLEN]; + + sa = (struct sockaddr *) ls->sockaddr; + + if (sa->sa_family == AF_INET6) { + + if (ngx_strcmp(&value[i].data[10], "n") == 0) { + ls->ipv6only = 1; + + } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { + ls->ipv6only = 2; + + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid ipv6only flags \"%s\"", + &value[i].data[9]); + return NGX_CONF_ERROR; + } + + ls->bind = 1; + + } else { + len = ngx_sock_ntop(sa, buf, NGX_SOCKADDR_STRLEN, 1); + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "ipv6only is not supported " + "on addr \"%*s\", ignored", len, buf); + } + + continue; +#else + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "bind ipv6only is not supported " + "on this platform"); + return NGX_CONF_ERROR; +#endif + } + if (ngx_strcmp(value[i].data, "ssl") == 0) { #if (NGX_MAIL_SSL) ls->ssl = 1; diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -21,25 +21,27 @@ static void ngx_mail_ssl_handshake_handl void ngx_mail_init_connection(ngx_connection_t *c) { - in_addr_t in_addr; - socklen_t len; - ngx_uint_t i; - struct sockaddr_in sin; - ngx_mail_log_ctx_t *ctx; - ngx_mail_in_port_t *mip; - ngx_mail_in_addr_t *mia; - ngx_mail_session_t *s; + ngx_uint_t i; + ngx_mail_port_t *port; + struct sockaddr *sa; + struct sockaddr_in *sin; + ngx_mail_log_ctx_t *ctx; + ngx_mail_in_addr_t *addr; + ngx_mail_session_t *s; + ngx_mail_addr_conf_t *addr_conf; +#if (NGX_HAVE_INET6) + struct sockaddr_in6 *sin6; + ngx_mail_in6_addr_t *addr6; +#endif + /* find the server configuration for the address:port */ /* AF_INET only */ - mip = c->listening->servers; - mia = mip->addrs; + port = c->listening->servers; - i = 0; - - if (mip->naddrs > 1) { + if (port->naddrs > 1) { /* * There are several addresses on this port and one of them @@ -49,45 +51,79 @@ ngx_mail_init_connection(ngx_connection_ * AcceptEx() already gave this address. */ -#if (NGX_WIN32) - if (c->local_sockaddr) { - in_addr = - ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr; + if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) { + ngx_mail_close_connection(c); + return; + } + + sa = c->local_sockaddr; + + switch (sa->sa_family) { - } else -#endif - { - len = sizeof(struct sockaddr_in); - if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) { - ngx_connection_error(c, ngx_socket_errno, - "getsockname() failed"); - ngx_mail_close_connection(c); - return; +#if (NGX_HAVE_INET6) + case AF_INET6: + sin6 = (struct sockaddr_in6 *) sa; + + addr6 = port->addrs; + + /* the last address is "*" */ + + for (i = 0; i < port->naddrs - 1; i++) { + if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) { + break; + } } - in_addr = sin.sin_addr.s_addr; + addr_conf = &addr6[i].conf; + + break; +#endif + + default: /* AF_INET */ + sin = (struct sockaddr_in *) sa; + + addr = port->addrs; + + /* the last address is "*" */ + + for (i = 0; i < port->naddrs - 1; i++) { + if (addr[i].addr == sin->sin_addr.s_addr) { + break; + } + } + + addr_conf = &addr[i].conf; + + break; } - /* the last address is "*" */ + } else { + switch (c->local_sockaddr->sa_family) { - for ( /* void */ ; i < mip->naddrs - 1; i++) { - if (in_addr == mia[i].addr) { - break; - } +#if (NGX_HAVE_INET6) + case AF_INET6: + addr6 = port->addrs; + addr_conf = &addr6[0].conf; + break; +#endif + + default: /* AF_INET */ + addr = port->addrs; + addr_conf = &addr[0].conf; + break; } } - s = ngx_pcalloc(c->pool, sizeof(ngx_mail_session_t)); if (s == NULL) { ngx_mail_close_connection(c); return; } - s->main_conf = mia[i].ctx->main_conf; - s->srv_conf = mia[i].ctx->srv_conf; + s->main_conf = addr_conf->ctx->main_conf; + s->srv_conf = addr_conf->ctx->srv_conf; - s->addr_text = &mia[i].addr_text; + s->addr_text = &addr_conf->addr_text; c->data = s; s->connection = c; @@ -124,7 +160,7 @@ ngx_mail_init_connection(ngx_connection_ return; } - if (mia[i].ssl) { + if (addr_conf->ssl) { c->log->action = "SSL handshaking"; diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -66,6 +66,12 @@ ngx_mail_smtp_init_session(ngx_mail_sess return; } + if (c->sockaddr->sa_family != AF_INET) { + s->host = smtp_tempunavail; + ngx_mail_smtp_greeting(s, c); + return; + } + c->log->action = "in resolving client address"; ctx = ngx_resolve_start(cscf->resolver, NULL);