1 diff -Nur apache_1.3.22.orig/README.v6 apache_1.3.22/README.v6
2 --- apache_1.3.22.orig/README.v6 Thu Jan 1 01:00:00 1970
3 +++ apache_1.3.22/README.v6 Fri Dec 7 17:27:28 2001
5 +IPv6-ready apache 1.3.x
9 +This patchkit enables apache 1.3.x to perform HTTP connection over IPv6.
10 +Most of optional modules are left unchanged, i.e. it won't support IPv6,
11 +and it may not compile.
13 +Basically you can write IPv6 address where IPv4 address fits.
15 +extra command-line argument:
16 + -4 Assume IPv4 address on ambiguous directives
17 + -6 Assume IPv6 address on ambiguous directives (default)
19 + The above two can be used, for example, to disambiguate
24 + Listen is expanded to take one or two arguments.
28 + This is to let you specify "Listen :: 80", since "Listen :::80"
34 + "deny from" and "allow from" supports IPv6 addresses, under the
36 + {deny,allow} from v6addr
37 + {deny,allow} from v6addr/v6mask
38 + {deny,allow} from v6addr/prefixlen
39 + Also, wildcard ("*") and string hostname matches IPv6 hosts as well.
43 + http/ftp proxying for both IPv4 and IPv6 is possible.
44 + Access control functions (NoProxy) are not updated yet.
46 + NOTE: for security reasons, we recommend you to filter out
47 + outsider's access to your proxy, by directives like below:
51 + allow from 10.0.0.0/8
52 + allow from 3ffe:9999:8888:7777::/64
56 + If you would like to this feature, you must describe 'Listen'
57 + part on configuration file explicitly. like below:
62 + NameVirtualHost is expanded to take one more two arguments.
63 + NameVirtualHost address
64 + NameVirtualHost address:port
65 + NameVirtualHost address port
66 + This is to let you specify IPv6 address into address part.
68 + Note that, if colon is found in the specified address string,
69 + the code will to resolve the address in the following way:
70 + 1. try to resolve as address:port (most of IPv6 address fails)
71 + 2. if (1) is failed, try to resolve as address only
72 + If there's ambiguity, i.e. 3ffe:0501::1:2, the address may not be
73 + parsed as you expect (3ffe:0501::1 with port 2, or 3ffe:0501::1:2
74 + with default port). To get the right effect you are encouraged
75 + to specify it without ambiguity. In IPv6 case "address port"
76 + (specify address and port separated by a space) is the safest way.
78 + <VirtualHost host:port [host:port ...]>
79 + If you would like to specify IPv6 numeric address in host part,
80 + use bracketed format like below:
81 + <VirtualHost [::1]:80>
82 + Note: Now we DO NOT handle old non-bracketed format,
83 + <VirtualHost 0:0:0:0:0:0:0:1:80>
84 + so configuration file must be updated.
85 + Note: The following is bad example to specify host ::1 port 80.
86 + This will treated as host ::1:80.
87 + <VirtualHost ::1:80>
89 +logresolve (src/support)
90 + error statistics in nameserver cache code is omitted.
93 + Originally mod_unique_id used IPv4 address as a seed for UNIQUE_ID,
94 + and took IPv4 address registered onto DNS for the hostname (UNIX
95 + hostname taken by gethostname(3)). Therefore, this does not work
96 + for IPv6-only hosts as they do not have IPv4 address for them.
98 + Now, UNIQUE_ID can be generated using IPv6 address. IPv6 address can
99 + be used as the seed for UNIQUE_ID.
100 + Because of this, UNIQUE_ID will be longer than normal apache. This
101 + may cause problem with some of the CGI scripts.
102 + The preference of the addresses is based on the order returned
103 + by getaddrinfo(). If your getaddrinfo() returns IPv4 address, IPv4
104 + adderss will be used as a seed.
105 + Note that some of IPv6 addresses are "scoped"; If you happened to use
106 + link-local or site-local address as a seed, the UNIQUE_ID may not be
109 + If longer UNIQUE_ID causes a problem, define SHORT_UNIQUE_ID in
110 + mod_unique_id.c. In this case, length of UNIQUE_ID will be kept the
111 + same. However, for IPv6 addresses mod_unique_id.c will use the last
112 + 32bit (not the whole 128bit) as the seed. Therefore, there can be
113 + collision in UNIQUE_ID.
115 + The behavior should be improved in the near future; we welcome your
118 +Modules known to be incompatible with IPv6
122 + Configure has extra option, --enable-rule=INET6. if the option
123 + is specified, IPv6 code will be enabled.
126 + We do not support IPv4 mapped address (IPv6 address format like
127 + ::ffff:10.1.1.1) in configuration file.
129 +This kit assumes that you have working(*) getaddrinfo() and getnameinfo()
130 +library functions. Even if you don't have one, don't panic. We have
131 +included last-resort version (which support IPv4 only) into the kit.
132 +For more complete implementation you might want to check BIND 8.2.
133 +(*) NOTE: we have noticed that some of IPv6 stack is shipped with broken
134 +getaddrinfo(). In such cases, you should get and install BIND 8.2.
136 +When compiling this kit onto IPv6, you may need to specify some additional
137 +library paths or cpp defs (like -linet6 or -DINET6).
138 +Now you don't have to specify --enable-rule=INET6. The "configure" script
139 +will give you some warnings if the IPv6 stack is not known to the
140 +"configure" script. Currently, the following IPv6 stacks are supported:
141 +- KAME IPv6 stack, http://www.kame.net/
142 + use configure.v6 for convenience,
143 +- Linux IPv6 stack, http://www.linux.org/
144 + use configure.v6 for convenience.
145 +- Solaris 8 IPv6 stack, http://www.sun.com/
146 + use configure.v6 for convenience.
147 +To disable IPv6 support, specify --disable-rule=INET6 to the "configure"
150 +CAVEAT: This patchkit may change some of apache module API, to avoid
151 +IPv4-dependent structure member variable. Please let us know if there's
152 +any troubles as we know very little about the apache module API.
155 + Thanks to all people submitted patches/fixes for this patch kit,
157 + "Chris P. Ross" <cross@eng.us.uu.net>
160 + Jun-ichiro itojun Hagino, KAME project
161 + http://www.kame.net/
162 + mailto:core@kame.net
164 + Arkadiusz Miskiewicz, Polish Linux Distribution project (IPv6)
165 + http://www.pld.org.pl/
166 + mailto:pld-list@pld.org.pl
167 + Satoshi SHIDA, Linux IPv6 Users Group JP
168 + http://www.v6.linux.or.jp/
169 + YOSHIFUJI Hideaki, USAGI Project
170 + http://www.linux-ipv6.org/
171 diff -Nur apache_1.3.22.orig/conf/httpd.conf-dist apache_1.3.22/conf/httpd.conf-dist
172 --- apache_1.3.22.orig/conf/httpd.conf-dist Sat Oct 6 05:40:04 2001
173 +++ apache_1.3.22/conf/httpd.conf-dist Fri Dec 7 17:27:28 2001
176 #Listen 12.34.56.78:80
178 +# Listen can take two arguments.
179 +# (this is an extension for supporting IPv6 addresses)
184 # BindAddress: You can support virtual hosts with this option. This directive
185 # is used to tell the server which IP address to listen to. It can either
186 diff -Nur apache_1.3.22.orig/configure.v6 apache_1.3.22/configure.v6
187 --- apache_1.3.22.orig/configure.v6 Thu Jan 1 01:00:00 1970
188 +++ apache_1.3.22/configure.v6 Fri Dec 7 17:27:28 2001
192 +./configure --enable-rule=INET6 --enable-module=proxy $*
193 diff -Nur apache_1.3.22.orig/src/Configuration.tmpl apache_1.3.22/src/Configuration.tmpl
194 --- apache_1.3.22.orig/src/Configuration.tmpl Fri Dec 7 17:26:57 2001
195 +++ apache_1.3.22/src/Configuration.tmpl Fri Dec 7 17:27:28 2001
197 # Rule EXPAT=default : If Expat can be found at the system or
198 # in lib/expat-lite, use it; otherwise
213 # Note: this rule is only used when compiling mod_auth_digest.
214 diff -Nur apache_1.3.22.orig/src/Configure apache_1.3.22/src/Configure
215 --- apache_1.3.22.orig/src/Configure Fri Dec 7 17:26:57 2001
216 +++ apache_1.3.22/src/Configure Fri Dec 7 17:27:28 2001
218 RULE_EXPAT=`./helpers/CutRule EXPAT $file`
219 RULE_SHARED_CORE=`./helpers/CutRule SHARED_CORE $file`
220 RULE_SHARED_CHAIN=`./helpers/CutRule SHARED_CHAIN $file`
221 +RULE_INET6=`./helpers/CutRule INET6 $file`
223 ####################################################################
224 ## Rule SHARED_CORE implies required DSO support
225 @@ -1692,6 +1693,124 @@
230 +if [ "$RULE_INET6" = "yes" ]; then
231 + echo " + enabling INET6 support"
232 + CFLAGS="$CFLAGS -DINET6"
233 + CFLAGS="$CFLAGS -Dss_family=__ss_family -Dss_len=__ss_len"
234 + IPV6_STACKTYPE="UNKNOWN"
235 + for i in KAME Linux Solaris; do
238 + if [ -f /usr/include/netinet6/in6.h -a "x`egrep '__KAME__' /usr/include/netinet6/in6.h 2>/dev/null`" != "x" ]; then
243 + if [ /usr/include/netinet/ip6.h -a -d /usr/include/linux ]; then
248 + SOL_VERSION=`(uname -v) 2>/dev/null` || SOL_VERSION="unknown"
249 + case "${PLAT}-${SOL_VERSION}" in
250 + *-solaris2.27*-*IPv6*)
251 + if [ -f /etc/hostname -o -f /etc/hostname.[a-z]*[0-9] ]; then
252 + IPV6_STACKTYPE="Solaris 7 (${SOL_VERSION})"
258 + if [ "$IPV6_STACKTYPE" != "UNKNOWN" ]; then
262 + if [ "$IPV6_STACKTYPE" != "UNKNOWN" ]; then
263 + echo " + You seem to be using $IPV6_STACKTYPE stack"
264 + if ./helpers/TestCompile func getaddrinfo; then
265 + echo " - Assuming you have working getaddrinfo in libc"
267 + if [ -f /usr/local/v6/lib/libinet6.a -a "x`egrep '^EXTRA_L' Makefile.config | grep linet6`" = "x" ]; then
268 + LIBS="$LIBS -L/usr/local/v6/lib -linet6"
269 + echo " - using getaddrinfo in libinet6"
270 + elif [ -f /usr/local/lib/libinet6.a -a "x`egrep '^EXTRA_L' Makefile.config | grep linet6`" = "x" ]; then
271 + LIBS="$LIBS -L/usr/local/lib -linet6"
272 + echo " - using getaddrinfo in libinet6"
273 + elif [ -f /usr/inet6/lib/libinet6.a -a "x`egrep '^EXTRA_L' Makefile.config | grep linet6`" = "x" ]; then
274 + echo " - using getaddrinfo in libinet6"
276 + echo "** WARNING: No getaddrinfo found, linkage may fail"
281 + echo "** WARNING: We have no explicit knowledge about the IPv6"
282 + echo "** implementation on this host. You may need to specify"
283 + echo "** EXTRA_LIBS so that we can find getaddrinfo() and"
284 + echo "** getnameinfo() library functions."
289 + LIBS="$LIBS -lresolv"
293 + CFLAGS="$CFLAGS -DNEED_GETADDRINFO -DNEED_GETNAMEINFO"
294 + if [ -f /usr/include/netdb.h -a "x`egrep 'addrinfo' /usr/include/netdb.h`" = "x" ]; then
295 + CFLAGS="$CFLAGS -DNEED_ADDRINFO"
299 +echo '#include <sys/types.h>' >testfunc.c
300 +echo '#include <sys/socket.h>' >>testfunc.c
301 +echo 'int testfunc(){ struct sockaddr sa; int i = sa.sa_len; };' >>testfunc.c
303 +eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null"
304 +if [ -f testfunc.o ]; then
305 + echo " + you have sa_len in struct sockaddr."
306 + CFLAGS="$CFLAGS -DHAVE_SOCKADDR_LEN"
308 + echo " + you don't have sa_len in struct sockaddr."
310 +rm -f testfunc.c testfunc.o
312 +echo '#include <sys/types.h>' >testfunc.c
313 +echo '#include <sys/socket.h>' >>testfunc.c
314 +echo 'struct sockaddr_storage sockaddr_storage;' >>testfunc.c
316 +eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null"
317 +if [ -f testfunc.o ]; then
318 + echo " + assuming you have struct sockaddr_storage"
320 + CFLAGS="$CFLAGS -DNEED_SOCKADDR_STORAGE"
321 + echo " + you need struct sockaddr_storage"
323 +rm -f testfunc.c testfunc.o
325 +echo '#include <sys/types.h>' >testfunc.c
326 +echo '#include <sys/socket.h>' >>testfunc.c
327 +echo 'int testfunc(){ socklen_t t; }' >>testfunc.c
329 +eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null"
330 +if [ ! -f testfunc.o ]; then
331 + CFLAGS="$CFLAGS -Dsocklen_t=int"
333 +rm -f testfunc.c testfunc.o
335 +echo '#include <sys/types.h>' >testfunc.c
336 +echo '#include <sys/socket.h>' >>testfunc.c
337 +echo 'struct sockaddr_in sin;' >>testfunc.c
338 +echo 'int main(){ int i = sin.sin_len; }' >>testfunc.c
340 +eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null"
341 +if [ -f testfunc.o ]; then
342 + CFLAGS="$CFLAGS -DSIN_LEN"
344 +rm -f testfunc.c testfunc.o
347 ####################################################################
348 ## Find out what modules we want and try and configure things for them
349 ## Module lines can look like this:
350 @@ -2287,6 +2406,38 @@
351 echo "#define AP_LONGEST_LONG $AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H
352 echo "#endif" >>$AP_CONFIG_AUTO_H
354 +if [ x`./helpers/TestCompile -r sizeof 'uint32_t'` != x"" ]; then
355 + echo "" >>$AP_CONFIG_AUTO_H
356 + echo "/* determine: use uint32_t as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
357 + echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H
358 + echo "#define ap_uint32_t uint32_t" >>$AP_CONFIG_AUTO_H
359 + echo "#endif" >>$AP_CONFIG_AUTO_H
360 + echo " - use uint32_t as 32bit unsigned int"
361 +elif [ x`./helpers/TestCompile -r sizeof 'u_int32_t'` != x"" ]; then
362 + echo "" >>$AP_CONFIG_AUTO_H
363 + echo "/* determine: use u_int32_t as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
364 + echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H
365 + echo "#define ap_uint32_t u_int32_t" >>$AP_CONFIG_AUTO_H
366 + echo "#endif" >>$AP_CONFIG_AUTO_H
367 + echo " - use u_int32_t as 32bit unsigned int"
368 +elif [ x`./helpers/TestCompile -r sizeof 'unsigned int'` = x"4" ]; then
369 + echo "" >>$AP_CONFIG_AUTO_H
370 + echo "/* determine: use unsigned int as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
371 + echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H
372 + echo "#define ap_uint32_t unsigned int" >>$AP_CONFIG_AUTO_H
373 + echo "#endif" >>$AP_CONFIG_AUTO_H
374 + echo " - use unsigned int as 32bit unsigned int"
375 +elif [ x`./helpers/TestCompile -r sizeof 'unsigned long int'` = x"4" ]; then
376 + echo "" >>$AP_CONFIG_AUTO_H
377 + echo "/* determine: use unsigned long int as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
378 + echo "#ifndef uint32_t" >>$AP_CONFIG_AUTO_H
379 + echo "#define uint32_t unsigned long int" >>$AP_CONFIG_AUTO_H
380 + echo "#endif" >>$AP_CONFIG_AUTO_H
381 + echo " - use unsigned long int as 32bit unsigned int"
383 + echo " - Warning: cannot determine what type should we use as 32bit unsigned int"
386 ####################################################################
387 ## More building ap_config_auto.h
389 diff -Nur apache_1.3.22.orig/src/ap/ap_snprintf.c apache_1.3.22/src/ap/ap_snprintf.c
390 --- apache_1.3.22.orig/src/ap/ap_snprintf.c Thu May 10 16:04:22 2001
391 +++ apache_1.3.22/src/ap/ap_snprintf.c Fri Dec 7 17:27:28 2001
405 +static char *conv_sockaddr(struct sockaddr *sa, char *buf_end, int *len)
408 + char hostnamebuf[MAXHOSTNAMELEN];
409 + char portnamebuf[MAXHOSTNAMELEN];
414 + salen = SA_LEN(sa);
416 + salen = sa->sa_len;
418 + if (getnameinfo(sa, salen, hostnamebuf, sizeof(hostnamebuf),
419 + portnamebuf, sizeof(portnamebuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
420 + strcpy(hostnamebuf, "???");
421 + strcpy(portnamebuf, "???");
423 + if (strcmp(portnamebuf,"0") == 0)
424 + strcpy(portnamebuf, "*");
425 + q = portnamebuf + strlen(portnamebuf);
426 + while (portnamebuf < q)
429 + q = hostnamebuf + strlen(hostnamebuf);
430 + while (hostnamebuf < q)
433 + *len = buf_end - p;
441 * Convert a floating point number to a string formats 'f', 'e' or 'E'.
442 * The result is placed in buf, and len denotes the length of the string
443 @@ -1055,6 +1092,7 @@
444 /* print a struct sockaddr_in as a.b.c.d:port */
448 struct sockaddr_in *si;
450 si = va_arg(ap, struct sockaddr_in *);
451 @@ -1063,6 +1101,16 @@
452 if (adjust_precision && precision < s_len)
456 + struct sockaddr *sa;
458 + sa = va_arg(ap, struct sockaddr *);
460 + s = conv_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len);
461 + if (adjust_precision && precision < s_len)
468 diff -Nur apache_1.3.22.orig/src/ap/ap_snprintf.c~ apache_1.3.22/src/ap/ap_snprintf.c~
469 --- apache_1.3.22.orig/src/ap/ap_snprintf.c~ Thu Jan 1 01:00:00 1970
470 +++ apache_1.3.22/src/ap/ap_snprintf.c~ Fri Dec 7 17:27:28 2001
472 +/* ====================================================================
473 + * The Apache Software License, Version 1.1
475 + * Copyright (c) 2000 The Apache Software Foundation. All rights
478 + * Redistribution and use in source and binary forms, with or without
479 + * modification, are permitted provided that the following conditions
482 + * 1. Redistributions of source code must retain the above copyright
483 + * notice, this list of conditions and the following disclaimer.
485 + * 2. Redistributions in binary form must reproduce the above copyright
486 + * notice, this list of conditions and the following disclaimer in
487 + * the documentation and/or other materials provided with the
490 + * 3. The end-user documentation included with the redistribution,
491 + * if any, must include the following acknowledgment:
492 + * "This product includes software developed by the
493 + * Apache Software Foundation (http://www.apache.org/)."
494 + * Alternately, this acknowledgment may appear in the software itself,
495 + * if and wherever such third-party acknowledgments normally appear.
497 + * 4. The names "Apache" and "Apache Software Foundation" must
498 + * not be used to endorse or promote products derived from this
499 + * software without prior written permission. For written
500 + * permission, please contact apache@apache.org.
502 + * 5. Products derived from this software may not be called "Apache",
503 + * nor may "Apache" appear in their name, without prior written
504 + * permission of the Apache Software Foundation.
506 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
507 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
508 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
509 + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
510 + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
511 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
512 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
513 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
514 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
515 + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
516 + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
518 + * ====================================================================
520 + * This software consists of voluntary contributions made by many
521 + * individuals on behalf of the Apache Software Foundation. For more
522 + * information on the Apache Software Foundation, please see
523 + * <http://www.apache.org/>.
525 + * Portions of this software are based upon public domain software
526 + * originally written at the National Center for Supercomputing Applications,
527 + * University of Illinois, Urbana-Champaign.
531 + * This code is based on, and used with the permission of, the
532 + * SIO stdio-replacement strx_* functions by Panos Tsirigotis
533 + * <panos@alumni.cs.colorado.edu> for xinetd.
541 +#include <sys/types.h>
561 +#ifndef AP_LONGEST_LONG
562 +#define AP_LONGEST_LONG long
565 +#define WIDE_INT long
566 +#define WIDEST_INT AP_LONGEST_LONG
568 +typedef WIDE_INT wide_int;
569 +typedef unsigned WIDE_INT u_wide_int;
570 +typedef WIDEST_INT widest_int;
572 +/* Although Tandem supports "long long" there is no unsigned variant. */
573 +typedef unsigned long u_widest_int;
575 +typedef unsigned WIDEST_INT u_widest_int;
577 +typedef int bool_int;
579 +#define S_NULL "(null)"
580 +#define S_NULL_LEN 6
582 +#define FLOAT_DIGITS 6
583 +#define EXPONENT_LENGTH 10
586 + * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
588 + * XXX: this is a magic number; do not decrease it
590 +#define NUM_BUF_SIZE 512
593 + * cvt.c - IEEE floating point formatting routines for FreeBSD
594 + * from GNU libc-4.6.27. Modified to be thread safe.
598 + * ap_ecvt converts to decimal
599 + * the number of digits is specified by ndigit
600 + * decpt is set to the position of the decimal point
601 + * sign is set to 0 for positive, 1 for negative
606 +/* buf must have at least NDIG bytes */
607 +static char *ap_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf)
611 + register char *p, *p1;
613 + if (ndigits >= NDIG - 1)
614 + ndigits = NDIG - 2;
622 + arg = modf(arg, &fi);
629 + while (p1 > &buf[0] && fi != 0) {
630 + fj = modf(fi / 10, &fi);
631 + *--p1 = (int) ((fj + .03) * 10) + '0';
634 + while (p1 < &buf[NDIG])
637 + else if (arg > 0) {
638 + while ((fj = arg * 10) < 1) {
643 + p1 = &buf[ndigits];
647 + if (p1 < &buf[0]) {
651 + while (p <= p1 && p < &buf[NDIG]) {
653 + arg = modf(arg, &fj);
654 + *p++ = (int) fj + '0';
656 + if (p1 >= &buf[NDIG]) {
657 + buf[NDIG - 1] = '\0';
662 + while (*p1 > '9') {
680 +static char *ap_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
682 + return (ap_cvt(arg, ndigits, decpt, sign, 1, buf));
685 +static char *ap_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
687 + return (ap_cvt(arg, ndigits, decpt, sign, 0, buf));
691 + * ap_gcvt - Floating output conversion to
692 + * minimal length string
695 +static char *ap_gcvt(double number, int ndigit, char *buf, boolean_e altform)
698 + register char *p1, *p2;
702 + p1 = ap_ecvt(number, ndigit, &decpt, &sign, buf1);
706 + for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
708 + if ((decpt >= 0 && decpt - ndigit > 4)
709 + || (decpt < 0 && decpt < -3)) { /* use E-style */
713 + for (i = 1; i < ndigit; i++)
722 + if (decpt / 100 > 0)
723 + *p2++ = decpt / 100 + '0';
724 + if (decpt / 10 > 0)
725 + *p2++ = (decpt % 100) / 10 + '0';
726 + *p2++ = decpt % 10 + '0';
732 + while (decpt < 0) {
737 + for (i = 1; i <= ndigit; i++) {
742 + if (ndigit < decpt) {
743 + while (ndigit++ < decpt)
748 + if (p2[-1] == '.' && !altform)
755 + * The INS_CHAR macro inserts a character in the buffer and writes
756 + * the buffer back to disk if necessary
757 + * It uses the char pointers sp and bep:
758 + * sp points to the next available character in the buffer
759 + * bep points to the end-of-buffer+1
760 + * While using this macro, note that the nextb pointer is NOT updated.
762 + * NOTE: Evaluation of the c argument should not have any side-effects
764 +#define INS_CHAR(c, sp, bep, cc) \
767 + vbuff->curpos = sp; \
768 + if (flush_func(vbuff)) \
770 + sp = vbuff->curpos; \
771 + bep = vbuff->endpos; \
777 +#define NUM( c ) ( c - '0' )
779 +#define STR_TO_DEC( str, num ) \
780 + num = NUM( *str++ ) ; \
781 + while ( ap_isdigit( *str ) ) \
784 + num += NUM( *str++ ) ; \
788 + * This macro does zero padding so that the precision
789 + * requirement is satisfied. The padding is done by
790 + * adding '0's to the left of the string that is going
793 +#define FIX_PRECISION( adjust, precision, s, s_len ) \
795 + while ( s_len < precision ) \
802 + * Macro that does padding. The padding is done by printing
803 + * the character ch.
805 +#define PAD( width, len, ch ) do \
807 + INS_CHAR( ch, sp, bep, cc ) ; \
810 + while ( width > len )
813 + * Prefix the character ch to the string str
815 + * Set the has_prefix flag
817 +#define PREFIX( str, length, ch ) *--str = ch ; length++ ; has_prefix = YES
821 + * Convert num to its decimal format.
823 + * - a pointer to a string containing the number (no sign)
824 + * - len contains the length of the string
825 + * - is_negative is set to TRUE or FALSE depending on the sign
826 + * of the number (always set to FALSE if is_unsigned is TRUE)
828 + * The caller provides a buffer for the string: that is the buf_end argument
829 + * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
830 + * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
832 + * Note: we have 2 versions. One is used when we need to use quads
833 + * (conv_10_quad), the other when we don't (conv_10). We're assuming the
834 + * latter is faster.
836 +static char *conv_10(register wide_int num, register bool_int is_unsigned,
837 + register bool_int *is_negative, char *buf_end,
840 + register char *p = buf_end;
841 + register u_wide_int magnitude;
844 + magnitude = (u_wide_int) num;
845 + *is_negative = FALSE;
848 + *is_negative = (num < 0);
851 + * On a 2's complement machine, negating the most negative integer
852 + * results in a number that cannot be represented as a signed integer.
853 + * Here is what we do to obtain the number's magnitude:
854 + * a. add 1 to the number
855 + * b. negate it (becomes positive)
856 + * c. convert it to unsigned
859 + if (*is_negative) {
860 + wide_int t = num + 1;
862 + magnitude = ((u_wide_int) -t) + 1;
865 + magnitude = (u_wide_int) num;
869 + * We use a do-while loop so that we write at least 1 digit
872 + register u_wide_int new_magnitude = magnitude / 10;
874 + *--p = (char) (magnitude - new_magnitude * 10 + '0');
875 + magnitude = new_magnitude;
879 + *len = buf_end - p;
883 +static char *conv_10_quad(widest_int num, register bool_int is_unsigned,
884 + register bool_int *is_negative, char *buf_end,
887 + register char *p = buf_end;
888 + u_widest_int magnitude;
891 + * We see if we can use the faster non-quad version by checking the
892 + * number against the largest long value it can be. If <=, we
893 + * punt to the quicker version.
895 + if ((num <= ULONG_MAX && is_unsigned) || (num <= LONG_MAX && !is_unsigned))
896 + return(conv_10( (wide_int)num, is_unsigned, is_negative,
900 + magnitude = (u_widest_int) num;
901 + *is_negative = FALSE;
904 + *is_negative = (num < 0);
907 + * On a 2's complement machine, negating the most negative integer
908 + * results in a number that cannot be represented as a signed integer.
909 + * Here is what we do to obtain the number's magnitude:
910 + * a. add 1 to the number
911 + * b. negate it (becomes positive)
912 + * c. convert it to unsigned
915 + if (*is_negative) {
916 + widest_int t = num + 1;
918 + magnitude = ((u_widest_int) -t) + 1;
921 + magnitude = (u_widest_int) num;
925 + * We use a do-while loop so that we write at least 1 digit
928 + u_widest_int new_magnitude = magnitude / 10;
930 + *--p = (char) (magnitude - new_magnitude * 10 + '0');
931 + magnitude = new_magnitude;
935 + *len = buf_end - p;
941 +static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
943 + unsigned addr = ntohl(ia->s_addr);
945 + bool_int is_negative;
948 + p = conv_10((addr & 0x000000FF) , TRUE, &is_negative, p, &sub_len);
950 + p = conv_10((addr & 0x0000FF00) >> 8, TRUE, &is_negative, p, &sub_len);
952 + p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
954 + p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
956 + *len = buf_end - p;
962 +static char *conv_sockaddr_in(struct sockaddr_in *si, char *buf_end, int *len)
965 + bool_int is_negative;
968 + p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
970 + p = conv_in_addr(&si->sin_addr, p, &sub_len);
972 + *len = buf_end - p;
979 +static char *conv_sockaddr(struct sockaddr *sa, char *buf_end, int *len)
982 + char hostnamebuf[MAXHOSTNAMELEN];
983 + char portnamebuf[MAXHOSTNAMELEN];
988 + salen = SA_LEN(sa);
990 + salen = sa->sa_len;
992 + if (getnameinfo(sa, salen, hostnamebuf, sizeof(hostnamebuf),
993 + portnamebuf, sizeof(portnamebuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
994 + strcpy(hostnamebuf, "???");
995 + strcpy(portnamebuf, "???");
997 + if (strcmp(portnamebuf,"0") == 0)
998 + strcpy(portnamebuf, "*");
999 + q = portnamebuf + strlen(portnamebuf);
1000 + while (portnamebuf < q)
1003 + q = hostnamebuf + strlen(hostnamebuf);
1004 + while (hostnamebuf < q)
1007 + *len = buf_end - p;
1015 + * Convert a floating point number to a string formats 'f', 'e' or 'E'.
1016 + * The result is placed in buf, and len denotes the length of the string
1017 + * The sign is returned in the is_negative argument (and is not placed
1020 +static char *conv_fp(register char format, register double num,
1021 + boolean_e add_dp, int precision, bool_int *is_negative,
1022 + char *buf, int *len)
1024 + register char *s = buf;
1026 + int decimal_point;
1029 + if (format == 'f')
1030 + p = ap_fcvt(num, precision, &decimal_point, is_negative, buf1);
1031 + else /* either e or E format */
1032 + p = ap_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
1035 + * Check for Infinity and NaN
1037 + if (ap_isalpha(*p)) {
1038 + *len = strlen(strcpy(buf, p));
1039 + *is_negative = FALSE;
1043 + if (format == 'f') {
1044 + if (decimal_point <= 0) {
1046 + if (precision > 0) {
1048 + while (decimal_point++ < 0)
1055 + while (decimal_point-- > 0)
1057 + if (precision > 0 || add_dp)
1063 + if (precision > 0 || add_dp)
1068 + * copy the rest of p, the NUL is NOT copied
1073 + if (format != 'f') {
1074 + char temp[EXPONENT_LENGTH]; /* for exponent conversion */
1076 + bool_int exponent_is_negative;
1078 + *s++ = format; /* either e or E */
1080 + if (decimal_point != 0) {
1081 + p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative,
1082 + &temp[EXPONENT_LENGTH], &t_len);
1083 + *s++ = exponent_is_negative ? '-' : '+';
1086 + * Make sure the exponent has at least 2 digits
1106 + * Convert num to a base X number where X is a power of 2. nbits determines X.
1107 + * For example, if nbits is 3, we do base 8 conversion
1109 + * a pointer to a string containing the number
1111 + * The caller provides a buffer for the string: that is the buf_end argument
1112 + * which is a pointer to the END of the buffer + 1 (i.e. if the buffer
1113 + * is declared as buf[ 100 ], buf_end should be &buf[ 100 ])
1115 + * As with conv_10, we have a faster version which is used when
1116 + * the number isn't quad size.
1118 +static char *conv_p2(register u_wide_int num, register int nbits,
1119 + char format, char *buf_end, register int *len)
1121 + register int mask = (1 << nbits) - 1;
1122 + register char *p = buf_end;
1123 + static const char low_digits[] = "0123456789abcdef";
1124 + static const char upper_digits[] = "0123456789ABCDEF";
1125 + register const char *digits = (format == 'X') ? upper_digits : low_digits;
1128 + *--p = digits[num & mask];
1133 + *len = buf_end - p;
1137 +static char *conv_p2_quad(u_widest_int num, register int nbits,
1138 + char format, char *buf_end, register int *len)
1140 + register int mask = (1 << nbits) - 1;
1141 + register char *p = buf_end;
1142 + static const char low_digits[] = "0123456789abcdef";
1143 + static const char upper_digits[] = "0123456789ABCDEF";
1144 + register const char *digits = (format == 'X') ? upper_digits : low_digits;
1146 + if (num <= ULONG_MAX)
1147 + return(conv_p2( (u_wide_int)num, nbits, format, buf_end, len));
1150 + *--p = digits[num & mask];
1155 + *len = buf_end - p;
1161 + * Do format conversion placing the output in buffer
1163 +API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
1164 + ap_vformatter_buff *vbuff, const char *fmt, va_list ap)
1166 + register char *sp;
1167 + register char *bep;
1168 + register int cc = 0;
1171 + register char *s = NULL;
1175 + register int min_width = 0;
1176 + int precision = 0;
1184 + widest_int i_quad = (widest_int) 0;
1185 + u_widest_int ui_quad;
1186 + wide_int i_num = (wide_int) 0;
1187 + u_wide_int ui_num;
1189 + char num_buf[NUM_BUF_SIZE];
1190 + char char_buf[2]; /* for printing %% and %<unknown> */
1192 + enum var_type_enum {
1193 + IS_QUAD, IS_LONG, IS_SHORT, IS_INT
1195 + enum var_type_enum var_type = IS_INT;
1200 + boolean_e alternate_form;
1201 + boolean_e print_sign;
1202 + boolean_e print_blank;
1203 + boolean_e adjust_precision;
1204 + boolean_e adjust_width;
1205 + bool_int is_negative;
1207 + sp = vbuff->curpos;
1208 + bep = vbuff->endpos;
1211 + if (*fmt != '%') {
1212 + INS_CHAR(*fmt, sp, bep, cc);
1216 + * Default variable settings
1219 + alternate_form = print_sign = print_blank = NO;
1221 + prefix_char = NUL;
1226 + * Try to avoid checking for flags, width or precision
1228 + if (!ap_islower(*fmt)) {
1230 + * Recognize flags: -, #, BLANK, +
1235 + else if (*fmt == '+')
1237 + else if (*fmt == '#')
1238 + alternate_form = YES;
1239 + else if (*fmt == ' ')
1240 + print_blank = YES;
1241 + else if (*fmt == '0')
1248 + * Check if a width was specified
1250 + if (ap_isdigit(*fmt)) {
1251 + STR_TO_DEC(fmt, min_width);
1252 + adjust_width = YES;
1254 + else if (*fmt == '*') {
1255 + min_width = va_arg(ap, int);
1257 + adjust_width = YES;
1258 + if (min_width < 0) {
1260 + min_width = -min_width;
1264 + adjust_width = NO;
1267 + * Check if a precision was specified
1269 + * XXX: an unreasonable amount of precision may be specified
1270 + * resulting in overflow of num_buf. Currently we
1271 + * ignore this possibility.
1273 + if (*fmt == '.') {
1274 + adjust_precision = YES;
1276 + if (ap_isdigit(*fmt)) {
1277 + STR_TO_DEC(fmt, precision);
1279 + else if (*fmt == '*') {
1280 + precision = va_arg(ap, int);
1282 + if (precision < 0)
1289 + adjust_precision = NO;
1292 + adjust_precision = adjust_width = NO;
1297 + if (*fmt == 'q') {
1298 + var_type = IS_QUAD;
1301 + else if (*fmt == 'l') {
1302 + var_type = IS_LONG;
1305 + else if (*fmt == 'h') {
1306 + var_type = IS_SHORT;
1310 + var_type = IS_INT;
1314 + * Argument extraction and printing.
1315 + * First we determine the argument type.
1316 + * Then, we convert the argument to a string.
1317 + * On exit from the switch, s points to the string that
1318 + * must be printed, s_len has the length of the string
1319 + * The precision requirements, if any, are reflected in s_len.
1321 + * NOTE: pad_char may be set to '0' because of the 0 flag.
1322 + * It is reset to ' ' by non-numeric formats
1326 + if (var_type == IS_QUAD) {
1327 + i_quad = va_arg(ap, u_widest_int);
1328 + s = conv_10_quad(i_quad, 1, &is_negative,
1329 + &num_buf[NUM_BUF_SIZE], &s_len);
1332 + if (var_type == IS_LONG)
1333 + i_num = (wide_int) va_arg(ap, u_wide_int);
1334 + else if (var_type == IS_SHORT)
1335 + i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int);
1337 + i_num = (wide_int) va_arg(ap, unsigned int);
1338 + s = conv_10(i_num, 1, &is_negative,
1339 + &num_buf[NUM_BUF_SIZE], &s_len);
1341 + FIX_PRECISION(adjust_precision, precision, s, s_len);
1346 + if (var_type == IS_QUAD) {
1347 + i_quad = va_arg(ap, widest_int);
1348 + s = conv_10_quad(i_quad, 0, &is_negative,
1349 + &num_buf[NUM_BUF_SIZE], &s_len);
1352 + if (var_type == IS_LONG)
1353 + i_num = (wide_int) va_arg(ap, wide_int);
1354 + else if (var_type == IS_SHORT)
1355 + i_num = (wide_int) (short) va_arg(ap, int);
1357 + i_num = (wide_int) va_arg(ap, int);
1358 + s = conv_10(i_num, 0, &is_negative,
1359 + &num_buf[NUM_BUF_SIZE], &s_len);
1361 + FIX_PRECISION(adjust_precision, precision, s, s_len);
1364 + prefix_char = '-';
1365 + else if (print_sign)
1366 + prefix_char = '+';
1367 + else if (print_blank)
1368 + prefix_char = ' ';
1373 + if (var_type == IS_QUAD) {
1374 + ui_quad = va_arg(ap, u_widest_int);
1375 + s = conv_p2_quad(ui_quad, 3, *fmt,
1376 + &num_buf[NUM_BUF_SIZE], &s_len);
1379 + if (var_type == IS_LONG)
1380 + ui_num = (u_wide_int) va_arg(ap, u_wide_int);
1381 + else if (var_type == IS_SHORT)
1382 + ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
1384 + ui_num = (u_wide_int) va_arg(ap, unsigned int);
1385 + s = conv_p2(ui_num, 3, *fmt,
1386 + &num_buf[NUM_BUF_SIZE], &s_len);
1388 + FIX_PRECISION(adjust_precision, precision, s, s_len);
1389 + if (alternate_form && *s != '0') {
1398 + if (var_type == IS_QUAD) {
1399 + ui_quad = va_arg(ap, u_widest_int);
1400 + s = conv_p2_quad(ui_quad, 4, *fmt,
1401 + &num_buf[NUM_BUF_SIZE], &s_len);
1404 + if (var_type == IS_LONG)
1405 + ui_num = (u_wide_int) va_arg(ap, u_wide_int);
1406 + else if (var_type == IS_SHORT)
1407 + ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int);
1409 + ui_num = (u_wide_int) va_arg(ap, unsigned int);
1410 + s = conv_p2(ui_num, 4, *fmt,
1411 + &num_buf[NUM_BUF_SIZE], &s_len);
1413 + FIX_PRECISION(adjust_precision, precision, s, s_len);
1414 + if (alternate_form && i_num != 0) {
1415 + *--s = *fmt; /* 'x' or 'X' */
1423 + s = va_arg(ap, char *);
1425 + s_len = strlen(s);
1426 + if (adjust_precision && precision < s_len)
1427 + s_len = precision;
1431 + s_len = S_NULL_LEN;
1440 + fp_num = va_arg(ap, double);
1442 + * * We use &num_buf[ 1 ], so that we have room for the sign
1445 + if (isnan(fp_num)) {
1452 + if (isinf(fp_num)) {
1459 + s = conv_fp(*fmt, fp_num, alternate_form,
1460 + (adjust_precision == NO) ? FLOAT_DIGITS : precision,
1461 + &is_negative, &num_buf[1], &s_len);
1463 + prefix_char = '-';
1464 + else if (print_sign)
1465 + prefix_char = '+';
1466 + else if (print_blank)
1467 + prefix_char = ' ';
1474 + if (adjust_precision == NO)
1475 + precision = FLOAT_DIGITS;
1476 + else if (precision == 0)
1479 + * * We use &num_buf[ 1 ], so that we have room for the sign
1481 + s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1],
1484 + prefix_char = *s++;
1485 + else if (print_sign)
1486 + prefix_char = '+';
1487 + else if (print_blank)
1488 + prefix_char = ' ';
1490 + s_len = strlen(s);
1492 + if (alternate_form && (q = strchr(s, '.')) == NULL) {
1494 + s[s_len] = '\0'; /* delimit for following strchr() */
1496 + if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)
1502 + char_buf[0] = (char) (va_arg(ap, int));
1510 + char_buf[0] = '%';
1518 + if (var_type == IS_QUAD)
1519 + *(va_arg(ap, widest_int *)) = cc;
1520 + else if (var_type == IS_LONG)
1521 + *(va_arg(ap, long *)) = cc;
1522 + else if (var_type == IS_SHORT)
1523 + *(va_arg(ap, short *)) = cc;
1525 + *(va_arg(ap, int *)) = cc;
1529 + * This is where we extend the printf format, with a second
1535 + * If the pointer size is equal to or smaller than the size
1536 + * of the largest unsigned int, we convert the pointer to a
1537 + * hex number, otherwise we print "%p" to indicate that we
1538 + * don't handle "%p".
1541 +#ifdef AP_VOID_P_IS_QUAD
1542 + if (sizeof(void *) <= sizeof(u_widest_int)) {
1543 + ui_quad = (u_widest_int) va_arg(ap, void *);
1544 + s = conv_p2_quad(ui_quad, 4, 'x',
1545 + &num_buf[NUM_BUF_SIZE], &s_len);
1548 + if (sizeof(void *) <= sizeof(u_wide_int)) {
1549 + ui_num = (u_wide_int) va_arg(ap, void *);
1550 + s = conv_p2(ui_num, 4, 'x',
1551 + &num_buf[NUM_BUF_SIZE], &s_len);
1557 + prefix_char = NUL;
1562 + /* print a struct sockaddr_in as a.b.c.d:port */
1566 + struct sockaddr_in *si;
1568 + si = va_arg(ap, struct sockaddr_in *);
1570 + s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);
1571 + if (adjust_precision && precision < s_len)
1572 + s_len = precision;
1575 + struct sockaddr *sa;
1577 + sa = va_arg(ap, struct sockaddr *);
1579 + s = conv_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len);
1580 + if (adjust_precision && precision < s_len)
1581 + s_len = precision;
1586 + s_len = S_NULL_LEN;
1592 + /* print a struct in_addr as a.b.c.d */
1595 + struct in_addr *ia;
1597 + ia = va_arg(ap, struct in_addr *);
1599 + s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
1600 + if (adjust_precision && precision < s_len)
1601 + s_len = precision;
1605 + s_len = S_NULL_LEN;
1612 + /* if %p ends the string, oh well ignore it */
1618 + prefix_char = NUL;
1625 + * The last character of the format string was %.
1632 + * The default case is for unrecognized %'s.
1633 + * We print %<char> to help the user identify what
1634 + * option is not understood.
1635 + * This is also useful in case the user wants to pass
1636 + * the output of format_converter to another function
1637 + * that understands some other %<char> (like syslog).
1638 + * Note that we can't point s inside fmt because the
1639 + * unknown <char> could be preceded by width etc.
1642 + char_buf[0] = '%';
1643 + char_buf[1] = *fmt;
1650 + if (prefix_char != NUL && s != S_NULL && s != char_buf) {
1651 + *--s = prefix_char;
1655 + if (adjust_width && adjust == RIGHT && min_width > s_len) {
1656 + if (pad_char == '0' && prefix_char != NUL) {
1657 + INS_CHAR(*s, sp, bep, cc);
1662 + PAD(min_width, s_len, pad_char);
1666 + * Print the string s.
1668 + for (i = s_len; i != 0; i--) {
1669 + INS_CHAR(*s, sp, bep, cc);
1673 + if (adjust_width && adjust == LEFT && min_width > s_len)
1674 + PAD(min_width, s_len, pad_char);
1678 + vbuff->curpos = sp;
1683 +static int snprintf_flush(ap_vformatter_buff *vbuff)
1685 + /* if the buffer fills we have to abort immediately, there is no way
1686 + * to "flush" an ap_snprintf... there's nowhere to flush it to.
1692 +API_EXPORT(int) ap_snprintf(char *buf, size_t len, const char *format,...)
1696 + ap_vformatter_buff vbuff;
1701 + /* save one byte for nul terminator */
1702 + vbuff.curpos = buf;
1703 + vbuff.endpos = buf + len - 1;
1704 + va_start(ap, format);
1705 + cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
1707 + *vbuff.curpos = '\0';
1708 + return (cc == -1) ? len : cc;
1712 +API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
1716 + ap_vformatter_buff vbuff;
1721 + /* save one byte for nul terminator */
1722 + vbuff.curpos = buf;
1723 + vbuff.endpos = buf + len - 1;
1724 + cc = ap_vformatter(snprintf_flush, &vbuff, format, ap);
1725 + *vbuff.curpos = '\0';
1726 + return (cc == -1) ? len : cc;
1728 diff -Nur apache_1.3.22.orig/src/include/ap.h apache_1.3.22/src/include/ap.h
1729 --- apache_1.3.22.orig/src/include/ap.h Mon Jan 15 18:04:22 2001
1730 +++ apache_1.3.22/src/include/ap.h Fri Dec 7 17:27:28 2001
1732 * with some extensions. The extensions are:
1734 * %pA takes a struct in_addr *, and prints it as a.b.c.d
1735 - * %pI takes a struct sockaddr_in * and prints it as a.b.c.d:port
1736 + * %pI takes a struct sockaddr * and prints it as a.b.c.d:port, or
1737 + * ipv6-numeric-addr:port
1738 * %pp takes a void * and outputs it in hex
1740 * The %p hacks are to force gcc's printf warning code to skip
1741 diff -Nur apache_1.3.22.orig/src/include/ap_config.h apache_1.3.22/src/include/ap_config.h
1742 --- apache_1.3.22.orig/src/include/ap_config.h Mon Oct 8 17:49:33 2001
1743 +++ apache_1.3.22/src/include/ap_config.h Fri Dec 7 17:27:28 2001
1744 @@ -405,6 +405,10 @@
1747 #define S_IWOTH 000002
1749 +typedef int rlim_t;
1751 +typedef u_long n_long;
1754 #define STDIN_FILENO 0
1755 @@ -1488,6 +1492,70 @@
1756 #define ap_wait_t int
1760 +#define sockaddr_storage sockaddr
1761 +#define ss_family sa_family
1762 +#define ss_len sa_len
1764 +#include "sockaddr_storage.h" /* sshida@st.rim.or.jp */
1767 +#ifndef INET6_ADDRSTRLEN
1768 +#define INET6_ADDRSTRLEN 46
1770 +#ifndef INET_ADDRSTRLEN
1771 +#define INET_ADDRSTRLEN 16
1774 +#define NI_MAXHOST 1025
1777 +#define NI_MAXSERV 32
1780 +#if defined(NEED_GETADDRINFO) || defined(NEED_GETNAMEINFO)
1782 + * minimal definitions for fake getaddrinfo()/getnameinfo().
1785 +#define EAI_NODATA 1
1786 +#define EAI_MEMORY 2
1790 +#define AI_PASSIVE 1
1791 +#define AI_CANONNAME 2
1792 +#define AI_NUMERICHOST 4
1793 +#define NI_NUMERICHOST 8
1794 +#define NI_NAMEREQD 16
1795 +#define NI_NUMERICSERV 32
1799 +#ifdef NEED_GETADDRINFO
1800 +#ifdef NEED_ADDRINFO
1802 + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
1803 + int ai_family; /* PF_xxx */
1804 + int ai_socktype; /* SOCK_xxx */
1805 + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
1806 + size_t ai_addrlen; /* length of ai_addr */
1807 + char *ai_canonname; /* canonical name for hostname */
1808 + struct sockaddr *ai_addr; /* binary address */
1809 + struct addrinfo *ai_next; /* next structure in linked list */
1812 +extern char *gai_strerror(int ecode);
1813 +extern void freeaddrinfo(struct addrinfo *ai);
1814 +extern int getaddrinfo(const char *hostname, const char *servname,
1815 + const struct addrinfo *hints, struct addrinfo **res);
1817 +#ifdef NEED_GETNAMEINFO
1818 +extern int getnameinfo(const struct sockaddr *sa, size_t salen,
1819 + char *host, size_t hostlen, char *serv, size_t servlen,
1826 diff -Nur apache_1.3.22.orig/src/include/http_conf_globals.h apache_1.3.22/src/include/http_conf_globals.h
1827 --- apache_1.3.22.orig/src/include/http_conf_globals.h Fri Dec 7 17:26:57 2001
1828 +++ apache_1.3.22/src/include/http_conf_globals.h Fri Dec 7 17:27:28 2001
1830 extern API_VAR_EXPORT int ap_max_requests_per_child;
1831 extern API_VAR_EXPORT int ap_threads_per_child;
1832 extern API_VAR_EXPORT int ap_excess_requests_per_child;
1833 -extern struct in_addr ap_bind_address;
1834 +extern struct sockaddr_storage ap_bind_address;
1835 +extern API_VAR_EXPORT int ap_default_family;
1836 extern listen_rec *ap_listeners;
1837 extern API_VAR_EXPORT int ap_daemons_to_start;
1838 extern API_VAR_EXPORT int ap_daemons_min_free;
1839 diff -Nur apache_1.3.22.orig/src/include/http_vhost.h apache_1.3.22/src/include/http_vhost.h
1840 --- apache_1.3.22.orig/src/include/http_vhost.h Mon Jan 15 18:04:37 2001
1841 +++ apache_1.3.22/src/include/http_vhost.h Fri Dec 7 17:27:28 2001
1843 const char *ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s);
1845 /* handle NameVirtualHost directive */
1846 -const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg);
1847 +const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *h, char *p);
1849 /* given an ip address only, give our best guess as to what vhost it is */
1850 void ap_update_vhost_given_ip(conn_rec *conn);
1851 diff -Nur apache_1.3.22.orig/src/include/httpd.h apache_1.3.22/src/include/httpd.h
1852 --- apache_1.3.22.orig/src/include/httpd.h Fri Dec 7 17:26:57 2001
1853 +++ apache_1.3.22/src/include/httpd.h Fri Dec 7 17:27:28 2001
1856 /* Who is the client? */
1858 - struct sockaddr_in local_addr; /* local address */
1859 - struct sockaddr_in remote_addr; /* remote address */
1860 + struct sockaddr_storage local_addr; /* local address */
1861 + struct sockaddr_storage remote_addr; /* remote address */
1862 char *remote_ip; /* Client's IP address */
1863 char *remote_host; /* Client's DNS name, if known.
1864 * NULL if DNS hasn't been checked,
1866 typedef struct server_addr_rec server_addr_rec;
1867 struct server_addr_rec {
1868 server_addr_rec *next;
1869 - struct in_addr host_addr; /* The bound address, for this server */
1870 - unsigned short host_port; /* The bound port, for this server */
1871 + struct sockaddr_storage host_addr; /* The bound address, for this server */
1872 + unsigned short host_port; /* The bound port, for this server XXX */
1873 char *virthost; /* The name given in <VirtualHost> */
1876 @@ -1024,7 +1024,7 @@
1877 /* These are more like real hosts than virtual hosts */
1880 - struct sockaddr_in local_addr; /* local IP address and port */
1881 + struct sockaddr_storage local_addr; /* local IP address and port */
1883 int used; /* Only used during restart */
1884 /* more stuff here, like which protocol is bound to the port */
1885 @@ -1184,7 +1184,7 @@
1886 #endif /*#ifdef CHARSET_EBCDIC*/
1888 char *ap_get_local_host(pool *);
1889 -unsigned long ap_get_virthost_addr(char *hostname, unsigned short *port);
1890 +struct sockaddr *ap_get_virthost_addr(char *hostname, unsigned short *port);
1892 extern API_VAR_EXPORT time_t ap_restart_time;
1894 diff -Nur apache_1.3.22.orig/src/include/sa_len.h apache_1.3.22/src/include/sa_len.h
1895 --- apache_1.3.22.orig/src/include/sa_len.h Thu Jan 1 01:00:00 1970
1896 +++ apache_1.3.22/src/include/sa_len.h Fri Dec 7 17:27:28 2001
1898 +/* sa_len.h : tiny version of SA_LEN (written by <yoshfuji@ecei.tohoku.ac.jp>) */
1900 +#include <sys/types.h>
1901 +#include <sys/socket.h>
1902 +#include <netinet/in.h>
1903 +#include <sys/un.h>
1905 +#ifndef HAVE_SOCKADDR_LEN
1907 +#define SA_LEN(s_) ap_sa_len((s_)->sa_family)
1909 +static NET_SIZE_T ap_sa_len (sa_family_t af)
1912 +#if defined(AF_INET)
1914 + return (sizeof(struct sockaddr_in));
1915 +#endif /* AF_INET */
1916 +#if defined(AF_INET6)
1918 + return (sizeof(struct sockaddr_in6));
1922 +#endif /* AF_LOCAL */
1923 +#if defined(AF_UNIX) && (AF_UNIX != AF_LOCAL)
1925 +#endif /* AF_UNIX */
1926 +#if defined(AF_FILE) && (AF_FILE != AF_LOCAL || AF_FILE != AF_UNIX)
1928 +#endif /* AF_FILE */
1929 +#if defined(AF_LOCAL) || defined(AF_UNIX) || defined(AF_FILE)
1930 + return (sizeof(struct sockaddr_un));
1931 +#endif /* defined(AF_LOCAL) || defined(AF_UNIX) || defined(AF_FILE) */
1937 +#endif /* SA_LEN */
1938 +#endif /* HAVE_SOCKADDR_LEN */
1939 diff -Nur apache_1.3.22.orig/src/include/sockaddr_storage.h apache_1.3.22/src/include/sockaddr_storage.h
1940 --- apache_1.3.22.orig/src/include/sockaddr_storage.h Thu Jan 1 01:00:00 1970
1941 +++ apache_1.3.22/src/include/sockaddr_storage.h Fri Dec 7 17:27:28 2001
1944 +struct sockaddr_storage
1946 + RFC2553 proposes struct sockaddr_storage.
1947 + This is a placeholder for all sockaddr-variant structures. This is
1948 + implemented like follows:
1950 + You should use this structure to hold any of sockaddr-variant
1953 +#ifdef NEED_SOCKADDR_STORAGE
1955 +struct sockaddr_storage {
1956 +#ifdef HAVE_SOCKADDR_LEN
1960 + u_short ss_family;
1962 + u_char __padding[128 - 2];
1968 + Alternatively, you may want to implement sockunion.h, with the
1969 + following content:
1971 + NOTE: For better portability, struct sockaddr_storage should be used.
1972 + union sockunion is okay, but is not really portable enough.
1976 +#ifdef HAVE_SOCKADDR_LEN
1980 + u_short si_family;
1984 + struct sockaddr_in su_sin;
1986 + struct sockaddr_in6 su_sin6;
1989 +#ifdef HAVE_SOCKADDR_LEN
1990 +#define su_len su_si.si_len
1992 +#define su_family su_si.si_family
1993 +#define su_port su_si.si_port
1995 +#endif /* NEED_SOCKADDR_STORAGE */
1996 diff -Nur apache_1.3.22.orig/src/main/getaddrinfo.c apache_1.3.22/src/main/getaddrinfo.c
1997 --- apache_1.3.22.orig/src/main/getaddrinfo.c Thu Jan 1 01:00:00 1970
1998 +++ apache_1.3.22/src/main/getaddrinfo.c Fri Dec 7 17:27:28 2001
2001 + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
2002 + * All rights reserved.
2004 + * Redistribution and use in source and binary forms, with or without
2005 + * modification, are permitted provided that the following conditions
2007 + * 1. Redistributions of source code must retain the above copyright
2008 + * notice, this list of conditions and the following disclaimer.
2009 + * 2. Redistributions in binary form must reproduce the above copyright
2010 + * notice, this list of conditions and the following disclaimer in the
2011 + * documentation and/or other materials provided with the distribution.
2012 + * 3. Neither the name of the project nor the names of its contributors
2013 + * may be used to endorse or promote products derived from this software
2014 + * without specific prior written permission.
2016 + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2017 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2018 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2019 + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2020 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2021 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2022 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2023 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2024 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2025 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2029 + * fake library for ssh v6 enabler patch
2031 + * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
2032 + * These funtions are defined in rfc2133.
2034 + * But these functions are not implemented correctly. The minimum subset
2035 + * is implemented for ssh use only. For exapmle, this routine assumes
2036 + * that ai_family is AF_INET. Don't use it for another purpose.
2038 + * In the case not using 'configure --enable-ipv6', this getaddrinfo.c
2039 + * will be used if you have broken getaddrinfo or no getaddrinfo.
2043 +#include <stdlib.h>
2044 +#include <sys/types.h>
2045 +#include <sys/socket.h>
2046 +#include <netinet/in.h>
2047 +#include <arpa/inet.h>
2052 +static struct addrinfo *
2053 +malloc_ai(port, addr, socktype, protocol)
2059 + struct addrinfo *ai;
2061 + if (ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) +
2062 + sizeof(struct sockaddr_in))) {
2063 + memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
2064 + ai->ai_addr = (struct sockaddr *)(ai + 1);
2065 +#if defined(HAVE_SOCKADDR_LEN)
2066 + ai->ai_addr->sa_len =
2068 + ai->ai_addrlen = sizeof(struct sockaddr_in);
2069 + ai->ai_addr->sa_family = ai->ai_family = AF_INET;
2070 + ai->ai_socktype = socktype;
2071 + ai->ai_protocol = protocol;
2072 + ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
2073 + ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
2081 +gai_strerror(ecode)
2086 + return "no address associated with hostname.";
2088 + return "memory allocation failure.";
2090 + return "unknown error.";
2096 +struct addrinfo *ai;
2098 + struct addrinfo *next;
2101 + next = ai->ai_next;
2103 + } while (ai = next);
2107 +getaddrinfo(hostname, servname, hints, res)
2108 +const char *hostname, *servname;
2109 +const struct addrinfo *hints;
2110 +struct addrinfo **res;
2112 + struct addrinfo *cur, *prev = NULL;
2113 + struct hostent *hp;
2117 + port = htons(atoi(servname));
2120 + if (hints && hints->ai_flags & AI_PASSIVE)
2121 + if (*res = malloc_ai(port, htonl(0x00000000),
2122 + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM,
2123 + (*res)->ai_protocol))
2126 + return EAI_MEMORY;
2128 + if (*res = malloc_ai(port, htonl(0x7f000001),
2129 + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM,
2130 + (*res)->ai_protocol))
2133 + return EAI_MEMORY;
2134 + if (inet_addr(hostname) != -1)
2135 + if (*res = malloc_ai(port, inet_addr(hostname),
2136 + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM,
2137 + (*res)->ai_protocol))
2140 + return EAI_MEMORY;
2141 + if ((hp = gethostbyname(hostname)) &&
2142 + hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
2143 + for (i = 0; hp->h_addr_list[i]; i++)
2144 + if (cur = malloc_ai(port,
2145 + ((struct in_addr *)hp->h_addr_list[i])->s_addr,
2146 + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM,
2147 + (*res)->ai_protocol)) {
2149 + prev->ai_next = cur;
2155 + freeaddrinfo(*res);
2156 + return EAI_MEMORY;
2160 + return EAI_NODATA;
2162 diff -Nur apache_1.3.22.orig/src/main/getnameinfo.c apache_1.3.22/src/main/getnameinfo.c
2163 --- apache_1.3.22.orig/src/main/getnameinfo.c Thu Jan 1 01:00:00 1970
2164 +++ apache_1.3.22/src/main/getnameinfo.c Fri Dec 7 17:27:28 2001
2167 + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
2168 + * All rights reserved.
2170 + * Redistribution and use in source and binary forms, with or without
2171 + * modification, are permitted provided that the following conditions
2173 + * 1. Redistributions of source code must retain the above copyright
2174 + * notice, this list of conditions and the following disclaimer.
2175 + * 2. Redistributions in binary form must reproduce the above copyright
2176 + * notice, this list of conditions and the following disclaimer in the
2177 + * documentation and/or other materials provided with the distribution.
2178 + * 3. Neither the name of the project nor the names of its contributors
2179 + * may be used to endorse or promote products derived from this software
2180 + * without specific prior written permission.
2182 + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2183 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2184 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2185 + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2186 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2187 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2188 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2189 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2190 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2191 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2195 + * fake library for ssh v6 enabler patch
2197 + * This file includes getnameinfo().
2198 + * These funtions are defined in rfc2133.
2200 + * But these functions are not implemented correctly. The minimum subset
2201 + * is implemented for ssh use only. For exapmle, this routine assumes
2202 + * that ai_family is AF_INET. Don't use it for another purpose.
2204 + * In the case not using 'configure --enable-ipv6', this getnameinfo.c
2205 + * will be used if you have broken getnameinfo or no getnameinfo.
2209 +#include <stdlib.h>
2210 +#include <sys/types.h>
2211 +#include <sys/socket.h>
2212 +#include <netinet/in.h>
2213 +#include <arpa/inet.h>
2215 +#include <string.h>
2220 +getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
2221 +const struct sockaddr *sa;
2229 + struct sockaddr_in *sin = (struct sockaddr_in *)sa;
2230 + struct hostent *hp;
2234 + sprintf(tmpserv, "%d", ntohs(sin->sin_port));
2235 + if (strlen(tmpserv) > servlen)
2236 + return EAI_MEMORY;
2238 + strcpy(serv, tmpserv);
2241 + if (flags & NI_NUMERICHOST)
2242 + if (strlen(inet_ntoa(sin->sin_addr)) > hostlen)
2243 + return EAI_MEMORY;
2245 + strcpy(host, inet_ntoa(sin->sin_addr));
2249 + if (hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr),
2251 + if (strlen(hp->h_name) > hostlen)
2252 + return EAI_MEMORY;
2254 + strcpy(host, hp->h_name);
2258 + return EAI_NODATA;
2261 diff -Nur apache_1.3.22.orig/src/main/http_config.c apache_1.3.22/src/main/http_config.c
2262 --- apache_1.3.22.orig/src/main/http_config.c Fri Dec 7 17:26:57 2001
2263 +++ apache_1.3.22/src/main/http_config.c Fri Dec 7 17:27:28 2001
2264 @@ -1564,7 +1564,6 @@
2265 ap_scoreboard_fname = DEFAULT_SCOREBOARD;
2266 ap_lock_fname = DEFAULT_LOCKFILE;
2267 ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD;
2268 - ap_bind_address.s_addr = htonl(INADDR_ANY);
2269 ap_listeners = NULL;
2270 ap_listenbacklog = DEFAULT_LISTENBACKLOG;
2271 ap_extended_status = 0;
2272 @@ -1597,7 +1596,13 @@
2274 s->addrs = ap_pcalloc(p, sizeof(server_addr_rec));
2275 /* NOT virtual host; don't match any real network interface */
2276 - s->addrs->host_addr.s_addr = htonl(INADDR_ANY);
2277 + memset(&s->addrs->host_addr, 0, sizeof(s->addrs->host_addr));
2279 + s->addrs->host_addr.ss_family = ap_default_family; /* XXX: needed?, XXX: PF_xxx can be different from AF_xxx */
2281 +#ifdef HAVE_SOCKADDR_LEN
2282 + s->addrs->host_addr.ss_len = sizeof(s->addrs->host_addr); /* XXX: needed ? */
2284 s->addrs->host_port = 0; /* matches any port */
2285 s->addrs->virthost = ""; /* must be non-NULL */
2286 s->names = s->wild_names = NULL;
2287 @@ -1616,19 +1621,33 @@
2288 static void default_listeners(pool *p, server_rec *s)
2291 + struct addrinfo hints, *res0, *res;
2293 + char servbuf[NI_MAXSERV];
2295 if (ap_listeners != NULL) {
2298 + ap_snprintf(servbuf, sizeof(servbuf), "%d", s->port ? s->port : DEFAULT_HTTP_PORT);
2299 + memset (&hints, 0, sizeof(hints));
2300 + hints.ai_family = ap_default_family;
2301 + hints.ai_socktype = SOCK_STREAM;
2302 + hints.ai_flags = AI_PASSIVE;
2303 + gai = getaddrinfo(NULL, servbuf, &hints, &res0);
2305 + fprintf(stderr, "default_listeners(): getaddrinfo(PASSIVE) for family %u: %s\n",
2306 + gai_strerror(gai), ap_default_family);
2309 /* allocate a default listener */
2310 new = ap_pcalloc(p, sizeof(listen_rec));
2311 - new->local_addr.sin_family = AF_INET;
2312 - new->local_addr.sin_addr = ap_bind_address;
2313 - new->local_addr.sin_port = htons(s->port ? s->port : DEFAULT_HTTP_PORT);
2314 + memcpy(&new->local_addr, res0->ai_addr, res0->ai_addrlen);
2320 + freeaddrinfo(res0);
2324 diff -Nur apache_1.3.22.orig/src/main/http_core.c apache_1.3.22/src/main/http_core.c
2325 --- apache_1.3.22.orig/src/main/http_core.c Tue Sep 4 20:15:15 2001
2326 +++ apache_1.3.22/src/main/http_core.c Fri Dec 7 17:27:28 2001
2328 #include "util_md5.h"
2329 #include "scoreboard.h"
2330 #include "fnmatch.h"
2331 +#include "sa_len.h"
2333 #ifdef USE_MMAP_FILES
2334 #include <sys/mman.h>
2336 /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
2337 static ap_inline void do_double_reverse (conn_rec *conn)
2339 - struct hostent *hptr;
2340 + struct addrinfo hints, *res, *res0;
2341 + char hostbuf1[128], hostbuf2[128]; /* INET6_ADDRSTRLEN(=46) is enough */
2344 if (conn->double_reverse) {
2346 @@ -605,28 +608,51 @@
2347 conn->double_reverse = -1;
2350 - hptr = gethostbyname(conn->remote_host);
2354 - for (haddr = hptr->h_addr_list; *haddr; haddr++) {
2355 - if (((struct in_addr *)(*haddr))->s_addr
2356 - == conn->remote_addr.sin_addr.s_addr) {
2357 - conn->double_reverse = 1;
2360 + memset(&hints, 0, sizeof(hints));
2361 + hints.ai_family = PF_UNSPEC;
2362 + hints.ai_socktype = SOCK_STREAM;
2363 + if (getaddrinfo(conn->remote_host, NULL, &hints, &res0)) {
2364 + conn->double_reverse = -1;
2367 + for (res = res0; res; res = res->ai_next) {
2368 + if (res->ai_addr->sa_family != conn->remote_addr.ss_family ||
2369 + !(res->ai_family == AF_INET
2371 + || res->ai_family == AF_INET6
2376 +#ifndef HAVE_SOCKADDR_LEN
2377 + if (res->ai_addrlen != SA_LEN((struct sockaddr *)&conn->remote_addr))
2379 + if (res->ai_addr->sa_len != conn->remote_addr.ss_len)
2382 + if (getnameinfo(res->ai_addr, res->ai_addrlen,
2383 + hostbuf1, sizeof(hostbuf1), NULL, 0,
2386 + if (getnameinfo(((struct sockaddr *)&conn->remote_addr), res->ai_addrlen,
2387 + hostbuf2, sizeof(hostbuf2), NULL, 0,
2390 + if (strcmp(hostbuf1, hostbuf2) == 0){
2395 - conn->double_reverse = -1;
2396 + conn->double_reverse = ok ? 1 : -1;
2397 + freeaddrinfo(res0);
2400 API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
2403 - struct in_addr *iaddr;
2404 - struct hostent *hptr;
2405 int hostname_lookups;
2406 int old_stat = SERVER_DEAD; /* we shouldn't ever be in this state */
2407 + char hostnamebuf[MAXHOSTNAMELEN];
2409 /* If we haven't checked the host name, and we want to */
2411 @@ -648,10 +674,14 @@
2412 || hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
2413 old_stat = ap_update_child_status(conn->child_num, SERVER_BUSY_DNS,
2414 (request_rec*)NULL);
2415 - iaddr = &(conn->remote_addr.sin_addr);
2416 - hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
2417 - if (hptr != NULL) {
2418 - conn->remote_host = ap_pstrdup(conn->pool, (void *)hptr->h_name);
2419 + if (!getnameinfo((struct sockaddr *)&conn->remote_addr,
2421 + SA_LEN((struct sockaddr *)&conn->remote_addr),
2423 + conn->remote_addr.ss_len,
2425 + hostnamebuf, sizeof(hostnamebuf), NULL, 0, 0)) {
2426 + conn->remote_host = ap_pstrdup(conn->pool, (void *)hostnamebuf);
2427 ap_str_tolower(conn->remote_host);
2429 if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
2432 conn_rec *conn = r->connection;
2434 + char hbuf[MAXHOSTNAMELEN];
2436 d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
2438 @@ -741,23 +772,22 @@
2440 if (d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
2441 if (conn->local_host == NULL) {
2442 - struct in_addr *iaddr;
2443 - struct hostent *hptr;
2445 old_stat = ap_update_child_status(conn->child_num,
2446 SERVER_BUSY_DNS, r);
2447 - iaddr = &(conn->local_addr.sin_addr);
2448 - hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr),
2450 - if (hptr != NULL) {
2451 - conn->local_host = ap_pstrdup(conn->pool,
2452 - (void *)hptr->h_name);
2453 - ap_str_tolower(conn->local_host);
2456 - conn->local_host = ap_pstrdup(conn->pool,
2457 - r->server->server_hostname);
2458 + if (getnameinfo((struct sockaddr *)&conn->local_addr,
2460 + SA_LEN((struct sockaddr *)&conn->local_addr),
2462 + conn->local_addr.ss_len,
2464 + hbuf, sizeof(hbuf), NULL, 0, 0) == 0) {
2465 + conn->local_host = ap_pstrdup(conn->pool, hbuf);
2467 + conn->local_host = ap_pstrdup(conn->pool,
2468 + r->server->server_hostname);
2470 + ap_str_tolower(conn->local_host);
2471 (void) ap_update_child_status(conn->child_num, old_stat, r);
2473 return conn->local_host;
2474 @@ -776,11 +806,13 @@
2476 if (d->use_canonical_name == USE_CANONICAL_NAME_OFF
2477 || d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
2478 - return r->hostname ? ntohs(r->connection->local_addr.sin_port)
2483 + return r->hostname
2484 + ? ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port)
2487 + return r->hostname
2488 + ? ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port)
2492 API_EXPORT(char *) ap_construct_url(pool *p, const char *uri,
2493 @@ -2503,12 +2535,25 @@
2495 static const char *set_bind_address(cmd_parms *cmd, void *dummy, char *arg)
2497 + struct addrinfo hints, *res;
2498 + struct sockaddr *sa;
2501 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2506 - ap_bind_address.s_addr = ap_get_virthost_addr(arg, NULL);
2507 + if (strcmp(arg, "*") == 0)
2510 + sa = ap_get_virthost_addr(arg, NULL);
2511 +#ifdef HAVE_SOCKADDR_LEN
2512 + sa_len = sa->sa_len;
2514 + sa_len = SA_LEN(sa);
2516 + memcpy(&ap_bind_address, &sa, sa_len);
2520 @@ -2540,44 +2585,70 @@
2524 -static const char *set_listener(cmd_parms *cmd, void *dummy, char *ips)
2525 +static const char *set_listener(cmd_parms *cmd, void *dummy, char *h, char *p)
2529 - unsigned short port;
2530 + char *host, *port;
2531 + struct addrinfo hints, *res;
2534 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2539 - ports = strchr(ips, ':');
2540 - if (ports != NULL) {
2541 - if (ports == ips) {
2542 - return "Missing IP address";
2544 - else if (ports[1] == '\0') {
2545 - return "Address must end in :<port-number>";
2546 + host = port = NULL;
2548 + port = strrchr(h, ':');
2549 + if (port != NULL) {
2551 + return "Missing IP address";
2553 + else if (port[1] == '\0') {
2554 + return "Address must end in :<port-number>";
2563 - *(ports++) = '\0';
2572 - new=ap_pcalloc(cmd->pool, sizeof(listen_rec));
2573 - new->local_addr.sin_family = AF_INET;
2574 - if (ports == ips) { /* no address */
2575 - new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
2578 - new->local_addr.sin_addr.s_addr = ap_get_virthost_addr(ips, NULL);
2580 - port = atoi(ports);
2582 - return "Port must be numeric";
2583 + if (host && strcmp(host, "*") == 0)
2586 + new = ap_pcalloc(cmd->pool, sizeof(listen_rec));
2588 + memset(&hints, 0, sizeof(hints));
2589 + hints.ai_family = host ? PF_UNSPEC : ap_default_family;
2590 + hints.ai_flags = AI_PASSIVE;
2591 + hints.ai_socktype = SOCK_STREAM;
2592 + error = getaddrinfo(host, port, &hints, &res);
2593 + if (error || !res) {
2594 + fprintf(stderr, "could not resolve ");
2596 + fprintf(stderr, "host \"%s\" ", host);
2598 + fprintf(stderr, "port \"%s\" ", port);
2599 + fprintf(stderr, "--- %s\n", gai_strerror(error));
2602 + if (res->ai_next) {
2604 + fprintf(stderr, "host \"%s\" ", host);
2606 + fprintf(stderr, "port \"%s\" ", port);
2607 + fprintf(stderr, "resolved to multiple addresses, ambiguous.\n");
2610 - new->local_addr.sin_port = htons(port);
2612 + memcpy(&new->local_addr, res->ai_addr, res->ai_addrlen);
2616 new->next = ap_listeners;
2617 @@ -3163,7 +3234,7 @@
2618 { "ThreadStackSize", set_threadstacksize, NULL, RSRC_CONF, TAKE1,
2619 "Stack size each created thread will use."},
2621 -{ "Listen", set_listener, NULL, RSRC_CONF, TAKE1,
2622 +{ "Listen", set_listener, NULL, RSRC_CONF, TAKE12,
2623 "A port number or a numeric IP address and a port number"},
2624 { "SendBufferSize", set_send_buffer_size, NULL, RSRC_CONF, TAKE1,
2625 "Send buffer size in bytes"},
2626 @@ -3197,7 +3268,7 @@
2627 "Name of the config file to be included" },
2628 { "LogLevel", set_loglevel, NULL, RSRC_CONF, TAKE1,
2629 "Level of verbosity in error logging" },
2630 -{ "NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, TAKE1,
2631 +{ "NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, TAKE12,
2632 "A numeric IP address:port, or the name of a host" },
2634 { "BS2000Account", set_bs2000_account, NULL, RSRC_CONF, TAKE1,
2635 diff -Nur apache_1.3.22.orig/src/main/http_main.c apache_1.3.22/src/main/http_main.c
2636 --- apache_1.3.22.orig/src/main/http_main.c Fri Dec 7 17:26:57 2001
2637 +++ apache_1.3.22/src/main/http_main.c Fri Dec 7 17:27:28 2001
2639 #include <bstring.h> /* for IRIX, FD_SET calls bzero() */
2642 +#include "sa_len.h"
2645 /* special debug stuff -- PCS */
2647 @@ -250,7 +252,12 @@
2648 API_VAR_EXPORT char *ap_scoreboard_fname=NULL;
2649 char *ap_lock_fname;
2650 API_VAR_EXPORT char *ap_server_argv0=NULL;
2651 -struct in_addr ap_bind_address;
2653 +API_VAR_EXPORT int ap_default_family = PF_INET6;
2655 +API_VAR_EXPORT int ap_default_family = PF_INET;
2657 +struct sockaddr_storage ap_bind_address;
2658 API_VAR_EXPORT int ap_daemons_to_start=0;
2659 API_VAR_EXPORT int ap_daemons_min_free=0;
2660 API_VAR_EXPORT int ap_daemons_max_free=0;
2661 @@ -1310,7 +1317,11 @@
2662 fprintf(stderr, "Usage: %s [-D name] [-d directory] [-f file]\n", bin);
2664 fprintf(stderr, " %s [-C \"directive\"] [-c \"directive\"]\n", pad);
2665 - fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T]\n", pad);
2666 + fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T]"
2671 fprintf(stderr, "Options:\n");
2673 fprintf(stderr, " -R directory : specify an alternate location for shared object files\n");
2674 @@ -1332,6 +1343,10 @@
2676 fprintf(stderr, " -t : run syntax check for config files (with docroot check)\n");
2677 fprintf(stderr, " -T : run syntax check for config files (without docroot check)\n");
2679 + fprintf(stderr, " -4 : assume IPv4 on parsing configuration file\n");
2680 + fprintf(stderr, " -6 : assume IPv6 on parsing configuration file\n");
2683 fprintf(stderr, " -n name : name the Apache service for -k options below;\n");
2684 fprintf(stderr, " -k stop|shutdown : tell running Apache to shutdown\n");
2685 @@ -3495,11 +3510,13 @@
2688 static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout,
2689 - const struct sockaddr_in *remaddr,
2690 - const struct sockaddr_in *saddr,
2691 + const struct sockaddr *remaddr,
2692 + const struct sockaddr *saddr,
2695 conn_rec *conn = (conn_rec *) ap_pcalloc(p, sizeof(conn_rec));
2696 + char hostnamebuf[MAXHOSTNAMELEN];
2699 /* Got a connection structure, so initialize what fields we can
2700 * (the rest are zeroed out by pcalloc).
2701 @@ -3508,17 +3525,29 @@
2702 conn->child_num = child_num;
2705 - conn->local_addr = *saddr;
2706 - conn->local_ip = ap_pstrdup(conn->pool,
2707 - inet_ntoa(conn->local_addr.sin_addr));
2709 + addr_len = SA_LEN(saddr);
2711 + addr_len = saddr->sa_len;
2713 + memcpy(&conn->local_addr, saddr, addr_len);
2714 + getnameinfo((struct sockaddr *)&conn->local_addr, addr_len,
2715 + hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
2716 + conn->local_ip = ap_pstrdup(conn->pool, hostnamebuf);
2717 conn->server = server; /* just a guess for now */
2718 ap_update_vhost_given_ip(conn);
2719 conn->base_server = conn->server;
2720 conn->client = inout;
2722 - conn->remote_addr = *remaddr;
2723 - conn->remote_ip = ap_pstrdup(conn->pool,
2724 - inet_ntoa(conn->remote_addr.sin_addr));
2726 + addr_len = SA_LEN(remaddr);
2728 + addr_len = remaddr->sa_len;
2730 + memcpy(&conn->remote_addr, remaddr, addr_len);
2731 + getnameinfo((struct sockaddr *)&conn->remote_addr, addr_len,
2732 + hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
2733 + conn->remote_ip = ap_pstrdup(conn->pool, hostnamebuf);
2735 conn->ctx = ap_ctx_new(conn->pool);
2737 @@ -3569,21 +3598,47 @@
2738 #define sock_disable_nagle(s) /* NOOP */
2741 -static int make_sock(pool *p, const struct sockaddr_in *server)
2742 +static int make_sock(pool *p, const struct sockaddr *server)
2747 + char addr[INET6_ADDRSTRLEN + 128];
2748 + char a0[INET6_ADDRSTRLEN];
2749 + char p0[NI_MAXSERV];
2754 - if (server->sin_addr.s_addr != htonl(INADDR_ANY))
2755 - ap_snprintf(addr, sizeof(addr), "address %s port %d",
2756 - inet_ntoa(server->sin_addr), ntohs(server->sin_port));
2758 - ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
2759 + switch(server->sa_family){
2766 + ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
2767 + "make_sock: unsupported address family %u",
2768 + server->sa_family);
2769 + ap_unblock_alarms();
2773 + getnameinfo(server,
2779 + a0, sizeof(a0), p0, sizeof(p0), NI_NUMERICHOST | NI_NUMERICSERV);
2780 + ap_snprintf(addr, sizeof(addr), "address %s port %s", a0, p0);
2782 + if (atoi(p0) < 1024)
2786 /* note that because we're about to slack we don't use psocket */
2788 - if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
2789 + if ((s = socket(server->sa_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
2790 ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
2791 "make_sock: failed to get a socket for %s", addr);
2793 @@ -3686,15 +3741,19 @@
2796 /* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */
2797 - if (ntohs(server->sin_port) < 1024)
2802 - if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) {
2804 + if (bind(s, server, SA_LEN(server)) == -1)
2806 + if (bind(s, server, server->sa_len) == -1)
2809 ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
2810 "make_sock: could not bind to %s", addr);
2812 - if (ntohs(server->sin_port) < 1024)
2817 @@ -3707,7 +3766,7 @@
2821 - if (ntohs(server->sin_port) < 1024)
2826 @@ -3854,15 +3913,17 @@
2828 fd = find_listener(lr);
2830 - fd = make_sock(p, &lr->local_addr);
2831 + fd = make_sock(p, (struct sockaddr *)&lr->local_addr);
2834 ap_note_cleanups_for_socket(p, fd);
2836 /* if we get here, (fd >= 0) && (fd < FD_SETSIZE) */
2837 - FD_SET(fd, &listenfds);
2838 - if (fd > listenmaxfd)
2841 + FD_SET(fd, &listenfds);
2842 + if (fd > listenmaxfd)
2846 if (lr->next == NULL)
2848 @@ -4174,8 +4235,8 @@
2849 static void child_main(int child_num_arg)
2852 - struct sockaddr sa_server;
2853 - struct sockaddr sa_client;
2854 + struct sockaddr_storage sa_server;
2855 + struct sockaddr_storage sa_client;
2858 /* All of initialization is a critical section, we don't care if we're
2859 @@ -4340,7 +4401,7 @@
2862 clen = sizeof(sa_client);
2863 - csd = ap_accept(sd, &sa_client, &clen);
2864 + csd = ap_accept(sd, (struct sockaddr *)&sa_client, &clen);
2865 if (csd >= 0 || errno != EINTR)
2868 @@ -4490,7 +4551,7 @@
2871 clen = sizeof(sa_server);
2872 - if (getsockname(csd, &sa_server, &clen) < 0) {
2873 + if (getsockname(csd, (struct sockaddr *)&sa_server, &clen) < 0) {
2874 ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "getsockname");
2877 @@ -4535,8 +4596,8 @@
2878 ap_bpushfd(conn_io, csd, dupped_csd);
2880 current_conn = new_connection(ptrans, server_conf, conn_io,
2881 - (struct sockaddr_in *) &sa_client,
2882 - (struct sockaddr_in *) &sa_server,
2883 + (struct sockaddr *)&sa_client,
2884 + (struct sockaddr *)&sa_server,
2888 @@ -4680,12 +4741,13 @@
2891 /* BS2000 requires a "special" version of fork() before a setuid() call */
2892 - if ((pid = os_fork(ap_user_name)) == -1) {
2893 + if ((pid = os_fork(ap_user_name)) == -1)
2895 - if ((pid = os_fork(s, slot)) == -1) {
2896 + if ((pid = os_fork(s, slot)) == -1)
2898 - if ((pid = fork()) == -1) {
2899 + if ((pid = fork()) == -1)
2902 ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process");
2904 /* fork didn't succeed. Fix the scoreboard or else
2905 @@ -5294,7 +5356,10 @@
2906 ap_setup_prelinked_modules();
2908 while ((c = getopt(argc, argv,
2909 - "D:C:c:xXd:f:vVlLR:StTh"
2910 + "D:C:c:xXd:f:vVlLR:StTh4"
2914 #ifdef DEBUG_SIGSTOP
2917 @@ -5369,8 +5434,14 @@
2918 ap_configtestonly = 1;
2919 ap_docrootcheck = 0;
2924 + ap_default_family = PF_INET;
2928 + ap_default_family = PF_INET6;
2934 @@ -5450,9 +5521,10 @@
2938 - struct sockaddr sa_server, sa_client;
2940 + struct sockaddr_storage sa_server, sa_client;
2942 + char servbuf[NI_MAXSERV];
2945 /* Yes this is called twice. */
2946 @@ -5499,25 +5571,32 @@
2949 l = sizeof(sa_client);
2950 - if ((getpeername(sock_in, &sa_client, &l)) < 0) {
2951 + if ((getpeername(sock_in, (struct sockaddr *)&sa_client, &l)) < 0) {
2952 /* get peername will fail if the input isn't a socket */
2953 perror("getpeername");
2954 memset(&sa_client, '\0', sizeof(sa_client));
2957 l = sizeof(sa_server);
2958 - if (getsockname(sock_in, &sa_server, &l) < 0) {
2959 + if (getsockname(sock_in, (struct sockaddr *)&sa_server, &l) < 0) {
2960 perror("getsockname");
2961 fprintf(stderr, "Error getting local address\n");
2964 - server_conf->port = ntohs(((struct sockaddr_in *) &sa_server)->sin_port);
2965 + if (getnameinfo(((struct sockaddr *)&sa_server), l,
2966 + NULL, 0, servbuf, sizeof(servbuf),
2968 + fprintf(stderr, "getnameinfo(): family=%d\n", sa_server.ss_family);
2971 + servbuf[sizeof(servbuf)-1] = '\0';
2972 + server_conf->port = atoi(servbuf);
2973 cio = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
2975 cio->fd_in = sock_in;
2976 conn = new_connection(ptrans, server_conf, cio,
2977 - (struct sockaddr_in *) &sa_client,
2978 - (struct sockaddr_in *) &sa_server, -1);
2979 + (struct sockaddr *)&sa_client,
2980 + (struct sockaddr *)&sa_server, -1);
2982 while ((r = ap_read_request(conn)) != NULL) {
2984 @@ -7696,7 +7775,11 @@
2985 * but only handle the -L option
2987 llp_dir = SHARED_CORE_DIR;
2988 - while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLR:SZ:tTh")) != -1) {
2989 + while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLR:SZ:tTh4"
2997 @@ -7713,6 +7796,10 @@
3008 diff -Nur apache_1.3.22.orig/src/main/http_vhost.c apache_1.3.22/src/main/http_vhost.c
3009 --- apache_1.3.22.orig/src/main/http_vhost.c Sat Feb 24 11:09:46 2001
3010 +++ apache_1.3.22/src/main/http_vhost.c Fri Dec 7 17:27:28 2001
3012 #include "http_log.h"
3013 #include "http_vhost.h"
3014 #include "http_protocol.h"
3015 +#include "sa_len.h"
3018 * After all the definitions there's an explanation of how it's all put
3019 @@ -165,78 +166,114 @@
3020 * *paddr is the variable used to keep track of **paddr between calls
3021 * port is the default port to assume
3023 -static const char *get_addresses(pool *p, char *w, server_addr_rec ***paddr,
3025 +static const char *get_addresses(pool *p, char *w, char *pstr,
3026 + server_addr_rec ***paddr, unsigned port)
3028 - struct hostent *hep;
3029 - unsigned long my_addr;
3030 + struct addrinfo hints, *res, *res0;
3031 server_addr_rec *sar;
3033 - int i, is_an_ip_addr;
3034 + char *t = NULL, *u = NULL, *v = NULL;
3035 + char *hoststr = NULL, *portstr = NULL;
3036 + char portpool[10];
3038 + char servbuf[NI_MAXSERV];
3041 + if (w == 0 || *w == 0)
3044 - t = strchr(w, ':');
3046 - if (strcmp(t + 1, "*") == 0) {
3048 + portstr = portpool;
3049 + ap_snprintf(portpool, sizeof(portpool), "%u", port);
3054 + u = strrchr(w, ']');
3055 + if (u) { /* [host]:port or [host] */
3061 - else if ((i = atoi(t + 1))) {
3063 + /* w uv , w=v , w=v */
3064 + /* u!=0: [host]:port , u==0: [host:port , host */
3065 + t = strchr(v, ':');
3066 + if (t != NULL && strchr(t+1, ':') == NULL) {
3067 + /* [host]:port-w/o-colons, host-without-colons:port-w/o-colons */
3072 - return ":port must be numeric";
3080 - is_an_ip_addr = 0;
3081 - if (strcmp(w, "*") == 0) {
3082 - my_addr = htonl(INADDR_ANY);
3083 - is_an_ip_addr = 1;
3085 - else if (strcasecmp(w, "_default_") == 0
3086 - || strcmp(w, "255.255.255.255") == 0) {
3087 - my_addr = DEFAULT_VHOST_ADDR;
3088 - is_an_ip_addr = 1;
3090 - else if ((my_addr = ap_inet_addr(w)) != INADDR_NONE) {
3091 - is_an_ip_addr = 1;
3092 + memset(&hints, 0, sizeof(hints));
3093 + hints.ai_socktype = SOCK_STREAM;
3094 + if (strcmp(w, "*") == 0 || strlen(w) == 0) {
3096 + hints.ai_family = PF_UNSPEC;
3097 + hints.ai_flags = AI_PASSIVE;
3099 + else if (strcasecmp(w, "_default4_") == 0 ||
3100 + ((ap_default_family == PF_INET
3102 + || ap_default_family == PF_UNSPEC
3104 + ) && strcasecmp(w, "_default_") == 0)){
3105 + hoststr = "255.255.255.255";
3106 + hints.ai_family = PF_INET;
3109 + else if (strcasecmp(w, "_default6_") == 0 ||
3110 + ((ap_default_family == PF_INET6
3111 + || ap_default_family == PF_UNSPEC
3112 + ) && strcasecmp(w, "_default_") == 0)){
3113 + hoststr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
3114 + hints.ai_family = PF_INET6;
3116 - if (is_an_ip_addr) {
3117 - sar = ap_pcalloc(p, sizeof(server_addr_rec));
3119 - *paddr = &sar->next;
3120 - sar->host_addr.s_addr = my_addr;
3121 - sar->host_port = port;
3122 - sar->virthost = ap_pstrdup(p, w);
3129 + hints.ai_family = PF_UNSPEC;
3132 - hep = gethostbyname(w);
3134 - if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
3135 + error = getaddrinfo(hoststr, portstr, &hints, &res0);
3136 + if (error || !res0) {
3137 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
3138 - "Cannot resolve host name %s --- ignoring!", w);
3141 + "Cannot resolve host %s port %s --- ignoring!", hoststr, portstr);
3142 + if (t != NULL) *t = ':';
3143 + if (u != NULL) *u = ']';
3147 - for (i = 0; hep->h_addr_list[i]; ++i) {
3148 + for (res=res0; res; res=res->ai_next) {
3149 + switch (res->ai_addr->sa_family) {
3156 + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
3157 + "Unsupported address family %u, for host %s port %s --- ignoring!",
3158 + res->ai_addr->sa_family, hoststr, portstr);
3161 sar = ap_pcalloc(p, sizeof(server_addr_rec));
3163 *paddr = &sar->next;
3164 - sar->host_addr = *(struct in_addr *) hep->h_addr_list[i];
3165 - sar->host_port = port;
3166 + memcpy(&sar->host_addr, res->ai_addr, res->ai_addrlen);
3167 + if (getnameinfo(res->ai_addr, res->ai_addrlen, NULL, 0, servbuf,
3168 + sizeof(servbuf), NI_NUMERICSERV) == 0)
3169 + sar->host_port = atoi(servbuf);
3171 + sar->host_port = 0;
3172 sar->virthost = ap_pstrdup(p, w);
3177 + freeaddrinfo(res0);
3178 + if (t != NULL) *t = ':';
3179 + if (u != NULL) *u = ']';
3184 /* start the list of addreses */
3186 while (hostname[0]) {
3187 - err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
3188 + err = get_addresses(p, ap_getword_conf(p, &hostname), NULL,
3193 @@ -268,10 +306,11 @@
3197 -const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg)
3198 +const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *h,
3201 /* use whatever port the main server has at this point */
3202 - return get_addresses(cmd->pool, arg, &name_vhost_list_tail,
3203 + return get_addresses(cmd->pool, h, p, &name_vhost_list_tail,
3207 @@ -345,6 +384,19 @@
3208 return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
3211 +static unsigned hash_addr(struct sockaddr *sa)
3213 + switch (sa->sa_family) {
3215 + return hash_inaddr(((struct sockaddr_in *)sa)->sin_addr.s_addr);
3218 + return hash_inaddr(((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12]);
3221 + return hash_inaddr(sa->sa_family);
3226 static ipaddr_chain *new_ipaddr_chain(pool *p,
3227 @@ -372,25 +424,77 @@
3232 -static ap_inline ipaddr_chain *find_ipaddr(struct in_addr *server_ip,
3234 +static ap_inline ipaddr_chain *find_ipaddr(struct sockaddr *sa)
3239 + char a[NI_MAXHOST], b[NI_MAXHOST];
3241 /* scan the hash table for an exact match first */
3242 - addr = server_ip->s_addr;
3243 - bucket = hash_inaddr(addr);
3244 + bucket = hash_addr(sa);
3245 for (trav = iphash_table[bucket]; trav; trav = trav->next) {
3246 server_addr_rec *sar = trav->sar;
3247 - if ((sar->host_addr.s_addr == addr)
3248 - && (sar->host_port == 0 || sar->host_port == port
3251 + if (sar->host_addr.ss_family != sa->sa_family)
3253 + switch (sa->sa_family) {
3256 + struct sockaddr_in *sin1, *sin2;
3257 + sin1 = (struct sockaddr_in *)&sar->host_addr;
3258 + sin2 = (struct sockaddr_in *)sa;
3259 + if (sin1->sin_port == 0 || sin2->sin_port == 0
3260 + || sin1->sin_port == sin2->sin_port) {
3261 + if (memcmp(&sin1->sin_addr, &sin2->sin_addr,
3262 + sizeof(sin1->sin_addr)) == 0) {
3271 + struct sockaddr_in6 *sin1, *sin2;
3272 + sin1 = (struct sockaddr_in6 *)&sar->host_addr;
3273 + sin2 = (struct sockaddr_in6 *)sa;
3274 + if (sin1->sin6_port == 0 || sin2->sin6_port == 0
3275 + || sin1->sin6_port == sin2->sin6_port) {
3276 + if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
3277 + sizeof(sin1->sin6_addr)) == 0) {
3284 + default: /*unsupported*/
3290 + if (sa->sa_family == AF_INET6 &&
3291 + IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)) {
3293 + * This is just horrible. I just hate IPv4 mapped address. It
3294 + * complicates access control too much.
3295 + * Due to hashed lookup, we need to visit it again.
3297 + struct sockaddr_in sin;
3299 + memset(&sin, 0, sizeof(sin));
3300 + sin.sin_family = AF_INET;
3302 + sin.sin_len = sizeof(sin);
3304 + sin.sin_port = ((struct sockaddr_in6 *)sa)->sin6_port;
3305 + memcpy(&sin.sin_addr,
3306 + &((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12],
3307 + sizeof(sin.sin_addr));
3308 + return find_ipaddr((struct sockaddr *)&sin);
3315 @@ -416,21 +520,7 @@
3317 char buf[MAX_STRING_LEN];
3319 - if (ic->sar->host_addr.s_addr == DEFAULT_VHOST_ADDR) {
3320 - len = ap_snprintf(buf, sizeof(buf), "_default_:%u",
3321 - ic->sar->host_port);
3323 - else if (ic->sar->host_addr.s_addr == INADDR_ANY) {
3324 - len = ap_snprintf(buf, sizeof(buf), "*:%u",
3325 - ic->sar->host_port);
3328 - len = ap_snprintf(buf, sizeof(buf), "%pA:%u",
3329 - &ic->sar->host_addr, ic->sar->host_port);
3331 - if (ic->sar->host_port == 0) {
3334 + len = ap_snprintf(buf, sizeof(buf), "%pI", &ic->sar->host_addr);
3335 if (ic->names == NULL) {
3336 if (ic->server == NULL)
3337 fprintf(f, "%-22s WARNING: No <VirtualHost> defined for this NameVirtualHost!\n", buf);
3338 @@ -558,10 +648,37 @@
3339 * occured in the config file, we'll copy it in that order.
3341 for (sar = name_vhost_list; sar; sar = sar->next) {
3342 - unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
3343 + unsigned bucket = hash_addr((struct sockaddr *)&sar->host_addr);
3344 ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar);
3348 + switch (sar->host_addr.ss_family) {
3351 + struct sockaddr_in *sin;
3352 + sin = (struct sockaddr_in *)&sar->host_addr;
3353 + if (sin->sin_addr.s_addr == INADDR_ANY)
3360 + struct sockaddr_in6 *sin6;
3361 + sin6 = (struct sockaddr_in6 *)&sar->host_addr;
3362 + if (*(ap_uint32_t *)&sin6->sin6_addr.s6_addr[0] == 0
3363 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[4] == 0
3364 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[8] == 0
3365 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[12] == 0) {
3373 - if (sar->host_addr.s_addr != INADDR_ANY) {
3375 *iphash_table_tail[bucket] = ic;
3376 iphash_table_tail[bucket] = &ic->next;
3378 @@ -588,12 +705,45 @@
3379 has_default_vhost_addr = 0;
3380 for (sar = s->addrs; sar; sar = sar->next) {
3385 + switch (sar->host_addr.ss_family) {
3388 + struct sockaddr_in *sin;
3389 + sin = (struct sockaddr_in *)&sar->host_addr;
3390 + if (sin->sin_addr.s_addr == DEFAULT_VHOST_ADDR)
3392 + else if (sin->sin_addr.s_addr == INADDR_ANY)
3399 + struct sockaddr_in6 *sin6;
3400 + sin6 = (struct sockaddr_in6 *)&sar->host_addr;
3401 + if (*(ap_uint32_t *)&sin6->sin6_addr.s6_addr[0] == ~0
3402 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[4] == ~0
3403 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[8] == ~0
3404 + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[12] == ~0) {
3412 - if (sar->host_addr.s_addr == DEFAULT_VHOST_ADDR
3413 - || sar->host_addr.s_addr == INADDR_ANY) {
3414 - ic = find_default_server(sar->host_port);
3415 - if (!ic || !add_name_vhost_config(p, main_s, s, sar, ic)) {
3416 - if (ic && ic->sar->host_port != 0) {
3418 + /* add it to default bucket for each appropriate sar
3419 + * since we need to do a port test
3421 + ipaddr_chain *other;
3423 + other = find_default_server(sar->host_port);
3424 + if (!other || !add_name_vhost_config(p, main_s, s, sar, other)) {
3425 + if (other && other->sar->host_port != 0) {
3426 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
3427 main_s, "_default_ VirtualHost overlap on port %u,"
3428 " the first has precedence", sar->host_port);
3429 @@ -606,10 +756,11 @@
3432 /* see if it matches something we've already got */
3433 - ic = find_ipaddr(&sar->host_addr, sar->host_port);
3434 + ic = find_ipaddr((struct sockaddr *)&sar->host_addr);
3437 - unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
3439 + hash_addr((struct sockaddr *)&sar->host_addr);
3441 ic = new_ipaddr_chain(p, s, sar);
3442 ic->next = *iphash_table_tail[bucket];
3443 @@ -646,19 +797,33 @@
3447 + char hostnamebuf[MAXHOSTNAMELEN];
3449 - if ((h = gethostbyaddr((char *) &(s->addrs->host_addr),
3450 - sizeof(struct in_addr), AF_INET))) {
3451 - s->server_hostname = ap_pstrdup(p, (char *) h->h_name);
3452 + if (!getnameinfo((struct sockaddr *)&s->addrs->host_addr,
3454 + SA_LEN((struct sockaddr *)&s->addrs->host_addr),
3456 + s->addrs->host_addr.ss_len,
3458 + hostnamebuf, sizeof(hostnamebuf),
3460 + s->server_hostname = ap_pstrdup(p, hostnamebuf);
3463 /* again, what can we do? They didn't specify a
3464 ServerName, and their DNS isn't working. -djg */
3465 + getnameinfo((struct sockaddr *)&s->addrs->host_addr,
3467 + SA_LEN((struct sockaddr *)&s->addrs->host_addr),
3469 + s->addrs->host_addr.ss_len,
3471 + hostnamebuf, sizeof(hostnamebuf),
3472 + NULL, 0, NI_NUMERICHOST);
3473 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s,
3474 "Failed to resolve server name "
3475 "for %s (check DNS) -- or specify an explicit "
3477 - inet_ntoa(s->addrs->host_addr));
3478 + "ServerName", hostnamebuf);
3479 s->server_hostname =
3480 ap_pstrdup(p, "bogus_host_without_reverse_dns");
3482 @@ -705,35 +870,58 @@
3483 char *host = ap_palloc(r->pool, strlen(r->hostname) + 1);
3486 + const char *u = NULL, *v = NULL;
3488 /* check and copy the host part */
3489 - src = r->hostname;
3490 + u = src = r->hostname;
3494 - if (*src == '.') {
3501 - if (*src == '/' || *src == '\\') {
3504 - if (*src == ':') {
3505 - /* check the port part */
3507 - if (!ap_isdigit(*src)) {
3511 - if (src[-1] == ':')
3515 + if (*u == '[') { /* IPv6 numeral address in brackets */
3516 + v = strchr(u, ']');
3518 + /* missing closing bracket */
3521 + if (v == (u + 1)) {
3522 + /* bad empty address */
3525 + for (src = u+1; src < v; src++) /* copy IPv6 adress */
3530 + while (*v) { /* check if portnum is correct */
3531 + if (!ap_isdigit(*v++))
3538 + if (*src == '.') {
3545 + if (*src == '/' || *src == '\\') {
3548 + if (*src == ':') {
3549 + /* sheck the port part */
3551 + if (!ap_isdigit(*src)) {
3555 + if (src[-1] == ':')
3563 /* strip trailing gubbins */
3564 if (dst > host && dst[-1] == '.') {
3567 r->status = HTTP_BAD_REQUEST;
3568 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
3569 - "Client sent malformed Host header");
3570 + "Client sent malformed Host header <<%s>>",u);
3574 @@ -851,11 +1039,25 @@
3575 * names we'll match have ports associated with them
3577 const char *host = r->hostname;
3578 - unsigned port = ntohs(r->connection->local_addr.sin_port);
3584 + switch (r->connection->local_addr.ss_family) {
3586 + port = ntohs(((struct sockaddr_in *)
3587 + &r->connection->local_addr)->sin_port);
3591 + port = ntohs(((struct sockaddr_in6 *)
3592 + &r->connection->local_addr)->sin6_port);
3600 /* Recall that the name_chain is a list of server_addr_recs, some of
3601 @@ -910,7 +1112,22 @@
3605 - unsigned port = ntohs(r->connection->local_addr.sin_port);
3608 + switch (r->connection->local_addr.ss_family) {
3610 + port = ntohs(((struct sockaddr_in *)
3611 + &r->connection->local_addr)->sin_port);
3615 + port = ntohs(((struct sockaddr_in6 *)
3616 + &r->connection->local_addr)->sin6_port);
3624 * This is in conjunction with the ServerPath code in http_core, so we
3625 @@ -970,10 +1187,22 @@
3626 void ap_update_vhost_given_ip(conn_rec *conn)
3629 - unsigned port = ntohs(conn->local_addr.sin_port);
3630 + char portbuf[NI_MAXSERV];
3633 + if (getnameinfo((struct sockaddr *)&conn->local_addr,
3635 + SA_LEN((struct sockaddr *)&conn->local_addr),
3637 + conn->local_addr.ss_len,
3639 + NULL, 0, portbuf, sizeof(portbuf), NI_NUMERICSERV) != 0) {
3642 + port = atoi(portbuf);
3644 /* scan the hash table for an exact match first */
3645 - trav = find_ipaddr(&conn->local_addr.sin_addr, port);
3646 + trav = find_ipaddr((struct sockaddr *)&conn->local_addr);
3648 /* save the name_chain for later in case this is a name-vhost */
3649 conn->vhost_lookup_data = trav->names;
3650 @@ -991,6 +1220,7 @@
3655 /* otherwise we're stuck with just the main server
3656 * and no name-based vhosts
3658 diff -Nur apache_1.3.22.orig/src/main/rfc1413.c apache_1.3.22/src/main/rfc1413.c
3659 --- apache_1.3.22.orig/src/main/rfc1413.c Mon Jan 15 18:05:04 2001
3660 +++ apache_1.3.22/src/main/rfc1413.c Fri Dec 7 17:27:28 2001
3662 #include "http_log.h" /* for aplog_error */
3663 #include "rfc1413.h"
3664 #include "http_main.h" /* set_callback_and_alarm */
3665 +#include "sa_len.h"
3668 /* Semi-well-known port */
3669 @@ -109,12 +110,13 @@
3671 /* bind_connect - bind both ends of a socket */
3672 /* Ambarish fix this. Very broken */
3673 -static int get_rfc1413(int sock, const struct sockaddr_in *our_sin,
3674 - const struct sockaddr_in *rmt_sin,
3675 +static int get_rfc1413(int sock, const struct sockaddr *our_sin,
3676 + const struct sockaddr *rmt_sin,
3677 char user[RFC1413_USERLEN+1], server_rec *srv)
3679 - struct sockaddr_in rmt_query_sin, our_query_sin;
3680 - unsigned int rmt_port, our_port;
3681 + struct sockaddr_storage rmt_query_sin, our_query_sin;
3682 + unsigned int o_rmt_port, o_our_port; /* original port pair */
3683 + unsigned int rmt_port, our_port; /* replied port pair */
3686 char buffer[RFC1413_MAXDATA + 1];
3687 @@ -129,16 +131,47 @@
3688 * addresses from the query socket.
3691 - our_query_sin = *our_sin;
3692 - our_query_sin.sin_port = htons(ANY_PORT);
3694 - our_query_sin.sin_addr.s_addr = INADDR_ANY;
3696 + memcpy(&our_query_sin, our_sin, SA_LEN(our_sin));
3697 + memcpy(&rmt_query_sin, rmt_sin, SA_LEN(rmt_sin));
3699 + memcpy(&our_query_sin, our_sin, our_sin->sa_len);
3700 + memcpy(&rmt_query_sin, rmt_sin, rmt_sin->sa_len);
3702 - rmt_query_sin = *rmt_sin;
3703 - rmt_query_sin.sin_port = htons(RFC1413_PORT);
3704 + switch (our_sin->sa_family) {
3707 + ((struct sockaddr_in *)&our_query_sin)->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(??) */
3709 + ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
3710 + o_our_port = ntohs(((struct sockaddr_in *)our_sin)->sin_port);
3711 + ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC1413_PORT);
3712 + o_rmt_port = ntohs(((struct sockaddr_in *)rmt_sin)->sin_port);
3717 + memcpy(&((struct sockaddr_in6 *)&our_query_sin)->sin6_addr,
3718 + &in6addr_any, sizeof(struct in6_addr));
3720 + ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
3721 + o_our_port = ntohs(((struct sockaddr_in6 *)our_sin)->sin6_port);
3722 + ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC1413_PORT);
3723 + o_rmt_port = ntohs(((struct sockaddr_in6 *)rmt_sin)->sin6_port);
3727 + /* unsupported AF */
3731 if (bind(sock, (struct sockaddr *) &our_query_sin,
3732 - sizeof(struct sockaddr_in)) < 0) {
3734 + SA_LEN((struct sockaddr *) &our_query_sin)
3736 + our_query_sin.ss_len
3739 ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
3740 "bind: rfc1413: Error binding to local port");
3742 @@ -149,12 +182,18 @@
3745 if (connect(sock, (struct sockaddr *) &rmt_query_sin,
3746 - sizeof(struct sockaddr_in)) < 0)
3749 + SA_LEN((struct sockaddr *) &rmt_query_sin)
3751 + rmt_query_sin.ss_len
3758 - buflen = ap_snprintf(buffer, sizeof(buffer), "%u,%u\r\n", ntohs(rmt_sin->sin_port),
3759 - ntohs(our_sin->sin_port));
3760 + buflen = ap_snprintf(buffer, sizeof(buffer), "%u,%u\r\n", o_rmt_port,
3763 /* send query to server. Handle short write. */
3764 #ifdef CHARSET_EBCDIC
3766 ascii2ebcdic(buffer, buffer, (size_t)i);
3768 if (sscanf(buffer, "%u , %u : USERID :%*[^:]:%512s", &rmt_port, &our_port,
3769 - user) != 3 || ntohs(rmt_sin->sin_port) != rmt_port
3770 - || ntohs(our_sin->sin_port) != our_port)
3771 + user) != 3 || o_rmt_port != rmt_port || o_our_port != our_port) {
3776 * Strip trailing carriage return. It is part of the
3779 result = FROM_UNKNOWN;
3781 - sock = ap_psocket(conn->pool, AF_INET, SOCK_STREAM, IPPROTO_TCP);
3782 + sock = ap_psocket(conn->pool, conn->remote_addr.ss_family, SOCK_STREAM, IPPROTO_TCP);
3784 ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
3785 "socket: rfc1413: error creating socket");
3786 @@ -256,8 +295,10 @@
3787 if (ap_setjmp(timebuf) == 0) {
3788 ap_set_callback_and_alarm(ident_timeout, ap_rfc1413_timeout);
3790 - if (get_rfc1413(sock, &conn->local_addr, &conn->remote_addr, user, srv) >= 0)
3791 + if (get_rfc1413(sock, (struct sockaddr *)&conn->local_addr,
3792 + (struct sockaddr *)&conn->remote_addr, user, srv) >= 0) {
3796 ap_set_callback_and_alarm(NULL, 0);
3797 ap_pclosesocket(conn->pool, sock);
3798 diff -Nur apache_1.3.22.orig/src/main/util.c apache_1.3.22/src/main/util.c
3799 --- apache_1.3.22.orig/src/main/util.c Wed Jul 25 15:25:18 2001
3800 +++ apache_1.3.22/src/main/util.c Fri Dec 7 17:27:28 2001
3801 @@ -1962,52 +1962,87 @@
3802 * Parses a host of the form <address>[:port]
3803 * :port is permitted if 'port' is not NULL
3805 -unsigned long ap_get_virthost_addr(char *w, unsigned short *ports)
3806 +struct sockaddr *ap_get_virthost_addr(char *w, unsigned short *ports)
3808 - struct hostent *hep;
3809 - unsigned long my_addr;
3812 - p = strchr(w, ':');
3813 + static struct sockaddr_storage ss;
3814 + struct addrinfo hints, *res;
3819 + char servbuf[NI_MAXSERV];
3825 + if (r = strrchr(w+1, ']')){
3841 + p = strchr(w, ':');
3842 + if (p != NULL && strchr(p+1, ':') != NULL)
3845 if (ports != NULL) {
3847 - if (p != NULL && strcmp(p + 1, "*") != 0)
3848 - *ports = atoi(p + 1);
3849 + if (p != NULL && *p && strcmp(p + 1, "*") != 0)
3853 + memset(&hints, 0, sizeof(hints));
3854 + hints.ai_socktype = SOCK_STREAM;
3857 if (strcmp(w, "*") == 0) {
3860 - return htonl(INADDR_ANY);
3863 - my_addr = ap_inet_addr((char *)w);
3864 - if (my_addr != INADDR_NONE) {
3869 + hints.ai_flags = AI_PASSIVE;
3870 + hints.ai_family = ap_default_family;
3873 + hints.ai_family = PF_UNSPEC;
3876 - hep = gethostbyname(w);
3877 + error = getaddrinfo(host, port, &hints, &res);
3879 - if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
3880 - fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w);
3881 + if (error || !res) {
3882 + fprintf(stderr, "ap_get_vitrhost_addr(): getaddrinfo(%s):%s --- exiting!\n", w, gai_strerror(error));
3886 - if (hep->h_addr_list[1]) {
3887 - fprintf(stderr, "Host %s has multiple addresses ---\n", w);
3888 + if (res->ai_next) {
3889 + fprintf(stderr, "ap_get_vitrhost_addr(): Host %s has multiple addresses ---\n", w);
3890 fprintf(stderr, "you must choose one explicitly for use as\n");
3891 fprintf(stderr, "a virtual host. Exiting!!!\n");
3900 - return ((struct in_addr *) (hep->h_addr))->s_addr;
3901 + memcpy(&ss, res->ai_addr, res->ai_addrlen);
3902 + if (getnameinfo(res->ai_addr, res->ai_addrlen,
3903 + NULL, 0, servbuf, sizeof(servbuf),
3905 + fprintf(stderr, "ap_get_virthost_addr(): getnameinfo() failed --- Exiting!!!\n");
3908 + if (ports) *ports = atoi(servbuf);
3909 + freeaddrinfo(res);
3910 + return (struct sockaddr *)&ss;
3914 @@ -2035,7 +2070,8 @@
3916 char str[MAXHOSTNAMELEN];
3917 char *server_hostname = NULL;
3918 - struct hostent *p;
3919 + struct addrinfo hints, *res;
3922 #ifdef BEOS /* BeOS returns zero as an error for gethostname */
3923 if (gethostname(str, sizeof(str) - 1) == 0) {
3924 @@ -2048,29 +2084,38 @@
3928 - str[sizeof(str) - 1] = '\0';
3929 - if ((!(p = gethostbyname(str)))
3930 - || (!(server_hostname = find_fqdn(a, p)))) {
3931 - /* Recovery - return the default servername by IP: */
3932 - if (p && p->h_addr_list && p->h_addr_list[0]) {
3933 - ap_snprintf(str, sizeof(str), "%pA", p->h_addr_list[0]);
3934 - server_hostname = ap_pstrdup(a, str);
3935 - /* We will drop through to report the IP-named server */
3939 - /* Since we found a fqdn, return it with no logged message. */
3940 - return server_hostname;
3943 - /* If we don't have an fdqn or IP, fall back to the loopback addr */
3944 - if (!server_hostname)
3945 - server_hostname = ap_pstrdup(a, "127.0.0.1");
3947 - ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, NULL,
3948 - "%s: Could not determine the server's fully qualified "
3949 - "domain name, using %s for ServerName",
3950 - ap_server_argv0, server_hostname);
3951 + str[sizeof(str) - 1] = '\0';
3952 + memset(&hints, 0, sizeof(hints));
3953 + hints.ai_family = PF_UNSPEC;
3954 + hints.ai_flags = AI_CANONNAME;
3955 + error = getaddrinfo(str, NULL, &hints, &res);
3958 + /* Recovery - return the default servername by IP: */
3960 + fprintf(stderr, "%s: cannot determine local host name.\n",
3962 + fprintf(stderr, "Use the ServerName directive to set it manually.\n");
3965 + server_hostname = ap_pstrdup(a, res->ai_canonname);
3967 + else if (1) /*fqdn found*/
3969 + /* XXX should check more conditions */
3970 + server_hostname = ap_pstrdup(a, res->ai_canonname);
3974 + ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, NULL,
3975 + "%s: Could not determine the server's fully qualified "
3976 + "domain name, using %s for ServerName",
3977 + ap_server_argv0, server_hostname);
3980 + /* Since we found a fdqn, return it with no logged message. */
3981 + freeaddrinfo(res);
3984 return server_hostname;
3986 @@ -2149,7 +2194,7 @@
3987 char *quote_doubled_str, *dest;
3990 - num_quotes += str[len++] == '\"';
3991 + num_quotes += str[len++] == '\"';
3994 quote_doubled_str = ap_palloc(p, len + num_quotes + 1);
3995 @@ -2274,3 +2319,11 @@
4000 +#ifdef NEED_GETADDRINFO
4001 +#include "getaddrinfo.c"
4004 +#ifdef NEED_GETNAMEINFO
4005 +#include "getnameinfo.c"
4007 diff -Nur apache_1.3.22.orig/src/main/util_script.c apache_1.3.22/src/main/util_script.c
4008 --- apache_1.3.22.orig/src/main/util_script.c Wed May 9 07:17:11 2001
4009 +++ apache_1.3.22/src/main/util_script.c Fri Dec 7 17:27:28 2001
4011 #include "http_request.h" /* for sub_req_lookup_uri() */
4012 #include "util_script.h"
4013 #include "util_date.h" /* For parseHTTPdate() */
4014 +#include "sa_len.h"
4019 array_header *hdrs_arr = ap_table_elts(r->headers_in);
4020 table_entry *hdrs = (table_entry *) hdrs_arr->elts;
4022 + char servbuf[NI_MAXSERV];
4024 /* use a temporary table which we'll overlap onto
4025 * r->subprocess_env later
4026 @@ -298,8 +300,16 @@
4027 ap_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
4028 ap_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */
4030 - ap_table_addn(e, "REMOTE_PORT",
4031 - ap_psprintf(r->pool, "%d", ntohs(c->remote_addr.sin_port)));
4032 + servbuf[0] = '\0';
4033 + if (!getnameinfo((struct sockaddr *)&c->remote_addr,
4034 +#ifndef HAVE_SOCKADDR_LEN
4035 + SA_LEN((struct sockaddr *)&c->remote_addr),
4037 + c->remote_addr.ss_len,
4039 + NULL, 0, servbuf, sizeof(servbuf), NI_NUMERICSERV)){
4040 + ap_table_addn(e, "REMOTE_PORT", ap_pstrdup(r->pool, servbuf));
4044 ap_table_addn(e, "REMOTE_USER", c->user);
4045 diff -Nur apache_1.3.22.orig/src/main/util_uri.c apache_1.3.22/src/main/util_uri.c
4046 --- apache_1.3.22.orig/src/main/util_uri.c Thu Aug 23 08:38:25 2001
4047 +++ apache_1.3.22/src/main/util_uri.c Fri Dec 7 17:27:28 2001
4048 @@ -419,6 +419,12 @@
4049 * the hostname. If there's a port it is the first colon.
4051 s = memchr(hostinfo, ':', uri - hostinfo);
4052 + if (*hostinfo == '[') {
4053 + s = memchr(hostinfo+1, ']', uri - hostinfo - 1);
4055 + s = strchr(s, ':');
4057 + s = memchr(hostinfo, ':', uri - hostinfo);
4059 /* we expect the common case to have no port */
4060 uptr->hostname = ap_pstrndup(p, hostinfo, uri - hostinfo);
4061 @@ -475,7 +481,12 @@
4062 /* We expect hostinfo to point to the first character of
4063 * the hostname. There must be a port, separated by a colon
4065 - s = strchr(hostinfo, ':');
4066 + if (*hostinfo == '[') {
4067 + s = strchr(hostinfo+1, ']');
4069 + s = strchr(s, ':');
4071 + s = strchr(hostinfo, ':');
4073 return HTTP_BAD_REQUEST;
4075 diff -Nur apache_1.3.22.orig/src/modules/proxy/mod_proxy.c apache_1.3.22/src/modules/proxy/mod_proxy.c
4076 --- apache_1.3.22.orig/src/modules/proxy/mod_proxy.c Fri Dec 7 17:26:57 2001
4077 +++ apache_1.3.22/src/modules/proxy/mod_proxy.c Fri Dec 7 17:27:28 2001
4078 @@ -555,11 +555,31 @@
4079 struct proxy_remote *new;
4082 + char *bl = NULL, *br = NULL;
4085 if (p == NULL || p[1] != '/' || p[2] != '/' || p[3] == '\0')
4086 return "ProxyRemote: Bad syntax for a remote proxy server";
4087 - q = strchr(p + 3, ':');
4090 + br = strrchr(bl+1, ']');
4094 + if (*(br+1) == ':'){ /* [host]:xx */
4097 + else if (*(br+1) == '\0'){ /* [host] */
4101 + q = strrchr(br, ':'); /* XXX */
4104 + q = strrchr(bl, ':'); /* XXX */
4107 + q = strrchr(bl, ':');
4109 if (sscanf(q + 1, "%u", &port) != 1 || port > 65535)
4110 return "ProxyRemote: Bad syntax for a remote proxy server (bad port number)";
4113 if (strchr(f, ':') == NULL)
4114 ap_str_tolower(f); /* lowercase scheme */
4115 - ap_str_tolower(p + 3); /* lowercase hostname */
4116 + ap_str_tolower(bl); /* lowercase hostname */
4121 new = ap_push_array(conf->proxies);
4124 - new->hostname = p + 3;
4125 + new->hostname = bl;
4129 diff -Nur apache_1.3.22.orig/src/modules/proxy/mod_proxy.h apache_1.3.22/src/modules/proxy/mod_proxy.h
4130 --- apache_1.3.22.orig/src/modules/proxy/mod_proxy.h Fri Oct 5 10:19:15 2001
4131 +++ apache_1.3.22/src/modules/proxy/mod_proxy.h Fri Dec 7 17:27:28 2001
4133 int ap_proxy_is_domainname(struct dirconn_entry *This, pool *p);
4134 int ap_proxy_is_hostname(struct dirconn_entry *This, pool *p);
4135 int ap_proxy_is_word(struct dirconn_entry *This, pool *p);
4136 -int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r);
4137 +int ap_proxy_doconnect(int sock, struct sockaddr *addr, request_rec *r);
4138 int ap_proxy_garbage_init(server_rec *, pool *);
4139 /* This function is called by ap_table_do() for all header lines */
4140 int ap_proxy_send_hdr_line(void *p, const char *key, const char *value);
4141 diff -Nur apache_1.3.22.orig/src/modules/proxy/proxy_connect.c apache_1.3.22/src/modules/proxy/proxy_connect.c
4142 --- apache_1.3.22.orig/src/modules/proxy/proxy_connect.c Fri Oct 5 10:19:15 2001
4143 +++ apache_1.3.22/src/modules/proxy/proxy_connect.c Fri Dec 7 17:27:28 2001
4144 @@ -114,14 +114,15 @@
4145 const char *proxyhost, int proxyport)
4147 struct sockaddr_in server;
4148 - struct in_addr destaddr;
4149 - struct hostent server_hp;
4150 - const char *host, *err;
4151 + struct addrinfo hints, *res, *res0;
4152 + const char *hoststr;
4153 + const char *portstr = NULL;
4156 char buffer[HUGE_STRING_LEN];
4162 void *sconf = r->server->module_config;
4163 proxy_server_conf *conf =
4164 @@ -129,26 +130,59 @@
4165 struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
4167 memset(&server, '\0', sizeof(server));
4168 +#ifdef HAVE_SOCKADDR_LEN
4169 + server.sin_len = sizeof(server);
4171 server.sin_family = AF_INET;
4173 /* Break the URL into host:port pairs */
4177 p = strchr(url, ':');
4179 - port = DEFAULT_HTTPS_PORT;
4181 - port = atoi(p + 1);
4184 + ap_snprintf(pbuf, sizeof(pbuf), "%d", DEFAULT_HTTPS_PORT);
4190 + port = atoi(portstr);
4192 + memset(&hints, 0, sizeof(hints));
4193 + hints.ai_family = PF_UNSPEC;
4194 + hints.ai_socktype = SOCK_STREAM;
4195 + hints.ai_protocol = IPPROTO_TCP;
4196 + error = getaddrinfo(hoststr, portstr, &hints, &res0);
4198 + return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
4199 + gai_strerror(error)); /* give up */
4202 /* check if ProxyBlock directive on this host */
4203 - destaddr.s_addr = ap_inet_addr(host);
4204 - for (i = 0; i < conf->noproxies->nelts; i++) {
4205 - if ((npent[i].name != NULL && strstr(host, npent[i].name) != NULL)
4206 - || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
4207 + for (res = res0; res; res = res = res->ai_next) {
4208 + struct sockaddr_in *sin;
4212 + for (i = 0; i < conf->noproxies->nelts; i++) {
4213 + if (npent[i].name != NULL && strstr(hoststr, npent[i].name))
4215 + if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0)
4217 + switch (res->ai_family) {
4219 + sin = (struct sockaddr_in *)res->ai_addr;
4220 + if (sin->sin_addr.s_addr == npent[i].addr.s_addr)
4226 + freeaddrinfo(res0);
4227 return ap_proxyerror(r, HTTP_FORBIDDEN,
4228 "Connect to remote machine blocked");
4232 /* Check if it is an allowed port */
4233 @@ -159,59 +193,64 @@
4234 case DEFAULT_SNEWS_PORT:
4237 + freeaddrinfo(res0);
4238 return HTTP_FORBIDDEN;
4240 - } else if(!allowed_port(conf, port))
4241 + } else if(!allowed_port(conf, port)) {
4242 + freeaddrinfo(res0);
4243 return HTTP_FORBIDDEN;
4249 + freeaddrinfo(res0);
4251 + ap_snprintf(pbuf, sizeof(pbuf), "%d", proxyport);
4252 + memset(&hints, 0, sizeof(hints));
4253 + hints.ai_family = PF_UNSPEC;
4254 + hints.ai_socktype = SOCK_STREAM;
4255 + hints.ai_protocol = IPPROTO_TCP;
4256 + error = getaddrinfo(proxyhost, pbuf, &hints, &res0);
4258 + return HTTP_INTERNAL_SERVER_ERROR; /* XXX */
4260 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "CONNECT to remote proxy %s on port %d", proxyhost, proxyport);
4263 - ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "CONNECT to %s on port %d", host, port);
4264 + ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "CONNECT to %s on port %d", hoststr, port);
4267 - server.sin_port = (proxyport ? htons(proxyport) : htons(port));
4268 - err = ap_proxy_host2addr(proxyhost ? proxyhost : host, &server_hp);
4271 - return ap_proxyerror(r,
4272 - proxyhost ? HTTP_BAD_GATEWAY : HTTP_INTERNAL_SERVER_ERROR,
4275 - sock = ap_psocket(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP);
4277 - ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4278 - "proxy: error creating socket");
4279 - return HTTP_INTERNAL_SERVER_ERROR;
4282 + for (res = res0; res; res = res->ai_next) {
4283 + sock = ap_psocket(r->pool, res->ai_family, res->ai_socktype, res->ai_protocol);
4287 #ifdef CHECK_FD_SETSIZE
4288 - if (sock >= FD_SETSIZE) {
4289 - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r->server,
4290 - "proxy_connect_handler: filedescriptor (%u) "
4291 - "larger than FD_SETSIZE (%u) "
4292 - "found, you probably need to rebuild Apache with a "
4293 - "larger FD_SETSIZE", sock, FD_SETSIZE);
4294 - ap_pclosesocket(r->pool, sock);
4295 - return HTTP_INTERNAL_SERVER_ERROR;
4297 + if (sock >= FD_SETSIZE) {
4298 + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL,
4299 + "proxy_connect_handler: filedescriptor (%u) "
4300 + "larger than FD_SETSIZE (%u) "
4301 + "found, you probably need to rebuild Apache with a "
4302 + "larger FD_SETSIZE. Anyway try to open next socket.",
4303 + sock, FD_SETSIZE);
4304 + ap_pclosesocket(r->pool, sock);
4310 - while (server_hp.h_addr_list[j] != NULL) {
4311 - memcpy(&server.sin_addr, server_hp.h_addr_list[j],
4312 - sizeof(struct in_addr));
4313 - i = ap_proxy_doconnect(sock, &server, r);
4314 + i = ap_proxy_doconnect(sock, res->ai_addr, r);
4319 + freeaddrinfo(res0);
4321 ap_pclosesocket(r->pool, sock);
4322 - return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, ap_pstrcat(r->pool,
4323 - "Could not connect to remote machine:<br>",
4324 - strerror(errno), NULL));
4325 + return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
4326 + ap_pstrcat(r->pool,
4327 + "Could not connect to remote machine:<br>",
4328 + strerror(errno), NULL));
4331 /* If we are connecting through a remote proxy, we need to pass
4332 diff -Nur apache_1.3.22.orig/src/modules/proxy/proxy_ftp.c apache_1.3.22/src/modules/proxy/proxy_ftp.c
4333 --- apache_1.3.22.orig/src/modules/proxy/proxy_ftp.c Fri Oct 5 10:19:15 2001
4334 +++ apache_1.3.22/src/modules/proxy/proxy_ftp.c Fri Dec 7 17:27:28 2001
4336 #include "http_main.h"
4337 #include "http_log.h"
4338 #include "http_core.h"
4339 +#include "sa_len.h"
4341 #define AUTODETECT_PWD
4343 @@ -451,8 +452,10 @@
4345 int port, i, j, len, sock, dsock, rc, nocache = 0;
4347 - struct sockaddr_in server;
4348 - struct hostent server_hp;
4349 + struct sockaddr_storage server;
4350 + struct addrinfo hints, *res, *res0;
4353 struct in_addr destaddr;
4356 @@ -473,11 +476,18 @@
4357 unsigned int presult, h0, h1, h2, h3, p0, p1;
4359 unsigned short pport;
4360 - struct sockaddr_in data_addr;
4361 + struct sockaddr_storage data_addr;
4362 + struct sockaddr_in *sin;
4367 +/* stuff for LPSV/EPSV */
4368 + unsigned int paf, holen, ho[16], polen, po[2];
4369 + struct sockaddr_in6 *sin6;
4373 /* stuff for responses */
4374 char resp[MAX_STRING_LEN];
4376 @@ -547,62 +557,52 @@
4380 - memset(&server, 0, sizeof(struct sockaddr_in));
4381 - server.sin_family = AF_INET;
4382 - server.sin_port = htons(port);
4383 - err = ap_proxy_host2addr(host, &server_hp);
4385 - return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
4387 - sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
4389 - ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4390 - "proxy: error creating socket");
4391 - return HTTP_INTERNAL_SERVER_ERROR;
4393 + ap_snprintf(portbuf, sizeof(portbuf), "%d", port);
4394 + memset(&hints, 0, sizeof(hints));
4395 + hints.ai_family = PF_UNSPEC;
4396 + hints.ai_socktype = SOCK_STREAM;
4397 + error = getaddrinfo(host, portbuf, &hints, &res0);
4399 + return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
4400 + gai_strerror(error));
4404 + for (res = res0; res; res = res->ai_next) {
4405 + sock = ap_psocket(p, res->ai_family, res->ai_socktype,
4406 + res->ai_protocol);
4410 #if !defined(TPF) && !defined(BEOS)
4411 - if (conf->recv_buffer_size > 0
4412 - && setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
4413 - (const char *) &conf->recv_buffer_size, sizeof(int))
4415 - ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4416 - "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
4418 + if (conf->recv_buffer_size > 0
4419 + && setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
4420 + (const char *) &conf->recv_buffer_size, sizeof(int))
4422 + ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4423 + "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
4427 - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &one,
4428 - sizeof(one)) == -1) {
4429 + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &one,
4430 + sizeof(one)) == -1) {
4431 #ifndef _OSD_POSIX /* BS2000 has this option "always on" */
4432 - ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4433 - "proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)");
4434 - ap_pclosesocket(p, sock);
4435 - return HTTP_INTERNAL_SERVER_ERROR;
4436 + ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4437 + "proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)");
4438 + ap_pclosesocket(p, sock);
4439 + freeaddrinfo(res0);
4440 + return HTTP_INTERNAL_SERVER_ERROR;
4441 #endif /*_OSD_POSIX*/
4444 -#ifdef SINIX_D_RESOLVER_BUG
4446 - struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list;
4448 - for (; ip_addr->s_addr != 0; ++ip_addr) {
4449 - memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr));
4450 - i = ap_proxy_doconnect(sock, &server, r);
4457 - while (server_hp.h_addr_list[j] != NULL) {
4458 - memcpy(&server.sin_addr, server_hp.h_addr_list[j],
4459 - sizeof(struct in_addr));
4460 - i = ap_proxy_doconnect(sock, &server, r);
4463 + i = ap_proxy_doconnect(sock, res->ai_addr, r);
4465 + memcpy(&server, res->ai_addr, res->ai_addrlen);
4469 + ap_pclosesocket(p, sock);
4472 + freeaddrinfo(res0);
4474 ap_pclosesocket(p, sock);
4475 return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
4479 /* try to set up PASV data connection first */
4480 - dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
4481 + dsock = ap_psocket(p, server.ss_family, SOCK_STREAM, IPPROTO_TCP);
4483 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4484 "proxy: error creating PASV socket");
4485 @@ -825,11 +825,22 @@
4489 - ap_bputs("PASV" CRLF, f);
4491 + if (server.ss_family == AF_INET)
4493 + else if (lpsvmode)
4498 + ap_bputs(CRLF, f);
4500 + Explain0("FTP: passive command issued");
4501 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: PASV command issued");
4502 - /* possible results: 227, 421, 500, 501, 502, 530 */
4503 + /* possible results: 227, 228, 229, 421, 500, 501, 502, 530 */
4504 /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
4505 + /* 228 Entering Long Passive Mode (...). */
4506 + /* 229 Entering Extended Passive Mode (...). */
4507 /* 421 Service not available, closing control connection. */
4508 /* 500 Syntax error, command unrecognized. */
4509 /* 501 Syntax error in parameters or arguments. */
4511 i = ap_bgets(pasv, sizeof(pasv), f);
4513 ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r,
4514 - "PASV: control connection is toast");
4515 + "%s: control connection is toast", cmd);
4516 ap_pclosesocket(p, dsock);
4519 @@ -870,10 +881,14 @@
4520 pport = (p1 << 8) + p0;
4521 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: contacting host %d.%d.%d.%d:%d",
4522 h3, h2, h1, h0, pport);
4523 - data_addr.sin_family = AF_INET;
4524 - data_addr.sin_addr.s_addr = htonl(paddr);
4525 - data_addr.sin_port = htons(pport);
4526 - i = ap_proxy_doconnect(dsock, &data_addr, r);
4527 + sin = (struct sockaddr_in *)&data_addr;
4528 + sin->sin_family = AF_INET;
4530 + sin->sin_len = sizeof(*sin);
4532 + sin->sin_addr.s_addr = htonl(paddr);
4533 + sin->sin_port = htons(pport);
4534 + i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r);
4538 @@ -881,17 +896,76 @@
4540 "Could not connect to remote machine: ",
4541 strerror(errno), NULL));
4546 + } else if (presult == 228 && pstr != NULL
4548 +"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
4549 + &paf, &holen, &ho[0], &ho[1], &ho[2], &ho[3],
4550 + &ho[4], &ho[5], &ho[6], &ho[7], &ho[8], &ho[9], &ho[10], &ho[11],
4551 + &ho[12], &ho[13], &ho[14], &ho[15], &polen, &po[0], &po[1]) == 21
4552 + && paf == 6 && holen == 16 && polen == 2) {
4554 + sin6 = (struct sockaddr_in6 *)&data_addr;
4555 + sin6->sin6_family = AF_INET6;
4557 + sin6->sin6_len = sizeof(*sin6);
4559 + for (i = 0; i < 16; i++)
4560 + sin6->sin6_addr.s6_addr[i] = ho[i] & 0xff;
4561 + sin6->sin6_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff));
4562 + i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r);
4565 + ap_kill_timeout(r);
4566 + return ap_proxyerror(r, HTTP_BAD_GATEWAY,
4567 + ap_pstrcat(r->pool,
4568 + "Could not connect to remote machine: ",
4569 + strerror(errno), NULL));
4573 + } else if (presult == 229 && pstr != NULL
4574 + && pstr[0] == pstr[1] && pstr[0] == pstr[2]
4575 + && pstr[0] == pstr[strlen(pstr) - 1]) {
4576 + /* expect "|||port|" */
4578 + memcpy(&data_addr, &server, SA_LEN((struct sockaddr *)&server));
4580 + memcpy(&data_addr, &server, server.ss_len);
4582 + switch (data_addr.ss_family) {
4584 + sin = (struct sockaddr_in *)&data_addr;
4585 + sin->sin_port = htons(atoi(pstr + 3));
4588 + sin6 = (struct sockaddr_in6 *)&data_addr;
4589 + sin6->sin6_port = htons(atoi(pstr + 3));
4592 + i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r);
4595 + ap_kill_timeout(r);
4596 + return ap_proxyerror(r, HTTP_BAD_GATEWAY,
4597 + ap_pstrcat(r->pool,
4598 + "Could not connect to remote machine: ",
4599 + strerror(errno), NULL));
4603 + } else if (!lpsvmode && strcmp(cmd, "EPSV") == 0) {
4608 ap_pclosesocket(p, dsock); /* and try the regular way */
4611 if (!pasvmode) { /* set up data connection */
4612 - clen = sizeof(struct sockaddr_in);
4613 + clen = sizeof(server);
4614 if (getsockname(sock, (struct sockaddr *) &server, &clen) < 0) {
4615 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4616 "proxy: error getting socket address");
4618 return HTTP_INTERNAL_SERVER_ERROR;
4621 - dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
4622 + dsock = ap_psocket(p, server.ss_family, SOCK_STREAM, IPPROTO_TCP);
4624 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4625 "proxy: error creating socket");
4626 @@ -921,13 +995,26 @@
4627 #endif /*_OSD_POSIX*/
4630 - if (bind(dsock, (struct sockaddr *) &server,
4631 - sizeof(struct sockaddr_in)) == -1) {
4634 + if (bind(dsock, (struct sockaddr *) &server, SA_LEN((struct sockaddr *)&server)) == -1)
4636 + if (bind(dsock, (struct sockaddr *) &server, server.ss_len) == -1)
4639 + char hostnamebuf[MAXHOSTNAMELEN], portnamebuf[MAXHOSTNAMELEN];
4641 - ap_snprintf(buff, sizeof(buff), "%s:%d", inet_ntoa(server.sin_addr), server.sin_port);
4642 + getnameinfo((struct sockaddr *)&server,
4644 + SA_LEN((struct sockaddr *)&server),
4648 + hostnamebuf, sizeof(hostnamebuf),
4649 + portnamebuf, sizeof(portnamebuf),
4650 + NI_NUMERICHOST | NI_NUMERICSERV);
4651 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4652 - "proxy: error binding to ftp data socket %s", buff);
4653 + "proxy: error binding to ftp data socket %s:%s",
4654 + hostnamebuf, portnamebuf);
4656 ap_pclosesocket(p, dsock);
4657 return HTTP_INTERNAL_SERVER_ERROR;
4658 @@ -1186,7 +1273,7 @@
4660 if (!pasvmode) { /* wait for connection */
4661 ap_hard_timeout("proxy ftp data connect", r);
4662 - clen = sizeof(struct sockaddr_in);
4663 + clen = sizeof(server);
4665 csd = accept(dsock, (struct sockaddr *) &server, &clen);
4666 while (csd == -1 && errno == EINTR);
4667 diff -Nur apache_1.3.22.orig/src/modules/proxy/proxy_http.c apache_1.3.22/src/modules/proxy/proxy_http.c
4668 --- apache_1.3.22.orig/src/modules/proxy/proxy_http.c Fri Dec 7 17:26:57 2001
4669 +++ apache_1.3.22/src/modules/proxy/proxy_http.c Fri Dec 7 17:27:28 2001
4671 array_header *reqhdrs_arr;
4673 table_entry *reqhdrs;
4674 - struct sockaddr_in server;
4675 - struct in_addr destaddr;
4676 - struct hostent server_hp;
4677 + struct addrinfo hints, *res, *res0;
4680 char buffer[HUGE_STRING_LEN];
4683 struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts;
4686 - memset(&server, '\0', sizeof(server));
4687 - server.sin_family = AF_INET;
4689 /* We break the URL into host, port, path-search */
4691 urlptr = strstr(url, "://");
4693 return HTTP_BAD_REQUEST;
4695 destport = DEFAULT_HTTP_PORT;
4696 + ap_snprintf(portstr, sizeof(portstr), "%d", DEFAULT_HTTP_PORT);
4697 + destportstr = portstr;
4699 ap_hook_use("ap::mod_proxy::http::handler::set_destport",
4700 AP_HOOK_SIG2(int,ptr),
4701 @@ -229,7 +227,20 @@
4706 + if (*desthost == '['){
4707 + char *u = strrchr(desthost+1, ']');
4711 + if (*(u+1) == ':'){ /* [host]:xx */
4713 + } else if (*(u+1) == '\0'){ /* [host] */
4716 + return HTTP_BAD_REQUEST;
4718 + return HTTP_BAD_REQUEST;
4720 strp2 = strchr(desthost, ':');
4721 if (strp2 != NULL) {
4723 @@ -240,41 +251,69 @@
4726 /* check if ProxyBlock directive on this host */
4727 - destaddr.s_addr = ap_inet_addr(desthost);
4728 - for (i = 0; i < conf->noproxies->nelts; i++) {
4729 - if (destaddr.s_addr == npent[i].addr.s_addr ||
4730 - (npent[i].name != NULL &&
4731 - (npent[i].name[0] == '*' || strstr(desthost, npent[i].name) != NULL)))
4732 + memset(&hints, 0, sizeof(hints));
4733 + hints.ai_family = PF_UNSPEC;
4734 + hints.ai_socktype = SOCK_STREAM;
4735 + hints.ai_protocol = IPPROTO_TCP;
4736 + error = getaddrinfo(desthost, destportstr, &hints, &res0);
4738 + return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
4739 + gai_strerror(error)); /* give up */
4742 + /* check if ProxyBlock directive on this host */
4743 + for (res = res0; res; res = res->ai_next) {
4744 + struct sockaddr_in *sin;
4746 + struct sockaddr_in6 *sin6;
4751 + for (i = 0; i < conf->noproxies->nelts; i++) {
4752 + if (npent[i].name != NULL && strstr(desthost, npent[i].name))
4754 + if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0)
4756 + switch (res->ai_family) {
4758 + sin = (struct sockaddr_in *)res->ai_addr;
4759 + if (sin->sin_addr.s_addr == npent[i].addr.s_addr)
4765 + freeaddrinfo(res0);
4766 return ap_proxyerror(r, HTTP_FORBIDDEN,
4767 "Connect to remote machine blocked");
4770 - if (proxyhost != NULL) {
4771 - server.sin_port = htons(proxyport);
4772 - err = ap_proxy_host2addr(proxyhost, &server_hp);
4774 - return DECLINED; /* try another */
4776 - peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport);
4780 - server.sin_port = htons(destport);
4781 - err = ap_proxy_host2addr(desthost, &server_hp);
4783 - return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
4785 - peer = ap_psprintf(p, "%s:%u", desthost, destport);
4789 - sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
4791 - ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4792 - "proxy: error creating socket");
4793 - return HTTP_INTERNAL_SERVER_ERROR;
4799 + if (proxyhost != NULL) {
4802 + freeaddrinfo(res0);
4803 + ap_snprintf(pbuf, sizeof(pbuf), "%d", proxyport);
4804 + memset(&hints, 0, sizeof(hints));
4805 + hints.ai_family = PF_UNSPEC;
4806 + hints.ai_socktype = SOCK_STREAM;
4807 + hints.ai_protocol = IPPROTO_TCP;
4808 + error = getaddrinfo(proxyhost, pbuf, &hints, &res0);
4810 + return DECLINED; /* try another */
4812 + peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport);
4817 + for (res = res0; res; res = res->ai_next) {
4818 + sock = ap_psocket(p, res->ai_family, res->ai_socktype,
4819 + res->ai_protocol);
4823 #if !defined(TPF) && !defined(BEOS)
4824 if (conf->recv_buffer_size) {
4825 if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
4826 @@ -286,28 +325,12 @@
4830 -#ifdef SINIX_D_RESOLVER_BUG
4832 - struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list;
4834 - for (; ip_addr->s_addr != 0; ++ip_addr) {
4835 - memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr));
4836 - i = ap_proxy_doconnect(sock, &server, r);
4843 - while (server_hp.h_addr_list[j] != NULL) {
4844 - memcpy(&server.sin_addr, server_hp.h_addr_list[j],
4845 - sizeof(struct in_addr));
4846 - i = ap_proxy_doconnect(sock, &server, r);
4847 + i = ap_proxy_doconnect(sock, res->ai_addr, r);
4851 + ap_pclosesocket(p, sock);
4854 + freeaddrinfo(res0);
4856 if (proxyhost != NULL)
4857 return DECLINED; /* try again another way */
4858 @@ -527,17 +550,31 @@
4861 /* check if NoCache directive on this host */
4863 + struct sockaddr_in *sin;
4865 + struct sockaddr_in6 *sin6;
4869 for (i = 0; i < conf->nocaches->nelts; i++) {
4870 - if (destaddr.s_addr == ncent[i].addr.s_addr ||
4871 - (ncent[i].name != NULL &&
4872 - (ncent[i].name[0] == '*' ||
4873 - strstr(desthost, ncent[i].name) != NULL))) {
4876 + if (ncent[i].name != NULL &&
4877 + (ncent[i].name[0] == '*' ||
4878 + strstr(desthost, ncent[i].name) != NULL)) {
4882 + switch (res->ai_addr->sa_family) {
4884 + sin = (struct sockaddr_in *)res->ai_addr;
4885 + if (sin->sin_addr.s_addr == ncent[i].addr.s_addr) {
4894 i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache);
4895 if (i != DECLINED) {
4896 diff -Nur apache_1.3.22.orig/src/modules/proxy/proxy_util.c apache_1.3.22/src/modules/proxy/proxy_util.c
4897 --- apache_1.3.22.orig/src/modules/proxy/proxy_util.c Mon Sep 24 22:14:27 2001
4898 +++ apache_1.3.22/src/modules/proxy/proxy_util.c Fri Dec 7 17:27:28 2001
4900 #include "http_log.h"
4901 #include "util_uri.h"
4902 #include "util_date.h" /* get ap_checkmask() decl. */
4903 +#include "sa_len.h"
4905 static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
4906 static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
4909 char *strp, *host, *url = *urlp;
4910 char *user = NULL, *password = NULL;
4911 + char *t = NULL, *u = NULL, *v = NULL;
4913 if (url[0] != '/' || url[1] != '/')
4914 return "Malformed URL";
4915 @@ -256,11 +258,22 @@
4916 *passwordp = password;
4919 - strp = strrchr(host, ':');
4920 - if (strp != NULL) {
4923 - for (i = 0; strp[i] != '\0'; i++)
4925 + if (*host == '['){
4926 + u = strrchr(host, ']');
4933 + t = strrchr(v, ':');
4939 + for (i=0; strp[i] != '\0'; i++)
4940 if (!ap_isdigit(strp[i]))
4943 @@ -278,17 +291,29 @@
4944 return "Missing host in URL";
4945 /* check hostname syntax */
4946 for (i = 0; host[i] != '\0'; i++)
4947 - if (!ap_isdigit(host[i]) && host[i] != '.')
4948 + if (!ap_isxdigit(host[i]) && host[i] != '.' && host[i] != ':')
4950 /* must be an IP address */
4951 #if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS)
4952 if (host[i] == '\0' && (inet_addr(host) == -1))
4953 + return "Bad IP address in URL";
4955 + if (host[i] == '\0') {
4956 + struct addrinfo hints, *res0;
4958 + memset(&hints, 0, sizeof(hints));
4959 + hints.ai_family = PF_UNSPEC;
4960 + hints.ai_flags = AI_NUMERICHOST;
4961 + if (gai = getaddrinfo(host, NULL, &hints, &res0)) {
4963 + return gai_strerror(gai);
4965 - if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
4966 + return "Bad IP address in URL";
4969 - return "Bad IP address in URL";
4971 + freeaddrinfo(res0);
4977 @@ -1237,22 +1262,45 @@
4978 return host != NULL && strstr(host, This->name) != NULL;
4981 -int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r)
4982 +int ap_proxy_doconnect(int sock, struct sockaddr *addr, request_rec *r)
4986 + char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
4987 +#ifdef NI_WITHSCOPEID
4988 + const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
4990 + const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
4993 ap_hard_timeout("proxy connect", r);
4994 +#ifdef HAVE_SOCKADDR_LEN
4995 + salen = addr->sa_len;
4997 + switch (addr->sa_family) {
4999 + salen = sizeof(struct sockaddr_in6);
5002 + salen = sizeof(struct sockaddr_in);
5007 - i = connect(sock, (struct sockaddr *) addr, sizeof(struct sockaddr_in));
5008 + i = connect(sock, addr, salen);
5009 #if defined(WIN32) || defined(NETWARE)
5010 if (i == SOCKET_ERROR)
5011 errno = WSAGetLastError();
5013 } while (i == -1 && errno == EINTR);
5015 + if (getnameinfo(addr, salen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
5017 + strcpy(hbuf, "?");
5018 + strcpy(pbuf, "?");
5020 ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
5021 - "proxy connect to %s port %d failed",
5022 - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
5023 + "proxy connect to %s port %s failed", hbuf, pbuf);
5027 diff -Nur apache_1.3.22.orig/src/modules/standard/mod_access.c apache_1.3.22/src/modules/standard/mod_access.c
5028 --- apache_1.3.22.orig/src/modules/standard/mod_access.c Mon Jan 15 18:05:34 2001
5029 +++ apache_1.3.22/src/modules/standard/mod_access.c Fri Dec 7 17:27:28 2001
5046 - unsigned long net;
5047 - unsigned long mask;
5048 + struct in_addr net;
5049 + struct in_addr mask;
5053 + struct in6_addr net6;
5054 + struct in6_addr mask6;
5058 enum allowdeny_type type;
5060 @@ -167,90 +176,230 @@
5063 else if ((s = strchr(where, '/'))) {
5064 - unsigned long mask;
5065 + struct addrinfo hints, *resnet, *resmask;
5066 + struct sockaddr_storage net, mask;
5072 + a->type = T_FAIL; /*just in case*/
5073 /* trample on where, we won't be using it any more */
5077 - || (a->x.ip.net = ap_inet_addr(where)) == INADDR_NONE) {
5079 + for (p = s; *p; p++) {
5086 + memset(&hints, 0, sizeof(hints));
5087 + hints.ai_family = PF_UNSPEC;
5088 + hints.ai_socktype = SOCK_STREAM; /*dummy*/
5089 +#ifdef AI_NUMERICHOST
5090 + hints.ai_flags = AI_NUMERICHOST; /*don't resolve*/
5093 + error = getaddrinfo(where, NULL, &hints, &resnet);
5094 + if (error || !resnet) {
5096 + freeaddrinfo(resnet);
5098 return "syntax error in network portion of network/netmask";
5100 + if (resnet->ai_next) {
5101 + freeaddrinfo(resnet);
5103 + return "network/netmask resolved to multiple addresses";
5105 + memcpy(&net, resnet->ai_addr, resnet->ai_addrlen);
5106 + freeaddrinfo(resnet);
5108 - /* is_ip just tests if it matches [\d.]+ */
5110 + switch (net.ss_family) {
5113 + a->x.ip.net.s_addr = ((struct sockaddr_in *)&net)->sin_addr.s_addr;
5118 + memcpy(&a->x.ip6.net6, &((struct sockaddr_in6 *)&net)->sin6_addr,
5119 + sizeof(a->x.ip6.net6));
5124 - return "syntax error in mask portion of network/netmask";
5125 + return "unknown address family for network";
5127 - /* is it in /a.b.c.d form? */
5128 - if (strchr(s, '.')) {
5129 - mask = ap_inet_addr(s);
5130 - if (mask == INADDR_NONE) {
5132 + if (!justdigits) {
5133 + memset(&hints, 0, sizeof(hints));
5134 + hints.ai_family = PF_UNSPEC;
5135 + hints.ai_socktype = SOCK_STREAM; /*dummy*/
5136 +#ifdef AI_NUMERICHOST
5137 + hints.ai_flags = AI_NUMERICHOST; /*don't resolve*/
5140 + error = getaddrinfo(s, NULL, &hints, &resmask);
5141 + if (error || !resmask) {
5143 + freeaddrinfo(resmask);
5145 return "syntax error in mask portion of network/netmask";
5149 - /* assume it's in /nnn form */
5151 - if (mask > 32 || mask <= 0) {
5153 - return "invalid mask in network/netmask";
5155 - mask = 0xFFFFFFFFUL << (32 - mask);
5156 - mask = htonl(mask);
5158 - a->x.ip.mask = mask;
5159 - a->x.ip.net = (a->x.ip.net & mask); /* pjr - This fixes PR 4770 */
5161 - else if (ap_isdigit(*where) && is_ip(where)) {
5162 - /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
5168 - /* parse components */
5175 - if (!ap_isdigit(*t)) {
5176 + if (resmask->ai_next) {
5177 + freeaddrinfo(resmask);
5179 - return "invalid ip address";
5180 + return "network/netmask resolved to multiple addresses";
5182 - while (ap_isdigit(*t)) {
5189 + memcpy(&mask, resmask->ai_addr, resmask->ai_addrlen);
5190 + freeaddrinfo(resmask);
5192 + if (net.ss_family != mask.ss_family) {
5194 - return "invalid ip address";
5195 + return "network/netmask resolved to different address family";
5198 - return "invalid ip address, only 4 octets allowed";
5200 + switch (a->type) {
5202 + a->x.ip.mask.s_addr =
5203 + ((struct sockaddr_in *)&mask)->sin_addr.s_addr;
5207 + memcpy(&a->x.ip6.mask6,
5208 + &((struct sockaddr_in6 *)&mask)->sin6_addr,
5209 + sizeof(a->x.ip6.mask6));
5214 - if (octet < 0 || octet > 255) {
5216 - return "each octet must be between 0 and 255 inclusive";
5220 + switch (a->type) {
5222 + if (mask < 0 || 32 < mask) {
5224 + return "netmask out of range";
5226 + a->x.ip.mask.s_addr = htonl(0xFFFFFFFFUL << (32 - mask));
5232 + if (mask < 0 || 128 < mask) {
5234 + return "netmask out of range";
5236 + for (i = 0; i < mask / 8; i++) {
5237 + a->x.ip6.mask6.s6_addr[i] = 0xff;
5240 + a->x.ip6.mask6.s6_addr[i] = 0xff << (8 - (mask % 8));
5245 - a->x.ip.net |= octet << shift;
5246 - a->x.ip.mask |= 0xFFUL << shift;
5250 - a->x.ip.net = ntohl(a->x.ip.net);
5251 - a->x.ip.mask = ntohl(a->x.ip.mask);
5255 + struct addrinfo hints, *res;
5256 + struct sockaddr_storage ss;
5259 + a->type = T_FAIL; /*just in case*/
5261 + /* First, try using the old apache code to match */
5262 + /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
5263 + if (ap_isdigit(*where) && is_ip(where)) {
5269 + /* parse components */
5271 + a->x.ip.net.s_addr = 0;
5272 + a->x.ip.mask.s_addr = 0;
5276 + if (!ap_isdigit(*t)) {
5278 + return "invalid ip address";
5280 + while (ap_isdigit(*t)) {
5288 + return "invalid ip address";
5291 + return "invalid ip address, only 4 octets allowed";
5294 + if (octet < 0 || octet > 255) {
5296 + return "each octet must be between 0 and 255 inclusive";
5298 + a->x.ip.net.s_addr |= octet << shift;
5299 + a->x.ip.mask.s_addr |= 0xFFUL << shift;
5303 + a->x.ip.net.s_addr = ntohl(a->x.ip.net.s_addr);
5304 + a->x.ip.mask.s_addr = ntohl(a->x.ip.mask.s_addr);
5309 + /* IPv4/v6 numeric address */
5310 + memset(&hints, 0, sizeof(hints));
5311 + hints.ai_family = PF_UNSPEC;
5312 + hints.ai_socktype = SOCK_STREAM; /*dummy*/
5313 +#ifdef AI_NUMERICHOST
5314 + hints.ai_flags = AI_NUMERICHOST; /*don't resolve*/
5317 + error = getaddrinfo(where, NULL, &hints, &res);
5318 + if (error || !res) {
5320 + freeaddrinfo(res);
5324 + if (res->ai_next) {
5325 + freeaddrinfo(res);
5327 + return "network/netmask resolved to multiple addresses";
5329 + memcpy(&ss, res->ai_addr, res->ai_addrlen);
5330 + freeaddrinfo(res);
5332 + switch (ss.ss_family) {
5335 + a->x.ip.net.s_addr = ((struct sockaddr_in *)&ss)->sin_addr.s_addr;
5336 + memset(&a->x.ip.mask, 0xff, sizeof(a->x.ip.mask));
5341 + memcpy(&a->x.ip6.net6, &((struct sockaddr_in6 *)&ss)->sin6_addr,
5342 + sizeof(a->x.ip6.net6));
5343 + memset(&a->x.ip6.mask6, 0xff, sizeof(a->x.ip6.mask6));
5348 + return "unknown address family for network";
5353 @@ -315,12 +464,63 @@
5357 - if (ap[i].x.ip.net != INADDR_NONE
5358 - && (r->connection->remote_addr.sin_addr.s_addr
5359 - & ap[i].x.ip.mask) == ap[i].x.ip.net) {
5361 + if (ap[i].x.ip.net.s_addr == INADDR_NONE)
5363 + switch (r->connection->remote_addr.ss_family) {
5365 + if ((((struct sockaddr_in *)&r->connection->remote_addr)->sin_addr.s_addr
5366 + & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) {
5372 + if (!IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr)) /*XXX*/
5374 + if ((*(ap_uint32_t *)&((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr.s6_addr[12]
5375 + & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) {
5386 + struct in6_addr masked;
5388 + if (IN6_IS_ADDR_UNSPECIFIED(&ap[i].x.ip6.net6))
5390 + switch (r->connection->remote_addr.ss_family) {
5392 + if (!IN6_IS_ADDR_V4MAPPED(&ap[i].x.ip6.net6)) /*XXX*/
5394 + memset(&masked, 0, sizeof(masked));
5395 + masked.s6_addr[10] = masked.s6_addr[11] = 0xff;
5396 + memcpy(&masked.s6_addr[12],
5397 + &((struct sockaddr_in *)&r->connection->remote_addr)->sin_addr.s_addr,
5398 + sizeof(struct sockaddr_in));
5399 + for (j = 0; j < sizeof(struct in6_addr); j++)
5400 + masked.s6_addr[j] &= ap[i].x.ip6.mask6.s6_addr[j];
5401 + if (memcmp(&masked, &ap[i].x.ip6.net6, sizeof(masked)) == 0)
5405 + memset(&masked, 0, sizeof(masked));
5407 + &((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr,
5409 + for (j = 0; j < sizeof(struct in6_addr); j++)
5410 + masked.s6_addr[j] &= ap[i].x.ip6.mask6.s6_addr[j];
5411 + if (memcmp(&masked, &ap[i].x.ip6.net6, sizeof(masked)) == 0)
5421 diff -Nur apache_1.3.22.orig/src/modules/standard/mod_unique_id.c apache_1.3.22/src/modules/standard/mod_unique_id.c
5422 --- apache_1.3.22.orig/src/modules/standard/mod_unique_id.c Tue Oct 2 18:11:13 2001
5423 +++ apache_1.3.22/src/modules/standard/mod_unique_id.c Fri Dec 7 17:27:28 2001
5425 #include "http_config.h"
5426 #include "http_log.h"
5427 #include "multithread.h"
5428 +#include "sa_len.h"
5430 +/*#define SHORT_UNIQUE_ID*/
5434 - unsigned int in_addr;
5436 + struct in_addr in;
5438 +# ifdef SHORT_UNIQUE_ID
5441 + struct in6_addr in6;
5449 * this shouldn't be a problem till year 2106.
5452 -static unsigned global_in_addr;
5453 +static struct sockaddr_storage global_addr;
5458 #define MAXHOSTNAMELEN 256
5460 char str[MAXHOSTNAMELEN + 1];
5461 - struct hostent *hent;
5462 + struct addrinfo hints, *res, *res0;
5464 #ifndef NO_GETTIMEOFDAY
5469 unique_id_rec_offset[0] = XtOffsetOf(unique_id_rec, stamp);
5470 unique_id_rec_size[0] = sizeof(cur_unique_id->stamp);
5471 - unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, in_addr);
5472 - unique_id_rec_size[1] = sizeof(cur_unique_id->in_addr);
5473 + unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, addr);
5474 + unique_id_rec_size[1] = sizeof(cur_unique_id.addr);
5475 unique_id_rec_offset[2] = XtOffsetOf(unique_id_rec, pid);
5476 unique_id_rec_size[2] = sizeof(cur_unique_id->pid);
5478 @@ -269,17 +282,44 @@
5480 str[sizeof(str) - 1] = '\0';
5482 - if ((hent = gethostbyname(str)) == NULL) {
5483 + memset(&hints, 0, sizeof(hints));
5484 + hints.ai_family = PF_UNSPEC;
5485 + error = getaddrinfo(str, NULL, &hints, &res0);
5487 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s,
5488 - "mod_unique_id: unable to gethostbyname(\"%s\")", str);
5489 + "mod_unique_id: getaddrinfo failed for \"%s\" (%s)", str,
5490 + gai_strerror(error));
5494 - global_in_addr = ((struct in_addr *) hent->h_addr_list[0])->s_addr;
5496 + for (res = res0; res; res = res->ai_next) {
5497 + switch (res->ai_family) {
5502 + memcpy(&global_addr, res->ai_addr, res->ai_addrlen);
5507 + freeaddrinfo(res0);
5509 + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s,
5510 + "mod_unique_id: no known AF found for \"%s\"", str);
5514 + getnameinfo((struct sockaddr *)&global_addr,
5516 + SA_LEN((struct sockaddr *)&global_addr),
5518 + global_addr.ss_len,
5520 + str, sizeof(str), NULL, 0, NI_NUMERICHOST);
5521 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, s,
5522 - "mod_unique_id: using ip addr %s",
5523 - inet_ntoa(*(struct in_addr *) hent->h_addr_list[0]));
5524 + "mod_unique_id: using ip addr %s", str);
5527 * If the server is pummelled with restart requests we could possibly end
5528 @@ -336,7 +376,23 @@
5529 "oh no! pids are greater than 32-bits! I'm broken!");
5532 - cur_unique_id->in_addr = global_in_addr;
5533 + memset(&cur_unique_id.addr, 0, sizeof(cur_unique_id.addr));
5534 + switch (global_addr.ss_family) {
5536 + cur_unique_id.addr.in = ((struct sockaddr_in *)&global_addr)->sin_addr;
5540 +#ifdef SHORT_UNIQUE_ID
5541 + cur_unique_id.addr.in6 =
5542 + ((struct sockaddr_in6 *)&global_addr)->sin6_addr.s6_addr32[3];
5544 + cur_unique_id.addr.in6 =
5545 + ((struct sockaddr_in6 *)&global_addr)->sin6_addr;
5552 * If we use 0 as the initial counter we have a little less protection
5553 diff -Nur apache_1.3.22.orig/src/support/ab.c apache_1.3.22/src/support/ab.c
5554 --- apache_1.3.22.orig/src/support/ab.c Mon Oct 8 19:54:42 2001
5555 +++ apache_1.3.22/src/support/ab.c Fri Dec 7 17:41:39 2001
5557 #include <sys/uio.h>
5560 +#include "sa_len.h"
5562 #endif /* NO_APACHE_INCLUDES */
5566 auth[1024], /* optional (basic/uuencoded)
5567 * authentification */
5568 hdrs[4096]; /* optional arbitrary headers */
5569 -int port = 80; /* port number */
5570 +char *port = "80"; /* port number */
5572 int use_html = 0; /* use html in the report */
5575 struct data *stats; /* date for each request */
5577 fd_set readbits, writebits; /* bits for select */
5578 -struct sockaddr_in server; /* server addr structure */
5579 +struct sockaddr_storage server; /* server addr structure */
5582 #define ab_close(s) close(s)
5585 printf("Server Software: %s\n", servername);
5586 printf("Server Hostname: %s\n", hostname);
5587 - printf("Server Port: %d\n", port);
5588 + printf("Server Port: %s\n", port);
5590 printf("Document Path: %s\n", path);
5591 printf("Document Length: %d bytes\n", doclen);
5596 - c->fd = socket(AF_INET, SOCK_STREAM, 0);
5597 + c->fd = socket(server.ss_family, SOCK_STREAM, 0);
5601 @@ -879,7 +881,12 @@
5604 gettimeofday(&c->start, 0);
5605 - if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) {
5607 + if (connect(c->fd, (struct sockaddr *) & server, SA_LEN((struct sockaddr*)&server)) < 0)
5609 + if (connect(c->fd, (struct sockaddr *) & server, server.ss_len) < 0)
5612 if (errno == EINPROGRESS) {
5613 c->state = STATE_CONNECTING;
5615 @@ -1209,16 +1216,20 @@
5618 /* get server information */
5619 - struct hostent *he;
5620 - he = gethostbyname(host);
5622 - char theerror[1024];
5623 - sprintf(theerror, "Bad hostname: %s\n", host);
5626 - server.sin_family = he->h_addrtype;
5627 - server.sin_port = htons(connectport);
5628 - server.sin_addr.s_addr = ((unsigned long *) (he->h_addr_list[0]))[0];
5629 + struct addrinfo hints, *res;
5632 + memset(&hints, 0, sizeof(hints));
5633 + hints.ai_family = PF_UNSPEC;
5634 + error = getaddrinfo(host, port, &hints, &res);
5636 + char *theerror=malloc(strlen(host)+16);
5637 + sprintf(theerror, "Bad hostname: %s\n", host);
5641 + memcpy(&server, res->ai_addr, res->ai_addrlen);
5642 + freeaddrinfo(res);
5645 con = malloc(concurrency * sizeof(struct connection));
5646 @@ -1425,7 +1436,7 @@
5648 strcpy(hostname, h);
5655 @@ -1668,3 +1679,7 @@
5660 +#ifdef NEED_GETADDRINFO
5661 +#include "../main/getaddrinfo.c"
5663 diff -Nur apache_1.3.22.orig/src/support/logresolve.c apache_1.3.22/src/support/logresolve.c
5664 --- apache_1.3.22.orig/src/support/logresolve.c Wed May 23 00:52:21 2001
5665 +++ apache_1.3.22/src/support/logresolve.c Fri Dec 7 17:27:28 2001
5668 #endif /* !MPE && !WIN32*/
5670 -static void cgethost(struct in_addr ipnum, char *string, int check);
5671 +#include "sa_len.h"
5673 +static void cgethost(struct sockaddr *sa, char *string, int check);
5674 static int getline(char *s, int n);
5675 static void stats(FILE *output);
5681 - struct in_addr ipnum;
5682 + struct sockaddr_storage addr;
5686 @@ -122,17 +124,48 @@
5687 * IP numbers with their IP number as hostname, setting noname flag
5690 -static void cgethost (struct in_addr ipnum, char *string, int check)
5691 +static void cgethost (struct sockaddr *sa, char *string, int check)
5693 + ap_uint32_t hashval;
5694 + struct sockaddr_in *sin;
5696 + struct sockaddr_in6 *sin6;
5698 struct nsrec **current, *new;
5699 - struct hostent *hostdata;
5701 + char hostnamebuf[MAXHOSTNAMELEN];
5703 + switch (sa->sa_family) {
5705 + hashval = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
5709 + hashval = *(ap_uint32_t *)&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12];
5717 + current = &nscache[((hashval + (hashval >> 8) +
5718 + (hashval >> 16) + (hashval >> 24)) % BUCKETS)];
5720 - current = &nscache[((ipnum.s_addr + (ipnum.s_addr >> 8) +
5721 - (ipnum.s_addr >> 16) + (ipnum.s_addr >> 24)) % BUCKETS)];
5722 + while (*current) {
5724 + if (SA_LEN(sa) == SA_LEN((struct sockaddr *)&(*current)->addr)
5725 + && memcmp(sa, &(*current)->addr, SA_LEN(sa)) == 0)
5727 + if (sa->sa_len == (*current)->addr.ss_len
5728 + && memcmp(sa, &(*current)->addr, sa->sa_len) == 0)
5734 - while (*current != NULL && ipnum.s_addr != (*current)->ipnum.s_addr)
5735 current = &(*current)->next;
5738 if (*current == NULL) {
5740 @@ -145,45 +178,55 @@
5744 - new->ipnum = ipnum;
5746 + memcpy(&new->addr, sa, SA_LEN(sa));
5748 + memcpy(&new->addr, sa, sa->sa_len);
5751 - hostdata = gethostbyaddr((const char *) &ipnum, sizeof(struct in_addr),
5753 - if (hostdata == NULL) {
5754 - if (h_errno > MAX_ERR)
5755 - errors[UNKNOWN_ERR]++;
5757 - errors[h_errno]++;
5758 - new->noname = h_errno;
5759 - name = strdup(inet_ntoa(ipnum));
5763 - name = strdup(hostdata->h_name);
5765 - if (name == NULL) {
5767 - fprintf(stderr, "Insufficient memory\n");
5770 - hostdata = gethostbyname(name);
5771 - if (hostdata != NULL) {
5774 - for (hptr = hostdata->h_addr_list; *hptr != NULL; hptr++)
5775 - if (((struct in_addr *) (*hptr))->s_addr == ipnum.s_addr)
5777 - if (*hptr == NULL)
5780 - if (hostdata == NULL) {
5781 - fprintf(stderr, "Bad host: %s != %s\n", name,
5782 - inet_ntoa(ipnum));
5783 - new->noname = NO_REVERSE;
5785 - name = strdup(inet_ntoa(ipnum));
5786 - errors[NO_REVERSE]++;
5787 + new->noname = getnameinfo(sa,
5793 + hostnamebuf, sizeof(hostnamebuf), NULL, 0, 0);
5794 + name = strdup(hostnamebuf);
5796 + struct addrinfo hints, *res;
5798 + memset(&hints, 0, sizeof(hints));
5799 + hints.ai_family = PF_UNSPEC;
5800 + error = getaddrinfo(hostnamebuf, NULL, &hints, &res);
5804 + if (SA_LEN(sa) == res->ai_addrlen
5805 + && memcmp(sa, res->ai_addr, SA_LEN(sa)) == 0)
5807 + if (sa->sa_len == res->ai_addrlen
5808 + && memcmp(sa, res->ai_addr, sa->sa_len) == 0)
5813 + res = res->ai_next;
5825 + hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
5826 + fprintf(stderr, "Bad host: %s != %s\n", name, hostnamebuf);
5827 + new->noname = NO_REVERSE;
5829 + name = strdup(hostnamebuf);
5832 new->hostname = name;
5835 struct nsrec *current;
5836 char *errstring[MAX_ERR + 3];
5837 + char hostnamebuf[MAXHOSTNAMELEN];
5839 for (i = 0; i < MAX_ERR + 3; i++)
5840 errstring[i] = "Unknown error";
5841 @@ -242,7 +286,14 @@
5843 for (i = 0; i < BUCKETS; i++)
5844 for (current = nscache[i]; current != NULL; current = current->next) {
5845 - ipstring = inet_ntoa(current->ipnum);
5846 + getnameinfo((struct sockaddr *)¤t->addr,
5848 + SA_LEN((struct sockaddr *)¤t->addr),
5850 + current->addr.ss_len,
5852 + hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
5853 + ipstring = hostnamebuf;
5854 if (current->noname == 0)
5855 fprintf(output, " %3d %15s - %s\n", i, ipstring,
5857 @@ -276,9 +327,10 @@
5859 int main (int argc, char *argv[])
5861 - struct in_addr ipnum;
5862 char *bar, hoststring[MAXDNAME + 1], line[MAXLINE], *statfile;
5864 + struct addrinfo hints, *res;
5869 @@ -322,8 +374,10 @@
5870 bar = strchr(line, ' ');
5873 - ipnum.s_addr = inet_addr(line);
5874 - if (ipnum.s_addr == 0xffffffffu) {
5875 + memset(&hints, 0, sizeof(hints));
5876 + hints.ai_family = PF_UNSPEC;
5877 + error = getaddrinfo(line, NULL, &hints, &res);
5882 @@ -333,11 +387,12 @@
5886 - cgethost(ipnum, hoststring, check);
5887 + cgethost(res->ai_addr, hoststring, check);
5889 printf("%s %s\n", hoststring, bar + 1);
5892 + freeaddrinfo(res);
5896 @@ -358,3 +413,11 @@
5901 +#ifdef NEED_GETADDRINFO
5902 +#include "../main/getaddrinfo.c"
5905 +#ifdef NEED_GETNAMEINFO
5906 +#include "../main/getnameinfo.c"