]>
Commit | Line | Data |
---|---|---|
831e4313 | 1 | diff -Nru apache_1.3.20/README.v6 apache_1.3.20.new/README.v6 |
2 | --- apache_1.3.20/README.v6 Thu Jan 1 01:00:00 1970 | |
3 | +++ apache_1.3.20.new/README.v6 Mon May 21 10:54:52 2001 | |
4 | @@ -0,0 +1,166 @@ | |
5 | +IPv6-ready apache 1.3.x | |
6 | +KAME Project | |
7 | +$Id$ | |
8 | + | |
9 | +This patchkit enables apache 1.3.x to perform HTTP connection over IPv6. | |
10 | +Most of optional modules are left unchanged, i.e. it won't support IPv6, | |
11 | +and it may not compile. | |
12 | + | |
13 | +Basically you can write IPv6 address where IPv4 address fits. | |
14 | + | |
15 | +extra command-line argument: | |
16 | + -4 Assume IPv4 address on ambiguous directives | |
17 | + -6 Assume IPv6 address on ambiguous directives (default) | |
18 | + | |
19 | + The above two can be used, for example, to disambiguate | |
20 | + "BindAddress *". | |
21 | + | |
22 | +base commands: | |
23 | + Listen | |
24 | + Listen is expanded to take one or two arguments. | |
25 | + Listen port | |
26 | + Listen address:port | |
27 | + Listen address port | |
28 | + This is to let you specify "Listen :: 80", since "Listen :::80" | |
29 | + won't work. | |
30 | + | |
31 | +mod_access: | |
32 | + deny from | |
33 | + allow from | |
34 | + "deny from" and "allow from" supports IPv6 addresses, under the | |
35 | + following forms: | |
36 | + {deny,allow} from v6addr | |
37 | + {deny,allow} from v6addr/v6mask | |
38 | + {deny,allow} from v6addr/prefixlen | |
39 | + Also, wildcard ("*") and string hostname matches IPv6 hosts as well. | |
40 | + | |
41 | +mod_proxy: | |
42 | + ProxyRequests on | |
43 | + http/ftp proxying for both IPv4 and IPv6 is possible. | |
44 | + Access control functions (NoProxy) are not updated yet. | |
45 | + | |
46 | + NOTE: for security reasons, we recommend you to filter out | |
47 | + outsider's access to your proxy, by directives like below: | |
48 | + <Directory proxy:*> | |
49 | + order deny,allow | |
50 | + deny from all | |
51 | + allow from 10.0.0.0/8 | |
52 | + allow from 3ffe:9999:8888:7777::/64 | |
53 | + </Directory> | |
54 | + | |
55 | +virtual host: | |
56 | + If you would like to this feature, you must describe 'Listen' | |
57 | + part on configuration file explicitly. like below: | |
58 | + Listen :: 80 | |
59 | + Listen 0.0.0.0 80 | |
60 | + | |
61 | + NameVirtualHost | |
62 | + NameVirtualHost is expanded to take one more two arguments. | |
63 | + NameVirtualHost address | |
64 | + NameVirtualHost address:port | |
65 | + NameVirtualHost address port | |
66 | + This is to let you specify IPv6 address into address part. | |
67 | + | |
68 | + Note that, if colon is found in the specified address string, | |
69 | + the code will to resolve the address in the following way: | |
70 | + 1. try to resolve as address:port (most of IPv6 address fails) | |
71 | + 2. if (1) is failed, try to resolve as address only | |
72 | + If there's ambiguity, i.e. 3ffe:0501::1:2, the address may not be | |
73 | + parsed as you expect (3ffe:0501::1 with port 2, or 3ffe:0501::1:2 | |
74 | + with default port). To get the right effect you are encouraged | |
75 | + to specify it without ambiguity. In IPv6 case "address port" | |
76 | + (specify address and port separated by a space) is the safest way. | |
77 | + | |
78 | + <VirtualHost host:port [host:port ...]> | |
79 | + If you would like to specify IPv6 numeric address in host part, | |
80 | + use bracketed format like below: | |
81 | + <VirtualHost [::1]:80> | |
82 | + Note: Now we DO NOT handle old non-bracketed format, | |
83 | + <VirtualHost 0:0:0:0:0:0:0:1:80> | |
84 | + so configuration file must be updated. | |
85 | + Note: The following is bad example to specify host ::1 port 80. | |
86 | + This will treated as host ::1:80. | |
87 | + <VirtualHost ::1:80> | |
88 | + | |
89 | +logresolve (src/support) | |
90 | + error statistics in nameserver cache code is omitted. | |
91 | + | |
92 | +mod_unique_id | |
93 | + Originally mod_unique_id used IPv4 address as a seed for UNIQUE_ID, | |
94 | + and took IPv4 address registered onto DNS for the hostname (UNIX | |
95 | + hostname taken by gethostname(3)). Therefore, this does not work | |
96 | + for IPv6-only hosts as they do not have IPv4 address for them. | |
97 | + | |
98 | + Now, UNIQUE_ID can be generated using IPv6 address. IPv6 address can | |
99 | + be used as the seed for UNIQUE_ID. | |
100 | + Because of this, UNIQUE_ID will be longer than normal apache. This | |
101 | + may cause problem with some of the CGI scripts. | |
102 | + The preference of the addresses is based on the order returned | |
103 | + by getaddrinfo(). If your getaddrinfo() returns IPv4 address, IPv4 | |
104 | + adderss will be used as a seed. | |
105 | + Note that some of IPv6 addresses are "scoped"; If you happened to use | |
106 | + link-local or site-local address as a seed, the UNIQUE_ID may not be | |
107 | + worldwide unique. | |
108 | + | |
109 | + If longer UNIQUE_ID causes a problem, define SHORT_UNIQUE_ID in | |
110 | + mod_unique_id.c. In this case, length of UNIQUE_ID will be kept the | |
111 | + same. However, for IPv6 addresses mod_unique_id.c will use the last | |
112 | + 32bit (not the whole 128bit) as the seed. Therefore, there can be | |
113 | + collision in UNIQUE_ID. | |
114 | + | |
115 | + The behavior should be improved in the near future; we welcome your | |
116 | + inputs. | |
117 | + | |
118 | +Modules known to be incompatible with IPv6 | |
119 | + (please report us) | |
120 | + | |
121 | +configure | |
122 | + Configure has extra option, --enable-rule=INET6. if the option | |
123 | + is specified, IPv6 code will be enabled. | |
124 | + | |
125 | +configuration file | |
126 | + We do not support IPv4 mapped address (IPv6 address format like | |
127 | + ::ffff:10.1.1.1) in configuration file. | |
128 | + | |
129 | +This kit assumes that you have working(*) getaddrinfo() and getnameinfo() | |
130 | +library functions. Even if you don't have one, don't panic. We have | |
131 | +included last-resort version (which support IPv4 only) into the kit. | |
132 | +For more complete implementation you might want to check BIND 8.2. | |
133 | +(*) NOTE: we have noticed that some of IPv6 stack is shipped with broken | |
134 | +getaddrinfo(). In such cases, you should get and install BIND 8.2. | |
135 | + | |
136 | +When compiling this kit onto IPv6, you may need to specify some additional | |
137 | +library paths or cpp defs (like -linet6 or -DINET6). | |
138 | +Now you don't have to specify --enable-rule=INET6. The "configure" script | |
139 | +will give you some warnings if the IPv6 stack is not known to the | |
140 | +"configure" script. Currently, the following IPv6 stacks are supported: | |
141 | +- KAME IPv6 stack, http://www.kame.net/ | |
142 | + use configure.v6 for convenience, | |
143 | +- Linux IPv6 stack, http://www.linux.org/ | |
144 | + use configure.v6 for convenience. | |
145 | +- Solaris 8 IPv6 stack, http://www.sun.com/ | |
146 | + use configure.v6 for convenience. | |
147 | +To disable IPv6 support, specify --disable-rule=INET6 to the "configure" | |
148 | +script. | |
149 | + | |
150 | +CAVEAT: This patchkit may change some of apache module API, to avoid | |
151 | +IPv4-dependent structure member variable. Please let us know if there's | |
152 | +any troubles as we know very little about the apache module API. | |
153 | + | |
154 | +Acknowledgements | |
155 | + Thanks to all people submitted patches/fixes for this patch kit, | |
156 | + including: | |
157 | + "Chris P. Ross" <cross@eng.us.uu.net> | |
158 | + | |
159 | +Author contacts | |
160 | + Jun-ichiro itojun Hagino, KAME project | |
161 | + http://www.kame.net/ | |
162 | + mailto:core@kame.net | |
163 | +Linux Port | |
164 | + Arkadiusz Miskiewicz, Polish Linux Distribution project (IPv6) | |
165 | + http://www.pld.org.pl/ | |
166 | + mailto:pld-list@pld.org.pl | |
167 | + Satoshi SHIDA, Linux IPv6 Users Group JP | |
168 | + http://www.v6.linux.or.jp/ | |
169 | + YOSHIFUJI Hideaki, USAGI Project | |
170 | + http://www.linux-ipv6.org/ | |
171 | diff -Nru apache_1.3.20/conf/httpd.conf-dist apache_1.3.20.new/conf/httpd.conf-dist | |
172 | --- apache_1.3.20/conf/httpd.conf-dist Sun May 13 19:59:49 2001 | |
173 | +++ apache_1.3.20.new/conf/httpd.conf-dist Mon May 21 10:54:52 2001 | |
174 | @@ -174,6 +174,11 @@ | |
175 | #Listen 3000 | |
176 | #Listen 12.34.56.78:80 | |
177 | ||
178 | +# Listen can take two arguments. | |
179 | +# (this is an extension for supporting IPv6 addresses) | |
180 | +#Listen :: 80 | |
181 | +#Listen 0.0.0.0 80 | |
182 | + | |
183 | # | |
184 | # BindAddress: You can support virtual hosts with this option. This directive | |
185 | # is used to tell the server which IP address to listen to. It can either | |
186 | diff -Nru apache_1.3.20/configure.v6 apache_1.3.20.new/configure.v6 | |
187 | --- apache_1.3.20/configure.v6 Thu Jan 1 01:00:00 1970 | |
188 | +++ apache_1.3.20.new/configure.v6 Mon May 21 10:54:52 2001 | |
189 | @@ -0,0 +1,3 @@ | |
190 | +#! /bin/sh | |
191 | + | |
192 | +./configure --enable-rule=INET6 --enable-module=proxy $* | |
193 | diff -Nru apache_1.3.20/src/Configuration.tmpl apache_1.3.20.new/src/Configuration.tmpl | |
194 | --- apache_1.3.20/src/Configuration.tmpl Mon May 21 11:02:04 2001 | |
195 | +++ apache_1.3.20.new/src/Configuration.tmpl Mon May 21 10:54:52 2001 | |
196 | @@ -184,6 +184,9 @@ | |
197 | # directory is present. This rule will always be interpreted as "no" | |
198 | # if the directory is not present. | |
199 | # | |
200 | +# INET6: | |
201 | +# IPv6 support. | |
202 | +# | |
203 | ||
204 | Rule SOCKS4=no | |
205 | Rule SOCKS5=no | |
206 | @@ -191,6 +194,7 @@ | |
207 | Rule IRIXN32=yes | |
208 | Rule PARANOID=no | |
209 | Rule EXPAT=default | |
210 | +Rule INET6=no | |
211 | ||
212 | # DEV_RANDOM: | |
213 | # Note: this rule is only used when compiling mod_auth_digest. | |
214 | diff -Nru apache_1.3.20/src/Configure apache_1.3.20.new/src/Configure | |
215 | --- apache_1.3.20/src/Configure Mon May 21 11:02:03 2001 | |
216 | +++ apache_1.3.20.new/src/Configure Mon May 21 10:54:52 2001 | |
217 | @@ -237,6 +237,7 @@ | |
218 | RULE_EXPAT=`./helpers/CutRule EXPAT $file` | |
219 | RULE_SHARED_CORE=`./helpers/CutRule SHARED_CORE $file` | |
220 | RULE_SHARED_CHAIN=`./helpers/CutRule SHARED_CHAIN $file` | |
221 | +RULE_INET6=`./helpers/CutRule INET6 $file` | |
222 | ||
223 | #################################################################### | |
224 | ## Rule SHARED_CORE implies required DSO support | |
225 | @@ -1661,6 +1662,124 @@ | |
226 | esac | |
227 | fi | |
228 | ||
229 | +# INET6 support. | |
230 | +if [ "$RULE_INET6" = "yes" ]; then | |
231 | + echo " + enabling INET6 support" | |
232 | + CFLAGS="$CFLAGS -DINET6" | |
233 | + CFLAGS="$CFLAGS -Dss_family=__ss_family -Dss_len=__ss_len" | |
234 | + IPV6_STACKTYPE="UNKNOWN" | |
235 | + for i in KAME Linux Solaris; do | |
236 | + case "$i" in | |
237 | + KAME) | |
238 | + if [ -f /usr/include/netinet6/in6.h -a "x`egrep '__KAME__' /usr/include/netinet6/in6.h 2>/dev/null`" != "x" ]; then | |
239 | + IPV6_STACKTYPE=$i | |
240 | + fi | |
241 | + ;; | |
242 | + Linux) | |
243 | + if [ /usr/include/netinet/ip6.h -a -d /usr/include/linux ]; then | |
244 | + IPV6_STACKTYPE=$i | |
245 | + fi | |
246 | + ;; | |
247 | + Solaris) | |
248 | + SOL_VERSION=`(uname -v) 2>/dev/null` || SOL_VERSION="unknown" | |
249 | + case "${PLAT}-${SOL_VERSION}" in | |
250 | + *-solaris2.27*-*IPv6*) | |
251 | + if [ -f /etc/hostname -o -f /etc/hostname.[a-z]*[0-9] ]; then | |
252 | + IPV6_STACKTYPE="Solaris 7 (${SOL_VERSION})" | |
253 | + fi | |
254 | + ;; | |
255 | + esac | |
256 | + ;; | |
257 | + esac | |
258 | + if [ "$IPV6_STACKTYPE" != "UNKNOWN" ]; then | |
259 | + break | |
260 | + fi | |
261 | + done | |
262 | + if [ "$IPV6_STACKTYPE" != "UNKNOWN" ]; then | |
263 | + echo " + You seem to be using $IPV6_STACKTYPE stack" | |
264 | + if ./helpers/TestCompile func getaddrinfo; then | |
265 | + echo " - Assuming you have working getaddrinfo in libc" | |
266 | + else | |
267 | + if [ -f /usr/local/v6/lib/libinet6.a -a "x`egrep '^EXTRA_L' Makefile.config | grep linet6`" = "x" ]; then | |
268 | + LIBS="$LIBS -L/usr/local/v6/lib -linet6" | |
269 | + echo " - using getaddrinfo in libinet6" | |
270 | + elif [ -f /usr/local/lib/libinet6.a -a "x`egrep '^EXTRA_L' Makefile.config | grep linet6`" = "x" ]; then | |
271 | + LIBS="$LIBS -L/usr/local/lib -linet6" | |
272 | + echo " - using getaddrinfo in libinet6" | |
273 | + elif [ -f /usr/inet6/lib/libinet6.a -a "x`egrep '^EXTRA_L' Makefile.config | grep linet6`" = "x" ]; then | |
274 | + echo " - using getaddrinfo in libinet6" | |
275 | + else | |
276 | + echo "** WARNING: No getaddrinfo found, linkage may fail" | |
277 | + fi | |
278 | + fi | |
279 | + else | |
280 | + echo "" | |
281 | + echo "** WARNING: We have no explicit knowledge about the IPv6" | |
282 | + echo "** implementation on this host. You may need to specify" | |
283 | + echo "** EXTRA_LIBS so that we can find getaddrinfo() and" | |
284 | + echo "** getnameinfo() library functions." | |
285 | + echo "" | |
286 | + fi | |
287 | + case $PLAT in | |
288 | + *-solaris2* ) | |
289 | + LIBS="$LIBS -lresolv" | |
290 | + ;; | |
291 | + esac | |
292 | +else | |
293 | + CFLAGS="$CFLAGS -DNEED_GETADDRINFO -DNEED_GETNAMEINFO" | |
294 | + if [ -f /usr/include/netdb.h -a "x`egrep 'addrinfo' /usr/include/netdb.h`" = "x" ]; then | |
295 | + CFLAGS="$CFLAGS -DNEED_ADDRINFO" | |
296 | + fi | |
297 | +fi | |
298 | + | |
299 | +echo '#include <sys/types.h>' >testfunc.c | |
300 | +echo '#include <sys/socket.h>' >>testfunc.c | |
301 | +echo 'int testfunc(){ struct sockaddr sa; int i = sa.sa_len; };' >>testfunc.c | |
302 | +rm -f testfunc.o | |
303 | +eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null" | |
304 | +if [ -f testfunc.o ]; then | |
305 | + echo " + you have sa_len in struct sockaddr." | |
306 | + CFLAGS="$CFLAGS -DHAVE_SOCKADDR_LEN" | |
307 | +else | |
308 | + echo " + you don't have sa_len in struct sockaddr." | |
309 | +fi | |
310 | +rm -f testfunc.c testfunc.o | |
311 | + | |
312 | +echo '#include <sys/types.h>' >testfunc.c | |
313 | +echo '#include <sys/socket.h>' >>testfunc.c | |
314 | +echo 'struct sockaddr_storage sockaddr_storage;' >>testfunc.c | |
315 | +rm -f testfunc.o | |
316 | +eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null" | |
317 | +if [ -f testfunc.o ]; then | |
318 | + echo " + assuming you have struct sockaddr_storage" | |
319 | +else | |
320 | + CFLAGS="$CFLAGS -DNEED_SOCKADDR_STORAGE" | |
321 | + echo " + you need struct sockaddr_storage" | |
322 | +fi | |
323 | +rm -f testfunc.c testfunc.o | |
324 | + | |
325 | +echo '#include <sys/types.h>' >testfunc.c | |
326 | +echo '#include <sys/socket.h>' >>testfunc.c | |
327 | +echo 'int testfunc(){ socklen_t t; }' >>testfunc.c | |
328 | +rm -f testfunc.o | |
329 | +eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null" | |
330 | +if [ ! -f testfunc.o ]; then | |
331 | + CFLAGS="$CFLAGS -Dsocklen_t=int" | |
332 | +fi | |
333 | +rm -f testfunc.c testfunc.o | |
334 | + | |
335 | +echo '#include <sys/types.h>' >testfunc.c | |
336 | +echo '#include <sys/socket.h>' >>testfunc.c | |
337 | +echo 'struct sockaddr_in sin;' >>testfunc.c | |
338 | +echo 'int main(){ int i = sin.sin_len; }' >>testfunc.c | |
339 | +rm -f testfunc.o | |
340 | +eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null" | |
341 | +if [ -f testfunc.o ]; then | |
342 | + CFLAGS="$CFLAGS -DSIN_LEN" | |
343 | +fi | |
344 | +rm -f testfunc.c testfunc.o | |
345 | + | |
346 | + | |
347 | #################################################################### | |
348 | ## Find out what modules we want and try and configure things for them | |
349 | ## Module lines can look like this: | |
350 | @@ -2252,6 +2371,38 @@ | |
351 | echo "#ifndef AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H | |
352 | echo "#define AP_LONGEST_LONG $AP_LONGEST_LONG" >>$AP_CONFIG_AUTO_H | |
353 | echo "#endif" >>$AP_CONFIG_AUTO_H | |
354 | + | |
355 | +if [ x`./helpers/TestCompile -r sizeof 'uint32_t'` != x"" ]; then | |
356 | + echo "" >>$AP_CONFIG_AUTO_H | |
357 | + echo "/* determine: use uint32_t as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H | |
358 | + echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H | |
359 | + echo "#define ap_uint32_t uint32_t" >>$AP_CONFIG_AUTO_H | |
360 | + echo "#endif" >>$AP_CONFIG_AUTO_H | |
361 | + echo " - use uint32_t as 32bit unsigned int" | |
362 | +elif [ x`./helpers/TestCompile -r sizeof 'u_int32_t'` != x"" ]; then | |
363 | + echo "" >>$AP_CONFIG_AUTO_H | |
364 | + echo "/* determine: use u_int32_t as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H | |
365 | + echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H | |
366 | + echo "#define ap_uint32_t u_int32_t" >>$AP_CONFIG_AUTO_H | |
367 | + echo "#endif" >>$AP_CONFIG_AUTO_H | |
368 | + echo " - use u_int32_t as 32bit unsigned int" | |
369 | +elif [ x`./helpers/TestCompile -r sizeof 'unsigned int'` = x"4" ]; then | |
370 | + echo "" >>$AP_CONFIG_AUTO_H | |
371 | + echo "/* determine: use unsigned int as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H | |
372 | + echo "#ifndef ap_uint32_t" >>$AP_CONFIG_AUTO_H | |
373 | + echo "#define ap_uint32_t unsigned int" >>$AP_CONFIG_AUTO_H | |
374 | + echo "#endif" >>$AP_CONFIG_AUTO_H | |
375 | + echo " - use unsigned int as 32bit unsigned int" | |
376 | +elif [ x`./helpers/TestCompile -r sizeof 'unsigned long int'` = x"4" ]; then | |
377 | + echo "" >>$AP_CONFIG_AUTO_H | |
378 | + echo "/* determine: use unsigned long int as 32bit unsigned int */" >>$AP_CONFIG_AUTO_H | |
379 | + echo "#ifndef uint32_t" >>$AP_CONFIG_AUTO_H | |
380 | + echo "#define uint32_t unsigned long int" >>$AP_CONFIG_AUTO_H | |
381 | + echo "#endif" >>$AP_CONFIG_AUTO_H | |
382 | + echo " - use unsigned long int as 32bit unsigned int" | |
383 | +else | |
384 | + echo " - Warning: cannot determine what type should we use as 32bit unsigned int" | |
385 | +fi | |
386 | ||
387 | #################################################################### | |
388 | ## More building ap_config_auto.h | |
389 | diff -Nru apache_1.3.20/src/ap/ap_snprintf.c apache_1.3.20.new/src/ap/ap_snprintf.c | |
390 | --- apache_1.3.20/src/ap/ap_snprintf.c Thu May 10 16:04:22 2001 | |
391 | +++ apache_1.3.20.new/src/ap/ap_snprintf.c Mon May 21 10:55:24 2001 | |
392 | @@ -73,6 +73,7 @@ | |
393 | #include <string.h> | |
394 | #include <stdlib.h> | |
395 | #include <math.h> | |
396 | +#include "sa_len.h" | |
397 | #ifdef WIN32 | |
398 | #include <float.h> | |
399 | #endif | |
400 | @@ -504,6 +505,42 @@ | |
401 | ||
402 | ||
403 | ||
404 | +#ifdef INET6 | |
405 | +static char *conv_sockaddr(struct sockaddr *sa, char *buf_end, int *len) | |
406 | +{ | |
407 | + char *p = buf_end; | |
408 | + char hostnamebuf[MAXHOSTNAMELEN]; | |
409 | + char portnamebuf[MAXHOSTNAMELEN]; | |
410 | + char *q; | |
411 | + int salen; | |
412 | + | |
413 | +#ifndef SIN6_LEN | |
414 | + salen = SA_LEN(sa); | |
415 | +#else | |
416 | + salen = sa->sa_len; | |
417 | +#endif | |
418 | + if (getnameinfo(sa, salen, hostnamebuf, sizeof(hostnamebuf), | |
419 | + portnamebuf, sizeof(portnamebuf), NI_NUMERICHOST | NI_NUMERICSERV)) { | |
420 | + strcpy(hostnamebuf, "???"); | |
421 | + strcpy(portnamebuf, "???"); | |
422 | + } | |
423 | + if (strcmp(portnamebuf,"0") == 0) | |
424 | + strcpy(portnamebuf, "*"); | |
425 | + q = portnamebuf + strlen(portnamebuf); | |
426 | + while (portnamebuf < q) | |
427 | + *--p = *--q; | |
428 | + *--p = ':'; | |
429 | + q = hostnamebuf + strlen(hostnamebuf); | |
430 | + while (hostnamebuf < q) | |
431 | + *--p = *--q; | |
432 | + | |
433 | + *len = buf_end - p; | |
434 | + return (p); | |
435 | +} | |
436 | +#endif /*INET6*/ | |
437 | + | |
438 | + | |
439 | + | |
440 | /* | |
441 | * Convert a floating point number to a string formats 'f', 'e' or 'E'. | |
442 | * The result is placed in buf, and len denotes the length of the string | |
443 | @@ -1055,6 +1092,7 @@ | |
444 | /* print a struct sockaddr_in as a.b.c.d:port */ | |
445 | case 'I': | |
446 | { | |
447 | +#ifndef INET6 | |
448 | struct sockaddr_in *si; | |
449 | ||
450 | si = va_arg(ap, struct sockaddr_in *); | |
451 | @@ -1063,6 +1101,16 @@ | |
452 | if (adjust_precision && precision < s_len) | |
453 | s_len = precision; | |
454 | } | |
455 | +#else | |
456 | + struct sockaddr *sa; | |
457 | + | |
458 | + sa = va_arg(ap, struct sockaddr *); | |
459 | + if (sa != NULL) { | |
460 | + s = conv_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len); | |
461 | + if (adjust_precision && precision < s_len) | |
462 | + s_len = precision; | |
463 | + } | |
464 | +#endif | |
465 | else { | |
466 | s = S_NULL; | |
467 | s_len = S_NULL_LEN; | |
468 | diff -Nru apache_1.3.20/src/ap/ap_snprintf.c~ apache_1.3.20.new/src/ap/ap_snprintf.c~ | |
469 | --- apache_1.3.20/src/ap/ap_snprintf.c~ Thu Jan 1 01:00:00 1970 | |
470 | +++ apache_1.3.20.new/src/ap/ap_snprintf.c~ Mon May 21 10:54:52 2001 | |
471 | @@ -0,0 +1,1256 @@ | |
472 | +/* ==================================================================== | |
473 | + * The Apache Software License, Version 1.1 | |
474 | + * | |
475 | + * Copyright (c) 2000 The Apache Software Foundation. All rights | |
476 | + * reserved. | |
477 | + * | |
478 | + * Redistribution and use in source and binary forms, with or without | |
479 | + * modification, are permitted provided that the following conditions | |
480 | + * are met: | |
481 | + * | |
482 | + * 1. Redistributions of source code must retain the above copyright | |
483 | + * notice, this list of conditions and the following disclaimer. | |
484 | + * | |
485 | + * 2. Redistributions in binary form must reproduce the above copyright | |
486 | + * notice, this list of conditions and the following disclaimer in | |
487 | + * the documentation and/or other materials provided with the | |
488 | + * distribution. | |
489 | + * | |
490 | + * 3. The end-user documentation included with the redistribution, | |
491 | + * if any, must include the following acknowledgment: | |
492 | + * "This product includes software developed by the | |
493 | + * Apache Software Foundation (http://www.apache.org/)." | |
494 | + * Alternately, this acknowledgment may appear in the software itself, | |
495 | + * if and wherever such third-party acknowledgments normally appear. | |
496 | + * | |
497 | + * 4. The names "Apache" and "Apache Software Foundation" must | |
498 | + * not be used to endorse or promote products derived from this | |
499 | + * software without prior written permission. For written | |
500 | + * permission, please contact apache@apache.org. | |
501 | + * | |
502 | + * 5. Products derived from this software may not be called "Apache", | |
503 | + * nor may "Apache" appear in their name, without prior written | |
504 | + * permission of the Apache Software Foundation. | |
505 | + * | |
506 | + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |
507 | + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
508 | + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
509 | + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |
510 | + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
511 | + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
512 | + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |
513 | + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
514 | + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
515 | + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
516 | + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
517 | + * SUCH DAMAGE. | |
518 | + * ==================================================================== | |
519 | + * | |
520 | + * This software consists of voluntary contributions made by many | |
521 | + * individuals on behalf of the Apache Software Foundation. For more | |
522 | + * information on the Apache Software Foundation, please see | |
523 | + * <http://www.apache.org/>. | |
524 | + * | |
525 | + * Portions of this software are based upon public domain software | |
526 | + * originally written at the National Center for Supercomputing Applications, | |
527 | + * University of Illinois, Urbana-Champaign. | |
528 | + */ | |
529 | + | |
530 | +/* | |
531 | + * This code is based on, and used with the permission of, the | |
532 | + * SIO stdio-replacement strx_* functions by Panos Tsirigotis | |
533 | + * <panos@alumni.cs.colorado.edu> for xinetd. | |
534 | + */ | |
535 | + | |
536 | +#include "httpd.h" | |
537 | + | |
538 | +#include <stdio.h> | |
539 | +#include <ctype.h> | |
540 | +#ifndef NETWARE | |
541 | +#include <sys/types.h> | |
542 | +#endif | |
543 | +#include <stdarg.h> | |
544 | +#include <string.h> | |
545 | +#include <stdlib.h> | |
546 | +#include <math.h> | |
547 | +#ifdef WIN32 | |
548 | +#include <float.h> | |
549 | +#endif | |
550 | + | |
551 | +typedef enum { | |
552 | + NO = 0, YES = 1 | |
553 | +} boolean_e; | |
554 | + | |
555 | +#ifndef FALSE | |
556 | +#define FALSE 0 | |
557 | +#endif | |
558 | +#ifndef TRUE | |
559 | +#define TRUE 1 | |
560 | +#endif | |
561 | +#ifndef AP_LONGEST_LONG | |
562 | +#define AP_LONGEST_LONG long | |
563 | +#endif | |
564 | +#define NUL '\0' | |
565 | +#define WIDE_INT long | |
566 | +#define WIDEST_INT AP_LONGEST_LONG | |
567 | + | |
568 | +typedef WIDE_INT wide_int; | |
569 | +typedef unsigned WIDE_INT u_wide_int; | |
570 | +typedef WIDEST_INT widest_int; | |
571 | +#ifdef __TANDEM | |
572 | +/* Although Tandem supports "long long" there is no unsigned variant. */ | |
573 | +typedef unsigned long u_widest_int; | |
574 | +#else | |
575 | +typedef unsigned WIDEST_INT u_widest_int; | |
576 | +#endif | |
577 | +typedef int bool_int; | |
578 | + | |
579 | +#define S_NULL "(null)" | |
580 | +#define S_NULL_LEN 6 | |
581 | + | |
582 | +#define FLOAT_DIGITS 6 | |
583 | +#define EXPONENT_LENGTH 10 | |
584 | + | |
585 | +/* | |
586 | + * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions | |
587 | + * | |
588 | + * XXX: this is a magic number; do not decrease it | |
589 | + */ | |
590 | +#define NUM_BUF_SIZE 512 | |
591 | + | |
592 | +/* | |
593 | + * cvt.c - IEEE floating point formatting routines for FreeBSD | |
594 | + * from GNU libc-4.6.27. Modified to be thread safe. | |
595 | + */ | |
596 | + | |
597 | +/* | |
598 | + * ap_ecvt converts to decimal | |
599 | + * the number of digits is specified by ndigit | |
600 | + * decpt is set to the position of the decimal point | |
601 | + * sign is set to 0 for positive, 1 for negative | |
602 | + */ | |
603 | + | |
604 | +#define NDIG 80 | |
605 | + | |
606 | +/* buf must have at least NDIG bytes */ | |
607 | +static char *ap_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf) | |
608 | +{ | |
609 | + register int r2; | |
610 | + double fi, fj; | |
611 | + register char *p, *p1; | |
612 | + | |
613 | + if (ndigits >= NDIG - 1) | |
614 | + ndigits = NDIG - 2; | |
615 | + r2 = 0; | |
616 | + *sign = 0; | |
617 | + p = &buf[0]; | |
618 | + if (arg < 0) { | |
619 | + *sign = 1; | |
620 | + arg = -arg; | |
621 | + } | |
622 | + arg = modf(arg, &fi); | |
623 | + p1 = &buf[NDIG]; | |
624 | + /* | |
625 | + * Do integer part | |
626 | + */ | |
627 | + if (fi != 0) { | |
628 | + p1 = &buf[NDIG]; | |
629 | + while (p1 > &buf[0] && fi != 0) { | |
630 | + fj = modf(fi / 10, &fi); | |
631 | + *--p1 = (int) ((fj + .03) * 10) + '0'; | |
632 | + r2++; | |
633 | + } | |
634 | + while (p1 < &buf[NDIG]) | |
635 | + *p++ = *p1++; | |
636 | + } | |
637 | + else if (arg > 0) { | |
638 | + while ((fj = arg * 10) < 1) { | |
639 | + arg = fj; | |
640 | + r2--; | |
641 | + } | |
642 | + } | |
643 | + p1 = &buf[ndigits]; | |
644 | + if (eflag == 0) | |
645 | + p1 += r2; | |
646 | + *decpt = r2; | |
647 | + if (p1 < &buf[0]) { | |
648 | + buf[0] = '\0'; | |
649 | + return (buf); | |
650 | + } | |
651 | + while (p <= p1 && p < &buf[NDIG]) { | |
652 | + arg *= 10; | |
653 | + arg = modf(arg, &fj); | |
654 | + *p++ = (int) fj + '0'; | |
655 | + } | |
656 | + if (p1 >= &buf[NDIG]) { | |
657 | + buf[NDIG - 1] = '\0'; | |
658 | + return (buf); | |
659 | + } | |
660 | + p = p1; | |
661 | + *p1 += 5; | |
662 | + while (*p1 > '9') { | |
663 | + *p1 = '0'; | |
664 | + if (p1 > buf) | |
665 | + ++ * --p1; | |
666 | + else { | |
667 | + *p1 = '1'; | |
668 | + (*decpt)++; | |
669 | + if (eflag == 0) { | |
670 | + if (p > buf) | |
671 | + *p = '0'; | |
672 | + p++; | |
673 | + } | |
674 | + } | |
675 | + } | |
676 | + *p = '\0'; | |
677 | + return (buf); | |
678 | +} | |
679 | + | |
680 | +static char *ap_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf) | |
681 | +{ | |
682 | + return (ap_cvt(arg, ndigits, decpt, sign, 1, buf)); | |
683 | +} | |
684 | + | |
685 | +static char *ap_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf) | |
686 | +{ | |
687 | + return (ap_cvt(arg, ndigits, decpt, sign, 0, buf)); | |
688 | +} | |
689 | + | |
690 | +/* | |
691 | + * ap_gcvt - Floating output conversion to | |
692 | + * minimal length string | |
693 | + */ | |
694 | + | |
695 | +static char *ap_gcvt(double number, int ndigit, char *buf, boolean_e altform) | |
696 | +{ | |
697 | + int sign, decpt; | |
698 | + register char *p1, *p2; | |
699 | + register int i; | |
700 | + char buf1[NDIG]; | |
701 | + | |
702 | + p1 = ap_ecvt(number, ndigit, &decpt, &sign, buf1); | |
703 | + p2 = buf; | |
704 | + if (sign) | |
705 | + *p2++ = '-'; | |
706 | + for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--) | |
707 | + ndigit--; | |
708 | + if ((decpt >= 0 && decpt - ndigit > 4) | |
709 | + || (decpt < 0 && decpt < -3)) { /* use E-style */ | |
710 | + decpt--; | |
711 | + *p2++ = *p1++; | |
712 | + *p2++ = '.'; | |
713 | + for (i = 1; i < ndigit; i++) | |
714 | + *p2++ = *p1++; | |
715 | + *p2++ = 'e'; | |
716 | + if (decpt < 0) { | |
717 | + decpt = -decpt; | |
718 | + *p2++ = '-'; | |
719 | + } | |
720 | + else | |
721 | + *p2++ = '+'; | |
722 | + if (decpt / 100 > 0) | |
723 | + *p2++ = decpt / 100 + '0'; | |
724 | + if (decpt / 10 > 0) | |
725 | + *p2++ = (decpt % 100) / 10 + '0'; | |
726 | + *p2++ = decpt % 10 + '0'; | |
727 | + } | |
728 | + else { | |
729 | + if (decpt <= 0) { | |
730 | + if (*p1 != '0') | |
731 | + *p2++ = '.'; | |
732 | + while (decpt < 0) { | |
733 | + decpt++; | |
734 | + *p2++ = '0'; | |
735 | + } | |
736 | + } | |
737 | + for (i = 1; i <= ndigit; i++) { | |
738 | + *p2++ = *p1++; | |
739 | + if (i == decpt) | |
740 | + *p2++ = '.'; | |
741 | + } | |
742 | + if (ndigit < decpt) { | |
743 | + while (ndigit++ < decpt) | |
744 | + *p2++ = '0'; | |
745 | + *p2++ = '.'; | |
746 | + } | |
747 | + } | |
748 | + if (p2[-1] == '.' && !altform) | |
749 | + p2--; | |
750 | + *p2 = '\0'; | |
751 | + return (buf); | |
752 | +} | |
753 | + | |
754 | +/* | |
755 | + * The INS_CHAR macro inserts a character in the buffer and writes | |
756 | + * the buffer back to disk if necessary | |
757 | + * It uses the char pointers sp and bep: | |
758 | + * sp points to the next available character in the buffer | |
759 | + * bep points to the end-of-buffer+1 | |
760 | + * While using this macro, note that the nextb pointer is NOT updated. | |
761 | + * | |
762 | + * NOTE: Evaluation of the c argument should not have any side-effects | |
763 | + */ | |
764 | +#define INS_CHAR(c, sp, bep, cc) \ | |
765 | + { \ | |
766 | + if (sp >= bep) { \ | |
767 | + vbuff->curpos = sp; \ | |
768 | + if (flush_func(vbuff)) \ | |
769 | + return -1; \ | |
770 | + sp = vbuff->curpos; \ | |
771 | + bep = vbuff->endpos; \ | |
772 | + } \ | |
773 | + *sp++ = (c); \ | |
774 | + cc++; \ | |
775 | + } | |
776 | + | |
777 | +#define NUM( c ) ( c - '0' ) | |
778 | + | |
779 | +#define STR_TO_DEC( str, num ) \ | |
780 | + num = NUM( *str++ ) ; \ | |
781 | + while ( ap_isdigit( *str ) ) \ | |
782 | + { \ | |
783 | + num *= 10 ; \ | |
784 | + num += NUM( *str++ ) ; \ | |
785 | + } | |
786 | + | |
787 | +/* | |
788 | + * This macro does zero padding so that the precision | |
789 | + * requirement is satisfied. The padding is done by | |
790 | + * adding '0's to the left of the string that is going | |
791 | + * to be printed. | |
792 | + */ | |
793 | +#define FIX_PRECISION( adjust, precision, s, s_len ) \ | |
794 | + if ( adjust ) \ | |
795 | + while ( s_len < precision ) \ | |
796 | + { \ | |
797 | + *--s = '0' ; \ | |
798 | + s_len++ ; \ | |
799 | + } | |
800 | + | |
801 | +/* | |
802 | + * Macro that does padding. The padding is done by printing | |
803 | + * the character ch. | |
804 | + */ | |
805 | +#define PAD( width, len, ch ) do \ | |
806 | + { \ | |
807 | + INS_CHAR( ch, sp, bep, cc ) ; \ | |
808 | + width-- ; \ | |
809 | + } \ | |
810 | + while ( width > len ) | |
811 | + | |
812 | +/* | |
813 | + * Prefix the character ch to the string str | |
814 | + * Increase length | |
815 | + * Set the has_prefix flag | |
816 | + */ | |
817 | +#define PREFIX( str, length, ch ) *--str = ch ; length++ ; has_prefix = YES | |
818 | + | |
819 | + | |
820 | +/* | |
821 | + * Convert num to its decimal format. | |
822 | + * Return value: | |
823 | + * - a pointer to a string containing the number (no sign) | |
824 | + * - len contains the length of the string | |
825 | + * - is_negative is set to TRUE or FALSE depending on the sign | |
826 | + * of the number (always set to FALSE if is_unsigned is TRUE) | |
827 | + * | |
828 | + * The caller provides a buffer for the string: that is the buf_end argument | |
829 | + * which is a pointer to the END of the buffer + 1 (i.e. if the buffer | |
830 | + * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) | |
831 | + * | |
832 | + * Note: we have 2 versions. One is used when we need to use quads | |
833 | + * (conv_10_quad), the other when we don't (conv_10). We're assuming the | |
834 | + * latter is faster. | |
835 | + */ | |
836 | +static char *conv_10(register wide_int num, register bool_int is_unsigned, | |
837 | + register bool_int *is_negative, char *buf_end, | |
838 | + register int *len) | |
839 | +{ | |
840 | + register char *p = buf_end; | |
841 | + register u_wide_int magnitude; | |
842 | + | |
843 | + if (is_unsigned) { | |
844 | + magnitude = (u_wide_int) num; | |
845 | + *is_negative = FALSE; | |
846 | + } | |
847 | + else { | |
848 | + *is_negative = (num < 0); | |
849 | + | |
850 | + /* | |
851 | + * On a 2's complement machine, negating the most negative integer | |
852 | + * results in a number that cannot be represented as a signed integer. | |
853 | + * Here is what we do to obtain the number's magnitude: | |
854 | + * a. add 1 to the number | |
855 | + * b. negate it (becomes positive) | |
856 | + * c. convert it to unsigned | |
857 | + * d. add 1 | |
858 | + */ | |
859 | + if (*is_negative) { | |
860 | + wide_int t = num + 1; | |
861 | + | |
862 | + magnitude = ((u_wide_int) -t) + 1; | |
863 | + } | |
864 | + else | |
865 | + magnitude = (u_wide_int) num; | |
866 | + } | |
867 | + | |
868 | + /* | |
869 | + * We use a do-while loop so that we write at least 1 digit | |
870 | + */ | |
871 | + do { | |
872 | + register u_wide_int new_magnitude = magnitude / 10; | |
873 | + | |
874 | + *--p = (char) (magnitude - new_magnitude * 10 + '0'); | |
875 | + magnitude = new_magnitude; | |
876 | + } | |
877 | + while (magnitude); | |
878 | + | |
879 | + *len = buf_end - p; | |
880 | + return (p); | |
881 | +} | |
882 | + | |
883 | +static char *conv_10_quad(widest_int num, register bool_int is_unsigned, | |
884 | + register bool_int *is_negative, char *buf_end, | |
885 | + register int *len) | |
886 | +{ | |
887 | + register char *p = buf_end; | |
888 | + u_widest_int magnitude; | |
889 | + | |
890 | + /* | |
891 | + * We see if we can use the faster non-quad version by checking the | |
892 | + * number against the largest long value it can be. If <=, we | |
893 | + * punt to the quicker version. | |
894 | + */ | |
895 | + if ((num <= ULONG_MAX && is_unsigned) || (num <= LONG_MAX && !is_unsigned)) | |
896 | + return(conv_10( (wide_int)num, is_unsigned, is_negative, | |
897 | + buf_end, len)); | |
898 | + | |
899 | + if (is_unsigned) { | |
900 | + magnitude = (u_widest_int) num; | |
901 | + *is_negative = FALSE; | |
902 | + } | |
903 | + else { | |
904 | + *is_negative = (num < 0); | |
905 | + | |
906 | + /* | |
907 | + * On a 2's complement machine, negating the most negative integer | |
908 | + * results in a number that cannot be represented as a signed integer. | |
909 | + * Here is what we do to obtain the number's magnitude: | |
910 | + * a. add 1 to the number | |
911 | + * b. negate it (becomes positive) | |
912 | + * c. convert it to unsigned | |
913 | + * d. add 1 | |
914 | + */ | |
915 | + if (*is_negative) { | |
916 | + widest_int t = num + 1; | |
917 | + | |
918 | + magnitude = ((u_widest_int) -t) + 1; | |
919 | + } | |
920 | + else | |
921 | + magnitude = (u_widest_int) num; | |
922 | + } | |
923 | + | |
924 | + /* | |
925 | + * We use a do-while loop so that we write at least 1 digit | |
926 | + */ | |
927 | + do { | |
928 | + u_widest_int new_magnitude = magnitude / 10; | |
929 | + | |
930 | + *--p = (char) (magnitude - new_magnitude * 10 + '0'); | |
931 | + magnitude = new_magnitude; | |
932 | + } | |
933 | + while (magnitude); | |
934 | + | |
935 | + *len = buf_end - p; | |
936 | + return (p); | |
937 | +} | |
938 | + | |
939 | + | |
940 | + | |
941 | +static char *conv_in_addr(struct in_addr *ia, char *buf_end, int *len) | |
942 | +{ | |
943 | + unsigned addr = ntohl(ia->s_addr); | |
944 | + char *p = buf_end; | |
945 | + bool_int is_negative; | |
946 | + int sub_len; | |
947 | + | |
948 | + p = conv_10((addr & 0x000000FF) , TRUE, &is_negative, p, &sub_len); | |
949 | + *--p = '.'; | |
950 | + p = conv_10((addr & 0x0000FF00) >> 8, TRUE, &is_negative, p, &sub_len); | |
951 | + *--p = '.'; | |
952 | + p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len); | |
953 | + *--p = '.'; | |
954 | + p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len); | |
955 | + | |
956 | + *len = buf_end - p; | |
957 | + return (p); | |
958 | +} | |
959 | + | |
960 | + | |
961 | + | |
962 | +static char *conv_sockaddr_in(struct sockaddr_in *si, char *buf_end, int *len) | |
963 | +{ | |
964 | + char *p = buf_end; | |
965 | + bool_int is_negative; | |
966 | + int sub_len; | |
967 | + | |
968 | + p = conv_10(ntohs(si->sin_port), TRUE, &is_negative, p, &sub_len); | |
969 | + *--p = ':'; | |
970 | + p = conv_in_addr(&si->sin_addr, p, &sub_len); | |
971 | + | |
972 | + *len = buf_end - p; | |
973 | + return (p); | |
974 | +} | |
975 | + | |
976 | + | |
977 | + | |
978 | +#ifdef INET6 | |
979 | +static char *conv_sockaddr(struct sockaddr *sa, char *buf_end, int *len) | |
980 | +{ | |
981 | + char *p = buf_end; | |
982 | + char hostnamebuf[MAXHOSTNAMELEN]; | |
983 | + char portnamebuf[MAXHOSTNAMELEN]; | |
984 | + char *q; | |
985 | + int salen; | |
986 | + | |
987 | +#ifndef SIN6_LEN | |
988 | + salen = SA_LEN(sa); | |
989 | +#else | |
990 | + salen = sa->sa_len; | |
991 | +#endif | |
992 | + if (getnameinfo(sa, salen, hostnamebuf, sizeof(hostnamebuf), | |
993 | + portnamebuf, sizeof(portnamebuf), NI_NUMERICHOST | NI_NUMERICSERV)) { | |
994 | + strcpy(hostnamebuf, "???"); | |
995 | + strcpy(portnamebuf, "???"); | |
996 | + } | |
997 | + if (strcmp(portnamebuf,"0") == 0) | |
998 | + strcpy(portnamebuf, "*"); | |
999 | + q = portnamebuf + strlen(portnamebuf); | |
1000 | + while (portnamebuf < q) | |
1001 | + *--p = *--q; | |
1002 | + *--p = ':'; | |
1003 | + q = hostnamebuf + strlen(hostnamebuf); | |
1004 | + while (hostnamebuf < q) | |
1005 | + *--p = *--q; | |
1006 | + | |
1007 | + *len = buf_end - p; | |
1008 | + return (p); | |
1009 | +} | |
1010 | +#endif /*INET6*/ | |
1011 | + | |
1012 | + | |
1013 | + | |
1014 | +/* | |
1015 | + * Convert a floating point number to a string formats 'f', 'e' or 'E'. | |
1016 | + * The result is placed in buf, and len denotes the length of the string | |
1017 | + * The sign is returned in the is_negative argument (and is not placed | |
1018 | + * in buf). | |
1019 | + */ | |
1020 | +static char *conv_fp(register char format, register double num, | |
1021 | + boolean_e add_dp, int precision, bool_int *is_negative, | |
1022 | + char *buf, int *len) | |
1023 | +{ | |
1024 | + register char *s = buf; | |
1025 | + register char *p; | |
1026 | + int decimal_point; | |
1027 | + char buf1[NDIG]; | |
1028 | + | |
1029 | + if (format == 'f') | |
1030 | + p = ap_fcvt(num, precision, &decimal_point, is_negative, buf1); | |
1031 | + else /* either e or E format */ | |
1032 | + p = ap_ecvt(num, precision + 1, &decimal_point, is_negative, buf1); | |
1033 | + | |
1034 | + /* | |
1035 | + * Check for Infinity and NaN | |
1036 | + */ | |
1037 | + if (ap_isalpha(*p)) { | |
1038 | + *len = strlen(strcpy(buf, p)); | |
1039 | + *is_negative = FALSE; | |
1040 | + return (buf); | |
1041 | + } | |
1042 | + | |
1043 | + if (format == 'f') { | |
1044 | + if (decimal_point <= 0) { | |
1045 | + *s++ = '0'; | |
1046 | + if (precision > 0) { | |
1047 | + *s++ = '.'; | |
1048 | + while (decimal_point++ < 0) | |
1049 | + *s++ = '0'; | |
1050 | + } | |
1051 | + else if (add_dp) | |
1052 | + *s++ = '.'; | |
1053 | + } | |
1054 | + else { | |
1055 | + while (decimal_point-- > 0) | |
1056 | + *s++ = *p++; | |
1057 | + if (precision > 0 || add_dp) | |
1058 | + *s++ = '.'; | |
1059 | + } | |
1060 | + } | |
1061 | + else { | |
1062 | + *s++ = *p++; | |
1063 | + if (precision > 0 || add_dp) | |
1064 | + *s++ = '.'; | |
1065 | + } | |
1066 | + | |
1067 | + /* | |
1068 | + * copy the rest of p, the NUL is NOT copied | |
1069 | + */ | |
1070 | + while (*p) | |
1071 | + *s++ = *p++; | |
1072 | + | |
1073 | + if (format != 'f') { | |
1074 | + char temp[EXPONENT_LENGTH]; /* for exponent conversion */ | |
1075 | + int t_len; | |
1076 | + bool_int exponent_is_negative; | |
1077 | + | |
1078 | + *s++ = format; /* either e or E */ | |
1079 | + decimal_point--; | |
1080 | + if (decimal_point != 0) { | |
1081 | + p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative, | |
1082 | + &temp[EXPONENT_LENGTH], &t_len); | |
1083 | + *s++ = exponent_is_negative ? '-' : '+'; | |
1084 | + | |
1085 | + /* | |
1086 | + * Make sure the exponent has at least 2 digits | |
1087 | + */ | |
1088 | + if (t_len == 1) | |
1089 | + *s++ = '0'; | |
1090 | + while (t_len--) | |
1091 | + *s++ = *p++; | |
1092 | + } | |
1093 | + else { | |
1094 | + *s++ = '+'; | |
1095 | + *s++ = '0'; | |
1096 | + *s++ = '0'; | |
1097 | + } | |
1098 | + } | |
1099 | + | |
1100 | + *len = s - buf; | |
1101 | + return (buf); | |
1102 | +} | |
1103 | + | |
1104 | + | |
1105 | +/* | |
1106 | + * Convert num to a base X number where X is a power of 2. nbits determines X. | |
1107 | + * For example, if nbits is 3, we do base 8 conversion | |
1108 | + * Return value: | |
1109 | + * a pointer to a string containing the number | |
1110 | + * | |
1111 | + * The caller provides a buffer for the string: that is the buf_end argument | |
1112 | + * which is a pointer to the END of the buffer + 1 (i.e. if the buffer | |
1113 | + * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) | |
1114 | + * | |
1115 | + * As with conv_10, we have a faster version which is used when | |
1116 | + * the number isn't quad size. | |
1117 | + */ | |
1118 | +static char *conv_p2(register u_wide_int num, register int nbits, | |
1119 | + char format, char *buf_end, register int *len) | |
1120 | +{ | |
1121 | + register int mask = (1 << nbits) - 1; | |
1122 | + register char *p = buf_end; | |
1123 | + static const char low_digits[] = "0123456789abcdef"; | |
1124 | + static const char upper_digits[] = "0123456789ABCDEF"; | |
1125 | + register const char *digits = (format == 'X') ? upper_digits : low_digits; | |
1126 | + | |
1127 | + do { | |
1128 | + *--p = digits[num & mask]; | |
1129 | + num >>= nbits; | |
1130 | + } | |
1131 | + while (num); | |
1132 | + | |
1133 | + *len = buf_end - p; | |
1134 | + return (p); | |
1135 | +} | |
1136 | + | |
1137 | +static char *conv_p2_quad(u_widest_int num, register int nbits, | |
1138 | + char format, char *buf_end, register int *len) | |
1139 | +{ | |
1140 | + register int mask = (1 << nbits) - 1; | |
1141 | + register char *p = buf_end; | |
1142 | + static const char low_digits[] = "0123456789abcdef"; | |
1143 | + static const char upper_digits[] = "0123456789ABCDEF"; | |
1144 | + register const char *digits = (format == 'X') ? upper_digits : low_digits; | |
1145 | + | |
1146 | + if (num <= ULONG_MAX) | |
1147 | + return(conv_p2( (u_wide_int)num, nbits, format, buf_end, len)); | |
1148 | + | |
1149 | + do { | |
1150 | + *--p = digits[num & mask]; | |
1151 | + num >>= nbits; | |
1152 | + } | |
1153 | + while (num); | |
1154 | + | |
1155 | + *len = buf_end - p; | |
1156 | + return (p); | |
1157 | +} | |
1158 | + | |
1159 | + | |
1160 | +/* | |
1161 | + * Do format conversion placing the output in buffer | |
1162 | + */ | |
1163 | +API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *), | |
1164 | + ap_vformatter_buff *vbuff, const char *fmt, va_list ap) | |
1165 | +{ | |
1166 | + register char *sp; | |
1167 | + register char *bep; | |
1168 | + register int cc = 0; | |
1169 | + register int i; | |
1170 | + | |
1171 | + register char *s = NULL; | |
1172 | + char *q; | |
1173 | + int s_len; | |
1174 | + | |
1175 | + register int min_width = 0; | |
1176 | + int precision = 0; | |
1177 | + enum { | |
1178 | + LEFT, RIGHT | |
1179 | + } adjust; | |
1180 | + char pad_char; | |
1181 | + char prefix_char; | |
1182 | + | |
1183 | + double fp_num; | |
1184 | + widest_int i_quad = (widest_int) 0; | |
1185 | + u_widest_int ui_quad; | |
1186 | + wide_int i_num = (wide_int) 0; | |
1187 | + u_wide_int ui_num; | |
1188 | + | |
1189 | + char num_buf[NUM_BUF_SIZE]; | |
1190 | + char char_buf[2]; /* for printing %% and %<unknown> */ | |
1191 | + | |
1192 | + enum var_type_enum { | |
1193 | + IS_QUAD, IS_LONG, IS_SHORT, IS_INT | |
1194 | + }; | |
1195 | + enum var_type_enum var_type = IS_INT; | |
1196 | + | |
1197 | + /* | |
1198 | + * Flag variables | |
1199 | + */ | |
1200 | + boolean_e alternate_form; | |
1201 | + boolean_e print_sign; | |
1202 | + boolean_e print_blank; | |
1203 | + boolean_e adjust_precision; | |
1204 | + boolean_e adjust_width; | |
1205 | + bool_int is_negative; | |
1206 | + | |
1207 | + sp = vbuff->curpos; | |
1208 | + bep = vbuff->endpos; | |
1209 | + | |
1210 | + while (*fmt) { | |
1211 | + if (*fmt != '%') { | |
1212 | + INS_CHAR(*fmt, sp, bep, cc); | |
1213 | + } | |
1214 | + else { | |
1215 | + /* | |
1216 | + * Default variable settings | |
1217 | + */ | |
1218 | + adjust = RIGHT; | |
1219 | + alternate_form = print_sign = print_blank = NO; | |
1220 | + pad_char = ' '; | |
1221 | + prefix_char = NUL; | |
1222 | + | |
1223 | + fmt++; | |
1224 | + | |
1225 | + /* | |
1226 | + * Try to avoid checking for flags, width or precision | |
1227 | + */ | |
1228 | + if (!ap_islower(*fmt)) { | |
1229 | + /* | |
1230 | + * Recognize flags: -, #, BLANK, + | |
1231 | + */ | |
1232 | + for (;; fmt++) { | |
1233 | + if (*fmt == '-') | |
1234 | + adjust = LEFT; | |
1235 | + else if (*fmt == '+') | |
1236 | + print_sign = YES; | |
1237 | + else if (*fmt == '#') | |
1238 | + alternate_form = YES; | |
1239 | + else if (*fmt == ' ') | |
1240 | + print_blank = YES; | |
1241 | + else if (*fmt == '0') | |
1242 | + pad_char = '0'; | |
1243 | + else | |
1244 | + break; | |
1245 | + } | |
1246 | + | |
1247 | + /* | |
1248 | + * Check if a width was specified | |
1249 | + */ | |
1250 | + if (ap_isdigit(*fmt)) { | |
1251 | + STR_TO_DEC(fmt, min_width); | |
1252 | + adjust_width = YES; | |
1253 | + } | |
1254 | + else if (*fmt == '*') { | |
1255 | + min_width = va_arg(ap, int); | |
1256 | + fmt++; | |
1257 | + adjust_width = YES; | |
1258 | + if (min_width < 0) { | |
1259 | + adjust = LEFT; | |
1260 | + min_width = -min_width; | |
1261 | + } | |
1262 | + } | |
1263 | + else | |
1264 | + adjust_width = NO; | |
1265 | + | |
1266 | + /* | |
1267 | + * Check if a precision was specified | |
1268 | + * | |
1269 | + * XXX: an unreasonable amount of precision may be specified | |
1270 | + * resulting in overflow of num_buf. Currently we | |
1271 | + * ignore this possibility. | |
1272 | + */ | |
1273 | + if (*fmt == '.') { | |
1274 | + adjust_precision = YES; | |
1275 | + fmt++; | |
1276 | + if (ap_isdigit(*fmt)) { | |
1277 | + STR_TO_DEC(fmt, precision); | |
1278 | + } | |
1279 | + else if (*fmt == '*') { | |
1280 | + precision = va_arg(ap, int); | |
1281 | + fmt++; | |
1282 | + if (precision < 0) | |
1283 | + precision = 0; | |
1284 | + } | |
1285 | + else | |
1286 | + precision = 0; | |
1287 | + } | |
1288 | + else | |
1289 | + adjust_precision = NO; | |
1290 | + } | |
1291 | + else | |
1292 | + adjust_precision = adjust_width = NO; | |
1293 | + | |
1294 | + /* | |
1295 | + * Modifier check | |
1296 | + */ | |
1297 | + if (*fmt == 'q') { | |
1298 | + var_type = IS_QUAD; | |
1299 | + fmt++; | |
1300 | + } | |
1301 | + else if (*fmt == 'l') { | |
1302 | + var_type = IS_LONG; | |
1303 | + fmt++; | |
1304 | + } | |
1305 | + else if (*fmt == 'h') { | |
1306 | + var_type = IS_SHORT; | |
1307 | + fmt++; | |
1308 | + } | |
1309 | + else { | |
1310 | + var_type = IS_INT; | |
1311 | + } | |
1312 | + | |
1313 | + /* | |
1314 | + * Argument extraction and printing. | |
1315 | + * First we determine the argument type. | |
1316 | + * Then, we convert the argument to a string. | |
1317 | + * On exit from the switch, s points to the string that | |
1318 | + * must be printed, s_len has the length of the string | |
1319 | + * The precision requirements, if any, are reflected in s_len. | |
1320 | + * | |
1321 | + * NOTE: pad_char may be set to '0' because of the 0 flag. | |
1322 | + * It is reset to ' ' by non-numeric formats | |
1323 | + */ | |
1324 | + switch (*fmt) { | |
1325 | + case 'u': | |
1326 | + if (var_type == IS_QUAD) { | |
1327 | + i_quad = va_arg(ap, u_widest_int); | |
1328 | + s = conv_10_quad(i_quad, 1, &is_negative, | |
1329 | + &num_buf[NUM_BUF_SIZE], &s_len); | |
1330 | + } | |
1331 | + else { | |
1332 | + if (var_type == IS_LONG) | |
1333 | + i_num = (wide_int) va_arg(ap, u_wide_int); | |
1334 | + else if (var_type == IS_SHORT) | |
1335 | + i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int); | |
1336 | + else | |
1337 | + i_num = (wide_int) va_arg(ap, unsigned int); | |
1338 | + s = conv_10(i_num, 1, &is_negative, | |
1339 | + &num_buf[NUM_BUF_SIZE], &s_len); | |
1340 | + } | |
1341 | + FIX_PRECISION(adjust_precision, precision, s, s_len); | |
1342 | + break; | |
1343 | + | |
1344 | + case 'd': | |
1345 | + case 'i': | |
1346 | + if (var_type == IS_QUAD) { | |
1347 | + i_quad = va_arg(ap, widest_int); | |
1348 | + s = conv_10_quad(i_quad, 0, &is_negative, | |
1349 | + &num_buf[NUM_BUF_SIZE], &s_len); | |
1350 | + } | |
1351 | + else { | |
1352 | + if (var_type == IS_LONG) | |
1353 | + i_num = (wide_int) va_arg(ap, wide_int); | |
1354 | + else if (var_type == IS_SHORT) | |
1355 | + i_num = (wide_int) (short) va_arg(ap, int); | |
1356 | + else | |
1357 | + i_num = (wide_int) va_arg(ap, int); | |
1358 | + s = conv_10(i_num, 0, &is_negative, | |
1359 | + &num_buf[NUM_BUF_SIZE], &s_len); | |
1360 | + } | |
1361 | + FIX_PRECISION(adjust_precision, precision, s, s_len); | |
1362 | + | |
1363 | + if (is_negative) | |
1364 | + prefix_char = '-'; | |
1365 | + else if (print_sign) | |
1366 | + prefix_char = '+'; | |
1367 | + else if (print_blank) | |
1368 | + prefix_char = ' '; | |
1369 | + break; | |
1370 | + | |
1371 | + | |
1372 | + case 'o': | |
1373 | + if (var_type == IS_QUAD) { | |
1374 | + ui_quad = va_arg(ap, u_widest_int); | |
1375 | + s = conv_p2_quad(ui_quad, 3, *fmt, | |
1376 | + &num_buf[NUM_BUF_SIZE], &s_len); | |
1377 | + } | |
1378 | + else { | |
1379 | + if (var_type == IS_LONG) | |
1380 | + ui_num = (u_wide_int) va_arg(ap, u_wide_int); | |
1381 | + else if (var_type == IS_SHORT) | |
1382 | + ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int); | |
1383 | + else | |
1384 | + ui_num = (u_wide_int) va_arg(ap, unsigned int); | |
1385 | + s = conv_p2(ui_num, 3, *fmt, | |
1386 | + &num_buf[NUM_BUF_SIZE], &s_len); | |
1387 | + } | |
1388 | + FIX_PRECISION(adjust_precision, precision, s, s_len); | |
1389 | + if (alternate_form && *s != '0') { | |
1390 | + *--s = '0'; | |
1391 | + s_len++; | |
1392 | + } | |
1393 | + break; | |
1394 | + | |
1395 | + | |
1396 | + case 'x': | |
1397 | + case 'X': | |
1398 | + if (var_type == IS_QUAD) { | |
1399 | + ui_quad = va_arg(ap, u_widest_int); | |
1400 | + s = conv_p2_quad(ui_quad, 4, *fmt, | |
1401 | + &num_buf[NUM_BUF_SIZE], &s_len); | |
1402 | + } | |
1403 | + else { | |
1404 | + if (var_type == IS_LONG) | |
1405 | + ui_num = (u_wide_int) va_arg(ap, u_wide_int); | |
1406 | + else if (var_type == IS_SHORT) | |
1407 | + ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int); | |
1408 | + else | |
1409 | + ui_num = (u_wide_int) va_arg(ap, unsigned int); | |
1410 | + s = conv_p2(ui_num, 4, *fmt, | |
1411 | + &num_buf[NUM_BUF_SIZE], &s_len); | |
1412 | + } | |
1413 | + FIX_PRECISION(adjust_precision, precision, s, s_len); | |
1414 | + if (alternate_form && i_num != 0) { | |
1415 | + *--s = *fmt; /* 'x' or 'X' */ | |
1416 | + *--s = '0'; | |
1417 | + s_len += 2; | |
1418 | + } | |
1419 | + break; | |
1420 | + | |
1421 | + | |
1422 | + case 's': | |
1423 | + s = va_arg(ap, char *); | |
1424 | + if (s != NULL) { | |
1425 | + s_len = strlen(s); | |
1426 | + if (adjust_precision && precision < s_len) | |
1427 | + s_len = precision; | |
1428 | + } | |
1429 | + else { | |
1430 | + s = S_NULL; | |
1431 | + s_len = S_NULL_LEN; | |
1432 | + } | |
1433 | + pad_char = ' '; | |
1434 | + break; | |
1435 | + | |
1436 | + | |
1437 | + case 'f': | |
1438 | + case 'e': | |
1439 | + case 'E': | |
1440 | + fp_num = va_arg(ap, double); | |
1441 | + /* | |
1442 | + * * We use &num_buf[ 1 ], so that we have room for the sign | |
1443 | + */ | |
1444 | +#ifdef HAVE_ISNAN | |
1445 | + if (isnan(fp_num)) { | |
1446 | + s = "nan"; | |
1447 | + s_len = 3; | |
1448 | + } | |
1449 | + else | |
1450 | +#endif | |
1451 | +#ifdef HAVE_ISINF | |
1452 | + if (isinf(fp_num)) { | |
1453 | + s = "inf"; | |
1454 | + s_len = 3; | |
1455 | + } | |
1456 | + else | |
1457 | +#endif | |
1458 | + { | |
1459 | + s = conv_fp(*fmt, fp_num, alternate_form, | |
1460 | + (adjust_precision == NO) ? FLOAT_DIGITS : precision, | |
1461 | + &is_negative, &num_buf[1], &s_len); | |
1462 | + if (is_negative) | |
1463 | + prefix_char = '-'; | |
1464 | + else if (print_sign) | |
1465 | + prefix_char = '+'; | |
1466 | + else if (print_blank) | |
1467 | + prefix_char = ' '; | |
1468 | + } | |
1469 | + break; | |
1470 | + | |
1471 | + | |
1472 | + case 'g': | |
1473 | + case 'G': | |
1474 | + if (adjust_precision == NO) | |
1475 | + precision = FLOAT_DIGITS; | |
1476 | + else if (precision == 0) | |
1477 | + precision = 1; | |
1478 | + /* | |
1479 | + * * We use &num_buf[ 1 ], so that we have room for the sign | |
1480 | + */ | |
1481 | + s = ap_gcvt(va_arg(ap, double), precision, &num_buf[1], | |
1482 | + alternate_form); | |
1483 | + if (*s == '-') | |
1484 | + prefix_char = *s++; | |
1485 | + else if (print_sign) | |
1486 | + prefix_char = '+'; | |
1487 | + else if (print_blank) | |
1488 | + prefix_char = ' '; | |
1489 | + | |
1490 | + s_len = strlen(s); | |
1491 | + | |
1492 | + if (alternate_form && (q = strchr(s, '.')) == NULL) { | |
1493 | + s[s_len++] = '.'; | |
1494 | + s[s_len] = '\0'; /* delimit for following strchr() */ | |
1495 | + } | |
1496 | + if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL) | |
1497 | + *q = 'E'; | |
1498 | + break; | |
1499 | + | |
1500 | + | |
1501 | + case 'c': | |
1502 | + char_buf[0] = (char) (va_arg(ap, int)); | |
1503 | + s = &char_buf[0]; | |
1504 | + s_len = 1; | |
1505 | + pad_char = ' '; | |
1506 | + break; | |
1507 | + | |
1508 | + | |
1509 | + case '%': | |
1510 | + char_buf[0] = '%'; | |
1511 | + s = &char_buf[0]; | |
1512 | + s_len = 1; | |
1513 | + pad_char = ' '; | |
1514 | + break; | |
1515 | + | |
1516 | + | |
1517 | + case 'n': | |
1518 | + if (var_type == IS_QUAD) | |
1519 | + *(va_arg(ap, widest_int *)) = cc; | |
1520 | + else if (var_type == IS_LONG) | |
1521 | + *(va_arg(ap, long *)) = cc; | |
1522 | + else if (var_type == IS_SHORT) | |
1523 | + *(va_arg(ap, short *)) = cc; | |
1524 | + else | |
1525 | + *(va_arg(ap, int *)) = cc; | |
1526 | + break; | |
1527 | + | |
1528 | + /* | |
1529 | + * This is where we extend the printf format, with a second | |
1530 | + * type specifier | |
1531 | + */ | |
1532 | + case 'p': | |
1533 | + switch(*++fmt) { | |
1534 | + /* | |
1535 | + * If the pointer size is equal to or smaller than the size | |
1536 | + * of the largest unsigned int, we convert the pointer to a | |
1537 | + * hex number, otherwise we print "%p" to indicate that we | |
1538 | + * don't handle "%p". | |
1539 | + */ | |
1540 | + case 'p': | |
1541 | +#ifdef AP_VOID_P_IS_QUAD | |
1542 | + if (sizeof(void *) <= sizeof(u_widest_int)) { | |
1543 | + ui_quad = (u_widest_int) va_arg(ap, void *); | |
1544 | + s = conv_p2_quad(ui_quad, 4, 'x', | |
1545 | + &num_buf[NUM_BUF_SIZE], &s_len); | |
1546 | + } | |
1547 | +#else | |
1548 | + if (sizeof(void *) <= sizeof(u_wide_int)) { | |
1549 | + ui_num = (u_wide_int) va_arg(ap, void *); | |
1550 | + s = conv_p2(ui_num, 4, 'x', | |
1551 | + &num_buf[NUM_BUF_SIZE], &s_len); | |
1552 | + } | |
1553 | +#endif | |
1554 | + else { | |
1555 | + s = "%p"; | |
1556 | + s_len = 2; | |
1557 | + prefix_char = NUL; | |
1558 | + } | |
1559 | + pad_char = ' '; | |
1560 | + break; | |
1561 | + | |
1562 | + /* print a struct sockaddr_in as a.b.c.d:port */ | |
1563 | + case 'I': | |
1564 | + { | |
1565 | +#ifndef INET6 | |
1566 | + struct sockaddr_in *si; | |
1567 | + | |
1568 | + si = va_arg(ap, struct sockaddr_in *); | |
1569 | + if (si != NULL) { | |
1570 | + s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len); | |
1571 | + if (adjust_precision && precision < s_len) | |
1572 | + s_len = precision; | |
1573 | + } | |
1574 | +#else | |
1575 | + struct sockaddr *sa; | |
1576 | + | |
1577 | + sa = va_arg(ap, struct sockaddr *); | |
1578 | + if (sa != NULL) { | |
1579 | + s = conv_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len); | |
1580 | + if (adjust_precision && precision < s_len) | |
1581 | + s_len = precision; | |
1582 | + } | |
1583 | +#endif | |
1584 | + else { | |
1585 | + s = S_NULL; | |
1586 | + s_len = S_NULL_LEN; | |
1587 | + } | |
1588 | + pad_char = ' '; | |
1589 | + } | |
1590 | + break; | |
1591 | + | |
1592 | + /* print a struct in_addr as a.b.c.d */ | |
1593 | + case 'A': | |
1594 | + { | |
1595 | + struct in_addr *ia; | |
1596 | + | |
1597 | + ia = va_arg(ap, struct in_addr *); | |
1598 | + if (ia != NULL) { | |
1599 | + s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len); | |
1600 | + if (adjust_precision && precision < s_len) | |
1601 | + s_len = precision; | |
1602 | + } | |
1603 | + else { | |
1604 | + s = S_NULL; | |
1605 | + s_len = S_NULL_LEN; | |
1606 | + } | |
1607 | + pad_char = ' '; | |
1608 | + } | |
1609 | + break; | |
1610 | + | |
1611 | + case NUL: | |
1612 | + /* if %p ends the string, oh well ignore it */ | |
1613 | + continue; | |
1614 | + | |
1615 | + default: | |
1616 | + s = "bogus %p"; | |
1617 | + s_len = 8; | |
1618 | + prefix_char = NUL; | |
1619 | + break; | |
1620 | + } | |
1621 | + break; | |
1622 | + | |
1623 | + case NUL: | |
1624 | + /* | |
1625 | + * The last character of the format string was %. | |
1626 | + * We ignore it. | |
1627 | + */ | |
1628 | + continue; | |
1629 | + | |
1630 | + | |
1631 | + /* | |
1632 | + * The default case is for unrecognized %'s. | |
1633 | + * We print %<char> to help the user identify what | |
1634 | + * option is not understood. | |
1635 | + * This is also useful in case the user wants to pass | |
1636 | + * the output of format_converter to another function | |
1637 | + * that understands some other %<char> (like syslog). | |
1638 | + * Note that we can't point s inside fmt because the | |
1639 | + * unknown <char> could be preceded by width etc. | |
1640 | + */ | |
1641 | + default: | |
1642 | + char_buf[0] = '%'; | |
1643 | + char_buf[1] = *fmt; | |
1644 | + s = char_buf; | |
1645 | + s_len = 2; | |
1646 | + pad_char = ' '; | |
1647 | + break; | |
1648 | + } | |
1649 | + | |
1650 | + if (prefix_char != NUL && s != S_NULL && s != char_buf) { | |
1651 | + *--s = prefix_char; | |
1652 | + s_len++; | |
1653 | + } | |
1654 | + | |
1655 | + if (adjust_width && adjust == RIGHT && min_width > s_len) { | |
1656 | + if (pad_char == '0' && prefix_char != NUL) { | |
1657 | + INS_CHAR(*s, sp, bep, cc); | |
1658 | + s++; | |
1659 | + s_len--; | |
1660 | + min_width--; | |
1661 | + } | |
1662 | + PAD(min_width, s_len, pad_char); | |
1663 | + } | |
1664 | + | |
1665 | + /* | |
1666 | + * Print the string s. | |
1667 | + */ | |
1668 | + for (i = s_len; i != 0; i--) { | |
1669 | + INS_CHAR(*s, sp, bep, cc); | |
1670 | + s++; | |
1671 | + } | |
1672 | + | |
1673 | + if (adjust_width && adjust == LEFT && min_width > s_len) | |
1674 | + PAD(min_width, s_len, pad_char); | |
1675 | + } | |
1676 | + fmt++; | |
1677 | + } | |
1678 | + vbuff->curpos = sp; | |
1679 | + return cc; | |
1680 | +} | |
1681 | + | |
1682 | + | |
1683 | +static int snprintf_flush(ap_vformatter_buff *vbuff) | |
1684 | +{ | |
1685 | + /* if the buffer fills we have to abort immediately, there is no way | |
1686 | + * to "flush" an ap_snprintf... there's nowhere to flush it to. | |
1687 | + */ | |
1688 | + return -1; | |
1689 | +} | |
1690 | + | |
1691 | + | |
1692 | +API_EXPORT(int) ap_snprintf(char *buf, size_t len, const char *format,...) | |
1693 | +{ | |
1694 | + int cc; | |
1695 | + va_list ap; | |
1696 | + ap_vformatter_buff vbuff; | |
1697 | + | |
1698 | + if (len == 0) | |
1699 | + return 0; | |
1700 | + | |
1701 | + /* save one byte for nul terminator */ | |
1702 | + vbuff.curpos = buf; | |
1703 | + vbuff.endpos = buf + len - 1; | |
1704 | + va_start(ap, format); | |
1705 | + cc = ap_vformatter(snprintf_flush, &vbuff, format, ap); | |
1706 | + va_end(ap); | |
1707 | + *vbuff.curpos = '\0'; | |
1708 | + return (cc == -1) ? len : cc; | |
1709 | +} | |
1710 | + | |
1711 | + | |
1712 | +API_EXPORT(int) ap_vsnprintf(char *buf, size_t len, const char *format, | |
1713 | + va_list ap) | |
1714 | +{ | |
1715 | + int cc; | |
1716 | + ap_vformatter_buff vbuff; | |
1717 | + | |
1718 | + if (len == 0) | |
1719 | + return 0; | |
1720 | + | |
1721 | + /* save one byte for nul terminator */ | |
1722 | + vbuff.curpos = buf; | |
1723 | + vbuff.endpos = buf + len - 1; | |
1724 | + cc = ap_vformatter(snprintf_flush, &vbuff, format, ap); | |
1725 | + *vbuff.curpos = '\0'; | |
1726 | + return (cc == -1) ? len : cc; | |
1727 | +} | |
1728 | diff -Nru apache_1.3.20/src/include/ap.h apache_1.3.20.new/src/include/ap.h | |
1729 | --- apache_1.3.20/src/include/ap.h Mon Jan 15 18:04:22 2001 | |
1730 | +++ apache_1.3.20.new/src/include/ap.h Mon May 21 10:54:52 2001 | |
1731 | @@ -91,7 +91,8 @@ | |
1732 | * with some extensions. The extensions are: | |
1733 | * | |
1734 | * %pA takes a struct in_addr *, and prints it as a.b.c.d | |
1735 | - * %pI takes a struct sockaddr_in * and prints it as a.b.c.d:port | |
1736 | + * %pI takes a struct sockaddr * and prints it as a.b.c.d:port, or | |
1737 | + * ipv6-numeric-addr:port | |
1738 | * %pp takes a void * and outputs it in hex | |
1739 | * | |
1740 | * The %p hacks are to force gcc's printf warning code to skip | |
1741 | diff -Nru apache_1.3.20/src/include/ap_config.h apache_1.3.20.new/src/include/ap_config.h | |
1742 | --- apache_1.3.20/src/include/ap_config.h Fri Apr 6 05:13:11 2001 | |
1743 | +++ apache_1.3.20.new/src/include/ap_config.h Mon May 21 10:54:52 2001 | |
1744 | @@ -395,6 +395,10 @@ | |
1745 | #endif | |
1746 | #ifndef S_IWOTH | |
1747 | #define S_IWOTH 000002 | |
1748 | +#ifndef rlim_t | |
1749 | +typedef int rlim_t; | |
1750 | +#endif | |
1751 | +typedef u_long n_long; | |
1752 | #endif | |
1753 | ||
1754 | #define STDIN_FILENO 0 | |
1755 | @@ -1413,6 +1417,70 @@ | |
1756 | ||
1757 | #ifndef ap_wait_t | |
1758 | #define ap_wait_t int | |
1759 | +#endif | |
1760 | + | |
1761 | +#ifndef INET6 | |
1762 | +#define sockaddr_storage sockaddr | |
1763 | +#define ss_family sa_family | |
1764 | +#define ss_len sa_len | |
1765 | +#else | |
1766 | +#include "sockaddr_storage.h" /* sshida@st.rim.or.jp */ | |
1767 | +#endif | |
1768 | + | |
1769 | +#ifndef INET6_ADDRSTRLEN | |
1770 | +#define INET6_ADDRSTRLEN 46 | |
1771 | +#endif | |
1772 | +#ifndef INET_ADDRSTRLEN | |
1773 | +#define INET_ADDRSTRLEN 16 | |
1774 | +#endif | |
1775 | +#ifndef NI_MAXHOST | |
1776 | +#define NI_MAXHOST 1025 | |
1777 | +#endif | |
1778 | +#ifndef NI_MAXSERV | |
1779 | +#define NI_MAXSERV 32 | |
1780 | +#endif | |
1781 | + | |
1782 | +#if defined(NEED_GETADDRINFO) || defined(NEED_GETNAMEINFO) | |
1783 | +/* | |
1784 | + * minimal definitions for fake getaddrinfo()/getnameinfo(). | |
1785 | + */ | |
1786 | +#ifndef EAI_NODATA | |
1787 | +#define EAI_NODATA 1 | |
1788 | +#define EAI_MEMORY 2 | |
1789 | +#endif | |
1790 | + | |
1791 | +#ifndef AI_PASSIVE | |
1792 | +#define AI_PASSIVE 1 | |
1793 | +#define AI_CANONNAME 2 | |
1794 | +#define AI_NUMERICHOST 4 | |
1795 | +#define NI_NUMERICHOST 8 | |
1796 | +#define NI_NAMEREQD 16 | |
1797 | +#define NI_NUMERICSERV 32 | |
1798 | +#endif | |
1799 | +#endif | |
1800 | + | |
1801 | +#ifdef NEED_GETADDRINFO | |
1802 | +#ifdef NEED_ADDRINFO | |
1803 | +struct addrinfo { | |
1804 | + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ | |
1805 | + int ai_family; /* PF_xxx */ | |
1806 | + int ai_socktype; /* SOCK_xxx */ | |
1807 | + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ | |
1808 | + size_t ai_addrlen; /* length of ai_addr */ | |
1809 | + char *ai_canonname; /* canonical name for hostname */ | |
1810 | + struct sockaddr *ai_addr; /* binary address */ | |
1811 | + struct addrinfo *ai_next; /* next structure in linked list */ | |
1812 | +}; | |
1813 | +#endif | |
1814 | +extern char *gai_strerror(int ecode); | |
1815 | +extern void freeaddrinfo(struct addrinfo *ai); | |
1816 | +extern int getaddrinfo(const char *hostname, const char *servname, | |
1817 | + const struct addrinfo *hints, struct addrinfo **res); | |
1818 | +#endif | |
1819 | +#ifdef NEED_GETNAMEINFO | |
1820 | +extern int getnameinfo(const struct sockaddr *sa, size_t salen, | |
1821 | + char *host, size_t hostlen, char *serv, size_t servlen, | |
1822 | + int flag); | |
1823 | #endif | |
1824 | ||
1825 | #ifdef __cplusplus | |
1826 | diff -Nru apache_1.3.20/src/include/http_conf_globals.h apache_1.3.20.new/src/include/http_conf_globals.h | |
1827 | --- apache_1.3.20/src/include/http_conf_globals.h Mon May 21 11:02:03 2001 | |
1828 | +++ apache_1.3.20.new/src/include/http_conf_globals.h Mon May 21 10:54:52 2001 | |
1829 | @@ -82,7 +82,8 @@ | |
1830 | extern API_VAR_EXPORT int ap_max_requests_per_child; | |
1831 | extern API_VAR_EXPORT int ap_threads_per_child; | |
1832 | extern API_VAR_EXPORT int ap_excess_requests_per_child; | |
1833 | -extern struct in_addr ap_bind_address; | |
1834 | +extern struct sockaddr_storage ap_bind_address; | |
1835 | +extern API_VAR_EXPORT int ap_default_family; | |
1836 | extern listen_rec *ap_listeners; | |
1837 | extern API_VAR_EXPORT int ap_daemons_to_start; | |
1838 | extern API_VAR_EXPORT int ap_daemons_min_free; | |
1839 | diff -Nru apache_1.3.20/src/include/http_vhost.h apache_1.3.20.new/src/include/http_vhost.h | |
1840 | --- apache_1.3.20/src/include/http_vhost.h Mon Jan 15 18:04:37 2001 | |
1841 | +++ apache_1.3.20.new/src/include/http_vhost.h Mon May 21 10:54:52 2001 | |
1842 | @@ -73,7 +73,7 @@ | |
1843 | const char *ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s); | |
1844 | ||
1845 | /* handle NameVirtualHost directive */ | |
1846 | -const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg); | |
1847 | +const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *h, char *p); | |
1848 | ||
1849 | /* given an ip address only, give our best guess as to what vhost it is */ | |
1850 | void ap_update_vhost_given_ip(conn_rec *conn); | |
1851 | diff -Nru apache_1.3.20/src/include/httpd.h apache_1.3.20.new/src/include/httpd.h | |
1852 | --- apache_1.3.20/src/include/httpd.h Mon May 21 11:02:04 2001 | |
1853 | +++ apache_1.3.20.new/src/include/httpd.h Mon May 21 10:54:52 2001 | |
1854 | @@ -908,8 +908,8 @@ | |
1855 | ||
1856 | /* Who is the client? */ | |
1857 | ||
1858 | - struct sockaddr_in local_addr; /* local address */ | |
1859 | - struct sockaddr_in remote_addr; /* remote address */ | |
1860 | + struct sockaddr_storage local_addr; /* local address */ | |
1861 | + struct sockaddr_storage remote_addr; /* remote address */ | |
1862 | char *remote_ip; /* Client's IP address */ | |
1863 | char *remote_host; /* Client's DNS name, if known. | |
1864 | * NULL if DNS hasn't been checked, | |
1865 | @@ -951,8 +951,8 @@ | |
1866 | typedef struct server_addr_rec server_addr_rec; | |
1867 | struct server_addr_rec { | |
1868 | server_addr_rec *next; | |
1869 | - struct in_addr host_addr; /* The bound address, for this server */ | |
1870 | - unsigned short host_port; /* The bound port, for this server */ | |
1871 | + struct sockaddr_storage host_addr; /* The bound address, for this server */ | |
1872 | + unsigned short host_port; /* The bound port, for this server XXX */ | |
1873 | char *virthost; /* The name given in <VirtualHost> */ | |
1874 | }; | |
1875 | ||
1876 | @@ -1020,7 +1020,7 @@ | |
1877 | /* These are more like real hosts than virtual hosts */ | |
1878 | struct listen_rec { | |
1879 | listen_rec *next; | |
1880 | - struct sockaddr_in local_addr; /* local IP address and port */ | |
1881 | + struct sockaddr_storage local_addr; /* local IP address and port */ | |
1882 | int fd; | |
1883 | int used; /* Only used during restart */ | |
1884 | /* more stuff here, like which protocol is bound to the port */ | |
1885 | @@ -1180,7 +1180,7 @@ | |
1886 | #endif /*#ifdef CHARSET_EBCDIC*/ | |
1887 | ||
1888 | char *ap_get_local_host(pool *); | |
1889 | -unsigned long ap_get_virthost_addr(char *hostname, unsigned short *port); | |
1890 | +struct sockaddr *ap_get_virthost_addr(char *hostname, unsigned short *port); | |
1891 | ||
1892 | extern API_VAR_EXPORT time_t ap_restart_time; | |
1893 | ||
1894 | diff -Nru apache_1.3.20/src/include/sa_len.h apache_1.3.20.new/src/include/sa_len.h | |
1895 | --- apache_1.3.20/src/include/sa_len.h Thu Jan 1 01:00:00 1970 | |
1896 | +++ apache_1.3.20.new/src/include/sa_len.h Mon May 21 10:54:52 2001 | |
1897 | @@ -0,0 +1,41 @@ | |
1898 | +/* sa_len.h : tiny version of SA_LEN (written by <yoshfuji@ecei.tohoku.ac.jp>) */ | |
1899 | + | |
1900 | +#include <sys/types.h> | |
1901 | +#include <sys/socket.h> | |
1902 | +#include <netinet/in.h> | |
1903 | +#include <sys/un.h> | |
1904 | + | |
1905 | +#ifndef HAVE_SOCKADDR_LEN | |
1906 | +#ifndef SA_LEN | |
1907 | +#define SA_LEN(s_) ap_sa_len((s_)->sa_family) | |
1908 | + | |
1909 | +static NET_SIZE_T ap_sa_len (sa_family_t af) | |
1910 | +{ | |
1911 | + switch (af){ | |
1912 | +#if defined(AF_INET) | |
1913 | + case AF_INET: | |
1914 | + return (sizeof(struct sockaddr_in)); | |
1915 | +#endif /* AF_INET */ | |
1916 | +#if defined(AF_INET6) | |
1917 | + case AF_INET6: | |
1918 | + return (sizeof(struct sockaddr_in6)); | |
1919 | +#endif | |
1920 | +#ifdef AF_LOCAL | |
1921 | + case AF_LOCAL: | |
1922 | +#endif /* AF_LOCAL */ | |
1923 | +#if defined(AF_UNIX) && (AF_UNIX != AF_LOCAL) | |
1924 | + case AF_UNIX: | |
1925 | +#endif /* AF_UNIX */ | |
1926 | +#if defined(AF_FILE) && (AF_FILE != AF_LOCAL || AF_FILE != AF_UNIX) | |
1927 | + case AF_FILE: | |
1928 | +#endif /* AF_FILE */ | |
1929 | +#if defined(AF_LOCAL) || defined(AF_UNIX) || defined(AF_FILE) | |
1930 | + return (sizeof(struct sockaddr_un)); | |
1931 | +#endif /* defined(AF_LOCAL) || defined(AF_UNIX) || defined(AF_FILE) */ | |
1932 | + default: | |
1933 | + return 0; | |
1934 | + } | |
1935 | + return 0; | |
1936 | +} | |
1937 | +#endif /* SA_LEN */ | |
1938 | +#endif /* HAVE_SOCKADDR_LEN */ | |
1939 | diff -Nru apache_1.3.20/src/include/sockaddr_storage.h apache_1.3.20.new/src/include/sockaddr_storage.h | |
1940 | --- apache_1.3.20/src/include/sockaddr_storage.h Thu Jan 1 01:00:00 1970 | |
1941 | +++ apache_1.3.20.new/src/include/sockaddr_storage.h Mon May 21 10:54:52 2001 | |
1942 | @@ -0,0 +1,53 @@ | |
1943 | +/* | |
1944 | +struct sockaddr_storage | |
1945 | + | |
1946 | + RFC2553 proposes struct sockaddr_storage. | |
1947 | + This is a placeholder for all sockaddr-variant structures. This is | |
1948 | + implemented like follows: | |
1949 | + | |
1950 | + You should use this structure to hold any of sockaddr-variant | |
1951 | + structures. | |
1952 | +*/ | |
1953 | +#ifdef NEED_SOCKADDR_STORAGE | |
1954 | + | |
1955 | +struct sockaddr_storage { | |
1956 | +#ifdef HAVE_SOCKADDR_LEN | |
1957 | + u_char ss_len; | |
1958 | + u_char ss_family; | |
1959 | +#else | |
1960 | + u_short ss_family; | |
1961 | +#endif | |
1962 | + u_char __padding[128 - 2]; | |
1963 | +}; | |
1964 | + | |
1965 | +/* | |
1966 | +union sockunion | |
1967 | + | |
1968 | + Alternatively, you may want to implement sockunion.h, with the | |
1969 | + following content: | |
1970 | + | |
1971 | + NOTE: For better portability, struct sockaddr_storage should be used. | |
1972 | + union sockunion is okay, but is not really portable enough. | |
1973 | +*/ | |
1974 | +union sockunion { | |
1975 | + struct sockinet { | |
1976 | +#ifdef HAVE_SOCKADDR_LEN | |
1977 | + u_char si_len; | |
1978 | + u_char si_family; | |
1979 | +#else | |
1980 | + u_short si_family; | |
1981 | +#endif | |
1982 | + u_short si_port; | |
1983 | + } su_si; | |
1984 | + struct sockaddr_in su_sin; | |
1985 | +#ifdef INET6 | |
1986 | + struct sockaddr_in6 su_sin6; | |
1987 | +#endif | |
1988 | +}; | |
1989 | +#ifdef HAVE_SOCKADDR_LEN | |
1990 | +#define su_len su_si.si_len | |
1991 | +#endif | |
1992 | +#define su_family su_si.si_family | |
1993 | +#define su_port su_si.si_port | |
1994 | + | |
1995 | +#endif /* NEED_SOCKADDR_STORAGE */ | |
1996 | diff -Nru apache_1.3.20/src/main/getaddrinfo.c apache_1.3.20.new/src/main/getaddrinfo.c | |
1997 | --- apache_1.3.20/src/main/getaddrinfo.c Thu Jan 1 01:00:00 1970 | |
1998 | +++ apache_1.3.20.new/src/main/getaddrinfo.c Mon May 21 10:54:52 2001 | |
1999 | @@ -0,0 +1,162 @@ | |
2000 | +/* | |
2001 | + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. | |
2002 | + * All rights reserved. | |
2003 | + * | |
2004 | + * Redistribution and use in source and binary forms, with or without | |
2005 | + * modification, are permitted provided that the following conditions | |
2006 | + * are met: | |
2007 | + * 1. Redistributions of source code must retain the above copyright | |
2008 | + * notice, this list of conditions and the following disclaimer. | |
2009 | + * 2. Redistributions in binary form must reproduce the above copyright | |
2010 | + * notice, this list of conditions and the following disclaimer in the | |
2011 | + * documentation and/or other materials provided with the distribution. | |
2012 | + * 3. Neither the name of the project nor the names of its contributors | |
2013 | + * may be used to endorse or promote products derived from this software | |
2014 | + * without specific prior written permission. | |
2015 | + * | |
2016 | + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
2017 | + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
2018 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
2019 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
2020 | + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
2021 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
2022 | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
2023 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
2024 | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
2025 | + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
2026 | + * SUCH DAMAGE. | |
2027 | + */ | |
2028 | +/* | |
2029 | + * fake library for ssh v6 enabler patch | |
2030 | + * | |
2031 | + * This file includes getaddrinfo(), freeaddrinfo() and gai_strerror(). | |
2032 | + * These funtions are defined in rfc2133. | |
2033 | + * | |
2034 | + * But these functions are not implemented correctly. The minimum subset | |
2035 | + * is implemented for ssh use only. For exapmle, this routine assumes | |
2036 | + * that ai_family is AF_INET. Don't use it for another purpose. | |
2037 | + * | |
2038 | + * In the case not using 'configure --enable-ipv6', this getaddrinfo.c | |
2039 | + * will be used if you have broken getaddrinfo or no getaddrinfo. | |
2040 | + */ | |
2041 | + | |
2042 | +#if 0 | |
2043 | +#include <stdlib.h> | |
2044 | +#include <sys/types.h> | |
2045 | +#include <sys/socket.h> | |
2046 | +#include <netinet/in.h> | |
2047 | +#include <arpa/inet.h> | |
2048 | +#include <netdb.h> | |
2049 | +#include "gai.h" | |
2050 | +#endif | |
2051 | + | |
2052 | +static struct addrinfo * | |
2053 | +malloc_ai(port, addr, socktype, protocol) | |
2054 | +int port; | |
2055 | +u_long addr; | |
2056 | +int socktype; | |
2057 | +int protocol; | |
2058 | +{ | |
2059 | + struct addrinfo *ai; | |
2060 | + | |
2061 | + if (ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + | |
2062 | + sizeof(struct sockaddr_in))) { | |
2063 | + memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); | |
2064 | + ai->ai_addr = (struct sockaddr *)(ai + 1); | |
2065 | +#if defined(HAVE_SOCKADDR_LEN) | |
2066 | + ai->ai_addr->sa_len = | |
2067 | +#endif | |
2068 | + ai->ai_addrlen = sizeof(struct sockaddr_in); | |
2069 | + ai->ai_addr->sa_family = ai->ai_family = AF_INET; | |
2070 | + ai->ai_socktype = socktype; | |
2071 | + ai->ai_protocol = protocol; | |
2072 | + ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port; | |
2073 | + ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr; | |
2074 | + return ai; | |
2075 | + } else { | |
2076 | + return NULL; | |
2077 | + } | |
2078 | +} | |
2079 | + | |
2080 | +char * | |
2081 | +gai_strerror(ecode) | |
2082 | +int ecode; | |
2083 | +{ | |
2084 | + switch (ecode) { | |
2085 | + case EAI_NODATA: | |
2086 | + return "no address associated with hostname."; | |
2087 | + case EAI_MEMORY: | |
2088 | + return "memory allocation failure."; | |
2089 | + default: | |
2090 | + return "unknown error."; | |
2091 | + } | |
2092 | +} | |
2093 | + | |
2094 | +void | |
2095 | +freeaddrinfo(ai) | |
2096 | +struct addrinfo *ai; | |
2097 | +{ | |
2098 | + struct addrinfo *next; | |
2099 | + | |
2100 | + do { | |
2101 | + next = ai->ai_next; | |
2102 | + free(ai); | |
2103 | + } while (ai = next); | |
2104 | +} | |
2105 | + | |
2106 | +int | |
2107 | +getaddrinfo(hostname, servname, hints, res) | |
2108 | +const char *hostname, *servname; | |
2109 | +const struct addrinfo *hints; | |
2110 | +struct addrinfo **res; | |
2111 | +{ | |
2112 | + struct addrinfo *cur, *prev = NULL; | |
2113 | + struct hostent *hp; | |
2114 | + int i, port; | |
2115 | + | |
2116 | + if (servname) | |
2117 | + port = htons(atoi(servname)); | |
2118 | + else | |
2119 | + port = 0; | |
2120 | + if (hints && hints->ai_flags & AI_PASSIVE) | |
2121 | + if (*res = malloc_ai(port, htonl(0x00000000), | |
2122 | + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM, | |
2123 | + (*res)->ai_protocol)) | |
2124 | + return 0; | |
2125 | + else | |
2126 | + return EAI_MEMORY; | |
2127 | + if (!hostname) | |
2128 | + if (*res = malloc_ai(port, htonl(0x7f000001), | |
2129 | + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM, | |
2130 | + (*res)->ai_protocol)) | |
2131 | + return 0; | |
2132 | + else | |
2133 | + return EAI_MEMORY; | |
2134 | + if (inet_addr(hostname) != -1) | |
2135 | + if (*res = malloc_ai(port, inet_addr(hostname), | |
2136 | + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM, | |
2137 | + (*res)->ai_protocol)) | |
2138 | + return 0; | |
2139 | + else | |
2140 | + return EAI_MEMORY; | |
2141 | + if ((hp = gethostbyname(hostname)) && | |
2142 | + hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) { | |
2143 | + for (i = 0; hp->h_addr_list[i]; i++) | |
2144 | + if (cur = malloc_ai(port, | |
2145 | + ((struct in_addr *)hp->h_addr_list[i])->s_addr, | |
2146 | + (*res)->ai_socktype ? (*res)->ai_socktype : SOCK_STREAM, | |
2147 | + (*res)->ai_protocol)) { | |
2148 | + if (prev) | |
2149 | + prev->ai_next = cur; | |
2150 | + else | |
2151 | + *res = cur; | |
2152 | + prev = cur; | |
2153 | + } else { | |
2154 | + if (*res) | |
2155 | + freeaddrinfo(*res); | |
2156 | + return EAI_MEMORY; | |
2157 | + } | |
2158 | + return 0; | |
2159 | + } | |
2160 | + return EAI_NODATA; | |
2161 | +} | |
2162 | diff -Nru apache_1.3.20/src/main/getnameinfo.c apache_1.3.20.new/src/main/getnameinfo.c | |
2163 | --- apache_1.3.20/src/main/getnameinfo.c Thu Jan 1 01:00:00 1970 | |
2164 | +++ apache_1.3.20.new/src/main/getnameinfo.c Mon May 21 10:54:52 2001 | |
2165 | @@ -0,0 +1,95 @@ | |
2166 | +/* | |
2167 | + * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. | |
2168 | + * All rights reserved. | |
2169 | + * | |
2170 | + * Redistribution and use in source and binary forms, with or without | |
2171 | + * modification, are permitted provided that the following conditions | |
2172 | + * are met: | |
2173 | + * 1. Redistributions of source code must retain the above copyright | |
2174 | + * notice, this list of conditions and the following disclaimer. | |
2175 | + * 2. Redistributions in binary form must reproduce the above copyright | |
2176 | + * notice, this list of conditions and the following disclaimer in the | |
2177 | + * documentation and/or other materials provided with the distribution. | |
2178 | + * 3. Neither the name of the project nor the names of its contributors | |
2179 | + * may be used to endorse or promote products derived from this software | |
2180 | + * without specific prior written permission. | |
2181 | + * | |
2182 | + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | |
2183 | + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
2184 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
2185 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | |
2186 | + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
2187 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
2188 | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
2189 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
2190 | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
2191 | + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
2192 | + * SUCH DAMAGE. | |
2193 | + */ | |
2194 | +/* | |
2195 | + * fake library for ssh v6 enabler patch | |
2196 | + * | |
2197 | + * This file includes getnameinfo(). | |
2198 | + * These funtions are defined in rfc2133. | |
2199 | + * | |
2200 | + * But these functions are not implemented correctly. The minimum subset | |
2201 | + * is implemented for ssh use only. For exapmle, this routine assumes | |
2202 | + * that ai_family is AF_INET. Don't use it for another purpose. | |
2203 | + * | |
2204 | + * In the case not using 'configure --enable-ipv6', this getnameinfo.c | |
2205 | + * will be used if you have broken getnameinfo or no getnameinfo. | |
2206 | + */ | |
2207 | + | |
2208 | +#if 0 | |
2209 | +#include <stdlib.h> | |
2210 | +#include <sys/types.h> | |
2211 | +#include <sys/socket.h> | |
2212 | +#include <netinet/in.h> | |
2213 | +#include <arpa/inet.h> | |
2214 | +#include <netdb.h> | |
2215 | +#include <string.h> | |
2216 | +#include "gai.h" | |
2217 | +#endif | |
2218 | + | |
2219 | +int | |
2220 | +getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) | |
2221 | +const struct sockaddr *sa; | |
2222 | +size_t salen; | |
2223 | +char *host; | |
2224 | +size_t hostlen; | |
2225 | +char *serv; | |
2226 | +size_t servlen; | |
2227 | +int flags; | |
2228 | +{ | |
2229 | + struct sockaddr_in *sin = (struct sockaddr_in *)sa; | |
2230 | + struct hostent *hp; | |
2231 | + char tmpserv[16]; | |
2232 | + | |
2233 | + if (serv) { | |
2234 | + sprintf(tmpserv, "%d", ntohs(sin->sin_port)); | |
2235 | + if (strlen(tmpserv) > servlen) | |
2236 | + return EAI_MEMORY; | |
2237 | + else | |
2238 | + strcpy(serv, tmpserv); | |
2239 | + } | |
2240 | + if (host) | |
2241 | + if (flags & NI_NUMERICHOST) | |
2242 | + if (strlen(inet_ntoa(sin->sin_addr)) > hostlen) | |
2243 | + return EAI_MEMORY; | |
2244 | + else { | |
2245 | + strcpy(host, inet_ntoa(sin->sin_addr)); | |
2246 | + return 0; | |
2247 | + } | |
2248 | + else | |
2249 | + if (hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), | |
2250 | + AF_INET)) | |
2251 | + if (strlen(hp->h_name) > hostlen) | |
2252 | + return EAI_MEMORY; | |
2253 | + else { | |
2254 | + strcpy(host, hp->h_name); | |
2255 | + return 0; | |
2256 | + } | |
2257 | + else | |
2258 | + return EAI_NODATA; | |
2259 | + return 0; | |
2260 | +} | |
2261 | diff -Nru apache_1.3.20/src/main/http_config.c apache_1.3.20.new/src/main/http_config.c | |
2262 | --- apache_1.3.20/src/main/http_config.c Mon May 21 11:02:04 2001 | |
2263 | +++ apache_1.3.20.new/src/main/http_config.c Mon May 21 10:54:52 2001 | |
2264 | @@ -1564,7 +1564,6 @@ | |
2265 | ap_scoreboard_fname = DEFAULT_SCOREBOARD; | |
2266 | ap_lock_fname = DEFAULT_LOCKFILE; | |
2267 | ap_max_requests_per_child = DEFAULT_MAX_REQUESTS_PER_CHILD; | |
2268 | - ap_bind_address.s_addr = htonl(INADDR_ANY); | |
2269 | ap_listeners = NULL; | |
2270 | ap_listenbacklog = DEFAULT_LISTENBACKLOG; | |
2271 | ap_extended_status = 0; | |
2272 | @@ -1597,7 +1596,13 @@ | |
2273 | s->next = NULL; | |
2274 | s->addrs = ap_pcalloc(p, sizeof(server_addr_rec)); | |
2275 | /* NOT virtual host; don't match any real network interface */ | |
2276 | - s->addrs->host_addr.s_addr = htonl(INADDR_ANY); | |
2277 | + memset(&s->addrs->host_addr, 0, sizeof(s->addrs->host_addr)); | |
2278 | +#if 0 | |
2279 | + s->addrs->host_addr.ss_family = ap_default_family; /* XXX: needed?, XXX: PF_xxx can be different from AF_xxx */ | |
2280 | +#endif | |
2281 | +#ifdef HAVE_SOCKADDR_LEN | |
2282 | + s->addrs->host_addr.ss_len = sizeof(s->addrs->host_addr); /* XXX: needed ? */ | |
2283 | +#endif | |
2284 | s->addrs->host_port = 0; /* matches any port */ | |
2285 | s->addrs->virthost = ""; /* must be non-NULL */ | |
2286 | s->names = s->wild_names = NULL; | |
2287 | @@ -1616,19 +1621,33 @@ | |
2288 | static void default_listeners(pool *p, server_rec *s) | |
2289 | { | |
2290 | listen_rec *new; | |
2291 | + struct addrinfo hints, *res0, *res; | |
2292 | + int gai; | |
2293 | + char servbuf[NI_MAXSERV]; | |
2294 | ||
2295 | if (ap_listeners != NULL) { | |
2296 | return; | |
2297 | } | |
2298 | + ap_snprintf(servbuf, sizeof(servbuf), "%d", s->port ? s->port : DEFAULT_HTTP_PORT); | |
2299 | + memset (&hints, 0, sizeof(hints)); | |
2300 | + hints.ai_family = ap_default_family; | |
2301 | + hints.ai_socktype = SOCK_STREAM; | |
2302 | + hints.ai_flags = AI_PASSIVE; | |
2303 | + gai = getaddrinfo(NULL, servbuf, &hints, &res0); | |
2304 | + if (gai){ | |
2305 | + fprintf(stderr, "default_listeners(): getaddrinfo(PASSIVE) for family %u: %s\n", | |
2306 | + gai_strerror(gai), ap_default_family); | |
2307 | + exit (1); | |
2308 | + } | |
2309 | /* allocate a default listener */ | |
2310 | new = ap_pcalloc(p, sizeof(listen_rec)); | |
2311 | - new->local_addr.sin_family = AF_INET; | |
2312 | - new->local_addr.sin_addr = ap_bind_address; | |
2313 | - new->local_addr.sin_port = htons(s->port ? s->port : DEFAULT_HTTP_PORT); | |
2314 | + memcpy(&new->local_addr, res0->ai_addr, res0->ai_addrlen); | |
2315 | new->fd = -1; | |
2316 | new->used = 0; | |
2317 | new->next = NULL; | |
2318 | ap_listeners = new; | |
2319 | + | |
2320 | + freeaddrinfo(res0); | |
2321 | } | |
2322 | ||
2323 | ||
2324 | diff -Nru apache_1.3.20/src/main/http_core.c apache_1.3.20.new/src/main/http_core.c | |
2325 | --- apache_1.3.20/src/main/http_core.c Fri Mar 9 11:10:25 2001 | |
2326 | +++ apache_1.3.20.new/src/main/http_core.c Mon May 21 10:54:52 2001 | |
2327 | @@ -71,6 +71,7 @@ | |
2328 | #include "util_md5.h" | |
2329 | #include "scoreboard.h" | |
2330 | #include "fnmatch.h" | |
2331 | +#include "sa_len.h" | |
2332 | ||
2333 | #ifdef USE_MMAP_FILES | |
2334 | #include <sys/mman.h> | |
2335 | @@ -594,7 +595,9 @@ | |
2336 | /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */ | |
2337 | static ap_inline void do_double_reverse (conn_rec *conn) | |
2338 | { | |
2339 | - struct hostent *hptr; | |
2340 | + struct addrinfo hints, *res, *res0; | |
2341 | + char hostbuf1[128], hostbuf2[128]; /* INET6_ADDRSTRLEN(=46) is enough */ | |
2342 | + int ok = 0; | |
2343 | ||
2344 | if (conn->double_reverse) { | |
2345 | /* already done */ | |
2346 | @@ -605,28 +608,51 @@ | |
2347 | conn->double_reverse = -1; | |
2348 | return; | |
2349 | } | |
2350 | - hptr = gethostbyname(conn->remote_host); | |
2351 | - if (hptr) { | |
2352 | - char **haddr; | |
2353 | - | |
2354 | - for (haddr = hptr->h_addr_list; *haddr; haddr++) { | |
2355 | - if (((struct in_addr *)(*haddr))->s_addr | |
2356 | - == conn->remote_addr.sin_addr.s_addr) { | |
2357 | - conn->double_reverse = 1; | |
2358 | - return; | |
2359 | - } | |
2360 | + memset(&hints, 0, sizeof(hints)); | |
2361 | + hints.ai_family = PF_UNSPEC; | |
2362 | + hints.ai_socktype = SOCK_STREAM; | |
2363 | + if (getaddrinfo(conn->remote_host, NULL, &hints, &res0)) { | |
2364 | + conn->double_reverse = -1; | |
2365 | + return; | |
2366 | + } | |
2367 | + for (res = res0; res; res = res->ai_next) { | |
2368 | + if (res->ai_addr->sa_family != conn->remote_addr.ss_family || | |
2369 | + !(res->ai_family == AF_INET | |
2370 | +#ifdef INET6 | |
2371 | + || res->ai_family == AF_INET6 | |
2372 | +#endif | |
2373 | + ) | |
2374 | + ) | |
2375 | + continue; | |
2376 | +#ifndef HAVE_SOCKADDR_LEN | |
2377 | + if (res->ai_addrlen != SA_LEN((struct sockaddr *)&conn->remote_addr)) | |
2378 | +#else | |
2379 | + if (res->ai_addr->sa_len != conn->remote_addr.ss_len) | |
2380 | +#endif | |
2381 | + continue; | |
2382 | + if (getnameinfo(res->ai_addr, res->ai_addrlen, | |
2383 | + hostbuf1, sizeof(hostbuf1), NULL, 0, | |
2384 | + NI_NUMERICHOST)) | |
2385 | + continue; | |
2386 | + if (getnameinfo(((struct sockaddr *)&conn->remote_addr), res->ai_addrlen, | |
2387 | + hostbuf2, sizeof(hostbuf2), NULL, 0, | |
2388 | + NI_NUMERICHOST)) | |
2389 | + continue; | |
2390 | + if (strcmp(hostbuf1, hostbuf2) == 0){ | |
2391 | + ok = 1; | |
2392 | + break; | |
2393 | } | |
2394 | } | |
2395 | - conn->double_reverse = -1; | |
2396 | + conn->double_reverse = ok ? 1 : -1; | |
2397 | + freeaddrinfo(res0); | |
2398 | } | |
2399 | ||
2400 | API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config, | |
2401 | int type) | |
2402 | { | |
2403 | - struct in_addr *iaddr; | |
2404 | - struct hostent *hptr; | |
2405 | int hostname_lookups; | |
2406 | int old_stat = SERVER_DEAD; /* we shouldn't ever be in this state */ | |
2407 | + char hostnamebuf[MAXHOSTNAMELEN]; | |
2408 | ||
2409 | /* If we haven't checked the host name, and we want to */ | |
2410 | if (dir_config) { | |
2411 | @@ -648,10 +674,14 @@ | |
2412 | || hostname_lookups != HOSTNAME_LOOKUP_OFF)) { | |
2413 | old_stat = ap_update_child_status(conn->child_num, SERVER_BUSY_DNS, | |
2414 | (request_rec*)NULL); | |
2415 | - iaddr = &(conn->remote_addr.sin_addr); | |
2416 | - hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET); | |
2417 | - if (hptr != NULL) { | |
2418 | - conn->remote_host = ap_pstrdup(conn->pool, (void *)hptr->h_name); | |
2419 | + if (!getnameinfo((struct sockaddr *)&conn->remote_addr, | |
2420 | +#ifndef SIN6_LEN | |
2421 | + SA_LEN((struct sockaddr *)&conn->remote_addr), | |
2422 | +#else | |
2423 | + conn->remote_addr.ss_len, | |
2424 | +#endif | |
2425 | + hostnamebuf, sizeof(hostnamebuf), NULL, 0, 0)) { | |
2426 | + conn->remote_host = ap_pstrdup(conn->pool, (void *)hostnamebuf); | |
2427 | ap_str_tolower(conn->remote_host); | |
2428 | ||
2429 | if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) { | |
2430 | @@ -732,6 +762,7 @@ | |
2431 | { | |
2432 | conn_rec *conn = r->connection; | |
2433 | core_dir_config *d; | |
2434 | + char hbuf[MAXHOSTNAMELEN]; | |
2435 | ||
2436 | d = (core_dir_config *)ap_get_module_config(r->per_dir_config, | |
2437 | &core_module); | |
2438 | @@ -741,23 +772,22 @@ | |
2439 | } | |
2440 | if (d->use_canonical_name == USE_CANONICAL_NAME_DNS) { | |
2441 | if (conn->local_host == NULL) { | |
2442 | - struct in_addr *iaddr; | |
2443 | - struct hostent *hptr; | |
2444 | int old_stat; | |
2445 | old_stat = ap_update_child_status(conn->child_num, | |
2446 | SERVER_BUSY_DNS, r); | |
2447 | - iaddr = &(conn->local_addr.sin_addr); | |
2448 | - hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), | |
2449 | - AF_INET); | |
2450 | - if (hptr != NULL) { | |
2451 | - conn->local_host = ap_pstrdup(conn->pool, | |
2452 | - (void *)hptr->h_name); | |
2453 | - ap_str_tolower(conn->local_host); | |
2454 | - } | |
2455 | - else { | |
2456 | - conn->local_host = ap_pstrdup(conn->pool, | |
2457 | - r->server->server_hostname); | |
2458 | + if (getnameinfo((struct sockaddr *)&conn->local_addr, | |
2459 | +#ifndef SIN6_LEN | |
2460 | + SA_LEN((struct sockaddr *)&conn->local_addr), | |
2461 | +#else | |
2462 | + conn->local_addr.ss_len, | |
2463 | +#endif | |
2464 | + hbuf, sizeof(hbuf), NULL, 0, 0) == 0) { | |
2465 | + conn->local_host = ap_pstrdup(conn->pool, hbuf); | |
2466 | + } else { | |
2467 | + conn->local_host = ap_pstrdup(conn->pool, | |
2468 | + r->server->server_hostname); | |
2469 | } | |
2470 | + ap_str_tolower(conn->local_host); | |
2471 | (void) ap_update_child_status(conn->child_num, old_stat, r); | |
2472 | } | |
2473 | return conn->local_host; | |
2474 | @@ -776,11 +806,13 @@ | |
2475 | ||
2476 | if (d->use_canonical_name == USE_CANONICAL_NAME_OFF | |
2477 | || d->use_canonical_name == USE_CANONICAL_NAME_DNS) { | |
2478 | - return r->hostname ? ntohs(r->connection->local_addr.sin_port) | |
2479 | - : port; | |
2480 | - } | |
2481 | - /* default */ | |
2482 | - return port; | |
2483 | + return r->hostname | |
2484 | + ? ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port) | |
2485 | + : port; | |
2486 | + } | |
2487 | + return r->hostname | |
2488 | + ? ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port) | |
2489 | + : port; | |
2490 | } | |
2491 | ||
2492 | API_EXPORT(char *) ap_construct_url(pool *p, const char *uri, | |
2493 | @@ -2499,12 +2531,25 @@ | |
2494 | ||
2495 | static const char *set_bind_address(cmd_parms *cmd, void *dummy, char *arg) | |
2496 | { | |
2497 | + struct addrinfo hints, *res; | |
2498 | + struct sockaddr *sa; | |
2499 | + size_t sa_len; | |
2500 | + int error; | |
2501 | const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); | |
2502 | if (err != NULL) { | |
2503 | return err; | |
2504 | } | |
2505 | ||
2506 | - ap_bind_address.s_addr = ap_get_virthost_addr(arg, NULL); | |
2507 | + if (strcmp(arg, "*") == 0) | |
2508 | + arg = NULL; | |
2509 | + | |
2510 | + sa = ap_get_virthost_addr(arg, NULL); | |
2511 | +#ifdef HAVE_SOCKADDR_LEN | |
2512 | + sa_len = sa->sa_len; | |
2513 | +#else | |
2514 | + sa_len = SA_LEN(sa); | |
2515 | +#endif | |
2516 | + memcpy(&ap_bind_address, &sa, sa_len); | |
2517 | return NULL; | |
2518 | } | |
2519 | ||
2520 | @@ -2521,44 +2566,70 @@ | |
2521 | } | |
2522 | #endif | |
2523 | ||
2524 | -static const char *set_listener(cmd_parms *cmd, void *dummy, char *ips) | |
2525 | +static const char *set_listener(cmd_parms *cmd, void *dummy, char *h, char *p) | |
2526 | { | |
2527 | listen_rec *new; | |
2528 | - char *ports; | |
2529 | - unsigned short port; | |
2530 | + char *host, *port; | |
2531 | + struct addrinfo hints, *res; | |
2532 | + int error; | |
2533 | ||
2534 | const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); | |
2535 | if (err != NULL) { | |
2536 | return err; | |
2537 | } | |
2538 | ||
2539 | - ports = strchr(ips, ':'); | |
2540 | - if (ports != NULL) { | |
2541 | - if (ports == ips) { | |
2542 | - return "Missing IP address"; | |
2543 | - } | |
2544 | - else if (ports[1] == '\0') { | |
2545 | - return "Address must end in :<port-number>"; | |
2546 | + host = port = NULL; | |
2547 | + if (!p) { | |
2548 | + port = strrchr(h, ':'); | |
2549 | + if (port != NULL) { | |
2550 | + if (port == h) { | |
2551 | + return "Missing IP address"; | |
2552 | + } | |
2553 | + else if (port[1] == '\0') { | |
2554 | + return "Address must end in :<port-number>"; | |
2555 | + } | |
2556 | + *(port++) = '\0'; | |
2557 | + if (*h) | |
2558 | + host = h; | |
2559 | + } else { | |
2560 | + host = NULL; | |
2561 | + port = h; | |
2562 | } | |
2563 | - *(ports++) = '\0'; | |
2564 | - } | |
2565 | - else { | |
2566 | - ports = ips; | |
2567 | + } else { | |
2568 | + host = h; | |
2569 | + port = p; | |
2570 | } | |
2571 | ||
2572 | - new=ap_pcalloc(cmd->pool, sizeof(listen_rec)); | |
2573 | - new->local_addr.sin_family = AF_INET; | |
2574 | - if (ports == ips) { /* no address */ | |
2575 | - new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
2576 | - } | |
2577 | - else { | |
2578 | - new->local_addr.sin_addr.s_addr = ap_get_virthost_addr(ips, NULL); | |
2579 | - } | |
2580 | - port = atoi(ports); | |
2581 | - if (!port) { | |
2582 | - return "Port must be numeric"; | |
2583 | + if (host && strcmp(host, "*") == 0) | |
2584 | + host = NULL; | |
2585 | + | |
2586 | + new = ap_pcalloc(cmd->pool, sizeof(listen_rec)); | |
2587 | + | |
2588 | + memset(&hints, 0, sizeof(hints)); | |
2589 | + hints.ai_family = host ? PF_UNSPEC : ap_default_family; | |
2590 | + hints.ai_flags = AI_PASSIVE; | |
2591 | + hints.ai_socktype = SOCK_STREAM; | |
2592 | + error = getaddrinfo(host, port, &hints, &res); | |
2593 | + if (error || !res) { | |
2594 | + fprintf(stderr, "could not resolve "); | |
2595 | + if (host) | |
2596 | + fprintf(stderr, "host \"%s\" ", host); | |
2597 | + if (port) | |
2598 | + fprintf(stderr, "port \"%s\" ", port); | |
2599 | + fprintf(stderr, "--- %s\n", gai_strerror(error)); | |
2600 | + exit(1); | |
2601 | + } | |
2602 | + if (res->ai_next) { | |
2603 | + if (host) | |
2604 | + fprintf(stderr, "host \"%s\" ", host); | |
2605 | + if (port) | |
2606 | + fprintf(stderr, "port \"%s\" ", port); | |
2607 | + fprintf(stderr, "resolved to multiple addresses, ambiguous.\n"); | |
2608 | + exit(1); | |
2609 | } | |
2610 | - new->local_addr.sin_port = htons(port); | |
2611 | + | |
2612 | + memcpy(&new->local_addr, res->ai_addr, res->ai_addrlen); | |
2613 | + | |
2614 | new->fd = -1; | |
2615 | new->used = 0; | |
2616 | new->next = ap_listeners; | |
2617 | @@ -3144,7 +3215,7 @@ | |
2618 | { "ThreadStackSize", set_threadstacksize, NULL, RSRC_CONF, TAKE1, | |
2619 | "Stack size each created thread will use."}, | |
2620 | #endif | |
2621 | -{ "Listen", set_listener, NULL, RSRC_CONF, TAKE1, | |
2622 | +{ "Listen", set_listener, NULL, RSRC_CONF, TAKE12, | |
2623 | "A port number or a numeric IP address and a port number"}, | |
2624 | { "SendBufferSize", set_send_buffer_size, NULL, RSRC_CONF, TAKE1, | |
2625 | "Send buffer size in bytes"}, | |
2626 | @@ -3165,7 +3236,7 @@ | |
2627 | "Name of the config file to be included" }, | |
2628 | { "LogLevel", set_loglevel, NULL, RSRC_CONF, TAKE1, | |
2629 | "Level of verbosity in error logging" }, | |
2630 | -{ "NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, TAKE1, | |
2631 | +{ "NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, TAKE12, | |
2632 | "A numeric IP address:port, or the name of a host" }, | |
2633 | #ifdef _OSD_POSIX | |
2634 | { "BS2000Account", set_bs2000_account, NULL, RSRC_CONF, TAKE1, | |
2635 | diff -Nru apache_1.3.20/src/main/http_main.c apache_1.3.20.new/src/main/http_main.c | |
2636 | --- apache_1.3.20/src/main/http_main.c Mon May 21 11:02:04 2001 | |
2637 | +++ apache_1.3.20.new/src/main/http_main.c Mon May 21 11:06:01 2001 | |
2638 | @@ -124,6 +124,8 @@ | |
2639 | #include <bstring.h> /* for IRIX, FD_SET calls bzero() */ | |
2640 | #endif | |
2641 | ||
2642 | +#include "sa_len.h" | |
2643 | + | |
2644 | #ifdef MULTITHREAD | |
2645 | /* special debug stuff -- PCS */ | |
2646 | ||
2647 | @@ -250,7 +252,12 @@ | |
2648 | API_VAR_EXPORT char *ap_scoreboard_fname=NULL; | |
2649 | char *ap_lock_fname; | |
2650 | API_VAR_EXPORT char *ap_server_argv0=NULL; | |
2651 | -struct in_addr ap_bind_address; | |
2652 | +#ifdef INET6 | |
2653 | +API_VAR_EXPORT int ap_default_family = PF_INET6; | |
2654 | +#else | |
2655 | +API_VAR_EXPORT int ap_default_family = PF_INET; | |
2656 | +#endif | |
2657 | +struct sockaddr_storage ap_bind_address; | |
2658 | API_VAR_EXPORT int ap_daemons_to_start=0; | |
2659 | API_VAR_EXPORT int ap_daemons_min_free=0; | |
2660 | API_VAR_EXPORT int ap_daemons_max_free=0; | |
2661 | @@ -1086,7 +1093,11 @@ | |
2662 | fprintf(stderr, "Usage: %s [-D name] [-d directory] [-f file]\n", bin); | |
2663 | #endif | |
2664 | fprintf(stderr, " %s [-C \"directive\"] [-c \"directive\"]\n", pad); | |
2665 | - fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T]\n", pad); | |
2666 | + fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t] [-T]" | |
2667 | +#ifdef INET6 | |
2668 | + " [-46]" | |
2669 | +#endif | |
2670 | + "\n", pad); | |
2671 | fprintf(stderr, "Options:\n"); | |
2672 | #ifdef SHARED_CORE | |
2673 | fprintf(stderr, " -R directory : specify an alternate location for shared object files\n"); | |
2674 | @@ -1108,6 +1119,10 @@ | |
2675 | #endif | |
2676 | fprintf(stderr, " -t : run syntax check for config files (with docroot check)\n"); | |
2677 | fprintf(stderr, " -T : run syntax check for config files (without docroot check)\n"); | |
2678 | +#ifdef INET6 | |
2679 | + fprintf(stderr, " -4 : assume IPv4 on parsing configuration file\n"); | |
2680 | + fprintf(stderr, " -6 : assume IPv6 on parsing configuration file\n"); | |
2681 | +#endif | |
2682 | #ifdef WIN32 | |
2683 | fprintf(stderr, " -n name : name the Apache service for -k options below;\n"); | |
2684 | fprintf(stderr, " -k stop|shutdown : tell running Apache to shutdown\n"); | |
2685 | @@ -3252,11 +3267,13 @@ | |
2686 | ||
2687 | ||
2688 | static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout, | |
2689 | - const struct sockaddr_in *remaddr, | |
2690 | - const struct sockaddr_in *saddr, | |
2691 | + const struct sockaddr *remaddr, | |
2692 | + const struct sockaddr *saddr, | |
2693 | int child_num) | |
2694 | { | |
2695 | conn_rec *conn = (conn_rec *) ap_pcalloc(p, sizeof(conn_rec)); | |
2696 | + char hostnamebuf[MAXHOSTNAMELEN]; | |
2697 | + size_t addr_len; | |
2698 | ||
2699 | /* Got a connection structure, so initialize what fields we can | |
2700 | * (the rest are zeroed out by pcalloc). | |
2701 | @@ -3265,17 +3282,29 @@ | |
2702 | conn->child_num = child_num; | |
2703 | ||
2704 | conn->pool = p; | |
2705 | - conn->local_addr = *saddr; | |
2706 | - conn->local_ip = ap_pstrdup(conn->pool, | |
2707 | - inet_ntoa(conn->local_addr.sin_addr)); | |
2708 | +#ifndef SIN6_LEN | |
2709 | + addr_len = SA_LEN(saddr); | |
2710 | +#else | |
2711 | + addr_len = saddr->sa_len; | |
2712 | +#endif | |
2713 | + memcpy(&conn->local_addr, saddr, addr_len); | |
2714 | + getnameinfo((struct sockaddr *)&conn->local_addr, addr_len, | |
2715 | + hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST); | |
2716 | + conn->local_ip = ap_pstrdup(conn->pool, hostnamebuf); | |
2717 | conn->server = server; /* just a guess for now */ | |
2718 | ap_update_vhost_given_ip(conn); | |
2719 | conn->base_server = conn->server; | |
2720 | conn->client = inout; | |
2721 | ||
2722 | - conn->remote_addr = *remaddr; | |
2723 | - conn->remote_ip = ap_pstrdup(conn->pool, | |
2724 | - inet_ntoa(conn->remote_addr.sin_addr)); | |
2725 | +#ifndef SIN6_LEN | |
2726 | + addr_len = SA_LEN(remaddr); | |
2727 | +#else | |
2728 | + addr_len = remaddr->sa_len; | |
2729 | +#endif | |
2730 | + memcpy(&conn->remote_addr, remaddr, addr_len); | |
2731 | + getnameinfo((struct sockaddr *)&conn->remote_addr, addr_len, | |
2732 | + hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST); | |
2733 | + conn->remote_ip = ap_pstrdup(conn->pool, hostnamebuf); | |
2734 | #ifdef EAPI | |
2735 | conn->ctx = ap_ctx_new(conn->pool); | |
2736 | #endif /* EAPI */ | |
2737 | @@ -3326,21 +3355,47 @@ | |
2738 | #define sock_disable_nagle(s) /* NOOP */ | |
2739 | #endif | |
2740 | ||
2741 | -static int make_sock(pool *p, const struct sockaddr_in *server) | |
2742 | +static int make_sock(pool *p, const struct sockaddr *server) | |
2743 | { | |
2744 | int s; | |
2745 | int one = 1; | |
2746 | - char addr[512]; | |
2747 | + char addr[INET6_ADDRSTRLEN + 128]; | |
2748 | + char a0[INET6_ADDRSTRLEN]; | |
2749 | + char p0[NI_MAXSERV]; | |
2750 | +#ifdef MPE | |
2751 | + int privport = 0; | |
2752 | +#endif | |
2753 | ||
2754 | - if (server->sin_addr.s_addr != htonl(INADDR_ANY)) | |
2755 | - ap_snprintf(addr, sizeof(addr), "address %s port %d", | |
2756 | - inet_ntoa(server->sin_addr), ntohs(server->sin_port)); | |
2757 | - else | |
2758 | - ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port)); | |
2759 | + switch(server->sa_family){ | |
2760 | + case AF_INET: | |
2761 | +#ifdef INET6 | |
2762 | + case AF_INET6: | |
2763 | +#endif | |
2764 | + break; | |
2765 | + default: | |
2766 | + ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, | |
2767 | + "make_sock: unsupported address family %u", | |
2768 | + server->sa_family); | |
2769 | + ap_unblock_alarms(); | |
2770 | + exit(1); | |
2771 | + } | |
2772 | + | |
2773 | + getnameinfo(server, | |
2774 | +#ifndef SIN6_LEN | |
2775 | + SA_LEN(server), | |
2776 | +#else | |
2777 | + server->sa_len, | |
2778 | +#endif | |
2779 | + a0, sizeof(a0), p0, sizeof(p0), NI_NUMERICHOST | NI_NUMERICSERV); | |
2780 | + ap_snprintf(addr, sizeof(addr), "address %s port %s", a0, p0); | |
2781 | +#ifdef MPE | |
2782 | + if (atoi(p0) < 1024) | |
2783 | + privport++; | |
2784 | +#endif | |
2785 | ||
2786 | /* note that because we're about to slack we don't use psocket */ | |
2787 | ap_block_alarms(); | |
2788 | - if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { | |
2789 | + if ((s = socket(server->sa_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { | |
2790 | ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, | |
2791 | "make_sock: failed to get a socket for %s", addr); | |
2792 | ||
2793 | @@ -3443,15 +3498,19 @@ | |
2794 | ||
2795 | #ifdef MPE | |
2796 | /* MPE requires CAP=PM and GETPRIVMODE to bind to ports less than 1024 */ | |
2797 | - if (ntohs(server->sin_port) < 1024) | |
2798 | + if (privport) | |
2799 | GETPRIVMODE(); | |
2800 | #endif | |
2801 | - | |
2802 | - if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) { | |
2803 | +#ifndef SIN6_LEN | |
2804 | + if (bind(s, server, SA_LEN(server)) == -1) | |
2805 | +#else | |
2806 | + if (bind(s, server, server->sa_len) == -1) | |
2807 | +#endif | |
2808 | + { | |
2809 | ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, | |
2810 | "make_sock: could not bind to %s", addr); | |
2811 | #ifdef MPE | |
2812 | - if (ntohs(server->sin_port) < 1024) | |
2813 | + if (privport) | |
2814 | GETUSERMODE(); | |
2815 | #endif | |
2816 | ||
2817 | @@ -3464,7 +3523,7 @@ | |
2818 | exit(1); | |
2819 | } | |
2820 | #ifdef MPE | |
2821 | - if (ntohs(server->sin_port) < 1024) | |
2822 | + if (privport) | |
2823 | GETUSERMODE(); | |
2824 | #endif | |
2825 | ||
2826 | @@ -3611,15 +3670,17 @@ | |
2827 | for (;;) { | |
2828 | fd = find_listener(lr); | |
2829 | if (fd < 0) { | |
2830 | - fd = make_sock(p, &lr->local_addr); | |
2831 | + fd = make_sock(p, (struct sockaddr *)&lr->local_addr); | |
2832 | } | |
2833 | else { | |
2834 | ap_note_cleanups_for_socket(p, fd); | |
2835 | } | |
2836 | /* if we get here, (fd >= 0) && (fd < FD_SETSIZE) */ | |
2837 | - FD_SET(fd, &listenfds); | |
2838 | - if (fd > listenmaxfd) | |
2839 | - listenmaxfd = fd; | |
2840 | + if (fd > 0) { | |
2841 | + FD_SET(fd, &listenfds); | |
2842 | + if (fd > listenmaxfd) | |
2843 | + listenmaxfd = fd; | |
2844 | + } | |
2845 | lr->fd = fd; | |
2846 | if (lr->next == NULL) | |
2847 | break; | |
2848 | @@ -3918,8 +3979,8 @@ | |
2849 | static void child_main(int child_num_arg) | |
2850 | { | |
2851 | NET_SIZE_T clen; | |
2852 | - struct sockaddr sa_server; | |
2853 | - struct sockaddr sa_client; | |
2854 | + struct sockaddr_storage sa_server; | |
2855 | + struct sockaddr_storage sa_client; | |
2856 | listen_rec *lr; | |
2857 | ||
2858 | /* All of initialization is a critical section, we don't care if we're | |
2859 | @@ -4084,7 +4145,7 @@ | |
2860 | usr1_just_die = 0; | |
2861 | for (;;) { | |
2862 | clen = sizeof(sa_client); | |
2863 | - csd = ap_accept(sd, &sa_client, &clen); | |
2864 | + csd = ap_accept(sd, (struct sockaddr *)&sa_client, &clen); | |
2865 | if (csd >= 0 || errno != EINTR) | |
2866 | break; | |
2867 | if (deferred_die) { | |
2868 | @@ -4234,7 +4295,7 @@ | |
2869 | */ | |
2870 | ||
2871 | clen = sizeof(sa_server); | |
2872 | - if (getsockname(csd, &sa_server, &clen) < 0) { | |
2873 | + if (getsockname(csd, (struct sockaddr *)&sa_server, &clen) < 0) { | |
2874 | ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "getsockname"); | |
2875 | continue; | |
2876 | } | |
2877 | @@ -4279,8 +4340,8 @@ | |
2878 | ap_bpushfd(conn_io, csd, dupped_csd); | |
2879 | ||
2880 | current_conn = new_connection(ptrans, server_conf, conn_io, | |
2881 | - (struct sockaddr_in *) &sa_client, | |
2882 | - (struct sockaddr_in *) &sa_server, | |
2883 | + (struct sockaddr *)&sa_client, | |
2884 | + (struct sockaddr *)&sa_server, | |
2885 | my_child_num); | |
2886 | ||
2887 | /* | |
2888 | @@ -4424,12 +4485,13 @@ | |
2889 | ||
2890 | #ifdef _OSD_POSIX | |
2891 | /* BS2000 requires a "special" version of fork() before a setuid() call */ | |
2892 | - if ((pid = os_fork(ap_user_name)) == -1) { | |
2893 | + if ((pid = os_fork(ap_user_name)) == -1) | |
2894 | #elif defined(TPF) | |
2895 | - if ((pid = os_fork(s, slot)) == -1) { | |
2896 | + if ((pid = os_fork(s, slot)) == -1) | |
2897 | #else | |
2898 | - if ((pid = fork()) == -1) { | |
2899 | + if ((pid = fork()) == -1) | |
2900 | #endif | |
2901 | + { | |
2902 | ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process"); | |
2903 | ||
2904 | /* fork didn't succeed. Fix the scoreboard or else | |
2905 | @@ -5003,7 +5065,10 @@ | |
2906 | ap_setup_prelinked_modules(); | |
2907 | ||
2908 | while ((c = getopt(argc, argv, | |
2909 | - "D:C:c:xXd:f:vVlLR:StTh" | |
2910 | + "D:C:c:xXd:f:vVlLR:StTh4" | |
2911 | +#ifdef INET6 | |
2912 | + "6" | |
2913 | +#endif | |
2914 | #ifdef DEBUG_SIGSTOP | |
2915 | "Z:" | |
2916 | #endif | |
2917 | @@ -5078,8 +5143,14 @@ | |
2918 | ap_configtestonly = 1; | |
2919 | ap_docrootcheck = 0; | |
2920 | break; | |
2921 | - case 'h': | |
2922 | - usage(argv[0]); | |
2923 | + case '4': | |
2924 | + ap_default_family = PF_INET; | |
2925 | + break; | |
2926 | +#ifdef INET6 | |
2927 | + case '6': | |
2928 | + ap_default_family = PF_INET6; | |
2929 | + break; | |
2930 | +#endif | |
2931 | case '?': | |
2932 | usage(argv[0]); | |
2933 | } | |
2934 | @@ -5158,9 +5229,10 @@ | |
2935 | else { | |
2936 | conn_rec *conn; | |
2937 | request_rec *r; | |
2938 | - struct sockaddr sa_server, sa_client; | |
2939 | BUFF *cio; | |
2940 | + struct sockaddr_storage sa_server, sa_client; | |
2941 | NET_SIZE_T l; | |
2942 | + char servbuf[NI_MAXSERV]; | |
2943 | ||
2944 | ap_set_version(); | |
2945 | /* Yes this is called twice. */ | |
2946 | @@ -5207,25 +5279,32 @@ | |
2947 | #endif | |
2948 | ||
2949 | l = sizeof(sa_client); | |
2950 | - if ((getpeername(sock_in, &sa_client, &l)) < 0) { | |
2951 | + if ((getpeername(sock_in, (struct sockaddr *)&sa_client, &l)) < 0) { | |
2952 | /* get peername will fail if the input isn't a socket */ | |
2953 | perror("getpeername"); | |
2954 | memset(&sa_client, '\0', sizeof(sa_client)); | |
2955 | } | |
2956 | ||
2957 | l = sizeof(sa_server); | |
2958 | - if (getsockname(sock_in, &sa_server, &l) < 0) { | |
2959 | + if (getsockname(sock_in, (struct sockaddr *)&sa_server, &l) < 0) { | |
2960 | perror("getsockname"); | |
2961 | fprintf(stderr, "Error getting local address\n"); | |
2962 | exit(1); | |
2963 | } | |
2964 | - server_conf->port = ntohs(((struct sockaddr_in *) &sa_server)->sin_port); | |
2965 | + if (getnameinfo(((struct sockaddr *)&sa_server), l, | |
2966 | + NULL, 0, servbuf, sizeof(servbuf), | |
2967 | + NI_NUMERICSERV)){ | |
2968 | + fprintf(stderr, "getnameinfo(): family=%d\n", sa_server.ss_family); | |
2969 | + exit(1); | |
2970 | + } | |
2971 | + servbuf[sizeof(servbuf)-1] = '\0'; | |
2972 | + server_conf->port = atoi(servbuf); | |
2973 | cio = ap_bcreate(ptrans, B_RDWR | B_SOCKET); | |
2974 | cio->fd = sock_out; | |
2975 | cio->fd_in = sock_in; | |
2976 | conn = new_connection(ptrans, server_conf, cio, | |
2977 | - (struct sockaddr_in *) &sa_client, | |
2978 | - (struct sockaddr_in *) &sa_server, -1); | |
2979 | + (struct sockaddr *)&sa_client, | |
2980 | + (struct sockaddr *)&sa_server, -1); | |
2981 | ||
2982 | while ((r = ap_read_request(conn)) != NULL) { | |
2983 | ||
2984 | @@ -7383,7 +7462,11 @@ | |
2985 | * but only handle the -L option | |
2986 | */ | |
2987 | llp_dir = SHARED_CORE_DIR; | |
2988 | - while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLR:SZ:tTh")) != -1) { | |
2989 | + while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLR:SZ:tTh4" | |
2990 | +#ifdef INET6 | |
2991 | + "6" | |
2992 | +#endif | |
2993 | + )) != -1) { | |
2994 | switch (c) { | |
2995 | case 'D': | |
2996 | case 'C': | |
2997 | @@ -7400,6 +7483,10 @@ | |
2998 | case 't': | |
2999 | case 'T': | |
3000 | case 'h': | |
3001 | + case '4': | |
3002 | +#ifdef INET6 | |
3003 | + case '6': | |
3004 | +#endif | |
3005 | case '?': | |
3006 | break; | |
3007 | case 'R': | |
3008 | diff -Nru apache_1.3.20/src/main/http_vhost.c apache_1.3.20.new/src/main/http_vhost.c | |
3009 | --- apache_1.3.20/src/main/http_vhost.c Sat Feb 24 11:09:46 2001 | |
3010 | +++ apache_1.3.20.new/src/main/http_vhost.c Mon May 21 10:54:52 2001 | |
3011 | @@ -68,6 +68,7 @@ | |
3012 | #include "http_log.h" | |
3013 | #include "http_vhost.h" | |
3014 | #include "http_protocol.h" | |
3015 | +#include "sa_len.h" | |
3016 | ||
3017 | /* | |
3018 | * After all the definitions there's an explanation of how it's all put | |
3019 | @@ -165,78 +166,114 @@ | |
3020 | * *paddr is the variable used to keep track of **paddr between calls | |
3021 | * port is the default port to assume | |
3022 | */ | |
3023 | -static const char *get_addresses(pool *p, char *w, server_addr_rec ***paddr, | |
3024 | - unsigned port) | |
3025 | +static const char *get_addresses(pool *p, char *w, char *pstr, | |
3026 | + server_addr_rec ***paddr, unsigned port) | |
3027 | { | |
3028 | - struct hostent *hep; | |
3029 | - unsigned long my_addr; | |
3030 | + struct addrinfo hints, *res, *res0; | |
3031 | server_addr_rec *sar; | |
3032 | - char *t; | |
3033 | - int i, is_an_ip_addr; | |
3034 | + char *t = NULL, *u = NULL, *v = NULL; | |
3035 | + char *hoststr = NULL, *portstr = NULL; | |
3036 | + char portpool[10]; | |
3037 | + int error; | |
3038 | + char servbuf[NI_MAXSERV]; | |
3039 | ||
3040 | - if (*w == 0) | |
3041 | + if (w == 0 || *w == 0) | |
3042 | return NULL; | |
3043 | ||
3044 | - t = strchr(w, ':'); | |
3045 | - if (t) { | |
3046 | - if (strcmp(t + 1, "*") == 0) { | |
3047 | - port = 0; | |
3048 | + portstr = portpool; | |
3049 | + ap_snprintf(portpool, sizeof(portpool), "%u", port); | |
3050 | + if (!pstr) { | |
3051 | + v = w; | |
3052 | + u = NULL; | |
3053 | + if (*w == '['){ | |
3054 | + u = strrchr(w, ']'); | |
3055 | + if (u) { /* [host]:port or [host] */ | |
3056 | + w++; | |
3057 | + *u = '\0'; | |
3058 | + v = u + 1; | |
3059 | + } | |
3060 | } | |
3061 | - else if ((i = atoi(t + 1))) { | |
3062 | - port = i; | |
3063 | + /* w uv , w=v , w=v */ | |
3064 | + /* u!=0: [host]:port , u==0: [host:port , host */ | |
3065 | + t = strchr(v, ':'); | |
3066 | + if (t != NULL && strchr(t+1, ':') == NULL) { | |
3067 | + /* [host]:port-w/o-colons, host-without-colons:port-w/o-colons */ | |
3068 | + *t = '\0'; | |
3069 | + portstr = t + 1; | |
3070 | } | |
3071 | else { | |
3072 | - return ":port must be numeric"; | |
3073 | + portstr = "0"; | |
3074 | } | |
3075 | - *t = 0; | |
3076 | + } else { | |
3077 | + portstr = pstr; | |
3078 | } | |
3079 | ||
3080 | - is_an_ip_addr = 0; | |
3081 | - if (strcmp(w, "*") == 0) { | |
3082 | - my_addr = htonl(INADDR_ANY); | |
3083 | - is_an_ip_addr = 1; | |
3084 | - } | |
3085 | - else if (strcasecmp(w, "_default_") == 0 | |
3086 | - || strcmp(w, "255.255.255.255") == 0) { | |
3087 | - my_addr = DEFAULT_VHOST_ADDR; | |
3088 | - is_an_ip_addr = 1; | |
3089 | - } | |
3090 | - else if ((my_addr = ap_inet_addr(w)) != INADDR_NONE) { | |
3091 | - is_an_ip_addr = 1; | |
3092 | + memset(&hints, 0, sizeof(hints)); | |
3093 | + hints.ai_socktype = SOCK_STREAM; | |
3094 | + if (strcmp(w, "*") == 0 || strlen(w) == 0) { | |
3095 | + hoststr = NULL; | |
3096 | + hints.ai_family = PF_UNSPEC; | |
3097 | + hints.ai_flags = AI_PASSIVE; | |
3098 | + } | |
3099 | + else if (strcasecmp(w, "_default4_") == 0 || | |
3100 | + ((ap_default_family == PF_INET | |
3101 | +#ifndef INET6 | |
3102 | + || ap_default_family == PF_UNSPEC | |
3103 | +#endif | |
3104 | + ) && strcasecmp(w, "_default_") == 0)){ | |
3105 | + hoststr = "255.255.255.255"; | |
3106 | + hints.ai_family = PF_INET; | |
3107 | + } | |
3108 | +#ifdef INET6 | |
3109 | + else if (strcasecmp(w, "_default6_") == 0 || | |
3110 | + ((ap_default_family == PF_INET6 | |
3111 | + || ap_default_family == PF_UNSPEC | |
3112 | + ) && strcasecmp(w, "_default_") == 0)){ | |
3113 | + hoststr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; | |
3114 | + hints.ai_family = PF_INET6; | |
3115 | } | |
3116 | - if (is_an_ip_addr) { | |
3117 | - sar = ap_pcalloc(p, sizeof(server_addr_rec)); | |
3118 | - **paddr = sar; | |
3119 | - *paddr = &sar->next; | |
3120 | - sar->host_addr.s_addr = my_addr; | |
3121 | - sar->host_port = port; | |
3122 | - sar->virthost = ap_pstrdup(p, w); | |
3123 | - if (t != NULL) | |
3124 | - *t = ':'; | |
3125 | - return NULL; | |
3126 | +#endif | |
3127 | + else{ | |
3128 | + hoststr = w; | |
3129 | + hints.ai_family = PF_UNSPEC; | |
3130 | } | |
3131 | ||
3132 | - hep = gethostbyname(w); | |
3133 | - | |
3134 | - if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) { | |
3135 | + error = getaddrinfo(hoststr, portstr, &hints, &res0); | |
3136 | + if (error || !res0) { | |
3137 | ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, | |
3138 | - "Cannot resolve host name %s --- ignoring!", w); | |
3139 | - if (t != NULL) | |
3140 | - *t = ':'; | |
3141 | + "Cannot resolve host %s port %s --- ignoring!", hoststr, portstr); | |
3142 | + if (t != NULL) *t = ':'; | |
3143 | + if (u != NULL) *u = ']'; | |
3144 | return NULL; | |
3145 | } | |
3146 | - | |
3147 | - for (i = 0; hep->h_addr_list[i]; ++i) { | |
3148 | + for (res=res0; res; res=res->ai_next) { | |
3149 | + switch (res->ai_addr->sa_family) { | |
3150 | + case AF_INET: | |
3151 | +#ifdef INET6 | |
3152 | + case AF_INET6: | |
3153 | +#endif | |
3154 | + break; | |
3155 | + default: | |
3156 | + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, | |
3157 | + "Unsupported address family %u, for host %s port %s --- ignoring!", | |
3158 | + res->ai_addr->sa_family, hoststr, portstr); | |
3159 | + continue; | |
3160 | + } | |
3161 | sar = ap_pcalloc(p, sizeof(server_addr_rec)); | |
3162 | **paddr = sar; | |
3163 | *paddr = &sar->next; | |
3164 | - sar->host_addr = *(struct in_addr *) hep->h_addr_list[i]; | |
3165 | - sar->host_port = port; | |
3166 | + memcpy(&sar->host_addr, res->ai_addr, res->ai_addrlen); | |
3167 | + if (getnameinfo(res->ai_addr, res->ai_addrlen, NULL, 0, servbuf, | |
3168 | + sizeof(servbuf), NI_NUMERICSERV) == 0) | |
3169 | + sar->host_port = atoi(servbuf); | |
3170 | + else | |
3171 | + sar->host_port = 0; | |
3172 | sar->virthost = ap_pstrdup(p, w); | |
3173 | } | |
3174 | ||
3175 | - if (t != NULL) | |
3176 | - *t = ':'; | |
3177 | + freeaddrinfo(res0); | |
3178 | + if (t != NULL) *t = ':'; | |
3179 | + if (u != NULL) *u = ']'; | |
3180 | return NULL; | |
3181 | } | |
3182 | ||
3183 | @@ -250,7 +287,8 @@ | |
3184 | /* start the list of addreses */ | |
3185 | addrs = &s->addrs; | |
3186 | while (hostname[0]) { | |
3187 | - err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port); | |
3188 | + err = get_addresses(p, ap_getword_conf(p, &hostname), NULL, | |
3189 | + &addrs, s->port); | |
3190 | if (err) { | |
3191 | *addrs = NULL; | |
3192 | return err; | |
3193 | @@ -268,10 +306,11 @@ | |
3194 | } | |
3195 | ||
3196 | ||
3197 | -const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg) | |
3198 | +const char *ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *h, | |
3199 | + char *p) | |
3200 | { | |
3201 | /* use whatever port the main server has at this point */ | |
3202 | - return get_addresses(cmd->pool, arg, &name_vhost_list_tail, | |
3203 | + return get_addresses(cmd->pool, h, p, &name_vhost_list_tail, | |
3204 | cmd->server->port); | |
3205 | } | |
3206 | ||
3207 | @@ -345,6 +384,19 @@ | |
3208 | return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE; | |
3209 | } | |
3210 | ||
3211 | +static unsigned hash_addr(struct sockaddr *sa) | |
3212 | +{ | |
3213 | + switch (sa->sa_family) { | |
3214 | + case AF_INET: | |
3215 | + return hash_inaddr(((struct sockaddr_in *)sa)->sin_addr.s_addr); | |
3216 | +#ifdef INET6 | |
3217 | + case AF_INET6: | |
3218 | + return hash_inaddr(((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12]); | |
3219 | +#endif | |
3220 | + default: | |
3221 | + return hash_inaddr(sa->sa_family); | |
3222 | + } | |
3223 | +} | |
3224 | ||
3225 | ||
3226 | static ipaddr_chain *new_ipaddr_chain(pool *p, | |
3227 | @@ -372,25 +424,77 @@ | |
3228 | return new; | |
3229 | } | |
3230 | ||
3231 | - | |
3232 | -static ap_inline ipaddr_chain *find_ipaddr(struct in_addr *server_ip, | |
3233 | - unsigned port) | |
3234 | +static ap_inline ipaddr_chain *find_ipaddr(struct sockaddr *sa) | |
3235 | { | |
3236 | unsigned bucket; | |
3237 | ipaddr_chain *trav; | |
3238 | - unsigned addr; | |
3239 | + char a[NI_MAXHOST], b[NI_MAXHOST]; | |
3240 | ||
3241 | /* scan the hash table for an exact match first */ | |
3242 | - addr = server_ip->s_addr; | |
3243 | - bucket = hash_inaddr(addr); | |
3244 | + bucket = hash_addr(sa); | |
3245 | for (trav = iphash_table[bucket]; trav; trav = trav->next) { | |
3246 | server_addr_rec *sar = trav->sar; | |
3247 | - if ((sar->host_addr.s_addr == addr) | |
3248 | - && (sar->host_port == 0 || sar->host_port == port | |
3249 | - || port == 0)) { | |
3250 | - return trav; | |
3251 | + if (sar->host_addr.ss_family != sa->sa_family) | |
3252 | + continue; | |
3253 | + switch (sa->sa_family) { | |
3254 | + case AF_INET: | |
3255 | + { | |
3256 | + struct sockaddr_in *sin1, *sin2; | |
3257 | + sin1 = (struct sockaddr_in *)&sar->host_addr; | |
3258 | + sin2 = (struct sockaddr_in *)sa; | |
3259 | + if (sin1->sin_port == 0 || sin2->sin_port == 0 | |
3260 | + || sin1->sin_port == sin2->sin_port) { | |
3261 | + if (memcmp(&sin1->sin_addr, &sin2->sin_addr, | |
3262 | + sizeof(sin1->sin_addr)) == 0) { | |
3263 | + return trav; | |
3264 | + } | |
3265 | + } | |
3266 | + break; | |
3267 | + } | |
3268 | +#ifdef INET6 | |
3269 | + case AF_INET6: | |
3270 | + { | |
3271 | + struct sockaddr_in6 *sin1, *sin2; | |
3272 | + sin1 = (struct sockaddr_in6 *)&sar->host_addr; | |
3273 | + sin2 = (struct sockaddr_in6 *)sa; | |
3274 | + if (sin1->sin6_port == 0 || sin2->sin6_port == 0 | |
3275 | + || sin1->sin6_port == sin2->sin6_port) { | |
3276 | + if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr, | |
3277 | + sizeof(sin1->sin6_addr)) == 0) { | |
3278 | + return trav; | |
3279 | + } | |
3280 | + } | |
3281 | + break; | |
3282 | + } | |
3283 | +#endif | |
3284 | + default: /*unsupported*/ | |
3285 | + break; | |
3286 | } | |
3287 | } | |
3288 | + | |
3289 | +#ifdef INET6 | |
3290 | + if (sa->sa_family == AF_INET6 && | |
3291 | + IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)) { | |
3292 | + /* | |
3293 | + * This is just horrible. I just hate IPv4 mapped address. It | |
3294 | + * complicates access control too much. | |
3295 | + * Due to hashed lookup, we need to visit it again. | |
3296 | + */ | |
3297 | + struct sockaddr_in sin; | |
3298 | + | |
3299 | + memset(&sin, 0, sizeof(sin)); | |
3300 | + sin.sin_family = AF_INET; | |
3301 | +#ifdef SIN6_LEN | |
3302 | + sin.sin_len = sizeof(sin); | |
3303 | +#endif | |
3304 | + sin.sin_port = ((struct sockaddr_in6 *)sa)->sin6_port; | |
3305 | + memcpy(&sin.sin_addr, | |
3306 | + &((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12], | |
3307 | + sizeof(sin.sin_addr)); | |
3308 | + return find_ipaddr((struct sockaddr *)&sin); | |
3309 | + } | |
3310 | +#endif | |
3311 | + | |
3312 | return NULL; | |
3313 | } | |
3314 | ||
3315 | @@ -416,21 +520,7 @@ | |
3316 | int len; | |
3317 | char buf[MAX_STRING_LEN]; | |
3318 | ||
3319 | - if (ic->sar->host_addr.s_addr == DEFAULT_VHOST_ADDR) { | |
3320 | - len = ap_snprintf(buf, sizeof(buf), "_default_:%u", | |
3321 | - ic->sar->host_port); | |
3322 | - } | |
3323 | - else if (ic->sar->host_addr.s_addr == INADDR_ANY) { | |
3324 | - len = ap_snprintf(buf, sizeof(buf), "*:%u", | |
3325 | - ic->sar->host_port); | |
3326 | - } | |
3327 | - else { | |
3328 | - len = ap_snprintf(buf, sizeof(buf), "%pA:%u", | |
3329 | - &ic->sar->host_addr, ic->sar->host_port); | |
3330 | - } | |
3331 | - if (ic->sar->host_port == 0) { | |
3332 | - buf[len-1] = '*'; | |
3333 | - } | |
3334 | + len = ap_snprintf(buf, sizeof(buf), "%pI", &ic->sar->host_addr); | |
3335 | if (ic->names == NULL) { | |
3336 | if (ic->server == NULL) | |
3337 | fprintf(f, "%-22s WARNING: No <VirtualHost> defined for this NameVirtualHost!\n", buf); | |
3338 | @@ -558,10 +648,37 @@ | |
3339 | * occured in the config file, we'll copy it in that order. | |
3340 | */ | |
3341 | for (sar = name_vhost_list; sar; sar = sar->next) { | |
3342 | - unsigned bucket = hash_inaddr(sar->host_addr.s_addr); | |
3343 | + unsigned bucket = hash_addr((struct sockaddr *)&sar->host_addr); | |
3344 | ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar); | |
3345 | + int wildcard; | |
3346 | + | |
3347 | + wildcard = 0; | |
3348 | + switch (sar->host_addr.ss_family) { | |
3349 | + case AF_INET: | |
3350 | + { | |
3351 | + struct sockaddr_in *sin; | |
3352 | + sin = (struct sockaddr_in *)&sar->host_addr; | |
3353 | + if (sin->sin_addr.s_addr == INADDR_ANY) | |
3354 | + wildcard++; | |
3355 | + break; | |
3356 | + } | |
3357 | +#ifdef INET6 | |
3358 | + case AF_INET6: | |
3359 | + { | |
3360 | + struct sockaddr_in6 *sin6; | |
3361 | + sin6 = (struct sockaddr_in6 *)&sar->host_addr; | |
3362 | + if (*(ap_uint32_t *)&sin6->sin6_addr.s6_addr[0] == 0 | |
3363 | + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[4] == 0 | |
3364 | + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[8] == 0 | |
3365 | + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[12] == 0) { | |
3366 | + wildcard++; | |
3367 | + } | |
3368 | + break; | |
3369 | + } | |
3370 | +#endif | |
3371 | + } | |
3372 | ||
3373 | - if (sar->host_addr.s_addr != INADDR_ANY) { | |
3374 | + if (!wildcard) { | |
3375 | *iphash_table_tail[bucket] = ic; | |
3376 | iphash_table_tail[bucket] = &ic->next; | |
3377 | } | |
3378 | @@ -588,12 +705,45 @@ | |
3379 | has_default_vhost_addr = 0; | |
3380 | for (sar = s->addrs; sar; sar = sar->next) { | |
3381 | ipaddr_chain *ic; | |
3382 | + int wildcard; | |
3383 | + | |
3384 | + wildcard = 0; | |
3385 | + switch (sar->host_addr.ss_family) { | |
3386 | + case AF_INET: | |
3387 | + { | |
3388 | + struct sockaddr_in *sin; | |
3389 | + sin = (struct sockaddr_in *)&sar->host_addr; | |
3390 | + if (sin->sin_addr.s_addr == DEFAULT_VHOST_ADDR) | |
3391 | + wildcard++; | |
3392 | + else if (sin->sin_addr.s_addr == INADDR_ANY) | |
3393 | + wildcard++; | |
3394 | + break; | |
3395 | + } | |
3396 | +#ifdef INET6 | |
3397 | + case AF_INET6: | |
3398 | + { | |
3399 | + struct sockaddr_in6 *sin6; | |
3400 | + sin6 = (struct sockaddr_in6 *)&sar->host_addr; | |
3401 | + if (*(ap_uint32_t *)&sin6->sin6_addr.s6_addr[0] == ~0 | |
3402 | + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[4] == ~0 | |
3403 | + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[8] == ~0 | |
3404 | + && *(ap_uint32_t *)&sin6->sin6_addr.s6_addr[12] == ~0) { | |
3405 | + wildcard++; | |
3406 | + } | |
3407 | + break; | |
3408 | + } | |
3409 | +#endif | |
3410 | + } | |
3411 | ||
3412 | - if (sar->host_addr.s_addr == DEFAULT_VHOST_ADDR | |
3413 | - || sar->host_addr.s_addr == INADDR_ANY) { | |
3414 | - ic = find_default_server(sar->host_port); | |
3415 | - if (!ic || !add_name_vhost_config(p, main_s, s, sar, ic)) { | |
3416 | - if (ic && ic->sar->host_port != 0) { | |
3417 | + if (wildcard) { | |
3418 | + /* add it to default bucket for each appropriate sar | |
3419 | + * since we need to do a port test | |
3420 | + */ | |
3421 | + ipaddr_chain *other; | |
3422 | + | |
3423 | + other = find_default_server(sar->host_port); | |
3424 | + if (!other || !add_name_vhost_config(p, main_s, s, sar, other)) { | |
3425 | + if (other && other->sar->host_port != 0) { | |
3426 | ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, | |
3427 | main_s, "_default_ VirtualHost overlap on port %u," | |
3428 | " the first has precedence", sar->host_port); | |
3429 | @@ -606,10 +756,11 @@ | |
3430 | } | |
3431 | else { | |
3432 | /* see if it matches something we've already got */ | |
3433 | - ic = find_ipaddr(&sar->host_addr, sar->host_port); | |
3434 | + ic = find_ipaddr((struct sockaddr *)&sar->host_addr); | |
3435 | ||
3436 | if (!ic) { | |
3437 | - unsigned bucket = hash_inaddr(sar->host_addr.s_addr); | |
3438 | + unsigned bucket = | |
3439 | + hash_addr((struct sockaddr *)&sar->host_addr); | |
3440 | ||
3441 | ic = new_ipaddr_chain(p, s, sar); | |
3442 | ic->next = *iphash_table_tail[bucket]; | |
3443 | @@ -646,19 +797,33 @@ | |
3444 | } | |
3445 | else { | |
3446 | struct hostent *h; | |
3447 | + char hostnamebuf[MAXHOSTNAMELEN]; | |
3448 | ||
3449 | - if ((h = gethostbyaddr((char *) &(s->addrs->host_addr), | |
3450 | - sizeof(struct in_addr), AF_INET))) { | |
3451 | - s->server_hostname = ap_pstrdup(p, (char *) h->h_name); | |
3452 | + if (!getnameinfo((struct sockaddr *)&s->addrs->host_addr, | |
3453 | +#ifndef SIN6_LEN | |
3454 | + SA_LEN((struct sockaddr *)&s->addrs->host_addr), | |
3455 | +#else | |
3456 | + s->addrs->host_addr.ss_len, | |
3457 | +#endif | |
3458 | + hostnamebuf, sizeof(hostnamebuf), | |
3459 | + NULL, 0, 0)) { | |
3460 | + s->server_hostname = ap_pstrdup(p, hostnamebuf); | |
3461 | } | |
3462 | else { | |
3463 | /* again, what can we do? They didn't specify a | |
3464 | ServerName, and their DNS isn't working. -djg */ | |
3465 | + getnameinfo((struct sockaddr *)&s->addrs->host_addr, | |
3466 | +#ifndef SIN6_LEN | |
3467 | + SA_LEN((struct sockaddr *)&s->addrs->host_addr), | |
3468 | +#else | |
3469 | + s->addrs->host_addr.ss_len, | |
3470 | +#endif | |
3471 | + hostnamebuf, sizeof(hostnamebuf), | |
3472 | + NULL, 0, NI_NUMERICHOST); | |
3473 | ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s, | |
3474 | "Failed to resolve server name " | |
3475 | "for %s (check DNS) -- or specify an explicit " | |
3476 | - "ServerName", | |
3477 | - inet_ntoa(s->addrs->host_addr)); | |
3478 | + "ServerName", hostnamebuf); | |
3479 | s->server_hostname = | |
3480 | ap_pstrdup(p, "bogus_host_without_reverse_dns"); | |
3481 | } | |
3482 | @@ -705,35 +870,58 @@ | |
3483 | char *host = ap_palloc(r->pool, strlen(r->hostname) + 1); | |
3484 | const char *src; | |
3485 | char *dst; | |
3486 | + const char *u = NULL, *v = NULL; | |
3487 | ||
3488 | /* check and copy the host part */ | |
3489 | - src = r->hostname; | |
3490 | + u = src = r->hostname; | |
3491 | ||
3492 | dst = host; | |
3493 | - while (*src) { | |
3494 | - if (*src == '.') { | |
3495 | - *dst++ = *src++; | |
3496 | - if (*src == '.') | |
3497 | - goto bad; | |
3498 | - else | |
3499 | - continue; | |
3500 | - } | |
3501 | - if (*src == '/' || *src == '\\') { | |
3502 | - goto bad; | |
3503 | - } | |
3504 | - if (*src == ':') { | |
3505 | - /* check the port part */ | |
3506 | - while (*++src) { | |
3507 | - if (!ap_isdigit(*src)) { | |
3508 | - goto bad; | |
3509 | - } | |
3510 | - } | |
3511 | - if (src[-1] == ':') | |
3512 | - goto bad; | |
3513 | - else | |
3514 | - break; | |
3515 | + if (*u == '[') { /* IPv6 numeral address in brackets */ | |
3516 | + v = strchr(u, ']'); | |
3517 | + if (v == NULL) { | |
3518 | + /* missing closing bracket */ | |
3519 | + goto bad; | |
3520 | + } | |
3521 | + if (v == (u + 1)) { | |
3522 | + /* bad empty address */ | |
3523 | + goto bad; | |
3524 | + } | |
3525 | + for (src = u+1; src < v; src++) /* copy IPv6 adress */ | |
3526 | + *dst = *src; | |
3527 | + v++; | |
3528 | + if (*v == ':') { | |
3529 | + v++; | |
3530 | + while (*v) { /* check if portnum is correct */ | |
3531 | + if (!ap_isdigit(*v++)) | |
3532 | + goto bad; | |
3533 | + } | |
3534 | } | |
3535 | - *dst++ = *src++; | |
3536 | + } else { | |
3537 | + while (*src) { | |
3538 | + if (*src == '.') { | |
3539 | + *dst++ = *src++; | |
3540 | + if (*src == '.') | |
3541 | + goto bad; | |
3542 | + else | |
3543 | + continue; | |
3544 | + } | |
3545 | + if (*src == '/' || *src == '\\') { | |
3546 | + goto bad; | |
3547 | + } | |
3548 | + if (*src == ':') { | |
3549 | + /* sheck the port part */ | |
3550 | + while (*++src) { | |
3551 | + if (!ap_isdigit(*src)) { | |
3552 | + goto bad; | |
3553 | + } | |
3554 | + } | |
3555 | + if (src[-1] == ':') | |
3556 | + goto bad; | |
3557 | + else | |
3558 | + break; | |
3559 | + } | |
3560 | + *dst++ = *src++; | |
3561 | + } | |
3562 | } | |
3563 | /* strip trailing gubbins */ | |
3564 | if (dst > host && dst[-1] == '.') { | |
3565 | @@ -748,7 +936,7 @@ | |
3566 | bad: | |
3567 | r->status = HTTP_BAD_REQUEST; | |
3568 | ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, | |
3569 | - "Client sent malformed Host header"); | |
3570 | + "Client sent malformed Host header <<%s>>",u); | |
3571 | return; | |
3572 | } | |
3573 | ||
3574 | @@ -851,11 +1039,25 @@ | |
3575 | * names we'll match have ports associated with them | |
3576 | */ | |
3577 | const char *host = r->hostname; | |
3578 | - unsigned port = ntohs(r->connection->local_addr.sin_port); | |
3579 | + unsigned port; | |
3580 | server_rec *s; | |
3581 | server_rec *last_s; | |
3582 | name_chain *src; | |
3583 | ||
3584 | + switch (r->connection->local_addr.ss_family) { | |
3585 | + case AF_INET: | |
3586 | + port = ntohs(((struct sockaddr_in *) | |
3587 | + &r->connection->local_addr)->sin_port); | |
3588 | + break; | |
3589 | +#ifdef INET6 | |
3590 | + case AF_INET6: | |
3591 | + port = ntohs(((struct sockaddr_in6 *) | |
3592 | + &r->connection->local_addr)->sin6_port); | |
3593 | + break; | |
3594 | +#endif | |
3595 | + default: | |
3596 | + port = 0; /*XXX*/ | |
3597 | + } | |
3598 | last_s = NULL; | |
3599 | ||
3600 | /* Recall that the name_chain is a list of server_addr_recs, some of | |
3601 | @@ -910,7 +1112,22 @@ | |
3602 | server_rec *s; | |
3603 | server_rec *last_s; | |
3604 | name_chain *src; | |
3605 | - unsigned port = ntohs(r->connection->local_addr.sin_port); | |
3606 | + unsigned port; | |
3607 | + | |
3608 | + switch (r->connection->local_addr.ss_family) { | |
3609 | + case AF_INET: | |
3610 | + port = ntohs(((struct sockaddr_in *) | |
3611 | + &r->connection->local_addr)->sin_port); | |
3612 | + break; | |
3613 | +#ifdef INET6 | |
3614 | + case AF_INET6: | |
3615 | + port = ntohs(((struct sockaddr_in6 *) | |
3616 | + &r->connection->local_addr)->sin6_port); | |
3617 | + break; | |
3618 | +#endif | |
3619 | + default: | |
3620 | + port = 0; /*XXX*/ | |
3621 | + } | |
3622 | ||
3623 | /* | |
3624 | * This is in conjunction with the ServerPath code in http_core, so we | |
3625 | @@ -970,10 +1187,22 @@ | |
3626 | void ap_update_vhost_given_ip(conn_rec *conn) | |
3627 | { | |
3628 | ipaddr_chain *trav; | |
3629 | - unsigned port = ntohs(conn->local_addr.sin_port); | |
3630 | + char portbuf[NI_MAXSERV]; | |
3631 | + unsigned port; | |
3632 | + | |
3633 | + if (getnameinfo((struct sockaddr *)&conn->local_addr, | |
3634 | +#ifndef SIN6_LEN | |
3635 | + SA_LEN((struct sockaddr *)&conn->local_addr), | |
3636 | +#else | |
3637 | + conn->local_addr.ss_len, | |
3638 | +#endif | |
3639 | + NULL, 0, portbuf, sizeof(portbuf), NI_NUMERICSERV) != 0) { | |
3640 | + goto fail; | |
3641 | + } | |
3642 | + port = atoi(portbuf); | |
3643 | ||
3644 | /* scan the hash table for an exact match first */ | |
3645 | - trav = find_ipaddr(&conn->local_addr.sin_addr, port); | |
3646 | + trav = find_ipaddr((struct sockaddr *)&conn->local_addr); | |
3647 | if (trav) { | |
3648 | /* save the name_chain for later in case this is a name-vhost */ | |
3649 | conn->vhost_lookup_data = trav->names; | |
3650 | @@ -991,6 +1220,7 @@ | |
3651 | return; | |
3652 | } | |
3653 | ||
3654 | +fail: | |
3655 | /* otherwise we're stuck with just the main server | |
3656 | * and no name-based vhosts | |
3657 | */ | |
3658 | diff -Nru apache_1.3.20/src/main/rfc1413.c apache_1.3.20.new/src/main/rfc1413.c | |
3659 | --- apache_1.3.20/src/main/rfc1413.c Mon Jan 15 18:05:04 2001 | |
3660 | +++ apache_1.3.20.new/src/main/rfc1413.c Mon May 21 10:54:52 2001 | |
3661 | @@ -82,6 +82,7 @@ | |
3662 | #include "http_log.h" /* for aplog_error */ | |
3663 | #include "rfc1413.h" | |
3664 | #include "http_main.h" /* set_callback_and_alarm */ | |
3665 | +#include "sa_len.h" | |
3666 | ||
3667 | /* Local stuff. */ | |
3668 | /* Semi-well-known port */ | |
3669 | @@ -109,12 +110,13 @@ | |
3670 | ||
3671 | /* bind_connect - bind both ends of a socket */ | |
3672 | /* Ambarish fix this. Very broken */ | |
3673 | -static int get_rfc1413(int sock, const struct sockaddr_in *our_sin, | |
3674 | - const struct sockaddr_in *rmt_sin, | |
3675 | +static int get_rfc1413(int sock, const struct sockaddr *our_sin, | |
3676 | + const struct sockaddr *rmt_sin, | |
3677 | char user[RFC1413_USERLEN+1], server_rec *srv) | |
3678 | { | |
3679 | - struct sockaddr_in rmt_query_sin, our_query_sin; | |
3680 | - unsigned int rmt_port, our_port; | |
3681 | + struct sockaddr_storage rmt_query_sin, our_query_sin; | |
3682 | + unsigned int o_rmt_port, o_our_port; /* original port pair */ | |
3683 | + unsigned int rmt_port, our_port; /* replied port pair */ | |
3684 | int i; | |
3685 | char *cp; | |
3686 | char buffer[RFC1413_MAXDATA + 1]; | |
3687 | @@ -129,16 +131,47 @@ | |
3688 | * addresses from the query socket. | |
3689 | */ | |
3690 | ||
3691 | - our_query_sin = *our_sin; | |
3692 | - our_query_sin.sin_port = htons(ANY_PORT); | |
3693 | -#ifdef MPE | |
3694 | - our_query_sin.sin_addr.s_addr = INADDR_ANY; | |
3695 | +#ifndef SIN6_LEN | |
3696 | + memcpy(&our_query_sin, our_sin, SA_LEN(our_sin)); | |
3697 | + memcpy(&rmt_query_sin, rmt_sin, SA_LEN(rmt_sin)); | |
3698 | +#else | |
3699 | + memcpy(&our_query_sin, our_sin, our_sin->sa_len); | |
3700 | + memcpy(&rmt_query_sin, rmt_sin, rmt_sin->sa_len); | |
3701 | #endif | |
3702 | - rmt_query_sin = *rmt_sin; | |
3703 | - rmt_query_sin.sin_port = htons(RFC1413_PORT); | |
3704 | + switch (our_sin->sa_family) { | |
3705 | + case AF_INET: | |
3706 | +#ifdef MPE | |
3707 | + ((struct sockaddr_in *)&our_query_sin)->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(??) */ | |
3708 | +#endif | |
3709 | + ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT); | |
3710 | + o_our_port = ntohs(((struct sockaddr_in *)our_sin)->sin_port); | |
3711 | + ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC1413_PORT); | |
3712 | + o_rmt_port = ntohs(((struct sockaddr_in *)rmt_sin)->sin_port); | |
3713 | + break; | |
3714 | +#ifdef INET6 | |
3715 | + case AF_INET6: | |
3716 | +#ifdef MPE | |
3717 | + memcpy(&((struct sockaddr_in6 *)&our_query_sin)->sin6_addr, | |
3718 | + &in6addr_any, sizeof(struct in6_addr)); | |
3719 | +#endif | |
3720 | + ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT); | |
3721 | + o_our_port = ntohs(((struct sockaddr_in6 *)our_sin)->sin6_port); | |
3722 | + ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC1413_PORT); | |
3723 | + o_rmt_port = ntohs(((struct sockaddr_in6 *)rmt_sin)->sin6_port); | |
3724 | + break; | |
3725 | +#endif | |
3726 | + default: | |
3727 | + /* unsupported AF */ | |
3728 | + return -1; | |
3729 | + } | |
3730 | ||
3731 | if (bind(sock, (struct sockaddr *) &our_query_sin, | |
3732 | - sizeof(struct sockaddr_in)) < 0) { | |
3733 | +#ifndef SIN6_LEN | |
3734 | + SA_LEN((struct sockaddr *) &our_query_sin) | |
3735 | +#else | |
3736 | + our_query_sin.ss_len | |
3737 | +#endif | |
3738 | + ) < 0) { | |
3739 | ap_log_error(APLOG_MARK, APLOG_CRIT, srv, | |
3740 | "bind: rfc1413: Error binding to local port"); | |
3741 | return -1; | |
3742 | @@ -149,12 +182,18 @@ | |
3743 | * the service | |
3744 | */ | |
3745 | if (connect(sock, (struct sockaddr *) &rmt_query_sin, | |
3746 | - sizeof(struct sockaddr_in)) < 0) | |
3747 | - return -1; | |
3748 | +#ifndef SIN6_LEN | |
3749 | + SA_LEN((struct sockaddr *) &rmt_query_sin) | |
3750 | +#else | |
3751 | + rmt_query_sin.ss_len | |
3752 | +#endif | |
3753 | + ) < 0) { | |
3754 | + return -1; | |
3755 | + } | |
3756 | ||
3757 | /* send the data */ | |
3758 | - buflen = ap_snprintf(buffer, sizeof(buffer), "%u,%u\r\n", ntohs(rmt_sin->sin_port), | |
3759 | - ntohs(our_sin->sin_port)); | |
3760 | + buflen = ap_snprintf(buffer, sizeof(buffer), "%u,%u\r\n", o_rmt_port, | |
3761 | + o_our_port); | |
3762 | ||
3763 | /* send query to server. Handle short write. */ | |
3764 | #ifdef CHARSET_EBCDIC | |
3765 | @@ -219,9 +258,9 @@ | |
3766 | ascii2ebcdic(buffer, buffer, (size_t)i); | |
3767 | #endif | |
3768 | if (sscanf(buffer, "%u , %u : USERID :%*[^:]:%512s", &rmt_port, &our_port, | |
3769 | - user) != 3 || ntohs(rmt_sin->sin_port) != rmt_port | |
3770 | - || ntohs(our_sin->sin_port) != our_port) | |
3771 | + user) != 3 || o_rmt_port != rmt_port || o_our_port != our_port) { | |
3772 | return -1; | |
3773 | + } | |
3774 | ||
3775 | /* | |
3776 | * Strip trailing carriage return. It is part of the | |
3777 | @@ -243,7 +282,7 @@ | |
3778 | ||
3779 | result = FROM_UNKNOWN; | |
3780 | ||
3781 | - sock = ap_psocket(conn->pool, AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
3782 | + sock = ap_psocket(conn->pool, conn->remote_addr.ss_family, SOCK_STREAM, IPPROTO_TCP); | |
3783 | if (sock < 0) { | |
3784 | ap_log_error(APLOG_MARK, APLOG_CRIT, srv, | |
3785 | "socket: rfc1413: error creating socket"); | |
3786 | @@ -256,8 +295,10 @@ | |
3787 | if (ap_setjmp(timebuf) == 0) { | |
3788 | ap_set_callback_and_alarm(ident_timeout, ap_rfc1413_timeout); | |
3789 | ||
3790 | - if (get_rfc1413(sock, &conn->local_addr, &conn->remote_addr, user, srv) >= 0) | |
3791 | + if (get_rfc1413(sock, (struct sockaddr *)&conn->local_addr, | |
3792 | + (struct sockaddr *)&conn->remote_addr, user, srv) >= 0) { | |
3793 | result = user; | |
3794 | + } | |
3795 | } | |
3796 | ap_set_callback_and_alarm(NULL, 0); | |
3797 | ap_pclosesocket(conn->pool, sock); | |
3798 | diff -Nru apache_1.3.20/src/main/util.c apache_1.3.20.new/src/main/util.c | |
3799 | --- apache_1.3.20/src/main/util.c Fri Mar 30 19:37:54 2001 | |
3800 | +++ apache_1.3.20.new/src/main/util.c Mon May 21 11:04:30 2001 | |
3801 | @@ -1959,52 +1959,87 @@ | |
3802 | * Parses a host of the form <address>[:port] | |
3803 | * :port is permitted if 'port' is not NULL | |
3804 | */ | |
3805 | -unsigned long ap_get_virthost_addr(char *w, unsigned short *ports) | |
3806 | +struct sockaddr *ap_get_virthost_addr(char *w, unsigned short *ports) | |
3807 | { | |
3808 | - struct hostent *hep; | |
3809 | - unsigned long my_addr; | |
3810 | - char *p; | |
3811 | - | |
3812 | - p = strchr(w, ':'); | |
3813 | + static struct sockaddr_storage ss; | |
3814 | + struct addrinfo hints, *res; | |
3815 | + char *p, *r; | |
3816 | + char *host; | |
3817 | + char *port = "0"; | |
3818 | + int error; | |
3819 | + char servbuf[NI_MAXSERV]; | |
3820 | + | |
3821 | + if (w == NULL) | |
3822 | + w = "*"; | |
3823 | + p = r = NULL; | |
3824 | + if (*w == '['){ | |
3825 | + if (r = strrchr(w+1, ']')){ | |
3826 | + *r = '\0'; | |
3827 | + p = r + 1; | |
3828 | + switch(*p){ | |
3829 | + case ':': | |
3830 | + p++; | |
3831 | + /* nobreak; */ | |
3832 | + case '\0': | |
3833 | + w++; | |
3834 | + break; | |
3835 | + default: | |
3836 | + p = NULL; | |
3837 | + } | |
3838 | + } | |
3839 | + } | |
3840 | + else{ | |
3841 | + p = strchr(w, ':'); | |
3842 | + if (p != NULL && strchr(p+1, ':') != NULL) | |
3843 | + p = NULL; | |
3844 | + } | |
3845 | if (ports != NULL) { | |
3846 | - *ports = 0; | |
3847 | - if (p != NULL && strcmp(p + 1, "*") != 0) | |
3848 | - *ports = atoi(p + 1); | |
3849 | + if (p != NULL && *p && strcmp(p + 1, "*") != 0) | |
3850 | + port = p + 1; | |
3851 | } | |
3852 | ||
3853 | + memset(&hints, 0, sizeof(hints)); | |
3854 | + hints.ai_socktype = SOCK_STREAM; | |
3855 | if (p != NULL) | |
3856 | *p = '\0'; | |
3857 | if (strcmp(w, "*") == 0) { | |
3858 | - if (p != NULL) | |
3859 | - *p = ':'; | |
3860 | - return htonl(INADDR_ANY); | |
3861 | - } | |
3862 | - | |
3863 | - my_addr = ap_inet_addr((char *)w); | |
3864 | - if (my_addr != INADDR_NONE) { | |
3865 | - if (p != NULL) | |
3866 | - *p = ':'; | |
3867 | - return my_addr; | |
3868 | + host = NULL; | |
3869 | + hints.ai_flags = AI_PASSIVE; | |
3870 | + hints.ai_family = ap_default_family; | |
3871 | + } else { | |
3872 | + host = w; | |
3873 | + hints.ai_family = PF_UNSPEC; | |
3874 | } | |
3875 | ||
3876 | - hep = gethostbyname(w); | |
3877 | + error = getaddrinfo(host, port, &hints, &res); | |
3878 | ||
3879 | - if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) { | |
3880 | - fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w); | |
3881 | + if (error || !res) { | |
3882 | + fprintf(stderr, "ap_get_vitrhost_addr(): getaddrinfo(%s):%s --- exiting!\n", w, gai_strerror(error)); | |
3883 | exit(1); | |
3884 | } | |
3885 | ||
3886 | - if (hep->h_addr_list[1]) { | |
3887 | - fprintf(stderr, "Host %s has multiple addresses ---\n", w); | |
3888 | + if (res->ai_next) { | |
3889 | + fprintf(stderr, "ap_get_vitrhost_addr(): Host %s has multiple addresses ---\n", w); | |
3890 | fprintf(stderr, "you must choose one explicitly for use as\n"); | |
3891 | fprintf(stderr, "a virtual host. Exiting!!!\n"); | |
3892 | exit(1); | |
3893 | } | |
3894 | ||
3895 | + if (r != NULL) | |
3896 | + *r = ']'; | |
3897 | if (p != NULL) | |
3898 | *p = ':'; | |
3899 | ||
3900 | - return ((struct in_addr *) (hep->h_addr))->s_addr; | |
3901 | + memcpy(&ss, res->ai_addr, res->ai_addrlen); | |
3902 | + if (getnameinfo(res->ai_addr, res->ai_addrlen, | |
3903 | + NULL, 0, servbuf, sizeof(servbuf), | |
3904 | + NI_NUMERICSERV)){ | |
3905 | + fprintf(stderr, "ap_get_virthost_addr(): getnameinfo() failed --- Exiting!!!\n"); | |
3906 | + exit(1); | |
3907 | + } | |
3908 | + if (ports) *ports = atoi(servbuf); | |
3909 | + freeaddrinfo(res); | |
3910 | + return (struct sockaddr *)&ss; | |
3911 | } | |
3912 | ||
3913 | ||
3914 | @@ -2032,7 +2067,8 @@ | |
3915 | #endif | |
3916 | char str[MAXHOSTNAMELEN]; | |
3917 | char *server_hostname = NULL; | |
3918 | - struct hostent *p; | |
3919 | + struct addrinfo hints, *res; | |
3920 | + int error; | |
3921 | ||
3922 | #ifdef BEOS /* BeOS returns zero as an error for gethostname */ | |
3923 | if (gethostname(str, sizeof(str) - 1) == 0) { | |
3924 | @@ -2045,29 +2081,38 @@ | |
3925 | } | |
3926 | else | |
3927 | { | |
3928 | - str[sizeof(str) - 1] = '\0'; | |
3929 | - if ((!(p = gethostbyname(str))) | |
3930 | - || (!(server_hostname = find_fqdn(a, p)))) { | |
3931 | - /* Recovery - return the default servername by IP: */ | |
3932 | - if (p && p->h_addr_list && p->h_addr_list[0]) { | |
3933 | - ap_snprintf(str, sizeof(str), "%pA", p->h_addr_list[0]); | |
3934 | - server_hostname = ap_pstrdup(a, str); | |
3935 | - /* We will drop through to report the IP-named server */ | |
3936 | - } | |
3937 | - } | |
3938 | - else | |
3939 | - /* Since we found a fqdn, return it with no logged message. */ | |
3940 | - return server_hostname; | |
3941 | - } | |
3942 | - | |
3943 | - /* If we don't have an fdqn or IP, fall back to the loopback addr */ | |
3944 | - if (!server_hostname) | |
3945 | - server_hostname = ap_pstrdup(a, "127.0.0.1"); | |
3946 | - | |
3947 | - ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, NULL, | |
3948 | - "%s: Could not determine the server's fully qualified " | |
3949 | - "domain name, using %s for ServerName", | |
3950 | - ap_server_argv0, server_hostname); | |
3951 | + str[sizeof(str) - 1] = '\0'; | |
3952 | + memset(&hints, 0, sizeof(hints)); | |
3953 | + hints.ai_family = PF_UNSPEC; | |
3954 | + hints.ai_flags = AI_CANONNAME; | |
3955 | + error = getaddrinfo(str, NULL, &hints, &res); | |
3956 | + if (error) | |
3957 | + { | |
3958 | + /* Recovery - return the default servername by IP: */ | |
3959 | + | |
3960 | + fprintf(stderr, "%s: cannot determine local host name.\n", | |
3961 | + ap_server_argv0); | |
3962 | + fprintf(stderr, "Use the ServerName directive to set it manually.\n"); | |
3963 | + exit(1); | |
3964 | + | |
3965 | + server_hostname = ap_pstrdup(a, res->ai_canonname); | |
3966 | + } | |
3967 | + else if (1) /*fqdn found*/ | |
3968 | + { | |
3969 | + /* XXX should check more conditions */ | |
3970 | + server_hostname = ap_pstrdup(a, res->ai_canonname); | |
3971 | + } | |
3972 | + else | |
3973 | + { | |
3974 | + ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, NULL, | |
3975 | + "%s: Could not determine the server's fully qualified " | |
3976 | + "domain name, using %s for ServerName", | |
3977 | + ap_server_argv0, server_hostname); | |
3978 | + } | |
3979 | + | |
3980 | + /* Since we found a fdqn, return it with no logged message. */ | |
3981 | + freeaddrinfo(res); | |
3982 | + } | |
3983 | ||
3984 | return server_hostname; | |
3985 | } | |
3986 | @@ -2146,7 +2191,7 @@ | |
3987 | char *quote_doubled_str, *dest; | |
3988 | ||
3989 | while (str[len]) { | |
3990 | - num_quotes += str[len++] == '\"'; | |
3991 | + num_quotes += str[len++] == '\"'; | |
3992 | } | |
3993 | ||
3994 | quote_doubled_str = ap_palloc(p, len + num_quotes + 1); | |
3995 | @@ -2271,3 +2316,11 @@ | |
3996 | } | |
3997 | *dest = 0; | |
3998 | } | |
3999 | + | |
4000 | +#ifdef NEED_GETADDRINFO | |
4001 | +#include "getaddrinfo.c" | |
4002 | +#endif | |
4003 | + | |
4004 | +#ifdef NEED_GETNAMEINFO | |
4005 | +#include "getnameinfo.c" | |
4006 | +#endif | |
4007 | diff -Nru apache_1.3.20/src/main/util_script.c apache_1.3.20.new/src/main/util_script.c | |
4008 | --- apache_1.3.20/src/main/util_script.c Wed May 9 07:17:11 2001 | |
4009 | +++ apache_1.3.20.new/src/main/util_script.c Mon May 21 10:54:52 2001 | |
4010 | @@ -67,6 +67,7 @@ | |
4011 | #include "http_request.h" /* for sub_req_lookup_uri() */ | |
4012 | #include "util_script.h" | |
4013 | #include "util_date.h" /* For parseHTTPdate() */ | |
4014 | +#include "sa_len.h" | |
4015 | ||
4016 | #ifdef OS2 | |
4017 | #define INCL_DOS | |
4018 | @@ -208,6 +209,7 @@ | |
4019 | array_header *hdrs_arr = ap_table_elts(r->headers_in); | |
4020 | table_entry *hdrs = (table_entry *) hdrs_arr->elts; | |
4021 | int i; | |
4022 | + char servbuf[NI_MAXSERV]; | |
4023 | ||
4024 | /* use a temporary table which we'll overlap onto | |
4025 | * r->subprocess_env later | |
4026 | @@ -298,8 +300,16 @@ | |
4027 | ap_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */ | |
4028 | ap_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */ | |
4029 | ||
4030 | - ap_table_addn(e, "REMOTE_PORT", | |
4031 | - ap_psprintf(r->pool, "%d", ntohs(c->remote_addr.sin_port))); | |
4032 | + servbuf[0] = '\0'; | |
4033 | + if (!getnameinfo((struct sockaddr *)&c->remote_addr, | |
4034 | +#ifndef HAVE_SOCKADDR_LEN | |
4035 | + SA_LEN((struct sockaddr *)&c->remote_addr), | |
4036 | +#else | |
4037 | + c->remote_addr.ss_len, | |
4038 | +#endif | |
4039 | + NULL, 0, servbuf, sizeof(servbuf), NI_NUMERICSERV)){ | |
4040 | + ap_table_addn(e, "REMOTE_PORT", ap_pstrdup(r->pool, servbuf)); | |
4041 | + } | |
4042 | ||
4043 | if (c->user) { | |
4044 | ap_table_addn(e, "REMOTE_USER", c->user); | |
4045 | diff -Nru apache_1.3.20/src/main/util_uri.c apache_1.3.20.new/src/main/util_uri.c | |
4046 | --- apache_1.3.20/src/main/util_uri.c Sun Apr 8 09:50:02 2001 | |
4047 | +++ apache_1.3.20.new/src/main/util_uri.c Mon May 21 10:54:52 2001 | |
4048 | @@ -418,6 +418,12 @@ | |
4049 | * the hostname. If there's a port it is the first colon. | |
4050 | */ | |
4051 | s = memchr(hostinfo, ':', uri - hostinfo); | |
4052 | + if (*hostinfo == '[') { | |
4053 | + s = memchr(hostinfo+1, ']', uri - hostinfo - 1); | |
4054 | + if (s) | |
4055 | + s = strchr(s, ':'); | |
4056 | + } else | |
4057 | + s = memchr(hostinfo, ':', uri - hostinfo); | |
4058 | if (s == NULL) { | |
4059 | /* we expect the common case to have no port */ | |
4060 | uptr->hostname = ap_pstrndup(p, hostinfo, uri - hostinfo); | |
4061 | @@ -474,7 +480,12 @@ | |
4062 | /* We expect hostinfo to point to the first character of | |
4063 | * the hostname. There must be a port, separated by a colon | |
4064 | */ | |
4065 | - s = strchr(hostinfo, ':'); | |
4066 | + if (*hostinfo == '[') { | |
4067 | + s = strchr(hostinfo+1, ']'); | |
4068 | + if (s) | |
4069 | + s = strchr(s, ':'); | |
4070 | + } else | |
4071 | + s = strchr(hostinfo, ':'); | |
4072 | if (s == NULL) { | |
4073 | return HTTP_BAD_REQUEST; | |
4074 | } | |
4075 | diff -Nru apache_1.3.20/src/modules/proxy/mod_proxy.c apache_1.3.20.new/src/modules/proxy/mod_proxy.c | |
4076 | --- apache_1.3.20/src/modules/proxy/mod_proxy.c Mon May 21 11:02:04 2001 | |
4077 | +++ apache_1.3.20.new/src/modules/proxy/mod_proxy.c Mon May 21 10:54:52 2001 | |
4078 | @@ -555,11 +555,31 @@ | |
4079 | struct proxy_remote *new; | |
4080 | char *p, *q; | |
4081 | int port; | |
4082 | + char *bl = NULL, *br = NULL; | |
4083 | ||
4084 | p = strchr(r, ':'); | |
4085 | if (p == NULL || p[1] != '/' || p[2] != '/' || p[3] == '\0') | |
4086 | return "ProxyRemote: Bad syntax for a remote proxy server"; | |
4087 | - q = strchr(p + 3, ':'); | |
4088 | + bl = p + 3; | |
4089 | + if (*bl == '['){ | |
4090 | + br = strrchr(bl+1, ']'); | |
4091 | + if (br){ | |
4092 | + bl++; | |
4093 | + *br = '\0'; | |
4094 | + if (*(br+1) == ':'){ /* [host]:xx */ | |
4095 | + q = br+1; | |
4096 | + } | |
4097 | + else if (*(br+1) == '\0'){ /* [host] */ | |
4098 | + q = NULL; | |
4099 | + } | |
4100 | + else | |
4101 | + q = strrchr(br, ':'); /* XXX */ | |
4102 | + } | |
4103 | + else | |
4104 | + q = strrchr(bl, ':'); /* XXX */ | |
4105 | + } | |
4106 | + else | |
4107 | + q = strrchr(bl, ':'); | |
4108 | if (q != NULL) { | |
4109 | if (sscanf(q + 1, "%u", &port) != 1 || port > 65535) | |
4110 | return "ProxyRemote: Bad syntax for a remote proxy server (bad port number)"; | |
4111 | @@ -570,7 +590,7 @@ | |
4112 | *p = '\0'; | |
4113 | if (strchr(f, ':') == NULL) | |
4114 | ap_str_tolower(f); /* lowercase scheme */ | |
4115 | - ap_str_tolower(p + 3); /* lowercase hostname */ | |
4116 | + ap_str_tolower(bl); /* lowercase hostname */ | |
4117 | ||
4118 | if (port == -1) { | |
4119 | int i; | |
4120 | @@ -583,7 +603,7 @@ | |
4121 | new = ap_push_array(conf->proxies); | |
4122 | new->scheme = f; | |
4123 | new->protocol = r; | |
4124 | - new->hostname = p + 3; | |
4125 | + new->hostname = bl; | |
4126 | new->port = port; | |
4127 | return NULL; | |
4128 | } | |
4129 | diff -Nru apache_1.3.20/src/modules/proxy/mod_proxy.h apache_1.3.20.new/src/modules/proxy/mod_proxy.h | |
4130 | --- apache_1.3.20/src/modules/proxy/mod_proxy.h Mon Jan 15 18:05:28 2001 | |
4131 | +++ apache_1.3.20.new/src/modules/proxy/mod_proxy.h Mon May 21 10:54:52 2001 | |
4132 | @@ -318,7 +318,7 @@ | |
4133 | int ap_proxy_is_domainname(struct dirconn_entry *This, pool *p); | |
4134 | int ap_proxy_is_hostname(struct dirconn_entry *This, pool *p); | |
4135 | int ap_proxy_is_word(struct dirconn_entry *This, pool *p); | |
4136 | -int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r); | |
4137 | +int ap_proxy_doconnect(int sock, struct sockaddr *addr, request_rec *r); | |
4138 | int ap_proxy_garbage_init(server_rec *, pool *); | |
4139 | /* This function is called by ap_table_do() for all header lines */ | |
4140 | int ap_proxy_send_hdr_line(void *p, const char *key, const char *value); | |
4141 | diff -Nru apache_1.3.20/src/modules/proxy/proxy_connect.c apache_1.3.20.new/src/modules/proxy/proxy_connect.c | |
4142 | --- apache_1.3.20/src/modules/proxy/proxy_connect.c Mon Jan 15 18:05:29 2001 | |
4143 | +++ apache_1.3.20.new/src/modules/proxy/proxy_connect.c Mon May 21 10:54:52 2001 | |
4144 | @@ -116,14 +116,15 @@ | |
4145 | const char *proxyhost, int proxyport) | |
4146 | { | |
4147 | struct sockaddr_in server; | |
4148 | - struct in_addr destaddr; | |
4149 | - struct hostent server_hp; | |
4150 | - const char *host, *err; | |
4151 | + struct addrinfo hints, *res, *res0; | |
4152 | + const char *hoststr; | |
4153 | + const char *portstr = NULL; | |
4154 | char *p; | |
4155 | int port, sock; | |
4156 | char buffer[HUGE_STRING_LEN]; | |
4157 | - int nbytes, i, j; | |
4158 | + int nbytes, i; | |
4159 | fd_set fds; | |
4160 | + int error; | |
4161 | ||
4162 | void *sconf = r->server->module_config; | |
4163 | proxy_server_conf *conf = | |
4164 | @@ -131,26 +132,59 @@ | |
4165 | struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; | |
4166 | ||
4167 | memset(&server, '\0', sizeof(server)); | |
4168 | +#ifdef HAVE_SOCKADDR_LEN | |
4169 | + server.sin_len = sizeof(server); | |
4170 | +#endif | |
4171 | server.sin_family = AF_INET; | |
4172 | ||
4173 | /* Break the URL into host:port pairs */ | |
4174 | ||
4175 | - host = url; | |
4176 | + hoststr = url; | |
4177 | p = strchr(url, ':'); | |
4178 | - if (p == NULL) | |
4179 | - port = DEFAULT_HTTPS_PORT; | |
4180 | - else { | |
4181 | - port = atoi(p + 1); | |
4182 | + if (p == NULL) { | |
4183 | + char pbuf[32]; | |
4184 | + ap_snprintf(pbuf, sizeof(pbuf), "%d", DEFAULT_HTTPS_PORT); | |
4185 | + portstr = pbuf; | |
4186 | + } else { | |
4187 | + portstr = p + 1; | |
4188 | *p = '\0'; | |
4189 | } | |
4190 | + port = atoi(portstr); | |
4191 | + | |
4192 | + memset(&hints, 0, sizeof(hints)); | |
4193 | + hints.ai_family = PF_UNSPEC; | |
4194 | + hints.ai_socktype = SOCK_STREAM; | |
4195 | + hints.ai_protocol = IPPROTO_TCP; | |
4196 | + error = getaddrinfo(hoststr, portstr, &hints, &res0); | |
4197 | + if (error) { | |
4198 | + return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, | |
4199 | + gai_strerror(error)); /* give up */ | |
4200 | + } | |
4201 | ||
4202 | /* check if ProxyBlock directive on this host */ | |
4203 | - destaddr.s_addr = ap_inet_addr(host); | |
4204 | - for (i = 0; i < conf->noproxies->nelts; i++) { | |
4205 | - if ((npent[i].name != NULL && strstr(host, npent[i].name) != NULL) | |
4206 | - || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') | |
4207 | + for (res = res0; res; res = res = res->ai_next) { | |
4208 | + struct sockaddr_in *sin; | |
4209 | + int fail; | |
4210 | + | |
4211 | + fail = 0; | |
4212 | + for (i = 0; i < conf->noproxies->nelts; i++) { | |
4213 | + if (npent[i].name != NULL && strstr(hoststr, npent[i].name)) | |
4214 | + fail++; | |
4215 | + if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0) | |
4216 | + fail++; | |
4217 | + switch (res->ai_family) { | |
4218 | + case AF_INET: | |
4219 | + sin = (struct sockaddr_in *)res->ai_addr; | |
4220 | + if (sin->sin_addr.s_addr == npent[i].addr.s_addr) | |
4221 | + fail++; | |
4222 | + break; | |
4223 | + } | |
4224 | + } | |
4225 | + if (fail) { | |
4226 | + freeaddrinfo(res0); | |
4227 | return ap_proxyerror(r, HTTP_FORBIDDEN, | |
4228 | "Connect to remote machine blocked"); | |
4229 | + } | |
4230 | } | |
4231 | ||
4232 | /* Check if it is an allowed port */ | |
4233 | @@ -161,59 +195,64 @@ | |
4234 | case DEFAULT_SNEWS_PORT: | |
4235 | break; | |
4236 | default: | |
4237 | + freeaddrinfo(res0); | |
4238 | return HTTP_FORBIDDEN; | |
4239 | } | |
4240 | - } else if(!allowed_port(conf, port)) | |
4241 | + } else if(!allowed_port(conf, port)) { | |
4242 | + freeaddrinfo(res0); | |
4243 | return HTTP_FORBIDDEN; | |
4244 | + } | |
4245 | ||
4246 | if (proxyhost) { | |
4247 | + char pbuf[10]; | |
4248 | + | |
4249 | + freeaddrinfo(res0); | |
4250 | + | |
4251 | + ap_snprintf(pbuf, sizeof(pbuf), "%d", proxyport); | |
4252 | + memset(&hints, 0, sizeof(hints)); | |
4253 | + hints.ai_family = PF_UNSPEC; | |
4254 | + hints.ai_socktype = SOCK_STREAM; | |
4255 | + hints.ai_protocol = IPPROTO_TCP; | |
4256 | + error = getaddrinfo(proxyhost, pbuf, &hints, &res0); | |
4257 | + if (error) | |
4258 | + return HTTP_INTERNAL_SERVER_ERROR; /* XXX */ | |
4259 | + | |
4260 | Explain2("CONNECT to remote proxy %s on port %d", proxyhost, proxyport); | |
4261 | } | |
4262 | else { | |
4263 | - Explain2("CONNECT to %s on port %d", host, port); | |
4264 | + Explain2("CONNECT to %s on port %d", hoststr, port); | |
4265 | } | |
4266 | ||
4267 | - server.sin_port = (proxyport ? htons(proxyport) : htons(port)); | |
4268 | - err = ap_proxy_host2addr(proxyhost ? proxyhost : host, &server_hp); | |
4269 | - | |
4270 | - if (err != NULL) | |
4271 | - return ap_proxyerror(r, | |
4272 | - proxyhost ? HTTP_BAD_GATEWAY : HTTP_INTERNAL_SERVER_ERROR, | |
4273 | - err); | |
4274 | - | |
4275 | - sock = ap_psocket(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP); | |
4276 | - if (sock == -1) { | |
4277 | - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4278 | - "proxy: error creating socket"); | |
4279 | - return HTTP_INTERNAL_SERVER_ERROR; | |
4280 | - } | |
4281 | + sock = i = -1; | |
4282 | + for (res = res0; res; res = res->ai_next) { | |
4283 | + sock = ap_psocket(r->pool, res->ai_family, res->ai_socktype, res->ai_protocol); | |
4284 | + if (sock == -1) | |
4285 | + continue; | |
4286 | ||
4287 | #ifdef CHECK_FD_SETSIZE | |
4288 | - if (sock >= FD_SETSIZE) { | |
4289 | - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL, | |
4290 | - "proxy_connect_handler: filedescriptor (%u) " | |
4291 | - "larger than FD_SETSIZE (%u) " | |
4292 | - "found, you probably need to rebuild Apache with a " | |
4293 | - "larger FD_SETSIZE", sock, FD_SETSIZE); | |
4294 | - ap_pclosesocket(r->pool, sock); | |
4295 | - return HTTP_INTERNAL_SERVER_ERROR; | |
4296 | - } | |
4297 | + if (sock >= FD_SETSIZE) { | |
4298 | + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL, | |
4299 | + "proxy_connect_handler: filedescriptor (%u) " | |
4300 | + "larger than FD_SETSIZE (%u) " | |
4301 | + "found, you probably need to rebuild Apache with a " | |
4302 | + "larger FD_SETSIZE. Anyway try to open next socket.", | |
4303 | + sock, FD_SETSIZE); | |
4304 | + ap_pclosesocket(r->pool, sock); | |
4305 | + continue; | |
4306 | + } | |
4307 | #endif | |
4308 | ||
4309 | - j = 0; | |
4310 | - while (server_hp.h_addr_list[j] != NULL) { | |
4311 | - memcpy(&server.sin_addr, server_hp.h_addr_list[j], | |
4312 | - sizeof(struct in_addr)); | |
4313 | - i = ap_proxy_doconnect(sock, &server, r); | |
4314 | + i = ap_proxy_doconnect(sock, res->ai_addr, r); | |
4315 | if (i == 0) | |
4316 | break; | |
4317 | - j++; | |
4318 | } | |
4319 | + freeaddrinfo(res0); | |
4320 | if (i == -1) { | |
4321 | ap_pclosesocket(r->pool, sock); | |
4322 | - return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, ap_pstrcat(r->pool, | |
4323 | - "Could not connect to remote machine:<br>", | |
4324 | - strerror(errno), NULL)); | |
4325 | + return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, | |
4326 | + ap_pstrcat(r->pool, | |
4327 | + "Could not connect to remote machine:<br>", | |
4328 | + strerror(errno), NULL)); | |
4329 | } | |
4330 | ||
4331 | /* If we are connecting through a remote proxy, we need to pass | |
4332 | diff -Nru apache_1.3.20/src/modules/proxy/proxy_ftp.c apache_1.3.20.new/src/modules/proxy/proxy_ftp.c | |
4333 | --- apache_1.3.20/src/modules/proxy/proxy_ftp.c Fri Mar 9 11:10:31 2001 | |
4334 | +++ apache_1.3.20.new/src/modules/proxy/proxy_ftp.c Mon May 21 10:54:52 2001 | |
4335 | @@ -62,6 +62,7 @@ | |
4336 | #include "http_main.h" | |
4337 | #include "http_log.h" | |
4338 | #include "http_core.h" | |
4339 | +#include "sa_len.h" | |
4340 | ||
4341 | #define AUTODETECT_PWD | |
4342 | ||
4343 | @@ -453,8 +454,10 @@ | |
4344 | const char *err; | |
4345 | int port, i, j, len, sock, dsock, rc, nocache = 0; | |
4346 | int csd = 0; | |
4347 | - struct sockaddr_in server; | |
4348 | - struct hostent server_hp; | |
4349 | + struct sockaddr_storage server; | |
4350 | + struct addrinfo hints, *res, *res0; | |
4351 | + char portbuf[10]; | |
4352 | + int error; | |
4353 | struct in_addr destaddr; | |
4354 | table *resp_hdrs; | |
4355 | BUFF *f; | |
4356 | @@ -475,11 +478,18 @@ | |
4357 | unsigned int presult, h0, h1, h2, h3, p0, p1; | |
4358 | unsigned int paddr; | |
4359 | unsigned short pport; | |
4360 | - struct sockaddr_in data_addr; | |
4361 | + struct sockaddr_storage data_addr; | |
4362 | + struct sockaddr_in *sin; | |
4363 | int pasvmode = 0; | |
4364 | char pasv[64]; | |
4365 | char *pstr; | |
4366 | ||
4367 | +/* stuff for LPSV/EPSV */ | |
4368 | + unsigned int paf, holen, ho[16], polen, po[2]; | |
4369 | + struct sockaddr_in6 *sin6; | |
4370 | + int lpsvmode = 0; | |
4371 | + char *cmd; | |
4372 | + | |
4373 | /* stuff for responses */ | |
4374 | char resp[MAX_STRING_LEN]; | |
4375 | char *size = NULL; | |
4376 | @@ -549,62 +559,52 @@ | |
4377 | if (parms != NULL) | |
4378 | *(parms++) = '\0'; | |
4379 | ||
4380 | - memset(&server, 0, sizeof(struct sockaddr_in)); | |
4381 | - server.sin_family = AF_INET; | |
4382 | - server.sin_port = htons(port); | |
4383 | - err = ap_proxy_host2addr(host, &server_hp); | |
4384 | - if (err != NULL) | |
4385 | - return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err); | |
4386 | - | |
4387 | - sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); | |
4388 | - if (sock == -1) { | |
4389 | - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4390 | - "proxy: error creating socket"); | |
4391 | - return HTTP_INTERNAL_SERVER_ERROR; | |
4392 | - } | |
4393 | + ap_snprintf(portbuf, sizeof(portbuf), "%d", port); | |
4394 | + memset(&hints, 0, sizeof(hints)); | |
4395 | + hints.ai_family = PF_UNSPEC; | |
4396 | + hints.ai_socktype = SOCK_STREAM; | |
4397 | + error = getaddrinfo(host, portbuf, &hints, &res0); | |
4398 | + if (error) { | |
4399 | + return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, | |
4400 | + gai_strerror(error)); | |
4401 | + } | |
4402 | + | |
4403 | + i = -1; | |
4404 | + for (res = res0; res; res = res->ai_next) { | |
4405 | + sock = ap_psocket(p, res->ai_family, res->ai_socktype, | |
4406 | + res->ai_protocol); | |
4407 | + if (sock == -1) | |
4408 | + continue; | |
4409 | ||
4410 | #if !defined(TPF) && !defined(BEOS) | |
4411 | - if (conf->recv_buffer_size > 0 | |
4412 | - && setsockopt(sock, SOL_SOCKET, SO_RCVBUF, | |
4413 | - (const char *) &conf->recv_buffer_size, sizeof(int)) | |
4414 | - == -1) { | |
4415 | - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4416 | - "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); | |
4417 | - } | |
4418 | + if (conf->recv_buffer_size > 0 | |
4419 | + && setsockopt(sock, SOL_SOCKET, SO_RCVBUF, | |
4420 | + (const char *) &conf->recv_buffer_size, sizeof(int)) | |
4421 | + == -1) { | |
4422 | + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4423 | + "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); | |
4424 | + } | |
4425 | #endif | |
4426 | ||
4427 | - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &one, | |
4428 | - sizeof(one)) == -1) { | |
4429 | + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &one, | |
4430 | + sizeof(one)) == -1) { | |
4431 | #ifndef _OSD_POSIX /* BS2000 has this option "always on" */ | |
4432 | - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4433 | - "proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)"); | |
4434 | - ap_pclosesocket(p, sock); | |
4435 | - return HTTP_INTERNAL_SERVER_ERROR; | |
4436 | + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4437 | + "proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)"); | |
4438 | + ap_pclosesocket(p, sock); | |
4439 | + freeaddrinfo(res0); | |
4440 | + return HTTP_INTERNAL_SERVER_ERROR; | |
4441 | #endif /*_OSD_POSIX*/ | |
4442 | - } | |
4443 | - | |
4444 | -#ifdef SINIX_D_RESOLVER_BUG | |
4445 | - { | |
4446 | - struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list; | |
4447 | - | |
4448 | - for (; ip_addr->s_addr != 0; ++ip_addr) { | |
4449 | - memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr)); | |
4450 | - i = ap_proxy_doconnect(sock, &server, r); | |
4451 | - if (i == 0) | |
4452 | - break; | |
4453 | } | |
4454 | - } | |
4455 | -#else | |
4456 | - j = 0; | |
4457 | - while (server_hp.h_addr_list[j] != NULL) { | |
4458 | - memcpy(&server.sin_addr, server_hp.h_addr_list[j], | |
4459 | - sizeof(struct in_addr)); | |
4460 | - i = ap_proxy_doconnect(sock, &server, r); | |
4461 | - if (i == 0) | |
4462 | + | |
4463 | + i = ap_proxy_doconnect(sock, res->ai_addr, r); | |
4464 | + if (i == 0){ | |
4465 | + memcpy(&server, res->ai_addr, res->ai_addrlen); | |
4466 | break; | |
4467 | - j++; | |
4468 | + } | |
4469 | + ap_pclosesocket(p, sock); | |
4470 | } | |
4471 | -#endif | |
4472 | + freeaddrinfo(res0); | |
4473 | if (i == -1) { | |
4474 | ap_pclosesocket(p, sock); | |
4475 | return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool, | |
4476 | @@ -808,7 +808,7 @@ | |
4477 | } | |
4478 | ||
4479 | /* try to set up PASV data connection first */ | |
4480 | - dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); | |
4481 | + dsock = ap_psocket(p, server.ss_family, SOCK_STREAM, IPPROTO_TCP); | |
4482 | if (dsock == -1) { | |
4483 | ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4484 | "proxy: error creating PASV socket"); | |
4485 | @@ -827,11 +827,21 @@ | |
4486 | } | |
4487 | #endif | |
4488 | ||
4489 | - ap_bputs("PASV" CRLF, f); | |
4490 | +lpsvagain: | |
4491 | + if (server.ss_family == AF_INET) | |
4492 | + cmd = "PASV"; | |
4493 | + else if (lpsvmode) | |
4494 | + cmd = "LPSV"; | |
4495 | + else | |
4496 | + cmd = "EPSV"; | |
4497 | + ap_bputs(cmd, f); | |
4498 | + ap_bputs(CRLF, f); | |
4499 | ap_bflush(f); | |
4500 | - Explain0("FTP: PASV command issued"); | |
4501 | + Explain0("FTP: passive command issued"); | |
4502 | /* possible results: 227, 421, 500, 501, 502, 530 */ | |
4503 | /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */ | |
4504 | + /* 228 Entering Long Passive Mode (...). */ | |
4505 | + /* 229 Entering Extended Passive Mode (...). */ | |
4506 | /* 421 Service not available, closing control connection. */ | |
4507 | /* 500 Syntax error, command unrecognized. */ | |
4508 | /* 501 Syntax error in parameters or arguments. */ | |
4509 | @@ -840,7 +850,7 @@ | |
4510 | i = ap_bgets(pasv, sizeof(pasv), f); | |
4511 | if (i == -1) { | |
4512 | ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r, | |
4513 | - "PASV: control connection is toast"); | |
4514 | + "%s: control connection is toast", cmd); | |
4515 | ap_pclosesocket(p, dsock); | |
4516 | ap_bclose(f); | |
4517 | ap_kill_timeout(r); | |
4518 | @@ -872,10 +882,14 @@ | |
4519 | pport = (p1 << 8) + p0; | |
4520 | Explain5("FTP: contacting host %d.%d.%d.%d:%d", | |
4521 | h3, h2, h1, h0, pport); | |
4522 | - data_addr.sin_family = AF_INET; | |
4523 | - data_addr.sin_addr.s_addr = htonl(paddr); | |
4524 | - data_addr.sin_port = htons(pport); | |
4525 | - i = ap_proxy_doconnect(dsock, &data_addr, r); | |
4526 | + sin = (struct sockaddr_in *)&data_addr; | |
4527 | + sin->sin_family = AF_INET; | |
4528 | +#ifdef SIN6_LEN | |
4529 | + sin->sin_len = sizeof(*sin); | |
4530 | +#endif | |
4531 | + sin->sin_addr.s_addr = htonl(paddr); | |
4532 | + sin->sin_port = htons(pport); | |
4533 | + i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r); | |
4534 | ||
4535 | if (i == -1) { | |
4536 | ap_kill_timeout(r); | |
4537 | @@ -883,17 +897,76 @@ | |
4538 | ap_pstrcat(r->pool, | |
4539 | "Could not connect to remote machine: ", | |
4540 | strerror(errno), NULL)); | |
4541 | + } else { | |
4542 | + pasvmode = 1; | |
4543 | } | |
4544 | - else { | |
4545 | + } else if (presult == 228 && pstr != NULL | |
4546 | + && sscanf(pstr, | |
4547 | +"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", | |
4548 | + &paf, &holen, &ho[0], &ho[1], &ho[2], &ho[3], | |
4549 | + &ho[4], &ho[5], &ho[6], &ho[7], &ho[8], &ho[9], &ho[10], &ho[11], | |
4550 | + &ho[12], &ho[13], &ho[14], &ho[15], &polen, &po[0], &po[1]) == 21 | |
4551 | + && paf == 6 && holen == 16 && polen == 2) { | |
4552 | + int i; | |
4553 | + sin6 = (struct sockaddr_in6 *)&data_addr; | |
4554 | + sin6->sin6_family = AF_INET6; | |
4555 | +#ifdef SIN6_LEN | |
4556 | + sin6->sin6_len = sizeof(*sin6); | |
4557 | +#endif | |
4558 | + for (i = 0; i < 16; i++) | |
4559 | + sin6->sin6_addr.s6_addr[i] = ho[i] & 0xff; | |
4560 | + sin6->sin6_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff)); | |
4561 | + i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r); | |
4562 | + | |
4563 | + if (i == -1) { | |
4564 | + ap_kill_timeout(r); | |
4565 | + return ap_proxyerror(r, HTTP_BAD_GATEWAY, | |
4566 | + ap_pstrcat(r->pool, | |
4567 | + "Could not connect to remote machine: ", | |
4568 | + strerror(errno), NULL)); | |
4569 | + } else { | |
4570 | + pasvmode = 1; | |
4571 | + } | |
4572 | + } else if (presult == 229 && pstr != NULL | |
4573 | + && pstr[0] == pstr[1] && pstr[0] == pstr[2] | |
4574 | + && pstr[0] == pstr[strlen(pstr) - 1]) { | |
4575 | + /* expect "|||port|" */ | |
4576 | +#ifndef SIN6_LEN | |
4577 | + memcpy(&data_addr, &server, SA_LEN((struct sockaddr *)&server)); | |
4578 | +#else | |
4579 | + memcpy(&data_addr, &server, server.ss_len); | |
4580 | +#endif | |
4581 | + switch (data_addr.ss_family) { | |
4582 | + case AF_INET: | |
4583 | + sin = (struct sockaddr_in *)&data_addr; | |
4584 | + sin->sin_port = htons(atoi(pstr + 3)); | |
4585 | + break; | |
4586 | + case AF_INET6: | |
4587 | + sin6 = (struct sockaddr_in6 *)&data_addr; | |
4588 | + sin6->sin6_port = htons(atoi(pstr + 3)); | |
4589 | + break; | |
4590 | + } | |
4591 | + i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r); | |
4592 | + | |
4593 | + if (i == -1) { | |
4594 | + ap_kill_timeout(r); | |
4595 | + return ap_proxyerror(r, HTTP_BAD_GATEWAY, | |
4596 | + ap_pstrcat(r->pool, | |
4597 | + "Could not connect to remote machine: ", | |
4598 | + strerror(errno), NULL)); | |
4599 | + } else { | |
4600 | pasvmode = 1; | |
4601 | } | |
4602 | + } else if (!lpsvmode && strcmp(cmd, "EPSV") == 0) { | |
4603 | + lpsvmode = 1; | |
4604 | + goto lpsvagain; | |
4605 | } | |
4606 | else | |
4607 | ap_pclosesocket(p, dsock); /* and try the regular way */ | |
4608 | } | |
4609 | ||
4610 | if (!pasvmode) { /* set up data connection */ | |
4611 | - clen = sizeof(struct sockaddr_in); | |
4612 | + clen = sizeof(server); | |
4613 | if (getsockname(sock, (struct sockaddr *) &server, &clen) < 0) { | |
4614 | ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4615 | "proxy: error getting socket address"); | |
4616 | @@ -902,7 +975,7 @@ | |
4617 | return HTTP_INTERNAL_SERVER_ERROR; | |
4618 | } | |
4619 | ||
4620 | - dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); | |
4621 | + dsock = ap_psocket(p, server.ss_family, SOCK_STREAM, IPPROTO_TCP); | |
4622 | if (dsock == -1) { | |
4623 | ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4624 | "proxy: error creating socket"); | |
4625 | @@ -923,13 +996,26 @@ | |
4626 | #endif /*_OSD_POSIX*/ | |
4627 | } | |
4628 | ||
4629 | - if (bind(dsock, (struct sockaddr *) &server, | |
4630 | - sizeof(struct sockaddr_in)) == -1) { | |
4631 | - char buff[22]; | |
4632 | +#ifndef SIN6_LEN | |
4633 | + if (bind(dsock, (struct sockaddr *) &server, SA_LEN((struct sockaddr *)&server)) == -1) | |
4634 | +#else | |
4635 | + if (bind(dsock, (struct sockaddr *) &server, server.ss_len) == -1) | |
4636 | +#endif | |
4637 | + { | |
4638 | + char hostnamebuf[MAXHOSTNAMELEN], portnamebuf[MAXHOSTNAMELEN]; | |
4639 | ||
4640 | - ap_snprintf(buff, sizeof(buff), "%s:%d", inet_ntoa(server.sin_addr), server.sin_port); | |
4641 | + getnameinfo((struct sockaddr *)&server, | |
4642 | +#ifndef SIN6_LEN | |
4643 | + SA_LEN((struct sockaddr *)&server), | |
4644 | +#else | |
4645 | + server.ss_len, | |
4646 | +#endif | |
4647 | + hostnamebuf, sizeof(hostnamebuf), | |
4648 | + portnamebuf, sizeof(portnamebuf), | |
4649 | + NI_NUMERICHOST | NI_NUMERICSERV); | |
4650 | ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4651 | - "proxy: error binding to ftp data socket %s", buff); | |
4652 | + "proxy: error binding to ftp data socket %s:%s", | |
4653 | + hostnamebuf, portnamebuf); | |
4654 | ap_bclose(f); | |
4655 | ap_pclosesocket(p, dsock); | |
4656 | return HTTP_INTERNAL_SERVER_ERROR; | |
4657 | @@ -1188,7 +1274,7 @@ | |
4658 | ||
4659 | if (!pasvmode) { /* wait for connection */ | |
4660 | ap_hard_timeout("proxy ftp data connect", r); | |
4661 | - clen = sizeof(struct sockaddr_in); | |
4662 | + clen = sizeof(server); | |
4663 | do | |
4664 | csd = accept(dsock, (struct sockaddr *) &server, &clen); | |
4665 | while (csd == -1 && errno == EINTR); | |
4666 | diff -Nru apache_1.3.20/src/modules/proxy/proxy_http.c apache_1.3.20.new/src/modules/proxy/proxy_http.c | |
4667 | --- apache_1.3.20/src/modules/proxy/proxy_http.c Mon May 21 11:02:04 2001 | |
4668 | +++ apache_1.3.20.new/src/modules/proxy/proxy_http.c Mon May 21 10:54:52 2001 | |
4669 | @@ -177,9 +177,8 @@ | |
4670 | array_header *reqhdrs_arr; | |
4671 | table *resp_hdrs; | |
4672 | table_entry *reqhdrs; | |
4673 | - struct sockaddr_in server; | |
4674 | - struct in_addr destaddr; | |
4675 | - struct hostent server_hp; | |
4676 | + struct addrinfo hints, *res, *res0; | |
4677 | + int error; | |
4678 | BUFF *f; | |
4679 | char buffer[HUGE_STRING_LEN]; | |
4680 | char portstr[32]; | |
4681 | @@ -201,9 +200,6 @@ | |
4682 | struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts; | |
4683 | int nocache = 0; | |
4684 | ||
4685 | - memset(&server, '\0', sizeof(server)); | |
4686 | - server.sin_family = AF_INET; | |
4687 | - | |
4688 | /* We break the URL into host, port, path-search */ | |
4689 | ||
4690 | urlptr = strstr(url, "://"); | |
4691 | @@ -211,6 +207,8 @@ | |
4692 | return HTTP_BAD_REQUEST; | |
4693 | urlptr += 3; | |
4694 | destport = DEFAULT_HTTP_PORT; | |
4695 | + ap_snprintf(portstr, sizeof(portstr), "%d", DEFAULT_HTTP_PORT); | |
4696 | + destportstr = portstr; | |
4697 | #ifdef EAPI | |
4698 | ap_hook_use("ap::mod_proxy::http::handler::set_destport", | |
4699 | AP_HOOK_SIG2(int,ptr), | |
4700 | @@ -229,7 +227,20 @@ | |
4701 | urlptr = strp; | |
4702 | desthost = q; | |
4703 | } | |
4704 | - | |
4705 | + if (*desthost == '['){ | |
4706 | + char *u = strrchr(desthost+1, ']'); | |
4707 | + if (u){ | |
4708 | + desthost++; | |
4709 | + *u = '\0'; | |
4710 | + if (*(u+1) == ':'){ /* [host]:xx */ | |
4711 | + strp2 = u+1; | |
4712 | + } else if (*(u+1) == '\0'){ /* [host] */ | |
4713 | + strp2 = NULL; | |
4714 | + } else | |
4715 | + return HTTP_BAD_REQUEST; | |
4716 | + } else | |
4717 | + return HTTP_BAD_REQUEST; | |
4718 | + } else | |
4719 | strp2 = strchr(desthost, ':'); | |
4720 | if (strp2 != NULL) { | |
4721 | *(strp2++) = '\0'; | |
4722 | @@ -240,41 +251,69 @@ | |
4723 | } | |
4724 | ||
4725 | /* check if ProxyBlock directive on this host */ | |
4726 | - destaddr.s_addr = ap_inet_addr(desthost); | |
4727 | - for (i = 0; i < conf->noproxies->nelts; i++) { | |
4728 | - if (destaddr.s_addr == npent[i].addr.s_addr || | |
4729 | - (npent[i].name != NULL && | |
4730 | - (npent[i].name[0] == '*' || strstr(desthost, npent[i].name) != NULL))) | |
4731 | + memset(&hints, 0, sizeof(hints)); | |
4732 | + hints.ai_family = PF_UNSPEC; | |
4733 | + hints.ai_socktype = SOCK_STREAM; | |
4734 | + hints.ai_protocol = IPPROTO_TCP; | |
4735 | + error = getaddrinfo(desthost, destportstr, &hints, &res0); | |
4736 | + if (error) { | |
4737 | + return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, | |
4738 | + gai_strerror(error)); /* give up */ | |
4739 | + } | |
4740 | + | |
4741 | + /* check if ProxyBlock directive on this host */ | |
4742 | + for (res = res0; res; res = res->ai_next) { | |
4743 | + struct sockaddr_in *sin; | |
4744 | + #ifdef INET6 | |
4745 | + struct sockaddr_in6 *sin6; | |
4746 | + #endif | |
4747 | + int fail; | |
4748 | + | |
4749 | + fail = 0; | |
4750 | + for (i = 0; i < conf->noproxies->nelts; i++) { | |
4751 | + if (npent[i].name != NULL && strstr(desthost, npent[i].name)) | |
4752 | + fail++; | |
4753 | + if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0) | |
4754 | + fail++; | |
4755 | + switch (res->ai_family) { | |
4756 | + case AF_INET: | |
4757 | + sin = (struct sockaddr_in *)res->ai_addr; | |
4758 | + if (sin->sin_addr.s_addr == npent[i].addr.s_addr) | |
4759 | + fail++; | |
4760 | + break; | |
4761 | + } | |
4762 | + } | |
4763 | + if (fail) { | |
4764 | + freeaddrinfo(res0); | |
4765 | return ap_proxyerror(r, HTTP_FORBIDDEN, | |
4766 | "Connect to remote machine blocked"); | |
4767 | - } | |
4768 | - | |
4769 | - if (proxyhost != NULL) { | |
4770 | - server.sin_port = htons(proxyport); | |
4771 | - err = ap_proxy_host2addr(proxyhost, &server_hp); | |
4772 | - if (err != NULL) | |
4773 | - return DECLINED; /* try another */ | |
4774 | -#ifdef EAPI | |
4775 | - peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport); | |
4776 | -#endif | |
4777 | - } | |
4778 | - else { | |
4779 | - server.sin_port = htons(destport); | |
4780 | - err = ap_proxy_host2addr(desthost, &server_hp); | |
4781 | - if (err != NULL) | |
4782 | - return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err); | |
4783 | -#ifdef EAPI | |
4784 | - peer = ap_psprintf(p, "%s:%u", desthost, destport); | |
4785 | -#endif | |
4786 | - } | |
4787 | - | |
4788 | - sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); | |
4789 | - if (sock == -1) { | |
4790 | - ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
4791 | - "proxy: error creating socket"); | |
4792 | - return HTTP_INTERNAL_SERVER_ERROR; | |
4793 | - } | |
4794 | - | |
4795 | + } | |
4796 | + } | |
4797 | + | |
4798 | + if (proxyhost != NULL) { | |
4799 | + char pbuf[10]; | |
4800 | + | |
4801 | + freeaddrinfo(res0); | |
4802 | + ap_snprintf(pbuf, sizeof(pbuf), "%d", proxyport); | |
4803 | + memset(&hints, 0, sizeof(hints)); | |
4804 | + hints.ai_family = PF_UNSPEC; | |
4805 | + hints.ai_socktype = SOCK_STREAM; | |
4806 | + hints.ai_protocol = IPPROTO_TCP; | |
4807 | + error = getaddrinfo(proxyhost, pbuf, &hints, &res0); | |
4808 | + if (error) | |
4809 | + return DECLINED; /* try another */ | |
4810 | + #ifdef EAPI | |
4811 | + peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport); | |
4812 | + #endif | |
4813 | + } | |
4814 | + | |
4815 | + sock = i = -1; | |
4816 | + for (res = res0; res; res = res->ai_next) { | |
4817 | + sock = ap_psocket(p, res->ai_family, res->ai_socktype, | |
4818 | + res->ai_protocol); | |
4819 | + if (sock < 0) | |
4820 | + continue; | |
4821 | + | |
4822 | #if !defined(TPF) && !defined(BEOS) | |
4823 | if (conf->recv_buffer_size) { | |
4824 | if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, | |
4825 | @@ -286,28 +325,12 @@ | |
4826 | } | |
4827 | #endif | |
4828 | ||
4829 | -#ifdef SINIX_D_RESOLVER_BUG | |
4830 | - { | |
4831 | - struct in_addr *ip_addr = (struct in_addr *) *server_hp.h_addr_list; | |
4832 | - | |
4833 | - for (; ip_addr->s_addr != 0; ++ip_addr) { | |
4834 | - memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr)); | |
4835 | - i = ap_proxy_doconnect(sock, &server, r); | |
4836 | - if (i == 0) | |
4837 | - break; | |
4838 | - } | |
4839 | - } | |
4840 | -#else | |
4841 | - j = 0; | |
4842 | - while (server_hp.h_addr_list[j] != NULL) { | |
4843 | - memcpy(&server.sin_addr, server_hp.h_addr_list[j], | |
4844 | - sizeof(struct in_addr)); | |
4845 | - i = ap_proxy_doconnect(sock, &server, r); | |
4846 | + i = ap_proxy_doconnect(sock, res->ai_addr, r); | |
4847 | if (i == 0) | |
4848 | break; | |
4849 | - j++; | |
4850 | + ap_pclosesocket(p, sock); | |
4851 | } | |
4852 | -#endif | |
4853 | + freeaddrinfo(res0); | |
4854 | if (i == -1) { | |
4855 | if (proxyhost != NULL) | |
4856 | return DECLINED; /* try again another way */ | |
4857 | @@ -515,17 +538,31 @@ | |
4858 | ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, datestr)); | |
4859 | ||
4860 | /* check if NoCache directive on this host */ | |
4861 | + { | |
4862 | + struct sockaddr_in *sin; | |
4863 | +#ifdef INET6 | |
4864 | + struct sockaddr_in6 *sin6; | |
4865 | +#endif | |
4866 | + | |
4867 | if (nocache == 0) { | |
4868 | for (i = 0; i < conf->nocaches->nelts; i++) { | |
4869 | - if (destaddr.s_addr == ncent[i].addr.s_addr || | |
4870 | - (ncent[i].name != NULL && | |
4871 | - (ncent[i].name[0] == '*' || | |
4872 | - strstr(desthost, ncent[i].name) != NULL))) { | |
4873 | - nocache = 1; | |
4874 | - break; | |
4875 | + if (ncent[i].name != NULL && | |
4876 | + (ncent[i].name[0] == '*' || | |
4877 | + strstr(desthost, ncent[i].name) != NULL)) { | |
4878 | + nocache = 1; | |
4879 | + break; | |
4880 | + } | |
4881 | + switch (res->ai_addr->sa_family) { | |
4882 | + case AF_INET: | |
4883 | + sin = (struct sockaddr_in *)res->ai_addr; | |
4884 | + if (sin->sin_addr.s_addr == ncent[i].addr.s_addr) { | |
4885 | + nocache = 1; | |
4886 | + break; | |
4887 | + } | |
4888 | } | |
4889 | } | |
4890 | } | |
4891 | + } | |
4892 | ||
4893 | i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache); | |
4894 | if (i != DECLINED) { | |
4895 | diff -Nru apache_1.3.20/src/modules/proxy/proxy_util.c apache_1.3.20.new/src/modules/proxy/proxy_util.c | |
4896 | --- apache_1.3.20/src/modules/proxy/proxy_util.c Fri Mar 16 08:01:23 2001 | |
4897 | +++ apache_1.3.20.new/src/modules/proxy/proxy_util.c Mon May 21 10:54:52 2001 | |
4898 | @@ -64,6 +64,7 @@ | |
4899 | #include "http_log.h" | |
4900 | #include "util_uri.h" | |
4901 | #include "util_date.h" /* get ap_checkmask() decl. */ | |
4902 | +#include "sa_len.h" | |
4903 | ||
4904 | static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r); | |
4905 | static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r); | |
4906 | @@ -218,6 +219,7 @@ | |
4907 | int i; | |
4908 | char *strp, *host, *url = *urlp; | |
4909 | char *user = NULL, *password = NULL; | |
4910 | + char *t = NULL, *u = NULL, *v = NULL; | |
4911 | ||
4912 | if (url[0] != '/' || url[1] != '/') | |
4913 | return "Malformed URL"; | |
4914 | @@ -256,11 +258,22 @@ | |
4915 | *passwordp = password; | |
4916 | } | |
4917 | ||
4918 | - strp = strrchr(host, ':'); | |
4919 | - if (strp != NULL) { | |
4920 | - *(strp++) = '\0'; | |
4921 | - | |
4922 | - for (i = 0; strp[i] != '\0'; i++) | |
4923 | + v = host; | |
4924 | + if (*host == '['){ | |
4925 | + u = strrchr(host, ']'); | |
4926 | + if (u){ | |
4927 | + host++; | |
4928 | + *u = '\0'; | |
4929 | + v = u + 1; | |
4930 | + } | |
4931 | + } | |
4932 | + t = strrchr(v, ':'); | |
4933 | + if (t){ | |
4934 | + *t = '\0'; | |
4935 | + strp = t + 1; | |
4936 | + } | |
4937 | + if (strp){ | |
4938 | + for (i=0; strp[i] != '\0'; i++) | |
4939 | if (!ap_isdigit(strp[i])) | |
4940 | break; | |
4941 | ||
4942 | @@ -278,17 +291,29 @@ | |
4943 | return "Missing host in URL"; | |
4944 | /* check hostname syntax */ | |
4945 | for (i = 0; host[i] != '\0'; i++) | |
4946 | - if (!ap_isdigit(host[i]) && host[i] != '.') | |
4947 | + if (!ap_isxdigit(host[i]) && host[i] != '.' && host[i] != ':') | |
4948 | break; | |
4949 | /* must be an IP address */ | |
4950 | #if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS) | |
4951 | if (host[i] == '\0' && (inet_addr(host) == -1)) | |
4952 | + return "Bad IP address in URL"; | |
4953 | +#else | |
4954 | + if (host[i] == '\0') { | |
4955 | + struct addrinfo hints, *res0; | |
4956 | + int gai; | |
4957 | + memset(&hints, 0, sizeof(hints)); | |
4958 | + hints.ai_family = PF_UNSPEC; | |
4959 | + hints.ai_flags = AI_NUMERICHOST; | |
4960 | + if (gai = getaddrinfo(host, NULL, &hints, &res0)) { | |
4961 | +#if 0 | |
4962 | + return gai_strerror(gai); | |
4963 | #else | |
4964 | - if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1)) | |
4965 | + return "Bad IP address in URL"; | |
4966 | #endif | |
4967 | - { | |
4968 | - return "Bad IP address in URL"; | |
4969 | + } | |
4970 | + freeaddrinfo(res0); | |
4971 | } | |
4972 | +#endif | |
4973 | ||
4974 | /* if (strchr(host,'.') == NULL && domain != NULL) | |
4975 | host = pstrcat(p, host, domain, NULL); | |
4976 | @@ -1238,22 +1263,45 @@ | |
4977 | return host != NULL && strstr(host, This->name) != NULL; | |
4978 | } | |
4979 | ||
4980 | -int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r) | |
4981 | +int ap_proxy_doconnect(int sock, struct sockaddr *addr, request_rec *r) | |
4982 | { | |
4983 | int i; | |
4984 | + int salen; | |
4985 | + char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV]; | |
4986 | +#ifdef NI_WITHSCOPEID | |
4987 | + const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID; | |
4988 | +#else | |
4989 | + const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; | |
4990 | +#endif | |
4991 | ||
4992 | ap_hard_timeout("proxy connect", r); | |
4993 | +#ifdef HAVE_SOCKADDR_LEN | |
4994 | + salen = addr->sa_len; | |
4995 | +#else | |
4996 | + switch (addr->sa_family) { | |
4997 | + case AF_INET6: | |
4998 | + salen = sizeof(struct sockaddr_in6); | |
4999 | + break; | |
5000 | + default: | |
5001 | + salen = sizeof(struct sockaddr_in); | |
5002 | + break; | |
5003 | + } | |
5004 | +#endif | |
5005 | do { | |
5006 | - i = connect(sock, (struct sockaddr *) addr, sizeof(struct sockaddr_in)); | |
5007 | + i = connect(sock, addr, salen); | |
5008 | #if defined(WIN32) || defined(NETWARE) | |
5009 | if (i == SOCKET_ERROR) | |
5010 | errno = WSAGetLastError(); | |
5011 | #endif /* WIN32 */ | |
5012 | } while (i == -1 && errno == EINTR); | |
5013 | if (i == -1) { | |
5014 | + if (getnameinfo(addr, salen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf), | |
5015 | + niflags) != 0) { | |
5016 | + strcpy(hbuf, "?"); | |
5017 | + strcpy(pbuf, "?"); | |
5018 | + } | |
5019 | ap_log_rerror(APLOG_MARK, APLOG_ERR, r, | |
5020 | - "proxy connect to %s port %d failed", | |
5021 | - inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); | |
5022 | + "proxy connect to %s port %s failed", hbuf, pbuf); | |
5023 | } | |
5024 | ap_kill_timeout(r); | |
5025 | ||
5026 | diff -Nru apache_1.3.20/src/modules/standard/mod_access.c apache_1.3.20.new/src/modules/standard/mod_access.c | |
5027 | --- apache_1.3.20/src/modules/standard/mod_access.c Mon Jan 15 18:05:34 2001 | |
5028 | +++ apache_1.3.20.new/src/modules/standard/mod_access.c Mon May 21 10:54:52 2001 | |
5029 | @@ -74,7 +74,10 @@ | |
5030 | T_ALL, | |
5031 | T_IP, | |
5032 | T_HOST, | |
5033 | - T_FAIL | |
5034 | + T_FAIL, | |
5035 | +#ifdef INET6 | |
5036 | + T_IP6, | |
5037 | +#endif | |
5038 | }; | |
5039 | ||
5040 | typedef struct { | |
5041 | @@ -82,9 +85,15 @@ | |
5042 | union { | |
5043 | char *from; | |
5044 | struct { | |
5045 | - unsigned long net; | |
5046 | - unsigned long mask; | |
5047 | + struct in_addr net; | |
5048 | + struct in_addr mask; | |
5049 | } ip; | |
5050 | +#ifdef INET6 | |
5051 | + struct { | |
5052 | + struct in6_addr net6; | |
5053 | + struct in6_addr mask6; | |
5054 | + } ip6; | |
5055 | +#endif | |
5056 | } x; | |
5057 | enum allowdeny_type type; | |
5058 | } allowdeny; | |
5059 | @@ -167,90 +176,230 @@ | |
5060 | ||
5061 | } | |
5062 | else if ((s = strchr(where, '/'))) { | |
5063 | - unsigned long mask; | |
5064 | + struct addrinfo hints, *resnet, *resmask; | |
5065 | + struct sockaddr_storage net, mask; | |
5066 | + int error; | |
5067 | + char *p; | |
5068 | + int justdigits; | |
5069 | ||
5070 | - a->type = T_IP; | |
5071 | + a->type = T_FAIL; /*just in case*/ | |
5072 | /* trample on where, we won't be using it any more */ | |
5073 | *s++ = '\0'; | |
5074 | ||
5075 | - if (!is_ip(where) | |
5076 | - || (a->x.ip.net = ap_inet_addr(where)) == INADDR_NONE) { | |
5077 | + justdigits = 0; | |
5078 | + for (p = s; *p; p++) { | |
5079 | + if (!isdigit(*p)) | |
5080 | + break; | |
5081 | + } | |
5082 | + if (!*p) | |
5083 | + justdigits++; | |
5084 | + | |
5085 | + memset(&hints, 0, sizeof(hints)); | |
5086 | + hints.ai_family = PF_UNSPEC; | |
5087 | + hints.ai_socktype = SOCK_STREAM; /*dummy*/ | |
5088 | +#ifdef AI_NUMERICHOST | |
5089 | + hints.ai_flags = AI_NUMERICHOST; /*don't resolve*/ | |
5090 | +#endif | |
5091 | + resnet = NULL; | |
5092 | + error = getaddrinfo(where, NULL, &hints, &resnet); | |
5093 | + if (error || !resnet) { | |
5094 | + if (resnet) | |
5095 | + freeaddrinfo(resnet); | |
5096 | a->type = T_FAIL; | |
5097 | return "syntax error in network portion of network/netmask"; | |
5098 | } | |
5099 | + if (resnet->ai_next) { | |
5100 | + freeaddrinfo(resnet); | |
5101 | + a->type = T_FAIL; | |
5102 | + return "network/netmask resolved to multiple addresses"; | |
5103 | + } | |
5104 | + memcpy(&net, resnet->ai_addr, resnet->ai_addrlen); | |
5105 | + freeaddrinfo(resnet); | |
5106 | ||
5107 | - /* is_ip just tests if it matches [\d.]+ */ | |
5108 | - if (!is_ip(s)) { | |
5109 | + switch (net.ss_family) { | |
5110 | + case AF_INET: | |
5111 | + a->type = T_IP; | |
5112 | + a->x.ip.net.s_addr = ((struct sockaddr_in *)&net)->sin_addr.s_addr; | |
5113 | + break; | |
5114 | +#ifdef INET6 | |
5115 | + case AF_INET6: | |
5116 | + a->type = T_IP6; | |
5117 | + memcpy(&a->x.ip6.net6, &((struct sockaddr_in6 *)&net)->sin6_addr, | |
5118 | + sizeof(a->x.ip6.net6)); | |
5119 | + break; | |
5120 | +#endif | |
5121 | + default: | |
5122 | a->type = T_FAIL; | |
5123 | - return "syntax error in mask portion of network/netmask"; | |
5124 | + return "unknown address family for network"; | |
5125 | } | |
5126 | - /* is it in /a.b.c.d form? */ | |
5127 | - if (strchr(s, '.')) { | |
5128 | - mask = ap_inet_addr(s); | |
5129 | - if (mask == INADDR_NONE) { | |
5130 | + | |
5131 | + if (!justdigits) { | |
5132 | + memset(&hints, 0, sizeof(hints)); | |
5133 | + hints.ai_family = PF_UNSPEC; | |
5134 | + hints.ai_socktype = SOCK_STREAM; /*dummy*/ | |
5135 | +#ifdef AI_NUMERICHOST | |
5136 | + hints.ai_flags = AI_NUMERICHOST; /*don't resolve*/ | |
5137 | +#endif | |
5138 | + resmask = NULL; | |
5139 | + error = getaddrinfo(s, NULL, &hints, &resmask); | |
5140 | + if (error || !resmask) { | |
5141 | + if (resmask) | |
5142 | + freeaddrinfo(resmask); | |
5143 | a->type = T_FAIL; | |
5144 | return "syntax error in mask portion of network/netmask"; | |
5145 | } | |
5146 | - } | |
5147 | - else { | |
5148 | - /* assume it's in /nnn form */ | |
5149 | - mask = atoi(s); | |
5150 | - if (mask > 32 || mask <= 0) { | |
5151 | - a->type = T_FAIL; | |
5152 | - return "invalid mask in network/netmask"; | |
5153 | - } | |
5154 | - mask = 0xFFFFFFFFUL << (32 - mask); | |
5155 | - mask = htonl(mask); | |
5156 | - } | |
5157 | - a->x.ip.mask = mask; | |
5158 | - a->x.ip.net = (a->x.ip.net & mask); /* pjr - This fixes PR 4770 */ | |
5159 | - } | |
5160 | - else if (ap_isdigit(*where) && is_ip(where)) { | |
5161 | - /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */ | |
5162 | - int shift; | |
5163 | - char *t; | |
5164 | - int octet; | |
5165 | - | |
5166 | - a->type = T_IP; | |
5167 | - /* parse components */ | |
5168 | - s = where; | |
5169 | - a->x.ip.net = 0; | |
5170 | - a->x.ip.mask = 0; | |
5171 | - shift = 24; | |
5172 | - while (*s) { | |
5173 | - t = s; | |
5174 | - if (!ap_isdigit(*t)) { | |
5175 | + if (resmask->ai_next) { | |
5176 | + freeaddrinfo(resmask); | |
5177 | a->type = T_FAIL; | |
5178 | - return "invalid ip address"; | |
5179 | + return "network/netmask resolved to multiple addresses"; | |
5180 | } | |
5181 | - while (ap_isdigit(*t)) { | |
5182 | - ++t; | |
5183 | - } | |
5184 | - if (*t == '.') { | |
5185 | - *t++ = 0; | |
5186 | - } | |
5187 | - else if (*t) { | |
5188 | + memcpy(&mask, resmask->ai_addr, resmask->ai_addrlen); | |
5189 | + freeaddrinfo(resmask); | |
5190 | + | |
5191 | + if (net.ss_family != mask.ss_family) { | |
5192 | a->type = T_FAIL; | |
5193 | - return "invalid ip address"; | |
5194 | + return "network/netmask resolved to different address family"; | |
5195 | } | |
5196 | - if (shift < 0) { | |
5197 | - return "invalid ip address, only 4 octets allowed"; | |
5198 | + | |
5199 | + switch (a->type) { | |
5200 | + case T_IP: | |
5201 | + a->x.ip.mask.s_addr = | |
5202 | + ((struct sockaddr_in *)&mask)->sin_addr.s_addr; | |
5203 | + break; | |
5204 | +#ifdef INET6 | |
5205 | + case T_IP6: | |
5206 | + memcpy(&a->x.ip6.mask6, | |
5207 | + &((struct sockaddr_in6 *)&mask)->sin6_addr, | |
5208 | + sizeof(a->x.ip6.mask6)); | |
5209 | + break; | |
5210 | +#endif | |
5211 | } | |
5212 | - octet = atoi(s); | |
5213 | - if (octet < 0 || octet > 255) { | |
5214 | - a->type = T_FAIL; | |
5215 | - return "each octet must be between 0 and 255 inclusive"; | |
5216 | + } else { | |
5217 | + int mask; | |
5218 | + mask = atoi(s); | |
5219 | + switch (a->type) { | |
5220 | + case T_IP: | |
5221 | + if (mask < 0 || 32 < mask) { | |
5222 | + a->type = T_FAIL; | |
5223 | + return "netmask out of range"; | |
5224 | + } | |
5225 | + a->x.ip.mask.s_addr = htonl(0xFFFFFFFFUL << (32 - mask)); | |
5226 | + break; | |
5227 | +#ifdef INET6 | |
5228 | + case T_IP6: | |
5229 | + { | |
5230 | + int i; | |
5231 | + if (mask < 0 || 128 < mask) { | |
5232 | + a->type = T_FAIL; | |
5233 | + return "netmask out of range"; | |
5234 | + } | |
5235 | + for (i = 0; i < mask / 8; i++) { | |
5236 | + a->x.ip6.mask6.s6_addr[i] = 0xff; | |
5237 | + } | |
5238 | + if (mask % 8) | |
5239 | + a->x.ip6.mask6.s6_addr[i] = 0xff << (8 - (mask % 8)); | |
5240 | + break; | |
5241 | + } | |
5242 | +#endif | |
5243 | } | |
5244 | - a->x.ip.net |= octet << shift; | |
5245 | - a->x.ip.mask |= 0xFFUL << shift; | |
5246 | - s = t; | |
5247 | - shift -= 8; | |
5248 | } | |
5249 | - a->x.ip.net = ntohl(a->x.ip.net); | |
5250 | - a->x.ip.mask = ntohl(a->x.ip.mask); | |
5251 | } | |
5252 | else { | |
5253 | - a->type = T_HOST; | |
5254 | + struct addrinfo hints, *res; | |
5255 | + struct sockaddr_storage ss; | |
5256 | + int error; | |
5257 | + | |
5258 | + a->type = T_FAIL; /*just in case*/ | |
5259 | + | |
5260 | + /* First, try using the old apache code to match */ | |
5261 | + /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */ | |
5262 | + if (ap_isdigit(*where) && is_ip(where)) { | |
5263 | + int shift; | |
5264 | + char *t; | |
5265 | + int octet; | |
5266 | + | |
5267 | + a->type = T_IP; | |
5268 | + /* parse components */ | |
5269 | + s = where; | |
5270 | + a->x.ip.net.s_addr = 0; | |
5271 | + a->x.ip.mask.s_addr = 0; | |
5272 | + shift = 24; | |
5273 | + while (*s) { | |
5274 | + t = s; | |
5275 | + if (!ap_isdigit(*t)) { | |
5276 | + a->type = T_FAIL; | |
5277 | + return "invalid ip address"; | |
5278 | + } | |
5279 | + while (ap_isdigit(*t)) { | |
5280 | + ++t; | |
5281 | + } | |
5282 | + if (*t == '.') { | |
5283 | + *t++ = 0; | |
5284 | + } | |
5285 | + else if (*t) { | |
5286 | + a->type = T_FAIL; | |
5287 | + return "invalid ip address"; | |
5288 | + } | |
5289 | + if (shift < 0) { | |
5290 | + return "invalid ip address, only 4 octets allowed"; | |
5291 | + } | |
5292 | + octet = atoi(s); | |
5293 | + if (octet < 0 || octet > 255) { | |
5294 | + a->type = T_FAIL; | |
5295 | + return "each octet must be between 0 and 255 inclusive"; | |
5296 | + } | |
5297 | + a->x.ip.net.s_addr |= octet << shift; | |
5298 | + a->x.ip.mask.s_addr |= 0xFFUL << shift; | |
5299 | + s = t; | |
5300 | + shift -= 8; | |
5301 | + } | |
5302 | + a->x.ip.net.s_addr = ntohl(a->x.ip.net.s_addr); | |
5303 | + a->x.ip.mask.s_addr = ntohl(a->x.ip.mask.s_addr); | |
5304 | + | |
5305 | + return NULL; | |
5306 | + } | |
5307 | + | |
5308 | + /* IPv4/v6 numeric address */ | |
5309 | + memset(&hints, 0, sizeof(hints)); | |
5310 | + hints.ai_family = PF_UNSPEC; | |
5311 | + hints.ai_socktype = SOCK_STREAM; /*dummy*/ | |
5312 | +#ifdef AI_NUMERICHOST | |
5313 | + hints.ai_flags = AI_NUMERICHOST; /*don't resolve*/ | |
5314 | +#endif | |
5315 | + res = NULL; | |
5316 | + error = getaddrinfo(where, NULL, &hints, &res); | |
5317 | + if (error || !res) { | |
5318 | + if (res) | |
5319 | + freeaddrinfo(res); | |
5320 | + a->type = T_HOST; | |
5321 | + return NULL; | |
5322 | + } | |
5323 | + if (res->ai_next) { | |
5324 | + freeaddrinfo(res); | |
5325 | + a->type = T_FAIL; | |
5326 | + return "network/netmask resolved to multiple addresses"; | |
5327 | + } | |
5328 | + memcpy(&ss, res->ai_addr, res->ai_addrlen); | |
5329 | + freeaddrinfo(res); | |
5330 | + | |
5331 | + switch (ss.ss_family) { | |
5332 | + case AF_INET: | |
5333 | + a->type = T_IP; | |
5334 | + a->x.ip.net.s_addr = ((struct sockaddr_in *)&ss)->sin_addr.s_addr; | |
5335 | + memset(&a->x.ip.mask, 0xff, sizeof(a->x.ip.mask)); | |
5336 | + break; | |
5337 | +#ifdef INET6 | |
5338 | + case AF_INET6: | |
5339 | + a->type = T_IP6; | |
5340 | + memcpy(&a->x.ip6.net6, &((struct sockaddr_in6 *)&ss)->sin6_addr, | |
5341 | + sizeof(a->x.ip6.net6)); | |
5342 | + memset(&a->x.ip6.mask6, 0xff, sizeof(a->x.ip6.mask6)); | |
5343 | + break; | |
5344 | +#endif | |
5345 | + default: | |
5346 | + a->type = T_FAIL; | |
5347 | + return "unknown address family for network"; | |
5348 | + } | |
5349 | } | |
5350 | ||
5351 | return NULL; | |
5352 | @@ -315,12 +464,63 @@ | |
5353 | return 1; | |
5354 | ||
5355 | case T_IP: | |
5356 | - if (ap[i].x.ip.net != INADDR_NONE | |
5357 | - && (r->connection->remote_addr.sin_addr.s_addr | |
5358 | - & ap[i].x.ip.mask) == ap[i].x.ip.net) { | |
5359 | - return 1; | |
5360 | + if (ap[i].x.ip.net.s_addr == INADDR_NONE) | |
5361 | + break; | |
5362 | + switch (r->connection->remote_addr.ss_family) { | |
5363 | + case AF_INET: | |
5364 | + if ((((struct sockaddr_in *)&r->connection->remote_addr)->sin_addr.s_addr | |
5365 | + & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) { | |
5366 | + return 1; | |
5367 | + } | |
5368 | + break; | |
5369 | +#ifdef INET6 | |
5370 | + case AF_INET6: | |
5371 | + if (!IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr)) /*XXX*/ | |
5372 | + break; | |
5373 | + if ((*(ap_uint32_t *)&((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr.s6_addr[12] | |
5374 | + & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) { | |
5375 | + return 1; | |
5376 | + } | |
5377 | + break; | |
5378 | +#endif | |
5379 | + } | |
5380 | + break; | |
5381 | + | |
5382 | +#ifdef INET6 | |
5383 | + case T_IP6: | |
5384 | + { | |
5385 | + struct in6_addr masked; | |
5386 | + int j; | |
5387 | + if (IN6_IS_ADDR_UNSPECIFIED(&ap[i].x.ip6.net6)) | |
5388 | + break; | |
5389 | + switch (r->connection->remote_addr.ss_family) { | |
5390 | + case AF_INET: | |
5391 | + if (!IN6_IS_ADDR_V4MAPPED(&ap[i].x.ip6.net6)) /*XXX*/ | |
5392 | + break; | |
5393 | + memset(&masked, 0, sizeof(masked)); | |
5394 | + masked.s6_addr[10] = masked.s6_addr[11] = 0xff; | |
5395 | + memcpy(&masked.s6_addr[12], | |
5396 | + &((struct sockaddr_in *)&r->connection->remote_addr)->sin_addr.s_addr, | |
5397 | + sizeof(struct sockaddr_in)); | |
5398 | + for (j = 0; j < sizeof(struct in6_addr); j++) | |
5399 | + masked.s6_addr[j] &= ap[i].x.ip6.mask6.s6_addr[j]; | |
5400 | + if (memcmp(&masked, &ap[i].x.ip6.net6, sizeof(masked)) == 0) | |
5401 | + return 1; | |
5402 | + break; | |
5403 | + case AF_INET6: | |
5404 | + memset(&masked, 0, sizeof(masked)); | |
5405 | + memcpy(&masked, | |
5406 | + &((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr, | |
5407 | + sizeof(masked)); | |
5408 | + for (j = 0; j < sizeof(struct in6_addr); j++) | |
5409 | + masked.s6_addr[j] &= ap[i].x.ip6.mask6.s6_addr[j]; | |
5410 | + if (memcmp(&masked, &ap[i].x.ip6.net6, sizeof(masked)) == 0) | |
5411 | + return 1; | |
5412 | + break; | |
5413 | } | |
5414 | break; | |
5415 | + } | |
5416 | +#endif | |
5417 | ||
5418 | case T_HOST: | |
5419 | if (!gothost) { | |
5420 | diff -Nru apache_1.3.20/src/modules/standard/mod_unique_id.c apache_1.3.20.new/src/modules/standard/mod_unique_id.c | |
5421 | --- apache_1.3.20/src/modules/standard/mod_unique_id.c Mon Jan 15 18:05:51 2001 | |
5422 | +++ apache_1.3.20.new/src/modules/standard/mod_unique_id.c Mon May 21 10:54:52 2001 | |
5423 | @@ -67,14 +67,26 @@ | |
5424 | #include "http_config.h" | |
5425 | #include "http_log.h" | |
5426 | #include "multithread.h" | |
5427 | +#include "sa_len.h" | |
5428 | ||
5429 | #ifdef MULTITHREAD | |
5430 | #error sorry this module does not support multithreaded servers yet | |
5431 | #endif | |
5432 | ||
5433 | +/*#define SHORT_UNIQUE_ID*/ | |
5434 | + | |
5435 | typedef struct { | |
5436 | unsigned int stamp; | |
5437 | - unsigned int in_addr; | |
5438 | + union { | |
5439 | + struct in_addr in; | |
5440 | +#ifdef INET6 | |
5441 | +# ifdef SHORT_UNIQUE_ID | |
5442 | + ap_uint32_t in6; | |
5443 | +# else | |
5444 | + struct in6_addr in6; | |
5445 | +# endif | |
5446 | +#endif | |
5447 | + } addr; | |
5448 | unsigned int pid; | |
5449 | unsigned short counter; | |
5450 | } unique_id_rec; | |
5451 | @@ -144,7 +156,7 @@ | |
5452 | * this shouldn't be a problem till year 2106. | |
5453 | */ | |
5454 | ||
5455 | -static unsigned global_in_addr; | |
5456 | +static struct sockaddr_storage global_addr; | |
5457 | ||
5458 | static APACHE_TLS unique_id_rec cur_unique_id; | |
5459 | ||
5460 | @@ -164,7 +176,8 @@ | |
5461 | #define MAXHOSTNAMELEN 256 | |
5462 | #endif | |
5463 | char str[MAXHOSTNAMELEN + 1]; | |
5464 | - struct hostent *hent; | |
5465 | + struct addrinfo hints, *res, *res0; | |
5466 | + int error; | |
5467 | #ifndef NO_GETTIMEOFDAY | |
5468 | struct timeval tv; | |
5469 | #endif | |
5470 | @@ -174,8 +187,8 @@ | |
5471 | */ | |
5472 | unique_id_rec_offset[0] = XtOffsetOf(unique_id_rec, stamp); | |
5473 | unique_id_rec_size[0] = sizeof(cur_unique_id.stamp); | |
5474 | - unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, in_addr); | |
5475 | - unique_id_rec_size[1] = sizeof(cur_unique_id.in_addr); | |
5476 | + unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, addr); | |
5477 | + unique_id_rec_size[1] = sizeof(cur_unique_id.addr); | |
5478 | unique_id_rec_offset[2] = XtOffsetOf(unique_id_rec, pid); | |
5479 | unique_id_rec_size[2] = sizeof(cur_unique_id.pid); | |
5480 | unique_id_rec_offset[3] = XtOffsetOf(unique_id_rec, counter); | |
5481 | @@ -201,17 +214,44 @@ | |
5482 | } | |
5483 | str[sizeof(str) - 1] = '\0'; | |
5484 | ||
5485 | - if ((hent = gethostbyname(str)) == NULL) { | |
5486 | + memset(&hints, 0, sizeof(hints)); | |
5487 | + hints.ai_family = PF_UNSPEC; | |
5488 | + error = getaddrinfo(str, NULL, &hints, &res0); | |
5489 | + if (error) { | |
5490 | ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s, | |
5491 | - "mod_unique_id: unable to gethostbyname(\"%s\")", str); | |
5492 | + "mod_unique_id: getaddrinfo failed for \"%s\" (%s)", str, | |
5493 | + gai_strerror(error)); | |
5494 | exit(1); | |
5495 | } | |
5496 | ||
5497 | - global_in_addr = ((struct in_addr *) hent->h_addr_list[0])->s_addr; | |
5498 | + error = 1; | |
5499 | + for (res = res0; res; res = res->ai_next) { | |
5500 | + switch (res->ai_family) { | |
5501 | + case AF_INET: | |
5502 | +#ifdef INET6 | |
5503 | + case AF_INET6: | |
5504 | +#endif | |
5505 | + memcpy(&global_addr, res->ai_addr, res->ai_addrlen); | |
5506 | + error = 0; | |
5507 | + break; | |
5508 | + } | |
5509 | + } | |
5510 | + freeaddrinfo(res0); | |
5511 | + if (error) { | |
5512 | + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s, | |
5513 | + "mod_unique_id: no known AF found for \"%s\"", str); | |
5514 | + exit(1); | |
5515 | + } | |
5516 | ||
5517 | + getnameinfo((struct sockaddr *)&global_addr, | |
5518 | +#ifndef SIN6_LEN | |
5519 | + SA_LEN((struct sockaddr *)&global_addr), | |
5520 | +#else | |
5521 | + global_addr.ss_len, | |
5522 | +#endif | |
5523 | + str, sizeof(str), NULL, 0, NI_NUMERICHOST); | |
5524 | ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, s, | |
5525 | - "mod_unique_id: using ip addr %s", | |
5526 | - inet_ntoa(*(struct in_addr *) hent->h_addr_list[0])); | |
5527 | + "mod_unique_id: using ip addr %s", str); | |
5528 | ||
5529 | /* | |
5530 | * If the server is pummelled with restart requests we could possibly end | |
5531 | @@ -270,7 +310,23 @@ | |
5532 | "oh no! pids are greater than 32-bits! I'm broken!"); | |
5533 | } | |
5534 | ||
5535 | - cur_unique_id.in_addr = global_in_addr; | |
5536 | + memset(&cur_unique_id.addr, 0, sizeof(cur_unique_id.addr)); | |
5537 | + switch (global_addr.ss_family) { | |
5538 | + case AF_INET: | |
5539 | + cur_unique_id.addr.in = ((struct sockaddr_in *)&global_addr)->sin_addr; | |
5540 | + break; | |
5541 | +#ifdef INET6 | |
5542 | + case AF_INET6: | |
5543 | +#ifdef SHORT_UNIQUE_ID | |
5544 | + cur_unique_id.addr.in6 = | |
5545 | + ((struct sockaddr_in6 *)&global_addr)->sin6_addr.s6_addr32[3]; | |
5546 | +#else | |
5547 | + cur_unique_id.addr.in6 = | |
5548 | + ((struct sockaddr_in6 *)&global_addr)->sin6_addr; | |
5549 | +#endif | |
5550 | + break; | |
5551 | +#endif | |
5552 | + } | |
5553 | ||
5554 | /* | |
5555 | * If we use 0 as the initial counter we have a little less protection | |
5556 | diff -Nru apache_1.3.20/src/support/ab.c apache_1.3.20.new/src/support/ab.c | |
5557 | --- apache_1.3.20/src/support/ab.c Fri Mar 9 11:10:55 2001 | |
5558 | +++ apache_1.3.20.new/src/support/ab.c Mon May 21 10:54:52 2001 | |
5559 | @@ -140,6 +140,8 @@ | |
5560 | #include <sys/uio.h> | |
5561 | #endif | |
5562 | ||
5563 | +#include "sa_len.h" | |
5564 | + | |
5565 | #endif /* NO_APACHE_INCLUDES */ | |
5566 | /* ------------------- DEFINITIONS -------------------------- */ | |
5567 | ||
5568 | @@ -195,7 +197,7 @@ | |
5569 | auth[1024], /* optional (basic/uuencoded) | |
5570 | * authentification */ | |
5571 | hdrs[4096]; /* optional arbitrary headers */ | |
5572 | -int port = 80; /* port number */ | |
5573 | +char *port = "80"; /* port number */ | |
5574 | ||
5575 | int use_html = 0; /* use html in the report */ | |
5576 | char *tablestring; | |
5577 | @@ -227,7 +229,7 @@ | |
5578 | struct data *stats; /* date for each request */ | |
5579 | ||
5580 | fd_set readbits, writebits; /* bits for select */ | |
5581 | -struct sockaddr_in server; /* server addr structure */ | |
5582 | +struct sockaddr_storage server; /* server addr structure */ | |
5583 | ||
5584 | #ifndef BEOS | |
5585 | #define ab_close(s) close(s) | |
5586 | @@ -332,7 +334,7 @@ | |
5587 | printf("\r \r"); | |
5588 | printf("Server Software: %s\n", servername); | |
5589 | printf("Server Hostname: %s\n", hostname); | |
5590 | - printf("Server Port: %d\n", port); | |
5591 | + printf("Server Port: %s\n", port); | |
5592 | printf("\n"); | |
5593 | printf("Document Path: %s\n", path); | |
5594 | printf("Document Length: %d bytes\n", doclen); | |
5595 | @@ -531,14 +533,19 @@ | |
5596 | c->cbx = 0; | |
5597 | c->gotheader = 0; | |
5598 | ||
5599 | - c->fd = socket(AF_INET, SOCK_STREAM, 0); | |
5600 | + c->fd = socket(server.ss_family, SOCK_STREAM, 0); | |
5601 | if (c->fd < 0) | |
5602 | err("socket"); | |
5603 | ||
5604 | nonblock(c->fd); | |
5605 | gettimeofday(&c->start, 0); | |
5606 | ||
5607 | - if (connect(c->fd, (struct sockaddr *) & server, sizeof(server)) < 0) { | |
5608 | +#ifndef SIN6_LEN | |
5609 | + if (connect(c->fd, (struct sockaddr *) & server, SA_LEN((struct sockaddr*)&server)) < 0) | |
5610 | +#else | |
5611 | + if (connect(c->fd, (struct sockaddr *) &server, server.ss_len) < 0) | |
5612 | +#endif | |
5613 | + { | |
5614 | if (errno == EINPROGRESS) { | |
5615 | c->state = STATE_CONNECTING; | |
5616 | FD_SET(c->fd, &writebits); | |
5617 | @@ -772,14 +779,17 @@ | |
5618 | } | |
5619 | ||
5620 | { | |
5621 | - /* get server information */ | |
5622 | - struct hostent *he; | |
5623 | - he = gethostbyname(hostname); | |
5624 | - if (!he) | |
5625 | - err("bad hostname"); | |
5626 | - server.sin_family = he->h_addrtype; | |
5627 | - server.sin_port = htons(port); | |
5628 | - server.sin_addr.s_addr = ((unsigned long *) (he->h_addr_list[0]))[0]; | |
5629 | + /* get server information */ | |
5630 | + struct addrinfo hints, *res; | |
5631 | + int error; | |
5632 | + | |
5633 | + memset(&hints, 0, sizeof(hints)); | |
5634 | + hints.ai_family = PF_UNSPEC; | |
5635 | + error = getaddrinfo(hostname, port, &hints, &res); | |
5636 | + if (error) | |
5637 | + err("bad hostname"); | |
5638 | + memcpy(&server, res->ai_addr, res->ai_addrlen); | |
5639 | + freeaddrinfo(res); | |
5640 | } | |
5641 | ||
5642 | con = malloc(concurrency * sizeof(struct connection)); | |
5643 | @@ -954,7 +964,7 @@ | |
5644 | *cp = '\0'; | |
5645 | strcpy(hostname, h); | |
5646 | if (p != NULL) | |
5647 | - port = atoi(p); | |
5648 | + port = strdup(p); | |
5649 | return 0; | |
5650 | } | |
5651 | ||
5652 | @@ -1131,3 +1141,7 @@ | |
5653 | ||
5654 | exit(0); | |
5655 | } | |
5656 | + | |
5657 | +#ifdef NEED_GETADDRINFO | |
5658 | +#include "../main/getaddrinfo.c" | |
5659 | +#endif | |
5660 | diff -Nru apache_1.3.20/src/support/logresolve.c apache_1.3.20.new/src/support/logresolve.c | |
5661 | --- apache_1.3.20/src/support/logresolve.c Mon Apr 2 11:22:11 2001 | |
5662 | +++ apache_1.3.20.new/src/support/logresolve.c Mon May 21 10:54:52 2001 | |
5663 | @@ -54,7 +54,9 @@ | |
5664 | #endif /* BEOS */ | |
5665 | #endif /* !MPE && !WIN32*/ | |
5666 | ||
5667 | -static void cgethost(struct in_addr ipnum, char *string, int check); | |
5668 | +#include "sa_len.h" | |
5669 | + | |
5670 | +static void cgethost(struct sockaddr *sa, char *string, int check); | |
5671 | static int getline(char *s, int n); | |
5672 | static void stats(FILE *output); | |
5673 | ||
5674 | @@ -91,7 +93,7 @@ | |
5675 | */ | |
5676 | ||
5677 | struct nsrec { | |
5678 | - struct in_addr ipnum; | |
5679 | + struct sockaddr_storage addr; | |
5680 | char *hostname; | |
5681 | int noname; | |
5682 | struct nsrec *next; | |
5683 | @@ -122,17 +124,48 @@ | |
5684 | * IP numbers with their IP number as hostname, setting noname flag | |
5685 | */ | |
5686 | ||
5687 | -static void cgethost (struct in_addr ipnum, char *string, int check) | |
5688 | +static void cgethost (struct sockaddr *sa, char *string, int check) | |
5689 | { | |
5690 | + ap_uint32_t hashval; | |
5691 | + struct sockaddr_in *sin; | |
5692 | +#ifdef INET6 | |
5693 | + struct sockaddr_in6 *sin6; | |
5694 | +#endif | |
5695 | struct nsrec **current, *new; | |
5696 | - struct hostent *hostdata; | |
5697 | char *name; | |
5698 | + char hostnamebuf[MAXHOSTNAMELEN]; | |
5699 | + | |
5700 | + switch (sa->sa_family) { | |
5701 | + case AF_INET: | |
5702 | + hashval = ((struct sockaddr_in *)sa)->sin_addr.s_addr; | |
5703 | + break; | |
5704 | +#ifdef INET6 | |
5705 | + case AF_INET6: | |
5706 | + hashval = *(ap_uint32_t *)&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12]; | |
5707 | + break; | |
5708 | +#endif | |
5709 | + default: | |
5710 | + hashval = 0; | |
5711 | + break; | |
5712 | + } | |
5713 | + | |
5714 | + current = &nscache[((hashval + (hashval >> 8) + | |
5715 | + (hashval >> 16) + (hashval >> 24)) % BUCKETS)]; | |
5716 | ||
5717 | - current = &nscache[((ipnum.s_addr + (ipnum.s_addr >> 8) + | |
5718 | - (ipnum.s_addr >> 16) + (ipnum.s_addr >> 24)) % BUCKETS)]; | |
5719 | + while (*current) { | |
5720 | +#ifndef SIN6_LEN | |
5721 | + if (SA_LEN(sa) == SA_LEN((struct sockaddr *)&(*current)->addr) | |
5722 | + && memcmp(sa, &(*current)->addr, SA_LEN(sa)) == 0) | |
5723 | +#else | |
5724 | + if (sa->sa_len == (*current)->addr.ss_len | |
5725 | + && memcmp(sa, &(*current)->addr, sa->sa_len) == 0) | |
5726 | +#endif | |
5727 | + { | |
5728 | + break; | |
5729 | + } | |
5730 | ||
5731 | - while (*current != NULL && ipnum.s_addr != (*current)->ipnum.s_addr) | |
5732 | current = &(*current)->next; | |
5733 | + } | |
5734 | ||
5735 | if (*current == NULL) { | |
5736 | cachesize++; | |
5737 | @@ -145,45 +178,55 @@ | |
5738 | *current = new; | |
5739 | new->next = NULL; | |
5740 | ||
5741 | - new->ipnum = ipnum; | |
5742 | +#ifndef SIN6_LEN | |
5743 | + memcpy(&new->addr, sa, SA_LEN(sa)); | |
5744 | +#else | |
5745 | + memcpy(&new->addr, sa, sa->sa_len); | |
5746 | +#endif | |
5747 | ||
5748 | - hostdata = gethostbyaddr((const char *) &ipnum, sizeof(struct in_addr), | |
5749 | - AF_INET); | |
5750 | - if (hostdata == NULL) { | |
5751 | - if (h_errno > MAX_ERR) | |
5752 | - errors[UNKNOWN_ERR]++; | |
5753 | - else | |
5754 | - errors[h_errno]++; | |
5755 | - new->noname = h_errno; | |
5756 | - name = strdup(inet_ntoa(ipnum)); | |
5757 | - } | |
5758 | - else { | |
5759 | - new->noname = 0; | |
5760 | - name = strdup(hostdata->h_name); | |
5761 | - if (check) { | |
5762 | - if (name == NULL) { | |
5763 | - perror("strdup"); | |
5764 | - fprintf(stderr, "Insufficient memory\n"); | |
5765 | - exit(1); | |
5766 | - } | |
5767 | - hostdata = gethostbyname(name); | |
5768 | - if (hostdata != NULL) { | |
5769 | - char **hptr; | |
5770 | - | |
5771 | - for (hptr = hostdata->h_addr_list; *hptr != NULL; hptr++) | |
5772 | - if (((struct in_addr *) (*hptr))->s_addr == ipnum.s_addr) | |
5773 | - break; | |
5774 | - if (*hptr == NULL) | |
5775 | - hostdata = NULL; | |
5776 | - } | |
5777 | - if (hostdata == NULL) { | |
5778 | - fprintf(stderr, "Bad host: %s != %s\n", name, | |
5779 | - inet_ntoa(ipnum)); | |
5780 | - new->noname = NO_REVERSE; | |
5781 | - free(name); | |
5782 | - name = strdup(inet_ntoa(ipnum)); | |
5783 | - errors[NO_REVERSE]++; | |
5784 | + new->noname = getnameinfo(sa, | |
5785 | +#ifndef SIN6_LEN | |
5786 | + SA_LEN(sa), | |
5787 | +#else | |
5788 | + sa->sa_len, | |
5789 | +#endif | |
5790 | + hostnamebuf, sizeof(hostnamebuf), NULL, 0, 0); | |
5791 | + name = strdup(hostnamebuf); | |
5792 | + if (check) { | |
5793 | + struct addrinfo hints, *res; | |
5794 | + int error; | |
5795 | + memset(&hints, 0, sizeof(hints)); | |
5796 | + hints.ai_family = PF_UNSPEC; | |
5797 | + error = getaddrinfo(hostnamebuf, NULL, &hints, &res); | |
5798 | + if (!error) { | |
5799 | + while (res) { | |
5800 | +#ifndef SIN6_LEN | |
5801 | + if (SA_LEN(sa) == res->ai_addrlen | |
5802 | + && memcmp(sa, res->ai_addr, SA_LEN(sa)) == 0) | |
5803 | +#else | |
5804 | + if (sa->sa_len == res->ai_addrlen | |
5805 | + && memcmp(sa, res->ai_addr, sa->sa_len) == 0) | |
5806 | +#endif | |
5807 | + { | |
5808 | + break; | |
5809 | + } | |
5810 | + res = res->ai_next; | |
5811 | } | |
5812 | + if (!res) | |
5813 | + error++; | |
5814 | + } | |
5815 | + if (error) { | |
5816 | + getnameinfo(sa, | |
5817 | +#ifndef SIN6_LEN | |
5818 | + SA_LEN(sa), | |
5819 | +#else | |
5820 | + sa->sa_len, | |
5821 | +#endif | |
5822 | + hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST); | |
5823 | + fprintf(stderr, "Bad host: %s != %s\n", name, hostnamebuf); | |
5824 | + new->noname = NO_REVERSE; | |
5825 | + free(name); | |
5826 | + name = strdup(hostnamebuf); | |
5827 | } | |
5828 | } | |
5829 | new->hostname = name; | |
5830 | @@ -211,6 +254,7 @@ | |
5831 | char *ipstring; | |
5832 | struct nsrec *current; | |
5833 | char *errstring[MAX_ERR + 3]; | |
5834 | + char hostnamebuf[MAXHOSTNAMELEN]; | |
5835 | ||
5836 | for (i = 0; i < MAX_ERR + 3; i++) | |
5837 | errstring[i] = "Unknown error"; | |
5838 | @@ -242,7 +286,14 @@ | |
5839 | ||
5840 | for (i = 0; i < BUCKETS; i++) | |
5841 | for (current = nscache[i]; current != NULL; current = current->next) { | |
5842 | - ipstring = inet_ntoa(current->ipnum); | |
5843 | + getnameinfo((struct sockaddr *)¤t->addr, | |
5844 | +#ifndef SIN6_LEN | |
5845 | + SA_LEN((struct sockaddr *)¤t->addr), | |
5846 | +#else | |
5847 | + current->addr.ss_len, | |
5848 | +#endif | |
5849 | + hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST); | |
5850 | + ipstring = hostnamebuf; | |
5851 | if (current->noname == 0) | |
5852 | fprintf(output, " %3d %15s - %s\n", i, ipstring, | |
5853 | current->hostname); | |
5854 | @@ -276,9 +327,10 @@ | |
5855 | ||
5856 | int main (int argc, char *argv[]) | |
5857 | { | |
5858 | - struct in_addr ipnum; | |
5859 | char *bar, hoststring[MAXDNAME + 1], line[MAXLINE], *statfile; | |
5860 | int i, check; | |
5861 | + struct addrinfo hints, *res; | |
5862 | + int error; | |
5863 | ||
5864 | #ifdef WIN32 | |
5865 | WSADATA wsaData; | |
5866 | @@ -322,8 +374,10 @@ | |
5867 | bar = strchr(line, ' '); | |
5868 | if (bar != NULL) | |
5869 | *bar = '\0'; | |
5870 | - ipnum.s_addr = inet_addr(line); | |
5871 | - if (ipnum.s_addr == 0xffffffffu) { | |
5872 | + memset(&hints, 0, sizeof(hints)); | |
5873 | + hints.ai_family = PF_UNSPEC; | |
5874 | + error = getaddrinfo(line, NULL, &hints, &res); | |
5875 | + if (error) { | |
5876 | if (bar != NULL) | |
5877 | *bar = ' '; | |
5878 | puts(line); | |
5879 | @@ -333,11 +387,12 @@ | |
5880 | ||
5881 | resolves++; | |
5882 | ||
5883 | - cgethost(ipnum, hoststring, check); | |
5884 | + cgethost(res->ai_addr, hoststring, check); | |
5885 | if (bar != NULL) | |
5886 | printf("%s %s\n", hoststring, bar + 1); | |
5887 | else | |
5888 | puts(hoststring); | |
5889 | + freeaddrinfo(res); | |
5890 | } | |
5891 | ||
5892 | #ifdef WIN32 | |
5893 | @@ -358,3 +413,11 @@ | |
5894 | ||
5895 | return (0); | |
5896 | } | |
5897 | + | |
5898 | +#ifdef NEED_GETADDRINFO | |
5899 | +#include "../main/getaddrinfo.c" | |
5900 | +#endif | |
5901 | + | |
5902 | +#ifdef NEED_GETNAMEINFO | |
5903 | +#include "../main/getnameinfo.c" | |
5904 | +#endif |