summaryrefslogtreecommitdiff
path: root/usr.sbin/httpd
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/httpd')
-rw-r--r--usr.sbin/httpd/Makefile.bsd-wrapper14
-rw-r--r--usr.sbin/httpd/README.v6127
-rw-r--r--usr.sbin/httpd/conf/httpd.conf-dist9
-rw-r--r--usr.sbin/httpd/htdocs/manual/index.html5
-rw-r--r--usr.sbin/httpd/htdocs/manual/ipv6.html228
-rw-r--r--usr.sbin/httpd/htdocs/manual/misc/rewriteguide.html2
-rw-r--r--usr.sbin/httpd/htdocs/manual/mod/core.html3
-rw-r--r--usr.sbin/httpd/httpd.812
-rw-r--r--usr.sbin/httpd/src/Configuration.tmpl4
-rw-r--r--usr.sbin/httpd/src/Configure61
-rw-r--r--usr.sbin/httpd/src/include/ap.h7
-rw-r--r--usr.sbin/httpd/src/include/ap_config.h15
-rw-r--r--usr.sbin/httpd/src/include/ap_config_auto.h20
-rw-r--r--usr.sbin/httpd/src/include/http_conf_globals.h5
-rw-r--r--usr.sbin/httpd/src/include/http_vhost.h4
-rw-r--r--usr.sbin/httpd/src/include/httpd.h33
-rw-r--r--usr.sbin/httpd/src/main/http_config.c33
-rw-r--r--usr.sbin/httpd/src/main/http_core.c229
-rw-r--r--usr.sbin/httpd/src/main/http_main.c133
-rw-r--r--usr.sbin/httpd/src/main/http_vhost.c422
-rw-r--r--usr.sbin/httpd/src/main/rfc1413.c68
-rw-r--r--usr.sbin/httpd/src/main/util.c126
-rw-r--r--usr.sbin/httpd/src/main/util_script.c13
-rw-r--r--usr.sbin/httpd/src/main/util_uri.c72
-rw-r--r--usr.sbin/httpd/src/modules/proxy/mod_proxy.c28
-rw-r--r--usr.sbin/httpd/src/modules/proxy/mod_proxy.h2
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_connect.c138
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_ftp.c185
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_http.c229
-rw-r--r--usr.sbin/httpd/src/modules/proxy/proxy_util.c96
-rw-r--r--usr.sbin/httpd/src/modules/ssl/Makefile.tmpl12
-rw-r--r--usr.sbin/httpd/src/modules/ssl/ssl_engine_ext.c4
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_access.c321
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_unique_id.c70
-rw-r--r--usr.sbin/httpd/src/modules/standard/mod_usertrack.c10
-rw-r--r--usr.sbin/httpd/src/support/logresolve.c149
36 files changed, 2163 insertions, 726 deletions
diff --git a/usr.sbin/httpd/Makefile.bsd-wrapper b/usr.sbin/httpd/Makefile.bsd-wrapper
index e8e9de2bb8f..585383dc2d3 100644
--- a/usr.sbin/httpd/Makefile.bsd-wrapper
+++ b/usr.sbin/httpd/Makefile.bsd-wrapper
@@ -1,5 +1,5 @@
# Build wrapper for Apache
-# $OpenBSD: Makefile.bsd-wrapper,v 1.64 2008/01/08 10:08:31 henning Exp $
+# $OpenBSD: Makefile.bsd-wrapper,v 1.65 2008/05/09 08:06:27 mbalmer Exp $
# Our lndir is hacked; specify a full path to avoid potential conflicts
# with the one installed with X11.
@@ -93,7 +93,8 @@ DSO_MODULE_ARGS= \
--enable-module=usertrack \
--enable-shared=usertrack \
--enable-module=vhost_alias \
- --enable-shared=vhost_alias
+ --enable-shared=vhost_alias \
+ --enable-rule=INET6
INSTALL_MODULES=
@@ -252,6 +253,7 @@ MANUALFILES= \
manual/handler.html \
manual/index.html \
manual/invoking.html \
+ manual/ipv6.html \
manual/keepalive.html \
manual/location.html \
manual/logs.html \
@@ -739,6 +741,14 @@ cleanman:
@echo NOMAN is set
.endif
+man:
+ @-for i in ${MANUALFILES}; do \
+ j=`dirname $$i`; \
+ echo "Installing ${DESTDIR}${HTTPD_HTDOCSDIR}/$$i"; \
+ ${INSTALL} ${INSTALL_COPY} -g ${BINGRP} -m 444 \
+ htdocs/$$i ${DESTDIR}${HTTPD_HTDOCSDIR}/$$j/; \
+ done
+
distribution:
@-for i in ${MODCONFDIR}; do \
echo "Installing ${DESTDIR}${HTTPD_SYSCONFDIR}/$$i"; \
diff --git a/usr.sbin/httpd/README.v6 b/usr.sbin/httpd/README.v6
new file mode 100644
index 00000000000..5160c617bb1
--- /dev/null
+++ b/usr.sbin/httpd/README.v6
@@ -0,0 +1,127 @@
+$OpenBSD: README.v6,v 1.1 2008/05/09 08:06:27 mbalmer Exp $
+$Id: README.v6,v 1.1 2008/05/09 08:06:27 mbalmer Exp $
+
+IPv6 support for the OpenBSD httpd(8)
+
+To support IPv6 the apache module API/ABI had to be changed, to avoid
+IPv4-dependent structure member variables (like use of u_long to hold
+an IPv4 address, or whatever). Keep this in mind when writing new
+modules or adding modules to the ports collection.
+
+Basically you can write IPv6 address where IPv4 address fits.
+
+extra command-line argument:
+ -4 Assume IPv4 address on ambiguous directives (default)
+ -6 Assume IPv6 address on ambiguous directives
+
+ The above two can be used, for example, to disambiguate
+ "BindAddress *".
+
+base commands:
+ Listen
+ Listen is expanded to take one or two arguments.
+ Listen port
+ Listen address:port
+ Listen address port
+ This is to let you specify "Listen :: 80", since "Listen :::80"
+ won't work.
+
+mod_access:
+ deny from
+ allow from
+ "deny from" and "allow from" supports IPv6 addresses, under the
+ following forms:
+ {deny,allow} from v6addr
+ {deny,allow} from v6addr/v6mask
+ {deny,allow} from v6addr/prefixlen
+ Also, wildcard ("*") and string hostname matches IPv6 hosts as well.
+
+mod_proxy:
+ ProxyRequests on
+ http/ftp proxying for both IPv4 and IPv6 is possible.
+ Access control functions (NoProxy) are not updated yet.
+
+ NOTE: for security reasons, we recommend you to filter out
+ outsider's access to your proxy, by directives like below:
+ <Directory proxy:*>
+ order deny,allow
+ deny from all
+ allow from 10.0.0.0/8
+ allow from 3ffe:9999:8888:7777::/64
+ </Directory>
+
+virtual host:
+ If you would like to this feature, you must describe 'Listen'
+ part on configuration file explicitly. like below:
+ Listen :: 80
+ Listen 0.0.0.0 80
+
+ NameVirtualHost
+ NameVirtualHost is expanded to take one more two arguments.
+ NameVirtualHost address
+ NameVirtualHost address:port
+ NameVirtualHost address port
+ This is to let you specify IPv6 address into address part.
+
+ Note that, if a colon is found in the specified address string,
+ the code will to resolve the address in the following way:
+ 1. try to resolve as address:port (most of IPv6 address fails)
+ 2. if (1) is failed, try to resolve as address only
+ If there's ambiguity, i.e. 3ffe:0501::1:2, the address may not be
+ parsed as you expect (3ffe:0501::1 with port 2, or 3ffe:0501::1:2
+ with default port). To get the right effect you are encouraged
+ to specify it without ambiguity. In IPv6 case "address port"
+ (specify address and port separated by a space) is the safest way.
+
+ <VirtualHost host:port [host:port ...]>
+ If you would like to specify IPv6 numeric address in host part,
+ use bracketed format like below:
+ <VirtualHost [::1]:80>
+ Note: Now we DO NOT handle old non-bracketed format,
+ <VirtualHost 0:0:0:0:0:0:0:1:80>
+ so configuration file must be updated.
+ Note: The following is bad example to specify host ::1 port 80.
+ This will treated as host ::1:80.
+ <VirtualHost ::1:80>
+
+logresolve (src/support)
+ error statistics in nameserver cache code is omitted.
+
+mod_unique_id
+ Originally mod_unique_id used IPv4 address as a seed for UNIQUE_ID,
+ and took IPv4 address registered onto DNS for the hostname (UNIX
+ hostname taken by gethostname(3)). Therefore, this does not work
+ for IPv6-only hosts as they do not have IPv4 address for them.
+
+ Now, UNIQUE_ID can be generated using IPv6 address. IPv6 address can
+ be used as the seed for UNIQUE_ID.
+ Because of this, UNIQUE_ID will be longer than normal apache. This
+ may cause problem with some of the CGI scripts.
+ The preference of the addresses is based on the order returned
+ by getaddrinfo(). If your getaddrinfo() returns IPv4 address, IPv4
+ adderss will be used as a seed.
+ Note that some of IPv6 addresses are "scoped"; If you happened to use
+ link-local or site-local address as a seed, the UNIQUE_ID may not be
+ worldwide unique.
+
+ If longer UNIQUE_ID causes a problem, define SHORT_UNIQUE_ID in
+ mod_unique_id.c. In this case, length of UNIQUE_ID will be kept the
+ same. However, for IPv6 addresses mod_unique_id.c will use the last
+ 32bit (not the whole 128bit) as the seed. Therefore, there can be
+ collision in UNIQUE_ID.
+
+ The behavior should be improved in the near future; we welcome your
+ inputs.
+
+configuration file
+ We do not support IPv4 mapped addresses (IPv6 address format like
+ ::ffff:10.1.1.1) in configuration file.
+
+Credit:
+
+This file is derived from the README.v6 file that accompanied the
+original patchkit for Apache 1.3.9 from the KAME project. It was
+written by Jun-ichiro itojun Hagino.
+
+ http://www.kame.net/
+ mailto:core@kame.net
diff --git a/usr.sbin/httpd/conf/httpd.conf-dist b/usr.sbin/httpd/conf/httpd.conf-dist
index 84da5f10142..5e159777b3b 100644
--- a/usr.sbin/httpd/conf/httpd.conf-dist
+++ b/usr.sbin/httpd/conf/httpd.conf-dist
@@ -185,6 +185,11 @@ MaxSTACKPerChild 0
#Listen 3000
#Listen 12.34.56.78:80
+# Listen can take two arguments.
+# (this is an extension for supporting IPv6 addresses)
+#Listen :: 80
+#Listen 0.0.0.0 80
+
#
# BindAddress: You can support virtual hosts with this option. This directive
# is used to tell the server which IP address to listen to. It can either
@@ -945,7 +950,7 @@ ServerSignature On
#
# Use name-based virtual hosting.
#
-#NameVirtualHost *:80
+#NameVirtualHost 0.0.0.0:80
#
# VirtualHost example:
@@ -953,7 +958,7 @@ ServerSignature On
# The first VirtualHost section is used for requests without a known
# server name.
#
-#<VirtualHost *:80>
+#<VirtualHost 0.0.0.0:80>
# ServerAdmin webmaster@dummy-host.example.com
# DocumentRoot /www/docs/dummy-host.example.com
# ServerName dummy-host.example.com
diff --git a/usr.sbin/httpd/htdocs/manual/index.html b/usr.sbin/httpd/htdocs/manual/index.html
index e19b0ebe715..0c4ada5943d 100644
--- a/usr.sbin/httpd/htdocs/manual/index.html
+++ b/usr.sbin/httpd/htdocs/manual/index.html
@@ -141,7 +141,10 @@
<td align="center" bgcolor="#e9e9e9">
<strong>Platform Specific Notes</strong> </td>
</tr>
-
+ <tr>
+ <td><a href="ipv6.html">Support for IPv6</a>
+ </td>
+ </tr>
</table>
</td>
diff --git a/usr.sbin/httpd/htdocs/manual/ipv6.html b/usr.sbin/httpd/htdocs/manual/ipv6.html
new file mode 100644
index 00000000000..cb2e46e5c55
--- /dev/null
+++ b/usr.sbin/httpd/htdocs/manual/ipv6.html
@@ -0,0 +1,228 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta name="generator" content="HTML Tidy, see www.w3.org" />
+
+ <title>IPv6 Support for the OpenBSD Apache HTTP Server</title>
+ </head>
+ <!-- Background white, links blue (unvisited), navy (visited), red (active) -->
+
+ <body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
+ vlink="#000080" alink="#FF0000">
+ <div align="CENTER">
+ <img src="images/sub.gif" alt="[APACHE DOCUMENTATION]" />
+
+ <h3>Apache HTTP Server</h3>
+ </div>
+
+
+
+ <h1 align="center">IPv6 Support for the OpenBSD Apache HTTP Server</h1>
+
+ <p>This document explains how OpenBSD Apache makes use of IPv6.</p>
+
+
+<p>
+To support IPv6 the apache module API/ABI had to be changed, to avoid
+IPv4-dependent structure member variables (like use of u_long to hold
+an IPv4 address, or whatever). Keep this in mind when writing new
+modules or adding modules to the ports collection.
+</p>
+
+Basically you can write IPv6 address where IPv4 address fits.
+
+<h2>extra command-line argument</h2>
+
+<dl>
+<dt>-4</dt><dd>Assume IPv4 address on ambiguous directives (default)</dd>
+<dt>-6</dt><dd>Assume IPv6 address on ambiguous directives</dd>
+</dl>
+
+<p>
+The above two can be used, for example, to disambiguate "BindAddress *".
+</p>
+
+<h2>base commands</h2>
+<h3>Listen</h3>
+<p>
+Listen is expanded to take one or two arguments.
+</p>
+<pre>
+ Listen port
+ Listen address:port
+ Listen address port
+</pre>
+<p>
+This is to let you specify "Listen :: 80", since "Listen :::80"
+won't work.
+</p>
+<p>
+If you want httpd to listen on port 80 of all IPv4 and IPv6 addresses
+simultaneously, you would specify this using the following commands in
+your main server configuration:
+<pre>
+ Listen 0.0.0.0 80
+ Listen :: 80
+</pre>
+
+
+<h2>mod_access</h2>
+
+deny from<br>
+allow from
+
+<p>
+"deny from" and "allow from" supports IPv6 addresses, under the
+following forms:
+</p>
+
+<pre>
+ {deny,allow} from v6addr
+ {deny,allow} from v6addr/v6mask
+ {deny,allow} from v6addr/prefixlen
+</pre>
+
+<p>
+Also, wildcard ("*") and string hostname matches IPv6 hosts as well.
+</p>
+
+<h2>mod_proxy</h2>
+
+ProxyRequests on<br>
+
+<p>
+http/ftp proxying for both IPv4 and IPv6 is possible.
+Access control functions (NoProxy) are not updated yet.
+</p>
+<p>
+NOTE: for security reasons, we recommend you to filter out
+outsider's access to your proxy, by directives like below:
+</p>
+<pre>
+ <Directory proxy:*>
+ order deny,allow
+ deny from all
+ allow from 10.0.0.0/8
+ allow from 3ffe:9999:8888:7777::/64
+ </Directory>
+</pre>
+
+<h2>virtual host</h2>
+<p>
+If you would like to this feature, you must describe 'Listen'
+part on configuration file explicitly. like below:
+</p>
+<pre>
+ Listen :: 80
+ Listen 0.0.0.0 80
+</pre>
+
+NameVirtualHost<br>
+<p>
+NameVirtualHost is expanded to take one or two arguments.
+</p>
+<pre>
+ NameVirtualHost address
+ NameVirtualHost address:port
+ NameVirtualHost address port
+</pre>
+<p>
+This is to let you specify IPv6 address into address part.
+</p>
+<p>
+Note that, if a colon is found in the specified address string,
+the code will try to resolve the address in the following way:
+<ol>
+ <li>try to resolve as address:port (most of IPv6 address fails)
+ <li>if (1) is failed, try to resolve as address only
+</ol>
+</p>
+<p>
+If there's ambiguity, i.e. 3ffe:0501::1:2, the address may not be
+parsed as you expect (3ffe:0501::1 with port 2, or 3ffe:0501::1:2
+with default port). To get the right effect you are encouraged
+to specify it without ambiguity. In IPv6 case "address port"
+(specify address and port separated by a space) is the safest way.
+</p>
+
+<pre>
+&lt;VirtualHost host:port [host:port ...]&gt;<br>
+</pre>
+<p>
+If you would like to specify IPv6 numeric address in host part,
+use bracketed format like below:
+<p>
+<pre>
+ &lt;VirtualHost [::1]:80&gt;
+</pre>
+<p>
+Note: Now we DO NOT handle old non-bracketed format,
+</p>
+<pre>
+ &lt;VirtualHost 0:0:0:0:0:0:0:1:80&gt;
+</pre>
+<p>
+so configuration file must be updated.
+</p>
+<p>
+Note: The following is bad example to specify host ::1 port 80.
+This will treated as host ::1:80.
+</p>
+<pre>
+ &lt;VirtualHost ::1:80&gt;
+</pre>
+
+<h2>logresolve (src/support)</h2>
+<p>
+error statistics in nameserver cache code is omitted.
+</p>
+
+<h2>mod_unique_id</h2>
+<p>
+Originally mod_unique_id used IPv4 address as a seed for UNIQUE_ID,
+and took IPv4 address registered onto DNS for the hostname (UNIX
+hostname taken by gethostname(3)). Therefore, this does not work
+for IPv6-only hosts as they do not have IPv4 address for them.
+</p>
+<p>
+Now, UNIQUE_ID can be generated using IPv6 address. IPv6 address can
+be used as the seed for UNIQUE_ID.
+Because of this, UNIQUE_ID will be longer than normal apache. This
+may cause problem with some of the CGI scripts.
+The preference of the addresses is based on the order returned
+by getaddrinfo(). If your getaddrinfo() returns IPv4 address, IPv4
+adderss will be used as a seed.
+</p>
+<p>
+Note that some of IPv6 addresses are "scoped"; If you happened to use
+link-local or site-local address as a seed, the UNIQUE_ID may not be
+worldwide unique.
+</p>
+<p>
+If longer UNIQUE_ID causes a problem, define SHORT_UNIQUE_ID in
+mod_unique_id.c. In this case, length of UNIQUE_ID will be kept the
+same. However, for IPv6 addresses mod_unique_id.c will use the last
+32bit (not the whole 128bit) as the seed. Therefore, there can be
+collision in UNIQUE_ID.
+</p>
+<p>
+The behavior should be improved in the near future; we welcome your
+inputs.
+</p>
+
+<h2>configuration file</h2>
+<p>
+We do not support IPv4 mapped addresses (IPv6 address format like
+::ffff:10.1.1.1) in configuration file.
+</p>
+
+ <hr />
+
+ <h3 align="CENTER">Apache HTTP Server</h3>
+ <a href="./"><img src="images/index.gif" alt="Index" /></a>
+
+ </body>
+</html>
+
diff --git a/usr.sbin/httpd/htdocs/manual/misc/rewriteguide.html b/usr.sbin/httpd/htdocs/manual/misc/rewriteguide.html
index 195daefd044..bd62b24d778 100644
--- a/usr.sbin/httpd/htdocs/manual/misc/rewriteguide.html
+++ b/usr.sbin/httpd/htdocs/manual/misc/rewriteguide.html
@@ -2103,7 +2103,7 @@ perl.apache.org OK
<tr>
<td>
<pre>
-&lt;VirtualHost *:8008&gt;
+&lt;VirtualHost 0.0.0.0:8008&gt;
...
RewriteEngine On
# Either use the (plaintext) allow list from goodsites.txt
diff --git a/usr.sbin/httpd/htdocs/manual/mod/core.html b/usr.sbin/httpd/htdocs/manual/mod/core.html
index 18ed5be92f9..55829a0e982 100644
--- a/usr.sbin/httpd/htdocs/manual/mod/core.html
+++ b/usr.sbin/httpd/htdocs/manual/mod/core.html
@@ -2867,7 +2867,8 @@ Syntax OK
<blockquote>
<code>NameVirtualHost 111.22.33.44:8080</code>
</blockquote>
- In Apache 1.3.13 and greater you can specify a <code>*</code>
+ In OpenBSD Apache you can specify a <code>0.0.0.0</code>(IPv4)
+ or <code>::</code>(IPv6)
for the <em>addr</em>. This creates a wildcard NameVirtualHost
which will match connections to any address that isn't
configured with a more specific NameVirtualHost directive or <a
diff --git a/usr.sbin/httpd/httpd.8 b/usr.sbin/httpd/httpd.8
index ad5e80ab516..6f97df90143 100644
--- a/usr.sbin/httpd/httpd.8
+++ b/usr.sbin/httpd/httpd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: httpd.8,v 1.27 2007/05/31 19:20:24 jmc Exp $
+.\" $OpenBSD: httpd.8,v 1.28 2008/05/09 08:06:27 mbalmer Exp $
.\" Copyright (c) 1995-1997 David Robinson. All rights reserved.
.\" Copyright (c) 1997-1999 The Apache Group. All rights reserved.
.\" Copyright (c) 1998-1999 Bob Beck. All rights reserved.
@@ -50,7 +50,7 @@
.\" Supercomputing Applications, University of Illinois, Urbana-Champaign.
.\" For more information on the Apache Group and the Apache HTTP server
.\" project, please see <http://www.apache.org/>.
-.Dd $Mdocdate: May 31 2007 $
+.Dd $Mdocdate: May 9 2008 $
.Dt HTTPD 8
.Os
.Sh NAME
@@ -59,7 +59,7 @@
.Sh SYNOPSIS
.Nm httpd
.Bk -words
-.Op Fl FhLlSTtuVvX
+.Op Fl 46FhLlSTtuVvX
.Op Fl C Ar directive
.Op Fl c Ar directive
.Op Fl D Ar parameter
@@ -159,6 +159,12 @@ by default with
.Pp
The options are as follows:
.Bl -tag -width Ds
+.It Fl 4
+Assume IPv4 address on ambiguous directives (default)
+.It Fl 6
+Assume IPv6 address on ambiguous directives
+.Pp
+The above two can be used, for example, to disambiguate "BindAddress *".
.It Fl C Ar directive
Process the configuration
.Ar directive
diff --git a/usr.sbin/httpd/src/Configuration.tmpl b/usr.sbin/httpd/src/Configuration.tmpl
index 9912cb46d94..f471d8d7545 100644
--- a/usr.sbin/httpd/src/Configuration.tmpl
+++ b/usr.sbin/httpd/src/Configuration.tmpl
@@ -235,6 +235,9 @@ Rule SHARED_CHAIN=default
# implementation and uses the Win32 native calls. Should be faster
# and more reliable for high-load systems.
#
+# INET6:
+# IPv6 support.
+#
Rule SOCKS4=no
Rule SOCKS5=no
@@ -243,6 +246,7 @@ Rule IRIXN32=yes
Rule PARANOID=no
Rule EXPAT=default
Rule CYGWIN_WINSOCK=no
+Rule INET6=yes
# DEV_RANDOM:
# Note: this rule is only used when compiling mod_auth_digest.
diff --git a/usr.sbin/httpd/src/Configure b/usr.sbin/httpd/src/Configure
index 0cbd290df05..4447623f70a 100644
--- a/usr.sbin/httpd/src/Configure
+++ b/usr.sbin/httpd/src/Configure
@@ -1,5 +1,5 @@
#!/bin/sh
-# $OpenBSD: Configure,v 1.27 2007/02/14 20:11:09 millert Exp $
+# $OpenBSD: Configure,v 1.28 2008/05/09 08:06:27 mbalmer Exp $
## ====================================================================
## The Apache Software License, Version 1.1
##
@@ -240,6 +240,7 @@ RULE_EXPAT=`${SHELL} helpers/CutRule EXPAT $file`
RULE_CYGWIN_WINSOCK=`${SHELL} helpers/CutRule CYGWIN_WINSOCK $file`
RULE_SHARED_CORE=`${SHELL} helpers/CutRule SHARED_CORE $file`
RULE_SHARED_CHAIN=`${SHELL} helpers/CutRule SHARED_CHAIN $file`
+RULE_INET6=`${SHELL} helpers/CutRule INET6 $file`
####################################################################
## Rule SHARED_CORE implies required DSO support
@@ -1670,7 +1671,7 @@ case "$PLAT" in
# Test for the presence of the "union semun":
if TCADDINCL='#include <sys/types.h>
#include <sys/ipc.h>
-#include <sys/sem.h>' ./helpers/TestCompile sizeof "union semun"; then
+#include <sys/sem.h>' ${SHELL} helpers/TestCompile sizeof "union semun"; then
: Okay, union semun is defined
else
CFLAGS="$CFLAGS -DNEED_UNION_SEMUN"
@@ -1726,6 +1727,62 @@ if [ "x$RULE_SOCKS5" = "xyes" ]; then
esac
fi
+# INET6 support.
+if [ "$RULE_INET6" = "yes" ]; then
+ echo " + enabling INET6 support"
+ CFLAGS="$CFLAGS -DINET6"
+ CFLAGS="$CFLAGS -Dss_family=__ss_family -Dss_len=__ss_len"
+ IPV6_STACKTYPE=KAME
+fi
+
+echo '#include <sys/types.h>' >testfunc.c
+echo '#include <sys/socket.h>' >>testfunc.c
+echo 'int testfunc(){ struct sockaddr sa; int i = sa.sa_len; };' >>testfunc.c
+rm -f testfunc.o
+eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null"
+if [ -f testfunc.o ]; then
+ echo " + you have sa_len in struct sockaddr."
+ CFLAGS="$CFLAGS -DHAVE_SOCKADDR_LEN"
+else
+ echo " + you don't have sa_len in struct sockaddr."
+fi
+rm -f testfunc.c testfunc.o
+
+echo '#include <sys/types.h>' >testfunc.c
+echo '#include <sys/socket.h>' >>testfunc.c
+echo 'struct sockaddr_storage sockaddr_storage;' >>testfunc.c
+rm -f testfunc.o
+eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null"
+if [ -f testfunc.o ]; then
+ echo " + assuming you have struct sockaddr_storage"
+else
+ CFLAGS="$CFLAGS -DNEED_SOCKADDR_STORAGE"
+ echo " + you need struct sockaddr_storage"
+fi
+rm -f testfunc.c testfunc.o
+
+echo '#include <sys/types.h>' >testfunc.c
+echo '#include <sys/socket.h>' >>testfunc.c
+echo 'int testfunc(){ socklen_t t; }' >>testfunc.c
+rm -f testfunc.o
+eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null"
+if [ ! -f testfunc.o ]; then
+ CFLAGS="$CFLAGS -Dsocklen_t=int"
+fi
+rm -f testfunc.c testfunc.o
+
+echo '#include <sys/types.h>' >testfunc.c
+echo '#include <sys/socket.h>' >>testfunc.c
+echo 'struct sockaddr_in sin;' >>testfunc.c
+echo 'int main(){ int i = sin.sin_len; }' >>testfunc.c
+rm -f testfunc.o
+eval "${MAKE-make} -f Makefile.config testfunc.o >/dev/null 2>/dev/null"
+if [ -f testfunc.o ]; then
+ CFLAGS="$CFLAGS -DSIN_LEN"
+fi
+rm -f testfunc.c testfunc.o
+
+
####################################################################
## Find out what modules we want and try and configure things for them
## Module lines can look like this:
diff --git a/usr.sbin/httpd/src/include/ap.h b/usr.sbin/httpd/src/include/ap.h
index 4a3b554221e..dbe41bfe83d 100644
--- a/usr.sbin/httpd/src/include/ap.h
+++ b/usr.sbin/httpd/src/include/ap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ap.h,v 1.13 2005/03/28 23:26:51 niallo Exp $ */
+/* $OpenBSD: ap.h,v 1.14 2008/05/09 08:06:27 mbalmer Exp $ */
/* ====================================================================
* The Apache Software License, Version 1.1
@@ -88,8 +88,9 @@ API_EXPORT(long) ap_strtol(const char *nptr, char **endptr, int base);
/* ap_vformatter() is a generic printf-style formatting routine
* with some extensions. The extensions are:
*
- * %pA takes a struct in_addr *, and prints it as a.b.c.d
- * %pI takes a struct sockaddr_in * and prints it as a.b.c.d:port
+ * %pA takes a struct in_addr *, and prints it as a.b.c.d
+ * %pI takes a struct sockaddr * and prints it as a.b.c.d:port, or
+ * ipv6-numeric-addr:port
* %pp takes a void * and outputs it in hex
*
* The %p hacks are to force gcc's printf warning code to skip
diff --git a/usr.sbin/httpd/src/include/ap_config.h b/usr.sbin/httpd/src/include/ap_config.h
index b9313af6062..bd489a78357 100644
--- a/usr.sbin/httpd/src/include/ap_config.h
+++ b/usr.sbin/httpd/src/include/ap_config.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ap_config.h,v 1.21 2006/04/04 11:39:28 henning Exp $ */
+/* $OpenBSD: ap_config.h,v 1.22 2008/05/09 08:06:27 mbalmer Exp $ */
/* ====================================================================
* The Apache Software License, Version 1.1
@@ -332,6 +332,19 @@ Sigfunc *signal(int signo, Sigfunc * func);
#define ap_wait_t int
#endif
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+#ifndef INET_ADDRSTRLEN
+#define INET_ADDRSTRLEN 16
+#endif
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+#ifndef NI_MAXSERV
+#define NI_MAXSERV 32
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/usr.sbin/httpd/src/include/ap_config_auto.h b/usr.sbin/httpd/src/include/ap_config_auto.h
index 34b9b0e8e69..8c460078960 100644
--- a/usr.sbin/httpd/src/include/ap_config_auto.h
+++ b/usr.sbin/httpd/src/include/ap_config_auto.h
@@ -66,6 +66,26 @@
#define AP_OFF_T_IS_QUAD 1
#endif
+/* build flag: -DINET6 */
+#ifndef INET6
+#define INET6 1
+#endif
+
+/* build flag: -Dss_family=__ss_family */
+#ifndef ss_family
+#define ss_family __ss_family
+#endif
+
+/* build flag: -Dss_len=__ss_len */
+#ifndef ss_len
+#define ss_len __ss_len
+#endif
+
+/* build flag: -DHAVE_SOCKADDR_LEN */
+#ifndef HAVE_SOCKADDR_LEN
+#define HAVE_SOCKADDR_LEN 1
+#endif
+
/* build flag: -DMOD_SSL=208116 */
#ifndef MOD_SSL
#define MOD_SSL 208116
diff --git a/usr.sbin/httpd/src/include/http_conf_globals.h b/usr.sbin/httpd/src/include/http_conf_globals.h
index 2559a0d15aa..14ff3b2afcd 100644
--- a/usr.sbin/httpd/src/include/http_conf_globals.h
+++ b/usr.sbin/httpd/src/include/http_conf_globals.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: http_conf_globals.h,v 1.16 2006/02/22 15:07:12 henning Exp $ */
+/* $OpenBSD: http_conf_globals.h,v 1.17 2008/05/09 08:06:28 mbalmer Exp $ */
/* ====================================================================
* The Apache Software License, Version 1.1
@@ -83,7 +83,8 @@ extern API_VAR_EXPORT int ap_max_rss_per_child;
extern API_VAR_EXPORT int ap_max_stack_per_child;
extern API_VAR_EXPORT int ap_threads_per_child;
extern API_VAR_EXPORT int ap_excess_requests_per_child;
-extern API_VAR_EXPORT struct in_addr ap_bind_address;
+extern API_VAR_EXPORT struct sockaddr_storage ap_bind_address;
+extern API_VAR_EXPORT int ap_default_family;
extern listen_rec *ap_listeners;
extern API_VAR_EXPORT int ap_daemons_to_start;
extern API_VAR_EXPORT int ap_daemons_min_free;
diff --git a/usr.sbin/httpd/src/include/http_vhost.h b/usr.sbin/httpd/src/include/http_vhost.h
index 0677e51654f..1ff99faee40 100644
--- a/usr.sbin/httpd/src/include/http_vhost.h
+++ b/usr.sbin/httpd/src/include/http_vhost.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: http_vhost.h,v 1.7 2005/03/28 23:26:51 niallo Exp $ */
+/* $OpenBSD: http_vhost.h,v 1.8 2008/05/09 08:06:28 mbalmer Exp $ */
/* ====================================================================
* The Apache Software License, Version 1.1
@@ -77,7 +77,7 @@ API_EXPORT(const char *) ap_parse_vhost_addrs(pool *p, const char *hostname,
/* handle NameVirtualHost directive */
API_EXPORT_NONSTD(const char *) ap_set_name_virtual_host (cmd_parms *cmd,
- void *dummy, char *arg);
+ void *dummy, char *h, char *p);
/* given an ip address only, give our best guess as to what vhost it is */
API_EXPORT(void) ap_update_vhost_given_ip(conn_rec *conn);
diff --git a/usr.sbin/httpd/src/include/httpd.h b/usr.sbin/httpd/src/include/httpd.h
index 79ee6ef0493..957d1995cf5 100644
--- a/usr.sbin/httpd/src/include/httpd.h
+++ b/usr.sbin/httpd/src/include/httpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: httpd.h,v 1.27 2006/02/22 15:07:12 henning Exp $ */
+/* $OpenBSD: httpd.h,v 1.28 2008/05/09 08:06:28 mbalmer Exp $ */
/* ====================================================================
* The Apache Software License, Version 1.1
@@ -66,6 +66,13 @@ extern "C" {
#endif
/*
+ * Define APACHE6 so that additional modules depending on Apache can
+ * tell if this a pacthed apache-1.3.*. With this definition apache6
+ * is working together with e.g. the ap-perl module in NetBSD.
+ */
+#define APACHE6 1
+
+/*
* httpd.h: header for simple (ha! not anymore) http daemon
*/
@@ -847,8 +854,8 @@ struct conn_rec {
/* Who is the client? */
- struct sockaddr_in local_addr; /* local address */
- struct sockaddr_in remote_addr; /* remote address */
+ struct sockaddr_storage local_addr; /* local address */
+ struct sockaddr_storage remote_addr; /* remote address */
char *remote_ip; /* Client's IP address */
char *remote_host; /* Client's DNS name, if known.
* NULL if DNS hasn't been checked,
@@ -888,9 +895,9 @@ struct conn_rec {
typedef struct server_addr_rec server_addr_rec;
struct server_addr_rec {
server_addr_rec *next;
- struct in_addr host_addr; /* The bound address, for this server */
+ struct sockaddr_storage host_addr; /* The bound address, for this server */
unsigned short host_port; /* The bound port, for this server */
- char *virthost; /* The name given in <VirtualHost> */
+ char *virthost; /* The name given in <VirtualHost> */
};
struct server_rec {
@@ -942,7 +949,7 @@ struct server_rec {
array_header *names; /* Normal names for ServerAlias servers */
array_header *wild_names;/* Wildcarded names for ServerAlias servers */
- uid_t server_uid; /* effective user id when calling exec wrapper */
+ uid_t server_uid; /* effective user id when calling exec wrapper */
gid_t server_gid; /* effective group id when calling exec wrapper */
int limit_req_line; /* limit on size of the HTTP request line */
@@ -950,20 +957,18 @@ struct server_rec {
int limit_req_fields; /* limit on number of request header fields */
ap_ctx *ctx;
- };
+};
- /* These are more like real hosts than virtual hosts */
- struct listen_rec {
+/* These are more like real hosts than virtual hosts */
+struct listen_rec {
listen_rec *next;
- struct sockaddr_in local_addr; /* local IP address and port */
+ struct sockaddr_storage local_addr; /* local IP address and port */
int fd;
int used; /* Only used during restart */
/* more stuff here, like which protocol is bound to the port */
};
-/* Prototypes for utilities... util.c.
- */
-
+/* Prototypes for utilities... util.c. */
extern void ap_util_init(void);
/* Time */
@@ -1098,7 +1103,7 @@ API_EXPORT(char *) ap_os_canonical_filename(pool *p, const char *file);
API_EXPORT(char *) ap_get_local_host(pool *);
-API_EXPORT(unsigned long) ap_get_virthost_addr(char *hostname,
+API_EXPORT(struct sockaddr *) ap_get_virthost_addr(char *hostname,
unsigned short *port);
extern API_VAR_EXPORT time_t ap_restart_time;
diff --git a/usr.sbin/httpd/src/main/http_config.c b/usr.sbin/httpd/src/main/http_config.c
index 9b3e53b5e62..dfd17b48ae3 100644
--- a/usr.sbin/httpd/src/main/http_config.c
+++ b/usr.sbin/httpd/src/main/http_config.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: http_config.c,v 1.18 2007/11/19 14:59:10 robert Exp $ */
+/* $OpenBSD: http_config.c,v 1.19 2008/05/09 08:06:28 mbalmer Exp $ */
/* ====================================================================
* The Apache Software License, Version 1.1
@@ -1556,7 +1556,6 @@ static void init_config_globals(pool *p)
ap_max_nofile_per_child = DEFAULT_MAX_NOFILE_PER_CHILD;
ap_max_rss_per_child = DEFAULT_MAX_RSS_PER_CHILD;
ap_max_stack_per_child = DEFAULT_MAX_STACK_PER_CHILD;
- ap_bind_address.s_addr = htonl(INADDR_ANY);
ap_listeners = NULL;
ap_listenbacklog = DEFAULT_LISTENBACKLOG;
ap_extended_status = 0;
@@ -1589,7 +1588,13 @@ static server_rec *init_server_config(pool *p)
s->next = NULL;
s->addrs = ap_pcalloc(p, sizeof(server_addr_rec));
/* NOT virtual host; don't match any real network interface */
- s->addrs->host_addr.s_addr = htonl(INADDR_ANY);
+ memset(&s->addrs->host_addr, 0, sizeof(s->addrs->host_addr));
+#if 0
+ s->addrs->host_addr.ss_family = ap_default_family; /* XXX: needed?, XXX: PF_xxx can be different from AF_xxx */
+#endif
+#ifdef HAVE_SOCKADDR_LEN
+ s->addrs->host_addr.ss_len = sizeof(s->addrs->host_addr); /* XXX: needed ? */
+#endif
s->addrs->host_port = 0; /* matches any port */
s->addrs->virthost = ""; /* must be non-NULL */
s->names = s->wild_names = NULL;
@@ -1606,21 +1611,33 @@ static server_rec *init_server_config(pool *p)
static void default_listeners(pool *p, server_rec *s)
{
listen_rec *new;
+ struct addrinfo hints, *res0, *res;
+ int gai;
+ char servbuf[NI_MAXSERV];
if (ap_listeners != NULL) {
return;
}
+ ap_snprintf(servbuf, sizeof(servbuf), "%d", s->port ? s->port : DEFAULT_HTTP_PORT);
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_family = ap_default_family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+ gai = getaddrinfo(NULL, servbuf, &hints, &res0);
+ if (gai){
+ fprintf(stderr, "default_listeners(): getaddrinfo(PASSIVE) for family %u: %s\n",
+ ap_default_family, gai_strerror(gai));
+ exit (1);
+ }
/* allocate a default listener */
new = ap_pcalloc(p, sizeof(listen_rec));
- new->local_addr.sin_family = AF_INET;
- new->local_addr.sin_addr = ap_bind_address;
- /* Buck ugly cast to get around terniary op bug in some (MS) compilers */
- new->local_addr.sin_port = htons((unsigned short)(s->port ? s->port
- : DEFAULT_HTTP_PORT));
+ memcpy(&new->local_addr, res0->ai_addr, res0->ai_addrlen);
new->fd = -1;
new->used = 0;
new->next = NULL;
ap_listeners = new;
+
+ freeaddrinfo(res0);
}
diff --git a/usr.sbin/httpd/src/main/http_core.c b/usr.sbin/httpd/src/main/http_core.c
index 7248c212b75..d5c543d0c39 100644
--- a/usr.sbin/httpd/src/main/http_core.c
+++ b/usr.sbin/httpd/src/main/http_core.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: http_core.c,v 1.22 2007/08/24 11:31:29 mbalmer Exp $ */
+/* $OpenBSD: http_core.c,v 1.23 2008/05/09 08:06:28 mbalmer Exp $ */
/* ====================================================================
* The Apache Software License, Version 1.1
@@ -536,7 +536,7 @@ API_EXPORT(const char *) ap_auth_nonce(request_rec *r)
* file if you care. So the adhoc value should do.
*/
return ap_psprintf(r->pool,"%pp%pp%pp%pp%pp",
- (void *)&((r->connection->local_addr).sin_addr ),
+ (void *)&(r->connection->local_host),
(void *)ap_user_name,
(void *)ap_listeners,
(void *)ap_server_argv0,
@@ -617,7 +617,9 @@ API_EXPORT(char *) ap_response_code_string(request_rec *r, int error_index)
*/
static ap_inline void do_double_reverse (conn_rec *conn)
{
- struct hostent *hptr;
+ struct addrinfo hints, *res, *res0;
+ char hostbuf1[128], hostbuf2[128]; /* INET6_ADDRSTRLEN(=46) is enough */
+ int ok = 0;
if (conn->double_reverse) {
/* already done */
@@ -629,30 +631,49 @@ static ap_inline void do_double_reverse (conn_rec *conn)
conn->remote_host = ""; /* prevent another lookup */
return;
}
- hptr = gethostbyname(conn->remote_host);
- if (hptr) {
- char **haddr;
-
- for (haddr = hptr->h_addr_list; *haddr; haddr++) {
- if (((struct in_addr *)(*haddr))->s_addr
- == conn->remote_addr.sin_addr.s_addr) {
- conn->double_reverse = 1;
- return;
- }
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if (getaddrinfo(conn->remote_host, NULL, &hints, &res0)) {
+ conn->double_reverse = -1;
+ return;
+ }
+ for (res = res0; res; res = res->ai_next) {
+ if (res->ai_addr->sa_family != conn->remote_addr.ss_family ||
+ !(res->ai_family == AF_INET
+ || res->ai_family == AF_INET6
+ )
+ )
+ continue;
+#ifndef HAVE_SOCKADDR_LEN
+ if (res->ai_addrlen != SA_LEN((struct sockaddr *)&conn->remote_addr))
+#else
+ if (res->ai_addr->sa_len != conn->remote_addr.ss_len)
+#endif
+ continue;
+ if (getnameinfo(res->ai_addr, res->ai_addrlen,
+ hostbuf1, sizeof(hostbuf1), NULL, 0,
+ NI_NUMERICHOST))
+ continue;
+ if (getnameinfo(((struct sockaddr *)&conn->remote_addr), res->ai_addrlen,
+ hostbuf2, sizeof(hostbuf2), NULL, 0,
+ NI_NUMERICHOST))
+ continue;
+ if (strcmp(hostbuf1, hostbuf2) == 0){
+ ok = 1;
+ break;
}
}
- conn->double_reverse = -1;
- /* invalidate possible reverse-resolved hostname if forward lookup fails */
- conn->remote_host = "";
+ conn->double_reverse = ok ? 1 : -1;
+ freeaddrinfo(res0);
}
API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
int type)
{
- struct in_addr *iaddr;
- struct hostent *hptr;
int hostname_lookups;
int old_stat = SERVER_DEAD; /* we shouldn't ever be in this state */
+ char hostnamebuf[MAXHOSTNAMELEN];
/* If we haven't checked the host name, and we want to */
if (dir_config) {
@@ -674,10 +695,14 @@ API_EXPORT(const char *) ap_get_remote_host(conn_rec *conn, void *dir_config,
|| hostname_lookups != HOSTNAME_LOOKUP_OFF)) {
old_stat = ap_update_child_status(conn->child_num, SERVER_BUSY_DNS,
(request_rec*)NULL);
- iaddr = &(conn->remote_addr.sin_addr);
- hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
- if (hptr != NULL) {
- conn->remote_host = ap_pstrdup(conn->pool, (void *)hptr->h_name);
+ if (!getnameinfo((struct sockaddr *)&conn->remote_addr,
+#ifndef SIN6_LEN
+ SA_LEN((struct sockaddr *)&conn->remote_addr),
+#else
+ conn->remote_addr.ss_len,
+#endif
+ hostnamebuf, sizeof(hostnamebuf), NULL, 0, 0)) {
+ conn->remote_host = ap_pstrdup(conn->pool, (void *)hostnamebuf);
ap_str_tolower(conn->remote_host);
if (hostname_lookups == HOSTNAME_LOOKUP_DOUBLE) {
@@ -755,6 +780,7 @@ API_EXPORT(const char *) ap_get_server_name(request_rec *r)
{
conn_rec *conn = r->connection;
core_dir_config *d;
+ char hbuf[MAXHOSTNAMELEN];
d = (core_dir_config *)ap_get_module_config(r->per_dir_config,
&core_module);
@@ -764,23 +790,22 @@ API_EXPORT(const char *) ap_get_server_name(request_rec *r)
}
if (d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
if (conn->local_host == NULL) {
- struct in_addr *iaddr;
- struct hostent *hptr;
int old_stat;
old_stat = ap_update_child_status(conn->child_num,
SERVER_BUSY_DNS, r);
- iaddr = &(conn->local_addr.sin_addr);
- hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr),
- AF_INET);
- if (hptr != NULL) {
- conn->local_host = ap_pstrdup(conn->pool,
- (void *)hptr->h_name);
- ap_str_tolower(conn->local_host);
- }
- else {
- conn->local_host = ap_pstrdup(conn->pool,
- r->server->server_hostname);
+ if (getnameinfo((struct sockaddr *)&conn->local_addr,
+#ifndef SIN6_LEN
+ SA_LEN((struct sockaddr *)&conn->local_addr),
+#else
+ conn->local_addr.ss_len,
+#endif
+ hbuf, sizeof(hbuf), NULL, 0, 0) == 0) {
+ conn->local_host = ap_pstrdup(conn->pool, hbuf);
+ } else {
+ conn->local_host = ap_pstrdup(conn->pool,
+ r->server->server_hostname);
}
+ ap_str_tolower(conn->local_host);
(void) ap_update_child_status(conn->child_num, old_stat, r);
}
return conn->local_host;
@@ -792,29 +817,20 @@ API_EXPORT(const char *) ap_get_server_name(request_rec *r)
API_EXPORT(unsigned) ap_get_server_port(const request_rec *r)
{
unsigned port;
- unsigned cport = ntohs(r->connection->local_addr.sin_port);
core_dir_config *d =
(core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
+
+ port = r->server->port ? r->server->port : ap_default_port(r);
if (d->use_canonical_name == USE_CANONICAL_NAME_OFF
- || d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
-
- /* With UseCanonicalName Off Apache will form self-referential
- * URLs using the hostname and port supplied by the client if
- * any are supplied (otherwise it will use the canonical name).
- */
- port = r->parsed_uri.port_str ? r->parsed_uri.port :
- cport ? cport :
- r->server->port ? r->server->port :
- ap_default_port(r);
- } else { /* d->use_canonical_name == USE_CANONICAL_NAME_ON */
- port = r->server->port ? r->server->port :
- cport ? cport :
- ap_default_port(r);
+ || d->use_canonical_name == USE_CANONICAL_NAME_DNS) {
+ return r->hostname
+ ? ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port)
+ : port;
}
-
- /* default */
- return port;
+ return r->hostname
+ ? ntohs(((struct sockaddr_in *)&r->connection->local_addr)->sin_port)
+ : port;
}
API_EXPORT(char *) ap_construct_url(pool *p, const char *uri,
@@ -2380,12 +2396,25 @@ static const char *set_limit_nofile(cmd_parms *cmd, core_dir_config *conf,
static const char *set_bind_address(cmd_parms *cmd, void *dummy, char *arg)
{
+ struct addrinfo hints, *res;
+ struct sockaddr *sa;
+ size_t sa_len;
+ int error;
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
- ap_bind_address.s_addr = ap_get_virthost_addr(arg, NULL);
+ if (strcmp(arg, "*") == 0)
+ arg = NULL;
+
+ sa = ap_get_virthost_addr(arg, NULL);
+#ifdef HAVE_SOCKADDR_LEN
+ sa_len = sa->sa_len;
+#else
+ sa_len = SA_LEN(sa);
+#endif
+ memcpy(&ap_bind_address, &sa, sa_len);
return NULL;
}
@@ -2402,48 +2431,78 @@ static const char *set_acceptfilter(cmd_parms *cmd, void *dummy, int flag)
return NULL;
}
-static const char *set_listener(cmd_parms *cmd, void *dummy, char *ips)
+static const char *set_listener(cmd_parms *cmd, void *dummy, char *h, char *p)
{
listen_rec *new;
- char *ports, *endptr;
- long port;
+ char *host, *port, *endptr;
+ struct addrinfo hints, *res;
+ int error;
const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
if (err != NULL) {
return err;
}
- ports = strchr(ips, ':');
- if (ports != NULL) {
- if (ports == ips) {
+ host = port = NULL;
+ if (!p) {
+ port = strrchr(h, ':');
+ if (port != NULL) {
+ if (port == h) {
return "Missing IP address";
}
- else if (ports[1] == '\0') {
+ else if (port[1] == '\0') {
return "Address must end in :<port-number>";
}
- *(ports++) = '\0';
- }
- else {
- ports = ips;
- }
+ *(port++) = '\0';
+ if (*h)
+ host = h;
+ } else {
+ host = NULL;
+ port = h;
+ }
+ } else {
+ host = h;
+ port = p;
+ }
+
+ /* strip [] for ipv6 before calling getaddrinfo */
+ if (host && host[0] == '[') {
+ if (strlen(host) < 2 || host[strlen(host) - 1] != ']')
+ return "Malformed IPv6 Address in :<host>";
+ host[strlen(host) - 1] = 0;
+ host++;
+ }
+
+ if (host && strcmp(host, "*") == 0)
+ host = NULL;
+
+ new = ap_pcalloc(cmd->pool, sizeof(listen_rec));
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = host ? PF_UNSPEC : ap_default_family;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(host, port, &hints, &res);
+ if (error || !res) {
+ fprintf(stderr, "could not resolve ");
+ if (host)
+ fprintf(stderr, "host \"%s\" ", host);
+ if (port)
+ fprintf(stderr, "port \"%s\" ", port);
+ fprintf(stderr, "--- %s\n", gai_strerror(error));
+ exit(1);
+ }
+ if (res->ai_next) {
+ if (host)
+ fprintf(stderr, "host \"%s\" ", host);
+ if (port)
+ fprintf(stderr, "port \"%s\" ", port);
+ fprintf(stderr, "resolved to multiple addresses, ambiguous.\n");
+ exit(1);
+ }
+
+ memcpy(&new->local_addr, res->ai_addr, res->ai_addrlen);
- new=ap_pcalloc(cmd->pool, sizeof(listen_rec));
- new->local_addr.sin_family = AF_INET;
- if (ports == ips) { /* no address */
- new->local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- }
- else {
- new->local_addr.sin_addr.s_addr = ap_get_virthost_addr(ips, NULL);
- }
- errno = 0; /* clear errno before calling strtol */
- port = ap_strtol(ports, &endptr, 10);
- if (errno /* some sort of error */
- || (endptr && *endptr) /* make sure no trailing characters */
- || port < 1 || port > 65535) /* underflow/overflow */
- {
- return "Missing, invalid, or non-numeric port";
- }
- new->local_addr.sin_port = htons((unsigned short)port);
new->fd = -1;
new->used = 0;
new->next = ap_listeners;
@@ -3198,7 +3257,7 @@ static const command_rec core_cmds[] = {
OR_ALL, TAKE12, "soft/hard limits for max number of files per process" },
{ "BindAddress", set_bind_address, NULL, RSRC_CONF, TAKE1,
"'*', a numeric IP address, or the name of a host with a unique IP address"},
-{ "Listen", set_listener, NULL, RSRC_CONF, TAKE1,
+{ "Listen", set_listener, NULL, RSRC_CONF, TAKE12,
"A port number or a numeric IP address and a port number"},
{ "SendBufferSize", set_send_buffer_size, NULL, RSRC_CONF, TAKE1,
"Send buffer size in bytes"},
@@ -3226,7 +3285,7 @@ static const command_rec core_cmds[] = {
"Name of the config file to be included" },
{ "LogLevel", set_loglevel, NULL, RSRC_CONF, TAKE1,
"Level of verbosity in error logging" },
-{ "NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, TAKE1,
+{ "NameVirtualHost", ap_set_name_virtual_host, NULL, RSRC_CONF, TAKE12,
"A numeric IP address:port, or the name of a host" },
{ "CGICommandArgs", set_cgi_command_args, NULL, OR_OPTIONS, FLAG,
"Allow or Disallow CGI requests to pass args on the command line" },
diff --git a/usr.sbin/httpd/src/main/http_main.c b/usr.sbin/httpd/src/main/http_main.c
index e336256bc4d..ace88475e8d 100644
--- a/usr.sbin/httpd/src/main/http_main.c
+++ b/usr.sbin/httpd/src/main/http_main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: http_main.c,v 1.49 2007/08/09 10:44:54 martynas Exp $ */
+/* $OpenBSD: http_main.c,v 1.50 2008/05/09 08:06:28 mbalmer Exp $ */
/* ====================================================================
* The Apache Software License, Version 1.1
@@ -168,7 +168,8 @@ API_VAR_EXPORT char *ap_pid_fname=NULL;
API_VAR_EXPORT char *ap_scoreboard_fname=NULL;
API_VAR_EXPORT char *ap_lock_fname=NULL;
API_VAR_EXPORT char *ap_server_argv0=NULL;
-API_VAR_EXPORT struct in_addr ap_bind_address={0};
+API_VAR_EXPORT int ap_default_family = PF_INET;
+API_VAR_EXPORT struct sockaddr_storage ap_bind_address;
API_VAR_EXPORT int ap_daemons_to_start=0;
API_VAR_EXPORT int ap_daemons_min_free=0;
API_VAR_EXPORT int ap_daemons_max_free=0;
@@ -1807,11 +1808,13 @@ static int init_suexec(void)
static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout,
- const struct sockaddr_in *remaddr,
- const struct sockaddr_in *saddr,
+ const struct sockaddr *remaddr,
+ const struct sockaddr *saddr,
int child_num)
{
conn_rec *conn = (conn_rec *) ap_pcalloc(p, sizeof(conn_rec));
+ char hostnamebuf[MAXHOSTNAMELEN];
+ size_t addr_len;
/* Got a connection structure, so initialize what fields we can
* (the rest are zeroed out by pcalloc).
@@ -1820,17 +1823,29 @@ static conn_rec *new_connection(pool *p, server_rec *server, BUFF *inout,
conn->child_num = child_num;
conn->pool = p;
- conn->local_addr = *saddr;
- conn->local_ip = ap_pstrdup(conn->pool,
- inet_ntoa(conn->local_addr.sin_addr));
+#ifndef SIN6_LEN
+ addr_len = SA_LEN(saddr);
+#else
+ addr_len = saddr->sa_len;
+#endif
+ memcpy(&conn->local_addr, saddr, addr_len);
+ getnameinfo((struct sockaddr *)&conn->local_addr, addr_len,
+ hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
+ conn->local_ip = ap_pstrdup(conn->pool, hostnamebuf);
conn->server = server; /* just a guess for now */
ap_update_vhost_given_ip(conn);
conn->base_server = conn->server;
conn->client = inout;
- conn->remote_addr = *remaddr;
- conn->remote_ip = ap_pstrdup(conn->pool,
- inet_ntoa(conn->remote_addr.sin_addr));
+#ifndef SIN6_LEN
+ addr_len = SA_LEN(remaddr);
+#else
+ addr_len = remaddr->sa_len;
+#endif
+ memcpy(&conn->remote_addr, remaddr, addr_len);
+ getnameinfo((struct sockaddr *)&conn->remote_addr, addr_len,
+ hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
+ conn->remote_ip = ap_pstrdup(conn->pool, hostnamebuf);
conn->ctx = ap_ctx_new(conn->pool);
/*
@@ -1876,21 +1891,42 @@ static void sock_disable_nagle(int s, struct sockaddr_in *sin_client)
}
}
-static int make_sock(pool *p, const struct sockaddr_in *server)
+static int make_sock(pool *p, const struct sockaddr *server)
{
int s;
int one = 1;
- char addr[512];
-
- if (server->sin_addr.s_addr != htonl(INADDR_ANY))
- ap_snprintf(addr, sizeof(addr), "address %s port %d",
- inet_ntoa(server->sin_addr), ntohs(server->sin_port));
- else
- ap_snprintf(addr, sizeof(addr), "port %d", ntohs(server->sin_port));
+ char addr[INET6_ADDRSTRLEN + 128];
+ char a0[INET6_ADDRSTRLEN];
+ char p0[NI_MAXSERV];
+
+ switch(server->sa_family){
+ case AF_INET:
+ case AF_INET6:
+ break;
+ default:
+ ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
+ "make_sock: unsupported address family %u",
+ server->sa_family);
+ ap_unblock_alarms();
+ exit(1);
+ }
+
+ getnameinfo(server,
+#ifndef SIN6_LEN
+ SA_LEN(server),
+#else
+ server->sa_len,
+#endif
+ a0, sizeof(a0), p0, sizeof(p0), NI_NUMERICHOST | NI_NUMERICSERV);
+ ap_snprintf(addr, sizeof(addr), "address %s port %s", a0, p0);
+#ifdef MPE
+ if (atoi(p0) < 1024)
+ privport++;
+#endif
/* note that because we're about to slack we don't use psocket */
ap_block_alarms();
- if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+ if ((s = socket(server->sa_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
"make_sock: failed to get a socket for %s", addr);
@@ -1951,8 +1987,12 @@ static int make_sock(pool *p, const struct sockaddr_in *server)
}
}
-
- if (bind(s, (struct sockaddr *) server, sizeof(struct sockaddr_in)) == -1) {
+#ifndef SIN6_LEN
+ if (bind(s, server, SA_LEN(server)) == -1)
+#else
+ if (bind(s, server, server->sa_len) == -1)
+#endif
+ {
ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,
"make_sock: could not bind to %s", addr);
@@ -2065,15 +2105,17 @@ static void setup_listeners(pool *p)
for (;;) {
fd = find_listener(lr);
if (fd < 0) {
- fd = make_sock(p, &lr->local_addr);
+ fd = make_sock(p, (struct sockaddr *)&lr->local_addr);
}
else {
ap_note_cleanups_for_socket_ex(p, fd, 1);
}
/* if we get here, (fd >= 0) && (fd < FD_SETSIZE) */
- FD_SET(fd, &listenfds);
- if (fd > listenmaxfd)
- listenmaxfd = fd;
+ if (fd >= 0) {
+ FD_SET(fd, &listenfds);
+ if (fd > listenmaxfd)
+ listenmaxfd = fd;
+ }
lr->fd = fd;
if (lr->next == NULL)
break;
@@ -2231,8 +2273,8 @@ API_EXPORT(void) ap_child_terminate(request_rec *r)
static void child_main(int child_num_arg)
{
NET_SIZE_T clen;
- struct sockaddr sa_server;
- struct sockaddr sa_client;
+ struct sockaddr_storage sa_server;
+ struct sockaddr_storage sa_client;
listen_rec *lr;
struct rlimit rlp;
@@ -2422,7 +2464,7 @@ static void child_main(int child_num_arg)
usr1_just_die = 0;
for (;;) {
clen = sizeof(sa_client);
- csd = ap_accept(sd, &sa_client, &clen);
+ csd = ap_accept(sd, (struct sockaddr *)&sa_client, &clen);
if (csd >= 0 || errno != EINTR)
break;
if (deferred_die) {
@@ -2526,7 +2568,7 @@ static void child_main(int child_num_arg)
*/
clen = sizeof(sa_server);
- if (getsockname(csd, &sa_server, &clen) < 0) {
+ if (getsockname(csd, (struct sockaddr *)&sa_server, &clen) < 0) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, server_conf,
"getsockname, client %pA probably dropped the "
"connection",
@@ -2545,8 +2587,8 @@ static void child_main(int child_num_arg)
ap_bpushfd(conn_io, csd, dupped_csd);
current_conn = new_connection(ptrans, server_conf, conn_io,
- (struct sockaddr_in *) &sa_client,
- (struct sockaddr_in *) &sa_server,
+ (struct sockaddr *)&sa_client,
+ (struct sockaddr *)&sa_server,
my_child_num);
/*
@@ -3206,7 +3248,7 @@ int REALMAIN(int argc, char *argv[])
ap_setup_prelinked_modules();
while ((c = getopt(argc, argv,
- "D:C:c:xXd:Ff:vVlLR:StThu"
+ "D:C:c:xXd:Ff:vVlLR:StThu46"
#ifdef DEBUG_SIGSTOP
"Z:"
#endif
@@ -3272,6 +3314,13 @@ int REALMAIN(int argc, char *argv[])
break;
case 'h':
usage(argv[0]);
+ break;
+ case '4':
+ ap_default_family = PF_INET;
+ break;
+ case '6':
+ ap_default_family = PF_INET6;
+ break;
case 'u':
ap_server_chroot = 0;
break;
@@ -3307,9 +3356,10 @@ int REALMAIN(int argc, char *argv[])
else {
conn_rec *conn;
request_rec *r;
- struct sockaddr sa_server, sa_client;
BUFF *cio;
+ struct sockaddr_storage sa_server, sa_client;
NET_SIZE_T l;
+ char servbuf[NI_MAXSERV];
ap_set_version();
/* Yes this is called twice. */
@@ -3338,25 +3388,32 @@ int REALMAIN(int argc, char *argv[])
sock_out = fileno(stdout);
l = sizeof(sa_client);
- if ((getpeername(sock_in, &sa_client, &l)) < 0) {
+ if ((getpeername(sock_in, (struct sockaddr *)&sa_client, &l)) < 0) {
/* get peername will fail if the input isn't a socket */
perror("getpeername");
memset(&sa_client, '\0', sizeof(sa_client));
}
l = sizeof(sa_server);
- if (getsockname(sock_in, &sa_server, &l) < 0) {
+ if (getsockname(sock_in, (struct sockaddr *)&sa_server, &l) < 0) {
perror("getsockname");
fprintf(stderr, "Error getting local address\n");
exit(1);
}
- server_conf->port = ntohs(((struct sockaddr_in *) &sa_server)->sin_port);
+ if (getnameinfo(((struct sockaddr *)&sa_server), l,
+ NULL, 0, servbuf, sizeof(servbuf),
+ NI_NUMERICSERV)){
+ fprintf(stderr, "getnameinfo(): family=%d\n", sa_server.ss_family);
+ exit(1);
+ }
+ servbuf[sizeof(servbuf)-1] = '\0';
+ server_conf->port = atoi(servbuf);
cio = ap_bcreate(ptrans, B_RDWR | B_SOCKET);
cio->fd = sock_out;
cio->fd_in = sock_in;
conn = new_connection(ptrans, server_conf, cio,
- (struct sockaddr_in *) &sa_client,
- (struct sockaddr_in *) &sa_server, -1);
+ (struct sockaddr *)&sa_client,
+ (struct sockaddr *)&sa_server, -1);
while ((r = ap_read_request(conn)) != NULL) {
diff --git a/usr.sbin/httpd/src/main/http_vhost.c b/usr.sbin/httpd/src/main/http_vhost.c
index 3d9df203ac2..c659dbb1a7c 100644
--- a/usr.sbin/httpd/src/main/http_vhost.c
+++ b/usr.sbin/httpd/src/main/http_vhost.c
@@ -165,78 +165,108 @@ API_EXPORT(void) ap_init_vhost_config(pool *p)
* *paddr is the variable used to keep track of **paddr between calls
* port is the default port to assume
*/
-static const char *get_addresses(pool *p, char *w, server_addr_rec ***paddr,
- unsigned port)
+static const char *get_addresses(pool *p, char *w, char *pstr,
+ server_addr_rec ***paddr, unsigned port)
{
- struct hostent *hep;
- unsigned long my_addr;
+ struct addrinfo hints, *res, *res0;
server_addr_rec *sar;
- char *t;
- int i, is_an_ip_addr;
+ char *t = NULL, *u = NULL, *v = NULL;
+ char *hoststr = NULL, *portstr = NULL;
+ char portpool[10];
+ int error;
+ char servbuf[NI_MAXSERV];
- if (*w == 0)
+ if (w == 0 || *w == 0)
return NULL;
- t = strchr(w, ':');
- if (t) {
- if (strcmp(t + 1, "*") == 0) {
- port = 0;
+ portstr = portpool;
+ ap_snprintf(portpool, sizeof(portpool), "%u", port);
+ if (!pstr) {
+ v = w;
+ u = NULL;
+ if (*w == '['){
+ u = strrchr(w, ']');
+ if (u) { /* [host]:port or [host] */
+ w++;
+ *u = '\0';
+ v = u + 1;
+ }
}
- else if ((i = atoi(t + 1))) {
- port = i;
+ /* w uv , w=v , w=v */
+ /* u!=0: [host]:port , u==0: [host:port , host */
+ t = strchr(v, ':');
+ if (t != NULL && strchr(t+1, ':') == NULL) {
+ /* [host]:port-w/o-colons, host-without-colons:port-w/o-colons */
+ *t = '\0';
+ portstr = t + 1;
}
else {
- return ":port must be numeric";
+ portstr = "0";
}
- *t = 0;
+ } else {
+ portstr = pstr;
}
- is_an_ip_addr = 0;
- if (strcmp(w, "*") == 0) {
- my_addr = htonl(INADDR_ANY);
- is_an_ip_addr = 1;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ if (strcmp(w, "*") == 0 || strlen(w) == 0) {
+ hoststr = NULL;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_PASSIVE;
}
- else if (strcasecmp(w, "_default_") == 0
- || strcmp(w, "255.255.255.255") == 0) {
- my_addr = DEFAULT_VHOST_ADDR;
- is_an_ip_addr = 1;
+ else if (strcasecmp(w, "_default4_") == 0 ||
+ ((ap_default_family == PF_INET
+ || ap_default_family == PF_UNSPEC
+ ) && strcasecmp(w, "_default_") == 0)){
+ hoststr = "255.255.255.255";
+ hints.ai_family = PF_INET;
}
- else if ((my_addr = ap_inet_addr(w)) != INADDR_NONE) {
- is_an_ip_addr = 1;
+ else if (strcasecmp(w, "_default6_") == 0 ||
+ ((ap_default_family == PF_INET6
+ || ap_default_family == PF_UNSPEC
+ ) && strcasecmp(w, "_default_") == 0)){
+ hoststr = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+ hints.ai_family = PF_INET6;
}
- if (is_an_ip_addr) {
- sar = ap_pcalloc(p, sizeof(server_addr_rec));
- **paddr = sar;
- *paddr = &sar->next;
- sar->host_addr.s_addr = my_addr;
- sar->host_port = port;
- sar->virthost = ap_pstrdup(p, w);
- if (t != NULL)
- *t = ':';
- return NULL;
+ else{
+ hoststr = w;
+ hints.ai_family = PF_UNSPEC;
}
- hep = gethostbyname(w);
-
- if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
+ error = getaddrinfo(hoststr, portstr, &hints, &res0);
+ if (error || !res0) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
- "Cannot resolve host name %s --- ignoring!", w);
- if (t != NULL)
- *t = ':';
+ "Cannot resolve host %s port %s --- ignoring!", hoststr, portstr);
+ if (t != NULL) *t = ':';
+ if (u != NULL) *u = ']';
return NULL;
}
-
- for (i = 0; hep->h_addr_list[i]; ++i) {
+ for (res=res0; res; res=res->ai_next) {
+ switch (res->ai_addr->sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ break;
+ default:
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL,
+ "Unsupported address family %u, for host %s port %s --- ignoring!",
+ res->ai_addr->sa_family, hoststr, portstr);
+ continue;
+ }
sar = ap_pcalloc(p, sizeof(server_addr_rec));
**paddr = sar;
*paddr = &sar->next;
- sar->host_addr = *(struct in_addr *) hep->h_addr_list[i];
- sar->host_port = port;
+ memcpy(&sar->host_addr, res->ai_addr, res->ai_addrlen);
+ if (getnameinfo(res->ai_addr, res->ai_addrlen, NULL, 0, servbuf,
+ sizeof(servbuf), NI_NUMERICSERV) == 0)
+ sar->host_port = atoi(servbuf);
+ else
+ sar->host_port = 0;
sar->virthost = ap_pstrdup(p, w);
}
- if (t != NULL)
- *t = ':';
+ freeaddrinfo(res0);
+ if (t != NULL) *t = ':';
+ if (u != NULL) *u = ']';
return NULL;
}
@@ -250,7 +280,8 @@ API_EXPORT(const char *) ap_parse_vhost_addrs(pool *p, const char *hostname, ser
/* start the list of addreses */
addrs = &s->addrs;
while (hostname[0]) {
- err = get_addresses(p, ap_getword_conf(p, &hostname), &addrs, s->port);
+ err = get_addresses(p, ap_getword_conf(p, &hostname), NULL,
+ &addrs, s->port);
if (err) {
*addrs = NULL;
return err;
@@ -268,10 +299,11 @@ API_EXPORT(const char *) ap_parse_vhost_addrs(pool *p, const char *hostname, ser
}
-API_EXPORT_NONSTD(const char *) ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *arg)
+API_EXPORT_NONSTD(const char *) ap_set_name_virtual_host (cmd_parms *cmd, void *dummy, char *h,
+ char *p)
{
/* use whatever port the main server has at this point */
- return get_addresses(cmd->pool, arg, &name_vhost_list_tail,
+ return get_addresses(cmd->pool, h, p, &name_vhost_list_tail,
cmd->server->port);
}
@@ -345,6 +377,17 @@ static ap_inline unsigned hash_inaddr(unsigned key)
return ((key >> 8) ^ key) % IPHASH_TABLE_SIZE;
}
+static unsigned hash_addr(struct sockaddr *sa)
+{
+ switch (sa->sa_family) {
+ case AF_INET:
+ return hash_inaddr(((struct sockaddr_in *)sa)->sin_addr.s_addr);
+ case AF_INET6:
+ return hash_inaddr(((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12]);
+ default:
+ return hash_inaddr(sa->sa_family);
+ }
+}
static ipaddr_chain *new_ipaddr_chain(pool *p,
@@ -372,25 +415,52 @@ static name_chain *new_name_chain(pool *p, server_rec *s, server_addr_rec *sar)
return new;
}
-
-static ap_inline ipaddr_chain *find_ipaddr(struct in_addr *server_ip,
- unsigned port)
+static ap_inline ipaddr_chain *find_ipaddr(struct sockaddr *sa)
{
unsigned bucket;
ipaddr_chain *trav;
- unsigned addr;
+ char a[NI_MAXHOST], b[NI_MAXHOST];
/* scan the hash table for an exact match first */
- addr = server_ip->s_addr;
- bucket = hash_inaddr(addr);
+ bucket = hash_addr(sa);
for (trav = iphash_table[bucket]; trav; trav = trav->next) {
server_addr_rec *sar = trav->sar;
- if ((sar->host_addr.s_addr == addr)
- && (sar->host_port == 0 || sar->host_port == port
- || port == 0)) {
- return trav;
+ if (sar->host_addr.ss_family != sa->sa_family)
+ continue;
+ switch (sa->sa_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin1, *sin2;
+ sin1 = (struct sockaddr_in *)&sar->host_addr;
+ sin2 = (struct sockaddr_in *)sa;
+ if (sin1->sin_port == 0 || sin2->sin_port == 0
+ || sin1->sin_port == sin2->sin_port) {
+ if (memcmp(&sin1->sin_addr, &sin2->sin_addr,
+ sizeof(sin1->sin_addr)) == 0) {
+ return trav;
+ }
+ }
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin1, *sin2;
+ sin1 = (struct sockaddr_in6 *)&sar->host_addr;
+ sin2 = (struct sockaddr_in6 *)sa;
+ if (sin1->sin6_port == 0 || sin2->sin6_port == 0
+ || sin1->sin6_port == sin2->sin6_port) {
+ if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
+ sizeof(sin1->sin6_addr)) == 0) {
+ return trav;
+ }
+ }
+ break;
+ }
+ default: /*unsupported*/
+ break;
}
}
+
return NULL;
}
@@ -416,21 +486,7 @@ static void dump_a_vhost(FILE *f, ipaddr_chain *ic)
int len;
char buf[MAX_STRING_LEN];
- if (ic->sar->host_addr.s_addr == DEFAULT_VHOST_ADDR) {
- len = ap_snprintf(buf, sizeof(buf), "_default_:%u",
- ic->sar->host_port);
- }
- else if (ic->sar->host_addr.s_addr == INADDR_ANY) {
- len = ap_snprintf(buf, sizeof(buf), "*:%u",
- ic->sar->host_port);
- }
- else {
- len = ap_snprintf(buf, sizeof(buf), "%pA:%u",
- &ic->sar->host_addr, ic->sar->host_port);
- }
- if (ic->sar->host_port == 0) {
- buf[len-1] = '*';
- }
+ len = ap_snprintf(buf, sizeof(buf), "%pI", &ic->sar->host_addr);
if (ic->names == NULL) {
if (ic->server == NULL)
fprintf(f, "%-22s WARNING: No <VirtualHost> defined for this NameVirtualHost!\n", buf);
@@ -558,10 +614,35 @@ API_EXPORT(void) ap_fini_vhost_config(pool *p, server_rec *main_s)
* occured in the config file, we'll copy it in that order.
*/
for (sar = name_vhost_list; sar; sar = sar->next) {
- unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
+ unsigned bucket = hash_addr((struct sockaddr *)&sar->host_addr);
ipaddr_chain *ic = new_ipaddr_chain(p, NULL, sar);
+ int wildcard;
+
+ wildcard = 0;
+ switch (sar->host_addr.ss_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)&sar->host_addr;
+ if (sin->sin_addr.s_addr == INADDR_ANY)
+ wildcard++;
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *)&sar->host_addr;
+ if (*(uint32_t *)&sin6->sin6_addr.s6_addr[0] == 0
+ && *(uint32_t *)&sin6->sin6_addr.s6_addr[4] == 0
+ && *(uint32_t *)&sin6->sin6_addr.s6_addr[8] == 0
+ && *(uint32_t *)&sin6->sin6_addr.s6_addr[12] == 0) {
+ wildcard++;
+ }
+ break;
+ }
+ }
- if (sar->host_addr.s_addr != INADDR_ANY) {
+ if (!wildcard) {
*iphash_table_tail[bucket] = ic;
iphash_table_tail[bucket] = &ic->next;
}
@@ -588,12 +669,43 @@ API_EXPORT(void) ap_fini_vhost_config(pool *p, server_rec *main_s)
has_default_vhost_addr = 0;
for (sar = s->addrs; sar; sar = sar->next) {
ipaddr_chain *ic;
+ int wildcard;
+
+ wildcard = 0;
+ switch (sar->host_addr.ss_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)&sar->host_addr;
+ if (sin->sin_addr.s_addr == DEFAULT_VHOST_ADDR)
+ wildcard++;
+ else if (sin->sin_addr.s_addr == INADDR_ANY)
+ wildcard++;
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *)&sar->host_addr;
+ if (*(uint32_t *)&sin6->sin6_addr.s6_addr[0] == ~0
+ && *(uint32_t *)&sin6->sin6_addr.s6_addr[4] == ~0
+ && *(uint32_t *)&sin6->sin6_addr.s6_addr[8] == ~0
+ && *(uint32_t *)&sin6->sin6_addr.s6_addr[12] == ~0) {
+ wildcard++;
+ }
+ break;
+ }
+ }
+
+ if (wildcard) {
+ /* add it to default bucket for each appropriate sar
+ * since we need to do a port test
+ */
+ ipaddr_chain *other;
- if (sar->host_addr.s_addr == DEFAULT_VHOST_ADDR
- || sar->host_addr.s_addr == INADDR_ANY) {
- ic = find_default_server(sar->host_port);
- if (!ic || !add_name_vhost_config(p, main_s, s, sar, ic)) {
- if (ic && ic->sar->host_port != 0) {
+ other = find_default_server(sar->host_port);
+ if (!other || !add_name_vhost_config(p, main_s, s, sar, other)) {
+ if (other && other->sar->host_port != 0) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING,
main_s, "_default_ VirtualHost overlap on port %u,"
" the first has precedence", sar->host_port);
@@ -606,10 +718,11 @@ API_EXPORT(void) ap_fini_vhost_config(pool *p, server_rec *main_s)
}
else {
/* see if it matches something we've already got */
- ic = find_ipaddr(&sar->host_addr, sar->host_port);
+ ic = find_ipaddr((struct sockaddr *)&sar->host_addr);
if (!ic) {
- unsigned bucket = hash_inaddr(sar->host_addr.s_addr);
+ unsigned bucket =
+ hash_addr((struct sockaddr *)&sar->host_addr);
ic = new_ipaddr_chain(p, s, sar);
ic->next = *iphash_table_tail[bucket];
@@ -646,19 +759,33 @@ API_EXPORT(void) ap_fini_vhost_config(pool *p, server_rec *main_s)
}
else {
struct hostent *h;
+ char hostnamebuf[MAXHOSTNAMELEN];
- if ((h = gethostbyaddr((char *) &(s->addrs->host_addr),
- sizeof(struct in_addr), AF_INET))) {
- s->server_hostname = ap_pstrdup(p, (char *) h->h_name);
+ if (!getnameinfo((struct sockaddr *)&s->addrs->host_addr,
+#ifndef SIN6_LEN
+ SA_LEN((struct sockaddr *)&s->addrs->host_addr),
+#else
+ s->addrs->host_addr.ss_len,
+#endif
+ hostnamebuf, sizeof(hostnamebuf),
+ NULL, 0, 0)) {
+ s->server_hostname = ap_pstrdup(p, hostnamebuf);
}
else {
/* again, what can we do? They didn't specify a
ServerName, and their DNS isn't working. -djg */
+ getnameinfo((struct sockaddr *)&s->addrs->host_addr,
+#ifndef SIN6_LEN
+ SA_LEN((struct sockaddr *)&s->addrs->host_addr),
+#else
+ s->addrs->host_addr.ss_len,
+#endif
+ hostnamebuf, sizeof(hostnamebuf),
+ NULL, 0, NI_NUMERICHOST);
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, main_s,
"Failed to resolve server name "
"for %s (check DNS) -- or specify an explicit "
- "ServerName",
- inet_ntoa(s->addrs->host_addr));
+ "ServerName", hostnamebuf);
s->server_hostname =
ap_pstrdup(p, "bogus_host_without_reverse_dns");
}
@@ -705,35 +832,58 @@ static void fix_hostname(request_rec *r)
char *host = ap_palloc(r->pool, strlen(r->hostname) + 1);
const char *src;
char *dst;
+ const char *u = NULL, *v = NULL;
/* check and copy the host part */
- src = r->hostname;
+ u = src = r->hostname;
dst = host;
- while (*src) {
- if (*src == '.') {
- *dst++ = *src++;
- if (*src == '.')
+ if (*u == '[') { /* IPv6 numeral address in brackets */
+ v = strchr(u, ']');
+ if (v == NULL) {
+ /* missing closing bracket */
+ goto bad;
+ }
+ if (v == (u + 1)) {
+ /* bad empty address */
+ goto bad;
+ }
+ for (src = u+1; src < v; src++) /* copy IPv6 adress */
+ *dst = *src;
+ v++;
+ if (*v == ':') {
+ v++;
+ while (*v) { /* check if portnum is correct */
+ if (!ap_isdigit(*v++))
+ goto bad;
+ }
+ }
+ } else {
+ while (*src) {
+ if (*src == '.') {
+ *dst++ = *src++;
+ if (*src == '.')
+ goto bad;
+ else
+ continue;
+ }
+ if (*src == '/' || *src == '\\') {
goto bad;
- else
- continue;
- }
- if (*src == '/' || *src == '\\') {
- goto bad;
- }
- if (*src == ':') {
- /* check the port part */
- while (*++src) {
- if (!ap_isdigit(*src)) {
- goto bad;
- }
- }
- if (src[-1] == ':')
- goto bad;
- else
- break;
+ }
+ if (*src == ':') {
+ /* sheck the port part */
+ while (*++src) {
+ if (!ap_isdigit(*src)) {
+ goto bad;
+ }
+ }
+ if (src[-1] == ':')
+ goto bad;
+ else
+ break;
+ }
+ *dst++ = *src++;
}
- *dst++ = *src++;
}
/* strip trailing gubbins */
if (dst > host && dst[-1] == '.') {
@@ -748,7 +898,7 @@ static void fix_hostname(request_rec *r)
bad:
r->status = HTTP_BAD_REQUEST;
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
- "Client sent malformed Host header");
+ "Client sent malformed Host header <<%s>>",u);
return;
}
@@ -851,11 +1001,23 @@ static void check_hostalias(request_rec *r)
* names we'll match have ports associated with them
*/
const char *host = r->hostname;
- unsigned port = ntohs(r->connection->local_addr.sin_port);
+ unsigned port;
server_rec *s;
server_rec *last_s;
name_chain *src;
+ switch (r->connection->local_addr.ss_family) {
+ case AF_INET:
+ port = ntohs(((struct sockaddr_in *)
+ &r->connection->local_addr)->sin_port);
+ break;
+ case AF_INET6:
+ port = ntohs(((struct sockaddr_in6 *)
+ &r->connection->local_addr)->sin6_port);
+ break;
+ default:
+ port = 0; /*XXX*/
+ }
last_s = NULL;
/* Recall that the name_chain is a list of server_addr_recs, some of
@@ -910,7 +1072,20 @@ static void check_serverpath(request_rec *r)
server_rec *s;
server_rec *last_s;
name_chain *src;
- unsigned port = ntohs(r->connection->local_addr.sin_port);
+ unsigned port;
+
+ switch (r->connection->local_addr.ss_family) {
+ case AF_INET:
+ port = ntohs(((struct sockaddr_in *)
+ &r->connection->local_addr)->sin_port);
+ break;
+ case AF_INET6:
+ port = ntohs(((struct sockaddr_in6 *)
+ &r->connection->local_addr)->sin6_port);
+ break;
+ default:
+ port = 0; /*XXX*/
+ }
/*
* This is in conjunction with the ServerPath code in http_core, so we
@@ -970,10 +1145,22 @@ API_EXPORT(void) ap_update_vhost_from_headers(request_rec *r)
API_EXPORT(void) ap_update_vhost_given_ip(conn_rec *conn)
{
ipaddr_chain *trav;
- unsigned port = ntohs(conn->local_addr.sin_port);
+ char portbuf[NI_MAXSERV];
+ unsigned port;
+
+ if (getnameinfo((struct sockaddr *)&conn->local_addr,
+#ifndef SIN6_LEN
+ SA_LEN((struct sockaddr *)&conn->local_addr),
+#else
+ conn->local_addr.ss_len,
+#endif
+ NULL, 0, portbuf, sizeof(portbuf), NI_NUMERICSERV) != 0) {
+ goto fail;
+ }
+ port = atoi(portbuf);
/* scan the hash table for an exact match first */
- trav = find_ipaddr(&conn->local_addr.sin_addr, port);
+ trav = find_ipaddr((struct sockaddr *)&conn->local_addr);
if (trav) {
/* save the name_chain for later in case this is a name-vhost */
conn->vhost_lookup_data = trav->names;
@@ -991,6 +1178,7 @@ API_EXPORT(void) ap_update_vhost_given_ip(conn_rec *conn)
return;
}
+fail:
/* otherwise we're stuck with just the main server
* and no name-based vhosts
*/
diff --git a/usr.sbin/httpd/src/main/rfc1413.c b/usr.sbin/httpd/src/main/rfc1413.c
index 7321b0d2b1c..b543e298d58 100644
--- a/usr.sbin/httpd/src/main/rfc1413.c
+++ b/usr.sbin/httpd/src/main/rfc1413.c
@@ -110,12 +110,13 @@ static void ident_timeout(int sig)
/* bind_connect - bind both ends of a socket */
/* Ambarish fix this. Very broken */
-static int get_rfc1413(int sock, const struct sockaddr_in *our_sin,
- const struct sockaddr_in *rmt_sin,
+static int get_rfc1413(int sock, const struct sockaddr *our_sin,
+ const struct sockaddr *rmt_sin,
char user[RFC1413_USERLEN+1], server_rec *srv)
{
- struct sockaddr_in rmt_query_sin, our_query_sin;
- unsigned int rmt_port, our_port;
+ struct sockaddr_storage rmt_query_sin, our_query_sin;
+ unsigned int o_rmt_port, o_our_port; /* original port pair */
+ unsigned int rmt_port, our_port; /* replied port pair */
int i;
char *cp;
char buffer[RFC1413_MAXDATA + 1];
@@ -130,13 +131,38 @@ static int get_rfc1413(int sock, const struct sockaddr_in *our_sin,
* addresses from the query socket.
*/
- our_query_sin = *our_sin;
- our_query_sin.sin_port = htons(ANY_PORT);
- rmt_query_sin = *rmt_sin;
- rmt_query_sin.sin_port = htons(RFC1413_PORT);
+#ifndef SIN6_LEN
+ memcpy(&our_query_sin, our_sin, SA_LEN(our_sin));
+ memcpy(&rmt_query_sin, rmt_sin, SA_LEN(rmt_sin));
+#else
+ memcpy(&our_query_sin, our_sin, our_sin->sa_len);
+ memcpy(&rmt_query_sin, rmt_sin, rmt_sin->sa_len);
+#endif
+ switch (our_sin->sa_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
+ o_our_port = ntohs(((struct sockaddr_in *)our_sin)->sin_port);
+ ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC1413_PORT);
+ o_rmt_port = ntohs(((struct sockaddr_in *)rmt_sin)->sin_port);
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
+ o_our_port = ntohs(((struct sockaddr_in6 *)our_sin)->sin6_port);
+ ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC1413_PORT);
+ o_rmt_port = ntohs(((struct sockaddr_in6 *)rmt_sin)->sin6_port);
+ break;
+ default:
+ /* unsupported AF */
+ return -1;
+ }
if (bind(sock, (struct sockaddr *) &our_query_sin,
- sizeof(struct sockaddr_in)) < 0) {
+#ifndef SIN6_LEN
+ SA_LEN((struct sockaddr *) &our_query_sin)
+#else
+ our_query_sin.ss_len
+#endif
+ ) < 0) {
ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
"bind: rfc1413: Error binding to local port");
return -1;
@@ -147,12 +173,18 @@ static int get_rfc1413(int sock, const struct sockaddr_in *our_sin,
* the service
*/
if (connect(sock, (struct sockaddr *) &rmt_query_sin,
- sizeof(struct sockaddr_in)) < 0)
- return -1;
+#ifndef SIN6_LEN
+ SA_LEN((struct sockaddr *) &rmt_query_sin)
+#else
+ rmt_query_sin.ss_len
+#endif
+ ) < 0) {
+ return -1;
+ }
/* send the data */
- buflen = ap_snprintf(buffer, sizeof(buffer), "%u,%u\r\n", ntohs(rmt_sin->sin_port),
- ntohs(our_sin->sin_port));
+ buflen = ap_snprintf(buffer, sizeof(buffer), "%u,%u\r\n", o_rmt_port,
+ o_our_port);
/* send query to server. Handle short write. */
i = 0;
@@ -197,9 +229,9 @@ static int get_rfc1413(int sock, const struct sockaddr_in *our_sin,
/* RFC1413_USERLEN = 512 */
if (sscanf(buffer, "%u , %u : USERID :%*[^:]:%512s", &rmt_port, &our_port,
- user) != 3 || ntohs(rmt_sin->sin_port) != rmt_port
- || ntohs(our_sin->sin_port) != our_port)
+ user) != 3 || o_rmt_port != rmt_port || o_our_port != our_port) {
return -1;
+ }
/*
* Strip trailing carriage return. It is part of the
@@ -221,7 +253,7 @@ API_EXPORT(char *) ap_rfc1413(conn_rec *conn, server_rec *srv)
result = FROM_UNKNOWN;
- sock = ap_psocket_ex(conn->pool, AF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
+ sock = ap_psocket_ex(conn->pool, conn->remote_addr.ss_family, SOCK_STREAM, IPPROTO_TCP, 1);
if (sock < 0) {
ap_log_error(APLOG_MARK, APLOG_CRIT, srv,
"socket: rfc1413: error creating socket");
@@ -234,8 +266,10 @@ API_EXPORT(char *) ap_rfc1413(conn_rec *conn, server_rec *srv)
if (ap_setjmp(timebuf) == 0) {
ap_set_callback_and_alarm(ident_timeout, ap_rfc1413_timeout);
- if (get_rfc1413(sock, &conn->local_addr, &conn->remote_addr, user, srv) >= 0)
+ if (get_rfc1413(sock, (struct sockaddr *)&conn->local_addr,
+ (struct sockaddr *)&conn->remote_addr, user, srv) >= 0) {
result = user;
+ }
}
ap_set_callback_and_alarm(NULL, 0);
ap_pclosesocket(conn->pool, sock);
diff --git a/usr.sbin/httpd/src/main/util.c b/usr.sbin/httpd/src/main/util.c
index 556416fa4dc..a473eee9f74 100644
--- a/usr.sbin/httpd/src/main/util.c
+++ b/usr.sbin/httpd/src/main/util.c
@@ -1854,52 +1854,87 @@ API_EXPORT(gid_t) ap_gname2id(const char *name)
* Parses a host of the form <address>[:port]
* :port is permitted if 'port' is not NULL
*/
-API_EXPORT(unsigned long) ap_get_virthost_addr(char *w, unsigned short *ports)
-{
- struct hostent *hep;
- unsigned long my_addr;
- char *p;
-
- p = strchr(w, ':');
+API_EXPORT(struct sockaddr *) ap_get_virthost_addr(char *w, unsigned short *ports)
+{
+ static struct sockaddr_storage ss;
+ struct addrinfo hints, *res;
+ char *p, *r;
+ char *host;
+ char *port = "0";
+ int error;
+ char servbuf[NI_MAXSERV];
+
+ if (w == NULL)
+ w = "*";
+ p = r = NULL;
+ if (*w == '['){
+ if (r = strrchr(w+1, ']')){
+ *r = '\0';
+ p = r + 1;
+ switch(*p){
+ case ':':
+ p++;
+ /* nobreak; */
+ case '\0':
+ w++;
+ break;
+ default:
+ p = NULL;
+ }
+ }
+ }
+ else{
+ p = strchr(w, ':');
+ if (p != NULL && strchr(p+1, ':') != NULL)
+ p = NULL;
+ }
if (ports != NULL) {
- *ports = 0;
- if (p != NULL && strcmp(p + 1, "*") != 0)
- *ports = atoi(p + 1);
+ if (p != NULL && *p && strcmp(p + 1, "*") != 0)
+ port = p + 1;
}
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
if (p != NULL)
*p = '\0';
if (strcmp(w, "*") == 0) {
- if (p != NULL)
- *p = ':';
- return htonl(INADDR_ANY);
- }
-
- my_addr = ap_inet_addr((char *)w);
- if (my_addr != INADDR_NONE) {
- if (p != NULL)
- *p = ':';
- return my_addr;
+ host = NULL;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = ap_default_family;
+ } else {
+ host = w;
+ hints.ai_family = PF_UNSPEC;
}
- hep = gethostbyname(w);
+ error = getaddrinfo(host, port, &hints, &res);
- if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
- fprintf(stderr, "Cannot resolve host name %s --- exiting!\n", w);
+ if (error || !res) {
+ fprintf(stderr, "ap_get_vitrhost_addr(): getaddrinfo(%s):%s --- exiting!\n", w, gai_strerror(error));
exit(1);
}
- if (hep->h_addr_list[1]) {
- fprintf(stderr, "Host %s has multiple addresses ---\n", w);
+ if (res->ai_next) {
+ fprintf(stderr, "ap_get_vitrhost_addr(): Host %s has multiple addresses ---\n", w);
fprintf(stderr, "you must choose one explicitly for use as\n");
fprintf(stderr, "a virtual host. Exiting!!!\n");
exit(1);
}
+ if (r != NULL)
+ *r = ']';
if (p != NULL)
*p = ':';
- return ((struct in_addr *) (hep->h_addr))->s_addr;
+ memcpy(&ss, res->ai_addr, res->ai_addrlen);
+ if (getnameinfo(res->ai_addr, res->ai_addrlen,
+ NULL, 0, servbuf, sizeof(servbuf),
+ NI_NUMERICSERV)){
+ fprintf(stderr, "ap_get_virthost_addr(): getnameinfo() failed --- Exiting!!!\n");
+ exit(1);
+ }
+ if (ports) *ports = atoi(servbuf);
+ freeaddrinfo(res);
+ return (struct sockaddr *)&ss;
}
@@ -1927,7 +1962,8 @@ API_EXPORT(char *) ap_get_local_host(pool *a)
#endif
char str[MAXHOSTNAMELEN];
char *server_hostname = NULL;
- struct hostent *p;
+ struct addrinfo hints, *res;
+ int error;
if (gethostname(str, sizeof(str) - 1) != 0) {
ap_log_error(APLOG_MARK, APLOG_WARNING, NULL,
@@ -1936,23 +1972,25 @@ API_EXPORT(char *) ap_get_local_host(pool *a)
}
else
{
- str[sizeof(str) - 1] = '\0';
- if ((!(p = gethostbyname(str)))
- || (!(server_hostname = find_fqdn(a, p)))) {
- if (p == NULL || p->h_addr_list == NULL)
- server_hostname=NULL;
- else {
- /* Recovery - return the default servername by IP: */
- if (p->h_addr_list[0]) {
- ap_snprintf(str, sizeof(str), "%pA", p->h_addr_list[0]);
- server_hostname = ap_pstrdup(a, str);
- /* We will drop through to report the IP-named server */
- }
- }
- }
+ str[sizeof(str) - 1] = '\0';
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_CANONNAME;
+ res = NULL;
+ error = getaddrinfo(str, NULL, &hints, &res);
+ if (error == 0 && res)
+ {
+ /* Since we found a fqdn, rturn it with no logged message. */
+ server_hostname = ap_pstrdup(a, res->ai_canonname);
+ freeaddrinfo(res);
+ return server_hostname;
+ }
else
- /* Since we found a fqdn, return it with no logged message. */
- return server_hostname;
+ {
+ /* Recovery - return the default server by IP: */
+ server_hostname = ap_pstrdup(a, str);
+ /* We will drop through to report the IP-named server */
+ }
}
/* If we don't have an fqdn or IP, fall back to the loopback addr */
@@ -1964,6 +2002,8 @@ API_EXPORT(char *) ap_get_local_host(pool *a)
"domain name, using %s for ServerName",
ap_server_argv0, server_hostname);
+ if (res)
+ freeaddrinfo(res);
return server_hostname;
}
diff --git a/usr.sbin/httpd/src/main/util_script.c b/usr.sbin/httpd/src/main/util_script.c
index 7029c1f6e73..de946c0ec92 100644
--- a/usr.sbin/httpd/src/main/util_script.c
+++ b/usr.sbin/httpd/src/main/util_script.c
@@ -196,6 +196,7 @@ API_EXPORT(void) ap_add_common_vars(request_rec *r)
array_header *hdrs_arr = ap_table_elts(r->headers_in);
table_entry *hdrs = (table_entry *) hdrs_arr->elts;
int i;
+ char servbuf[NI_MAXSERV];
/* use a temporary table which we'll overlap onto
* r->subprocess_env later
@@ -258,8 +259,16 @@ API_EXPORT(void) ap_add_common_vars(request_rec *r)
ap_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
ap_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */
- ap_table_addn(e, "REMOTE_PORT",
- ap_psprintf(r->pool, "%d", ntohs(c->remote_addr.sin_port)));
+ servbuf[0] = '\0';
+ if (!getnameinfo((struct sockaddr *)&c->remote_addr,
+#ifndef HAVE_SOCKADDR_LEN
+ SA_LEN((struct sockaddr *)&c->remote_addr),
+#else
+ c->remote_addr.ss_len,
+#endif
+ NULL, 0, servbuf, sizeof(servbuf), NI_NUMERICSERV)){
+ ap_table_addn(e, "REMOTE_PORT", ap_pstrdup(r->pool, servbuf));
+ }
if (c->user) {
ap_table_addn(e, "REMOTE_USER", c->user);
diff --git a/usr.sbin/httpd/src/main/util_uri.c b/usr.sbin/httpd/src/main/util_uri.c
index 6daf5fcdb65..18554a0f685 100644
--- a/usr.sbin/httpd/src/main/util_uri.c
+++ b/usr.sbin/httpd/src/main/util_uri.c
@@ -410,45 +410,50 @@ API_EXPORT(int) ap_parse_uri_components(pool *p, const char *uri,
* &hostinfo[-1] < &hostinfo[0] ... and this loop is valid C.
*/
do {
- --s;
+ --s;
} while (s >= hostinfo && *s != '@');
if (s < hostinfo) {
- /* again we want the common case to be fall through */
- deal_with_host:
- /* We expect hostinfo to point to the first character of
- * the hostname. If there's a port it is the first colon.
- */
- s = memchr(hostinfo, ':', uri - hostinfo);
- if (s == NULL) {
- /* we expect the common case to have no port */
- uptr->hostname = ap_pstrndup(p, hostinfo, uri - hostinfo);
- goto deal_with_path;
- }
- uptr->hostname = ap_pstrndup(p, hostinfo, s - hostinfo);
- ++s;
- uptr->port_str = ap_pstrndup(p, s, uri - s);
- if (uri != s) {
- port = ap_strtol(uptr->port_str, &endstr, 10);
- uptr->port = port;
- if (*endstr == '\0') {
- goto deal_with_path;
- }
- /* Invalid characters after ':' found */
- return HTTP_BAD_REQUEST;
- }
- uptr->port = ap_default_port_for_scheme(uptr->scheme);
- goto deal_with_path;
+ /* again we want the common case to be fall through */
+deal_with_host:
+ /* We expect hostinfo to point to the first character of
+ * the hostname. If there's a port it is the first colon.
+ */
+ if (*hostinfo == '[') {
+ s = memchr(hostinfo+1, ']', uri - hostinfo - 1);
+ if (s)
+ s = strchr(s, ':');
+ } else
+ s = memchr(hostinfo, ':', uri - hostinfo);
+ if (s == NULL) {
+ /* we expect the common case to have no port */
+ uptr->hostname = ap_pstrndup(p, hostinfo, uri - hostinfo);
+ goto deal_with_path;
+ }
+ uptr->hostname = ap_pstrndup(p, hostinfo, s - hostinfo);
+ ++s;
+ uptr->port_str = ap_pstrndup(p, s, uri - s);
+ if (uri != s) {
+ port = ap_strtol(uptr->port_str, &endstr, 10);
+ uptr->port = port;
+ if (*endstr == '\0') {
+ goto deal_with_path;
+ }
+ /* Invalid characters after ':' found */
+ return HTTP_BAD_REQUEST;
+ }
+ uptr->port = ap_default_port_for_scheme(uptr->scheme);
+ goto deal_with_path;
}
/* first colon delimits username:password */
s1 = memchr(hostinfo, ':', s - hostinfo);
if (s1) {
- uptr->user = ap_pstrndup(p, hostinfo, s1 - hostinfo);
- ++s1;
- uptr->password = ap_pstrndup(p, s1, s - s1);
+ uptr->user = ap_pstrndup(p, hostinfo, s1 - hostinfo);
+ ++s1;
+ uptr->password = ap_pstrndup(p, s1, s - s1);
}
else {
- uptr->user = ap_pstrndup(p, hostinfo, s - hostinfo);
+ uptr->user = ap_pstrndup(p, hostinfo, s - hostinfo);
}
hostinfo = s + 1;
goto deal_with_host;
@@ -475,7 +480,12 @@ API_EXPORT(int) ap_parse_hostinfo_components(pool *p, const char *hostinfo,
/* We expect hostinfo to point to the first character of
* the hostname. There must be a port, separated by a colon
*/
- s = strchr(hostinfo, ':');
+ if (*hostinfo == '[') {
+ s = strchr(hostinfo+1, ']');
+ if (s)
+ s = strchr(s, ':');
+ } else
+ s = strchr(hostinfo, ':');
if (s == NULL) {
return HTTP_BAD_REQUEST;
}
diff --git a/usr.sbin/httpd/src/modules/proxy/mod_proxy.c b/usr.sbin/httpd/src/modules/proxy/mod_proxy.c
index 5206151041d..42f070ccb15 100644
--- a/usr.sbin/httpd/src/modules/proxy/mod_proxy.c
+++ b/usr.sbin/httpd/src/modules/proxy/mod_proxy.c
@@ -565,11 +565,31 @@ static const char *
struct proxy_remote *new;
char *p, *q;
int port;
+ char *bl = NULL, *br = NULL;
p = strchr(r, ':');
if (p == NULL || p[1] != '/' || p[2] != '/' || p[3] == '\0')
- return "ProxyRemote: Bad syntax for a remote proxy server";
- q = strchr(p + 3, ':');
+ return "ProxyRemote: Bad syntax for a remote proxy server";
+ bl = p + 3;
+ if (*bl == '['){
+ br = strrchr(bl+1, ']');
+ if (br){
+ bl++;
+ *br = '\0';
+ if (*(br+1) == ':'){ /* [host]:xx */
+ q = br+1;
+ }
+ else if (*(br+1) == '\0'){ /* [host] */
+ q = NULL;
+ }
+ else
+ q = strrchr(br, ':'); /* XXX */
+ }
+ else
+ q = strrchr(bl, ':'); /* XXX */
+ }
+ else
+ q = strrchr(bl, ':');
if (q != NULL) {
if (sscanf(q + 1, "%u", &port) != 1 || port > 65535)
return "ProxyRemote: Bad syntax for a remote proxy server (bad port number)";
@@ -580,7 +600,7 @@ static const char *
*p = '\0';
if (strchr(f, ':') == NULL)
ap_str_tolower(f); /* lowercase scheme */
- ap_str_tolower(p + 3); /* lowercase hostname */
+ ap_str_tolower(bl); /* lowercase hostname */
if (port == -1) {
int i;
@@ -593,7 +613,7 @@ static const char *
new = ap_push_array(conf->proxies);
new->scheme = f;
new->protocol = r;
- new->hostname = p + 3;
+ new->hostname = bl;
new->port = port;
return NULL;
}
diff --git a/usr.sbin/httpd/src/modules/proxy/mod_proxy.h b/usr.sbin/httpd/src/modules/proxy/mod_proxy.h
index 78e9b17c919..adacd729449 100644
--- a/usr.sbin/httpd/src/modules/proxy/mod_proxy.h
+++ b/usr.sbin/httpd/src/modules/proxy/mod_proxy.h
@@ -312,7 +312,7 @@ int ap_proxy_is_ipaddr(struct dirconn_entry *This, pool *p);
int ap_proxy_is_domainname(struct dirconn_entry *This, pool *p);
int ap_proxy_is_hostname(struct dirconn_entry *This, pool *p);
int ap_proxy_is_word(struct dirconn_entry *This, pool *p);
-int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r);
+int ap_proxy_doconnect(int sock, struct sockaddr *addr, request_rec *r);
int ap_proxy_garbage_init(server_rec *, pool *);
/* This function is called by ap_table_do() for all header lines */
int ap_proxy_send_hdr_line(void *p, const char *key, const char *value);
diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_connect.c b/usr.sbin/httpd/src/modules/proxy/proxy_connect.c
index 6e802651bbf..42b39a33bfc 100644
--- a/usr.sbin/httpd/src/modules/proxy/proxy_connect.c
+++ b/usr.sbin/httpd/src/modules/proxy/proxy_connect.c
@@ -109,14 +109,15 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
const char *proxyhost, int proxyport)
{
struct sockaddr_in server;
- struct in_addr destaddr;
- struct hostent server_hp;
- const char *host, *err;
+ struct addrinfo hints, *res, *res0;
+ const char *hoststr;
+ const char *portstr = NULL;
char *p;
int port, sock;
char buffer[HUGE_STRING_LEN];
- int nbytes, i, j;
+ int nbytes, i;
fd_set fds;
+ int error;
void *sconf = r->server->module_config;
proxy_server_conf *conf =
@@ -124,27 +125,60 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
memset(&server, '\0', sizeof(server));
+#ifdef HAVE_SOCKADDR_LEN
+ server.sin_len = sizeof(server);
+#endif
server.sin_family = AF_INET;
/* Break the URL into host:port pairs */
- host = url;
+ hoststr = url;
p = strchr(url, ':');
- if (p == NULL)
- port = DEFAULT_HTTPS_PORT;
- else {
- port = atoi(p + 1);
- *p = '\0';
+ if (p == NULL) {
+ char pbuf[32];
+ ap_snprintf(pbuf, sizeof(pbuf), "%d", DEFAULT_HTTPS_PORT);
+ portstr = pbuf;
+ } else {
+ portstr = p + 1;
+ *p = '\0';
+ }
+ port = atoi(portstr);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ error = getaddrinfo(hoststr, portstr, &hints, &res0);
+ if (error && proxyhost == NULL) {
+ return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ gai_strerror(error)); /* give up */
}
/* check if ProxyBlock directive on this host */
- destaddr.s_addr = ap_inet_addr(host);
for (i = 0; i < conf->noproxies->nelts; i++) {
- if ((npent[i].name != NULL && strstr(host, npent[i].name) != NULL)
- || destaddr.s_addr == npent[i].addr.s_addr
- || npent[i].name[0] == '*')
- return ap_proxyerror(r, HTTP_FORBIDDEN,
- "Connect to remote machine blocked");
+ int fail;
+ struct sockaddr_in *sin;
+
+ fail = 0;
+ if (npent[i].name != NULL && strstr(hoststr, npent[i].name))
+ fail++;
+ if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0)
+ fail++;
+ for (res = res0; res; res = res->ai_next) {
+ switch (res->ai_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)res->ai_addr;
+ if (sin->sin_addr.s_addr == npent[i].addr.s_addr)
+ fail++;
+ break;
+ }
+ }
+ if (fail) {
+ if (res0 != NULL)
+ freeaddrinfo(res0);
+ return ap_proxyerror(r, HTTP_FORBIDDEN,
+ "Connect to remote machine blocked");
+ }
}
/* Check if it is an allowed port */
@@ -155,54 +189,60 @@ int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url,
case DEFAULT_SNEWS_PORT:
break;
default:
+ if (res0 != NULL)
+ freeaddrinfo(res0);
return HTTP_FORBIDDEN;
}
}
- else if (!allowed_port(conf, port))
+ else if(!allowed_port(conf, port)) {
+ if (res0 != NULL)
+ freeaddrinfo(res0);
return HTTP_FORBIDDEN;
+ }
if (proxyhost) {
+ char pbuf[10];
+
+ if (res0 != NULL)
+ freeaddrinfo(res0);
+ ap_snprintf(pbuf, sizeof(pbuf), "%d", proxyport);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ error = getaddrinfo(proxyhost, pbuf, &hints, &res0);
+ if (error)
+ return HTTP_INTERNAL_SERVER_ERROR; /* XXX */
+
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
- "CONNECT to remote proxy %s on port %d", proxyhost, proxyport);
+ "CONNECT to remote proxy %s on port %d", proxyhost, proxyport);
}
else {
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
- "CONNECT to %s on port %d", host, port);
+ "CONNECT to %s on port %d", hoststr, port);
}
- /* Nasty cast to work around broken terniary expressions on MSVC */
- server.sin_port = htons((unsigned short)(proxyport ? proxyport : port));
- err = ap_proxy_host2addr(proxyhost ? proxyhost : host, &server_hp);
+ sock = i = -1;
+ for (res = res0; res; res = res->ai_next) {
+ sock = ap_psocket(r->pool, res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (sock == -1)
+ continue;
- if (err != NULL)
- return ap_proxyerror(r,
- proxyhost ? HTTP_BAD_GATEWAY : HTTP_INTERNAL_SERVER_ERROR, err);
+ if (sock >= FD_SETSIZE) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_WARNING, NULL,
+ "proxy_connect_handler: filedescriptor (%u) "
+ "larger than FD_SETSIZE (%u) "
+ "found, you probably need to rebuild Apache with a "
+ "larger FD_SETSIZE", sock, FD_SETSIZE);
+ ap_pclosesocket(r->pool, sock);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
- sock = ap_psocket_ex(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
- if (sock == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: error creating socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (sock >= FD_SETSIZE) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_WARNING, NULL,
- "proxy_connect_handler: filedescriptor (%u) "
- "larger than FD_SETSIZE (%u) "
- "found, you probably need to rebuild Apache with a "
- "larger FD_SETSIZE", sock, FD_SETSIZE);
- ap_pclosesocket(r->pool, sock);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- j = 0;
- while (server_hp.h_addr_list[j] != NULL) {
- memcpy(&server.sin_addr, server_hp.h_addr_list[j],
- sizeof(struct in_addr));
- i = ap_proxy_doconnect(sock, &server, r);
- if (i == 0)
- break;
- j++;
+ i = ap_proxy_doconnect(sock, res->ai_addr, r);
+ if (i == 0)
+ break;
}
+ freeaddrinfo(res0);
if (i == -1) {
ap_pclosesocket(r->pool, sock);
return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, ap_pstrcat(r->pool,
diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c b/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c
index cbd976ac131..9c5d6b4ca01 100644
--- a/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c
+++ b/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c
@@ -556,8 +556,10 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
const char *err;
int destport, i, j, len, rc, nocache = 0;
int csd = 0, sock = -1, dsock = -1;
- struct sockaddr_in server;
- struct hostent server_hp;
+ struct sockaddr_storage server;
+ struct addrinfo hints, *res, *res0;
+ char portbuf[10];
+ int error;
struct in_addr destaddr;
table *resp_hdrs;
BUFF *ctrl = NULL;
@@ -580,10 +582,17 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
unsigned int presult, h0, h1, h2, h3, p0, p1;
unsigned int paddr;
unsigned short pport;
- struct sockaddr_in data_addr;
+ struct sockaddr_storage data_addr;
+ struct sockaddr_in *sin;
int pasvmode = 0;
char pasv[64];
- char *pstr;
+ char *pstr, *host, *port;
+
+/* stuff for LPSV/EPSV */
+ unsigned int paf, holen, ho[16], polen, po[2];
+ struct sockaddr_in6 *sin6;
+ int lpsvmode = 0;
+ char *cmd;
/* stuff for responses */
char resp[MAX_STRING_LEN];
@@ -596,6 +605,17 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
/* We break the URL into host, port, path-search */
+ host = r->parsed_uri.hostname;
+ port = (r->parsed_uri.port != 0)
+ ? r->parsed_uri.port
+ : ap_default_port_for_request(r);
+ path = ap_pstrdup(p, r->parsed_uri.path);
+ if (path == NULL)
+ path = "";
+ else
+ while (*path == '/')
+ ++path;
+
urlptr = strstr(url, "://");
if (urlptr == NULL)
return HTTP_BAD_REQUEST;
@@ -678,20 +698,22 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
if (parms != NULL)
*(parms++) = '\0';
- memset(&server, 0, sizeof(struct sockaddr_in));
- server.sin_family = AF_INET;
- server.sin_port = htons((unsigned short)destport);
- err = ap_proxy_host2addr(desthost, &server_hp);
- if (err != NULL)
- return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
-
- sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
- if (sock == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
- "proxy: error creating socket");
- return HTTP_INTERNAL_SERVER_ERROR;
+ ap_snprintf(portbuf, sizeof(portbuf), "%d", port);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(host, portbuf, &hints, &res0);
+ if (error) {
+ return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ gai_strerror(error));
}
+ i = -1;
+ for (res = res0; res; res = res->ai_next) {
+ dsock = ap_psocket(p, server.ss_family, SOCK_STREAM, res->ai_protocol);
+ if (sock == -1)
+ continue;
+
if (conf->recv_buffer_size > 0
&& setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
(const char *)&conf->recv_buffer_size, sizeof(int))
@@ -705,18 +727,18 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
"proxy: error setting reuseaddr option: setsockopt(SO_REUSEADDR)");
ap_pclosesocket(p, sock);
+ freeaddrinfo(res0);
return HTTP_INTERNAL_SERVER_ERROR;
}
- j = 0;
- while (server_hp.h_addr_list[j] != NULL) {
- memcpy(&server.sin_addr, server_hp.h_addr_list[j],
- sizeof(struct in_addr));
- i = ap_proxy_doconnect(sock, &server, r);
- if (i == 0)
+ i = ap_proxy_doconnect(sock, res->ai_addr, r);
+ if (i == 0){
+ memcpy(&server, res->ai_addr, res->ai_addrlen);
break;
- j++;
+ }
+ ap_pclosesocket(p, sock);
}
+ freeaddrinfo(res0);
if (i == -1) {
return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,
@@ -941,11 +963,21 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
}
}
- ap_bputs("PASV" CRLF, ctrl);
+lpsvagain:
+ if (server.ss_family == AF_INET)
+ cmd = "PASV";
+ else if (lpsvmode)
+ cmd = "LPSV";
+ else
+ cmd = "EPSV";
+ ap_bputs(cmd, ctrl);
+ ap_bputs(CRLF, ctrl);
ap_bflush(ctrl);
- ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: PASV command issued");
+ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: passive command issued");
/* possible results: 227, 421, 500, 501, 502, 530 */
/* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
+ /* 228 Entering Long Passive Mode (...). */
+ /* 229 Entering Extended Passive Mode (...). */
/* 421 Service not available, closing control connection. */
/* 500 Syntax error, command unrecognized. */
/* 501 Syntax error in parameters or arguments. */
@@ -956,7 +988,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
if (i == -1 || i == 421) {
return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
- "proxy: PASV: control connection is toast"));
+ "proxy: passive: control connection is toast"));
}
else {
pasv[i - 1] = '\0';
@@ -984,10 +1016,14 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
pport = (p1 << 8) + p0;
ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "FTP: contacting host %d.%d.%d.%d:%d",
h3, h2, h1, h0, pport);
- data_addr.sin_family = AF_INET;
- data_addr.sin_addr.s_addr = htonl(paddr);
- data_addr.sin_port = htons(pport);
- i = ap_proxy_doconnect(dsock, &data_addr, r);
+ sin = (struct sockaddr_in *)&data_addr;
+ sin->sin_family = AF_INET;
+#ifdef SIN6_LEN
+ sin->sin_len = sizeof(*sin);
+#endif
+ sin->sin_addr.s_addr = htonl(paddr);
+ sin->sin_port = htons(pport);
+ i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r);
if (i == -1) {
return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
@@ -997,6 +1033,64 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
strerror(errno), NULL)));
}
pasvmode = 1;
+ } else if (presult == 228 && pstr != NULL
+ && sscanf(pstr,
+"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
+ &paf, &holen, &ho[0], &ho[1], &ho[2], &ho[3],
+ &ho[4], &ho[5], &ho[6], &ho[7], &ho[8], &ho[9], &ho[10], &ho[11],
+ &ho[12], &ho[13], &ho[14], &ho[15], &polen, &po[0], &po[1]) == 21
+ && paf == 6 && holen == 16 && polen == 2) {
+ int i;
+ sin6 = (struct sockaddr_in6 *)&data_addr;
+ sin6->sin6_family = AF_INET6;
+#ifdef SIN6_LEN
+ sin6->sin6_len = sizeof(*sin6);
+#endif
+ for (i = 0; i < 16; i++)
+ sin6->sin6_addr.s6_addr[i] = ho[i] & 0xff;
+ sin6->sin6_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff));
+ i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r);
+
+ if (i == -1) {
+ ap_kill_timeout(r);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ ap_pstrcat(r->pool,
+ "Could not connect to remote machine: ",
+ strerror(errno), NULL));
+ }
+ pasvmode = 1;
+ } else if (presult == 229 && pstr != NULL
+ && pstr[0] == pstr[1] && pstr[0] == pstr[2]
+ && pstr[0] == pstr[strlen(pstr) - 1]) {
+ /* expect "|||port|" */
+#ifndef SIN6_LEN
+ memcpy(&data_addr, &server, SA_LEN((struct sockaddr *)&server));
+#else
+ memcpy(&data_addr, &server, server.ss_len);
+#endif
+ switch (data_addr.ss_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)&data_addr;
+ sin->sin_port = htons(atoi(pstr + 3));
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&data_addr;
+ sin6->sin6_port = htons(atoi(pstr + 3));
+ break;
+ }
+ i = ap_proxy_doconnect(dsock, (struct sockaddr *)&data_addr, r);
+
+ if (i == -1) {
+ ap_kill_timeout(r);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ ap_pstrcat(r->pool,
+ "Could not connect to remote machine: ",
+ strerror(errno), NULL));
+ }
+ pasvmode = 1;
+ } else if (!lpsvmode && strcmp(cmd, "EPSV") == 0) {
+ lpsvmode = 1;
+ goto lpsvagain;
}
else {
ap_pclosesocket(p, dsock); /* and try the regular way */
@@ -1005,14 +1099,14 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
}
if (!pasvmode) { /* set up data connection */
- clen = sizeof(struct sockaddr_in);
+ clen = sizeof(server);
if (getsockname(sock, (struct sockaddr *)&server, &clen) < 0) {
return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
"proxy: error getting socket address"));
}
- dsock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
+ dsock = ap_psocket_ex(p, server.ss_family, SOCK_STREAM, IPPROTO_TCP, 1);
if (dsock == -1) {
return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
@@ -1026,13 +1120,28 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
"proxy: error setting reuseaddr option"));
}
- if (bind(dsock, (struct sockaddr *)&server,
- sizeof(struct sockaddr_in)) == -1) {
+#ifndef SIN6_LEN
+ if (bind(dsock, (struct sockaddr *) &server, SA_LEN((struct sockaddr *)&server)) == -1)
+#else
+ if (bind(dsock, (struct sockaddr *) &server, server.ss_len) == -1)
+#endif
+ {
+ char hostnamebuf[MAXHOSTNAMELEN], portnamebuf[MAXHOSTNAMELEN];
+
+ getnameinfo((struct sockaddr *)&server,
+#ifndef SIN6_LEN
+ SA_LEN((struct sockaddr *)&server),
+#else
+ server.ss_len,
+#endif
+ hostnamebuf, sizeof(hostnamebuf),
+ portnamebuf, sizeof(portnamebuf),
+ NI_NUMERICHOST | NI_NUMERICSERV);
return ftp_cleanup_and_return(r, ctrl, data, sock, dsock,
- ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
- ap_psprintf(p, "proxy: error binding to ftp data socket %s:%d",
- inet_ntoa(server.sin_addr), server.sin_port)));
+ ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ ap_psprintf(p, "proxy: error binding to ftp data socket %s:%s",
+ hostnamebuf, portnamebuf)));
}
listen(dsock, 2); /* only need a short queue */
}
@@ -1279,7 +1388,7 @@ int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url)
if (!pasvmode) { /* wait for connection */
ap_hard_timeout("proxy ftp data connect", r);
- clen = sizeof(struct sockaddr_in);
+ clen = sizeof(server);
do
csd = accept(dsock, (struct sockaddr *)&server, &clen);
while (csd == -1 && errno == EINTR);
diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_http.c b/usr.sbin/httpd/src/modules/proxy/proxy_http.c
index 46630aafe32..6f0b96b5fe5 100644
--- a/usr.sbin/httpd/src/modules/proxy/proxy_http.c
+++ b/usr.sbin/httpd/src/modules/proxy/proxy_http.c
@@ -151,23 +151,21 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
{
const char *strp;
char *strp2;
- const char *err, *desthost, *hostname;
+ const char *err, *desthost;
int i, j, sock,/* len,*/ backasswards;
table *req_hdrs, *resp_hdrs;
array_header *reqhdrs_arr;
table_entry *reqhdrs_elts;
- struct sockaddr_in server;
- struct in_addr destaddr;
- struct hostent server_hp;
BUFF *f;
char buffer[HUGE_STRING_LEN];
char portstr[32];
pool *p = r->pool;
- int destport = 0;
- int chunked = 0;
+ int chunked = 0, destport = 0;
char *destportstr = NULL;
const char *urlptr = NULL;
const char *datestr, *urlstr;
+ struct addrinfo hints, *res, *res0;
+ int error;
int result, major, minor;
const char *content_length;
char *peer;
@@ -182,20 +180,19 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
if (conf->cache.root == NULL)
nocache = 1;
- memset(&server, '\0', sizeof(server));
- server.sin_family = AF_INET;
-
/* We break the URL into host, port, path-search */
urlptr = strstr(url, "://");
if (urlptr == NULL)
return HTTP_BAD_REQUEST;
- urlptr += 3;
destport = DEFAULT_HTTP_PORT;
+ urlptr += 3;
ap_hook_use("ap::mod_proxy::http::handler::set_destport",
AP_HOOK_SIG2(int,ptr),
AP_HOOK_TOPMOST,
&destport, r);
+ ap_snprintf(portstr, sizeof(portstr), "%d", DEFAULT_HTTP_PORT);
+ destportstr = portstr;
strp = strchr(urlptr, '/');
if (strp == NULL) {
desthost = ap_pstrdup(p, urlptr);
@@ -208,39 +205,88 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
urlptr = strp;
desthost = q;
}
+ if (*desthost == '['){
+ char *u = strrchr(desthost+1, ']');
+ if (u){
+ desthost++;
+ *u = '\0';
+ if (*(u+1) == ':'){ /* [host]:xx */
+ strp2 = u+1;
+ }
+ else if (*(u+1) == '\0'){ /* [host] */
+ strp2 = NULL;
+ }
+ else
+ return HTTP_BAD_REQUEST;
+ }
+ else
+ return HTTP_BAD_REQUEST;
+ }
+ else
+ strp2 = strrchr(desthost, ':');
- strp2 = strchr(desthost, ':');
if (strp2 != NULL) {
*(strp2++) = '\0';
- if (ap_isdigit(*strp2)) {
- destport = atoi(strp2);
+ if (ap_isdigit(*strp2))
destportstr = strp2;
- }
}
-
- /* check if ProxyBlock directive on this host */
- destaddr.s_addr = ap_inet_addr(desthost);
- for (i = 0; i < conf->noproxies->nelts; i++) {
- if (destaddr.s_addr == npent[i].addr.s_addr ||
- (npent[i].name != NULL &&
- (npent[i].name[0] == '*' || strstr(desthost, npent[i].name) != NULL)))
- return ap_proxyerror(r, HTTP_FORBIDDEN,
- "Connect to remote machine blocked");
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ error = getaddrinfo(desthost, destportstr, &hints, &res0);
+ if (error && proxyhost == NULL) {
+ return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR,
+ gai_strerror(error)); /* give up */
+ }
+
+ /* check if ProxyBlock directive on this host */
+ for (i = 0; i < conf->noproxies->nelts; i++) {
+ int fail;
+ struct sockaddr_in *sin;
+
+ fail = 0;
+ if (npent[i].name != NULL && strstr(desthost, npent[i].name))
+ fail++;
+ if (npent[i].name != NULL && strcmp(npent[i].name, "*") == 0)
+ fail++;
+ for (res = res0; res; res = res->ai_next) {
+ switch (res->ai_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)res->ai_addr;
+ if (sin->sin_addr.s_addr == npent[i].addr.s_addr)
+ fail++;
+ break;
+
+ }
+ }
+ if (fail) {
+ if (res0 != NULL)
+ freeaddrinfo(res0);
+ return ap_proxyerror(r, HTTP_FORBIDDEN,
+ "Connect to remote machine blocked");
+ }
}
-
if (proxyhost != NULL) {
- server.sin_port = htons((unsigned short)proxyport);
- err = ap_proxy_host2addr(proxyhost, &server_hp);
- if (err != NULL)
- return DECLINED; /* try another */
- peer = ap_psprintf(p, "%s:%u", proxyhost, proxyport);
+ char pbuf[10];
+
+ if (res0 != NULL)
+ freeaddrinfo(res0);
+
+ ap_snprintf(pbuf, sizeof(pbuf), "%d", proxyport);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ error = getaddrinfo(proxyhost, pbuf, &hints, &res0);
+ if (error)
+ return DECLINED; /* try another */
}
- else {
- server.sin_port = htons((unsigned short)destport);
- err = ap_proxy_host2addr(desthost, &server_hp);
- if (err != NULL)
- return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);
- peer = ap_psprintf(p, "%s:%u", desthost, destport);
+
+
+ /* check if ProxyBlock directive on this host */
+ for (i = 0; i < conf->noproxies->nelts; i++) {
+ peer = ap_psprintf(p, "%s:%s", desthost, destportstr);
}
@@ -248,31 +294,29 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
* we have worked out who exactly we are going to connect to, now make
* that connection...
*/
- sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);
- if (sock == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
- "proxy: error creating socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (conf->recv_buffer_size) {
- if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
- (const char *)&conf->recv_buffer_size, sizeof(int))
- == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
- "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
- }
+ sock = i = -1;
+ for (res = res0; res; res = res->ai_next) {
+ sock = ap_psocket(p, res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (sock < 0)
+ continue;
+
+ if (conf->recv_buffer_size) {
+ if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+ (const char *)&conf->recv_buffer_size, sizeof(int))
+ == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+ "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
+ }
+ }
+
+ i = ap_proxy_doconnect(sock, res->ai_addr, r);
+ if (i == 0)
+ break;
+ ap_pclosesocket(p, sock);
}
+ freeaddrinfo(res0);
- j = 0;
- while (server_hp.h_addr_list[j] != NULL) {
- memcpy(&server.sin_addr, server_hp.h_addr_list[j],
- sizeof(struct in_addr));
- i = ap_proxy_doconnect(sock, &server, r);
- if (i == 0)
- break;
- j++;
- }
if (i == -1) {
if (proxyhost != NULL)
return DECLINED; /* try again another way */
@@ -313,39 +357,17 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
ap_hard_timeout("proxy send", r);
ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.1" CRLF,
NULL);
-
- if (conf->preserve_host) {
- hostname = ap_table_get(r->headers_in, "Host");
- if (!hostname) {
- hostname = r->server->server_hostname;
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, r,
- "proxy: No host line on incoming request "
- "and preserve host set forcing hostname to "
- "be %s for uri %s", hostname, r->uri);
- }
- strp2 = strchr(hostname, ':');
- if (strp2 != NULL) {
- *(strp2++) = '\0';
- if (ap_isdigit(*strp2)) {
- destport = atoi(strp2);
- destportstr = strp2;
- }
- }
- }
- else
- hostname = desthost;
-
{
int rc = DECLINED;
ap_hook_use("ap::mod_proxy::http::handler::write_host_header",
- AP_HOOK_SIG6(int,ptr,ptr,ptr,int,ptr),
+ AP_HOOK_SIG6(ptr,ptr,ptr,ptr,ptr,ptr),
AP_HOOK_DECLINE(DECLINED),
- &rc, r, f, hostname, destport, destportstr);
+ &rc, r, f, desthost, destportstr, destportstr);
if (rc == DECLINED) {
- if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
- ap_bvputs(f, "Host: ", hostname, ":", destportstr, CRLF, NULL);
+ if (destportstr != NULL)
+ ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
else
- ap_bvputs(f, "Host: ", hostname, CRLF, NULL);
+ ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
}
}
@@ -592,21 +614,31 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
if ((urlstr = ap_table_get(resp_hdrs, "Content-Location")) != NULL)
ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map(r, urlstr));
- /* check if NoCache directive on this host */
+/* check if NoCache directive on this host */
+ {
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+
if (nocache == 0) {
- for (i = 0; i < conf->nocaches->nelts; i++) {
- if (destaddr.s_addr == ncent[i].addr.s_addr ||
- (ncent[i].name != NULL &&
- (ncent[i].name[0] == '*' ||
- strstr(desthost, ncent[i].name) != NULL))) {
- nocache = 1;
- break;
- }
- }
+ for (i = 0; i < conf->nocaches->nelts; i++) {
+ if (ncent[i].name != NULL &&
+ (ncent[i].name[0] == '*' ||
+ strstr(desthost, ncent[i].name) != NULL)) {
+ nocache = 1;
+ break;
+ }
+ switch (res->ai_addr->sa_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)res->ai_addr;
+ if (sin->sin_addr.s_addr == ncent[i].addr.s_addr) {
+ nocache = 1;
+ break;
+ }
+ }
+ }
- /*
- * update the cache file, possibly even fulfilling the request if it
- * turns out a conditional allowed us to serve the object from the
+ /* update the cache file, possibly even fulfilling the request if
+ * it turns out a conditional allowed us to serve the object from the
* cache...
*/
i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache);
@@ -618,6 +650,7 @@ int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,
/* write status line and headers to the cache file */
ap_proxy_write_headers(c, ap_pstrcat(p, "HTTP/1.1 ", r->status_line, NULL), resp_hdrs);
}
+ }
/* Setup the headers for our client from upstreams response-headers */
ap_proxy_table_replace(r->headers_out, resp_hdrs);
diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_util.c b/usr.sbin/httpd/src/modules/proxy/proxy_util.c
index 08a53579c9e..d06f26246b3 100644
--- a/usr.sbin/httpd/src/modules/proxy/proxy_util.c
+++ b/usr.sbin/httpd/src/modules/proxy/proxy_util.c
@@ -206,6 +206,7 @@ char *
int i;
char *strp, *host, *url = *urlp;
char *user = NULL, *password = NULL;
+ char *t = NULL, *u = NULL, *v = NULL;
if (url[0] != '/' || url[1] != '/')
return "Malformed URL";
@@ -244,35 +245,57 @@ char *
*passwordp = password;
}
- strp = strrchr(host, ':');
- if (strp != NULL) {
- *(strp++) = '\0';
-
- for (i = 0; strp[i] != '\0'; i++)
- if (!ap_isdigit(strp[i]))
- break;
-
- /* if (i == 0) the no port was given; keep default */
- if (strp[i] != '\0') {
- return "Bad port number in URL";
- }
+ v = host;
+ if (*host == '['){
+ u = strrchr(host, ']');
+ if (u){
+ host++;
+ *u = '\0';
+ v = u + 1;
+ }
+ }
+ t = strrchr(v, ':');
+ if (t){
+ *t = '\0';
+ strp = t + 1;
+ }
+ if (strp){
+ for (i=0; strp[i] != '\0'; i++)
+ if (!ap_isdigit(strp[i]))
+ break;
+
+ /* if (i == 0) the no port was given; keep default */
+ if (strp[i] != '\0') {
+ return "Bad port number in URL";
+ }
else if (i > 0) {
- *port = atoi(strp);
- if (*port > 65535)
- return "Port number in URL > 65535";
- }
+ *port = atoi(strp);
+ if (*port > 65535)
+ return "Port number in URL > 65535";
+ }
}
ap_str_tolower(host); /* DNS names are case-insensitive */
if (*host == '\0')
return "Missing host in URL";
/* check hostname syntax */
for (i = 0; host[i] != '\0'; i++)
- if (!ap_isdigit(host[i]) && host[i] != '.')
- break;
+ if (!ap_isxdigit(host[i]) && host[i] != '.' && host[i] != ':')
+ break;
/* must be an IP address */
- if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
- {
- return "Bad IP address in URL";
+ if (host[i] == '\0') {
+ struct addrinfo hints, *res0;
+ int gai;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ if (gai = getaddrinfo(host, NULL, &hints, &res0)) {
+#if 0
+ return gai_strerror(gai);
+#else
+ return "Bad IP address in URL";
+#endif
+ }
+ freeaddrinfo(res0);
}
/* if (strchr(host,'.') == NULL && domain != NULL)
@@ -1248,18 +1271,41 @@ static int proxy_match_word(struct dirconn_entry *This, request_rec *r)
return host != NULL && strstr(host, This->name) != NULL;
}
-int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r)
+int ap_proxy_doconnect(int sock, struct sockaddr *addr, request_rec *r)
{
int i;
+ int salen;
+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
+#ifdef NI_WITHSCOPEID
+ const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
+#else
+ const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+#endif
ap_hard_timeout("proxy connect", r);
+#ifdef HAVE_SOCKADDR_LEN
+ salen = addr->sa_len;
+#else
+ switch (addr->sa_family) {
+ case AF_INET6:
+ salen = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ salen = sizeof(struct sockaddr_in);
+ break;
+ }
+#endif
do {
- i = connect(sock, (struct sockaddr *)addr, sizeof(struct sockaddr_in));
+ i = connect(sock, addr, salen);
} while (i == -1 && errno == EINTR);
if (i == -1) {
+ if (getnameinfo(addr, salen, hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
+ niflags) != 0) {
+ strcpy(hbuf, "?");
+ strcpy(pbuf, "?");
+ }
ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
- "proxy connect to %s port %d failed",
- inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
+ "proxy connect to %s port %s failed", hbuf, pbuf);
}
ap_kill_timeout(r);
diff --git a/usr.sbin/httpd/src/modules/ssl/Makefile.tmpl b/usr.sbin/httpd/src/modules/ssl/Makefile.tmpl
index 92aa0439c05..b0dd6a2203f 100644
--- a/usr.sbin/httpd/src/modules/ssl/Makefile.tmpl
+++ b/usr.sbin/httpd/src/modules/ssl/Makefile.tmpl
@@ -510,6 +510,18 @@ ssl_util.o ssl_util.lo: ssl_util.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
$(INCDIR)/util_md5.h $(INCDIR)/ap_md5.h \
$(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h
+ssl_util_sdbm.o ssl_util_sdbm.lo: ssl_util_sdbm.c mod_ssl.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/httpd.h $(INCDIR)/ap_mm.h $(INCDIR)/ap_alloc.h \
+ $(INCDIR)/ap_hook.h $(INCDIR)/ap_ctx.h $(INCDIR)/buff.h \
+ $(INCDIR)/ap.h $(INCDIR)/util_uri.h \
+ $(INCDIR)/http_config.h $(INCDIR)/http_conf_globals.h \
+ $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_core.h \
+ $(INCDIR)/http_log.h $(INCDIR)/scoreboard.h \
+ $(INCDIR)/util_md5.h $(INCDIR)/ap_md5.h \
+ $(INCDIR)/fnmatch.h ssl_expr.h ssl_util_ssl.h ssl_util_table.h
ssl_util_ssl.o ssl_util_ssl.lo: ssl_util_ssl.c mod_ssl.h $(INCDIR)/ap_config.h \
$(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
$(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
diff --git a/usr.sbin/httpd/src/modules/ssl/ssl_engine_ext.c b/usr.sbin/httpd/src/modules/ssl/ssl_engine_ext.c
index 61c63c765a8..944ec338619 100644
--- a/usr.sbin/httpd/src/modules/ssl/ssl_engine_ext.c
+++ b/usr.sbin/httpd/src/modules/ssl/ssl_engine_ext.c
@@ -218,7 +218,7 @@ static int ssl_ext_mp_handler(request_rec *, void *, char *, char *, int, char
static int ssl_ext_mp_set_destport(request_rec *);
static char *ssl_ext_mp_new_connection(request_rec *, BUFF *, char *);
static void ssl_ext_mp_close_connection(void *);
-static int ssl_ext_mp_write_host_header(request_rec *, BUFF *, char *, int, char *);
+static int ssl_ext_mp_write_host_header(request_rec *, BUFF *, char *, char *, char *);
#ifdef SSL_EXPERIMENTAL_PROXY
static void ssl_ext_mp_init(server_rec *, pool *);
static int ssl_ext_mp_verify_cb(int, X509_STORE_CTX *);
@@ -559,7 +559,7 @@ static void ssl_ext_mp_close_connection(void *_fb)
}
static int ssl_ext_mp_write_host_header(
- request_rec *r, BUFF *fb, char *host, int port, char *portstr)
+ request_rec *r, BUFF *fb, char *host, char *port, char *portstr)
{
if (ap_ctx_get(r->ctx, "ssl::proxy::enabled") == PFALSE)
return DECLINED;
diff --git a/usr.sbin/httpd/src/modules/standard/mod_access.c b/usr.sbin/httpd/src/modules/standard/mod_access.c
index 68dec7aa3d9..68f752648ee 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_access.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_access.c
@@ -74,7 +74,8 @@ enum allowdeny_type {
T_ALL,
T_IP,
T_HOST,
- T_FAIL
+ T_FAIL,
+ T_IP6,
};
typedef struct {
@@ -85,6 +86,10 @@ typedef struct {
struct in_addr net;
struct in_addr mask;
} ip;
+ struct {
+ struct in6_addr net6;
+ struct in6_addr mask6;
+ } ip6;
} x;
enum allowdeny_type type;
} allowdeny;
@@ -167,93 +172,222 @@ static const char *allow_cmd(cmd_parms *cmd, void *dv, char *from, char *where)
}
else if ((s = strchr(where, '/'))) {
- struct in_addr mask;
+ struct addrinfo hints, *resnet, *resmask;
+ struct sockaddr_storage net, mask;
+ int error;
+ char *p;
+ int justdigits;
- a->type = T_IP;
+ a->type = T_FAIL; /*just in case*/
/* trample on where, we won't be using it any more */
*s++ = '\0';
- if (!is_ip(where)
- || (a->x.ip.net.s_addr = ap_inet_addr(where)) == INADDR_NONE) {
+ justdigits = 0;
+ for (p = s; *p; p++) {
+ if (!isdigit(*p))
+ break;
+ }
+ if (!*p)
+ justdigits++;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM; /*dummy*/
+#ifdef AI_NUMERICHOST
+ hints.ai_flags = AI_NUMERICHOST; /*don't resolve*/
+#endif
+ resnet = NULL;
+ error = getaddrinfo(where, NULL, &hints, &resnet);
+ if (error || !resnet) {
+ if (resnet)
+ freeaddrinfo(resnet);
a->type = T_FAIL;
return "syntax error in network portion of network/netmask";
}
-
- /* is_ip just tests if it matches [\d.]+ */
- if (!is_ip(s)) {
+ if (resnet->ai_next) {
+ freeaddrinfo(resnet);
a->type = T_FAIL;
- return "syntax error in mask portion of network/netmask";
+ return "network/netmask resolved to multiple addresses";
}
- /* is it in /a.b.c.d form? */
- if (strchr(s, '.')) {
- mask.s_addr = ap_inet_addr(s);
- if (mask.s_addr == INADDR_NONE) {
- a->type = T_FAIL;
- return "syntax error in mask portion of network/netmask";
- }
+ memcpy(&net, resnet->ai_addr, resnet->ai_addrlen);
+ freeaddrinfo(resnet);
+
+ switch (net.ss_family) {
+ case AF_INET:
+ a->type = T_IP;
+ a->x.ip.net.s_addr = ((struct sockaddr_in *)&net)->sin_addr.s_addr;
+ break;
+ case AF_INET6:
+ a->type = T_IP6;
+ memcpy(&a->x.ip6.net6, &((struct sockaddr_in6 *)&net)->sin6_addr,
+ sizeof(a->x.ip6.net6));
+ break;
+ default:
+ a->type = T_FAIL;
+ return "unknown address family for network";
}
- else {
- int i;
- /* assume it's in /nnn form */
- i = atoi(s);
- if (i > 32 || i <= 0) {
+ if (!justdigits) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM; /*dummy*/
+#ifdef AI_NUMERICHOST
+ hints.ai_flags = AI_NUMERICHOST; /*don't resolve*/
+#endif
+ resmask = NULL;
+ error = getaddrinfo(s, NULL, &hints, &resmask);
+ if (error || !resmask) {
+ if (resmask)
+ freeaddrinfo(resmask);
a->type = T_FAIL;
- return "invalid mask in network/netmask";
+ return "syntax error in mask portion of network/netmask";
}
- mask.s_addr = 0xFFFFFFFFUL << (32 - i);
- mask.s_addr = htonl(mask.s_addr);
- }
- a->x.ip.mask = mask;
- a->x.ip.net.s_addr = (a->x.ip.net.s_addr & mask.s_addr); /* pjr - This fixes PR 4770 */
- }
- else if (ap_isdigit(*where) && is_ip(where)) {
- /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
- int shift;
- char *t;
- int octet;
-
- a->type = T_IP;
- /* parse components */
- s = where;
- a->x.ip.net.s_addr = 0;
- a->x.ip.mask.s_addr = 0;
- shift = 24;
- while (*s) {
- t = s;
- if (!ap_isdigit(*t)) {
+ if (resmask->ai_next) {
+ freeaddrinfo(resmask);
a->type = T_FAIL;
- return "invalid ip address";
- }
- while (ap_isdigit(*t)) {
- ++t;
+ return "network/netmask resolved to multiple addresses";
}
- if (*t == '.') {
- *t++ = 0;
- }
- else if (*t) {
+ memcpy(&mask, resmask->ai_addr, resmask->ai_addrlen);
+ freeaddrinfo(resmask);
+
+ if (net.ss_family != mask.ss_family) {
a->type = T_FAIL;
- return "invalid ip address";
+ return "network/netmask resolved to different address family";
}
- if (shift < 0) {
- a->type = T_FAIL;
- return "invalid ip address, only 4 octets allowed";
+
+ switch (a->type) {
+ case T_IP:
+ a->x.ip.mask.s_addr =
+ ((struct sockaddr_in *)&mask)->sin_addr.s_addr;
+ break;
+ case T_IP6:
+ memcpy(&a->x.ip6.mask6,
+ &((struct sockaddr_in6 *)&mask)->sin6_addr,
+ sizeof(a->x.ip6.mask6));
+ break;
}
- octet = atoi(s);
- if (octet < 0 || octet > 255) {
- a->type = T_FAIL;
- return "each octet must be between 0 and 255 inclusive";
+ } else {
+ int mask;
+ mask = atoi(s);
+ switch (a->type) {
+ case T_IP:
+ if (mask < 0 || 32 < mask) {
+ a->type = T_FAIL;
+ return "netmask out of range";
+ }
+ a->x.ip.mask.s_addr = htonl(0xFFFFFFFFUL << (32 - mask));
+ break;
+ case T_IP6:
+ {
+ int i;
+ if (mask < 0 || 128 < mask) {
+ a->type = T_FAIL;
+ return "netmask out of range";
+ }
+ for (i = 0; i < mask / 8; i++) {
+ a->x.ip6.mask6.s6_addr[i] = 0xff;
+ }
+ if (mask % 8)
+ a->x.ip6.mask6.s6_addr[i] = 0xff << (8 - (mask % 8));
+ break;
+ }
}
- a->x.ip.net.s_addr |= (unsigned int)octet << shift;
- a->x.ip.mask.s_addr |= 0xFFUL << shift;
- s = t;
- shift -= 8;
}
- a->x.ip.net.s_addr = htonl(a->x.ip.net.s_addr);
- a->x.ip.mask.s_addr = htonl(a->x.ip.mask.s_addr);
}
else {
- a->type = T_HOST;
+ struct addrinfo hints, *res;
+ struct sockaddr_storage ss;
+ int error;
+
+ a->type = T_FAIL; /*just in case*/
+
+ /* First, try using the old apache code to match */
+ /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */
+ if (ap_isdigit(*where) && is_ip(where)) {
+ int shift;
+ char *t;
+ int octet;
+
+ a->type = T_IP;
+ /* parse components */
+ s = where;
+ a->x.ip.net.s_addr = 0;
+ a->x.ip.mask.s_addr = 0;
+ shift = 24;
+ while (*s) {
+ t = s;
+ if (!ap_isdigit(*t)) {
+ a->type = T_FAIL;
+ return "invalid ip address";
+ }
+ while (ap_isdigit(*t)) {
+ ++t;
+ }
+ if (*t == '.') {
+ *t++ = 0;
+ }
+ else if (*t) {
+ a->type = T_FAIL;
+ return "invalid ip address";
+ }
+ if (shift < 0) {
+ return "invalid ip address, only 4 octets allowed";
+ }
+ octet = atoi(s);
+ if (octet < 0 || octet > 255) {
+ a->type = T_FAIL;
+ return "each octet must be between 0 and 255 inclusive";
+ }
+ a->x.ip.net.s_addr |= octet << shift;
+ a->x.ip.mask.s_addr |= 0xFFUL << shift;
+ s = t;
+ shift -= 8;
+ }
+ a->x.ip.net.s_addr = ntohl(a->x.ip.net.s_addr);
+ a->x.ip.mask.s_addr = ntohl(a->x.ip.mask.s_addr);
+
+ return NULL;
+ }
+
+ /* IPv4/v6 numeric address */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM; /*dummy*/
+#ifdef AI_NUMERICHOST
+ hints.ai_flags = AI_NUMERICHOST; /*don't resolve*/
+#endif
+ res = NULL;
+ error = getaddrinfo(where, NULL, &hints, &res);
+ if (error || !res) {
+ if (res)
+ freeaddrinfo(res);
+ a->type = T_HOST;
+ return NULL;
+ }
+ if (res->ai_next) {
+ freeaddrinfo(res);
+ a->type = T_FAIL;
+ return "network/netmask resolved to multiple addresses";
+ }
+ memcpy(&ss, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+
+ switch (ss.ss_family) {
+ case AF_INET:
+ a->type = T_IP;
+ a->x.ip.net.s_addr = ((struct sockaddr_in *)&ss)->sin_addr.s_addr;
+ memset(&a->x.ip.mask, 0xff, sizeof(a->x.ip.mask));
+ break;
+ case AF_INET6:
+ a->type = T_IP6;
+ memcpy(&a->x.ip6.net6, &((struct sockaddr_in6 *)&ss)->sin6_addr,
+ sizeof(a->x.ip6.net6));
+ memset(&a->x.ip6.mask6, 0xff, sizeof(a->x.ip6.mask6));
+ break;
+ default:
+ a->type = T_FAIL;
+ return "unknown address family for network";
+ }
}
return NULL;
@@ -318,12 +452,59 @@ static int find_allowdeny(request_rec *r, array_header *a, int method)
return 1;
case T_IP:
- if (ap[i].x.ip.net.s_addr != INADDR_NONE
- && (r->connection->remote_addr.sin_addr.s_addr
- & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) {
- return 1;
+ if (ap[i].x.ip.net.s_addr == INADDR_NONE)
+ break;
+ switch (r->connection->remote_addr.ss_family) {
+ case AF_INET:
+ if ((((struct sockaddr_in *)&r->connection->remote_addr)->sin_addr.s_addr
+ & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) {
+ return 1;
+ }
+ break;
+ case AF_INET6:
+ if (!IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr)) /*XXX*/
+ break;
+ if ((*(uint32_t *)&((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr.s6_addr[12]
+ & ap[i].x.ip.mask.s_addr) == ap[i].x.ip.net.s_addr) {
+ return 1;
+ }
+ break;
+ }
+ break;
+
+ case T_IP6:
+ {
+ struct in6_addr masked;
+ int j;
+ if (IN6_IS_ADDR_UNSPECIFIED(&ap[i].x.ip6.net6))
+ break;
+ switch (r->connection->remote_addr.ss_family) {
+ case AF_INET:
+ if (!IN6_IS_ADDR_V4MAPPED(&ap[i].x.ip6.net6)) /*XXX*/
+ break;
+ memset(&masked, 0, sizeof(masked));
+ masked.s6_addr[10] = masked.s6_addr[11] = 0xff;
+ memcpy(&masked.s6_addr[12],
+ &((struct sockaddr_in *)&r->connection->remote_addr)->sin_addr.s_addr,
+ sizeof(struct sockaddr_in));
+ for (j = 0; j < sizeof(struct in6_addr); j++)
+ masked.s6_addr[j] &= ap[i].x.ip6.mask6.s6_addr[j];
+ if (memcmp(&masked, &ap[i].x.ip6.net6, sizeof(masked)) == 0)
+ return 1;
+ break;
+ case AF_INET6:
+ memset(&masked, 0, sizeof(masked));
+ memcpy(&masked,
+ &((struct sockaddr_in6 *)&r->connection->remote_addr)->sin6_addr,
+ sizeof(masked));
+ for (j = 0; j < sizeof(struct in6_addr); j++)
+ masked.s6_addr[j] &= ap[i].x.ip6.mask6.s6_addr[j];
+ if (memcmp(&masked, &ap[i].x.ip6.net6, sizeof(masked)) == 0)
+ return 1;
+ break;
}
break;
+ }
case T_HOST:
if (!gothost) {
diff --git a/usr.sbin/httpd/src/modules/standard/mod_unique_id.c b/usr.sbin/httpd/src/modules/standard/mod_unique_id.c
index 36319a0a47a..b13723a4f2a 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_unique_id.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_unique_id.c
@@ -70,7 +70,14 @@
typedef struct {
unsigned int stamp;
- unsigned int in_addr;
+ union {
+ uint32_t in;
+#ifdef SHORT_UNIQUE_ID
+ uint32_t in6;
+#else
+ struct in6_addr in6;
+#endif
+ } addr;
unsigned int pid;
unsigned short counter;
} unique_id_rec;
@@ -139,7 +146,7 @@ typedef struct {
* this shouldn't be a problem till year 2106.
*/
-static unsigned global_in_addr;
+static struct sockaddr_storage global_addr;
/* Even when not MULTITHREAD, this will return a single structure, since
@@ -168,7 +175,8 @@ static void unique_id_global_init(server_rec *s, pool *p)
#define MAXHOSTNAMELEN 256
#endif
char str[MAXHOSTNAMELEN + 1];
- struct hostent *hent;
+ struct addrinfo hints, *res, *res0;
+ int error;
struct timeval tv;
unique_id_rec *cur_unique_id = get_cur_unique_id(1);
@@ -177,8 +185,8 @@ static void unique_id_global_init(server_rec *s, pool *p)
*/
unique_id_rec_offset[0] = XtOffsetOf(unique_id_rec, stamp);
unique_id_rec_size[0] = sizeof(cur_unique_id->stamp);
- unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, in_addr);
- unique_id_rec_size[1] = sizeof(cur_unique_id->in_addr);
+ unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, addr);
+ unique_id_rec_size[1] = sizeof(cur_unique_id->addr);
unique_id_rec_offset[2] = XtOffsetOf(unique_id_rec, pid);
unique_id_rec_size[2] = sizeof(cur_unique_id->pid);
unique_id_rec_offset[3] = XtOffsetOf(unique_id_rec, counter);
@@ -204,17 +212,42 @@ static void unique_id_global_init(server_rec *s, pool *p)
}
str[sizeof(str) - 1] = '\0';
- if ((hent = gethostbyname(str)) == NULL) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ error = getaddrinfo(str, NULL, &hints, &res0);
+ if (error) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s,
- "mod_unique_id: unable to gethostbyname(\"%s\")", str);
+ "mod_unique_id: getaddrinfo failed for \"%s\" (%s)", str,
+ gai_strerror(error));
exit(1);
}
- global_in_addr = ((struct in_addr *) hent->h_addr_list[0])->s_addr;
+ error = 1;
+ for (res = res0; res; res = res->ai_next) {
+ switch (res->ai_family) {
+ case AF_INET:
+ case AF_INET6:
+ memcpy(&global_addr, res->ai_addr, res->ai_addrlen);
+ error = 0;
+ break;
+ }
+ }
+ freeaddrinfo(res0);
+ if (error) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, s,
+ "mod_unique_id: no known AF found for \"%s\"", str);
+ exit(1);
+ }
+ getnameinfo((struct sockaddr *)&global_addr,
+#ifndef SIN6_LEN
+ SA_LEN((struct sockaddr *)&global_addr),
+#else
+ global_addr.ss_len,
+#endif
+ str, sizeof(str), NULL, 0, NI_NUMERICHOST);
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, s,
- "mod_unique_id: using ip addr %s",
- inet_ntoa(*(struct in_addr *) hent->h_addr_list[0]));
+ "mod_unique_id: using ip addr %s", str);
/*
* If the server is pummelled with restart requests we could possibly end
@@ -265,7 +298,22 @@ static void unique_id_child_init(server_rec *s, pool *p)
"oh no! pids are greater than 32-bits! I'm broken!");
}
- cur_unique_id->in_addr = global_in_addr;
+ memset(&cur_unique_id->addr, 0, sizeof(cur_unique_id->addr));
+ switch (global_addr.ss_family) {
+ case AF_INET:
+ cur_unique_id->addr.in =
+ ((struct sockaddr_in *)&global_addr)->sin_addr.s_addr;
+ break;
+ case AF_INET6:
+#ifdef SHORT_UNIQUE_ID
+ cur_unique_id->addr.in6 =
+ ((struct sockaddr_in6 *)&global_addr)->sin6_addr.s6_addr32[3];
+#else
+ cur_unique_id->addr.in6 =
+ ((struct sockaddr_in6 *)&global_addr)->sin6_addr;
+#endif
+ break;
+ }
/*
* If we use 0 as the initial counter we have a little less protection
diff --git a/usr.sbin/httpd/src/modules/standard/mod_usertrack.c b/usr.sbin/httpd/src/modules/standard/mod_usertrack.c
index 56f9f556502..37abaf4f314 100644
--- a/usr.sbin/httpd/src/modules/standard/mod_usertrack.c
+++ b/usr.sbin/httpd/src/modules/standard/mod_usertrack.c
@@ -147,13 +147,17 @@ static char * make_cookie_id(char * buffer, int bufsize, request_rec *r,
{
struct timeval tv;
struct timezone tz = {0, 0};
+ char hbuf[NI_MAXHOST];
cookie_dir_rec *dcfg;
long reqtime = (long) r->request_time;
long clocktime;
- unsigned long ipaddr = ntohl(r->connection->remote_addr.sin_addr.s_addr);
+ getnameinfo((struct sockaddr *)&r->connection->remote_addr,
+ r->connection->remote_addr.ss_len,
+ hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
+
const char *rname = ap_get_remote_host(r->connection, r->per_dir_config,
REMOTE_NAME);
dcfg = ap_get_module_config(r->per_dir_config, &usertrack_module);
@@ -167,8 +171,8 @@ static char * make_cookie_id(char * buffer, int bufsize, request_rec *r,
clocktime = (long) (tv.tv_usec / 1000);
if (cformat == CF_COMPACT)
- ap_snprintf(buffer, bufsize, "%s%lx%x%lx%lx",
- dcfg->prefix_string, ipaddr, (int) getpid(),
+ ap_snprintf(buffer, bufsize, "%s%s%x%lx%lx",
+ dcfg->prefix_string, hbuf, (int) getpid(),
reqtime, clocktime);
else
ap_snprintf(buffer, bufsize, "%s%s.%d%ld%ld",
diff --git a/usr.sbin/httpd/src/support/logresolve.c b/usr.sbin/httpd/src/support/logresolve.c
index df940d75d65..662145b6d1d 100644
--- a/usr.sbin/httpd/src/support/logresolve.c
+++ b/usr.sbin/httpd/src/support/logresolve.c
@@ -46,7 +46,7 @@
#include <arpa/inet.h>
-static void cgethost(struct in_addr ipnum, char *string, int check);
+static void cgethost(struct sockaddr *sa, char *string, int check);
static int getline(char *s, int n);
static void stats(FILE *output);
static void usage(void);
@@ -71,7 +71,7 @@ static void usage(void);
*/
struct nsrec {
- struct in_addr ipnum;
+ struct sockaddr_storage addr;
char *hostname;
int noname;
struct nsrec *next;
@@ -102,17 +102,44 @@ static int errors[MAX_ERR + 3];
* IP numbers with their IP number as hostname, setting noname flag
*/
-static void cgethost (struct in_addr ipnum, char *string, int check)
+static void cgethost (struct sockaddr *sa, char *string, int check)
{
+ uint32_t hashval;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
struct nsrec **current, *new;
- struct hostent *hostdata;
char *name;
+ char hostnamebuf[MAXHOSTNAMELEN];
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ hashval = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
+ break;
+ case AF_INET6:
+ hashval = *(uint32_t *)&((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12];
+ break;
+ default:
+ hashval = 0;
+ break;
+ }
+
+ current = &nscache[((hashval + (hashval >> 8) +
+ (hashval >> 16) + (hashval >> 24)) % BUCKETS)];
- current = &nscache[((ipnum.s_addr + (ipnum.s_addr >> 8) +
- (ipnum.s_addr >> 16) + (ipnum.s_addr >> 24)) % BUCKETS)];
+ while (*current) {
+#ifndef SIN6_LEN
+ if (SA_LEN(sa) == SA_LEN((struct sockaddr *)&(*current)->addr)
+ && memcmp(sa, &(*current)->addr, SA_LEN(sa)) == 0)
+#else
+ if (sa->sa_len == (*current)->addr.ss_len
+ && memcmp(sa, &(*current)->addr, sa->sa_len) == 0)
+#endif
+ {
+ break;
+ }
- while (*current != NULL && ipnum.s_addr != (*current)->ipnum.s_addr)
current = &(*current)->next;
+ }
if (*current == NULL) {
cachesize++;
@@ -125,45 +152,55 @@ static void cgethost (struct in_addr ipnum, char *string, int check)
*current = new;
new->next = NULL;
- new->ipnum = ipnum;
-
- hostdata = gethostbyaddr((const char *) &ipnum, sizeof(struct in_addr),
- AF_INET);
- if (hostdata == NULL) {
- if (h_errno > MAX_ERR)
- errors[UNKNOWN_ERR]++;
- else
- errors[h_errno]++;
- new->noname = h_errno;
- name = strdup(inet_ntoa(ipnum));
- }
- else {
- new->noname = 0;
- name = strdup(hostdata->h_name);
- if (check) {
- if (name == NULL) {
- perror("strdup");
- fprintf(stderr, "Insufficient memory\n");
- exit(1);
- }
- hostdata = gethostbyname(name);
- if (hostdata != NULL) {
- char **hptr;
-
- for (hptr = hostdata->h_addr_list; *hptr != NULL; hptr++)
- if (((struct in_addr *) (*hptr))->s_addr == ipnum.s_addr)
- break;
- if (*hptr == NULL)
- hostdata = NULL;
- }
- if (hostdata == NULL) {
- fprintf(stderr, "Bad host: %s != %s\n", name,
- inet_ntoa(ipnum));
- new->noname = NO_REVERSE;
- free(name);
- name = strdup(inet_ntoa(ipnum));
- errors[NO_REVERSE]++;
+#ifndef SIN6_LEN
+ memcpy(&new->addr, sa, SA_LEN(sa));
+#else
+ memcpy(&new->addr, sa, sa->sa_len);
+#endif
+
+ new->noname = getnameinfo(sa,
+#ifndef SIN6_LEN
+ SA_LEN(sa),
+#else
+ sa->sa_len,
+#endif
+ hostnamebuf, sizeof(hostnamebuf), NULL, 0, 0);
+ name = strdup(hostnamebuf);
+ if (check) {
+ struct addrinfo hints, *res;
+ int error;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ error = getaddrinfo(hostnamebuf, NULL, &hints, &res);
+ if (!error) {
+ while (res) {
+#ifndef SIN6_LEN
+ if (SA_LEN(sa) == res->ai_addrlen
+ && memcmp(sa, res->ai_addr, SA_LEN(sa)) == 0)
+#else
+ if (sa->sa_len == res->ai_addrlen
+ && memcmp(sa, res->ai_addr, sa->sa_len) == 0)
+#endif
+ {
+ break;
+ }
+ res = res->ai_next;
}
+ if (!res)
+ error++;
+ }
+ if (error) {
+ getnameinfo(sa,
+#ifndef SIN6_LEN
+ SA_LEN(sa),
+#else
+ sa->sa_len,
+#endif
+ hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
+ fprintf(stderr, "Bad host: %s != %s\n", name, hostnamebuf);
+ new->noname = NO_REVERSE;
+ free(name);
+ name = strdup(hostnamebuf);
}
}
new->hostname = name;
@@ -191,6 +228,7 @@ static void stats (FILE *output)
char *ipstring;
struct nsrec *current;
char *errstring[MAX_ERR + 3];
+ char hostnamebuf[MAXHOSTNAMELEN];
for (i = 0; i < MAX_ERR + 3; i++)
errstring[i] = "Unknown error";
@@ -222,7 +260,14 @@ static void stats (FILE *output)
for (i = 0; i < BUCKETS; i++)
for (current = nscache[i]; current != NULL; current = current->next) {
- ipstring = inet_ntoa(current->ipnum);
+ getnameinfo((struct sockaddr *)&current->addr,
+#ifndef SIN6_LEN
+ SA_LEN((struct sockaddr *)&current->addr),
+#else
+ current->addr.ss_len,
+#endif
+ hostnamebuf, sizeof(hostnamebuf), NULL, 0, NI_NUMERICHOST);
+ ipstring = hostnamebuf;
if (current->noname == 0)
fprintf(output, " %3d %15s - %s\n", i, ipstring,
current->hostname);
@@ -259,9 +304,10 @@ static void usage(void)
int main (int argc, char *argv[])
{
- struct in_addr ipnum;
char *bar, hoststring[MAXDNAME + 1], line[MAXLINE], *statfile;
int i, check;
+ struct addrinfo hints, *res;
+ int error;
int ch;
check = 0;
@@ -301,8 +347,10 @@ int main (int argc, char *argv[])
bar = strchr(line, ' ');
if (bar != NULL)
*bar = '\0';
- ipnum.s_addr = inet_addr(line);
- if (ipnum.s_addr == 0xffffffffu) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ error = getaddrinfo(line, NULL, &hints, &res);
+ if (error) {
if (bar != NULL)
*bar = ' ';
puts(line);
@@ -312,11 +360,12 @@ int main (int argc, char *argv[])
resolves++;
- cgethost(ipnum, hoststring, check);
+ cgethost(res->ai_addr, hoststring, check);
if (bar != NULL)
printf("%s %s\n", hoststring, bar + 1);
else
puts(hoststring);
+ freeaddrinfo(res);
}
if (statfile != NULL) {