]> git.pld-linux.org Git - packages/apache.git/blame - apache-ipv6-PLD.patch
- updated to 1.3.23: merge DEVEL branch to HEAD.
[packages/apache.git] / apache-ipv6-PLD.patch
CommitLineData
35b9807c
JB
1diff -Nur apache_1.3.22.orig/README.v6 apache_1.3.22/README.v6
2--- apache_1.3.22.orig/README.v6 Thu Jan 1 01:00:00 1970
f6e312e2 3+++ apache_1.3.22/README.v6 Tue Dec 18 23:14:29 2001
5ff5e565 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/
35b9807c
JB
171diff -Nur apache_1.3.22.orig/conf/httpd.conf-dist apache_1.3.22/conf/httpd.conf-dist
172--- apache_1.3.22.orig/conf/httpd.conf-dist Sat Oct 6 05:40:04 2001
f6e312e2 173+++ apache_1.3.22/conf/httpd.conf-dist Tue Dec 18 23:14:29 2001
5ff5e565 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
35b9807c
JB
186diff -Nur apache_1.3.22.orig/configure.v6 apache_1.3.22/configure.v6
187--- apache_1.3.22.orig/configure.v6 Thu Jan 1 01:00:00 1970
f6e312e2 188+++ apache_1.3.22/configure.v6 Tue Dec 18 23:14:29 2001
5ff5e565 189@@ -0,0 +1,3 @@
190+#! /bin/sh
191+
192+./configure --enable-rule=INET6 --enable-module=proxy $*
35b9807c 193diff -Nur apache_1.3.22.orig/src/Configuration.tmpl apache_1.3.22/src/Configuration.tmpl
f6e312e2
JB
194--- apache_1.3.22.orig/src/Configuration.tmpl Tue Dec 18 23:14:14 2001
195+++ apache_1.3.22/src/Configuration.tmpl Tue Dec 18 23:14:29 2001
cd7c2de0 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
5ff5e565 200+# INET6:
201+# IPv6 support.
202+#
203
204 Rule SOCKS4=no
205 Rule SOCKS5=no
cd7c2de0 206@@ -198,6 +201,7 @@
5ff5e565 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.
35b9807c 214diff -Nur apache_1.3.22.orig/src/Configure apache_1.3.22/src/Configure
f6e312e2
JB
215--- apache_1.3.22.orig/src/Configure Tue Dec 18 23:14:13 2001
216+++ apache_1.3.22/src/Configure Tue Dec 18 23:14:29 2001
5ff5e565 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
35b9807c 225@@ -1692,6 +1693,124 @@
5ff5e565 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:
35b9807c 350@@ -2287,6 +2406,38 @@
5ff5e565 351 echo "#define AP_LONGEST_LONG $AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H
352 echo "#endif" >>$AP_CONFIG_AUTO_H
35b9807c 353
5ff5e565 354+if [ x`./helpers/TestCompile -r sizeof 'uint32_t'` != x"" ]; then
355+ echo "" >>$AP_CONFIG_AUTO_H
356+ echo "/* determine: use uint32_t as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
357+ echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H
358+ echo "#define ap_uint32_t uint32_t" >>$AP_CONFIG_AUTO_H
359+ echo "#endif" >>$AP_CONFIG_AUTO_H
360+ echo " - use uint32_t as 32bit unsigned int"
361+elif [ x`./helpers/TestCompile -r sizeof 'u_int32_t'` != x"" ]; then
362+ echo "" >>$AP_CONFIG_AUTO_H
363+ echo "/* determine: use u_int32_t as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
364+ echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H
365+ echo "#define ap_uint32_t u_int32_t" >>$AP_CONFIG_AUTO_H
366+ echo "#endif" >>$AP_CONFIG_AUTO_H
367+ echo " - use u_int32_t as 32bit unsigned int"
368+elif [ x`./helpers/TestCompile -r sizeof 'unsigned int'` = x"4" ]; then
369+ echo "" >>$AP_CONFIG_AUTO_H
370+ echo "/* determine: use unsigned int as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
371+ echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H
372+ echo "#define ap_uint32_t unsigned int" >>$AP_CONFIG_AUTO_H
373+ echo "#endif" >>$AP_CONFIG_AUTO_H
374+ echo " - use unsigned int as 32bit unsigned int"
375+elif [ x`./helpers/TestCompile -r sizeof 'unsigned long int'` = x"4" ]; then
376+ echo "" >>$AP_CONFIG_AUTO_H
377+ echo "/* determine: use unsigned long int as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H
378+ echo "#ifndef uint32_t" >>$AP_CONFIG_AUTO_H
379+ echo "#define uint32_t unsigned long int" >>$AP_CONFIG_AUTO_H
380+ echo "#endif" >>$AP_CONFIG_AUTO_H
381+ echo " - use unsigned long int as 32bit unsigned int"
382+else
383+ echo " - Warning: cannot determine what type should we use as 32bit unsigned int"
384+fi
35b9807c 385+
5ff5e565 386 ####################################################################
387 ## More building ap_config_auto.h
35b9807c
JB
388 ##
389diff -Nur apache_1.3.22.orig/src/ap/ap_snprintf.c apache_1.3.22/src/ap/ap_snprintf.c
390--- apache_1.3.22.orig/src/ap/ap_snprintf.c Thu May 10 16:04:22 2001
f6e312e2 391+++ apache_1.3.22/src/ap/ap_snprintf.c Tue Dec 18 23:14:29 2001
5ff5e565 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;
35b9807c
JB
468diff -Nur apache_1.3.22.orig/src/ap/ap_snprintf.c~ apache_1.3.22/src/ap/ap_snprintf.c~
469--- apache_1.3.22.orig/src/ap/ap_snprintf.c~ Thu Jan 1 01:00:00 1970
f6e312e2 470+++ apache_1.3.22/src/ap/ap_snprintf.c~ Tue Dec 18 23:14:29 2001
5ff5e565 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+}
35b9807c
JB
1728diff -Nur apache_1.3.22.orig/src/include/ap.h apache_1.3.22/src/include/ap.h
1729--- apache_1.3.22.orig/src/include/ap.h Mon Jan 15 18:04:22 2001
f6e312e2 1730+++ apache_1.3.22/src/include/ap.h Tue Dec 18 23:14:29 2001
5ff5e565 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
35b9807c
JB
1741diff -Nur apache_1.3.22.orig/src/include/ap_config.h apache_1.3.22/src/include/ap_config.h
1742--- apache_1.3.22.orig/src/include/ap_config.h Mon Oct 8 17:49:33 2001
f6e312e2 1743+++ apache_1.3.22/src/include/ap_config.h Tue Dec 18 23:14:29 2001
35b9807c 1744@@ -405,6 +405,10 @@
5ff5e565 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
35b9807c 1755@@ -1488,6 +1492,70 @@
5ff5e565 1756 #define ap_wait_t int
35b9807c
JB
1757 #endif
1758
5ff5e565 1759+#ifndef INET6
1760+#define sockaddr_storage sockaddr
1761+#define ss_family sa_family
1762+#define ss_len sa_len
1763+#else
1764+#include "sockaddr_storage.h" /* sshida@st.rim.or.jp */
1765+#endif
1766+
1767+#ifndef INET6_ADDRSTRLEN
1768+#define INET6_ADDRSTRLEN 46
1769+#endif
1770+#ifndef INET_ADDRSTRLEN
1771+#define INET_ADDRSTRLEN 16
1772+#endif
1773+#ifndef NI_MAXHOST
1774+#define NI_MAXHOST 1025
1775+#endif
1776+#ifndef NI_MAXSERV
1777+#define NI_MAXSERV 32
1778+#endif
1779+
1780+#if defined(NEED_GETADDRINFO) || defined(NEED_GETNAMEINFO)
1781+/*
1782+ * minimal definitions for fake getaddrinfo()/getnameinfo().
1783+ */
1784+#ifndef EAI_NODATA
1785+#define EAI_NODATA 1
1786+#define EAI_MEMORY 2
1787+#endif
1788+
1789+#ifndef AI_PASSIVE
1790+#define AI_PASSIVE 1
1791+#define AI_CANONNAME 2
1792+#define AI_NUMERICHOST 4
1793+#define NI_NUMERICHOST 8
1794+#define NI_NAMEREQD 16
1795+#define NI_NUMERICSERV 32
1796+#endif
1797+#endif
1798+
1799+#ifdef NEED_GETADDRINFO
1800+#ifdef NEED_ADDRINFO
1801+struct addrinfo {
1802+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
1803+ int ai_family; /* PF_xxx */
1804+ int ai_socktype; /* SOCK_xxx */
1805+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
1806+ size_t ai_addrlen; /* length of ai_addr */
1807+ char *ai_canonname; /* canonical name for hostname */
1808+ struct sockaddr *ai_addr; /* binary address */
1809+ struct addrinfo *ai_next; /* next structure in linked list */
1810+};
1811+#endif
1812+extern char *gai_strerror(int ecode);
1813+extern void freeaddrinfo(struct addrinfo *ai);
1814+extern int getaddrinfo(const char *hostname, const char *servname,
1815+ const struct addrinfo *hints, struct addrinfo **res);
1816+#endif
1817+#ifdef NEED_GETNAMEINFO
1818+extern int getnameinfo(const struct sockaddr *sa, size_t salen,
1819+ char *host, size_t hostlen, char *serv, size_t servlen,
1820+ int flag);
35b9807c
JB
1821+#endif
1822+
5ff5e565 1823 #ifdef __cplusplus
35b9807c
JB
1824 }
1825 #endif
1826diff -Nur apache_1.3.22.orig/src/include/http_conf_globals.h apache_1.3.22/src/include/http_conf_globals.h
f6e312e2
JB
1827--- apache_1.3.22.orig/src/include/http_conf_globals.h Tue Dec 18 23:14:13 2001
1828+++ apache_1.3.22/src/include/http_conf_globals.h Tue Dec 18 23:14:29 2001
5ff5e565 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;
35b9807c
JB
1839diff -Nur apache_1.3.22.orig/src/include/http_vhost.h apache_1.3.22/src/include/http_vhost.h
1840--- apache_1.3.22.orig/src/include/http_vhost.h Mon Jan 15 18:04:37 2001
f6e312e2 1841+++ apache_1.3.22/src/include/http_vhost.h Tue Dec 18 23:14:29 2001
5ff5e565 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);
35b9807c 1851diff -Nur apache_1.3.22.orig/src/include/httpd.h apache_1.3.22/src/include/httpd.h
f6e312e2
JB
1852--- apache_1.3.22.orig/src/include/httpd.h Tue Dec 18 23:14:14 2001
1853+++ apache_1.3.22/src/include/httpd.h Tue Dec 18 23:14:29 2001
35b9807c 1854@@ -912,8 +912,8 @@
5ff5e565 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,
35b9807c 1865@@ -955,8 +955,8 @@
5ff5e565 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
35b9807c 1876@@ -1024,7 +1024,7 @@
5ff5e565 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 */
35b9807c 1885@@ -1184,7 +1184,7 @@
5ff5e565 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
35b9807c
JB
1894diff -Nur apache_1.3.22.orig/src/include/sa_len.h apache_1.3.22/src/include/sa_len.h
1895--- apache_1.3.22.orig/src/include/sa_len.h Thu Jan 1 01:00:00 1970
f6e312e2 1896+++ apache_1.3.22/src/include/sa_len.h Tue Dec 18 23:14:29 2001
5ff5e565 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 */
35b9807c
JB
1939diff -Nur apache_1.3.22.orig/src/include/sockaddr_storage.h apache_1.3.22/src/include/sockaddr_storage.h
1940--- apache_1.3.22.orig/src/include/sockaddr_storage.h Thu Jan 1 01:00:00 1970
f6e312e2 1941+++ apache_1.3.22/src/include/sockaddr_storage.h Tue Dec 18 23:14:29 2001
5ff5e565 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 */
35b9807c
JB
1996diff -Nur apache_1.3.22.orig/src/main/getaddrinfo.c apache_1.3.22/src/main/getaddrinfo.c
1997--- apache_1.3.22.orig/src/main/getaddrinfo.c Thu Jan 1 01:00:00 1970
f6e312e2 1998+++ apache_1.3.22/src/main/getaddrinfo.c Tue Dec 18 23:14:29 2001
5ff5e565 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+}
35b9807c
JB
2162diff -Nur apache_1.3.22.orig/src/main/getnameinfo.c apache_1.3.22/src/main/getnameinfo.c
2163--- apache_1.3.22.orig/src/main/getnameinfo.c Thu Jan 1 01:00:00 1970
f6e312e2 2164+++ apache_1.3.22/src/main/getnameinfo.c Tue Dec 18 23:14:29 2001
5ff5e565 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+}
35b9807c 2261diff -Nur apache_1.3.22.orig/src/main/http_config.c apache_1.3.22/src/main/http_config.c
f6e312e2
JB
2262--- apache_1.3.22.orig/src/main/http_config.c Tue Dec 18 23:14:13 2001
2263+++ apache_1.3.22/src/main/http_config.c Tue Dec 18 23:14:29 2001
5ff5e565 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
35b9807c
JB
2324diff -Nur apache_1.3.22.orig/src/main/http_core.c apache_1.3.22/src/main/http_core.c
2325--- apache_1.3.22.orig/src/main/http_core.c Tue Sep 4 20:15:15 2001
f6e312e2 2326+++ apache_1.3.22/src/main/http_core.c Tue Dec 18 23:14:29 2001
5ff5e565 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,
35b9807c 2493@@ -2503,12 +2535,25 @@
5ff5e565 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
35b9807c
JB
2520@@ -2540,44 +2585,70 @@
2521 return NULL;
5ff5e565 2522 }
5ff5e565 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;
35b9807c 2617@@ -3163,7 +3234,7 @@
5ff5e565 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"},
35b9807c 2626@@ -3197,7 +3268,7 @@
5ff5e565 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,
35b9807c 2635diff -Nur apache_1.3.22.orig/src/main/http_main.c apache_1.3.22/src/main/http_main.c
f6e312e2
JB
2636--- apache_1.3.22.orig/src/main/http_main.c Tue Dec 18 23:14:13 2001
2637+++ apache_1.3.22/src/main/http_main.c Tue Dec 18 23:14:29 2001
5ff5e565 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;
35b9807c 2661@@ -1310,7 +1317,11 @@
5ff5e565 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");
35b9807c 2674@@ -1332,6 +1343,10 @@
5ff5e565 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");
35b9807c 2685@@ -3495,11 +3510,13 @@
5ff5e565 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).
35b9807c 2701@@ -3508,17 +3525,29 @@
5ff5e565 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 */
35b9807c 2737@@ -3569,21 +3598,47 @@
5ff5e565 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
35b9807c 2793@@ -3686,15 +3741,19 @@
5ff5e565 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
35b9807c 2817@@ -3707,7 +3766,7 @@
5ff5e565 2818 exit(1);
2819 }
2820 #ifdef MPE
2821- if (ntohs(server->sin_port) < 1024)
2822+ if (privport)
2823 GETUSERMODE();
2824 #endif
2825
35b9807c 2826@@ -3854,15 +3913,17 @@
5ff5e565 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;
35b9807c 2848@@ -4174,8 +4235,8 @@
5ff5e565 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
35b9807c 2859@@ -4340,7 +4401,7 @@
5ff5e565 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) {
35b9807c 2868@@ -4490,7 +4551,7 @@
5ff5e565 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 }
35b9807c 2877@@ -4535,8 +4596,8 @@
5ff5e565 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 /*
35b9807c 2888@@ -4680,12 +4741,13 @@
5ff5e565 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
35b9807c 2905@@ -5294,7 +5356,10 @@
5ff5e565 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
35b9807c 2917@@ -5369,8 +5434,14 @@
5ff5e565 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 }
35b9807c 2934@@ -5450,9 +5521,10 @@
5ff5e565 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. */
35b9807c 2946@@ -5499,25 +5571,32 @@
5ff5e565 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
35b9807c 2984@@ -7696,7 +7775,11 @@
5ff5e565 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':
35b9807c 2997@@ -7713,6 +7796,10 @@
5ff5e565 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':
35b9807c
JB
3008diff -Nur apache_1.3.22.orig/src/main/http_vhost.c apache_1.3.22/src/main/http_vhost.c
3009--- apache_1.3.22.orig/src/main/http_vhost.c Sat Feb 24 11:09:46 2001
f6e312e2 3010+++ apache_1.3.22/src/main/http_vhost.c Tue Dec 18 23:14:29 2001
5ff5e565 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 */
35b9807c
JB
3658diff -Nur apache_1.3.22.orig/src/main/rfc1413.c apache_1.3.22/src/main/rfc1413.c
3659--- apache_1.3.22.orig/src/main/rfc1413.c Mon Jan 15 18:05:04 2001
f6e312e2 3660+++ apache_1.3.22/src/main/rfc1413.c Tue Dec 18 23:14:29 2001
5ff5e565 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);
35b9807c
JB
3798diff -Nur apache_1.3.22.orig/src/main/util.c apache_1.3.22/src/main/util.c
3799--- apache_1.3.22.orig/src/main/util.c Wed Jul 25 15:25:18 2001
f6e312e2 3800+++ apache_1.3.22/src/main/util.c Tue Dec 18 23:14:29 2001
35b9807c 3801@@ -1962,52 +1962,87 @@
5ff5e565 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
35b9807c 3914@@ -2035,7 +2070,8 @@
5ff5e565 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) {
35b9807c 3924@@ -2048,29 +2084,38 @@
5ff5e565 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 }
35b9807c 3986@@ -2149,7 +2194,7 @@
5ff5e565 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);
35b9807c 3995@@ -2274,3 +2319,11 @@
5ff5e565 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
35b9807c
JB
4007diff -Nur apache_1.3.22.orig/src/main/util_script.c apache_1.3.22/src/main/util_script.c
4008--- apache_1.3.22.orig/src/main/util_script.c Wed May 9 07:17:11 2001
f6e312e2 4009+++ apache_1.3.22/src/main/util_script.c Tue Dec 18 23:14:29 2001
5ff5e565 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);
35b9807c
JB
4045diff -Nur apache_1.3.22.orig/src/main/util_uri.c apache_1.3.22/src/main/util_uri.c
4046--- apache_1.3.22.orig/src/main/util_uri.c Thu Aug 23 08:38:25 2001
f6e312e2 4047+++ apache_1.3.22/src/main/util_uri.c Tue Dec 18 23:14:29 2001
35b9807c 4048@@ -419,6 +419,12 @@
5ff5e565 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);
35b9807c 4061@@ -475,7 +481,12 @@
5ff5e565 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 }
35b9807c 4075diff -Nur apache_1.3.22.orig/src/modules/proxy/mod_proxy.c apache_1.3.22/src/modules/proxy/mod_proxy.c
f6e312e2
JB
4076--- apache_1.3.22.orig/src/modules/proxy/mod_proxy.c Tue Dec 18 23:14:13 2001
4077+++ apache_1.3.22/src/modules/proxy/mod_proxy.c Tue Dec 18 23:14:29 2001
5ff5e565 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 }
35b9807c
JB
4129diff -Nur apache_1.3.22.orig/src/modules/proxy/mod_proxy.h apache_1.3.22/src/modules/proxy/mod_proxy.h
4130--- apache_1.3.22.orig/src/modules/proxy/mod_proxy.h Fri Oct 5 10:19:15 2001
f6e312e2 4131+++ apache_1.3.22/src/modules/proxy/mod_proxy.h Tue Dec 18 23:14:29 2001
35b9807c 4132@@ -316,7 +316,7 @@
5ff5e565 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);
35b9807c
JB
4141diff -Nur apache_1.3.22.orig/src/modules/proxy/proxy_connect.c apache_1.3.22/src/modules/proxy/proxy_connect.c
4142--- apache_1.3.22.orig/src/modules/proxy/proxy_connect.c Fri Oct 5 10:19:15 2001
f6e312e2 4143+++ apache_1.3.22/src/modules/proxy/proxy_connect.c Tue Dec 18 23:14:29 2001
cd7c2de0 4144@@ -114,14 +114,15 @@
5ff5e565 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 =
cd7c2de0 4164@@ -129,26 +130,59 @@
5ff5e565 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 */
cd7c2de0 4233@@ -159,59 +193,64 @@
5ff5e565 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+
cd7c2de0 4260 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "CONNECT to remote proxy %s on port %d", proxyhost, proxyport);
5ff5e565 4261 }
4262 else {
cd7c2de0 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);
5ff5e565 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) {
cd7c2de0 4289- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r->server,
5ff5e565 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
35b9807c
JB
4332diff -Nur apache_1.3.22.orig/src/modules/proxy/proxy_ftp.c apache_1.3.22/src/modules/proxy/proxy_ftp.c
4333--- apache_1.3.22.orig/src/modules/proxy/proxy_ftp.c Fri Oct 5 10:19:15 2001
f6e312e2 4334+++ apache_1.3.22/src/modules/proxy/proxy_ftp.c Tue Dec 18 23:14:29 2001
5ff5e565 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
cd7c2de0 4343@@ -451,8 +452,10 @@
5ff5e565 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;
cd7c2de0 4356@@ -473,11 +476,18 @@
5ff5e565 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;
cd7c2de0 4376@@ -547,62 +557,52 @@
5ff5e565 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,
cd7c2de0 4476@@ -806,7 +806,7 @@
5ff5e565 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");
cd7c2de0 4485@@ -825,11 +825,22 @@
5ff5e565 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);
5ff5e565 4500+ Explain0("FTP: passive command issued");
cd7c2de0 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 */
5ff5e565 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. */
cd7c2de0 4510@@ -838,7 +849,7 @@
5ff5e565 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);
cd7c2de0 4519@@ -870,10 +881,14 @@
5ff5e565 4520 pport = (p1 << 8) + p0;
cd7c2de0 4521 ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r->server, "FTP: contacting host %d.%d.%d.%d:%d",
5ff5e565 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);
cd7c2de0 4538@@ -881,17 +896,76 @@
5ff5e565 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");
cd7c2de0 4617@@ -900,7 +974,7 @@
5ff5e565 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");
cd7c2de0 4626@@ -921,13 +995,26 @@
5ff5e565 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;
cd7c2de0 4658@@ -1186,7 +1273,7 @@
5ff5e565 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);
35b9807c 4667diff -Nur apache_1.3.22.orig/src/modules/proxy/proxy_http.c apache_1.3.22/src/modules/proxy/proxy_http.c
f6e312e2
JB
4668--- apache_1.3.22.orig/src/modules/proxy/proxy_http.c Tue Dec 18 23:14:13 2001
4669+++ apache_1.3.22/src/modules/proxy/proxy_http.c Tue Dec 18 23:14:29 2001
5ff5e565 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 */
35b9807c
JB
4858@@ -527,17 +550,31 @@
4859 }
5ff5e565 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) {
35b9807c
JB
4896diff -Nur apache_1.3.22.orig/src/modules/proxy/proxy_util.c apache_1.3.22/src/modules/proxy/proxy_util.c
4897--- apache_1.3.22.orig/src/modules/proxy/proxy_util.c Mon Sep 24 22:14:27 2001
f6e312e2 4898+++ apache_1.3.22/src/modules/proxy/proxy_util.c Tue Dec 18 23:14:29 2001
5ff5e565 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
35b9807c
JB
4975 *urlp = url;
4976 *hostp = host;
4977@@ -1237,22 +1262,45 @@
5ff5e565 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
35b9807c
JB
5027diff -Nur apache_1.3.22.orig/src/modules/standard/mod_access.c apache_1.3.22/src/modules/standard/mod_access.c
5028--- apache_1.3.22.orig/src/modules/standard/mod_access.c Mon Jan 15 18:05:34 2001
f6e312e2 5029+++ apache_1.3.22/src/modules/standard/mod_access.c Tue Dec 18 23:14:29 2001
5ff5e565 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) {
35b9807c
JB
5421diff -Nur apache_1.3.22.orig/src/modules/standard/mod_unique_id.c apache_1.3.22/src/modules/standard/mod_unique_id.c
5422--- apache_1.3.22.orig/src/modules/standard/mod_unique_id.c Tue Oct 2 18:11:13 2001
f6e312e2 5423+++ apache_1.3.22/src/modules/standard/mod_unique_id.c Tue Dec 18 23:14:29 2001
cd7c2de0 5424@@ -67,10 +67,22 @@
5ff5e565 5425 #include "http_config.h"
5426 #include "http_log.h"
5427 #include "multithread.h"
5428+#include "sa_len.h"
5ff5e565 5429+
cd7c2de0 5430+/*#define SHORT_UNIQUE_ID*/
5431
5ff5e565 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;
cd7c2de0 5446 #ifdef MULTITHREAD
5447 unsigned int tid;
5448@@ -142,7 +154,7 @@
5ff5e565 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
cd7c2de0 5455 #ifdef WIN32
5ff5e565 5456
cd7c2de0 5457@@ -221,7 +233,8 @@
5ff5e565 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
cd7c2de0 5467@@ -232,8 +245,8 @@
5ff5e565 5468 */
5469 unique_id_rec_offset[0] = XtOffsetOf(unique_id_rec, stamp);
cd7c2de0 5470 unique_id_rec_size[0] = sizeof(cur_unique_id->stamp);
5ff5e565 5471- unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, in_addr);
cd7c2de0 5472- unique_id_rec_size[1] = sizeof(cur_unique_id->in_addr);
5ff5e565 5473+ unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, addr);
c0a28ae9 5474+ unique_id_rec_size[1] = sizeof(cur_unique_id->addr);
5ff5e565 5475 unique_id_rec_offset[2] = XtOffsetOf(unique_id_rec, pid);
cd7c2de0 5476 unique_id_rec_size[2] = sizeof(cur_unique_id->pid);
5477 #ifdef MULTITHREAD
5478@@ -269,17 +282,44 @@
5ff5e565 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
cd7c2de0 5528@@ -336,7 +376,23 @@
5ff5e565 5529 "oh no! pids are greater than 32-bits! I'm broken!");
5530 }
5531
cd7c2de0 5532- cur_unique_id->in_addr = global_in_addr;
c0a28ae9 5533+ memset(&cur_unique_id->addr, 0, sizeof(cur_unique_id->addr));
5ff5e565 5534+ switch (global_addr.ss_family) {
5535+ case AF_INET:
c0a28ae9 5536+ cur_unique_id->addr.in = ((struct sockaddr_in *)&global_addr)->sin_addr;
5ff5e565 5537+ break;
5538+#ifdef INET6
5539+ case AF_INET6:
5540+#ifdef SHORT_UNIQUE_ID
c0a28ae9 5541+ cur_unique_id->addr.in6 =
5ff5e565 5542+ ((struct sockaddr_in6 *)&global_addr)->sin6_addr.s6_addr32[3];
5543+#else
c0a28ae9 5544+ cur_unique_id->addr.in6 =
5ff5e565 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
35b9807c
JB
5553diff -Nur apache_1.3.22.orig/src/support/ab.c apache_1.3.22/src/support/ab.c
5554--- apache_1.3.22.orig/src/support/ab.c Mon Oct 8 19:54:42 2001
f6e312e2 5555+++ apache_1.3.22/src/support/ab.c Tue Dec 18 23:17:14 2001
35b9807c 5556@@ -158,6 +158,8 @@
5ff5e565 5557 #include <sys/uio.h>
5558 #endif
5559
5560+#include "sa_len.h"
5561+
5562 #endif /* NO_APACHE_INCLUDES */
5ff5e565 5563
35b9807c 5564 #ifdef USE_SSL
f6e312e2
JB
5565@@ -246,7 +248,7 @@
5566 char servername[1024]; /* name that server reports */
5567 char hostname[1024]; /* host name */
5568 char proxyhost[1024]; /* proxy host name */
5569-int proxyport = 0; /* proxy port */
5570+char *proxyport = NULL; /* proxy port */
5571 int isproxy = 0;
5572 char path[1024]; /* path name */
5573 char postfile[1024]; /* name of file containing post data */
35b9807c 5574@@ -261,7 +263,7 @@
5ff5e565 5575 auth[1024], /* optional (basic/uuencoded)
5576 * authentification */
5577 hdrs[4096]; /* optional arbitrary headers */
5578-int port = 80; /* port number */
5579+char *port = "80"; /* port number */
5580
5581 int use_html = 0; /* use html in the report */
5582 char *tablestring;
35b9807c 5583@@ -298,7 +300,7 @@
5ff5e565 5584 struct data *stats; /* date for each request */
5585
5586 fd_set readbits, writebits; /* bits for select */
5587-struct sockaddr_in server; /* server addr structure */
5588+struct sockaddr_storage server; /* server addr structure */
5589
5590 #ifndef BEOS
5591 #define ab_close(s) close(s)
35b9807c 5592@@ -509,7 +511,7 @@
5ff5e565 5593 printf("\r \r");
5594 printf("Server Software: %s\n", servername);
5595 printf("Server Hostname: %s\n", hostname);
5596- printf("Server Port: %d\n", port);
5597+ printf("Server Port: %s\n", port);
5598 printf("\n");
5599 printf("Document Path: %s\n", path);
5600 printf("Document Length: %d bytes\n", doclen);
35b9807c 5601@@ -862,7 +864,7 @@
5ff5e565 5602 c->cbx = 0;
5603 c->gotheader = 0;
5604
5605- c->fd = socket(AF_INET, SOCK_STREAM, 0);
5606+ c->fd = socket(server.ss_family, SOCK_STREAM, 0);
35b9807c
JB
5607 if (c->fd < 0) {
5608 what = "SOCKET";
5609 goto bad;
5610@@ -879,7 +881,12 @@
5ff5e565 5611
35b9807c 5612 again:
5ff5e565 5613 gettimeofday(&c->start, 0);
5ff5e565 5614- if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) {
5615+#ifndef SIN6_LEN
5616+ if (connect(c->fd, (struct sockaddr *) & server, SA_LEN((struct sockaddr*)&server)) < 0)
5617+#else
35b9807c 5618+ if (connect(c->fd, (struct sockaddr *) & server, server.ss_len) < 0)
5ff5e565 5619+#endif
5620+ {
5621 if (errno == EINPROGRESS) {
5622 c->state = STATE_CONNECTING;
35b9807c 5623 }
f6e312e2
JB
5624@@ -1171,7 +1178,7 @@
5625 struct timeval timeout, now;
5626 fd_set sel_read, sel_except, sel_write;
5627 long i;
5628- int connectport;
5629+ char * connectport;
5630 char * url_on_request, * host;
5631
5632 /* There are four hostname's involved:
5633@@ -1209,16 +1216,21 @@
5ff5e565 5634 }
5ff5e565 5635 {
35b9807c 5636 /* get server information */
5ff5e565 5637- struct hostent *he;
35b9807c
JB
5638- he = gethostbyname(host);
5639- if (!he) {
5640- char theerror[1024];
5641- sprintf(theerror, "Bad hostname: %s\n", host);
5642- err(theerror);
5643- }
5ff5e565 5644- server.sin_family = he->h_addrtype;
35b9807c 5645- server.sin_port = htons(connectport);
5ff5e565 5646- server.sin_addr.s_addr = ((unsigned long *) (he->h_addr_list[0]))[0];
35b9807c 5647+ struct addrinfo hints, *res;
5ff5e565 5648+ int error;
5649+
5650+ memset(&hints, 0, sizeof(hints));
5651+ hints.ai_family = PF_UNSPEC;
f6e312e2
JB
5652+ hints.ai_socktype = SOCK_STREAM;
5653+ error = getaddrinfo(host, connectport, &hints, &res);
35b9807c
JB
5654+ if (error) {
5655+ char *theerror=malloc(strlen(host)+16);
5656+ sprintf(theerror, "Bad hostname: %s\n", host);
5657+ err(theerror);
5658+ free(theerror);
5659+ }
5ff5e565 5660+ memcpy(&server, res->ai_addr, res->ai_addrlen);
5661+ freeaddrinfo(res);
5662 }
5663
5664 con = malloc(concurrency * sizeof(struct connection));
f6e312e2
JB
5665@@ -1404,7 +1416,7 @@
5666 if (strlen(purl) > 8 && strncmp(purl, "https://", 8) == 0) {
5667 purl += 8;
5668 ssl = 1;
5669- port = 443;
5670+ port = "443";
5671 }
5672 #else
5673 if (strlen(purl) > 8 && strncmp(purl, "https://", 8) == 0) {
5674@@ -1425,7 +1437,7 @@
5ff5e565 5675 *cp = '\0';
5676 strcpy(hostname, h);
5677 if (p != NULL)
5678- port = atoi(p);
5679+ port = strdup(p);
5680 return 0;
5681 }
5682
f6e312e2
JB
5683@@ -1585,7 +1597,7 @@
5684 if ((p = strchr(optarg, ':'))) {
5685 *p = '\0';
5686 p++;
5687- proxyport = atoi(p);
5688+ proxyport = strdup(p);
5689 };
5690 strcpy(proxyhost, optarg);
5691 isproxy = 1;
5692@@ -1668,3 +1680,7 @@
5ff5e565 5693
5694 exit(0);
5695 }
5696+
5697+#ifdef NEED_GETADDRINFO
5698+#include "../main/getaddrinfo.c"
5699+#endif
35b9807c
JB
5700diff -Nur apache_1.3.22.orig/src/support/logresolve.c apache_1.3.22/src/support/logresolve.c
5701--- apache_1.3.22.orig/src/support/logresolve.c Wed May 23 00:52:21 2001
f6e312e2 5702+++ apache_1.3.22/src/support/logresolve.c Tue Dec 18 23:14:29 2001
5ff5e565 5703@@ -54,7 +54,9 @@
5704 #endif /* BEOS */
5705 #endif /* !MPE && !WIN32*/
5706
5707-static void cgethost(struct in_addr ipnum, char *string, int check);
5708+#include "sa_len.h"
5709+
5710+static void cgethost(struct sockaddr *sa, char *string, int check);
5711 static int getline(char *s, int n);
5712 static void stats(FILE *output);
5713
5714@@ -91,7 +93,7 @@
5715 */
5716
5717 struct nsrec {
5718- struct in_addr ipnum;
5719+ struct sockaddr_storage addr;
5720 char *hostname;
5721 int noname;
5722 struct nsrec *next;
5723@@ -122,17 +124,48 @@
5724 * IP numbers with their IP number as hostname, setting noname flag
5725 */
5726
5727-static void cgethost (struct in_addr ipnum, char *string, int check)
5728+static void cgethost (struct sockaddr *sa, char *string, int check)
5729 {
5730+ ap_uint32_t hashval;
5731+ struct sockaddr_in *sin;
5732+#ifdef INET6
5733+ struct sockaddr_in6 *sin6;
5734+#endif
5735 struct nsrec **current, *new;
5736- struct hostent *hostdata;
5737 char *name;
5738+ char hostnamebuf[MAXHOSTNAMELEN];
5739+
5740+ switch (sa->sa_family) {
5741+ case AF_INET:
5742+ hashval = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
5743+ break;
5744+#ifdef INET6
5745+ case AF_INET6:
5746+ hashval = *(ap_uint32_t *)&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12];
5747+ break;
5748+#endif
5749+ default:
5750+ hashval = 0;
5751+ break;
5752+ }
5753+
5754+ current = &nscache[((hashval + (hashval >> 8) +
5755+ (hashval >> 16) + (hashval >> 24)) % BUCKETS)];
5756
5757- current = &nscache[((ipnum.s_addr + (ipnum.s_addr >> 8) +
5758- (ipnum.s_addr >> 16) + (ipnum.s_addr >> 24)) % BUCKETS)];
5759+ while (*current) {
5760+#ifndef SIN6_LEN
5761+ if (SA_LEN(sa) == SA_LEN((struct sockaddr *)&(*current)->addr)
5762+ && memcmp(sa, &(*current)->addr, SA_LEN(sa)) == 0)
5763+#else
5764+ if (sa->sa_len == (*current)->addr.ss_len
5765+ && memcmp(sa, &(*current)->addr, sa->sa_len) == 0)
5766+#endif
5767+ {
5768+ break;
5769+ }
5770
5771- while (*current != NULL && ipnum.s_addr != (*current)->ipnum.s_addr)
5772 current = &(*current)->next;
5773+ }
5774
5775 if (*current == NULL) {
5776 cachesize++;
5777@@ -145,45 +178,55 @@
5778 *current = new;
5779 new->next = NULL;
5780
5781- new->ipnum = ipnum;
5782+#ifndef SIN6_LEN
5783+ memcpy(&new->addr, sa, SA_LEN(sa));
5784+#else
5785+ memcpy(&new->addr, sa, sa->sa_len);
5786+#endif
5787
5788- hostdata = gethostbyaddr((const char *) &ipnum, sizeof(struct in_addr),
5789- AF_INET);
5790- if (hostdata == NULL) {
5791- if (h_errno > MAX_ERR)
5792- errors[UNKNOWN_ERR]++;
5793- else
5794- errors[h_errno]++;
5795- new->noname = h_errno;
5796- name = strdup(inet_ntoa(ipnum));
5797- }
5798- else {
5799- new->noname = 0;
5800- name = strdup(hostdata->h_name);
5801- if (check) {
5802- if (name == NULL) {
5803- perror("strdup");
5804- fprintf(stderr, "Insufficient memory\n");
5805- exit(1);
5806- }
5807- hostdata = gethostbyname(name);
5808- if (hostdata != NULL) {
5809- char **hptr;
5810-
5811- for (hptr = hostdata->h_addr_list; *hptr != NULL; hptr++)
5812- if (((struct in_addr *) (*hptr))->s_addr == ipnum.s_addr)
5813- break;
5814- if (*hptr == NULL)
5815- hostdata = NULL;
5816- }
5817- if (hostdata == NULL) {
5818- fprintf(stderr, "Bad host: %s != %s\n", name,
5819- inet_ntoa(ipnum));
5820- new->noname = NO_REVERSE;
5821- free(name);
5822- name = strdup(inet_ntoa(ipnum));
5823- errors[NO_REVERSE]++;
5824+ new->noname = getnameinfo(sa,
5825+#ifndef SIN6_LEN
5826+ SA_LEN(sa),
5827+#else
5828+ sa->sa_len,
5829+#endif
5830+ hostnamebuf, sizeof(hostnamebuf), NULL, 0, 0);
5831+ name = strdup(hostnamebuf);
5832+ if (check) {
5833+ struct addrinfo hints, *res;
5834+ int error;
5835+ memset(&hints, 0, sizeof(hints));
5836+ hints.ai_family = PF_UNSPEC;
5837+ error = getaddrinfo(hostnamebuf, NULL, &hints, &res);
5838+ if (!error) {
5839+ while (res) {
5840+#ifndef SIN6_LEN
5841+ if (SA_LEN(sa) == res->ai_addrlen
5842+ && memcmp(sa, res->ai_addr, SA_LEN(sa)) == 0)
5843+#else
5844+ if (sa->sa_len == res->ai_addrlen
5845+ && memcmp(sa, res->ai_addr, sa->sa_len) == 0)
5846+#endif
5847+ {
5848+ break;
5849+ }
5850+ res = res->ai_next;
5851 }
5852+ if (!res)
5853+ error++;
5854+ }
5855+ if (error) {
5856+ getnameinfo(sa,
5857+#ifndef SIN6_LEN
5858+ SA_LEN(sa),
5859+#else
5860+ sa->sa_len,
5861+#endif
5862+ hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
5863+ fprintf(stderr, "Bad host: %s != %s\n", name, hostnamebuf);
5864+ new->noname = NO_REVERSE;
5865+ free(name);
5866+ name = strdup(hostnamebuf);
5867 }
5868 }
5869 new->hostname = name;
5870@@ -211,6 +254,7 @@
5871 char *ipstring;
5872 struct nsrec *current;
5873 char *errstring[MAX_ERR + 3];
5874+ char hostnamebuf[MAXHOSTNAMELEN];
5875
5876 for (i = 0; i < MAX_ERR + 3; i++)
5877 errstring[i] = "Unknown error";
5878@@ -242,7 +286,14 @@
5879
5880 for (i = 0; i < BUCKETS; i++)
5881 for (current = nscache[i]; current != NULL; current = current->next) {
5882- ipstring = inet_ntoa(current->ipnum);
5883+ getnameinfo((struct sockaddr *)&current->addr,
5884+#ifndef SIN6_LEN
5885+ SA_LEN((struct sockaddr *)&current->addr),
5886+#else
5887+ current->addr.ss_len,
5888+#endif
5889+ hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
5890+ ipstring = hostnamebuf;
5891 if (current->noname == 0)
5892 fprintf(output, " %3d %15s - %s\n", i, ipstring,
5893 current->hostname);
5894@@ -276,9 +327,10 @@
5895
5896 int main (int argc, char *argv[])
5897 {
5898- struct in_addr ipnum;
5899 char *bar, hoststring[MAXDNAME + 1], line[MAXLINE], *statfile;
5900 int i, check;
5901+ struct addrinfo hints, *res;
5902+ int error;
5903
5904 #ifdef WIN32
5905 WSADATA wsaData;
5906@@ -322,8 +374,10 @@
5907 bar = strchr(line, ' ');
5908 if (bar != NULL)
5909 *bar = '\0';
5910- ipnum.s_addr = inet_addr(line);
5911- if (ipnum.s_addr == 0xffffffffu) {
5912+ memset(&hints, 0, sizeof(hints));
5913+ hints.ai_family = PF_UNSPEC;
5914+ error = getaddrinfo(line, NULL, &hints, &res);
5915+ if (error) {
5916 if (bar != NULL)
5917 *bar = ' ';
5918 puts(line);
5919@@ -333,11 +387,12 @@
5920
5921 resolves++;
5922
5923- cgethost(ipnum, hoststring, check);
5924+ cgethost(res->ai_addr, hoststring, check);
5925 if (bar != NULL)
5926 printf("%s %s\n", hoststring, bar + 1);
5927 else
5928 puts(hoststring);
5929+ freeaddrinfo(res);
5930 }
5931
5932 #ifdef WIN32
5933@@ -358,3 +413,11 @@
5934
5935 return (0);
5936 }
5937+
5938+#ifdef NEED_GETADDRINFO
5939+#include "../main/getaddrinfo.c"
5940+#endif
5941+
5942+#ifdef NEED_GETNAMEINFO
5943+#include "../main/getnameinfo.c"
5944+#endif
This page took 0.741154 seconds and 4 git commands to generate.