]> git.pld-linux.org Git - packages/apache.git/blob - apache-ipv6-PLD.patch
- resoled 4 from 5 rejects (maybe someone can help resolve src/support/ab.c.rej ?).
[packages/apache.git] / apache-ipv6-PLD.patch
1 diff -Nru apache_1.3.20/README.v6 apache_1.3.20.new/README.v6
2 --- apache_1.3.20/README.v6     Thu Jan  1 01:00:00 1970
3 +++ apache_1.3.20.new/README.v6 Mon May 21 10:54:52 2001
4 @@ -0,0 +1,166 @@
5 +IPv6-ready apache 1.3.x
6 +KAME Project
7 +$Id$
8 +
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.
12 +
13 +Basically you can write IPv6 address where IPv4 address fits.
14 +
15 +extra command-line argument:
16 +       -4      Assume IPv4 address on ambiguous directives
17 +       -6      Assume IPv6 address on ambiguous directives (default)
18 +
19 +       The above two can be used, for example, to disambiguate
20 +       "BindAddress *".
21 +
22 +base commands:
23 +    Listen
24 +       Listen is expanded to take one or two arguments.
25 +               Listen port
26 +               Listen address:port
27 +               Listen address port
28 +       This is to let you specify "Listen :: 80", since "Listen :::80"
29 +       won't work.
30 +
31 +mod_access:
32 +    deny from
33 +    allow from
34 +       "deny from" and "allow from" supports IPv6 addresses, under the
35 +       following forms:
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.
40 +
41 +mod_proxy:
42 +    ProxyRequests on
43 +       http/ftp proxying for both IPv4 and IPv6 is possible.
44 +       Access control functions (NoProxy) are not updated yet.
45 +
46 +       NOTE: for security reasons, we recommend you to filter out
47 +       outsider's access to your proxy, by directives like below:
48 +               <Directory proxy:*>
49 +               order deny,allow
50 +               deny from all
51 +               allow from 10.0.0.0/8
52 +               allow from 3ffe:9999:8888:7777::/64
53 +               </Directory>
54 +
55 +virtual host:
56 +       If you would like to this feature, you must describe 'Listen'
57 +       part on configuration file explicitly. like below:
58 +               Listen :: 80
59 +               Listen 0.0.0.0 80
60 +
61 +    NameVirtualHost
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.
67 +
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.
77 +
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>
88 +
89 +logresolve (src/support)
90 +       error statistics in nameserver cache code is omitted.
91 +
92 +mod_unique_id
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.
97 +
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
107 +       worldwide unique.
108 +
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.
114 +
115 +       The behavior should be improved in the near future; we welcome your
116 +       inputs.
117 +
118 +Modules known to be incompatible with IPv6
119 +       (please report us)
120 +
121 +configure
122 +       Configure has extra option, --enable-rule=INET6.  if the option
123 +       is specified, IPv6 code will be enabled.
124 +
125 +configuration file
126 +       We do not support IPv4 mapped address (IPv6 address format like
127 +       ::ffff:10.1.1.1) in configuration file. 
128 +
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.
135 +
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"
148 +script.
149 +
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.
153 +
154 +Acknowledgements
155 +       Thanks to all people submitted patches/fixes for this patch kit,
156 +       including:
157 +               "Chris P. Ross" <cross@eng.us.uu.net>
158 +
159 +Author contacts
160 +       Jun-ichiro itojun Hagino, KAME project
161 +        http://www.kame.net/
162 +        mailto:core@kame.net
163 +Linux Port
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 -Nru apache_1.3.20/conf/httpd.conf-dist apache_1.3.20.new/conf/httpd.conf-dist
172 --- apache_1.3.20/conf/httpd.conf-dist  Sun May 13 19:59:49 2001
173 +++ apache_1.3.20.new/conf/httpd.conf-dist      Mon May 21 10:54:52 2001
174 @@ -174,6 +174,11 @@
175  #Listen 3000
176  #Listen 12.34.56.78:80
177  
178 +# Listen can take two arguments.
179 +# (this is an extension for supporting IPv6 addresses)
180 +#Listen :: 80
181 +#Listen 0.0.0.0 80
182 +
183  #
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 -Nru apache_1.3.20/configure.v6 apache_1.3.20.new/configure.v6
187 --- apache_1.3.20/configure.v6  Thu Jan  1 01:00:00 1970
188 +++ apache_1.3.20.new/configure.v6      Mon May 21 10:54:52 2001
189 @@ -0,0 +1,3 @@
190 +#! /bin/sh
191 +
192 +./configure --enable-rule=INET6 --enable-module=proxy $*
193 diff -Nru apache_1.3.20/src/Configuration.tmpl apache_1.3.20.new/src/Configuration.tmpl
194 --- apache_1.3.22/src/Configuration.tmpl        Fri Oct  5 10:19:15 2001
195 +++ apache_1.3.22.new/src/Configuration.tmpl    Fri Nov 16 05:27:07 2001
196 @@ -191,6 +191,9 @@
197  #  Rule EXPAT=default   : If Expat can be found at the system or
198  #                         in lib/expat-lite, use it; otherwise
199  #                         skip it
200 +# INET6:
201 +#  IPv6 support.
202 +#
203  
204  Rule SOCKS4=no
205  Rule SOCKS5=no
206 @@ -198,6 +201,7 @@
207  Rule IRIXN32=yes
208  Rule PARANOID=no
209  Rule EXPAT=default
210 +Rule INET6=no
211  
212  # DEV_RANDOM:
213  #  Note: this rule is only used when compiling mod_auth_digest.
214 diff -Nru apache_1.3.20/src/Configure apache_1.3.20.new/src/Configure
215 --- apache_1.3.20/src/Configure Mon May 21 11:02:03 2001
216 +++ apache_1.3.20.new/src/Configure     Mon May 21 10:54:52 2001
217 @@ -237,6 +237,7 @@
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`
222  
223  ####################################################################
224  ## Rule SHARED_CORE implies required DSO support
225 @@ -1661,6 +1662,124 @@
226      esac
227  fi
228  
229 +# INET6 support.
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
236 +       case "$i" in
237 +       KAME)
238 +           if [ -f /usr/include/netinet6/in6.h -a "x`egrep '__KAME__' /usr/include/netinet6/in6.h 2>/dev/null`" != "x" ]; then
239 +               IPV6_STACKTYPE=$i
240 +           fi
241 +           ;;
242 +       Linux)
243 +           if [ /usr/include/netinet/ip6.h -a -d /usr/include/linux ]; then
244 +               IPV6_STACKTYPE=$i
245 +           fi
246 +           ;;
247 +       Solaris)
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})"
253 +                   fi
254 +                   ;;
255 +           esac
256 +           ;;
257 +       esac
258 +       if [ "$IPV6_STACKTYPE" != "UNKNOWN" ]; then
259 +           break
260 +       fi
261 +    done
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" 
266 +       else
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"
275 +           else
276 +               echo "** WARNING: No getaddrinfo found, linkage may fail" 
277 +           fi
278 +       fi
279 +    else
280 +       echo ""
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."
285 +       echo ""
286 +    fi
287 +    case $PLAT in
288 +       *-solaris2* )
289 +           LIBS="$LIBS -lresolv"
290 +           ;;
291 +    esac
292 +else
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"
296 +    fi
297 +fi
298 +
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
302 +rm -f testfunc.o
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"
307 +else
308 +    echo " + you don't have sa_len in struct sockaddr."
309 +fi
310 +rm -f testfunc.c testfunc.o
311 +
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
315 +rm -f testfunc.o
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"
319 +else
320 +    CFLAGS="$CFLAGS -DNEED_SOCKADDR_STORAGE"
321 +    echo " + you need struct sockaddr_storage"
322 +fi
323 +rm -f testfunc.c testfunc.o
324 +
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
328 +rm -f testfunc.o
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"
332 +fi
333 +rm -f testfunc.c testfunc.o
334 +
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
339 +rm -f testfunc.o
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"
343 +fi
344 +rm -f testfunc.c testfunc.o
345 +
346 +
347  ####################################################################
348  ## Find out what modules we want and try and configure things for them
349  ## Module lines can look like this:
350 @@ -2252,6 +2371,38 @@
351  echo "#ifndef AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H
352  echo "#define AP_LONGEST_LONG $AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H
353  echo "#endif" >>$AP_CONFIG_AUTO_H
354 +
355 +if [ x`./helpers/TestCompile -r sizeof 'uint32_t'` != x"" ]; then
356 +    echo "" >>$AP_CONFIG_AUTO_H
357 +    echo "/* determine: use uint32_t as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
358 +    echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H
359 +    echo "#define ap_uint32_t uint32_t" >>$AP_CONFIG_AUTO_H
360 +    echo "#endif" >>$AP_CONFIG_AUTO_H
361 +    echo "   - use uint32_t as 32bit unsigned int"
362 +elif [ x`./helpers/TestCompile -r sizeof 'u_int32_t'` != x"" ]; then
363 +    echo "" >>$AP_CONFIG_AUTO_H
364 +    echo "/* determine: use u_int32_t as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
365 +    echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H
366 +    echo "#define ap_uint32_t u_int32_t" >>$AP_CONFIG_AUTO_H
367 +    echo "#endif" >>$AP_CONFIG_AUTO_H
368 +    echo "   - use u_int32_t as 32bit unsigned int"
369 +elif [ x`./helpers/TestCompile -r sizeof 'unsigned int'` = x"4" ]; then
370 +    echo "" >>$AP_CONFIG_AUTO_H
371 +    echo "/* determine: use unsigned int as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
372 +    echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H
373 +    echo "#define ap_uint32_t unsigned int" >>$AP_CONFIG_AUTO_H
374 +    echo "#endif" >>$AP_CONFIG_AUTO_H
375 +    echo "   - use unsigned int as 32bit unsigned int"
376 +elif [ x`./helpers/TestCompile -r sizeof 'unsigned long int'` = x"4" ]; then
377 +    echo "" >>$AP_CONFIG_AUTO_H
378 +    echo "/* determine: use unsigned long int as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
379 +    echo "#ifndef uint32_t" >>$AP_CONFIG_AUTO_H
380 +    echo "#define uint32_t unsigned long int" >>$AP_CONFIG_AUTO_H
381 +    echo "#endif" >>$AP_CONFIG_AUTO_H
382 +    echo "   - use unsigned long int as 32bit unsigned int"
383 +else
384 +    echo "  - Warning: cannot determine what type should we use as 32bit unsigned int"
385 +fi
386  
387  ####################################################################
388  ## More building ap_config_auto.h
389 diff -Nru apache_1.3.20/src/ap/ap_snprintf.c apache_1.3.20.new/src/ap/ap_snprintf.c
390 --- apache_1.3.20/src/ap/ap_snprintf.c  Thu May 10 16:04:22 2001
391 +++ apache_1.3.20.new/src/ap/ap_snprintf.c      Mon May 21 10:55:24 2001
392 @@ -73,6 +73,7 @@
393  #include <string.h>
394  #include <stdlib.h>
395  #include <math.h>
396 +#include "sa_len.h"
397  #ifdef WIN32
398  #include <float.h>
399  #endif
400 @@ -504,6 +505,42 @@
401  
402  
403  
404 +#ifdef INET6
405 +static char *conv_sockaddr(struct sockaddr *sa, char *buf_end, int *len)
406 +{
407 +    char *p = buf_end;
408 +    char hostnamebuf[MAXHOSTNAMELEN];
409 +    char portnamebuf[MAXHOSTNAMELEN];
410 +    char *q;
411 +    int salen;
412 +
413 +#ifndef SIN6_LEN
414 +    salen = SA_LEN(sa);
415 +#else
416 +    salen = sa->sa_len;
417 +#endif
418 +    if (getnameinfo(sa, salen, hostnamebuf, sizeof(hostnamebuf),
419 +           portnamebuf, sizeof(portnamebuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
420 +       strcpy(hostnamebuf, "???");
421 +       strcpy(portnamebuf, "???");
422 +    }
423 +    if (strcmp(portnamebuf,"0") == 0)
424 +       strcpy(portnamebuf, "*");
425 +    q = portnamebuf + strlen(portnamebuf);
426 +    while (portnamebuf < q)
427 +       *--p = *--q;
428 +    *--p = ':';
429 +    q = hostnamebuf + strlen(hostnamebuf);
430 +    while (hostnamebuf < q)
431 +       *--p = *--q;
432 +
433 +    *len = buf_end - p;
434 +    return (p);
435 +}
436 +#endif /*INET6*/
437 +
438 +
439 +
440  /*
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 */
445                 case 'I':
446                     {
447 +#ifndef INET6
448                         struct sockaddr_in *si;
449  
450                         si = va_arg(ap, struct sockaddr_in *);
451 @@ -1063,6 +1101,16 @@
452                             if (adjust_precision && precision < s_len)
453                                 s_len = precision;
454                         }
455 +#else
456 +                       struct sockaddr *sa;
457 +
458 +                       sa = va_arg(ap, struct sockaddr *);
459 +                       if (sa != NULL) {
460 +                           s = conv_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len);
461 +                           if (adjust_precision && precision < s_len)
462 +                               s_len = precision;
463 +                       }
464 +#endif
465                         else {
466                             s = S_NULL;
467                             s_len = S_NULL_LEN;
468 diff -Nru apache_1.3.20/src/ap/ap_snprintf.c~ apache_1.3.20.new/src/ap/ap_snprintf.c~
469 --- apache_1.3.20/src/ap/ap_snprintf.c~ Thu Jan  1 01:00:00 1970
470 +++ apache_1.3.20.new/src/ap/ap_snprintf.c~     Mon May 21 10:54:52 2001
471 @@ -0,0 +1,1256 @@
472 +/* ====================================================================
473 + * The Apache Software License, Version 1.1
474 + *
475 + * Copyright (c) 2000 The Apache Software Foundation.  All rights
476 + * reserved.
477 + *
478 + * Redistribution and use in source and binary forms, with or without
479 + * modification, are permitted provided that the following conditions
480 + * are met:
481 + *
482 + * 1. Redistributions of source code must retain the above copyright
483 + *    notice, this list of conditions and the following disclaimer.
484 + *
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
488 + *    distribution.
489 + *
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.
496 + *
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.
501 + *
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.
505 + *
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
517 + * SUCH DAMAGE.
518 + * ====================================================================
519 + *
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/>.
524 + *
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.
528 + */
529 +
530 +/*
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.
534 + */
535 +
536 +#include "httpd.h"
537 +
538 +#include <stdio.h>
539 +#include <ctype.h>
540 +#ifndef NETWARE
541 +#include <sys/types.h>
542 +#endif
543 +#include <stdarg.h>
544 +#include <string.h>
545 +#include <stdlib.h>
546 +#include <math.h>
547 +#ifdef WIN32
548 +#include <float.h>
549 +#endif
550 +
551 +typedef enum {
552 +    NO = 0, YES = 1
553 +} boolean_e;
554 +
555 +#ifndef FALSE
556 +#define FALSE                  0
557 +#endif
558 +#ifndef TRUE
559 +#define TRUE                   1
560 +#endif
561 +#ifndef AP_LONGEST_LONG
562 +#define AP_LONGEST_LONG                long
563 +#endif
564 +#define NUL                    '\0'
565 +#define WIDE_INT               long
566 +#define WIDEST_INT             AP_LONGEST_LONG
567 +
568 +typedef WIDE_INT wide_int;
569 +typedef unsigned WIDE_INT u_wide_int;
570 +typedef WIDEST_INT widest_int;
571 +#ifdef __TANDEM
572 +/* Although Tandem supports "long long" there is no unsigned variant. */
573 +typedef unsigned long       u_widest_int;
574 +#else
575 +typedef unsigned WIDEST_INT u_widest_int;
576 +#endif
577 +typedef int bool_int;
578 +
579 +#define S_NULL                 "(null)"
580 +#define S_NULL_LEN             6
581 +
582 +#define FLOAT_DIGITS           6
583 +#define EXPONENT_LENGTH                10
584 +
585 +/*
586 + * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
587 + *
588 + * XXX: this is a magic number; do not decrease it
589 + */
590 +#define NUM_BUF_SIZE           512
591 +
592 +/*
593 + * cvt.c - IEEE floating point formatting routines for FreeBSD
594 + * from GNU libc-4.6.27.  Modified to be thread safe.
595 + */
596 +
597 +/*
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
602 + */
603 +
604 +#define        NDIG    80
605 +
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)
608 +{
609 +    register int r2;
610 +    double fi, fj;
611 +    register char *p, *p1;
612 +    
613 +    if (ndigits >= NDIG - 1)
614 +       ndigits = NDIG - 2;
615 +    r2 = 0;
616 +    *sign = 0;
617 +    p = &buf[0];
618 +    if (arg < 0) {
619 +       *sign = 1;
620 +       arg = -arg;
621 +    }
622 +    arg = modf(arg, &fi);
623 +    p1 = &buf[NDIG];
624 +    /*
625 +     * Do integer part
626 +     */
627 +    if (fi != 0) {
628 +       p1 = &buf[NDIG];
629 +       while (p1 > &buf[0] && fi != 0) {
630 +           fj = modf(fi / 10, &fi);
631 +           *--p1 = (int) ((fj + .03) * 10) + '0';
632 +           r2++;
633 +       }
634 +       while (p1 < &buf[NDIG])
635 +           *p++ = *p1++;
636 +    }
637 +    else if (arg > 0) {
638 +       while ((fj = arg * 10) < 1) {
639 +           arg = fj;
640 +           r2--;
641 +       }
642 +    }
643 +    p1 = &buf[ndigits];
644 +    if (eflag == 0)
645 +       p1 += r2;
646 +    *decpt = r2;
647 +    if (p1 < &buf[0]) {
648 +       buf[0] = '\0';
649 +       return (buf);
650 +    }
651 +    while (p <= p1 && p < &buf[NDIG]) {
652 +       arg *= 10;
653 +       arg = modf(arg, &fj);
654 +       *p++ = (int) fj + '0';
655 +    }
656 +    if (p1 >= &buf[NDIG]) {
657 +       buf[NDIG - 1] = '\0';
658 +       return (buf);
659 +    }
660 +    p = p1;
661 +    *p1 += 5;
662 +    while (*p1 > '9') {
663 +       *p1 = '0';
664 +       if (p1 > buf)
665 +           ++ * --p1;
666 +       else {
667 +           *p1 = '1';
668 +           (*decpt)++;
669 +           if (eflag == 0) {
670 +               if (p > buf)
671 +                   *p = '0';
672 +               p++;
673 +           }
674 +       }
675 +    }
676 +    *p = '\0';
677 +    return (buf);
678 +}
679 +
680 +static char *ap_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
681 +{
682 +    return (ap_cvt(arg, ndigits, decpt, sign, 1, buf));
683 +}
684 +
685 +static char *ap_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
686 +{
687 +    return (ap_cvt(arg, ndigits, decpt, sign, 0, buf));
688 +}
689 +
690 +/*
691 + * ap_gcvt  - Floating output conversion to
692 + * minimal length string
693 + */
694 +
695 +static char *ap_gcvt(double number, int ndigit, char *buf, boolean_e altform)
696 +{
697 +    int sign, decpt;
698 +    register char *p1, *p2;
699 +    register int i;
700 +    char buf1[NDIG];
701 +
702 +    p1 = ap_ecvt(number, ndigit, &decpt, &sign, buf1);
703 +    p2 = buf;
704 +    if (sign)
705 +       *p2++ = '-';
706 +    for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
707 +       ndigit--;
708 +    if ((decpt >= 0 && decpt - ndigit > 4)
709 +       || (decpt < 0 && decpt < -3)) {         /* use E-style */
710 +       decpt--;
711 +       *p2++ = *p1++;
712 +       *p2++ = '.';
713 +       for (i = 1; i < ndigit; i++)
714 +           *p2++ = *p1++;
715 +       *p2++ = 'e';
716 +       if (decpt < 0) {
717 +           decpt = -decpt;
718 +           *p2++ = '-';
719 +       }
720 +       else
721 +           *p2++ = '+';
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';
727 +    }
728 +    else {
729 +       if (decpt <= 0) {
730 +           if (*p1 != '0')
731 +               *p2++ = '.';
732 +           while (decpt < 0) {
733 +               decpt++;
734 +               *p2++ = '0';
735 +           }
736 +       }
737 +       for (i = 1; i <= ndigit; i++) {
738 +           *p2++ = *p1++;
739 +           if (i == decpt)
740 +               *p2++ = '.';
741 +       }
742 +       if (ndigit < decpt) {
743 +           while (ndigit++ < decpt)
744 +               *p2++ = '0';
745 +           *p2++ = '.';
746 +       }
747 +    }
748 +    if (p2[-1] == '.' && !altform)
749 +       p2--;
750 +    *p2 = '\0';
751 +    return (buf);
752 +}
753 +
754 +/*
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.
761 + *
762 + * NOTE: Evaluation of the c argument should not have any side-effects
763 + */
764 +#define INS_CHAR(c, sp, bep, cc)                               \
765 +           {                                                   \
766 +               if (sp >= bep) {                                \
767 +                   vbuff->curpos = sp;                         \
768 +                   if (flush_func(vbuff))                      \
769 +                       return -1;                              \
770 +                   sp = vbuff->curpos;                         \
771 +                   bep = vbuff->endpos;                        \
772 +               }                                               \
773 +               *sp++ = (c);                                    \
774 +               cc++;                                           \
775 +           }
776 +
777 +#define NUM( c )                       ( c - '0' )
778 +
779 +#define STR_TO_DEC( str, num )         \
780 +    num = NUM( *str++ ) ;              \
781 +    while ( ap_isdigit( *str ) )               \
782 +    {                                  \
783 +       num *= 10 ;                     \
784 +       num += NUM( *str++ ) ;          \
785 +    }
786 +
787 +/*
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
791 + * to be printed.
792 + */
793 +#define FIX_PRECISION( adjust, precision, s, s_len )   \
794 +    if ( adjust )                                      \
795 +       while ( s_len < precision )                     \
796 +       {                                               \
797 +           *--s = '0' ;                                \
798 +           s_len++ ;                                   \
799 +       }
800 +
801 +/*
802 + * Macro that does padding. The padding is done by printing
803 + * the character ch.
804 + */
805 +#define PAD( width, len, ch )  do              \
806 +       {                                       \
807 +           INS_CHAR( ch, sp, bep, cc ) ;       \
808 +           width-- ;                           \
809 +       }                                       \
810 +       while ( width > len )
811 +
812 +/*
813 + * Prefix the character ch to the string str
814 + * Increase length
815 + * Set the has_prefix flag
816 + */
817 +#define PREFIX( str, length, ch )       *--str = ch ; length++ ; has_prefix = YES
818 +
819 +
820 +/*
821 + * Convert num to its decimal format.
822 + * Return value:
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)
827 + *
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 ])
831 + *
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.
835 + */
836 +static char *conv_10(register wide_int num, register bool_int is_unsigned,
837 +                    register bool_int *is_negative, char *buf_end,
838 +                    register int *len)
839 +{
840 +    register char *p = buf_end;
841 +    register u_wide_int magnitude;
842 +
843 +    if (is_unsigned) {
844 +       magnitude = (u_wide_int) num;
845 +       *is_negative = FALSE;
846 +    }
847 +    else {
848 +       *is_negative = (num < 0);
849 +
850 +       /*
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
857 +        *      d. add 1
858 +        */
859 +       if (*is_negative) {
860 +           wide_int t = num + 1;
861 +
862 +           magnitude = ((u_wide_int) -t) + 1;
863 +       }
864 +       else
865 +           magnitude = (u_wide_int) num;
866 +    }
867 +
868 +    /*
869 +     * We use a do-while loop so that we write at least 1 digit 
870 +     */
871 +    do {
872 +       register u_wide_int new_magnitude = magnitude / 10;
873 +
874 +       *--p = (char) (magnitude - new_magnitude * 10 + '0');
875 +       magnitude = new_magnitude;
876 +    }
877 +    while (magnitude);
878 +
879 +    *len = buf_end - p;
880 +    return (p);
881 +}
882 +
883 +static char *conv_10_quad(widest_int num, register bool_int is_unsigned,
884 +                    register bool_int *is_negative, char *buf_end,
885 +                    register int *len)
886 +{
887 +    register char *p = buf_end;
888 +    u_widest_int magnitude;
889 +
890 +    /*
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.
894 +     */
895 +    if ((num <= ULONG_MAX && is_unsigned) || (num <= LONG_MAX && !is_unsigned))
896 +       return(conv_10( (wide_int)num, is_unsigned, is_negative,
897 +              buf_end, len));
898 +
899 +    if (is_unsigned) {
900 +       magnitude = (u_widest_int) num;
901 +       *is_negative = FALSE;
902 +    }
903 +    else {
904 +       *is_negative = (num < 0);
905 +
906 +       /*
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
913 +        *      d. add 1
914 +        */
915 +       if (*is_negative) {
916 +           widest_int t = num + 1;
917 +
918 +           magnitude = ((u_widest_int) -t) + 1;
919 +       }
920 +       else
921 +           magnitude = (u_widest_int) num;
922 +    }
923 +
924 +    /*
925 +     * We use a do-while loop so that we write at least 1 digit 
926 +     */
927 +    do {
928 +       u_widest_int new_magnitude = magnitude / 10;
929 +
930 +       *--p = (char) (magnitude - new_magnitude * 10 + '0');
931 +       magnitude = new_magnitude;
932 +    }
933 +    while (magnitude);
934 +
935 +    *len = buf_end - p;
936 +    return (p);
937 +}
938 +
939 +
940 +
941 +static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len)
942 +{
943 +    unsigned addr = ntohl(ia->s_addr);
944 +    char *p = buf_end;
945 +    bool_int is_negative;
946 +    int sub_len;
947 +
948 +    p = conv_10((addr & 0x000000FF)      , TRUE, &is_negative, p, &sub_len);
949 +    *--p = '.';
950 +    p = conv_10((addr & 0x0000FF00) >>  8, TRUE, &is_negative, p, &sub_len);
951 +    *--p = '.';
952 +    p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len);
953 +    *--p = '.';
954 +    p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len);
955 +
956 +    *len = buf_end - p;
957 +    return (p);
958 +}
959 +
960 +
961 +
962 +static char *conv_sockaddr_in(struct sockaddr_in *si, char *buf_end, int *len)
963 +{
964 +    char *p = buf_end;
965 +    bool_int is_negative;
966 +    int sub_len;
967 +
968 +    p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len);
969 +    *--p = ':';
970 +    p = conv_in_addr(&si->sin_addr, p, &sub_len);
971 +
972 +    *len = buf_end - p;
973 +    return (p);
974 +}
975 +
976 +
977 +
978 +#ifdef INET6
979 +static char *conv_sockaddr(struct sockaddr *sa, char *buf_end, int *len)
980 +{
981 +    char *p = buf_end;
982 +    char hostnamebuf[MAXHOSTNAMELEN];
983 +    char portnamebuf[MAXHOSTNAMELEN];
984 +    char *q;
985 +    int salen;
986 +
987 +#ifndef SIN6_LEN
988 +    salen = SA_LEN(sa);
989 +#else
990 +    salen = sa->sa_len;
991 +#endif
992 +    if (getnameinfo(sa, salen, hostnamebuf, sizeof(hostnamebuf),
993 +           portnamebuf, sizeof(portnamebuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
994 +       strcpy(hostnamebuf, "???");
995 +       strcpy(portnamebuf, "???");
996 +    }
997 +    if (strcmp(portnamebuf,"0") == 0)
998 +       strcpy(portnamebuf, "*");
999 +    q = portnamebuf + strlen(portnamebuf);
1000 +    while (portnamebuf < q)
1001 +       *--p = *--q;
1002 +    *--p = ':';
1003 +    q = hostnamebuf + strlen(hostnamebuf);
1004 +    while (hostnamebuf < q)
1005 +       *--p = *--q;
1006 +
1007 +    *len = buf_end - p;
1008 +    return (p);
1009 +}
1010 +#endif /*INET6*/
1011 +
1012 +
1013 +
1014 +/*
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
1018 + * in buf).
1019 + */
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)
1023 +{
1024 +    register char *s = buf;
1025 +    register char *p;
1026 +    int decimal_point;
1027 +    char buf1[NDIG];
1028 +
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);
1033 +
1034 +    /*
1035 +     * Check for Infinity and NaN
1036 +     */
1037 +    if (ap_isalpha(*p)) {
1038 +       *len = strlen(strcpy(buf, p));
1039 +       *is_negative = FALSE;
1040 +       return (buf);
1041 +    }
1042 +
1043 +    if (format == 'f') {
1044 +       if (decimal_point <= 0) {
1045 +           *s++ = '0';
1046 +           if (precision > 0) {
1047 +               *s++ = '.';
1048 +               while (decimal_point++ < 0)
1049 +                   *s++ = '0';
1050 +           }
1051 +           else if (add_dp)
1052 +               *s++ = '.';
1053 +       }
1054 +       else {
1055 +           while (decimal_point-- > 0)
1056 +               *s++ = *p++;
1057 +           if (precision > 0 || add_dp)
1058 +               *s++ = '.';
1059 +       }
1060 +    }
1061 +    else {
1062 +       *s++ = *p++;
1063 +       if (precision > 0 || add_dp)
1064 +           *s++ = '.';
1065 +    }
1066 +
1067 +    /*
1068 +     * copy the rest of p, the NUL is NOT copied
1069 +     */
1070 +    while (*p)
1071 +       *s++ = *p++;
1072 +
1073 +    if (format != 'f') {
1074 +       char temp[EXPONENT_LENGTH];     /* for exponent conversion */
1075 +       int t_len;
1076 +       bool_int exponent_is_negative;
1077 +
1078 +       *s++ = format;          /* either e or E */
1079 +       decimal_point--;
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 ? '-' : '+';
1084 +
1085 +           /*
1086 +            * Make sure the exponent has at least 2 digits
1087 +            */
1088 +           if (t_len == 1)
1089 +               *s++ = '0';
1090 +           while (t_len--)
1091 +               *s++ = *p++;
1092 +       }
1093 +       else {
1094 +           *s++ = '+';
1095 +           *s++ = '0';
1096 +           *s++ = '0';
1097 +       }
1098 +    }
1099 +
1100 +    *len = s - buf;
1101 +    return (buf);
1102 +}
1103 +
1104 +
1105 +/*
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
1108 + * Return value:
1109 + *      a pointer to a string containing the number
1110 + *
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 ])
1114 + *
1115 + * As with conv_10, we have a faster version which is used when
1116 + * the number isn't quad size.
1117 + */
1118 +static char *conv_p2(register u_wide_int num, register int nbits,
1119 +                    char format, char *buf_end, register int *len)
1120 +{
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;
1126 +
1127 +    do {
1128 +       *--p = digits[num & mask];
1129 +       num >>= nbits;
1130 +    }
1131 +    while (num);
1132 +
1133 +    *len = buf_end - p;
1134 +    return (p);
1135 +}
1136 +
1137 +static char *conv_p2_quad(u_widest_int num, register int nbits,
1138 +                    char format, char *buf_end, register int *len)
1139 +{
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;
1145 +
1146 +    if (num <= ULONG_MAX)
1147 +       return(conv_p2( (u_wide_int)num, nbits, format, buf_end, len));
1148 +
1149 +    do {
1150 +       *--p = digits[num & mask];
1151 +       num >>= nbits;
1152 +    }
1153 +    while (num);
1154 +
1155 +    *len = buf_end - p;
1156 +    return (p);
1157 +}
1158 +
1159 +
1160 +/*
1161 + * Do format conversion placing the output in buffer
1162 + */
1163 +API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),
1164 +    ap_vformatter_buff *vbuff, const char *fmt, va_list ap)
1165 +{
1166 +    register char *sp;
1167 +    register char *bep;
1168 +    register int cc = 0;
1169 +    register int i;
1170 +
1171 +    register char *s = NULL;
1172 +    char *q;
1173 +    int s_len;
1174 +
1175 +    register int min_width = 0;
1176 +    int precision = 0;
1177 +    enum {
1178 +       LEFT, RIGHT
1179 +    } adjust;
1180 +    char pad_char;
1181 +    char prefix_char;
1182 +
1183 +    double fp_num;
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;
1188 +
1189 +    char num_buf[NUM_BUF_SIZE];
1190 +    char char_buf[2];          /* for printing %% and %<unknown> */
1191 +
1192 +    enum var_type_enum {
1193 +       IS_QUAD, IS_LONG, IS_SHORT, IS_INT
1194 +    };
1195 +    enum var_type_enum var_type = IS_INT;
1196 +
1197 +    /*
1198 +     * Flag variables
1199 +     */
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;
1206 +
1207 +    sp = vbuff->curpos;
1208 +    bep = vbuff->endpos;
1209 +
1210 +    while (*fmt) {
1211 +       if (*fmt != '%') {
1212 +           INS_CHAR(*fmt, sp, bep, cc);
1213 +       }
1214 +       else {
1215 +           /*
1216 +            * Default variable settings
1217 +            */
1218 +           adjust = RIGHT;
1219 +           alternate_form = print_sign = print_blank = NO;
1220 +           pad_char = ' ';
1221 +           prefix_char = NUL;
1222 +
1223 +           fmt++;
1224 +
1225 +           /*
1226 +            * Try to avoid checking for flags, width or precision
1227 +            */
1228 +           if (!ap_islower(*fmt)) {
1229 +               /*
1230 +                * Recognize flags: -, #, BLANK, +
1231 +                */
1232 +               for (;; fmt++) {
1233 +                   if (*fmt == '-')
1234 +                       adjust = LEFT;
1235 +                   else if (*fmt == '+')
1236 +                       print_sign = YES;
1237 +                   else if (*fmt == '#')
1238 +                       alternate_form = YES;
1239 +                   else if (*fmt == ' ')
1240 +                       print_blank = YES;
1241 +                   else if (*fmt == '0')
1242 +                       pad_char = '0';
1243 +                   else
1244 +                       break;
1245 +               }
1246 +
1247 +               /*
1248 +                * Check if a width was specified
1249 +                */
1250 +               if (ap_isdigit(*fmt)) {
1251 +                   STR_TO_DEC(fmt, min_width);
1252 +                   adjust_width = YES;
1253 +               }
1254 +               else if (*fmt == '*') {
1255 +                   min_width = va_arg(ap, int);
1256 +                   fmt++;
1257 +                   adjust_width = YES;
1258 +                   if (min_width < 0) {
1259 +                       adjust = LEFT;
1260 +                       min_width = -min_width;
1261 +                   }
1262 +               }
1263 +               else
1264 +                   adjust_width = NO;
1265 +
1266 +               /*
1267 +                * Check if a precision was specified
1268 +                *
1269 +                * XXX: an unreasonable amount of precision may be specified
1270 +                * resulting in overflow of num_buf. Currently we
1271 +                * ignore this possibility.
1272 +                */
1273 +               if (*fmt == '.') {
1274 +                   adjust_precision = YES;
1275 +                   fmt++;
1276 +                   if (ap_isdigit(*fmt)) {
1277 +                       STR_TO_DEC(fmt, precision);
1278 +                   }
1279 +                   else if (*fmt == '*') {
1280 +                       precision = va_arg(ap, int);
1281 +                       fmt++;
1282 +                       if (precision < 0)
1283 +                           precision = 0;
1284 +                   }
1285 +                   else
1286 +                       precision = 0;
1287 +               }
1288 +               else
1289 +                   adjust_precision = NO;
1290 +           }
1291 +           else
1292 +               adjust_precision = adjust_width = NO;
1293 +
1294 +           /*
1295 +            * Modifier check
1296 +            */
1297 +           if (*fmt == 'q') {
1298 +               var_type = IS_QUAD;
1299 +               fmt++;
1300 +           }
1301 +           else if (*fmt == 'l') {
1302 +               var_type = IS_LONG;
1303 +               fmt++;
1304 +           }
1305 +           else if (*fmt == 'h') {
1306 +               var_type = IS_SHORT;
1307 +               fmt++;
1308 +           }
1309 +           else {
1310 +               var_type = IS_INT;
1311 +           }
1312 +
1313 +           /*
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.
1320 +            *
1321 +            * NOTE: pad_char may be set to '0' because of the 0 flag.
1322 +            *   It is reset to ' ' by non-numeric formats
1323 +            */
1324 +           switch (*fmt) {
1325 +           case 'u':
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);
1330 +               }
1331 +               else {
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);
1336 +                   else
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);
1340 +               }
1341 +               FIX_PRECISION(adjust_precision, precision, s, s_len);
1342 +               break;
1343 +
1344 +           case 'd':
1345 +           case 'i':
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);
1350 +               }
1351 +               else {
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);
1356 +                   else
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);
1360 +               }
1361 +               FIX_PRECISION(adjust_precision, precision, s, s_len);
1362 +
1363 +               if (is_negative)
1364 +                   prefix_char = '-';
1365 +               else if (print_sign)
1366 +                   prefix_char = '+';
1367 +               else if (print_blank)
1368 +                   prefix_char = ' ';
1369 +               break;
1370 +
1371 +
1372 +           case 'o':
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);
1377 +               }
1378 +               else {
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);
1383 +                   else
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);
1387 +               }
1388 +               FIX_PRECISION(adjust_precision, precision, s, s_len);
1389 +               if (alternate_form && *s != '0') {
1390 +                   *--s = '0';
1391 +                   s_len++;
1392 +               }
1393 +               break;
1394 +
1395 +
1396 +           case 'x':
1397 +           case 'X':
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);
1402 +               }
1403 +               else {
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);
1408 +                   else
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);
1412 +               }
1413 +               FIX_PRECISION(adjust_precision, precision, s, s_len);
1414 +               if (alternate_form && i_num != 0) {
1415 +                   *--s = *fmt;        /* 'x' or 'X' */
1416 +                   *--s = '0';
1417 +                   s_len += 2;
1418 +               }
1419 +               break;
1420 +
1421 +
1422 +           case 's':
1423 +               s = va_arg(ap, char *);
1424 +               if (s != NULL) {
1425 +                   s_len = strlen(s);
1426 +                   if (adjust_precision && precision < s_len)
1427 +                       s_len = precision;
1428 +               }
1429 +               else {
1430 +                   s = S_NULL;
1431 +                   s_len = S_NULL_LEN;
1432 +               }
1433 +               pad_char = ' ';
1434 +               break;
1435 +
1436 +
1437 +           case 'f':
1438 +           case 'e':
1439 +           case 'E':
1440 +               fp_num = va_arg(ap, double);
1441 +               /*
1442 +                * * We use &num_buf[ 1 ], so that we have room for the sign
1443 +                */
1444 +#ifdef HAVE_ISNAN
1445 +               if (isnan(fp_num)) {
1446 +                   s = "nan";
1447 +                   s_len = 3;
1448 +               }
1449 +               else
1450 +#endif
1451 +#ifdef HAVE_ISINF
1452 +               if (isinf(fp_num)) {
1453 +                   s = "inf";
1454 +                   s_len = 3;
1455 +               }
1456 +               else
1457 +#endif
1458 +               {
1459 +                   s = conv_fp(*fmt, fp_num, alternate_form,
1460 +                           (adjust_precision == NO) ? FLOAT_DIGITS : precision,
1461 +                               &is_negative, &num_buf[1], &s_len);
1462 +                   if (is_negative)
1463 +                       prefix_char = '-';
1464 +                   else if (print_sign)
1465 +                       prefix_char = '+';
1466 +                   else if (print_blank)
1467 +                       prefix_char = ' ';
1468 +               }
1469 +               break;
1470 +
1471 +
1472 +           case 'g':
1473 +           case 'G':
1474 +               if (adjust_precision == NO)
1475 +                   precision = FLOAT_DIGITS;
1476 +               else if (precision == 0)
1477 +                   precision = 1;
1478 +               /*
1479 +                * * We use &num_buf[ 1 ], so that we have room for the sign
1480 +                */
1481 +               s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1],
1482 +                           alternate_form);
1483 +               if (*s == '-')
1484 +                   prefix_char = *s++;
1485 +               else if (print_sign)
1486 +                   prefix_char = '+';
1487 +               else if (print_blank)
1488 +                   prefix_char = ' ';
1489 +
1490 +               s_len = strlen(s);
1491 +
1492 +               if (alternate_form && (q = strchr(s, '.')) == NULL) {
1493 +                   s[s_len++] = '.';
1494 +                   s[s_len] = '\0'; /* delimit for following strchr() */
1495 +               }
1496 +               if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)
1497 +                   *q = 'E';
1498 +               break;
1499 +
1500 +
1501 +           case 'c':
1502 +               char_buf[0] = (char) (va_arg(ap, int));
1503 +               s = &char_buf[0];
1504 +               s_len = 1;
1505 +               pad_char = ' ';
1506 +               break;
1507 +
1508 +
1509 +           case '%':
1510 +               char_buf[0] = '%';
1511 +               s = &char_buf[0];
1512 +               s_len = 1;
1513 +               pad_char = ' ';
1514 +               break;
1515 +
1516 +
1517 +           case 'n':
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;
1524 +               else
1525 +                   *(va_arg(ap, int *)) = cc;
1526 +               break;
1527 +
1528 +               /*
1529 +                * This is where we extend the printf format, with a second
1530 +                * type specifier
1531 +                */
1532 +           case 'p':
1533 +               switch(*++fmt) {
1534 +                   /*
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".
1539 +                    */
1540 +               case '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);
1546 +                   }
1547 +#else
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);
1552 +                   }
1553 +#endif
1554 +                   else {
1555 +                       s = "%p";
1556 +                       s_len = 2;
1557 +                       prefix_char = NUL;
1558 +                   }
1559 +                   pad_char = ' ';
1560 +                   break;
1561 +
1562 +                   /* print a struct sockaddr_in as a.b.c.d:port */
1563 +               case 'I':
1564 +                   {
1565 +#ifndef INET6
1566 +                       struct sockaddr_in *si;
1567 +
1568 +                       si = va_arg(ap, struct sockaddr_in *);
1569 +                       if (si != NULL) {
1570 +                           s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);
1571 +                           if (adjust_precision && precision < s_len)
1572 +                               s_len = precision;
1573 +                       }
1574 +#else
1575 +                       struct sockaddr *sa;
1576 +
1577 +                       sa = va_arg(ap, struct sockaddr *);
1578 +                       if (sa != NULL) {
1579 +                           s = conv_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len);
1580 +                           if (adjust_precision && precision < s_len)
1581 +                               s_len = precision;
1582 +                       }
1583 +#endif
1584 +                       else {
1585 +                           s = S_NULL;
1586 +                           s_len = S_NULL_LEN;
1587 +                       }
1588 +                       pad_char = ' ';
1589 +                   }
1590 +                   break;
1591 +
1592 +                   /* print a struct in_addr as a.b.c.d */
1593 +               case 'A':
1594 +                   {
1595 +                       struct in_addr *ia;
1596 +
1597 +                       ia = va_arg(ap, struct in_addr *);
1598 +                       if (ia != NULL) {
1599 +                           s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);
1600 +                           if (adjust_precision && precision < s_len)
1601 +                               s_len = precision;
1602 +                       }
1603 +                       else {
1604 +                           s = S_NULL;
1605 +                           s_len = S_NULL_LEN;
1606 +                       }
1607 +                       pad_char = ' ';
1608 +                   }
1609 +                   break;
1610 +
1611 +               case NUL:
1612 +                   /* if %p ends the string, oh well ignore it */
1613 +                   continue;
1614 +
1615 +               default:
1616 +                   s = "bogus %p";
1617 +                   s_len = 8;
1618 +                   prefix_char = NUL;
1619 +                   break;
1620 +               }
1621 +               break;
1622 +
1623 +           case NUL:
1624 +               /*
1625 +                * The last character of the format string was %.
1626 +                * We ignore it.
1627 +                */
1628 +               continue;
1629 +
1630 +
1631 +               /*
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.
1640 +                */
1641 +           default:
1642 +               char_buf[0] = '%';
1643 +               char_buf[1] = *fmt;
1644 +               s = char_buf;
1645 +               s_len = 2;
1646 +               pad_char = ' ';
1647 +               break;
1648 +           }
1649 +
1650 +           if (prefix_char != NUL && s != S_NULL && s != char_buf) {
1651 +               *--s = prefix_char;
1652 +               s_len++;
1653 +           }
1654 +
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);
1658 +                   s++;
1659 +                   s_len--;
1660 +                   min_width--;
1661 +               }
1662 +               PAD(min_width, s_len, pad_char);
1663 +           }
1664 +
1665 +           /*
1666 +            * Print the string s. 
1667 +            */
1668 +           for (i = s_len; i != 0; i--) {
1669 +               INS_CHAR(*s, sp, bep, cc);
1670 +               s++;
1671 +           }
1672 +
1673 +           if (adjust_width && adjust == LEFT && min_width > s_len)
1674 +               PAD(min_width, s_len, pad_char);
1675 +       }
1676 +       fmt++;
1677 +    }
1678 +    vbuff->curpos = sp;
1679 +    return cc;
1680 +}
1681 +
1682 +
1683 +static int snprintf_flush(ap_vformatter_buff *vbuff)
1684 +{
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.
1687 +     */
1688 +    return -1;
1689 +}
1690 +
1691 +
1692 +API_EXPORT(int) ap_snprintf(char *buf, size_t len, const char *format,...)
1693 +{
1694 +    int cc;
1695 +    va_list ap;
1696 +    ap_vformatter_buff vbuff;
1697 +
1698 +    if (len == 0)
1699 +       return 0;
1700 +
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);
1706 +    va_end(ap);
1707 +    *vbuff.curpos = '\0';
1708 +    return (cc == -1) ? len : cc;
1709 +}
1710 +
1711 +
1712 +API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format,
1713 +                            va_list ap)
1714 +{
1715 +    int cc;
1716 +    ap_vformatter_buff vbuff;
1717 +
1718 +    if (len == 0)
1719 +       return 0;
1720 +
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;
1727 +}
1728 diff -Nru apache_1.3.20/src/include/ap.h apache_1.3.20.new/src/include/ap.h
1729 --- apache_1.3.20/src/include/ap.h      Mon Jan 15 18:04:22 2001
1730 +++ apache_1.3.20.new/src/include/ap.h  Mon May 21 10:54:52 2001
1731 @@ -91,7 +91,8 @@
1732   * with some extensions.  The extensions are:
1733   *
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
1739   *
1740   * The %p hacks are to force gcc's printf warning code to skip
1741 diff -Nru apache_1.3.20/src/include/ap_config.h apache_1.3.20.new/src/include/ap_config.h
1742 --- apache_1.3.20/src/include/ap_config.h       Fri Apr  6 05:13:11 2001
1743 +++ apache_1.3.20.new/src/include/ap_config.h   Mon May 21 10:54:52 2001
1744 @@ -395,6 +395,10 @@
1745  #endif
1746  #ifndef S_IWOTH
1747  #define S_IWOTH 000002
1748 +#ifndef rlim_t
1749 +typedef int rlim_t;
1750 +#endif
1751 +typedef u_long n_long;
1752  #endif
1753  
1754  #define STDIN_FILENO  0
1755 @@ -1413,6 +1417,70 @@
1756  
1757  #ifndef ap_wait_t
1758  #define ap_wait_t int
1759 +#endif
1760 +
1761 +#ifndef INET6
1762 +#define sockaddr_storage       sockaddr
1763 +#define ss_family              sa_family
1764 +#define ss_len                 sa_len
1765 +#else
1766 +#include "sockaddr_storage.h"  /* sshida@st.rim.or.jp */
1767 +#endif
1768 +
1769 +#ifndef INET6_ADDRSTRLEN
1770 +#define INET6_ADDRSTRLEN       46
1771 +#endif
1772 +#ifndef INET_ADDRSTRLEN
1773 +#define INET_ADDRSTRLEN                16
1774 +#endif
1775 +#ifndef NI_MAXHOST
1776 +#define NI_MAXHOST             1025
1777 +#endif
1778 +#ifndef NI_MAXSERV
1779 +#define        NI_MAXSERV              32
1780 +#endif
1781 +
1782 +#if defined(NEED_GETADDRINFO) || defined(NEED_GETNAMEINFO)
1783 +/*
1784 + * minimal definitions for fake getaddrinfo()/getnameinfo().
1785 + */
1786 +#ifndef EAI_NODATA
1787 +#define EAI_NODATA     1
1788 +#define EAI_MEMORY     2
1789 +#endif
1790 +
1791 +#ifndef AI_PASSIVE
1792 +#define AI_PASSIVE     1
1793 +#define AI_CANONNAME   2
1794 +#define AI_NUMERICHOST 4
1795 +#define NI_NUMERICHOST 8
1796 +#define NI_NAMEREQD    16
1797 +#define NI_NUMERICSERV 32
1798 +#endif
1799 +#endif
1800 +
1801 +#ifdef NEED_GETADDRINFO
1802 +#ifdef NEED_ADDRINFO
1803 +struct addrinfo {
1804 +       int     ai_flags;       /* AI_PASSIVE, AI_CANONNAME */
1805 +       int     ai_family;      /* PF_xxx */
1806 +       int     ai_socktype;    /* SOCK_xxx */
1807 +       int     ai_protocol;    /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
1808 +       size_t  ai_addrlen;     /* length of ai_addr */
1809 +       char    *ai_canonname;  /* canonical name for hostname */
1810 +       struct sockaddr *ai_addr;       /* binary address */
1811 +       struct addrinfo *ai_next;       /* next structure in linked list */
1812 +};
1813 +#endif
1814 +extern char *gai_strerror(int ecode);
1815 +extern void freeaddrinfo(struct addrinfo *ai);
1816 +extern int getaddrinfo(const char *hostname, const char *servname,
1817 +       const struct addrinfo *hints, struct addrinfo **res);
1818 +#endif
1819 +#ifdef NEED_GETNAMEINFO
1820 +extern int getnameinfo(const struct sockaddr *sa, size_t salen,
1821 +       char *host, size_t hostlen, char *serv, size_t servlen,
1822 +       int flag);
1823  #endif
1824  
1825  #ifdef __cplusplus
1826 diff -Nru apache_1.3.20/src/include/http_conf_globals.h apache_1.3.20.new/src/include/http_conf_globals.h
1827 --- apache_1.3.20/src/include/http_conf_globals.h       Mon May 21 11:02:03 2001
1828 +++ apache_1.3.20.new/src/include/http_conf_globals.h   Mon May 21 10:54:52 2001
1829 @@ -82,7 +82,8 @@
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 -Nru apache_1.3.20/src/include/http_vhost.h apache_1.3.20.new/src/include/http_vhost.h
1840 --- apache_1.3.20/src/include/http_vhost.h      Mon Jan 15 18:04:37 2001
1841 +++ apache_1.3.20.new/src/include/http_vhost.h  Mon May 21 10:54:52 2001
1842 @@ -73,7 +73,7 @@
1843  const char *ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s);
1844  
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);
1848  
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 -Nru apache_1.3.20/src/include/httpd.h apache_1.3.20.new/src/include/httpd.h
1852 --- apache_1.3.20/src/include/httpd.h   Mon May 21 11:02:04 2001
1853 +++ apache_1.3.20.new/src/include/httpd.h       Mon May 21 10:54:52 2001
1854 @@ -908,8 +908,8 @@
1855  
1856      /* Who is the client? */
1857  
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,
1865 @@ -951,8 +951,8 @@
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> */
1874  };
1875  
1876 @@ -1020,7 +1020,7 @@
1877  /* These are more like real hosts than virtual hosts */
1878  struct listen_rec {
1879      listen_rec *next;
1880 -    struct sockaddr_in local_addr;     /* local IP address and port */
1881 +    struct sockaddr_storage local_addr;        /* local IP address and port */
1882      int fd;
1883      int used;                  /* Only used during restart */        
1884  /* more stuff here, like which protocol is bound to the port */
1885 @@ -1180,7 +1180,7 @@
1886  #endif /*#ifdef CHARSET_EBCDIC*/
1887  
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);
1891  
1892  extern API_VAR_EXPORT time_t ap_restart_time;
1893  
1894 diff -Nru apache_1.3.20/src/include/sa_len.h apache_1.3.20.new/src/include/sa_len.h
1895 --- apache_1.3.20/src/include/sa_len.h  Thu Jan  1 01:00:00 1970
1896 +++ apache_1.3.20.new/src/include/sa_len.h      Mon May 21 10:54:52 2001
1897 @@ -0,0 +1,41 @@
1898 +/* sa_len.h : tiny version of SA_LEN (written by <yoshfuji@ecei.tohoku.ac.jp>) */
1899
1900 +#include <sys/types.h>
1901 +#include <sys/socket.h>
1902 +#include <netinet/in.h>
1903 +#include <sys/un.h>
1904 +
1905 +#ifndef HAVE_SOCKADDR_LEN
1906 +#ifndef SA_LEN
1907 +#define SA_LEN(s_)     ap_sa_len((s_)->sa_family)
1908 +
1909 +static NET_SIZE_T ap_sa_len (sa_family_t af)
1910 +{
1911 +    switch (af){
1912 +#if defined(AF_INET)
1913 +    case AF_INET:
1914 +       return (sizeof(struct sockaddr_in));
1915 +#endif /* AF_INET */
1916 +#if defined(AF_INET6)
1917 +    case AF_INET6:
1918 +       return (sizeof(struct sockaddr_in6));
1919 +#endif
1920 +#ifdef AF_LOCAL
1921 +    case AF_LOCAL:
1922 +#endif /* AF_LOCAL */
1923 +#if defined(AF_UNIX) && (AF_UNIX != AF_LOCAL)
1924 +    case AF_UNIX:
1925 +#endif /* AF_UNIX */
1926 +#if defined(AF_FILE) && (AF_FILE != AF_LOCAL || AF_FILE != AF_UNIX)
1927 +    case AF_FILE:
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) */
1932 +    default:
1933 +       return 0;
1934 +    }
1935 +    return 0;
1936 +}
1937 +#endif /* SA_LEN */
1938 +#endif /* HAVE_SOCKADDR_LEN */
1939 diff -Nru apache_1.3.20/src/include/sockaddr_storage.h apache_1.3.20.new/src/include/sockaddr_storage.h
1940 --- apache_1.3.20/src/include/sockaddr_storage.h        Thu Jan  1 01:00:00 1970
1941 +++ apache_1.3.20.new/src/include/sockaddr_storage.h    Mon May 21 10:54:52 2001
1942 @@ -0,0 +1,53 @@
1943 +/*
1944 +struct sockaddr_storage
1945 +
1946 +   RFC2553 proposes struct sockaddr_storage.
1947 +   This is a placeholder for all sockaddr-variant structures. This is
1948 +   implemented like follows:
1949 +
1950 +   You should use this structure to hold any of sockaddr-variant
1951 +   structures.
1952 +*/
1953 +#ifdef NEED_SOCKADDR_STORAGE
1954 +
1955 +struct sockaddr_storage {
1956 +#ifdef HAVE_SOCKADDR_LEN
1957 +       u_char ss_len;
1958 +       u_char ss_family;
1959 +#else
1960 +       u_short ss_family;
1961 +#endif
1962 +       u_char __padding[128 - 2];
1963 +};
1964 +
1965 +/*
1966 +union sockunion
1967 +
1968 +   Alternatively, you may want to implement sockunion.h, with the
1969 +   following content:
1970 +
1971 +   NOTE: For better portability, struct sockaddr_storage should be used.
1972 +   union sockunion is okay, but is not really portable enough.
1973 +*/
1974 +union sockunion {
1975 +       struct sockinet {
1976 +#ifdef HAVE_SOCKADDR_LEN
1977 +               u_char si_len;
1978 +               u_char si_family;
1979 +#else
1980 +               u_short si_family;
1981 +#endif
1982 +               u_short si_port;
1983 +       } su_si;
1984 +       struct sockaddr_in  su_sin;
1985 +#ifdef INET6
1986 +       struct sockaddr_in6 su_sin6;
1987 +#endif
1988 +};
1989 +#ifdef HAVE_SOCKADDR_LEN
1990 +#define su_len         su_si.si_len
1991 +#endif
1992 +#define su_family      su_si.si_family
1993 +#define su_port                su_si.si_port
1994 +
1995 +#endif /* NEED_SOCKADDR_STORAGE */
1996 diff -Nru apache_1.3.20/src/main/getaddrinfo.c apache_1.3.20.new/src/main/getaddrinfo.c
1997 --- apache_1.3.20/src/main/getaddrinfo.c        Thu Jan  1 01:00:00 1970
1998 +++ apache_1.3.20.new/src/main/getaddrinfo.c    Mon May 21 10:54:52 2001
1999 @@ -0,0 +1,162 @@
2000 +/*
2001 + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
2002 + * All rights reserved.
2003 + * 
2004 + * Redistribution and use in source and binary forms, with or without
2005 + * modification, are permitted provided that the following conditions
2006 + * are met:
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.
2015 + * 
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
2026 + * SUCH DAMAGE.
2027 + */
2028 +/*
2029 + * fake library for ssh v6 enabler patch
2030 + *
2031 + * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror().
2032 + * These funtions are defined in rfc2133.
2033 + *
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.
2037 + * 
2038 + * In the case not using 'configure --enable-ipv6', this getaddrinfo.c
2039 + * will be used if you have broken getaddrinfo or no getaddrinfo.
2040 + */
2041 +
2042 +#if 0
2043 +#include <stdlib.h>
2044 +#include <sys/types.h>
2045 +#include <sys/socket.h>
2046 +#include <netinet/in.h>
2047 +#include <arpa/inet.h>
2048 +#include <netdb.h>
2049 +#include "gai.h"
2050 +#endif
2051 +
2052 +static struct addrinfo *
2053 +malloc_ai(port, addr, socktype, protocol)
2054 +int port;
2055 +u_long addr;
2056 +int socktype;
2057 +int protocol;
2058 +{
2059 +  struct addrinfo *ai;
2060 +
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 = 
2067 +#endif
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;
2074 +    return ai;
2075 +  } else {
2076 +    return NULL;
2077 +  }
2078 +}
2079 +
2080 +char *
2081 +gai_strerror(ecode)
2082 +int ecode;
2083 +{
2084 +  switch (ecode) {
2085 +  case EAI_NODATA:
2086 +    return "no address associated with hostname.";
2087 +  case EAI_MEMORY:
2088 +    return "memory allocation failure.";
2089 +  default:
2090 +    return "unknown error.";
2091 +  }
2092 +}    
2093 +
2094 +void
2095 +freeaddrinfo(ai)
2096 +struct addrinfo *ai;
2097 +{
2098 +  struct addrinfo *next;
2099 +  
2100 +  do {
2101 +    next = ai->ai_next;
2102 +    free(ai);
2103 +  } while (ai = next);
2104 +}
2105 +
2106 +int
2107 +getaddrinfo(hostname, servname, hints, res)
2108 +const char *hostname, *servname;
2109 +const struct addrinfo *hints;
2110 +struct addrinfo **res;
2111 +{
2112 +  struct addrinfo *cur, *prev = NULL;
2113 +  struct hostent *hp;
2114 +  int i, port;
2115 +  
2116 +  if (servname)
2117 +    port = htons(atoi(servname));
2118 +  else
2119 +    port = 0;
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))
2124 +      return 0;
2125 +    else
2126 +      return EAI_MEMORY;
2127 +  if (!hostname)
2128 +    if (*res = malloc_ai(port, htonl(0x7f000001),
2129 +                        (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM,
2130 +                        (*res)->ai_protocol))
2131 +      return 0;
2132 +    else
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))
2138 +      return 0;
2139 +    else
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)) {
2148 +       if (prev)
2149 +         prev->ai_next = cur;
2150 +       else
2151 +         *res = cur;
2152 +       prev = cur;
2153 +      } else {
2154 +       if (*res)
2155 +         freeaddrinfo(*res);
2156 +       return EAI_MEMORY;
2157 +      }
2158 +    return 0;
2159 +  }
2160 +  return EAI_NODATA;
2161 +}
2162 diff -Nru apache_1.3.20/src/main/getnameinfo.c apache_1.3.20.new/src/main/getnameinfo.c
2163 --- apache_1.3.20/src/main/getnameinfo.c        Thu Jan  1 01:00:00 1970
2164 +++ apache_1.3.20.new/src/main/getnameinfo.c    Mon May 21 10:54:52 2001
2165 @@ -0,0 +1,95 @@
2166 +/*
2167 + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
2168 + * All rights reserved.
2169 + * 
2170 + * Redistribution and use in source and binary forms, with or without
2171 + * modification, are permitted provided that the following conditions
2172 + * are met:
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.
2181 + * 
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
2192 + * SUCH DAMAGE.
2193 + */
2194 +/*
2195 + * fake library for ssh v6 enabler patch
2196 + *
2197 + * This file includes getnameinfo().
2198 + * These funtions are defined in rfc2133.
2199 + *
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.
2203 + * 
2204 + * In the case not using 'configure --enable-ipv6', this getnameinfo.c
2205 + * will be used if you have broken getnameinfo or no getnameinfo.
2206 + */
2207 +
2208 +#if 0
2209 +#include <stdlib.h>
2210 +#include <sys/types.h>
2211 +#include <sys/socket.h>
2212 +#include <netinet/in.h>
2213 +#include <arpa/inet.h>
2214 +#include <netdb.h>
2215 +#include <string.h>
2216 +#include "gai.h"
2217 +#endif
2218 +
2219 +int
2220 +getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
2221 +const struct sockaddr *sa;
2222 +size_t salen;
2223 +char *host;
2224 +size_t hostlen;
2225 +char *serv;
2226 +size_t servlen;
2227 +int flags;
2228 +{
2229 +  struct sockaddr_in *sin = (struct sockaddr_in *)sa;
2230 +  struct hostent *hp;
2231 +  char tmpserv[16];
2232 +  
2233 +  if (serv) {
2234 +    sprintf(tmpserv, "%d", ntohs(sin->sin_port));
2235 +    if (strlen(tmpserv) > servlen)
2236 +      return EAI_MEMORY;
2237 +    else
2238 +      strcpy(serv, tmpserv);
2239 +  }
2240 +  if (host)
2241 +    if (flags & NI_NUMERICHOST)
2242 +      if (strlen(inet_ntoa(sin->sin_addr)) > hostlen)
2243 +       return EAI_MEMORY;
2244 +      else {
2245 +       strcpy(host, inet_ntoa(sin->sin_addr));
2246 +       return 0;
2247 +      }
2248 +    else
2249 +      if (hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr),
2250 +                            AF_INET))
2251 +       if (strlen(hp->h_name) > hostlen)
2252 +         return EAI_MEMORY;
2253 +       else {
2254 +         strcpy(host, hp->h_name);
2255 +         return 0;
2256 +       }
2257 +      else
2258 +       return EAI_NODATA;
2259 +  return 0;
2260 +}
2261 diff -Nru apache_1.3.20/src/main/http_config.c apache_1.3.20.new/src/main/http_config.c
2262 --- apache_1.3.20/src/main/http_config.c        Mon May 21 11:02:04 2001
2263 +++ apache_1.3.20.new/src/main/http_config.c    Mon May 21 10:54:52 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 @@
2273      s->next = NULL;
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));
2278 +#if 0
2279 +    s->addrs->host_addr.ss_family = ap_default_family; /* XXX: needed?, XXX: PF_xxx can be different from AF_xxx */
2280 +#endif
2281 +#ifdef HAVE_SOCKADDR_LEN
2282 +    s->addrs->host_addr.ss_len = sizeof(s->addrs->host_addr); /* XXX: needed ? */
2283 +#endif
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)
2289  {
2290      listen_rec *new;
2291 +    struct addrinfo hints, *res0, *res;
2292 +    int gai;
2293 +    char servbuf[NI_MAXSERV];
2294  
2295      if (ap_listeners != NULL) {
2296         return;
2297      }
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);
2304 +    if (gai){
2305 +       fprintf(stderr, "default_listeners(): getaddrinfo(PASSIVE) for family %u: %s\n",
2306 +               gai_strerror(gai), ap_default_family);
2307 +       exit (1);
2308 +    }
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);
2315      new->fd = -1;
2316      new->used = 0;
2317      new->next = NULL;
2318      ap_listeners = new;
2319 +
2320 +    freeaddrinfo(res0);
2321  }
2322  
2323  
2324 diff -Nru apache_1.3.20/src/main/http_core.c apache_1.3.20.new/src/main/http_core.c
2325 --- apache_1.3.20/src/main/http_core.c  Fri Mar  9 11:10:25 2001
2326 +++ apache_1.3.20.new/src/main/http_core.c      Mon May 21 10:54:52 2001
2327 @@ -71,6 +71,7 @@
2328  #include "util_md5.h"
2329  #include "scoreboard.h"
2330  #include "fnmatch.h"
2331 +#include "sa_len.h"
2332  
2333  #ifdef USE_MMAP_FILES
2334  #include <sys/mman.h>
2335 @@ -594,7 +595,9 @@
2336  /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
2337  static ap_inline void do_double_reverse (conn_rec *conn)
2338  {
2339 -    struct hostent *hptr;
2340 +    struct addrinfo hints, *res, *res0;
2341 +    char hostbuf1[128], hostbuf2[128]; /* INET6_ADDRSTRLEN(=46) is enough */
2342 +    int ok = 0;
2343  
2344      if (conn->double_reverse) {
2345         /* already done */
2346 @@ -605,28 +608,51 @@
2347         conn->double_reverse = -1;
2348         return;
2349      }
2350 -    hptr = gethostbyname(conn->remote_host);
2351 -    if (hptr) {
2352 -       char **haddr;
2353 -
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;
2358 -               return;
2359 -           }
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;
2365 +       return;
2366 +    }
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 
2370 +#ifdef INET6
2371 +             || res->ai_family == AF_INET6
2372 +#endif
2373 +             )
2374 +           )
2375 +           continue;
2376 +#ifndef HAVE_SOCKADDR_LEN
2377 +       if (res->ai_addrlen != SA_LEN((struct sockaddr *)&conn->remote_addr))
2378 +#else
2379 +       if (res->ai_addr->sa_len != conn->remote_addr.ss_len)
2380 +#endif
2381 +           continue;
2382 +       if (getnameinfo(res->ai_addr, res->ai_addrlen,
2383 +            hostbuf1, sizeof(hostbuf1), NULL, 0,
2384 +            NI_NUMERICHOST))
2385 +           continue;
2386 +       if (getnameinfo(((struct sockaddr *)&conn->remote_addr), res->ai_addrlen,
2387 +            hostbuf2, sizeof(hostbuf2), NULL, 0,
2388 +            NI_NUMERICHOST))
2389 +           continue;
2390 +       if (strcmp(hostbuf1, hostbuf2) == 0){
2391 +           ok = 1;
2392 +           break;
2393         }
2394      }
2395 -    conn->double_reverse = -1;
2396 +    conn->double_reverse = ok ? 1 : -1;
2397 +    freeaddrinfo(res0);
2398  }
2399  
2400  API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
2401                                             int type)
2402  {
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];
2408  
2409      /* If we haven't checked the host name, and we want to */
2410      if (dir_config) {
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,
2420 +#ifndef SIN6_LEN
2421 +               SA_LEN((struct sockaddr *)&conn->remote_addr),
2422 +#else
2423 +               conn->remote_addr.ss_len,
2424 +#endif
2425 +               hostnamebuf, sizeof(hostnamebuf), NULL, 0, 0)) {
2426 +           conn->remote_host = ap_pstrdup(conn->pool, (void *)hostnamebuf);
2427             ap_str_tolower(conn->remote_host);
2428            
2429             if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
2430 @@ -732,6 +762,7 @@
2431  {
2432      conn_rec *conn = r->connection;
2433      core_dir_config *d;
2434 +    char hbuf[MAXHOSTNAMELEN];
2435  
2436      d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
2437                                                 &core_module);
2438 @@ -741,23 +772,22 @@
2439      }
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;
2444              int old_stat;
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),
2449 -                                AF_INET);
2450 -           if (hptr != NULL) {
2451 -               conn->local_host = ap_pstrdup(conn->pool,
2452 -                                             (void *)hptr->h_name);
2453 -               ap_str_tolower(conn->local_host);
2454 -           }
2455 -           else {
2456 -               conn->local_host = ap_pstrdup(conn->pool,
2457 -                                             r->server->server_hostname);
2458 +           if (getnameinfo((struct sockaddr *)&conn->local_addr,
2459 +#ifndef SIN6_LEN
2460 +                   SA_LEN((struct sockaddr *)&conn->local_addr),
2461 +#else
2462 +                   conn->local_addr.ss_len,
2463 +#endif
2464 +                   hbuf, sizeof(hbuf), NULL, 0, 0) == 0) {
2465 +               conn->local_host = ap_pstrdup(conn->pool, hbuf);
2466 +           } else {
2467 +               conn->local_host = ap_pstrdup(conn->pool,
2468 +                   r->server->server_hostname);
2469             }
2470 +           ap_str_tolower(conn->local_host);
2471             (void) ap_update_child_status(conn->child_num, old_stat, r);
2472         }
2473         return conn->local_host;
2474 @@ -776,11 +806,13 @@
2475  
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)
2479 -                          : port;
2480 -    }
2481 -    /* default */
2482 -    return port;
2483 +        return r->hostname
2484 +           ?  ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port)
2485 +           : port;
2486 +    }
2487 +    return r->hostname
2488 +       ? ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port)
2489 +       : port;
2490  }
2491  
2492  API_EXPORT(char *) ap_construct_url(pool *p, const char *uri,
2493 @@ -2499,12 +2531,25 @@
2494  
2495  static const char *set_bind_address(cmd_parms *cmd, void *dummy, char *arg) 
2496  {
2497 +    struct addrinfo hints, *res;
2498 +    struct sockaddr *sa;
2499 +    size_t sa_len;
2500 +    int error;
2501      const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2502      if (err != NULL) {
2503          return err;
2504      }
2505  
2506 -    ap_bind_address.s_addr = ap_get_virthost_addr(arg, NULL);
2507 +    if (strcmp(arg, "*") == 0)
2508 +      arg = NULL;
2509 +
2510 +    sa = ap_get_virthost_addr(arg, NULL);
2511 +#ifdef HAVE_SOCKADDR_LEN
2512 +    sa_len = sa->sa_len;
2513 +#else
2514 +    sa_len = SA_LEN(sa);
2515 +#endif
2516 +    memcpy(&ap_bind_address, &sa, sa_len);
2517      return NULL;
2518  }
2519  
2520 @@ -2521,44 +2566,70 @@
2521  }
2522  #endif
2523  
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)
2526  {
2527      listen_rec *new;
2528 -    char *ports;
2529 -    unsigned short port;
2530 +    char *host, *port;
2531 +    struct addrinfo hints, *res;
2532 +    int error;
2533      
2534      const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
2535      if (err != NULL) {
2536          return err;
2537      }
2538  
2539 -    ports = strchr(ips, ':');
2540 -    if (ports != NULL) {
2541 -       if (ports == ips) {
2542 -           return "Missing IP address";
2543 -       }
2544 -       else if (ports[1] == '\0') {
2545 -           return "Address must end in :<port-number>";
2546 +    host = port = NULL;
2547 +    if (!p) {
2548 +       port = strrchr(h, ':');
2549 +       if (port != NULL) {
2550 +           if (port == h) {
2551 +               return "Missing IP address";
2552 +           }
2553 +           else if (port[1] == '\0') {
2554 +               return "Address must end in :<port-number>";
2555 +           }
2556 +           *(port++) = '\0';
2557 +           if (*h)
2558 +               host = h;
2559 +       } else {
2560 +           host = NULL;
2561 +           port = h;
2562         }
2563 -       *(ports++) = '\0';
2564 -    }
2565 -    else {
2566 -       ports = ips;
2567 +    } else {
2568 +       host = h;
2569 +       port = p;
2570      }
2571  
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);
2576 -    }
2577 -    else {
2578 -       new->local_addr.sin_addr.s_addr = ap_get_virthost_addr(ips, NULL);
2579 -    }
2580 -    port = atoi(ports);
2581 -    if (!port) {
2582 -       return "Port must be numeric";
2583 +    if (host && strcmp(host, "*") == 0)
2584 +       host = NULL;
2585 +    
2586 +    new = ap_pcalloc(cmd->pool, sizeof(listen_rec));
2587 +
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 ");
2595 +       if (host)
2596 +           fprintf(stderr, "host \"%s\" ", host);
2597 +       if (port)
2598 +           fprintf(stderr, "port \"%s\" ", port);
2599 +       fprintf(stderr, "--- %s\n", gai_strerror(error));
2600 +       exit(1);
2601 +    }
2602 +    if (res->ai_next) {
2603 +        if (host)
2604 +           fprintf(stderr, "host \"%s\" ", host);
2605 +       if (port)
2606 +           fprintf(stderr, "port \"%s\" ", port);
2607 +       fprintf(stderr, "resolved to multiple addresses, ambiguous.\n");
2608 +       exit(1);
2609      }
2610 -    new->local_addr.sin_port = htons(port);
2611 +
2612 +    memcpy(&new->local_addr, res->ai_addr, res->ai_addrlen);
2613 +
2614      new->fd = -1;
2615      new->used = 0;
2616      new->next = ap_listeners;
2617 @@ -3144,7 +3215,7 @@
2618  { "ThreadStackSize", set_threadstacksize, NULL, RSRC_CONF, TAKE1,
2619    "Stack size each created thread will use."},
2620  #endif
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 @@ -3165,7 +3236,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" },
2633  #ifdef _OSD_POSIX
2634  { "BS2000Account", set_bs2000_account, NULL, RSRC_CONF, TAKE1,
2635 diff -Nru apache_1.3.20/src/main/http_main.c apache_1.3.20.new/src/main/http_main.c
2636 --- apache_1.3.20/src/main/http_main.c  Mon May 21 11:02:04 2001
2637 +++ apache_1.3.20.new/src/main/http_main.c      Mon May 21 11:06:01 2001
2638 @@ -124,6 +124,8 @@
2639  #include <bstring.h>           /* for IRIX, FD_SET calls bzero() */
2640  #endif
2641  
2642 +#include "sa_len.h"
2643 +
2644  #ifdef MULTITHREAD
2645  /* special debug stuff -- PCS */
2646  
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;
2652 +#ifdef INET6
2653 +API_VAR_EXPORT int ap_default_family = PF_INET6;
2654 +#else
2655 +API_VAR_EXPORT int ap_default_family = PF_INET;
2656 +#endif
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 @@ -1086,7 +1093,11 @@
2662      fprintf(stderr, "Usage: %s [-D name] [-d directory] [-f file]\n", bin);
2663  #endif
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]"
2667 +#ifdef INET6
2668 +           " [-46]"
2669 +#endif
2670 +           "\n", pad);
2671      fprintf(stderr, "Options:\n");
2672  #ifdef SHARED_CORE
2673      fprintf(stderr, "  -R directory     : specify an alternate location for shared object files\n");
2674 @@ -1108,6 +1119,10 @@
2675  #endif
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");
2678 +#ifdef INET6
2679 +    fprintf(stderr, "  -4               : assume IPv4 on parsing configuration file\n");
2680 +    fprintf(stderr, "  -6               : assume IPv6 on parsing configuration file\n");
2681 +#endif
2682  #ifdef WIN32
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 @@ -3252,11 +3267,13 @@
2686  
2687  
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,
2693                              int child_num)
2694  {
2695      conn_rec *conn = (conn_rec *) ap_pcalloc(p, sizeof(conn_rec));
2696 +    char hostnamebuf[MAXHOSTNAMELEN];
2697 +    size_t addr_len;
2698  
2699      /* Got a connection structure, so initialize what fields we can
2700       * (the rest are zeroed out by pcalloc).
2701 @@ -3265,17 +3282,29 @@
2702      conn->child_num = child_num;
2703  
2704      conn->pool = p;
2705 -    conn->local_addr = *saddr;
2706 -    conn->local_ip = ap_pstrdup(conn->pool,
2707 -                               inet_ntoa(conn->local_addr.sin_addr));
2708 +#ifndef SIN6_LEN
2709 +    addr_len = SA_LEN(saddr);
2710 +#else 
2711 +    addr_len = saddr->sa_len;
2712 +#endif
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;
2721  
2722 -    conn->remote_addr = *remaddr;
2723 -    conn->remote_ip = ap_pstrdup(conn->pool,
2724 -                             inet_ntoa(conn->remote_addr.sin_addr));
2725 +#ifndef SIN6_LEN 
2726 +    addr_len = SA_LEN(remaddr);
2727 +#else 
2728 +    addr_len = remaddr->sa_len;
2729 +#endif
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);           
2734  #ifdef EAPI
2735      conn->ctx = ap_ctx_new(conn->pool);
2736  #endif /* EAPI */
2737 @@ -3326,21 +3355,47 @@
2738  #define sock_disable_nagle(s)  /* NOOP */
2739  #endif
2740  
2741 -static int make_sock(pool *p, const struct sockaddr_in *server)
2742 +static int make_sock(pool *p, const struct sockaddr *server)
2743  {
2744      int s;
2745      int one = 1;
2746 -    char addr[512];
2747 +    char addr[INET6_ADDRSTRLEN + 128];
2748 +    char a0[INET6_ADDRSTRLEN];
2749 +    char p0[NI_MAXSERV];
2750 +#ifdef MPE
2751 +    int privport = 0;
2752 +#endif
2753  
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));
2757 -    else
2758 -       ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
2759 +    switch(server->sa_family){
2760 +    case AF_INET:
2761 +#ifdef INET6
2762 +    case AF_INET6:
2763 +#endif
2764 +      break;
2765 +    default:
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();
2770 +      exit(1);
2771 +    }
2772 +    
2773 +    getnameinfo(server,
2774 +#ifndef SIN6_LEN
2775 +               SA_LEN(server),
2776 +#else
2777 +               server->sa_len,
2778 +#endif
2779 +               a0, sizeof(a0), p0, sizeof(p0), NI_NUMERICHOST | NI_NUMERICSERV);
2780 +    ap_snprintf(addr, sizeof(addr), "address %s port %s", a0, p0);
2781 +#ifdef MPE
2782 +    if (atoi(p0) < 1024)
2783 +      privport++;
2784 +#endif
2785  
2786      /* note that because we're about to slack we don't use psocket */
2787      ap_block_alarms();
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);
2792  
2793 @@ -3443,15 +3498,19 @@
2794  
2795  #ifdef MPE
2796  /* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */
2797 -    if (ntohs(server->sin_port) < 1024)
2798 +    if (privport)
2799         GETPRIVMODE();
2800  #endif
2801 -
2802 -    if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) {
2803 +#ifndef SIN6_LEN
2804 +    if (bind(s, server, SA_LEN(server)) == -1)
2805 +#else
2806 +    if (bind(s, server, server->sa_len) == -1)
2807 +#endif
2808 +    {
2809         ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
2810             "make_sock: could not bind to %s", addr);
2811  #ifdef MPE
2812 -       if (ntohs(server->sin_port) < 1024)
2813 +       if (privport)
2814             GETUSERMODE();
2815  #endif
2816  
2817 @@ -3464,7 +3523,7 @@
2818         exit(1);
2819      }
2820  #ifdef MPE
2821 -    if (ntohs(server->sin_port) < 1024)
2822 +    if (privport)
2823         GETUSERMODE();
2824  #endif
2825  
2826 @@ -3611,15 +3670,17 @@
2827      for (;;) {
2828         fd = find_listener(lr);
2829         if (fd < 0) {
2830 -           fd = make_sock(p, &lr->local_addr);
2831 +           fd = make_sock(p, (struct sockaddr *)&lr->local_addr);
2832         }
2833         else {
2834             ap_note_cleanups_for_socket(p, fd);
2835         }
2836         /* if we get here, (fd >= 0) && (fd < FD_SETSIZE) */
2837 -       FD_SET(fd, &listenfds);
2838 -       if (fd > listenmaxfd)
2839 -           listenmaxfd = fd;
2840 +       if (fd > 0) {
2841 +           FD_SET(fd, &listenfds);
2842 +           if (fd > listenmaxfd)
2843 +               listenmaxfd = fd;
2844 +       }
2845         lr->fd = fd;
2846         if (lr->next == NULL)
2847             break;
2848 @@ -3918,8 +3979,8 @@
2849  static void child_main(int child_num_arg)
2850  {
2851      NET_SIZE_T clen;
2852 -    struct sockaddr sa_server;
2853 -    struct sockaddr sa_client;
2854 +    struct sockaddr_storage sa_server;
2855 +    struct sockaddr_storage sa_client;
2856      listen_rec *lr;
2857  
2858      /* All of initialization is a critical section, we don't care if we're
2859 @@ -4084,7 +4145,7 @@
2860             usr1_just_die = 0;
2861             for (;;) {
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)
2866                     break;
2867                 if (deferred_die) {
2868 @@ -4234,7 +4295,7 @@
2869          */
2870  
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");
2875             continue;
2876         }
2877 @@ -4279,8 +4340,8 @@
2878         ap_bpushfd(conn_io, csd, dupped_csd);
2879  
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,
2885                                           my_child_num);
2886  
2887         /*
2888 @@ -4424,12 +4485,13 @@
2889  
2890  #ifdef _OSD_POSIX
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)
2894  #elif defined(TPF)
2895 -    if ((pid = os_fork(s, slot)) == -1) {
2896 +    if ((pid = os_fork(s, slot)) == -1)
2897  #else
2898 -    if ((pid = fork()) == -1) {
2899 +    if ((pid = fork()) == -1)
2900  #endif
2901 +    {
2902         ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process");
2903  
2904         /* fork didn't succeed. Fix the scoreboard or else
2905 @@ -5003,7 +5065,10 @@
2906      ap_setup_prelinked_modules();
2907  
2908      while ((c = getopt(argc, argv,
2909 -                                   "D:C:c:xXd:f:vVlLR:StTh"
2910 +                                   "D:C:c:xXd:f:vVlLR:StTh4"
2911 +#ifdef INET6
2912 +                                   "6"
2913 +#endif
2914  #ifdef DEBUG_SIGSTOP
2915                                     "Z:"
2916  #endif
2917 @@ -5078,8 +5143,14 @@
2918             ap_configtestonly = 1;
2919             ap_docrootcheck = 0;
2920             break;
2921 -       case 'h':
2922 -           usage(argv[0]);
2923 +       case '4':
2924 +           ap_default_family = PF_INET;
2925 +           break;
2926 +#ifdef INET6
2927 +       case '6':
2928 +           ap_default_family = PF_INET6;
2929 +           break;
2930 +#endif
2931         case '?':
2932             usage(argv[0]);
2933         }
2934 @@ -5158,9 +5229,10 @@
2935      else {
2936         conn_rec *conn;
2937         request_rec *r;
2938 -       struct sockaddr sa_server, sa_client;
2939         BUFF *cio;
2940 +       struct sockaddr_storage sa_server, sa_client;
2941         NET_SIZE_T l;
2942 +       char servbuf[NI_MAXSERV];
2943  
2944         ap_set_version();
2945         /* Yes this is called twice. */
2946 @@ -5207,25 +5279,32 @@
2947  #endif
2948  
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));
2955         }
2956  
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");
2962             exit(1);
2963         }
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), 
2967 +                       NI_NUMERICSERV)){
2968 +           fprintf(stderr, "getnameinfo(): family=%d\n", sa_server.ss_family);
2969 +           exit(1);
2970 +       }
2971 +       servbuf[sizeof(servbuf)-1] = '\0';
2972 +       server_conf->port = atoi(servbuf);
2973         cio = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
2974          cio->fd = sock_out;
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);
2981  
2982         while ((r = ap_read_request(conn)) != NULL) {
2983  
2984 @@ -7383,7 +7462,11 @@
2985       * but only handle the -L option 
2986       */
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"
2990 +#ifdef INET6
2991 +               "6"
2992 +#endif
2993 +               )) != -1) {
2994         switch (c) {
2995         case 'D':
2996         case 'C':
2997 @@ -7400,6 +7483,10 @@
2998         case 't':
2999         case 'T':
3000         case 'h':
3001 +       case '4':
3002 +#ifdef INET6
3003 +       case '6':
3004 +#endif
3005         case '?':
3006             break;
3007         case 'R':
3008 diff -Nru apache_1.3.20/src/main/http_vhost.c apache_1.3.20.new/src/main/http_vhost.c
3009 --- apache_1.3.20/src/main/http_vhost.c Sat Feb 24 11:09:46 2001
3010 +++ apache_1.3.20.new/src/main/http_vhost.c     Mon May 21 10:54:52 2001
3011 @@ -68,6 +68,7 @@
3012  #include "http_log.h"
3013  #include "http_vhost.h"
3014  #include "http_protocol.h"
3015 +#include "sa_len.h"
3016  
3017  /*
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
3022   */
3023 -static const char *get_addresses(pool *p, char *w, server_addr_rec ***paddr,
3024 -                           unsigned port)
3025 +static const char *get_addresses(pool *p, char *w, char *pstr,
3026 +       server_addr_rec ***paddr, unsigned port)
3027  {
3028 -    struct hostent *hep;
3029 -    unsigned long my_addr;
3030 +    struct addrinfo hints, *res, *res0;
3031      server_addr_rec *sar;
3032 -    char *t;
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];
3037 +    int error;
3038 +    char servbuf[NI_MAXSERV];
3039  
3040 -    if (*w == 0)
3041 +    if (w == 0 || *w == 0)
3042         return NULL;
3043  
3044 -    t = strchr(w, ':');
3045 -    if (t) {
3046 -       if (strcmp(t + 1, "*") == 0) {
3047 -           port = 0;
3048 +    portstr = portpool;
3049 +    ap_snprintf(portpool, sizeof(portpool), "%u", port);
3050 +    if (!pstr) {
3051 +       v = w;
3052 +       u = NULL;
3053 +       if (*w == '['){
3054 +           u = strrchr(w, ']');
3055 +           if (u) {    /* [host]:port or [host] */
3056 +               w++;
3057 +               *u = '\0';
3058 +               v = u + 1;
3059 +           }
3060         }
3061 -       else if ((i = atoi(t + 1))) {
3062 -           port = i;
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 */
3068 +           *t = '\0';
3069 +           portstr = t + 1;
3070         }
3071         else {
3072 -           return ":port must be numeric";
3073 +           portstr = "0";
3074         }
3075 -       *t = 0;
3076 +    } else {
3077 +       portstr = pstr;
3078      }
3079  
3080 -    is_an_ip_addr = 0;
3081 -    if (strcmp(w, "*") == 0) {
3082 -       my_addr = htonl(INADDR_ANY);
3083 -       is_an_ip_addr = 1;
3084 -    }
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;
3089 -    }
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) {
3095 +       hoststr = NULL;
3096 +       hints.ai_family = PF_UNSPEC;
3097 +       hints.ai_flags = AI_PASSIVE;
3098 +    }
3099 +    else if (strcasecmp(w, "_default4_") == 0 ||
3100 +            ((ap_default_family == PF_INET
3101 +#ifndef INET6
3102 +              || ap_default_family == PF_UNSPEC
3103 +#endif
3104 +              ) && strcasecmp(w, "_default_") == 0)){
3105 +       hoststr = "255.255.255.255";
3106 +       hints.ai_family = PF_INET;
3107 +    }
3108 +#ifdef INET6
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;
3115      }
3116 -    if (is_an_ip_addr) {
3117 -       sar = ap_pcalloc(p, sizeof(server_addr_rec));
3118 -       **paddr = sar;
3119 -       *paddr = &sar->next;
3120 -       sar->host_addr.s_addr = my_addr;
3121 -       sar->host_port = port;
3122 -       sar->virthost = ap_pstrdup(p, w);
3123 -       if (t != NULL)
3124 -           *t = ':';
3125 -       return NULL;
3126 +#endif
3127 +    else{
3128 +       hoststr = w;
3129 +       hints.ai_family = PF_UNSPEC;
3130      }
3131  
3132 -    hep = gethostbyname(w);
3133 -
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);
3139 -       if (t != NULL)
3140 -           *t = ':';
3141 +           "Cannot resolve host %s port %s --- ignoring!", hoststr, portstr);
3142 +       if (t != NULL) *t = ':';
3143 +       if (u != NULL) *u = ']';
3144         return NULL;
3145      }
3146 -
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) {
3150 +       case AF_INET:
3151 +#ifdef INET6
3152 +       case AF_INET6:
3153 +#endif
3154 +           break;
3155 +       default:
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);
3159 +           continue;
3160 +       }
3161         sar = ap_pcalloc(p, sizeof(server_addr_rec));
3162         **paddr = sar;
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);
3170 +       else
3171 +               sar->host_port = 0;
3172         sar->virthost = ap_pstrdup(p, w);
3173      }
3174  
3175 -    if (t != NULL)
3176 -       *t = ':';
3177 +    freeaddrinfo(res0);
3178 +    if (t != NULL) *t = ':';
3179 +    if (u != NULL) *u = ']';
3180      return NULL;
3181  }
3182  
3183 @@ -250,7 +287,8 @@
3184      /* start the list of addreses */
3185      addrs = &s->addrs;
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,
3189 +               &addrs, s->port);
3190         if (err) {
3191             *addrs = NULL;
3192             return err;
3193 @@ -268,10 +306,11 @@
3194  }
3195  
3196  
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,
3199 +       char *p)
3200  {
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,
3204                             cmd->server->port);
3205  }
3206  
3207 @@ -345,6 +384,19 @@
3208      return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
3209  }
3210  
3211 +static unsigned hash_addr(struct sockaddr *sa)
3212 +{
3213 +    switch (sa->sa_family) {
3214 +    case AF_INET:
3215 +       return hash_inaddr(((struct sockaddr_in *)sa)->sin_addr.s_addr);
3216 +#ifdef INET6
3217 +    case AF_INET6:
3218 +       return hash_inaddr(((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12]);
3219 +#endif
3220 +    default:
3221 +       return hash_inaddr(sa->sa_family);
3222 +    }
3223 +}
3224  
3225  
3226  static ipaddr_chain *new_ipaddr_chain(pool *p,
3227 @@ -372,25 +424,77 @@
3228      return new;
3229  }
3230  
3231 -
3232 -static ap_inline ipaddr_chain *find_ipaddr(struct in_addr *server_ip,
3233 -    unsigned port)
3234 +static ap_inline ipaddr_chain *find_ipaddr(struct sockaddr *sa)
3235  {
3236      unsigned bucket;
3237      ipaddr_chain *trav;
3238 -    unsigned addr;
3239 +    char a[NI_MAXHOST], b[NI_MAXHOST];
3240  
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
3249 -               || port == 0)) {
3250 -           return trav;
3251 +       if (sar->host_addr.ss_family != sa->sa_family)
3252 +           continue;
3253 +       switch (sa->sa_family) {
3254 +       case AF_INET:
3255 +         {
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) {
3263 +                   return trav;
3264 +               }
3265 +           }
3266 +           break;
3267 +         }
3268 +#ifdef INET6
3269 +       case AF_INET6:
3270 +         {
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) {
3278 +                   return trav;
3279 +               }
3280 +           }
3281 +           break;
3282 +         }
3283 +#endif
3284 +       default: /*unsupported*/
3285 +           break;
3286         }
3287      }
3288 +
3289 +#ifdef INET6
3290 +    if (sa->sa_family == AF_INET6 &&
3291 +       IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)) {
3292 +       /*
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.
3296 +        */
3297 +       struct sockaddr_in sin;
3298 +
3299 +       memset(&sin, 0, sizeof(sin));
3300 +       sin.sin_family = AF_INET;
3301 +#ifdef SIN6_LEN
3302 +       sin.sin_len = sizeof(sin);
3303 +#endif
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);
3309 +    }
3310 +#endif
3311 +
3312      return NULL;
3313  }
3314  
3315 @@ -416,21 +520,7 @@
3316      int len;
3317      char buf[MAX_STRING_LEN];
3318  
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);
3322 -    }
3323 -    else if (ic->sar->host_addr.s_addr == INADDR_ANY) {
3324 -       len = ap_snprintf(buf, sizeof(buf), "*:%u",
3325 -               ic->sar->host_port);
3326 -    }
3327 -    else {
3328 -       len = ap_snprintf(buf, sizeof(buf), "%pA:%u",
3329 -               &ic->sar->host_addr, ic->sar->host_port);
3330 -    }
3331 -    if (ic->sar->host_port == 0) {
3332 -       buf[len-1] = '*';
3333 -    }
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.
3340       */
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);
3345 +       int wildcard;
3346 +
3347 +       wildcard = 0;
3348 +       switch (sar->host_addr.ss_family) {
3349 +       case AF_INET:
3350 +         {
3351 +           struct sockaddr_in *sin;
3352 +           sin = (struct sockaddr_in *)&sar->host_addr;
3353 +           if (sin->sin_addr.s_addr == INADDR_ANY)
3354 +               wildcard++;
3355 +           break;
3356 +         }
3357 +#ifdef INET6
3358 +       case AF_INET6:
3359 +         {
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) {
3366 +               wildcard++;
3367 +           }
3368 +           break;
3369 +         }
3370 +#endif
3371 +       }
3372  
3373 -       if (sar->host_addr.s_addr != INADDR_ANY) {
3374 +       if (!wildcard) {
3375             *iphash_table_tail[bucket] = ic;
3376             iphash_table_tail[bucket] = &ic->next;
3377         }
3378 @@ -588,12 +705,45 @@
3379         has_default_vhost_addr = 0;
3380         for (sar = s->addrs; sar; sar = sar->next) {
3381             ipaddr_chain *ic;
3382 +           int wildcard;
3383 +
3384 +           wildcard = 0;
3385 +           switch (sar->host_addr.ss_family) {
3386 +           case AF_INET:
3387 +             {
3388 +               struct sockaddr_in *sin;
3389 +               sin = (struct sockaddr_in *)&sar->host_addr;
3390 +               if (sin->sin_addr.s_addr == DEFAULT_VHOST_ADDR)
3391 +                   wildcard++;
3392 +               else if (sin->sin_addr.s_addr == INADDR_ANY)
3393 +                   wildcard++;
3394 +               break;
3395 +             }
3396 +#ifdef INET6
3397 +           case AF_INET6:
3398 +             {
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) {
3405 +                   wildcard++;
3406 +               }
3407 +               break;
3408 +             }
3409 +#endif
3410 +           }
3411  
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) {
3417 +           if (wildcard) {
3418 +               /* add it to default bucket for each appropriate sar
3419 +                * since we need to do a port test
3420 +                */
3421 +               ipaddr_chain *other;
3422 +
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 @@
3430             }
3431             else {
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);
3435  
3436                 if (!ic) {
3437 -                   unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
3438 +                   unsigned bucket =
3439 +                       hash_addr((struct sockaddr *)&sar->host_addr);
3440  
3441                     ic = new_ipaddr_chain(p, s, sar);
3442                     ic->next = *iphash_table_tail[bucket];
3443 @@ -646,19 +797,33 @@
3444             }
3445             else {
3446                 struct hostent *h;
3447 +               char hostnamebuf[MAXHOSTNAMELEN];
3448  
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,
3453 +#ifndef SIN6_LEN
3454 +                       SA_LEN((struct sockaddr *)&s->addrs->host_addr),
3455 +#else  
3456 +                       s->addrs->host_addr.ss_len,
3457 +#endif
3458 +                       hostnamebuf, sizeof(hostnamebuf),
3459 +                       NULL, 0, 0)) {
3460 +                   s->server_hostname = ap_pstrdup(p, hostnamebuf);
3461                 }
3462                 else {
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,
3466 +#ifndef SIN6_LEN
3467 +                       SA_LEN((struct sockaddr *)&s->addrs->host_addr),
3468 +#else  
3469 +                       s->addrs->host_addr.ss_len,
3470 +#endif
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 "
3476 -                           "ServerName",
3477 -                           inet_ntoa(s->addrs->host_addr));
3478 +                           "ServerName", hostnamebuf);
3479                     s->server_hostname =
3480                         ap_pstrdup(p, "bogus_host_without_reverse_dns");
3481                 }
3482 @@ -705,35 +870,58 @@
3483      char *host = ap_palloc(r->pool, strlen(r->hostname) + 1);
3484      const char *src;
3485      char *dst;
3486 +    const char *u = NULL, *v = NULL;
3487  
3488      /* check and copy the host part */
3489 -    src = r->hostname;
3490 +    u = src = r->hostname;
3491  
3492      dst = host;
3493 -    while (*src) {
3494 -       if (*src == '.') {
3495 -           *dst++ = *src++;
3496 -           if (*src == '.')
3497 -               goto bad;
3498 -           else
3499 -               continue;
3500 -       }
3501 -       if (*src == '/' || *src == '\\') {
3502 -           goto bad;
3503 -       }
3504 -        if (*src == ':') {
3505 -            /* check the port part */
3506 -            while (*++src) {
3507 -                if (!ap_isdigit(*src)) {
3508 -                    goto bad;
3509 -                }
3510 -            }
3511 -            if (src[-1] == ':')
3512 -                goto bad;
3513 -            else
3514 -                break;
3515 +     if (*u == '[') { /* IPv6 numeral address in brackets */
3516 +         v = strchr(u, ']');
3517 +       if (v == NULL) {
3518 +           /* missing closing bracket */
3519 +             goto bad;
3520 +       }
3521 +         if (v == (u + 1)) {
3522 +             /* bad empty address */
3523 +             goto bad;
3524 +       }
3525 +       for (src = u+1; src < v; src++)  /* copy IPv6 adress */
3526 +           *dst = *src;
3527 +       v++;
3528 +       if (*v == ':') {
3529 +          v++;
3530 +          while (*v) {  /* check if portnum is correct */
3531 +              if (!ap_isdigit(*v++))
3532 +                  goto bad;
3533 +          }
3534          }
3535 -       *dst++ = *src++;
3536 +     } else {
3537 +         while (*src) {
3538 +           if (*src == '.') {
3539 +               *dst++ = *src++;
3540 +               if (*src == '.')
3541 +                   goto bad;
3542 +               else
3543 +                   continue;
3544 +           }
3545 +           if (*src == '/' || *src == '\\') {
3546 +               goto bad;
3547 +           }
3548 +           if (*src == ':') {
3549 +               /* sheck the port part */
3550 +               while (*++src) {
3551 +                   if (!ap_isdigit(*src)) {
3552 +                       goto bad;
3553 +                   }
3554 +               }
3555 +               if (src[-1] == ':')
3556 +                   goto bad;
3557 +               else
3558 +                   break;
3559 +           }
3560 +           *dst++ = *src++;
3561 +         }
3562      }
3563      /* strip trailing gubbins */
3564      if (dst > host && dst[-1] == '.') {
3565 @@ -748,7 +936,7 @@
3566  bad:
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);
3571      return;
3572  }
3573  
3574 @@ -851,11 +1039,25 @@
3575       *   names we'll match have ports associated with them
3576       */
3577      const char *host = r->hostname;
3578 -    unsigned port = ntohs(r->connection->local_addr.sin_port);
3579 +    unsigned port;
3580      server_rec *s;
3581      server_rec *last_s;
3582      name_chain *src;
3583  
3584 +    switch (r->connection->local_addr.ss_family) {
3585 +    case AF_INET:
3586 +       port = ntohs(((struct sockaddr_in *)
3587 +                   &r->connection->local_addr)->sin_port);
3588 +       break;
3589 +#ifdef INET6
3590 +    case AF_INET6:
3591 +       port = ntohs(((struct sockaddr_in6 *)
3592 +                   &r->connection->local_addr)->sin6_port);
3593 +       break;
3594 +#endif
3595 +    default:
3596 +       port = 0;       /*XXX*/
3597 +    }
3598      last_s = NULL;
3599  
3600      /* Recall that the name_chain is a list of server_addr_recs, some of
3601 @@ -910,7 +1112,22 @@
3602      server_rec *s;
3603      server_rec *last_s;
3604      name_chain *src;
3605 -    unsigned port = ntohs(r->connection->local_addr.sin_port);
3606 +    unsigned port;
3607 +
3608 +    switch (r->connection->local_addr.ss_family) {
3609 +    case AF_INET:
3610 +       port = ntohs(((struct sockaddr_in *)
3611 +                   &r->connection->local_addr)->sin_port);
3612 +       break;
3613 +#ifdef INET6
3614 +    case AF_INET6:
3615 +       port = ntohs(((struct sockaddr_in6 *)
3616 +                   &r->connection->local_addr)->sin6_port);
3617 +       break;
3618 +#endif
3619 +    default:
3620 +       port = 0;       /*XXX*/
3621 +    }
3622  
3623      /*
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)
3627  {
3628      ipaddr_chain *trav;
3629 -    unsigned port = ntohs(conn->local_addr.sin_port);
3630 +    char portbuf[NI_MAXSERV];
3631 +    unsigned port;
3632 +
3633 +    if (getnameinfo((struct sockaddr *)&conn->local_addr,
3634 +#ifndef SIN6_LEN
3635 +       SA_LEN((struct sockaddr *)&conn->local_addr),
3636 +#else  
3637 +       conn->local_addr.ss_len,
3638 +#endif
3639 +       NULL, 0, portbuf, sizeof(portbuf), NI_NUMERICSERV) != 0) {
3640 +       goto fail;
3641 +    }
3642 +    port = atoi(portbuf);
3643  
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);
3647      if (trav) {
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 @@
3651         return;
3652      }
3653  
3654 +fail:
3655      /* otherwise we're stuck with just the main server
3656       * and no name-based vhosts
3657       */
3658 diff -Nru apache_1.3.20/src/main/rfc1413.c apache_1.3.20.new/src/main/rfc1413.c
3659 --- apache_1.3.20/src/main/rfc1413.c    Mon Jan 15 18:05:04 2001
3660 +++ apache_1.3.20.new/src/main/rfc1413.c        Mon May 21 10:54:52 2001
3661 @@ -82,6 +82,7 @@
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"
3666  
3667  /* Local stuff. */
3668  /* Semi-well-known port */
3669 @@ -109,12 +110,13 @@
3670  
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)
3678  {
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 */
3684      int i;
3685      char *cp;
3686      char buffer[RFC1413_MAXDATA + 1];
3687 @@ -129,16 +131,47 @@
3688       * addresses from the query socket.
3689       */
3690  
3691 -    our_query_sin = *our_sin;
3692 -    our_query_sin.sin_port = htons(ANY_PORT);
3693 -#ifdef MPE 
3694 -    our_query_sin.sin_addr.s_addr = INADDR_ANY;
3695 +#ifndef SIN6_LEN
3696 +    memcpy(&our_query_sin, our_sin, SA_LEN(our_sin));
3697 +    memcpy(&rmt_query_sin, rmt_sin, SA_LEN(rmt_sin));
3698 +#else
3699 +    memcpy(&our_query_sin, our_sin, our_sin->sa_len);
3700 +    memcpy(&rmt_query_sin, rmt_sin, rmt_sin->sa_len);
3701  #endif
3702 -    rmt_query_sin = *rmt_sin;
3703 -    rmt_query_sin.sin_port = htons(RFC1413_PORT);
3704 +    switch (our_sin->sa_family) {
3705 +    case AF_INET:
3706 +#ifdef MPE
3707 +      ((struct sockaddr_in *)&our_query_sin)->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(??) */
3708 +#endif
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);
3713 +      break;
3714 +#ifdef INET6
3715 +    case AF_INET6:
3716 +#ifdef MPE
3717 +      memcpy(&((struct sockaddr_in6 *)&our_query_sin)->sin6_addr, 
3718 +            &in6addr_any, sizeof(struct in6_addr));
3719 +#endif
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);
3724 +      break;
3725 +#endif
3726 +    default:
3727 +      /* unsupported AF */
3728 +      return -1;
3729 +    }
3730  
3731      if (bind(sock, (struct sockaddr *) &our_query_sin,
3732 -            sizeof(struct sockaddr_in)) < 0) {
3733 +#ifndef SIN6_LEN
3734 +            SA_LEN((struct sockaddr *) &our_query_sin)
3735 +#else
3736 +            our_query_sin.ss_len
3737 +#endif
3738 +            ) < 0) {
3739         ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
3740                     "bind: rfc1413: Error binding to local port");
3741         return -1;
3742 @@ -149,12 +182,18 @@
3743   * the service
3744   */
3745      if (connect(sock, (struct sockaddr *) &rmt_query_sin,
3746 -               sizeof(struct sockaddr_in)) < 0)
3747 -                   return -1;
3748 +#ifndef SIN6_LEN
3749 +               SA_LEN((struct sockaddr *) &rmt_query_sin)
3750 +#else
3751 +               rmt_query_sin.ss_len
3752 +#endif
3753 +               ) < 0) {
3754 +       return -1;
3755 +    }
3756  
3757  /* send the data */
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,
3761 +               o_our_port);
3762  
3763      /* send query to server. Handle short write. */
3764  #ifdef CHARSET_EBCDIC
3765 @@ -219,9 +258,9 @@
3766      ascii2ebcdic(buffer, buffer, (size_t)i);
3767  #endif
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) {
3772         return -1;
3773 +    }
3774  
3775      /*
3776       * Strip trailing carriage return. It is part of the
3777 @@ -243,7 +282,7 @@
3778  
3779      result = FROM_UNKNOWN;
3780  
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);
3783      if (sock < 0) {
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);
3789  
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) {
3793             result = user;
3794 +       }
3795      }
3796      ap_set_callback_and_alarm(NULL, 0);
3797      ap_pclosesocket(conn->pool, sock);
3798 diff -Nru apache_1.3.20/src/main/util.c apache_1.3.20.new/src/main/util.c
3799 --- apache_1.3.20/src/main/util.c       Fri Mar 30 19:37:54 2001
3800 +++ apache_1.3.20.new/src/main/util.c   Mon May 21 11:04:30 2001
3801 @@ -1959,52 +1959,87 @@
3802   * Parses a host of the form <address>[:port]
3803   * :port is permitted if 'port' is not NULL
3804   */
3805 -unsigned long ap_get_virthost_addr(char *w, unsigned short *ports)
3806 +struct sockaddr *ap_get_virthost_addr(char *w, unsigned short *ports)
3807  {
3808 -    struct hostent *hep;
3809 -    unsigned long my_addr;
3810 -    char *p;
3811 -
3812 -    p = strchr(w, ':');
3813 +    static struct sockaddr_storage ss;
3814 +    struct addrinfo hints, *res;
3815 +    char *p, *r;
3816 +    char *host;
3817 +    char *port = "0";
3818 +    int error;
3819 +    char servbuf[NI_MAXSERV];
3820 +
3821 +    if (w == NULL)
3822 +       w = "*";
3823 +    p = r = NULL;
3824 +    if (*w == '['){
3825 +       if (r = strrchr(w+1, ']')){
3826 +           *r = '\0';
3827 +           p = r + 1;
3828 +           switch(*p){
3829 +           case ':':
3830 +             p++;
3831 +             /* nobreak; */
3832 +           case '\0':
3833 +             w++;
3834 +             break;
3835 +           default:
3836 +             p = NULL;
3837 +           }
3838 +       }
3839 +    }
3840 +    else{
3841 +       p = strchr(w, ':');
3842 +       if (p != NULL && strchr(p+1, ':') != NULL)
3843 +           p = NULL;
3844 +    }
3845      if (ports != NULL) {
3846 -       *ports = 0;
3847 -       if (p != NULL && strcmp(p + 1, "*") != 0)
3848 -           *ports = atoi(p + 1);
3849 +       if (p != NULL && *p && strcmp(p + 1, "*") != 0)
3850 +           port = p + 1;
3851      }
3852  
3853 +    memset(&hints, 0, sizeof(hints));
3854 +    hints.ai_socktype = SOCK_STREAM;
3855      if (p != NULL)
3856         *p = '\0';
3857      if (strcmp(w, "*") == 0) {
3858 -       if (p != NULL)
3859 -           *p = ':';
3860 -       return htonl(INADDR_ANY);
3861 -    }
3862 -
3863 -    my_addr = ap_inet_addr((char *)w);
3864 -    if (my_addr != INADDR_NONE) {
3865 -       if (p != NULL)
3866 -           *p = ':';
3867 -       return my_addr;
3868 +       host = NULL;
3869 +       hints.ai_flags = AI_PASSIVE;
3870 +       hints.ai_family = ap_default_family;
3871 +    } else {
3872 +       host = w;
3873 +       hints.ai_family = PF_UNSPEC;
3874      }
3875  
3876 -    hep = gethostbyname(w);
3877 +    error = getaddrinfo(host, port, &hints, &res);
3878  
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));
3883         exit(1);
3884      }
3885  
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");
3892         exit(1);
3893      }
3894  
3895 +    if (r != NULL)
3896 +       *r = ']';
3897      if (p != NULL)
3898         *p = ':';
3899  
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),
3904 +                   NI_NUMERICSERV)){
3905 +       fprintf(stderr, "ap_get_virthost_addr(): getnameinfo() failed --- Exiting!!!\n");
3906 +       exit(1);
3907 +    }
3908 +    if (ports) *ports = atoi(servbuf);
3909 +    freeaddrinfo(res);
3910 +    return (struct sockaddr *)&ss;
3911  }
3912  
3913  
3914 @@ -2032,7 +2067,8 @@
3915  #endif
3916      char str[MAXHOSTNAMELEN];
3917      char *server_hostname = NULL;
3918 -    struct hostent *p;
3919 +    struct addrinfo hints, *res;
3920 +    int error;
3921  
3922  #ifdef BEOS /* BeOS returns zero as an error for gethostname */
3923      if (gethostname(str, sizeof(str) - 1) == 0) {
3924 @@ -2045,29 +2081,38 @@
3925      }
3926      else 
3927      {
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 */
3936 -            }
3937 -        }
3938 -       else
3939 -            /* Since we found a fqdn, return it with no logged message. */
3940 -            return server_hostname;
3941 -    }
3942 -
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");
3946 -    
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);
3956 +       if (error)
3957 +       {
3958 +              /* Recovery - return the default servername by IP: */
3959 +
3960 +           fprintf(stderr, "%s: cannot determine local host name.\n",
3961 +                 ap_server_argv0);
3962 +           fprintf(stderr, "Use the ServerName directive to set it manually.\n");
3963 +           exit(1);
3964 +
3965 +           server_hostname = ap_pstrdup(a, res->ai_canonname);
3966 +       }
3967 +       else if (1)     /*fqdn found*/
3968 +       {
3969 +           /* XXX should check more conditions */
3970 +           server_hostname = ap_pstrdup(a, res->ai_canonname);
3971 +       }
3972 +        else
3973 +       {
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);
3978 +       }
3979 +
3980 +       /* Since we found a fdqn, return it with no logged message. */
3981 +       freeaddrinfo(res);
3982 +      }
3983      
3984      return server_hostname;
3985  }
3986 @@ -2146,7 +2191,7 @@
3987      char *quote_doubled_str, *dest;
3988      
3989      while (str[len]) {
3990 -        num_quotes += str[len++] == '\"';
3991 +       num_quotes += str[len++] == '\"';
3992      }
3993      
3994      quote_doubled_str = ap_palloc(p, len + num_quotes + 1);
3995 @@ -2271,3 +2316,11 @@
3996      }
3997      *dest = 0;
3998  }
3999 +
4000 +#ifdef NEED_GETADDRINFO
4001 +#include "getaddrinfo.c"
4002 +#endif
4003 +
4004 +#ifdef NEED_GETNAMEINFO
4005 +#include "getnameinfo.c"
4006 +#endif
4007 diff -Nru apache_1.3.20/src/main/util_script.c apache_1.3.20.new/src/main/util_script.c
4008 --- apache_1.3.20/src/main/util_script.c        Wed May  9 07:17:11 2001
4009 +++ apache_1.3.20.new/src/main/util_script.c    Mon May 21 10:54:52 2001
4010 @@ -67,6 +67,7 @@
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"
4015  
4016  #ifdef OS2
4017  #define INCL_DOS
4018 @@ -208,6 +209,7 @@
4019      array_header *hdrs_arr = ap_table_elts(r->headers_in);
4020      table_entry *hdrs = (table_entry *) hdrs_arr->elts;
4021      int i;
4022 +    char servbuf[NI_MAXSERV];
4023  
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 */
4029  
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),
4036 +#else
4037 +                    c->remote_addr.ss_len,
4038 +#endif
4039 +                    NULL, 0, servbuf, sizeof(servbuf), NI_NUMERICSERV)){
4040 +       ap_table_addn(e, "REMOTE_PORT", ap_pstrdup(r->pool, servbuf));
4041 +    }
4042  
4043      if (c->user) {
4044         ap_table_addn(e, "REMOTE_USER", c->user);
4045 diff -Nru apache_1.3.20/src/main/util_uri.c apache_1.3.20.new/src/main/util_uri.c
4046 --- apache_1.3.20/src/main/util_uri.c   Sun Apr  8 09:50:02 2001
4047 +++ apache_1.3.20.new/src/main/util_uri.c       Mon May 21 10:54:52 2001
4048 @@ -418,6 +418,12 @@
4049           * the hostname.  If there's a port it is the first colon.
4050           */
4051          s = memchr(hostinfo, ':', uri - hostinfo);
4052 +       if (*hostinfo == '[') {
4053 +           s = memchr(hostinfo+1, ']', uri - hostinfo - 1);
4054 +           if (s)
4055 +               s = strchr(s, ':');
4056 +       } else
4057 +           s = memchr(hostinfo, ':', uri - hostinfo);              
4058          if (s == NULL) {
4059              /* we expect the common case to have no port */
4060              uptr->hostname = ap_pstrndup(p, hostinfo, uri - hostinfo);
4061 @@ -474,7 +480,12 @@
4062      /* We expect hostinfo to point to the first character of
4063       * the hostname.  There must be a port, separated by a colon
4064       */
4065 -    s = strchr(hostinfo, ':');
4066 +    if (*hostinfo == '[') {
4067 +        s = strchr(hostinfo+1, ']');
4068 +        if (s)
4069 +            s = strchr(s, ':');
4070 +    } else
4071 +        s = strchr(hostinfo, ':');
4072      if (s == NULL) {
4073          return HTTP_BAD_REQUEST;
4074      }
4075 diff -Nru apache_1.3.20/src/modules/proxy/mod_proxy.c apache_1.3.20.new/src/modules/proxy/mod_proxy.c
4076 --- apache_1.3.20/src/modules/proxy/mod_proxy.c Mon May 21 11:02:04 2001
4077 +++ apache_1.3.20.new/src/modules/proxy/mod_proxy.c     Mon May 21 10:54:52 2001
4078 @@ -555,11 +555,31 @@
4079      struct proxy_remote *new;
4080      char *p, *q;
4081      int port;
4082 +    char *bl = NULL, *br = NULL;
4083  
4084      p = strchr(r, ':');
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, ':');
4088 +    bl = p + 3;
4089 +    if (*bl == '['){
4090 +       br = strrchr(bl+1, ']');
4091 +       if (br){
4092 +           bl++;
4093 +           *br = '\0';
4094 +           if (*(br+1) == ':'){        /* [host]:xx */
4095 +               q = br+1;
4096 +           }
4097 +           else if (*(br+1) == '\0'){  /* [host] */
4098 +               q = NULL;
4099 +           }
4100 +           else
4101 +               q = strrchr(br, ':');   /* XXX */
4102 +       }
4103 +       else
4104 +           q = strrchr(bl, ':');       /* XXX */
4105 +    }
4106 +    else
4107 +       q = strrchr(bl, ':');
4108      if (q != NULL) {
4109         if (sscanf(q + 1, "%u", &port) != 1 || port > 65535)
4110             return "ProxyRemote: Bad syntax for a remote proxy server (bad port number)";
4111 @@ -570,7 +590,7 @@
4112      *p = '\0';
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 */
4117  
4118      if (port == -1) {
4119         int i;
4120 @@ -583,7 +603,7 @@
4121      new = ap_push_array(conf->proxies);
4122      new->scheme = f;
4123      new->protocol = r;
4124 -    new->hostname = p + 3;
4125 +    new->hostname = bl;
4126      new->port = port;
4127      return NULL;
4128  }
4129 diff -Nru apache_1.3.20/src/modules/proxy/mod_proxy.h apache_1.3.20.new/src/modules/proxy/mod_proxy.h
4130 --- apache_1.3.20/src/modules/proxy/mod_proxy.h Mon Jan 15 18:05:28 2001
4131 +++ apache_1.3.20.new/src/modules/proxy/mod_proxy.h     Mon May 21 10:54:52 2001
4132 @@ -318,7 +318,7 @@
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 -Nru apache_1.3.20/src/modules/proxy/proxy_connect.c apache_1.3.20.new/src/modules/proxy/proxy_connect.c
4142 --- apache_1.3.22/src/modules/proxy/proxy_connect.c.orig        Fri Oct  5 10:19:15 2001
4143 +++ apache_1.3.20/src/modules/proxy/proxy_connect.c     Fri Nov 16 05:27:07 2001
4144 @@ -114,14 +114,15 @@
4145                           const char *proxyhost, int proxyport)
4146  {
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;
4154      char *p;
4155      int port, sock;
4156      char buffer[HUGE_STRING_LEN];
4157 -    int nbytes, i, j;
4158 +    int nbytes, i;
4159      fd_set fds;
4160 +    int error;
4161  
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;
4166  
4167      memset(&server, '\0', sizeof(server));
4168 +#ifdef HAVE_SOCKADDR_LEN
4169 +    server.sin_len = sizeof(server);
4170 +#endif
4171      server.sin_family = AF_INET;
4172  
4173      /* Break the URL into host:port pairs */
4174  
4175 -    host = url;
4176 +    hoststr = url;
4177      p = strchr(url, ':');
4178 -    if (p == NULL)
4179 -       port = DEFAULT_HTTPS_PORT;
4180 -    else {
4181 -       port = atoi(p + 1);
4182 +    if (p == NULL) {
4183 +       char pbuf[32];
4184 +       ap_snprintf(pbuf, sizeof(pbuf), "%d", DEFAULT_HTTPS_PORT);
4185 +       portstr = pbuf;
4186 +    } else {
4187 +       portstr = p + 1;
4188         *p = '\0';
4189      }
4190 +    port = atoi(portstr);
4191 +
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);
4197 +    if (error) {
4198 +       return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
4199 +                   gai_strerror(error));       /* give up */
4200 +    }
4201  
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;
4209 +       int fail;
4210 +
4211 +       fail = 0;
4212 +       for (i = 0; i < conf->noproxies->nelts; i++) {
4213 +           if (npent[i].name != NULL && strstr(hoststr, npent[i].name))
4214 +               fail++;
4215 +           if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0)
4216 +               fail++;
4217 +           switch (res->ai_family) {
4218 +           case AF_INET:
4219 +               sin = (struct sockaddr_in *)res->ai_addr;
4220 +               if (sin->sin_addr.s_addr == npent[i].addr.s_addr)
4221 +                   fail++;
4222 +               break;
4223 +           }
4224 +       }
4225 +       if (fail) {
4226 +           freeaddrinfo(res0);
4227             return ap_proxyerror(r, HTTP_FORBIDDEN,
4228                                  "Connect to remote machine blocked");
4229 +       }
4230      }
4231  
4232      /* Check if it is an allowed port */
4233 @@ -159,59 +193,64 @@
4234             case DEFAULT_SNEWS_PORT:
4235                 break;
4236             default:
4237 +               freeaddrinfo(res0);
4238                 return HTTP_FORBIDDEN;
4239         }
4240 -    } else if(!allowed_port(conf, port))
4241 +    } else if(!allowed_port(conf, port)) {
4242 +       freeaddrinfo(res0);
4243         return HTTP_FORBIDDEN;
4244 +    }
4245  
4246      if (proxyhost) {
4247 +       char pbuf[10];
4248 +
4249 +       freeaddrinfo(res0);
4250 +
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);
4257 +       if (error)
4258 +           return HTTP_INTERNAL_SERVER_ERROR;  /* XXX */
4259 +
4260         ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "CONNECT to remote proxy %s on port %d", proxyhost, proxyport);
4261      }
4262      else {
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);
4265      }
4266  
4267 -    server.sin_port = (proxyport ? htons(proxyport) : htons(port));
4268 -    err = ap_proxy_host2addr(proxyhost ? proxyhost : host, &server_hp);
4269 -
4270 -    if (err != NULL)
4271 -       return ap_proxyerror(r,
4272 -                            proxyhost ? HTTP_BAD_GATEWAY : HTTP_INTERNAL_SERVER_ERROR,
4273 -                            err);
4274 -
4275 -    sock = ap_psocket(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP);
4276 -    if (sock == -1) {
4277 -       ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4278 -                   "proxy: error creating socket");
4279 -       return HTTP_INTERNAL_SERVER_ERROR;
4280 -    }
4281 +    sock = i = -1;
4282 +    for (res = res0; res; res = res->ai_next) {
4283 +       sock = ap_psocket(r->pool, res->ai_family, res->ai_socktype, res->ai_protocol);
4284 +       if (sock == -1)
4285 +           continue;
4286  
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;
4296 -    }
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);
4305 +           continue;
4306 +       }
4307  #endif
4308  
4309 -    j = 0;
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);
4315         if (i == 0)
4316             break;
4317 -       j++;
4318      }
4319 +    freeaddrinfo(res0);
4320      if (i == -1) {
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));
4329      }
4330  
4331      /* If we are connecting through a remote proxy, we need to pass
4332 diff -Nru apache_1.3.20/src/modules/proxy/proxy_ftp.c apache_1.3.20.new/src/modules/proxy/proxy_ftp.c
4333 --- apache_1.3.22/src/modules/proxy/proxy_ftp.c.orig    Fri Oct  5 10:19:15 2001
4334 +++ apache_1.3.22/src/modules/proxy/proxy_ftp.c Fri Nov 16 05:34:23 2001
4335 @@ -62,6 +62,7 @@
4336  #include "http_main.h"
4337  #include "http_log.h"
4338  #include "http_core.h"
4339 +#include "sa_len.h"
4340  
4341  #define AUTODETECT_PWD
4342  
4343 @@ -451,8 +452,10 @@
4344      const char *err;
4345      int port, i, j, len, sock, dsock, rc, nocache = 0;
4346      int csd = 0;
4347 -    struct sockaddr_in server;
4348 -    struct hostent server_hp;
4349 +    struct sockaddr_storage server;
4350 +    struct addrinfo hints, *res, *res0;
4351 +    char portbuf[10];
4352 +    int error;
4353      struct in_addr destaddr;
4354      table *resp_hdrs;
4355      BUFF *f;
4356 @@ -473,11 +476,18 @@
4357      unsigned int presult, h0, h1, h2, h3, p0, p1;
4358      unsigned int paddr;
4359      unsigned short pport;
4360 -    struct sockaddr_in data_addr;
4361 +    struct sockaddr_storage data_addr;
4362 +    struct sockaddr_in *sin;
4363      int pasvmode = 0;
4364      char pasv[64];
4365      char *pstr;
4366  
4367 +/* stuff for LPSV/EPSV */
4368 +    unsigned int paf, holen, ho[16], polen, po[2];
4369 +    struct sockaddr_in6 *sin6;
4370 +    int lpsvmode = 0;
4371 +    char *cmd;
4372 +
4373  /* stuff for responses */
4374      char resp[MAX_STRING_LEN];
4375      char *size = NULL;
4376 @@ -547,62 +557,52 @@
4377      if (parms != NULL)
4378         *(parms++) = '\0';
4379  
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);
4384 -    if (err != NULL)
4385 -       return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
4386 -
4387 -    sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
4388 -    if (sock == -1) {
4389 -       ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4390 -                    "proxy: error creating socket");
4391 -       return HTTP_INTERNAL_SERVER_ERROR;
4392 -    }
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);
4398 +    if (error) {
4399 +       return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
4400 +           gai_strerror(error));
4401 +    }
4402 +
4403 +    i = -1;
4404 +    for (res = res0; res; res = res->ai_next) {
4405 +       sock = ap_psocket(p, res->ai_family, res->ai_socktype,
4406 +           res->ai_protocol);
4407 +       if (sock == -1)
4408 +           continue;
4409  
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))
4414 -           == -1) {
4415 -           ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4416 -                        "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
4417 -    }
4418 +       if (conf->recv_buffer_size > 0
4419 +           && setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
4420 +                          (const char *) &conf->recv_buffer_size, sizeof(int))
4421 +               == -1) {
4422 +               ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4423 +                            "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
4424 +       }
4425  #endif
4426  
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*/
4442 -    }
4443 -
4444 -#ifdef SINIX_D_RESOLVER_BUG
4445 -    {
4446 -       struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list;
4447 -
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);
4451 -           if (i == 0)
4452 -               break;
4453         }
4454 -    }
4455 -#else
4456 -    j = 0;
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);
4461 -       if (i == 0)
4462 +
4463 +       i = ap_proxy_doconnect(sock, res->ai_addr, r);
4464 +       if (i == 0){
4465 +           memcpy(&server, res->ai_addr, res->ai_addrlen);
4466             break;
4467 -       j++;
4468 +       }
4469 +       ap_pclosesocket(p, sock);
4470      }
4471 -#endif
4472 +    freeaddrinfo(res0);
4473      if (i == -1) {
4474         ap_pclosesocket(p, sock);
4475         return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
4476 @@ -806,7 +806,7 @@
4477      }
4478  
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);
4482      if (dsock == -1) {
4483         ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4484                      "proxy: error creating PASV socket");
4485 @@ -825,11 +825,22 @@
4486      }
4487  #endif
4488  
4489 -    ap_bputs("PASV" CRLF, f);
4490 +lpsvagain:
4491 +    if (server.ss_family == AF_INET)
4492 +       cmd = "PASV";
4493 +    else if (lpsvmode)
4494 +       cmd = "LPSV";
4495 +    else
4496 +       cmd = "EPSV";
4497 +    ap_bputs(cmd, f);
4498 +    ap_bputs(CRLF, f);
4499      ap_bflush(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. */
4510 @@ -838,7 +849,7 @@
4511      i = ap_bgets(pasv, sizeof(pasv), f);
4512      if (i == -1) {
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);
4517         ap_bclose(f);
4518         ap_kill_timeout(r);
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;
4529 +#ifdef SIN6_LEN
4530 +           sin->sin_len = sizeof(*sin);
4531 +#endif
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);
4535  
4536             if (i == -1) {
4537                 ap_kill_timeout(r);
4538 @@ -881,17 +896,76 @@
4539                                      ap_pstrcat(r->pool,
4540                                                 "Could not connect to remote machine: ",
4541                                                 strerror(errno), NULL));
4542 +           } else {
4543 +               pasvmode = 1;
4544             }
4545 -           else {
4546 +       } else if (presult == 228 && pstr != NULL
4547 +               && sscanf(pstr,
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) {
4553 +           int i;
4554 +           sin6 = (struct sockaddr_in6 *)&data_addr;
4555 +           sin6->sin6_family = AF_INET6;
4556 +#ifdef SIN6_LEN
4557 +           sin6->sin6_len = sizeof(*sin6);
4558 +#endif
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);
4563 +
4564 +           if (i == -1) {
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));
4570 +           } else {
4571 +               pasvmode = 1;
4572 +           }
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|" */
4577 +#ifndef SIN6_LEN
4578 +           memcpy(&data_addr, &server, SA_LEN((struct sockaddr *)&server));
4579 +#else
4580 +           memcpy(&data_addr, &server, server.ss_len);
4581 +#endif
4582 +           switch (data_addr.ss_family) {
4583 +           case AF_INET:
4584 +               sin = (struct sockaddr_in *)&data_addr;
4585 +               sin->sin_port = htons(atoi(pstr + 3));
4586 +               break;
4587 +           case AF_INET6:
4588 +               sin6 = (struct sockaddr_in6 *)&data_addr;
4589 +               sin6->sin6_port = htons(atoi(pstr + 3));
4590 +               break;
4591 +           }
4592 +           i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r);
4593 +
4594 +           if (i == -1) {
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));
4600 +           } else {
4601                 pasvmode = 1;
4602             }
4603 +       } else if (!lpsvmode && strcmp(cmd, "EPSV") == 0) {
4604 +           lpsvmode = 1;
4605 +           goto lpsvagain;
4606         }
4607         else
4608             ap_pclosesocket(p, dsock);  /* and try the regular way */
4609      }
4610  
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");
4617 @@ -900,7 +974,7 @@
4618             return HTTP_INTERNAL_SERVER_ERROR;
4619         }
4620  
4621 -       dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
4622 +       dsock = ap_psocket(p, server.ss_family, SOCK_STREAM, IPPROTO_TCP);
4623         if (dsock == -1) {
4624             ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4625                          "proxy: error creating socket");
4626 @@ -921,13 +995,26 @@
4627  #endif /*_OSD_POSIX*/
4628         }
4629  
4630 -       if (bind(dsock, (struct sockaddr *) &server,
4631 -                sizeof(struct sockaddr_in)) == -1) {
4632 -           char buff[22];
4633 +#ifndef SIN6_LEN
4634 +       if (bind(dsock, (struct sockaddr *) &server, SA_LEN((struct sockaddr *)&server)) == -1)
4635 +#else
4636 +       if (bind(dsock, (struct sockaddr *) &server, server.ss_len) == -1)
4637 +#endif
4638 +       {
4639 +           char hostnamebuf[MAXHOSTNAMELEN], portnamebuf[MAXHOSTNAMELEN];
4640  
4641 -           ap_snprintf(buff, sizeof(buff), "%s:%d", inet_ntoa(server.sin_addr), server.sin_port);
4642 +           getnameinfo((struct sockaddr *)&server,
4643 +#ifndef SIN6_LEN
4644 +                   SA_LEN((struct sockaddr *)&server),
4645 +#else
4646 +                   server.ss_len,
4647 +#endif
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);
4655             ap_bclose(f);
4656             ap_pclosesocket(p, dsock);
4657             return HTTP_INTERNAL_SERVER_ERROR;
4658 @@ -1186,7 +1273,7 @@
4659  
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);
4664         do
4665             csd = accept(dsock, (struct sockaddr *) &server, &clen);
4666         while (csd == -1 && errno == EINTR);
4667 diff -Nru apache_1.3.20/src/modules/proxy/proxy_http.c apache_1.3.20.new/src/modules/proxy/proxy_http.c
4668 --- apache_1.3.20/src/modules/proxy/proxy_http.c        Mon May 21 11:02:04 2001
4669 +++ apache_1.3.20.new/src/modules/proxy/proxy_http.c    Mon May 21 10:54:52 2001
4670 @@ -177,9 +177,8 @@
4671      array_header *reqhdrs_arr;
4672      table *resp_hdrs;
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;
4678 +    int error;
4679      BUFF *f;
4680      char buffer[HUGE_STRING_LEN];
4681      char portstr[32];
4682 @@ -201,9 +200,6 @@
4683      struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts;
4684      int nocache = 0;
4685  
4686 -    memset(&server, '\0', sizeof(server));
4687 -    server.sin_family = AF_INET;
4688 -
4689  /* We break the URL into host, port, path-search */
4690  
4691      urlptr = strstr(url, "://");
4692 @@ -211,6 +207,8 @@
4693         return HTTP_BAD_REQUEST;
4694      urlptr += 3;
4695      destport = DEFAULT_HTTP_PORT;
4696 +    ap_snprintf(portstr, sizeof(portstr), "%d", DEFAULT_HTTP_PORT);
4697 +    destportstr = portstr;           
4698  #ifdef EAPI
4699      ap_hook_use("ap::mod_proxy::http::handler::set_destport", 
4700                  AP_HOOK_SIG2(int,ptr), 
4701 @@ -229,7 +227,20 @@
4702         urlptr = strp;
4703         desthost = q;
4704      }
4705 -
4706 +   if (*desthost == '['){
4707 +       char *u = strrchr(desthost+1, ']');
4708 +       if (u){
4709 +          desthost++;
4710 +          *u = '\0';
4711 +          if (*(u+1) == ':'){ /* [host]:xx */
4712 +              strp2 = u+1;
4713 +          } else if (*(u+1) == '\0'){   /* [host] */
4714 +              strp2 = NULL;
4715 +          } else
4716 +              return HTTP_BAD_REQUEST;
4717 +       } else
4718 +           return HTTP_BAD_REQUEST;
4719 +   } else
4720      strp2 = strchr(desthost, ':');
4721      if (strp2 != NULL) {
4722         *(strp2++) = '\0';
4723 @@ -240,41 +251,69 @@
4724      }
4725  
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);
4737 +     if (error) {
4738 +       return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
4739 +               gai_strerror(error));       /* give up */
4740 +     }
4741 +    
4742 + /* check if ProxyBlock directive on this host */
4743 +     for (res = res0; res; res = res->ai_next) {
4744 +       struct sockaddr_in *sin;
4745 + #ifdef INET6
4746 +       struct sockaddr_in6 *sin6;
4747 + #endif
4748 +       int fail;
4749 +       
4750 +       fail = 0;
4751 +       for (i = 0; i < conf->noproxies->nelts; i++) {
4752 +           if (npent[i].name != NULL && strstr(desthost, npent[i].name))
4753 +               fail++;
4754 +           if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0)
4755 +               fail++;
4756 +           switch (res->ai_family) {
4757 +               case AF_INET:
4758 +                   sin = (struct sockaddr_in *)res->ai_addr;
4759 +                   if (sin->sin_addr.s_addr == npent[i].addr.s_addr)
4760 +                       fail++;
4761 +                   break;
4762 +                   }
4763 +           }
4764 +       if (fail) {
4765 +           freeaddrinfo(res0);                  
4766              return ap_proxyerror(r, HTTP_FORBIDDEN,
4767                                   "Connect to remote machine blocked");
4768 -    }
4769 -
4770 -    if (proxyhost != NULL) {
4771 -       server.sin_port = htons(proxyport);
4772 -       err = ap_proxy_host2addr(proxyhost, &server_hp);
4773 -       if (err != NULL)
4774 -           return DECLINED;    /* try another */
4775 -#ifdef EAPI
4776 -       peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport);  
4777 -#endif
4778 -    }
4779 -    else {
4780 -       server.sin_port = htons(destport);
4781 -       err = ap_proxy_host2addr(desthost, &server_hp);
4782 -       if (err != NULL)
4783 -           return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
4784 -#ifdef EAPI
4785 -       peer =  ap_psprintf(p, "%s:%u", desthost, destport);  
4786 -#endif
4787 -    }
4788 -
4789 -    sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP);
4790 -    if (sock == -1) {
4791 -       ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
4792 -                   "proxy: error creating socket");
4793 -       return HTTP_INTERNAL_SERVER_ERROR;
4794 -    }
4795 -
4796 +       }
4797 +      }
4798 +  
4799 +      if (proxyhost != NULL) {
4800 +       char pbuf[10];
4801 +       
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);
4809 +       if (error)
4810 +            return DECLINED;    /* try another */
4811 +  #ifdef EAPI
4812 +        peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport);  
4813 +  #endif
4814 +      }
4815 +  
4816 +     sock = i = -1;
4817 +     for (res = res0; res; res = res->ai_next) {
4818 +       sock = ap_psocket(p, res->ai_family, res->ai_socktype,
4819 +               res->ai_protocol);
4820 +       if (sock < 0)
4821 +           continue;
4822 +    
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 @@
4827      }
4828  #endif
4829  
4830 -#ifdef SINIX_D_RESOLVER_BUG
4831 -    {
4832 -       struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list;
4833 -
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);
4837 -           if (i == 0)
4838 -               break;
4839 -       }
4840 -    }
4841 -#else
4842 -    j = 0;
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);
4848         if (i == 0)
4849             break;
4850 -       j++;
4851 +       ap_pclosesocket(p, sock); 
4852      }
4853 -#endif
4854 +    freeaddrinfo(res0);
4855      if (i == -1) {
4856         if (proxyhost != NULL)
4857             return DECLINED;    /* try again another way */
4858 @@ -515,17 +538,31 @@
4859         ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, datestr));
4860  
4861  /* check if NoCache directive on this host */
4862 +  {
4863 +    struct sockaddr_in *sin;
4864 +#ifdef INET6
4865 +    struct sockaddr_in6 *sin6;
4866 +#endif
4867 +
4868      if (nocache == 0) {
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))) {
4874 -              nocache = 1;
4875 -              break;
4876 +           if (ncent[i].name != NULL && 
4877 +               (ncent[i].name[0] == '*' ||
4878 +                strstr(desthost, ncent[i].name) != NULL)) {
4879 +               nocache = 1;
4880 +               break;
4881 +           }
4882 +           switch (res->ai_addr->sa_family) {
4883 +           case AF_INET:
4884 +               sin = (struct sockaddr_in *)res->ai_addr;
4885 +               if (sin->sin_addr.s_addr == ncent[i].addr.s_addr) {
4886 +                   nocache = 1;
4887 +                   break;
4888 +               }
4889             }
4890         }
4891      }
4892 +  }
4893  
4894      i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache);
4895      if (i != DECLINED) {
4896 diff -Nru apache_1.3.20/src/modules/proxy/proxy_util.c apache_1.3.20.new/src/modules/proxy/proxy_util.c
4897 --- apache_1.3.20/src/modules/proxy/proxy_util.c        Fri Mar 16 08:01:23 2001
4898 +++ apache_1.3.20.new/src/modules/proxy/proxy_util.c    Mon May 21 10:54:52 2001
4899 @@ -64,6 +64,7 @@
4900  #include "http_log.h"
4901  #include "util_uri.h"
4902  #include "util_date.h" /* get ap_checkmask() decl. */
4903 +#include "sa_len.h"
4904  
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);
4907 @@ -218,6 +219,7 @@
4908      int i;
4909      char *strp, *host, *url = *urlp;
4910      char *user = NULL, *password = NULL;
4911 +    char *t = NULL, *u = NULL, *v = NULL;
4912  
4913      if (url[0] != '/' || url[1] != '/')
4914         return "Malformed URL";
4915 @@ -256,11 +258,22 @@
4916         *passwordp = password;
4917      }
4918  
4919 -    strp = strrchr(host, ':');
4920 -    if (strp != NULL) {
4921 -       *(strp++) = '\0';
4922 -
4923 -       for (i = 0; strp[i] != '\0'; i++)
4924 +    v = host;
4925 +    if (*host == '['){
4926 +       u = strrchr(host, ']');
4927 +       if (u){
4928 +           host++;
4929 +           *u = '\0';
4930 +           v = u + 1;
4931 +       }
4932 +    }
4933 +    t = strrchr(v, ':');
4934 +    if (t){
4935 +       *t = '\0';
4936 +       strp = t + 1;
4937 +    }
4938 +    if (strp){
4939 +       for (i=0; strp[i] != '\0'; i++)
4940             if (!ap_isdigit(strp[i]))
4941                 break;
4942  
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] != ':')
4949             break;
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";
4954 +#else
4955 +    if (host[i] == '\0') {
4956 +       struct addrinfo hints, *res0;
4957 +       int gai;
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)) {
4962 +#if 0
4963 +           return gai_strerror(gai);
4964  #else
4965 -    if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
4966 +           return "Bad IP address in URL";
4967  #endif
4968 -    {
4969 -       return "Bad IP address in URL";
4970 +       }
4971 +       freeaddrinfo(res0);
4972      }
4973 +#endif
4974  
4975  /*    if (strchr(host,'.') == NULL && domain != NULL)
4976     host = pstrcat(p, host, domain, NULL);
4977 @@ -1238,22 +1263,45 @@
4978      return host != NULL && strstr(host, This->name) != NULL;
4979  }
4980  
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)
4983  {
4984      int i;
4985 +    int salen;
4986 +    char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
4987 +#ifdef NI_WITHSCOPEID
4988 +    const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
4989 +#else
4990 +    const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
4991 +#endif
4992  
4993      ap_hard_timeout("proxy connect", r);
4994 +#ifdef HAVE_SOCKADDR_LEN
4995 +    salen = addr->sa_len;
4996 +#else
4997 +    switch (addr->sa_family) {
4998 +    case AF_INET6:
4999 +       salen = sizeof(struct sockaddr_in6);
5000 +       break;
5001 +    default:
5002 +       salen = sizeof(struct sockaddr_in);
5003 +       break;
5004 +    }
5005 +#endif
5006      do {
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();
5012  #endif /* WIN32 */
5013      } while (i == -1 && errno == EINTR);
5014      if (i == -1) {
5015 +       if (getnameinfo(addr, salen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
5016 +               niflags) != 0) {
5017 +           strcpy(hbuf, "?");
5018 +           strcpy(pbuf, "?");
5019 +       }
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);
5024      }
5025      ap_kill_timeout(r);
5026  
5027 diff -Nru apache_1.3.20/src/modules/standard/mod_access.c apache_1.3.20.new/src/modules/standard/mod_access.c
5028 --- apache_1.3.20/src/modules/standard/mod_access.c     Mon Jan 15 18:05:34 2001
5029 +++ apache_1.3.20.new/src/modules/standard/mod_access.c Mon May 21 10:54:52 2001
5030 @@ -74,7 +74,10 @@
5031      T_ALL,
5032      T_IP,
5033      T_HOST,
5034 -    T_FAIL
5035 +    T_FAIL,
5036 +#ifdef INET6
5037 +    T_IP6,
5038 +#endif
5039  };
5040  
5041  typedef struct {
5042 @@ -82,9 +85,15 @@
5043      union {
5044         char *from;
5045         struct {
5046 -           unsigned long net;
5047 -           unsigned long mask;
5048 +           struct in_addr net;
5049 +           struct in_addr mask;
5050         } ip;
5051 +#ifdef INET6
5052 +       struct {
5053 +           struct in6_addr net6;
5054 +           struct in6_addr mask6;
5055 +       } ip6;
5056 +#endif
5057      } x;
5058      enum allowdeny_type type;
5059  } allowdeny;
5060 @@ -167,90 +176,230 @@
5061  
5062      }
5063      else if ((s = strchr(where, '/'))) {
5064 -       unsigned long mask;
5065 +       struct addrinfo hints, *resnet, *resmask;
5066 +       struct sockaddr_storage net, mask;
5067 +       int error;
5068 +       char *p;
5069 +       int justdigits;
5070  
5071 -       a->type = T_IP;
5072 +       a->type = T_FAIL;       /*just in case*/
5073         /* trample on where, we won't be using it any more */
5074         *s++ = '\0';
5075  
5076 -       if (!is_ip(where)
5077 -           || (a->x.ip.net = ap_inet_addr(where)) == INADDR_NONE) {
5078 +       justdigits = 0;
5079 +       for (p = s; *p; p++) {
5080 +           if (!isdigit(*p))
5081 +               break;
5082 +       }
5083 +       if (!*p)
5084 +           justdigits++;
5085 +
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*/
5091 +#endif
5092 +       resnet = NULL;
5093 +       error = getaddrinfo(where, NULL, &hints, &resnet);
5094 +       if (error || !resnet) {
5095 +           if (resnet)
5096 +               freeaddrinfo(resnet);
5097             a->type = T_FAIL;
5098             return "syntax error in network portion of network/netmask";
5099         }
5100 +       if (resnet->ai_next) {
5101 +           freeaddrinfo(resnet);
5102 +           a->type = T_FAIL;
5103 +           return "network/netmask resolved to multiple addresses";
5104 +       }
5105 +       memcpy(&net, resnet->ai_addr, resnet->ai_addrlen);
5106 +       freeaddrinfo(resnet);
5107  
5108 -       /* is_ip just tests if it matches [\d.]+ */
5109 -       if (!is_ip(s)) {
5110 +       switch (net.ss_family) {
5111 +       case AF_INET:
5112 +           a->type = T_IP;
5113 +           a->x.ip.net.s_addr = ((struct sockaddr_in *)&net)->sin_addr.s_addr;
5114 +           break;
5115 +#ifdef INET6
5116 +       case AF_INET6:
5117 +           a->type = T_IP6;
5118 +           memcpy(&a->x.ip6.net6, &((struct sockaddr_in6 *)&net)->sin6_addr,
5119 +               sizeof(a->x.ip6.net6));
5120 +           break;
5121 +#endif
5122 +       default:
5123             a->type = T_FAIL;
5124 -           return "syntax error in mask portion of network/netmask";
5125 +           return "unknown address family for network";
5126         }
5127 -       /* is it in /a.b.c.d form? */
5128 -       if (strchr(s, '.')) {
5129 -           mask = ap_inet_addr(s);
5130 -           if (mask == INADDR_NONE) {
5131 +
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*/
5138 +#endif
5139 +           resmask = NULL;
5140 +           error = getaddrinfo(s, NULL, &hints, &resmask);
5141 +           if (error || !resmask) {
5142 +               if (resmask)
5143 +                   freeaddrinfo(resmask);
5144                 a->type = T_FAIL;
5145                 return "syntax error in mask portion of network/netmask";
5146             }
5147 -       }
5148 -       else {
5149 -           /* assume it's in /nnn form */
5150 -           mask = atoi(s);
5151 -           if (mask > 32 || mask <= 0) {
5152 -               a->type = T_FAIL;
5153 -               return "invalid mask in network/netmask";
5154 -           }
5155 -           mask = 0xFFFFFFFFUL << (32 - mask);
5156 -           mask = htonl(mask);
5157 -       }
5158 -       a->x.ip.mask = mask;
5159 -        a->x.ip.net  = (a->x.ip.net & mask);   /* pjr - This fixes PR 4770 */
5160 -    }
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 */
5163 -       int shift;
5164 -       char *t;
5165 -       int octet;
5166 -
5167 -       a->type = T_IP;
5168 -       /* parse components */
5169 -       s = where;
5170 -       a->x.ip.net = 0;
5171 -       a->x.ip.mask = 0;
5172 -       shift = 24;
5173 -       while (*s) {
5174 -           t = s;
5175 -           if (!ap_isdigit(*t)) {
5176 +           if (resmask->ai_next) {
5177 +               freeaddrinfo(resmask);
5178                 a->type = T_FAIL;
5179 -               return "invalid ip address";
5180 +               return "network/netmask resolved to multiple addresses";
5181             }
5182 -           while (ap_isdigit(*t)) {
5183 -               ++t;
5184 -           }
5185 -           if (*t == '.') {
5186 -               *t++ = 0;
5187 -           }
5188 -           else if (*t) {
5189 +           memcpy(&mask, resmask->ai_addr, resmask->ai_addrlen);
5190 +           freeaddrinfo(resmask);
5191 +
5192 +           if (net.ss_family != mask.ss_family) {
5193                 a->type = T_FAIL;
5194 -               return "invalid ip address";
5195 +               return "network/netmask resolved to different address family";
5196             }
5197 -           if (shift < 0) {
5198 -               return "invalid ip address, only 4 octets allowed";
5199 +
5200 +           switch (a->type) {
5201 +           case T_IP:
5202 +               a->x.ip.mask.s_addr =
5203 +                   ((struct sockaddr_in *)&mask)->sin_addr.s_addr;
5204 +               break;
5205 +#ifdef INET6
5206 +           case T_IP6:
5207 +               memcpy(&a->x.ip6.mask6,
5208 +                   &((struct sockaddr_in6 *)&mask)->sin6_addr,
5209 +                   sizeof(a->x.ip6.mask6));
5210 +               break;
5211 +#endif
5212             }
5213 -           octet = atoi(s);
5214 -           if (octet < 0 || octet > 255) {
5215 -               a->type = T_FAIL;
5216 -               return "each octet must be between 0 and 255 inclusive";
5217 +       } else {
5218 +           int mask;
5219 +           mask = atoi(s);
5220 +           switch (a->type) {
5221 +           case T_IP:
5222 +               if (mask < 0 || 32 < mask) {
5223 +                   a->type = T_FAIL;
5224 +                   return "netmask out of range";
5225 +               }
5226 +               a->x.ip.mask.s_addr = htonl(0xFFFFFFFFUL << (32 - mask));
5227 +               break;
5228 +#ifdef INET6
5229 +           case T_IP6:
5230 +             {
5231 +               int i;
5232 +               if (mask < 0 || 128 < mask) {
5233 +                   a->type = T_FAIL;
5234 +                   return "netmask out of range";
5235 +               }
5236 +               for (i = 0; i < mask / 8; i++) {
5237 +                   a->x.ip6.mask6.s6_addr[i] = 0xff;
5238 +               }
5239 +               if (mask % 8)
5240 +                   a->x.ip6.mask6.s6_addr[i] = 0xff << (8 - (mask % 8));
5241 +               break;
5242 +             }
5243 +#endif
5244             }
5245 -           a->x.ip.net |= octet << shift;
5246 -           a->x.ip.mask |= 0xFFUL << shift;
5247 -           s = t;
5248 -           shift -= 8;
5249         }
5250 -       a->x.ip.net = ntohl(a->x.ip.net);
5251 -       a->x.ip.mask = ntohl(a->x.ip.mask);
5252      }
5253      else {
5254 -       a->type = T_HOST;
5255 +       struct addrinfo hints, *res;
5256 +       struct sockaddr_storage ss;
5257 +       int error;
5258 +
5259 +       a->type = T_FAIL;       /*just in case*/
5260 +
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)) {
5264 +           int shift;
5265 +           char *t;
5266 +           int octet;
5267 +
5268 +           a->type = T_IP;
5269 +           /* parse components */
5270 +           s = where;
5271 +           a->x.ip.net.s_addr = 0;
5272 +           a->x.ip.mask.s_addr = 0;
5273 +           shift = 24;
5274 +           while (*s) {
5275 +               t = s;
5276 +               if (!ap_isdigit(*t)) {
5277 +                   a->type = T_FAIL;
5278 +                   return "invalid ip address";
5279 +               }
5280 +               while (ap_isdigit(*t)) {
5281 +                   ++t;
5282 +               }
5283 +               if (*t == '.') {
5284 +                   *t++ = 0;
5285 +               }
5286 +               else if (*t) {
5287 +                   a->type = T_FAIL;
5288 +                   return "invalid ip address";
5289 +               }
5290 +               if (shift < 0) {
5291 +                   return "invalid ip address, only 4 octets allowed";
5292 +               }
5293 +               octet = atoi(s);
5294 +               if (octet < 0 || octet > 255) {
5295 +                   a->type = T_FAIL;
5296 +                   return "each octet must be between 0 and 255 inclusive";
5297 +               }
5298 +               a->x.ip.net.s_addr |= octet << shift;
5299 +               a->x.ip.mask.s_addr |= 0xFFUL << shift;
5300 +               s = t;
5301 +               shift -= 8;
5302 +           }
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);
5305 +
5306 +           return NULL;
5307 +       }
5308 +
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*/
5315 +#endif
5316 +       res = NULL;
5317 +       error = getaddrinfo(where, NULL, &hints, &res);
5318 +       if (error || !res) {
5319 +           if (res)
5320 +               freeaddrinfo(res);
5321 +           a->type = T_HOST;
5322 +           return NULL;
5323 +       }
5324 +       if (res->ai_next) {
5325 +           freeaddrinfo(res);
5326 +           a->type = T_FAIL;
5327 +           return "network/netmask resolved to multiple addresses";
5328 +       }
5329 +       memcpy(&ss, res->ai_addr, res->ai_addrlen);
5330 +       freeaddrinfo(res);
5331 +
5332 +       switch (ss.ss_family) {
5333 +       case AF_INET:
5334 +           a->type = T_IP;
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));
5337 +           break;
5338 +#ifdef INET6
5339 +       case AF_INET6:
5340 +           a->type = T_IP6;
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));
5344 +           break;
5345 +#endif
5346 +       default:
5347 +           a->type = T_FAIL;
5348 +           return "unknown address family for network";
5349 +       }
5350      }
5351  
5352      return NULL;
5353 @@ -315,12 +464,63 @@
5354             return 1;
5355  
5356         case T_IP:
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) {
5360 -               return 1;
5361 +           if (ap[i].x.ip.net.s_addr == INADDR_NONE)
5362 +               break;
5363 +           switch (r->connection->remote_addr.ss_family) {
5364 +           case AF_INET:
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) {
5367 +                   return 1;
5368 +               }
5369 +               break;
5370 +#ifdef INET6
5371 +           case AF_INET6:
5372 +               if (!IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr))    /*XXX*/
5373 +                   break;
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) {
5376 +                   return 1;
5377 +               }
5378 +               break;
5379 +#endif
5380 +           }
5381 +           break;
5382 +
5383 +#ifdef INET6
5384 +       case T_IP6:
5385 +         {
5386 +           struct in6_addr masked;
5387 +           int j;
5388 +           if (IN6_IS_ADDR_UNSPECIFIED(&ap[i].x.ip6.net6))
5389 +               break;
5390 +           switch (r->connection->remote_addr.ss_family) {
5391 +           case AF_INET:
5392 +               if (!IN6_IS_ADDR_V4MAPPED(&ap[i].x.ip6.net6))   /*XXX*/
5393 +                   break;
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)
5402 +                   return 1;
5403 +               break;
5404 +           case AF_INET6:
5405 +               memset(&masked, 0, sizeof(masked));
5406 +               memcpy(&masked,
5407 +                   &((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr,
5408 +                   sizeof(masked));
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)
5412 +                   return 1;
5413 +               break;
5414             }
5415             break;
5416 +         }
5417 +#endif
5418  
5419         case T_HOST:
5420             if (!gothost) {
5421 diff -Nru apache_1.3.20/src/modules/standard/mod_unique_id.c apache_1.3.20.new/src/modules/standard/mod_unique_id.c
5422 --- apache_1.3.22/src/modules/standard/mod_unique_id.c.orig     Tue Oct  2 18:11:13 2001
5423 +++ apache_1.3.22/src/modules/standard/mod_unique_id.c  Fri Nov 16 05:41:26 2001
5424 @@ -67,10 +67,22 @@
5425  #include "http_config.h"
5426  #include "http_log.h"
5427  #include "multithread.h"
5428 +#include "sa_len.h"
5429 +
5430 +/*#define SHORT_UNIQUE_ID*/
5431  
5432  typedef struct {
5433      unsigned int stamp;
5434 -    unsigned int in_addr;
5435 +    union {
5436 +       struct in_addr in;
5437 +#ifdef INET6
5438 +# ifdef SHORT_UNIQUE_ID
5439 +       ap_uint32_t in6;
5440 +# else
5441 +       struct in6_addr in6;
5442 +# endif
5443 +#endif
5444 +    } addr;
5445      unsigned int pid;
5446  #ifdef MULTITHREAD
5447      unsigned int tid;
5448 @@ -142,7 +154,7 @@
5449   * this shouldn't be a problem till year 2106.
5450   */
5451  
5452 -static unsigned global_in_addr;
5453 +static struct sockaddr_storage global_addr;
5454  
5455  #ifdef WIN32
5456  
5457 @@ -221,7 +233,8 @@
5458  #define MAXHOSTNAMELEN 256
5459  #endif
5460      char str[MAXHOSTNAMELEN + 1];
5461 -    struct hostent *hent;
5462 +    struct addrinfo hints, *res, *res0;
5463 +    int error;
5464  #ifndef NO_GETTIMEOFDAY
5465      struct timeval tv;
5466  #endif
5467 @@ -232,8 +245,8 @@
5468       */
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);
5477  #ifdef MULTITHREAD
5478 @@ -269,17 +282,44 @@
5479      }
5480      str[sizeof(str) - 1] = '\0';
5481  
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);
5486 +    if (error) {
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));
5491          exit(1);
5492      }
5493  
5494 -    global_in_addr = ((struct in_addr *) hent->h_addr_list[0])->s_addr;
5495 +    error = 1;
5496 +    for (res = res0; res; res = res->ai_next) {
5497 +       switch (res->ai_family) {
5498 +       case AF_INET:
5499 +#ifdef INET6
5500 +       case AF_INET6:
5501 +#endif
5502 +           memcpy(&global_addr, res->ai_addr, res->ai_addrlen);
5503 +           error = 0;
5504 +           break;
5505 +       }
5506 +    }
5507 +    freeaddrinfo(res0);
5508 +    if (error) {
5509 +        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s,
5510 +                    "mod_unique_id: no known AF found for \"%s\"", str);
5511 +        exit(1);
5512 +    }
5513  
5514 +    getnameinfo((struct sockaddr *)&global_addr,
5515 +#ifndef SIN6_LEN
5516 +       SA_LEN((struct sockaddr *)&global_addr),
5517 +#else
5518 +       global_addr.ss_len,
5519 +#endif
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);
5525  
5526      /*
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!");
5530      }
5531  
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) {
5535 +    case AF_INET:
5536 +       cur_unique_id.addr.in = ((struct sockaddr_in *)&global_addr)->sin_addr;
5537 +       break;
5538 +#ifdef INET6
5539 +    case AF_INET6:
5540 +#ifdef SHORT_UNIQUE_ID
5541 +       cur_unique_id.addr.in6 =
5542 +           ((struct sockaddr_in6 *)&global_addr)->sin6_addr.s6_addr32[3];
5543 +#else
5544 +       cur_unique_id.addr.in6 =
5545 +           ((struct sockaddr_in6 *)&global_addr)->sin6_addr;
5546 +#endif
5547 +       break;
5548 +#endif
5549 +    }
5550  
5551      /*
5552       * If we use 0 as the initial counter we have a little less protection
5553 diff -Nru apache_1.3.20/src/support/ab.c apache_1.3.20.new/src/support/ab.c
5554 --- apache_1.3.20/src/support/ab.c      Fri Mar  9 11:10:55 2001
5555 +++ apache_1.3.20.new/src/support/ab.c  Mon May 21 10:54:52 2001
5556 @@ -140,6 +140,8 @@
5557  #include <sys/uio.h>
5558  #endif
5559  
5560 +#include "sa_len.h"
5561 +
5562  #endif                         /* NO_APACHE_INCLUDES */
5563  /* ------------------- DEFINITIONS -------------------------- */
5564  
5565 @@ -195,7 +197,7 @@
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 */
5571  
5572  int use_html = 0;              /* use html in the report */
5573  char *tablestring;
5574 @@ -227,7 +229,7 @@
5575  struct data *stats;            /* date for each request */
5576  
5577  fd_set readbits, writebits;    /* bits for select */
5578 -struct sockaddr_in server;     /* server addr structure */
5579 +struct sockaddr_storage server;      /* server addr structure */
5580  
5581  #ifndef BEOS
5582  #define ab_close(s) close(s)
5583 @@ -332,7 +334,7 @@
5584      printf("\r                                                                           \r");
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);
5589      printf("\n");
5590      printf("Document Path:          %s\n", path);
5591      printf("Document Length:        %d bytes\n", doclen);
5592 @@ -531,14 +533,19 @@
5593      c->cbx = 0;
5594      c->gotheader = 0;
5595  
5596 -    c->fd = socket(AF_INET, SOCK_STREAM, 0);
5597 +    c->fd = socket(server.ss_family, SOCK_STREAM, 0);
5598      if (c->fd < 0)
5599         err("socket");
5600  
5601      nonblock(c->fd);
5602      gettimeofday(&c->start, 0);
5603  
5604 -    if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) {
5605 +#ifndef SIN6_LEN
5606 +    if (connect(c->fd, (struct sockaddr *) & server, SA_LEN((struct sockaddr*)&server)) < 0)
5607 +#else
5608 +    if (connect(c->fd, (struct sockaddr *) &server, server.ss_len) < 0)
5609 +#endif
5610 +    {
5611         if (errno == EINPROGRESS) {
5612             c->state = STATE_CONNECTING;
5613             FD_SET(c->fd, &writebits);
5614 @@ -772,14 +779,17 @@
5615      }
5616  
5617      {
5618 -       /* get server information */
5619 -       struct hostent *he;
5620 -       he = gethostbyname(hostname);
5621 -       if (!he)
5622 -           err("bad hostname");
5623 -       server.sin_family = he->h_addrtype;
5624 -       server.sin_port = htons(port);
5625 -       server.sin_addr.s_addr = ((unsigned long *) (he->h_addr_list[0]))[0];
5626 +        /* get server information */
5627 +       struct addrinfo hints, *res;
5628 +       int error;
5629 +
5630 +       memset(&hints, 0, sizeof(hints));
5631 +       hints.ai_family = PF_UNSPEC;
5632 +       error = getaddrinfo(hostname, port, &hints, &res);
5633 +       if (error)
5634 +               err("bad hostname");
5635 +       memcpy(&server, res->ai_addr, res->ai_addrlen);
5636 +       freeaddrinfo(res);
5637      }
5638  
5639      con = malloc(concurrency * sizeof(struct connection));
5640 @@ -954,7 +964,7 @@
5641      *cp = '\0';
5642      strcpy(hostname, h);
5643      if (p != NULL)
5644 -       port = atoi(p);
5645 +        port = strdup(p);
5646      return 0;
5647  }
5648  
5649 @@ -1131,3 +1141,7 @@
5650  
5651      exit(0);
5652  }
5653 +
5654 +#ifdef NEED_GETADDRINFO
5655 +#include "../main/getaddrinfo.c"
5656 +#endif
5657 diff -Nru apache_1.3.20/src/support/logresolve.c apache_1.3.20.new/src/support/logresolve.c
5658 --- apache_1.3.20/src/support/logresolve.c      Mon Apr  2 11:22:11 2001
5659 +++ apache_1.3.20.new/src/support/logresolve.c  Mon May 21 10:54:52 2001
5660 @@ -54,7 +54,9 @@
5661  #endif /* BEOS */
5662  #endif /* !MPE && !WIN32*/
5663  
5664 -static void cgethost(struct in_addr ipnum, char *string, int check);
5665 +#include "sa_len.h"
5666 +
5667 +static void cgethost(struct sockaddr *sa, char *string, int check);
5668  static int getline(char *s, int n);
5669  static void stats(FILE *output);
5670  
5671 @@ -91,7 +93,7 @@
5672   */
5673  
5674  struct nsrec {
5675 -    struct in_addr ipnum;
5676 +    struct sockaddr_storage addr;
5677      char *hostname;
5678      int noname;
5679      struct nsrec *next;
5680 @@ -122,17 +124,48 @@
5681   * IP numbers with their IP number as hostname, setting noname flag
5682   */
5683  
5684 -static void cgethost (struct in_addr ipnum, char *string, int check)
5685 +static void cgethost (struct sockaddr *sa, char *string, int check)
5686  {
5687 +    ap_uint32_t hashval;
5688 +    struct sockaddr_in *sin;
5689 +#ifdef INET6
5690 +    struct sockaddr_in6 *sin6;
5691 +#endif
5692      struct nsrec **current, *new;
5693 -    struct hostent *hostdata;
5694      char *name;
5695 +    char hostnamebuf[MAXHOSTNAMELEN];
5696 +
5697 +    switch (sa->sa_family) {
5698 +    case AF_INET:
5699 +       hashval = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
5700 +       break;
5701 +#ifdef INET6
5702 +    case AF_INET6:
5703 +       hashval = *(ap_uint32_t *)&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12];
5704 +       break;
5705 +#endif
5706 +    default:
5707 +       hashval = 0;
5708 +       break;
5709 +    }
5710 +
5711 +    current = &nscache[((hashval + (hashval >> 8) +
5712 +                        (hashval >> 16) + (hashval >> 24)) % BUCKETS)];
5713  
5714 -    current = &nscache[((ipnum.s_addr + (ipnum.s_addr >> 8) +
5715 -                        (ipnum.s_addr >> 16) + (ipnum.s_addr >> 24)) % BUCKETS)];
5716 +    while (*current) {
5717 +#ifndef SIN6_LEN
5718 +       if (SA_LEN(sa) == SA_LEN((struct sockaddr *)&(*current)->addr)
5719 +        && memcmp(sa, &(*current)->addr, SA_LEN(sa)) == 0)
5720 +#else
5721 +       if (sa->sa_len == (*current)->addr.ss_len
5722 +        && memcmp(sa, &(*current)->addr, sa->sa_len) == 0)
5723 +#endif
5724 +       {
5725 +           break;
5726 +       }
5727  
5728 -    while (*current != NULL && ipnum.s_addr != (*current)->ipnum.s_addr)
5729         current = &(*current)->next;
5730 +    }
5731  
5732      if (*current == NULL) {
5733         cachesize++;
5734 @@ -145,45 +178,55 @@
5735         *current = new;
5736         new->next = NULL;
5737  
5738 -       new->ipnum = ipnum;
5739 +#ifndef SIN6_LEN
5740 +       memcpy(&new->addr, sa, SA_LEN(sa));
5741 +#else
5742 +       memcpy(&new->addr, sa, sa->sa_len);
5743 +#endif
5744  
5745 -       hostdata = gethostbyaddr((const char *) &ipnum, sizeof(struct in_addr),
5746 -                                AF_INET);
5747 -       if (hostdata == NULL) {
5748 -           if (h_errno > MAX_ERR)
5749 -               errors[UNKNOWN_ERR]++;
5750 -           else
5751 -               errors[h_errno]++;
5752 -           new->noname = h_errno;
5753 -           name = strdup(inet_ntoa(ipnum));
5754 -       }
5755 -       else {
5756 -           new->noname = 0;
5757 -           name = strdup(hostdata->h_name);
5758 -           if (check) {
5759 -               if (name == NULL) {
5760 -                   perror("strdup");
5761 -                   fprintf(stderr, "Insufficient memory\n");
5762 -                   exit(1);
5763 -               }
5764 -               hostdata = gethostbyname(name);
5765 -               if (hostdata != NULL) {
5766 -                   char **hptr;
5767 -
5768 -                   for (hptr = hostdata->h_addr_list; *hptr != NULL; hptr++)
5769 -                       if (((struct in_addr *) (*hptr))->s_addr == ipnum.s_addr)
5770 -                           break;
5771 -                   if (*hptr == NULL)
5772 -                       hostdata = NULL;
5773 -               }
5774 -               if (hostdata == NULL) {
5775 -                   fprintf(stderr, "Bad host: %s != %s\n", name,
5776 -                           inet_ntoa(ipnum));
5777 -                   new->noname = NO_REVERSE;
5778 -                   free(name);
5779 -                   name = strdup(inet_ntoa(ipnum));
5780 -                   errors[NO_REVERSE]++;
5781 +       new->noname = getnameinfo(sa,
5782 +#ifndef SIN6_LEN
5783 +               SA_LEN(sa),
5784 +#else
5785 +               sa->sa_len,
5786 +#endif
5787 +                   hostnamebuf, sizeof(hostnamebuf), NULL, 0, 0);
5788 +       name = strdup(hostnamebuf);
5789 +       if (check) {
5790 +           struct addrinfo hints, *res;
5791 +           int error;
5792 +           memset(&hints, 0, sizeof(hints));
5793 +           hints.ai_family = PF_UNSPEC;
5794 +           error = getaddrinfo(hostnamebuf, NULL, &hints, &res);
5795 +           if (!error) {
5796 +               while (res) {
5797 +#ifndef SIN6_LEN
5798 +                   if (SA_LEN(sa) == res->ai_addrlen
5799 +                    && memcmp(sa, res->ai_addr, SA_LEN(sa)) == 0)
5800 +#else
5801 +                   if (sa->sa_len == res->ai_addrlen
5802 +                    && memcmp(sa, res->ai_addr, sa->sa_len) == 0)
5803 +#endif
5804 +                   {
5805 +                       break;
5806 +                   }
5807 +                   res = res->ai_next;
5808                 }
5809 +               if (!res)
5810 +                   error++;
5811 +           }
5812 +           if (error) {
5813 +               getnameinfo(sa,
5814 +#ifndef SIN6_LEN
5815 +                   SA_LEN(sa),
5816 +#else
5817 +                   sa->sa_len,
5818 +#endif
5819 +                   hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
5820 +               fprintf(stderr, "Bad host: %s != %s\n", name, hostnamebuf);
5821 +               new->noname = NO_REVERSE;
5822 +               free(name);
5823 +               name = strdup(hostnamebuf);
5824             }
5825         }
5826         new->hostname = name;
5827 @@ -211,6 +254,7 @@
5828      char *ipstring;
5829      struct nsrec *current;
5830      char *errstring[MAX_ERR + 3];
5831 +    char hostnamebuf[MAXHOSTNAMELEN];
5832  
5833      for (i = 0; i < MAX_ERR + 3; i++)
5834         errstring[i] = "Unknown error";
5835 @@ -242,7 +286,14 @@
5836  
5837      for (i = 0; i < BUCKETS; i++)
5838         for (current = nscache[i]; current != NULL; current = current->next) {
5839 -           ipstring = inet_ntoa(current->ipnum);
5840 +           getnameinfo((struct sockaddr *)&current->addr,
5841 +#ifndef SIN6_LEN
5842 +                   SA_LEN((struct sockaddr *)&current->addr),
5843 +#else
5844 +                   current->addr.ss_len,
5845 +#endif
5846 +                   hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
5847 +           ipstring = hostnamebuf;
5848             if (current->noname == 0)
5849                 fprintf(output, "  %3d  %15s - %s\n", i, ipstring,
5850                         current->hostname);
5851 @@ -276,9 +327,10 @@
5852  
5853  int main (int argc, char *argv[])
5854  {
5855 -    struct in_addr ipnum;
5856      char *bar, hoststring[MAXDNAME + 1], line[MAXLINE], *statfile;
5857      int i, check;
5858 +    struct addrinfo hints, *res;
5859 +    int error;
5860  
5861  #ifdef WIN32
5862      WSADATA wsaData;
5863 @@ -322,8 +374,10 @@
5864         bar = strchr(line, ' ');
5865         if (bar != NULL)
5866             *bar = '\0';
5867 -       ipnum.s_addr = inet_addr(line);
5868 -       if (ipnum.s_addr == 0xffffffffu) {
5869 +       memset(&hints, 0, sizeof(hints));
5870 +       hints.ai_family = PF_UNSPEC;
5871 +       error = getaddrinfo(line, NULL, &hints, &res);
5872 +       if (error) {
5873             if (bar != NULL)
5874                 *bar = ' ';
5875             puts(line);
5876 @@ -333,11 +387,12 @@
5877  
5878         resolves++;
5879  
5880 -       cgethost(ipnum, hoststring, check);
5881 +       cgethost(res->ai_addr, hoststring, check);
5882         if (bar != NULL)
5883             printf("%s %s\n", hoststring, bar + 1);
5884         else
5885             puts(hoststring);
5886 +       freeaddrinfo(res);
5887      }
5888  
5889  #ifdef WIN32
5890 @@ -358,3 +413,11 @@
5891  
5892      return (0);
5893  }
5894 +
5895 +#ifdef NEED_GETADDRINFO
5896 +#include "../main/getaddrinfo.c"
5897 +#endif
5898 +
5899 +#ifdef NEED_GETNAMEINFO
5900 +#include "../main/getnameinfo.c"
5901 +#endif
This page took 1.302295 seconds and 4 git commands to generate.